diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8f860968..2e91d73b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 9.12.0 '@huntabyte/eslint-config': specifier: ^0.3.2 - version: 0.3.2(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0)) + version: 0.3.2(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3) '@typescript-eslint/eslint-plugin': specifier: ^8.10.0 version: 8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3) @@ -172,8 +172,8 @@ importers: specifier: ^10.4.19 version: 10.4.20(postcss@8.4.47) bits-ui: - specifier: 1.0.0-next.28 - version: 1.0.0-next.28(svelte@5.0.4) + specifier: 1.0.0-next.30 + version: 1.0.0-next.30(svelte@5.0.4) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -2299,6 +2299,12 @@ packages: peerDependencies: svelte: ^5.0.0-next.1 + bits-ui@1.0.0-next.30: + resolution: {integrity: sha512-CvoJ2kJ3Y+uhmHSFMvgyfkuB9ChGVwj1Hr+QxDJdzrgiAA9jHejI/bIp4xFbUYFaLafkoAbZxei9c88HRps11Q==} + engines: {node: '>=18', pnpm: '>=8.7.0'} + peerDependencies: + svelte: ^5.0.0-next.1 + blake3-wasm@2.1.5: resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} @@ -6026,7 +6032,7 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@antfu/eslint-config@2.22.0(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0))': + '@antfu/eslint-config@2.22.0(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3)': dependencies: '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 @@ -6051,7 +6057,7 @@ snapshots: eslint-plugin-toml: 0.11.1(eslint@9.7.0) eslint-plugin-unicorn: 54.0.0(eslint@9.7.0) eslint-plugin-unused-imports: 4.0.0(@typescript-eslint/eslint-plugin@8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0) - eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0)) + eslint-plugin-vitest: 0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3)(vitest@2.1.3) eslint-plugin-vue: 9.27.0(eslint@9.7.0) eslint-plugin-yml: 1.14.0(eslint@9.7.0) eslint-processor-vue-blocks: 0.1.2(@vue/compiler-sfc@3.5.12)(eslint@9.7.0) @@ -6738,9 +6744,9 @@ snapshots: '@humanwhocodes/retry@0.3.0': {} - '@huntabyte/eslint-config@0.3.2(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0))': + '@huntabyte/eslint-config@0.3.2(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3)': dependencies: - '@antfu/eslint-config': 2.22.0(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0)) + '@antfu/eslint-config': 2.22.0(@vue/compiler-sfc@3.5.12)(eslint-plugin-svelte@2.44.1(eslint@9.7.0)(svelte@5.0.4))(eslint@9.7.0)(svelte-eslint-parser@0.42.0(svelte@5.0.4))(svelte@5.0.4)(typescript@5.6.3)(vitest@2.1.3) '@antfu/install-pkg': 0.3.3 '@clack/prompts': 0.7.0 '@huntabyte/eslint-plugin': 0.1.0(eslint@9.7.0) @@ -7798,7 +7804,7 @@ snapshots: chai: 5.1.1 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.4.9(@types/node@20.16.14)(terser@5.36.0))': + '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.4.9)': dependencies: '@vitest/spy': 2.1.3 estree-walker: 3.0.3 @@ -8067,6 +8073,16 @@ snapshots: svelte: 5.0.4 svelte-toolbelt: 0.4.4(svelte@5.0.4) + bits-ui@1.0.0-next.30(svelte@5.0.4): + dependencies: + '@floating-ui/core': 1.6.4 + '@floating-ui/dom': 1.6.7 + '@internationalized/date': 3.5.6 + esm-env: 1.0.0 + runed: 0.15.2(svelte@5.0.4) + svelte: 5.0.4 + svelte-toolbelt: 0.4.4(svelte@5.0.4) + blake3-wasm@2.1.5: {} boolbase@1.0.0: {} @@ -9084,7 +9100,7 @@ snapshots: optionalDependencies: '@typescript-eslint/eslint-plugin': 8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3) - eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3)(vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0)): + eslint-plugin-vitest@0.5.4(@typescript-eslint/eslint-plugin@8.0.0-alpha.40(@typescript-eslint/parser@8.0.0-alpha.40(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3))(eslint@9.7.0)(typescript@5.6.3)(vitest@2.1.3): dependencies: '@typescript-eslint/utils': 7.16.0(eslint@9.7.0)(typescript@5.6.3) eslint: 9.7.0 @@ -12311,7 +12327,7 @@ snapshots: vitest@2.1.3(@types/node@20.16.14)(terser@5.36.0): dependencies: '@vitest/expect': 2.1.3 - '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.9(@types/node@20.16.14)(terser@5.36.0)) + '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.9) '@vitest/pretty-format': 2.1.3 '@vitest/runner': 2.1.3 '@vitest/snapshot': 2.1.3 diff --git a/sites/docs/package.json b/sites/docs/package.json index ad4bb7ee9..784613cb8 100644 --- a/sites/docs/package.json +++ b/sites/docs/package.json @@ -43,7 +43,7 @@ "acorn": "^8.13.0", "acorn-typescript": "^1.4.13", "autoprefixer": "^10.4.19", - "bits-ui": "1.0.0-next.28", + "bits-ui": "1.0.0-next.30", "clsx": "^2.1.1", "concurrently": "^9.0.1", "d3-scale": "^4.0.2", diff --git a/sites/docs/src/__registry__/index.js b/sites/docs/src/__registry__/index.js index abe2f098a..5669d0911 100644 --- a/sites/docs/src/__registry__/index.js +++ b/sites/docs/src/__registry__/index.js @@ -531,6 +531,38 @@ export const Index = { files: ["../lib/registry/default/example/input-file.svelte"], raw: () => import("../lib/registry/default/example/input-file.svelte?raw").then((m) => m.default), }, + "input-otp-demo": { + name: "input-otp-demo", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/default/example/input-otp-demo.svelte").then((m) => m.default), + files: ["../lib/registry/default/example/input-otp-demo.svelte"], + raw: () => import("../lib/registry/default/example/input-otp-demo.svelte?raw").then((m) => m.default), + }, + "input-otp-form": { + name: "input-otp-form", + type: "registry:example", + registryDependencies: ["input-otp","form"], + component: () => import("../lib/registry/default/example/input-otp-form.svelte").then((m) => m.default), + files: ["../lib/registry/default/example/input-otp-form.svelte"], + raw: () => import("../lib/registry/default/example/input-otp-form.svelte?raw").then((m) => m.default), + }, + "input-otp-pattern": { + name: "input-otp-pattern", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/default/example/input-otp-pattern.svelte").then((m) => m.default), + files: ["../lib/registry/default/example/input-otp-pattern.svelte"], + raw: () => import("../lib/registry/default/example/input-otp-pattern.svelte?raw").then((m) => m.default), + }, + "input-otp-separator": { + name: "input-otp-separator", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/default/example/input-otp-separator.svelte").then((m) => m.default), + files: ["../lib/registry/default/example/input-otp-separator.svelte"], + raw: () => import("../lib/registry/default/example/input-otp-separator.svelte?raw").then((m) => m.default), + }, "input-with-button": { name: "input-with-button", type: "registry:example", @@ -1564,6 +1596,38 @@ export const Index = { files: ["../lib/registry/new-york/example/input-file.svelte"], raw: () => import("../lib/registry/new-york/example/input-file.svelte?raw").then((m) => m.default), }, + "input-otp-demo": { + name: "input-otp-demo", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/new-york/example/input-otp-demo.svelte").then((m) => m.default), + files: ["../lib/registry/new-york/example/input-otp-demo.svelte"], + raw: () => import("../lib/registry/new-york/example/input-otp-demo.svelte?raw").then((m) => m.default), + }, + "input-otp-form": { + name: "input-otp-form", + type: "registry:example", + registryDependencies: ["input-otp","form"], + component: () => import("../lib/registry/new-york/example/input-otp-form.svelte").then((m) => m.default), + files: ["../lib/registry/new-york/example/input-otp-form.svelte"], + raw: () => import("../lib/registry/new-york/example/input-otp-form.svelte?raw").then((m) => m.default), + }, + "input-otp-pattern": { + name: "input-otp-pattern", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/new-york/example/input-otp-pattern.svelte").then((m) => m.default), + files: ["../lib/registry/new-york/example/input-otp-pattern.svelte"], + raw: () => import("../lib/registry/new-york/example/input-otp-pattern.svelte?raw").then((m) => m.default), + }, + "input-otp-separator": { + name: "input-otp-separator", + type: "registry:example", + registryDependencies: ["input-otp"], + component: () => import("../lib/registry/new-york/example/input-otp-separator.svelte").then((m) => m.default), + files: ["../lib/registry/new-york/example/input-otp-separator.svelte"], + raw: () => import("../lib/registry/new-york/example/input-otp-separator.svelte?raw").then((m) => m.default), + }, "input-with-button": { name: "input-with-button", type: "registry:example", diff --git a/sites/docs/src/content/components/input-otp.md b/sites/docs/src/content/components/input-otp.md new file mode 100644 index 000000000..0a03bd555 --- /dev/null +++ b/sites/docs/src/content/components/input-otp.md @@ -0,0 +1,129 @@ +--- +title: Input OTP +description: Accessible one-time password component with copy paste functionality. +component: true +links: + source: https://github.com/huntabyte/shadcn-svelte/tree/main/sites/docs/src/lib/registry/default/ui/input-otp + doc: https://next.bits-ui.com/docs/components/pin-input + api: https://next.bits-ui.com/docs/components/pin-input#api-reference +--- + + + + + +
+ +
+ +## About + +Input OTP is built on top of Bits UI's [PinInput](https://next.bits-ui.com/docs/components/pin-input) which is inspired by [@guilherme_rodz](https://twitter.com/guilherme_rodz)'s Input OTP component. + +## Installation + + +{#snippet cli()} + +{/snippet} +{#snippet manual()} + + + +Install `bits-ui`: + + + +Copy and paste the component source files linked at the top of this page into your project. + +{/snippet} + + +## Usage + +```svelte + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 3) as cell} + + {/each} + + + + {#each cells.slice(0, 3) as cell} + + {/each} + + {/snippet} + +``` + +## Examples + +### Pattern + +Use the `pattern` prop to define a custom pattern for the OTP input. + + + +
+ +
+ +```svelte showLineNumbers {3,6} + + + + + +``` + +### Separator + +You can use the `InputOTP.Separator` component to add a separator between the groups of cells. + + + +
+ +
+ +```svelte showLineNumbers + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 2) as cell} + + {/each} + + + + {#each cells.slice(2, 4) as cell} + + {/each} + + {/snippet} + +``` + +### Form + + + +
+ +
diff --git a/sites/docs/src/lib/components/docs/component-preview.svelte b/sites/docs/src/lib/components/docs/component-preview.svelte index ed189d41c..7fe11d63b 100644 --- a/sites/docs/src/lib/components/docs/component-preview.svelte +++ b/sites/docs/src/lib/components/docs/component-preview.svelte @@ -28,6 +28,7 @@ let component: Promise = $state() as Promise; $effect(() => { + console.log(Index[$config.style][name]); component = Index[$config.style][name]?.component() as Promise; }); diff --git a/sites/docs/src/lib/config/docs.ts b/sites/docs/src/lib/config/docs.ts index c81e365f0..1590526fc 100644 --- a/sites/docs/src/lib/config/docs.ts +++ b/sites/docs/src/lib/config/docs.ts @@ -222,6 +222,12 @@ export const docsConfig: DocsConfig = { href: "/docs/components/input", items: [], }, + { + title: "Input OTP", + href: "/docs/components/input-otp", + items: [], + label: "New", + }, { title: "Label", href: "/docs/components/label", diff --git a/sites/docs/src/lib/registry/default/example/input-otp-demo.svelte b/sites/docs/src/lib/registry/default/example/input-otp-demo.svelte new file mode 100644 index 000000000..f8f013afe --- /dev/null +++ b/sites/docs/src/lib/registry/default/example/input-otp-demo.svelte @@ -0,0 +1,19 @@ + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 3) as cell} + + {/each} + + + + {#each cells.slice(3, 6) as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/default/example/input-otp-form.svelte b/sites/docs/src/lib/registry/default/example/input-otp-form.svelte new file mode 100644 index 000000000..f6f2000af --- /dev/null +++ b/sites/docs/src/lib/registry/default/example/input-otp-form.svelte @@ -0,0 +1,59 @@ + + + + +
+ + + {#snippet children({ props })} + + {#snippet children({ cells })} + + {#each cells as cell} + + {/each} + + {/snippet} + + {/snippet} + + Please enter the one-time password sent to your phone. + + + Submit + {#if browser} + + {/if} + diff --git a/sites/docs/src/lib/registry/default/example/input-otp-pattern.svelte b/sites/docs/src/lib/registry/default/example/input-otp-pattern.svelte new file mode 100644 index 000000000..02f07e82e --- /dev/null +++ b/sites/docs/src/lib/registry/default/example/input-otp-pattern.svelte @@ -0,0 +1,14 @@ + + + + {#snippet children({ cells })} + + {#each cells as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/default/example/input-otp-separator.svelte b/sites/docs/src/lib/registry/default/example/input-otp-separator.svelte new file mode 100644 index 000000000..5d80da14a --- /dev/null +++ b/sites/docs/src/lib/registry/default/example/input-otp-separator.svelte @@ -0,0 +1,25 @@ + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 2) as cell} + + {/each} + + + + {#each cells.slice(2, 4) as cell} + + {/each} + + + + {#each cells.slice(4, 6) as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/default/ui/input-otp/index.ts b/sites/docs/src/lib/registry/default/ui/input-otp/index.ts new file mode 100644 index 000000000..e9ae273e9 --- /dev/null +++ b/sites/docs/src/lib/registry/default/ui/input-otp/index.ts @@ -0,0 +1,15 @@ +import Root from "./input-otp.svelte"; +import Group from "./input-otp-group.svelte"; +import Slot from "./input-otp-slot.svelte"; +import Separator from "./input-otp-separator.svelte"; + +export { + Root, + Group, + Slot, + Separator, + Root as InputOTP, + Group as InputOTPGroup, + Slot as InputOTPSlot, + Separator as InputOTPSeparator, +}; diff --git a/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-group.svelte b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-group.svelte new file mode 100644 index 000000000..7ef58a5a3 --- /dev/null +++ b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-group.svelte @@ -0,0 +1,16 @@ + + +
+ {@render children?.()} +
diff --git a/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-separator.svelte b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-separator.svelte new file mode 100644 index 000000000..40c9712fa --- /dev/null +++ b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-separator.svelte @@ -0,0 +1,19 @@ + + +
+ {#if children} + {@render children?.()} + {:else} + + {/if} +
diff --git a/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-slot.svelte b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-slot.svelte new file mode 100644 index 000000000..f5c6035c4 --- /dev/null +++ b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp-slot.svelte @@ -0,0 +1,30 @@ + + + + {cell.char} + {#if cell.hasFakeCaret} +
+ +
+ {/if} +
diff --git a/sites/docs/src/lib/registry/default/ui/input-otp/input-otp.svelte b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp.svelte new file mode 100644 index 000000000..8b59b3f40 --- /dev/null +++ b/sites/docs/src/lib/registry/default/ui/input-otp/input-otp.svelte @@ -0,0 +1,22 @@ + + + diff --git a/sites/docs/src/lib/registry/new-york/example/input-otp-demo.svelte b/sites/docs/src/lib/registry/new-york/example/input-otp-demo.svelte new file mode 100644 index 000000000..b0b8f3e54 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/example/input-otp-demo.svelte @@ -0,0 +1,19 @@ + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 3) as cell} + + {/each} + + + + {#each cells.slice(3, 6) as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/new-york/example/input-otp-form.svelte b/sites/docs/src/lib/registry/new-york/example/input-otp-form.svelte new file mode 100644 index 000000000..aceff3f2e --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/example/input-otp-form.svelte @@ -0,0 +1,59 @@ + + + + +
+ + + {#snippet children({ props })} + + {#snippet children({ cells })} + + {#each cells as cell} + + {/each} + + {/snippet} + + {/snippet} + + Please enter the one-time password sent to your phone. + + + Submit + {#if browser} + + {/if} + diff --git a/sites/docs/src/lib/registry/new-york/example/input-otp-pattern.svelte b/sites/docs/src/lib/registry/new-york/example/input-otp-pattern.svelte new file mode 100644 index 000000000..06f14ff74 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/example/input-otp-pattern.svelte @@ -0,0 +1,14 @@ + + + + {#snippet children({ cells })} + + {#each cells as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/new-york/example/input-otp-separator.svelte b/sites/docs/src/lib/registry/new-york/example/input-otp-separator.svelte new file mode 100644 index 000000000..e55eae51a --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/example/input-otp-separator.svelte @@ -0,0 +1,25 @@ + + + + {#snippet children({ cells })} + + {#each cells.slice(0, 2) as cell} + + {/each} + + + + {#each cells.slice(2, 4) as cell} + + {/each} + + + + {#each cells.slice(4, 6) as cell} + + {/each} + + {/snippet} + diff --git a/sites/docs/src/lib/registry/new-york/ui/input-otp/index.ts b/sites/docs/src/lib/registry/new-york/ui/input-otp/index.ts new file mode 100644 index 000000000..e9ae273e9 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/ui/input-otp/index.ts @@ -0,0 +1,15 @@ +import Root from "./input-otp.svelte"; +import Group from "./input-otp-group.svelte"; +import Slot from "./input-otp-slot.svelte"; +import Separator from "./input-otp-separator.svelte"; + +export { + Root, + Group, + Slot, + Separator, + Root as InputOTP, + Group as InputOTPGroup, + Slot as InputOTPSlot, + Separator as InputOTPSeparator, +}; diff --git a/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-group.svelte b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-group.svelte new file mode 100644 index 000000000..7ef58a5a3 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-group.svelte @@ -0,0 +1,16 @@ + + +
+ {@render children?.()} +
diff --git a/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-separator.svelte b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-separator.svelte new file mode 100644 index 000000000..eedef2f74 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-separator.svelte @@ -0,0 +1,19 @@ + + +
+ {#if children} + {@render children?.()} + {:else} + + {/if} +
diff --git a/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-slot.svelte b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-slot.svelte new file mode 100644 index 000000000..986d799ed --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp-slot.svelte @@ -0,0 +1,30 @@ + + + + {cell.char} + {#if cell.hasFakeCaret} +
+ +
+ {/if} +
diff --git a/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp.svelte b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp.svelte new file mode 100644 index 000000000..8b59b3f40 --- /dev/null +++ b/sites/docs/src/lib/registry/new-york/ui/input-otp/input-otp.svelte @@ -0,0 +1,22 @@ + + + diff --git a/sites/docs/src/routes/(app)/+page.server.ts b/sites/docs/src/routes/(app)/+page.server.ts index 8dee6183d..f65a63bcc 100644 --- a/sites/docs/src/routes/(app)/+page.server.ts +++ b/sites/docs/src/routes/(app)/+page.server.ts @@ -13,6 +13,7 @@ import { formSchema as textareaSchema } from "$lib/registry/default/example/text import { formSchema as comboboxFormSchema } from "$lib/registry/default/example/combobox-form.svelte"; import { formSchema as datePickerFormSchema } from "$lib/registry/default/example/date-picker-form.svelte"; import { formSchema as checkboxMultipleSchema } from "$lib/registry/default/example/checkbox-form-multiple.svelte"; +import { formSchema as inputOtpSchema } from "$lib/registry/default/example/input-otp-form.svelte"; export const actions: Actions = { username: async (e) => handleForm(e, formSchema), @@ -24,6 +25,7 @@ export const actions: Actions = { textarea: async (e) => handleForm(e, textareaSchema), combobox: async (e) => handleForm(e, comboboxFormSchema), datePicker: async (e) => handleForm(e, datePickerFormSchema), + inputOtp: async (e) => handleForm(e, inputOtpSchema), }; async function handleForm(event: RequestEvent, schema: AnyZodObject) { diff --git a/sites/docs/src/routes/(app)/docs/+layout.server.ts b/sites/docs/src/routes/(app)/docs/+layout.server.ts index a9358f050..bd99042f6 100644 --- a/sites/docs/src/routes/(app)/docs/+layout.server.ts +++ b/sites/docs/src/routes/(app)/docs/+layout.server.ts @@ -11,6 +11,7 @@ import { formSchema as textareaSchema } from "$lib/registry/default/example/text import { formSchema as comboboxFormSchema } from "$lib/registry/default/example/combobox-form.svelte"; import { formSchema as datePickerFormSchema } from "$lib/registry/default/example/date-picker-form.svelte"; import { formSchema as checkboxMultipleSchema } from "$lib/registry/default/example/checkbox-form-multiple.svelte"; +import { formSchema as inputOtpSchema } from "$lib/registry/default/example/input-otp-form.svelte"; export const load: LayoutServerLoad = async () => { return { @@ -23,6 +24,7 @@ export const load: LayoutServerLoad = async () => { textarea: await superValidate(zod(textareaSchema)), combobox: await superValidate(zod(comboboxFormSchema)), datePicker: await superValidate(zod(datePickerFormSchema)), + inputOtp: await superValidate(zod(inputOtpSchema)), }; };