-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 🚧 Create funnel client * 🚧 Createstep api 변경 * 🚧 App router nested example * 🚧 Default step example add * 🚧 Readme update
- Loading branch information
Showing
30 changed files
with
832 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,44 @@ | ||
name: Release | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
concurrency: ${{ github.workflow }}-${{ github.ref }} | ||
|
||
jobs: | ||
release: | ||
name: Release | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout Repo | ||
uses: actions/checkout@v4 | ||
|
||
- name: Setup pnpm 8 | ||
uses: pnpm/action-setup@v3 | ||
with: | ||
version: 8 | ||
|
||
- name: Setup Node.js 20.x | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20.x | ||
|
||
- name: Install Dependencies | ||
run: pnpm i | ||
|
||
- name: Create Release Pull Request or Publish to npm | ||
id: changesets | ||
uses: changesets/action@v1 | ||
with: | ||
# This expects you to have a script called release which does a build for your packages and calls changeset publish | ||
publish: pnpm release | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
||
- name: Send a Slack notification if a publish happens | ||
if: steps.changesets.outputs.published == 'true' | ||
# You can do something when a publish happens. | ||
run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!" | ||
# name: Release | ||
|
||
# on: | ||
# push: | ||
# branches: | ||
# - main | ||
|
||
# concurrency: ${{ github.workflow }}-${{ github.ref }} | ||
|
||
# jobs: | ||
# release: | ||
# name: Release | ||
# runs-on: ubuntu-latest | ||
# steps: | ||
# - name: Checkout Repo | ||
# uses: actions/checkout@v4 | ||
|
||
# - name: Setup pnpm 8 | ||
# uses: pnpm/action-setup@v3 | ||
# with: | ||
# version: 8 | ||
|
||
# - name: Setup Node.js 20.x | ||
# uses: actions/setup-node@v4 | ||
# with: | ||
# node-version: 20.x | ||
|
||
# - name: Install Dependencies | ||
# run: pnpm i | ||
|
||
# - name: Create Release Pull Request or Publish to npm | ||
# id: changesets | ||
# uses: changesets/action@v1 | ||
# with: | ||
# # This expects you to have a script called release which does a build for your packages and calls changeset publish | ||
# publish: pnpm release | ||
# env: | ||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
||
# - name: Send a Slack notification if a publish happens | ||
# if: steps.changesets.outputs.published == 'true' | ||
# # You can do something when a publish happens. | ||
# run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,199 @@ | ||
# Summery | ||
![usefunnel thumbnail](/thumbnail.png) | ||
|
||
Funnel의 Best Practice를 구합니다. | ||
# useFunnel | ||
|
||
Manage your funnels declaratively and explicitly. | ||
|
||
# Quick Start | ||
|
||
## next.js app router | ||
|
||
### Installation | ||
|
||
``` | ||
npm i qs @xionhub/funnel-core @xionhub/funnel-client @xionhub/funnel-app-router-adapter | ||
``` | ||
|
||
``` | ||
yarn add qs @xionhub/funnel-core @xionhub/funnel-client @xionhub/funnel-app-router-adapter | ||
``` | ||
|
||
``` | ||
pnpm i qs @xionhub/funnel-core @xionhub/funnel-client @xionhub/funnel-app-router-adapter | ||
``` | ||
|
||
### create funnelOptions | ||
|
||
```tsx | ||
import { funnelOptions } from "@xionhub/funnel-core"; | ||
|
||
const basicFunnelOptions = () => | ||
funnelOptions({ | ||
steps: ["a", "b", "c"] as const, | ||
funnelId: "hello-this-is-funnel-id", | ||
}); | ||
``` | ||
|
||
### import useFunnel | ||
|
||
```tsx | ||
"use client"; | ||
import { useFunnel } from "@xionhub/funnel-app-router-adapter"; | ||
import { useRouter } from "next/navigation"; | ||
|
||
export const BasicFunnel = () => { | ||
const [Funnel, controller] = useFunnel(basicFunnelOptions()); | ||
const router = useRouter(); | ||
return ( | ||
<Funnel> | ||
<Funnel.Step name="a"> | ||
<FunnelItem | ||
setStep={() => { | ||
router.push(`/funnel?${controller.createStep("b")}`); | ||
}} | ||
step="a" | ||
/> | ||
</Funnel.Step> | ||
<Funnel.Step name="b"> | ||
<FunnelItem | ||
setStep={() => { | ||
router.push(`/funnel?${controller.createStep("c")}`); | ||
}} | ||
step="b" | ||
/> | ||
</Funnel.Step> | ||
<Funnel.Step name="c"> | ||
<FunnelItem | ||
setStep={() => { | ||
router.push(`/funnel?${controller.createStep("a")}`); | ||
}} | ||
step="c" | ||
/> | ||
</Funnel.Step> | ||
</Funnel> | ||
); | ||
}; | ||
|
||
const FunnelItem = ({ setStep, step }: Props) => { | ||
return ( | ||
<div className=" flex flex-col gap-y-16 justify-center items-center"> | ||
<div>current location {step}</div> | ||
<button | ||
className=" bg-purple-400 rounded-full py-4 px-4" | ||
onClick={() => setStep()} | ||
> | ||
go to next funnel | ||
</button> | ||
</div> | ||
); | ||
}; | ||
``` | ||
|
||
### Wrapping Suspense | ||
|
||
```tsx | ||
import { Suspense } from "react"; | ||
import { BasicFunnel } from "~/src/basic-funnel"; | ||
|
||
export default function Page() { | ||
return ( | ||
<div> | ||
<Suspense> | ||
<BasicFunnel /> | ||
</Suspense> | ||
</div> | ||
); | ||
} | ||
``` | ||
|
||
# API | ||
|
||
## useCoreFunnel | ||
|
||
```tsx | ||
declare const useCoreFunnel: <Steps extends NonEmptyArray<string>>( | ||
options: FunnelOptions<Steps> & { | ||
onStepChange?: FunnelStepChangeFunction<Steps>; | ||
} | ||
) => [ | ||
((props: RouteFunnelProps<Steps>) => JSX.Element) & { | ||
Step: (props: StepProps<Steps>) => JSX.Element; | ||
Guard: <T>(props: GuardProps<T>) => JSX.Element; | ||
}, | ||
{ | ||
funnelId: string; | ||
step: Steps[number] | undefined; | ||
onStepChange: FunnelStepChangeFunction<Steps>; | ||
steps: Steps; | ||
}, | ||
]; | ||
``` | ||
|
||
## Guard | ||
|
||
```tsx | ||
interface GuardProps<T> { | ||
condition: (() => T) | (() => Promise<T>); | ||
children?: ReactNode; | ||
onRestrict?: (param: Awaited<T>) => void; | ||
conditionBy?: (param: Awaited<T>) => boolean; | ||
fallback?: ReactNode; | ||
} | ||
``` | ||
|
||
`condition` is a function that must return whether the funnel can be accessed. | ||
|
||
`onRestrict` runs when condition is false. | ||
|
||
`conditionBy` is required if the value returned by condition is not boolean. It should return a boolean. | ||
|
||
`fallback` is the fallback that will be displayed when the condition is Falsy. | ||
|
||
## useFunnel For App Router | ||
|
||
```tsx | ||
declare const useFunnel: <Steps extends NonEmptyArray<string>>( | ||
options: Omit<FunnelOptions<Steps>, "step"> | ||
) => [ | ||
((props: RouteFunnelProps<Steps>) => JSX.Element) & { | ||
Step: (props: StepProps<Steps>) => JSX.Element; | ||
Guard: <T>(props: _GuardProps<T>) => JSX.Element; | ||
}, | ||
{ | ||
createStep: ( | ||
step: Steps[number], | ||
searchParams?: URLSearchParams, | ||
deleteQueryParams?: string[] | string | ||
) => string; | ||
funnelId: string; | ||
step: Steps[number] | undefined; | ||
steps: Steps; | ||
}, | ||
]; | ||
``` | ||
|
||
`createStep` is the same API as FunnelClient.createStep. | ||
|
||
Using createStep, you can create, delete, or update the query string for the next step. | ||
|
||
## Funnel Client | ||
|
||
### FunnelClient.createStep | ||
|
||
```tsx | ||
createStep(step:string , options:{ | ||
searchParams?: URLSearchParams; | ||
deleteQueryParams?: string[] | string; | ||
qsOptions?: QueryString.IStringifyBaseOptions; | ||
}) | ||
``` | ||
|
||
For deleteQueryParams, enter the key value of queryParams you want to delete. qsOptions uses StringifyBaseOptions from the qs library. | ||
|
||
# Get More Example | ||
|
||
[App Router Example](https://github.com/XionWCFM/funnel/tree/main/apps/app-router-example) | ||
|
||
# License | ||
|
||
Licensed under the MIT license. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Suspense } from "react"; | ||
import { DefaultStepFunnel } from "~/src/default-step-funnel"; | ||
|
||
export default function Page() { | ||
return ( | ||
<div> | ||
<Suspense> | ||
<DefaultStepFunnel /> | ||
</Suspense> | ||
</div> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.