From d7113d4d0767ffc34402e5fdbda2a21e21280510 Mon Sep 17 00:00:00 2001 From: GregorGabric Date: Fri, 31 Jul 2026 19:56:57 +0200 Subject: [PATCH] Add React Aria 1.20 components and examples --- apps/preskok/content/docs/forms/meta.json | 1 + .../content/docs/forms/token-field.mdx | 76 ++++++++ apps/preskok/content/docs/layout/table.mdx | 12 ++ apps/preskok/content/docs/popups/menu.mdx | 7 + apps/preskok/content/docs/popups/meta.json | 1 + .../content/docs/popups/preview-trigger.mdx | 78 ++++++++ apps/preskok/content/docs/text/keyboard.mdx | 11 ++ apps/preskok/lib/source.ts | 16 ++ apps/preskok/package.json | 9 +- apps/preskok/public/r/badge.json | 2 +- apps/preskok/public/r/calendar.json | 4 +- .../public/r/color-field-preskok-demo.json | 2 +- .../public/r/color-picker-preskok-demo.json | 2 +- apps/preskok/public/r/color-picker.json | 4 +- .../r/color-swatch-picker-preskok-demo.json | 2 +- apps/preskok/public/r/file-trigger.json | 2 +- .../r/keyboard-shortcuts-preskok-demo.json | 19 ++ .../r/menu-context-menu-preskok-demo.json | 16 ++ .../r/preview-trigger-preskok-demo.json | 18 ++ apps/preskok/public/r/preview-trigger.json | 19 ++ apps/preskok/public/r/registry.json | 114 +++++++++++- .../table-interactive-cells-preskok-demo.json | 17 ++ .../public/r/token-field-preskok-demo.json | 15 ++ apps/preskok/public/r/token-field.json | 20 ++ apps/preskok/registry.json | 114 +++++++++++- apps/preskok/registry/__index__.tsx | 126 +++++++++++++ .../examples/color-field-preskok-demo.tsx | 2 +- .../examples/color-picker-preskok-demo.tsx | 2 +- .../color-swatch-picker-preskok-demo.tsx | 2 +- .../keyboard-shortcuts-preskok-demo.tsx | 43 +++++ .../menu-context-menu-preskok-demo.tsx | 79 ++++++++ .../examples/preview-trigger-preskok-demo.tsx | 79 ++++++++ .../table-interactive-cells-preskok-demo.tsx | 54 ++++++ .../examples/token-field-preskok-demo.tsx | 78 ++++++++ .../preskok/ui/preskok-ui/calendar.tsx | 2 +- .../preskok/ui/preskok-ui/color-picker.tsx | 2 +- .../preskok/ui/preskok-ui/file-trigger.tsx | 20 +- .../preskok/ui/preskok-ui/preview-trigger.tsx | 17 ++ .../preskok/ui/preskok-ui/token-field.tsx | 82 +++++++++ apps/preskok/registry/registry-examples.ts | 56 ++++++ apps/preskok/registry/registry-preskok.ts | 31 +++- apps/preskok/source.config.ts | 20 +- pnpm-lock.yaml | 173 ++++-------------- 43 files changed, 1269 insertions(+), 180 deletions(-) create mode 100644 apps/preskok/content/docs/forms/token-field.mdx create mode 100644 apps/preskok/content/docs/popups/preview-trigger.mdx create mode 100644 apps/preskok/public/r/keyboard-shortcuts-preskok-demo.json create mode 100644 apps/preskok/public/r/menu-context-menu-preskok-demo.json create mode 100644 apps/preskok/public/r/preview-trigger-preskok-demo.json create mode 100644 apps/preskok/public/r/preview-trigger.json create mode 100644 apps/preskok/public/r/table-interactive-cells-preskok-demo.json create mode 100644 apps/preskok/public/r/token-field-preskok-demo.json create mode 100644 apps/preskok/public/r/token-field.json create mode 100644 apps/preskok/registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx create mode 100644 apps/preskok/registry/preskok/examples/menu-context-menu-preskok-demo.tsx create mode 100644 apps/preskok/registry/preskok/examples/preview-trigger-preskok-demo.tsx create mode 100644 apps/preskok/registry/preskok/examples/table-interactive-cells-preskok-demo.tsx create mode 100644 apps/preskok/registry/preskok/examples/token-field-preskok-demo.tsx create mode 100644 apps/preskok/registry/preskok/ui/preskok-ui/preview-trigger.tsx create mode 100644 apps/preskok/registry/preskok/ui/preskok-ui/token-field.tsx diff --git a/apps/preskok/content/docs/forms/meta.json b/apps/preskok/content/docs/forms/meta.json index 62f2dcb28..d12b6419f 100644 --- a/apps/preskok/content/docs/forms/meta.json +++ b/apps/preskok/content/docs/forms/meta.json @@ -19,6 +19,7 @@ "list-box", "choice-box", "multi-select", + "token-field", "tag-field", "tag-group", "calendar", diff --git a/apps/preskok/content/docs/forms/token-field.mdx b/apps/preskok/content/docs/forms/token-field.mdx new file mode 100644 index 000000000..628680a68 --- /dev/null +++ b/apps/preskok/content/docs/forms/token-field.mdx @@ -0,0 +1,76 @@ +--- +title: Token Field +description: Enter free text with selectable inline tokens. +status: new +--- + +import { CodeTabs } from "@/components/code-tabs" +import { ComponentPreview } from "@/components/component-preview" +import { ComponentSource } from "@/components/component-source" + + + +## Installation + + + + + CLI + Manual + + + +```bash +npx preskok-ui@latest add token-field +``` + + + + + + + + + +Copy and paste the following code into your project. + + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { TokenFieldValue } from "react-aria-components/TokenField" + +import { Token, TokenField } from "@/components/ui/preskok-ui/token-field" + +const value = new TokenFieldValue([ + { type: "text", text: "Find " }, + { type: "token", text: "status:available" }, +]) + +export function TokenFieldDemo() { + return ( + + {(segment) => {segment.text}} + + ) +} +``` + +`TokenField` uses a `TokenFieldValue` to represent its sequence of text and token +segments. Extend that value class when the field needs custom tokenization rules. diff --git a/apps/preskok/content/docs/layout/table.mdx b/apps/preskok/content/docs/layout/table.mdx index e52bec823..2133e1914 100644 --- a/apps/preskok/content/docs/layout/table.mdx +++ b/apps/preskok/content/docs/layout/table.mdx @@ -30,6 +30,18 @@ import { ComponentSource } from "@/components/component-source" description="Table with drag and drop functionality." /> +## Interactive cells + + + +Set `keyboardNavigationBehavior="tab"` when cells contain interactive controls. +This keeps arrow keys and text input inside the control while + +Tab moves through each focusable cell. + ## Installation diff --git a/apps/preskok/content/docs/popups/menu.mdx b/apps/preskok/content/docs/popups/menu.mdx index 6ec29329f..2e6940970 100644 --- a/apps/preskok/content/docs/popups/menu.mdx +++ b/apps/preskok/content/docs/popups/menu.mdx @@ -74,6 +74,13 @@ export function MenuDemo() { ## Examples +### Context Menu + + + ### Submenu + +## Installation + + + + + CLI + Manual + + + +```bash +npx preskok-ui@latest add preview-trigger +``` + + + + + + + + + +Copy and paste the following code into your project. + + + + +Update the import paths to match your project setup. + + + + + + + +## Usage + +```tsx +import { Link } from "@/components/ui/preskok-ui/link" +import { + PreviewContent, + PreviewTrigger, +} from "@/components/ui/preskok-ui/preview-trigger" + +export function PreviewTriggerDemo() { + return ( + + Volvo EX30 + + Interactive preview content + + + ) +} +``` + +Preview content opens after a warmup delay on hover or focus and on long press +for touch input. While it is open, Tab moves focus into the popover and + +Escape closes it and restores focus. diff --git a/apps/preskok/content/docs/text/keyboard.mdx b/apps/preskok/content/docs/text/keyboard.mdx index 5bfaa5d1a..38f5c466e 100644 --- a/apps/preskok/content/docs/text/keyboard.mdx +++ b/apps/preskok/content/docs/text/keyboard.mdx @@ -12,6 +12,17 @@ import { ComponentSource } from "@/components/component-source" description="Common shortcut badges." /> +## Shortcuts + + + +`useKeyboard` accepts shortcut strings such as `Mod+s`, where `Mod` resolves to +Command on macOS and Control on other platforms. A shortcut handler prevents the +browser default and stops propagation unless it returns a different policy. + ## Installation ```bash diff --git a/apps/preskok/lib/source.ts b/apps/preskok/lib/source.ts index 17d65fcab..8f2a7311d 100644 --- a/apps/preskok/lib/source.ts +++ b/apps/preskok/lib/source.ts @@ -1,4 +1,6 @@ +import { createElement } from "react" import { loader } from "fumadocs-core/source" +import { statusBadgesPlugin } from "fumadocs-core/source/status-badges" import { docs } from "fumadocs-mdx:collections/server" export const docsRoute = "" @@ -6,6 +8,20 @@ export const docsImageRoute = "/og/docs" export const source = loader({ baseUrl: docsRoute, + plugins: [ + statusBadgesPlugin({ + renderBadge: (status) => + createElement( + "small", + { + className: + "bg-primary/10 text-primary dark:bg-primary/15 shrink-0 rounded-full px-1.5 py-0.5 font-medium", + "data-status": status, + }, + status.charAt(0).toUpperCase() + status.slice(1) + ), + }), + ], source: docs.toFumadocsSource(), }) diff --git a/apps/preskok/package.json b/apps/preskok/package.json index 1ca6833a6..89badf3ba 100644 --- a/apps/preskok/package.json +++ b/apps/preskok/package.json @@ -17,9 +17,7 @@ "postinstall": "fumadocs-mdx" }, "dependencies": { - "@internationalized/date": "^3.12.2", - "@react-aria/i18n": "^3.13.1", - "@react-stately/color": "^3.10.1", + "@internationalized/date": "^3.12.3", "@tabler/icons-react": "^3.44.0", "@tailwindcss/postcss": "^4.3.1", "@tanstack/react-table": "^8.21.3", @@ -49,11 +47,12 @@ "ntcjs": "^1.1.3", "postcss": "^8.5.15", "react": "19.2.7", - "react-aria-components": "^1.19.0", + "react-aria": "^3.51.0", + "react-aria-components": "^1.20.0", "react-dom": "19.2.7", "react-number-format": "^5.4.5", "react-resizable-panels": "^4.11.2", - "react-stately": "^3.48.0", + "react-stately": "^3.49.0", "recharts": "3.9.0", "rimraf": "^6.1.3", "shadcn": "^4.11.0", diff --git a/apps/preskok/public/r/badge.json b/apps/preskok/public/r/badge.json index 404187816..4a52b7fbc 100644 --- a/apps/preskok/public/r/badge.json +++ b/apps/preskok/public/r/badge.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/preskok/ui/preskok-ui/badge.tsx", - "content": "\"use client\"\n\nimport type { ComponentProps } from \"react\"\nimport React from \"react\"\nimport { tv, type VariantProps } from \"tailwind-variants\"\n\nconst badgeIntents = {\n primary: [\n \"[--badge-primary:color-mix(in_oklab,var(--color-primary)_10%,white_90%)] [--badge-primary-foreground:color-mix(in_oklab,var(--color-primary)_60%,white_40%)] bg-(--badge-primary)\",\n \"dark:bg-primary/15 text-primary dark:text-(--badge-primary-foreground) dark:group-hover:bg-primary/25\",\n \"group-hover:bg-[color-mix(in_oklab,var(--color-primary)_15%,white_85%)] dark:group-hover:bg-primary/20\",\n ],\n secondary: [\n \"bg-secondary group-hover:bg-border text-secondary-foreground\",\n ],\n success: [\n \"bg-emerald-500/15 text-emerald-700 group-hover:bg-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-400 dark:group-hover:bg-emerald-500/20\",\n ],\n info: \"bg-sky-500/15 text-sky-700 group-hover:bg-sky-500/25 dark:bg-sky-500/10 dark:text-sky-300 dark:group-hover:bg-sky-500/20\",\n warning:\n \"bg-amber-400/20 text-amber-700 group-hover:bg-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400 dark:group-hover:bg-amber-400/15\",\n danger:\n \"bg-red-500/15 text-red-700 group-hover:bg-red-500/25 dark:bg-red-500/10 dark:text-red-400 dark:group-hover:bg-red-500/20\",\n outline:\n \"inset-ring-border bg-transparent text-foreground group-hover:bg-secondary\",\n}\nconst badgeStyles = tv({\n base: \"inset-ring inset-ring-transparent inline-flex items-center gap-x-1.5 py-0.5 font-medium text-xs/5 **:data-[slot=icon]:size-3 forced-colors:outline\",\n variants: {\n intent: { ...badgeIntents },\n isCircle: {\n true: \"rounded-full px-2\",\n false: \"rounded-sm px-1.5\",\n },\n },\n defaultVariants: {\n intent: \"primary\",\n isCircle: true,\n },\n})\n\ninterface BadgeProps\n extends ComponentProps<\"span\">, VariantProps {\n className?: string\n children: React.ReactNode\n}\n\nconst Badge = ({\n children,\n intent,\n isCircle = true,\n className,\n ...props\n}: BadgeProps) => {\n return (\n \n {children}\n \n )\n}\nexport { Badge, badgeIntents, badgeStyles }\nexport type { BadgeProps }\n", + "content": "\"use client\"\n\nimport type { ComponentProps } from \"react\"\nimport React from \"react\"\nimport { tv, type VariantProps } from \"tailwind-variants\"\n\nconst badgeIntents = {\n primary: [\n \"[--badge-primary:color-mix(in_oklab,var(--color-primary)_10%,white_90%)] [--badge-primary-foreground:color-mix(in_oklab,var(--color-primary)_60%,white_40%)] bg-(--badge-primary)\",\n \"dark:bg-primary/15 text-primary dark:text-(--badge-primary-foreground) dark:group-hover:bg-primary/25\",\n \"group-hover:bg-[color-mix(in_oklab,var(--color-primary)_15%,white_85%)] dark:group-hover:bg-primary/20\",\n ],\n secondary: [\"bg-secondary group-hover:bg-border text-secondary-foreground\"],\n success: [\n \"bg-emerald-500/15 text-emerald-700 group-hover:bg-emerald-500/25 dark:bg-emerald-500/10 dark:text-emerald-400 dark:group-hover:bg-emerald-500/20\",\n ],\n info: \"bg-sky-500/15 text-sky-700 group-hover:bg-sky-500/25 dark:bg-sky-500/10 dark:text-sky-300 dark:group-hover:bg-sky-500/20\",\n warning:\n \"bg-amber-400/20 text-amber-700 group-hover:bg-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400 dark:group-hover:bg-amber-400/15\",\n danger:\n \"bg-red-500/15 text-red-700 group-hover:bg-red-500/25 dark:bg-red-500/10 dark:text-red-400 dark:group-hover:bg-red-500/20\",\n outline:\n \"inset-ring-border bg-transparent text-foreground group-hover:bg-secondary\",\n}\nconst badgeStyles = tv({\n base: \"inset-ring inset-ring-transparent inline-flex items-center gap-x-1.5 py-0.5 font-medium text-xs/5 **:data-[slot=icon]:size-3 forced-colors:outline\",\n variants: {\n intent: { ...badgeIntents },\n isCircle: {\n true: \"rounded-full px-2\",\n false: \"rounded-sm px-1.5\",\n },\n },\n defaultVariants: {\n intent: \"primary\",\n isCircle: true,\n },\n})\n\ninterface BadgeProps\n extends ComponentProps<\"span\">, VariantProps {\n className?: string\n children: React.ReactNode\n}\n\nconst Badge = ({\n children,\n intent,\n isCircle = true,\n className,\n ...props\n}: BadgeProps) => {\n return (\n \n {children}\n \n )\n}\nexport { Badge, badgeIntents, badgeStyles }\nexport type { BadgeProps }\n", "type": "registry:ui" } ], diff --git a/apps/preskok/public/r/calendar.json b/apps/preskok/public/r/calendar.json index 547a6c585..134fe780e 100644 --- a/apps/preskok/public/r/calendar.json +++ b/apps/preskok/public/r/calendar.json @@ -4,8 +4,8 @@ "description": "A calendar component with single and range selection support", "dependencies": [ "@internationalized/date", - "@react-aria/i18n", "lucide-react", + "react-aria", "react-aria-components", "tailwind-merge" ], @@ -16,7 +16,7 @@ "files": [ { "path": "registry/preskok/ui/preskok-ui/calendar.tsx", - "content": "\"use client\"\n\nimport { use } from \"react\"\nimport {\n getLocalTimeZone,\n today,\n type CalendarDate,\n} from \"@internationalized/date\"\nimport { useDateFormatter } from \"@react-aria/i18n\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\nimport type {\n CalendarProps as CalendarPrimitiveProps,\n CalendarState,\n DateValue,\n} from \"react-aria-components/Calendar\"\nimport {\n CalendarCell,\n CalendarGrid,\n CalendarGridBody,\n CalendarGridHeader as CalendarGridHeaderPrimitive,\n CalendarHeaderCell,\n Calendar as CalendarPrimitive,\n CalendarStateContext,\n Heading,\n} from \"react-aria-components/Calendar\"\nimport { composeRenderProps } from \"react-aria-components/composeRenderProps\"\nimport { useLocale } from \"react-aria-components/I18nProvider\"\nimport {\n RangeCalendarStateContext,\n type RangeCalendarState,\n} from \"react-aria-components/RangeCalendar\"\nimport { twMerge } from \"tailwind-merge\"\n\nimport { Button } from \"./button\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n} from \"./select\"\n\ntype CalendarSelectionMode = \"single\" | \"multiple\"\ntype CalendarHeaderState =\n | CalendarState\n | RangeCalendarState\n\ninterface CalendarProps extends Omit<\n CalendarPrimitiveProps,\n \"visibleDuration\"\n> {\n className?: string\n}\n\nconst Calendar = ({\n className,\n ...props\n}: CalendarProps) => {\n const now = today(getLocalTimeZone())\n\n return (\n \n \n \n \n \n {(date) => (\n \n twMerge(\n \"text-foreground hover:bg-secondary-foreground/15 relative flex size-11 cursor-default items-center justify-center rounded-lg tabular-nums outline-hidden sm:size-9 sm:text-sm/6 forced-colors:text-[ButtonText] forced-colors:outline-0\",\n isSelected &&\n \"bg-primary pressed:bg-primary text-primary-foreground hover:bg-primary/90 data-invalid:bg-destructive data-invalid:text-destructive-foreground forced-colors:bg-[Highlight] forced-colors:text-[Highlight] forced-colors:data-invalid:bg-[Mark]\",\n isDisabled &&\n \"text-muted-foreground forced-colors:text-[GrayText]\",\n date.compare(now) === 0 &&\n \"after:bg-primary selected:after:bg-primary-foreground focus-visible:after:bg-primary-foreground after:pointer-events-none after:absolute after:start-1/2 after:bottom-1 after:z-10 after:size-[3px] after:-translate-x-1/2 after:rounded-full\",\n className\n )\n )}\n >\n {({ formattedDate, isFocusVisible }) => (\n \n {formattedDate}\n \n )}\n \n )}\n \n \n \n )\n}\n\nconst CalendarHeader = ({\n isRange,\n className,\n ...props\n}: React.ComponentProps<\"header\"> & { isRange?: boolean }) => {\n const { direction } = useLocale()\n const calendarState = use(CalendarStateContext)\n const rangeState = use(RangeCalendarStateContext)\n const state = (calendarState ?? rangeState) as CalendarHeaderState\n const monthFormatter = useDateFormatter({\n month: \"long\",\n timeZone: state.timeZone,\n })\n const monthYearFormatter = useDateFormatter({\n month: \"long\",\n year: \"numeric\",\n timeZone: state.timeZone,\n })\n const headingText = getCalendarHeadingText({\n monthFormatter,\n monthYearFormatter,\n state,\n })\n\n return (\n \n {!isRange && (\n
\n \n \n
\n )}\n \n {headingText}\n \n
\n \n {direction === \"rtl\" ? (\n \n ) : (\n \n )}\n \n \n {direction === \"rtl\" ? (\n \n ) : (\n \n )}\n \n
\n \n )\n}\n\nfunction getCalendarHeadingText({\n monthFormatter,\n monthYearFormatter,\n state,\n}: {\n monthFormatter: Intl.DateTimeFormat\n monthYearFormatter: Intl.DateTimeFormat\n state: CalendarHeaderState\n}) {\n const start = state.visibleRange.start\n const end = state.visibleRange.end\n const startDate = start.toDate(state.timeZone)\n const endDate = end.toDate(state.timeZone)\n\n if (start.year !== end.year) {\n return `${monthYearFormatter.format(startDate)} - ${monthYearFormatter.format(endDate)}`\n }\n\n if (start.month !== end.month) {\n return `${monthFormatter.format(startDate)} - ${monthYearFormatter.format(endDate)}`\n }\n\n return monthYearFormatter.format(startDate)\n}\n\nconst SelectMonth = ({\n state,\n}: {\n state: CalendarState\n}) => {\n const months = []\n\n const formatter = useDateFormatter({\n month: \"long\",\n timeZone: state.timeZone,\n })\n\n const numMonths = state.focusedDate.calendar.getMonthsInYear(\n state.focusedDate\n )\n for (let i = 1; i <= numMonths; i++) {\n const date = state.focusedDate.set({ month: i })\n months.push(formatter.format(date.toDate(state.timeZone)))\n }\n return (\n {\n state.setFocusedDate(state.focusedDate.set({ month: Number(value) }))\n }}\n >\n \n \n {months.map((month, index) => (\n \n {month}\n \n ))}\n \n \n )\n}\n\nconst SelectYear = ({\n state,\n}: {\n state: CalendarState\n}) => {\n const years: { value: CalendarDate; formatted: string }[] = []\n const formatter = useDateFormatter({\n year: \"numeric\",\n timeZone: state.timeZone,\n })\n\n for (let i = -20; i <= 20; i++) {\n const date = state.focusedDate.add({ years: i })\n years.push({\n value: date,\n formatted: formatter.format(date.toDate(state.timeZone)),\n })\n }\n return (\n {\n state.setFocusedDate(years[Number(value)]?.value as CalendarDate)\n }}\n >\n \n \n {years.map((year, i) => (\n \n {year.formatted}\n \n ))}\n \n \n )\n}\n\nconst CalendarGridHeader = () => {\n return (\n \n {(day) => (\n \n {day}\n \n )}\n \n )\n}\n\nexport { Calendar, CalendarGridHeader, CalendarHeader, SelectMonth, SelectYear }\nexport type { CalendarProps }\n", + "content": "\"use client\"\n\nimport { use } from \"react\"\nimport {\n getLocalTimeZone,\n today,\n type CalendarDate,\n} from \"@internationalized/date\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\nimport { useDateFormatter } from \"react-aria/useDateFormatter\"\nimport type {\n CalendarProps as CalendarPrimitiveProps,\n CalendarState,\n DateValue,\n} from \"react-aria-components/Calendar\"\nimport {\n CalendarCell,\n CalendarGrid,\n CalendarGridBody,\n CalendarGridHeader as CalendarGridHeaderPrimitive,\n CalendarHeaderCell,\n Calendar as CalendarPrimitive,\n CalendarStateContext,\n Heading,\n} from \"react-aria-components/Calendar\"\nimport { composeRenderProps } from \"react-aria-components/composeRenderProps\"\nimport { useLocale } from \"react-aria-components/I18nProvider\"\nimport {\n RangeCalendarStateContext,\n type RangeCalendarState,\n} from \"react-aria-components/RangeCalendar\"\nimport { twMerge } from \"tailwind-merge\"\n\nimport { Button } from \"./button\"\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n} from \"./select\"\n\ntype CalendarSelectionMode = \"single\" | \"multiple\"\ntype CalendarHeaderState =\n | CalendarState\n | RangeCalendarState\n\ninterface CalendarProps extends Omit<\n CalendarPrimitiveProps,\n \"visibleDuration\"\n> {\n className?: string\n}\n\nconst Calendar = ({\n className,\n ...props\n}: CalendarProps) => {\n const now = today(getLocalTimeZone())\n\n return (\n \n \n \n \n \n {(date) => (\n \n twMerge(\n \"text-foreground hover:bg-secondary-foreground/15 relative flex size-11 cursor-default items-center justify-center rounded-lg tabular-nums outline-hidden sm:size-9 sm:text-sm/6 forced-colors:text-[ButtonText] forced-colors:outline-0\",\n isSelected &&\n \"bg-primary pressed:bg-primary text-primary-foreground hover:bg-primary/90 data-invalid:bg-destructive data-invalid:text-destructive-foreground forced-colors:bg-[Highlight] forced-colors:text-[Highlight] forced-colors:data-invalid:bg-[Mark]\",\n isDisabled &&\n \"text-muted-foreground forced-colors:text-[GrayText]\",\n date.compare(now) === 0 &&\n \"after:bg-primary selected:after:bg-primary-foreground focus-visible:after:bg-primary-foreground after:pointer-events-none after:absolute after:start-1/2 after:bottom-1 after:z-10 after:size-[3px] after:-translate-x-1/2 after:rounded-full\",\n className\n )\n )}\n >\n {({ formattedDate, isFocusVisible }) => (\n \n {formattedDate}\n \n )}\n \n )}\n \n \n \n )\n}\n\nconst CalendarHeader = ({\n isRange,\n className,\n ...props\n}: React.ComponentProps<\"header\"> & { isRange?: boolean }) => {\n const { direction } = useLocale()\n const calendarState = use(CalendarStateContext)\n const rangeState = use(RangeCalendarStateContext)\n const state = (calendarState ?? rangeState) as CalendarHeaderState\n const monthFormatter = useDateFormatter({\n month: \"long\",\n timeZone: state.timeZone,\n })\n const monthYearFormatter = useDateFormatter({\n month: \"long\",\n year: \"numeric\",\n timeZone: state.timeZone,\n })\n const headingText = getCalendarHeadingText({\n monthFormatter,\n monthYearFormatter,\n state,\n })\n\n return (\n \n {!isRange && (\n
\n \n \n
\n )}\n \n {headingText}\n \n
\n \n {direction === \"rtl\" ? (\n \n ) : (\n \n )}\n \n \n {direction === \"rtl\" ? (\n \n ) : (\n \n )}\n \n
\n \n )\n}\n\nfunction getCalendarHeadingText({\n monthFormatter,\n monthYearFormatter,\n state,\n}: {\n monthFormatter: Intl.DateTimeFormat\n monthYearFormatter: Intl.DateTimeFormat\n state: CalendarHeaderState\n}) {\n const start = state.visibleRange.start\n const end = state.visibleRange.end\n const startDate = start.toDate(state.timeZone)\n const endDate = end.toDate(state.timeZone)\n\n if (start.year !== end.year) {\n return `${monthYearFormatter.format(startDate)} - ${monthYearFormatter.format(endDate)}`\n }\n\n if (start.month !== end.month) {\n return `${monthFormatter.format(startDate)} - ${monthYearFormatter.format(endDate)}`\n }\n\n return monthYearFormatter.format(startDate)\n}\n\nconst SelectMonth = ({\n state,\n}: {\n state: CalendarState\n}) => {\n const months = []\n\n const formatter = useDateFormatter({\n month: \"long\",\n timeZone: state.timeZone,\n })\n\n const numMonths = state.focusedDate.calendar.getMonthsInYear(\n state.focusedDate\n )\n for (let i = 1; i <= numMonths; i++) {\n const date = state.focusedDate.set({ month: i })\n months.push(formatter.format(date.toDate(state.timeZone)))\n }\n return (\n {\n state.setFocusedDate(state.focusedDate.set({ month: Number(value) }))\n }}\n >\n \n \n {months.map((month, index) => (\n \n {month}\n \n ))}\n \n \n )\n}\n\nconst SelectYear = ({\n state,\n}: {\n state: CalendarState\n}) => {\n const years: { value: CalendarDate; formatted: string }[] = []\n const formatter = useDateFormatter({\n year: \"numeric\",\n timeZone: state.timeZone,\n })\n\n for (let i = -20; i <= 20; i++) {\n const date = state.focusedDate.add({ years: i })\n years.push({\n value: date,\n formatted: formatter.format(date.toDate(state.timeZone)),\n })\n }\n return (\n {\n state.setFocusedDate(years[Number(value)]?.value as CalendarDate)\n }}\n >\n \n \n {years.map((year, i) => (\n \n {year.formatted}\n \n ))}\n \n \n )\n}\n\nconst CalendarGridHeader = () => {\n return (\n \n {(day) => (\n \n {day}\n \n )}\n \n )\n}\n\nexport { Calendar, CalendarGridHeader, CalendarHeader, SelectMonth, SelectYear }\nexport type { CalendarProps }\n", "type": "registry:ui" } ], diff --git a/apps/preskok/public/r/color-field-preskok-demo.json b/apps/preskok/public/r/color-field-preskok-demo.json index 268c6f6db..36febe7f2 100644 --- a/apps/preskok/public/r/color-field-preskok-demo.json +++ b/apps/preskok/public/r/color-field-preskok-demo.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/preskok/examples/color-field-preskok-demo.tsx", - "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor, type Color } from \"@react-stately/color\"\n\nimport { ColorField } from \"@/components/ui/preskok-ui/color-field\"\nimport { Label } from \"@/components/ui/preskok-ui/field\"\nimport { Input } from \"@/components/ui/preskok-ui/input\"\n\nexport default function ColorFieldPreskokDemo() {\n const [color, setColor] = useState(parseColor(\"#1d4ed8\"))\n\n function handleColorChange(value: Color | null) {\n if (value) {\n setColor(value)\n }\n }\n\n return (\n
\n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n

\n Current value: {color.toString(\"hex\")}\n

\n
\n )\n}\n", + "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor, type Color } from \"react-stately/Color\"\n\nimport { ColorField } from \"@/components/ui/preskok-ui/color-field\"\nimport { Label } from \"@/components/ui/preskok-ui/field\"\nimport { Input } from \"@/components/ui/preskok-ui/input\"\n\nexport default function ColorFieldPreskokDemo() {\n const [color, setColor] = useState(parseColor(\"#1d4ed8\"))\n\n function handleColorChange(value: Color | null) {\n if (value) {\n setColor(value)\n }\n }\n\n return (\n
\n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n

\n Current value: {color.toString(\"hex\")}\n

\n
\n )\n}\n", "type": "registry:example" } ], diff --git a/apps/preskok/public/r/color-picker-preskok-demo.json b/apps/preskok/public/r/color-picker-preskok-demo.json index 7d5d1a2c9..bfd31144d 100644 --- a/apps/preskok/public/r/color-picker-preskok-demo.json +++ b/apps/preskok/public/r/color-picker-preskok-demo.json @@ -7,7 +7,7 @@ "files": [ { "path": "registry/preskok/examples/color-picker-preskok-demo.tsx", - "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor } from \"@react-stately/color\"\n\nimport { ColorPicker } from \"@/components/ui/preskok-ui/color-picker\"\n\nexport default function ColorPickerPreskokDemo() {\n const [color, setColor] = useState(parseColor(\"hsl(216, 98%, 52%)\"))\n\n return (\n
\n \n \n
\n )\n}\n", + "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor } from \"react-stately/Color\"\n\nimport { ColorPicker } from \"@/components/ui/preskok-ui/color-picker\"\n\nexport default function ColorPickerPreskokDemo() {\n const [color, setColor] = useState(parseColor(\"hsl(216, 98%, 52%)\"))\n\n return (\n
\n \n \n
\n )\n}\n", "type": "registry:example" } ], diff --git a/apps/preskok/public/r/color-picker.json b/apps/preskok/public/r/color-picker.json index 5cc5b477a..4b948c483 100644 --- a/apps/preskok/public/r/color-picker.json +++ b/apps/preskok/public/r/color-picker.json @@ -3,9 +3,9 @@ "name": "color-picker", "description": "A comprehensive color picker with multiple input methods", "dependencies": [ - "@react-stately/color", "lucide-react", "react-aria-components", + "react-stately", "tailwind-merge" ], "registryDependencies": [ @@ -20,7 +20,7 @@ "files": [ { "path": "registry/preskok/ui/preskok-ui/color-picker.tsx", - "content": "\"use client\"\n\nimport React, { use } from \"react\"\nimport { parseColor } from \"@react-stately/color\"\nimport { PipetteIcon } from \"lucide-react\"\nimport {\n ColorPicker as ColorPickerPrimitive,\n ColorPickerStateContext,\n type ColorPickerProps as ColorPickerPrimitiveProps,\n} from \"react-aria-components/ColorPicker\"\nimport { twJoin, twMerge } from \"tailwind-merge\"\n\nimport { Button } from \"./button\"\nimport { ColorArea } from \"./color-area\"\nimport { ColorField } from \"./color-field\"\nimport { ColorSlider } from \"./color-slider\"\nimport { ColorSwatch } from \"./color-swatch\"\nimport { Description } from \"./field\"\nimport { Popover, PopoverContent, type PopoverContentProps } from \"./popover\"\n\ninterface ColorPickerProps\n extends\n Omit,\n Pick {\n label?: string\n className?: string\n children?: React.ReactNode\n showArrow?: boolean\n isDisabled?: boolean\n description?: string\n eyeDropper?: boolean\n}\n\nconst ColorPicker = ({\n showArrow = false,\n placement = \"bottom start\",\n label,\n isDisabled,\n children,\n description,\n eyeDropper,\n className,\n ...props\n}: ColorPickerProps) => {\n return (\n
\n \n \n \n \n {label && label}\n \n \n
\n {children || (\n <>\n \n \n
\n {eyeDropper && }\n \n
\n \n )}\n
\n \n
\n
\n {description && {description}}\n
\n )\n}\n\ndeclare global {\n interface Window {\n EyeDropper?: new () => { open: () => Promise<{ sRGBHex: string }> }\n }\n}\n\nconst EyeDropper = () => {\n const state = use(ColorPickerStateContext)!\n\n if (!window.EyeDropper) {\n return \"EyeDropper is not supported in your browser.\"\n }\n\n return (\n {\n const eyeDropper = window.EyeDropper ? new window.EyeDropper() : null\n await eyeDropper?.open().then((result) => {\n state.setColor(parseColor(result.sRGBHex))\n })\n }}\n >\n \n \n )\n}\n\nexport { ColorPicker, EyeDropper }\nexport type { ColorPickerProps }\n", + "content": "\"use client\"\n\nimport React, { use } from \"react\"\nimport { PipetteIcon } from \"lucide-react\"\nimport {\n ColorPicker as ColorPickerPrimitive,\n ColorPickerStateContext,\n type ColorPickerProps as ColorPickerPrimitiveProps,\n} from \"react-aria-components/ColorPicker\"\nimport { parseColor } from \"react-stately/Color\"\nimport { twJoin, twMerge } from \"tailwind-merge\"\n\nimport { Button } from \"./button\"\nimport { ColorArea } from \"./color-area\"\nimport { ColorField } from \"./color-field\"\nimport { ColorSlider } from \"./color-slider\"\nimport { ColorSwatch } from \"./color-swatch\"\nimport { Description } from \"./field\"\nimport { Popover, PopoverContent, type PopoverContentProps } from \"./popover\"\n\ninterface ColorPickerProps\n extends\n Omit,\n Pick {\n label?: string\n className?: string\n children?: React.ReactNode\n showArrow?: boolean\n isDisabled?: boolean\n description?: string\n eyeDropper?: boolean\n}\n\nconst ColorPicker = ({\n showArrow = false,\n placement = \"bottom start\",\n label,\n isDisabled,\n children,\n description,\n eyeDropper,\n className,\n ...props\n}: ColorPickerProps) => {\n return (\n
\n \n \n \n \n {label && label}\n \n \n
\n {children || (\n <>\n \n \n
\n {eyeDropper && }\n \n
\n \n )}\n
\n \n
\n
\n {description && {description}}\n
\n )\n}\n\ndeclare global {\n interface Window {\n EyeDropper?: new () => { open: () => Promise<{ sRGBHex: string }> }\n }\n}\n\nconst EyeDropper = () => {\n const state = use(ColorPickerStateContext)!\n\n if (!window.EyeDropper) {\n return \"EyeDropper is not supported in your browser.\"\n }\n\n return (\n {\n const eyeDropper = window.EyeDropper ? new window.EyeDropper() : null\n await eyeDropper?.open().then((result) => {\n state.setColor(parseColor(result.sRGBHex))\n })\n }}\n >\n \n \n )\n}\n\nexport { ColorPicker, EyeDropper }\nexport type { ColorPickerProps }\n", "type": "registry:ui" } ], diff --git a/apps/preskok/public/r/color-swatch-picker-preskok-demo.json b/apps/preskok/public/r/color-swatch-picker-preskok-demo.json index 1c24dfb7d..27f0c4d60 100644 --- a/apps/preskok/public/r/color-swatch-picker-preskok-demo.json +++ b/apps/preskok/public/r/color-swatch-picker-preskok-demo.json @@ -8,7 +8,7 @@ "files": [ { "path": "registry/preskok/examples/color-swatch-picker-preskok-demo.tsx", - "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor } from \"@react-stately/color\"\n\nimport { ColorSwatch } from \"@/components/ui/preskok-ui/color-swatch\"\nimport {\n ColorSwatchPicker,\n ColorSwatchPickerItem,\n} from \"@/components/ui/preskok-ui/color-swatch-picker\"\n\nexport default function ColorSwatchPreskokDemo() {\n const [value, setValue] = useState(() => parseColor(\"#2563eb\"))\n\n return (\n
\n \n {colors.map((color) => (\n \n \n \n ))}\n \n

\n Selected: {value.toString(\"hex\")}\n

\n
\n )\n}\n\nconst colors = [\n { value: \"#ffffff\" },\n { value: \"#111827\" },\n { value: \"#2563eb\" },\n { value: \"#16a34a\" },\n { value: \"#f59e0b\" },\n { value: \"#dc2626\" },\n { value: \"#9333ea\", isDisabled: true },\n]\n", + "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { parseColor } from \"react-stately/Color\"\n\nimport { ColorSwatch } from \"@/components/ui/preskok-ui/color-swatch\"\nimport {\n ColorSwatchPicker,\n ColorSwatchPickerItem,\n} from \"@/components/ui/preskok-ui/color-swatch-picker\"\n\nexport default function ColorSwatchPreskokDemo() {\n const [value, setValue] = useState(() => parseColor(\"#2563eb\"))\n\n return (\n
\n \n {colors.map((color) => (\n \n \n \n ))}\n \n

\n Selected: {value.toString(\"hex\")}\n

\n
\n )\n}\n\nconst colors = [\n { value: \"#ffffff\" },\n { value: \"#111827\" },\n { value: \"#2563eb\" },\n { value: \"#16a34a\" },\n { value: \"#f59e0b\" },\n { value: \"#dc2626\" },\n { value: \"#9333ea\", isDisabled: true },\n]\n", "type": "registry:example" } ], diff --git a/apps/preskok/public/r/file-trigger.json b/apps/preskok/public/r/file-trigger.json index 1431cbbf7..25e58462c 100644 --- a/apps/preskok/public/r/file-trigger.json +++ b/apps/preskok/public/r/file-trigger.json @@ -14,7 +14,7 @@ "files": [ { "path": "registry/preskok/ui/preskok-ui/file-trigger.tsx", - "content": "\"use client\"\n\nimport React from \"react\"\nimport { CameraIcon, FolderIcon, PaperclipIcon } from \"lucide-react\"\nimport {\n FileTrigger as FileTriggerPrimitive,\n type FileTriggerProps as FileTriggerPrimitiveProps,\n} from \"react-aria-components/FileTrigger\"\nimport type { VariantProps } from \"tailwind-variants\"\n\nimport { Button, type buttonStyles } from \"./button\"\nimport { Loader } from \"./loader\"\n\ninterface FileTriggerProps\n extends FileTriggerPrimitiveProps, VariantProps {\n isDisabled?: boolean\n ref?: React.RefObject\n className?: string\n}\n\nconst FileTrigger = ({\n acceptDirectory,\n allowsMultiple,\n children,\n defaultCamera,\n intent = \"outline\",\n isDisabled,\n isPending,\n size = \"md\",\n isCircle = false,\n ref,\n className,\n ...props\n}: FileTriggerProps) => {\n const defaultLabel = getDefaultLabel({\n acceptDirectory,\n allowsMultiple,\n defaultCamera,\n })\n const label = children ?? (isCircle ? null : defaultLabel)\n\n return (\n \n \n \n {label}\n \n \n )\n}\n\nfunction FileTriggerIcon({\n acceptDirectory,\n defaultCamera,\n isPending,\n}: Pick) {\n if (isPending) {\n return \n }\n\n if (defaultCamera) {\n return \n }\n\n if (acceptDirectory) {\n return \n }\n\n return \n}\n\nfunction getDefaultLabel({\n acceptDirectory,\n allowsMultiple,\n defaultCamera,\n}: Pick<\n FileTriggerProps,\n \"acceptDirectory\" | \"allowsMultiple\" | \"defaultCamera\"\n>) {\n if (defaultCamera) {\n return \"Open camera\"\n }\n\n if (allowsMultiple) {\n return \"Browse files\"\n }\n\n if (acceptDirectory) {\n return \"Browse folder\"\n }\n\n return \"Browse file\"\n}\n\nexport { FileTrigger }\nexport type { FileTriggerProps }\n", + "content": "\"use client\"\n\nimport React from \"react\"\nimport { CameraIcon, FolderIcon, PaperclipIcon } from \"lucide-react\"\nimport {\n FileTrigger as FileTriggerPrimitive,\n type FileTriggerProps as FileTriggerPrimitiveProps,\n} from \"react-aria-components/FileTrigger\"\nimport type { VariantProps } from \"tailwind-variants\"\n\nimport { Button, type buttonStyles } from \"./button\"\n\ninterface FileTriggerProps\n extends FileTriggerPrimitiveProps, VariantProps {\n isDisabled?: boolean\n ref?: React.RefObject\n className?: string\n}\n\nconst FileTrigger = ({\n acceptDirectory,\n allowsMultiple,\n children,\n defaultCamera,\n intent = \"outline\",\n isDisabled,\n isPending,\n size = \"md\",\n isCircle = false,\n ref,\n className,\n ...props\n}: FileTriggerProps) => {\n const defaultLabel = getDefaultLabel({\n acceptDirectory,\n allowsMultiple,\n defaultCamera,\n })\n const label = children ?? (isCircle ? null : defaultLabel)\n\n return (\n \n \n {!isPending && (\n \n )}\n {label}\n \n \n )\n}\n\nfunction FileTriggerIcon({\n acceptDirectory,\n defaultCamera,\n}: Pick) {\n if (defaultCamera) {\n return \n }\n\n if (acceptDirectory) {\n return \n }\n\n return \n}\n\nfunction getDefaultLabel({\n acceptDirectory,\n allowsMultiple,\n defaultCamera,\n}: Pick<\n FileTriggerProps,\n \"acceptDirectory\" | \"allowsMultiple\" | \"defaultCamera\"\n>) {\n if (defaultCamera) {\n return \"Open camera\"\n }\n\n if (allowsMultiple) {\n return \"Browse files\"\n }\n\n if (acceptDirectory) {\n return \"Browse folder\"\n }\n\n return \"Browse file\"\n}\n\nexport { FileTrigger }\nexport type { FileTriggerProps }\n", "type": "registry:ui" } ], diff --git a/apps/preskok/public/r/keyboard-shortcuts-preskok-demo.json b/apps/preskok/public/r/keyboard-shortcuts-preskok-demo.json new file mode 100644 index 000000000..389ea03b2 --- /dev/null +++ b/apps/preskok/public/r/keyboard-shortcuts-preskok-demo.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "keyboard-shortcuts-preskok-demo", + "dependencies": [ + "react-aria" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/keyboard.json" + ], + "files": [ + { + "path": "registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx", + "content": "\"use client\"\n\nimport { useState } from \"react\"\nimport { useKeyboard } from \"react-aria/useKeyboard\"\n\nimport { Input } from \"@/components/ui/preskok-ui/input\"\nimport { Keyboard } from \"@/components/ui/preskok-ui/keyboard\"\n\nexport default function KeyboardShortcutsPreskokDemo() {\n const [message, setMessage] = useState(\"No shortcut used yet\")\n const { keyboardProps } = useKeyboard({\n shortcuts: {\n \"Mod+s\": () => setMessage(\"Draft saved\"),\n Escape: () => setMessage(\"Editing cancelled\"),\n },\n })\n\n return (\n
\n
\n \n
\n Save ⌘S\n ·\n Cancel Esc\n
\n
\n \n \n {message}\n

\n
\n )\n}\n", + "type": "registry:example" + } + ], + "type": "registry:example" +} \ No newline at end of file diff --git a/apps/preskok/public/r/menu-context-menu-preskok-demo.json b/apps/preskok/public/r/menu-context-menu-preskok-demo.json new file mode 100644 index 000000000..e95fb1b5d --- /dev/null +++ b/apps/preskok/public/r/menu-context-menu-preskok-demo.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "menu-context-menu-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/menu.json" + ], + "files": [ + { + "path": "registry/preskok/examples/menu-context-menu-preskok-demo.tsx", + "content": "\"use client\"\n\nimport {\n ArchiveIcon,\n CarFrontIcon,\n CopyIcon,\n ExternalLinkIcon,\n FolderInputIcon,\n PencilIcon,\n} from \"lucide-react\"\n\nimport { Badge } from \"@/components/ui/preskok-ui/badge\"\nimport { Button } from \"@/components/ui/preskok-ui/button\"\nimport {\n Menu,\n MenuContent,\n MenuItem,\n MenuLabel,\n MenuSeparator,\n MenuSubMenu,\n} from \"@/components/ui/preskok-ui/menu\"\n\nexport default function MenuContextMenuPreskokDemo() {\n return (\n \n \n \n \n \n 2025 Volvo EX30\n €39,900\n \n \n Single Motor Extended Range\n \n Available\n \n \n \n Right-click or long-press for actions.\n \n \n \n \n \n \n Open vehicle\n \n \n \n Edit details\n \n \n \n Duplicate\n \n \n \n \n Move to\n \n \n Available\n Reserved\n In service\n \n \n \n \n \n Archive vehicle\n \n \n \n )\n}\n", + "type": "registry:example" + } + ], + "type": "registry:example" +} \ No newline at end of file diff --git a/apps/preskok/public/r/preview-trigger-preskok-demo.json b/apps/preskok/public/r/preview-trigger-preskok-demo.json new file mode 100644 index 000000000..e2556ae75 --- /dev/null +++ b/apps/preskok/public/r/preview-trigger-preskok-demo.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "preview-trigger-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/badge.json", + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/link.json", + "https://ui-three-mu.vercel.app/r/preview-trigger.json" + ], + "files": [ + { + "path": "registry/preskok/examples/preview-trigger-preskok-demo.tsx", + "content": "\"use client\"\n\nimport { Badge } from \"@/components/ui/preskok-ui/badge\"\nimport { Button } from \"@/components/ui/preskok-ui/button\"\nimport { Link } from \"@/components/ui/preskok-ui/link\"\nimport {\n PreviewContent,\n PreviewTrigger,\n} from \"@/components/ui/preskok-ui/preview-trigger\"\n\nexport default function PreviewTriggerPreskokDemo() {\n return (\n

\n Compare{\" \"}\n \n \n 2025 Volvo EX30\n \n \n

\n
\n

Volvo EX30

\n

\n Single Motor · 2025\n

\n
\n \n
\n
\n
\n

Offer price

\n

\n €39,900\n

\n
\n Available\n
\n \n {\" \"}\n and{\" \"}\n \n \n 2024 Cupra Born\n \n \n
\n
\n

Cupra Born

\n

\n 77 kWh e-Boost · 2024\n

\n
\n \n
\n
\n
\n

Offer price

\n

\n €37,500\n

\n
\n Reserved\n
\n
\n
\n .\n

\n )\n}\n", + "type": "registry:example" + } + ], + "type": "registry:example" +} \ No newline at end of file diff --git a/apps/preskok/public/r/preview-trigger.json b/apps/preskok/public/r/preview-trigger.json new file mode 100644 index 000000000..91f02fdb2 --- /dev/null +++ b/apps/preskok/public/r/preview-trigger.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "preview-trigger", + "description": "A trigger that displays an interactive popover on hover, focus, or long press", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/popover.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/preview-trigger.tsx", + "content": "\"use client\"\n\nimport type { PreviewTriggerProps } from \"react-aria-components/PreviewTrigger\"\nimport { PreviewTrigger as PreviewTriggerPrimitive } from \"react-aria-components/PreviewTrigger\"\n\nimport { PopoverContent, type PopoverContentProps } from \"./popover\"\n\nconst PreviewTrigger = (props: PreviewTriggerProps) => (\n \n)\n\nconst PreviewContent = (props: PopoverContentProps) => (\n \n)\n\nexport { PreviewContent, PreviewTrigger }\nexport type { PopoverContentProps as PreviewContentProps, PreviewTriggerProps }\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/preskok/public/r/registry.json b/apps/preskok/public/r/registry.json index f8ad7a685..bae80afae 100644 --- a/apps/preskok/public/r/registry.json +++ b/apps/preskok/public/r/registry.json @@ -532,6 +532,23 @@ ], "type": "registry:ui" }, + { + "name": "preview-trigger", + "description": "A trigger that displays an interactive popover on hover, focus, or long press", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/popover.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/preview-trigger.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, { "name": "tooltip", "description": "A tooltip component with arrow and multiple styling options", @@ -1114,8 +1131,8 @@ "description": "A calendar component with single and range selection support", "dependencies": [ "@internationalized/date", - "@react-aria/i18n", "lucide-react", + "react-aria", "react-aria-components", "tailwind-merge" ], @@ -1435,6 +1452,24 @@ ], "type": "registry:ui" }, + { + "name": "token-field", + "description": "A text field that supports editable inline tokens", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/field.json", + "https://ui-three-mu.vercel.app/r/primitive.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/token-field.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, { "name": "toggle", "description": "A toggle button component with multiple variants", @@ -1935,9 +1970,9 @@ "name": "color-picker", "description": "A comprehensive color picker with multiple input methods", "dependencies": [ - "@react-stately/color", "lucide-react", "react-aria-components", + "react-stately", "tailwind-merge" ], "registryDependencies": [ @@ -2416,6 +2451,19 @@ ], "type": "registry:example" }, + { + "name": "token-field-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/token-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/token-field-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "sidebar-preskok-demo", "registryDependencies": [ @@ -2801,6 +2849,23 @@ ], "type": "registry:example" }, + { + "name": "keyboard-shortcuts-preskok-demo", + "dependencies": [ + "react-aria" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/keyboard.json" + ], + "files": [ + { + "path": "registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "line-chart-preskok-demo", "registryDependencies": [ @@ -3794,6 +3859,21 @@ ], "type": "registry:example" }, + { + "name": "table-interactive-cells-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/table.json", + "https://ui-three-mu.vercel.app/r/text-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/table-interactive-cells-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "tabs-demo", "registryDependencies": [ @@ -3860,6 +3940,22 @@ ], "type": "registry:example" }, + { + "name": "preview-trigger-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/badge.json", + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/link.json", + "https://ui-three-mu.vercel.app/r/preview-trigger.json" + ], + "files": [ + { + "path": "registry/preskok/examples/preview-trigger-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "tooltip-demo", "registryDependencies": [ @@ -3987,6 +4083,20 @@ ], "type": "registry:example" }, + { + "name": "menu-context-menu-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/menu.json" + ], + "files": [ + { + "path": "registry/preskok/examples/menu-context-menu-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "menu-description-demo", "registryDependencies": [ diff --git a/apps/preskok/public/r/table-interactive-cells-preskok-demo.json b/apps/preskok/public/r/table-interactive-cells-preskok-demo.json new file mode 100644 index 000000000..d93bbd024 --- /dev/null +++ b/apps/preskok/public/r/table-interactive-cells-preskok-demo.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "table-interactive-cells-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/table.json", + "https://ui-three-mu.vercel.app/r/text-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/table-interactive-cells-preskok-demo.tsx", + "content": "\"use client\"\n\nimport { Input } from \"@/components/ui/preskok-ui/input\"\nimport {\n Table,\n TableBody,\n TableCell,\n TableColumn,\n TableHeader,\n TableRow,\n} from \"@/components/ui/preskok-ui/table\"\nimport { TextField } from \"@/components/ui/preskok-ui/text-field\"\n\nconst vehicles = [\n { id: 1, vehicle: \"Volvo EX30\", stock: \"VE-204\", note: \"Demo vehicle\" },\n { id: 2, vehicle: \"BMW i4\", stock: \"BM-118\", note: \"Priority lead\" },\n { id: 3, vehicle: \"Audi Q4 e-tron\", stock: \"AU-512\", note: \"\" },\n]\n\nexport default function TableInteractiveCellsPreskokDemo() {\n return (\n
\n \n \n Vehicle\n Stock\n Internal note\n \n \n {(vehicle) => (\n \n \n {vehicle.vehicle}\n \n {vehicle.stock}\n \n \n \n \n \n \n )}\n \n \n
\n )\n}\n", + "type": "registry:example" + } + ], + "type": "registry:example" +} \ No newline at end of file diff --git a/apps/preskok/public/r/token-field-preskok-demo.json b/apps/preskok/public/r/token-field-preskok-demo.json new file mode 100644 index 000000000..85bed7217 --- /dev/null +++ b/apps/preskok/public/r/token-field-preskok-demo.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "token-field-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/token-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/token-field-preskok-demo.tsx", + "content": "\"use client\"\n\nimport {\n TokenFieldValue,\n type TokenFieldSegment,\n} from \"react-aria-components/TokenField\"\n\nimport { Token, TokenField } from \"@/components/ui/preskok-ui/token-field\"\n\nclass TokenizingFieldValue extends TokenFieldValue {\n tokenRegex: RegExp\n\n constructor(segments: Array, tokenRegex: RegExp) {\n super(segments)\n this.tokenRegex = tokenRegex\n }\n\n static tokenize(text: string, tokenRegex: RegExp) {\n const value = new this([], tokenRegex)\n return new this(value.tokenize(text), tokenRegex)\n }\n\n createFieldValue(segments: Array): this {\n const Constructor = this.constructor as new (\n segments: Array,\n tokenRegex: RegExp\n ) => this\n\n return new Constructor(segments, this.tokenRegex)\n }\n\n tokenize(text: string): Array {\n if (text.length === 0) {\n return [{ type: \"text\", text }]\n }\n\n this.tokenRegex.lastIndex = 0\n\n let match: RegExpExecArray | null = null\n let start = 0\n const segments: Array = []\n\n while ((match = this.tokenRegex.exec(text))) {\n if (match.index > start) {\n segments.push({ type: \"text\", text: text.slice(start, match.index) })\n }\n\n segments.push({ type: \"token\", text: match[0] })\n start = match.index + match[0].length\n }\n\n if (start < text.length) {\n segments.push({ type: \"text\", text: text.slice(start) })\n }\n\n return segments\n }\n}\n\nconst initialValue = TokenizingFieldValue.tokenize(\n \"Move #available vehicles to @Maja for today’s review.\",\n /(?<=\\s|^)[#@]\\S+(?=\\s)/g\n)\n\nexport default function TokenFieldPreskokDemo() {\n return (\n
\n \n {(segment) => {segment.text}}\n \n
\n )\n}\n", + "type": "registry:example" + } + ], + "type": "registry:example" +} \ No newline at end of file diff --git a/apps/preskok/public/r/token-field.json b/apps/preskok/public/r/token-field.json new file mode 100644 index 000000000..2e7bd36ac --- /dev/null +++ b/apps/preskok/public/r/token-field.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://ui.shadcn.com/schema/registry-item.json", + "name": "token-field", + "description": "A text field that supports editable inline tokens", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/field.json", + "https://ui-three-mu.vercel.app/r/primitive.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/token-field.tsx", + "content": "\"use client\"\n\nimport type {\n TokenFieldProps as TokenFieldPrimitiveProps,\n TokenFieldValue,\n TokenInputProps,\n TokenProps,\n} from \"react-aria-components/TokenField\"\nimport {\n TokenField as TokenFieldPrimitive,\n TokenInput as TokenInputPrimitive,\n Token as TokenPrimitive,\n} from \"react-aria-components/TokenField\"\n\nimport { cx } from \"@/lib/primitive\"\n\nimport { Description, fieldStyles, Label } from \"./field\"\n\ninterface TokenFieldProps<\n T extends TokenFieldValue = TokenFieldValue,\n> extends Omit, \"children\"> {\n children: TokenInputProps[\"children\"]\n description?: React.ReactNode\n inputClassName?: string\n inputRef?: React.Ref\n label?: React.ReactNode\n placeholder?: string\n}\n\nconst TokenField = ({\n children,\n className,\n description,\n inputClassName,\n inputRef,\n label,\n placeholder,\n ...props\n}: TokenFieldProps) => {\n return (\n \n {label != null && }\n \n {children}\n \n {description != null && {description}}\n \n )\n}\n\nconst Token = ({ className, ...props }: TokenProps) => (\n \n)\n\nexport { Token, TokenField }\nexport type { TokenFieldProps, TokenProps }\n", + "type": "registry:ui" + } + ], + "type": "registry:ui" +} \ No newline at end of file diff --git a/apps/preskok/registry.json b/apps/preskok/registry.json index f8ad7a685..bae80afae 100644 --- a/apps/preskok/registry.json +++ b/apps/preskok/registry.json @@ -532,6 +532,23 @@ ], "type": "registry:ui" }, + { + "name": "preview-trigger", + "description": "A trigger that displays an interactive popover on hover, focus, or long press", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/popover.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/preview-trigger.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, { "name": "tooltip", "description": "A tooltip component with arrow and multiple styling options", @@ -1114,8 +1131,8 @@ "description": "A calendar component with single and range selection support", "dependencies": [ "@internationalized/date", - "@react-aria/i18n", "lucide-react", + "react-aria", "react-aria-components", "tailwind-merge" ], @@ -1435,6 +1452,24 @@ ], "type": "registry:ui" }, + { + "name": "token-field", + "description": "A text field that supports editable inline tokens", + "dependencies": [ + "react-aria-components@^1.20.0" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/field.json", + "https://ui-three-mu.vercel.app/r/primitive.json" + ], + "files": [ + { + "path": "registry/preskok/ui/preskok-ui/token-field.tsx", + "type": "registry:ui" + } + ], + "type": "registry:ui" + }, { "name": "toggle", "description": "A toggle button component with multiple variants", @@ -1935,9 +1970,9 @@ "name": "color-picker", "description": "A comprehensive color picker with multiple input methods", "dependencies": [ - "@react-stately/color", "lucide-react", "react-aria-components", + "react-stately", "tailwind-merge" ], "registryDependencies": [ @@ -2416,6 +2451,19 @@ ], "type": "registry:example" }, + { + "name": "token-field-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/token-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/token-field-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "sidebar-preskok-demo", "registryDependencies": [ @@ -2801,6 +2849,23 @@ ], "type": "registry:example" }, + { + "name": "keyboard-shortcuts-preskok-demo", + "dependencies": [ + "react-aria" + ], + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/keyboard.json" + ], + "files": [ + { + "path": "registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "line-chart-preskok-demo", "registryDependencies": [ @@ -3794,6 +3859,21 @@ ], "type": "registry:example" }, + { + "name": "table-interactive-cells-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/input.json", + "https://ui-three-mu.vercel.app/r/table.json", + "https://ui-three-mu.vercel.app/r/text-field.json" + ], + "files": [ + { + "path": "registry/preskok/examples/table-interactive-cells-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "tabs-demo", "registryDependencies": [ @@ -3860,6 +3940,22 @@ ], "type": "registry:example" }, + { + "name": "preview-trigger-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/badge.json", + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/link.json", + "https://ui-three-mu.vercel.app/r/preview-trigger.json" + ], + "files": [ + { + "path": "registry/preskok/examples/preview-trigger-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "tooltip-demo", "registryDependencies": [ @@ -3987,6 +4083,20 @@ ], "type": "registry:example" }, + { + "name": "menu-context-menu-preskok-demo", + "registryDependencies": [ + "https://ui-three-mu.vercel.app/r/button.json", + "https://ui-three-mu.vercel.app/r/menu.json" + ], + "files": [ + { + "path": "registry/preskok/examples/menu-context-menu-preskok-demo.tsx", + "type": "registry:example" + } + ], + "type": "registry:example" + }, { "name": "menu-description-demo", "registryDependencies": [ diff --git a/apps/preskok/registry/__index__.tsx b/apps/preskok/registry/__index__.tsx index 85f164153..945fc5c2d 100644 --- a/apps/preskok/registry/__index__.tsx +++ b/apps/preskok/registry/__index__.tsx @@ -304,6 +304,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "preview-trigger": { + name: "preview-trigger", + description: "A trigger that displays an interactive popover on hover, focus, or long press", + type: "registry:ui", + registryDependencies: ["popover"], + files: [{ + path: "registry/preskok/ui/preskok-ui/preview-trigger.tsx", + type: "registry:ui", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/ui/preskok-ui/preview-trigger.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "tooltip": { name: "tooltip", description: "A tooltip component with arrow and multiple styling options", @@ -1136,6 +1154,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "token-field": { + name: "token-field", + description: "A text field that supports editable inline tokens", + type: "registry:ui", + registryDependencies: ["field","primitive"], + files: [{ + path: "registry/preskok/ui/preskok-ui/token-field.tsx", + type: "registry:ui", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/ui/preskok-ui/token-field.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "toggle": { name: "toggle", description: "A toggle button component with multiple variants", @@ -2002,6 +2038,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "token-field-preskok-demo": { + name: "token-field-preskok-demo", + description: "", + type: "registry:example", + registryDependencies: ["token-field"], + files: [{ + path: "registry/preskok/examples/token-field-preskok-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/examples/token-field-preskok-demo.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "sidebar-preskok-demo": { name: "sidebar-preskok-demo", description: "", @@ -2464,6 +2518,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "keyboard-shortcuts-preskok-demo": { + name: "keyboard-shortcuts-preskok-demo", + description: "", + type: "registry:example", + registryDependencies: ["input","keyboard"], + files: [{ + path: "registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "line-chart-preskok-demo": { name: "line-chart-preskok-demo", description: "", @@ -3742,6 +3814,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "table-interactive-cells-preskok-demo": { + name: "table-interactive-cells-preskok-demo", + description: "", + type: "registry:example", + registryDependencies: ["input","table","text-field"], + files: [{ + path: "registry/preskok/examples/table-interactive-cells-preskok-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/examples/table-interactive-cells-preskok-demo.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "tabs-demo": { name: "tabs-demo", description: "", @@ -3832,6 +3922,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "preview-trigger-preskok-demo": { + name: "preview-trigger-preskok-demo", + description: "", + type: "registry:example", + registryDependencies: ["badge","button","link","preview-trigger"], + files: [{ + path: "registry/preskok/examples/preview-trigger-preskok-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/examples/preview-trigger-preskok-demo.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "tooltip-demo": { name: "tooltip-demo", description: "", @@ -3994,6 +4102,24 @@ import * as React from "react" categories: undefined, meta: undefined, }, + "menu-context-menu-preskok-demo": { + name: "menu-context-menu-preskok-demo", + description: "", + type: "registry:example", + registryDependencies: ["button","menu"], + files: [{ + path: "registry/preskok/examples/menu-context-menu-preskok-demo.tsx", + type: "registry:example", + target: "" + }], + component: React.lazy(async () => { + const mod = await import("@/registry/preskok/examples/menu-context-menu-preskok-demo.tsx") + const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name + return { default: mod.default || mod[exportName] } + }), + categories: undefined, + meta: undefined, + }, "menu-description-demo": { name: "menu-description-demo", description: "", diff --git a/apps/preskok/registry/preskok/examples/color-field-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/color-field-preskok-demo.tsx index 982356d26..f7478b4d3 100644 --- a/apps/preskok/registry/preskok/examples/color-field-preskok-demo.tsx +++ b/apps/preskok/registry/preskok/examples/color-field-preskok-demo.tsx @@ -1,7 +1,7 @@ "use client" import { useState } from "react" -import { parseColor, type Color } from "@react-stately/color" +import { parseColor, type Color } from "react-stately/Color" import { ColorField } from "@/registry/preskok/ui/preskok-ui/color-field" import { Label } from "@/registry/preskok/ui/preskok-ui/field" diff --git a/apps/preskok/registry/preskok/examples/color-picker-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/color-picker-preskok-demo.tsx index fa2755ea4..a10b6b0b2 100644 --- a/apps/preskok/registry/preskok/examples/color-picker-preskok-demo.tsx +++ b/apps/preskok/registry/preskok/examples/color-picker-preskok-demo.tsx @@ -1,7 +1,7 @@ "use client" import { useState } from "react" -import { parseColor } from "@react-stately/color" +import { parseColor } from "react-stately/Color" import { ColorPicker } from "@/registry/preskok/ui/preskok-ui/color-picker" diff --git a/apps/preskok/registry/preskok/examples/color-swatch-picker-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/color-swatch-picker-preskok-demo.tsx index af2322e67..b60af0f25 100644 --- a/apps/preskok/registry/preskok/examples/color-swatch-picker-preskok-demo.tsx +++ b/apps/preskok/registry/preskok/examples/color-swatch-picker-preskok-demo.tsx @@ -1,7 +1,7 @@ "use client" import { useState } from "react" -import { parseColor } from "@react-stately/color" +import { parseColor } from "react-stately/Color" import { ColorSwatch } from "@/registry/preskok/ui/preskok-ui/color-swatch" import { diff --git a/apps/preskok/registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx new file mode 100644 index 000000000..d54e09d0e --- /dev/null +++ b/apps/preskok/registry/preskok/examples/keyboard-shortcuts-preskok-demo.tsx @@ -0,0 +1,43 @@ +"use client" + +import { useState } from "react" +import { useKeyboard } from "react-aria/useKeyboard" + +import { Input } from "@/registry/preskok/ui/preskok-ui/input" +import { Keyboard } from "@/registry/preskok/ui/preskok-ui/keyboard" + +export default function KeyboardShortcutsPreskokDemo() { + const [message, setMessage] = useState("No shortcut used yet") + const { keyboardProps } = useKeyboard({ + shortcuts: { + "Mod+s": () => setMessage("Draft saved"), + Escape: () => setMessage("Editing cancelled"), + }, + }) + + return ( +
+
+ +
+ Save ⌘S + + Cancel Esc +
+
+ +

+ {message} +

+
+ ) +} diff --git a/apps/preskok/registry/preskok/examples/menu-context-menu-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/menu-context-menu-preskok-demo.tsx new file mode 100644 index 000000000..6fc578104 --- /dev/null +++ b/apps/preskok/registry/preskok/examples/menu-context-menu-preskok-demo.tsx @@ -0,0 +1,79 @@ +"use client" + +import { + ArchiveIcon, + CarFrontIcon, + CopyIcon, + ExternalLinkIcon, + FolderInputIcon, + PencilIcon, +} from "lucide-react" + +import { Badge } from "@/registry/preskok/ui/preskok-ui/badge" +import { Button } from "@/registry/preskok/ui/preskok-ui/button" +import { + Menu, + MenuContent, + MenuItem, + MenuLabel, + MenuSeparator, + MenuSubMenu, +} from "@/registry/preskok/ui/preskok-ui/menu" + +export default function MenuContextMenuPreskokDemo() { + return ( + + + + + + Open vehicle + + + + Edit details + + + + Duplicate + + + + + Move to + + + Available + Reserved + In service + + + + + + Archive vehicle + + + + ) +} diff --git a/apps/preskok/registry/preskok/examples/preview-trigger-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/preview-trigger-preskok-demo.tsx new file mode 100644 index 000000000..de357286a --- /dev/null +++ b/apps/preskok/registry/preskok/examples/preview-trigger-preskok-demo.tsx @@ -0,0 +1,79 @@ +"use client" + +import { Badge } from "@/registry/preskok/ui/preskok-ui/badge" +import { Button } from "@/registry/preskok/ui/preskok-ui/button" +import { Link } from "@/registry/preskok/ui/preskok-ui/link" +import { + PreviewContent, + PreviewTrigger, +} from "@/registry/preskok/ui/preskok-ui/preview-trigger" + +export default function PreviewTriggerPreskokDemo() { + return ( +

+ Compare{" "} + + + 2025 Volvo EX30 + + +

+
+

Volvo EX30

+

+ Single Motor · 2025 +

+
+ +
+
+
+

Offer price

+

+ €39,900 +

+
+ Available +
+ + {" "} + and{" "} + + + 2024 Cupra Born + + +
+
+

Cupra Born

+

+ 77 kWh e-Boost · 2024 +

+
+ +
+
+
+

Offer price

+

+ €37,500 +

+
+ Reserved +
+
+
+ . +

+ ) +} diff --git a/apps/preskok/registry/preskok/examples/table-interactive-cells-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/table-interactive-cells-preskok-demo.tsx new file mode 100644 index 000000000..5834e109c --- /dev/null +++ b/apps/preskok/registry/preskok/examples/table-interactive-cells-preskok-demo.tsx @@ -0,0 +1,54 @@ +"use client" + +import { Input } from "@/registry/preskok/ui/preskok-ui/input" +import { + Table, + TableBody, + TableCell, + TableColumn, + TableHeader, + TableRow, +} from "@/registry/preskok/ui/preskok-ui/table" +import { TextField } from "@/registry/preskok/ui/preskok-ui/text-field" + +const vehicles = [ + { id: 1, vehicle: "Volvo EX30", stock: "VE-204", note: "Demo vehicle" }, + { id: 2, vehicle: "BMW i4", stock: "BM-118", note: "Priority lead" }, + { id: 3, vehicle: "Audi Q4 e-tron", stock: "AU-512", note: "" }, +] + +export default function TableInteractiveCellsPreskokDemo() { + return ( +
+ + + Vehicle + Stock + Internal note + + + {(vehicle) => ( + + + {vehicle.vehicle} + + {vehicle.stock} + + + + + + + )} + +
+
+ ) +} diff --git a/apps/preskok/registry/preskok/examples/token-field-preskok-demo.tsx b/apps/preskok/registry/preskok/examples/token-field-preskok-demo.tsx new file mode 100644 index 000000000..defc42f06 --- /dev/null +++ b/apps/preskok/registry/preskok/examples/token-field-preskok-demo.tsx @@ -0,0 +1,78 @@ +"use client" + +import { + TokenFieldValue, + type TokenFieldSegment, +} from "react-aria-components/TokenField" + +import { Token, TokenField } from "@/registry/preskok/ui/preskok-ui/token-field" + +class TokenizingFieldValue extends TokenFieldValue { + tokenRegex: RegExp + + constructor(segments: Array, tokenRegex: RegExp) { + super(segments) + this.tokenRegex = tokenRegex + } + + static tokenize(text: string, tokenRegex: RegExp) { + const value = new this([], tokenRegex) + return new this(value.tokenize(text), tokenRegex) + } + + createFieldValue(segments: Array): this { + const Constructor = this.constructor as new ( + segments: Array, + tokenRegex: RegExp + ) => this + + return new Constructor(segments, this.tokenRegex) + } + + tokenize(text: string): Array { + if (text.length === 0) { + return [{ type: "text", text }] + } + + this.tokenRegex.lastIndex = 0 + + let match: RegExpExecArray | null = null + let start = 0 + const segments: Array = [] + + while ((match = this.tokenRegex.exec(text))) { + if (match.index > start) { + segments.push({ type: "text", text: text.slice(start, match.index) }) + } + + segments.push({ type: "token", text: match[0] }) + start = match.index + match[0].length + } + + if (start < text.length) { + segments.push({ type: "text", text: text.slice(start) }) + } + + return segments + } +} + +const initialValue = TokenizingFieldValue.tokenize( + "Move #available vehicles to @Maja for today’s review.", + /(?<=\s|^)[#@]\S+(?=\s)/g +) + +export default function TokenFieldPreskokDemo() { + return ( +
+ + {(segment) => {segment.text}} + +
+ ) +} diff --git a/apps/preskok/registry/preskok/ui/preskok-ui/calendar.tsx b/apps/preskok/registry/preskok/ui/preskok-ui/calendar.tsx index 573571542..df612b383 100644 --- a/apps/preskok/registry/preskok/ui/preskok-ui/calendar.tsx +++ b/apps/preskok/registry/preskok/ui/preskok-ui/calendar.tsx @@ -6,7 +6,6 @@ import { today, type CalendarDate, } from "@internationalized/date" -import { useDateFormatter } from "@react-aria/i18n" import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react" import type { CalendarProps as CalendarPrimitiveProps, @@ -29,6 +28,7 @@ import { RangeCalendarStateContext, type RangeCalendarState, } from "react-aria-components/RangeCalendar" +import { useDateFormatter } from "react-aria/useDateFormatter" import { twMerge } from "tailwind-merge" import { Button } from "./button" diff --git a/apps/preskok/registry/preskok/ui/preskok-ui/color-picker.tsx b/apps/preskok/registry/preskok/ui/preskok-ui/color-picker.tsx index 597127f9d..4e1916056 100644 --- a/apps/preskok/registry/preskok/ui/preskok-ui/color-picker.tsx +++ b/apps/preskok/registry/preskok/ui/preskok-ui/color-picker.tsx @@ -1,13 +1,13 @@ "use client" import React, { use } from "react" -import { parseColor } from "@react-stately/color" import { PipetteIcon } from "lucide-react" import { ColorPicker as ColorPickerPrimitive, ColorPickerStateContext, type ColorPickerProps as ColorPickerPrimitiveProps, } from "react-aria-components/ColorPicker" +import { parseColor } from "react-stately/Color" import { twJoin, twMerge } from "tailwind-merge" import { Button } from "./button" diff --git a/apps/preskok/registry/preskok/ui/preskok-ui/file-trigger.tsx b/apps/preskok/registry/preskok/ui/preskok-ui/file-trigger.tsx index 1dc400267..cd4da7149 100644 --- a/apps/preskok/registry/preskok/ui/preskok-ui/file-trigger.tsx +++ b/apps/preskok/registry/preskok/ui/preskok-ui/file-trigger.tsx @@ -9,7 +9,6 @@ import { import type { VariantProps } from "tailwind-variants" import { Button, type buttonStyles } from "./button" -import { Loader } from "./loader" interface FileTriggerProps extends FileTriggerPrimitiveProps, VariantProps { @@ -50,15 +49,17 @@ const FileTrigger = ({ @@ -68,12 +69,7 @@ const FileTrigger = ({ function FileTriggerIcon({ acceptDirectory, defaultCamera, - isPending, -}: Pick) { - if (isPending) { - return - } - +}: Pick) { if (defaultCamera) { return } diff --git a/apps/preskok/registry/preskok/ui/preskok-ui/preview-trigger.tsx b/apps/preskok/registry/preskok/ui/preskok-ui/preview-trigger.tsx new file mode 100644 index 000000000..947aa49a3 --- /dev/null +++ b/apps/preskok/registry/preskok/ui/preskok-ui/preview-trigger.tsx @@ -0,0 +1,17 @@ +"use client" + +import type { PreviewTriggerProps } from "react-aria-components/PreviewTrigger" +import { PreviewTrigger as PreviewTriggerPrimitive } from "react-aria-components/PreviewTrigger" + +import { PopoverContent, type PopoverContentProps } from "./popover" + +const PreviewTrigger = (props: PreviewTriggerProps) => ( + +) + +const PreviewContent = (props: PopoverContentProps) => ( + +) + +export { PreviewContent, PreviewTrigger } +export type { PopoverContentProps as PreviewContentProps, PreviewTriggerProps } diff --git a/apps/preskok/registry/preskok/ui/preskok-ui/token-field.tsx b/apps/preskok/registry/preskok/ui/preskok-ui/token-field.tsx new file mode 100644 index 000000000..6ec008ae8 --- /dev/null +++ b/apps/preskok/registry/preskok/ui/preskok-ui/token-field.tsx @@ -0,0 +1,82 @@ +"use client" + +import type { + TokenFieldProps as TokenFieldPrimitiveProps, + TokenFieldValue, + TokenInputProps, + TokenProps, +} from "react-aria-components/TokenField" +import { + TokenField as TokenFieldPrimitive, + TokenInput as TokenInputPrimitive, + Token as TokenPrimitive, +} from "react-aria-components/TokenField" + +import { cx } from "@/registry/preskok/lib/primitive" + +import { Description, fieldStyles, Label } from "./field" + +interface TokenFieldProps< + T extends TokenFieldValue = TokenFieldValue, +> extends Omit, "children"> { + children: TokenInputProps["children"] + description?: React.ReactNode + inputClassName?: string + inputRef?: React.Ref + label?: React.ReactNode + placeholder?: string +} + +const TokenField = ({ + children, + className, + description, + inputClassName, + inputRef, + label, + placeholder, + ...props +}: TokenFieldProps) => { + return ( + + {label != null && } + + {children} + + {description != null && {description}} + + ) +} + +const Token = ({ className, ...props }: TokenProps) => ( + +) + +export { Token, TokenField } +export type { TokenFieldProps, TokenProps } diff --git a/apps/preskok/registry/registry-examples.ts b/apps/preskok/registry/registry-examples.ts index 31cfab9d6..304b142dc 100644 --- a/apps/preskok/registry/registry-examples.ts +++ b/apps/preskok/registry/registry-examples.ts @@ -23,6 +23,17 @@ export const examples: Registry["items"] = [ }, ], }, + { + name: "token-field-preskok-demo", + type: "registry:example", + registryDependencies: ["token-field"], + files: [ + { + path: "examples/token-field-preskok-demo.tsx", + type: "registry:example", + }, + ], + }, { name: "sidebar-preskok-demo", type: "registry:example", @@ -332,6 +343,18 @@ export const examples: Registry["items"] = [ }, ], }, + { + name: "keyboard-shortcuts-preskok-demo", + type: "registry:example", + dependencies: ["react-aria"], + registryDependencies: ["input", "keyboard"], + files: [ + { + path: "examples/keyboard-shortcuts-preskok-demo.tsx", + type: "registry:example", + }, + ], + }, { name: "line-chart-preskok-demo", type: "registry:example", @@ -1174,6 +1197,17 @@ export const examples: Registry["items"] = [ }, ], }, + { + name: "table-interactive-cells-preskok-demo", + type: "registry:example", + registryDependencies: ["input", "table", "text-field"], + files: [ + { + path: "examples/table-interactive-cells-preskok-demo.tsx", + type: "registry:example", + }, + ], + }, { name: "tabs-demo", type: "registry:example", @@ -1229,6 +1263,17 @@ export const examples: Registry["items"] = [ }, ], }, + { + name: "preview-trigger-preskok-demo", + type: "registry:example", + registryDependencies: ["badge", "button", "link", "preview-trigger"], + files: [ + { + path: "examples/preview-trigger-preskok-demo.tsx", + type: "registry:example", + }, + ], + }, { name: "tooltip-demo", type: "registry:example", @@ -1329,6 +1374,17 @@ export const examples: Registry["items"] = [ }, ], }, + { + name: "menu-context-menu-preskok-demo", + type: "registry:example", + registryDependencies: ["button", "menu"], + files: [ + { + path: "examples/menu-context-menu-preskok-demo.tsx", + type: "registry:example", + }, + ], + }, { name: "menu-description-demo", type: "registry:example", diff --git a/apps/preskok/registry/registry-preskok.ts b/apps/preskok/registry/registry-preskok.ts index 0013d5c33..6e5d83e39 100644 --- a/apps/preskok/registry/registry-preskok.ts +++ b/apps/preskok/registry/registry-preskok.ts @@ -210,6 +210,20 @@ export const preskokUi: Registry["items"] = [ }, ], }, + { + name: "preview-trigger", + type: "registry:ui", + description: + "A trigger that displays an interactive popover on hover, focus, or long press", + dependencies: ["react-aria-components@^1.20.0"], + registryDependencies: ["popover"], + files: [ + { + path: "ui/preskok-ui/preview-trigger.tsx", + type: "registry:ui", + }, + ], + }, { name: "tooltip", type: "registry:ui", @@ -668,8 +682,8 @@ export const preskokUi: Registry["items"] = [ description: "A calendar component with single and range selection support", dependencies: [ "@internationalized/date", - "@react-aria/i18n", "lucide-react", + "react-aria", "react-aria-components", "tailwind-merge", ], @@ -964,6 +978,19 @@ export const preskokUi: Registry["items"] = [ }, ], }, + { + name: "token-field", + type: "registry:ui", + description: "A text field that supports editable inline tokens", + dependencies: ["react-aria-components@^1.20.0"], + registryDependencies: ["field", "primitive"], + files: [ + { + path: "ui/preskok-ui/token-field.tsx", + type: "registry:ui", + }, + ], + }, { name: "toggle", @@ -1370,9 +1397,9 @@ export const preskokUi: Registry["items"] = [ type: "registry:ui", description: "A comprehensive color picker with multiple input methods", dependencies: [ - "@react-stately/color", "lucide-react", "react-aria-components", + "react-stately", "tailwind-merge", ], registryDependencies: [ diff --git a/apps/preskok/source.config.ts b/apps/preskok/source.config.ts index 6ac386c00..30603345b 100644 --- a/apps/preskok/source.config.ts +++ b/apps/preskok/source.config.ts @@ -1,4 +1,6 @@ +import { pageSchema } from "fumadocs-core/source/schema" import { defineConfig, defineDocs } from "fumadocs-mdx/config" +import { z } from "zod" export default defineConfig({ mdxOptions: { @@ -22,18 +24,18 @@ export default defineConfig({ export const docs = defineDocs({ dir: "content/docs", docs: { + schema: pageSchema.extend({ + status: z.string().optional(), + // links: z + // .object({ + // doc: z.string().optional(), + // api: z.string().optional(), + // }) + // .optional(), + }), postprocess: { extractLinkReferences: true, includeProcessedMarkdown: true, }, - // TODO: Upgrade to zod 4 first - // schema: frontmatterSchema.extend({ - // links: z - // .object({ - // doc: z.string().optional(), - // api: z.string().optional(), - // }) - // .optional(), - // }), }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 372facf04..94281838c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,14 +15,8 @@ importers: apps/preskok: dependencies: '@internationalized/date': - specifier: ^3.12.2 - version: 3.12.2 - '@react-aria/i18n': - specifier: ^3.13.1 - version: 3.13.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - '@react-stately/color': - specifier: ^3.10.1 - version: 3.10.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^3.12.3 + version: 3.12.3 '@tabler/icons-react': specifier: ^3.44.0 version: 3.44.0(react@19.2.7) @@ -110,9 +104,12 @@ importers: react: specifier: 19.2.7 version: 19.2.7 + react-aria: + specifier: ^3.51.0 + version: 3.51.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-aria-components: - specifier: ^1.19.0 - version: 1.19.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^1.20.0 + version: 1.20.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-dom: specifier: 19.2.7 version: 19.2.7(react@19.2.7) @@ -123,8 +120,8 @@ importers: specifier: ^4.11.2 version: 4.11.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-stately: - specifier: ^3.48.0 - version: 3.48.0(react@19.2.7) + specifier: ^3.49.0 + version: 3.49.0(react@19.2.7) recharts: specifier: 3.9.0 version: 3.9.0(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react-is@16.13.1)(react@19.2.7)(redux@5.0.1) @@ -576,21 +573,6 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@formatjs/ecma402-abstract@2.3.6': - resolution: {integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==} - - '@formatjs/fast-memoize@2.2.7': - resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==} - - '@formatjs/icu-messageformat-parser@2.11.4': - resolution: {integrity: sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==} - - '@formatjs/icu-skeleton-parser@1.8.16': - resolution: {integrity: sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==} - - '@formatjs/intl-localematcher@0.6.2': - resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} - '@fuma-translate/react@1.0.2': resolution: {integrity: sha512-uOiOtBx3nRXR8Nu1GzBf1tApgF1FErDBTHxRIAQeyQdyOoZbrNRN6H4kDCWObY4qyGeGbHydG0DHzgeUgFDMIw==} peerDependencies: @@ -809,17 +791,14 @@ packages: cpu: [x64] os: [win32] - '@internationalized/date@3.12.2': - resolution: {integrity: sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==} - - '@internationalized/message@3.1.10': - resolution: {integrity: sha512-nc0Or6EdWHqZRcsXb6P9hBIpLsfSl/ILh0rk5h/OVBpzmhdExXtPy2cQtWsq8XKRBpRHwDNnAHt4OpolcB7dog==} + '@internationalized/date@3.12.3': + resolution: {integrity: sha512-fuLX+3ZKLsxI73y8b01EG/WjHb6gE6weCqlfawPO27kBWGMh9G1yH6Csv1uU7/cac9H2GHmOMt6CjmuQ1aia4Q==} '@internationalized/number@3.6.7': resolution: {integrity: sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==} - '@internationalized/string@3.2.9': - resolution: {integrity: sha512-kzP/M/mbQxODlmOt4bIQZ2SBVUWUSqMLXooXixnX7noche8WHaQcA+nwFN1K2KCF/cp+LDUhcJsCicwkvhD1pg==} + '@internationalized/string@3.2.10': + resolution: {integrity: sha512-PDx6//vHSpRnHfxqMqto11zQvhsaU74O3mKv2F/0eicGZcl9NLjQmGlbHz/LsJh5tLKp4A4L7ZVTzN1/MmMTvA==} '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -1293,20 +1272,8 @@ packages: '@radix-ui/rect@1.1.2': resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} - '@react-aria/i18n@3.13.1': - resolution: {integrity: sha512-z56ZYcbfpNmMyiGLhyEjytpmEfoTlBaksk84q4kds3HvNkf7QWKj+DJVfVDrJX+c1LyuBsszLSX7yxJRiHsYKQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - - '@react-stately/color@3.10.1': - resolution: {integrity: sha512-v4YlLa/oRQpPa/M9Yq1e0Bl8Z7xzGZdNDAIbfIMZuiJtacaOKriPW+AOgjjT/Ab0fNX2YDbwIYvkiMOJBnTi5A==} - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - - '@react-types/shared@3.36.0': - resolution: {integrity: sha512-DkP/H0C2YjjS7gZWKNqOmU8a16qHPjQNdzMwmTq9SzplM6Iw0kVMTZ0OIoe6FOgGqa+FwMsE2QbPjh/n3g/jXQ==} + '@react-types/shared@3.36.1': + resolution: {integrity: sha512-AzsuD9OfxTOZMMvTRhlN3oHBwOmFN7tDh27LzqmHt4+uOgPhJT7ZM7/kVs/8/o0WxayMUIk3hBmCFRHv1FUoag==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 @@ -2531,9 +2498,6 @@ packages: decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} @@ -3393,9 +3357,6 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} - intl-messageformat@10.7.18: - resolution: {integrity: sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==} - ip-address@10.2.0: resolution: {integrity: sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==} engines: {node: '>= 12'} @@ -4492,14 +4453,14 @@ packages: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} - react-aria-components@1.19.0: - resolution: {integrity: sha512-2smSS5nqJ8cGYMQezuUXveZm7eMyHCqTN6mDpylQBYLYbdF5dxCCuW1DHn1VKLe1DybSfPvX/cZtJlDmvFfn8A==} + react-aria-components@1.20.0: + resolution: {integrity: sha512-BMbpIgoV9aELeBrB0Y120NgoigHb5OdcJwc+4e7uSnbTbamea6lo+gqcc4LAxzMaK3Jf+7LI1oCDE6yANsmxIQ==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-aria@3.50.0: - resolution: {integrity: sha512-S0Os6QZk33fzUAKu1QLT9afoUaCBt1ZNdoiq0n2YMVgKIdNIQS8zxiZ8O9hYE6QyDkHKjD6q39LQZ+qaSAIgjw==} + react-aria@3.51.0: + resolution: {integrity: sha512-AyWLw0XR38cFPwBu/ErgGaVrc5dupLEKmRlMXTGvFKOtbaGRQ2+yQJkjVhpdHhoRhU4+G+tJDFeHDTS8tK3bfQ==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 @@ -4556,8 +4517,8 @@ packages: react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 - react-stately@3.48.0: - resolution: {integrity: sha512-ImicSAG+lTotAe5izcs1fz49Zk48w7pDusqYg04WaPhCoej8BJ24soMu3iLXIrsi273s4P1gZrYGrqReMfgEEA==} + react-stately@3.49.0: + resolution: {integrity: sha512-13iNq2KzBrRAzxRc+n53hgROfIistiYY/sPtIhCw1qUB7/kmo+X1xEU2uiS5zcCIrc55AUPwoHqOIIpKWSwB9A==} peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 @@ -5625,32 +5586,6 @@ snapshots: '@floating-ui/utils@0.2.11': {} - '@formatjs/ecma402-abstract@2.3.6': - dependencies: - '@formatjs/fast-memoize': 2.2.7 - '@formatjs/intl-localematcher': 0.6.2 - decimal.js: 10.6.0 - tslib: 2.8.1 - - '@formatjs/fast-memoize@2.2.7': - dependencies: - tslib: 2.8.1 - - '@formatjs/icu-messageformat-parser@2.11.4': - dependencies: - '@formatjs/ecma402-abstract': 2.3.6 - '@formatjs/icu-skeleton-parser': 1.8.16 - tslib: 2.8.1 - - '@formatjs/icu-skeleton-parser@1.8.16': - dependencies: - '@formatjs/ecma402-abstract': 2.3.6 - tslib: 2.8.1 - - '@formatjs/intl-localematcher@0.6.2': - dependencies: - tslib: 2.8.1 - '@fuma-translate/react@1.0.2(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: react: 19.2.7 @@ -5791,20 +5726,15 @@ snapshots: '@img/sharp-win32-x64@0.34.5': optional: true - '@internationalized/date@3.12.2': - dependencies: - '@swc/helpers': 0.5.23 - - '@internationalized/message@3.1.10': + '@internationalized/date@3.12.3': dependencies: '@swc/helpers': 0.5.23 - intl-messageformat: 10.7.18 '@internationalized/number@3.6.7': dependencies: '@swc/helpers': 0.5.23 - '@internationalized/string@3.2.9': + '@internationalized/string@3.2.10': dependencies: '@swc/helpers': 0.5.23 @@ -6282,24 +6212,7 @@ snapshots: '@radix-ui/rect@1.1.2': {} - '@react-aria/i18n@3.13.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@internationalized/date': 3.12.2 - '@internationalized/message': 3.1.10 - '@internationalized/string': 3.2.9 - '@swc/helpers': 0.5.23 - react: 19.2.7 - react-aria: 3.50.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - react-dom: 19.2.7(react@19.2.7) - - '@react-stately/color@3.10.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': - dependencies: - '@swc/helpers': 0.5.23 - react: 19.2.7 - react-dom: 19.2.7(react@19.2.7) - react-stately: 3.48.0(react@19.2.7) - - '@react-types/shared@3.36.0(react@19.2.7)': + '@react-types/shared@3.36.1(react@19.2.7)': dependencies: react: 19.2.7 @@ -7458,8 +7371,6 @@ snapshots: decimal.js-light@2.5.1: {} - decimal.js@10.6.0: {} - decode-named-character-reference@1.3.0: dependencies: character-entities: 2.0.2 @@ -8568,13 +8479,6 @@ snapshots: internmap@2.0.3: {} - intl-messageformat@10.7.18: - dependencies: - '@formatjs/ecma402-abstract': 2.3.6 - '@formatjs/fast-memoize': 2.2.7 - '@formatjs/icu-messageformat-parser': 2.11.4 - tslib: 2.8.1 - ip-address@10.2.0: {} ipaddr.js@1.9.1: {} @@ -9831,29 +9735,30 @@ snapshots: iconv-lite: 0.7.2 unpipe: 1.0.0 - react-aria-components@1.19.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-aria-components@1.20.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@internationalized/date': 3.12.2 - '@react-types/shared': 3.36.0(react@19.2.7) + '@internationalized/date': 3.12.3 + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.7) '@swc/helpers': 0.5.23 client-only: 0.0.1 react: 19.2.7 - react-aria: 3.50.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react-aria: 3.51.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-dom: 19.2.7(react@19.2.7) - react-stately: 3.48.0(react@19.2.7) + react-stately: 3.49.0(react@19.2.7) - react-aria@3.50.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + react-aria@3.51.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@internationalized/date': 3.12.2 + '@internationalized/date': 3.12.3 '@internationalized/number': 3.6.7 - '@internationalized/string': 3.2.9 - '@react-types/shared': 3.36.0(react@19.2.7) + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.7) '@swc/helpers': 0.5.23 aria-hidden: 1.2.6 clsx: 2.1.1 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-stately: 3.48.0(react@19.2.7) + react-stately: 3.49.0(react@19.2.7) use-sync-external-store: 1.6.0(react@19.2.7) react-dom@19.2.7(react@19.2.7): @@ -9901,12 +9806,12 @@ snapshots: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - react-stately@3.48.0(react@19.2.7): + react-stately@3.49.0(react@19.2.7): dependencies: - '@internationalized/date': 3.12.2 + '@internationalized/date': 3.12.3 '@internationalized/number': 3.6.7 - '@internationalized/string': 3.2.9 - '@react-types/shared': 3.36.0(react@19.2.7) + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.7) '@swc/helpers': 0.5.23 react: 19.2.7 use-sync-external-store: 1.6.0(react@19.2.7)