From 6166e778b8658a3053a1ee5bc721612ad389cf36 Mon Sep 17 00:00:00 2001 From: Damian Ricobelli Date: Mon, 27 Jan 2025 01:19:16 -0300 Subject: [PATCH] docs: update logic and docs --- apps/www/content/docs/components/stepper.mdx | 165 +++++----- apps/www/package.json | 2 +- apps/www/public/r/colors/index.json | 244 ++++++++++++++ .../public/r/styles/default/stepper-demo.json | 2 +- .../r/styles/default/stepper-description.json | 2 +- .../public/r/styles/default/stepper-form.json | 2 +- .../public/r/styles/default/stepper-icon.json | 2 +- .../default/stepper-label-orientation.json | 2 +- .../default/stepper-responsive-variant.json | 2 +- .../r/styles/default/stepper-tracking.json | 2 +- .../r/styles/default/stepper-variants.json | 2 +- apps/www/public/r/styles/default/stepper.json | 2 +- .../r/styles/new-york/stepper-demo.json | 2 +- .../styles/new-york/stepper-description.json | 2 +- .../r/styles/new-york/stepper-form.json | 2 +- .../r/styles/new-york/stepper-icon.json | 2 +- .../new-york/stepper-label-orientation.json | 2 +- .../new-york/stepper-responsive-variant.json | 2 +- .../r/styles/new-york/stepper-tracking.json | 2 +- .../r/styles/new-york/stepper-variants.json | 2 +- .../www/public/r/styles/new-york/stepper.json | 2 +- .../default/examples/stepper-demo.tsx | 50 +-- .../default/examples/stepper-description.tsx | 50 +-- .../default/examples/stepper-form.tsx | 187 +++++------ .../default/examples/stepper-icon.tsx | 51 +-- .../examples/stepper-label-orientation.tsx | 49 +-- .../examples/stepper-responsive-variant.tsx | 61 ++-- .../default/examples/stepper-tracking.tsx | 45 ++- .../default/examples/stepper-variants.tsx | 107 ++++--- .../examples/stepper-with-description.tsx | 74 ----- apps/www/registry/default/ui/stepper.tsx | 298 +++++------------- .../new-york/examples/stepper-demo.tsx | 50 +-- .../new-york/examples/stepper-description.tsx | 50 +-- .../new-york/examples/stepper-form.tsx | 187 +++++------ .../new-york/examples/stepper-icon.tsx | 51 +-- .../examples/stepper-label-orientation.tsx | 49 +-- .../examples/stepper-responsive-variant.tsx | 61 ++-- .../new-york/examples/stepper-tracking.tsx | 45 ++- .../new-york/examples/stepper-variants.tsx | 107 ++++--- .../examples/stepper-with-description.tsx | 74 ----- apps/www/registry/new-york/ui/stepper.tsx | 298 +++++------------- pnpm-lock.yaml | 37 +-- 42 files changed, 1217 insertions(+), 1211 deletions(-) delete mode 100644 apps/www/registry/default/examples/stepper-with-description.tsx delete mode 100644 apps/www/registry/new-york/examples/stepper-with-description.tsx diff --git a/apps/www/content/docs/components/stepper.mdx b/apps/www/content/docs/components/stepper.mdx index 4df49e06953..5ad08739655 100644 --- a/apps/www/content/docs/components/stepper.mdx +++ b/apps/www/content/docs/components/stepper.mdx @@ -61,15 +61,13 @@ A `Stepper` component is composed of the following parts: - `StepperTitle` - Step title. - `StepperDescription` - Step description. - `StepperPanel` - Section to render the step content based on the current step. -- `StepperControls` - Step controls to navigate through the steps. -- `StepperAction` - Next, previous and reset buttons. +- `StepperControls` - Section to render the buttons to navigate through the steps. ## Usage ```tsx showLineNumbers import { Stepper, - StepperAction, StepperControls, StepperDescription, StepperNavigation, @@ -96,10 +94,7 @@ export function Component() { ... - - - ... - + ... ) } @@ -138,17 +133,12 @@ export function MyFirstStepper() { ```tsx export function MyFirstStepper() { - const steps = stepperInstance.steps return ( {({ methods }) => ( - {steps.map((step) => ( - methods.goTo(step.id)} - > + {methods.all.map((step) => ( + methods.goTo(step.id)}> {step.title} ))} @@ -166,12 +156,16 @@ export function MyFirstStepper() { const steps = stepperInstance.steps return ( - {/* StepperNavigation code */} - {steps.map((step) => ( - - {({ step }) =>

Content for {step.id}

} -
- ))} + {({ methods }) => ( + <> + {/* StepperNavigation code */} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} + + )}
) } @@ -187,13 +181,26 @@ export function MyFirstStepper() { const steps = stepperInstance.steps return ( - {/* StepperNavigation code */} - {/* StepperPanel code */} - - Previous - Next - Reset - + {({ methods }) => ( + <> + {/* StepperNavigation code */} + {/* StepperPanel code */} + + {!methods.isLast && ( + + )} + + + + )} ) } @@ -203,43 +210,49 @@ export function MyFirstStepper() { ```tsx export function MyFirstStepper() { - const steps = stepperInstance.steps return ( {({ methods }) => ( <> - {steps.map((step) => ( - methods.goTo(step.id)} - > + {methods.all.map((step) => ( + methods.goTo(step.id)}> {step.title} ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + )}
) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} ``` @@ -295,7 +308,7 @@ The children accept a function that has as parameters the `methods` prop. The `m If you don't need the `methods` prop, you can just pass the children directly - and get the methods from the `useStepper` hook. + and get the methods from the `useStepper` hook from your stepper instance. **Props** @@ -355,22 +368,14 @@ The `StepperDescription` component is used to render the description of the step ## StepperPanel -The `StepperPanel` component is used to render the content of the step. You just need to pass the `when` prop which is the step you want to render. - -The children accept a function that has as parameters the step and a function `onBeforeAction` that allows to execute a callback before an action `prev`, `next` or ` - - - You don't have to worry about the stepper knowing which panel to render. If - the step is not correct, the panel will not be rendered. - +The `StepperPanel` component is used to render the content of the step. **Props** -| Name | Type | Description | -| ---------- | ------------------------------------------------------- | ----------------------------------------- | -| `children` | `React.ReactNode or function({step, onBeforeCallback})` | Content to render. | -| `when` | `Step` | Used to conditionally render the content. | -| `asChild` | `boolean` | Render as child. | +| Name | Type | Description | +| ---------- | ----------------- | ------------------ | +| `children` | `React.ReactNode` | Content to render. | +| `asChild` | `boolean` | Render as child. | ## StepperControls @@ -383,23 +388,33 @@ The `StepperControls` component is used to render the buttons to navigate throug | `children` | `React.ReactNode` | Buttons to render. | | `asChild` | `boolean` | Render as child. | -### StepperAction +## Before/after actions -The `StepperAction` component is used to render the buttons to navigate through the steps. You just need to pass the `action` prop which is the action you want to perform. +You can add a callback to the `next` and `prev` methods to execute a callback before or after the action is executed. +**This is useful if you need to validate the form or check if the step is valid before moving to the prev/next step.** - - If you need to execute a function before the button action is executed, you - can use the `onBeforeAction` prop. - +For example: -**Props** +```tsx +methods.beforeNext(async () => { + const valid = await form.trigger() + if (!valid) return false + return true +}) +``` + +That function will validate the form and check if the step is valid before moving to the next step returning a boolean value. + +More info about the `beforeNext` and `beforePrev` methods can be found in the [API References](https://stepperize.vercel.app/docs/react/api-references/hook#beforeafter-functions). -| Name | Type | Description | -| ---------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------- | -| `children` | `React.ReactNode` | Buttons to render. | -| `asChild` | `boolean` | Render as child. | -| `action` | `prev, next or reset` | Action to perform. | -| `onBeforeAction` | `(event: React.MouseEvent, prevStep: Step, nextStep: Step) => boolean` | Function to execute before the action is performed. | +## Skip steps + +Through the methods you can access functions like `goTo` to skip to a specific step. + +```tsx +// From step 1 to step 3 +methods.goTo("step-3") +``` ## Examples diff --git a/apps/www/package.json b/apps/www/package.json index 111de6e4b7f..3f1300eaab6 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -52,7 +52,7 @@ "@radix-ui/react-toggle": "^1.0.3", "@radix-ui/react-toggle-group": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.6", - "@stepperize/react": "^4.1.3", + "@stepperize/react": "^4.2.0", "@tanstack/react-table": "^8.9.1", "@vercel/analytics": "^1.2.2", "@vercel/og": "^0.0.21", diff --git a/apps/www/public/r/colors/index.json b/apps/www/public/r/colors/index.json index c25158efb11..c06c452a3ff 100644 --- a/apps/www/public/r/colors/index.json +++ b/apps/www/public/r/colors/index.json @@ -6,6 +6,7 @@ "hex": "#000000", "rgb": "rgb(0,0,0)", "hsl": "hsl(0,0%,0%)", + "oklch": "oklch(0.00,0.00,0)", "rgbChannel": "0 0 0", "hslChannel": "0 0% 0%" }, @@ -13,6 +14,7 @@ "hex": "#ffffff", "rgb": "rgb(255,255,255)", "hsl": "hsl(0,0%,100%)", + "oklch": "oklch(1.00,0.00,0)", "rgbChannel": "255 255 255", "hslChannel": "0 0% 100%" }, @@ -22,6 +24,7 @@ "hex": "#f8fafc", "rgb": "rgb(248,250,252)", "hsl": "hsl(210,40%,98%)", + "oklch": "oklch(0.98,0.00,248)", "rgbChannel": "248 250 252", "hslChannel": "210 40% 98%" }, @@ -30,6 +33,7 @@ "hex": "#f1f5f9", "rgb": "rgb(241,245,249)", "hsl": "hsl(210,40%,96.1%)", + "oklch": "oklch(0.97,0.01,248)", "rgbChannel": "241 245 249", "hslChannel": "210 40% 96.1%" }, @@ -38,6 +42,7 @@ "hex": "#e2e8f0", "rgb": "rgb(226,232,240)", "hsl": "hsl(214.3,31.8%,91.4%)", + "oklch": "oklch(0.93,0.01,256)", "rgbChannel": "226 232 240", "hslChannel": "214.3 31.8% 91.4%" }, @@ -46,6 +51,7 @@ "hex": "#cbd5e1", "rgb": "rgb(203,213,225)", "hsl": "hsl(212.7,26.8%,83.9%)", + "oklch": "oklch(0.87,0.02,253)", "rgbChannel": "203 213 225", "hslChannel": "212.7 26.8% 83.9%" }, @@ -54,6 +60,7 @@ "hex": "#94a3b8", "rgb": "rgb(148,163,184)", "hsl": "hsl(215,20.2%,65.1%)", + "oklch": "oklch(0.71,0.04,257)", "rgbChannel": "148 163 184", "hslChannel": "215 20.2% 65.1%" }, @@ -62,6 +69,7 @@ "hex": "#64748b", "rgb": "rgb(100,116,139)", "hsl": "hsl(215.4,16.3%,46.9%)", + "oklch": "oklch(0.55,0.04,257)", "rgbChannel": "100 116 139", "hslChannel": "215.4 16.3% 46.9%" }, @@ -70,6 +78,7 @@ "hex": "#475569", "rgb": "rgb(71,85,105)", "hsl": "hsl(215.3,19.3%,34.5%)", + "oklch": "oklch(0.45,0.04,257)", "rgbChannel": "71 85 105", "hslChannel": "215.3 19.3% 34.5%" }, @@ -78,6 +87,7 @@ "hex": "#334155", "rgb": "rgb(51,65,85)", "hsl": "hsl(215.3,25%,26.7%)", + "oklch": "oklch(0.37,0.04,257)", "rgbChannel": "51 65 85", "hslChannel": "215.3 25% 26.7%" }, @@ -86,6 +96,7 @@ "hex": "#1e293b", "rgb": "rgb(30,41,59)", "hsl": "hsl(217.2,32.6%,17.5%)", + "oklch": "oklch(0.28,0.04,260)", "rgbChannel": "30 41 59", "hslChannel": "217.2 32.6% 17.5%" }, @@ -94,6 +105,7 @@ "hex": "#0f172a", "rgb": "rgb(15,23,42)", "hsl": "hsl(222.2,47.4%,11.2%)", + "oklch": "oklch(0.21,0.04,266)", "rgbChannel": "15 23 42", "hslChannel": "222.2 47.4% 11.2%" }, @@ -102,6 +114,7 @@ "hex": "#020617", "rgb": "rgb(2,6,23)", "hsl": "hsl(222.2,84%,4.9%)", + "oklch": "oklch(0.13,0.04,265)", "rgbChannel": "2 6 23", "hslChannel": "222.2 84% 4.9%" } @@ -112,6 +125,7 @@ "hex": "#f9fafb", "rgb": "rgb(249,250,251)", "hsl": "hsl(210,20%,98%)", + "oklch": "oklch(0.98,0.00,248)", "rgbChannel": "249 250 251", "hslChannel": "210 20% 98%" }, @@ -120,6 +134,7 @@ "hex": "#f3f4f6", "rgb": "rgb(243,244,246)", "hsl": "hsl(220,14.3%,95.9%)", + "oklch": "oklch(0.97,0.00,265)", "rgbChannel": "243 244 246", "hslChannel": "220 14.3% 95.9%" }, @@ -128,6 +143,7 @@ "hex": "#e5e7eb", "rgb": "rgb(229,231,235)", "hsl": "hsl(220,13%,91%)", + "oklch": "oklch(0.93,0.01,265)", "rgbChannel": "229 231 235", "hslChannel": "220 13% 91%" }, @@ -136,6 +152,7 @@ "hex": "#d1d5db", "rgb": "rgb(209,213,219)", "hsl": "hsl(216,12.2%,83.9%)", + "oklch": "oklch(0.87,0.01,258)", "rgbChannel": "209 213 219", "hslChannel": "216 12.2% 83.9%" }, @@ -144,6 +161,7 @@ "hex": "#9ca3af", "rgb": "rgb(156,163,175)", "hsl": "hsl(217.9,10.6%,64.9%)", + "oklch": "oklch(0.71,0.02,261)", "rgbChannel": "156 163 175", "hslChannel": "217.9 10.6% 64.9%" }, @@ -152,6 +170,7 @@ "hex": "#6b7280", "rgb": "rgb(107,114,128)", "hsl": "hsl(220,8.9%,46.1%)", + "oklch": "oklch(0.55,0.02,264)", "rgbChannel": "107 114 128", "hslChannel": "220 8.9% 46.1%" }, @@ -160,6 +179,7 @@ "hex": "#4b5563", "rgb": "rgb(75,85,99)", "hsl": "hsl(215,13.8%,34.1%)", + "oklch": "oklch(0.45,0.03,257)", "rgbChannel": "75 85 99", "hslChannel": "215 13.8% 34.1%" }, @@ -168,6 +188,7 @@ "hex": "#374151", "rgb": "rgb(55,65,81)", "hsl": "hsl(216.9,19.1%,26.7%)", + "oklch": "oklch(0.37,0.03,260)", "rgbChannel": "55 65 81", "hslChannel": "216.9 19.1% 26.7%" }, @@ -176,6 +197,7 @@ "hex": "#1f2937", "rgb": "rgb(31,41,55)", "hsl": "hsl(215,27.9%,16.9%)", + "oklch": "oklch(0.28,0.03,257)", "rgbChannel": "31 41 55", "hslChannel": "215 27.9% 16.9%" }, @@ -184,6 +206,7 @@ "hex": "#111827", "rgb": "rgb(17,24,39)", "hsl": "hsl(220.9,39.3%,11%)", + "oklch": "oklch(0.21,0.03,265)", "rgbChannel": "17 24 39", "hslChannel": "220.9 39.3% 11%" }, @@ -192,6 +215,7 @@ "hex": "#030712", "rgb": "rgb(3,7,18)", "hsl": "hsl(224,71.4%,4.1%)", + "oklch": "oklch(0.13,0.03,262)", "rgbChannel": "3 7 18", "hslChannel": "224 71.4% 4.1%" } @@ -202,6 +226,7 @@ "hex": "#fafafa", "rgb": "rgb(250,250,250)", "hsl": "hsl(0,0%,98%)", + "oklch": "oklch(0.99,0.00,0)", "rgbChannel": "250 250 250", "hslChannel": "0 0% 98%" }, @@ -210,6 +235,7 @@ "hex": "#f4f4f5", "rgb": "rgb(244,244,245)", "hsl": "hsl(240,4.8%,95.9%)", + "oklch": "oklch(0.97,0.00,286)", "rgbChannel": "244 244 245", "hslChannel": "240 4.8% 95.9%" }, @@ -218,6 +244,7 @@ "hex": "#e4e4e7", "rgb": "rgb(228,228,231)", "hsl": "hsl(240,5.9%,90%)", + "oklch": "oklch(0.92,0.00,286)", "rgbChannel": "228 228 231", "hslChannel": "240 5.9% 90%" }, @@ -226,6 +253,7 @@ "hex": "#d4d4d8", "rgb": "rgb(212,212,216)", "hsl": "hsl(240,4.9%,83.9%)", + "oklch": "oklch(0.87,0.01,286)", "rgbChannel": "212 212 216", "hslChannel": "240 4.9% 83.9%" }, @@ -234,6 +262,7 @@ "hex": "#a1a1aa", "rgb": "rgb(161,161,170)", "hsl": "hsl(240,5%,64.9%)", + "oklch": "oklch(0.71,0.01,286)", "rgbChannel": "161 161 170", "hslChannel": "240 5% 64.9%" }, @@ -242,6 +271,7 @@ "hex": "#71717a", "rgb": "rgb(113,113,122)", "hsl": "hsl(240,3.8%,46.1%)", + "oklch": "oklch(0.55,0.01,286)", "rgbChannel": "113 113 122", "hslChannel": "240 3.8% 46.1%" }, @@ -250,6 +280,7 @@ "hex": "#52525b", "rgb": "rgb(82,82,91)", "hsl": "hsl(240,5.2%,33.9%)", + "oklch": "oklch(0.44,0.01,286)", "rgbChannel": "82 82 91", "hslChannel": "240 5.2% 33.9%" }, @@ -258,6 +289,7 @@ "hex": "#3f3f46", "rgb": "rgb(63,63,70)", "hsl": "hsl(240,5.3%,26.1%)", + "oklch": "oklch(0.37,0.01,286)", "rgbChannel": "63 63 70", "hslChannel": "240 5.3% 26.1%" }, @@ -266,6 +298,7 @@ "hex": "#27272a", "rgb": "rgb(39,39,42)", "hsl": "hsl(240,3.7%,15.9%)", + "oklch": "oklch(0.27,0.01,286)", "rgbChannel": "39 39 42", "hslChannel": "240 3.7% 15.9%" }, @@ -274,6 +307,7 @@ "hex": "#18181b", "rgb": "rgb(24,24,27)", "hsl": "hsl(240,5.9%,10%)", + "oklch": "oklch(0.21,0.01,286)", "rgbChannel": "24 24 27", "hslChannel": "240 5.9% 10%" }, @@ -282,6 +316,7 @@ "hex": "#09090b", "rgb": "rgb(9,9,11)", "hsl": "hsl(240,10%,3.9%)", + "oklch": "oklch(0.14,0.00,286)", "rgbChannel": "9 9 11", "hslChannel": "240 10% 3.9%" } @@ -292,6 +327,7 @@ "hex": "#fafafa", "rgb": "rgb(250,250,250)", "hsl": "hsl(0,0%,98%)", + "oklch": "oklch(0.99,0.00,0)", "rgbChannel": "250 250 250", "hslChannel": "0 0% 98%" }, @@ -300,6 +336,7 @@ "hex": "#f5f5f5", "rgb": "rgb(245,245,245)", "hsl": "hsl(0,0%,96.1%)", + "oklch": "oklch(0.97,0.00,0)", "rgbChannel": "245 245 245", "hslChannel": "0 0% 96.1%" }, @@ -308,6 +345,7 @@ "hex": "#e5e5e5", "rgb": "rgb(229,229,229)", "hsl": "hsl(0,0%,89.8%)", + "oklch": "oklch(0.92,0.00,0)", "rgbChannel": "229 229 229", "hslChannel": "0 0% 89.8%" }, @@ -316,6 +354,7 @@ "hex": "#d4d4d4", "rgb": "rgb(212,212,212)", "hsl": "hsl(0,0%,83.1%)", + "oklch": "oklch(0.87,0.00,0)", "rgbChannel": "212 212 212", "hslChannel": "0 0% 83.1%" }, @@ -324,6 +363,7 @@ "hex": "#a3a3a3", "rgb": "rgb(163,163,163)", "hsl": "hsl(0,0%,63.9%)", + "oklch": "oklch(0.72,0.00,0)", "rgbChannel": "163 163 163", "hslChannel": "0 0% 63.9%" }, @@ -332,6 +372,7 @@ "hex": "#737373", "rgb": "rgb(115,115,115)", "hsl": "hsl(0,0%,45.1%)", + "oklch": "oklch(0.56,0.00,0)", "rgbChannel": "115 115 115", "hslChannel": "0 0% 45.1%" }, @@ -340,6 +381,7 @@ "hex": "#525252", "rgb": "rgb(82,82,82)", "hsl": "hsl(0,0%,32.2%)", + "oklch": "oklch(0.44,0.00,0)", "rgbChannel": "82 82 82", "hslChannel": "0 0% 32.2%" }, @@ -348,6 +390,7 @@ "hex": "#404040", "rgb": "rgb(64,64,64)", "hsl": "hsl(0,0%,25.1%)", + "oklch": "oklch(0.37,0.00,0)", "rgbChannel": "64 64 64", "hslChannel": "0 0% 25.1%" }, @@ -356,6 +399,7 @@ "hex": "#262626", "rgb": "rgb(38,38,38)", "hsl": "hsl(0,0%,14.9%)", + "oklch": "oklch(0.27,0.00,0)", "rgbChannel": "38 38 38", "hslChannel": "0 0% 14.9%" }, @@ -364,6 +408,7 @@ "hex": "#171717", "rgb": "rgb(23,23,23)", "hsl": "hsl(0,0%,9%)", + "oklch": "oklch(0.20,0.00,0)", "rgbChannel": "23 23 23", "hslChannel": "0 0% 9%" }, @@ -372,6 +417,7 @@ "hex": "#0a0a0a", "rgb": "rgb(10,10,10)", "hsl": "hsl(0,0%,3.9%)", + "oklch": "oklch(0.14,0.00,0)", "rgbChannel": "10 10 10", "hslChannel": "0 0% 3.9%" } @@ -382,6 +428,7 @@ "hex": "#fafaf9", "rgb": "rgb(250,250,249)", "hsl": "hsl(60,9.1%,97.8%)", + "oklch": "oklch(0.98,0.00,106)", "rgbChannel": "250 250 249", "hslChannel": "60 9.1% 97.8%" }, @@ -390,6 +437,7 @@ "hex": "#f5f5f4", "rgb": "rgb(245,245,244)", "hsl": "hsl(60,4.8%,95.9%)", + "oklch": "oklch(0.97,0.00,106)", "rgbChannel": "245 245 244", "hslChannel": "60 4.8% 95.9%" }, @@ -398,6 +446,7 @@ "hex": "#e7e5e4", "rgb": "rgb(231,229,228)", "hsl": "hsl(20,5.9%,90%)", + "oklch": "oklch(0.92,0.00,49)", "rgbChannel": "231 229 228", "hslChannel": "20 5.9% 90%" }, @@ -406,6 +455,7 @@ "hex": "#d6d3d1", "rgb": "rgb(214,211,209)", "hsl": "hsl(24,5.7%,82.9%)", + "oklch": "oklch(0.87,0.00,56)", "rgbChannel": "214 211 209", "hslChannel": "24 5.7% 82.9%" }, @@ -414,6 +464,7 @@ "hex": "#a8a29e", "rgb": "rgb(168,162,158)", "hsl": "hsl(24,5.4%,63.9%)", + "oklch": "oklch(0.72,0.01,56)", "rgbChannel": "168 162 158", "hslChannel": "24 5.4% 63.9%" }, @@ -422,6 +473,7 @@ "hex": "#78716c", "rgb": "rgb(120,113,108)", "hsl": "hsl(25,5.3%,44.7%)", + "oklch": "oklch(0.55,0.01,58)", "rgbChannel": "120 113 108", "hslChannel": "25 5.3% 44.7%" }, @@ -430,6 +482,7 @@ "hex": "#57534e", "rgb": "rgb(87,83,78)", "hsl": "hsl(33.3,5.5%,32.4%)", + "oklch": "oklch(0.44,0.01,74)", "rgbChannel": "87 83 78", "hslChannel": "33.3 5.5% 32.4%" }, @@ -438,6 +491,7 @@ "hex": "#44403c", "rgb": "rgb(68,64,60)", "hsl": "hsl(30,6.3%,25.1%)", + "oklch": "oklch(0.37,0.01,68)", "rgbChannel": "68 64 60", "hslChannel": "30 6.3% 25.1%" }, @@ -446,6 +500,7 @@ "hex": "#292524", "rgb": "rgb(41,37,36)", "hsl": "hsl(12,6.5%,15.1%)", + "oklch": "oklch(0.27,0.01,34)", "rgbChannel": "41 37 36", "hslChannel": "12 6.5% 15.1%" }, @@ -454,6 +509,7 @@ "hex": "#1c1917", "rgb": "rgb(28,25,23)", "hsl": "hsl(24,9.8%,10%)", + "oklch": "oklch(0.22,0.01,56)", "rgbChannel": "28 25 23", "hslChannel": "24 9.8% 10%" }, @@ -462,6 +518,7 @@ "hex": "#0c0a09", "rgb": "rgb(12,10,9)", "hsl": "hsl(20,14.3%,4.1%)", + "oklch": "oklch(0.15,0.00,49)", "rgbChannel": "12 10 9", "hslChannel": "20 14.3% 4.1%" } @@ -472,6 +529,7 @@ "hex": "#fef2f2", "rgb": "rgb(254,242,242)", "hsl": "hsl(0,85.7%,97.3%)", + "oklch": "oklch(0.97,0.01,17)", "rgbChannel": "254 242 242", "hslChannel": "0 85.7% 97.3%" }, @@ -480,6 +538,7 @@ "hex": "#fee2e2", "rgb": "rgb(254,226,226)", "hsl": "hsl(0,93.3%,94.1%)", + "oklch": "oklch(0.94,0.03,18)", "rgbChannel": "254 226 226", "hslChannel": "0 93.3% 94.1%" }, @@ -488,6 +547,7 @@ "hex": "#fecaca", "rgb": "rgb(254,202,202)", "hsl": "hsl(0,96.3%,89.4%)", + "oklch": "oklch(0.88,0.06,18)", "rgbChannel": "254 202 202", "hslChannel": "0 96.3% 89.4%" }, @@ -496,6 +556,7 @@ "hex": "#fca5a5", "rgb": "rgb(252,165,165)", "hsl": "hsl(0,93.5%,81.8%)", + "oklch": "oklch(0.81,0.10,20)", "rgbChannel": "252 165 165", "hslChannel": "0 93.5% 81.8%" }, @@ -504,6 +565,7 @@ "hex": "#f87171", "rgb": "rgb(248,113,113)", "hsl": "hsl(0,90.6%,70.8%)", + "oklch": "oklch(0.71,0.17,22)", "rgbChannel": "248 113 113", "hslChannel": "0 90.6% 70.8%" }, @@ -512,6 +574,7 @@ "hex": "#ef4444", "rgb": "rgb(239,68,68)", "hsl": "hsl(0,84.2%,60.2%)", + "oklch": "oklch(0.64,0.21,25)", "rgbChannel": "239 68 68", "hslChannel": "0 84.2% 60.2%" }, @@ -520,6 +583,7 @@ "hex": "#dc2626", "rgb": "rgb(220,38,38)", "hsl": "hsl(0,72.2%,50.6%)", + "oklch": "oklch(0.58,0.22,27)", "rgbChannel": "220 38 38", "hslChannel": "0 72.2% 50.6%" }, @@ -528,6 +592,7 @@ "hex": "#b91c1c", "rgb": "rgb(185,28,28)", "hsl": "hsl(0,73.7%,41.8%)", + "oklch": "oklch(0.51,0.19,28)", "rgbChannel": "185 28 28", "hslChannel": "0 73.7% 41.8%" }, @@ -536,6 +601,7 @@ "hex": "#991b1b", "rgb": "rgb(153,27,27)", "hsl": "hsl(0,70%,35.3%)", + "oklch": "oklch(0.44,0.16,27)", "rgbChannel": "153 27 27", "hslChannel": "0 70% 35.3%" }, @@ -544,6 +610,7 @@ "hex": "#7f1d1d", "rgb": "rgb(127,29,29)", "hsl": "hsl(0,62.8%,30.6%)", + "oklch": "oklch(0.40,0.13,26)", "rgbChannel": "127 29 29", "hslChannel": "0 62.8% 30.6%" }, @@ -552,6 +619,7 @@ "hex": "#450a0a", "rgb": "rgb(69,10,10)", "hsl": "hsl(0,74.7%,15.5%)", + "oklch": "oklch(0.26,0.09,26)", "rgbChannel": "69 10 10", "hslChannel": "0 74.7% 15.5%" } @@ -562,6 +630,7 @@ "hex": "#fff7ed", "rgb": "rgb(255,247,237)", "hsl": "hsl(33.3,100%,96.5%)", + "oklch": "oklch(0.98,0.02,74)", "rgbChannel": "255 247 237", "hslChannel": "33.3 100% 96.5%" }, @@ -570,6 +639,7 @@ "hex": "#ffedd5", "rgb": "rgb(255,237,213)", "hsl": "hsl(34.3,100%,91.8%)", + "oklch": "oklch(0.95,0.04,75)", "rgbChannel": "255 237 213", "hslChannel": "34.3 100% 91.8%" }, @@ -578,6 +648,7 @@ "hex": "#fed7aa", "rgb": "rgb(254,215,170)", "hsl": "hsl(32.1,97.7%,83.1%)", + "oklch": "oklch(0.90,0.07,71)", "rgbChannel": "254 215 170", "hslChannel": "32.1 97.7% 83.1%" }, @@ -586,6 +657,7 @@ "hex": "#fdba74", "rgb": "rgb(253,186,116)", "hsl": "hsl(30.7,97.2%,72.4%)", + "oklch": "oklch(0.84,0.12,66)", "rgbChannel": "253 186 116", "hslChannel": "30.7 97.2% 72.4%" }, @@ -594,6 +666,7 @@ "hex": "#fb923c", "rgb": "rgb(251,146,60)", "hsl": "hsl(27,96%,61%)", + "oklch": "oklch(0.76,0.16,56)", "rgbChannel": "251 146 60", "hslChannel": "27 96% 61%" }, @@ -602,6 +675,7 @@ "hex": "#f97316", "rgb": "rgb(249,115,22)", "hsl": "hsl(24.6,95%,53.1%)", + "oklch": "oklch(0.70,0.19,48)", "rgbChannel": "249 115 22", "hslChannel": "24.6 95% 53.1%" }, @@ -610,6 +684,7 @@ "hex": "#ea580c", "rgb": "rgb(234,88,12)", "hsl": "hsl(20.5,90.2%,48.2%)", + "oklch": "oklch(0.65,0.19,41)", "rgbChannel": "234 88 12", "hslChannel": "20.5 90.2% 48.2%" }, @@ -618,6 +693,7 @@ "hex": "#c2410c", "rgb": "rgb(194,65,12)", "hsl": "hsl(17.5,88.3%,40.4%)", + "oklch": "oklch(0.55,0.17,38)", "rgbChannel": "194 65 12", "hslChannel": "17.5 88.3% 40.4%" }, @@ -626,6 +702,7 @@ "hex": "#9a3412", "rgb": "rgb(154,52,18)", "hsl": "hsl(15,79.1%,33.7%)", + "oklch": "oklch(0.47,0.14,37)", "rgbChannel": "154 52 18", "hslChannel": "15 79.1% 33.7%" }, @@ -634,6 +711,7 @@ "hex": "#7c2d12", "rgb": "rgb(124,45,18)", "hsl": "hsl(15.3,74.6%,27.8%)", + "oklch": "oklch(0.41,0.12,38)", "rgbChannel": "124 45 18", "hslChannel": "15.3 74.6% 27.8%" }, @@ -642,6 +720,7 @@ "hex": "#431407", "rgb": "rgb(67,20,7)", "hsl": "hsl(13,81.1%,14.5%)", + "oklch": "oklch(0.27,0.08,36)", "rgbChannel": "67 20 7", "hslChannel": "13 81.1% 14.5%" } @@ -652,6 +731,7 @@ "hex": "#fffbeb", "rgb": "rgb(255,251,235)", "hsl": "hsl(48,100%,96.1%)", + "oklch": "oklch(0.99,0.02,95)", "rgbChannel": "255 251 235", "hslChannel": "48 100% 96.1%" }, @@ -660,6 +740,7 @@ "hex": "#fef3c7", "rgb": "rgb(254,243,199)", "hsl": "hsl(48,96.5%,88.8%)", + "oklch": "oklch(0.96,0.06,96)", "rgbChannel": "254 243 199", "hslChannel": "48 96.5% 88.8%" }, @@ -668,6 +749,7 @@ "hex": "#fde68a", "rgb": "rgb(253,230,138)", "hsl": "hsl(48,96.6%,76.7%)", + "oklch": "oklch(0.92,0.12,96)", "rgbChannel": "253 230 138", "hslChannel": "48 96.6% 76.7%" }, @@ -676,6 +758,7 @@ "hex": "#fcd34d", "rgb": "rgb(252,211,77)", "hsl": "hsl(45.9,96.7%,64.5%)", + "oklch": "oklch(0.88,0.15,92)", "rgbChannel": "252 211 77", "hslChannel": "45.9 96.7% 64.5%" }, @@ -684,6 +767,7 @@ "hex": "#fbbf24", "rgb": "rgb(251,191,36)", "hsl": "hsl(43.3,96.4%,56.3%)", + "oklch": "oklch(0.84,0.16,84)", "rgbChannel": "251 191 36", "hslChannel": "43.3 96.4% 56.3%" }, @@ -692,6 +776,7 @@ "hex": "#f59e0b", "rgb": "rgb(245,158,11)", "hsl": "hsl(37.7,92.1%,50.2%)", + "oklch": "oklch(0.77,0.16,70)", "rgbChannel": "245 158 11", "hslChannel": "37.7 92.1% 50.2%" }, @@ -700,6 +785,7 @@ "hex": "#d97706", "rgb": "rgb(217,119,6)", "hsl": "hsl(32.1,94.6%,43.7%)", + "oklch": "oklch(0.67,0.16,58)", "rgbChannel": "217 119 6", "hslChannel": "32.1 94.6% 43.7%" }, @@ -708,6 +794,7 @@ "hex": "#b45309", "rgb": "rgb(180,83,9)", "hsl": "hsl(26,90.5%,37.1%)", + "oklch": "oklch(0.56,0.15,49)", "rgbChannel": "180 83 9", "hslChannel": "26 90.5% 37.1%" }, @@ -716,6 +803,7 @@ "hex": "#92400e", "rgb": "rgb(146,64,14)", "hsl": "hsl(22.7,82.5%,31.4%)", + "oklch": "oklch(0.47,0.12,46)", "rgbChannel": "146 64 14", "hslChannel": "22.7 82.5% 31.4%" }, @@ -724,6 +812,7 @@ "hex": "#78350f", "rgb": "rgb(120,53,15)", "hsl": "hsl(21.7,77.8%,26.5%)", + "oklch": "oklch(0.41,0.11,46)", "rgbChannel": "120 53 15", "hslChannel": "21.7 77.8% 26.5%" }, @@ -732,6 +821,7 @@ "hex": "#451a03", "rgb": "rgb(69,26,3)", "hsl": "hsl(20.9,91.7%,14.1%)", + "oklch": "oklch(0.28,0.07,46)", "rgbChannel": "69 26 3", "hslChannel": "20.9 91.7% 14.1%" } @@ -742,6 +832,7 @@ "hex": "#fefce8", "rgb": "rgb(254,252,232)", "hsl": "hsl(54.5,91.7%,95.3%)", + "oklch": "oklch(0.99,0.03,102)", "rgbChannel": "254 252 232", "hslChannel": "54.5 91.7% 95.3%" }, @@ -750,6 +841,7 @@ "hex": "#fef9c3", "rgb": "rgb(254,249,195)", "hsl": "hsl(54.9,96.7%,88%)", + "oklch": "oklch(0.97,0.07,103)", "rgbChannel": "254 249 195", "hslChannel": "54.9 96.7% 88%" }, @@ -758,6 +850,7 @@ "hex": "#fef08a", "rgb": "rgb(254,240,138)", "hsl": "hsl(52.8,98.3%,76.9%)", + "oklch": "oklch(0.95,0.12,102)", "rgbChannel": "254 240 138", "hslChannel": "52.8 98.3% 76.9%" }, @@ -766,6 +859,7 @@ "hex": "#fde047", "rgb": "rgb(253,224,71)", "hsl": "hsl(50.4,97.8%,63.5%)", + "oklch": "oklch(0.91,0.17,98)", "rgbChannel": "253 224 71", "hslChannel": "50.4 97.8% 63.5%" }, @@ -774,6 +868,7 @@ "hex": "#facc15", "rgb": "rgb(250,204,21)", "hsl": "hsl(47.9,95.8%,53.1%)", + "oklch": "oklch(0.86,0.17,92)", "rgbChannel": "250 204 21", "hslChannel": "47.9 95.8% 53.1%" }, @@ -782,6 +877,7 @@ "hex": "#eab308", "rgb": "rgb(234,179,8)", "hsl": "hsl(45.4,93.4%,47.5%)", + "oklch": "oklch(0.80,0.16,86)", "rgbChannel": "234 179 8", "hslChannel": "45.4 93.4% 47.5%" }, @@ -790,6 +886,7 @@ "hex": "#ca8a04", "rgb": "rgb(202,138,4)", "hsl": "hsl(40.6,96.1%,40.4%)", + "oklch": "oklch(0.68,0.14,76)", "rgbChannel": "202 138 4", "hslChannel": "40.6 96.1% 40.4%" }, @@ -798,6 +895,7 @@ "hex": "#a16207", "rgb": "rgb(161,98,7)", "hsl": "hsl(35.5,91.7%,32.9%)", + "oklch": "oklch(0.55,0.12,66)", "rgbChannel": "161 98 7", "hslChannel": "35.5 91.7% 32.9%" }, @@ -806,6 +904,7 @@ "hex": "#854d0e", "rgb": "rgb(133,77,14)", "hsl": "hsl(31.8,81%,28.8%)", + "oklch": "oklch(0.48,0.10,62)", "rgbChannel": "133 77 14", "hslChannel": "31.8 81% 28.8%" }, @@ -814,6 +913,7 @@ "hex": "#713f12", "rgb": "rgb(113,63,18)", "hsl": "hsl(28.4,72.5%,25.7%)", + "oklch": "oklch(0.42,0.09,58)", "rgbChannel": "113 63 18", "hslChannel": "28.4 72.5% 25.7%" }, @@ -822,6 +922,7 @@ "hex": "#422006", "rgb": "rgb(66,32,6)", "hsl": "hsl(26,83.3%,14.1%)", + "oklch": "oklch(0.29,0.06,54)", "rgbChannel": "66 32 6", "hslChannel": "26 83.3% 14.1%" } @@ -832,6 +933,7 @@ "hex": "#f7fee7", "rgb": "rgb(247,254,231)", "hsl": "hsl(78.3,92%,95.1%)", + "oklch": "oklch(0.99,0.03,121)", "rgbChannel": "247 254 231", "hslChannel": "78.3 92% 95.1%" }, @@ -840,6 +942,7 @@ "hex": "#ecfccb", "rgb": "rgb(236,252,203)", "hsl": "hsl(79.6,89.1%,89.2%)", + "oklch": "oklch(0.97,0.07,122)", "rgbChannel": "236 252 203", "hslChannel": "79.6 89.1% 89.2%" }, @@ -848,6 +951,7 @@ "hex": "#d9f99d", "rgb": "rgb(217,249,157)", "hsl": "hsl(80.9,88.5%,79.6%)", + "oklch": "oklch(0.94,0.12,124)", "rgbChannel": "217 249 157", "hslChannel": "80.9 88.5% 79.6%" }, @@ -856,6 +960,7 @@ "hex": "#bef264", "rgb": "rgb(190,242,100)", "hsl": "hsl(82,84.5%,67.1%)", + "oklch": "oklch(0.90,0.18,127)", "rgbChannel": "190 242 100", "hslChannel": "82 84.5% 67.1%" }, @@ -864,6 +969,7 @@ "hex": "#a3e635", "rgb": "rgb(163,230,53)", "hsl": "hsl(82.7,78%,55.5%)", + "oklch": "oklch(0.85,0.21,129)", "rgbChannel": "163 230 53", "hslChannel": "82.7 78% 55.5%" }, @@ -872,6 +978,7 @@ "hex": "#84cc16", "rgb": "rgb(132,204,22)", "hsl": "hsl(83.7,80.5%,44.3%)", + "oklch": "oklch(0.77,0.20,131)", "rgbChannel": "132 204 22", "hslChannel": "83.7 80.5% 44.3%" }, @@ -880,6 +987,7 @@ "hex": "#65a30d", "rgb": "rgb(101,163,13)", "hsl": "hsl(84.8,85.2%,34.5%)", + "oklch": "oklch(0.65,0.18,132)", "rgbChannel": "101 163 13", "hslChannel": "84.8 85.2% 34.5%" }, @@ -888,6 +996,7 @@ "hex": "#4d7c0f", "rgb": "rgb(77,124,15)", "hsl": "hsl(85.9,78.4%,27.3%)", + "oklch": "oklch(0.53,0.14,132)", "rgbChannel": "77 124 15", "hslChannel": "85.9 78.4% 27.3%" }, @@ -896,6 +1005,7 @@ "hex": "#3f6212", "rgb": "rgb(63,98,18)", "hsl": "hsl(86.3,69%,22.7%)", + "oklch": "oklch(0.45,0.11,131)", "rgbChannel": "63 98 18", "hslChannel": "86.3 69% 22.7%" }, @@ -904,6 +1014,7 @@ "hex": "#365314", "rgb": "rgb(54,83,20)", "hsl": "hsl(87.6,61.2%,20.2%)", + "oklch": "oklch(0.41,0.10,131)", "rgbChannel": "54 83 20", "hslChannel": "87.6 61.2% 20.2%" }, @@ -912,6 +1023,7 @@ "hex": "#1a2e05", "rgb": "rgb(26,46,5)", "hsl": "hsl(89.3,80.4%,10%)", + "oklch": "oklch(0.27,0.07,132)", "rgbChannel": "26 46 5", "hslChannel": "89.3 80.4% 10%" } @@ -922,6 +1034,7 @@ "hex": "#f0fdf4", "rgb": "rgb(240,253,244)", "hsl": "hsl(138.5,76.5%,96.7%)", + "oklch": "oklch(0.98,0.02,156)", "rgbChannel": "240 253 244", "hslChannel": "138.5 76.5% 96.7%" }, @@ -930,6 +1043,7 @@ "hex": "#dcfce7", "rgb": "rgb(220,252,231)", "hsl": "hsl(140.6,84.2%,92.5%)", + "oklch": "oklch(0.96,0.04,157)", "rgbChannel": "220 252 231", "hslChannel": "140.6 84.2% 92.5%" }, @@ -938,6 +1052,7 @@ "hex": "#bbf7d0", "rgb": "rgb(187,247,208)", "hsl": "hsl(141,78.9%,85.1%)", + "oklch": "oklch(0.93,0.08,156)", "rgbChannel": "187 247 208", "hslChannel": "141 78.9% 85.1%" }, @@ -946,6 +1061,7 @@ "hex": "#86efac", "rgb": "rgb(134,239,172)", "hsl": "hsl(141.7,76.6%,73.1%)", + "oklch": "oklch(0.87,0.14,154)", "rgbChannel": "134 239 172", "hslChannel": "141.7 76.6% 73.1%" }, @@ -954,6 +1070,7 @@ "hex": "#4ade80", "rgb": "rgb(74,222,128)", "hsl": "hsl(141.9,69.2%,58%)", + "oklch": "oklch(0.80,0.18,152)", "rgbChannel": "74 222 128", "hslChannel": "141.9 69.2% 58%" }, @@ -962,6 +1079,7 @@ "hex": "#22c55e", "rgb": "rgb(34,197,94)", "hsl": "hsl(142.1,70.6%,45.3%)", + "oklch": "oklch(0.72,0.19,150)", "rgbChannel": "34 197 94", "hslChannel": "142.1 70.6% 45.3%" }, @@ -970,6 +1088,7 @@ "hex": "#16a34a", "rgb": "rgb(22,163,74)", "hsl": "hsl(142.1,76.2%,36.3%)", + "oklch": "oklch(0.63,0.17,149)", "rgbChannel": "22 163 74", "hslChannel": "142.1 76.2% 36.3%" }, @@ -978,6 +1097,7 @@ "hex": "#15803d", "rgb": "rgb(21,128,61)", "hsl": "hsl(142.4,71.8%,29.2%)", + "oklch": "oklch(0.53,0.14,150)", "rgbChannel": "21 128 61", "hslChannel": "142.4 71.8% 29.2%" }, @@ -986,6 +1106,7 @@ "hex": "#166534", "rgb": "rgb(22,101,52)", "hsl": "hsl(142.8,64.2%,24.1%)", + "oklch": "oklch(0.45,0.11,151)", "rgbChannel": "22 101 52", "hslChannel": "142.8 64.2% 24.1%" }, @@ -994,6 +1115,7 @@ "hex": "#14532d", "rgb": "rgb(20,83,45)", "hsl": "hsl(143.8,61.2%,20.2%)", + "oklch": "oklch(0.39,0.09,153)", "rgbChannel": "20 83 45", "hslChannel": "143.8 61.2% 20.2%" }, @@ -1002,6 +1124,7 @@ "hex": "#052e16", "rgb": "rgb(5,46,22)", "hsl": "hsl(144.9,80.4%,10%)", + "oklch": "oklch(0.27,0.06,153)", "rgbChannel": "5 46 22", "hslChannel": "144.9 80.4% 10%" } @@ -1012,6 +1135,7 @@ "hex": "#ecfdf5", "rgb": "rgb(236,253,245)", "hsl": "hsl(151.8,81%,95.9%)", + "oklch": "oklch(0.98,0.02,166)", "rgbChannel": "236 253 245", "hslChannel": "151.8 81% 95.9%" }, @@ -1020,6 +1144,7 @@ "hex": "#d1fae5", "rgb": "rgb(209,250,229)", "hsl": "hsl(149.3,80.4%,90%)", + "oklch": "oklch(0.95,0.05,163)", "rgbChannel": "209 250 229", "hslChannel": "149.3 80.4% 90%" }, @@ -1028,6 +1153,7 @@ "hex": "#a7f3d0", "rgb": "rgb(167,243,208)", "hsl": "hsl(152.4,76%,80.4%)", + "oklch": "oklch(0.90,0.09,164)", "rgbChannel": "167 243 208", "hslChannel": "152.4 76% 80.4%" }, @@ -1036,6 +1162,7 @@ "hex": "#6ee7b7", "rgb": "rgb(110,231,183)", "hsl": "hsl(156.2,71.6%,66.9%)", + "oklch": "oklch(0.85,0.13,165)", "rgbChannel": "110 231 183", "hslChannel": "156.2 71.6% 66.9%" }, @@ -1044,6 +1171,7 @@ "hex": "#34d399", "rgb": "rgb(52,211,153)", "hsl": "hsl(158.1,64.4%,51.6%)", + "oklch": "oklch(0.77,0.15,163)", "rgbChannel": "52 211 153", "hslChannel": "158.1 64.4% 51.6%" }, @@ -1052,6 +1180,7 @@ "hex": "#10b981", "rgb": "rgb(16,185,129)", "hsl": "hsl(160.1,84.1%,39.4%)", + "oklch": "oklch(0.70,0.15,162)", "rgbChannel": "16 185 129", "hslChannel": "160.1 84.1% 39.4%" }, @@ -1060,6 +1189,7 @@ "hex": "#059669", "rgb": "rgb(5,150,105)", "hsl": "hsl(161.4,93.5%,30.4%)", + "oklch": "oklch(0.60,0.13,163)", "rgbChannel": "5 150 105", "hslChannel": "161.4 93.5% 30.4%" }, @@ -1068,6 +1198,7 @@ "hex": "#047857", "rgb": "rgb(4,120,87)", "hsl": "hsl(162.9,93.5%,24.3%)", + "oklch": "oklch(0.51,0.10,166)", "rgbChannel": "4 120 87", "hslChannel": "162.9 93.5% 24.3%" }, @@ -1076,6 +1207,7 @@ "hex": "#065f46", "rgb": "rgb(6,95,70)", "hsl": "hsl(163.1,88.1%,19.8%)", + "oklch": "oklch(0.43,0.09,167)", "rgbChannel": "6 95 70", "hslChannel": "163.1 88.1% 19.8%" }, @@ -1084,6 +1216,7 @@ "hex": "#064e3b", "rgb": "rgb(6,78,59)", "hsl": "hsl(164.2,85.7%,16.5%)", + "oklch": "oklch(0.38,0.07,169)", "rgbChannel": "6 78 59", "hslChannel": "164.2 85.7% 16.5%" }, @@ -1092,6 +1225,7 @@ "hex": "#022c22", "rgb": "rgb(2,44,34)", "hsl": "hsl(165.7,91.3%,9%)", + "oklch": "oklch(0.26,0.05,173)", "rgbChannel": "2 44 34", "hslChannel": "165.7 91.3% 9%" } @@ -1102,6 +1236,7 @@ "hex": "#f0fdfa", "rgb": "rgb(240,253,250)", "hsl": "hsl(166.2,76.5%,96.7%)", + "oklch": "oklch(0.98,0.01,181)", "rgbChannel": "240 253 250", "hslChannel": "166.2 76.5% 96.7%" }, @@ -1110,6 +1245,7 @@ "hex": "#ccfbf1", "rgb": "rgb(204,251,241)", "hsl": "hsl(167.2,85.5%,89.2%)", + "oklch": "oklch(0.95,0.05,181)", "rgbChannel": "204 251 241", "hslChannel": "167.2 85.5% 89.2%" }, @@ -1118,6 +1254,7 @@ "hex": "#99f6e4", "rgb": "rgb(153,246,228)", "hsl": "hsl(168.4,83.8%,78.2%)", + "oklch": "oklch(0.91,0.09,180)", "rgbChannel": "153 246 228", "hslChannel": "168.4 83.8% 78.2%" }, @@ -1126,6 +1263,7 @@ "hex": "#5eead4", "rgb": "rgb(94,234,212)", "hsl": "hsl(170.6,76.9%,64.3%)", + "oklch": "oklch(0.85,0.13,181)", "rgbChannel": "94 234 212", "hslChannel": "170.6 76.9% 64.3%" }, @@ -1134,6 +1272,7 @@ "hex": "#2dd4bf", "rgb": "rgb(45,212,191)", "hsl": "hsl(172.5,66%,50.4%)", + "oklch": "oklch(0.78,0.13,182)", "rgbChannel": "45 212 191", "hslChannel": "172.5 66% 50.4%" }, @@ -1142,6 +1281,7 @@ "hex": "#14b8a6", "rgb": "rgb(20,184,166)", "hsl": "hsl(173.4,80.4%,40%)", + "oklch": "oklch(0.70,0.12,183)", "rgbChannel": "20 184 166", "hslChannel": "173.4 80.4% 40%" }, @@ -1150,6 +1290,7 @@ "hex": "#0d9488", "rgb": "rgb(13,148,136)", "hsl": "hsl(174.7,83.9%,31.6%)", + "oklch": "oklch(0.60,0.10,185)", "rgbChannel": "13 148 136", "hslChannel": "174.7 83.9% 31.6%" }, @@ -1158,6 +1299,7 @@ "hex": "#0f766e", "rgb": "rgb(15,118,110)", "hsl": "hsl(175.3,77.4%,26.1%)", + "oklch": "oklch(0.51,0.09,186)", "rgbChannel": "15 118 110", "hslChannel": "175.3 77.4% 26.1%" }, @@ -1166,6 +1308,7 @@ "hex": "#115e59", "rgb": "rgb(17,94,89)", "hsl": "hsl(176.1,69.4%,21.8%)", + "oklch": "oklch(0.44,0.07,188)", "rgbChannel": "17 94 89", "hslChannel": "176.1 69.4% 21.8%" }, @@ -1174,6 +1317,7 @@ "hex": "#134e4a", "rgb": "rgb(19,78,74)", "hsl": "hsl(175.9,60.8%,19%)", + "oklch": "oklch(0.39,0.06,188)", "rgbChannel": "19 78 74", "hslChannel": "175.9 60.8% 19%" }, @@ -1182,6 +1326,7 @@ "hex": "#042f2e", "rgb": "rgb(4,47,46)", "hsl": "hsl(178.6,84.3%,10%)", + "oklch": "oklch(0.28,0.04,193)", "rgbChannel": "4 47 46", "hslChannel": "178.6 84.3% 10%" } @@ -1192,6 +1337,7 @@ "hex": "#ecfeff", "rgb": "rgb(236,254,255)", "hsl": "hsl(183.2,100%,96.3%)", + "oklch": "oklch(0.98,0.02,201)", "rgbChannel": "236 254 255", "hslChannel": "183.2 100% 96.3%" }, @@ -1200,6 +1346,7 @@ "hex": "#cffafe", "rgb": "rgb(207,250,254)", "hsl": "hsl(185.1,95.9%,90.4%)", + "oklch": "oklch(0.96,0.04,203)", "rgbChannel": "207 250 254", "hslChannel": "185.1 95.9% 90.4%" }, @@ -1208,6 +1355,7 @@ "hex": "#a5f3fc", "rgb": "rgb(165,243,252)", "hsl": "hsl(186.2,93.5%,81.8%)", + "oklch": "oklch(0.92,0.08,205)", "rgbChannel": "165 243 252", "hslChannel": "186.2 93.5% 81.8%" }, @@ -1216,6 +1364,7 @@ "hex": "#67e8f9", "rgb": "rgb(103,232,249)", "hsl": "hsl(187,92.4%,69%)", + "oklch": "oklch(0.87,0.12,207)", "rgbChannel": "103 232 249", "hslChannel": "187 92.4% 69%" }, @@ -1224,6 +1373,7 @@ "hex": "#22d3ee", "rgb": "rgb(34,211,238)", "hsl": "hsl(187.9,85.7%,53.3%)", + "oklch": "oklch(0.80,0.13,212)", "rgbChannel": "34 211 238", "hslChannel": "187.9 85.7% 53.3%" }, @@ -1232,6 +1382,7 @@ "hex": "#06b6d4", "rgb": "rgb(6,182,212)", "hsl": "hsl(188.7,94.5%,42.7%)", + "oklch": "oklch(0.71,0.13,215)", "rgbChannel": "6 182 212", "hslChannel": "188.7 94.5% 42.7%" }, @@ -1240,6 +1391,7 @@ "hex": "#0891b2", "rgb": "rgb(8,145,178)", "hsl": "hsl(191.6,91.4%,36.5%)", + "oklch": "oklch(0.61,0.11,222)", "rgbChannel": "8 145 178", "hslChannel": "191.6 91.4% 36.5%" }, @@ -1248,6 +1400,7 @@ "hex": "#0e7490", "rgb": "rgb(14,116,144)", "hsl": "hsl(192.9,82.3%,31%)", + "oklch": "oklch(0.52,0.09,223)", "rgbChannel": "14 116 144", "hslChannel": "192.9 82.3% 31%" }, @@ -1256,6 +1409,7 @@ "hex": "#155e75", "rgb": "rgb(21,94,117)", "hsl": "hsl(194.4,69.6%,27.1%)", + "oklch": "oklch(0.45,0.08,224)", "rgbChannel": "21 94 117", "hslChannel": "194.4 69.6% 27.1%" }, @@ -1264,6 +1418,7 @@ "hex": "#164e63", "rgb": "rgb(22,78,99)", "hsl": "hsl(196.4,63.6%,23.7%)", + "oklch": "oklch(0.40,0.07,227)", "rgbChannel": "22 78 99", "hslChannel": "196.4 63.6% 23.7%" }, @@ -1272,6 +1427,7 @@ "hex": "#083344", "rgb": "rgb(8,51,68)", "hsl": "hsl(197,78.9%,14.9%)", + "oklch": "oklch(0.30,0.05,230)", "rgbChannel": "8 51 68", "hslChannel": "197 78.9% 14.9%" } @@ -1282,6 +1438,7 @@ "hex": "#f0f9ff", "rgb": "rgb(240,249,255)", "hsl": "hsl(204,100%,97.1%)", + "oklch": "oklch(0.98,0.01,237)", "rgbChannel": "240 249 255", "hslChannel": "204 100% 97.1%" }, @@ -1290,6 +1447,7 @@ "hex": "#e0f2fe", "rgb": "rgb(224,242,254)", "hsl": "hsl(204,93.8%,93.7%)", + "oklch": "oklch(0.95,0.03,237)", "rgbChannel": "224 242 254", "hslChannel": "204 93.8% 93.7%" }, @@ -1298,6 +1456,7 @@ "hex": "#bae6fd", "rgb": "rgb(186,230,253)", "hsl": "hsl(200.6,94.4%,86.1%)", + "oklch": "oklch(0.90,0.06,231)", "rgbChannel": "186 230 253", "hslChannel": "200.6 94.4% 86.1%" }, @@ -1306,6 +1465,7 @@ "hex": "#7dd3fc", "rgb": "rgb(125,211,252)", "hsl": "hsl(199.4,95.5%,73.9%)", + "oklch": "oklch(0.83,0.10,230)", "rgbChannel": "125 211 252", "hslChannel": "199.4 95.5% 73.9%" }, @@ -1314,6 +1474,7 @@ "hex": "#38bdf8", "rgb": "rgb(56,189,248)", "hsl": "hsl(198.4,93.2%,59.6%)", + "oklch": "oklch(0.75,0.14,233)", "rgbChannel": "56 189 248", "hslChannel": "198.4 93.2% 59.6%" }, @@ -1322,6 +1483,7 @@ "hex": "#0ea5e9", "rgb": "rgb(14,165,233)", "hsl": "hsl(198.6,88.7%,48.4%)", + "oklch": "oklch(0.68,0.15,237)", "rgbChannel": "14 165 233", "hslChannel": "198.6 88.7% 48.4%" }, @@ -1330,6 +1492,7 @@ "hex": "#0284c7", "rgb": "rgb(2,132,199)", "hsl": "hsl(200.4,98%,39.4%)", + "oklch": "oklch(0.59,0.14,242)", "rgbChannel": "2 132 199", "hslChannel": "200.4 98% 39.4%" }, @@ -1338,6 +1501,7 @@ "hex": "#0369a1", "rgb": "rgb(3,105,161)", "hsl": "hsl(201.3,96.3%,32.2%)", + "oklch": "oklch(0.50,0.12,243)", "rgbChannel": "3 105 161", "hslChannel": "201.3 96.3% 32.2%" }, @@ -1346,6 +1510,7 @@ "hex": "#075985", "rgb": "rgb(7,89,133)", "hsl": "hsl(201,90%,27.5%)", + "oklch": "oklch(0.44,0.10,241)", "rgbChannel": "7 89 133", "hslChannel": "201 90% 27.5%" }, @@ -1354,6 +1519,7 @@ "hex": "#0c4a6e", "rgb": "rgb(12,74,110)", "hsl": "hsl(202,80.3%,23.9%)", + "oklch": "oklch(0.39,0.08,241)", "rgbChannel": "12 74 110", "hslChannel": "202 80.3% 23.9%" }, @@ -1362,6 +1528,7 @@ "hex": "#082f49", "rgb": "rgb(8,47,73)", "hsl": "hsl(204,80.2%,15.9%)", + "oklch": "oklch(0.29,0.06,243)", "rgbChannel": "8 47 73", "hslChannel": "204 80.2% 15.9%" } @@ -1372,6 +1539,7 @@ "hex": "#eff6ff", "rgb": "rgb(239,246,255)", "hsl": "hsl(213.8,100%,96.9%)", + "oklch": "oklch(0.97,0.01,255)", "rgbChannel": "239 246 255", "hslChannel": "213.8 100% 96.9%" }, @@ -1380,6 +1548,7 @@ "hex": "#dbeafe", "rgb": "rgb(219,234,254)", "hsl": "hsl(214.3,94.6%,92.7%)", + "oklch": "oklch(0.93,0.03,256)", "rgbChannel": "219 234 254", "hslChannel": "214.3 94.6% 92.7%" }, @@ -1388,6 +1557,7 @@ "hex": "#bfdbfe", "rgb": "rgb(191,219,254)", "hsl": "hsl(213.3,96.9%,87.3%)", + "oklch": "oklch(0.88,0.06,254)", "rgbChannel": "191 219 254", "hslChannel": "213.3 96.9% 87.3%" }, @@ -1396,6 +1566,7 @@ "hex": "#93c5fd", "rgb": "rgb(147,197,253)", "hsl": "hsl(211.7,96.4%,78.4%)", + "oklch": "oklch(0.81,0.10,252)", "rgbChannel": "147 197 253", "hslChannel": "211.7 96.4% 78.4%" }, @@ -1404,6 +1575,7 @@ "hex": "#60a5fa", "rgb": "rgb(96,165,250)", "hsl": "hsl(213.1,93.9%,67.8%)", + "oklch": "oklch(0.71,0.14,255)", "rgbChannel": "96 165 250", "hslChannel": "213.1 93.9% 67.8%" }, @@ -1412,6 +1584,7 @@ "hex": "#3b82f6", "rgb": "rgb(59,130,246)", "hsl": "hsl(217.2,91.2%,59.8%)", + "oklch": "oklch(0.62,0.19,260)", "rgbChannel": "59 130 246", "hslChannel": "217.2 91.2% 59.8%" }, @@ -1420,6 +1593,7 @@ "hex": "#2563eb", "rgb": "rgb(37,99,235)", "hsl": "hsl(221.2,83.2%,53.3%)", + "oklch": "oklch(0.55,0.22,263)", "rgbChannel": "37 99 235", "hslChannel": "221.2 83.2% 53.3%" }, @@ -1428,6 +1602,7 @@ "hex": "#1d4ed8", "rgb": "rgb(29,78,216)", "hsl": "hsl(224.3,76.3%,48%)", + "oklch": "oklch(0.49,0.22,264)", "rgbChannel": "29 78 216", "hslChannel": "224.3 76.3% 48%" }, @@ -1436,6 +1611,7 @@ "hex": "#1e40af", "rgb": "rgb(30,64,175)", "hsl": "hsl(225.9,70.7%,40.2%)", + "oklch": "oklch(0.42,0.18,266)", "rgbChannel": "30 64 175", "hslChannel": "225.9 70.7% 40.2%" }, @@ -1444,6 +1620,7 @@ "hex": "#1e3a8a", "rgb": "rgb(30,58,138)", "hsl": "hsl(224.4,64.3%,32.9%)", + "oklch": "oklch(0.38,0.14,266)", "rgbChannel": "30 58 138", "hslChannel": "224.4 64.3% 32.9%" }, @@ -1452,6 +1629,7 @@ "hex": "#172554", "rgb": "rgb(23,37,84)", "hsl": "hsl(226.2,57%,21%)", + "oklch": "oklch(0.28,0.09,268)", "rgbChannel": "23 37 84", "hslChannel": "226.2 57% 21%" } @@ -1462,6 +1640,7 @@ "hex": "#eef2ff", "rgb": "rgb(238,242,255)", "hsl": "hsl(225.9,100%,96.7%)", + "oklch": "oklch(0.96,0.02,272)", "rgbChannel": "238 242 255", "hslChannel": "225.9 100% 96.7%" }, @@ -1470,6 +1649,7 @@ "hex": "#e0e7ff", "rgb": "rgb(224,231,255)", "hsl": "hsl(226.5,100%,93.9%)", + "oklch": "oklch(0.93,0.03,273)", "rgbChannel": "224 231 255", "hslChannel": "226.5 100% 93.9%" }, @@ -1478,6 +1658,7 @@ "hex": "#c7d2fe", "rgb": "rgb(199,210,254)", "hsl": "hsl(228,96.5%,88.8%)", + "oklch": "oklch(0.87,0.06,274)", "rgbChannel": "199 210 254", "hslChannel": "228 96.5% 88.8%" }, @@ -1486,6 +1667,7 @@ "hex": "#a5b4fc", "rgb": "rgb(165,180,252)", "hsl": "hsl(229.7,93.5%,81.8%)", + "oklch": "oklch(0.79,0.10,275)", "rgbChannel": "165 180 252", "hslChannel": "229.7 93.5% 81.8%" }, @@ -1494,6 +1676,7 @@ "hex": "#818cf8", "rgb": "rgb(129,140,248)", "hsl": "hsl(234.5,89.5%,73.9%)", + "oklch": "oklch(0.68,0.16,277)", "rgbChannel": "129 140 248", "hslChannel": "234.5 89.5% 73.9%" }, @@ -1502,6 +1685,7 @@ "hex": "#6366f1", "rgb": "rgb(99,102,241)", "hsl": "hsl(238.7,83.5%,66.7%)", + "oklch": "oklch(0.59,0.20,277)", "rgbChannel": "99 102 241", "hslChannel": "238.7 83.5% 66.7%" }, @@ -1510,6 +1694,7 @@ "hex": "#4f46e5", "rgb": "rgb(79,70,229)", "hsl": "hsl(243.4,75.4%,58.6%)", + "oklch": "oklch(0.51,0.23,277)", "rgbChannel": "79 70 229", "hslChannel": "243.4 75.4% 58.6%" }, @@ -1518,6 +1703,7 @@ "hex": "#4338ca", "rgb": "rgb(67,56,202)", "hsl": "hsl(244.5,57.9%,50.6%)", + "oklch": "oklch(0.46,0.21,277)", "rgbChannel": "67 56 202", "hslChannel": "244.5 57.9% 50.6%" }, @@ -1526,6 +1712,7 @@ "hex": "#3730a3", "rgb": "rgb(55,48,163)", "hsl": "hsl(243.7,54.5%,41.4%)", + "oklch": "oklch(0.40,0.18,277)", "rgbChannel": "55 48 163", "hslChannel": "243.7 54.5% 41.4%" }, @@ -1534,6 +1721,7 @@ "hex": "#312e81", "rgb": "rgb(49,46,129)", "hsl": "hsl(242.2,47.4%,34.3%)", + "oklch": "oklch(0.36,0.14,279)", "rgbChannel": "49 46 129", "hslChannel": "242.2 47.4% 34.3%" }, @@ -1542,6 +1730,7 @@ "hex": "#1e1b4b", "rgb": "rgb(30,27,75)", "hsl": "hsl(243.8,47.1%,20%)", + "oklch": "oklch(0.26,0.09,281)", "rgbChannel": "30 27 75", "hslChannel": "243.8 47.1% 20%" } @@ -1552,6 +1741,7 @@ "hex": "#f5f3ff", "rgb": "rgb(245,243,255)", "hsl": "hsl(250,100%,97.6%)", + "oklch": "oklch(0.97,0.02,294)", "rgbChannel": "245 243 255", "hslChannel": "250 100% 97.6%" }, @@ -1560,6 +1750,7 @@ "hex": "#ede9fe", "rgb": "rgb(237,233,254)", "hsl": "hsl(251.4,91.3%,95.5%)", + "oklch": "oklch(0.94,0.03,295)", "rgbChannel": "237 233 254", "hslChannel": "251.4 91.3% 95.5%" }, @@ -1568,6 +1759,7 @@ "hex": "#ddd6fe", "rgb": "rgb(221,214,254)", "hsl": "hsl(250.5,95.2%,91.8%)", + "oklch": "oklch(0.89,0.05,293)", "rgbChannel": "221 214 254", "hslChannel": "250.5 95.2% 91.8%" }, @@ -1576,6 +1768,7 @@ "hex": "#c4b5fd", "rgb": "rgb(196,181,253)", "hsl": "hsl(252.5,94.7%,85.1%)", + "oklch": "oklch(0.81,0.10,294)", "rgbChannel": "196 181 253", "hslChannel": "252.5 94.7% 85.1%" }, @@ -1584,6 +1777,7 @@ "hex": "#a78bfa", "rgb": "rgb(167,139,250)", "hsl": "hsl(255.1,91.7%,76.3%)", + "oklch": "oklch(0.71,0.16,294)", "rgbChannel": "167 139 250", "hslChannel": "255.1 91.7% 76.3%" }, @@ -1592,6 +1786,7 @@ "hex": "#8b5cf6", "rgb": "rgb(139,92,246)", "hsl": "hsl(258.3,89.5%,66.3%)", + "oklch": "oklch(0.61,0.22,293)", "rgbChannel": "139 92 246", "hslChannel": "258.3 89.5% 66.3%" }, @@ -1600,6 +1795,7 @@ "hex": "#7c3aed", "rgb": "rgb(124,58,237)", "hsl": "hsl(262.1,83.3%,57.8%)", + "oklch": "oklch(0.54,0.25,293)", "rgbChannel": "124 58 237", "hslChannel": "262.1 83.3% 57.8%" }, @@ -1608,6 +1804,7 @@ "hex": "#6d28d9", "rgb": "rgb(109,40,217)", "hsl": "hsl(263.4,70%,50.4%)", + "oklch": "oklch(0.49,0.24,293)", "rgbChannel": "109 40 217", "hslChannel": "263.4 70% 50.4%" }, @@ -1616,6 +1813,7 @@ "hex": "#5b21b6", "rgb": "rgb(91,33,182)", "hsl": "hsl(263.4,69.3%,42.2%)", + "oklch": "oklch(0.43,0.21,293)", "rgbChannel": "91 33 182", "hslChannel": "263.4 69.3% 42.2%" }, @@ -1624,6 +1822,7 @@ "hex": "#4c1d95", "rgb": "rgb(76,29,149)", "hsl": "hsl(263.5,67.4%,34.9%)", + "oklch": "oklch(0.38,0.18,294)", "rgbChannel": "76 29 149", "hslChannel": "263.5 67.4% 34.9%" }, @@ -1632,6 +1831,7 @@ "hex": "#1e1b4b", "rgb": "rgb(46,16,101)", "hsl": "hsl(261.2,72.6%,22.9%)", + "oklch": "oklch(0.28,0.14,291)", "rgbChannel": "46 16 101", "hslChannel": "261.2 72.6% 22.9%" } @@ -1642,6 +1842,7 @@ "hex": "#faf5ff", "rgb": "rgb(250,245,255)", "hsl": "hsl(270,100%,98%)", + "oklch": "oklch(0.98,0.01,308)", "rgbChannel": "250 245 255", "hslChannel": "270 100% 98%" }, @@ -1650,6 +1851,7 @@ "hex": "#f3e8ff", "rgb": "rgb(243,232,255)", "hsl": "hsl(268.7,100%,95.5%)", + "oklch": "oklch(0.95,0.03,307)", "rgbChannel": "243 232 255", "hslChannel": "268.7 100% 95.5%" }, @@ -1658,6 +1860,7 @@ "hex": "#e9d5ff", "rgb": "rgb(233,213,255)", "hsl": "hsl(268.6,100%,91.8%)", + "oklch": "oklch(0.90,0.06,307)", "rgbChannel": "233 213 255", "hslChannel": "268.6 100% 91.8%" }, @@ -1666,6 +1869,7 @@ "hex": "#d8b4fe", "rgb": "rgb(216,180,254)", "hsl": "hsl(269.2,97.4%,85.1%)", + "oklch": "oklch(0.83,0.11,306)", "rgbChannel": "216 180 254", "hslChannel": "269.2 97.4% 85.1%" }, @@ -1674,6 +1878,7 @@ "hex": "#c084fc", "rgb": "rgb(192,132,252)", "hsl": "hsl(270,95.2%,75.3%)", + "oklch": "oklch(0.72,0.18,306)", "rgbChannel": "192 132 252", "hslChannel": "270 95.2% 75.3%" }, @@ -1682,6 +1887,7 @@ "hex": "#a855f7", "rgb": "rgb(168,85,247)", "hsl": "hsl(270.7,91%,65.1%)", + "oklch": "oklch(0.63,0.23,304)", "rgbChannel": "168 85 247", "hslChannel": "270.7 91% 65.1%" }, @@ -1690,6 +1896,7 @@ "hex": "#9333ea", "rgb": "rgb(147,51,234)", "hsl": "hsl(271.5,81.3%,55.9%)", + "oklch": "oklch(0.56,0.25,302)", "rgbChannel": "147 51 234", "hslChannel": "271.5 81.3% 55.9%" }, @@ -1698,6 +1905,7 @@ "hex": "#7e22ce", "rgb": "rgb(126,34,206)", "hsl": "hsl(272.1,71.7%,47.1%)", + "oklch": "oklch(0.50,0.24,302)", "rgbChannel": "126 34 206", "hslChannel": "272.1 71.7% 47.1%" }, @@ -1706,6 +1914,7 @@ "hex": "#6b21a8", "rgb": "rgb(107,33,168)", "hsl": "hsl(272.9,67.2%,39.4%)", + "oklch": "oklch(0.44,0.20,304)", "rgbChannel": "107 33 168", "hslChannel": "272.9 67.2% 39.4%" }, @@ -1714,6 +1923,7 @@ "hex": "#581c87", "rgb": "rgb(88,28,135)", "hsl": "hsl(273.6,65.6%,32%)", + "oklch": "oklch(0.38,0.17,305)", "rgbChannel": "88 28 135", "hslChannel": "273.6 65.6% 32%" }, @@ -1722,6 +1932,7 @@ "hex": "#3b0764", "rgb": "rgb(59,7,100)", "hsl": "hsl(273.5,86.9%,21%)", + "oklch": "oklch(0.29,0.14,303)", "rgbChannel": "59 7 100", "hslChannel": "273.5 86.9% 21%" } @@ -1732,6 +1943,7 @@ "hex": "#fdf4ff", "rgb": "rgb(253,244,255)", "hsl": "hsl(289.1,100%,97.8%)", + "oklch": "oklch(0.98,0.02,320)", "rgbChannel": "253 244 255", "hslChannel": "289.1 100% 97.8%" }, @@ -1740,6 +1952,7 @@ "hex": "#fae8ff", "rgb": "rgb(250,232,255)", "hsl": "hsl(287,100%,95.5%)", + "oklch": "oklch(0.95,0.04,319)", "rgbChannel": "250 232 255", "hslChannel": "287 100% 95.5%" }, @@ -1748,6 +1961,7 @@ "hex": "#f5d0fe", "rgb": "rgb(245,208,254)", "hsl": "hsl(288.3,95.8%,90.6%)", + "oklch": "oklch(0.90,0.07,320)", "rgbChannel": "245 208 254", "hslChannel": "288.3 95.8% 90.6%" }, @@ -1756,6 +1970,7 @@ "hex": "#f0abfc", "rgb": "rgb(240,171,252)", "hsl": "hsl(291.1,93.1%,82.9%)", + "oklch": "oklch(0.83,0.13,321)", "rgbChannel": "240 171 252", "hslChannel": "291.1 93.1% 82.9%" }, @@ -1764,6 +1979,7 @@ "hex": "#e879f9", "rgb": "rgb(232,121,249)", "hsl": "hsl(292,91.4%,72.5%)", + "oklch": "oklch(0.75,0.21,322)", "rgbChannel": "232 121 249", "hslChannel": "292 91.4% 72.5%" }, @@ -1772,6 +1988,7 @@ "hex": "#d946ef", "rgb": "rgb(217,70,239)", "hsl": "hsl(292.2,84.1%,60.6%)", + "oklch": "oklch(0.67,0.26,322)", "rgbChannel": "217 70 239", "hslChannel": "292.2 84.1% 60.6%" }, @@ -1780,6 +1997,7 @@ "hex": "#c026d3", "rgb": "rgb(192,38,211)", "hsl": "hsl(293.4,69.5%,48.8%)", + "oklch": "oklch(0.59,0.26,323)", "rgbChannel": "192 38 211", "hslChannel": "293.4 69.5% 48.8%" }, @@ -1788,6 +2006,7 @@ "hex": "#a21caf", "rgb": "rgb(162,28,175)", "hsl": "hsl(294.7,72.4%,39.8%)", + "oklch": "oklch(0.52,0.23,324)", "rgbChannel": "162 28 175", "hslChannel": "294.7 72.4% 39.8%" }, @@ -1796,6 +2015,7 @@ "hex": "#86198f", "rgb": "rgb(134,25,143)", "hsl": "hsl(295.4,70.2%,32.9%)", + "oklch": "oklch(0.45,0.19,325)", "rgbChannel": "134 25 143", "hslChannel": "295.4 70.2% 32.9%" }, @@ -1804,6 +2024,7 @@ "hex": "#701a75", "rgb": "rgb(112,26,117)", "hsl": "hsl(296.7,63.6%,28%)", + "oklch": "oklch(0.40,0.16,326)", "rgbChannel": "112 26 117", "hslChannel": "296.7 63.6% 28%" }, @@ -1812,6 +2033,7 @@ "hex": "#4a044e", "rgb": "rgb(74,4,78)", "hsl": "hsl(296.8,90.2%,16.1%)", + "oklch": "oklch(0.29,0.13,326)", "rgbChannel": "74 4 78", "hslChannel": "296.8 90.2% 16.1%" } @@ -1822,6 +2044,7 @@ "hex": "#fdf2f8", "rgb": "rgb(253,242,248)", "hsl": "hsl(327.3,73.3%,97.1%)", + "oklch": "oklch(0.97,0.01,343)", "rgbChannel": "253 242 248", "hslChannel": "327.3 73.3% 97.1%" }, @@ -1830,6 +2053,7 @@ "hex": "#fce7f3", "rgb": "rgb(252,231,243)", "hsl": "hsl(325.7,77.8%,94.7%)", + "oklch": "oklch(0.95,0.03,342)", "rgbChannel": "252 231 243", "hslChannel": "325.7 77.8% 94.7%" }, @@ -1838,6 +2062,7 @@ "hex": "#fbcfe8", "rgb": "rgb(251,207,232)", "hsl": "hsl(325.9,84.6%,89.8%)", + "oklch": "oklch(0.90,0.06,343)", "rgbChannel": "251 207 232", "hslChannel": "325.9 84.6% 89.8%" }, @@ -1846,6 +2071,7 @@ "hex": "#f9a8d4", "rgb": "rgb(249,168,212)", "hsl": "hsl(327.4,87.1%,81.8%)", + "oklch": "oklch(0.82,0.11,346)", "rgbChannel": "249 168 212", "hslChannel": "327.4 87.1% 81.8%" }, @@ -1854,6 +2080,7 @@ "hex": "#f472b6", "rgb": "rgb(244,114,182)", "hsl": "hsl(328.6,85.5%,70.2%)", + "oklch": "oklch(0.73,0.18,350)", "rgbChannel": "244 114 182", "hslChannel": "328.6 85.5% 70.2%" }, @@ -1862,6 +2089,7 @@ "hex": "#ec4899", "rgb": "rgb(236,72,153)", "hsl": "hsl(330.4,81.2%,60.4%)", + "oklch": "oklch(0.66,0.21,354)", "rgbChannel": "236 72 153", "hslChannel": "330.4 81.2% 60.4%" }, @@ -1870,6 +2098,7 @@ "hex": "#db2777", "rgb": "rgb(219,39,119)", "hsl": "hsl(333.3,71.4%,50.6%)", + "oklch": "oklch(0.59,0.22,1)", "rgbChannel": "219 39 119", "hslChannel": "333.3 71.4% 50.6%" }, @@ -1878,6 +2107,7 @@ "hex": "#be185d", "rgb": "rgb(190,24,93)", "hsl": "hsl(335.1,77.6%,42%)", + "oklch": "oklch(0.52,0.20,4)", "rgbChannel": "190 24 93", "hslChannel": "335.1 77.6% 42%" }, @@ -1886,6 +2116,7 @@ "hex": "#9d174d", "rgb": "rgb(157,23,77)", "hsl": "hsl(335.8,74.4%,35.3%)", + "oklch": "oklch(0.46,0.17,4)", "rgbChannel": "157 23 77", "hslChannel": "335.8 74.4% 35.3%" }, @@ -1894,6 +2125,7 @@ "hex": "#831843", "rgb": "rgb(131,24,67)", "hsl": "hsl(335.9,69%,30.4%)", + "oklch": "oklch(0.41,0.14,2)", "rgbChannel": "131 24 67", "hslChannel": "335.9 69% 30.4%" }, @@ -1902,6 +2134,7 @@ "hex": "#500724", "rgb": "rgb(80,7,36)", "hsl": "hsl(336.2,83.9%,17.1%)", + "oklch": "oklch(0.28,0.10,4)", "rgbChannel": "80 7 36", "hslChannel": "336.2 83.9% 17.1%" } @@ -1912,6 +2145,7 @@ "hex": "#fff1f2", "rgb": "rgb(255,241,242)", "hsl": "hsl(355.7,100%,97.3%)", + "oklch": "oklch(0.97,0.02,12)", "rgbChannel": "255 241 242", "hslChannel": "355.7 100% 97.3%" }, @@ -1920,6 +2154,7 @@ "hex": "#ffe4e6", "rgb": "rgb(255,228,230)", "hsl": "hsl(355.6,100%,94.7%)", + "oklch": "oklch(0.94,0.03,13)", "rgbChannel": "255 228 230", "hslChannel": "355.6 100% 94.7%" }, @@ -1928,6 +2163,7 @@ "hex": "#fecdd3", "rgb": "rgb(254,205,211)", "hsl": "hsl(352.7,96.1%,90%)", + "oklch": "oklch(0.89,0.06,10)", "rgbChannel": "254 205 211", "hslChannel": "352.7 96.1% 90%" }, @@ -1936,6 +2172,7 @@ "hex": "#fda4af", "rgb": "rgb(253,164,175)", "hsl": "hsl(352.6,95.7%,81.8%)", + "oklch": "oklch(0.81,0.11,12)", "rgbChannel": "253 164 175", "hslChannel": "352.6 95.7% 81.8%" }, @@ -1944,6 +2181,7 @@ "hex": "#fb7185", "rgb": "rgb(251,113,133)", "hsl": "hsl(351.3,94.5%,71.4%)", + "oklch": "oklch(0.72,0.17,13)", "rgbChannel": "251 113 133", "hslChannel": "351.3 94.5% 71.4%" }, @@ -1952,6 +2190,7 @@ "hex": "#f43f5e", "rgb": "rgb(244,63,94)", "hsl": "hsl(349.7,89.2%,60.2%)", + "oklch": "oklch(0.65,0.22,16)", "rgbChannel": "244 63 94", "hslChannel": "349.7 89.2% 60.2%" }, @@ -1960,6 +2199,7 @@ "hex": "#e11d48", "rgb": "rgb(225,29,72)", "hsl": "hsl(346.8,77.2%,49.8%)", + "oklch": "oklch(0.59,0.22,18)", "rgbChannel": "225 29 72", "hslChannel": "346.8 77.2% 49.8%" }, @@ -1968,6 +2208,7 @@ "hex": "#be123c", "rgb": "rgb(190,18,60)", "hsl": "hsl(345.3,82.7%,40.8%)", + "oklch": "oklch(0.51,0.20,17)", "rgbChannel": "190 18 60", "hslChannel": "345.3 82.7% 40.8%" }, @@ -1976,6 +2217,7 @@ "hex": "#9f1239", "rgb": "rgb(159,18,57)", "hsl": "hsl(343.4,79.7%,34.7%)", + "oklch": "oklch(0.45,0.17,14)", "rgbChannel": "159 18 57", "hslChannel": "343.4 79.7% 34.7%" }, @@ -1984,6 +2226,7 @@ "hex": "#881337", "rgb": "rgb(136,19,55)", "hsl": "hsl(341.5,75.5%,30.4%)", + "oklch": "oklch(0.41,0.15,10)", "rgbChannel": "136 19 55", "hslChannel": "341.5 75.5% 30.4%" }, @@ -1992,6 +2235,7 @@ "hex": "#4c0519", "rgb": "rgb(76,5,25)", "hsl": "hsl(343.1,87.7%,15.9%)", + "oklch": "oklch(0.27,0.10,12)", "rgbChannel": "76 5 25", "hslChannel": "343.1 87.7% 15.9%" } diff --git a/apps/www/public/r/styles/default/stepper-demo.json b/apps/www/public/r/styles/default/stepper-demo.json index fc5b662b963..6a48974d5c2 100644 --- a/apps/www/public/r/styles/default/stepper-demo.json +++ b/apps/www/public/r/styles/default/stepper-demo.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-demo.tsx", - "content": "import {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperDemo() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n
\n ))}\n
\n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n
\n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-description.json b/apps/www/public/r/styles/default/stepper-description.json index 6a110c6f99d..4cfbf2201b0 100644 --- a/apps/www/public/r/styles/default/stepper-description.json +++ b/apps/www/public/r/styles/default/stepper-description.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-description.tsx", - "content": "import {\n Stepper,\n StepperAction,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n description: \"This is the first step\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n description: \"This is the second step\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n description: \"This is the third step\",\n }\n)\n\nexport default function StepperDemo() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {step.description}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n description: \"This is the first step\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n description: \"This is the second step\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n description: \"This is the third step\",\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {step.description}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-form.json b/apps/www/public/r/styles/default/stepper-form.json index 5d6a43cce8d..4f6a19a2c84 100644 --- a/apps/www/public/r/styles/default/stepper-form.json +++ b/apps/www/public/r/styles/default/stepper-form.json @@ -10,7 +10,7 @@ "files": [ { "path": "examples/stepper-form.tsx", - "content": "import { zodResolver } from \"@hookform/resolvers/zod\"\nimport { useForm, useFormContext } from \"react-hook-form\"\nimport { z } from \"zod\"\n\nimport { Form } from \"@/registry/default/ui/form\"\nimport { Input } from \"@/registry/default/ui/input\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst shippingSchema = z.object({\n address: z.string().min(1, \"Address is required\"),\n city: z.string().min(1, \"City is required\"),\n postalCode: z.string().min(5, \"Postal code is required\"),\n})\n\nconst paymentSchema = z.object({\n cardNumber: z.string().min(16, \"Card number is required\"),\n expirationDate: z.string().min(5, \"Expiration date is required\"),\n cvv: z.string().min(3, \"CVV is required\"),\n})\n\ntype ShippingFormValues = z.infer\ntype PaymentFormValues = z.infer\n\nconst stepperInstance = defineStepper(\n {\n id: \"shipping\",\n title: \"Shipping\",\n schema: shippingSchema,\n },\n {\n id: \"payment\",\n title: \"Payment\",\n schema: paymentSchema,\n },\n {\n id: \"complete\",\n title: \"Complete\",\n schema: z.object({}),\n }\n)\n\nexport default function StepperForm() {\n return (\n \n \n \n )\n}\n\nconst FormStepperComponent = () => {\n const { steps, useStepper, utils } = stepperInstance\n const methods = useStepper()\n\n const form = useForm({\n mode: \"onTouched\",\n resolver: zodResolver(methods.current.schema),\n })\n\n const onSubmit = (values: z.infer) => {\n console.log(`Form values for step ${methods.current.id}:`, values)\n }\n\n const currentIndex = utils.getIndex(methods.current.id)\n\n return (\n
\n \n \n {steps.map((step) => (\n {\n const valid = await form.trigger()\n if (!valid) return\n if (utils.getIndex(step.id) - currentIndex > 1) return\n methods.goTo(step.id)\n }}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n shipping: () => ,\n payment: () => ,\n complete: () => ,\n })}\n \n Previous\n {\n const valid = await form.trigger()\n if (!valid) return false\n if (utils.getIndex(nextStep.id as any) - currentIndex > 1)\n return false\n return true\n }}\n >\n Next\n \n Reset\n \n \n \n )\n}\n\nconst ShippingForm = () => {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Address\n \n \n {errors.address && (\n \n {errors.address.message}\n \n )}\n
\n
\n \n City\n \n \n {errors.city && (\n \n {errors.city.message}\n \n )}\n
\n
\n \n Postal Code\n \n \n {errors.postalCode && (\n \n {errors.postalCode.message}\n \n )}\n
\n
\n )\n}\n\nfunction PaymentForm() {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Card Number\n \n \n {errors.cardNumber && (\n \n {errors.cardNumber.message}\n \n )}\n
\n
\n \n Expiration Date\n \n \n {errors.expirationDate && (\n \n {errors.expirationDate.message}\n \n )}\n
\n
\n \n CVV\n \n \n {errors.cvv && (\n {errors.cvv.message}\n )}\n
\n
\n )\n}\n\nfunction CompleteComponent() {\n return
Thank you! Your order is complete.
\n}\n", + "content": "import * as React from \"react\"\nimport { zodResolver } from \"@hookform/resolvers/zod\"\nimport { useForm, useFormContext } from \"react-hook-form\"\nimport { z } from \"zod\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Form } from \"@/registry/default/ui/form\"\nimport { Input } from \"@/registry/default/ui/input\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst shippingSchema = z.object({\n address: z.string().min(1, \"Address is required\"),\n city: z.string().min(1, \"City is required\"),\n postalCode: z.string().min(5, \"Postal code is required\"),\n})\n\nconst paymentSchema = z.object({\n cardNumber: z.string().min(16, \"Card number is required\"),\n expirationDate: z.string().min(5, \"Expiration date is required\"),\n cvv: z.string().min(3, \"CVV is required\"),\n})\n\ntype ShippingFormValues = z.infer\ntype PaymentFormValues = z.infer\n\nconst ShippingForm = () => {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Address\n \n \n {errors.address && (\n \n {errors.address.message}\n \n )}\n
\n
\n \n City\n \n \n {errors.city && (\n \n {errors.city.message}\n \n )}\n
\n
\n \n Postal Code\n \n \n {errors.postalCode && (\n \n {errors.postalCode.message}\n \n )}\n
\n
\n )\n}\n\nfunction PaymentForm() {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Card Number\n \n \n {errors.cardNumber && (\n \n {errors.cardNumber.message}\n \n )}\n
\n
\n \n Expiration Date\n \n \n {errors.expirationDate && (\n \n {errors.expirationDate.message}\n \n )}\n
\n
\n \n CVV\n \n \n {errors.cvv && (\n {errors.cvv.message}\n )}\n
\n
\n )\n}\n\nfunction CompleteComponent() {\n return
Thank you! Your order is complete.
\n}\n\nconst stepperInstance = defineStepper(\n {\n id: \"shipping\",\n title: \"Shipping\",\n schema: shippingSchema,\n Component: ShippingForm,\n },\n {\n id: \"payment\",\n title: \"Payment\",\n schema: paymentSchema,\n Component: PaymentForm,\n },\n {\n id: \"complete\",\n title: \"Complete\",\n schema: z.object({}),\n Component: CompleteComponent,\n }\n)\n\nexport default function StepperForm() {\n return (\n \n \n \n )\n}\n\nconst FormStepperComponent = () => {\n const { useStepper } = stepperInstance\n const methods = useStepper()\n\n const form = useForm({\n mode: \"onTouched\",\n resolver: zodResolver(methods.current.schema),\n })\n\n const onSubmit = (values: z.infer) => {\n console.log(`Form values for step ${methods.current.id}:`, values)\n }\n\n return (\n
\n \n \n {methods.all.map((step) => (\n {\n const valid = await form.trigger()\n if (!valid) return\n methods.goTo(step.id)\n }}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n shipping: ({ Component }) => ,\n payment: ({ Component }) => ,\n complete: ({ Component }) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n {\n if (methods.isLast) {\n return methods.reset()\n }\n methods.beforeNext(async () => {\n const valid = await form.trigger()\n if (!valid) return false\n return true\n })\n }}\n >\n {methods.isLast ? \"Reset\" : \"Next\"}\n \n \n \n \n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-icon.json b/apps/www/public/r/styles/default/stepper-icon.json index fe6947c6478..c31631c523a 100644 --- a/apps/www/public/r/styles/default/stepper-icon.json +++ b/apps/www/public/r/styles/default/stepper-icon.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-icon.tsx", - "content": "import { HomeIcon, SettingsIcon, UserIcon } from \"lucide-react\"\n\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n icon: ,\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n icon: ,\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n icon: ,\n }\n)\n\nexport default function StepperIcon() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n icon={step.icon}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\nimport { HomeIcon, SettingsIcon, UserIcon } from \"lucide-react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n icon: ,\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n icon: ,\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n icon: ,\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n icon={step.icon}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-label-orientation.json b/apps/www/public/r/styles/default/stepper-label-orientation.json index 8a3a1ec6800..52552c2870c 100644 --- a/apps/www/public/r/styles/default/stepper-label-orientation.json +++ b/apps/www/public/r/styles/default/stepper-label-orientation.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-label-orientation.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\ntype LabelOrientation = \"horizontal\" | \"vertical\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const steps = stepperInstance.steps\n\n const [labelOrientation, setLabelOrientation] =\n React.useState(\"horizontal\")\n return (\n
\n \n setLabelOrientation(value as LabelOrientation)\n }\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\ntype LabelOrientation = \"horizontal\" | \"vertical\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const [labelOrientation, setLabelOrientation] =\n React.useState(\"horizontal\")\n return (\n
\n \n setLabelOrientation(value as LabelOrientation)\n }\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n
\n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-responsive-variant.json b/apps/www/public/r/styles/default/stepper-responsive-variant.json index d223e5cff32..1d212773ace 100644 --- a/apps/www/public/r/styles/default/stepper-responsive-variant.json +++ b/apps/www/public/r/styles/default/stepper-responsive-variant.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-responsive-variant.tsx", - "content": "import { useMediaQuery } from \"@/hooks/use-media-query\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperResponsiveVariant() {\n const steps = stepperInstance.steps\n const isMobile = useMediaQuery(\"(max-width: 768px)\")\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {isMobile && (\n \n {({ step }) => (\n

\n Content for {step.id}\n

\n )}\n \n )}\n \n ))}\n
\n {!isMobile &&\n steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { useMediaQuery } from \"@/hooks/use-media-query\"\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperResponsiveVariant() {\n const isMobile = useMediaQuery(\"(max-width: 768px)\")\n return (\n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {isMobile &&\n methods.when(step.id, (step) => (\n \n

\n Content for {step.id}\n

\n
\n ))}\n \n ))}\n
\n {!isMobile &&\n methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-tracking.json b/apps/www/public/r/styles/default/stepper-tracking.json index 6bc678c8290..332fb48efd2 100644 --- a/apps/www/public/r/styles/default/stepper-tracking.json +++ b/apps/www/public/r/styles/default/stepper-tracking.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-tracking.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n },\n {\n id: \"step-4\",\n title: \"Step 4\",\n },\n {\n id: \"step-5\",\n title: \"Step 5\",\n },\n {\n id: \"step-6\",\n title: \"Step 6\",\n }\n)\n\nexport default function StepperVerticalFollow() {\n const steps = stepperInstance.steps\n\n const [tracking, setTracking] = React.useState(false)\n return (\n
\n setTracking(value === \"true\")}\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n
\n

\n Content for {step.id}\n

\n
\n \n Previous\n Next\n Reset\n \n
\n \n ))}\n
\n \n )}\n \n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n },\n {\n id: \"step-4\",\n title: \"Step 4\",\n },\n {\n id: \"step-5\",\n title: \"Step 5\",\n },\n {\n id: \"step-6\",\n title: \"Step 6\",\n }\n)\n\nexport default function StepperVerticalFollow() {\n const [tracking, setTracking] = React.useState(false)\n return (\n
\n setTracking(value === \"true\")}\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {methods.when(step.id, () => (\n \n
\n

\n Content for {step.id}\n

\n
\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n {methods.isLast ? \"Reset\" : \"Next\"}\n \n \n
\n ))}\n \n ))}\n
\n \n )}\n \n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper-variants.json b/apps/www/public/r/styles/default/stepper-variants.json index 3e5ee2c4c88..7a72008bdcd 100644 --- a/apps/www/public/r/styles/default/stepper-variants.json +++ b/apps/www/public/r/styles/default/stepper-variants.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-variants.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\ntype Variant = \"horizontal\" | \"vertical\" | \"circle\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const steps = stepperInstance.steps\n\n const [variant, setVariant] = React.useState(\"horizontal\")\n return (\n
\n setVariant(value as Variant)}\n >\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n \n {variant === \"horizontal\" && }\n {variant === \"vertical\" && }\n {variant === \"circle\" && }\n
\n )\n}\n\nconst HorizontalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n\nconst VerticalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n \n ))}\n
\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n\nconst CircleStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n \n {methods.current.title}\n \n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/default/ui/button\"\nimport { Label } from \"@/registry/default/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/default/ui/stepper\"\n\ntype Variant = \"horizontal\" | \"vertical\" | \"circle\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const [variant, setVariant] = React.useState(\"horizontal\")\n return (\n
\n setVariant(value as Variant)}\n >\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n \n {variant === \"horizontal\" && }\n {variant === \"vertical\" && }\n {variant === \"circle\" && }\n
\n )\n}\n\nconst HorizontalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n \n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n\nconst VerticalStepper = () => {\n return (\n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {methods.when(step.id, () => (\n \n

Content for {step.id}

\n
\n ))}\n \n ))}\n
\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst CircleStepper = () => {\n return (\n \n {({ methods }) => (\n <>\n \n \n {methods.current.title}\n \n \n {methods.when(methods.current.id, () => (\n \n

\n Content for {methods.current.id}\n

\n
\n ))}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/default/stepper.json b/apps/www/public/r/styles/default/stepper.json index c18aae4a179..40329946988 100644 --- a/apps/www/public/r/styles/default/stepper.json +++ b/apps/www/public/r/styles/default/stepper.json @@ -14,7 +14,7 @@ "files": [ { "path": "ui/stepper.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport * as Stepperize from \"@stepperize/react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/default/ui/button\"\n\ntype StepperProviderProps = StepperConfig & {\n children: React.ReactNode\n}\n\ntype StepperVariant = \"horizontal\" | \"vertical\" | \"circle\"\ntype StepperLabelOrientation = \"horizontal\" | \"vertical\"\n\ntype StepperConfig = {\n instance: ReturnType>\n variant?: StepperVariant\n labelOrientation?: StepperLabelOrientation\n tracking?: boolean\n}\n\nconst StepContext = React.createContext>({\n instance: {} as ReturnType>,\n variant: \"horizontal\",\n})\n\nconst StepperProvider = ({\n children,\n ...props\n}: StepperProviderProps) => {\n const Scope = props.instance.Scoped\n return (\n \n {children}\n \n )\n}\n\nconst useStepper = (): StepperConfig => {\n const context = React.useContext(StepContext)\n if (!context) {\n throw new Error(\"useStepper must be used within a Stepper\")\n }\n return context\n}\n\nfunction Stepper({\n children,\n variant = \"horizontal\",\n className,\n labelOrientation = \"horizontal\",\n tracking = false,\n ...props\n}: StepperConfig &\n Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n }) {\n const { instance } = props\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n return (\n \n
\n {typeof children === \"function\" ? children({ methods }) : children}\n
\n \n )\n}\n\nconst StepperNavigation = ({\n children,\n className,\n \"aria-label\": ariaLabel = \"Stepper Navigation\",\n ...props\n}: Omit, \"children\"> & {\n children: React.ReactNode\n}) => {\n const { variant, instance } = useStepper()\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n return (\n \n
    {children}
\n \n )\n}\n\nconst listVariants = cva(\"stepper-navigation-list flex gap-2\", {\n variants: {\n variant: {\n horizontal: \"flex-row items-center justify-between\",\n vertical: \"flex-col\",\n circle: \"flex-row items-center justify-between\",\n },\n },\n})\n\nconst StepperStep = ({\n children,\n className,\n of,\n icon,\n ...props\n}: React.ComponentProps<\"button\"> & { of: T; icon?: Icon }) => {\n const id = React.useId()\n const { instance, variant, labelOrientation } = useStepper()\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n const currentStep = methods.current\n\n const isLast = instance.utils.getLast().id === of.id\n const stepIndex = instance.utils.getIndex(of.id)\n const currentIndex = instance.utils.getIndex(currentStep?.id ?? \"\")\n const isActive = currentStep?.id === of.id\n\n const dataState = getStepState(currentIndex, stepIndex)\n const childMap = useStepChildren(children)\n\n const title = childMap.get(\"title\")\n const description = childMap.get(\"description\")\n const panel = childMap.get(\"panel\")\n\n if (variant === \"circle\") {\n return (\n \n \n
\n {title}\n {description}\n
\n \n )\n }\n\n return (\n <>\n \n \n onStepKeyDown(\n e,\n instance.utils.getNext(of.id),\n instance.utils.getPrev(of.id)\n )\n }\n {...props}\n >\n {icon ?? stepIndex + 1}\n \n {variant === \"horizontal\" && labelOrientation === \"vertical\" && (\n \n )}\n
\n {title}\n {description}\n
\n \n\n {variant === \"horizontal\" && labelOrientation === \"horizontal\" && (\n \n )}\n\n {variant === \"vertical\" && (\n
\n {!isLast && (\n
\n \n
\n )}\n
{panel}
\n
\n )}\n \n )\n}\n\nconst StepperSeparator = ({\n orientation,\n isLast,\n labelOrientation,\n state,\n disabled,\n}: {\n isLast: boolean\n state: string\n disabled?: boolean\n} & VariantProps) => {\n if (isLast) return null\n return (\n \n )\n}\n\nconst classForSeparator = cva(\n [\n \"bg-muted\",\n \"data-[state=completed]:bg-primary data-[disabled]:opacity-50\",\n \"transition-all duration-300 ease-in-out\",\n ],\n {\n variants: {\n orientation: {\n horizontal: \"h-0.5 flex-1\",\n vertical: \"h-full w-0.5\",\n },\n labelOrientation: {\n vertical:\n \"absolute left-[calc(50%+30px)] right-[calc(-50%+20px)] top-5 block shrink-0\",\n },\n },\n }\n)\n\nconst onStepKeyDown = (\n e: React.KeyboardEvent,\n nextStep: Stepperize.Step,\n prevStep: Stepperize.Step\n) => {\n const { key } = e\n const directions = {\n next: [\"ArrowRight\", \"ArrowDown\"],\n prev: [\"ArrowLeft\", \"ArrowUp\"],\n }\n\n if (directions.next.includes(key) || directions.prev.includes(key)) {\n const direction = directions.next.includes(key) ? \"next\" : \"prev\"\n const step = direction === \"next\" ? nextStep : prevStep\n\n if (!step) return\n\n const stepElement = document.getElementById(`step-${step.id}`)\n if (!stepElement) return\n\n const isActive =\n stepElement.parentElement?.getAttribute(\"data-state\") !== \"inactive\"\n if (isActive || direction === \"prev\") {\n stepElement.focus()\n }\n }\n}\n\nconst getStepState = (currentIndex: number, stepIndex: number) => {\n if (currentIndex === stepIndex) return \"active\"\n if (currentIndex > stepIndex) return \"completed\"\n return \"inactive\"\n}\n\nconst extractChildren = (children: React.ReactNode) => {\n const childrenArray = React.Children.toArray(children)\n const map = new Map()\n\n for (const child of childrenArray) {\n if (React.isValidElement(child)) {\n if (child.type === StepperTitle) {\n map.set(\"title\", child)\n } else if (child.type === StepperDescription) {\n map.set(\"description\", child)\n } else if (child.type === StepperPanel) {\n map.set(\"panel\", child)\n }\n }\n }\n\n return map\n}\n\nconst useStepChildren = (children: React.ReactNode) => {\n return React.useMemo(() => extractChildren(children), [children])\n}\n\nconst StepperTitle = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"h4\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"h4\"\n\n return (\n \n {children}\n \n )\n}\n\nconst StepperDescription = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"p\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"p\"\n\n return (\n \n {children}\n \n )\n}\n\ntype CircleStepIndicatorProps = {\n currentStep: number\n totalSteps: number\n size?: number\n strokeWidth?: number\n}\n\nconst CircleStepIndicator = ({\n currentStep,\n totalSteps,\n size = 80,\n strokeWidth = 6,\n}: CircleStepIndicatorProps) => {\n const radius = (size - strokeWidth) / 2\n const circumference = radius * 2 * Math.PI\n const fillPercentage = (currentStep / totalSteps) * 100\n const dashOffset = circumference - (circumference * fillPercentage) / 100\n\n return (\n \n \n Step Indicator\n \n \n \n
\n \n {currentStep} of {totalSteps}\n \n
\n \n )\n}\n\nconst StepperPanel = ({\n children,\n className,\n when,\n asChild,\n ...props\n}: Omit, \"children\"> & {\n asChild?: boolean\n when: T\n children:\n | React.ReactNode\n | ((props: {\n step: T\n onBeforeAction: (\n action: StepAction,\n callback: (params: {\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n ) => void\n }) => React.ReactNode)\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { instance, tracking } = useStepper()\n\n const methods = instance.useStepper()\n\n if (instance.utils.getIndex(when.id) === -1) {\n throw new Error(`Step ${when.id} does not exist in the stepper instance`)\n }\n\n const onBeforeAction = React.useCallback(\n async (\n action: StepAction,\n callback: (params: {\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n ) => {\n const prevStep = methods.current\n const nextStep =\n action === \"next\"\n ? instance.utils.getNext(prevStep.id)\n : action === \"prev\"\n ? instance.utils.getPrev(prevStep.id)\n : instance.utils.getFirst()\n\n const shouldProceed = await callback({ prevStep, nextStep })\n if (shouldProceed) {\n if (action === \"next\") methods.next()\n if (action === \"prev\") methods.prev()\n if (action === \"reset\") methods.reset()\n }\n },\n [methods, instance.utils]\n )\n\n return (\n <>\n {methods.when(when.id, (step) => (\n scrollIntoStepperPanel(node, tracking)}\n {...props}\n >\n {typeof children === \"function\"\n ? children({ step: step as T, onBeforeAction })\n : children}\n \n ))}\n \n )\n}\n\nfunction scrollIntoStepperPanel(\n node: HTMLDivElement | null,\n tracking?: boolean\n) {\n if (tracking) {\n node?.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n}\n\nconst StepperControls = ({\n children,\n asChild,\n className,\n ...props\n}: Omit, \"children\"> & {\n asChild?: boolean\n children:\n | React.ReactNode\n | ((props: {\n methods: Stepperize.Stepper\n }) => React.ReactNode)\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { instance } = useStepper()\n\n const methods = instance.useStepper()\n\n return (\n \n {typeof children === \"function\" ? children({ methods }) : children}\n \n )\n}\n\ntype StepAction = \"next\" | \"prev\" | \"reset\"\n\ntype StepperActionProps = {\n action: StepAction\n children: React.ReactNode\n asChild?: boolean\n onBeforeAction?: ({\n event,\n prevStep,\n nextStep,\n }: {\n event: React.MouseEvent\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n className?: string\n}\n\nconst StepperAction = ({\n action,\n children,\n asChild = false,\n onBeforeAction,\n className,\n disabled,\n ...props\n}: React.ComponentProps<\"button\"> & StepperActionProps) => {\n const { instance } = useStepper()\n const methods = instance.useStepper()\n\n const currentStep = methods.current\n\n const isDisabled = (action: StepAction) =>\n action === \"prev\" && methods.isFirst\n\n const actionMap = React.useMemo(\n () => ({\n next: methods.next,\n prev: methods.prev,\n reset: methods.reset,\n }),\n [methods]\n )\n\n const handleClick = React.useCallback(\n async (event: React.MouseEvent) => {\n if (onBeforeAction) {\n const nextStep =\n action === \"next\"\n ? instance.utils.getNext(currentStep.id)\n : action === \"prev\"\n ? instance.utils.getPrev(currentStep.id)\n : instance.utils.getFirst()\n const shouldProceed = await onBeforeAction({\n event,\n prevStep: currentStep,\n nextStep,\n })\n if (!shouldProceed) {\n return\n }\n }\n\n actionMap[action]?.()\n },\n [onBeforeAction, actionMap, action, instance.utils, currentStep]\n )\n\n const Comp = asChild ? Slot : Button\n\n if (\n (methods.isLast && (action === \"next\" || action === \"prev\")) ||\n (!methods.isLast && action === \"reset\")\n ) {\n return null\n }\n\n return (\n \n {children}\n \n )\n}\n\nconst defineStepper: typeof Stepperize.defineStepper = Stepperize.defineStepper\n\nexport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport * as Stepperize from \"@stepperize/react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/default/ui/button\"\n\ntype StepperVariant = \"horizontal\" | \"vertical\" | \"circle\"\ntype StepperLabelOrientation = \"horizontal\" | \"vertical\"\n\ntype StepperConfig = {\n instance: ReturnType>\n variant?: StepperVariant\n labelOrientation?: StepperLabelOrientation\n tracking?: boolean\n}\n\ntype StepperProviderProps = StepperConfig & {\n children: React.ReactNode\n}\n\nconst StepContext = React.createContext | null>(null)\n\nconst StepperProvider = ({\n children,\n ...props\n}: StepperProviderProps) => {\n const { instance } = props\n const Scoped = instance.Scoped\n return (\n \n {children}\n \n )\n}\n\nconst useStepper = (): StepperConfig => {\n const context = React.useContext(StepContext)\n if (!context) {\n throw new Error(\"useStepper must be used within a StepperProvider.\")\n }\n return context\n}\n\ntype StepperProps = StepperConfig &\n Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n }\n\nconst Stepper = ({\n children,\n variant = \"horizontal\",\n labelOrientation = \"horizontal\",\n tracking = false,\n instance,\n ...props\n}: StepperProps) => (\n \n {children}\n \n)\n\nconst StepperContainer = ({\n children,\n className,\n ...props\n}: Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n}) => {\n const { instance } = useStepper()\n const methods = instance.useStepper()\n\n return (\n
\n {typeof children === \"function\" ? children({ methods }) : children}\n
\n )\n}\n\nconst StepperNavigation = ({\n children,\n className,\n \"aria-label\": ariaLabel = \"Stepper Navigation\",\n ...props\n}: Omit, \"children\"> & {\n children: React.ReactNode\n}) => {\n const { variant } = useStepper()\n\n return (\n \n
    {children}
\n \n )\n}\n\nconst listVariants = cva(\"stepper-navigation-list flex gap-2\", {\n variants: {\n variant: {\n horizontal: \"flex-row items-center justify-between\",\n vertical: \"flex-col\",\n circle: \"flex-row items-center justify-between\",\n },\n },\n})\n\nconst StepperStep = ({\n children,\n className,\n of,\n icon,\n ...props\n}: React.ComponentProps<\"button\"> & { of: T; icon?: Icon }) => {\n const { instance, variant, labelOrientation } = useStepper()\n\n const methods = instance.useStepper()\n\n const currentStep = methods.current\n\n const isLast = instance.utils.getLast().id === of.id\n const stepIndex = instance.utils.getIndex(of.id)\n const currentIndex = instance.utils.getIndex(currentStep?.id ?? \"\")\n const isActive = currentStep?.id === of.id\n\n const dataState = getStepState(currentIndex, stepIndex)\n const childMap = useStepChildren(children)\n\n const title = childMap.get(\"title\")\n const description = childMap.get(\"description\")\n const panel = childMap.get(\"panel\")\n\n if (variant === \"circle\") {\n return (\n \n \n
\n {title}\n {description}\n
\n \n )\n }\n\n return (\n <>\n \n \n onStepKeyDown(\n e,\n instance.utils.getNext(of.id),\n instance.utils.getPrev(of.id)\n )\n }\n {...props}\n >\n {icon ?? stepIndex + 1}\n \n {variant === \"horizontal\" && labelOrientation === \"vertical\" && (\n \n )}\n
\n {title}\n {description}\n
\n \n\n {variant === \"horizontal\" && labelOrientation === \"horizontal\" && (\n \n )}\n\n {variant === \"vertical\" && (\n
\n {!isLast && (\n
\n \n
\n )}\n
{panel}
\n
\n )}\n \n )\n}\n\nconst StepperSeparator = ({\n orientation,\n isLast,\n labelOrientation,\n state,\n disabled,\n}: {\n isLast: boolean\n state: string\n disabled?: boolean\n} & VariantProps) => {\n if (isLast) {\n return null\n }\n return (\n \n )\n}\n\nconst classForSeparator = cva(\n [\n \"bg-muted\",\n \"data-[state=completed]:bg-primary data-[disabled]:opacity-50\",\n \"transition-all duration-300 ease-in-out\",\n ],\n {\n variants: {\n orientation: {\n horizontal: \"h-0.5 flex-1\",\n vertical: \"h-full w-0.5\",\n },\n labelOrientation: {\n vertical:\n \"absolute left-[calc(50%+30px)] right-[calc(-50%+20px)] top-5 block shrink-0\",\n },\n },\n }\n)\n\nconst onStepKeyDown = (\n e: React.KeyboardEvent,\n nextStep: Stepperize.Step,\n prevStep: Stepperize.Step\n) => {\n const { key } = e\n const directions = {\n next: [\"ArrowRight\", \"ArrowDown\"],\n prev: [\"ArrowLeft\", \"ArrowUp\"],\n }\n\n if (directions.next.includes(key) || directions.prev.includes(key)) {\n const direction = directions.next.includes(key) ? \"next\" : \"prev\"\n const step = direction === \"next\" ? nextStep : prevStep\n\n if (!step) {\n return\n }\n\n const stepElement = document.getElementById(`step-${step.id}`)\n if (!stepElement) {\n return\n }\n\n const isActive =\n stepElement.parentElement?.getAttribute(\"data-state\") !== \"inactive\"\n if (isActive || direction === \"prev\") {\n stepElement.focus()\n }\n }\n}\n\nconst getStepState = (currentIndex: number, stepIndex: number) => {\n if (currentIndex === stepIndex) {\n return \"active\"\n }\n if (currentIndex > stepIndex) {\n return \"completed\"\n }\n return \"inactive\"\n}\n\nconst extractChildren = (children: React.ReactNode) => {\n const childrenArray = React.Children.toArray(children)\n const map = new Map()\n\n for (const child of childrenArray) {\n if (React.isValidElement(child)) {\n if (child.type === StepperTitle) {\n map.set(\"title\", child)\n } else if (child.type === StepperDescription) {\n map.set(\"description\", child)\n } else if (child.type === StepperPanel) {\n map.set(\"panel\", child)\n }\n }\n }\n\n return map\n}\n\nconst useStepChildren = (children: React.ReactNode) => {\n return React.useMemo(() => extractChildren(children), [children])\n}\n\nconst StepperTitle = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"h4\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"h4\"\n\n return (\n \n {children}\n \n )\n}\n\nconst StepperDescription = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"p\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"p\"\n\n return (\n \n {children}\n \n )\n}\n\ntype CircleStepIndicatorProps = {\n currentStep: number\n totalSteps: number\n size?: number\n strokeWidth?: number\n}\n\nconst CircleStepIndicator = ({\n currentStep,\n totalSteps,\n size = 80,\n strokeWidth = 6,\n}: CircleStepIndicatorProps) => {\n const radius = (size - strokeWidth) / 2\n const circumference = radius * 2 * Math.PI\n const fillPercentage = (currentStep / totalSteps) * 100\n const dashOffset = circumference - (circumference * fillPercentage) / 100\n return (\n \n \n Step Indicator\n \n \n \n
\n \n {currentStep} of {totalSteps}\n \n
\n \n )\n}\n\nconst StepperPanel = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { tracking } = useStepper()\n\n return (\n scrollIntoStepperPanel(node, tracking)}\n {...props}\n >\n {children}\n \n )\n}\n\nfunction scrollIntoStepperPanel(\n node: HTMLDivElement | null,\n tracking?: boolean\n) {\n if (tracking) {\n node?.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n}\n\nconst StepperControls = ({\n children,\n asChild,\n ...props\n}: React.ComponentProps<\"div\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"div\"\n return (\n \n {children}\n \n )\n}\n\nconst defineStepper: typeof Stepperize.defineStepper = Stepperize.defineStepper\n\nexport {\n defineStepper,\n Stepper,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n}\n", "type": "registry:ui", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-demo.json b/apps/www/public/r/styles/new-york/stepper-demo.json index 8732ce9be87..28bd7d4a481 100644 --- a/apps/www/public/r/styles/new-york/stepper-demo.json +++ b/apps/www/public/r/styles/new-york/stepper-demo.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-demo.tsx", - "content": "import {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperDemo() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-description.json b/apps/www/public/r/styles/new-york/stepper-description.json index 5b3d1ba2d5f..ce1a4098be2 100644 --- a/apps/www/public/r/styles/new-york/stepper-description.json +++ b/apps/www/public/r/styles/new-york/stepper-description.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-description.tsx", - "content": "import {\n Stepper,\n StepperAction,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n description: \"This is the first step\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n description: \"This is the second step\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n description: \"This is the third step\",\n }\n)\n\nexport default function StepperDemo() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {step.description}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n description: \"This is the first step\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n description: \"This is the second step\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n description: \"This is the third step\",\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {step.description}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-form.json b/apps/www/public/r/styles/new-york/stepper-form.json index f177415f0e8..c9529b817da 100644 --- a/apps/www/public/r/styles/new-york/stepper-form.json +++ b/apps/www/public/r/styles/new-york/stepper-form.json @@ -10,7 +10,7 @@ "files": [ { "path": "examples/stepper-form.tsx", - "content": "import { zodResolver } from \"@hookform/resolvers/zod\"\nimport { useForm, useFormContext } from \"react-hook-form\"\nimport { z } from \"zod\"\n\nimport { Form } from \"@/registry/new-york/ui/form\"\nimport { Input } from \"@/registry/new-york/ui/input\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst shippingSchema = z.object({\n address: z.string().min(1, \"Address is required\"),\n city: z.string().min(1, \"City is required\"),\n postalCode: z.string().min(5, \"Postal code is required\"),\n})\n\nconst paymentSchema = z.object({\n cardNumber: z.string().min(16, \"Card number is required\"),\n expirationDate: z.string().min(5, \"Expiration date is required\"),\n cvv: z.string().min(3, \"CVV is required\"),\n})\n\ntype ShippingFormValues = z.infer\ntype PaymentFormValues = z.infer\n\nconst stepperInstance = defineStepper(\n {\n id: \"shipping\",\n title: \"Shipping\",\n schema: shippingSchema,\n },\n {\n id: \"payment\",\n title: \"Payment\",\n schema: paymentSchema,\n },\n {\n id: \"complete\",\n title: \"Complete\",\n schema: z.object({}),\n }\n)\n\nexport default function StepperForm() {\n return (\n \n \n \n )\n}\n\nconst FormStepperComponent = () => {\n const { steps, useStepper, utils } = stepperInstance\n const methods = useStepper()\n\n const form = useForm({\n mode: \"onTouched\",\n resolver: zodResolver(methods.current.schema),\n })\n\n const onSubmit = (values: z.infer) => {\n console.log(`Form values for step ${methods.current.id}:`, values)\n }\n\n const currentIndex = utils.getIndex(methods.current.id)\n\n return (\n
\n \n \n {steps.map((step) => (\n {\n const valid = await form.trigger()\n if (!valid) return\n if (utils.getIndex(step.id) - currentIndex > 1) return\n methods.goTo(step.id)\n }}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n shipping: () => ,\n payment: () => ,\n complete: () => ,\n })}\n \n Previous\n {\n const valid = await form.trigger()\n if (!valid) return false\n if (utils.getIndex(nextStep.id as any) - currentIndex > 1)\n return false\n return true\n }}\n >\n Next\n \n Reset\n \n \n \n )\n}\n\nconst ShippingForm = () => {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Address\n \n \n {errors.address && (\n \n {errors.address.message}\n \n )}\n
\n
\n \n City\n \n \n {errors.city && (\n \n {errors.city.message}\n \n )}\n
\n
\n \n Postal Code\n \n \n {errors.postalCode && (\n \n {errors.postalCode.message}\n \n )}\n
\n
\n )\n}\n\nfunction PaymentForm() {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Card Number\n \n \n {errors.cardNumber && (\n \n {errors.cardNumber.message}\n \n )}\n
\n
\n \n Expiration Date\n \n \n {errors.expirationDate && (\n \n {errors.expirationDate.message}\n \n )}\n
\n
\n \n CVV\n \n \n {errors.cvv && (\n {errors.cvv.message}\n )}\n
\n
\n )\n}\n\nfunction CompleteComponent() {\n return
Thank you! Your order is complete.
\n}\n", + "content": "import * as React from \"react\"\nimport { zodResolver } from \"@hookform/resolvers/zod\"\nimport { useForm, useFormContext } from \"react-hook-form\"\nimport { z } from \"zod\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Form } from \"@/registry/new-york/ui/form\"\nimport { Input } from \"@/registry/new-york/ui/input\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst shippingSchema = z.object({\n address: z.string().min(1, \"Address is required\"),\n city: z.string().min(1, \"City is required\"),\n postalCode: z.string().min(5, \"Postal code is required\"),\n})\n\nconst paymentSchema = z.object({\n cardNumber: z.string().min(16, \"Card number is required\"),\n expirationDate: z.string().min(5, \"Expiration date is required\"),\n cvv: z.string().min(3, \"CVV is required\"),\n})\n\ntype ShippingFormValues = z.infer\ntype PaymentFormValues = z.infer\n\nconst ShippingForm = () => {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Address\n \n \n {errors.address && (\n \n {errors.address.message}\n \n )}\n
\n
\n \n City\n \n \n {errors.city && (\n \n {errors.city.message}\n \n )}\n
\n
\n \n Postal Code\n \n \n {errors.postalCode && (\n \n {errors.postalCode.message}\n \n )}\n
\n
\n )\n}\n\nfunction PaymentForm() {\n const {\n register,\n formState: { errors },\n } = useFormContext()\n\n return (\n
\n
\n \n Card Number\n \n \n {errors.cardNumber && (\n \n {errors.cardNumber.message}\n \n )}\n
\n
\n \n Expiration Date\n \n \n {errors.expirationDate && (\n \n {errors.expirationDate.message}\n \n )}\n
\n
\n \n CVV\n \n \n {errors.cvv && (\n {errors.cvv.message}\n )}\n
\n
\n )\n}\n\nfunction CompleteComponent() {\n return
Thank you! Your order is complete.
\n}\n\nconst stepperInstance = defineStepper(\n {\n id: \"shipping\",\n title: \"Shipping\",\n schema: shippingSchema,\n Component: ShippingForm,\n },\n {\n id: \"payment\",\n title: \"Payment\",\n schema: paymentSchema,\n Component: PaymentForm,\n },\n {\n id: \"complete\",\n title: \"Complete\",\n schema: z.object({}),\n Component: CompleteComponent,\n }\n)\n\nexport default function StepperForm() {\n return (\n \n \n \n )\n}\n\nconst FormStepperComponent = () => {\n const { useStepper } = stepperInstance\n const methods = useStepper()\n\n const form = useForm({\n mode: \"onTouched\",\n resolver: zodResolver(methods.current.schema),\n })\n\n const onSubmit = (values: z.infer) => {\n console.log(`Form values for step ${methods.current.id}:`, values)\n }\n\n return (\n
\n \n \n {methods.all.map((step) => (\n {\n const valid = await form.trigger()\n if (!valid) return\n methods.goTo(step.id)\n }}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n shipping: ({ Component }) => ,\n payment: ({ Component }) => ,\n complete: ({ Component }) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n {\n if (methods.isLast) {\n return methods.reset()\n }\n methods.beforeNext(async () => {\n const valid = await form.trigger()\n if (!valid) return false\n return true\n })\n }}\n >\n {methods.isLast ? \"Reset\" : \"Next\"}\n \n \n \n \n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-icon.json b/apps/www/public/r/styles/new-york/stepper-icon.json index e9573a8f65e..d91ad347537 100644 --- a/apps/www/public/r/styles/new-york/stepper-icon.json +++ b/apps/www/public/r/styles/new-york/stepper-icon.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-icon.tsx", - "content": "import { HomeIcon, SettingsIcon, UserIcon } from \"lucide-react\"\n\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n icon: ,\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n icon: ,\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n icon: ,\n }\n)\n\nexport default function StepperIcon() {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n icon={step.icon}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\nimport { HomeIcon, SettingsIcon, UserIcon } from \"lucide-react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n icon: ,\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n icon: ,\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n icon: ,\n }\n)\n\nexport default function StepperDemo() {\n return (\n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n icon={step.icon}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-label-orientation.json b/apps/www/public/r/styles/new-york/stepper-label-orientation.json index c6e985863df..d5005d0045b 100644 --- a/apps/www/public/r/styles/new-york/stepper-label-orientation.json +++ b/apps/www/public/r/styles/new-york/stepper-label-orientation.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-label-orientation.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\ntype LabelOrientation = \"horizontal\" | \"vertical\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const steps = stepperInstance.steps\n\n const [labelOrientation, setLabelOrientation] =\n React.useState(\"horizontal\")\n return (\n
\n \n setLabelOrientation(value as LabelOrientation)\n }\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\ntype LabelOrientation = \"horizontal\" | \"vertical\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const [labelOrientation, setLabelOrientation] =\n React.useState(\"horizontal\")\n return (\n
\n \n setLabelOrientation(value as LabelOrientation)\n }\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n \n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n
\n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-responsive-variant.json b/apps/www/public/r/styles/new-york/stepper-responsive-variant.json index 0b858184023..0800e76a9e6 100644 --- a/apps/www/public/r/styles/new-york/stepper-responsive-variant.json +++ b/apps/www/public/r/styles/new-york/stepper-responsive-variant.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-responsive-variant.tsx", - "content": "import { useMediaQuery } from \"@/hooks/use-media-query\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperResponsiveVariant() {\n const steps = stepperInstance.steps\n const isMobile = useMediaQuery(\"(max-width: 768px)\")\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {isMobile && (\n \n {({ step }) => (\n

\n Content for {step.id}\n

\n )}\n \n )}\n \n ))}\n
\n {!isMobile &&\n steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { useMediaQuery } from \"@/hooks/use-media-query\"\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperResponsiveVariant() {\n const isMobile = useMediaQuery(\"(max-width: 768px)\")\n return (\n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {isMobile &&\n methods.when(step.id, (step) => (\n \n

\n Content for {step.id}\n

\n
\n ))}\n \n ))}\n
\n {!isMobile &&\n methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-tracking.json b/apps/www/public/r/styles/new-york/stepper-tracking.json index 1b8733dc0ed..bb990294c11 100644 --- a/apps/www/public/r/styles/new-york/stepper-tracking.json +++ b/apps/www/public/r/styles/new-york/stepper-tracking.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-tracking.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n },\n {\n id: \"step-4\",\n title: \"Step 4\",\n },\n {\n id: \"step-5\",\n title: \"Step 5\",\n },\n {\n id: \"step-6\",\n title: \"Step 6\",\n }\n)\n\nexport default function StepperVerticalFollow() {\n const steps = stepperInstance.steps\n\n const [tracking, setTracking] = React.useState(false)\n return (\n
\n setTracking(value === \"true\")}\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n
\n

\n Content for {step.id}\n

\n
\n \n Previous\n Next\n Reset\n \n
\n \n ))}\n
\n \n )}\n \n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n },\n {\n id: \"step-4\",\n title: \"Step 4\",\n },\n {\n id: \"step-5\",\n title: \"Step 5\",\n },\n {\n id: \"step-6\",\n title: \"Step 6\",\n }\n)\n\nexport default function StepperVerticalFollow() {\n const [tracking, setTracking] = React.useState(false)\n return (\n
\n setTracking(value === \"true\")}\n >\n
\n \n \n
\n
\n \n \n
\n \n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {methods.when(step.id, () => (\n \n
\n

\n Content for {step.id}\n

\n
\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n {methods.isLast ? \"Reset\" : \"Next\"}\n \n \n
\n ))}\n \n ))}\n
\n \n )}\n \n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper-variants.json b/apps/www/public/r/styles/new-york/stepper-variants.json index fa53f00b7ee..b158ed315d5 100644 --- a/apps/www/public/r/styles/new-york/stepper-variants.json +++ b/apps/www/public/r/styles/new-york/stepper-variants.json @@ -9,7 +9,7 @@ "files": [ { "path": "examples/stepper-variants.tsx", - "content": "import * as React from \"react\"\n\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\ntype Variant = \"horizontal\" | \"vertical\" | \"circle\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const steps = stepperInstance.steps\n\n const [variant, setVariant] = React.useState(\"horizontal\")\n return (\n
\n setVariant(value as Variant)}\n >\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n \n {variant === \"horizontal\" && }\n {variant === \"vertical\" && }\n {variant === \"circle\" && }\n
\n )\n}\n\nconst HorizontalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n\nconst VerticalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n \n ))}\n
\n \n Previous\n Next\n Reset\n \n \n )}\n \n )\n}\n\nconst CircleStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n <>\n \n \n {methods.current.title}\n \n \n {steps.map((step) => (\n \n {({ step }) => (\n

Content for {step.id}

\n )}\n \n ))}\n \n Previous\n Next\n Reset\n \n \n )}\n
\n )\n}\n", + "content": "import * as React from \"react\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\nimport { Label } from \"@/registry/new-york/ui/label\"\nimport { RadioGroup, RadioGroupItem } from \"@/registry/new-york/ui/radio-group\"\nimport {\n Stepper,\n StepperControls,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n} from \"@/registry/new-york/ui/stepper\"\n\ntype Variant = \"horizontal\" | \"vertical\" | \"circle\"\n\nconst stepperInstance = defineStepper(\n {\n id: \"step-1\",\n title: \"Step 1\",\n },\n {\n id: \"step-2\",\n title: \"Step 2\",\n },\n {\n id: \"step-3\",\n title: \"Step 3\",\n }\n)\n\nexport default function StepperVariants() {\n const [variant, setVariant] = React.useState(\"horizontal\")\n return (\n
\n setVariant(value as Variant)}\n >\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n \n {variant === \"horizontal\" && }\n {variant === \"vertical\" && }\n {variant === \"circle\" && }\n
\n )\n}\n\nconst HorizontalStepper = () => {\n const steps = stepperInstance.steps\n return (\n \n {({ methods }) => (\n \n \n {steps.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n \n ))}\n \n {methods.switch({\n \"step-1\": (step) => ,\n \"step-2\": (step) => ,\n \"step-3\": (step) => ,\n })}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst Content = ({ id }: { id: string }) => {\n return (\n \n

Content for {id}

\n
\n )\n}\n\nconst VerticalStepper = () => {\n return (\n \n {({ methods }) => (\n <>\n \n {methods.all.map((step) => (\n methods.goTo(step.id)}\n >\n {step.title}\n {methods.when(step.id, () => (\n \n

Content for {step.id}

\n
\n ))}\n \n ))}\n
\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n \n )\n}\n\nconst CircleStepper = () => {\n return (\n \n {({ methods }) => (\n <>\n \n \n {methods.current.title}\n \n \n {methods.when(methods.current.id, () => (\n \n

\n Content for {methods.current.id}\n

\n
\n ))}\n \n {!methods.isLast && (\n \n Previous\n \n )}\n \n \n \n )}\n
\n )\n}\n", "type": "registry:example", "target": "" } diff --git a/apps/www/public/r/styles/new-york/stepper.json b/apps/www/public/r/styles/new-york/stepper.json index a1ba04d15ee..df1a9f4d3a5 100644 --- a/apps/www/public/r/styles/new-york/stepper.json +++ b/apps/www/public/r/styles/new-york/stepper.json @@ -14,7 +14,7 @@ "files": [ { "path": "ui/stepper.tsx", - "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport * as Stepperize from \"@stepperize/react\"\nimport { VariantProps, cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/new-york/ui/button\"\n\ntype StepperProviderProps = StepperConfig & {\n children: React.ReactNode\n}\n\ntype StepperVariant = \"horizontal\" | \"vertical\" | \"circle\"\ntype StepperLabelOrientation = \"horizontal\" | \"vertical\"\n\ntype StepperConfig = {\n instance: ReturnType>\n variant?: StepperVariant\n labelOrientation?: StepperLabelOrientation\n tracking?: boolean\n}\n\nconst StepContext = React.createContext>({\n instance: {} as ReturnType>,\n variant: \"horizontal\",\n})\n\nconst StepperProvider = ({\n children,\n ...props\n}: StepperProviderProps) => {\n const Scope = props.instance.Scoped\n return (\n \n {children}\n \n )\n}\n\nconst useStepper = (): StepperConfig => {\n const context = React.useContext(StepContext)\n if (!context) {\n throw new Error(\"useStepper must be used within a Stepper\")\n }\n return context\n}\n\nfunction Stepper({\n children,\n variant = \"horizontal\",\n className,\n labelOrientation = \"horizontal\",\n tracking = false,\n ...props\n}: StepperConfig &\n Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n }) {\n const { instance } = props\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n return (\n \n
\n {typeof children === \"function\" ? children({ methods }) : children}\n
\n \n )\n}\n\nconst StepperNavigation = ({\n children,\n className,\n \"aria-label\": ariaLabel = \"Stepper Navigation\",\n ...props\n}: Omit, \"children\"> & {\n children: React.ReactNode\n}) => {\n const { variant, instance } = useStepper()\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n return (\n \n
    {children}
\n \n )\n}\n\nconst listVariants = cva(\"stepper-navigation-list flex gap-2\", {\n variants: {\n variant: {\n horizontal: \"flex-row items-center justify-between\",\n vertical: \"flex-col\",\n circle: \"flex-row items-center justify-between\",\n },\n },\n})\n\nconst StepperStep = ({\n children,\n className,\n of,\n icon,\n ...props\n}: React.ComponentProps<\"button\"> & { of: T; icon?: Icon }) => {\n const id = React.useId()\n const { instance, variant, labelOrientation } = useStepper()\n\n const methods = instance.useStepper() as Stepperize.Stepper\n\n const currentStep = methods.current\n\n const isLast = instance.utils.getLast().id === of.id\n const stepIndex = instance.utils.getIndex(of.id)\n const currentIndex = instance.utils.getIndex(currentStep?.id ?? \"\")\n const isActive = currentStep?.id === of.id\n\n const dataState = getStepState(currentIndex, stepIndex)\n const childMap = useStepChildren(children)\n\n const title = childMap.get(\"title\")\n const description = childMap.get(\"description\")\n const panel = childMap.get(\"panel\")\n\n if (variant === \"circle\") {\n return (\n \n \n
\n {title}\n {description}\n
\n \n )\n }\n\n return (\n <>\n \n \n onStepKeyDown(\n e,\n instance.utils.getNext(of.id),\n instance.utils.getPrev(of.id)\n )\n }\n {...props}\n >\n {icon ?? stepIndex + 1}\n \n {variant === \"horizontal\" && labelOrientation === \"vertical\" && (\n \n )}\n
\n {title}\n {description}\n
\n \n\n {variant === \"horizontal\" && labelOrientation === \"horizontal\" && (\n \n )}\n\n {variant === \"vertical\" && (\n
\n {!isLast && (\n
\n \n
\n )}\n
{panel}
\n
\n )}\n \n )\n}\n\nconst StepperSeparator = ({\n orientation,\n isLast,\n labelOrientation,\n state,\n disabled,\n}: {\n isLast: boolean\n state: string\n disabled?: boolean\n} & VariantProps) => {\n if (isLast) return null\n return (\n \n )\n}\n\nconst classForSeparator = cva(\n [\n \"bg-muted\",\n \"data-[state=completed]:bg-primary data-[disabled]:opacity-50\",\n \"transition-all duration-300 ease-in-out\",\n ],\n {\n variants: {\n orientation: {\n horizontal: \"h-0.5 flex-1\",\n vertical: \"h-full w-0.5\",\n },\n labelOrientation: {\n vertical:\n \"absolute left-[calc(50%+30px)] right-[calc(-50%+20px)] top-5 block shrink-0\",\n },\n },\n }\n)\n\nconst onStepKeyDown = (\n e: React.KeyboardEvent,\n nextStep: Stepperize.Step,\n prevStep: Stepperize.Step\n) => {\n const { key } = e\n const directions = {\n next: [\"ArrowRight\", \"ArrowDown\"],\n prev: [\"ArrowLeft\", \"ArrowUp\"],\n }\n\n if (directions.next.includes(key) || directions.prev.includes(key)) {\n const direction = directions.next.includes(key) ? \"next\" : \"prev\"\n const step = direction === \"next\" ? nextStep : prevStep\n\n if (!step) return\n\n const stepElement = document.getElementById(`step-${step.id}`)\n if (!stepElement) return\n\n const isActive =\n stepElement.parentElement?.getAttribute(\"data-state\") !== \"inactive\"\n if (isActive || direction === \"prev\") {\n stepElement.focus()\n }\n }\n}\n\nconst getStepState = (currentIndex: number, stepIndex: number) => {\n if (currentIndex === stepIndex) return \"active\"\n if (currentIndex > stepIndex) return \"completed\"\n return \"inactive\"\n}\n\nconst extractChildren = (children: React.ReactNode) => {\n const childrenArray = React.Children.toArray(children)\n const map = new Map()\n\n for (const child of childrenArray) {\n if (React.isValidElement(child)) {\n if (child.type === StepperTitle) {\n map.set(\"title\", child)\n } else if (child.type === StepperDescription) {\n map.set(\"description\", child)\n } else if (child.type === StepperPanel) {\n map.set(\"panel\", child)\n }\n }\n }\n\n return map\n}\n\nconst useStepChildren = (children: React.ReactNode) => {\n return React.useMemo(() => extractChildren(children), [children])\n}\n\nconst StepperTitle = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"h4\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"h4\"\n\n return (\n \n {children}\n \n )\n}\n\nconst StepperDescription = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"p\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"p\"\n\n return (\n \n {children}\n \n )\n}\n\ntype CircleStepIndicatorProps = {\n currentStep: number\n totalSteps: number\n size?: number\n strokeWidth?: number\n}\n\nconst CircleStepIndicator = ({\n currentStep,\n totalSteps,\n size = 80,\n strokeWidth = 6,\n}: CircleStepIndicatorProps) => {\n const radius = (size - strokeWidth) / 2\n const circumference = radius * 2 * Math.PI\n const fillPercentage = (currentStep / totalSteps) * 100\n const dashOffset = circumference - (circumference * fillPercentage) / 100\n\n return (\n \n \n Step Indicator\n \n \n \n
\n \n {currentStep} of {totalSteps}\n \n
\n \n )\n}\n\nconst StepperPanel = ({\n children,\n className,\n when,\n asChild,\n ...props\n}: Omit, \"children\"> & {\n asChild?: boolean\n when: T\n children:\n | React.ReactNode\n | ((props: {\n step: T\n onBeforeAction: (\n action: StepAction,\n callback: (params: {\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n ) => void\n }) => React.ReactNode)\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { instance, tracking } = useStepper()\n\n const methods = instance.useStepper()\n\n if (instance.utils.getIndex(when.id) === -1) {\n throw new Error(`Step ${when.id} does not exist in the stepper instance`)\n }\n\n const onBeforeAction = React.useCallback(\n async (\n action: StepAction,\n callback: (params: {\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n ) => {\n const prevStep = methods.current\n const nextStep =\n action === \"next\"\n ? instance.utils.getNext(prevStep.id)\n : action === \"prev\"\n ? instance.utils.getPrev(prevStep.id)\n : instance.utils.getFirst()\n\n const shouldProceed = await callback({ prevStep, nextStep })\n if (shouldProceed) {\n if (action === \"next\") methods.next()\n if (action === \"prev\") methods.prev()\n if (action === \"reset\") methods.reset()\n }\n },\n [methods, instance.utils]\n )\n\n return (\n <>\n {methods.when(when.id, (step) => (\n scrollIntoStepperPanel(node, tracking)}\n {...props}\n >\n {typeof children === \"function\"\n ? children({ step: step as T, onBeforeAction })\n : children}\n \n ))}\n \n )\n}\n\nfunction scrollIntoStepperPanel(\n node: HTMLDivElement | null,\n tracking?: boolean\n) {\n if (tracking) {\n node?.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n}\n\nconst StepperControls = ({\n children,\n asChild,\n className,\n ...props\n}: Omit, \"children\"> & {\n asChild?: boolean\n children:\n | React.ReactNode\n | ((props: {\n methods: Stepperize.Stepper\n }) => React.ReactNode)\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { instance } = useStepper()\n\n const methods = instance.useStepper()\n\n return (\n \n {typeof children === \"function\" ? children({ methods }) : children}\n \n )\n}\n\ntype StepAction = \"next\" | \"prev\" | \"reset\"\n\ntype StepperActionProps = {\n action: StepAction\n children: React.ReactNode\n asChild?: boolean\n onBeforeAction?: ({\n event,\n prevStep,\n nextStep,\n }: {\n event: React.MouseEvent\n prevStep: Stepperize.Step\n nextStep: Stepperize.Step\n }) => Promise | boolean\n className?: string\n}\n\nconst StepperAction = ({\n action,\n children,\n asChild = false,\n onBeforeAction,\n className,\n disabled,\n ...props\n}: React.ComponentProps<\"button\"> & StepperActionProps) => {\n const { instance } = useStepper()\n const methods = instance.useStepper()\n\n const currentStep = methods.current\n\n const isDisabled = (action: StepAction) =>\n action === \"prev\" && methods.isFirst\n\n const actionMap = React.useMemo(\n () => ({\n next: methods.next,\n prev: methods.prev,\n reset: methods.reset,\n }),\n [methods]\n )\n\n const handleClick = React.useCallback(\n async (event: React.MouseEvent) => {\n if (onBeforeAction) {\n const nextStep =\n action === \"next\"\n ? instance.utils.getNext(currentStep.id)\n : action === \"prev\"\n ? instance.utils.getPrev(currentStep.id)\n : instance.utils.getFirst()\n const shouldProceed = await onBeforeAction({\n event,\n prevStep: currentStep,\n nextStep,\n })\n if (!shouldProceed) {\n return\n }\n }\n\n actionMap[action]?.()\n },\n [onBeforeAction, actionMap, action, instance.utils, currentStep]\n )\n\n const Comp = asChild ? Slot : Button\n\n if (\n (methods.isLast && (action === \"next\" || action === \"prev\")) ||\n (!methods.isLast && action === \"reset\")\n ) {\n return null\n }\n\n return (\n \n {children}\n \n )\n}\n\nconst defineStepper: typeof Stepperize.defineStepper = Stepperize.defineStepper\n\nexport {\n Stepper,\n StepperAction,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n defineStepper,\n}\n", + "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport * as Stepperize from \"@stepperize/react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/new-york/ui/button\"\n\ntype StepperVariant = \"horizontal\" | \"vertical\" | \"circle\"\ntype StepperLabelOrientation = \"horizontal\" | \"vertical\"\n\ntype StepperConfig = {\n instance: ReturnType>\n variant?: StepperVariant\n labelOrientation?: StepperLabelOrientation\n tracking?: boolean\n}\n\ntype StepperProviderProps = StepperConfig & {\n children: React.ReactNode\n}\n\nconst StepContext = React.createContext | null>(null)\n\nconst StepperProvider = ({\n children,\n ...props\n}: StepperProviderProps) => {\n const { instance } = props\n const Scoped = instance.Scoped\n return (\n \n {children}\n \n )\n}\n\nconst useStepper = (): StepperConfig => {\n const context = React.useContext(StepContext)\n if (!context) {\n throw new Error(\"useStepper must be used within a StepperProvider.\")\n }\n return context\n}\n\ntype StepperProps = StepperConfig &\n Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n }\n\nconst Stepper = ({\n children,\n variant = \"horizontal\",\n labelOrientation = \"horizontal\",\n tracking = false,\n instance,\n ...props\n}: StepperProps) => (\n \n {children}\n \n)\n\nconst StepperContainer = ({\n children,\n className,\n ...props\n}: Omit, \"children\"> & {\n children:\n | React.ReactNode\n | ((props: { methods: Stepperize.Stepper }) => React.ReactNode)\n}) => {\n const { instance } = useStepper()\n const methods = instance.useStepper()\n\n return (\n
\n {typeof children === \"function\" ? children({ methods }) : children}\n
\n )\n}\n\nconst StepperNavigation = ({\n children,\n className,\n \"aria-label\": ariaLabel = \"Stepper Navigation\",\n ...props\n}: Omit, \"children\"> & {\n children: React.ReactNode\n}) => {\n const { variant } = useStepper()\n\n return (\n \n
    {children}
\n \n )\n}\n\nconst listVariants = cva(\"stepper-navigation-list flex gap-2\", {\n variants: {\n variant: {\n horizontal: \"flex-row items-center justify-between\",\n vertical: \"flex-col\",\n circle: \"flex-row items-center justify-between\",\n },\n },\n})\n\nconst StepperStep = ({\n children,\n className,\n of,\n icon,\n ...props\n}: React.ComponentProps<\"button\"> & { of: T; icon?: Icon }) => {\n const { instance, variant, labelOrientation } = useStepper()\n\n const methods = instance.useStepper()\n\n const currentStep = methods.current\n\n const isLast = instance.utils.getLast().id === of.id\n const stepIndex = instance.utils.getIndex(of.id)\n const currentIndex = instance.utils.getIndex(currentStep?.id ?? \"\")\n const isActive = currentStep?.id === of.id\n\n const dataState = getStepState(currentIndex, stepIndex)\n const childMap = useStepChildren(children)\n\n const title = childMap.get(\"title\")\n const description = childMap.get(\"description\")\n const panel = childMap.get(\"panel\")\n\n if (variant === \"circle\") {\n return (\n \n \n
\n {title}\n {description}\n
\n \n )\n }\n\n return (\n <>\n \n \n onStepKeyDown(\n e,\n instance.utils.getNext(of.id),\n instance.utils.getPrev(of.id)\n )\n }\n {...props}\n >\n {icon ?? stepIndex + 1}\n \n {variant === \"horizontal\" && labelOrientation === \"vertical\" && (\n \n )}\n
\n {title}\n {description}\n
\n \n\n {variant === \"horizontal\" && labelOrientation === \"horizontal\" && (\n \n )}\n\n {variant === \"vertical\" && (\n
\n {!isLast && (\n
\n \n
\n )}\n
{panel}
\n
\n )}\n \n )\n}\n\nconst StepperSeparator = ({\n orientation,\n isLast,\n labelOrientation,\n state,\n disabled,\n}: {\n isLast: boolean\n state: string\n disabled?: boolean\n} & VariantProps) => {\n if (isLast) {\n return null\n }\n return (\n \n )\n}\n\nconst classForSeparator = cva(\n [\n \"bg-muted\",\n \"data-[state=completed]:bg-primary data-[disabled]:opacity-50\",\n \"transition-all duration-300 ease-in-out\",\n ],\n {\n variants: {\n orientation: {\n horizontal: \"h-0.5 flex-1\",\n vertical: \"h-full w-0.5\",\n },\n labelOrientation: {\n vertical:\n \"absolute left-[calc(50%+30px)] right-[calc(-50%+20px)] top-5 block shrink-0\",\n },\n },\n }\n)\n\nconst onStepKeyDown = (\n e: React.KeyboardEvent,\n nextStep: Stepperize.Step,\n prevStep: Stepperize.Step\n) => {\n const { key } = e\n const directions = {\n next: [\"ArrowRight\", \"ArrowDown\"],\n prev: [\"ArrowLeft\", \"ArrowUp\"],\n }\n\n if (directions.next.includes(key) || directions.prev.includes(key)) {\n const direction = directions.next.includes(key) ? \"next\" : \"prev\"\n const step = direction === \"next\" ? nextStep : prevStep\n\n if (!step) {\n return\n }\n\n const stepElement = document.getElementById(`step-${step.id}`)\n if (!stepElement) {\n return\n }\n\n const isActive =\n stepElement.parentElement?.getAttribute(\"data-state\") !== \"inactive\"\n if (isActive || direction === \"prev\") {\n stepElement.focus()\n }\n }\n}\n\nconst getStepState = (currentIndex: number, stepIndex: number) => {\n if (currentIndex === stepIndex) {\n return \"active\"\n }\n if (currentIndex > stepIndex) {\n return \"completed\"\n }\n return \"inactive\"\n}\n\nconst extractChildren = (children: React.ReactNode) => {\n const childrenArray = React.Children.toArray(children)\n const map = new Map()\n\n for (const child of childrenArray) {\n if (React.isValidElement(child)) {\n if (child.type === StepperTitle) {\n map.set(\"title\", child)\n } else if (child.type === StepperDescription) {\n map.set(\"description\", child)\n } else if (child.type === StepperPanel) {\n map.set(\"panel\", child)\n }\n }\n }\n\n return map\n}\n\nconst useStepChildren = (children: React.ReactNode) => {\n return React.useMemo(() => extractChildren(children), [children])\n}\n\nconst StepperTitle = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"h4\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"h4\"\n\n return (\n \n {children}\n \n )\n}\n\nconst StepperDescription = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"p\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"p\"\n\n return (\n \n {children}\n \n )\n}\n\ntype CircleStepIndicatorProps = {\n currentStep: number\n totalSteps: number\n size?: number\n strokeWidth?: number\n}\n\nconst CircleStepIndicator = ({\n currentStep,\n totalSteps,\n size = 80,\n strokeWidth = 6,\n}: CircleStepIndicatorProps) => {\n const radius = (size - strokeWidth) / 2\n const circumference = radius * 2 * Math.PI\n const fillPercentage = (currentStep / totalSteps) * 100\n const dashOffset = circumference - (circumference * fillPercentage) / 100\n return (\n \n \n Step Indicator\n \n \n \n
\n \n {currentStep} of {totalSteps}\n \n
\n \n )\n}\n\nconst StepperPanel = ({\n children,\n className,\n asChild,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean\n}) => {\n const Comp = asChild ? Slot : \"div\"\n const { tracking } = useStepper()\n\n return (\n scrollIntoStepperPanel(node, tracking)}\n {...props}\n >\n {children}\n \n )\n}\n\nfunction scrollIntoStepperPanel(\n node: HTMLDivElement | null,\n tracking?: boolean\n) {\n if (tracking) {\n node?.scrollIntoView({ behavior: \"smooth\", block: \"center\" })\n }\n}\n\nconst StepperControls = ({\n children,\n asChild,\n ...props\n}: React.ComponentProps<\"div\"> & { asChild?: boolean }) => {\n const Comp = asChild ? Slot : \"div\"\n return (\n \n {children}\n \n )\n}\n\nconst defineStepper: typeof Stepperize.defineStepper = Stepperize.defineStepper\n\nexport {\n defineStepper,\n Stepper,\n StepperControls,\n StepperDescription,\n StepperNavigation,\n StepperPanel,\n StepperStep,\n StepperTitle,\n}\n", "type": "registry:ui", "target": "" } diff --git a/apps/www/registry/default/examples/stepper-demo.tsx b/apps/www/registry/default/examples/stepper-demo.tsx index d77ef0677c3..50bf927e75b 100644 --- a/apps/www/registry/default/examples/stepper-demo.tsx +++ b/apps/www/registry/default/examples/stepper-demo.tsx @@ -1,6 +1,8 @@ +import * as React from "react" + +import { Button } from "@/registry/default/ui/button" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -25,7 +27,6 @@ const stepperInstance = defineStepper( ) export default function StepperDemo() { - const steps = stepperInstance.steps return ( {({ methods }) => ( - <> + - {steps.map((step) => ( + {methods.all.map((step) => ( ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + - +
)}
) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} diff --git a/apps/www/registry/default/examples/stepper-description.tsx b/apps/www/registry/default/examples/stepper-description.tsx index 5bb54592c7b..f28f20a384b 100644 --- a/apps/www/registry/default/examples/stepper-description.tsx +++ b/apps/www/registry/default/examples/stepper-description.tsx @@ -1,6 +1,8 @@ +import * as React from "react" + +import { Button } from "@/registry/default/ui/button" import { Stepper, - StepperAction, StepperControls, StepperDescription, StepperNavigation, @@ -29,7 +31,6 @@ const stepperInstance = defineStepper( ) export default function StepperDemo() { - const steps = stepperInstance.steps return ( {({ methods }) => ( - <> + - {steps.map((step) => ( + {methods.all.map((step) => ( ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + - +
)}
) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} diff --git a/apps/www/registry/default/examples/stepper-form.tsx b/apps/www/registry/default/examples/stepper-form.tsx index a5c3184d98a..dbbbdb069d7 100644 --- a/apps/www/registry/default/examples/stepper-form.tsx +++ b/apps/www/registry/default/examples/stepper-form.tsx @@ -1,12 +1,13 @@ +import * as React from "react" import { zodResolver } from "@hookform/resolvers/zod" import { useForm, useFormContext } from "react-hook-form" import { z } from "zod" +import { Button } from "@/registry/default/ui/button" import { Form } from "@/registry/default/ui/form" import { Input } from "@/registry/default/ui/input" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperStep, @@ -29,93 +30,6 @@ const paymentSchema = z.object({ type ShippingFormValues = z.infer type PaymentFormValues = z.infer -const stepperInstance = defineStepper( - { - id: "shipping", - title: "Shipping", - schema: shippingSchema, - }, - { - id: "payment", - title: "Payment", - schema: paymentSchema, - }, - { - id: "complete", - title: "Complete", - schema: z.object({}), - } -) - -export default function StepperForm() { - return ( - - - - ) -} - -const FormStepperComponent = () => { - const { steps, useStepper, utils } = stepperInstance - const methods = useStepper() - - const form = useForm({ - mode: "onTouched", - resolver: zodResolver(methods.current.schema), - }) - - const onSubmit = (values: z.infer) => { - console.log(`Form values for step ${methods.current.id}:`, values) - } - - const currentIndex = utils.getIndex(methods.current.id) - - return ( -
- - - {steps.map((step) => ( - { - const valid = await form.trigger() - if (!valid) return - if (utils.getIndex(step.id) - currentIndex > 1) return - methods.goTo(step.id) - }} - > - {step.title} - - ))} - - {methods.switch({ - shipping: () => , - payment: () => , - complete: () => , - })} - - Previous - { - const valid = await form.trigger() - if (!valid) return false - if (utils.getIndex(nextStep.id as any) - currentIndex > 1) - return false - return true - }} - > - Next - - Reset - - - - ) -} - const ShippingForm = () => { const { register, @@ -249,3 +163,100 @@ function PaymentForm() { function CompleteComponent() { return
Thank you! Your order is complete.
} + +const stepperInstance = defineStepper( + { + id: "shipping", + title: "Shipping", + schema: shippingSchema, + Component: ShippingForm, + }, + { + id: "payment", + title: "Payment", + schema: paymentSchema, + Component: PaymentForm, + }, + { + id: "complete", + title: "Complete", + schema: z.object({}), + Component: CompleteComponent, + } +) + +export default function StepperForm() { + return ( + + + + ) +} + +const FormStepperComponent = () => { + const { useStepper } = stepperInstance + const methods = useStepper() + + const form = useForm({ + mode: "onTouched", + resolver: zodResolver(methods.current.schema), + }) + + const onSubmit = (values: z.infer) => { + console.log(`Form values for step ${methods.current.id}:`, values) + } + + return ( +
+ + + {methods.all.map((step) => ( + { + const valid = await form.trigger() + if (!valid) return + methods.goTo(step.id) + }} + > + {step.title} + + ))} + + {methods.switch({ + shipping: ({ Component }) => , + payment: ({ Component }) => , + complete: ({ Component }) => , + })} + + {!methods.isLast && ( + + )} + + + + + ) +} diff --git a/apps/www/registry/default/examples/stepper-icon.tsx b/apps/www/registry/default/examples/stepper-icon.tsx index 45caf09fb9e..a6039f007ee 100644 --- a/apps/www/registry/default/examples/stepper-icon.tsx +++ b/apps/www/registry/default/examples/stepper-icon.tsx @@ -1,8 +1,9 @@ +import * as React from "react" import { HomeIcon, SettingsIcon, UserIcon } from "lucide-react" +import { Button } from "@/registry/default/ui/button" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -29,8 +30,7 @@ const stepperInstance = defineStepper( } ) -export default function StepperIcon() { - const steps = stepperInstance.steps +export default function StepperDemo() { return ( {({ methods }) => ( - <> + - {steps.map((step) => ( + {methods.all.map((step) => ( ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + - +
)}
) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} diff --git a/apps/www/registry/default/examples/stepper-label-orientation.tsx b/apps/www/registry/default/examples/stepper-label-orientation.tsx index 136a02d15d4..f50027a9695 100644 --- a/apps/www/registry/default/examples/stepper-label-orientation.tsx +++ b/apps/www/registry/default/examples/stepper-label-orientation.tsx @@ -1,10 +1,10 @@ import * as React from "react" +import { Button } from "@/registry/default/ui/button" import { Label } from "@/registry/default/ui/label" import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -31,8 +31,6 @@ const stepperInstance = defineStepper( ) export default function StepperVariants() { - const steps = stepperInstance.steps - const [labelOrientation, setLabelOrientation] = React.useState("horizontal") return ( @@ -59,9 +57,9 @@ export default function StepperVariants() { labelOrientation={labelOrientation} > {({ methods }) => ( - <> + - {steps.map((step) => ( + {methods.all.map((step) => ( ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + - +
)} ) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} diff --git a/apps/www/registry/default/examples/stepper-responsive-variant.tsx b/apps/www/registry/default/examples/stepper-responsive-variant.tsx index 85fb106db93..5f2cc917961 100644 --- a/apps/www/registry/default/examples/stepper-responsive-variant.tsx +++ b/apps/www/registry/default/examples/stepper-responsive-variant.tsx @@ -1,7 +1,9 @@ +import * as React from "react" + import { useMediaQuery } from "@/hooks/use-media-query" +import { Button } from "@/registry/default/ui/button" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -26,7 +28,6 @@ const stepperInstance = defineStepper( ) export default function StepperResponsiveVariant() { - const steps = stepperInstance.steps const isMobile = useMediaQuery("(max-width: 768px)") return ( ( <> - {steps.map((step) => ( + {methods.all.map((step) => ( methods.goTo(step.id)} > {step.title} - {isMobile && ( - - {({ step }) => ( + {isMobile && + methods.when(step.id, (step) => ( +

Content for {step.id}

- )} -
- )} +
+ ))}
))}
{!isMobile && - steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + )}
) } + +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} diff --git a/apps/www/registry/default/examples/stepper-tracking.tsx b/apps/www/registry/default/examples/stepper-tracking.tsx index 9f8a550e06f..d745fdf4d34 100644 --- a/apps/www/registry/default/examples/stepper-tracking.tsx +++ b/apps/www/registry/default/examples/stepper-tracking.tsx @@ -1,10 +1,10 @@ import * as React from "react" +import { Button } from "@/registry/default/ui/button" import { Label } from "@/registry/default/ui/label" import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -41,8 +41,6 @@ const stepperInstance = defineStepper( ) export default function StepperVerticalFollow() { - const steps = stepperInstance.steps - const [tracking, setTracking] = React.useState(false) return (
@@ -68,25 +66,40 @@ export default function StepperVerticalFollow() { {({ methods }) => ( <> - {steps.map((step) => ( + {methods.all.map((step) => ( methods.goTo(step.id)} > {step.title} - -
-

- Content for {step.id} -

-
- - Previous - Next - Reset - -
+ {methods.when(step.id, () => ( + +
+

+ Content for {step.id} +

+
+ + {!methods.isLast && ( + + )} + + +
+ ))}
))}
diff --git a/apps/www/registry/default/examples/stepper-variants.tsx b/apps/www/registry/default/examples/stepper-variants.tsx index f8aaef2a02d..06c12a65141 100644 --- a/apps/www/registry/default/examples/stepper-variants.tsx +++ b/apps/www/registry/default/examples/stepper-variants.tsx @@ -1,10 +1,10 @@ import * as React from "react" +import { Button } from "@/registry/default/ui/button" import { Label } from "@/registry/default/ui/label" import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group" import { Stepper, - StepperAction, StepperControls, StepperNavigation, StepperPanel, @@ -31,8 +31,6 @@ const stepperInstance = defineStepper( ) export default function StepperVariants() { - const steps = stepperInstance.steps - const [variant, setVariant] = React.useState("horizontal") return (
@@ -69,7 +67,7 @@ const HorizontalStepper = () => { variant="horizontal" > {({ methods }) => ( - <> + {steps.map((step) => ( { ))} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} + {methods.switch({ + "step-1": (step) => , + "step-2": (step) => , + "step-3": (step) => , + })} - Previous - Next - Reset + {!methods.isLast && ( + + )} + - +
)} ) } +const Content = ({ id }: { id: string }) => { + return ( + +

Content for {id}

+
+ ) +} + const VerticalStepper = () => { - const steps = stepperInstance.steps return ( { {({ methods }) => ( <> - {steps.map((step) => ( + {methods.all.map((step) => ( methods.goTo(step.id)} > {step.title} - - {({ step }) => ( + {methods.when(step.id, () => ( +

Content for {step.id}

- )} -
+
+ ))}
))}
- Previous - Next - Reset + {!methods.isLast && ( + + )} + )} @@ -145,7 +158,6 @@ const VerticalStepper = () => { } const CircleStepper = () => { - const steps = stepperInstance.steps return ( {({ methods }) => ( @@ -155,21 +167,26 @@ const CircleStepper = () => { {methods.current.title} - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} + {methods.when(methods.current.id, () => ( + +

+ Content for {methods.current.id} +

))} - Previous - Next - Reset + {!methods.isLast && ( + + )} + )} diff --git a/apps/www/registry/default/examples/stepper-with-description.tsx b/apps/www/registry/default/examples/stepper-with-description.tsx deleted file mode 100644 index 5b50b9d014a..00000000000 --- a/apps/www/registry/default/examples/stepper-with-description.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { - Stepper, - StepperAction, - StepperControls, - StepperDescription, - StepperNavigation, - StepperPanel, - StepperStep, - StepperTitle, - defineStepper, -} from "@/registry/default/ui/stepper" - -const stepperInstance = defineStepper( - { - id: "step-1", - title: "Step 1", - description: "This is the first step", - }, - { - id: "step-2", - title: "Step 2", - description: "This is the second step", - }, - { - id: "step-3", - title: "Step 3", - description: "This is the third step", - } -) - -export default function StepperWithDescription() { - const steps = stepperInstance.steps - return ( - - {({ methods }) => ( - <> - - {steps.map((step) => ( - methods.goTo(step.id)} - > - {step.title} - {step.description} - - ))} - - {steps.map((step) => ( - - {({ step }) => ( -

Content for {step.id}

- )} -
- ))} - - Previous - Next - Reset - - - )} -
- ) -} diff --git a/apps/www/registry/default/ui/stepper.tsx b/apps/www/registry/default/ui/stepper.tsx index 77ebbc599d7..053155850ac 100644 --- a/apps/www/registry/default/ui/stepper.tsx +++ b/apps/www/registry/default/ui/stepper.tsx @@ -3,15 +3,11 @@ import * as React from "react" import { Slot } from "@radix-ui/react-slot" import * as Stepperize from "@stepperize/react" -import { VariantProps, cva } from "class-variance-authority" +import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" import { Button } from "@/registry/default/ui/button" -type StepperProviderProps = StepperConfig & { - children: React.ReactNode -} - type StepperVariant = "horizontal" | "vertical" | "circle" type StepperLabelOrientation = "horizontal" | "vertical" @@ -22,59 +18,74 @@ type StepperConfig = { tracking?: boolean } -const StepContext = React.createContext>({ - instance: {} as ReturnType>, - variant: "horizontal", -}) +type StepperProviderProps = StepperConfig & { + children: React.ReactNode +} + +const StepContext = React.createContext | null>(null) const StepperProvider = ({ children, ...props }: StepperProviderProps) => { - const Scope = props.instance.Scoped + const { instance } = props + const Scoped = instance.Scoped return ( - + {children} - + ) } const useStepper = (): StepperConfig => { const context = React.useContext(StepContext) if (!context) { - throw new Error("useStepper must be used within a Stepper") + throw new Error("useStepper must be used within a StepperProvider.") } return context } -function Stepper({ +type StepperProps = StepperConfig & + Omit, "children"> & { + children: + | React.ReactNode + | ((props: { methods: Stepperize.Stepper }) => React.ReactNode) + } + +const Stepper = ({ children, variant = "horizontal", - className, labelOrientation = "horizontal", tracking = false, + instance, ...props -}: StepperConfig & - Omit, "children"> & { - children: - | React.ReactNode - | ((props: { methods: Stepperize.Stepper }) => React.ReactNode) - }) { - const { instance } = props +}: StepperProps) => ( + + {children} + +) - const methods = instance.useStepper() as Stepperize.Stepper +const StepperContainer = ({ + children, + className, + ...props +}: Omit, "children"> & { + children: + | React.ReactNode + | ((props: { methods: Stepperize.Stepper }) => React.ReactNode) +}) => { + const { instance } = useStepper() + const methods = instance.useStepper() return ( - -
- {typeof children === "function" ? children({ methods }) : children} -
-
+
+ {typeof children === "function" ? children({ methods }) : children} +
) } @@ -86,9 +97,7 @@ const StepperNavigation = ({ }: Omit, "children"> & { children: React.ReactNode }) => { - const { variant, instance } = useStepper() - - const methods = instance.useStepper() as Stepperize.Stepper + const { variant } = useStepper() return (