@kznlabs/labsui 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +5 -0
  2. package/dist/index.js +145 -53
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1460,7 +1460,7 @@ export function DeleteAccount({
1460
1460
  Delete account
1461
1461
  </Button>
1462
1462
  );
1463
- }` }], api: { entries: [{ kind: "component", name: "Button", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, default: "3000", description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, default: "false", description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, default: '"idle"', description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, default: '"left"', description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }] }], types: { ButtonStatus: '"idle" | "loading" | "success"', SwapDirection: '"left" | "right" | "up" | "down"' } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button-variants.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/button.tsx", type: "registry:ui", content: `"use client";
1463
+ }` }], api: { entries: [{ kind: "component", name: "Button", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, default: "3000", description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, default: "false", description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, default: '"idle"', description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, default: '"left"', description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }] }], types: { ButtonStatus: '"idle" | "loading" | "success"', SwapDirection: '"left" | "right" | "up" | "down"' } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button-variants.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/button.tsx", type: "registry:ui", content: `"use client";
1464
1464
 
1465
1465
  import { Check, Loader2 } from "lucide-react";
1466
1466
  import { AnimatePresence, type HTMLMotionProps, motion } from "motion/react";
@@ -1482,9 +1482,9 @@ type Phase = "idle" | "armed" | "loading" | "success";
1482
1482
 
1483
1483
  type ButtonProps = Omit<HTMLMotionProps<"button">, "children"> &
1484
1484
  VariantProps & {
1485
- /** Disables the button and shows a spinner before the label. */
1485
+ /** Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable. */
1486
1486
  loading?: boolean;
1487
- /** In-place feedback: \`loading\` spins, \`success\` swaps the label to \`successLabel\`. */
1487
+ /** In-place feedback: \`loading\` spins, \`success\` swaps the label to \`successLabel\`. Both ignore clicks and Enter, so a form can't submit twice. */
1488
1488
  status?: ButtonStatus;
1489
1489
  /** Text shown on \`status="success"\`, with a check icon. Defaults to "Done". */
1490
1490
  successLabel?: ReactNode;
@@ -4411,7 +4411,7 @@ export function RolePicker() {
4411
4411
  placeholder="Add roles…"
4412
4412
  />
4413
4413
  );
4414
- }` }], api: { entries: [{ kind: "component", name: "Combobox", props: [{ name: "options", type: "ComboboxOption[]", required: true, description: "Choices; filtered as the user types." }, { name: "aria-describedby", type: "string", required: false, description: "Ids of hint or error text; Field fills it in." }, { name: "aria-invalid", type: "boolean", required: false, description: "Error styling; Field sets it from `error`." }, { name: "aria-label", type: "string", required: false, description: "Accessible name when there is no visible label." }, { name: "defaultValue", type: "string | string[]", required: false, description: "Value, or values when `multiple`, at first render (uncontrolled)." }, { name: "disabled", type: "boolean", required: false, description: "Blocks typing and opening." }, { name: "emptyText", type: "ReactNode", required: false, description: "Shown in the list when nothing matches." }, { name: "id", type: "string", required: false, description: "Id of the input; Field fills it in." }, { name: "multiple", type: "boolean", required: false, description: "Picks stay open and show as removable tags; Backspace removes the last one." }, { name: "name", type: "string", required: false, description: "Submits the value(s) through hidden inputs (one per value when multiple)." }, { name: "onValueChange", type: "((value: string) => void) | ((value: string[]) => void)", required: false, description: "Called with the picked value, or every picked value when `multiple`." }, { name: "placeholder", type: "string", required: false, description: "Field text when nothing is picked." }, { name: "required", type: "boolean", required: false, description: "Form submit needs a value." }, { name: "value", type: "string | string[]", required: false, description: "Controlled value, or values when `multiple`; pair with `onValueChange`." }], description: "Select you can type into: the input filters the list, Up and Down move, Enter picks, Esc closes.\nSingle shows the pick in the input; `multiple` shows picks as tags and keeps the list open." }], types: { ComboboxOption: "{ value: string; label: string; icon?: ReactNode; keywords?: string[]; disabled?: boolean; }" } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/tag-input.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/combobox.tsx", type: "registry:ui", content: `"use client";
4414
+ }` }], api: { entries: [{ kind: "component", name: "Combobox", props: [{ name: "options", type: "ComboboxOption[]", required: true, description: "Choices; filtered as the user types." }, { name: "aria-describedby", type: "string", required: false, description: "Ids of hint or error text; Field fills it in." }, { name: "aria-invalid", type: "boolean", required: false, description: "Error styling; Field sets it from `error`." }, { name: "aria-label", type: "string", required: false, description: "Accessible name when there is no visible label." }, { name: "defaultValue", type: "string | string[]", required: false, description: "Value, or values when `multiple`, at first render (uncontrolled)." }, { name: "disabled", type: "boolean", required: false, description: "Blocks typing and opening." }, { name: "emptyText", type: "ReactNode", required: false, description: "Shown in the list when nothing matches." }, { name: "id", type: "string", required: false, description: "Id of the input; Field fills it in." }, { name: "multiple", type: "boolean", required: false, description: "Picks stay open and show as removable tags; Backspace removes the last one." }, { name: "name", type: "string", required: false, description: "Submits the value(s) through hidden inputs (one per value when multiple)." }, { name: "onValueChange", type: "((value: string) => void) | ((value: string[]) => void)", required: false, description: "Called with the picked value, or every picked value when `multiple`." }, { name: "placeholder", type: "string", required: false, description: "Field text when nothing is picked." }, { name: "required", type: "boolean", required: false, description: "Form submit needs a value." }, { name: "value", type: "string | string[]", required: false, description: "Controlled value, or values when `multiple`; pair with `onValueChange`." }], description: "Select you can type into: the input filters the list, Up and Down move, Enter picks, Esc closes.\nSingle shows the pick in the input; `multiple` shows picks as tags and keeps the list open." }], types: { ComboboxOption: "{ value: string; label: string; icon?: ReactNode; keywords?: string[]; disabled?: boolean; }" } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/form-value.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/tag-input.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/combobox.tsx", type: "registry:ui", content: `"use client";
4415
4415
 
4416
4416
  import { Check, ChevronsUpDown } from "lucide-react";
4417
4417
  import { AnimatePresence, motion } from "motion/react";
@@ -4419,6 +4419,7 @@ import { type KeyboardEvent, type ReactNode, useEffect, useId, useRef, useState
4419
4419
  import { createPortal } from "react-dom";
4420
4420
  import { useFieldControl } from "@/components/ui/field";
4421
4421
  import { Tag, tagFieldClass } from "@/components/ui/tag-input";
4422
+ import { FormValue } from "@/lib/form-value";
4422
4423
  import { listKeyTarget, scrollIntoList } from "@/lib/list";
4423
4424
  import { useMounted } from "@/lib/platform";
4424
4425
  import { useAnchor } from "@/lib/use-anchor";
@@ -4426,7 +4427,7 @@ import { useControllableState } from "@/lib/use-controllable-state";
4426
4427
  import { useDismiss } from "@/lib/use-dismiss";
4427
4428
  import { cn, material, spring } from "@/lib/utils";
4428
4429
 
4429
- type ComboboxOption = {
4430
+ export type ComboboxOption = {
4430
4431
  /** Submitted and matched value. */
4431
4432
  value: string;
4432
4433
  /** Text shown and searched. */
@@ -4522,6 +4523,7 @@ export function Combobox(allProps: ComboboxProps) {
4522
4523
  const box = useRef<HTMLDivElement>(null);
4523
4524
  const input = useRef<HTMLInputElement>(null);
4524
4525
  const list = useRef<HTMLDivElement>(null);
4526
+ const [invalid, setInvalid] = useState(false);
4525
4527
  // Public shape (string or string[]), "" = nothing picked.
4526
4528
  const [raw, setRaw] = useControllableState<string | string[] | undefined>(
4527
4529
  valueProp,
@@ -4653,6 +4655,7 @@ export function Combobox(allProps: ComboboxProps) {
4653
4655
  aria-required={required}
4654
4656
  disabled={disabled}
4655
4657
  {...aria}
4658
+ aria-invalid={aria["aria-invalid"] || (invalid && !values.length) || undefined}
4656
4659
  value={text}
4657
4660
  placeholder={hint}
4658
4661
  onChange={(event) => {
@@ -4674,6 +4677,12 @@ export function Combobox(allProps: ComboboxProps) {
4674
4677
  (multiple ? values : values.slice(0, 1)).map((picked) => (
4675
4678
  <input key={picked} type="hidden" name={name} value={picked} />
4676
4679
  ))}
4680
+ <FormValue
4681
+ value={values.join(",")}
4682
+ required={required && !disabled}
4683
+ anchor={input}
4684
+ onInvalid={() => setInvalid(true)}
4685
+ />
4677
4686
  {mounted &&
4678
4687
  createPortal(
4679
4688
  <AnimatePresence>
@@ -6018,14 +6027,15 @@ export function ReportFilters() {
6018
6027
  </Field>
6019
6028
  );
6020
6029
  }` }], api: { entries: [{ kind: "component", name: "DatePicker", props: [{ name: "aria-describedby", type: "string", required: false, description: "Ids of hint or error text; Field fills it in." }, { name: "aria-invalid", type: "boolean", required: false, description: "Error styling; Field sets it from `error`." }, { name: "aria-label", type: "string", required: false, description: "Accessible name when there is no visible label." }, { name: "defaultValue", type: "Date | DateRange | null", required: false, description: "Day or range at first render (uncontrolled)." }, { name: "disabled", type: "boolean", required: false, description: "Blocks opening." }, { name: "id", type: "string", required: false, description: "Pair with <Label htmlFor>, or let <Field> fill it in." }, { name: "isDisabled", type: "(date: Date) => boolean", required: false, description: "Extra rule, e.g. weekends off. Client-only (a function)." }, { name: "locale", type: "string", required: false, description: "BCP 47 locale for the button text and the calendar." }, { name: "max", type: "Date", required: false, description: "Latest selectable day." }, { name: "min", type: "Date", required: false, description: "Earliest selectable day." }, { name: "mode", type: '"single" | "range"', required: false, description: '"single": pick one day. "range": pick a start, then an end.' }, { name: "name", type: "string", required: false, description: "Submits ISO through a hidden input: `2026-10-21`, or `2026-10-03/2026-10-09` for a range." }, { name: "onValueChange", type: "((date: Date) => void) | ((range: DateRange) => void)", required: false, description: "Called with the picked day, or with the range once both ends are set." }, { name: "placeholder", type: "string", required: false, description: "Button text when nothing is picked." }, { name: "presets", type: "Preset<Date>[] | Preset<DateRange>[]", required: false, description: "Shortcuts beside the grid, e.g. Today, or Last 7 days for a range. Readers reach for these first." }, { name: "required", type: "boolean", required: false, description: "Form submit needs a date." }, { name: "value", type: "Date | DateRange | null", required: false, description: "Controlled day, or `{ from, to }` in range mode; null = nothing picked." }, { name: "weekStartsOn", type: "0 | 1 | 2 | 3 | 4 | 5 | 6", required: false, description: "0 is Sunday, 6 is Saturday. Default 1 (Monday, ISO)." }], description: `Field-styled button that opens a Calendar in a Popover, focused on the picked day. A single
6021
- date closes on pick; a range closes once both ends are set. Optional presets, form-ready.` }], types: { Preset: "{ label: string; value: Value }" } }, dependencies: ["lucide-react@1.63.0"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/calendar.json", "https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/input.json", "https://kznlabs.github.io/labsUI/r/popover.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/date-picker.tsx", type: "registry:ui", content: `"use client";
6030
+ date closes on pick; a range closes once both ends are set. Optional presets, form-ready.` }], types: { Preset: "{ label: string; value: Value }" } }, dependencies: ["lucide-react@1.63.0"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/calendar.json", "https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/form-value.json", "https://kznlabs.github.io/labsUI/r/input.json", "https://kznlabs.github.io/labsUI/r/popover.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/date-picker.tsx", type: "registry:ui", content: `"use client";
6022
6031
 
6023
6032
  import { CalendarDays } from "lucide-react";
6024
- import { useState } from "react";
6033
+ import { useRef, useState } from "react";
6025
6034
  import { Calendar, type DateRange, key } from "@/components/ui/calendar";
6026
6035
  import { useFieldControl } from "@/components/ui/field";
6027
6036
  import { fieldClass } from "@/components/ui/input";
6028
6037
  import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
6038
+ import { FormValue } from "@/lib/form-value";
6029
6039
  import { useControllableState } from "@/lib/use-controllable-state";
6030
6040
  import { cn } from "@/lib/utils";
6031
6041
 
@@ -6102,9 +6112,12 @@ export function DatePicker(allProps: DatePickerProps) {
6102
6112
  weekStartsOn,
6103
6113
  locale = "en-US",
6104
6114
  name,
6115
+ required,
6105
6116
  className,
6106
6117
  ...trigger
6107
6118
  } = useFieldControl(allProps);
6119
+ const anchor = useRef<HTMLButtonElement>(null);
6120
+ const [invalid, setInvalid] = useState(false);
6108
6121
  const range = mode === "range";
6109
6122
  const [open, setOpen] = useState(false);
6110
6123
  const [value, setValue] = useControllableState<Date | DateRange | null>(
@@ -6143,6 +6156,7 @@ export function DatePicker(allProps: DatePickerProps) {
6143
6156
  <>
6144
6157
  <Popover open={open} onOpenChange={setOpen}>
6145
6158
  <PopoverTrigger
6159
+ ref={anchor}
6146
6160
  variant="outline"
6147
6161
  className={cn(
6148
6162
  fieldClass,
@@ -6151,6 +6165,7 @@ export function DatePicker(allProps: DatePickerProps) {
6151
6165
  className,
6152
6166
  )}
6153
6167
  {...trigger}
6168
+ aria-invalid={trigger["aria-invalid"] || (invalid && !iso) || undefined}
6154
6169
  >
6155
6170
  <CalendarDays />
6156
6171
  <span className="truncate">{label ?? placeholder}</span>
@@ -6190,7 +6205,13 @@ export function DatePicker(allProps: DatePickerProps) {
6190
6205
  )}
6191
6206
  </PopoverContent>
6192
6207
  </Popover>
6193
- {name && <input type="hidden" name={name} value={iso} />}
6208
+ <FormValue
6209
+ name={name}
6210
+ value={iso}
6211
+ required={required && !trigger.disabled}
6212
+ anchor={anchor}
6213
+ onInvalid={() => setInvalid(true)}
6214
+ />
6194
6215
  </>
6195
6216
  );
6196
6217
  }
@@ -6219,7 +6240,7 @@ export function EditProfile() {
6219
6240
  </DialogContent>
6220
6241
  </Dialog>
6221
6242
  );
6222
- }` }], api: { entries: [{ kind: "function", name: "useDialog", signature: "useDialog() => Ctx" }, { kind: "component", name: "Dialog", props: [{ name: "children", type: "ReactNode", required: true, description: "`DialogTrigger` and `DialogContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, backdrop click or `DialogClose`." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "State root. Controlled (`open` + `onOpenChange`) or uncontrolled." }, { kind: "component", name: "DialogTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DialogClose", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, default: '"outline"', description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "function", name: "useModal", signature: "useModal() => RefObject<HTMLDivElement | null>", description: `Modal behavior shared by Dialog and Drawer: focus first field, trap Tab, restore focus,
6243
+ }` }], api: { entries: [{ kind: "function", name: "useDialog", signature: "useDialog() => Ctx" }, { kind: "component", name: "Dialog", props: [{ name: "children", type: "ReactNode", required: true, description: "`DialogTrigger` and `DialogContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, backdrop click or `DialogClose`." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "State root. Controlled (`open` + `onOpenChange`) or uncontrolled." }, { kind: "component", name: "DialogTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DialogClose", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, default: '"outline"', description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "function", name: "useModal", signature: "useModal() => RefObject<HTMLDivElement | null>", description: `Modal behavior shared by Dialog and Drawer: focus first field, trap Tab, restore focus,
6223
6244
  lock page scroll, close on Esc (topmost modal only). Attach the returned ref to the panel.` }, { kind: "component", name: "DialogContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Header, body and footer." }, { name: "alert", type: "boolean", required: false, default: "false", description: 'Confirm-a-destructive-action mode: role="alertdialog", backdrop click does not close.' }, { name: "showClose", type: "boolean", required: false, default: "!alert", description: "Close button in the corner. Off by default for `alert` dialogs." }], description: "Portal + blurred backdrop + spring scale-in. Esc/backdrop close, focus trap, scroll lock." }, { kind: "component", name: "DialogHeader", props: [], extends: "<div>" }, { kind: "component", name: "DialogFooter", props: [], extends: "<div>" }, { kind: "component", name: "DialogTitle", props: [], extends: "<h2>" }, { kind: "component", name: "DialogDescription", props: [], extends: "<p>" }], types: { Ctx: "{ open: boolean; setOpen: (open: boolean) => void; titleId: string; descId: string }" } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/dialog.tsx", type: "registry:ui", content: `"use client";
6224
6245
 
6225
6246
  import { X } from "lucide-react";
@@ -6519,7 +6540,7 @@ export function CartDrawer({ items }: { items: string[] }) {
6519
6540
  </DrawerContent>
6520
6541
  </Drawer>
6521
6542
  );
6522
- }` }], api: { entries: [{ kind: "component", name: "Drawer", props: [{ name: "children", type: "ReactNode", required: true, description: "`DialogTrigger` and `DialogContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, backdrop click or `DialogClose`." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }] }, { kind: "component", name: "DrawerTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DrawerClose", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, default: '"outline"', description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DrawerTitle", props: [], extends: "<h2>" }, { kind: "component", name: "DrawerDescription", props: [], extends: "<p>" }, { kind: "component", name: "DrawerContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Header, body and footer." }, { name: "showClose", type: "boolean", required: false, default: 'side === "left" || side === "right"', description: "Close button in the corner. On by default for side drawers." }, { name: "side", type: "Side", required: false, default: '"right"', description: "Edge it slides in from." }], description: `Panel that slides in from an edge on a spring. Swipe toward the edge to dismiss: side drawers
6543
+ }` }], api: { entries: [{ kind: "component", name: "Drawer", props: [{ name: "children", type: "ReactNode", required: true, description: "`DialogTrigger` and `DialogContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, backdrop click or `DialogClose`." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }] }, { kind: "component", name: "DrawerTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DrawerClose", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, default: '"outline"', description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "DrawerTitle", props: [], extends: "<h2>" }, { kind: "component", name: "DrawerDescription", props: [], extends: "<p>" }, { kind: "component", name: "DrawerContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Header, body and footer." }, { name: "showClose", type: "boolean", required: false, default: 'side === "left" || side === "right"', description: "Close button in the corner. On by default for side drawers." }, { name: "side", type: "Side", required: false, default: '"right"', description: "Edge it slides in from." }], description: `Panel that slides in from an edge on a spring. Swipe toward the edge to dismiss: side drawers
6523
6544
  drag from anywhere, top/bottom drawers from the handle or header so their content can scroll.` }, { kind: "component", name: "DrawerHeader", props: [], extends: "<div>", description: "Also a drag handle on top/bottom drawers." }, { kind: "component", name: "DrawerBody", props: [], extends: "<div>", description: "Scrolls when content is taller than the drawer." }, { kind: "component", name: "DrawerFooter", props: [], extends: "<div>" }], types: { Side: '"left" | "right" | "top" | "bottom"' } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/dialog.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/drawer.tsx", type: "registry:ui", content: `"use client";
6524
6545
 
6525
6546
  import { X } from "lucide-react";
@@ -6773,7 +6794,7 @@ export function ClipActions({ onDelete }: { onDelete: () => void }) {
6773
6794
  </DropdownMenuContent>
6774
6795
  </DropdownMenu>
6775
6796
  );
6776
- }` }], api: { entries: [{ kind: "component", name: "DropdownMenu", props: [{ name: "children", type: "ReactNode", required: true, description: "Trigger and content." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, outside click or a selection." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "Action menu anchored to a button. Controlled (`open` + `onOpenChange`) or uncontrolled." }, { kind: "component", name: "DropdownMenuTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button", description: "A Button. Keyboard: Enter, Space or Down opens on the first item, Up on the last." }, { kind: "component", name: "DropdownMenuContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Items, labels, groups and separators." }, { name: "align", type: '"start" | "end"', required: false, default: '"start"', description: "Edge of the trigger the menu lines up with." }] }, { kind: "component", name: "DropdownMenuItem", props: [{ name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }, { name: "onSelect", type: "() => void", required: false, description: "Called on click or Enter; the menu then closes." }, { name: "shortcut", type: "string", required: false, description: 'Right-aligned hint, e.g. "⌘S".' }, { name: "variant", type: '"default" | "destructive"', required: false, default: '"default"', description: '"destructive": red, for irreversible actions.' }] }, { kind: "component", name: "DropdownMenuCheckboxItem", props: [{ name: "checked", type: "boolean", required: true, description: "Shows the check mark." }, { name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "onCheckedChange", type: "(checked: boolean) => void", required: true, description: "Called with the new state." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }, { name: "shortcut", type: "string", required: false, description: 'Right-aligned hint, e.g. "⌘S".' }], description: "Toggles without closing the menu." }, { kind: "component", name: "DropdownMenuRadioGroup", props: [{ name: "children", type: "ReactNode", required: true, description: "`DropdownMenuRadioItem`s." }, { name: "onValueChange", type: "(value: string) => void", required: true, description: "Called with the picked item's value." }, { name: "value", type: "string", required: true, description: "Value of the checked item." }] }, { kind: "component", name: "DropdownMenuRadioItem", props: [{ name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "value", type: "string", required: true, description: "Checked when it equals the group's `value`." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }], description: "One choice of a RadioGroup; picking it keeps the menu open." }, { kind: "component", name: "DropdownMenuLabel", props: [], extends: "<div>" }, { kind: "component", name: "DropdownMenuSeparator", props: [] }], types: {} }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/dropdown-menu.tsx", type: "registry:ui", content: `"use client";
6797
+ }` }], api: { entries: [{ kind: "component", name: "DropdownMenu", props: [{ name: "children", type: "ReactNode", required: true, description: "Trigger and content." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc, outside click or a selection." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "Action menu anchored to a button. Controlled (`open` + `onOpenChange`) or uncontrolled." }, { kind: "component", name: "DropdownMenuTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button", description: "A Button. Keyboard: Enter, Space or Down opens on the first item, Up on the last." }, { kind: "component", name: "DropdownMenuContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Items, labels, groups and separators." }, { name: "align", type: '"start" | "end"', required: false, default: '"start"', description: "Edge of the trigger the menu lines up with." }] }, { kind: "component", name: "DropdownMenuItem", props: [{ name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }, { name: "onSelect", type: "() => void", required: false, description: "Called on click or Enter; the menu then closes." }, { name: "shortcut", type: "string", required: false, description: 'Right-aligned hint, e.g. "⌘S".' }, { name: "variant", type: '"default" | "destructive"', required: false, default: '"default"', description: '"destructive": red, for irreversible actions.' }] }, { kind: "component", name: "DropdownMenuCheckboxItem", props: [{ name: "checked", type: "boolean", required: true, description: "Shows the check mark." }, { name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "onCheckedChange", type: "(checked: boolean) => void", required: true, description: "Called with the new state." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }, { name: "shortcut", type: "string", required: false, description: 'Right-aligned hint, e.g. "⌘S".' }], description: "Toggles without closing the menu." }, { kind: "component", name: "DropdownMenuRadioGroup", props: [{ name: "children", type: "ReactNode", required: true, description: "`DropdownMenuRadioItem`s." }, { name: "onValueChange", type: "(value: string) => void", required: true, description: "Called with the picked item's value." }, { name: "value", type: "string", required: true, description: "Value of the checked item." }] }, { kind: "component", name: "DropdownMenuRadioItem", props: [{ name: "children", type: "ReactNode", required: true, description: "Label, optionally with a leading icon." }, { name: "value", type: "string", required: true, description: "Checked when it equals the group's `value`." }, { name: "disabled", type: "boolean", required: false, description: "Shown but not selectable." }], description: "One choice of a RadioGroup; picking it keeps the menu open." }, { kind: "component", name: "DropdownMenuLabel", props: [], extends: "<div>" }, { kind: "component", name: "DropdownMenuSeparator", props: [] }], types: {} }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/dropdown-menu.tsx", type: "registry:ui", content: `"use client";
6777
6798
 
6778
6799
  import { Check, Circle } from "lucide-react";
6779
6800
  import { AnimatePresence, motion } from "motion/react";
@@ -7401,6 +7422,42 @@ export function Field({
7401
7422
  </FieldContext>
7402
7423
  );
7403
7424
  }
7425
+ ` }] }, "form-value": { $schema: "https://kznlabs.github.io/labsUI/r/registry-item.schema.json", name: "form-value", type: "registry:lib", description: "Submits a custom control's value and takes part in native validation, which a hidden input\ncan't: an empty `required` value blocks submit, shows the browser's message and focuses `anchor`.", api: { entries: [{ kind: "component", name: "FormValue", props: [{ name: "anchor", type: "RefObject<HTMLElement | null>", required: true, description: "The visible control that gets focus when the value is invalid." }, { name: "value", type: "string", required: true, description: 'The value to submit, "" when nothing is picked.' }, { name: "name", type: "string", required: false, description: "Form field name; without it the value only takes part in validation." }, { name: "onInvalid", type: "() => void", required: false, description: "Called when a submit finds the value invalid." }, { name: "required", type: "boolean", required: false, description: "An empty value blocks submit." }], description: "Submits a custom control's value and takes part in native validation, which a hidden input\ncan't: an empty `required` value blocks submit, shows the browser's message and focuses `anchor`." }], types: {} }, dependencies: [], registryDependencies: [], files: [{ path: "lib/form-value.tsx", type: "registry:lib", content: `import type { RefObject } from "react";
7426
+
7427
+ type FormValueProps = {
7428
+ /** Form field name; without it the value only takes part in validation. */
7429
+ name?: string;
7430
+ /** The value to submit, "" when nothing is picked. */
7431
+ value: string;
7432
+ /** An empty value blocks submit. */
7433
+ required?: boolean;
7434
+ /** The visible control that gets focus when the value is invalid. */
7435
+ anchor: RefObject<HTMLElement | null>;
7436
+ /** Called when a submit finds the value invalid. */
7437
+ onInvalid?: () => void;
7438
+ };
7439
+
7440
+ /**
7441
+ * Submits a custom control's value and takes part in native validation, which a hidden input
7442
+ * can't: an empty \`required\` value blocks submit, shows the browser's message and focuses \`anchor\`.
7443
+ */
7444
+ export function FormValue({ name, value, required, anchor, onInvalid }: FormValueProps) {
7445
+ if (!name && !required) return null;
7446
+
7447
+ return (
7448
+ <input
7449
+ aria-hidden="true"
7450
+ tabIndex={-1}
7451
+ name={name}
7452
+ value={value}
7453
+ required={required}
7454
+ onChange={() => undefined}
7455
+ onInvalid={onInvalid}
7456
+ onFocus={() => anchor.current?.focus()}
7457
+ className="pointer-events-none absolute size-px opacity-0"
7458
+ />
7459
+ );
7460
+ }
7404
7461
  ` }] }, highlight: { $schema: "https://kznlabs.github.io/labsUI/r/registry-item.schema.json", name: "highlight", type: "registry:lib", description: "Lines of colored tokens, with Shiki loaded on demand. Runs anywhere: Code calls it in the\nbrowser, and a Server Component or a build can call it ahead of time and pass the result as\n`tokens`, so the browser never loads Shiki. Null for unknown languages.", api: { entries: [{ kind: "function", name: "highlightCode", signature: "highlightCode(code: string, language: string) => Promise<CodeToken[][] | null>", description: "Lines of colored tokens, with Shiki loaded on demand. Runs anywhere: Code calls it in the\nbrowser, and a Server Component or a build can call it ahead of time and pass the result as\n`tokens`, so the browser never loads Shiki. Null for unknown languages." }, { kind: "function", name: "languageOf", signature: "languageOf(name: string) => string", description: "Language from a file name's extension. Falls back to tsx." }], types: { CodeToken: "{ content: string; color?: string; fontStyle?: number }" } }, dependencies: ["shiki@^4.5.0"], registryDependencies: [], files: [{ path: "lib/highlight.ts", type: "registry:lib", content: `import type { BundledLanguage } from "shiki";
7405
7462
 
7406
7463
  /** A run of text in one color: \`light-dark()\` holds both themes, so the page's color scheme picks. */
@@ -10137,7 +10194,7 @@ export function ClipFilters() {
10137
10194
  </PopoverContent>
10138
10195
  </Popover>
10139
10196
  );
10140
- }` }], api: { entries: [{ kind: "component", name: "Popover", props: [{ name: "children", type: "ReactNode", required: true, description: "`PopoverTrigger` and `PopoverContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc or an outside click." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "Non-modal panel anchored to a button: filters, pickers, quick edits. Controlled or uncontrolled." }, { kind: "component", name: "PopoverTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Disables the button and shows a spinner before the label." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "PopoverContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Panel content." }, { name: "align", type: '"start" | "center" | "end"', required: false, default: '"center"', description: "Alignment with the trigger." }, { name: "side", type: '"top" | "bottom"', required: false, default: '"bottom"', description: "Preferred side; flips when there is no room." }], description: `Focus moves in on open. Esc or an outside click closes it; Esc returns focus to the trigger.
10197
+ }` }], api: { entries: [{ kind: "component", name: "Popover", props: [{ name: "children", type: "ReactNode", required: true, description: "`PopoverTrigger` and `PopoverContent`." }, { name: "defaultOpen", type: "boolean", required: false, default: "false", description: "Open at first render (uncontrolled)." }, { name: "onOpenChange", type: "(open: boolean) => void", required: false, description: "Called on the trigger, Esc or an outside click." }, { name: "open", type: "boolean", required: false, description: "Controlled state; pair with `onOpenChange`." }], description: "Non-modal panel anchored to a button: filters, pickers, quick edits. Controlled or uncontrolled." }, { kind: "component", name: "PopoverTrigger", props: [{ name: "children", type: "ReactNode", required: false, description: "Label; its width is reserved so loading and success never resize the button." }, { name: "confirmLabel", type: "ReactNode", required: false, description: "Two-step action: first click swaps the label to this, second click runs `onClick`." }, { name: "confirmTimeout", type: "number", required: false, description: "Ms before an armed confirm step resets. Also resets on blur or Esc." }, { name: "loading", type: "boolean", required: false, description: "Shows a spinner before the label and ignores clicks and Enter, so a form can't submit twice. Stays focusable." }, { name: "loadingLabel", type: "ReactNode", required: false, description: "Label shown while loading, with the spinner. Defaults to `children`." }, { name: "size", type: '"default" | "sm" | "lg" | "icon"', required: false, description: 'Height and padding; "icon" is square, so give it an `aria-label`.' }, { name: "status", type: "ButtonStatus", required: false, description: "In-place feedback: `loading` spins, `success` swaps the label to `successLabel`. Both ignore clicks and Enter, so a form can't submit twice." }, { name: "successLabel", type: "ReactNode", required: false, description: 'Text shown on `status="success"`, with a check icon. Defaults to "Done".' }, { name: "swap", type: "SwapDirection", required: false, description: 'Where the old label slides out to on a swap. Default "left".' }, { name: "variant", type: '"default" | "secondary" | "outline" | "ghost" | "destructive"', required: false, description: "Fill and emphasis: one primary action per view, `destructive` for irreversible ones." }], extends: "Button" }, { kind: "component", name: "PopoverContent", props: [{ name: "children", type: "ReactNode", required: true, description: "Panel content." }, { name: "align", type: '"start" | "center" | "end"', required: false, default: '"center"', description: "Alignment with the trigger." }, { name: "side", type: '"top" | "bottom"', required: false, default: '"bottom"', description: "Preferred side; flips when there is no room." }], description: `Focus moves in on open. Esc or an outside click closes it; Esc returns focus to the trigger.
10141
10198
  Not a focus trap: Tab past the end closes it and moves on, like any non-modal popup.` }], types: {} }, dependencies: ["motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/button.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/popover.tsx", type: "registry:ui", content: `"use client";
10142
10199
 
10143
10200
  import { AnimatePresence, motion } from "motion/react";
@@ -12331,7 +12388,7 @@ export function RolePicker() {
12331
12388
  </Field>
12332
12389
  );
12333
12390
  }` }], api: { entries: [{ kind: "component", name: "Select", props: [{ name: "options", type: "SelectGroup[] | SelectOption[]", required: true, description: "Flat options, or labeled groups of options." }, { name: "aria-describedby", type: "string", required: false, description: "Ids of hint or error text; Field fills it in." }, { name: "aria-invalid", type: "boolean", required: false, description: "Error styling; Field sets it from `error`." }, { name: "aria-label", type: "string", required: false, description: "Accessible name when there is no visible label." }, { name: "defaultValue", type: "string", required: false, description: "Value at first render (uncontrolled)." }, { name: "disabled", type: "boolean", required: false, description: "Blocks opening." }, { name: "id", type: "string", required: false, description: "Pair with <Label htmlFor>, or let <Field> fill it in." }, { name: "name", type: "string", required: false, description: "Submits the value with a form, through a hidden input." }, { name: "onValueChange", type: "(value: string) => void", required: false, description: "Called with the picked value." }, { name: "placeholder", type: "string", required: false, description: "Trigger text when nothing is picked." }, { name: "required", type: "boolean", required: false, description: "Form submit needs a value." }, { name: "value", type: "string", required: false, description: "Controlled value; pair with `onValueChange`." }], description: `Single-choice listbox styled like Input. Keyboard matches a native select: Up, Down, Home, End,
12334
- typeahead (also while closed), Enter or Space to pick, Esc to cancel.` }], types: { SelectOption: "{ value: string; label: string; icon?: ReactNode; disabled?: boolean }", SelectGroup: "{ label: string; options: SelectOption[] }" } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/input.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/select.tsx", type: "registry:ui", content: `"use client";
12391
+ typeahead (also while closed), Enter or Space to pick, Esc to cancel.` }], types: { SelectOption: "{ value: string; label: string; icon?: ReactNode; disabled?: boolean }", SelectGroup: "{ label: string; options: SelectOption[] }" } }, dependencies: ["lucide-react@1.63.0", "motion@14.7.1"], registryDependencies: ["https://kznlabs.github.io/labsUI/r/field.json", "https://kznlabs.github.io/labsUI/r/form-value.json", "https://kznlabs.github.io/labsUI/r/input.json", "https://kznlabs.github.io/labsUI/r/list.json", "https://kznlabs.github.io/labsUI/r/platform.json", "https://kznlabs.github.io/labsUI/r/use-anchor.json", "https://kznlabs.github.io/labsUI/r/use-controllable-state.json", "https://kznlabs.github.io/labsUI/r/use-dismiss.json", "https://kznlabs.github.io/labsUI/r/utils.json"], files: [{ path: "components/ui/select.tsx", type: "registry:ui", content: `"use client";
12335
12392
 
12336
12393
  import { Check, ChevronsUpDown } from "lucide-react";
12337
12394
  import { AnimatePresence, motion } from "motion/react";
@@ -12339,6 +12396,7 @@ import { type KeyboardEvent, type ReactNode, useEffect, useId, useRef, useState
12339
12396
  import { createPortal } from "react-dom";
12340
12397
  import { useFieldControl } from "@/components/ui/field";
12341
12398
  import { fieldClass } from "@/components/ui/input";
12399
+ import { FormValue } from "@/lib/form-value";
12342
12400
  import { listKeyTarget, scrollIntoList } from "@/lib/list";
12343
12401
  import { useMounted } from "@/lib/platform";
12344
12402
  import { useAnchor } from "@/lib/use-anchor";
@@ -12346,8 +12404,8 @@ import { useControllableState } from "@/lib/use-controllable-state";
12346
12404
  import { useDismiss } from "@/lib/use-dismiss";
12347
12405
  import { cn, material, spring } from "@/lib/utils";
12348
12406
 
12349
- type SelectOption = { value: string; label: string; icon?: ReactNode; disabled?: boolean };
12350
- type SelectGroup = { label: string; options: SelectOption[] };
12407
+ export type SelectOption = { value: string; label: string; icon?: ReactNode; disabled?: boolean };
12408
+ export type SelectGroup = { label: string; options: SelectOption[] };
12351
12409
 
12352
12410
  type SelectProps = {
12353
12411
  /** Flat options, or labeled groups of options. */
@@ -12403,6 +12461,7 @@ export function Select(allProps: SelectProps) {
12403
12461
  const list = useRef<HTMLDivElement>(null);
12404
12462
  const [value, setValue] = useControllableState(valueProp, defaultValue, onValueChange);
12405
12463
  const [open, setOpen] = useState(false);
12464
+ const [invalid, setInvalid] = useState(false);
12406
12465
  const [active, setActive] = useState<string>();
12407
12466
  const pos = useAnchor(open, trigger, list);
12408
12467
  const mounted = useMounted();
@@ -12507,6 +12566,7 @@ export function Select(allProps: SelectProps) {
12507
12566
  className,
12508
12567
  )}
12509
12568
  {...aria}
12569
+ aria-invalid={aria["aria-invalid"] || (invalid && !value) || undefined}
12510
12570
  >
12511
12571
  <span
12512
12572
  className={cn(
@@ -12519,7 +12579,13 @@ export function Select(allProps: SelectProps) {
12519
12579
  </span>
12520
12580
  <ChevronsUpDown className="text-muted-foreground" aria-hidden="true" />
12521
12581
  </button>
12522
- {name && <input type="hidden" name={name} value={value} />}
12582
+ <FormValue
12583
+ name={name}
12584
+ value={value}
12585
+ required={required && !disabled}
12586
+ anchor={trigger}
12587
+ onInvalid={() => setInvalid(true)}
12588
+ />
12523
12589
  {mounted &&
12524
12590
  createPortal(
12525
12591
  <AnimatePresence>
@@ -17182,9 +17248,9 @@ export const spring = { type: "spring", stiffness: 400, damping: 30 } as const;
17182
17248
  export const clamp = (value: number, min: number, max: number) =>
17183
17249
  Math.min(Math.max(value, min), max);
17184
17250
  ` }] } },
17185
- index: [{ name: "accent-picker", type: "registry:ui", title: "Accent Picker", description: "Accent color row: eight swatches (red to slate) that retint primary, focus rings, selection, switches and checkboxes app-wide. Persisted, applied before paint, or set your own hue with --accent-hue.", exports: ["AccentPicker"], keywords: ["accent", "app", "color", "radio", "retint", "row", "setaccent", "swatches", "that", "the", "via", "whole"], registryDependencies: ["theme", "utils"] }, { name: "accordion", type: "registry:ui", title: "Accordion", description: "Single or multiple panels with spring height animation. Closed content stays in the DOM for SEO.", exports: ["Accordion", "AccordionItem", "AccordionTrigger", "AccordionContent"], keywords: ["accordion", "accordioncontent", "accordionitem", "accordiontrigger", "allow", "and", "called", "children", "closed", "closes", "closing", "collapsible", "content", "controlled", "crawlable", "default", "defaultvalue", "every", "first", "heading", "height", "html", "independent", "inert", "item", "items", "level", "match", "matched", "mounted", "multiple", "none", "one", "only", "onvaluechange", "open", "outline", "page", "panel", "panels", "question", "remains", "render", "single", "stays", "text", "the", "time", "type", "uncontrolled", "unique", "value", "when", "while", "with", "within", "wrapping"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "alert", type: "registry:ui", title: "Alert", description: "Server-safe inline banner: tinted surface, colored icon, title, description and an optional action. Info, success, warning and destructive tones follow the accent and status tokens.", exports: ["Alert", "AlertTitle", "AlertDescription"], keywords: ["action", "add", "alert", "aligned", "and", "announced", "appears", "banner", "button", "colored", "default", "description", "did", "for", "icon", "inline", "live", "load", "none", "not", "null", "pass", "region", "replaces", "response", "right", "role", "sets", "should", "slot", "small", "something", "static", "surface", "the", "tint", "tinted", "title", "tone", "user", "variant", "when"], registryDependencies: ["utils"] }, { name: "app-window", type: "registry:ui", title: "AppWindow", description: "Window container with close / minimize / zoom controls, title, custom header slot and actions. SegmentedTabs is the compact view switcher for its title bar.", exports: ["AppWindow"], keywords: ["actions", "aligned", "area", "bar", "blurred", "bodyclassname", "button", "called", "centered", "classes", "content", "control", "custom", "dot", "for", "glass", "handler", "header", "into", "matching", "maximize", "minimize", "navbar", "onclose", "onmaximize", "onminimize", "passing", "pressed", "replaces", "right", "search", "shows", "slot", "surface", "tabs", "text", "the", "title", "titlebar", "translucent", "turns", "under", "when"], registryDependencies: ["utils"] }, { name: "aspect-ratio", type: "registry:ui", title: "Aspect Ratio", description: "Server-safe box locked to a ratio (16:9 thumbnails, 9:16 clips). A direct image or video child fills it with object-cover.", exports: ["AspectRatio"], keywords: ["box", "child", "cover", "direct", "fills", "height", "img", "locked", "object", "ratio", "video", "width"], registryDependencies: ["utils"] }, { name: "attachment", type: "registry:ui", title: "Attachment & Dropzone", description: "File chips with image thumbnails or type icons, size, a springing upload bar, error state and remove; the list springs chips in and closes the gap. FileDropzone wraps a real file input: click, keyboard and the native picker work, drop and paste are checked against accept and maxSize, and dropped files land in the input so forms and Server Actions receive them.", exports: ["formatBytes", "Attachment", "AttachmentList", "FileDropzone"], keywords: ["accept", "actions", "along", "and", "are", "area", "aria", "around", "attachments", "attribute", "back", "bar", "bcp", "blocks", "both", "bottom", "browse", "button", "bytes", "called", "child", "children", "chip", "click", "content", "createobjecturl", "default", "describedby", "disabled", "download", "drop", "dropped", "drops", "each", "edge", "enforced", "enter", "error", "failed", "field", "file", "files", "fills", "for", "form", "forms", "fresh", "from", "get", "given", "hint", "href", "icon", "ids", "image", "input", "into", "invalid", "key", "least", "line", "link", "locale", "makes", "maxsize", "mime", "more", "multiple", "name", "native", "needs", "one", "onfiles", "onreject", "onremove", "out", "passed", "paste", "pdf", "picked", "picker", "picks", "place", "plain", "pressed", "progress", "real", "reason", "red", "remove", "removed", "replaces", "required", "same", "server", "sets", "show", "shows", "size", "source", "space", "spring", "springs", "src", "styling", "submit", "syntax", "text", "than", "that", "the", "them", "thumbnail", "too", "turns", "type", "types", "upload", "uploading", "url", "when", "while", "with", "work", "written"], registryDependencies: ["field", "utils"] }, { name: "avatar", type: "registry:ui", title: "Avatar", description: "Image with initials fallback on error, three sizes and online/away/busy/offline dots.", exports: ["Avatar"], keywords: ["alt", "and", "announced", "corner", "diameter", "dot", "fails", "fallback", "for", "icon", "image", "initials", "loads", "name", "overrides", "person", "presence", "show", "size", "src", "status", "text", "the", "url", "used", "while", "with"], registryDependencies: ["utils"] }, { name: "avatar-group", type: "registry:ui", title: "AvatarGroup", description: "Overlapping avatars with a +N overflow chip. Hover gently enlarges the avatar on a spring, keeping stack order.", exports: ["AvatarGroup"], keywords: ["alt", "and", "avatar", "avatars", "before", "chip", "each", "enlarges", "every", "gently", "hover", "how", "many", "max", "name", "one", "order", "overflow", "overlapping", "people", "show", "size", "spring", "stack", "staying", "the", "users", "with"], registryDependencies: ["avatar", "utils"] }, { name: "badge", type: "registry:ui", title: "Badge & Pill", description: "Minimal status tags. Rounded badge or fully rounded pill, with optional dot. pulse adds an expanding live-status ring.", exports: ["Badge"], keywords: ["and", "color", "current", "dot", "emits", "expanding", "forever", "fully", "leading", "like", "live", "needs", "pill", "pulse", "ring", "rounded", "shape", "status", "surface", "tag", "text", "the", "variant"], registryDependencies: ["utils"] }, { name: "breadcrumb", type: "registry:ui", title: "Breadcrumb", description: "Navigation trail from a list of items: links up to the current page, which is marked for assistive tech. Server-safe, custom separator.", exports: ["Breadcrumb"], keywords: ["between", "chevron", "current", "default", "drawn", "ending", "first", "item", "items", "last", "links", "list", "outermost", "page", "safe", "separator", "server", "site", "sits", "the", "trail", "where"], registryDependencies: [] }, { name: "button", type: "registry:ui", title: "Button", description: "Five variants, four sizes, spring press feedback, an animated loading spinner and in-place success state, a two-step confirm that swaps the label on first click, and a configurable swap direction. Width stays fixed to the longest label.", exports: ["Button"], keywords: ["action", "also", "and", "aria", "armed", "before", "blur", "button", "check", "children", "click", "confirm", "confirmlabel", "confirmtimeout", "default", "defaults", "destructive", "disables", "done", "emphasis", "esc", "feedback", "fill", "first", "for", "give", "height", "icon", "irreversible", "its", "label", "left", "loading", "loadinglabel", "never", "old", "onclick", "one", "ones", "out", "padding", "per", "place", "primary", "reserved", "resets", "resize", "runs", "second", "shown", "shows", "size", "slides", "spinner", "spins", "square", "status", "step", "success", "successlabel", "swap", "swaps", "text", "the", "this", "two", "variant", "view", "where", "while", "width", "with"], registryDependencies: ["button-variants", "utils"] }, { name: "button-group", type: "registry:ui", title: "Button Group", description: "Joins buttons into one strip that shares borders, corners and active states. Horizontal or vertical.", exports: ["ButtonGroup"], keywords: ["and", "attached", "borders", "buttons", "connected", "control", "corners", "default", "fuse", "groups", "horizontal", "into", "orientation", "related", "single", "strip", "together", "toolbar", "true", "vertical"], registryDependencies: ["utils"] }, { name: "button-variants", type: "registry:ui", description: 'Button classes for non-button elements, e.g. `<a className={buttonVariants({ variant: "outline" })}>`.', exports: ["buttonVariants"], keywords: ["button", "buttonvariants", "classes", "classname", "elements", "for", "non", "outline", "variant"], registryDependencies: ["utils"] }, { name: "calendar", type: "registry:ui", title: "Calendar", description: "Month grid on the WAI-ARIA date-grid pattern: single date or range with a hover preview, min/max and custom disabled days, months that slide in from the direction of travel. Arrows, Home/End and PageUp/PageDown (+Shift for years). Hydration-safe: today is only marked in the browser.", exports: ["key", "Calendar"], keywords: ["and", "another", "any", "aria", "arrows", "autofocus", "bcp", "called", "client", "controlled", "current", "custom", "date", "datepicker", "dates", "day", "days", "default", "defaultmonth", "defaultvalue", "direction", "disabled", "displayed", "earliest", "end", "ends", "extra", "first", "focus", "for", "from", "function", "grid", "home", "hover", "into", "isdisabled", "iso", "keyboard", "latest", "like", "local", "locale", "max", "min", "mode", "monday", "month", "months", "mount", "names", "nothing", "null", "off", "one", "only", "onmonthchange", "onvaluechange", "pagedown", "pages", "pageup", "pattern", "pick", "picked", "preview", "range", "render", "rule", "saturday", "selectable", "sets", "shift", "shown", "single", "slide", "sorts", "start", "sunday", "the", "then", "this", "travel", "uncontrolled", "user", "value", "wai", "week", "weekday", "weekends", "weekstartson", "when", "with", "year", "yyyy"], registryDependencies: ["button", "use-controllable-state", "utils"] }, { name: "card", type: "registry:ui", title: "Card", description: "Composable surface: header, title, description, content and footer. Optional glass.", exports: ["Card", "CardHeader", "CardTitle", "CardDescription", "CardContent", "CardFooter"], keywords: ["backgrounds", "colored", "default", "directly", "fits", "follows", "glass", "heading", "level", "not", "outline", "over", "page", "place", "subtle", "textured", "that", "the", "translucency", "under", "when"], registryDependencies: ["utils"] }, { name: "carousel", type: "registry:ui", title: "Carousel", description: "Native scroll-snap row, so touch, trackpad and no-JS scrolling work, with spring-driven arrows, page dots, arrow keys and mouse drag that throws to the next snap point. APG carousel semantics: a labeled region of slides announced as 3 of 8.", exports: ["Carousel", "CarouselContent", "CarouselItem", "CarouselPrevious", "CarouselNext", "CarouselDots"], keywords: ["accessible", "all", "and", "announced", "any", "apg", "are", "arrow", "basis", "buttons", "carousel", "css", "default", "dot", "dots", "drag", "driven", "edge", "end", "fewer", "from", "gap", "hides", "keys", "label", "labeled", "left", "mouse", "name", "native", "not", "one", "overlaid", "page", "pages", "per", "projects", "region", "rem", "right", "row", "scroll", "scrolling", "semantics", "sized", "slide", "slides", "snap", "spring", "start", "the", "there", "total", "touch", "trackpad", "two", "variables", "view", "with", "work"], registryDependencies: ["button", "utils"] }, { name: "changelog", type: "registry:block", title: "Changelog", description: "Release notes on a Timeline: newest release highlighted, changes typed New / Improved / Fixed with Badges, and a Kbd shortcut to try the headline feature. Server-safe.", exports: ["Changelog"], keywords: ["are", "badges", "changes", "first", "highlighted", "how", "kbd", "newest", "notes", "one", "release", "releases", "shows", "the", "timeline", "try", "typed", "with"], registryDependencies: ["badge", "kbd", "timeline", "utils"] }, { name: "chart", type: "registry:ui", title: "Chart", description: "Line, area and bar (grouped or stacked) charts in SVG with a colorblind-validated eight-color palette that keeps each series' color. Crosshair tooltip listing every series, arrow-key readout, legend that hides series, direct end labels, a table view, and spring transitions between data.", exports: ["Chart"], keywords: ["add", "and", "are", "area", "areas", "arrow", "assistive", "axis", "bar", "bars", "bcp", "can", "captions", "categorical", "category", "chart", "charts", "compact", "crosshair", "currency", "data", "direct", "each", "eight", "end", "every", "filled", "fold", "for", "format", "grouping", "height", "hides", "index", "instead", "into", "key", "keys", "label", "labels", "legend", "line", "lines", "listing", "locale", "mark", "most", "names", "notation", "numbers", "object", "one", "only", "other", "pages", "palette", "past", "per", "plot", "plus", "props", "render", "row", "serializable", "series", "server", "split", "stack", "stacked", "style", "svg", "table", "tail", "tech", "that", "the", "them", "ticks", "too", "tooltip", "type", "usd", "value", "view", "with"], registryDependencies: ["button", "table", "use-dismiss", "utils"] }, { name: "checkbox", type: "registry:ui", title: "Checkbox", description: "Native checkbox with a spring-drawn check mark and an indeterminate state for select-all rows. Controlled or uncontrolled; submits with forms.", exports: ["Checkbox"], keywords: ["all", "called", "check", "checkbox", "checked", "controlled", "dash", "defaultchecked", "drawn", "field", "first", "indeterminate", "inside", "mixed", "native", "new", "oncheckedchange", "pair", "render", "rows", "select", "selected", "shows", "some", "spring", "state", "the", "uncontrolled", "with", "works"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "clip-card", type: "registry:block", title: "Clip Card", description: "Video tile: AspectRatio thumbnail (16:9 or 9:16), duration Badge, watched Progress along the bottom, and a ContextMenu of actions.", exports: ["ClipCard"], keywords: ["accessible", "actions", "ago", "along", "also", "and", "aspectratio", "badge", "bar", "bottom", "card", "click", "clip", "clips", "context", "contextmenuitem", "days", "duration", "f10", "film", "for", "glyph", "height", "how", "img", "items", "menu", "meta", "much", "name", "one", "opens", "print", "progress", "ratio", "right", "shift", "small", "stands", "the", "them", "thin", "thumbnail", "tile", "title", "under", "vertical", "video", "views", "was", "watched", "width", "without"], registryDependencies: ["aspect-ratio", "badge", "context-menu", "progress", "utils"] }, { name: "code", type: "registry:ui", title: "Code", description: "Shiki-highlighted code that follows light and dark through light-dark() token colors, as a block, an inline one-liner or a tabbed file panel. Line numbers (from any start line), tinted lines with an accent bar, <mark>ed words or column ranges, and per-line notes in a tooltip that keyboard users can tab to. Optional Prettier at display time; copy hands out exactly what is shown.", exports: ["CopyButton", "Code", "CodePanel"], keywords: ["accessible", "active", "add", "all", "and", "animates", "annotations", "bar", "bash", "before", "behind", "block", "body", "build", "button", "clipboard", "code", "collapse", "copied", "copy", "dark", "default", "dom", "each", "every", "excerpts", "file", "files", "first", "focus", "fold", "for", "format", "formatted", "from", "gets", "ghost", "gutter", "header", "highlight", "highlightcode", "highlighted", "highlighting", "hover", "ignored", "inline", "inside", "into", "its", "json", "keep", "label", "language", "least", "left", "light", "line", "linenumbers", "lines", "loads", "longer", "made", "many", "mark", "marks", "name", "never", "note", "notes", "number", "numbers", "one", "options", "own", "page", "paint", "panel", "per", "place", "prettier", "primary", "ranges", "refer", "registry", "remember", "renders", "run", "scrolling", "scrolls", "server", "sets", "shared", "shiki", "show", "source", "stays", "switching", "syntax", "tab", "terminal", "text", "than", "that", "the", "themes", "this", "time", "tint", "tokens", "too", "touch", "tsx", "turns", "variant", "vertically", "wheel", "with", "words", "wrapped", "written"], registryDependencies: ["button", "highlight", "overflow-focus", "tabs", "tooltip", "utils"] }, { name: "collapsible", type: "registry:ui", title: "Collapsible", description: "A single show/hide region with a spring height animation and rotating chevron. Controlled or uncontrolled; closed content stays in the DOM for SEO.", exports: ["Collapsible", "CollapsibleTrigger", "CollapsibleContent"], keywords: ["after", "and", "called", "chevron", "children", "closed", "collapsiblecontent", "collapsibletrigger", "content", "controlled", "crawlable", "default", "defaultopen", "first", "height", "hide", "html", "inert", "label", "mounted", "one", "onopenchange", "open", "pair", "region", "remains", "render", "rotating", "show", "springs", "state", "stays", "that", "the", "toggles", "trigger", "true", "uncontrolled", "when", "while", "with"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "combobox", type: "registry:ui", title: "Combobox", description: "A Select you can type into: the query filters by label and keywords (prefix matches first), arrows move, Enter picks. multiple keeps the list open and shows picks as removable tags. Submits through hidden inputs.", exports: ["Combobox"], keywords: ["accessible", "and", "aria", "backspace", "blocks", "called", "can", "choices", "closes", "controlled", "defaultvalue", "describedby", "disabled", "down", "emptytext", "enter", "error", "esc", "every", "field", "fills", "filtered", "filters", "first", "form", "from", "hidden", "hint", "ids", "input", "inputs", "into", "invalid", "keeps", "label", "last", "list", "matches", "move", "multiple", "name", "needs", "nothing", "one", "onvaluechange", "open", "opening", "options", "pair", "per", "pick", "picked", "picks", "placeholder", "removable", "removes", "render", "required", "select", "sets", "show", "shown", "shows", "single", "stay", "styling", "submit", "submits", "tags", "text", "the", "there", "through", "type", "types", "typing", "uncontrolled", "user", "value", "values", "visible", "when", "with", "you"], registryDependencies: ["field", "list", "platform", "tag-input", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "command", type: "registry:ui", title: "Command", description: "⌘K palette: filterable groups, arrow-key highlight, Enter to run, keyword matching. Inline or as CommandDialog with a global shortcut; the first Esc clears, the second closes.", exports: ["Command", "CommandInput", "CommandList", "CommandEmpty", "CommandGroup", "CommandSeparator", "CommandItem", "CommandDialog"], keywords: ["accessible", "after", "against", "and", "arrows", "but", "called", "children", "click", "close", "closes", "collapse", "command", "commanddialog", "commandempty", "commandinput", "commanditem", "commandlist", "content", "controlled", "ctrl", "defaults", "dialog", "disable", "disabled", "driven", "elsewhere", "end", "enter", "esc", "extra", "false", "filterable", "filtering", "for", "global", "group", "groups", "heading", "hidden", "hides", "home", "icon", "inline", "input", "inside", "item", "items", "its", "itself", "keepopen", "keyboard", "keywords", "label", "list", "listbox", "mac", "match", "matched", "matches", "mod", "move", "name", "none", "not", "only", "onopenchange", "onselect", "open", "option", "outside", "own", "pair", "palette", "pass", "passes", "placeholder", "preferences", "query", "results", "scrollable", "search", "selectable", "selecting", "selection", "selects", "separators", "settings", "shortcut", "shown", "shows", "stack", "state", "stay", "terms", "text", "the", "title", "toggle", "toggled", "use", "used", "value", "visible", "visually", "when", "while", "with", "would"], registryDependencies: ["dialog", "list", "search-input", "separator", "use-controllable-state", "use-hotkey", "utils"] }, { name: "confirm", type: "registry:ui", title: "Confirm", description: "Promise-based confirm dialog called like toast: await confirm({ title, description, destructive }) resolves true or false. Built on Dialog's alert mode, Cancel takes the first focus, Esc cancels, one host mounted in the layout.", exports: ["confirm", "Confirmer"], keywords: ["acting", "asks", "await", "before", "cancel", "confirm", "confirmer", "delete", "destructive", "esc", "false", "for", "host", "layout", "mount", "mounted", "needs", "newer", "next", "once", "project", "remove", "resolves", "root", "title", "toaster", "true"], registryDependencies: ["button", "dialog"] }, { name: "context-menu", type: "registry:ui", title: "Context Menu", description: "Right-click menu for an area, opening at the pointer and flipping at screen edges. Shares Dropdown Menu's items, checkbox and radio items, keyboard and typeahead; Menu key or Shift+F10 opens it from the keyboard.", exports: ["ContextMenuContent", "ContextMenuItem", "ContextMenuCheckboxItem", "ContextMenuRadioGroup", "ContextMenuRadioItem", "ContextMenuLabel", "ContextMenuSeparator", "ContextMenu", "ContextMenuTrigger"], keywords: ["actions", "align", "aligned", "and", "area", "but", "called", "center", "check", "checked", "children", "click", "clickable", "closes", "contextmenucontent", "contextmenutrigger", "destructive", "disabled", "dropdownmenuradioitem", "edge", "enter", "equals", "f10", "first", "focus", "focusable", "for", "group", "groups", "hint", "icon", "irreversible", "item", "items", "its", "key", "keyboard", "label", "labels", "leading", "lines", "mark", "menu", "new", "not", "oncheckedchange", "onopenchange", "onselect", "onvaluechange", "opens", "optionally", "picked", "pointer", "press", "red", "right", "selectable", "separators", "shift", "shortcut", "shown", "shows", "state", "the", "then", "trigger", "value", "variant", "when", "with"], registryDependencies: ["dropdown-menu", "utils"] }, { name: "count-to", type: "registry:ui", title: "CountTo", description: "Springs a number up from a start value once it scrolls into view. Prefix, suffix, decimals and locale.", exports: ["CountTo"], keywords: ["after", "and", "bcp", "before", "decimal", "decimals", "digits", "dom", "final", "for", "from", "grouping", "into", "locale", "number", "once", "point", "prefix", "scrolls", "seo", "springs", "starting", "stays", "suffix", "text", "the", "value", "view"], registryDependencies: ["utils"] }, { name: "custom-cursor", type: "registry:ui", title: "Custom Cursor", description: "Optional spring cursor that expands over interactive elements. Off on touch and reduced motion.", exports: ["CustomCursor"], keywords: ["coarse", "cursor", "dot", "elements", "expands", "interactive", "motion", "mount", "nothing", "once", "opt", "over", "pointers", "reduced", "renders", "ring", "spring", "touch", "trailing", "with"], registryDependencies: ["platform", "utils"] }, { name: "data-table", type: "registry:ui", title: "Data Table", description: "Table with columns as data: search across every column, sortable headers, checkbox selection that survives paging, a ⋯ menu per row, bulk actions in the toolbar and pagination. Built from Table, SearchInput, Checkbox, DropdownMenu, Pagination and Empty.", exports: ["DataTable"], keywords: ["accessor", "across", "actions", "all", "alternate", "and", "are", "backgrounds", "box", "bulk", "called", "cell", "checkbox", "client", "column", "columns", "compose", "controlled", "controls", "data", "defaultsort", "definitions", "display", "driven", "dropdownmenuitem", "each", "every", "field", "filters", "first", "for", "friends", "getrowid", "happen", "header", "ids", "items", "its", "jane", "kept", "label", "members", "menu", "name", "names", "onselectionchange", "order", "page", "pages", "pagesize", "pagination", "paging", "pair", "per", "placeholder", "readers", "receives", "render", "right", "row", "rowactions", "rowlabel", "rows", "screen", "search", "searchable", "searchplaceholder", "select", "selectable", "selected", "selection", "server", "show", "side", "sort", "sortable", "stable", "striped", "survives", "table", "that", "the", "toolbar", "with", "yourself"], registryDependencies: ["button", "checkbox", "dropdown-menu", "empty", "pagination", "search-input", "table", "use-controllable-state", "utils"] }, { name: "date-picker", type: "registry:ui", title: "Date Picker", description: "Field-styled button that opens a Calendar in a Popover, focused on the picked day. Single or range, presets such as Last 7 days, closes once the pick is complete, and submits ISO dates through a hidden input. Works inside Field.", exports: ["DatePicker"], keywords: ["accessible", "and", "are", "aria", "bcp", "beside", "blocks", "both", "button", "calendar", "called", "client", "closes", "controlled", "date", "day", "days", "default", "defaultvalue", "describedby", "disabled", "earliest", "end", "ends", "error", "extra", "field", "fill", "fills", "first", "focused", "for", "form", "from", "function", "grid", "hidden", "hint", "htmlfor", "ids", "input", "invalid", "isdisabled", "iso", "label", "last", "latest", "let", "locale", "max", "min", "mode", "monday", "name", "needs", "nothing", "null", "off", "once", "one", "only", "onvaluechange", "opening", "opens", "optional", "pair", "pick", "picked", "placeholder", "popover", "presets", "range", "reach", "readers", "ready", "render", "required", "rule", "saturday", "selectable", "set", "sets", "shortcuts", "single", "start", "styled", "styling", "submit", "submits", "sunday", "text", "that", "the", "then", "there", "these", "through", "today", "uncontrolled", "value", "visible", "weekends", "weekstartson", "when", "with"], registryDependencies: ["calendar", "field", "input", "popover", "use-controllable-state", "utils"] }, { name: "dialog", type: "registry:ui", title: "Dialog", description: "Portal modal with blurred backdrop, spring scale-in, focus trap, Esc and scroll lock.", exports: ["useDialog", "Dialog", "DialogTrigger", "DialogClose", "useModal", "DialogContent", "DialogHeader", "DialogFooter", "DialogTitle", "DialogDescription"], keywords: ["action", "alert", "alertdialog", "also", "and", "aria", "armed", "attach", "backdrop", "before", "behavior", "blur", "blurred", "body", "button", "called", "check", "children", "click", "close", "confirm", "confirmlabel", "confirmtimeout", "controlled", "corner", "default", "defaultopen", "defaults", "destructive", "dialog", "dialogclose", "dialogcontent", "dialogs", "dialogtrigger", "disables", "does", "done", "drawer", "emphasis", "esc", "feedback", "field", "fill", "first", "focus", "footer", "for", "give", "header", "height", "icon", "irreversible", "its", "label", "left", "loading", "loadinglabel", "lock", "modal", "mode", "never", "not", "off", "old", "onclick", "one", "ones", "only", "onopenchange", "open", "out", "padding", "page", "pair", "panel", "per", "place", "portal", "primary", "ref", "render", "reserved", "resets", "resize", "restore", "returned", "role", "root", "runs", "scale", "scroll", "second", "shared", "showclose", "shown", "shows", "size", "slides", "spinner", "spins", "spring", "square", "state", "status", "step", "success", "successlabel", "swap", "swaps", "tab", "text", "the", "this", "topmost", "trap", "trigger", "two", "uncontrolled", "variant", "view", "where", "while", "width", "with"], registryDependencies: ["button", "platform", "use-controllable-state", "utils"] }, { name: "drawer", type: "registry:ui", title: "Drawer", description: "Edge panel (left, right, top, bottom) that springs in and swipes away. Shares Dialog's focus trap, scroll lock and Esc handling. Sidebar uses it below md.", exports: ["Drawer", "DrawerTrigger", "DrawerClose", "DrawerTitle", "DrawerDescription", "DrawerContent", "DrawerHeader", "DrawerBody", "DrawerFooter"], keywords: ["action", "also", "and", "anywhere", "aria", "armed", "backdrop", "before", "blur", "body", "bottom", "button", "called", "can", "check", "children", "click", "close", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "corner", "default", "defaultopen", "defaults", "destructive", "dialogclose", "dialogcontent", "dialogtrigger", "disables", "dismiss", "done", "drag", "drawer", "drawers", "edge", "emphasis", "esc", "feedback", "fill", "first", "footer", "for", "from", "give", "handle", "header", "height", "icon", "irreversible", "its", "label", "left", "loading", "loadinglabel", "never", "old", "onclick", "one", "ones", "onopenchange", "open", "out", "padding", "pair", "panel", "per", "place", "primary", "render", "reserved", "resets", "resize", "runs", "scroll", "scrolls", "second", "showclose", "shown", "shows", "side", "size", "slides", "spinner", "spins", "spring", "square", "state", "status", "step", "success", "successlabel", "swap", "swaps", "swipe", "taller", "text", "than", "that", "the", "their", "this", "top", "toward", "trigger", "two", "uncontrolled", "variant", "view", "when", "where", "while", "width", "with"], registryDependencies: ["dialog", "platform", "utils"] }, { name: "dropdown-menu", type: "registry:ui", title: "Dropdown Menu", description: "Action menu anchored to a Button: items with icons and shortcuts, checkbox and radio items, labels, separators, destructive variant. Arrow keys, typeahead, focus follows the pointer, Esc returns focus.", exports: ["MenuContext", "DropdownMenu", "DropdownMenuTrigger", "DropdownMenuContent", "DropdownMenuItem", "DropdownMenuCheckboxItem", "DropdownMenuRadioGroup", "DropdownMenuRadioItem", "DropdownMenuLabel", "DropdownMenuSeparator"], keywords: ["action", "actions", "align", "aligned", "also", "anchored", "and", "aria", "armed", "before", "blur", "but", "button", "called", "check", "checked", "children", "choice", "click", "closes", "closing", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "default", "defaultopen", "defaults", "destructive", "disabled", "disables", "done", "down", "dropdownmenuradioitem", "edge", "emphasis", "enter", "equals", "esc", "feedback", "fill", "first", "for", "give", "group", "groups", "height", "hint", "icon", "irreversible", "item", "items", "its", "keeps", "keyboard", "label", "labels", "last", "leading", "left", "lines", "loading", "loadinglabel", "mark", "menu", "never", "new", "not", "old", "oncheckedchange", "onclick", "one", "ones", "onopenchange", "onselect", "onvaluechange", "open", "opens", "optionally", "out", "outside", "padding", "pair", "per", "picked", "picking", "place", "primary", "radiogroup", "red", "render", "reserved", "resets", "resize", "right", "runs", "second", "selectable", "selection", "separators", "shortcut", "shown", "shows", "size", "slides", "space", "spinner", "spins", "square", "state", "status", "step", "success", "successlabel", "swap", "swaps", "text", "the", "then", "this", "toggles", "trigger", "two", "uncontrolled", "value", "variant", "view", "when", "where", "while", "width", "with", "without"], registryDependencies: ["button", "list", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "empty", type: "registry:ui", title: "Empty", description: "Server-safe empty state: icon tile, title, one helpful sentence and the next action. Bordered variant for empty lists and drop zones.", exports: ["Empty"], keywords: ["about", "action", "and", "app", "area", "bordered", "children", "clips", "dashed", "description", "drop", "empty", "for", "helpful", "icon", "inside", "like", "list", "next", "one", "outline", "page", "rounded", "sentence", "shown", "state", "the", "tile", "title", "what", "yet", "zone"], registryDependencies: ["utils"] }, { name: "field", type: "registry:ui", title: "Field", description: "Label, control, description and error as one unit. Controls inside (Input, Textarea, Select, Checkbox, Switch, RadioGroup) get id, aria-describedby, aria-invalid and required automatically; errors spring in and are announced.", exports: ["useFieldControl", "Field"], keywords: ["and", "aria", "automatically", "beside", "checkbox", "children", "control", "controls", "describedby", "description", "dims", "disabled", "disables", "enclosing", "error", "explicit", "field", "fills", "first", "for", "form", "from", "hint", "horizontal", "ids", "invalid", "its", "label", "makes", "marks", "match", "must", "one", "orientation", "out", "outside", "own", "picks", "props", "renders", "required", "returns", "shown", "springs", "state", "switch", "the", "unchanged", "under", "unit", "use", "when", "win", "wired", "with"], registryDependencies: ["label", "utils"] }, { name: "highlight", type: "registry:lib", description: "Lines of colored tokens, with Shiki loaded on demand. Runs anywhere: Code calls it in the\nbrowser, and a Server Component or a build can call it ahead of time and pass the result as\n`tokens`, so the browser never loads Shiki. Null for unknown languages.", exports: ["highlightCode", "languageOf"], keywords: ["ahead", "and", "anywhere", "back", "browser", "build", "call", "calls", "can", "code", "colored", "component", "demand", "extension", "falls", "file", "for", "from", "language", "languages", "lines", "loaded", "loads", "name", "never", "null", "pass", "result", "runs", "server", "shiki", "the", "time", "tokens", "tsx", "unknown", "with"], registryDependencies: [] }, { name: "hover-card", type: "registry:ui", title: "Hover Card", description: "Rich preview (profile, product, clip) that opens after a hover delay or keyboard focus. The pointer can move into the card; supplementary only.", exports: ["HoverCard"], keywords: ["acts", "align", "alignment", "avatar", "before", "bio", "can", "card", "children", "clip", "closedelay", "closes", "content", "first", "flips", "focus", "hover", "into", "keyboard", "leaves", "link", "move", "must", "once", "only", "opendelay", "opens", "pointer", "preferred", "preview", "product", "profile", "rich", "room", "second", "side", "stats", "supplementary", "tap", "the", "there", "time", "touch", "trigger", "usually", "when", "with", "without", "work"], registryDependencies: ["platform", "use-anchor", "use-dismiss", "use-hover-open", "utils"] }, { name: "input", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["fieldClass", "Input"], keywords: ["and", "aria", "chrome", "field", "filled", "group", "handed", "inputgroup", "inside", "the", "works"], registryDependencies: ["field", "utils"] }, { name: "input-group", type: "registry:ui", title: "Input Group", description: "Server-safe wrapper that fuses an Input with icons, text (https://, USD) or buttons into one field with a shared border and focus ring. Clicking an addon focuses the input.", exports: ["InputGroup", "InputGroupAddon"], keywords: ["addons", "align", "and", "beside", "border", "button", "buttons", "clicking", "control", "data", "draws", "drops", "field", "focus", "focuses", "group", "https", "icon", "icons", "inner", "input", "its", "like", "made", "matched", "one", "own", "plain", "plus", "ring", "side", "sits", "slot", "text", "the"], registryDependencies: ["utils"] }, { name: "input-otp", type: "registry:ui", title: "Input OTP", description: "One-time code in separate slots, backed by one real input: paste and SMS autofill work, screen readers hear one field. Grouped slots, numeric or alphanumeric, characters spring in, onComplete to submit. verified turns each character into a check, then merges them into one mark.", exports: ["InputOTP"], keywords: ["accepted", "again", "allowed", "alphanumeric", "and", "announced", "are", "autocomplete", "autofill", "back", "beside", "between", "called", "change", "character", "characters", "charset", "check", "code", "controlled", "counts", "dash", "defaultvalue", "draws", "dropped", "each", "edit", "every", "false", "filled", "fires", "first", "for", "group", "groups", "input", "into", "label", "laid", "length", "mark", "merge", "merged", "number", "once", "oncomplete", "one", "only", "onvaluechange", "others", "over", "pair", "paste", "pasted", "per", "read", "readers", "real", "render", "screen", "set", "shown", "single", "sits", "slides", "slot", "slots", "sms", "submit", "the", "then", "time", "transparently", "turns", "typed", "uncontrolled", "uppercased", "value", "verified", "verifiedlabel", "via", "visual", "was", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "kbd", type: "registry:ui", title: "Kbd", description: "Server-safe key caps for shortcut hints. KbdGroup nests keys per the HTML spec.", exports: ["Kbd", "KbdGroup"], keywords: ["cap", "html", "kbd", "kbdgroup", "key", "keys", "made", "nested", "one", "per", "several", "shortcut", "spec", "the"], registryDependencies: ["utils"] }, { name: "label", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Label"], keywords: [], registryDependencies: ["utils"] }, { name: "list", type: "registry:lib", description: "The item a navigation key moves to in a list, from the item at `index` (-1: none active).\nUndefined when the key doesn't navigate.", exports: ["listKeyTarget", "scrollIntoList"], keywords: ["active", "box", "can", "doesn", "enough", "from", "index", "item", "just", "key", "list", "moves", "moving", "navigate", "navigation", "none", "page", "scrollintoview", "scrolls", "show", "the", "undefined", "way", "when", "without"], registryDependencies: ["utils"] }, { name: "marker", type: "registry:ui", title: "Marker", description: "Highlighter-pen <mark> in four tints that wraps cleanly across lines and can draw itself on, left to right, when it scrolls into view. Highlight marks every match of a search in a string, for transcripts and search results.", exports: ["Marker", "Highlight"], keywords: ["across", "before", "case", "cleanly", "color", "delay", "draw", "drawing", "draws", "every", "first", "full", "fully", "highlight", "highlighter", "insensitive", "inside", "instant", "into", "left", "lines", "mark", "markers", "marks", "match", "motion", "one", "paragraph", "pen", "query", "reduced", "right", "scrolls", "search", "seconds", "several", "shown", "stagger", "sweeps", "term", "terms", "text", "the", "time", "view", "with", "without", "wraps"], registryDependencies: ["utils"] }, { name: "menubar", type: "registry:ui", title: "Menubar", description: "Desktop-style menu bar on the WAI-ARIA menubar pattern: one menu open at a time, hovering the next title while one is open switches to it, ← → walk the bar with or without a menu open, one Tab stop. A single highlight springs between titles; menus reuse every DropdownMenu item.", exports: ["MenubarContent", "MenubarItem", "MenubarCheckboxItem", "MenubarRadioGroup", "MenubarRadioItem", "MenubarLabel", "MenubarSeparator", "Menubar", "MenubarMenu", "MenubarTrigger"], keywords: ["actions", "align", "aligned", "analytics", "and", "another", "apart", "bar", "between", "but", "called", "check", "checked", "children", "click", "closes", "desktop", "destructive", "disabled", "down", "dropdownmenuradioitem", "edge", "enter", "equals", "first", "for", "generated", "give", "group", "groups", "highlight", "hint", "hovering", "icon", "irreversible", "item", "items", "its", "label", "labels", "last", "leading", "left", "lines", "mark", "menu", "menubarcontent", "menubartrigger", "menus", "move", "new", "not", "omitted", "oncheckedchange", "one", "onselect", "onvaluechange", "open", "opens", "optional", "optionally", "picked", "red", "right", "selectable", "separators", "shortcut", "shown", "shows", "space", "springs", "stable", "state", "style", "switches", "tell", "tests", "the", "then", "time", "title", "titles", "toggles", "trigger", "value", "variant", "when", "while", "with"], registryDependencies: ["dropdown-menu", "list", "use-indicator", "utils"] }, { name: "message-bubble", type: "registry:ui", title: "Message Bubble", description: "User/assistant chat bubbles with avatar slot, streaming dots and copyable code blocks.", exports: ["MessageBubble"], keywords: ["above", "accent", "after", "and", "animated", "are", "assistant", "attachments", "avatar", "bubble", "chat", "children", "code", "content", "dots", "from", "inline", "left", "lists", "message", "name", "next", "rich", "right", "sender", "shown", "shows", "side", "size", "slot", "streaming", "surface", "text", "the", "time", "typing", "user"], registryDependencies: ["utils"] }, { name: "meter", type: "registry:ui", title: "Meter", description: "Server-safe gauge for a value in a known range (storage, quota, server load, password strength). Colors by <meter> thresholds, or stacked segments with a legend, like a storage bar.", exports: ["Meter"], keywords: ["above", "accessible", "also", "and", "away", "bar", "below", "between", "bound", "color", "colors", "decides", "defaults", "disk", "follow", "good", "green", "high", "known", "label", "legend", "like", "load", "low", "lower", "max", "measurement", "meter", "min", "name", "not", "one", "optimum", "orange", "overrides", "parts", "password", "progress", "quota", "range", "red", "region", "right", "segments", "server", "stacked", "storage", "strength", "sum", "task", "text", "the", "their", "this", "threshold", "thresholds", "total", "two", "upper", "use", "used", "value", "valuetext", "visible", "where", "with", "within"], registryDependencies: ["utils"] }, { name: "motion-provider", type: "registry:component", exports: ["MotionProvider"], keywords: [], registryDependencies: ["utils"] }, { name: "native-select", type: "registry:ui", title: "Native Select", description: "A real <select> with option groups: native picker on phones, no-JS forms, native required validation. Where customizable select is supported (appearance: base-select), the open list gets the menu look.", exports: ["NativeSelect", "NativeSelectGroup", "NativeSelectOption"], keywords: ["appearance", "base", "browser", "custom", "customizable", "elsewhere", "forms", "gets", "group", "heading", "icons", "instead", "invalid", "label", "labeled", "list", "look", "menu", "native", "need", "open", "optgroup", "options", "phones", "picker", "real", "rendering", "required", "select", "stays", "supports", "the", "use", "user", "validation", "when", "where", "without", "works"], registryDependencies: ["field", "input", "utils"] }, { name: "navigation-menu", type: "registry:ui", title: "Navigation Menu", description: "Website top navigation on the APG disclosure pattern: plain links and panels of rich links. Hover opens after a beat, then sliding along the bar switches panels at once; every panel shares one viewport that springs to the next panel's size and position while the content slides in from the side you moved toward. Click, Enter, ↓, ← → and Esc work; closed panels keep their links in the HTML for crawlers.", exports: ["NavigationMenu", "NavigationMenuList", "NavigationMenuItem", "NavigationMenuTrigger", "NavigationMenuContent", "NavigationMenuLink"], keywords: ["active", "after", "all", "along", "and", "aria", "bar", "beat", "bold", "called", "children", "classname", "click", "closed", "closes", "content", "controlled", "crawlers", "current", "defaultvalue", "description", "down", "enter", "entry", "esc", "find", "first", "focuses", "following", "for", "generated", "hidden", "hover", "html", "icon", "inset", "into", "item", "items", "its", "left", "level", "line", "link", "links", "look", "matched", "menu", "mouse", "muted", "navigation", "omitted", "once", "one", "onvaluechange", "open", "opened", "opens", "optional", "own", "padding", "page", "pair", "panel", "panels", "pill", "plain", "readers", "rem", "render", "rich", "right", "row", "selected", "single", "size", "sliding", "space", "springs", "stable", "stay", "still", "switches", "the", "them", "then", "tile", "title", "toggle", "top", "trigger", "uncontrolled", "under", "value", "viewport", "walk", "website", "while", "with", "your"], registryDependencies: ["use-controllable-state", "use-dismiss", "use-indicator", "utils"] }, { name: "newsletter", type: "registry:block", title: "Newsletter", description: "Email signup: InputGroup with the submit Button inside, native email validation, a loading → success toast and an in-place success state on the button.", exports: ["Newsletter"], keywords: ["above", "address", "after", "and", "button", "check", "confirm", "confirms", "description", "email", "field", "for", "form", "heading", "inbox", "inputgroup", "inside", "into", "its", "line", "loading", "message", "native", "next", "onsubscribe", "place", "placeholder", "rejection", "resets", "resolves", "saved", "shows", "signup", "submit", "submitlabel", "success", "successmessage", "supporting", "text", "that", "the", "then", "title", "toast", "turns", "under", "validation", "when", "with", "your"], registryDependencies: ["button", "input", "input-group", "toast", "utils"] }, { name: "number-input", type: "registry:ui", title: "Number Input", description: "Native number field with −/+ buttons: arrow keys, min/max/step validation and form submit from the platform; clamps on blur, rounds to the step's precision.", exports: ["NumberInput"], keywords: ["amount", "and", "are", "arrows", "arrowup", "buttons", "called", "cart", "change", "controlled", "defaultvalue", "down", "field", "first", "form", "helpers", "highest", "keyboard", "lowest", "max", "min", "native", "new", "number", "onvaluechange", "pair", "pointer", "quantity", "render", "step", "submit", "tabindex", "the", "uncontrolled", "use", "users", "validation", "value", "with"], registryDependencies: ["input", "input-group", "use-controllable-state", "utils"] }, { name: "overflow-focus", type: "registry:lib", description: `Drop inside a scroll container: while the container overflows it becomes keyboard-focusable
17251
+ index: [{ name: "accent-picker", type: "registry:ui", title: "Accent Picker", description: "Accent color row: eight swatches (red to slate) that retint primary, focus rings, selection, switches and checkboxes app-wide. Persisted, applied before paint, or set your own hue with --accent-hue.", exports: ["AccentPicker"], keywords: ["accent", "app", "color", "radio", "retint", "row", "setaccent", "swatches", "that", "the", "via", "whole"], registryDependencies: ["theme", "utils"] }, { name: "accordion", type: "registry:ui", title: "Accordion", description: "Single or multiple panels with spring height animation. Closed content stays in the DOM for SEO.", exports: ["Accordion", "AccordionItem", "AccordionTrigger", "AccordionContent"], keywords: ["accordion", "accordioncontent", "accordionitem", "accordiontrigger", "allow", "and", "called", "children", "closed", "closes", "closing", "collapsible", "content", "controlled", "crawlable", "default", "defaultvalue", "every", "first", "heading", "height", "html", "independent", "inert", "item", "items", "level", "match", "matched", "mounted", "multiple", "none", "one", "only", "onvaluechange", "open", "outline", "page", "panel", "panels", "question", "remains", "render", "single", "stays", "text", "the", "time", "type", "uncontrolled", "unique", "value", "when", "while", "with", "within", "wrapping"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "alert", type: "registry:ui", title: "Alert", description: "Server-safe inline banner: tinted surface, colored icon, title, description and an optional action. Info, success, warning and destructive tones follow the accent and status tokens.", exports: ["Alert", "AlertTitle", "AlertDescription"], keywords: ["action", "add", "alert", "aligned", "and", "announced", "appears", "banner", "button", "colored", "default", "description", "did", "for", "icon", "inline", "live", "load", "none", "not", "null", "pass", "region", "replaces", "response", "right", "role", "sets", "should", "slot", "small", "something", "static", "surface", "the", "tint", "tinted", "title", "tone", "user", "variant", "when"], registryDependencies: ["utils"] }, { name: "app-window", type: "registry:ui", title: "AppWindow", description: "Window container with close / minimize / zoom controls, title, custom header slot and actions. SegmentedTabs is the compact view switcher for its title bar.", exports: ["AppWindow"], keywords: ["actions", "aligned", "area", "bar", "blurred", "bodyclassname", "button", "called", "centered", "classes", "content", "control", "custom", "dot", "for", "glass", "handler", "header", "into", "matching", "maximize", "minimize", "navbar", "onclose", "onmaximize", "onminimize", "passing", "pressed", "replaces", "right", "search", "shows", "slot", "surface", "tabs", "text", "the", "title", "titlebar", "translucent", "turns", "under", "when"], registryDependencies: ["utils"] }, { name: "aspect-ratio", type: "registry:ui", title: "Aspect Ratio", description: "Server-safe box locked to a ratio (16:9 thumbnails, 9:16 clips). A direct image or video child fills it with object-cover.", exports: ["AspectRatio"], keywords: ["box", "child", "cover", "direct", "fills", "height", "img", "locked", "object", "ratio", "video", "width"], registryDependencies: ["utils"] }, { name: "attachment", type: "registry:ui", title: "Attachment & Dropzone", description: "File chips with image thumbnails or type icons, size, a springing upload bar, error state and remove; the list springs chips in and closes the gap. FileDropzone wraps a real file input: click, keyboard and the native picker work, drop and paste are checked against accept and maxSize, and dropped files land in the input so forms and Server Actions receive them.", exports: ["formatBytes", "Attachment", "AttachmentList", "FileDropzone"], keywords: ["accept", "actions", "along", "and", "are", "area", "aria", "around", "attachments", "attribute", "back", "bar", "bcp", "blocks", "both", "bottom", "browse", "button", "bytes", "called", "child", "children", "chip", "click", "content", "createobjecturl", "default", "describedby", "disabled", "download", "drop", "dropped", "drops", "each", "edge", "enforced", "enter", "error", "failed", "field", "file", "files", "fills", "for", "form", "forms", "fresh", "from", "get", "given", "hint", "href", "icon", "ids", "image", "input", "into", "invalid", "key", "least", "line", "link", "locale", "makes", "maxsize", "mime", "more", "multiple", "name", "native", "needs", "one", "onfiles", "onreject", "onremove", "out", "passed", "paste", "pdf", "picked", "picker", "picks", "place", "plain", "pressed", "progress", "real", "reason", "red", "remove", "removed", "replaces", "required", "same", "server", "sets", "show", "shows", "size", "source", "space", "spring", "springs", "src", "styling", "submit", "syntax", "text", "than", "that", "the", "them", "thumbnail", "too", "turns", "type", "types", "upload", "uploading", "url", "when", "while", "with", "work", "written"], registryDependencies: ["field", "utils"] }, { name: "avatar", type: "registry:ui", title: "Avatar", description: "Image with initials fallback on error, three sizes and online/away/busy/offline dots.", exports: ["Avatar"], keywords: ["alt", "and", "announced", "corner", "diameter", "dot", "fails", "fallback", "for", "icon", "image", "initials", "loads", "name", "overrides", "person", "presence", "show", "size", "src", "status", "text", "the", "url", "used", "while", "with"], registryDependencies: ["utils"] }, { name: "avatar-group", type: "registry:ui", title: "AvatarGroup", description: "Overlapping avatars with a +N overflow chip. Hover gently enlarges the avatar on a spring, keeping stack order.", exports: ["AvatarGroup"], keywords: ["alt", "and", "avatar", "avatars", "before", "chip", "each", "enlarges", "every", "gently", "hover", "how", "many", "max", "name", "one", "order", "overflow", "overlapping", "people", "show", "size", "spring", "stack", "staying", "the", "users", "with"], registryDependencies: ["avatar", "utils"] }, { name: "badge", type: "registry:ui", title: "Badge & Pill", description: "Minimal status tags. Rounded badge or fully rounded pill, with optional dot. pulse adds an expanding live-status ring.", exports: ["Badge"], keywords: ["and", "color", "current", "dot", "emits", "expanding", "forever", "fully", "leading", "like", "live", "needs", "pill", "pulse", "ring", "rounded", "shape", "status", "surface", "tag", "text", "the", "variant"], registryDependencies: ["utils"] }, { name: "breadcrumb", type: "registry:ui", title: "Breadcrumb", description: "Navigation trail from a list of items: links up to the current page, which is marked for assistive tech. Server-safe, custom separator.", exports: ["Breadcrumb"], keywords: ["between", "chevron", "current", "default", "drawn", "ending", "first", "item", "items", "last", "links", "list", "outermost", "page", "safe", "separator", "server", "site", "sits", "the", "trail", "where"], registryDependencies: [] }, { name: "button", type: "registry:ui", title: "Button", description: "Five variants, four sizes, spring press feedback, an animated loading spinner and in-place success state, a two-step confirm that swaps the label on first click, and a configurable swap direction. Width stays fixed to the longest label.", exports: ["Button"], keywords: ["action", "also", "and", "aria", "armed", "before", "blur", "both", "button", "can", "check", "children", "click", "clicks", "confirm", "confirmlabel", "confirmtimeout", "default", "defaults", "destructive", "done", "emphasis", "enter", "esc", "feedback", "fill", "first", "focusable", "for", "form", "give", "height", "icon", "ignore", "ignores", "irreversible", "its", "label", "left", "loading", "loadinglabel", "never", "old", "onclick", "one", "ones", "out", "padding", "per", "place", "primary", "reserved", "resets", "resize", "runs", "second", "shown", "shows", "size", "slides", "spinner", "spins", "square", "status", "stays", "step", "submit", "success", "successlabel", "swap", "swaps", "text", "the", "this", "twice", "two", "variant", "view", "where", "while", "width", "with"], registryDependencies: ["button-variants", "utils"] }, { name: "button-group", type: "registry:ui", title: "Button Group", description: "Joins buttons into one strip that shares borders, corners and active states. Horizontal or vertical.", exports: ["ButtonGroup"], keywords: ["and", "attached", "borders", "buttons", "connected", "control", "corners", "default", "fuse", "groups", "horizontal", "into", "orientation", "related", "single", "strip", "together", "toolbar", "true", "vertical"], registryDependencies: ["utils"] }, { name: "button-variants", type: "registry:ui", description: 'Button classes for non-button elements, e.g. `<a className={buttonVariants({ variant: "outline" })}>`.', exports: ["buttonVariants"], keywords: ["button", "buttonvariants", "classes", "classname", "elements", "for", "non", "outline", "variant"], registryDependencies: ["utils"] }, { name: "calendar", type: "registry:ui", title: "Calendar", description: "Month grid on the WAI-ARIA date-grid pattern: single date or range with a hover preview, min/max and custom disabled days, months that slide in from the direction of travel. Arrows, Home/End and PageUp/PageDown (+Shift for years). Hydration-safe: today is only marked in the browser.", exports: ["key", "Calendar"], keywords: ["and", "another", "any", "aria", "arrows", "autofocus", "bcp", "called", "client", "controlled", "current", "custom", "date", "datepicker", "dates", "day", "days", "default", "defaultmonth", "defaultvalue", "direction", "disabled", "displayed", "earliest", "end", "ends", "extra", "first", "focus", "for", "from", "function", "grid", "home", "hover", "into", "isdisabled", "iso", "keyboard", "latest", "like", "local", "locale", "max", "min", "mode", "monday", "month", "months", "mount", "names", "nothing", "null", "off", "one", "only", "onmonthchange", "onvaluechange", "pagedown", "pages", "pageup", "pattern", "pick", "picked", "preview", "range", "render", "rule", "saturday", "selectable", "sets", "shift", "shown", "single", "slide", "sorts", "start", "sunday", "the", "then", "this", "travel", "uncontrolled", "user", "value", "wai", "week", "weekday", "weekends", "weekstartson", "when", "with", "year", "yyyy"], registryDependencies: ["button", "use-controllable-state", "utils"] }, { name: "card", type: "registry:ui", title: "Card", description: "Composable surface: header, title, description, content and footer. Optional glass.", exports: ["Card", "CardHeader", "CardTitle", "CardDescription", "CardContent", "CardFooter"], keywords: ["backgrounds", "colored", "default", "directly", "fits", "follows", "glass", "heading", "level", "not", "outline", "over", "page", "place", "subtle", "textured", "that", "the", "translucency", "under", "when"], registryDependencies: ["utils"] }, { name: "carousel", type: "registry:ui", title: "Carousel", description: "Native scroll-snap row, so touch, trackpad and no-JS scrolling work, with spring-driven arrows, page dots, arrow keys and mouse drag that throws to the next snap point. APG carousel semantics: a labeled region of slides announced as 3 of 8.", exports: ["Carousel", "CarouselContent", "CarouselItem", "CarouselPrevious", "CarouselNext", "CarouselDots"], keywords: ["accessible", "all", "and", "announced", "any", "apg", "are", "arrow", "basis", "buttons", "carousel", "css", "default", "dot", "dots", "drag", "driven", "edge", "end", "fewer", "from", "gap", "hides", "keys", "label", "labeled", "left", "mouse", "name", "native", "not", "one", "overlaid", "page", "pages", "per", "projects", "region", "rem", "right", "row", "scroll", "scrolling", "semantics", "sized", "slide", "slides", "snap", "spring", "start", "the", "there", "total", "touch", "trackpad", "two", "variables", "view", "with", "work"], registryDependencies: ["button", "utils"] }, { name: "changelog", type: "registry:block", title: "Changelog", description: "Release notes on a Timeline: newest release highlighted, changes typed New / Improved / Fixed with Badges, and a Kbd shortcut to try the headline feature. Server-safe.", exports: ["Changelog"], keywords: ["are", "badges", "changes", "first", "highlighted", "how", "kbd", "newest", "notes", "one", "release", "releases", "shows", "the", "timeline", "try", "typed", "with"], registryDependencies: ["badge", "kbd", "timeline", "utils"] }, { name: "chart", type: "registry:ui", title: "Chart", description: "Line, area and bar (grouped or stacked) charts in SVG with a colorblind-validated eight-color palette that keeps each series' color. Crosshair tooltip listing every series, arrow-key readout, legend that hides series, direct end labels, a table view, and spring transitions between data.", exports: ["Chart"], keywords: ["add", "and", "are", "area", "areas", "arrow", "assistive", "axis", "bar", "bars", "bcp", "can", "captions", "categorical", "category", "chart", "charts", "compact", "crosshair", "currency", "data", "direct", "each", "eight", "end", "every", "filled", "fold", "for", "format", "grouping", "height", "hides", "index", "instead", "into", "key", "keys", "label", "labels", "legend", "line", "lines", "listing", "locale", "mark", "most", "names", "notation", "numbers", "object", "one", "only", "other", "pages", "palette", "past", "per", "plot", "plus", "props", "render", "row", "serializable", "series", "server", "split", "stack", "stacked", "style", "svg", "table", "tail", "tech", "that", "the", "them", "ticks", "too", "tooltip", "type", "usd", "value", "view", "with"], registryDependencies: ["button", "table", "use-dismiss", "utils"] }, { name: "checkbox", type: "registry:ui", title: "Checkbox", description: "Native checkbox with a spring-drawn check mark and an indeterminate state for select-all rows. Controlled or uncontrolled; submits with forms.", exports: ["Checkbox"], keywords: ["all", "called", "check", "checkbox", "checked", "controlled", "dash", "defaultchecked", "drawn", "field", "first", "indeterminate", "inside", "mixed", "native", "new", "oncheckedchange", "pair", "render", "rows", "select", "selected", "shows", "some", "spring", "state", "the", "uncontrolled", "with", "works"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "clip-card", type: "registry:block", title: "Clip Card", description: "Video tile: AspectRatio thumbnail (16:9 or 9:16), duration Badge, watched Progress along the bottom, and a ContextMenu of actions.", exports: ["ClipCard"], keywords: ["accessible", "actions", "ago", "along", "also", "and", "aspectratio", "badge", "bar", "bottom", "card", "click", "clip", "clips", "context", "contextmenuitem", "days", "duration", "f10", "film", "for", "glyph", "height", "how", "img", "items", "menu", "meta", "much", "name", "one", "opens", "print", "progress", "ratio", "right", "shift", "small", "stands", "the", "them", "thin", "thumbnail", "tile", "title", "under", "vertical", "video", "views", "was", "watched", "width", "without"], registryDependencies: ["aspect-ratio", "badge", "context-menu", "progress", "utils"] }, { name: "code", type: "registry:ui", title: "Code", description: "Shiki-highlighted code that follows light and dark through light-dark() token colors, as a block, an inline one-liner or a tabbed file panel. Line numbers (from any start line), tinted lines with an accent bar, <mark>ed words or column ranges, and per-line notes in a tooltip that keyboard users can tab to. Optional Prettier at display time; copy hands out exactly what is shown.", exports: ["CopyButton", "Code", "CodePanel"], keywords: ["accessible", "active", "add", "all", "and", "animates", "annotations", "bar", "bash", "before", "behind", "block", "body", "build", "button", "clipboard", "code", "collapse", "copied", "copy", "dark", "default", "dom", "each", "every", "excerpts", "file", "files", "first", "focus", "fold", "for", "format", "formatted", "from", "gets", "ghost", "gutter", "header", "highlight", "highlightcode", "highlighted", "highlighting", "hover", "ignored", "inline", "inside", "into", "its", "json", "keep", "label", "language", "least", "left", "light", "line", "linenumbers", "lines", "loads", "longer", "made", "many", "mark", "marks", "name", "never", "note", "notes", "number", "numbers", "one", "options", "own", "page", "paint", "panel", "per", "place", "prettier", "primary", "ranges", "refer", "registry", "remember", "renders", "run", "scrolling", "scrolls", "server", "sets", "shared", "shiki", "show", "source", "stays", "switching", "syntax", "tab", "terminal", "text", "than", "that", "the", "themes", "this", "time", "tint", "tokens", "too", "touch", "tsx", "turns", "variant", "vertically", "wheel", "with", "words", "wrapped", "written"], registryDependencies: ["button", "highlight", "overflow-focus", "tabs", "tooltip", "utils"] }, { name: "collapsible", type: "registry:ui", title: "Collapsible", description: "A single show/hide region with a spring height animation and rotating chevron. Controlled or uncontrolled; closed content stays in the DOM for SEO.", exports: ["Collapsible", "CollapsibleTrigger", "CollapsibleContent"], keywords: ["after", "and", "called", "chevron", "children", "closed", "collapsiblecontent", "collapsibletrigger", "content", "controlled", "crawlable", "default", "defaultopen", "first", "height", "hide", "html", "inert", "label", "mounted", "one", "onopenchange", "open", "pair", "region", "remains", "render", "rotating", "show", "springs", "state", "stays", "that", "the", "toggles", "trigger", "true", "uncontrolled", "when", "while", "with"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "combobox", type: "registry:ui", title: "Combobox", description: "A Select you can type into: the query filters by label and keywords (prefix matches first), arrows move, Enter picks. multiple keeps the list open and shows picks as removable tags. Submits through hidden inputs.", exports: ["Combobox"], keywords: ["accessible", "and", "aria", "backspace", "blocks", "called", "can", "choices", "closes", "controlled", "defaultvalue", "describedby", "disabled", "down", "emptytext", "enter", "error", "esc", "every", "field", "fills", "filtered", "filters", "first", "form", "from", "hidden", "hint", "ids", "input", "inputs", "into", "invalid", "keeps", "label", "last", "list", "matches", "move", "multiple", "name", "needs", "nothing", "one", "onvaluechange", "open", "opening", "options", "pair", "per", "pick", "picked", "picks", "placeholder", "removable", "removes", "render", "required", "select", "sets", "show", "shown", "shows", "single", "stay", "styling", "submit", "submits", "tags", "text", "the", "there", "through", "type", "types", "typing", "uncontrolled", "user", "value", "values", "visible", "when", "with", "you"], registryDependencies: ["field", "form-value", "list", "platform", "tag-input", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "command", type: "registry:ui", title: "Command", description: "⌘K palette: filterable groups, arrow-key highlight, Enter to run, keyword matching. Inline or as CommandDialog with a global shortcut; the first Esc clears, the second closes.", exports: ["Command", "CommandInput", "CommandList", "CommandEmpty", "CommandGroup", "CommandSeparator", "CommandItem", "CommandDialog"], keywords: ["accessible", "after", "against", "and", "arrows", "but", "called", "children", "click", "close", "closes", "collapse", "command", "commanddialog", "commandempty", "commandinput", "commanditem", "commandlist", "content", "controlled", "ctrl", "defaults", "dialog", "disable", "disabled", "driven", "elsewhere", "end", "enter", "esc", "extra", "false", "filterable", "filtering", "for", "global", "group", "groups", "heading", "hidden", "hides", "home", "icon", "inline", "input", "inside", "item", "items", "its", "itself", "keepopen", "keyboard", "keywords", "label", "list", "listbox", "mac", "match", "matched", "matches", "mod", "move", "name", "none", "not", "only", "onopenchange", "onselect", "open", "option", "outside", "own", "pair", "palette", "pass", "passes", "placeholder", "preferences", "query", "results", "scrollable", "search", "selectable", "selecting", "selection", "selects", "separators", "settings", "shortcut", "shown", "shows", "stack", "state", "stay", "terms", "text", "the", "title", "toggle", "toggled", "use", "used", "value", "visible", "visually", "when", "while", "with", "would"], registryDependencies: ["dialog", "list", "search-input", "separator", "use-controllable-state", "use-hotkey", "utils"] }, { name: "confirm", type: "registry:ui", title: "Confirm", description: "Promise-based confirm dialog called like toast: await confirm({ title, description, destructive }) resolves true or false. Built on Dialog's alert mode, Cancel takes the first focus, Esc cancels, one host mounted in the layout.", exports: ["confirm", "Confirmer"], keywords: ["acting", "asks", "await", "before", "cancel", "confirm", "confirmer", "delete", "destructive", "esc", "false", "for", "host", "layout", "mount", "mounted", "needs", "newer", "next", "once", "project", "remove", "resolves", "root", "title", "toaster", "true"], registryDependencies: ["button", "dialog"] }, { name: "context-menu", type: "registry:ui", title: "Context Menu", description: "Right-click menu for an area, opening at the pointer and flipping at screen edges. Shares Dropdown Menu's items, checkbox and radio items, keyboard and typeahead; Menu key or Shift+F10 opens it from the keyboard.", exports: ["ContextMenuContent", "ContextMenuItem", "ContextMenuCheckboxItem", "ContextMenuRadioGroup", "ContextMenuRadioItem", "ContextMenuLabel", "ContextMenuSeparator", "ContextMenu", "ContextMenuTrigger"], keywords: ["actions", "align", "aligned", "and", "area", "but", "called", "center", "check", "checked", "children", "click", "clickable", "closes", "contextmenucontent", "contextmenutrigger", "destructive", "disabled", "dropdownmenuradioitem", "edge", "enter", "equals", "f10", "first", "focus", "focusable", "for", "group", "groups", "hint", "icon", "irreversible", "item", "items", "its", "key", "keyboard", "label", "labels", "leading", "lines", "mark", "menu", "new", "not", "oncheckedchange", "onopenchange", "onselect", "onvaluechange", "opens", "optionally", "picked", "pointer", "press", "red", "right", "selectable", "separators", "shift", "shortcut", "shown", "shows", "state", "the", "then", "trigger", "value", "variant", "when", "with"], registryDependencies: ["dropdown-menu", "utils"] }, { name: "count-to", type: "registry:ui", title: "CountTo", description: "Springs a number up from a start value once it scrolls into view. Prefix, suffix, decimals and locale.", exports: ["CountTo"], keywords: ["after", "and", "bcp", "before", "decimal", "decimals", "digits", "dom", "final", "for", "from", "grouping", "into", "locale", "number", "once", "point", "prefix", "scrolls", "seo", "springs", "starting", "stays", "suffix", "text", "the", "value", "view"], registryDependencies: ["utils"] }, { name: "custom-cursor", type: "registry:ui", title: "Custom Cursor", description: "Optional spring cursor that expands over interactive elements. Off on touch and reduced motion.", exports: ["CustomCursor"], keywords: ["coarse", "cursor", "dot", "elements", "expands", "interactive", "motion", "mount", "nothing", "once", "opt", "over", "pointers", "reduced", "renders", "ring", "spring", "touch", "trailing", "with"], registryDependencies: ["platform", "utils"] }, { name: "data-table", type: "registry:ui", title: "Data Table", description: "Table with columns as data: search across every column, sortable headers, checkbox selection that survives paging, a ⋯ menu per row, bulk actions in the toolbar and pagination. Built from Table, SearchInput, Checkbox, DropdownMenu, Pagination and Empty.", exports: ["DataTable"], keywords: ["accessor", "across", "actions", "all", "alternate", "and", "are", "backgrounds", "box", "bulk", "called", "cell", "checkbox", "client", "column", "columns", "compose", "controlled", "controls", "data", "defaultsort", "definitions", "display", "driven", "dropdownmenuitem", "each", "every", "field", "filters", "first", "for", "friends", "getrowid", "happen", "header", "ids", "items", "its", "jane", "kept", "label", "members", "menu", "name", "names", "onselectionchange", "order", "page", "pages", "pagesize", "pagination", "paging", "pair", "per", "placeholder", "readers", "receives", "render", "right", "row", "rowactions", "rowlabel", "rows", "screen", "search", "searchable", "searchplaceholder", "select", "selectable", "selected", "selection", "server", "show", "side", "sort", "sortable", "stable", "striped", "survives", "table", "that", "the", "toolbar", "with", "yourself"], registryDependencies: ["button", "checkbox", "dropdown-menu", "empty", "pagination", "search-input", "table", "use-controllable-state", "utils"] }, { name: "date-picker", type: "registry:ui", title: "Date Picker", description: "Field-styled button that opens a Calendar in a Popover, focused on the picked day. Single or range, presets such as Last 7 days, closes once the pick is complete, and submits ISO dates through a hidden input. Works inside Field.", exports: ["DatePicker"], keywords: ["accessible", "and", "are", "aria", "bcp", "beside", "blocks", "both", "button", "calendar", "called", "client", "closes", "controlled", "date", "day", "days", "default", "defaultvalue", "describedby", "disabled", "earliest", "end", "ends", "error", "extra", "field", "fill", "fills", "first", "focused", "for", "form", "from", "function", "grid", "hidden", "hint", "htmlfor", "ids", "input", "invalid", "isdisabled", "iso", "label", "last", "latest", "let", "locale", "max", "min", "mode", "monday", "name", "needs", "nothing", "null", "off", "once", "one", "only", "onvaluechange", "opening", "opens", "optional", "pair", "pick", "picked", "placeholder", "popover", "presets", "range", "reach", "readers", "ready", "render", "required", "rule", "saturday", "selectable", "set", "sets", "shortcuts", "single", "start", "styled", "styling", "submit", "submits", "sunday", "text", "that", "the", "then", "there", "these", "through", "today", "uncontrolled", "value", "visible", "weekends", "weekstartson", "when", "with"], registryDependencies: ["calendar", "field", "form-value", "input", "popover", "use-controllable-state", "utils"] }, { name: "dialog", type: "registry:ui", title: "Dialog", description: "Portal modal with blurred backdrop, spring scale-in, focus trap, Esc and scroll lock.", exports: ["useDialog", "Dialog", "DialogTrigger", "DialogClose", "useModal", "DialogContent", "DialogHeader", "DialogFooter", "DialogTitle", "DialogDescription"], keywords: ["action", "alert", "alertdialog", "also", "and", "aria", "armed", "attach", "backdrop", "before", "behavior", "blur", "blurred", "body", "both", "button", "called", "can", "check", "children", "click", "clicks", "close", "confirm", "confirmlabel", "confirmtimeout", "controlled", "corner", "default", "defaultopen", "defaults", "destructive", "dialog", "dialogclose", "dialogcontent", "dialogs", "dialogtrigger", "does", "done", "drawer", "emphasis", "enter", "esc", "feedback", "field", "fill", "first", "focus", "focusable", "footer", "for", "form", "give", "header", "height", "icon", "ignore", "ignores", "irreversible", "its", "label", "left", "loading", "loadinglabel", "lock", "modal", "mode", "never", "not", "off", "old", "onclick", "one", "ones", "only", "onopenchange", "open", "out", "padding", "page", "pair", "panel", "per", "place", "portal", "primary", "ref", "render", "reserved", "resets", "resize", "restore", "returned", "role", "root", "runs", "scale", "scroll", "second", "shared", "showclose", "shown", "shows", "size", "slides", "spinner", "spins", "spring", "square", "state", "status", "stays", "step", "submit", "success", "successlabel", "swap", "swaps", "tab", "text", "the", "this", "topmost", "trap", "trigger", "twice", "two", "uncontrolled", "variant", "view", "where", "while", "width", "with"], registryDependencies: ["button", "platform", "use-controllable-state", "utils"] }, { name: "drawer", type: "registry:ui", title: "Drawer", description: "Edge panel (left, right, top, bottom) that springs in and swipes away. Shares Dialog's focus trap, scroll lock and Esc handling. Sidebar uses it below md.", exports: ["Drawer", "DrawerTrigger", "DrawerClose", "DrawerTitle", "DrawerDescription", "DrawerContent", "DrawerHeader", "DrawerBody", "DrawerFooter"], keywords: ["action", "also", "and", "anywhere", "aria", "armed", "backdrop", "before", "blur", "body", "both", "bottom", "button", "called", "can", "check", "children", "click", "clicks", "close", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "corner", "default", "defaultopen", "defaults", "destructive", "dialogclose", "dialogcontent", "dialogtrigger", "dismiss", "done", "drag", "drawer", "drawers", "edge", "emphasis", "enter", "esc", "feedback", "fill", "first", "focusable", "footer", "for", "form", "from", "give", "handle", "header", "height", "icon", "ignore", "ignores", "irreversible", "its", "label", "left", "loading", "loadinglabel", "never", "old", "onclick", "one", "ones", "onopenchange", "open", "out", "padding", "pair", "panel", "per", "place", "primary", "render", "reserved", "resets", "resize", "runs", "scroll", "scrolls", "second", "showclose", "shown", "shows", "side", "size", "slides", "spinner", "spins", "spring", "square", "state", "status", "stays", "step", "submit", "success", "successlabel", "swap", "swaps", "swipe", "taller", "text", "than", "that", "the", "their", "this", "top", "toward", "trigger", "twice", "two", "uncontrolled", "variant", "view", "when", "where", "while", "width", "with"], registryDependencies: ["dialog", "platform", "utils"] }, { name: "dropdown-menu", type: "registry:ui", title: "Dropdown Menu", description: "Action menu anchored to a Button: items with icons and shortcuts, checkbox and radio items, labels, separators, destructive variant. Arrow keys, typeahead, focus follows the pointer, Esc returns focus.", exports: ["MenuContext", "DropdownMenu", "DropdownMenuTrigger", "DropdownMenuContent", "DropdownMenuItem", "DropdownMenuCheckboxItem", "DropdownMenuRadioGroup", "DropdownMenuRadioItem", "DropdownMenuLabel", "DropdownMenuSeparator"], keywords: ["action", "actions", "align", "aligned", "also", "anchored", "and", "aria", "armed", "before", "blur", "both", "but", "button", "called", "can", "check", "checked", "children", "choice", "click", "clicks", "closes", "closing", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "default", "defaultopen", "defaults", "destructive", "disabled", "done", "down", "dropdownmenuradioitem", "edge", "emphasis", "enter", "equals", "esc", "feedback", "fill", "first", "focusable", "for", "form", "give", "group", "groups", "height", "hint", "icon", "ignore", "ignores", "irreversible", "item", "items", "its", "keeps", "keyboard", "label", "labels", "last", "leading", "left", "lines", "loading", "loadinglabel", "mark", "menu", "never", "new", "not", "old", "oncheckedchange", "onclick", "one", "ones", "onopenchange", "onselect", "onvaluechange", "open", "opens", "optionally", "out", "outside", "padding", "pair", "per", "picked", "picking", "place", "primary", "radiogroup", "red", "render", "reserved", "resets", "resize", "right", "runs", "second", "selectable", "selection", "separators", "shortcut", "shown", "shows", "size", "slides", "space", "spinner", "spins", "square", "state", "status", "stays", "step", "submit", "success", "successlabel", "swap", "swaps", "text", "the", "then", "this", "toggles", "trigger", "twice", "two", "uncontrolled", "value", "variant", "view", "when", "where", "while", "width", "with", "without"], registryDependencies: ["button", "list", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "empty", type: "registry:ui", title: "Empty", description: "Server-safe empty state: icon tile, title, one helpful sentence and the next action. Bordered variant for empty lists and drop zones.", exports: ["Empty"], keywords: ["about", "action", "and", "app", "area", "bordered", "children", "clips", "dashed", "description", "drop", "empty", "for", "helpful", "icon", "inside", "like", "list", "next", "one", "outline", "page", "rounded", "sentence", "shown", "state", "the", "tile", "title", "what", "yet", "zone"], registryDependencies: ["utils"] }, { name: "field", type: "registry:ui", title: "Field", description: "Label, control, description and error as one unit. Controls inside (Input, Textarea, Select, Checkbox, Switch, RadioGroup) get id, aria-describedby, aria-invalid and required automatically; errors spring in and are announced.", exports: ["useFieldControl", "Field"], keywords: ["and", "aria", "automatically", "beside", "checkbox", "children", "control", "controls", "describedby", "description", "dims", "disabled", "disables", "enclosing", "error", "explicit", "field", "fills", "first", "for", "form", "from", "hint", "horizontal", "ids", "invalid", "its", "label", "makes", "marks", "match", "must", "one", "orientation", "out", "outside", "own", "picks", "props", "renders", "required", "returns", "shown", "springs", "state", "switch", "the", "unchanged", "under", "unit", "use", "when", "win", "wired", "with"], registryDependencies: ["label", "utils"] }, { name: "form-value", type: "registry:lib", description: "Submits a custom control's value and takes part in native validation, which a hidden input\ncan't: an empty `required` value blocks submit, shows the browser's message and focuses `anchor`.", exports: ["FormValue"], keywords: ["anchor", "and", "blocks", "browser", "called", "can", "control", "custom", "empty", "field", "finds", "focus", "focuses", "form", "gets", "hidden", "input", "invalid", "message", "name", "native", "nothing", "oninvalid", "only", "part", "picked", "required", "shows", "submit", "submits", "takes", "that", "the", "validation", "value", "visible", "when", "which", "without"], registryDependencies: [] }, { name: "highlight", type: "registry:lib", description: "Lines of colored tokens, with Shiki loaded on demand. Runs anywhere: Code calls it in the\nbrowser, and a Server Component or a build can call it ahead of time and pass the result as\n`tokens`, so the browser never loads Shiki. Null for unknown languages.", exports: ["highlightCode", "languageOf"], keywords: ["ahead", "and", "anywhere", "back", "browser", "build", "call", "calls", "can", "code", "colored", "component", "demand", "extension", "falls", "file", "for", "from", "language", "languages", "lines", "loaded", "loads", "name", "never", "null", "pass", "result", "runs", "server", "shiki", "the", "time", "tokens", "tsx", "unknown", "with"], registryDependencies: [] }, { name: "hover-card", type: "registry:ui", title: "Hover Card", description: "Rich preview (profile, product, clip) that opens after a hover delay or keyboard focus. The pointer can move into the card; supplementary only.", exports: ["HoverCard"], keywords: ["acts", "align", "alignment", "avatar", "before", "bio", "can", "card", "children", "clip", "closedelay", "closes", "content", "first", "flips", "focus", "hover", "into", "keyboard", "leaves", "link", "move", "must", "once", "only", "opendelay", "opens", "pointer", "preferred", "preview", "product", "profile", "rich", "room", "second", "side", "stats", "supplementary", "tap", "the", "there", "time", "touch", "trigger", "usually", "when", "with", "without", "work"], registryDependencies: ["platform", "use-anchor", "use-dismiss", "use-hover-open", "utils"] }, { name: "input", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["fieldClass", "Input"], keywords: ["and", "aria", "chrome", "field", "filled", "group", "handed", "inputgroup", "inside", "the", "works"], registryDependencies: ["field", "utils"] }, { name: "input-group", type: "registry:ui", title: "Input Group", description: "Server-safe wrapper that fuses an Input with icons, text (https://, USD) or buttons into one field with a shared border and focus ring. Clicking an addon focuses the input.", exports: ["InputGroup", "InputGroupAddon"], keywords: ["addons", "align", "and", "beside", "border", "button", "buttons", "clicking", "control", "data", "draws", "drops", "field", "focus", "focuses", "group", "https", "icon", "icons", "inner", "input", "its", "like", "made", "matched", "one", "own", "plain", "plus", "ring", "side", "sits", "slot", "text", "the"], registryDependencies: ["utils"] }, { name: "input-otp", type: "registry:ui", title: "Input OTP", description: "One-time code in separate slots, backed by one real input: paste and SMS autofill work, screen readers hear one field. Grouped slots, numeric or alphanumeric, characters spring in, onComplete to submit. verified turns each character into a check, then merges them into one mark.", exports: ["InputOTP"], keywords: ["accepted", "again", "allowed", "alphanumeric", "and", "announced", "are", "autocomplete", "autofill", "back", "beside", "between", "called", "change", "character", "characters", "charset", "check", "code", "controlled", "counts", "dash", "defaultvalue", "draws", "dropped", "each", "edit", "every", "false", "filled", "fires", "first", "for", "group", "groups", "input", "into", "label", "laid", "length", "mark", "merge", "merged", "number", "once", "oncomplete", "one", "only", "onvaluechange", "others", "over", "pair", "paste", "pasted", "per", "read", "readers", "real", "render", "screen", "set", "shown", "single", "sits", "slides", "slot", "slots", "sms", "submit", "the", "then", "time", "transparently", "turns", "typed", "uncontrolled", "uppercased", "value", "verified", "verifiedlabel", "via", "visual", "was", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "kbd", type: "registry:ui", title: "Kbd", description: "Server-safe key caps for shortcut hints. KbdGroup nests keys per the HTML spec.", exports: ["Kbd", "KbdGroup"], keywords: ["cap", "html", "kbd", "kbdgroup", "key", "keys", "made", "nested", "one", "per", "several", "shortcut", "spec", "the"], registryDependencies: ["utils"] }, { name: "label", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Label"], keywords: [], registryDependencies: ["utils"] }, { name: "list", type: "registry:lib", description: "The item a navigation key moves to in a list, from the item at `index` (-1: none active).\nUndefined when the key doesn't navigate.", exports: ["listKeyTarget", "scrollIntoList"], keywords: ["active", "box", "can", "doesn", "enough", "from", "index", "item", "just", "key", "list", "moves", "moving", "navigate", "navigation", "none", "page", "scrollintoview", "scrolls", "show", "the", "undefined", "way", "when", "without"], registryDependencies: ["utils"] }, { name: "marker", type: "registry:ui", title: "Marker", description: "Highlighter-pen <mark> in four tints that wraps cleanly across lines and can draw itself on, left to right, when it scrolls into view. Highlight marks every match of a search in a string, for transcripts and search results.", exports: ["Marker", "Highlight"], keywords: ["across", "before", "case", "cleanly", "color", "delay", "draw", "drawing", "draws", "every", "first", "full", "fully", "highlight", "highlighter", "insensitive", "inside", "instant", "into", "left", "lines", "mark", "markers", "marks", "match", "motion", "one", "paragraph", "pen", "query", "reduced", "right", "scrolls", "search", "seconds", "several", "shown", "stagger", "sweeps", "term", "terms", "text", "the", "time", "view", "with", "without", "wraps"], registryDependencies: ["utils"] }, { name: "menubar", type: "registry:ui", title: "Menubar", description: "Desktop-style menu bar on the WAI-ARIA menubar pattern: one menu open at a time, hovering the next title while one is open switches to it, ← → walk the bar with or without a menu open, one Tab stop. A single highlight springs between titles; menus reuse every DropdownMenu item.", exports: ["MenubarContent", "MenubarItem", "MenubarCheckboxItem", "MenubarRadioGroup", "MenubarRadioItem", "MenubarLabel", "MenubarSeparator", "Menubar", "MenubarMenu", "MenubarTrigger"], keywords: ["actions", "align", "aligned", "analytics", "and", "another", "apart", "bar", "between", "but", "called", "check", "checked", "children", "click", "closes", "desktop", "destructive", "disabled", "down", "dropdownmenuradioitem", "edge", "enter", "equals", "first", "for", "generated", "give", "group", "groups", "highlight", "hint", "hovering", "icon", "irreversible", "item", "items", "its", "label", "labels", "last", "leading", "left", "lines", "mark", "menu", "menubarcontent", "menubartrigger", "menus", "move", "new", "not", "omitted", "oncheckedchange", "one", "onselect", "onvaluechange", "open", "opens", "optional", "optionally", "picked", "red", "right", "selectable", "separators", "shortcut", "shown", "shows", "space", "springs", "stable", "state", "style", "switches", "tell", "tests", "the", "then", "time", "title", "titles", "toggles", "trigger", "value", "variant", "when", "while", "with"], registryDependencies: ["dropdown-menu", "list", "use-indicator", "utils"] }, { name: "message-bubble", type: "registry:ui", title: "Message Bubble", description: "User/assistant chat bubbles with avatar slot, streaming dots and copyable code blocks.", exports: ["MessageBubble"], keywords: ["above", "accent", "after", "and", "animated", "are", "assistant", "attachments", "avatar", "bubble", "chat", "children", "code", "content", "dots", "from", "inline", "left", "lists", "message", "name", "next", "rich", "right", "sender", "shown", "shows", "side", "size", "slot", "streaming", "surface", "text", "the", "time", "typing", "user"], registryDependencies: ["utils"] }, { name: "meter", type: "registry:ui", title: "Meter", description: "Server-safe gauge for a value in a known range (storage, quota, server load, password strength). Colors by <meter> thresholds, or stacked segments with a legend, like a storage bar.", exports: ["Meter"], keywords: ["above", "accessible", "also", "and", "away", "bar", "below", "between", "bound", "color", "colors", "decides", "defaults", "disk", "follow", "good", "green", "high", "known", "label", "legend", "like", "load", "low", "lower", "max", "measurement", "meter", "min", "name", "not", "one", "optimum", "orange", "overrides", "parts", "password", "progress", "quota", "range", "red", "region", "right", "segments", "server", "stacked", "storage", "strength", "sum", "task", "text", "the", "their", "this", "threshold", "thresholds", "total", "two", "upper", "use", "used", "value", "valuetext", "visible", "where", "with", "within"], registryDependencies: ["utils"] }, { name: "motion-provider", type: "registry:component", exports: ["MotionProvider"], keywords: [], registryDependencies: ["utils"] }, { name: "native-select", type: "registry:ui", title: "Native Select", description: "A real <select> with option groups: native picker on phones, no-JS forms, native required validation. Where customizable select is supported (appearance: base-select), the open list gets the menu look.", exports: ["NativeSelect", "NativeSelectGroup", "NativeSelectOption"], keywords: ["appearance", "base", "browser", "custom", "customizable", "elsewhere", "forms", "gets", "group", "heading", "icons", "instead", "invalid", "label", "labeled", "list", "look", "menu", "native", "need", "open", "optgroup", "options", "phones", "picker", "real", "rendering", "required", "select", "stays", "supports", "the", "use", "user", "validation", "when", "where", "without", "works"], registryDependencies: ["field", "input", "utils"] }, { name: "navigation-menu", type: "registry:ui", title: "Navigation Menu", description: "Website top navigation on the APG disclosure pattern: plain links and panels of rich links. Hover opens after a beat, then sliding along the bar switches panels at once; every panel shares one viewport that springs to the next panel's size and position while the content slides in from the side you moved toward. Click, Enter, ↓, ← → and Esc work; closed panels keep their links in the HTML for crawlers.", exports: ["NavigationMenu", "NavigationMenuList", "NavigationMenuItem", "NavigationMenuTrigger", "NavigationMenuContent", "NavigationMenuLink"], keywords: ["active", "after", "all", "along", "and", "aria", "bar", "beat", "bold", "called", "children", "classname", "click", "closed", "closes", "content", "controlled", "crawlers", "current", "defaultvalue", "description", "down", "enter", "entry", "esc", "find", "first", "focuses", "following", "for", "generated", "hidden", "hover", "html", "icon", "inset", "into", "item", "items", "its", "left", "level", "line", "link", "links", "look", "matched", "menu", "mouse", "muted", "navigation", "omitted", "once", "one", "onvaluechange", "open", "opened", "opens", "optional", "own", "padding", "page", "pair", "panel", "panels", "pill", "plain", "readers", "rem", "render", "rich", "right", "row", "selected", "single", "size", "sliding", "space", "springs", "stable", "stay", "still", "switches", "the", "them", "then", "tile", "title", "toggle", "top", "trigger", "uncontrolled", "under", "value", "viewport", "walk", "website", "while", "with", "your"], registryDependencies: ["use-controllable-state", "use-dismiss", "use-indicator", "utils"] }, { name: "newsletter", type: "registry:block", title: "Newsletter", description: "Email signup: InputGroup with the submit Button inside, native email validation, a loading → success toast and an in-place success state on the button.", exports: ["Newsletter"], keywords: ["above", "address", "after", "and", "button", "check", "confirm", "confirms", "description", "email", "field", "for", "form", "heading", "inbox", "inputgroup", "inside", "into", "its", "line", "loading", "message", "native", "next", "onsubscribe", "place", "placeholder", "rejection", "resets", "resolves", "saved", "shows", "signup", "submit", "submitlabel", "success", "successmessage", "supporting", "text", "that", "the", "then", "title", "toast", "turns", "under", "validation", "when", "with", "your"], registryDependencies: ["button", "input", "input-group", "toast", "utils"] }, { name: "number-input", type: "registry:ui", title: "Number Input", description: "Native number field with −/+ buttons: arrow keys, min/max/step validation and form submit from the platform; clamps on blur, rounds to the step's precision.", exports: ["NumberInput"], keywords: ["amount", "and", "are", "arrows", "arrowup", "buttons", "called", "cart", "change", "controlled", "defaultvalue", "down", "field", "first", "form", "helpers", "highest", "keyboard", "lowest", "max", "min", "native", "new", "number", "onvaluechange", "pair", "pointer", "quantity", "render", "step", "submit", "tabindex", "the", "uncontrolled", "use", "users", "validation", "value", "with"], registryDependencies: ["input", "input-group", "use-controllable-state", "utils"] }, { name: "overflow-focus", type: "registry:lib", description: `Drop inside a scroll container: while the container overflows it becomes keyboard-focusable
17186
17252
  (tabIndex 0) so arrow keys can scroll it, and it leaves the tab order again once it fits.
17187
- Renders a hidden span, so server components (Table) can use it as a child.`, exports: ["OverflowFocus"], keywords: ["again", "and", "arrow", "becomes", "can", "child", "components", "container", "drop", "fits", "focusable", "hidden", "inside", "keyboard", "keys", "leaves", "once", "order", "overflows", "renders", "scroll", "server", "span", "tab", "tabindex", "table", "the", "use", "while"], registryDependencies: [] }, { name: "pagination", type: "registry:ui", title: "Pagination", description: "Server-safe page links from page and total: previous/next, ellipsis gaps and a sliding active pill, with numbers that swipe the way you moved. Links by default; buttons with onPageChange. The row keeps a fixed width so it never jumps.", exports: ["Pagination", "pageRange"], keywords: ["active", "always", "and", "arrows", "bar", "become", "between", "buttons", "called", "changes", "client", "controls", "current", "default", "each", "ellipsis", "first", "for", "from", "gaps", "href", "index", "instead", "items", "its", "keeps", "kept", "key", "labels", "last", "length", "links", "mounted", "moved", "never", "next", "number", "numbers", "one", "only", "onpagechange", "page", "pagerange", "pages", "parents", "phones", "picked", "pill", "previous", "remounting", "render", "returns", "row", "same", "show", "siblings", "side", "slides", "slot", "stays", "swipe", "swipes", "text", "that", "the", "total", "unused", "url", "way", "width", "with", "without", "work", "you"], registryDependencies: ["button-variants", "pagination-motion", "utils"] }, { name: "pagination-motion", type: "registry:ui", description: "Scopes the active pill's `layoutId` so several paginations on a page don't share it.", exports: ["PaginationMotion", "PaginationActivePill", "PaginationNumber"], keywords: ["active", "behind", "changes", "children", "direction", "don", "from", "items", "its", "layoutid", "link", "moved", "next", "number", "outline", "page", "pagination", "paginations", "pill", "scopes", "several", "share", "side", "slot", "springs", "swipes", "that", "the", "toward", "travel", "value", "when"], registryDependencies: ["utils"] }, { name: "platform", type: "registry:lib", description: "False on the server and during hydration, true after: gates portals and other client-only output.", exports: ["useMounted", "useIsMac", "useMediaQuery"], keywords: ["after", "and", "assumes", "client", "corrects", "ctrl", "during", "false", "gates", "hydration", "live", "match", "media", "not", "only", "other", "output", "portals", "query", "render", "server", "shortcuts", "ssr", "the", "then", "true", "use", "where"], registryDependencies: [] }, { name: "popover", type: "registry:ui", title: "Popover", description: "Non-modal panel anchored to a Button for filters, pickers and quick edits. Focus moves in, Esc returns it, outside clicks close; Selects and menus opened inside don't count as outside.", exports: ["Popover", "PopoverTrigger", "PopoverContent"], keywords: ["action", "align", "alignment", "also", "anchored", "and", "any", "aria", "armed", "before", "blur", "button", "called", "check", "children", "click", "closes", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "default", "defaultopen", "defaults", "destructive", "disables", "done", "edits", "emphasis", "end", "esc", "feedback", "fill", "filters", "first", "flips", "focus", "for", "give", "height", "icon", "irreversible", "its", "label", "left", "like", "loading", "loadinglabel", "modal", "moves", "never", "non", "not", "old", "onclick", "one", "ones", "onopenchange", "open", "out", "outside", "padding", "pair", "panel", "past", "per", "pickers", "place", "popovercontent", "popovertrigger", "popup", "preferred", "primary", "quick", "render", "reserved", "resets", "resize", "returns", "room", "runs", "second", "shown", "shows", "side", "size", "slides", "spinner", "spins", "square", "state", "status", "step", "success", "successlabel", "swap", "swaps", "tab", "text", "the", "there", "this", "trap", "trigger", "two", "uncontrolled", "variant", "view", "when", "where", "while", "width", "with"], registryDependencies: ["button", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "pricing", type: "registry:block", title: "Pricing", description: "Plan cards with a monthly / yearly segmented switch. Prices roll on a spring in the direction they moved; the featured plan is outlined in the accent. Card, Badge, ToggleGroup, Button.", exports: ["Pricing"], keywords: ["and", "bcp", "billing", "cards", "code", "currency", "defaultperiod", "display", "down", "drop", "eur", "first", "for", "formatting", "iso", "locale", "monthly", "next", "number", "order", "period", "plan", "plans", "price", "prices", "render", "rise", "rolling", "segmented", "selected", "spring", "swap", "switch", "the", "they", "togglegroup", "when", "with", "yearly", "yearlynote"], registryDependencies: ["badge", "card", "toggle-group", "utils"] }, { name: "product-card", type: "registry:block", title: "Product Card", description: "Shop tile: photos in an AspectRatio (a swipeable Carousel with dots when there are several), sale price, Badge and add-to-cart Button.", exports: ["ProductCard"], keywords: ["add", "addlabel", "are", "aspectratio", "badge", "bcp", "become", "button", "called", "card", "carousel", "code", "compareat", "currency", "current", "dots", "for", "formatting", "heading", "height", "href", "img", "iso", "label", "link", "locale", "major", "media", "name", "new", "number", "onaddtocart", "one", "original", "over", "page", "per", "photos", "pressed", "price", "product", "ratio", "sale", "several", "shop", "shows", "slide", "small", "square", "struck", "swipeable", "text", "the", "there", "through", "tile", "units", "when", "width", "with"], registryDependencies: ["aspect-ratio", "badge", "button", "carousel", "utils"] }, { name: "progress", type: "registry:ui", title: "Progress", description: "Accent bar that springs to each new value, with an optional label and percentage. Leave out value for an indeterminate sweep (static under reduced motion).", exports: ["Progress"], keywords: ["above", "accent", "accessible", "across", "allowed", "also", "aria", "bar", "colored", "duration", "each", "for", "frame", "indeterminate", "infinite", "its", "label", "layout", "max", "motion", "name", "new", "next", "omit", "one", "per", "percentage", "reduced", "scalex", "segment", "show", "showvalue", "size", "springs", "static", "sweeps", "that", "the", "there", "thickness", "tween", "under", "unknown", "value", "visible", "when", "work"], registryDependencies: ["utils"] }, { name: "quote", type: "registry:ui", title: "Quote", description: "Semantic figure, blockquote and figcaption. Plain, card and large variants, with author, subtitle, avatar, lang, typewriter and textSwap.", exports: ["Quote"], keywords: ["accent", "alt", "and", "array", "author", "avatar", "blockquote", "card", "children", "correct", "custom", "cycles", "delay", "display", "doe", "effect", "enables", "fades", "figcaption", "figure", "for", "into", "jane", "job", "lang", "language", "large", "line", "mark", "options", "pass", "plain", "pronunciation", "quote", "quoted", "quotes", "reader", "said", "screen", "scrolls", "secondary", "semantic", "seo", "size", "slot", "speed", "spring", "string", "strings", "subtitle", "supports", "surface", "swap", "text", "textswap", "the", "through", "title", "transitions", "typewriter", "under", "variant", "view", "when", "who", "with", "work", "wrote"], registryDependencies: ["text-swap", "typewriter", "utils"] }, { name: "radio-group", type: "registry:ui", title: "Radio Group", description: "Native radios in a fieldset with a legend: browser arrow keys and form submit, a dot that springs in, optional per-option descriptions, vertical or horizontal.", exports: ["RadioGroup", "RadioGroupItem"], keywords: ["adds", "and", "application", "aria", "arrow", "browser", "but", "called", "children", "conform", "controlled", "defaultvalue", "description", "disabled", "does", "entered", "expected", "field", "fieldset", "first", "form", "format", "generated", "group", "indicates", "invalid", "item", "items", "its", "keys", "label", "labels", "lay", "legend", "line", "muted", "name", "native", "not", "omitted", "one", "onvaluechange", "option", "orientation", "pair", "picked", "radios", "render", "rendered", "row", "selectable", "shown", "stack", "submit", "submitted", "the", "them", "uncontrolled", "under", "value", "visible", "when", "with", "work"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "rating", type: "registry:ui", title: "Rating", description: "Star rating on native radios (arrow keys, forms) with hover preview, or readOnly display with fractional stars for averages.", exports: ["Rating"], keywords: ["and", "arrow", "called", "chosen", "controlled", "defaultvalue", "display", "field", "filled", "first", "for", "form", "forms", "fractions", "group", "hidden", "hover", "image", "included", "inputs", "interactive", "keys", "label", "lift", "max", "name", "native", "number", "only", "onvaluechange", "pair", "partially", "picked", "press", "preview", "radios", "rating", "readers", "readonly", "render", "renders", "score", "screen", "size", "spring", "star", "stars", "the", "uncontrolled", "value", "visually", "with"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "relative-time", type: "registry:ui", title: "Relative Time", description: "Self-updating “5 minutes ago” in a semantic <time> with the full date as its title. Server renders the absolute date (no hydration mismatch); one shared ticker for the whole page.", exports: ["RelativeTime"], keywords: ["absolute", "ago", "and", "both", "client", "crawlers", "current", "date", "default", "differ", "full", "get", "hydration", "its", "itself", "keeps", "locale", "minutes", "mismatch", "not", "now", "one", "page", "pass", "real", "relative", "render", "renders", "semantic", "server", "shared", "stored", "text", "that", "the", "there", "ticker", "time", "timestamp", "title", "with", "would"], registryDependencies: ["utils"] }, { name: "resizable", type: "registry:ui", title: "Resizable", description: "Split panes for admin layouts, docs and editors. Hairline dividers with a wide grab area follow the pointer; collapsible panels snap shut past half their minimum. Dividers are APG window splitters: arrows step, Home/End jump to the limits, Enter or double-click collapses with a spring. Groups nest.", exports: ["ResizablePanelGroup", "ResizablePanel", "ResizableHandle"], keywords: ["adds", "admin", "after", "already", "and", "apg", "are", "arrow", "arrows", "basis", "between", "click", "collapsed", "collapsedsize", "collapses", "collapsible", "component", "cookie", "css", "default", "defaultsize", "direction", "divider", "docs", "dom", "double", "drag", "dragging", "each", "editors", "end", "enter", "evenly", "final", "find", "flex", "follows", "for", "grip", "group", "half", "handle", "handles", "home", "horizontal", "hydration", "icon", "jump", "key", "keyboardstep", "keys", "largest", "layout", "layouts", "left", "limits", "maxsize", "middle", "minimum", "minsize", "neighbor", "one", "onlayout", "order", "others", "panels", "panes", "parents", "past", "per", "plain", "pointer", "press", "rail", "rest", "save", "server", "share", "shows", "shut", "side", "size", "sizes", "smallest", "snaps", "split", "splitters", "spring", "ssr", "stacked", "starting", "step", "the", "their", "them", "toggle", "toggles", "two", "until", "vertical", "visible", "what", "when", "window", "withhandle", "without", "work", "wrappers"], registryDependencies: ["utils"] }, { name: "reveal", type: "registry:ui", title: "Reveal", description: "Scroll reveal: content fades and rises on a spring the first time it enters the viewport.", exports: ["Reveal"], keywords: ["after", "and", "content", "delay", "entering", "fades", "first", "into", "offset", "place", "rises", "scrolls", "seconds", "spring", "start", "stays", "the", "time", "view", "visible", "wait"], registryDependencies: ["utils"] }, { name: "scroll-area", type: "registry:ui", title: "Scroll Area", description: "Overlay scrollbars: thin thumbs that fade in while scrolling or on hover, widen under the pointer and drag. Scrolling stays native; the labeled region is keyboard-focusable.", exports: ["ScrollArea"], keywords: ["also", "and", "aria", "axes", "can", "classes", "drag", "fade", "focus", "for", "get", "give", "goes", "height", "here", "horizontal", "hover", "itself", "keyboard", "label", "mouse", "names", "native", "one", "orientation", "overlay", "padding", "region", "scroll", "scrollable", "scrollbars", "scrolling", "stays", "takes", "that", "the", "thin", "thumb", "thumbs", "touch", "users", "viewport", "viewportclassname", "wheel", "while", "widen"], registryDependencies: ["utils"] }, { name: "search-input", type: "registry:ui", title: "Search Input", description: 'Search field built on Input: leading icon, spring-in clear button, Esc to clear, and an optional focus shortcut ("/" or mod+k) with a Kbd hint.', exports: ["SearchInput"], keywords: ["accessible", "already", "and", "anywhere", "aside", "border", "browser", "button", "called", "change", "clear", "cleared", "clears", "command", "controlled", "ctrl", "default", "defaultvalue", "elsewhere", "embedded", "esc", "every", "field", "find", "first", "focus", "focused", "focuses", "for", "from", "ghost", "hidden", "hint", "htmlfor", "icon", "inputs", "kbd", "key", "label", "mac", "mod", "name", "onvaluechange", "opens", "optional", "own", "pair", "palette", "pass", "query", "render", "ring", "search", "second", "shadow", "shortcut", "single", "skipped", "spring", "steps", "still", "surface", "the", "uncontrolled", "value", "variant", "when", "while", "with", "you"], registryDependencies: ["input", "kbd", "platform", "use-controllable-state", "use-hotkey", "utils"] }, { name: "segmented-tabs", type: "registry:ui", title: "AppWindow", description: "Window container with close / minimize / zoom controls, title, custom header slot and actions. SegmentedTabs is the compact view switcher for its title bar.", exports: ["SegmentedTabs"], keywords: ["accessible", "active", "also", "always", "aria", "behind", "called", "current", "for", "indicator", "item", "items", "label", "labels", "list", "marked", "name", "onchange", "one", "pressed", "segmented", "slides", "spring", "tab", "tabs", "the", "under", "used", "value", "values", "with"], registryDependencies: ["overflow-focus", "use-indicator", "utils"] }, { name: "select", type: "registry:ui", title: "Select", description: "Single-choice listbox styled like Input, with groups, icons and disabled options. Native-select keyboard (arrows, typeahead even while closed), flips above the trigger near the viewport edge, submits via a hidden input.", exports: ["Select"], keywords: ["accessible", "also", "aria", "blocks", "called", "cancel", "choice", "closed", "controlled", "defaultvalue", "describedby", "disabled", "down", "end", "enter", "error", "esc", "field", "fill", "fills", "first", "flat", "form", "from", "groups", "hidden", "hint", "home", "htmlfor", "ids", "input", "invalid", "keyboard", "label", "labeled", "let", "like", "listbox", "matches", "name", "native", "needs", "nothing", "onvaluechange", "opening", "options", "pair", "pick", "picked", "placeholder", "render", "required", "select", "sets", "single", "space", "styled", "styling", "submit", "submits", "text", "the", "there", "through", "trigger", "typeahead", "uncontrolled", "value", "visible", "when", "while", "with"], registryDependencies: ["field", "input", "list", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "separator", type: "registry:ui", title: "Separator", description: 'Server-safe hairline, horizontal or vertical, decorative by default, with an optional centered label like "or".', exports: ["Separator"], keywords: ["assistive", "centered", "content", "decorative", "default", "direction", "false", "for", "horizontal", "label", "line", "only", "orientation", "purely", "separates", "set", "tech", "text", "the", "visual", "when"], registryDependencies: ["utils"] }, { name: "sidebar", type: "registry:ui", title: "Sidebar", description: "App navigation from data: header, groups (optionally foldable), badges and pinned footer entries. Collapses to an icon rail on a spring (⌘B / Ctrl+B) with labels kept for assistive tech; below md it is a left drawer.", exports: ["SidebarLayout", "Sidebar", "SidebarTrigger"], keywords: ["a11y", "accessible", "and", "aria", "below", "bottom", "but", "called", "client", "clip", "collapsed", "collapses", "controlled", "ctrl", "current", "data", "default", "defaultcollapsed", "drawer", "entries", "field", "footer", "for", "from", "groups", "header", "highlighted", "holds", "icon", "ignored", "item", "label", "labels", "landmark", "lays", "left", "links", "name", "navigation", "oncollapsedchange", "onselect", "page", "pair", "picked", "pinned", "rail", "routing", "settings", "shortcut", "side", "sidebar", "slot", "spring", "start", "state", "stay", "the", "toggle", "too", "top", "tree", "trigger", "true", "typing", "uncontrolled", "when", "while", "with", "workspace"], registryDependencies: ["button", "collapsible", "drawer", "platform", "use-controllable-state", "use-hotkey", "utils"] }, { name: "site-header", type: "registry:block", title: "Site Header", description: "Sticky, translucent site header from one nav array: brand, NavigationMenu panels from md up, a right Drawer with the same links below it, and your actions on the right. The hairline underneath appears only once content scrolls beneath it.", exports: ["SiteHeader"], keywords: ["accessible", "acme", "actions", "alike", "and", "appears", "aria", "below", "brand", "client", "close", "controls", "current", "demo", "desktop", "drawer", "every", "for", "from", "hairline", "hand", "header", "href", "label", "left", "level", "link", "links", "logo", "marks", "matching", "name", "nav", "navigation", "navigationmenu", "once", "onclick", "only", "onnavigate", "over", "page", "panels", "right", "routing", "same", "scrolls", "search", "shown", "sign", "site", "sticky", "stub", "the", "theme", "top", "under", "width", "with"], registryDependencies: ["button", "drawer", "navigation-menu", "use-disclosure", "utils"] }, { name: "skeleton", type: "registry:ui", title: "Skeleton", description: 'Server-safe loading placeholders that pulse (static under reduced motion). SkeletonGroup announces one "Loading" to screen readers.', exports: ["Skeleton", "SkeletonGroup"], keywords: ["announced", "block", "classes", "classname", "hear", "instead", "label", "loading", "nothing", "one", "placeholder", "readers", "screen", "shown", "size", "skeleton", "skeletons", "this", "while", "with", "wrap"], registryDependencies: ["utils"] }, { name: "slider", type: "registry:ui", title: "Slider", description: "Slider over native range inputs: thin accent track, white knob that lifts while held. One value or two for a range; keyboard, forms, touch and Field wiring come from the platform.", exports: ["Slider"], keywords: ["accent", "accessible", "and", "aria", "arrow", "blocks", "browser", "called", "defaults", "defaultvalue", "describedby", "disabled", "does", "drag", "dragging", "error", "every", "field", "fills", "filter", "first", "for", "forms", "from", "held", "highest", "hint", "ids", "increment", "inputs", "invalid", "keyboard", "keys", "knob", "labels", "lifts", "lowest", "max", "maximum", "min", "minimum", "name", "names", "native", "one", "onvaluechange", "over", "per", "price", "range", "readers", "render", "screen", "sets", "slider", "step", "styling", "submitted", "text", "that", "the", "thin", "thumb", "touch", "track", "twice", "two", "uncontrolled", "value", "values", "while", "white", "with", "work"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "spinner", type: "registry:ui", title: "Spinner", description: "Server-safe activity indicator: eight spokes in currentColor, three sizes, its own status label (or silent inside a parent that announces). Holds still under reduced motion.", exports: ["Spinner"], keywords: ["accessible", "activity", "already", "announces", "busy", "currentcolor", "diameter", "eight", "holds", "indicator", "label", "motion", "name", "parent", "pass", "reduced", "size", "spokes", "state", "still", "the", "under", "when"], registryDependencies: ["utils"] }, { name: "stat-tile", type: "registry:block", title: "Stat Tile", description: "Admin dashboard metric: value, a delta Badge that is green when the change is good news (invert for errors and latency), and an area Chart of the trend. Server-safe.", exports: ["StatTile"], keywords: ["admin", "and", "area", "axis", "badge", "below", "change", "chart", "dashboard", "data", "datakey", "delta", "down", "each", "errors", "for", "format", "formatted", "good", "green", "headline", "index", "intl", "invert", "key", "label", "last", "latency", "metric", "metrics", "month", "name", "news", "number", "period", "positive", "revenue", "row", "rows", "the", "tile", "tooltip", "trend", "unless", "value", "when", "where"], registryDependencies: ["badge", "card", "chart", "utils"] }, { name: "stats-strip", type: "registry:block", title: "Stats Strip", description: "Headline numbers, each card a <dl>: cards rise in turn with Reveal, then each number springs up with CountTo. Final values are in the HTML.", exports: ["StatsStrip"], keywords: ["card", "display", "each", "headline", "its", "number", "numbers", "order", "rises", "row", "springs", "stats", "then", "turn"], registryDependencies: ["card", "count-to", "reveal", "utils"] }, { name: "stepper", type: "registry:ui", title: "Stepper", description: "Multi-step form (questionnaire, checkout, setup wizard). Steps stay mounted so values survive Back and submit together; Continue checks only the current step's native constraints, plus an optional async onNext guard with a spinner. Progress header with springing connectors; works with onSubmit or a Server Action.", exports: ["Stepper", "StepperList", "StepperStep", "StepperFooter"], keywords: ["action", "after", "and", "are", "back", "backlabel", "button", "called", "check", "checks", "children", "connector", "constraints", "continue", "controlled", "current", "defaultvalue", "description", "every", "false", "fields", "fills", "finished", "first", "for", "form", "header", "hidden", "inactive", "its", "last", "links", "matches", "mounted", "multi", "native", "new", "nextlabel", "not", "one", "only", "onnext", "onsubmit", "onvaluechange", "optional", "order", "pass", "progress", "render", "resolve", "return", "runs", "server", "shown", "shows", "spinner", "spring", "start", "stay", "stays", "step", "steps", "submit", "submitlabel", "submits", "survive", "text", "the", "through", "title", "together", "uncontrolled", "unmounted", "value", "values", "while", "with"], registryDependencies: ["button", "use-controllable-state", "utils"] }, { name: "styles", type: "registry:file", exports: [], keywords: [], registryDependencies: [] }, { name: "switch", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Switch"], keywords: ["called", "checkbox", "checked", "controlled", "defaultchecked", "first", "knob", "native", "new", "oncheckedchange", "pair", "render", "role", "spring", "state", "switch", "the", "uncontrolled", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "table", type: "registry:ui", title: "Table", description: "Server-safe semantic <table> in a scrolling card: header, body, footer and caption, striped rows, tinted selected rows, and sortable headers that set aria-sort and flip their arrow.", exports: ["Table", "TableHeader", "TableBody", "TableFooter", "TableRow", "TableHead", "TableCell", "TableCaption"], keywords: ["alternating", "and", "aria", "around", "arrow", "button", "called", "card", "classes", "column", "containerclassname", "data", "direction", "for", "header", "keyboard", "makes", "narrow", "onsort", "pass", "pressed", "real", "requires", "row", "screens", "scrollable", "scrolling", "scrolls", "selected", "sets", "shading", "shows", "sideways", "sort", "sortable", "state", "striped", "table", "that", "the", "then", "tint", "when"], registryDependencies: ["overflow-focus", "utils"] }, { name: "tabs", type: "registry:ui", title: "Tabs", description: "WAI-ARIA tabs with arrow, Home and End keys. One indicator springs between tabs, segmented or underline. Inactive panels stay in the DOM for SEO; the active one fades in.", exports: ["Tabs", "TabsList", "TabsTrigger", "TabsContent"], keywords: ["activated", "active", "always", "and", "aria", "arrows", "bar", "behind", "called", "children", "content", "controlled", "crawlable", "defaultvalue", "dom", "end", "first", "focus", "hidden", "home", "html", "inactive", "indicator", "labels", "matches", "move", "muted", "one", "onvaluechange", "pair", "panel", "panels", "pill", "remains", "render", "segmented", "springs", "stay", "stays", "tab", "tabs", "tabscontent", "tabstrigger", "the", "their", "track", "uncontrolled", "under", "underline", "value", "variant", "wai", "while", "with"], registryDependencies: ["list", "use-controllable-state", "use-indicator", "utils"] }, { name: "tag-input", type: "registry:ui", title: "Tag Input", description: "Free-form tags: Enter or a separator adds, Backspace removes the last, pasting a list adds them all. Duplicates, a max and a validate function keep bad tags in the input. One hidden input per tag.", exports: ["tagFieldClass", "Tag", "TagInput"], keywords: ["accessible", "add", "after", "allowed", "and", "animatepresence", "backspace", "besides", "button", "called", "children", "chip", "commit", "controlled", "defaultvalue", "disabled", "empty", "enter", "every", "false", "first", "form", "free", "hidden", "hides", "input", "inside", "its", "keys", "last", "limit", "list", "many", "max", "mode", "most", "name", "one", "onremove", "onvaluechange", "out", "pair", "paste", "pasted", "per", "poplayout", "press", "reject", "removable", "remove", "removes", "render", "rendered", "return", "runs", "separator", "separators", "shows", "split", "springs", "stays", "stops", "submits", "tag", "tags", "text", "that", "the", "these", "too", "trimming", "type", "typed", "typing", "uncontrolled", "validate", "value", "when", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "terminal", type: "registry:ui", title: "Terminal", description: "Terminal window. Snippet mode types install commands once scrolled into view, with the full transcript kept in the DOM for SEO and no-JS; log mode streams lines into a live region that follows the bottom unless you scroll up, then offers a jump back. Status lines carry glyphs, copy grabs the commands.", exports: ["Terminal"], keywords: ["and", "append", "arrives", "back", "before", "body", "bodyclassname", "bottom", "character", "clipboard", "commands", "copy", "copytext", "defaults", "dom", "false", "follows", "for", "full", "hides", "install", "jump", "lines", "live", "log", "mode", "new", "offering", "once", "order", "output", "per", "prompt", "puts", "read", "reveals", "role", "scroll", "scrolling", "seo", "size", "snippet", "snippets", "speed", "stays", "sticks", "stream", "streams", "symbol", "terminal", "text", "the", "title", "typed", "types", "typing", "unless", "view", "what", "when", "window", "you"], registryDependencies: ["app-window", "code", "platform", "utils"] }, { name: "testimonial", type: "registry:block", title: "Testimonial", description: "A large Quote with its author, and everyone else who agrees as an overlapping AvatarGroup. Server-safe.", exports: ["Testimonial"], keywords: ["agrees", "and", "author", "avatar", "avatargroup", "behind", "beside", "carried", "children", "company", "crowd", "else", "everyone", "few", "first", "fold", "initials", "into", "its", "lang", "language", "large", "line", "one", "others", "otherslabel", "photo", "quote", "rest", "role", "said", "show", "stack", "streamers", "subtitle", "the", "trusted", "under", "url", "who", "with", "without"], registryDependencies: ["avatar", "avatar-group", "quote", "utils"] }, { name: "text-swap", type: "registry:ui", title: "TextSwap", description: "Spring-powered text morphing and ticker. Auto-cycles phrases or animates whenever children change with blur and slide transitions.", exports: ["TextSwap"], keywords: ["active", "array", "automatically", "between", "changing", "child", "children", "controlling", "cycle", "cycling", "default", "direction", "externally", "hover", "index", "interval", "items", "milliseconds", "mouse", "new", "pass", "pause", "pauseonhover", "single", "string", "swap", "swaps", "text", "the", "through", "true", "when"], registryDependencies: ["utils"] }, { name: "textarea", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Textarea"], keywords: ["auto", "cap", "content", "corner", "end", "field", "firefox", "grows", "max", "maxlength", "near", "needs", "red", "resizable", "show", "showcount", "sizing", "the", "then", "turns", "unsupported", "used", "warning", "where", "with"], registryDependencies: ["field", "input", "utils"] }, { name: "theme", type: "registry:lib", description: "Retints primary, focus rings, selection and switches app-wide. Persists like the theme.", exports: ["isDark", "setTheme", "subscribeTheme", "accents", "getAccent", "setAccent", "themeScript"], keywords: ["and", "app", "focus", "like", "persists", "primary", "retints", "rings", "selection", "switches", "the", "theme", "wide"], registryDependencies: [] }, { name: "theme-toggle", type: "registry:ui", title: "Theme Toggle", description: "Light/dark icon switch with spring rotate-swap; follows the OS until first use.", exports: ["ThemeToggle"], keywords: ["button", "click", "first", "follows", "icon", "moon", "rotate", "spring", "sun", "swap", "until"], registryDependencies: ["button", "theme", "utils"] }, { name: "timeline", type: "registry:ui", title: "Timeline", description: "Server-safe ordered list of events on a rail: icon or dot markers with status colors, machine-readable <time>, title and an optional body. For changelogs, experience and mod logs.", exports: ["Timeline", "TimelineItem"], keywords: ["above", "and", "body", "children", "color", "date", "datetime", "dot", "event", "events", "first", "for", "headline", "icon", "inside", "list", "machine", "marker", "newest", "oldest", "one", "optional", "order", "ordered", "pair", "rail", "readable", "render", "shown", "small", "the", "then", "time", "title", "variant", "with", "without", "yours"], registryDependencies: ["utils"] }, { name: "toast", type: "registry:ui", title: "Toast", description: "Stacked notifications. Hover to expand, swipe to dismiss, timers pause on hover.", exports: ["toast", "Toaster"], keywords: ["action", "description", "dismiss", "dismisses", "duration", "error", "expands", "focus", "hover", "layout", "loading", "mount", "once", "promise", "root", "saved", "stacked", "success", "swipe", "tap", "title", "toast", "toasts"], registryDependencies: ["use-dismiss", "utils"] }, { name: "toggle-group", type: "registry:ui", title: "Toggle Group", description: "Segmented control of toggle buttons. Single mode slides one pill to the pressed item (view mode, billing period); multiple mode toggles items independently (bold, italic). Arrow keys move between items.", exports: ["ToggleGroup", "ToggleGroupItem"], keywords: ["always", "and", "aria", "arrow", "behind", "between", "billing", "bold", "buttons", "called", "choice", "control", "controlled", "defaultvalue", "end", "every", "filters", "first", "height", "home", "icon", "independent", "italic", "item", "items", "keys", "label", "labels", "mode", "move", "multiple", "need", "one", "only", "onvaluechange", "pair", "period", "pill", "pressed", "render", "reported", "segment", "segmented", "set", "single", "size", "slides", "springs", "the", "time", "toggle", "toggles", "type", "uncontrolled", "value", "values", "view", "when", "with"], registryDependencies: ["list", "use-controllable-state", "use-indicator", "utils"] }, { name: "tooltip", type: "registry:ui", title: "Tooltip", description: "Short label on hover or keyboard focus, also wired as the trigger's aria-describedby. Warm-up: once one opens, neighbors open instantly. Hoverable, Esc dismisses, ignores touch.", exports: ["Tooltip"], keywords: ["accessible", "action", "align", "alignment", "also", "and", "aria", "becomes", "before", "button", "children", "content", "control", "default", "delay", "description", "dismisses", "element", "esc", "first", "flips", "focus", "focusable", "for", "hold", "hover", "how", "icon", "keyboard", "label", "one", "open", "opens", "own", "pointer", "preferred", "press", "reaches", "room", "short", "shows", "side", "stays", "still", "tap", "text", "the", "their", "there", "toggles", "tooltip", "touch", "trigger", "triggers", "wcag", "when", "while", "with"], registryDependencies: ["platform", "use-anchor", "use-dismiss", "use-hover-open", "utils"] }, { name: "typewriter", type: "registry:ui", title: "Typewriter", description: "Types out text character-by-character with optional phrase cycling and pulsing cursor. Full copy stays in the DOM for SEO.", exports: ["Typewriter"], keywords: ["and", "array", "before", "blinking", "called", "character", "classes", "cursor", "cursorchar", "cursorclassname", "custom", "cycle", "default", "delay", "deletespeed", "deleting", "dom", "effect", "for", "full", "fully", "headers", "hero", "loop", "milliseconds", "once", "oncomplete", "pause", "pauseduration", "per", "phrase", "phrases", "quotes", "seo", "show", "speed", "starting", "stays", "text", "the", "through", "true", "type", "typed", "typewriter", "typing", "wait", "when", "whether", "while"], registryDependencies: ["platform", "utils"] }, { name: "use-anchor", type: "registry:hook", description: `Fixed-position coordinates for a floating panel next to its anchor: on the preferred side,
17253
+ Renders a hidden span, so server components (Table) can use it as a child.`, exports: ["OverflowFocus"], keywords: ["again", "and", "arrow", "becomes", "can", "child", "components", "container", "drop", "fits", "focusable", "hidden", "inside", "keyboard", "keys", "leaves", "once", "order", "overflows", "renders", "scroll", "server", "span", "tab", "tabindex", "table", "the", "use", "while"], registryDependencies: [] }, { name: "pagination", type: "registry:ui", title: "Pagination", description: "Server-safe page links from page and total: previous/next, ellipsis gaps and a sliding active pill, with numbers that swipe the way you moved. Links by default; buttons with onPageChange. The row keeps a fixed width so it never jumps.", exports: ["Pagination", "pageRange"], keywords: ["active", "always", "and", "arrows", "bar", "become", "between", "buttons", "called", "changes", "client", "controls", "current", "default", "each", "ellipsis", "first", "for", "from", "gaps", "href", "index", "instead", "items", "its", "keeps", "kept", "key", "labels", "last", "length", "links", "mounted", "moved", "never", "next", "number", "numbers", "one", "only", "onpagechange", "page", "pagerange", "pages", "parents", "phones", "picked", "pill", "previous", "remounting", "render", "returns", "row", "same", "show", "siblings", "side", "slides", "slot", "stays", "swipe", "swipes", "text", "that", "the", "total", "unused", "url", "way", "width", "with", "without", "work", "you"], registryDependencies: ["button-variants", "pagination-motion", "utils"] }, { name: "pagination-motion", type: "registry:ui", description: "Scopes the active pill's `layoutId` so several paginations on a page don't share it.", exports: ["PaginationMotion", "PaginationActivePill", "PaginationNumber"], keywords: ["active", "behind", "changes", "children", "direction", "don", "from", "items", "its", "layoutid", "link", "moved", "next", "number", "outline", "page", "pagination", "paginations", "pill", "scopes", "several", "share", "side", "slot", "springs", "swipes", "that", "the", "toward", "travel", "value", "when"], registryDependencies: ["utils"] }, { name: "platform", type: "registry:lib", description: "False on the server and during hydration, true after: gates portals and other client-only output.", exports: ["useMounted", "useIsMac", "useMediaQuery"], keywords: ["after", "and", "assumes", "client", "corrects", "ctrl", "during", "false", "gates", "hydration", "live", "match", "media", "not", "only", "other", "output", "portals", "query", "render", "server", "shortcuts", "ssr", "the", "then", "true", "use", "where"], registryDependencies: [] }, { name: "popover", type: "registry:ui", title: "Popover", description: "Non-modal panel anchored to a Button for filters, pickers and quick edits. Focus moves in, Esc returns it, outside clicks close; Selects and menus opened inside don't count as outside.", exports: ["Popover", "PopoverTrigger", "PopoverContent"], keywords: ["action", "align", "alignment", "also", "anchored", "and", "any", "aria", "armed", "before", "blur", "both", "button", "called", "can", "check", "children", "click", "clicks", "closes", "confirm", "confirmlabel", "confirmtimeout", "content", "controlled", "default", "defaultopen", "defaults", "destructive", "done", "edits", "emphasis", "end", "enter", "esc", "feedback", "fill", "filters", "first", "flips", "focus", "focusable", "for", "form", "give", "height", "icon", "ignore", "ignores", "irreversible", "its", "label", "left", "like", "loading", "loadinglabel", "modal", "moves", "never", "non", "not", "old", "onclick", "one", "ones", "onopenchange", "open", "out", "outside", "padding", "pair", "panel", "past", "per", "pickers", "place", "popovercontent", "popovertrigger", "popup", "preferred", "primary", "quick", "render", "reserved", "resets", "resize", "returns", "room", "runs", "second", "shown", "shows", "side", "size", "slides", "spinner", "spins", "square", "state", "status", "stays", "step", "submit", "success", "successlabel", "swap", "swaps", "tab", "text", "the", "there", "this", "trap", "trigger", "twice", "two", "uncontrolled", "variant", "view", "when", "where", "while", "width", "with"], registryDependencies: ["button", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "pricing", type: "registry:block", title: "Pricing", description: "Plan cards with a monthly / yearly segmented switch. Prices roll on a spring in the direction they moved; the featured plan is outlined in the accent. Card, Badge, ToggleGroup, Button.", exports: ["Pricing"], keywords: ["and", "bcp", "billing", "cards", "code", "currency", "defaultperiod", "display", "down", "drop", "eur", "first", "for", "formatting", "iso", "locale", "monthly", "next", "number", "order", "period", "plan", "plans", "price", "prices", "render", "rise", "rolling", "segmented", "selected", "spring", "swap", "switch", "the", "they", "togglegroup", "when", "with", "yearly", "yearlynote"], registryDependencies: ["badge", "card", "toggle-group", "utils"] }, { name: "product-card", type: "registry:block", title: "Product Card", description: "Shop tile: photos in an AspectRatio (a swipeable Carousel with dots when there are several), sale price, Badge and add-to-cart Button.", exports: ["ProductCard"], keywords: ["add", "addlabel", "are", "aspectratio", "badge", "bcp", "become", "button", "called", "card", "carousel", "code", "compareat", "currency", "current", "dots", "for", "formatting", "heading", "height", "href", "img", "iso", "label", "link", "locale", "major", "media", "name", "new", "number", "onaddtocart", "one", "original", "over", "page", "per", "photos", "pressed", "price", "product", "ratio", "sale", "several", "shop", "shows", "slide", "small", "square", "struck", "swipeable", "text", "the", "there", "through", "tile", "units", "when", "width", "with"], registryDependencies: ["aspect-ratio", "badge", "button", "carousel", "utils"] }, { name: "progress", type: "registry:ui", title: "Progress", description: "Accent bar that springs to each new value, with an optional label and percentage. Leave out value for an indeterminate sweep (static under reduced motion).", exports: ["Progress"], keywords: ["above", "accent", "accessible", "across", "allowed", "also", "aria", "bar", "colored", "duration", "each", "for", "frame", "indeterminate", "infinite", "its", "label", "layout", "max", "motion", "name", "new", "next", "omit", "one", "per", "percentage", "reduced", "scalex", "segment", "show", "showvalue", "size", "springs", "static", "sweeps", "that", "the", "there", "thickness", "tween", "under", "unknown", "value", "visible", "when", "work"], registryDependencies: ["utils"] }, { name: "quote", type: "registry:ui", title: "Quote", description: "Semantic figure, blockquote and figcaption. Plain, card and large variants, with author, subtitle, avatar, lang, typewriter and textSwap.", exports: ["Quote"], keywords: ["accent", "alt", "and", "array", "author", "avatar", "blockquote", "card", "children", "correct", "custom", "cycles", "delay", "display", "doe", "effect", "enables", "fades", "figcaption", "figure", "for", "into", "jane", "job", "lang", "language", "large", "line", "mark", "options", "pass", "plain", "pronunciation", "quote", "quoted", "quotes", "reader", "said", "screen", "scrolls", "secondary", "semantic", "seo", "size", "slot", "speed", "spring", "string", "strings", "subtitle", "supports", "surface", "swap", "text", "textswap", "the", "through", "title", "transitions", "typewriter", "under", "variant", "view", "when", "who", "with", "work", "wrote"], registryDependencies: ["text-swap", "typewriter", "utils"] }, { name: "radio-group", type: "registry:ui", title: "Radio Group", description: "Native radios in a fieldset with a legend: browser arrow keys and form submit, a dot that springs in, optional per-option descriptions, vertical or horizontal.", exports: ["RadioGroup", "RadioGroupItem"], keywords: ["adds", "and", "application", "aria", "arrow", "browser", "but", "called", "children", "conform", "controlled", "defaultvalue", "description", "disabled", "does", "entered", "expected", "field", "fieldset", "first", "form", "format", "generated", "group", "indicates", "invalid", "item", "items", "its", "keys", "label", "labels", "lay", "legend", "line", "muted", "name", "native", "not", "omitted", "one", "onvaluechange", "option", "orientation", "pair", "picked", "radios", "render", "rendered", "row", "selectable", "shown", "stack", "submit", "submitted", "the", "them", "uncontrolled", "under", "value", "visible", "when", "with", "work"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "rating", type: "registry:ui", title: "Rating", description: "Star rating on native radios (arrow keys, forms) with hover preview, or readOnly display with fractional stars for averages.", exports: ["Rating"], keywords: ["and", "arrow", "called", "chosen", "controlled", "defaultvalue", "display", "field", "filled", "first", "for", "form", "forms", "fractions", "group", "hidden", "hover", "image", "included", "inputs", "interactive", "keys", "label", "lift", "max", "name", "native", "number", "only", "onvaluechange", "pair", "partially", "picked", "press", "preview", "radios", "rating", "readers", "readonly", "render", "renders", "score", "screen", "size", "spring", "star", "stars", "the", "uncontrolled", "value", "visually", "with"], registryDependencies: ["use-controllable-state", "utils"] }, { name: "relative-time", type: "registry:ui", title: "Relative Time", description: "Self-updating “5 minutes ago” in a semantic <time> with the full date as its title. Server renders the absolute date (no hydration mismatch); one shared ticker for the whole page.", exports: ["RelativeTime"], keywords: ["absolute", "ago", "and", "both", "client", "crawlers", "current", "date", "default", "differ", "full", "get", "hydration", "its", "itself", "keeps", "locale", "minutes", "mismatch", "not", "now", "one", "page", "pass", "real", "relative", "render", "renders", "semantic", "server", "shared", "stored", "text", "that", "the", "there", "ticker", "time", "timestamp", "title", "with", "would"], registryDependencies: ["utils"] }, { name: "resizable", type: "registry:ui", title: "Resizable", description: "Split panes for admin layouts, docs and editors. Hairline dividers with a wide grab area follow the pointer; collapsible panels snap shut past half their minimum. Dividers are APG window splitters: arrows step, Home/End jump to the limits, Enter or double-click collapses with a spring. Groups nest.", exports: ["ResizablePanelGroup", "ResizablePanel", "ResizableHandle"], keywords: ["adds", "admin", "after", "already", "and", "apg", "are", "arrow", "arrows", "basis", "between", "click", "collapsed", "collapsedsize", "collapses", "collapsible", "component", "cookie", "css", "default", "defaultsize", "direction", "divider", "docs", "dom", "double", "drag", "dragging", "each", "editors", "end", "enter", "evenly", "final", "find", "flex", "follows", "for", "grip", "group", "half", "handle", "handles", "home", "horizontal", "hydration", "icon", "jump", "key", "keyboardstep", "keys", "largest", "layout", "layouts", "left", "limits", "maxsize", "middle", "minimum", "minsize", "neighbor", "one", "onlayout", "order", "others", "panels", "panes", "parents", "past", "per", "plain", "pointer", "press", "rail", "rest", "save", "server", "share", "shows", "shut", "side", "size", "sizes", "smallest", "snaps", "split", "splitters", "spring", "ssr", "stacked", "starting", "step", "the", "their", "them", "toggle", "toggles", "two", "until", "vertical", "visible", "what", "when", "window", "withhandle", "without", "work", "wrappers"], registryDependencies: ["utils"] }, { name: "reveal", type: "registry:ui", title: "Reveal", description: "Scroll reveal: content fades and rises on a spring the first time it enters the viewport.", exports: ["Reveal"], keywords: ["after", "and", "content", "delay", "entering", "fades", "first", "into", "offset", "place", "rises", "scrolls", "seconds", "spring", "start", "stays", "the", "time", "view", "visible", "wait"], registryDependencies: ["utils"] }, { name: "scroll-area", type: "registry:ui", title: "Scroll Area", description: "Overlay scrollbars: thin thumbs that fade in while scrolling or on hover, widen under the pointer and drag. Scrolling stays native; the labeled region is keyboard-focusable.", exports: ["ScrollArea"], keywords: ["also", "and", "aria", "axes", "can", "classes", "drag", "fade", "focus", "for", "get", "give", "goes", "height", "here", "horizontal", "hover", "itself", "keyboard", "label", "mouse", "names", "native", "one", "orientation", "overlay", "padding", "region", "scroll", "scrollable", "scrollbars", "scrolling", "stays", "takes", "that", "the", "thin", "thumb", "thumbs", "touch", "users", "viewport", "viewportclassname", "wheel", "while", "widen"], registryDependencies: ["utils"] }, { name: "search-input", type: "registry:ui", title: "Search Input", description: 'Search field built on Input: leading icon, spring-in clear button, Esc to clear, and an optional focus shortcut ("/" or mod+k) with a Kbd hint.', exports: ["SearchInput"], keywords: ["accessible", "already", "and", "anywhere", "aside", "border", "browser", "button", "called", "change", "clear", "cleared", "clears", "command", "controlled", "ctrl", "default", "defaultvalue", "elsewhere", "embedded", "esc", "every", "field", "find", "first", "focus", "focused", "focuses", "for", "from", "ghost", "hidden", "hint", "htmlfor", "icon", "inputs", "kbd", "key", "label", "mac", "mod", "name", "onvaluechange", "opens", "optional", "own", "pair", "palette", "pass", "query", "render", "ring", "search", "second", "shadow", "shortcut", "single", "skipped", "spring", "steps", "still", "surface", "the", "uncontrolled", "value", "variant", "when", "while", "with", "you"], registryDependencies: ["input", "kbd", "platform", "use-controllable-state", "use-hotkey", "utils"] }, { name: "segmented-tabs", type: "registry:ui", title: "AppWindow", description: "Window container with close / minimize / zoom controls, title, custom header slot and actions. SegmentedTabs is the compact view switcher for its title bar.", exports: ["SegmentedTabs"], keywords: ["accessible", "active", "also", "always", "aria", "behind", "called", "current", "for", "indicator", "item", "items", "label", "labels", "list", "marked", "name", "onchange", "one", "pressed", "segmented", "slides", "spring", "tab", "tabs", "the", "under", "used", "value", "values", "with"], registryDependencies: ["overflow-focus", "use-indicator", "utils"] }, { name: "select", type: "registry:ui", title: "Select", description: "Single-choice listbox styled like Input, with groups, icons and disabled options. Native-select keyboard (arrows, typeahead even while closed), flips above the trigger near the viewport edge, submits via a hidden input.", exports: ["Select"], keywords: ["accessible", "also", "aria", "blocks", "called", "cancel", "choice", "closed", "controlled", "defaultvalue", "describedby", "disabled", "down", "end", "enter", "error", "esc", "field", "fill", "fills", "first", "flat", "form", "from", "groups", "hidden", "hint", "home", "htmlfor", "ids", "input", "invalid", "keyboard", "label", "labeled", "let", "like", "listbox", "matches", "name", "native", "needs", "nothing", "onvaluechange", "opening", "options", "pair", "pick", "picked", "placeholder", "render", "required", "select", "sets", "single", "space", "styled", "styling", "submit", "submits", "text", "the", "there", "through", "trigger", "typeahead", "uncontrolled", "value", "visible", "when", "while", "with"], registryDependencies: ["field", "form-value", "input", "list", "platform", "use-anchor", "use-controllable-state", "use-dismiss", "utils"] }, { name: "separator", type: "registry:ui", title: "Separator", description: 'Server-safe hairline, horizontal or vertical, decorative by default, with an optional centered label like "or".', exports: ["Separator"], keywords: ["assistive", "centered", "content", "decorative", "default", "direction", "false", "for", "horizontal", "label", "line", "only", "orientation", "purely", "separates", "set", "tech", "text", "the", "visual", "when"], registryDependencies: ["utils"] }, { name: "sidebar", type: "registry:ui", title: "Sidebar", description: "App navigation from data: header, groups (optionally foldable), badges and pinned footer entries. Collapses to an icon rail on a spring (⌘B / Ctrl+B) with labels kept for assistive tech; below md it is a left drawer.", exports: ["SidebarLayout", "Sidebar", "SidebarTrigger"], keywords: ["a11y", "accessible", "and", "aria", "below", "bottom", "but", "called", "client", "clip", "collapsed", "collapses", "controlled", "ctrl", "current", "data", "default", "defaultcollapsed", "drawer", "entries", "field", "footer", "for", "from", "groups", "header", "highlighted", "holds", "icon", "ignored", "item", "label", "labels", "landmark", "lays", "left", "links", "name", "navigation", "oncollapsedchange", "onselect", "page", "pair", "picked", "pinned", "rail", "routing", "settings", "shortcut", "side", "sidebar", "slot", "spring", "start", "state", "stay", "the", "toggle", "too", "top", "tree", "trigger", "true", "typing", "uncontrolled", "when", "while", "with", "workspace"], registryDependencies: ["button", "collapsible", "drawer", "platform", "use-controllable-state", "use-hotkey", "utils"] }, { name: "site-header", type: "registry:block", title: "Site Header", description: "Sticky, translucent site header from one nav array: brand, NavigationMenu panels from md up, a right Drawer with the same links below it, and your actions on the right. The hairline underneath appears only once content scrolls beneath it.", exports: ["SiteHeader"], keywords: ["accessible", "acme", "actions", "alike", "and", "appears", "aria", "below", "brand", "client", "close", "controls", "current", "demo", "desktop", "drawer", "every", "for", "from", "hairline", "hand", "header", "href", "label", "left", "level", "link", "links", "logo", "marks", "matching", "name", "nav", "navigation", "navigationmenu", "once", "onclick", "only", "onnavigate", "over", "page", "panels", "right", "routing", "same", "scrolls", "search", "shown", "sign", "site", "sticky", "stub", "the", "theme", "top", "under", "width", "with"], registryDependencies: ["button", "drawer", "navigation-menu", "use-disclosure", "utils"] }, { name: "skeleton", type: "registry:ui", title: "Skeleton", description: 'Server-safe loading placeholders that pulse (static under reduced motion). SkeletonGroup announces one "Loading" to screen readers.', exports: ["Skeleton", "SkeletonGroup"], keywords: ["announced", "block", "classes", "classname", "hear", "instead", "label", "loading", "nothing", "one", "placeholder", "readers", "screen", "shown", "size", "skeleton", "skeletons", "this", "while", "with", "wrap"], registryDependencies: ["utils"] }, { name: "slider", type: "registry:ui", title: "Slider", description: "Slider over native range inputs: thin accent track, white knob that lifts while held. One value or two for a range; keyboard, forms, touch and Field wiring come from the platform.", exports: ["Slider"], keywords: ["accent", "accessible", "and", "aria", "arrow", "blocks", "browser", "called", "defaults", "defaultvalue", "describedby", "disabled", "does", "drag", "dragging", "error", "every", "field", "fills", "filter", "first", "for", "forms", "from", "held", "highest", "hint", "ids", "increment", "inputs", "invalid", "keyboard", "keys", "knob", "labels", "lifts", "lowest", "max", "maximum", "min", "minimum", "name", "names", "native", "one", "onvaluechange", "over", "per", "price", "range", "readers", "render", "screen", "sets", "slider", "step", "styling", "submitted", "text", "that", "the", "thin", "thumb", "touch", "track", "twice", "two", "uncontrolled", "value", "values", "while", "white", "with", "work"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "spinner", type: "registry:ui", title: "Spinner", description: "Server-safe activity indicator: eight spokes in currentColor, three sizes, its own status label (or silent inside a parent that announces). Holds still under reduced motion.", exports: ["Spinner"], keywords: ["accessible", "activity", "already", "announces", "busy", "currentcolor", "diameter", "eight", "holds", "indicator", "label", "motion", "name", "parent", "pass", "reduced", "size", "spokes", "state", "still", "the", "under", "when"], registryDependencies: ["utils"] }, { name: "stat-tile", type: "registry:block", title: "Stat Tile", description: "Admin dashboard metric: value, a delta Badge that is green when the change is good news (invert for errors and latency), and an area Chart of the trend. Server-safe.", exports: ["StatTile"], keywords: ["admin", "and", "area", "axis", "badge", "below", "change", "chart", "dashboard", "data", "datakey", "delta", "down", "each", "errors", "for", "format", "formatted", "good", "green", "headline", "index", "intl", "invert", "key", "label", "last", "latency", "metric", "metrics", "month", "name", "news", "number", "period", "positive", "revenue", "row", "rows", "the", "tile", "tooltip", "trend", "unless", "value", "when", "where"], registryDependencies: ["badge", "card", "chart", "utils"] }, { name: "stats-strip", type: "registry:block", title: "Stats Strip", description: "Headline numbers, each card a <dl>: cards rise in turn with Reveal, then each number springs up with CountTo. Final values are in the HTML.", exports: ["StatsStrip"], keywords: ["card", "display", "each", "headline", "its", "number", "numbers", "order", "rises", "row", "springs", "stats", "then", "turn"], registryDependencies: ["card", "count-to", "reveal", "utils"] }, { name: "stepper", type: "registry:ui", title: "Stepper", description: "Multi-step form (questionnaire, checkout, setup wizard). Steps stay mounted so values survive Back and submit together; Continue checks only the current step's native constraints, plus an optional async onNext guard with a spinner. Progress header with springing connectors; works with onSubmit or a Server Action.", exports: ["Stepper", "StepperList", "StepperStep", "StepperFooter"], keywords: ["action", "after", "and", "are", "back", "backlabel", "button", "called", "check", "checks", "children", "connector", "constraints", "continue", "controlled", "current", "defaultvalue", "description", "every", "false", "fields", "fills", "finished", "first", "for", "form", "header", "hidden", "inactive", "its", "last", "links", "matches", "mounted", "multi", "native", "new", "nextlabel", "not", "one", "only", "onnext", "onsubmit", "onvaluechange", "optional", "order", "pass", "progress", "render", "resolve", "return", "runs", "server", "shown", "shows", "spinner", "spring", "start", "stay", "stays", "step", "steps", "submit", "submitlabel", "submits", "survive", "text", "the", "through", "title", "together", "uncontrolled", "unmounted", "value", "values", "while", "with"], registryDependencies: ["button", "use-controllable-state", "utils"] }, { name: "styles", type: "registry:file", exports: [], keywords: [], registryDependencies: [] }, { name: "switch", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Switch"], keywords: ["called", "checkbox", "checked", "controlled", "defaultchecked", "first", "knob", "native", "new", "oncheckedchange", "pair", "render", "role", "spring", "state", "switch", "the", "uncontrolled", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "table", type: "registry:ui", title: "Table", description: "Server-safe semantic <table> in a scrolling card: header, body, footer and caption, striped rows, tinted selected rows, and sortable headers that set aria-sort and flip their arrow.", exports: ["Table", "TableHeader", "TableBody", "TableFooter", "TableRow", "TableHead", "TableCell", "TableCaption"], keywords: ["alternating", "and", "aria", "around", "arrow", "button", "called", "card", "classes", "column", "containerclassname", "data", "direction", "for", "header", "keyboard", "makes", "narrow", "onsort", "pass", "pressed", "real", "requires", "row", "screens", "scrollable", "scrolling", "scrolls", "selected", "sets", "shading", "shows", "sideways", "sort", "sortable", "state", "striped", "table", "that", "the", "then", "tint", "when"], registryDependencies: ["overflow-focus", "utils"] }, { name: "tabs", type: "registry:ui", title: "Tabs", description: "WAI-ARIA tabs with arrow, Home and End keys. One indicator springs between tabs, segmented or underline. Inactive panels stay in the DOM for SEO; the active one fades in.", exports: ["Tabs", "TabsList", "TabsTrigger", "TabsContent"], keywords: ["activated", "active", "always", "and", "aria", "arrows", "bar", "behind", "called", "children", "content", "controlled", "crawlable", "defaultvalue", "dom", "end", "first", "focus", "hidden", "home", "html", "inactive", "indicator", "labels", "matches", "move", "muted", "one", "onvaluechange", "pair", "panel", "panels", "pill", "remains", "render", "segmented", "springs", "stay", "stays", "tab", "tabs", "tabscontent", "tabstrigger", "the", "their", "track", "uncontrolled", "under", "underline", "value", "variant", "wai", "while", "with"], registryDependencies: ["list", "use-controllable-state", "use-indicator", "utils"] }, { name: "tag-input", type: "registry:ui", title: "Tag Input", description: "Free-form tags: Enter or a separator adds, Backspace removes the last, pasting a list adds them all. Duplicates, a max and a validate function keep bad tags in the input. One hidden input per tag.", exports: ["tagFieldClass", "Tag", "TagInput"], keywords: ["accessible", "add", "after", "allowed", "and", "animatepresence", "backspace", "besides", "button", "called", "children", "chip", "commit", "controlled", "defaultvalue", "disabled", "empty", "enter", "every", "false", "first", "form", "free", "hidden", "hides", "input", "inside", "its", "keys", "last", "limit", "list", "many", "max", "mode", "most", "name", "one", "onremove", "onvaluechange", "out", "pair", "paste", "pasted", "per", "poplayout", "press", "reject", "removable", "remove", "removes", "render", "rendered", "return", "runs", "separator", "separators", "shows", "split", "springs", "stays", "stops", "submits", "tag", "tags", "text", "that", "the", "these", "too", "trimming", "type", "typed", "typing", "uncontrolled", "validate", "value", "when", "with"], registryDependencies: ["field", "use-controllable-state", "utils"] }, { name: "terminal", type: "registry:ui", title: "Terminal", description: "Terminal window. Snippet mode types install commands once scrolled into view, with the full transcript kept in the DOM for SEO and no-JS; log mode streams lines into a live region that follows the bottom unless you scroll up, then offers a jump back. Status lines carry glyphs, copy grabs the commands.", exports: ["Terminal"], keywords: ["and", "append", "arrives", "back", "before", "body", "bodyclassname", "bottom", "character", "clipboard", "commands", "copy", "copytext", "defaults", "dom", "false", "follows", "for", "full", "hides", "install", "jump", "lines", "live", "log", "mode", "new", "offering", "once", "order", "output", "per", "prompt", "puts", "read", "reveals", "role", "scroll", "scrolling", "seo", "size", "snippet", "snippets", "speed", "stays", "sticks", "stream", "streams", "symbol", "terminal", "text", "the", "title", "typed", "types", "typing", "unless", "view", "what", "when", "window", "you"], registryDependencies: ["app-window", "code", "platform", "utils"] }, { name: "testimonial", type: "registry:block", title: "Testimonial", description: "A large Quote with its author, and everyone else who agrees as an overlapping AvatarGroup. Server-safe.", exports: ["Testimonial"], keywords: ["agrees", "and", "author", "avatar", "avatargroup", "behind", "beside", "carried", "children", "company", "crowd", "else", "everyone", "few", "first", "fold", "initials", "into", "its", "lang", "language", "large", "line", "one", "others", "otherslabel", "photo", "quote", "rest", "role", "said", "show", "stack", "streamers", "subtitle", "the", "trusted", "under", "url", "who", "with", "without"], registryDependencies: ["avatar", "avatar-group", "quote", "utils"] }, { name: "text-swap", type: "registry:ui", title: "TextSwap", description: "Spring-powered text morphing and ticker. Auto-cycles phrases or animates whenever children change with blur and slide transitions.", exports: ["TextSwap"], keywords: ["active", "array", "automatically", "between", "changing", "child", "children", "controlling", "cycle", "cycling", "default", "direction", "externally", "hover", "index", "interval", "items", "milliseconds", "mouse", "new", "pass", "pause", "pauseonhover", "single", "string", "swap", "swaps", "text", "the", "through", "true", "when"], registryDependencies: ["utils"] }, { name: "textarea", type: "registry:ui", title: "Forms", description: "Input, Textarea, Label and Switch: smooth focus rings, native :user-invalid validation (red only after interaction), aria-invalid, auto-growing textarea with an optional character count, and a spring switch.", exports: ["Textarea"], keywords: ["auto", "cap", "content", "corner", "end", "field", "firefox", "grows", "max", "maxlength", "near", "needs", "red", "resizable", "show", "showcount", "sizing", "the", "then", "turns", "unsupported", "used", "warning", "where", "with"], registryDependencies: ["field", "input", "utils"] }, { name: "theme", type: "registry:lib", description: "Retints primary, focus rings, selection and switches app-wide. Persists like the theme.", exports: ["isDark", "setTheme", "subscribeTheme", "accents", "getAccent", "setAccent", "themeScript"], keywords: ["and", "app", "focus", "like", "persists", "primary", "retints", "rings", "selection", "switches", "the", "theme", "wide"], registryDependencies: [] }, { name: "theme-toggle", type: "registry:ui", title: "Theme Toggle", description: "Light/dark icon switch with spring rotate-swap; follows the OS until first use.", exports: ["ThemeToggle"], keywords: ["button", "click", "first", "follows", "icon", "moon", "rotate", "spring", "sun", "swap", "until"], registryDependencies: ["button", "theme", "utils"] }, { name: "timeline", type: "registry:ui", title: "Timeline", description: "Server-safe ordered list of events on a rail: icon or dot markers with status colors, machine-readable <time>, title and an optional body. For changelogs, experience and mod logs.", exports: ["Timeline", "TimelineItem"], keywords: ["above", "and", "body", "children", "color", "date", "datetime", "dot", "event", "events", "first", "for", "headline", "icon", "inside", "list", "machine", "marker", "newest", "oldest", "one", "optional", "order", "ordered", "pair", "rail", "readable", "render", "shown", "small", "the", "then", "time", "title", "variant", "with", "without", "yours"], registryDependencies: ["utils"] }, { name: "toast", type: "registry:ui", title: "Toast", description: "Stacked notifications. Hover to expand, swipe to dismiss, timers pause on hover.", exports: ["toast", "Toaster"], keywords: ["action", "description", "dismiss", "dismisses", "duration", "error", "expands", "focus", "hover", "layout", "loading", "mount", "once", "promise", "root", "saved", "stacked", "success", "swipe", "tap", "title", "toast", "toasts"], registryDependencies: ["use-dismiss", "utils"] }, { name: "toggle-group", type: "registry:ui", title: "Toggle Group", description: "Segmented control of toggle buttons. Single mode slides one pill to the pressed item (view mode, billing period); multiple mode toggles items independently (bold, italic). Arrow keys move between items.", exports: ["ToggleGroup", "ToggleGroupItem"], keywords: ["always", "and", "aria", "arrow", "behind", "between", "billing", "bold", "buttons", "called", "choice", "control", "controlled", "defaultvalue", "end", "every", "filters", "first", "height", "home", "icon", "independent", "italic", "item", "items", "keys", "label", "labels", "mode", "move", "multiple", "need", "one", "only", "onvaluechange", "pair", "period", "pill", "pressed", "render", "reported", "segment", "segmented", "set", "single", "size", "slides", "springs", "the", "time", "toggle", "toggles", "type", "uncontrolled", "value", "values", "view", "when", "with"], registryDependencies: ["list", "use-controllable-state", "use-indicator", "utils"] }, { name: "tooltip", type: "registry:ui", title: "Tooltip", description: "Short label on hover or keyboard focus, also wired as the trigger's aria-describedby. Warm-up: once one opens, neighbors open instantly. Hoverable, Esc dismisses, ignores touch.", exports: ["Tooltip"], keywords: ["accessible", "action", "align", "alignment", "also", "and", "aria", "becomes", "before", "button", "children", "content", "control", "default", "delay", "description", "dismisses", "element", "esc", "first", "flips", "focus", "focusable", "for", "hold", "hover", "how", "icon", "keyboard", "label", "one", "open", "opens", "own", "pointer", "preferred", "press", "reaches", "room", "short", "shows", "side", "stays", "still", "tap", "text", "the", "their", "there", "toggles", "tooltip", "touch", "trigger", "triggers", "wcag", "when", "while", "with"], registryDependencies: ["platform", "use-anchor", "use-dismiss", "use-hover-open", "utils"] }, { name: "typewriter", type: "registry:ui", title: "Typewriter", description: "Types out text character-by-character with optional phrase cycling and pulsing cursor. Full copy stays in the DOM for SEO.", exports: ["Typewriter"], keywords: ["and", "array", "before", "blinking", "called", "character", "classes", "cursor", "cursorchar", "cursorclassname", "custom", "cycle", "default", "delay", "deletespeed", "deleting", "dom", "effect", "for", "full", "fully", "headers", "hero", "loop", "milliseconds", "once", "oncomplete", "pause", "pauseduration", "per", "phrase", "phrases", "quotes", "seo", "show", "speed", "starting", "stays", "text", "the", "through", "true", "type", "typed", "typewriter", "typing", "wait", "when", "whether", "while"], registryDependencies: ["platform", "utils"] }, { name: "use-anchor", type: "registry:hook", description: `Fixed-position coordinates for a floating panel next to its anchor: on the preferred side,
17188
17254
  flipped when it doesn't fit, clamped to the viewport, kept in place on scroll and resize.
17189
17255
  Measures before paint, so nothing jumps.`, exports: ["useAnchor"], keywords: ["anchor", "and", "before", "clamped", "coordinates", "doesn", "fit", "fixed", "flipped", "floating", "for", "its", "jumps", "kept", "measures", "next", "nothing", "paint", "panel", "place", "position", "preferred", "resize", "scroll", "side", "the", "viewport", "when"], registryDependencies: ["utils"] }, { name: "use-controllable-state", type: "registry:hook", description: "State a parent may own. Controlled while `value` is defined; otherwise kept here, seeded from\n`defaultValue`. The setter always reports through `onChange`, so both modes stay observable.", exports: ["useControllableState"], keywords: ["always", "both", "controlled", "defaultvalue", "defined", "from", "here", "kept", "may", "modes", "observable", "onchange", "otherwise", "own", "parent", "reports", "seeded", "setter", "state", "stay", "the", "through", "value", "while"], registryDependencies: [] }, { name: "use-disclosure", type: "registry:hook", description: "Open state for any overlay. Spread `props` onto Dialog, Drawer, Popover or DropdownMenu and\nopen it from anywhere: `const drawer = useDisclosure(); <Drawer {...drawer.props}>`, `drawer.show()`.", exports: ["useDisclosure"], keywords: ["and", "any", "anywhere", "const", "dialog", "drawer", "dropdownmenu", "for", "from", "onto", "open", "overlay", "popover", "props", "show", "spread", "state", "usedisclosure"], registryDependencies: [] }, { name: "use-dismiss", type: "registry:hook", description: "Inside one of `refs` (panel first, then its trigger), or inside a floating child opened from\nthe panel: a Select list or menu portals out, but it is marked `data-floating`.", exports: ["isWithin", "useDismiss"], keywords: ["and", "but", "child", "children", "closes", "data", "first", "floating", "from", "inside", "its", "list", "marked", "menu", "one", "opened", "out", "outside", "panel", "pointerdown", "portals", "refs", "select", "the", "then", "trigger"], registryDependencies: [] }, { name: "use-hotkey", type: "registry:hook", description: '`"mod+k"`: ⌘K on Mac, Ctrl+K elsewhere, without Alt. `"/"`: the key alone, no modifiers.', exports: ["matchesHotkey", "useHotkey"], keywords: ["alone", "alt", "browser", "ctrl", "disable", "elsewhere", "false", "handler", "key", "keyboard", "leave", "mac", "mod", "modifiers", "pass", "preventdefault", "returns", "shortcut", "the", "undefined", "wide", "window", "without"], registryDependencies: [] }, { name: "use-hover-open", type: "registry:hook", description: "Open-on-hover state with intent delays, shared by Tooltip and HoverCard. Mouse only (touch\ntaps go to the trigger's own action); keyboard focus opens it too. Spread `trigger` on the\nanchor and `floating` on the panel so moving between them keeps it open.", exports: ["useHoverOpen"], keywords: ["action", "anchor", "and", "between", "delays", "floating", "focus", "hover", "hovercard", "intent", "keeps", "keyboard", "mouse", "moving", "only", "open", "opens", "own", "panel", "shared", "spread", "state", "taps", "the", "them", "too", "tooltip", "touch", "trigger", "with"], registryDependencies: [] }, { name: "use-indicator", type: "registry:hook", description: `Offset and width of the active item, for one indicator that springs between items (Tabs,
17190
17256
  ToggleGroup). Re-measures when the item or its row resizes (font swap, wrap), or the pill
@@ -17284,7 +17350,7 @@ async function fetchAllItems(source) {
17284
17350
  // jsr.json
17285
17351
  var jsr_default = {
17286
17352
  name: "@kznlabs/labsui",
17287
- version: "0.1.4",
17353
+ version: "0.1.6",
17288
17354
  license: "MIT",
17289
17355
  exports: "./src/index.ts",
17290
17356
  publish: {
@@ -18129,6 +18195,9 @@ function printView(views) {
18129
18195
  console.log(md.replace(/^(#{2,3} .*)$/gm, (line) => bold(line)));
18130
18196
  }
18131
18197
 
18198
+ // src/mcp.ts
18199
+ import { fileURLToPath } from "node:url";
18200
+
18132
18201
  // src/rules.ts
18133
18202
  var rules = (alias = "@/") => `# labsUI
18134
18203
 
@@ -18170,8 +18239,7 @@ labsUI components live in this project as source: edit them like your own code.
18170
18239
  - Pointer targets are at least 24×24 px. Prefer native validation
18171
18240
  (\`required\`, \`type\`, \`pattern\`).`;
18172
18241
 
18173
- // src/mcp.ts
18174
- var PROTOCOLS = ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
18242
+ // src/tools.ts
18175
18243
  var names = {
18176
18244
  type: "array",
18177
18245
  items: { type: "string", pattern: "^[a-z0-9][a-z0-9-]*$" },
@@ -18182,18 +18250,25 @@ var names = {
18182
18250
  var installed = {
18183
18251
  ...names,
18184
18252
  minItems: 0,
18185
- description: "Installed item names, e.g. button. Empty: every installed item."
18253
+ description: "Installed item names, e.g. button. Empty: all installed items."
18186
18254
  };
18187
18255
  var dryRun = {
18188
18256
  type: "boolean",
18189
18257
  default: false,
18190
18258
  description: "Report what would change, write nothing."
18191
18259
  };
18260
+ var readOnly = { readOnlyHint: true, openWorldHint: false };
18261
+ var writes = {
18262
+ readOnlyHint: false,
18263
+ destructiveHint: false,
18264
+ idempotentHint: true,
18265
+ openWorldHint: true
18266
+ };
18192
18267
  var TOOLS = [
18193
18268
  {
18194
18269
  name: "search",
18195
18270
  title: "Search labsUI",
18196
- description: "Find components, blocks, hooks and helpers by name, export (useModal) or intent (date range, toast promise). All words must match; best first. No query lists everything.",
18271
+ description: "Find labsUI components, blocks, hooks and helpers by name, export (useModal) or intent (date range, toast promise). All words must match, best match first; no query lists everything. Returns one line per hit: name, kind and summary. Start here when you don't know an item's name, then call view on the hits.",
18197
18272
  inputSchema: {
18198
18273
  type: "object",
18199
18274
  properties: {
@@ -18201,7 +18276,7 @@ var TOOLS = [
18201
18276
  kind: {
18202
18277
  type: "string",
18203
18278
  enum: ["component", "block", "hook", "helper", "setup"],
18204
- description: "Only items of this kind."
18279
+ description: "Only this kind: component (primitive), block (composed section), hook, helper or setup."
18205
18280
  },
18206
18281
  limit: {
18207
18282
  type: "integer",
@@ -18212,12 +18287,12 @@ var TOOLS = [
18212
18287
  }
18213
18288
  }
18214
18289
  },
18215
- annotations: { readOnlyHint: true, openWorldHint: false }
18290
+ annotations: readOnly
18216
18291
  },
18217
18292
  {
18218
18293
  name: "view",
18219
18294
  title: "View labsUI items",
18220
- description: "Exact props and types, a usage line, full examples, what it brings along and which npm packages it installs. Call before writing code with a component.",
18295
+ description: "Read the docs of labsUI items by name: exact props and types, a usage line, full examples, and the items and npm packages each brings along. Call it before writing code with a component instead of guessing props; find names with search, install with add.",
18221
18296
  inputSchema: {
18222
18297
  type: "object",
18223
18298
  properties: {
@@ -18226,72 +18301,60 @@ var TOOLS = [
18226
18301
  },
18227
18302
  required: ["names"]
18228
18303
  },
18229
- annotations: { readOnlyHint: true, openWorldHint: false }
18304
+ annotations: readOnly
18230
18305
  },
18231
18306
  {
18232
18307
  name: "add",
18233
18308
  title: "Add labsUI items",
18234
- description: "Copy items and everything they import into the project and install their npm packages. Keeps files that already exist. Reports what to mount in the root layout.",
18309
+ description: "Install labsUI items into the project: copies each item and everything it imports, then installs their npm packages. Existing files are kept, never overwritten. Returns the files written, the packages installed and anything to mount once in the root layout. Needs init first; dryRun previews. To bring installed items to a newer version, use update instead.",
18235
18310
  inputSchema: {
18236
18311
  type: "object",
18237
18312
  properties: { names, dryRun },
18238
18313
  required: ["names"]
18239
18314
  },
18240
- annotations: {
18241
- readOnlyHint: false,
18242
- destructiveHint: false,
18243
- idempotentHint: true,
18244
- openWorldHint: true
18245
- }
18315
+ annotations: writes
18246
18316
  },
18247
18317
  {
18248
18318
  name: "init",
18249
18319
  title: "Set up labsUI",
18250
- description: "One-time setup: styles, theme, utils and motion provider; imports labsui.css into the Tailwind stylesheet and writes labsui.json. Returns the root layout code to add.",
18320
+ description: "Set up labsUI in a project, once, before add: writes the styles, theme, utils and motion provider, imports labsui.css into the Tailwind stylesheet and records settings in labsui.json. Returns warnings, the files written and the root layout code to add. Needs React 19 and Tailwind v4; run doctor first if unsure. Safe to repeat: existing files are kept. dryRun previews.",
18251
18321
  inputSchema: {
18252
18322
  type: "object",
18253
18323
  properties: { dryRun }
18254
18324
  },
18255
- annotations: {
18256
- readOnlyHint: false,
18257
- destructiveHint: false,
18258
- idempotentHint: true,
18259
- openWorldHint: true
18260
- }
18325
+ annotations: writes
18261
18326
  },
18262
18327
  {
18263
18328
  name: "diff",
18264
18329
  title: "Diff installed labsUI items",
18265
- description: "How installed items differ from this labsui version, as unified patches from the registry file to the project's. No names: every item that differs.",
18330
+ description: "Compare installed labsUI items with this labsUI version. Returns a unified patch per changed file, from the registry file to the project file (+ lines exist only in the project); matching items are left out, and when nothing differs it says so. Use it to see local edits before update. Needs init.",
18266
18331
  inputSchema: {
18267
18332
  type: "object",
18268
18333
  properties: { names: installed }
18269
18334
  },
18270
- annotations: { readOnlyHint: true, openWorldHint: false }
18335
+ annotations: readOnly
18271
18336
  },
18272
18337
  {
18273
18338
  name: "update",
18274
18339
  title: "Update labsUI items",
18275
- description: "Bring installed items to this labsui version. Unedited files are replaced; edited ones are merged three ways from the version that installed them, with conflict markers where both sides changed the same lines. No names: everything installed.",
18340
+ description: "Bring installed labsUI items to this labsUI version. Unedited files are replaced; edited ones are merged three ways from the version that installed them, with conflict markers where both sides changed the same lines. Returns each changed item as replaced, merged, conflicts (with the files to resolve) or kept with the reason. Run diff first to see local edits; dryRun previews. Only for installed items: new ones go through add.",
18276
18341
  inputSchema: {
18277
18342
  type: "object",
18278
18343
  properties: { names: installed, dryRun }
18279
18344
  },
18280
- annotations: {
18281
- readOnlyHint: false,
18282
- destructiveHint: true,
18283
- idempotentHint: true,
18284
- openWorldHint: true
18285
- }
18345
+ annotations: { ...writes, destructiveHint: true }
18286
18346
  },
18287
18347
  {
18288
18348
  name: "doctor",
18289
18349
  title: "Check the labsUI setup",
18290
- description: "Checks React 19, Tailwind v4, the path alias, the stylesheet import, MotionProvider and themeScript wiring, mounted Toaster/Confirmer, missing npm packages or files, and local edits. Each problem comes with its fix.",
18350
+ description: "Check the labsUI setup: React 19, Tailwind v4, the path alias, the stylesheet import, MotionProvider and themeScript wiring, mounted Toaster/Confirmer, missing npm packages or files, and local edits. Returns pass, warn or fail per check, each problem with its fix. Run it after init or add, or when components look unstyled; for line-level changes use diff.",
18291
18351
  inputSchema: { type: "object", properties: {} },
18292
- annotations: { readOnlyHint: true, openWorldHint: false }
18352
+ annotations: readOnly
18293
18353
  }
18294
18354
  ];
18355
+
18356
+ // src/mcp.ts
18357
+ var PROTOCOLS = ["2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05"];
18295
18358
  var text = (text, structured) => ({
18296
18359
  content: [{ type: "text", text }],
18297
18360
  ...structured !== undefined && { structuredContent: structured }
@@ -18423,6 +18486,26 @@ function serve(ctx) {
18423
18486
  `);
18424
18487
  let queue = Promise.resolve();
18425
18488
  let buffer = "";
18489
+ let usesRoots = false;
18490
+ let sent = 0;
18491
+ const waiting = new Map;
18492
+ const ask = (method) => new Promise((resolve) => {
18493
+ const id = `labsui-${++sent}`;
18494
+ const settle = (result) => {
18495
+ clearTimeout(timer);
18496
+ waiting.delete(id);
18497
+ resolve(result);
18498
+ };
18499
+ const timer = setTimeout(() => settle(undefined), 5000);
18500
+ waiting.set(id, settle);
18501
+ write({ jsonrpc: "2.0", id, method });
18502
+ });
18503
+ const readRoots = async () => {
18504
+ const roots = (await ask("roots/list"))?.roots;
18505
+ const uri = roots?.find((root) => root.uri?.startsWith("file:"))?.uri;
18506
+ if (uri)
18507
+ ctx.cwd = fileURLToPath(uri);
18508
+ };
18426
18509
  const onLine = (line) => {
18427
18510
  let msg;
18428
18511
  try {
@@ -18430,6 +18513,15 @@ function serve(ctx) {
18430
18513
  } catch {
18431
18514
  return write({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
18432
18515
  }
18516
+ if (!Array.isArray(msg) && msg.method === undefined)
18517
+ return waiting.get(String(msg.id))?.(msg.result);
18518
+ if (!Array.isArray(msg) && !ctx.pinned) {
18519
+ if (msg.method === "initialize")
18520
+ usesRoots = Boolean(msg.params?.capabilities?.roots);
18521
+ const changed = msg.method === "notifications/initialized" || msg.method === "notifications/roots/list_changed";
18522
+ if (usesRoots && changed)
18523
+ queue = queue.then(readRoots);
18524
+ }
18433
18525
  queue = queue.then(async () => {
18434
18526
  try {
18435
18527
  if (Array.isArray(msg)) {
@@ -18570,7 +18662,7 @@ async function main() {
18570
18662
  case "rules":
18571
18663
  return console.log(rules(readConfig(cwd)?.alias));
18572
18664
  case "mcp":
18573
- return serve({ cwd, registry, version: VERSION });
18665
+ return serve({ cwd, pinned: values.cwd !== undefined, registry, version: VERSION });
18574
18666
  default:
18575
18667
  throw new CliError(`Unknown command "${command}". Run labsui --help.`);
18576
18668
  }