From 27c682122642721b881bc3dd84e9a507983efe37 Mon Sep 17 00:00:00 2001 From: junwen-k <40173716+junwen-k@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:11:05 +0800 Subject: [PATCH 001/103] docs: add overhaul roadmap Tracks the effort to catch up with the modern shadcn/ui ecosystem: docs refresh, registry modernization, styling refresh, and Base UI support. Work merges into the long-running 'next' branch. Co-Authored-By: Claude Fable 5 --- ROADMAP.md | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 ROADMAP.md diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..4e3ff38 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,121 @@ +# ui-x Overhaul Roadmap + +> Tracking document for bringing ui-x up to date with the modern shadcn ecosystem. +> Philosophy is unchanged: **additional** accessible, customizable components that +> complement (not fork) shadcn/ui — focused on form-heavy and data-entry components +> shadcn doesn't ship. + +## Branch strategy + +Overhaul work happens on feature branches (`docs/…`, `feat/…`) merged into the +long-running **`next`** integration branch via PRs. `next` merges into `main` +only once the overhaul is finalized. + +## Guiding decisions + +- **v3 is frozen.** `apps/v3` (Tailwind v3) receives no new content. It gets a + banner — "You are viewing docs for Tailwind v3. Switch to latest →" — and the + Tailwind v4 site becomes canonical at `ui-x.junwen-k.dev`. +- **Mirror shadcn's library support**: offer both Radix UI and Base UI variants, + matching `npx shadcn create` (Base UI is shadcn's default since July 2026). +- **Own the niche, acknowledge the overlap.** Components that shadcn has since + added (Kbd, Button Group, Input Group, Combobox, …) get an honest callout and + a recommendation, rather than silently competing. + +--- + +## Phase 0 — Housekeeping (unblocks everything) + +- [x] Decide fate of WIP `location-input`: **abandoned** (2026-07-09) — stale, + untracked files deleted. May revisit from scratch in Phase 5. +- [ ] Upgrade `shadcn` CLI from `2.4.0-canary.13` to v3.x; verify + `pnpm build:registry` still produces a valid registry. +- [ ] Dependency pass on `apps/v4`: zod (pinned at 3.21.4), lucide-react, + react-day-picker, radix packages, tailwindcss. +- [ ] Confirm both sites still build and deploy (`turbo build`). + +## Phase 1 — Documentation up to date (user-visible, low risk) + +- [x] Add v3 "you are viewing old docs" banner in `apps/v3` linking to the v4 + site (keep the existing `version-dropdown-menu` as secondary navigation). +- [ ] Point canonical domain / SEO (sitemap, robots, `metadataBase`, og) at the + v4 site; v3 moves to a `v3.` subdomain or subpath. +- [x] Update `installation.mdx` with registry install instructions and + requirements (`index.mdx` / `tailwind-v4.mdx` reviewed, still accurate). +- [ ] Refresh `changelog.mdx` — deferred: write a single entry once the + overhaul actually ships, not piecemeal. +- [x] Clear stale "New" labels in `src/config/docs.ts`. +- [x] **Overlap callouts** added to kbd, control-group, input-base, combobox — + placed above the preview, recommending the official shadcn/ui version; + ui-x's is "provided as-is" (calendar and native-select still need a diff + vs shadcn's versions — tracked in the audit table below). + +### Component overlap audit + +| ui-x component | shadcn equivalent (date added) | Action | +| --- | --- | --- | +| `kbd` | Kbd (Oct 2025) | ✅ Callout: recommend official, ours as-is | +| `control-group` | Button Group (Oct 2025) | ✅ Callout: recommend official, ours as-is | +| `input-base` | Input Group (Oct 2025) | ✅ Callout: recommend official, ours as-is | +| `combobox` / `combobox-primitive` | Combobox (built on Base UI's primitive, even in the Radix flavor) | ✅ Callouts on both pages: recommend official, ours as-is | +| `calendar` | Calendar upgrade (Jun 2025) | Diff ours vs theirs; possibly rebase on theirs | +| `native-select` | Field/Select ecosystem | Verify overlap; callout if needed | +| date/time fields, phone-input, dropzone, file-list, confirmer, timeline, description-list, wheel-picker, badge-group, emoji-picker, sortable, virtualizer, time | none | Still differentiated — highlight these | + +## Phase 2 — Registry modernization (decides architecture for Phases 3–4) + +- [ ] Evaluate distribution options and pick one: + - [ ] Namespaced registry (`npx shadcn add @ui-x/date-field`) + - [ ] GitHub-repo-as-registry (https://ui.shadcn.com/docs/registry/github) + - [ ] Keep current self-hosted registry.json, upgraded to CLI v3 schema +- [ ] Decide registry layout for dual-library support (how shadcn structures + Radix vs Base UI items — mirror it) and for style variants (new-york, + Luma, Rhea?). +- [ ] Universal registry items where applicable (hooks, utilities). +- [ ] Consider exposing the registry via MCP server. +- [ ] Evaluate migrating the v4 docs site from velite to fumadocs (shadcn's + current setup) — decide before writing large amounts of new MDX content + so it only gets authored once. + +## Phase 3 — Component styling refresh + +- [ ] Update all ui-x components to match latest shadcn conventions: + `data-slot` attributes, current sizing/spacing, tw-animate-css idioms, + current `new-york` output of the v3 CLI. +- [ ] Re-sync the vendored shadcn `ui/` components in `apps/v4` used by the + docs site itself. +- [ ] Verify every demo/example still renders correctly after restyle. + +## Phase 4 — Base UI + Radix dual support + +- [ ] Port each ui-x component to Base UI primitives alongside the Radix + version (start with the differentiated set: date/time fields, + phone-input, dropzone, confirmer, …). +- [ ] Docs: per-component library switcher or install-command tabs + (Radix / Base UI), mirroring shadcn's docs UX. +- [ ] Update demos/examples for both variants. + +## Phase 5 — New components & catch-up (stretch) + +- [ ] Revisit `location-input` (Google Places) from Phase 0. +- [ ] Survey what's newly worth building that shadcn still lacks + (chat components arrived Jun 2026 — avoid; form/data-entry gaps — pursue). + +--- + +## Open questions + +- Deprecation policy — **partially decided (2026-07-09)**: overlapped + components stay published but are "provided as-is" with a prominent callout + recommending the official shadcn/ui version. Still open: whether they are + ever removed from the registry, and whether they get styling refreshes in + Phase 3. +- Do we adopt shadcn's newer styles (Luma/Rhea) or stay `new-york`-only? +- Monorepo: `packages/` is empty — flatten, or reserve for shared registry + tooling in Phase 2? + +## Status log + +- **2026-07-09** — Roadmap created. Current state: v4 site has 34 registry + items; last feature work Jun 2025; shadcn has since shipped CLI v3, MCP, + Base UI default, GitHub registries, and 7+ overlapping components. From 77c5a2f3843917b7519809476741c48a254ab008 Mon Sep 17 00:00:00 2001 From: junwen-k <40173716+junwen-k@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:11:14 +0800 Subject: [PATCH 002/103] feat(v3): add version banner linking to latest docs The Tailwind v3 site is now frozen; a banner above the header points visitors to the Tailwind v4 documentation. Co-Authored-By: Claude Fable 5 --- apps/v3/src/app/(app)/layout.tsx | 2 ++ apps/v3/src/components/version-banner.tsx | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 apps/v3/src/components/version-banner.tsx diff --git a/apps/v3/src/app/(app)/layout.tsx b/apps/v3/src/app/(app)/layout.tsx index 6c7b767..4133b23 100644 --- a/apps/v3/src/app/(app)/layout.tsx +++ b/apps/v3/src/app/(app)/layout.tsx @@ -1,6 +1,7 @@ import { SiteFooter } from "@/components/site-footer" import { SiteHeader } from "@/components/site-header" import { SiteMain } from "@/components/site-main" +import { VersionBanner } from "@/components/version-banner" interface AppLayoutProps { children: React.ReactNode @@ -9,6 +10,7 @@ interface AppLayoutProps { export default function AppLayout({ children }: AppLayoutProps) { return ( <> + {children} diff --git a/apps/v3/src/components/version-banner.tsx b/apps/v3/src/components/version-banner.tsx new file mode 100644 index 0000000..423cf01 --- /dev/null +++ b/apps/v3/src/components/version-banner.tsx @@ -0,0 +1,16 @@ +import Link from "next/link" +import { ArrowRightIcon } from "lucide-react" + +export function VersionBanner() { + return ( +
+ + You are viewing the docs for Tailwind CSS v3. Switch to latest + + +
+ ) +} From fd5d60c64423cd7919cabd0a33e952d31f50a151 Mon Sep 17 00:00:00 2001 From: junwen-k <40173716+junwen-k@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:11:26 +0800 Subject: [PATCH 003/103] docs: update installation guide and remove stale sidebar labels Installation now documents the registry-based install flow and requirements instead of only deferring to shadcn/ui. Removes year-old "New" labels from the sidebar config. Co-Authored-By: Claude Fable 5 --- apps/v4/src/config/docs.ts | 4 ---- apps/v4/src/content/docs/installation.mdx | 21 ++++++++++++++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/v4/src/config/docs.ts b/apps/v4/src/config/docs.ts index 05b4ea5..d24c86d 100644 --- a/apps/v4/src/config/docs.ts +++ b/apps/v4/src/config/docs.ts @@ -79,7 +79,6 @@ export const docsConfig = { { title: "Phone Input", href: "/docs/primitives/phone-input", - label: "New", items: [], }, ], @@ -155,7 +154,6 @@ export const docsConfig = { { title: "Emoji Picker", href: "/docs/components/emoji-picker", - label: "New", items: [], }, { @@ -196,7 +194,6 @@ export const docsConfig = { { title: "Phone Input", href: "/docs/components/phone-input", - label: "New", items: [], }, { @@ -217,7 +214,6 @@ export const docsConfig = { { title: "Wheel Picker", href: "/docs/components/wheel-picker", - label: "New", items: [], }, ], diff --git a/apps/v4/src/content/docs/installation.mdx b/apps/v4/src/content/docs/installation.mdx index e59665d..02cef02 100644 --- a/apps/v4/src/content/docs/installation.mdx +++ b/apps/v4/src/content/docs/installation.mdx @@ -3,4 +3,23 @@ title: Installation description: How to install dependencies and structure your app. --- -For installation instructions and setting up dependencies, please refer to the official Shadcn [installation guide](https://ui.shadcn.com/docs/installation). This guide provides the most up-to-date information for structuring your app and ensuring compatibility. +junwen-k/ui-x is an extension of [shadcn/ui](https://ui.shadcn.com) and is distributed through the same registry system. Set up shadcn/ui in your project first by following the official [installation guide](https://ui.shadcn.com/docs/installation) for your framework. + +## Requirements + +- A project set up with [shadcn/ui](https://ui.shadcn.com/docs/installation) (Tailwind CSS v4 and React 19 for the latest components — see the [Tailwind v3 docs](https://v3-ui-x.junwen-k.dev) if you are still on v3). +- Components are currently built on [Radix UI](https://www.radix-ui.com) primitives, matching shadcn/ui's Radix-based components. + +## Installing components + +Every component can be installed with the shadcn CLI by pointing at this registry: + +```bash +npx shadcn@latest add https://ui-x.junwen-k.dev/r/date-field.json +``` + +Each component's documentation page includes its exact install command, along with a manual installation option if you prefer to copy the source directly. + +## Utilities + +Utility docs such as [Sortable](/docs/utilities/sortable) and [Virtualizer](/docs/utilities/virtualizer) are guides built around third-party libraries — their pages describe which packages to install. From 7983b1408917277928765dbaa405a2963f859e82 Mon Sep 17 00:00:00 2001 From: junwen-k <40173716+junwen-k@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:11:35 +0800 Subject: [PATCH 004/103] docs: add callouts recommending official shadcn/ui components Kbd, Control Group, Input Base and Combobox predate their shadcn/ui equivalents. Each page now leads with a prominent callout recommending the official version; the ui-x components remain provided as-is. Co-Authored-By: Claude Fable 5 --- apps/v4/src/content/docs/components/combobox.mdx | 6 ++++++ apps/v4/src/content/docs/components/control-group.mdx | 6 ++++++ apps/v4/src/content/docs/components/input-base.mdx | 6 ++++++ apps/v4/src/content/docs/components/kbd.mdx | 6 ++++++ apps/v4/src/content/docs/primitives/combobox.mdx | 6 ++++++ 5 files changed, 30 insertions(+) diff --git a/apps/v4/src/content/docs/components/combobox.mdx b/apps/v4/src/content/docs/components/combobox.mdx index b5bc6fa..4c3cdcf 100644 --- a/apps/v4/src/content/docs/components/combobox.mdx +++ b/apps/v4/src/content/docs/components/combobox.mdx @@ -5,6 +5,12 @@ links: doc: /docs/primitives/combobox --- + + +**Note**: shadcn/ui now includes its own [Combobox](https://ui.shadcn.com/docs/components/combobox) component, built on Base UI's Combobox primitive. We recommend using the official version — this component predates it and is provided as-is. + + + + +**Note**: shadcn/ui now includes a [Button Group](https://ui.shadcn.com/docs/components/button-group) component, added in October 2025, which covers most of the same use cases. We recommend using the official version — this component predates it and is provided as-is. + + + ## Installation diff --git a/apps/v4/src/content/docs/components/input-base.mdx b/apps/v4/src/content/docs/components/input-base.mdx index 4e1ca9f..ce9c268 100644 --- a/apps/v4/src/content/docs/components/input-base.mdx +++ b/apps/v4/src/content/docs/components/input-base.mdx @@ -3,6 +3,12 @@ title: Input Base description: Base component to create custom inputs. --- + + +**Note**: shadcn/ui now includes an [Input Group](https://ui.shadcn.com/docs/components/input-group) component, added in October 2025, for decorating inputs with icons, buttons and text. For that use case we recommend the official version — this component predates it and is provided as-is. Input Base still serves as the foundation for other ui-x components such as [Combobox](/docs/components/combobox) and the date/time fields. + + + ## Installation diff --git a/apps/v4/src/content/docs/components/kbd.mdx b/apps/v4/src/content/docs/components/kbd.mdx index 55778a4..8dec366 100644 --- a/apps/v4/src/content/docs/components/kbd.mdx +++ b/apps/v4/src/content/docs/components/kbd.mdx @@ -3,6 +3,12 @@ title: Kbd description: Displays which key or combination of keys performs a given action. --- + + +**Note**: shadcn/ui now includes its own [Kbd](https://ui.shadcn.com/docs/components/kbd) component, added in October 2025. We recommend using the official version — this component predates it and is provided as-is. + + + ## Installation diff --git a/apps/v4/src/content/docs/primitives/combobox.mdx b/apps/v4/src/content/docs/primitives/combobox.mdx index ff5c609..043ce98 100644 --- a/apps/v4/src/content/docs/primitives/combobox.mdx +++ b/apps/v4/src/content/docs/primitives/combobox.mdx @@ -6,6 +6,12 @@ links: doc: https://cmdk.paco.me --- + + +**Note**: [Base UI](https://base-ui.com/react/components/combobox) now ships a native Combobox primitive, which shadcn/ui's official [Combobox](https://ui.shadcn.com/docs/components/combobox) is built on. We recommend using those — this primitive predates them and is provided as-is. + + + ## About From 5b152f5803d6e88bc02397670017c025ce7e5737 Mon Sep 17 00:00:00 2001 From: junwen-k <40173716+junwen-k@users.noreply.github.com> Date: Thu, 9 Jul 2026 12:36:39 +0800 Subject: [PATCH 005/103] feat(input-base): refresh input family styling to match latest shadcn/ui Add aria-invalid destructive ring support via has-[[data-slot][aria-invalid=true]], port current Input/Textarea classes (file:inline-flex file:h-7, field-sizing-content, min-w-0) and InputGroupAddon typography onto adornments. Co-Authored-By: Claude Fable 5 --- apps/v4/src/registry/new-york/ui/input-base.tsx | 9 +++++---- apps/v4/src/registry/new-york/ui/native-select.tsx | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/v4/src/registry/new-york/ui/input-base.tsx b/apps/v4/src/registry/new-york/ui/input-base.tsx index 5c1c54a..6f82e46 100644 --- a/apps/v4/src/registry/new-york/ui/input-base.tsx +++ b/apps/v4/src/registry/new-york/ui/input-base.tsx @@ -70,7 +70,8 @@ function InputBase({ } })} className={cn( - "border-input selection:bg-primary selection:text-primary-foreground dark:bg-input/30 flex min-h-9 cursor-text items-center gap-2 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm", + "border-input selection:bg-primary selection:text-primary-foreground dark:bg-input/30 flex min-h-9 w-full min-w-0 cursor-text items-center gap-2 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm", + "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[[data-slot][aria-invalid=true]]:border-destructive", disabled && "pointer-events-none cursor-not-allowed opacity-50", focused && "border-ring ring-ring/50 ring-[3px]", error && @@ -135,7 +136,7 @@ function InputBaseAdornment({ ) { > - onChange?.({ - target: { value }, - } as React.ChangeEvent) - } - > - - - - - {options?.map((option) => ( - - {option.label} - - ))} - - + +
+ {children} +
+ ); }, ...components, @@ -144,4 +179,42 @@ function Calendar({ ); } -export { Calendar }; +function CalendarDayButton({ + className, + day, + modifiers, + ...props +}: React.ComponentProps) { + const defaultClassNames = getDefaultClassNames(); + + const ref = React.useRef(null); + React.useEffect(() => { + if (modifiers.focused) ref.current?.focus(); + }, [modifiers.focused]); + + return ( + \n \n \n \n );\n },\n UNMOUNTING_DELAY,\n);\n\nexport const Confirmer = CallableConfirm.Root;\n\nexport const confirm = CallableConfirm.call;\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/control-group.json b/apps/v4/public/r/control-group.json index 3f21670..e969286 100644 --- a/apps/v4/public/r/control-group.json +++ b/apps/v4/public/r/control-group.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "control-group", - "type": "registry:ui", "title": "Control Group", "description": "A component for grouping form controls like text inputs, buttons, selects and other elements into a single cohesive unit.", "dependencies": [ @@ -14,5 +13,6 @@ "content": "\"use client\";\n\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst ControlGroupContext = React.createContext<\n Pick\n>({\n orientation: \"horizontal\",\n});\n\nfunction useControlGroup() {\n const context = React.useContext(ControlGroupContext);\n if (!context) {\n throw new Error(\"useControlGroup must be used within a .\");\n }\n\n return context;\n}\n\nexport interface ControlGroupProps\n extends React.ComponentProps {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\nfunction ControlGroup({\n className,\n orientation = \"horizontal\",\n ...props\n}: ControlGroupProps) {\n return (\n \n \n \n );\n}\n\nfunction ControlGroupItem({\n className,\n ...props\n}: React.ComponentProps) {\n const { orientation } = useControlGroup();\n\n return (\n \n );\n}\n\nexport { ControlGroup, ControlGroupItem };\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-field.json b/apps/v4/public/r/date-field.json index 61bc1d6..36f2849 100644 --- a/apps/v4/public/r/date-field.json +++ b/apps/v4/public/r/date-field.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-field", - "type": "registry:ui", "title": "Date Field", "description": "Date Field allows user to enter date value.", "registryDependencies": [ @@ -13,5 +12,6 @@ "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n DateTimeField,\n DateTimeFieldDays,\n DateTimeFieldMonths,\n DateTimeFieldSeparator,\n DateTimeFieldYears,\n} from \"@/registry/new-york/ui/date-time-field\";\n\nfunction DateField(props: React.ComponentProps) {\n return ;\n}\n\nfunction DateFieldSeparator({\n children = \"/\",\n ...props\n}: React.ComponentProps) {\n return (\n \n {children}\n \n );\n}\n\nfunction DateFieldYears(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DateFieldMonths(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DateFieldDays(props: React.ComponentProps) {\n return ;\n}\n\nexport {\n DateField,\n DateFieldSeparator,\n DateFieldYears,\n DateFieldMonths,\n DateFieldDays,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-picker-primitive.json b/apps/v4/public/r/date-picker-primitive.json index 4c144de..93791a1 100644 --- a/apps/v4/public/r/date-picker-primitive.json +++ b/apps/v4/public/r/date-picker-primitive.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-picker-primitive", - "type": "registry:ui", "title": "Date Picker", "description": "An unstyled date picker component.", "dependencies": [ @@ -23,5 +22,6 @@ "content": "\"use client\";\n\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport type * as Radix from \"@radix-ui/react-primitive\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { format } from \"date-fns\";\nimport * as React from \"react\";\nimport {\n type Mode as DatePickerMode,\n type DateRange,\n DayPicker,\n type DayPickerProps as DayPickerPrimitiveProps,\n} from \"react-day-picker\";\n\nimport * as DateTimeFieldPrimitive from \"@/registry/new-york/ui/date-time-field-primitive\";\nimport * as DateTimeRangeFieldPrimitive from \"@/registry/new-york/ui/date-time-range-field-primitive\";\n\n// TODO: start month / end month sync with calendar and date field\n\nexport type DatePickerContextProps = {\n formatStr: string;\n month?: Date;\n onMonthChange: (month: Date) => void;\n disabled?: boolean;\n} & (\n | Required<\n Pick<\n DatePickerSingleProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n | Required<\n Pick<\n DatePickerSingleRequiredProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n | Required<\n Pick<\n DatePickerMultipleProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n | Required<\n Pick<\n DatePickerMultipleRequiredProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n | Required<\n Pick<\n DatePickerRangeProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n | Required<\n Pick<\n DatePickerRangeRequiredProps,\n \"mode\" | \"required\" | \"value\" | \"onValueChange\"\n >\n >\n);\n\nconst DatePickerContext = React.createContext({\n mode: \"single\",\n formatStr: \"PPP\",\n month: undefined,\n onMonthChange: () => {},\n value: null,\n onValueChange: () => {},\n disabled: false,\n required: false,\n});\n\nfunction useDatePicker() {\n const context = React.useContext(DatePickerContext);\n if (!context) {\n throw new Error(\"useDatePicker must be used within a .\");\n }\n\n return context;\n}\n\nexport interface DatePickerBaseProps\n extends React.ComponentProps {\n mode?: DatePickerMode | undefined;\n required?: boolean;\n formatStr?: string;\n month?: Date;\n defaultMonth?: Date;\n onMonthChange?: (month: Date) => void;\n disabled?: boolean;\n}\n\nexport type DatePickerValue =\n T extends \"single\"\n ? Date\n : T extends \"multiple\"\n ? Date[]\n : T extends \"range\"\n ? DateRange\n : never;\n\nexport interface DatePickerSingleProps {\n mode: \"single\";\n required?: false | undefined;\n value?: Date | null;\n defaultValue?: Date;\n onValueChange?: (value: Date | null) => void;\n}\n\nexport interface DatePickerSingleRequiredProps {\n mode: \"single\";\n required: true;\n value?: Date;\n defaultValue?: Date;\n onValueChange?: (value: Date) => void;\n}\n\nexport interface DatePickerMultipleProps {\n mode: \"multiple\";\n required?: false | undefined;\n value?: Date[] | null;\n defaultValue?: Date[];\n onValueChange?: (value: Date[] | null) => void;\n}\n\nexport interface DatePickerMultipleRequiredProps {\n mode: \"multiple\";\n required: true;\n value?: Date[];\n defaultValue?: Date[];\n onValueChange?: (value: Date[]) => void;\n}\n\nexport interface DatePickerRangeProps {\n mode: \"range\";\n required?: false | undefined;\n value?: DateRange | null;\n defaultValue?: DateRange;\n onValueChange?: (value: DateRange | null) => void;\n}\n\nexport interface DatePickerRangeRequiredProps {\n mode: \"range\";\n required: true;\n value?: DateRange;\n defaultValue?: DateRange;\n onValueChange?: (value: DateRange) => void;\n}\n\nexport type DatePickerProps = DatePickerBaseProps &\n (\n | DatePickerSingleProps\n | DatePickerSingleRequiredProps\n | DatePickerMultipleProps\n | DatePickerMultipleRequiredProps\n | DatePickerRangeProps\n | DatePickerRangeRequiredProps\n );\n\nfunction DatePicker({\n mode = \"single\" as T,\n formatStr = \"PPP\",\n open,\n onOpenChange,\n defaultOpen,\n modal,\n children,\n month: monthProp,\n defaultMonth,\n onMonthChange,\n value: valueProp,\n defaultValue,\n onValueChange,\n disabled,\n required = false,\n}: DatePickerProps) {\n const [value, setValue] = useControllableState>({\n prop: valueProp as DatePickerValue,\n defaultProp: defaultValue as DatePickerValue,\n onChange: onValueChange as (value: DatePickerValue) => void,\n });\n const [month, setMonth] = useControllableState({\n prop: monthProp,\n defaultProp: defaultMonth ?? new Date(),\n onChange: onMonthChange,\n });\n\n return (\n \n \n {children}\n \n \n );\n}\n\nfunction DatePickerDateField({\n disabled: disabledProp,\n ...props\n}: Omit<\n React.ComponentProps,\n \"value\" | \"onValueChange\"\n>) {\n const { mode, onMonthChange, value, onValueChange, required, disabled } =\n useDatePicker();\n\n if (mode !== \"single\") {\n throw new Error(\n ' should only be used when mode is \"single\"',\n );\n }\n\n return (\n {\n if (date) {\n onValueChange(date);\n onMonthChange(date);\n } else if (!required) {\n onValueChange(null);\n }\n }}\n {...props}\n />\n );\n}\n\nfunction DatePickerDateRangeField({\n disabled: disabledProp,\n ...props\n}: Omit<\n React.ComponentProps,\n \"value\" | \"onValueChange\"\n>) {\n const { mode, onMonthChange, value, onValueChange, required, disabled } =\n useDatePicker();\n\n if (mode !== \"range\") {\n throw new Error(\n ' should only be used when mode is \"range\"',\n );\n }\n\n return (\n {\n if (value) {\n onValueChange(value);\n if (value.from) {\n onMonthChange(value.from);\n }\n } else if (!required) {\n onValueChange(null);\n }\n }}\n {...props}\n />\n );\n}\n\nfunction DatePickerClear({\n onClick,\n ...props\n}: React.ComponentProps) {\n const { required, value, onValueChange } = useDatePicker();\n\n return (\n !required && onValueChange(null),\n )}\n {...props}\n />\n );\n}\n\nexport interface DatePickerValueProps\n extends Radix.PrimitivePropsWithRef {\n placeholder?: React.ReactNode;\n}\n\nfunction DatePickerValue({\n placeholder,\n children,\n ...props\n}: DatePickerValueProps) {\n const { mode, formatStr, value } = useDatePicker();\n\n const isValueEmpty = React.useMemo(() => {\n if (mode === \"single\") {\n return !value;\n }\n if (mode === \"multiple\") {\n return !value?.length;\n }\n return !value?.from;\n }, [mode, value]);\n\n const formattedValue = React.useMemo(() => {\n if (!value) {\n return null;\n }\n if (mode === \"single\") {\n return format(value, formatStr);\n }\n if (mode === \"multiple\") {\n return value.map((v) => format(v, formatStr)).join(\", \");\n }\n return `${value.from ? format(value.from, formatStr) : \"Select a date\"} - ${value.to ? format(value.to, formatStr) : \"Select a date\"}`;\n }, [mode, value, formatStr]);\n\n return (\n \n {isValueEmpty ? placeholder : (children ?? formattedValue)}\n \n );\n}\n\nexport interface DatePickerCalendarProps\n extends Omit<\n DayPickerPrimitiveProps,\n | \"mode\"\n | \"selected\"\n | \"onSelect\"\n | \"month\"\n | \"onMonthChange\"\n | \"disabled\"\n | \"required\"\n > {\n asChild?: boolean;\n children?: React.ReactNode;\n}\n\nfunction DatePickerCalendar({\n asChild,\n autoFocus = true,\n ...props\n}: DatePickerCalendarProps) {\n const {\n mode,\n month,\n onMonthChange,\n value,\n onValueChange,\n disabled,\n required,\n } = useDatePicker();\n\n const Comp = asChild ? (Slot as typeof DayPicker) : DayPicker;\n\n return (\n )}\n onSelect={(value: Date | Date[] | DateRange | undefined) => {\n if (!value && !required) {\n onValueChange(null);\n }\n if (mode === \"single\") {\n onValueChange(value as Date);\n }\n if (mode === \"multiple\") {\n onValueChange(value as Date[]);\n }\n if (mode === \"range\") {\n onValueChange(value as DateRange);\n }\n }}\n month={month}\n onMonthChange={onMonthChange}\n disabled={disabled}\n autoFocus={autoFocus}\n {...props}\n />\n );\n}\n\nfunction DatePickerTrigger(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerContent(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerPortal(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DatePickerAnchor(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DatePickerDateFieldSeparator(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateFieldYears(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateFieldMonths(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateFieldDays(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldFrom(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldTo(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldSeparator(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldYears(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldMonths(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerDateRangeFieldDays(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nexport {\n DatePicker as Root,\n DatePickerDateField as DateField,\n DatePickerDateFieldSeparator as DateFieldSeparator,\n DatePickerDateFieldYears as DateFieldYears,\n DatePickerDateFieldMonths as DateFieldMonths,\n DatePickerDateFieldDays as DateFieldDays,\n DatePickerDateRangeField as DateRangeField,\n DatePickerDateRangeFieldFrom as DateRangeFieldFrom,\n DatePickerDateRangeFieldTo as DateRangeFieldTo,\n DatePickerDateRangeFieldSeparator as DateRangeFieldSeparator,\n DatePickerDateRangeFieldYears as DateRangeFieldYears,\n DatePickerDateRangeFieldMonths as DateRangeFieldMonths,\n DatePickerDateRangeFieldDays as DateRangeFieldDays,\n DatePickerValue as Value,\n DatePickerClear as Clear,\n DatePickerTrigger as Trigger,\n DatePickerAnchor as Anchor,\n DatePickerPortal as Portal,\n DatePickerContent as Content,\n DatePickerCalendar as Calendar,\n useDatePicker,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-picker.json b/apps/v4/public/r/date-picker.json index a90032b..a2b08c6 100644 --- a/apps/v4/public/r/date-picker.json +++ b/apps/v4/public/r/date-picker.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-picker", - "type": "registry:ui", "title": "Date Picker", "description": "A date picker component lets users select a date.", "registryDependencies": [ @@ -17,5 +16,6 @@ "content": "\"use client\";\n\nimport { CalendarIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { buttonVariants } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport { Calendar } from \"@/registry/new-york/ui/calendar\";\nimport {\n DateFieldDays,\n DateFieldMonths,\n DateFieldSeparator,\n DateFieldYears,\n} from \"@/registry/new-york/ui/date-field\";\nimport * as DatePickerPrimitive from \"@/registry/new-york/ui/date-picker-primitive\";\nimport {\n InputBase,\n InputBaseAdornment,\n InputBaseAdornmentButton,\n InputBaseFlexWrapper,\n} from \"@/registry/new-york/ui/input-base\";\n\nfunction DatePicker(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DatePickerAnchor(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DatePickerInputBase({\n children,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n {children}\n \n \n \n Clear date\n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n}\n\nfunction DatePickerDateRangeField({\n disabled: disabledProp,\n className,\n ...props\n}: React.ComponentProps) {\n const { disabled } = DatePickerPrimitive.useDatePicker();\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n -\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n}\n\nfunction DatePickerDateField({\n disabled: disabledProp,\n className,\n ...props\n}: React.ComponentProps) {\n const { disabled } = DatePickerPrimitive.useDatePicker();\n\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n}\n\nfunction DatePickerInput(\n props: React.ComponentProps<\n typeof DatePickerDateField | typeof DatePickerDateRangeField\n >,\n) {\n const { mode } = DatePickerPrimitive.useDatePicker();\n\n return (\n \n {mode === \"range\" ? (\n )}\n />\n ) : (\n )}\n />\n )}\n \n );\n}\n\nfunction DatePickerTrigger({\n children,\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n {children}\n \n \n );\n}\n\nfunction DatePickerValue({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DatePickerContent({\n className,\n align = \"start\",\n alignOffset = 4,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n );\n}\n\nfunction DatePickerCalendar(props: React.ComponentProps) {\n return (\n \n \n \n );\n}\n\nexport {\n DatePicker,\n DatePickerAnchor,\n DatePickerInput,\n DatePickerTrigger,\n DatePickerValue,\n DatePickerContent,\n DatePickerCalendar,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-time-field-primitive.json b/apps/v4/public/r/date-time-field-primitive.json index 4679f89..585472f 100644 --- a/apps/v4/public/r/date-time-field-primitive.json +++ b/apps/v4/public/r/date-time-field-primitive.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-time-field-primitive", - "type": "registry:ui", "title": "Date Time Field Primitive", "description": "Date Time Field Primitive allows user to enter date and time value.", "dependencies": [ @@ -18,5 +17,6 @@ "content": "\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as React from \"react\";\n\nimport {\n UseTimescapeOptions,\n useTimescape,\n} from \"@/registry/new-york/hooks/use-timescape\";\n\nexport type DateTimeFieldContextProps = {\n disabled?: boolean;\n} & ReturnType;\n\nconst DateTimeFieldContext = React.createContext({\n getInputProps: () => ({ ref: () => null }),\n getRootProps: () => ({ ref: () => null }),\n options: {},\n disabled: false,\n});\n\nexport function useDateTimeField() {\n const context = React.useContext(DateTimeFieldContext);\n if (!context) {\n throw new Error(\n \"useDateTimeField must be used within a .\",\n );\n }\n\n return context;\n}\n\nexport interface DateTimeFieldProps\n extends UseTimescapeOptions,\n Omit, \"value\" | \"defaultValue\"> {\n disabled?: boolean;\n}\n\nexport function DateTimeField({\n value,\n defaultValue,\n onValueChange,\n disabled,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n ref,\n ...props\n}: DateTimeFieldProps) {\n const timescape = useTimescape({\n value,\n defaultValue,\n onValueChange,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n });\n\n const { ref: rootRef, ...rootProps } = timescape.getRootProps();\n const composedRefs = useComposedRefs(ref, (node) => rootRef(node)!);\n\n return (\n \n \n \n );\n}\n\nexport function DateTimeFieldSeparator({\n ref,\n ...props\n}: React.ComponentProps) {\n const { disabled } = useDateTimeField();\n\n return (\n \n );\n}\n\nexport function DateTimeFieldYears({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"years\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldMonths({\n disabled: disabledProp,\n ref,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"months\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldDays({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"days\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldHours({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"hours\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldMinutes({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"minutes\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldSeconds({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"seconds\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeFieldAmPm({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled, options } = useDateTimeField();\n const { ref: inputRef, ...inputProps } = getInputProps(\"am/pm\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n if (!options?.hour12) {\n return null;\n }\n\n return (\n \n );\n}\n\nexport {\n DateTimeField as Root,\n DateTimeFieldSeparator as Separator,\n DateTimeFieldDays as Days,\n DateTimeFieldMonths as Months,\n DateTimeFieldYears as Years,\n DateTimeFieldHours as Hours,\n DateTimeFieldMinutes as Minutes,\n DateTimeFieldSeconds as Seconds,\n DateTimeFieldAmPm as AmPm,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-time-field.json b/apps/v4/public/r/date-time-field.json index 9a72b33..dd8be68 100644 --- a/apps/v4/public/r/date-time-field.json +++ b/apps/v4/public/r/date-time-field.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-time-field", - "type": "registry:ui", "title": "Date Time Field", "description": "Date Time Field allows user to enter date and time value.", "registryDependencies": [ @@ -14,5 +13,6 @@ "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport * as DateTimeFieldPrimitive from \"@/registry/new-york/ui/date-time-field-primitive\";\nimport {\n InputBase,\n InputBaseControl,\n InputBaseInput,\n} from \"@/registry/new-york/ui/input-base\";\n\nfunction DateTimeField({\n children,\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n {children}\n \n );\n}\n\nfunction DateTimeFieldSeparator({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nconst dateTimeFieldInputStyle =\n \"focus:bg-primary focus:text-primary-foreground focus:placeholder:text-primary-foreground box-content h-fit flex-initial rounded-sm px-0.5 tabular-nums\";\n\nfunction DateTimeFieldYears({\n placeholder = \"yyyy\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldMonths({\n placeholder = \"mm\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldDays({\n placeholder = \"dd\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldHours({\n placeholder = \"--\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldMinutes({\n placeholder = \"--\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldSeconds({\n placeholder = \"--\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nfunction DateTimeFieldAmPm({\n placeholder = \"--\",\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n );\n}\n\nexport {\n DateTimeField,\n DateTimeFieldSeparator,\n DateTimeFieldYears,\n DateTimeFieldMonths,\n DateTimeFieldDays,\n DateTimeFieldHours,\n DateTimeFieldMinutes,\n DateTimeFieldSeconds,\n DateTimeFieldAmPm,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-time-range-field-primitive.json b/apps/v4/public/r/date-time-range-field-primitive.json index de08328..e9c8f25 100644 --- a/apps/v4/public/r/date-time-range-field-primitive.json +++ b/apps/v4/public/r/date-time-range-field-primitive.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-time-range-field-primitive", - "type": "registry:ui", "title": "Date Time Range Field Primitive", "description": "Date Time Range Field Primitive allows user to enter date and time value for a range of dates.", "dependencies": [ @@ -18,5 +17,6 @@ "content": "\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as React from \"react\";\n\nimport {\n UseTimescapeRangeOptions,\n useTimescapeRange,\n} from \"@/registry/new-york/hooks/use-timescape\";\n\nexport type DateTimeRangeFieldContextProps = {\n disabled?: boolean;\n} & ReturnType;\n\nconst DateTimeRangeFieldContext =\n React.createContext({\n from: {\n getInputProps: () => ({ ref: () => null }),\n options: {},\n },\n to: {\n getInputProps: () => ({ ref: () => null }),\n options: {},\n },\n getRootProps: () => ({ ref: () => null }),\n disabled: false,\n });\n\nexport function useDateTimeRangeField() {\n const context = React.useContext(DateTimeRangeFieldContext);\n if (!context) {\n throw new Error(\n \"useDateTimeRangeField must be used within a .\",\n );\n }\n\n return context;\n}\n\nexport interface DateTimeRangeFieldProps\n extends UseTimescapeRangeOptions,\n Omit, \"value\" | \"defaultValue\"> {\n disabled?: boolean;\n}\n\nexport function DateTimeRangeField({\n value,\n defaultValue,\n onValueChange,\n disabled,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n from,\n to,\n ref,\n ...props\n}: DateTimeRangeFieldProps) {\n const timescape = useTimescapeRange({\n value,\n defaultValue,\n onValueChange,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n from,\n to,\n });\n\n const { ref: rootRef, ...rootProps } = timescape.getRootProps();\n const composedRefs = useComposedRefs(ref, (node) => rootRef(node)!);\n\n return (\n \n \n \n );\n}\n\nexport function DateTimeRangeFieldSeparator(\n props: React.ComponentProps,\n) {\n const { disabled } = useDateTimeRangeField();\n\n return (\n \n );\n}\n\nconst DateTimeRangeFieldFromContext = React.createContext(false);\n\nexport function DateTimeRangeFieldFrom(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nconst DateTimeRangeFieldToContext = React.createContext(false);\n\nexport function DateTimeRangeFieldTo({\n ref,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n );\n}\n\nfunction useDateTimeFieldSegment() {\n const isFrom = React.useContext(DateTimeRangeFieldFromContext);\n const isTo = React.useContext(DateTimeRangeFieldToContext);\n const { disabled, from, to } = useDateTimeRangeField();\n\n if (!isFrom && !isTo) {\n throw new Error(\n \"useDateTimeFieldSegment should be used within or components\",\n );\n }\n\n return {\n ...(isFrom ? from : to),\n disabled,\n };\n}\n\nexport function DateTimeRangeFieldYears({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"years\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldMonths({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"months\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldDays({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"days\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldHours({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"hours\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldMinutes({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"minutes\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldSeconds({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"seconds\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n return (\n \n );\n}\n\nexport function DateTimeRangeFieldAmPm({\n ref,\n disabled: disabledProp,\n ...props\n}: React.ComponentProps) {\n const { getInputProps, options, disabled } = useDateTimeFieldSegment();\n const { ref: inputRef, ...inputProps } = getInputProps(\"am/pm\");\n const composedRefs = useComposedRefs(ref, inputRef);\n\n if (!options?.hour12) {\n return null;\n }\n\n return (\n \n );\n}\n\nexport {\n DateTimeRangeField as Root,\n DateTimeRangeFieldFrom as From,\n DateTimeRangeFieldTo as To,\n DateTimeRangeFieldSeparator as Separator,\n DateTimeRangeFieldYears as Years,\n DateTimeRangeFieldMonths as Months,\n DateTimeRangeFieldDays as Days,\n DateTimeRangeFieldHours as Hours,\n DateTimeRangeFieldMinutes as Minutes,\n DateTimeRangeFieldSeconds as Seconds,\n DateTimeRangeFieldAmPm as AmPm,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/date-time-range-field.json b/apps/v4/public/r/date-time-range-field.json index 58d4d1b..12cfe7a 100644 --- a/apps/v4/public/r/date-time-range-field.json +++ b/apps/v4/public/r/date-time-range-field.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "date-time-range-field", - "type": "registry:ui", "title": "Date Time Range Field", "description": "Date Time Range Field allows user to enter date and time value for a range of dates.", "registryDependencies": [ @@ -15,5 +14,6 @@ "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n DateTimeFieldAmPm,\n DateTimeFieldDays,\n DateTimeFieldHours,\n DateTimeFieldMinutes,\n DateTimeFieldMonths,\n DateTimeFieldSeconds,\n DateTimeFieldSeparator,\n DateTimeFieldYears,\n} from \"@/registry/new-york/ui/date-time-field\";\nimport * as DateTimeRangeFieldPrimitive from \"@/registry/new-york/ui/date-time-range-field-primitive\";\nimport { InputBase } from \"@/registry/new-york/ui/input-base\";\n\nfunction DateTimeRangeField({\n children,\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n {children}\n \n );\n}\n\nfunction DateTimeRangeFieldFrom({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DateTimeRangeFieldTo({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DateTimeRangeFieldSeparator(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DateTimeRangeFieldYears(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldMonths(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldDays(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldHours(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldMinutes(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldSeconds(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nfunction DateTimeRangeFieldAmPm(\n props: React.ComponentProps,\n) {\n return (\n \n \n \n );\n}\n\nexport {\n DateTimeRangeField,\n DateTimeRangeFieldFrom,\n DateTimeRangeFieldTo,\n DateTimeRangeFieldSeparator,\n DateTimeRangeFieldYears,\n DateTimeRangeFieldMonths,\n DateTimeRangeFieldDays,\n DateTimeRangeFieldHours,\n DateTimeRangeFieldMinutes,\n DateTimeRangeFieldSeconds,\n DateTimeRangeFieldAmPm,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/description-list.json b/apps/v4/public/r/description-list.json index 3937c97..ae5c739 100644 --- a/apps/v4/public/r/description-list.json +++ b/apps/v4/public/r/description-list.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "description-list", - "type": "registry:ui", "title": "Description List", "description": "A description list, with terms and descriptions.", "files": [ @@ -10,5 +9,6 @@ "content": "import React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction DescriptionList({ className, ...props }: React.ComponentProps<\"dl\">) {\n return (\n \n );\n}\n\nfunction DescriptionTerm({ className, ...props }: React.ComponentProps<\"dt\">) {\n return (\n \n );\n}\n\nfunction DescriptionDetail({\n className,\n ...props\n}: React.ComponentProps<\"dd\">) {\n return (\n \n );\n}\n\nfunction DescriptionGroup({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nexport {\n DescriptionList,\n DescriptionTerm,\n DescriptionDetail,\n DescriptionGroup,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/dropzone-primitive.json b/apps/v4/public/r/dropzone-primitive.json index 9b1830a..3426c56 100644 --- a/apps/v4/public/r/dropzone-primitive.json +++ b/apps/v4/public/r/dropzone-primitive.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "dropzone-primitive", - "type": "registry:ui", "title": "Dropzone Primitive", "description": "A dropzone is an area into which one or multiple objects can be dragged and dropped.", "dependencies": [ @@ -15,5 +14,6 @@ "content": "\"use client\";\n\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as React from \"react\";\nimport {\n type DropzoneOptions,\n type DropzoneState,\n FileRejection,\n FileWithPath,\n useDropzone as useReactDropzone,\n} from \"react-dropzone\";\n\nexport type DropzoneContextProps = DropzoneState & DropzoneOptions;\n\nconst DropzoneContext = React.createContext(\n {} as DropzoneContextProps,\n);\n\nfunction useDropzone() {\n const context = React.useContext(DropzoneContext);\n if (!context) {\n throw new Error(\"useDropzone must be used within a .\");\n }\n\n return context;\n}\n\nexport interface DropzoneProps extends DropzoneOptions {\n children:\n | React.ReactNode\n | ((state: DropzoneContextProps) => React.ReactNode);\n}\n\nfunction Dropzone({ children, ...props }: DropzoneProps) {\n const state = useReactDropzone(props);\n const context = { ...state, ...props };\n\n return (\n \n {typeof children === \"function\" ? children(context) : children}\n \n );\n}\n\nfunction DropzoneInput(props: React.ComponentProps) {\n const { getInputProps, disabled } = useDropzone();\n\n return (\n \n );\n}\n\nfunction DropzoneZone(props: React.ComponentProps) {\n const {\n getRootProps,\n isFocused,\n isDragActive,\n isDragAccept,\n isDragReject,\n isFileDialogActive,\n preventDropOnDocument,\n noClick,\n noKeyboard,\n noDrag,\n noDragEventsBubbling,\n disabled,\n } = useDropzone();\n\n return (\n \n );\n}\n\nfunction DropzoneTrigger({\n onClick,\n ...props\n}: React.ComponentProps) {\n const { open } = useDropzone();\n\n return (\n \n );\n}\n\nexport interface DropzoneDragAcceptedProps {\n children?: React.ReactNode;\n}\n\nfunction DropzoneDragAccepted({ children }: DropzoneDragAcceptedProps) {\n const { isDragAccept } = useDropzone();\n if (!isDragAccept) return null;\n return
{children}
;\n}\n\nexport interface DropzoneDragRejectedProps {\n children?: React.ReactNode;\n}\n\nfunction DropzoneDragRejected({ children }: DropzoneDragRejectedProps) {\n const { isDragReject } = useDropzone();\n if (!isDragReject) {\n return null;\n }\n\n return
{children}
;\n}\n\nexport interface DropzoneDragDefaultProps {\n children?: React.ReactNode;\n}\n\nfunction DropzoneDragDefault({ children }: DropzoneDragDefaultProps) {\n const { isDragActive } = useDropzone();\n if (isDragActive) {\n return null;\n }\n\n return
{children}
;\n}\n\nexport interface DropzoneAcceptedProps {\n children: (acceptedFiles: Readonly) => React.ReactNode;\n}\n\nfunction DropzoneAccepted({ children }: DropzoneAcceptedProps) {\n const { acceptedFiles } = useDropzone();\n return
{children(acceptedFiles)}
;\n}\n\nexport interface DropzoneRejectedProps {\n children: (fileRejections: Readonly) => React.ReactNode;\n}\n\nfunction DropzoneRejected({ children }: DropzoneRejectedProps) {\n const { fileRejections } = useDropzone();\n return
{children(fileRejections)}
;\n}\n\nexport {\n Dropzone as Root,\n DropzoneInput as Input,\n DropzoneZone as Zone,\n DropzoneTrigger as Trigger,\n DropzoneDragAccepted as DragAccepted,\n DropzoneDragRejected as DragRejected,\n DropzoneDragDefault as DragDefault,\n DropzoneAccepted as Accepted,\n DropzoneRejected as Rejected,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/dropzone.json b/apps/v4/public/r/dropzone.json index b709b08..14fbab6 100644 --- a/apps/v4/public/r/dropzone.json +++ b/apps/v4/public/r/dropzone.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "dropzone", - "type": "registry:ui", "title": "Dropzone", "description": "A dropzone is an area into which one or multiple objects can be dragged and dropped.", "dependencies": [ @@ -16,5 +15,6 @@ "content": "\"use client\";\n\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { BanIcon, CheckCircle2Icon, UploadIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport * as DropzonePrimitive from \"@/registry/new-york/ui/dropzone-primitive\";\n\nfunction Dropzone(props: React.ComponentProps) {\n return ;\n}\n\nfunction DropzoneInput(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DropzoneZone({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DropzoneUploadIcon({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n <>\n \n \n \n \n \n \n \n \n \n \n );\n}\n\nfunction DropzoneGroup({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DropzoneTitle({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DropzoneDescription({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction DropzoneTrigger(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction DropzoneAccepted(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction DropzoneRejected(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nexport {\n Dropzone,\n DropzoneInput,\n DropzoneZone,\n DropzoneUploadIcon,\n DropzoneGroup,\n DropzoneTitle,\n DropzoneDescription,\n DropzoneTrigger,\n DropzoneAccepted,\n DropzoneRejected,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/emoji-picker.json b/apps/v4/public/r/emoji-picker.json index be35efa..22b245a 100644 --- a/apps/v4/public/r/emoji-picker.json +++ b/apps/v4/public/r/emoji-picker.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "emoji-picker", - "type": "registry:ui", "title": "Emoji Picker", "description": "A emoji picker is a component that allows users to select an emoji from a list of emojis.", "dependencies": [ @@ -15,8 +14,9 @@ "files": [ { "path": "src/registry/new-york/ui/emoji-picker.tsx", - "content": "\"use client\";\n\nimport * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\";\nimport {\n type EmojiPickerListCategoryHeaderProps,\n type EmojiPickerListEmojiProps,\n type EmojiPickerListRowProps,\n EmojiPicker as EmojiPickerPrimitive,\n SkinTone,\n useActiveEmoji,\n useSkinTone,\n} from \"frimousse\";\nimport { LoaderIcon, SearchIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\n\nfunction EmojiPicker({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction EmojiPickerSearch({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n );\n}\n\nfunction EmojiPickerRow({ children, ...props }: EmojiPickerListRowProps) {\n return (\n
\n {children}\n
\n );\n}\n\nfunction EmojiPickerEmoji({\n emoji,\n className,\n ...props\n}: EmojiPickerListEmojiProps) {\n return (\n \n {emoji.emoji}\n \n );\n}\n\nfunction EmojiPickerCategoryHeader({\n category,\n ...props\n}: EmojiPickerListCategoryHeaderProps) {\n return (\n \n {category.label}\n \n );\n}\n\nfunction EmojiPickerContent({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n No emoji found.\n \n \n \n );\n}\n\nfunction EmojiPickerFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n \n \n \n );\n}\n\nfunction EmojiPickerActiveEmojiPreview({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n const emoji = useActiveEmoji();\n\n if (!emoji) {\n return (\n \n Select an emoji…\n \n );\n }\n\n return (\n
\n
\n
\n {emoji.emoji}\n
\n \n {emoji.label}\n \n
\n
\n );\n}\n\nfunction EmojiPickerSkinToneSelector() {\n const [skinTone, setSkinTone, skinToneVariations] = useSkinTone();\n\n return (\n \n \n \n \n \n value && setSkinTone(value as SkinTone)}\n aria-label=\"Select skin tone\"\n orientation=\"horizontal\"\n >\n {skinToneVariations.map((variation) => (\n \n {variation.emoji}\n \n ))}\n \n \n \n );\n}\n\nexport {\n EmojiPicker,\n EmojiPickerSearch,\n EmojiPickerContent,\n EmojiPickerFooter,\n};\n", + "content": "\"use client\";\n\nimport * as ToggleGroupPrimitive from \"@radix-ui/react-toggle-group\";\nimport {\n type EmojiPickerListCategoryHeaderProps,\n type EmojiPickerListEmojiProps,\n type EmojiPickerListRowProps,\n EmojiPicker as EmojiPickerPrimitive,\n SkinTone,\n useActiveEmoji,\n useSkinTone,\n} from \"frimousse\";\nimport { LoaderIcon, SearchIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/components/ui/popover\";\nimport { cn } from \"@/lib/utils\";\n\nfunction EmojiPicker({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction EmojiPickerSearch({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n );\n}\n\nfunction EmojiPickerRow({ children, ...props }: EmojiPickerListRowProps) {\n return (\n
\n {children}\n
\n );\n}\n\nfunction EmojiPickerEmoji({\n emoji,\n className,\n ...props\n}: EmojiPickerListEmojiProps) {\n return (\n \n {emoji.emoji}\n \n );\n}\n\nfunction EmojiPickerCategoryHeader({\n category,\n ...props\n}: EmojiPickerListCategoryHeaderProps) {\n return (\n \n {category.label}\n \n );\n}\n\nfunction EmojiPickerContent({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n \n \n \n \n No emoji found.\n \n \n \n );\n}\n\nfunction EmojiPickerFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n \n \n \n );\n}\n\nfunction EmojiPickerActiveEmojiPreview({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n const emoji = useActiveEmoji();\n\n if (!emoji) {\n return (\n \n Select an emoji…\n \n );\n }\n\n return (\n
\n
\n
\n {emoji.emoji}\n
\n \n {emoji.label}\n \n
\n
\n );\n}\n\nfunction EmojiPickerSkinToneSelector() {\n const [skinTone, setSkinTone, skinToneVariations] = useSkinTone();\n\n return (\n \n }\n >\n {\n skinToneVariations.find(\n (variation) => variation.skinTone === skinTone,\n )?.emoji\n }\n \n \n value && setSkinTone(value as SkinTone)}\n aria-label=\"Select skin tone\"\n orientation=\"horizontal\"\n >\n {skinToneVariations.map((variation) => (\n \n {variation.emoji}\n \n ))}\n \n \n \n );\n}\n\nexport {\n EmojiPicker,\n EmojiPickerSearch,\n EmojiPickerContent,\n EmojiPickerFooter,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/file-list.json b/apps/v4/public/r/file-list.json index d2164ce..4ef5bda 100644 --- a/apps/v4/public/r/file-list.json +++ b/apps/v4/public/r/file-list.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "file-list", - "type": "registry:ui", "title": "File List", "description": "A File List component displays a list of files with details such as name, size, and progress.", "dependencies": [ @@ -17,5 +16,6 @@ "content": "\"use client\";\n\nimport { FileTextIcon } from \"lucide-react\";\nimport prettyBytes from \"pretty-bytes\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Progress } from \"@/components/ui/progress\";\nimport { cn } from \"@/lib/utils\";\n\nfunction FileList({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListItem({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListIcon({\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n svg:not([class*='size-'])]:size-5\",\n className,\n )}\n {...props}\n >\n {children ?? }\n \n );\n}\n\nfunction FileListInfo({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListName({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n \n );\n}\n\nfunction FileListDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListDescriptionSeparator({\n children,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n \n {children ?? \"•\"}\n \n );\n}\n\ninterface FileListSizeProps extends React.ComponentProps<\"span\"> {\n children: number;\n}\n\nfunction FileListSize({ children, ...props }: FileListSizeProps) {\n return (\n \n {prettyBytes(children)}\n \n );\n}\n\nfunction FileListProgress({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction FileListDescriptionText({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n svg:not([class*='size-'])]:size-3\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction FileListContent(props: React.ComponentProps<\"div\">) {\n return
;\n}\n\nfunction FileListActions({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n );\n}\n\nfunction FileListAction({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nexport {\n FileList,\n FileListItem,\n FileListHeader,\n FileListIcon,\n FileListInfo,\n FileListName,\n FileListDescription,\n FileListDescriptionSeparator,\n FileListSize,\n FileListProgress,\n FileListDescriptionText,\n FileListContent,\n FileListActions,\n FileListAction,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/input-base.json b/apps/v4/public/r/input-base.json index 9f2e2ed..fa27b45 100644 --- a/apps/v4/public/r/input-base.json +++ b/apps/v4/public/r/input-base.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "input-base", - "type": "registry:ui", "title": "Input Base", "description": "Base component to create custom inputs.", "dependencies": [ @@ -16,8 +15,9 @@ "files": [ { "path": "src/registry/new-york/ui/input-base.tsx", - "content": "\"use client\";\n\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nexport type InputBaseContextProps = Pick<\n InputBaseProps,\n \"autoFocus\" | \"disabled\"\n> & {\n controlRef: React.RefObject;\n onFocusedChange: (focused: boolean) => void;\n};\n\nconst InputBaseContext = React.createContext({\n autoFocus: false,\n controlRef: { current: null },\n disabled: false,\n onFocusedChange: () => {},\n});\n\nfunction useInputBase() {\n const context = React.useContext(InputBaseContext);\n if (!context) {\n throw new Error(\"useInputBase must be used within a .\");\n }\n\n return context;\n}\n\nexport interface InputBaseProps\n extends React.ComponentProps {\n autoFocus?: boolean;\n disabled?: boolean;\n error?: boolean;\n}\n\nfunction InputBase({\n autoFocus,\n disabled,\n className,\n onClick,\n error,\n ...props\n}: InputBaseProps) {\n const [focused, setFocused] = React.useState(false);\n const controlRef = React.useRef(null);\n\n return (\n \n implementation.\n // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/InputBase/InputBase.js#L458~L460\n onClick={composeEventHandlers(onClick, (event) => {\n if (controlRef.current && event.currentTarget === event.target) {\n controlRef.current.focus();\n }\n })}\n className={cn(\n \"border-input selection:bg-primary selection:text-primary-foreground dark:bg-input/30 flex min-h-9 w-full min-w-0 cursor-text items-center gap-2 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm\",\n \"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[[data-slot][aria-invalid=true]]:border-destructive\",\n disabled && \"pointer-events-none cursor-not-allowed opacity-50\",\n focused && \"border-ring ring-ring/50 ring-[3px]\",\n error &&\n \"ring-destructive/20 dark:ring-destructive/40 border-destructive\",\n className,\n )}\n {...props}\n />\n \n );\n}\n\nfunction InputBaseFlexWrapper({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction InputBaseControl({\n ref,\n onFocus,\n onBlur,\n ...props\n}: React.ComponentProps) {\n const { controlRef, autoFocus, disabled, onFocusedChange } = useInputBase();\n\n const composedRefs = useComposedRefs(controlRef, ref);\n\n return (\n onFocusedChange(true))}\n onBlur={composeEventHandlers(onBlur, () => onFocusedChange(false))}\n {...{ disabled }}\n {...props}\n />\n );\n}\n\nexport interface InputBaseAdornmentProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\n\nfunction InputBaseAdornment({\n className,\n asChild,\n children,\n ...props\n}: InputBaseAdornmentProps) {\n const Comp = asChild ? Slot : typeof children === \"string\" ? \"p\" : \"div\";\n\n return (\n \n {children}\n \n );\n}\n\nfunction InputBaseAdornmentButton({\n type = \"button\",\n variant = \"ghost\",\n size = \"icon\",\n disabled: disabledProp,\n className,\n ...props\n}: React.ComponentProps) {\n const { disabled } = useInputBase();\n\n return (\n \n );\n}\n\nfunction InputBaseInput({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction InputBaseTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n \n );\n}\n\nexport {\n InputBase,\n InputBaseFlexWrapper,\n InputBaseControl,\n InputBaseAdornment,\n InputBaseAdornmentButton,\n InputBaseInput,\n InputBaseTextarea,\n useInputBase,\n};\n", + "content": "\"use client\";\n\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { Button, buttonVariants } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nexport type InputBaseContextProps = Pick<\n InputBaseProps,\n \"autoFocus\" | \"disabled\"\n> & {\n controlRef: React.RefObject;\n onFocusedChange: (focused: boolean) => void;\n};\n\nconst InputBaseContext = React.createContext({\n autoFocus: false,\n controlRef: { current: null },\n disabled: false,\n onFocusedChange: () => {},\n});\n\nfunction useInputBase() {\n const context = React.useContext(InputBaseContext);\n if (!context) {\n throw new Error(\"useInputBase must be used within a .\");\n }\n\n return context;\n}\n\nexport interface InputBaseProps\n extends React.ComponentProps {\n autoFocus?: boolean;\n disabled?: boolean;\n error?: boolean;\n}\n\nfunction InputBase({\n autoFocus,\n disabled,\n className,\n onClick,\n error,\n ...props\n}: InputBaseProps) {\n const [focused, setFocused] = React.useState(false);\n const controlRef = React.useRef(null);\n\n return (\n \n implementation.\n // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/InputBase/InputBase.js#L458~L460\n onClick={composeEventHandlers(onClick, (event) => {\n if (controlRef.current && event.currentTarget === event.target) {\n controlRef.current.focus();\n }\n })}\n className={cn(\n \"border-input selection:bg-primary selection:text-primary-foreground dark:bg-input/30 flex min-h-9 w-full min-w-0 cursor-text items-center gap-2 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm\",\n \"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[[data-slot][aria-invalid=true]]:border-destructive\",\n disabled && \"pointer-events-none cursor-not-allowed opacity-50\",\n focused && \"border-ring ring-ring/50 ring-[3px]\",\n error &&\n \"ring-destructive/20 dark:ring-destructive/40 border-destructive\",\n className,\n )}\n {...props}\n />\n \n );\n}\n\nfunction InputBaseFlexWrapper({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction InputBaseControl({\n ref,\n onFocus,\n onBlur,\n ...props\n}: React.ComponentProps) {\n const { controlRef, autoFocus, disabled, onFocusedChange } = useInputBase();\n\n const composedRefs = useComposedRefs(controlRef, ref);\n\n return (\n onFocusedChange(true))}\n onBlur={composeEventHandlers(onBlur, () => onFocusedChange(false))}\n {...{ disabled }}\n {...props}\n />\n );\n}\n\nexport interface InputBaseAdornmentProps extends React.ComponentProps<\"div\"> {\n asChild?: boolean;\n}\n\nfunction InputBaseAdornment({\n className,\n asChild,\n children,\n ...props\n}: InputBaseAdornmentProps) {\n const Comp = asChild ? Slot : typeof children === \"string\" ? \"p\" : \"div\";\n\n return (\n \n {children}\n \n );\n}\n\nfunction InputBaseAdornmentButton({\n type = \"button\",\n variant = \"ghost\",\n size = \"icon\",\n asChild = false,\n disabled: disabledProp,\n className,\n ...props\n}: Omit, \"style\"> & {\n asChild?: boolean;\n style?: React.CSSProperties;\n}) {\n const { disabled } = useInputBase();\n\n if (asChild) {\n return (\n \n );\n }\n\n return (\n \n );\n}\n\nfunction InputBaseInput({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nfunction InputBaseTextarea({\n className,\n ...props\n}: React.ComponentProps<\"textarea\">) {\n return (\n \n );\n}\n\nexport {\n InputBase,\n InputBaseFlexWrapper,\n InputBaseControl,\n InputBaseAdornment,\n InputBaseAdornmentButton,\n InputBaseInput,\n InputBaseTextarea,\n useInputBase,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/kbd.json b/apps/v4/public/r/kbd.json index 2f9db03..3a83c6c 100644 --- a/apps/v4/public/r/kbd.json +++ b/apps/v4/public/r/kbd.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "kbd", - "type": "registry:ui", "title": "Kbd", "description": "Displays which key or combination of keys performs a given action.", "dependencies": [ @@ -13,5 +12,6 @@ "content": "import { Slot } from \"@radix-ui/react-slot\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst kbdVariants = cva(\n \"pointer-events-none inline-flex w-fit items-center gap-1 rounded px-1.5 py-0.5 font-mono text-[10px] font-medium select-none [&_svg:not([class*='size-'])]:size-3\",\n {\n variants: {\n variant: {\n default:\n \"bg-primary text-primary-foreground shadow-[inset_0_-2px_0_0_var(--shadow-color)] shadow-primary-foreground/60\",\n secondary:\n \"bg-secondary text-secondary-foreground shadow-[inset_0_-2px_0_0_var(--shadow-color)] shadow-secondary-foreground/60\",\n outline: \"border text-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction Kbd({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"kbd\"> &\n VariantProps & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"kbd\";\n\n return (\n \n );\n}\n\nexport { Kbd, kbdVariants };\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/native-select.json b/apps/v4/public/r/native-select.json index 45bd81f..a269590 100644 --- a/apps/v4/public/r/native-select.json +++ b/apps/v4/public/r/native-select.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "native-select", - "type": "registry:ui", "title": "Native Select", "description": "Native select element.", "registryDependencies": [ @@ -13,5 +12,6 @@ "content": "\"use client\";\n\nimport { ChevronDownIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n InputBase,\n InputBaseAdornment,\n InputBaseControl,\n} from \"@/registry/new-york/ui/input-base\";\n\nfunction NativeSelect({ className, ...props }: React.ComponentProps<\"select\">) {\n return (\n select]:min-h-9 [&>select]:min-w-40 [&>select]:px-3 [&>select]:py-1\",\n className,\n )}\n >\n \n \n \n \n \n \n \n );\n}\n\nfunction NativeSelectGroup({\n className,\n ...props\n}: React.ComponentProps<\"optgroup\">) {\n return (\n \n );\n}\n\nfunction NativeSelectOption({\n className,\n ...props\n}: React.ComponentProps<\"option\">) {\n return (\n \n );\n}\n\nfunction NativeSelectPlaceholder({\n value = \"\",\n hidden = true,\n disabled = true,\n ...props\n}: React.ComponentProps<\"option\">) {\n return (\n
\n );\n}\n\nfunction PhoneInput(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction PhoneInputInput(\n props: React.ComponentProps,\n) {\n return (\n \n {React.useMemo(\n () => (\n \n ),\n [],\n )}\n \n );\n}\n\ntype PhoneInputCountrySelectProps = Omit<\n React.ComponentProps,\n \"value\" | \"onValueChange\"\n>;\n\nfunction PhoneInputCountrySelect(props: PhoneInputCountrySelectProps) {\n const { country, onCountryChange } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n onCountryChange(\n value === PhoneInputPrimitive.INTERNATIONAL_COUNTRY_CODE\n ? null\n : (value as PhoneInputPrimitive.Country),\n )\n }\n {...props}\n />\n );\n}\n\nfunction PhoneInputCountrySelectValue({\n placeholder = ,\n children,\n ...props\n}: React.ComponentProps) {\n const { country } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n {children ?? }\n \n );\n}\n\nfunction PhoneInputCountrySelectTrigger(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction PhoneInputCountrySelectContent(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction PhoneInputCountrySelectOptions() {\n return (\n <>\n \n {PhoneInputPrimitive.getCountryOptions().map((option) => (\n \n ))}\n \n );\n}\n\nfunction PhoneInputCountrySelectInternationalItem(\n props: Omit, \"value\">,\n) {\n const { country } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n
\n
\n \n
\n International\n
\n {country === null && (\n \n \n \n )}\n \n );\n}\n\ninterface PhoneInputCountrySelectItemProps\n extends Omit, \"value\"> {\n value: PhoneInputPrimitive.Country;\n}\n\nconst regionNames = new Intl.DisplayNames([\"en\"], {\n type: \"region\",\n});\n\nfunction PhoneInputCountrySelectItem({\n className,\n value,\n ...props\n}: PhoneInputCountrySelectItemProps) {\n return (\n \n
\n
\n \n
\n \n {regionNames.of(value)}\n \n
\n
\n {`+${getCountryCallingCode(value)}`}\n
\n \n \n \n \n \n \n );\n}\n\nexport type {\n Country,\n Value,\n} from \"@/registry/new-york/ui/phone-input-primitive\";\n\nexport {\n PhoneInput,\n PhoneInputFlag,\n PhoneInputInput,\n PhoneInputCountrySelect,\n PhoneInputCountrySelectContent,\n PhoneInputCountrySelectInternationalItem,\n PhoneInputCountrySelectItem,\n PhoneInputCountrySelectOptions,\n PhoneInputCountrySelectTrigger,\n PhoneInputCountrySelectValue,\n};\n", + "content": "\"use client\";\n\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport { CheckIcon, GlobeIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { getCountryCallingCode } from \"react-phone-number-input\";\nimport flags from \"react-phone-number-input/flags\";\n\nimport { Input } from \"@/components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport { cn } from \"@/lib/utils\";\nimport * as PhoneInputPrimitive from \"@/registry/new-york/ui/phone-input-primitive\";\n\ninterface PhoneInputFlagProps\n extends React.ComponentProps<\n NonNullable<(typeof flags)[keyof typeof flags]>\n > {\n country: PhoneInputPrimitive.Country | null;\n}\n\nfunction PhoneInputFlag({ country, ...props }: PhoneInputFlagProps) {\n const CountryFlag = country ? flags[country] : null;\n\n return (\n svg:not([class*='size-'])]:size-full\",\n CountryFlag &&\n \"[&>svg:not([class*='size-'])]:h-4 [&>svg:not([class*='size-'])]:w-6\",\n )}\n >\n {CountryFlag ? (\n \n ) : (\n \n )}\n \n );\n}\n\nfunction PhoneInput(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction PhoneInputInput(\n props: React.ComponentProps,\n) {\n return (\n \n {React.useMemo(\n () => (\n \n ),\n [],\n )}\n \n );\n}\n\ntype PhoneInputCountrySelectProps = Omit<\n React.ComponentProps,\n \"value\" | \"onValueChange\"\n>;\n\nfunction PhoneInputCountrySelect(props: PhoneInputCountrySelectProps) {\n const { country, onCountryChange } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n onCountryChange(\n value === PhoneInputPrimitive.INTERNATIONAL_COUNTRY_CODE\n ? null\n : (value as PhoneInputPrimitive.Country),\n )\n }\n {...props}\n />\n );\n}\n\nfunction PhoneInputCountrySelectValue({\n placeholder = ,\n children,\n ...props\n}: React.ComponentProps) {\n const { country } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n {children ?? }\n \n );\n}\n\nfunction PhoneInputCountrySelectTrigger(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction PhoneInputCountrySelectContent(\n props: React.ComponentProps,\n) {\n return (\n \n );\n}\n\nfunction PhoneInputCountrySelectOptions() {\n return (\n <>\n \n {PhoneInputPrimitive.getCountryOptions().map((option) => (\n \n ))}\n \n );\n}\n\nfunction PhoneInputCountrySelectInternationalItem(\n props: Omit, \"value\">,\n) {\n const { country } = PhoneInputPrimitive.usePhoneInput();\n\n return (\n \n
\n
\n \n
\n International\n
\n {country === null && (\n \n \n \n )}\n \n );\n}\n\ninterface PhoneInputCountrySelectItemProps\n extends Omit, \"value\"> {\n value: PhoneInputPrimitive.Country;\n}\n\nconst regionNames = new Intl.DisplayNames([\"en\"], {\n type: \"region\",\n});\n\nfunction PhoneInputCountrySelectItem({\n className,\n value,\n ...props\n}: PhoneInputCountrySelectItemProps) {\n return (\n \n
\n
\n \n
\n \n {regionNames.of(value)}\n \n
\n
\n {`+${getCountryCallingCode(value)}`}\n
\n \n \n \n \n \n \n );\n}\n\nexport type {\n Country,\n Value,\n} from \"@/registry/new-york/ui/phone-input-primitive\";\n\nexport {\n PhoneInput,\n PhoneInputFlag,\n PhoneInputInput,\n PhoneInputCountrySelect,\n PhoneInputCountrySelectContent,\n PhoneInputCountrySelectInternationalItem,\n PhoneInputCountrySelectItem,\n PhoneInputCountrySelectOptions,\n PhoneInputCountrySelectTrigger,\n PhoneInputCountrySelectValue,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/registry.json b/apps/v4/public/r/registry.json new file mode 100644 index 0000000..1132b2d --- /dev/null +++ b/apps/v4/public/r/registry.json @@ -0,0 +1,605 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry.json", + "name": "junwen-k/ui-x", + "homepage": "https://ui-x.junwen-k.dev/", + "items": [ + { + "name": "bprogress-provider-next-app", + "type": "registry:component", + "title": "BProgress Provider Next App", + "description": "A smooth progress bar for page transitions in Next.js apps, using the App Router.", + "dependencies": [ + "@bprogress/next" + ], + "files": [ + { + "path": "src/registry/new-york/components/bprogress-provider-next-app.tsx", + "target": "~/src/components/bprogress-provider.tsx", + "type": "registry:component" + } + ] + }, + { + "name": "bprogress-provider-next-pages", + "type": "registry:component", + "title": "BProgress Provider Next Pages", + "description": "A smooth progress bar for page transitions in Next.js pages, using the Pages Router.", + "dependencies": [ + "@bprogress/next" + ], + "files": [ + { + "path": "src/registry/new-york/components/bprogress-provider-next-pages.tsx", + "target": "~/src/components/bprogress-provider.tsx", + "type": "registry:component" + } + ] + }, + { + "name": "combobox-primitive", + "type": "registry:ui", + "title": "Combobox Primitive", + "description": "An unstyled combobox component. Input field with autocomplete & autosuggest functionalities.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-popover", + "@radix-ui/react-primitive@2.1.2", + "@radix-ui/react-roving-focus@1.1.9", + "@radix-ui/react-use-controllable-state@1.2.2", + "cmdk" + ], + "files": [ + { + "path": "src/registry/new-york/ui/combobox-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-time-field-primitive", + "type": "registry:ui", + "title": "Date Time Field Primitive", + "description": "Date Time Field Primitive allows user to enter date and time value.", + "dependencies": [ + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "timescape" + ], + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/use-timescape.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-time-field-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "emoji-picker", + "type": "registry:ui", + "title": "Emoji Picker", + "description": "A emoji picker is a component that allows users to select an emoji from a list of emojis.", + "dependencies": [ + "@radix-ui/react-toggle-group", + "frimousse" + ], + "registryDependencies": [ + "button", + "popover" + ], + "files": [ + { + "path": "src/registry/new-york/ui/emoji-picker.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "use-timescape", + "type": "registry:hook", + "title": "Use Timescape", + "description": "A reactive wrapper around Timescape that provides controlled and uncontrolled state management for date/time input.", + "dependencies": [ + "@radix-ui/react-use-controllable-state@1.2.2", + "react-day-picker", + "timescape" + ], + "files": [ + { + "path": "src/registry/new-york/hooks/use-timescape.ts", + "type": "registry:hook" + } + ] + }, + { + "name": "date-time-range-field-primitive", + "type": "registry:ui", + "title": "Date Time Range Field Primitive", + "description": "Date Time Range Field Primitive allows user to enter date and time value for a range of dates.", + "dependencies": [ + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "timescape" + ], + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/use-timescape.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-time-range-field-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-picker-primitive", + "type": "registry:ui", + "title": "Date Picker", + "description": "An unstyled date picker component.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-popover", + "@radix-ui/react-primitive@2.1.2", + "@radix-ui/react-slot", + "@radix-ui/react-use-controllable-state@1.2.2", + "date-fns", + "react-day-picker" + ], + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/date-time-field-primitive.json", + "https://ui-x.junwen-k.dev/r/date-time-range-field-primitive.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-picker-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "dropzone-primitive", + "type": "registry:ui", + "title": "Dropzone Primitive", + "description": "A dropzone is an area into which one or multiple objects can be dragged and dropped.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "react-dropzone" + ], + "files": [ + { + "path": "src/registry/new-york/ui/dropzone-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "password-input-primitive", + "type": "registry:ui", + "title": "Password Input Primitive", + "description": "Password Input provides a way for the user to securely enter a password, with the ability to toggle the visibility of the password.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "@radix-ui/react-use-controllable-state@1.2.2" + ], + "files": [ + { + "path": "src/registry/new-york/ui/password-input-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "phone-input-primitive", + "type": "registry:ui", + "title": "Phone Input Primitive", + "description": "Phone Input allows user to enter phone number in E.164 format.", + "dependencies": [ + "@radix-ui/react-use-controllable-state@1.2.2", + "react-phone-number-input" + ], + "files": [ + { + "path": "src/registry/new-york/ui/phone-input-primitive.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "sortable", + "type": "registry:ui", + "title": "Sortable", + "description": "Sortable provides a way to sort items in a list or grid.", + "dependencies": [ + "@dnd-kit/core", + "@dnd-kit/sortable", + "@dnd-kit/utilities", + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-portal", + "@radix-ui/react-primitive@2.1.2" + ], + "files": [ + { + "path": "src/registry/new-york/ui/sortable.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "virtualized", + "type": "registry:ui", + "title": "Virtualized", + "description": "A virtualized component that allows you to efficiently render large lists and tabular data.", + "dependencies": [ + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "virtua" + ], + "files": [ + { + "path": "src/registry/new-york/ui/virtualized.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "badge-group", + "type": "registry:ui", + "title": "Badge Group", + "description": "A badge group is a focusable list of labels, categories, keywords, filters, or other items, with support for keyboard navigation, selection, and removal.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-slot", + "@radix-ui/react-toggle-group", + "@radix-ui/react-use-controllable-state@1.2.2" + ], + "registryDependencies": [ + "badge" + ], + "files": [ + { + "path": "src/registry/new-york/ui/badge-group.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "calendar", + "type": "registry:ui", + "title": "Calendar", + "description": "A calendar component lets users select a date without any input or popper / modal.", + "dependencies": [ + "react-day-picker", + "date-fns" + ], + "registryDependencies": [ + "button" + ], + "files": [ + { + "path": "src/registry/new-york/ui/calendar.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "combobox", + "type": "registry:ui", + "title": "Combobox", + "description": "Input field with autocomplete & autosuggest functionalities.", + "dependencies": [ + "@radix-ui/react-slot" + ], + "registryDependencies": [ + "badge", + "https://ui-x.junwen-k.dev/r/combobox-primitive.json", + "https://ui-x.junwen-k.dev/r/input-base.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/combobox.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "confirmer", + "type": "registry:ui", + "title": "Confirmer", + "description": "Imperative confirm dialog implementation.", + "dependencies": [ + "react-call" + ], + "registryDependencies": [ + "alert-dialog", + "button" + ], + "files": [ + { + "path": "src/registry/new-york/ui/confirmer.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "control-group", + "type": "registry:ui", + "title": "Control Group", + "description": "A component for grouping form controls like text inputs, buttons, selects and other elements into a single cohesive unit.", + "dependencies": [ + "@radix-ui/react-primitive@2.1.2", + "@radix-ui/react-slot" + ], + "files": [ + { + "path": "src/registry/new-york/ui/control-group.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-field", + "type": "registry:ui", + "title": "Date Field", + "description": "Date Field allows user to enter date value.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/date-time-field.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-field.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-time-field", + "type": "registry:ui", + "title": "Date Time Field", + "description": "Date Time Field allows user to enter date and time value.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/date-time-field-primitive.json", + "https://ui-x.junwen-k.dev/r/input-base.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-time-field.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-time-range-field", + "type": "registry:ui", + "title": "Date Time Range Field", + "description": "Date Time Range Field allows user to enter date and time value for a range of dates.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/date-time-field.json", + "https://ui-x.junwen-k.dev/r/date-time-range-field-primitive.json", + "https://ui-x.junwen-k.dev/r/input-base.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-time-range-field.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "date-picker", + "type": "registry:ui", + "title": "Date Picker", + "description": "A date picker component lets users select a date.", + "registryDependencies": [ + "button", + "https://ui-x.junwen-k.dev/r/calendar.json", + "https://ui-x.junwen-k.dev/r/date-field.json", + "https://ui-x.junwen-k.dev/r/date-picker-primitive.json", + "https://ui-x.junwen-k.dev/r/input-base.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/date-picker.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "description-list", + "type": "registry:ui", + "title": "Description List", + "description": "A description list, with terms and descriptions.", + "files": [ + { + "path": "src/registry/new-york/ui/description-list.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "dropzone", + "type": "registry:ui", + "title": "Dropzone", + "description": "A dropzone is an area into which one or multiple objects can be dragged and dropped.", + "dependencies": [ + "@radix-ui/react-primitive@2.1.2" + ], + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/dropzone-primitive.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/dropzone.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "file-list", + "type": "registry:ui", + "title": "File List", + "description": "A File List component displays a list of files with details such as name, size, and progress.", + "dependencies": [ + "pretty-bytes" + ], + "registryDependencies": [ + "button", + "progress" + ], + "files": [ + { + "path": "src/registry/new-york/ui/file-list.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "input-base", + "type": "registry:ui", + "title": "Input Base", + "description": "Base component to create custom inputs.", + "dependencies": [ + "@radix-ui/primitive@1.1.2", + "@radix-ui/react-compose-refs@1.1.2", + "@radix-ui/react-primitive@2.1.2", + "@radix-ui/react-slot" + ], + "registryDependencies": [ + "button" + ], + "files": [ + { + "path": "src/registry/new-york/ui/input-base.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "kbd", + "type": "registry:ui", + "title": "Kbd", + "description": "Displays which key or combination of keys performs a given action.", + "dependencies": [ + "@radix-ui/react-slot" + ], + "files": [ + { + "path": "src/registry/new-york/ui/kbd.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "native-select", + "type": "registry:ui", + "title": "Native Select", + "description": "Native select element.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/input-base.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/native-select.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "password-input", + "type": "registry:ui", + "title": "Password Input", + "description": "Password Input provides a way for the user to securely enter a password, with the ability to toggle the visibility of the password.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/input-base.json", + "https://ui-x.junwen-k.dev/r/password-input-primitive.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/password-input.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "phone-input", + "type": "registry:ui", + "title": "Phone Input", + "description": "Phone Input allows user to enter phone number in E.164 format.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/phone-input-primitive.json", + "input", + "select" + ], + "files": [ + { + "path": "src/registry/new-york/ui/phone-input.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "time-field", + "type": "registry:ui", + "title": "Time Field", + "description": "Time Field allows user to enter time value.", + "registryDependencies": [ + "https://ui-x.junwen-k.dev/r/date-time-field.json" + ], + "files": [ + { + "path": "src/registry/new-york/ui/time-field.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "time", + "type": "registry:ui", + "title": "Time", + "description": "Displays a specific time (or datetime).", + "dependencies": [ + "date-fns" + ], + "files": [ + { + "path": "src/registry/new-york/ui/time.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "timeline", + "type": "registry:ui", + "title": "Timeline", + "description": "Timeline displays a list of events in chronological order.", + "dependencies": [ + "@radix-ui/react-slot" + ], + "files": [ + { + "path": "src/registry/new-york/ui/timeline.tsx", + "type": "registry:ui" + } + ] + }, + { + "name": "wheel-picker", + "type": "registry:ui", + "title": "Wheel Picker", + "description": "iOS-like wheel picker for React with smooth inertia scrolling and infinite loop support.", + "dependencies": [ + "@ncdai/react-wheel-picker" + ], + "files": [ + { + "path": "src/registry/new-york/ui/wheel-picker.tsx", + "type": "registry:ui" + } + ] + } + ] +} diff --git a/apps/v4/public/r/sortable.json b/apps/v4/public/r/sortable.json index 4d81619..aecf6a4 100644 --- a/apps/v4/public/r/sortable.json +++ b/apps/v4/public/r/sortable.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "sortable", - "type": "registry:ui", "title": "Sortable", "description": "Sortable provides a way to sort items in a list or grid.", "dependencies": [ @@ -19,5 +18,6 @@ "content": "\"use client\";\n\nimport type {\n DndContextProps,\n DragCancelEvent,\n DragEndEvent,\n DragStartEvent,\n UniqueIdentifier,\n} from \"@dnd-kit/core\";\nimport {\n DndContext,\n DragOverlay,\n KeyboardSensor,\n PointerSensor,\n closestCenter,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n NewIndexGetter,\n SortableContext,\n SortableContextProps,\n horizontalListSortingStrategy,\n sortableKeyboardCoordinates,\n useSortable as useDndSortable,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS, Transform } from \"@dnd-kit/utilities\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport * as PortalPrimitive from \"@radix-ui/react-portal\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst SortableImplContext = React.createContext<\n Pick &\n Required> & {\n activeId: UniqueIdentifier | null;\n }\n>({\n activeId: null,\n getTransformStyle: CSS.Transform.toString,\n});\n\nfunction useSortable() {\n const context = React.useContext(SortableImplContext);\n if (!context) {\n throw new Error(\"useSortable must be used within a .\");\n }\n\n return context;\n}\n\nexport interface SortableProps extends DndContextProps {\n onReorder?: (oldIndex: number, newIndex: number) => void;\n getNewIndex?: NewIndexGetter;\n getTransformStyle?: (\n transform: Transform | null,\n ) => React.CSSProperties[\"transform\"];\n}\n\nfunction Sortable({\n onDragStart,\n onDragEnd,\n onDragCancel,\n getNewIndex,\n collisionDetection = closestCenter,\n getTransformStyle = CSS.Transform.toString,\n ...props\n}: SortableProps) {\n const [activeId, setActiveId] = React.useState(null);\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n }),\n );\n\n return (\n \n (onDragStart, ({ active }) => setActiveId(active.id))}\n onDragEnd={composeEventHandlers<\n DragEndEvent & { defaultPrevented: boolean }\n >(onDragEnd, () => setActiveId(null))}\n onDragCancel={composeEventHandlers<\n DragCancelEvent & { defaultPrevented: boolean }\n >(onDragCancel, () => setActiveId(null))}\n collisionDetection={collisionDetection}\n sensors={sensors}\n {...props}\n />\n \n );\n}\n\nexport interface SortableListProps\n extends Omit,\n React.ComponentProps {\n orientation?: \"vertical\" | \"horizontal\";\n}\n\nfunction SortableList({\n orientation = \"vertical\",\n strategy = orientation === \"vertical\"\n ? verticalListSortingStrategy\n : horizontalListSortingStrategy,\n items,\n disabled,\n id,\n ref,\n ...props\n}: SortableListProps) {\n return (\n \n \n \n );\n}\n\nexport type SortableGridProps = Omit &\n React.ComponentProps;\n\nfunction SortableGrid({\n strategy,\n items,\n disabled,\n id,\n ref,\n ...props\n}: SortableGridProps) {\n return (\n \n \n \n );\n}\n\nconst SortableItemContext = React.createContext<\n Pick\n>({\n id: \"\",\n disabled: false,\n});\n\nfunction useSortableItem() {\n const context = React.useContext(SortableItemContext);\n if (!context) {\n throw new Error(\"useSortableItem must be used within a .\");\n }\n\n return context;\n}\n\nexport type SortableItemProps = Omit<\n React.ComponentProps,\n \"id\"\n> &\n Pick[0], \"id\" | \"disabled\">;\n\nfunction SortableItem({\n id,\n disabled,\n style: styleProp,\n ref,\n ...props\n}: SortableItemProps) {\n const { getTransformStyle, getNewIndex } = useSortable();\n const {\n attributes,\n setNodeRef,\n transform,\n transition,\n isDragging,\n isOver,\n isSorting,\n } = useDndSortable({\n id,\n disabled,\n getNewIndex,\n });\n\n const composedRefs = useComposedRefs(\n setNodeRef as React.RefCallback,\n ref,\n );\n const style = {\n transform: getTransformStyle(transform),\n transition,\n ...styleProp,\n };\n\n return (\n \n \n \n );\n}\n\nfunction SortableItemTrigger({\n className,\n disabled: disabledProp,\n ref,\n ...props\n}: React.ComponentProps) {\n const { getNewIndex } = useSortable();\n const { id, disabled } = useSortableItem();\n const { listeners, setActivatorNodeRef, isDragging, isOver, isSorting } =\n useDndSortable({\n id,\n disabled: disabledProp || disabled,\n getNewIndex,\n });\n\n const composedRefs = useComposedRefs(\n setActivatorNodeRef as React.RefCallback,\n ref,\n );\n\n return (\n \n );\n}\n\nexport interface SortableOverlayProps\n extends Omit, \"children\"> {\n children?: React.ReactNode | ((id: UniqueIdentifier) => React.ReactNode);\n}\n\nfunction SortableOverlay({ children, ...props }: SortableOverlayProps) {\n const { activeId } = useSortable();\n\n return (\n \n \n {activeId &&\n (typeof children === \"function\" ? children(activeId) : children)}\n \n \n );\n}\n\nexport {\n Sortable,\n SortableList,\n SortableGrid,\n SortableItem,\n SortableItemTrigger,\n SortableOverlay,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/time-field.json b/apps/v4/public/r/time-field.json index b43d82c..ff71cc9 100644 --- a/apps/v4/public/r/time-field.json +++ b/apps/v4/public/r/time-field.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "time-field", - "type": "registry:ui", "title": "Time Field", "description": "Time Field allows user to enter time value.", "registryDependencies": [ @@ -13,5 +12,6 @@ "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n DateTimeField,\n DateTimeFieldAmPm,\n DateTimeFieldHours,\n DateTimeFieldMinutes,\n DateTimeFieldSeconds,\n DateTimeFieldSeparator,\n} from \"@/registry/new-york/ui/date-time-field\";\n\nfunction TimeField(props: React.ComponentProps) {\n return ;\n}\n\nfunction TimeFieldSeparator({\n children = \":\",\n ...props\n}: React.ComponentProps) {\n return (\n \n {children}\n \n );\n}\n\nfunction TimeFieldHours(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction TimeFieldMinutes(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction TimeFieldSeconds(\n props: React.ComponentProps,\n) {\n return ;\n}\n\nfunction TimeFieldAmPm(props: React.ComponentProps) {\n return ;\n}\n\nexport {\n TimeField,\n TimeFieldSeparator,\n TimeFieldHours,\n TimeFieldMinutes,\n TimeFieldSeconds,\n TimeFieldAmPm,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/time.json b/apps/v4/public/r/time.json index 29beafe..f8ef037 100644 --- a/apps/v4/public/r/time.json +++ b/apps/v4/public/r/time.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "time", - "type": "registry:ui", "title": "Time", "description": "Displays a specific time (or datetime).", "dependencies": [ @@ -13,5 +12,6 @@ "content": "import { format } from \"date-fns\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface TimeProps\n extends Omit, \"children\"> {\n children: Parameters[0];\n dateTimeFormatStr?: Parameters[1];\n formatStr?: Parameters[1];\n}\n\nfunction Time({\n children,\n dateTimeFormatStr = \"yyyy-MM-dd\",\n formatStr = \"PPP\",\n className,\n ...props\n}: TimeProps) {\n return (\n \n {format(children, formatStr)}\n \n );\n}\n\nexport { Time };\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/timeline.json b/apps/v4/public/r/timeline.json index a991912..d59587c 100644 --- a/apps/v4/public/r/timeline.json +++ b/apps/v4/public/r/timeline.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "timeline", - "type": "registry:ui", "title": "Timeline", "description": "Timeline displays a list of events in chronological order.", "dependencies": [ @@ -13,5 +12,6 @@ "content": "\"use client\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ntype TimelineContextProps = {\n orientation: \"horizontal\" | \"vertical\";\n};\n\nconst TimelineContext = React.createContext(null);\n\nfunction useTimeline() {\n const context = React.useContext(TimelineContext);\n if (!context) {\n throw new Error(\"useTimeline must be used within a .\");\n }\n\n return context;\n}\n\nexport interface TimelineProps extends React.ComponentPropsWithoutRef<\"ol\"> {\n orientation?: \"horizontal\" | \"vertical\";\n}\n\nfunction Timeline({\n className,\n orientation = \"vertical\",\n ...props\n}: TimelineProps) {\n return (\n \n \n \n );\n}\n\nexport interface TimelineItemProps\n extends React.ComponentPropsWithoutRef<\"li\"> {\n asChild?: boolean;\n}\n\nfunction TimelineItem({ className, asChild, ...props }: TimelineItemProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"li\";\n\n return (\n \n );\n}\n\nexport interface TimelineSeparatorProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\n\nfunction TimelineSeparator({\n className,\n asChild,\n ...props\n}: TimelineSeparatorProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport interface TimelineDotProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n variant?: \"default\" | \"outline\";\n asChild?: boolean;\n}\n\nfunction TimelineDot({\n variant = \"default\",\n className,\n asChild,\n ...props\n}: TimelineDotProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport interface TimelineConnectorProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\n\nfunction TimelineConnector({\n className,\n asChild,\n ...props\n}: TimelineConnectorProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport interface TimelineContentProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\n\nfunction TimelineContent({\n className,\n asChild,\n ...props\n}: TimelineContentProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport interface TimelineTitleProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\n\nfunction TimelineTitle({ className, asChild, ...props }: TimelineTitleProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport interface TimelineDescriptionProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\n\nfunction TimelineDescription({\n className,\n asChild,\n ...props\n}: TimelineDescriptionProps) {\n const { orientation } = useTimeline();\n const Comp = asChild ? Slot : \"div\";\n\n return (\n \n );\n}\n\nexport {\n Timeline,\n TimelineItem,\n TimelineSeparator,\n TimelineDot,\n TimelineConnector,\n TimelineContent,\n TimelineTitle,\n TimelineDescription,\n useTimeline,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/use-timescape.json b/apps/v4/public/r/use-timescape.json index cd16016..d67b817 100644 --- a/apps/v4/public/r/use-timescape.json +++ b/apps/v4/public/r/use-timescape.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "use-timescape", - "type": "registry:hook", "title": "Use Timescape", "description": "A reactive wrapper around Timescape that provides controlled and uncontrolled state management for date/time input.", "dependencies": [ @@ -15,5 +14,6 @@ "content": "import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport * as React from \"react\";\nimport { DateRange } from \"react-day-picker\";\nimport {\n Options,\n useTimescape as useReactTimescape,\n useTimescapeRange as useReactTimescapeRange,\n} from \"timescape/react\";\n\nexport type TimescapeOptions = Omit;\n\nexport interface UseTimescapeOptions extends TimescapeOptions {\n value?: Date | null;\n defaultValue?: Date;\n onValueChange?: (value: Date | null) => void;\n}\n\nexport function useTimescape({\n value: valueProp,\n defaultValue,\n onValueChange,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n}: UseTimescapeOptions) {\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n onChange: onValueChange,\n });\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { update, _manager, ...timescape } = useReactTimescape({\n date: !value ? undefined : value, // This is the initial value.\n onChangeDate: (date) => setValue(date ?? null),\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n // Partial input does not work with reactive value at the moment.\n // For more information, see https://github.com/dan-lee/timescape/issues/51.\n disallowPartial: true,\n });\n\n React.useEffect(() => {\n update((prevOptions) => ({\n ...prevOptions,\n date: !value ? undefined : value,\n }));\n }, [value, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, digits }));\n }, [digits, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, hour12 }));\n }, [hour12, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, maxDate }));\n }, [maxDate, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, minDate }));\n }, [minDate, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, snapToStep }));\n }, [snapToStep, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, wheelControl }));\n }, [wheelControl, update]);\n\n React.useEffect(() => {\n update((prevOptions) => ({ ...prevOptions, wrapAround }));\n }, [wrapAround, update]);\n\n return timescape;\n}\n\nexport interface UseTimescapeRangeOptions extends TimescapeOptions {\n value?: DateRange | null;\n defaultValue?: DateRange;\n onValueChange?: (value: DateRange | null) => void;\n from?: TimescapeOptions;\n to?: TimescapeOptions;\n}\n\nexport const useTimescapeRange = ({\n value: valueProp,\n defaultValue,\n onValueChange,\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n from: fromOptions = {},\n to: toOptions = {},\n}: UseTimescapeRangeOptions) => {\n const [value, setValue] = useControllableState({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n onChange: onValueChange,\n });\n\n const { from, to, ...timescape } = useReactTimescapeRange({\n from: {\n date: !value?.from ? undefined : value.from, // This is the initial value.\n onChangeDate: (from) =>\n setValue((prevValue) => ({ from, to: prevValue?.to })),\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n // Partial input does not work with reactive value at the moment.\n // For more information, see https://github.com/dan-lee/timescape/issues/51.\n disallowPartial: true,\n ...fromOptions,\n },\n to: {\n date: !value?.to ? undefined : value.to, // This is the initial value.\n onChangeDate: (to) =>\n setValue((prevValue) => ({ from: prevValue?.from, to })),\n digits,\n hour12,\n maxDate,\n minDate,\n snapToStep,\n wheelControl,\n wrapAround,\n // Partial input does not work with reactive value at the moment.\n // For more information, see https://github.com/dan-lee/timescape/issues/51.\n disallowPartial: true,\n ...toOptions,\n },\n });\n\n // ----------------------------------------------------------------------------\n // Sync `from`\n // ----------------------------------------------------------------------------\n\n const { update: fromUpdate, ...fromTimescape } = from;\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n digits: fromOptions.digits ?? digits,\n }));\n }, [digits, fromOptions.digits, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n hour12: fromOptions.hour12 ?? hour12,\n }));\n }, [hour12, fromOptions.hour12, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n maxDate: fromOptions.maxDate ?? maxDate,\n }));\n }, [maxDate, fromOptions.maxDate, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n minDate: fromOptions.minDate ?? minDate,\n }));\n }, [minDate, fromOptions.minDate, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n snapToStep: fromOptions.snapToStep ?? snapToStep,\n }));\n }, [snapToStep, fromOptions.snapToStep, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n wheelControl: fromOptions.wheelControl ?? wheelControl,\n }));\n }, [wheelControl, fromOptions.wheelControl, fromUpdate]);\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n wrapAround: fromOptions.wrapAround ?? wrapAround,\n }));\n }, [wrapAround, fromOptions.wrapAround, fromUpdate]);\n\n // ----------------------------------------------------------------------------\n // Sync `to`\n // ----------------------------------------------------------------------------\n\n const { update: toUpdate, ...toTimescape } = to;\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n digits: toOptions.digits ?? digits,\n }));\n }, [digits, toOptions.digits, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n hour12: toOptions.hour12 ?? hour12,\n }));\n }, [hour12, toOptions.hour12, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n maxDate: toOptions.maxDate ?? maxDate,\n }));\n }, [maxDate, toOptions.maxDate, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n minDate: toOptions.minDate ?? minDate,\n }));\n }, [minDate, toOptions.minDate, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n snapToStep: toOptions.snapToStep ?? snapToStep,\n }));\n }, [snapToStep, toOptions.snapToStep, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n wheelControl: toOptions.wheelControl ?? wheelControl,\n }));\n }, [wheelControl, toOptions.wheelControl, toUpdate]);\n\n React.useEffect(() => {\n toUpdate((prevOptions) => ({\n ...prevOptions,\n wrapAround: toOptions.wrapAround ?? wrapAround,\n }));\n }, [wrapAround, toOptions.wrapAround, toUpdate]);\n\n // ----------------------------------------------------------------------------\n // Sync `value`\n // ----------------------------------------------------------------------------\n\n React.useEffect(() => {\n fromUpdate((prevOptions) => ({\n ...prevOptions,\n date: !value?.from ? undefined : value.from,\n }));\n toUpdate((prevOptions) => ({\n ...prevOptions,\n date: !value?.to ? undefined : value.to,\n }));\n }, [value, fromUpdate, toUpdate]);\n\n return {\n ...timescape,\n from: fromTimescape,\n to: toTimescape,\n };\n};\n", "type": "registry:hook" } - ] + ], + "type": "registry:hook" } \ No newline at end of file diff --git a/apps/v4/public/r/virtualized.json b/apps/v4/public/r/virtualized.json index 9e9b9aa..d79c65c 100644 --- a/apps/v4/public/r/virtualized.json +++ b/apps/v4/public/r/virtualized.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "virtualized", - "type": "registry:ui", "title": "Virtualized", "description": "A virtualized component that allows you to efficiently render large lists and tabular data.", "dependencies": [ @@ -15,5 +14,6 @@ "content": "\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"@radix-ui/react-primitive\";\nimport * as React from \"react\";\nimport { experimental_VGrid as VGrid, VList, Virtualizer } from \"virtua\";\n\nconst VirtualizedContext = React.createContext<{\n scrollRef: React.RefObject | null>;\n withScrollRef: boolean;\n}>({\n scrollRef: { current: null },\n withScrollRef: false,\n});\n\nfunction useVirtualized() {\n const context = React.useContext(VirtualizedContext);\n if (!context) {\n throw new Error(\"useVirtualized must be used within a .\");\n }\n return context;\n}\n\nfunction Virtualized({\n ref,\n ...props\n}: React.ComponentProps) {\n const scrollRef =\n React.useRef>(null);\n\n const composedRefs = useComposedRefs(scrollRef, ref);\n\n return (\n \n \n \n );\n}\n\nexport interface VirtualizedListProps\n extends Omit, \"horizontal\"> {\n orientation?: \"vertical\" | \"horizontal\";\n}\n\nfunction VirtualizedList({\n orientation = \"vertical\",\n ...props\n}: VirtualizedListProps) {\n const { withScrollRef } = useVirtualized();\n\n if (withScrollRef) {\n throw new Error(\n \" must not be used within a .\",\n );\n }\n\n return (\n \n );\n}\n\nfunction VirtualizedGrid(props: React.ComponentProps) {\n return ;\n}\n\nfunction VirtualizedVirtualizer({\n ...props\n}: Omit, \"scrollRef\">) {\n const { scrollRef, withScrollRef } = useVirtualized();\n\n return (\n \n );\n}\n\nexport {\n Virtualized,\n VirtualizedList,\n VirtualizedGrid,\n VirtualizedVirtualizer,\n};\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/public/r/wheel-picker.json b/apps/v4/public/r/wheel-picker.json index ec0925e..ebd7246 100644 --- a/apps/v4/public/r/wheel-picker.json +++ b/apps/v4/public/r/wheel-picker.json @@ -1,7 +1,6 @@ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "wheel-picker", - "type": "registry:ui", "title": "Wheel Picker", "description": "iOS-like wheel picker for React with smooth inertia scrolling and infinite loop support.", "dependencies": [ @@ -13,5 +12,6 @@ "content": "\"use client\";\n\nimport \"@ncdai/react-wheel-picker/style.css\";\n\nimport * as WheelPickerPrimitive from \"@ncdai/react-wheel-picker\";\nimport { WheelPickerOption } from \"@ncdai/react-wheel-picker\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nfunction WheelPickerWrapper({\n className,\n ...props\n}: React.ComponentProps) {\n return (\n [data-rwp]]:first:[&>[data-rwp-highlight-wrapper]]:rounded-s-md\",\n \"[&>[data-rwp]]:last:[&>[data-rwp-highlight-wrapper]]:rounded-e-md\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction WheelPicker({\n classNames,\n ...props\n}: React.ComponentProps) {\n return (\n \n );\n}\n\nexport { WheelPicker, WheelPickerWrapper, type WheelPickerOption };\n", "type": "registry:ui" } - ] + ], + "type": "registry:ui" } \ No newline at end of file diff --git a/apps/v4/src/app/globals.css b/apps/v4/src/app/globals.css index 360e594..ebaeb57 100644 --- a/apps/v4/src/app/globals.css +++ b/apps/v4/src/app/globals.css @@ -1,5 +1,6 @@ @import "tailwindcss"; @import "tw-animate-css"; +@import "shadcn/tailwind.css"; @custom-variant dark (&:is(.dark *)); @@ -8,6 +9,7 @@ --color-foreground: var(--foreground); --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); + --font-heading: var(--font-sans); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); @@ -37,10 +39,13 @@ --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); --color-card: var(--card); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); + --radius-3xl: calc(var(--radius) * 2.2); + --radius-4xl: calc(var(--radius) * 2.6); --animate-accordion-down: accordion-down 0.2s ease-out; --animate-accordion-up: accordion-up 0.2s ease-out; @@ -50,24 +55,6 @@ --animate-landing-vertical-line-intro: landing-vertical-line-intro var(--animation-duration, 1s) ease-in-out forwards; - @keyframes accordion-down { - from { - height: 0; - } - to { - height: var(--radix-accordion-content-height); - } - } - - @keyframes accordion-up { - from { - height: var(--radix-accordion-content-height); - } - to { - height: 0; - } - } - @keyframes landing-horizontal-line-intro { from { opacity: 1; @@ -123,11 +110,11 @@ --border: oklch(0.922 0 0); --input: oklch(0.922 0 0); --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); --sidebar: var(--background); --sidebar-foreground: var(--foreground); --sidebar-primary: oklch(0.205 0 0); @@ -157,11 +144,11 @@ --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); + --chart-1: oklch(0.87 0 0); + --chart-2: oklch(0.556 0 0); + --chart-3: oklch(0.439 0 0); + --chart-4: oklch(0.371 0 0); + --chart-5: oklch(0.269 0 0); --sidebar: var(--background); --sidebar-foreground: var(--foreground); --sidebar-primary: oklch(0.922 0 0); diff --git a/apps/v4/src/components/code-block-wrapper.tsx b/apps/v4/src/components/code-block-wrapper.tsx index e484ea1..74b5d36 100644 --- a/apps/v4/src/components/code-block-wrapper.tsx +++ b/apps/v4/src/components/code-block-wrapper.tsx @@ -3,11 +3,6 @@ import * as React from "react"; import { Button } from "@/components/ui/button"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; import { cn } from "@/lib/utils"; interface CodeBlockProps extends React.HTMLAttributes { @@ -23,36 +18,34 @@ export function CodeBlockWrapper({ const [isOpened, setIsOpened] = React.useState(false); return ( - -
- -
- {children} -
-
+
+
- - - + {children}
- +
+ +
+
); } diff --git a/apps/v4/src/components/component-demo-carousel-section.tsx b/apps/v4/src/components/component-demo-carousel-section.tsx index 812a0a3..764afa9 100644 --- a/apps/v4/src/components/component-demo-carousel-section.tsx +++ b/apps/v4/src/components/component-demo-carousel-section.tsx @@ -82,11 +82,13 @@ export function ComponentDemoCarouselSection() {

Explore more components

-
diff --git a/apps/v4/src/components/examples/control-group-split-button.tsx b/apps/v4/src/components/examples/control-group-split-button.tsx index a40241f..ac16d6d 100644 --- a/apps/v4/src/components/examples/control-group-split-button.tsx +++ b/apps/v4/src/components/examples/control-group-split-button.tsx @@ -25,10 +25,10 @@ export default function ControlGroupSplitButton() { - - + } + > + diff --git a/apps/v4/src/components/examples/control-group-vertical.tsx b/apps/v4/src/components/examples/control-group-vertical.tsx index 6fcf944..879f37a 100644 --- a/apps/v4/src/components/examples/control-group-vertical.tsx +++ b/apps/v4/src/components/examples/control-group-vertical.tsx @@ -1,15 +1,15 @@ -import { BadgeCheck, CreditCard } from "lucide-react" +import { BadgeCheck, CreditCard } from "lucide-react"; import { ControlGroup, ControlGroupItem, -} from "@/registry/new-york/ui/control-group" +} from "@/registry/new-york/ui/control-group"; import { InputBase, InputBaseAdornment, InputBaseControl, InputBaseInput, -} from "@/registry/new-york/ui/input-base" +} from "@/registry/new-york/ui/input-base"; export default function ControlGroupVertical() { return ( @@ -61,5 +61,5 @@ export default function ControlGroupVertical() {
- ) + ); } diff --git a/apps/v4/src/components/examples/emoji-picker-demo.tsx b/apps/v4/src/components/examples/emoji-picker-demo.tsx index 29d3639..157f0a2 100644 --- a/apps/v4/src/components/examples/emoji-picker-demo.tsx +++ b/apps/v4/src/components/examples/emoji-picker-demo.tsx @@ -22,11 +22,9 @@ export default function EmojiPickerDemo() { return ( - - + }> + + Try it - - - - Pick emoji - + }> + + Pick emoji diff --git a/apps/v4/src/components/examples/native-select-responsive.tsx b/apps/v4/src/components/examples/native-select-responsive.tsx index 6a2c41b..855fbee 100644 --- a/apps/v4/src/components/examples/native-select-responsive.tsx +++ b/apps/v4/src/components/examples/native-select-responsive.tsx @@ -25,7 +25,7 @@ export default function NativeSelectResponsive() { if (isDesktop) { return ( - setValue(value ?? "")}> diff --git a/apps/v4/src/components/examples/sortable-form.tsx b/apps/v4/src/components/examples/sortable-form.tsx index e32eb1e..de0278c 100644 --- a/apps/v4/src/components/examples/sortable-form.tsx +++ b/apps/v4/src/components/examples/sortable-form.tsx @@ -85,11 +85,11 @@ function Item({ onSubmit={onEdit} values={{ title, description }} > - - + } + > + + Edit + }> + Cancel @@ -370,11 +368,11 @@ export default function SortableForm() { actionText="Add item" onSubmit={(data) => append(data)} > - - + } + > + + Add Item diff --git a/apps/v4/src/components/examples/virtualizer-scroll-area.tsx b/apps/v4/src/components/examples/virtualizer-scroll-area.tsx index 7dcb017..60a3a20 100644 --- a/apps/v4/src/components/examples/virtualizer-scroll-area.tsx +++ b/apps/v4/src/components/examples/virtualizer-scroll-area.tsx @@ -1,6 +1,6 @@ "use client"; -import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"; +import { ScrollArea as ScrollAreaPrimitive } from "@base-ui/react/scroll-area"; import * as React from "react"; import { ScrollBar } from "@/components/ui/scroll-area"; @@ -17,23 +17,22 @@ const tags = Array.from({ length: 10000 }).map( export default function VirtualizerScrollArea() { return ( - - -
-

Tags

- - {tags.map((tag) => ( - <> -
- {tag} -
- - - ))} -
-
-
-
+ } + className="size-full rounded-[inherit]" + > +
+

Tags

+ + {tags.map((tag) => ( + +
{tag}
+ +
+ ))} +
+
+
diff --git a/apps/v4/src/components/examples/virtualizer-select.tsx b/apps/v4/src/components/examples/virtualizer-select.tsx index 2cc677e..576e7b1 100644 --- a/apps/v4/src/components/examples/virtualizer-select.tsx +++ b/apps/v4/src/components/examples/virtualizer-select.tsx @@ -1,19 +1,19 @@ "use client"; -import * as SelectPrimitive from "@radix-ui/react-select"; import * as React from "react"; import { VirtualizerHandle } from "virtua"; import { Select, + SelectContent, SelectItem, - SelectScrollDownButton, - SelectScrollUpButton, SelectTrigger, SelectValue, } from "@/components/ui/select"; -import { cn } from "@/lib/utils"; -import { VirtualizedVirtualizer } from "@/registry/new-york/ui/virtualized"; +import { + Virtualized, + VirtualizedVirtualizer, +} from "@/registry/new-york/ui/virtualized"; const items = Array.from({ length: 10000 }, (_, index) => ({ label: `Item ${index + 1}`, @@ -21,7 +21,7 @@ const items = Array.from({ length: 10000 }, (_, index) => ({ })); export default function VirtualizerSelect() { - const [value, setValue] = React.useState(""); + const [value, setValue] = React.useState(null); const [open, setOpen] = React.useState(false); const virtualizerRef = React.useRef(null); @@ -39,17 +39,18 @@ export default function VirtualizerSelect() { // Recover scroll position. virtualizerRef.current?.scrollToIndex(activeIndex, { align: "end" }); - const checkedElement = viewportRef.current?.querySelector( - "[data-state=checked]", + const selectedElement = viewportRef.current?.querySelector( + "[data-selected]", ) as HTMLElement; // Recover focus. - checkedElement?.focus({ preventScroll: true }); + selectedElement?.focus({ preventScroll: true }); }); }, [open, value, activeIndex]); return ( ); } diff --git a/apps/v4/src/components/examples/wheel-picker-form.tsx b/apps/v4/src/components/examples/wheel-picker-form.tsx index 7dd56a2..bdc993c 100644 --- a/apps/v4/src/components/examples/wheel-picker-form.tsx +++ b/apps/v4/src/components/examples/wheel-picker-form.tsx @@ -21,7 +21,6 @@ import { } from "@/components/ui/form"; import { Popover, - PopoverAnchor, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; @@ -105,27 +104,26 @@ export default function WheelPickerForm() { Event time - - + + + + + + + + + } > - - - - - - - - - - - - - - - + +
+ - } > - - {item.title} - {"label" in item && ( - - {item.label} - - )} - + {item.title} + {"label" in item && ( + + {item.label} + + )} ))} diff --git a/apps/v4/src/components/ui/accordion.tsx b/apps/v4/src/components/ui/accordion.tsx index f042898..fca40cd 100644 --- a/apps/v4/src/components/ui/accordion.tsx +++ b/apps/v4/src/components/ui/accordion.tsx @@ -1,25 +1,23 @@ -"use client"; - -import * as AccordionPrimitive from "@radix-ui/react-accordion"; -import { ChevronDownIcon } from "lucide-react"; -import * as React from "react"; +import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"; +import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import { cn } from "@/lib/utils"; -function Accordion({ - ...props -}: React.ComponentProps) { - return ; +function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { + return ( + + ); } -function AccordionItem({ - className, - ...props -}: React.ComponentProps) { +function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { return ( ); @@ -29,19 +27,26 @@ function AccordionTrigger({ className, children, ...props -}: React.ComponentProps) { +}: AccordionPrimitive.Trigger.Props) { return ( svg]:rotate-180", + "group/accordion-trigger focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:after:border-ring **:data-[slot=accordion-trigger-icon]:text-muted-foreground relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-3 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", className, )} {...props} > {children} - + + ); @@ -51,15 +56,22 @@ function AccordionContent({ className, children, ...props -}: React.ComponentProps) { +}: AccordionPrimitive.Panel.Props) { return ( - -
{children}
-
+
+ {children} +
+ ); } diff --git a/apps/v4/src/components/ui/alert-dialog.tsx b/apps/v4/src/components/ui/alert-dialog.tsx index 24f66b5..399fd2f 100644 --- a/apps/v4/src/components/ui/alert-dialog.tsx +++ b/apps/v4/src/components/ui/alert-dialog.tsx @@ -1,28 +1,22 @@ "use client"; -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; +import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"; import * as React from "react"; -import { buttonVariants } from "@/components/ui/button"; +import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; -function AlertDialog({ - ...props -}: React.ComponentProps) { +function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) { return ; } -function AlertDialogTrigger({ - ...props -}: React.ComponentProps) { +function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) { return ( ); } -function AlertDialogPortal({ - ...props -}: React.ComponentProps) { +function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) { return ( ); @@ -31,12 +25,12 @@ function AlertDialogPortal({ function AlertDialogOverlay({ className, ...props -}: React.ComponentProps) { +}: AlertDialogPrimitive.Backdrop.Props) { return ( - ) { +}: AlertDialogPrimitive.Popup.Props & { + size?: "default" | "sm"; +}) { return ( - ); @@ -84,7 +85,23 @@ function AlertDialogFooter({
+ ); +} + +function AlertDialogMedia({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
); @@ -112,7 +132,10 @@ function AlertDialogDescription({ return ( ); @@ -121,10 +144,11 @@ function AlertDialogDescription({ function AlertDialogAction({ className, ...props -}: React.ComponentProps) { +}: React.ComponentProps) { return ( - ); @@ -132,11 +156,16 @@ function AlertDialogAction({ function AlertDialogCancel({ className, + variant = "outline", + size = "default", ...props -}: React.ComponentProps) { +}: AlertDialogPrimitive.Close.Props & + Pick, "variant" | "size">) { return ( - } {...props} /> ); @@ -144,14 +173,15 @@ function AlertDialogCancel({ export { AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, - AlertDialogTrigger, + AlertDialogAction, + AlertDialogCancel, AlertDialogContent, - AlertDialogHeader, + AlertDialogDescription, AlertDialogFooter, + AlertDialogHeader, + AlertDialogMedia, + AlertDialogOverlay, + AlertDialogPortal, AlertDialogTitle, - AlertDialogDescription, - AlertDialogAction, - AlertDialogCancel, + AlertDialogTrigger, }; diff --git a/apps/v4/src/components/ui/alert.tsx b/apps/v4/src/components/ui/alert.tsx index f85fcf9..8e50f7b 100644 --- a/apps/v4/src/components/ui/alert.tsx +++ b/apps/v4/src/components/ui/alert.tsx @@ -4,13 +4,13 @@ import * as React from "react"; import { cn } from "@/lib/utils"; const alertVariants = cva( - "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", + "group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", { variants: { variant: { default: "bg-card text-card-foreground", destructive: - "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", + "bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current", }, }, defaultVariants: { @@ -39,7 +39,7 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3", className, )} {...props} @@ -55,7 +55,7 @@ function AlertDescription({
) { + return ( +
+ ); +} + +export { Alert, AlertTitle, AlertDescription, AlertAction }; diff --git a/apps/v4/src/components/ui/badge.tsx b/apps/v4/src/components/ui/badge.tsx index 14ed01e..a5fde4a 100644 --- a/apps/v4/src/components/ui/badge.tsx +++ b/apps/v4/src/components/ui/badge.tsx @@ -1,22 +1,24 @@ -import { Slot } from "@radix-ui/react-slot"; +import { mergeProps } from "@base-ui/react/merge-props"; +import { useRender } from "@base-ui/react/use-render"; import { type VariantProps, cva } from "class-variance-authority"; -import * as React from "react"; import { cn } from "@/lib/utils"; const badgeVariants = cva( - "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + "group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!", { variants: { variant: { - default: - "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80", secondary: - "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80", destructive: - "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20", outline: - "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", + "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground", + ghost: + "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50", + link: "text-primary underline-offset-4 hover:underline", }, }, defaultVariants: { @@ -27,20 +29,24 @@ const badgeVariants = cva( function Badge({ className, - variant, - asChild = false, + variant = "default", + render, ...props -}: React.ComponentProps<"span"> & - VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot : "span"; - - return ( - - ); +}: useRender.ComponentProps<"span"> & VariantProps) { + return useRender({ + defaultTagName: "span", + props: mergeProps<"span">( + { + className: cn(badgeVariants({ variant }), className), + }, + props, + ), + render, + state: { + slot: "badge", + variant, + }, + }); } export { Badge, badgeVariants }; diff --git a/apps/v4/src/components/ui/breadcrumb.tsx b/apps/v4/src/components/ui/breadcrumb.tsx index e37685e..b02df81 100644 --- a/apps/v4/src/components/ui/breadcrumb.tsx +++ b/apps/v4/src/components/ui/breadcrumb.tsx @@ -1,11 +1,19 @@ -import { Slot } from "@radix-ui/react-slot"; -import { ChevronRight, MoreHorizontal } from "lucide-react"; +import { mergeProps } from "@base-ui/react/merge-props"; +import { useRender } from "@base-ui/react/use-render"; +import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"; import * as React from "react"; import { cn } from "@/lib/utils"; -function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { - return