@ngrok/mantle 0.76.3 → 0.76.4
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.
- package/README.md +8 -8
- package/dist/accordion.d.ts +1 -2
- package/dist/accordion.js +1 -2
- package/dist/agent.json +1 -1
- package/dist/alert-dialog.d.ts +4 -45
- package/dist/alert-dialog.js +1 -2
- package/dist/alert.d.ts +2 -3
- package/dist/alert.js +1 -2
- package/dist/anchor-CcTY5SIz.js +1 -2
- package/dist/anchor.d.ts +1 -2
- package/dist/as-child-uN_018tj.d.ts +1 -2
- package/dist/badge.d.ts +1 -2
- package/dist/badge.js +1 -2
- package/dist/booleanish-BfvnW6vy.js +1 -2
- package/dist/browser-only-BSl_hruR.js +1 -2
- package/dist/browser-only.d.ts +1 -2
- package/dist/button-BAxneEMu.js +1 -2
- package/dist/{button-uMIZVKit.js → button-BfMn3PgP.js} +1 -2
- package/dist/button-mfYak6Rx.d.ts +71 -0
- package/dist/button.d.ts +3 -3
- package/dist/button.js +1 -1
- package/dist/calendar.d.ts +2 -3
- package/dist/calendar.js +1 -2
- package/dist/card.d.ts +1 -2
- package/dist/card.js +1 -2
- package/dist/checkbox.d.ts +1 -2
- package/dist/checkbox.js +1 -2
- package/dist/code-block.d.ts +1 -2
- package/dist/code-block.js +2 -3
- package/dist/code-block_highlight-utils.js +1 -1
- package/dist/code.d.ts +1 -2
- package/dist/code.js +1 -2
- package/dist/color.js +1 -2
- package/dist/combobox.d.ts +1 -2
- package/dist/combobox.js +1 -2
- package/dist/command.d.ts +1 -2
- package/dist/command.js +1 -2
- package/dist/compose-refs-Cjf2gfB8.js +1 -2
- package/dist/copy-to-clipboard-Baw30q9O.js +1 -2
- package/dist/cx-CBSnSC36.js +1 -2
- package/dist/cx.d.ts +1 -2
- package/dist/data-table.d.ts +2 -3
- package/dist/data-table.js +1 -2
- package/dist/description-list.d.ts +1 -2
- package/dist/description-list.js +1 -2
- package/dist/{dialog-DR2V7zsR.js → dialog-ebkUwitP.js} +1 -2
- package/dist/dialog.d.ts +2 -3
- package/dist/dialog.js +1 -1
- package/dist/direction-CcTY0FmA.d.ts +1 -2
- package/dist/direction-Wa9W2F61.js +1 -2
- package/dist/{dropdown-menu-C3YZJBkV.js → dropdown-menu-BHyYWtrH.js} +1 -2
- package/dist/dropdown-menu-BqdyTFLu.d.ts +1 -2
- package/dist/dropdown-menu.js +1 -1
- package/dist/empty.d.ts +1 -2
- package/dist/empty.js +1 -2
- package/dist/field-context-4k1kI7Bo.js +1 -2
- package/dist/field.d.ts +2 -3
- package/dist/field.js +1 -2
- package/dist/flag.d.ts +1 -2
- package/dist/flag.js +1 -2
- package/dist/hooks.d.ts +1 -2
- package/dist/hooks.js +1 -2
- package/dist/hover-card.d.ts +1 -2
- package/dist/hover-card.js +1 -2
- package/dist/icon-C8bYBIHW.js +1 -2
- package/dist/{icon-button-ntupABbM.d.ts → icon-button-D7hs6bX2.d.ts} +52 -44
- package/dist/{icon-button-C_Ht_g1C.js → icon-button-DUNHVWpb.js} +1 -2
- package/dist/icon-n49kOh4_.d.ts +1 -2
- package/dist/icons.d.ts +1 -2
- package/dist/icons.js +1 -2
- package/dist/in-view-BC3wmz-a.d.ts +1 -2
- package/dist/in-view-C2DpZ6s0.js +1 -2
- package/dist/{index-L3NmbHi5.d.ts → index-Bed_XLWa.d.ts} +16 -2
- package/dist/index-CJbKEKr2.d.ts +1 -2
- package/dist/{index-DBZ3eRsl.d.ts → index-CTU6apE6.d.ts} +2 -3
- package/dist/index-DorCusfG.d.ts +1 -2
- package/dist/input.d.ts +1 -2
- package/dist/input.js +1 -2
- package/dist/is-input-CXmS0OFN.js +1 -2
- package/dist/kbd-Bv6tefdB.js +1 -2
- package/dist/kbd.d.ts +1 -2
- package/dist/label-DhIUmTN2.js +1 -2
- package/dist/label.d.ts +1 -2
- package/dist/llms.txt +1 -1
- package/dist/main.d.ts +1 -2
- package/dist/main.js +1 -2
- package/dist/mantle.css +13 -6
- package/dist/media-object.d.ts +1 -2
- package/dist/media-object.js +1 -2
- package/dist/multi-select.d.ts +1 -2
- package/dist/multi-select.js +1 -2
- package/dist/otp-input.d.ts +1 -2
- package/dist/otp-input.js +1 -2
- package/dist/pagination.d.ts +2 -3
- package/dist/pagination.js +1 -2
- package/dist/popover-DponNBot.js +1 -2
- package/dist/popover.d.ts +1 -2
- package/dist/primitive-Cn3h4DJg.js +1 -2
- package/dist/primitive-FoWela9a.d.ts +1 -2
- package/dist/progress.d.ts +1 -2
- package/dist/progress.js +1 -2
- package/dist/qr-code.d.ts +1 -2
- package/dist/qr-code.js +1 -2
- package/dist/radio-group.d.ts +1 -2
- package/dist/radio-group.js +1 -2
- package/dist/{resolve-pre-rendered-props-C-vrNxH1.js → resolve-pre-rendered-props-D9nlC6xE.js} +2 -3
- package/dist/resolve-pre-rendered-props-DxJ9-DAl.d.ts +1 -2
- package/dist/sandboxed-on-click.d.ts +1 -2
- package/dist/sandboxed-on-click.js +1 -2
- package/dist/select-C15-XvRT.d.ts +1 -2
- package/dist/{select-Cxc9VmP8.js → select-g0E_TsXr.js} +1 -2
- package/dist/select.js +1 -1
- package/dist/{separator-Bqjy77rG.js → separator-BXFUCWFa.js} +1 -2
- package/dist/separator.d.ts +1 -2
- package/dist/separator.js +1 -1
- package/dist/sheet.d.ts +2 -3
- package/dist/sheet.js +1 -2
- package/dist/skeleton.d.ts +1 -2
- package/dist/skeleton.js +1 -2
- package/dist/skip-to-main-link.d.ts +1 -2
- package/dist/skip-to-main-link.js +1 -2
- package/dist/slider.d.ts +1 -2
- package/dist/slider.js +1 -2
- package/dist/slot-CV5fmqFr.js +1 -2
- package/dist/sort-BPX2Fk9t.js +1 -2
- package/dist/split-button.d.ts +5 -6
- package/dist/split-button.js +1 -2
- package/dist/svg-only-Cz1cby8y.js +1 -2
- package/dist/svg-only-f6ToFLH0.d.ts +1 -2
- package/dist/switch.d.ts +1 -2
- package/dist/switch.js +1 -2
- package/dist/table-BWD9IlIN.d.ts +1 -2
- package/dist/table-DWy_oNta.js +1 -2
- package/dist/tabs.d.ts +1 -2
- package/dist/tabs.js +1 -2
- package/dist/text-area.d.ts +1 -2
- package/dist/text-area.js +1 -2
- package/dist/theme-provider-MMwxHEfw.js +1 -2
- package/dist/theme.d.ts +1 -2
- package/dist/theme.js +1 -2
- package/dist/themes-CYNpplwN.d.ts +1 -2
- package/dist/toast-CR3MVChj.js +1 -2
- package/dist/toast.d.ts +1 -2
- package/dist/tooltip.d.ts +1 -2
- package/dist/tooltip.js +1 -2
- package/dist/traffic-policy-file-0g5RXFqu.js +1 -2
- package/dist/types-BvUzforF.d.ts +1 -2
- package/dist/types-D85fCNV3.js +1 -2
- package/dist/types.d.ts +1 -3
- package/dist/use-copy-to-clipboard-BLpquU9d.js +1 -2
- package/dist/use-isomorphic-layout-effect-DdTRtMY-.js +1 -2
- package/dist/use-matches-media-query-CMSxHR9n.js +1 -2
- package/dist/use-prefers-reduced-motion-CWIoFA6W.js +1 -2
- package/dist/utils.d.ts +1 -2
- package/dist/utils.js +1 -2
- package/dist/validation-DCyx-ceH.js +1 -2
- package/dist/validation-xyX_6kph.d.ts +1 -2
- package/dist/well.d.ts +1 -2
- package/dist/well.js +1 -2
- package/dist/with-style-props-CyImx7vd.d.ts +1 -2
- package/package.json +5 -5
- package/dist/accordion.js.map +0 -1
- package/dist/alert-dialog.js.map +0 -1
- package/dist/alert.js.map +0 -1
- package/dist/anchor-CcTY5SIz.js.map +0 -1
- package/dist/badge.js.map +0 -1
- package/dist/booleanish-BfvnW6vy.js.map +0 -1
- package/dist/browser-only-BSl_hruR.js.map +0 -1
- package/dist/button-BAxneEMu.js.map +0 -1
- package/dist/button-BXZ_JTu_.d.ts +0 -172
- package/dist/button-uMIZVKit.js.map +0 -1
- package/dist/calendar.js.map +0 -1
- package/dist/card.js.map +0 -1
- package/dist/checkbox.js.map +0 -1
- package/dist/code-block.js.map +0 -1
- package/dist/code.js.map +0 -1
- package/dist/color.js.map +0 -1
- package/dist/combobox.js.map +0 -1
- package/dist/command.js.map +0 -1
- package/dist/compose-refs-Cjf2gfB8.js.map +0 -1
- package/dist/copy-to-clipboard-Baw30q9O.js.map +0 -1
- package/dist/cx-CBSnSC36.js.map +0 -1
- package/dist/data-table.js.map +0 -1
- package/dist/deep-non-nullable-BxRoySYR.d.ts +0 -8
- package/dist/description-list.js.map +0 -1
- package/dist/dialog-DR2V7zsR.js.map +0 -1
- package/dist/direction-Wa9W2F61.js.map +0 -1
- package/dist/dropdown-menu-C3YZJBkV.js.map +0 -1
- package/dist/empty.js.map +0 -1
- package/dist/field-context-4k1kI7Bo.js.map +0 -1
- package/dist/field.js.map +0 -1
- package/dist/flag.js.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/hover-card.js.map +0 -1
- package/dist/icon-C8bYBIHW.js.map +0 -1
- package/dist/icon-button-C_Ht_g1C.js.map +0 -1
- package/dist/icons.js.map +0 -1
- package/dist/in-view-C2DpZ6s0.js.map +0 -1
- package/dist/input.js.map +0 -1
- package/dist/is-input-CXmS0OFN.js.map +0 -1
- package/dist/kbd-Bv6tefdB.js.map +0 -1
- package/dist/label-DhIUmTN2.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/media-object.js.map +0 -1
- package/dist/multi-select.js.map +0 -1
- package/dist/otp-input.js.map +0 -1
- package/dist/pagination.js.map +0 -1
- package/dist/popover-DponNBot.js.map +0 -1
- package/dist/primitive-Cn3h4DJg.js.map +0 -1
- package/dist/progress.js.map +0 -1
- package/dist/qr-code.js.map +0 -1
- package/dist/radio-group.js.map +0 -1
- package/dist/resolve-pre-rendered-props-C-vrNxH1.js.map +0 -1
- package/dist/sandboxed-on-click.js.map +0 -1
- package/dist/select-Cxc9VmP8.js.map +0 -1
- package/dist/separator-Bqjy77rG.js.map +0 -1
- package/dist/sheet.js.map +0 -1
- package/dist/skeleton.js.map +0 -1
- package/dist/skip-to-main-link.js.map +0 -1
- package/dist/slider.js.map +0 -1
- package/dist/slot-CV5fmqFr.js.map +0 -1
- package/dist/sort-BPX2Fk9t.js.map +0 -1
- package/dist/split-button.js.map +0 -1
- package/dist/svg-only-Cz1cby8y.js.map +0 -1
- package/dist/switch.js.map +0 -1
- package/dist/table-DWy_oNta.js.map +0 -1
- package/dist/tabs.js.map +0 -1
- package/dist/text-area.js.map +0 -1
- package/dist/theme-provider-MMwxHEfw.js.map +0 -1
- package/dist/theme.js.map +0 -1
- package/dist/toast-CR3MVChj.js.map +0 -1
- package/dist/tooltip.js.map +0 -1
- package/dist/traffic-policy-file-0g5RXFqu.js.map +0 -1
- package/dist/types-D85fCNV3.js.map +0 -1
- package/dist/use-copy-to-clipboard-BLpquU9d.js.map +0 -1
- package/dist/use-isomorphic-layout-effect-DdTRtMY-.js.map +0 -1
- package/dist/use-matches-media-query-CMSxHR9n.js.map +0 -1
- package/dist/use-prefers-reduced-motion-CWIoFA6W.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/validation-DCyx-ceH.js.map +0 -1
- package/dist/variant-props-CVymuSfa.d.ts +0 -13
- package/dist/well.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dialog-DR2V7zsR.js","names":["DialogPrimitive.Root","DialogPrimitive.Trigger","DialogPrimitive.Portal","DialogPrimitive.Close","DialogPrimitive.Overlay","DialogPrimitive.Content","DialogPrimitive.Title","DialogPrimitive.Description"],"sources":["../src/components/dialog/dialog.tsx"],"sourcesContent":["import { XIcon } from \"@phosphor-icons/react/X\";\nimport type { ComponentProps, ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { IconButton, type IconButtonProps } from \"../button/icon-button.js\";\nimport * as DialogPrimitive from \"./primitive.js\";\n\n/**\n * A window overlaid on either the primary window or another dialog window.\n * The root stateful component for the Dialog.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogroot\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Root = DialogPrimitive.Root;\nRoot.displayName = \"Dialog\";\n\n/**\n * A button that opens the dialog.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogtrigger\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Trigger = forwardRef<\n\tComponentRef<typeof DialogPrimitive.Trigger>,\n\tComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>\n>((props, ref) => <DialogPrimitive.Trigger ref={ref} data-slot=\"dialog-trigger\" {...props} />);\nTrigger.displayName = \"DialogTrigger\";\n\n/**\n * The portal container for the dialog. Renders the overlay and content into a\n * portal so the dialog escapes its parent's stacking context.\n *\n * Most consumers should not need to use this directly — `Dialog.Content`\n * already wraps its children in a portal. Use this only when you need to\n * customize the portal target or render the overlay yourself.\n *\n * @see https://mantle.ngrok.com/components/dialog#api-reference\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Portal>\n * <Dialog.Overlay />\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Portal>\n * </Dialog.Root>\n * ```\n */\nconst Portal = DialogPrimitive.Portal;\nPortal.displayName = \"DialogPortal\";\n\n/**\n * A button that closes the dialog when clicked. Wrap an interactive element\n * with `asChild` to delegate the close behavior to your own button.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogclose\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Close = forwardRef<\n\tComponentRef<typeof DialogPrimitive.Close>,\n\tComponentPropsWithoutRef<typeof DialogPrimitive.Close>\n>((props, ref) => <DialogPrimitive.Close ref={ref} data-slot=\"dialog-close\" {...props} />);\nClose.displayName = \"DialogClose\";\n\n/**\n * The backdrop overlay for the dialog. Sits between the page and the dialog\n * content and applies a blur and dim effect.\n *\n * Most consumers should not need to use this directly — `Dialog.Content`\n * renders an overlay automatically. Use this only when composing a custom\n * `Dialog.Portal` tree.\n *\n * @see https://mantle.ngrok.com/components/dialog#api-reference\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Portal>\n * <Dialog.Overlay />\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Portal>\n * </Dialog.Root>\n * ```\n */\nconst Overlay = forwardRef<\n\tComponentRef<\"div\">,\n\tComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay\n\t\tref={ref}\n\t\tdata-slot=\"dialog-overlay\"\n\t\tclassName={cx(\n\t\t\t\"bg-overlay data-state-closed:animate-out data-state-closed:fade-out-0 data-state-open:animate-in data-state-open:fade-in-0 fixed inset-0 z-50 backdrop-blur-xs\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nOverlay.displayName = \"DialogOverlay\";\n\ntype ContentProps = ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {\n\t/**\n\t * The preferred width of the `Dialog.Content` as a tailwind `max-w-` class.\n\t *\n\t * By default, a `Dialog`'s content width is responsive with a default\n\t * preferred width: the maximum width of the `Dialog.Content`\n\t *\n\t * @default `max-w-lg`\n\t */\n\tpreferredWidth?: `max-w-${string}`;\n};\n\n/**\n * The container for the dialog content.\n * Renders on top of the overlay and is centered in the viewport.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogcontent\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Content = forwardRef<ComponentRef<\"div\">, ContentProps>(\n\t({ children, className, preferredWidth = \"max-w-lg\", ...props }, ref) => (\n\t\t<Portal>\n\t\t\t<Overlay />\n\t\t\t<div className=\"fixed inset-4 z-50 flex items-center justify-center\">\n\t\t\t\t<DialogPrimitive.Content\n\t\t\t\t\tdata-mantle-modal-content\n\t\t\t\t\tdata-slot=\"dialog-content\"\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"flex max-h-full w-full flex-1 flex-col\",\n\t\t\t\t\t\t\"outline-hidden focus-within:outline-hidden\",\n\t\t\t\t\t\t\"border-dialog bg-dialog rounded-xl border shadow-lg transition-transform duration-200\",\n\t\t\t\t\t\t\"data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95\",\n\t\t\t\t\t\tpreferredWidth,\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\n\t\t\t\t\tref={ref}\n\t\t\t\t\t{...props}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</DialogPrimitive.Content>\n\t\t\t</div>\n\t\t</Portal>\n\t),\n);\nContent.displayName = \"DialogContent\";\n\n/**\n * Contains the header content of the dialog, including the title and close button.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogheader\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Header = ({ className, children, ...props }: ComponentProps<\"div\">) => (\n\t<div\n\t\tdata-slot=\"dialog-header\"\n\t\tclassName={cx(\n\t\t\t\"border-dialog-muted text-strong relative flex shrink-0 items-center justify-between gap-2 border-b px-6 py-4\",\n\t\t\t\"has-[.icon-button]:pr-4\", // when there are actions in the header, shorten the padding\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t</div>\n);\nHeader.displayName = \"DialogHeader\";\n\ntype CloseIconButtonProps = Partial<Omit<IconButtonProps, \"icon\">>;\n\n/**\n * An icon button that closes the dialog when clicked.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogcloseiconbutton\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst CloseIconButton = ({\n\tsize = \"md\",\n\ttype = \"button\",\n\tlabel = \"Close Dialog\",\n\tappearance = \"ghost\",\n\t...props\n}: CloseIconButtonProps) => (\n\t<DialogPrimitive.Close asChild>\n\t\t<IconButton\n\t\t\tappearance={appearance}\n\t\t\tdata-slot=\"dialog-close-icon-button\"\n\t\t\ticon={<XIcon />}\n\t\t\tlabel={label}\n\t\t\tsize={size}\n\t\t\ttype={type}\n\t\t\t{...props}\n\t\t/>\n\t</DialogPrimitive.Close>\n);\nCloseIconButton.displayName = \"DialogCloseIconButton\";\n\n/**\n * Contains the main content of the dialog.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogbody\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Body = ({ className, ...props }: ComponentProps<\"div\">) => (\n\t<div\n\t\tdata-slot=\"dialog-body\"\n\t\tclassName={cx(\n\t\t\t\"scrollbar scrollbar-gutter-stable text-body flex-1 overflow-y-auto p-6\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nBody.displayName = \"DialogBody\";\n\n/**\n * Contains the footer content of the dialog, including action buttons.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogfooter\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Footer = ({ className, ...props }: ComponentProps<\"div\">) => (\n\t<div\n\t\tdata-slot=\"dialog-footer\"\n\t\tclassName={cx(\n\t\t\t\"border-dialog-muted flex shrink-0 justify-end gap-2 border-t px-6 py-4\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nFooter.displayName = \"DialogFooter\";\n\n/**\n * An accessible name to be announced when the dialog is opened.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogtitle\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Title = forwardRef<\n\tComponentRef<typeof DialogPrimitive.Title>,\n\tComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tdata-slot=\"dialog-title\"\n\t\tclassName={cx(\"text-strong truncate text-lg font-medium\", className)}\n\t\t{...props}\n\t/>\n));\nTitle.displayName = \"DialogTitle\";\n\n/**\n * An accessible description to be announced when the dialog is opened.\n * Renders as a `div` by default, but can be changed to any other element using\n * the `asChild` prop.\n *\n * @see https://mantle.ngrok.com/components/dialog#dialogdescription\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Description = forwardRef<\n\tComponentRef<typeof DialogPrimitive.Description>,\n\tComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tdata-slot=\"dialog-description\"\n\t\tclassName={cx(\"text-muted\", className)}\n\t\t{...props}\n\t/>\n));\nDescription.displayName = \"DialogDescription\";\n\n/**\n * A window overlaid on either the primary window or another dialog window. Use\n * Dialog for a focused modal that interrupts the user to gather input or\n * confirm a non-destructive choice. For destructive or irreversible\n * confirmations (delete, sign out, leave without saving), prefer `AlertDialog`.\n * For side-panel content that slides in from an edge (filter panels, detail\n * views, navigation drawers), prefer `Sheet`.\n *\n * @see https://mantle.ngrok.com/components/dialog\n *\n * @example\n * Composition:\n * ```\n * Dialog.Root\n * ├── Dialog.Trigger\n * └── Dialog.Content\n * ├── Dialog.Header\n * │ ├── Dialog.Title\n * │ ├── Dialog.Description\n * │ └── Dialog.CloseIconButton\n * ├── Dialog.Body\n * └── Dialog.Footer\n * └── Dialog.Close\n * ```\n *\n * @example\n * ```tsx\n * <Dialog.Root>\n * <Dialog.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n * </Dialog.Trigger>\n * <Dialog.Content>\n * <Dialog.Header>\n * <Dialog.Title>Dialog Title</Dialog.Title>\n * <Dialog.Description>This is an optional description.</Dialog.Description>\n * <Dialog.CloseIconButton />\n * </Dialog.Header>\n * <Dialog.Body>\n * <p>This is the dialog content.</p>\n * </Dialog.Body>\n * <Dialog.Footer>\n * <Dialog.Close asChild>\n * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n * </Dialog.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Dialog.Footer>\n * </Dialog.Content>\n * </Dialog.Root>\n * ```\n */\nconst Dialog = {\n\t/**\n\t * A window overlaid on either the primary window or another dialog window.\n\t * The root stateful component for the Dialog.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * Contains the main content of the dialog.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogbody\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tBody,\n\t/**\n\t * A button that closes the dialog when clicked.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogclose\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tClose,\n\t/**\n\t * An icon button that closes the dialog when clicked.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogcloseiconbutton\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tCloseIconButton,\n\t/**\n\t * The container for the dialog content.\n\t * Renders on top of the overlay and is centered in the viewport.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * An accessible description to be announced when the dialog is opened.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogdescription\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * Contains the footer content of the dialog, including action buttons.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogfooter\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tFooter,\n\t/**\n\t * Contains the header content of the dialog, including the title and close button.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogheader\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tHeader,\n\t/**\n\t * The overlay backdrop for the dialog.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#api-reference\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Portal>\n\t * <Dialog.Overlay />\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Portal>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tOverlay,\n\t/**\n\t * The portal container for the dialog.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#api-reference\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Portal>\n\t * <Dialog.Overlay />\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Portal>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tPortal,\n\t/**\n\t * An accessible name to be announced when the dialog is opened.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogtitle\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tTitle,\n\t/**\n\t * A button that opens the dialog.\n\t *\n\t * @see https://mantle.ngrok.com/components/dialog#dialogtrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Dialog.Root>\n\t * <Dialog.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Dialog</Button>\n\t * </Dialog.Trigger>\n\t * <Dialog.Content>\n\t * <Dialog.Header>\n\t * <Dialog.Title>Dialog Title</Dialog.Title>\n\t * <Dialog.Description>This is an optional description.</Dialog.Description>\n\t * <Dialog.CloseIconButton />\n\t * </Dialog.Header>\n\t * <Dialog.Body>\n\t * <p>This is the dialog content.</p>\n\t * </Dialog.Body>\n\t * <Dialog.Footer>\n\t * <Dialog.Close asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Cancel</Button>\n\t * </Dialog.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Dialog.Footer>\n\t * </Dialog.Content>\n\t * </Dialog.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tDialog,\n};\n"],"mappings":"sSAsCA,MAAM,EAAOA,EACb,EAAK,YAAc,SAgCnB,MAAM,EAAU,GAGb,EAAO,IAAQ,EAACC,EAAD,CAA8B,MAAK,YAAU,iBAAiB,GAAI,CAAQ,CAAA,CAAC,EAC7F,EAAQ,YAAc,gBAwCtB,MAAM,EAASC,EACf,EAAO,YAAc,eAiCrB,MAAM,EAAQ,GAGX,EAAO,IAAQ,EAACC,EAAD,CAA4B,MAAK,YAAU,eAAe,GAAI,CAAQ,CAAA,CAAC,EACzF,EAAM,YAAc,cAwCpB,MAAM,EAAU,GAGb,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACC,EAAD,CACM,MACL,YAAU,iBACV,UAAW,EACV,iKACA,CACD,EACA,GAAI,CACJ,CAAA,CACD,EACD,EAAQ,YAAc,gBA6CtB,MAAM,EAAU,GACd,CAAE,WAAU,YAAW,iBAAiB,WAAY,GAAG,GAAS,IAChE,EAAC,EAAD,CAAA,SAAA,CACC,EAAC,EAAD,CAAU,CAAA,EACV,EAAC,MAAD,CAAK,UAAU,+DACd,EAACC,EAAD,CACC,4BAAA,GACA,YAAU,iBACV,UAAW,EACV,yCACA,6CACA,wFACA,2KACA,EACA,CACD,EACK,MACL,GAAI,EAEH,UACuB,CAAA,CACrB,CAAA,CACE,CAAA,CAAA,CAEV,EACA,EAAQ,YAAc,gBAgCtB,MAAM,GAAU,CAAE,YAAW,WAAU,GAAG,KACzC,EAAC,MAAD,CACC,YAAU,gBACV,UAAW,EACV,+GACA,0BACA,CACD,EACA,GAAI,EAEH,UACG,CAAA,EAEN,EAAO,YAAc,eAkCrB,MAAM,GAAmB,CACxB,OAAO,KACP,OAAO,SACP,QAAQ,eACR,aAAa,QACb,GAAG,KAEH,EAACF,EAAD,CAAuB,QAAA,YACtB,EAAC,EAAD,CACa,aACZ,YAAU,2BACV,KAAM,EAAC,EAAD,CAAQ,CAAA,EACP,QACD,OACA,OACN,GAAI,CACJ,CAAA,CACqB,CAAA,EAExB,EAAgB,YAAc,wBAgC9B,MAAM,GAAQ,CAAE,YAAW,GAAG,KAC7B,EAAC,MAAD,CACC,YAAU,cACV,UAAW,EACV,yEACA,CACD,EACA,GAAI,CACJ,CAAA,EAEF,EAAK,YAAc,aAgCnB,MAAM,GAAU,CAAE,YAAW,GAAG,KAC/B,EAAC,MAAD,CACC,YAAU,gBACV,UAAW,EACV,yEACA,CACD,EACA,GAAI,CACJ,CAAA,EAEF,EAAO,YAAc,eAgCrB,MAAM,EAAQ,GAGX,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACG,EAAD,CACM,MACL,YAAU,eACV,UAAW,EAAG,2CAA4C,CAAS,EACnE,GAAI,CACJ,CAAA,CACD,EACD,EAAM,YAAc,cAkCpB,MAAM,EAAc,GAGjB,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACC,EAAD,CACM,MACL,YAAU,qBACV,UAAW,EAAG,aAAc,CAAS,EACrC,GAAI,CACJ,CAAA,CACD,EACD,EAAY,YAAc,oBAoD1B,MAAM,EAAS,CAgCd,OA+BA,OA+BA,QA+BA,kBAgCA,UA+BA,cA+BA,SA+BA,SAkCA,UAkCA,SA+BA,QA+BA,SACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"direction-Wa9W2F61.js","names":[],"sources":["../src/utils/sorting/direction.ts"],"sourcesContent":["/**\n * Sorting modes\n * - alphanumeric: Sort by alphanumeric order (A-Z, 0-9, Z-A, 9-0)\n * - time: Sort by time (newest-to-oldest, oldest-to-newest)\n */\nconst sortingModes = [\"alphanumeric\", \"time\"] as const;\n\n/**\n * Sorting modes\n * - alphanumeric: Sort by alphanumeric order (A-Z, 0-9, Z-A, 9-0)\n * - time: Sort by time (newest-to-oldest, oldest-to-newest)\n */\ntype SortingMode = (typeof sortingModes)[number];\n\n/**\n * Type guard for sorting modes\n * - alphanumeric: Sort by alphanumeric order (A-Z, 0-9, Z-A, 9-0)\n * - time: Sort by time (newest-to-oldest, oldest-to-newest)\n *\n * @example isSortingMode(\"alphanumeric\") // true\n * @example isSortingMode(\"time\") // true\n * @example isSortingMode(\"foo\") // false\n */\nconst isSortingMode = (value: unknown): value is SortingMode =>\n\ttypeof value === \"string\" && sortingModes.includes(value as SortingMode);\n\n/**\n * Runtime type-to-value helper for sorting modes\n * - alphanumeric: Sort by alphanumeric order (A-Z, 0-9, Z-A, 9-0)\n * - time: Sort by time (newest-to-oldest, oldest-to-newest)\n *\n * @example $sortingMode(\"alphanumeric\") // \"alphanumeric\"\n * @example $sortingMode(\"time\") // \"time\"\n */\nconst $sortingMode = <T extends SortingMode = SortingMode>(value: T) => value;\n\n/**\n * Sorting directions\n * - asc: Ascending order (alphanumeric: A-Z, 0-9; time: oldest-to-newest)\n * - desc: Descending order (alphanumeric: Z-A, 9-0; time: newest-to-oldest)\n */\nconst sortingDirections = [\"asc\", \"desc\"] as const;\n\n/**\n * Sorting directions\n * - asc: Ascending order (alphanumeric: A-Z, 0-9; time: oldest-to-newest)\n * - desc: Descending order (alphanumeric: Z-A, 9-0; time: newest-to-oldest)\n */\ntype SortingDirection = (typeof sortingDirections)[number];\n\n/**\n * Type guard for sorting directions\n * - asc: Ascending order (alphanumeric: A-Z, 0-9; time: oldest-to-newest)\n * - desc: Descending order (alphanumeric: Z-A, 9-0; time: newest-to-oldest)\n *\n * @example isSortingDirection(\"asc\") // true\n * @example isSortingDirection(\"desc\") // true\n * @example isSortingDirection(\"foo\") // false\n */\nconst isSortingDirection = (value: unknown): value is SortingDirection =>\n\ttypeof value === \"string\" && sortingDirections.includes(value as SortingDirection);\n\n/**\n * Runtime type-to-value helper for sorting directions\n * - asc: Ascending order (alphanumeric: A-Z, 0-9; time: oldest-to-newest)\n * - desc: Descending order (alphanumeric: Z-A, 9-0; time: newest-to-oldest)\n *\n * @example $sortingDirection(\"asc\") // \"asc\"\n * @example $sortingDirection(\"desc\") // \"desc\"\n */\nconst $sortingDirection = <T extends SortingDirection = SortingDirection>(value: T) => value;\n\n/**\n * Alphanumeric sorting directions\n * - asc: Ascending order (A-Z, 0-9)\n * - desc: Descending order (Z-A, 9-0)\n */\nconst alphanumericSortingDirections = [...sortingDirections] as const;\n\n/**\n * Alphanumeric sorting directions\n * - asc: Ascending order (A-Z, 0-9)\n * - desc: Descending order (Z-A, 9-0)\n */\ntype AlphanumericSortingDirection = (typeof alphanumericSortingDirections)[number];\n\n/**\n * Type guard for alphanumeric sorting directions\n * - asc: Ascending order (A-Z, 0-9)\n * - desc: Descending order (Z-A, 9-0)\n *\n * @example isAlphanumericSortingDirection(\"asc\") // true\n * @example isAlphanumericSortingDirection(\"desc\") // true\n * @example isAlphanumericSortingDirection(\"foo\") // false\n */\nconst isAlphanumericSortingDirection = (value: unknown): value is AlphanumericSortingDirection =>\n\ttypeof value === \"string\" &&\n\talphanumericSortingDirections.includes(value as AlphanumericSortingDirection);\n\n/**\n * Runtime type-to-value helper for alphanumeric sorting directions\n * - asc: Ascending order (A-Z, 0-9)\n * - desc: Descending order (Z-A, 9-0)\n *\n * @example $alphanumericSortingDirection(\"asc\") // \"asc\"\n * @example $alphanumericSortingDirection(\"desc\") // \"desc\"\n */\nconst $alphanumericSortingDirection = <\n\tT extends AlphanumericSortingDirection = AlphanumericSortingDirection,\n>(\n\tvalue: T,\n) => value;\n\n/**\n * Time sorting directions\n * - newest-to-oldest: Descending order (newest first, oldest last)\n * - oldest-to-newest: Ascending order (oldest first, newest last)\n */\nconst timeSortingDirections = [\"newest-to-oldest\", \"oldest-to-newest\"] as const;\n\n/**\n * Time sorting directions\n * - newest-to-oldest: Descending order (newest first, oldest last)\n * - oldest-to-newest: Ascending order (oldest first, newest last)\n */\ntype TimeSortingDirection = (typeof timeSortingDirections)[number];\n\n/**\n * Type guard for time sorting directions\n * - newest-to-oldest: Descending order (newest first, oldest last)\n * - oldest-to-newest: Ascending order (oldest first, newest last)\n *\n * @example isTimeSortingDirection(\"newest-to-oldest\") // true\n * @example isTimeSortingDirection(\"oldest-to-newest\") // true\n * @example isTimeSortingDirection(\"foo\") // false\n * @example isTimeSortingDirection(\"asc\") // false\n * @example isTimeSortingDirection(\"desc\") // false\n */\nconst isTimeSortingDirection = (value: unknown): value is TimeSortingDirection =>\n\ttypeof value === \"string\" && timeSortingDirections.includes(value as TimeSortingDirection);\n\n/**\n * Converts a sorting direction to a time sorting direction\n * - asc -> oldest-to-newest\n * - desc -> newest-to-oldest\n */\nconst timeSortingByDirection = {\n\tasc: \"oldest-to-newest\",\n\tdesc: \"newest-to-oldest\",\n} as const satisfies Record<SortingDirection, TimeSortingDirection>;\n\n/**\n * Runtime type-to-value helper for time sorting directions.\n * If given a sorting direction, it will convert it to a time sorting direction.\n * - newest-to-oldest: Descending order (desc; newest first, oldest last)\n * - oldest-to-newest: Ascending order (asc; oldest first, newest last)\n *\n * @example $timeSortingDirection(\"asc\") // \"oldest-to-newest\"\n * @example $timeSortingDirection(\"desc\") // \"newest-to-oldest\"\n * @example $timeSortingDirection(\"oldest-to-newest\") // \"oldest-to-newest\"\n * @example $timeSortingDirection(\"newest-to-oldest\") // \"newest-to-oldest\"\n */\nfunction $timeSortingDirection<T extends TimeSortingDirection | SortingDirection>(value: T) {\n\tif (isSortingDirection(value)) {\n\t\treturn timeSortingByDirection[value];\n\t}\n\tif (isTimeSortingDirection(value)) {\n\t\treturn value;\n\t}\n\tthrow new Error(`Invalid time sorting direction given: \"${value}\"`);\n}\n\nexport {\n\t//,\n\t$alphanumericSortingDirection,\n\t$sortingDirection,\n\t$sortingMode,\n\t$timeSortingDirection,\n\talphanumericSortingDirections,\n\tisAlphanumericSortingDirection,\n\tisSortingDirection,\n\tisSortingMode,\n\tisTimeSortingDirection,\n\tsortingDirections,\n\tsortingModes,\n\ttimeSortingByDirection,\n\ttimeSortingDirections,\n};\n\nexport type {\n\t//,\n\tAlphanumericSortingDirection,\n\tSortingDirection,\n\tSortingMode,\n\tTimeSortingDirection,\n};\n"],"mappings":"AAKA,MAAM,EAAe,CAAC,eAAgB,MAAM,EAkBtC,EAAiB,GACtB,OAAO,GAAU,UAAY,EAAa,SAAS,CAAoB,EAUlE,EAAqD,GAAa,EAOlE,EAAoB,CAAC,MAAO,MAAM,EAkBlC,EAAsB,GAC3B,OAAO,GAAU,UAAY,EAAkB,SAAS,CAAyB,EAU5E,EAAoE,GAAa,EAOjF,EAAgC,CAAC,GAAG,CAAiB,EAkBrD,EAAkC,GACvC,OAAO,GAAU,UACjB,EAA8B,SAAS,CAAqC,EAUvE,EAGL,GACI,EAOC,EAAwB,CAAC,mBAAoB,kBAAkB,EAoB/D,EAA0B,GAC/B,OAAO,GAAU,UAAY,EAAsB,SAAS,CAA6B,EAOpF,EAAyB,CAC9B,IAAK,mBACL,KAAM,kBACP,EAaA,SAAS,EAAyE,EAAU,CAC3F,GAAI,EAAmB,CAAK,EAC3B,OAAO,EAAuB,GAE/B,GAAI,EAAuB,CAAK,EAC/B,OAAO,EAER,MAAU,MAAM,0CAA0C,EAAM,EAAE,CACnE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown-menu-C3YZJBkV.js","names":[],"sources":["../src/components/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import { CaretRightIcon } from \"@phosphor-icons/react/CaretRight\";\nimport { CheckIcon } from \"@phosphor-icons/react/Check\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport type { ComponentProps, ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport { Separator } from \"../separator/separator.js\";\n\n/**\n * A menu of options or actions, triggered by a button.\n * This is the root, stateful component that manages the open/closed state of the dropdown menu.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuroot\n *\n * @example\n * ```tsx\n * <DropdownMenu.Root>\n * <DropdownMenu.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Menu\n * </Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n * <DropdownMenu.Item>Item 2</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu.Root>\n * ```\n */\nconst Root = DropdownMenuPrimitive.Root;\nRoot.displayName = \"DropdownMenu\";\n\n/**\n * The trigger button that opens the dropdown menu.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenutrigger\n *\n * @example\n * ```tsx\n * <DropdownMenu.Root>\n * <DropdownMenu.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Menu\n * </Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu.Root>\n * ```\n */\nconst Trigger = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.Trigger>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>\n>((props, ref) => (\n\t<DropdownMenuPrimitive.Trigger ref={ref} data-slot=\"dropdown-menu-trigger\" {...props} />\n));\nTrigger.displayName = \"DropdownMenuTrigger\";\n\nconst Group = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.Group>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Group>\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Group\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-group\"\n\t\tclassName={cx(\"space-y-px\", className)}\n\t\t{...props}\n\t/>\n));\nGroup.displayName = \"DropdownMenuGroup\";\n\n/**\n * The portal container for rendering dropdown content outside the normal DOM tree.\n */\nconst Portal = DropdownMenuPrimitive.Portal;\nPortal.displayName = \"DropdownMenuPortal\";\n\nconst Sub = DropdownMenuPrimitive.Sub;\nSub.displayName = \"DropdownMenuSub\";\n\nconst RadioGroup = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.RadioGroup>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioGroup>\n>(({ className, ...props }, ref) => (\n\t<DropdownMenuPrimitive.RadioGroup\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-radio-group\"\n\t\tclassName={cx(\"space-y-px\", className)}\n\t\t{...props}\n\t/>\n));\nRadioGroup.displayName = \"DropdownMenuRadioGroup\";\n\n/**\n * A trigger for a dropdown menu sub-menu.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenusubtrigger\n */\nconst SubTrigger = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.SubTrigger>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, children, ...props }, ref) => (\n\t<DropdownMenuPrimitive.SubTrigger\n\t\tdata-slot=\"dropdown-menu-sub-trigger\"\n\t\tclassName={cx(\n\t\t\t\"focus:bg-accent data-state-open:bg-accent relative flex select-none items-center rounded-md py-1.5 pl-2 pr-9 text-sm outline-hidden\",\n\t\t\t\"data-highlighted:bg-active-menu-item data-state-open:bg-active-menu-item\",\n\t\t\t\"[&>svg]:size-5 [&_svg]:shrink-0\",\n\t\t\tinset && \"pl-8\",\n\t\t\tclassName,\n\t\t)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t{children}\n\t\t<span className=\"absolute right-2 flex items-center\">\n\t\t\t<Icon svg={<CaretRightIcon weight=\"bold\" />} className=\"size-4\" />\n\t\t</span>\n\t</DropdownMenuPrimitive.SubTrigger>\n));\nSubTrigger.displayName = \"DropdownMenuSubTrigger\";\n\n/**\n * The content container for a dropdown menu sub-menu.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenusubcontent\n */\nconst SubContent = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.SubContent>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, loop = true, ...props }, ref) => (\n\t<Portal>\n\t\t<DropdownMenuPrimitive.SubContent\n\t\t\tdata-slot=\"dropdown-menu-sub-content\"\n\t\t\tclassName={cx(\n\t\t\t\t\"scrollbar\",\n\t\t\t\t\"text-popover-foreground border-popover bg-popover p-1.25 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 z-50 min-w-32 overflow-hidden rounded-md border shadow-xl space-y-px font-sans\",\n\t\t\t\t\"my-2 max-h-[calc(var(--radix-dropdown-menu-content-available-height)-16px)] overflow-auto\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tloop={loop}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t/>\n\t</Portal>\n));\nSubContent.displayName = \"DropdownMenuSubContent\";\n\ntype DropdownMenuContentProps = ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> & {\n\t/**\n\t * Whether the DropdownMenuContent should match the width of the trigger or use the intrinsic content width.\n\t */\n\twidth?: \"trigger\" | \"content\";\n};\n\n/**\n * The container for the dropdown menu content.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenucontent\n *\n * @example\n * ```tsx\n * <DropdownMenu.Root>\n * <DropdownMenu.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Menu\n * </Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n * <DropdownMenu.Item>Item 2</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu.Root>\n * ```\n */\nconst Content = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.Content>,\n\tDropdownMenuContentProps\n>(({ className, onClick, loop = true, width, ...props }, ref) => (\n\t<Portal>\n\t\t<DropdownMenuPrimitive.Content\n\t\t\tref={ref}\n\t\t\tdata-slot=\"dropdown-menu-content\"\n\t\t\tclassName={cx(\n\t\t\t\t\"scrollbar\",\n\t\t\t\t\"text-popover-foreground border-popover bg-popover p-1.25 z-50 min-w-32 overflow-hidden rounded-md border shadow-xl outline-hidden space-y-px font-sans\",\n\t\t\t\t\"data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95\",\n\t\t\t\t\"my-2 max-h-[calc(var(--radix-dropdown-menu-content-available-height)-16px)] overflow-auto\",\n\t\t\t\twidth === \"trigger\" && \"w-(--radix-dropdown-menu-trigger-width)\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tloop={loop}\n\t\t\tonClick={(event) => {\n\t\t\t\t/**\n\t\t\t\t * Prevent the click event from propagating up to parent/containing elements\n\t\t\t\t * of the DropdownMenu\n\t\t\t\t */\n\t\t\t\tevent.stopPropagation();\n\t\t\t\tonClick?.(event);\n\t\t\t}}\n\t\t\t{...props}\n\t\t/>\n\t</Portal>\n));\nContent.displayName = \"DropdownMenuContent\";\n\n/**\n * An item in the dropdown menu.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuitem\n *\n * @example\n * ```tsx\n * <DropdownMenu.Root>\n * <DropdownMenu.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Menu\n * </Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n * <DropdownMenu.Item>Item 2</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu.Root>\n * ```\n */\nconst Item = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.Item>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Item\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-item\"\n\t\tclassName={cx(\n\t\t\t\"relative flex cursor-pointer select-none items-center rounded-md px-2 py-1.5 text-strong text-sm font-normal outline-hidden transition-colors\",\n\t\t\t\"data-highlighted:bg-active-menu-item\",\n\t\t\t\"focus:bg-accent focus:text-accent-foreground\",\n\t\t\t\"data-disabled:cursor-default data-disabled:opacity-50\",\n\t\t\t\"[&>svg]:size-5 [&_svg]:shrink-0\",\n\t\t\tinset && \"pl-8\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n));\nItem.displayName = \"DropdownMenuItem\";\n\n/**\n * A menu item with a checkbox that can be controlled or uncontrolled.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenucheckboxitem\n */\nconst CheckboxItem = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n\t<DropdownMenuPrimitive.CheckboxItem\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-checkbox-item\"\n\t\tclassName={cx(\n\t\t\t\"text-strong data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center gap-2 rounded-md py-1.5 pl-2 pr-9 text-sm font-normal outline-hidden\",\n\t\t\t\"data-highlighted:bg-active-menu-item\",\n\t\t\t\"aria-checked:bg-selected-menu-item\",\n\t\t\t\"data-highlighted:aria-checked:bg-active-selected-menu-item!\",\n\t\t\t\"[&>svg]:size-5 [&_svg]:shrink-0\",\n\t\t\tclassName,\n\t\t)}\n\t\tchecked={checked}\n\t\t{...props}\n\t>\n\t\t<span className=\"absolute right-2 flex items-center\">\n\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t<Icon svg={<CheckIcon weight=\"bold\" />} className=\"size-4 text-accent-600\" />\n\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t</span>\n\t\t{children}\n\t</DropdownMenuPrimitive.CheckboxItem>\n));\nCheckboxItem.displayName = \"DropdownMenuCheckboxItem\";\n\ntype DropdownMenuRadioItemProps = ComponentPropsWithoutRef<\n\ttypeof DropdownMenuPrimitive.RadioItem\n> & {\n\tname?: string;\n\tid?: string;\n};\n\n/**\n * A menu item with a radio button that can be controlled or uncontrolled.\n * Used within a RadioGroup to create a set of mutually exclusive options.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuradioitem\n */\nconst RadioItem = forwardRef<ComponentRef<\"input\">, DropdownMenuRadioItemProps>(\n\t({ className, children, ...props }, ref) => (\n\t\t<DropdownMenuPrimitive.RadioItem\n\t\t\tdata-slot=\"dropdown-menu-radio-item\"\n\t\t\tclassName={cx(\n\t\t\t\t\"group/dropdown-menu-radio-item\",\n\t\t\t\t\"text-strong data-disabled:pointer-events-none data-disabled:opacity-50 relative flex cursor-pointer select-none items-center gap-2 rounded-md py-1.5 px-2 text-sm font-normal outline-none\",\n\t\t\t\t\"data-highlighted:bg-active-menu-item\",\n\t\t\t\t\"aria-checked:bg-selected-menu-item aria-checked:pr-9\",\n\t\t\t\t\"data-highlighted:aria-checked:bg-active-selected-menu-item!\",\n\t\t\t\t\"[&>svg]:size-5 [&_svg]:shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t<span className=\"absolute right-2 items-center hidden group-aria-checked/dropdown-menu-radio-item:flex\">\n\t\t\t\t<DropdownMenuPrimitive.ItemIndicator>\n\t\t\t\t\t<Icon svg={<CheckIcon weight=\"bold\" />} className=\"size-4 text-accent-600\" />\n\t\t\t\t</DropdownMenuPrimitive.ItemIndicator>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</DropdownMenuPrimitive.RadioItem>\n\t),\n);\nRadioItem.displayName = \"DropdownMenuRadioItem\";\n\n/**\n * A label for a group of dropdown menu items.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenulabel\n */\nconst Label = forwardRef<\n\tComponentRef<typeof DropdownMenuPrimitive.Label>,\n\tComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n\t\tinset?: boolean;\n\t}\n>(({ className, inset, ...props }, ref) => (\n\t<DropdownMenuPrimitive.Label\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-label\"\n\t\tclassName={cx(\"px-2 py-1.5 text-sm font-medium\", inset && \"pl-8\", className)}\n\t\t{...props}\n\t/>\n));\nLabel.displayName = \"DropdownMenuLabel\";\n\n/**\n * A visual separator between dropdown menu items or groups.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuseparator\n */\nconst DropdownSeparator = forwardRef<\n\tComponentRef<typeof Separator>,\n\tComponentPropsWithoutRef<typeof Separator>\n>(({ className, ...props }, ref) => (\n\t<Separator\n\t\tref={ref}\n\t\tdata-slot=\"dropdown-menu-separator\"\n\t\tclassName={cx(\"-mx-1.25 my-1 w-auto\", className)}\n\t\t{...props}\n\t/>\n));\nDropdownSeparator.displayName = \"DropdownMenuSeparator\";\n\nconst Shortcut = ({ className, ...props }: ComponentProps<\"span\">) => {\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"dropdown-menu-shortcut\"\n\t\t\tclassName={cx(\"ml-auto text-xs tracking-widest opacity-60\", className)}\n\t\t\t{...props}\n\t\t/>\n\t);\n};\nShortcut.displayName = \"DropdownMenuShortcut\";\n\n/**\n * A menu of options or actions, triggered by a button.\n *\n * @see https://mantle.ngrok.com/components/dropdown-menu\n *\n * @example\n * Composition:\n * ```\n * DropdownMenu.Root\n * ├── DropdownMenu.Trigger\n * └── DropdownMenu.Content\n * ├── DropdownMenu.Group\n * │ ├── DropdownMenu.Label\n * │ ├── DropdownMenu.Item\n * │ │ └── DropdownMenu.Shortcut\n * │ ├── DropdownMenu.CheckboxItem\n * │ └── DropdownMenu.RadioGroup\n * │ └── DropdownMenu.RadioItem\n * ├── DropdownMenu.Separator\n * └── DropdownMenu.Sub\n * ├── DropdownMenu.SubTrigger\n * └── DropdownMenu.SubContent\n * ```\n *\n * @example\n * ```tsx\n * <DropdownMenu.Root>\n * <DropdownMenu.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Menu\n * </Button>\n * </DropdownMenu.Trigger>\n * <DropdownMenu.Content>\n * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n * <DropdownMenu.Item>Item 2</DropdownMenu.Item>\n * </DropdownMenu.Content>\n * </DropdownMenu.Root>\n * ```\n */\nconst DropdownMenu = {\n\t/**\n\t * The root, stateful component that manages the open/closed state of the dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger asChild>\n\t * <Button>Open Menu</Button>\n\t * </DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * A checkbox item in the dropdown menu that can be toggled on and off.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenucheckboxitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.CheckboxItem checked={true} onCheckedChange={setChecked}>\n\t * Show notifications\n\t * </DropdownMenu.CheckboxItem>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tCheckboxItem,\n\t/**\n\t * The container for the dropdown menu content. Appears in a portal with scrolling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenucontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content width=\"trigger\">\n\t * <DropdownMenu.Item>Edit</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Delete</DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * A group container for organizing related dropdown menu items.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenugroup\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Group>\n\t * <DropdownMenu.Label>Account</DropdownMenu.Label>\n\t * <DropdownMenu.Item>Profile</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Settings</DropdownMenu.Item>\n\t * </DropdownMenu.Group>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tGroup,\n\t/**\n\t * A standard item in the dropdown menu that can be selected or activated.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Item onSelect={() => handleEdit()}>\n\t * Edit\n\t * </DropdownMenu.Item>\n\t * <DropdownMenu.Item disabled>\n\t * Delete\n\t * </DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * A label for grouping and describing sections within the dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenulabel\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Label>My Account</DropdownMenu.Label>\n\t * <DropdownMenu.Item>Profile</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Settings</DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tLabel,\n\t/**\n\t * A radio group container for exclusive selection within the dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuradiogroup\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.RadioGroup value={value} onValueChange={setValue}>\n\t * <DropdownMenu.RadioItem value=\"option1\">Option 1</DropdownMenu.RadioItem>\n\t * <DropdownMenu.RadioItem value=\"option2\">Option 2</DropdownMenu.RadioItem>\n\t * </DropdownMenu.RadioGroup>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tRadioGroup,\n\t/**\n\t * A radio item in the dropdown menu where only one item in the group can be selected.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuradioitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.RadioGroup value=\"small\" onValueChange={setSize}>\n\t * <DropdownMenu.RadioItem value=\"small\">Small</DropdownMenu.RadioItem>\n\t * <DropdownMenu.RadioItem value=\"medium\">Medium</DropdownMenu.RadioItem>\n\t * <DropdownMenu.RadioItem value=\"large\">Large</DropdownMenu.RadioItem>\n\t * </DropdownMenu.RadioGroup>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tRadioItem,\n\t/**\n\t * A visual separator for dividing sections within the dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenuseparator\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Item>Edit</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Copy</DropdownMenu.Item>\n\t * <DropdownMenu.Separator />\n\t * <DropdownMenu.Item>Delete</DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tSeparator: DropdownSeparator,\n\t/**\n\t * A keyboard shortcut indicator for dropdown menu items.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenushortcut\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Item>\n\t * Save\n\t * <DropdownMenu.Shortcut>⌘S</DropdownMenu.Shortcut>\n\t * </DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tShortcut,\n\t/**\n\t * A submenu container for creating nested dropdown menus.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenusub\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Sub>\n\t * <DropdownMenu.SubTrigger>More options</DropdownMenu.SubTrigger>\n\t * <DropdownMenu.SubContent>\n\t * <DropdownMenu.Item>Sub item 1</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Sub item 2</DropdownMenu.Item>\n\t * </DropdownMenu.SubContent>\n\t * </DropdownMenu.Sub>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tSub,\n\t/**\n\t * The content container for submenu items.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenusubcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Sub>\n\t * <DropdownMenu.SubTrigger>Export</DropdownMenu.SubTrigger>\n\t * <DropdownMenu.SubContent>\n\t * <DropdownMenu.Item>Export as PDF</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Export as CSV</DropdownMenu.Item>\n\t * </DropdownMenu.SubContent>\n\t * </DropdownMenu.Sub>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tSubContent,\n\t/**\n\t * The trigger item that opens a submenu when hovered or focused.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenusubtrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger>Open</DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Sub>\n\t * <DropdownMenu.SubTrigger>Share</DropdownMenu.SubTrigger>\n\t * <DropdownMenu.SubContent>\n\t * <DropdownMenu.Item>Email</DropdownMenu.Item>\n\t * <DropdownMenu.Item>Copy link</DropdownMenu.Item>\n\t * </DropdownMenu.SubContent>\n\t * </DropdownMenu.Sub>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tSubTrigger,\n\t/**\n\t * The trigger button that opens the dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/dropdown-menu#dropdownmenutrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <DropdownMenu.Root>\n\t * <DropdownMenu.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">\n\t * Open Menu\n\t * </Button>\n\t * </DropdownMenu.Trigger>\n\t * <DropdownMenu.Content>\n\t * <DropdownMenu.Item>Item 1</DropdownMenu.Item>\n\t * </DropdownMenu.Content>\n\t * </DropdownMenu.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tDropdownMenu,\n};\n"],"mappings":"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"}
|
package/dist/empty.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"empty.js","names":[],"sources":["../src/components/empty/empty.tsx"],"sourcesContent":["import type { ComponentProps, HTMLAttributes, ReactNode } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { SvgOnly } from \"../icon/svg-only.js\";\nimport type { SvgAttributes } from \"../icon/types.js\";\nimport { Slot } from \"../slot/index.js\";\n\n/**\n * The root container for an empty state. Centers content horizontally\n * with consistent vertical padding and max-width.\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No results found</Empty.Title>\n * <Empty.Description>Try adjusting your search or filters.</Empty.Description>\n * <Empty.Actions>\n * <Button>Clear filters</Button>\n * </Empty.Actions>\n * </Empty.Root>\n * ```\n */\nconst Root = ({ asChild, children, className, ...props }: ComponentProps<\"div\"> & WithAsChild) => {\n\tconst Comp = asChild ? Slot : \"div\";\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"empty\"\n\t\t\tclassName={cx(\"mx-auto flex max-w-lg flex-col items-center p-6 text-center\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n};\nRoot.displayName = \"Empty\";\n\ntype EmptyIconProps = Omit<SvgAttributes, \"children\"> & {\n\t/**\n\t * A single SVG icon element.\n\t */\n\tsvg: ReactNode;\n};\n\n/**\n * Renders a large icon for the empty state. Pass a single SVG icon element\n * via the `svg` prop (e.g. from `@phosphor-icons/react`).\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No endpoints yet</Empty.Title>\n * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n * <Empty.Actions>\n * <Button>Create endpoint</Button>\n * </Empty.Actions>\n * </Empty.Root>\n * ```\n */\nconst Icon = ({ className, svg, ...props }: EmptyIconProps) => {\n\treturn (\n\t\t<SvgOnly\n\t\t\tdata-slot=\"empty-icon\"\n\t\t\tclassName={cx(\"mb-1 size-10 text-neutral-400\", className)}\n\t\t\tsvg={svg}\n\t\t\t{...props}\n\t\t/>\n\t);\n};\nIcon.displayName = \"EmptyIcon\";\n\n/**\n * The heading text for the empty state. Renders as an `h3` by default. Use the\n * `asChild` prop to render as a different heading level (e.g. `h1`, `h2`).\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No endpoints yet</Empty.Title>\n * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n * <Empty.Actions>\n * <Button>Create endpoint</Button>\n * </Empty.Actions>\n * </Empty.Root>\n *\n * <Empty.Title asChild>\n * <h2>No results found</h2>\n * </Empty.Title>\n * ```\n */\nconst Title = ({\n\tasChild,\n\tchildren,\n\tclassName,\n\t...props\n}: HTMLAttributes<HTMLHeadingElement> & WithAsChild) => {\n\tconst Comp = asChild ? Slot : \"h3\";\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"empty-title\"\n\t\t\tclassName={cx(\"text-strong text-sm font-medium font-sans\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n};\nTitle.displayName = \"EmptyTitle\";\n\n/**\n * Supporting descriptive text below the title. Renders as a `div` with\n * `space-y-4` so multiple paragraphs can be placed inside. Use the `asChild`\n * prop to render as a different element.\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No endpoints yet</Empty.Title>\n * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n * <Empty.Actions>\n * <Button>Create endpoint</Button>\n * </Empty.Actions>\n * </Empty.Root>\n *\n * <Empty.Description>\n * <p>Something went wrong.</p>\n * <p>Please try again in a few minutes.</p>\n * </Empty.Description>\n * ```\n */\nconst Description = ({\n\tasChild,\n\tchildren,\n\tclassName,\n\t...props\n}: ComponentProps<\"div\"> & WithAsChild) => {\n\tconst Comp = asChild ? Slot : \"div\";\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"empty-description\"\n\t\t\tclassName={cx(\"text-muted space-y-4 text-sm font-sans\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n};\nDescription.displayName = \"EmptyDescription\";\n\n/**\n * A container for action buttons or links in the empty state.\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No endpoints yet</Empty.Title>\n * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n * <Empty.Actions>\n * <Button>Create endpoint</Button>\n * <Button appearance=\"outlined\">Go back</Button>\n * </Empty.Actions>\n * </Empty.Root>\n * ```\n */\nconst Actions = ({\n\tasChild,\n\tchildren,\n\tclassName,\n\t...props\n}: ComponentProps<\"div\"> & WithAsChild) => {\n\tconst Comp = asChild ? Slot : \"div\";\n\n\treturn (\n\t\t<Comp\n\t\t\tdata-slot=\"empty-actions\"\n\t\t\tclassName={cx(\"mt-4 flex items-center gap-2\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n};\nActions.displayName = \"EmptyActions\";\n\n/**\n * Compound component for rendering empty states. Use with `Empty.Root`,\n * `Empty.Icon`, `Empty.Title`, `Empty.Description`, and `Empty.Actions`.\n *\n * @see https://mantle.ngrok.com/components/empty\n *\n * @example\n * Composition:\n * ```\n * Empty.Root\n * ├── Empty.Icon\n * ├── Empty.Title\n * ├── Empty.Description\n * └── Empty.Actions\n * ```\n *\n * @example\n * ```tsx\n * <Empty.Root>\n * <Empty.Icon svg={<GhostIcon />} />\n * <Empty.Title>No endpoints yet</Empty.Title>\n * <Empty.Description>\n * Create your first endpoint to get started.\n * </Empty.Description>\n * <Empty.Actions>\n * <Button>Create endpoint</Button>\n * </Empty.Actions>\n * </Empty.Root>\n * ```\n */\nconst Empty = {\n\t/**\n\t * The root container for an empty state. Centers content vertically and\n\t * horizontally with consistent padding and max-width.\n\t *\n\t * @see https://mantle.ngrok.com/components/empty\n\t *\n\t * @example\n\t * ```tsx\n\t * <Empty.Root>\n\t * <Empty.Icon svg={<GhostIcon />} />\n\t * <Empty.Title>No endpoints yet</Empty.Title>\n\t * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n\t * <Empty.Actions>\n\t * <Button>Create endpoint</Button>\n\t * </Empty.Actions>\n\t * </Empty.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * Renders a large icon for the empty state. Pass a single SVG icon element\n\t * via the `svg` prop.\n\t *\n\t * @see https://mantle.ngrok.com/components/empty\n\t *\n\t * @example\n\t * ```tsx\n\t * <Empty.Root>\n\t * <Empty.Icon svg={<GhostIcon />} />\n\t * <Empty.Title>No endpoints yet</Empty.Title>\n\t * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n\t * <Empty.Actions>\n\t * <Button>Create endpoint</Button>\n\t * </Empty.Actions>\n\t * </Empty.Root>\n\t * ```\n\t */\n\tIcon,\n\t/**\n\t * The heading text for the empty state. Renders as an `h3` by default.\n\t * Use `asChild` to render as a different heading level.\n\t *\n\t * @see https://mantle.ngrok.com/components/empty\n\t *\n\t * @example\n\t * ```tsx\n\t * <Empty.Root>\n\t * <Empty.Icon svg={<GhostIcon />} />\n\t * <Empty.Title>No endpoints yet</Empty.Title>\n\t * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n\t * <Empty.Actions>\n\t * <Button>Create endpoint</Button>\n\t * </Empty.Actions>\n\t * </Empty.Root>\n\t *\n\t * <Empty.Title asChild>\n\t * <h2>No results found</h2>\n\t * </Empty.Title>\n\t * ```\n\t */\n\tTitle,\n\t/**\n\t * Supporting descriptive text below the title. Renders as a `div` with\n\t * `space-y-4` for multiple paragraphs. Use `asChild` to render as a\n\t * different element.\n\t *\n\t * @see https://mantle.ngrok.com/components/empty\n\t *\n\t * @example\n\t * ```tsx\n\t * <Empty.Root>\n\t * <Empty.Icon svg={<GhostIcon />} />\n\t * <Empty.Title>No endpoints yet</Empty.Title>\n\t * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n\t * <Empty.Actions>\n\t * <Button>Create endpoint</Button>\n\t * </Empty.Actions>\n\t * </Empty.Root>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * A container for action buttons or links in the empty state.\n\t *\n\t * @see https://mantle.ngrok.com/components/empty\n\t *\n\t * @example\n\t * ```tsx\n\t * <Empty.Root>\n\t * <Empty.Icon svg={<GhostIcon />} />\n\t * <Empty.Title>No endpoints yet</Empty.Title>\n\t * <Empty.Description>Create your first endpoint to get started.</Empty.Description>\n\t * <Empty.Actions>\n\t * <Button>Create endpoint</Button>\n\t * </Empty.Actions>\n\t * </Empty.Root>\n\t * ```\n\t */\n\tActions,\n} as const;\n\nexport {\n\t//,\n\tEmpty,\n};\n"],"mappings":"0JAyBA,MAAM,GAAQ,CAAE,UAAS,WAAU,YAAW,GAAG,KAI/C,EAHY,EAAU,EAAO,MAG7B,CACC,YAAU,QACV,UAAW,EAAG,8DAA+D,CAAS,EACtF,GAAI,EAEH,UACI,CAAA,EAGR,EAAK,YAAc,QA2BnB,MAAM,GAAQ,CAAE,YAAW,MAAK,GAAG,KAEjC,EAAC,EAAD,CACC,YAAU,aACV,UAAW,EAAG,gCAAiC,CAAS,EACnD,MACL,GAAI,CACJ,CAAA,EAGH,EAAK,YAAc,YAwBnB,MAAM,GAAS,CACd,UACA,WACA,YACA,GAAG,KAKF,EAHY,EAAU,EAAO,KAG7B,CACC,YAAU,cACV,UAAW,EAAG,4CAA6C,CAAS,EACpE,GAAI,EAEH,UACI,CAAA,EAGR,EAAM,YAAc,aA0BpB,MAAM,GAAe,CACpB,UACA,WACA,YACA,GAAG,KAKF,EAHY,EAAU,EAAO,MAG7B,CACC,YAAU,oBACV,UAAW,EAAG,yCAA0C,CAAS,EACjE,GAAI,EAEH,UACI,CAAA,EAGR,EAAY,YAAc,mBAoB1B,MAAM,GAAW,CAChB,UACA,WACA,YACA,GAAG,KAKF,EAHY,EAAU,EAAO,MAG7B,CACC,YAAU,gBACV,UAAW,EAAG,+BAAgC,CAAS,EACvD,GAAI,EAEH,UACI,CAAA,EAGR,EAAQ,YAAc,eAgCtB,MAAM,EAAQ,CAmBb,OAmBA,OAuBA,QAoBA,cAkBA,SACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"field-context-4k1kI7Bo.js","names":[],"sources":["../src/components/field/field-context.ts"],"sourcesContent":["import { createContext, type ComponentProps } from \"react\";\nimport { parseValidation, type ValidationState } from \"./validation.js\";\n\n/**\n * ARIA and identity props that `Field.Control` applies to the field's\n * focusable control. `id` and `name` come from the surrounding `Field.Item`\n * so a caller only needs to declare `name` once.\n */\ntype FieldControlAriaProps = {\n\t/**\n\t * IDREFs for helper or error text that describe the focusable control.\n\t */\n\t\"aria-describedby\"?: string;\n\t/**\n\t * IDREFs for error text that represent the control's current error state.\n\t */\n\t\"aria-errormessage\"?: string;\n\t/**\n\t * The resolved ARIA invalid state for the focusable control.\n\t */\n\t\"aria-invalid\"?: ComponentProps<\"input\">[\"aria-invalid\"];\n\t/**\n\t * Stable DOM id for the focusable control, generated by `Field.Item` and\n\t * also used as `Field.Label`'s default `htmlFor`.\n\t */\n\tid?: string;\n\t/**\n\t * Form value identity from `Field.Item`'s required `name` prop.\n\t */\n\tname?: string;\n};\n\n/**\n * Context value owned by `Field.Item` and consumed by message/control parts.\n *\n * `Field.Item` owns the two stable slot IDs (one for the description, one for\n * the error list) so consumers don't manage ARIA wiring themselves. The IDs\n * are emitted unconditionally; ARIA treats unresolved IDREFs as no-ops, so\n * dangling IDs (when no description or error list is rendered) are harmless.\n */\ntype FieldItemContextValue = {\n\t/**\n\t * Stable DOM id applied to the `Field.Control` child and consumed by\n\t * `Field.Label` as the default `htmlFor` target.\n\t */\n\tcontrolId: string;\n\t/**\n\t * Stable ID for the rendered `Field.Description` slot, generated once per\n\t * `Field.Item`.\n\t */\n\tdescriptionId: string;\n\t/**\n\t * Stable ID for the rendered `Field.Errors` / `Field.ErrorList` slot,\n\t * generated once per `Field.Item`.\n\t */\n\terrorId: string;\n\t/**\n\t * Form-value name for the field, supplied by the required `name` prop on\n\t * `Field.Item` and splatted onto the `Field.Control` child.\n\t */\n\tname: string;\n\t/**\n\t * `true` while a non-empty `Field.Errors` / `Field.ErrorList` is mounted\n\t * under this `Field.Item`. Used by `Field.Item` to infer an `\"error\"`\n\t * validation state when no explicit `validation` prop is supplied.\n\t */\n\thasErrors: boolean;\n\t/**\n\t * Marks a non-empty `Field.Errors` / `Field.ErrorList` as mounted. Returns\n\t * its cleanup callback.\n\t */\n\tregisterError: () => () => void;\n\t/**\n\t * Validation state inferred or supplied by the surrounding `Field.Item`.\n\t */\n\tvalidation?: ValidationState;\n};\n\n/**\n * Options for resolving the ARIA props that `Field.Control` applies.\n */\ntype ResolveFieldControlAriaPropsOptions = {\n\t/**\n\t * The nearest `Field.Item` context, when the control is rendered inside one.\n\t */\n\tcontext: FieldItemContextValue | null;\n};\n\n/**\n * Context shared by the parts of a single `Field.Item`.\n */\nconst FieldItemContext = createContext<FieldItemContextValue | null>(null);\n\n/**\n * Context published by `Field.Control` carrying the resolved ARIA / identity\n * props that should land on the focusable control. Mantle compound triggers\n * (`Select.Trigger`, `MultiSelect.Trigger`, …) consume this so wrapping a\n * compound widget in `Field.Control` works — `cloneElement` only reaches the\n * direct child, which for a compound widget is a context provider that does\n * not forward ARIA props to its inner trigger.\n *\n * `null` when no `Field.Control` is in the tree.\n */\nconst FieldControlContext = createContext<FieldControlAriaProps | null>(null);\n\n/**\n * Resolves the ARIA, identity, and validation props that `Field.Control`\n * applies to its focusable child. `Field.Item` is the single source of truth\n * for `id`, `name`, `aria-*`, and `validation` — the resolver reads only the\n * surrounding `Field.Item` context and ignores anything supplied on the child\n * element. To override these values, set them on `Field.Item` itself.\n */\nconst resolveFieldControlAriaProps = ({ context }: ResolveFieldControlAriaPropsOptions) => {\n\tif (!context) {\n\t\treturn {\n\t\t\tariaProps: {} as const satisfies FieldControlAriaProps,\n\t\t\tvalidation: undefined,\n\t\t};\n\t}\n\n\tconst parsedValidation = parseValidation({\n\t\tdefaultAriaInvalid: false,\n\t\tvalidation: context.validation,\n\t});\n\t// Always emit both slot IDs in aria-describedby when inside a Field.Item.\n\t// Per WAI-ARIA, unresolved IDREFs are ignored by assistive tech, so the\n\t// dangling ID is harmless when the corresponding slot isn't rendered and\n\t// lets us skip mount-time bookkeeping. aria-errormessage is additionally\n\t// spec-gated on aria-invalid=\"true\", so it stays inert until the field is\n\t// actually invalid.\n\tconst ariaDescribedBy = `${context.descriptionId} ${context.errorId}`;\n\tconst ariaErrorMessage = parsedValidation.isInvalid ? context.errorId : undefined;\n\n\treturn {\n\t\tariaProps: {\n\t\t\t\"aria-describedby\": ariaDescribedBy,\n\t\t\t\"aria-errormessage\": ariaErrorMessage,\n\t\t\t\"aria-invalid\": parsedValidation.ariaInvalid,\n\t\t\tid: context.controlId,\n\t\t\tname: context.name,\n\t\t} satisfies FieldControlAriaProps,\n\t\tvalidation: parsedValidation.validation,\n\t};\n};\n\nexport {\n\t//,\n\tFieldControlContext,\n\tFieldItemContext,\n\tresolveFieldControlAriaProps,\n};\nexport type {\n\t//,\n\tFieldControlAriaProps,\n\tFieldItemContextValue,\n};\n"],"mappings":"mFA2FA,MAAM,EAAmB,EAA4C,IAAI,EAYnE,EAAsB,EAA4C,IAAI,EAStE,GAAgC,CAAE,aAAmD,CAC1F,GAAI,CAAC,EACJ,MAAO,CACN,UAAW,CAAC,EACZ,WAAY,IAAA,EACb,EAGD,IAAM,EAAmB,EAAgB,CACxC,mBAAoB,GACpB,WAAY,EAAQ,UACrB,CAAC,EAUD,MAAO,CACN,UAAW,CACV,mBAAoB,GALK,EAAQ,cAAc,GAAG,EAAQ,UAM1D,oBALuB,EAAiB,UAAY,EAAQ,QAAU,IAAA,GAMtE,eAAgB,EAAiB,YACjC,GAAI,EAAQ,UACZ,KAAM,EAAQ,IACf,EACA,WAAY,EAAiB,UAC9B,CACD"}
|
package/dist/field.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","names":[],"sources":["../src/components/field/error-helpers.ts","../src/components/field/field.tsx","../src/components/field/field-error-messages.ts"],"sourcesContent":["import { Children, Fragment, isValidElement, type ReactNode } from \"react\";\n\n/**\n * A validation message accepted by `Field.Errors`. Non-string absence values\n * are allowed so consumers can pass mapped validator output directly while\n * still rendering only real strings.\n */\ntype FieldErrorMessage = string | null | undefined | false;\n\ntype RenderableContentProps = { children?: ReactNode };\n\n/**\n * Options for checking a manual `Field.ErrorList` subtree.\n */\ntype HasRenderableErrorListChildrenOptions = {\n\t/**\n\t * The list children to inspect before rendering or wiring ARIA IDs.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * The local `Field.ErrorItem` component type from `field.tsx`. Passed in\n\t * (rather than imported) to avoid a circular dependency between\n\t * `field.tsx` and this helpers module.\n\t */\n\terrorItemType: unknown;\n};\n\n/**\n * Normalizes validator output into display-ready message strings without\n * coupling `Field.Errors` to a specific form library's error object shape.\n */\nconst normalizeErrorMessages = (messages: readonly FieldErrorMessage[] | undefined) => {\n\tconst normalizedMessages: string[] = [];\n\tconst seenMessages = new Set<string>();\n\n\tfor (const message of messages ?? []) {\n\t\tif (typeof message !== \"string\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalizedMessage = message.trim();\n\t\tif (normalizedMessage.length === 0 || seenMessages.has(normalizedMessage)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tseenMessages.add(normalizedMessage);\n\t\tnormalizedMessages.push(normalizedMessage);\n\t}\n\n\treturn normalizedMessages;\n};\n\n/**\n * Returns `true` when the supplied children would produce visible content in\n * a `Field.ErrorItem` — i.e. they are not `null`, `undefined`, `false`, or a\n * whitespace-only string. Used by both `Field.ErrorItem`'s render guard and\n * the `Field.ErrorList` walker so an empty item is identified consistently.\n */\nconst isErrorItemRenderable = (children: ReactNode): boolean => {\n\t// Booleans (including `true`) render nothing in React, so a `cond && expr`\n\t// pattern that resolves to `true` would otherwise count as renderable here.\n\tif (children == null || typeof children === \"boolean\") {\n\t\treturn false;\n\t}\n\tif (typeof children === \"string\" && children.trim().length === 0) {\n\t\treturn false;\n\t}\n\treturn true;\n};\n\n/**\n * Empty-detection walker for `Field.ErrorList`. Recurses through Fragments so\n * error items wrapped in conditional `<>…</>` still register, applies\n * `Field.ErrorItem`'s render guard so empty items do not count as content,\n * and treats any other child (custom component, host element, etc.) as\n * opaque-and-therefore-renderable.\n */\nconst hasRenderableErrorListChildren = ({\n\tchildren,\n\terrorItemType,\n}: HasRenderableErrorListChildrenOptions): boolean => {\n\tlet found = false;\n\n\tChildren.forEach(children, (child) => {\n\t\tif (found || child == null || typeof child === \"boolean\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof child === \"string\") {\n\t\t\tif (child.trim().length > 0) {\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!isValidElement<RenderableContentProps>(child)) {\n\t\t\tfound = true;\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === errorItemType) {\n\t\t\tfound = isErrorItemRenderable(child.props.children);\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === Fragment) {\n\t\t\tfound = hasRenderableErrorListChildren({\n\t\t\t\tchildren: child.props.children,\n\t\t\t\terrorItemType,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tfound = true;\n\t});\n\n\treturn found;\n};\n\nexport {\n\t//,\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n};\nexport type {\n\t//,\n\tFieldErrorMessage,\n};\n","import { QuestionIcon } from \"@phosphor-icons/react/Question\";\nimport {\n\tcloneElement,\n\ttype ComponentRef,\n\ttype ComponentProps,\n\tforwardRef,\n\tisValidElement,\n\ttype ReactElement,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseId,\n\tuseMemo,\n\tuseState,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/use-isomorphic-layout-effect.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { IconButton, type IconButtonProps } from \"../button/icon-button.js\";\nimport { Label } from \"../label/label.js\";\nimport { Popover } from \"../popover/index.js\";\nimport { Slot } from \"../slot/index.js\";\nimport {\n\tFieldControlContext,\n\tFieldItemContext,\n\tresolveFieldControlAriaProps,\n\ttype FieldControlAriaProps,\n} from \"./field-context.js\";\nimport {\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n\ttype FieldErrorMessage,\n} from \"./error-helpers.js\";\nimport { FieldValidationProvider, resolveValidation, type WithValidation } from \"./validation.js\";\n\n/**\n * Renders a semantic `<fieldset>` for grouping related controls under a\n * single accessible name. Resets the default browser fieldset chrome\n * (border, padding, `min-width` quirk) so it composes cleanly with\n * `Field.Legend` and `Field.Group`. Always renders a real `<fieldset>` so\n * the grouping semantics cannot be accidentally removed.\n *\n * Reach for `Field.Set` when the grouping carries semantic weight — most\n * commonly a `RadioGroup` (where the legend names the question the radios\n * answer) or a set of related checkboxes. For laying out unrelated fields\n * with consistent spacing, prefer `Field.Group` on its own.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst FieldSet = forwardRef<ComponentRef<\"fieldset\">, ComponentProps<\"fieldset\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<fieldset\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-set\"\n\t\t\t\tclassName={cx(\"flex w-full min-w-0 flex-col gap-4 border-0 p-0\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nFieldSet.displayName = \"FieldSet\";\n\n/**\n * The caption for a `Field.Set`. Always renders a semantic `<legend>` styled\n * to match the `Label` component so a fieldset reads like a section header,\n * and gives screen readers an accessible name for the surrounding group\n * (e.g. \"Notification frequency, group, Daily\").\n *\n * **Spacing.** Has a default `mb-1.5` so the legend sits 6px above the next\n * sibling — matching the figma. We use a margin (not the parent `Field.Set`'s\n * flex `gap`) because `<legend>` has special browser rendering inside a\n * `<fieldset>` that ignores the parent's flex `gap`. Override the default\n * with any `mb-*` utility on `Field.Legend`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst Legend = forwardRef<ComponentRef<\"legend\">, ComponentProps<\"legend\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<legend\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-legend\"\n\t\t\t\t// `mb-1.5` (not the parent's `gap-*`) drives the Legend ↔ next-sibling\n\t\t\t\t// spacing because `<legend>` has special browser rendering inside a\n\t\t\t\t// `<fieldset>` that ignores the parent's flex `gap`. Pairs with\n\t\t\t\t// RadioGroup.Item's own `py-1` for a 10px text-bottom-to-radio rhythm\n\t\t\t\t// matching the figma. Override with any `mb-*` utility on Field.Legend.\n\t\t\t\tclassName={cx(\"text-strong mb-1.5 text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLegend.displayName = \"FieldLegend\";\n\n/**\n * Caption for a `Field.Item`. Renders the Mantle `Label` with the same\n * `htmlFor`, click-to-focus, disabled, and typography behavior — but inside a\n * `Field.Item`, the label-to-control association is automatic: `Field.Item`\n * generates a stable control id, `Field.Control` splats that id onto its\n * focusable child, and `Field.Label` consumes the same id as the default\n * `htmlFor`. The required `name` on `Field.Item` is the single source of truth\n * for the control's form name — no matching `htmlFor` / `id` pair, no separate\n * `useId()` call.\n *\n * Pass an explicit `htmlFor` to opt out — for example when the focusable\n * element is rendered outside of `Field.Control` and the auto-generated id\n * never lands on it.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * // htmlFor is wired automatically from Field.Item's name.\n * <Field.Item name=\"apiKey\">\n * <Field.Label>API key</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * </Field.Item>\n *\n * // Opt out with an explicit htmlFor when needed.\n * <Field.Item name=\"legacy\">\n * <Field.Label htmlFor=\"legacy-control\">Legacy field</Field.Label>\n * <input id=\"legacy-control\" />\n * </Field.Item>\n * ```\n */\nconst FieldLabel = forwardRef<ComponentRef<\"label\">, ComponentProps<typeof Label>>(\n\t({ htmlFor, ...props }, ref) => {\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn <Label ref={ref} htmlFor={htmlFor ?? context?.controlId} {...props} />;\n\t},\n);\nFieldLabel.displayName = \"FieldLabel\";\n\n/**\n * Static, label-styled text for a `Field.Item` row that does **not** caption a\n * focusable form control. Renders a `<p>` (not a `<label>`) with the same\n * typography as `Field.Label`, so a read-only row inside a sheet or details\n * panel composes cleanly next to real form fields without misrepresenting\n * itself as a control caption.\n *\n * **When to use**\n * - A `Field.Item` row that displays a derived or system-managed value\n * (owner, created-at, computed status) where there is no `<input>`,\n * `<select>`, `<button>`, or other focusable target to label.\n * - Read-only summary rows inside a sheet or detail panel that should\n * visually align with sibling `Field.Item`s but have no editable control.\n * - Anywhere you would otherwise hand-roll a `<p>` styled to mimic\n * `Field.Label` typography — prefer this so intent is explicit at the call site.\n *\n * **When not to use**\n * - The row has a focusable control (input, select, checkbox, switch,\n * button trigger). Use `Field.Label` so the click-to-focus and\n * accessible-name association are wired correctly.\n * - For body copy, section headings, or any text whose typography happens\n * to look similar by accident — use the appropriate heading or `<p>`\n * directly. `Field.LabelText` exists specifically to slot into the\n * `Field.Label` position of a `Field.Item`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Item name=\"owner\">\n * <Field.LabelText>Owner</Field.LabelText>\n * <CredentialOwnerCard owner={owner} />\n * <Field.Description>The user or service user that owns this API key.</Field.Description>\n * </Field.Item>\n * ```\n */\nconst LabelText = forwardRef<ComponentRef<\"p\">, ComponentProps<\"p\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-text\"\n\t\t\t\tclassName={cx(\"text-strong text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelText.displayName = \"FieldLabelText\";\n\n/**\n * Horizontal layout container for the label area of a field. Aligns a\n * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n * like a help-icon `Popover.Trigger` on a shared center line with a tight\n * `gap-1`. Center-alignment is used (not baseline) so SVG icon buttons —\n * which have no text baseline — sit visually centered next to the label\n * text rather than dropping to the box bottom.\n *\n * Use this when the label needs sibling decorations that can't live inside\n * the `<Field.Label>` itself (e.g. an interactive help button — clicking inside a\n * `<label>` would forward focus to the associated control). For a label\n * with only an `(Optional)` suffix, place `Field.Optional` directly inside\n * the `<Field.Label>` instead — no `LabelRow` needed.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst LabelRow = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-row\"\n\t\t\t\tclassName={cx(\"flex items-center gap-1\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelRow.displayName = \"FieldLabelRow\";\n\n/**\n * `Popover.Root` re-export for the help-affordance pattern. Pair with\n * `Field.HelpTrigger` (renders a default question-mark `IconButton`) and\n * `Field.HelpContent` (the popover body) to drop a help button into a\n * `Field.LabelRow` without manually wiring `Popover` + `IconButton` +\n * `QuestionIcon`. All `Popover.Root` props are forwarded — pass `modal`,\n * `defaultOpen`, etc. as needed.\n *\n * Popover (not Tooltip) so the affordance is reachable on touch devices.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Help = Popover.Root;\n\nconst defaultHelpTriggerIcon = <QuestionIcon />;\n\n/**\n * Props for the default help popover trigger. A contextual label is required\n * so repeated help affordances do not all share the same accessible name.\n */\ntype FieldHelpTriggerProps = Partial<Omit<IconButtonProps, \"icon\" | \"label\">> &\n\tPick<IconButtonProps, \"label\"> & {\n\t\t/**\n\t\t * The icon to render inside the trigger button. Defaults to a Phosphor\n\t\t * `QuestionIcon` so the most common case only needs a contextual label.\n\t\t */\n\t\ticon?: ReactNode;\n\t};\n\n/**\n * The trigger for a `Field.Help` popover — a `Popover.Trigger` wired to a\n * ghost-appearance `IconButton` with a default Phosphor `QuestionIcon`.\n * Requires a contextual screen-reader label, and accepts `icon` or other\n * `IconButton` props for visual customization.\n *\n * Pre-styled with `text-body` (matching the figma) so the icon reads as\n * subtle metadata at rest; `IconButton`'s ghost `hover:text-strong` still\n * brightens it on interaction. Carries a default `-my-0.5` so the 24px\n * `xs` button keeps a full click target while contributing only 20px to\n * the `Field.LabelRow` flex line — matching the label's text line-height\n * so the label text is not pushed off-center.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpTrigger = forwardRef<ComponentRef<\"button\">, FieldHelpTriggerProps>(\n\t(\n\t\t{\n\t\t\tappearance = \"ghost\",\n\t\t\tclassName,\n\t\t\ticon = defaultHelpTriggerIcon,\n\t\t\tlabel,\n\t\t\tsize = \"xs\",\n\t\t\ttype = \"button\",\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Popover.Trigger asChild>\n\t\t\t<IconButton\n\t\t\t\tref={ref}\n\t\t\t\tappearance={appearance}\n\t\t\t\t// `-my-0.5` keeps the 24px (`size-6`) `xs` IconButton click target while\n\t\t\t\t// trimming 4px (2px each side) off its flex-line contribution so the row\n\t\t\t\t// height matches the label's 20px line-height. Without this the trigger\n\t\t\t\t// drives the LabelRow to 24px and pushes the label text down 2px.\n\t\t\t\tclassName={cx(\"text-body -my-0.5\", className)}\n\t\t\t\ticon={icon}\n\t\t\t\tlabel={label}\n\t\t\t\tsize={size}\n\t\t\t\ttype={type}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</Popover.Trigger>\n\t),\n);\nHelpTrigger.displayName = \"FieldHelpTrigger\";\n\n/**\n * The popover body for a `Field.Help`. Wraps `Popover.Content` so all\n * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n * work as expected, and overrides the inherited `data-slot` to\n * `field-help-content` so consumers can target it as part of a `Field`\n * subtree without colliding with other popovers.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpContent = forwardRef<ComponentRef<\"div\">, ComponentProps<typeof Popover.Content>>(\n\t(props, ref) => <Popover.Content ref={ref} data-slot=\"field-help-content\" {...props} />,\n);\nHelpContent.displayName = \"FieldHelpContent\";\n\n/**\n * Inline \"(Optional)\" suffix to mark a field as optional. Defaults to the\n * literal string `(Optional)` so the common case is `<Field.Optional />` with\n * no children — pass children to translate or replace the text. Renders a\n * `<span>` in `text-muted` at `text-sm` / `font-normal` so it reads as\n * secondary metadata next to the bolder Label text.\n *\n * Place inside the `<Field.Label>` so screen readers announce it as part of the\n * accessible name (e.g. \"Email, Optional, edit text\"). Pair with a small\n * `gap` on the label's flex layout, or rely on the natural inline spacing.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Optional = forwardRef<ComponentRef<\"span\">, ComponentProps<\"span\"> & WithAsChild>(\n\t({ asChild, children, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"span\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-optional\"\n\t\t\t\tclassName={cx(\"text-muted text-sm font-normal font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children ?? \"(Optional)\"}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nOptional.displayName = \"FieldOptional\";\n\n/**\n * Layout container that stacks multiple `Field.Item`s vertically with\n * `gap-4` between them. This is the default way to compose multiple fields\n * — most forms only need a `Field.Group` of `Field.Item`s. Reach for\n * `Field.Set` + `Field.Legend` only when the grouping carries semantic\n * weight (e.g. a `RadioGroup` or related checkboxes).\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Group = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-group\"\n\t\t\t\tclassName={cx(\"flex w-full flex-col gap-4\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nGroup.displayName = \"FieldGroup\";\n\n/**\n * A single form field — `Label`, a control (`Input`, `Select`, `Checkbox`,\n * etc.), and any `Field.Description`, `Field.Errors`, or `Field.ErrorList` siblings stacked\n * vertically with a consistent `gap-1.5` so help and error messaging sit\n * tightly under the input.\n *\n * Renders a plain `<div>` — the `<label htmlFor>` ↔ control association\n * already provides the right semantics for a single field, so no implicit\n * `role` is added. `Field.Item` owns the contextual description/error IDs\n * that `Field.Control` applies to the focusable control. Rendered errors\n * infer an `\"error\"` validation state unless `validation` is supplied as an\n * explicit override.\n *\n * **Single-slot constraint.** A `Field.Item` owns one description ID and one\n * errors ID, so render at most one `Field.Description` and one\n * `Field.Errors` *or* `Field.ErrorList` (not both) per item. A second instance\n * would duplicate the slot `id` in the DOM. Pass multiple messages to\n * `Field.Errors`, or multiple `Field.ErrorItem` children to `Field.ErrorList`,\n * instead.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\ntype FieldItemProps = ComponentProps<\"div\"> &\n\tWithAsChild &\n\tWithValidation & {\n\t\t/**\n\t\t * Form-value name for the field. Required so `Field.Control` can splat\n\t\t * it onto the focusable child while `Field.Item` owns the stable\n\t\t * generated control id used by `Field.Label`'s `htmlFor`.\n\t\t */\n\t\tname: string;\n\t};\n\nconst Item = forwardRef<ComponentRef<\"div\">, FieldItemProps>(\n\t({ asChild, children, className, name, validation: validationProp, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\t\tconst controlId = useId();\n\t\tconst descriptionId = useId();\n\t\tconst errorId = useId();\n\t\tconst [hasErrors, setHasErrors] = useState(false);\n\t\tconst validation = resolveValidation(validationProp ?? (hasErrors ? \"error\" : undefined));\n\n\t\tconst registerError = useCallback(() => {\n\t\t\tsetHasErrors(true);\n\n\t\t\treturn () => {\n\t\t\t\tsetHasErrors(false);\n\t\t\t};\n\t\t}, []);\n\n\t\tconst context = useMemo(\n\t\t\t() => ({\n\t\t\t\tcontrolId,\n\t\t\t\tdescriptionId,\n\t\t\t\terrorId,\n\t\t\t\thasErrors,\n\t\t\t\tname,\n\t\t\t\tregisterError,\n\t\t\t\tvalidation,\n\t\t\t}),\n\t\t\t[controlId, descriptionId, errorId, hasErrors, name, registerError, validation],\n\t\t);\n\n\t\treturn (\n\t\t\t<FieldItemContext.Provider value={context}>\n\t\t\t\t<FieldValidationProvider validation={validation}>\n\t\t\t\t\t<Comp\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tdata-slot=\"field-item\"\n\t\t\t\t\t\tdata-validation={validation}\n\t\t\t\t\t\tclassName={cx(\"flex w-full flex-col gap-1.5\", className)}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Comp>\n\t\t\t\t</FieldValidationProvider>\n\t\t\t</FieldItemContext.Provider>\n\t\t);\n\t},\n);\nItem.displayName = \"FieldItem\";\n\ntype FieldControlSlotProps = Omit<\n\tComponentProps<typeof Slot>,\n\t\"aria-describedby\" | \"aria-errormessage\" | \"aria-invalid\" | \"children\"\n>;\n\n/**\n * Element-child form of `Field.Control`. Renders via `Slot`, so it accepts\n * any HTML/Slot props and a forwarded ref — those land on the single child\n * element along with the generated ARIA props.\n */\ntype FieldControlElementProps = FieldControlSlotProps & {\n\t/**\n\t * A single control element to receive the field ARIA props.\n\t */\n\tchildren: ReactElement;\n};\n\n/**\n * Render-prop form of `Field.Control`. The caller owns the rendered element,\n * so `Field.Control` itself renders nothing — extra DOM props and `ref` have\n * no element to attach to and are intentionally not part of this variant.\n * Slot props are marked `never` so passing e.g. `className` alongside a\n * render-prop child is a type error rather than a silently ignored prop.\n */\ntype FieldControlRenderProps = {\n\t/**\n\t * A render function that places the field ARIA props onto a control of\n\t * the caller's choosing. Used for compound controls or wrappers where\n\t * `Slot` cannot reach the focusable element.\n\t */\n\tchildren: (props: FieldControlAriaProps) => ReactNode;\n} & { [K in keyof FieldControlSlotProps]?: never };\n\n/**\n * Props for `Field.Control`. A discriminated union over how the caller\n * supplies the focusable element:\n *\n * - `FieldControlElementProps` — pass a single React element child and\n * `Field.Control` clones the generated ARIA props onto it via `Slot`.\n * Accepts the full Slot prop surface plus a forwarded ref.\n * - `FieldControlRenderProps` — pass a render function that receives the\n * ARIA props and places them on a control of the caller's choosing. The\n * caller owns the rendered element, so DOM/Slot props and `ref` are\n * excluded from this variant at the type level.\n *\n * @example\n * ```tsx\n * // Element form — Slot splats id, name, and ARIA props onto <Input/>\n * <Field.Item name=\"email\">\n * <Field.Control>\n * <Input type=\"email\" />\n * </Field.Control>\n * </Field.Item>\n *\n * // Render-prop form — caller spreads the props onto its own element\n * <Field.Item name=\"acceptTerms\">\n * <Field.Control>\n * {(controlProps) => (\n * <label>\n * Accept terms\n * <input type=\"checkbox\" {...controlProps} />\n * </label>\n * )}\n * </Field.Control>\n * </Field.Item>\n * ```\n */\ntype FieldControlProps = FieldControlElementProps | FieldControlRenderProps;\n\n/**\n * Applies `Field.Item` description, error, and validation state to a single\n * focusable control. It always behaves like an `asChild` slot: pass one child\n * element to receive the generated ARIA props, or use a function child to\n * place those props manually. Mantle compound controls that consume\n * `FieldControlContext` can be wrapped at the root when their docs show that\n * composition; otherwise use the render-prop form to place the generated props\n * on the actual focusable element.\n *\n * `Field.Item` owns the full control contract — `id`, `name`, `aria-*`, and\n * `validation` all flow down from the surrounding `Field.Item` and overwrite\n * anything passed on the child. To override these values, set them on\n * `Field.Item` itself (e.g. `<Field.Item validation=\"error\">`); to opt out of\n * the contract entirely, render your control without `Field.Control`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Control = forwardRef<HTMLElement, FieldControlProps>(({ children, ...props }, ref) => {\n\tconst context = useContext(FieldItemContext);\n\t// Field.Item owns id, name, aria-*, and validation — `cloneElement` below\n\t// overwrites whatever the child supplied, and the resolver no longer reads\n\t// child-side overrides. To override any of these, set them on Field.Item.\n\tconst controlState = resolveFieldControlAriaProps({ context });\n\n\tif (typeof children === \"function\") {\n\t\treturn (\n\t\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t\t{children(controlState.ariaProps)}\n\t\t\t\t</FieldControlContext.Provider>\n\t\t\t</FieldValidationProvider>\n\t\t);\n\t}\n\n\tinvariant(\n\t\tisValidElement<FieldControlAriaProps>(children),\n\t\t\"Field.Control expects a single React element child (or a render-prop function). Got a non-element value (string, array, fragment, null, or undefined). Wrap the control in a single element, or use the function child form: <Field.Control>{(props) => <YourControl {...props} />}</Field.Control>.\",\n\t);\n\n\t// Both `cloneElement` and `FieldControlContext` flow the same resolved\n\t// props. `cloneElement` covers the simple case (Input, native input) where\n\t// the direct child is the focusable element. `FieldControlContext` covers\n\t// compound widgets like Select / MultiSelect, where the direct child is a\n\t// context provider (e.g. `Select.Root`) that does not forward ARIA props\n\t// to its inner focusable trigger — that trigger reads the context itself.\n\treturn (\n\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t<Slot ref={ref} {...props}>\n\t\t\t\t\t{cloneElement(children, controlState.ariaProps)}\n\t\t\t\t</Slot>\n\t\t\t</FieldControlContext.Provider>\n\t\t</FieldValidationProvider>\n\t);\n});\nControl.displayName = \"FieldControl\";\n\n/**\n * Helper / hint text. Renders a `<p>` in the muted body color so it reads\n * as secondary to the bolder content above it. Use inside `Field.Item`, below\n * the control, to clarify expected format or constraints for that single field.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single description\n * slot ID and applies it via context, so a second `Field.Description` would\n * duplicate that `id` in the DOM.\n *\n * **Auto-tighten.** When this description sits directly after rendered\n * `Field.Errors` or `Field.ErrorList` output, the parent's `gap-1.5`\n * collapses via a matching negative top margin so error list + helper read as\n * one tight block. Pass any margin utility (`mt-1`, `mt-0`, etc.) to override\n * — the rule's specificity is flattened to `(0,1,0)` so a single user class wins.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Description = forwardRef<ComponentRef<\"p\">, Omit<ComponentProps<\"p\">, \"id\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-description\"\n\t\t\t\tid={context?.descriptionId}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-body text-sm leading-4\",\n\t\t\t\t\t// When this description sits directly after a Field.ErrorList\n\t\t\t\t\t// sibling, collapse the parent's gap-1.5 with a matching negative\n\t\t\t\t\t// top margin so the list + helper read as one tight block.\n\t\t\t\t\t// Wrapping the matched selector in :where() flattens its specificity\n\t\t\t\t\t// to (0,1,0) so a user-supplied margin utility (mt-2, mt-0, etc.)\n\t\t\t\t\t// passed on Field.Description still overrides cleanly.\n\t\t\t\t\t\"[:where([data-slot=field-error-list]+&)]:-mt-1.5\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nDescription.displayName = \"FieldDescription\";\n\n/**\n * A single error message list item for a field. Renders an `<li>` in\n * `text-danger-600` so it stands out from a sibling `Field.Description`.\n * Must be rendered inside a `Field.ErrorList`. Empty or blank children render\n * nothing so message-less validator results do not produce empty list items.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorItem = forwardRef<ComponentRef<\"li\">, ComponentProps<\"li\">>(\n\t({ children, className, ...props }, ref) => {\n\t\tif (!isErrorItemRenderable(children)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<li\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-error\"\n\t\t\t\tclassName={cx(\"text-danger-600 text-sm leading-4\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</li>\n\t\t);\n\t},\n);\nFieldErrorItem.displayName = \"FieldErrorItem\";\n\n/**\n * Props for the `Field.Errors` convenience renderer. It owns its generated\n * children, so use `Field.ErrorList` / `Field.ErrorItem` directly when custom\n * list contents or polymorphic list markup are needed.\n */\ntype FieldErrorsProps = Omit<ComponentProps<\"ul\">, \"children\" | \"id\"> & {\n\t/**\n\t * Validation messages to render. Strings are trimmed, and empty, nullish,\n\t * or false values are ignored before rendering the list.\n\t */\n\tmessages?: readonly FieldErrorMessage[];\n};\n\n/**\n * Convenience renderer for string validation messages. Trims each message,\n * filters empty values, and renders a semantic `Field.ErrorList` containing\n * one `Field.ErrorItem` per remaining message.\n *\n * Accepts strings directly so product code can map any validation library's\n * error shape into messages without coupling Mantle to that library.\n * Deliberately does not support `asChild` because it owns the generated list\n * items; use `Field.ErrorList` with `asChild` for custom list markup.\n *\n * **At most one per `Field.Item`.** `Field.Errors` renders a `Field.ErrorList`\n * under the hood, and `Field.Item` owns a single errors slot ID. Use either\n * `Field.Errors` *or* `Field.ErrorList` per item, not both, and pass multiple\n * messages to one `Field.Errors` instead of rendering it twice.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrors = forwardRef<ComponentRef<\"ul\">, FieldErrorsProps>(\n\t({ messages, ...props }, ref) => (\n\t\t<FieldErrorList ref={ref} {...props}>\n\t\t\t{normalizeErrorMessages(messages).map((message) => (\n\t\t\t\t<FieldErrorItem key={message}>{message}</FieldErrorItem>\n\t\t\t))}\n\t\t</FieldErrorList>\n\t),\n);\nFieldErrors.displayName = \"FieldErrors\";\n\n/**\n * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>` with\n * `role=\"list\"` so a list of validation errors is announced as a list by\n * screen readers, including Safari/VoiceOver combinations that drop list\n * semantics when list styling is removed. Renders nothing when no children are\n * passed, or when all `Field.ErrorItem` children are empty.\n *\n * The list strips its default browser styling (`list-none`, `p-0`, `m-0`) and\n * stacks items as a flex column with no gap so consecutive errors read as a\n * single tight block.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single errors slot ID\n * and applies it via context. Use either `Field.ErrorList` *or* `Field.Errors`\n * per item, not both, and put multiple `Field.ErrorItem` children inside the\n * single list instead of rendering two `Field.ErrorList`s.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorList = forwardRef<\n\tComponentRef<\"ul\">,\n\tOmit<ComponentProps<\"ul\">, \"id\"> & WithAsChild\n>(({ asChild, children, className, ...props }, ref) => {\n\tconst hasRenderableChildren = hasRenderableErrorListChildren({\n\t\tchildren,\n\t\terrorItemType: FieldErrorItem,\n\t});\n\tconst context = useContext(FieldItemContext);\n\tconst registerError = context?.registerError;\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!hasRenderableChildren || registerError == null) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn registerError();\n\t}, [hasRenderableChildren, registerError]);\n\n\tif (!hasRenderableChildren) {\n\t\treturn null;\n\t}\n\n\tconst Comp = asChild ? Slot : \"ul\";\n\n\treturn (\n\t\t<Comp\n\t\t\tref={ref}\n\t\t\tdata-slot=\"field-error-list\"\n\t\t\tid={context?.errorId}\n\t\t\trole=\"list\"\n\t\t\tclassName={cx(\"m-0 flex w-full flex-col list-none p-0\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n});\nFieldErrorList.displayName = \"FieldErrorList\";\n\n/**\n * Compound component for semantic, accessible form fields. Composes a\n * `Field.Label`, control (`Input`, `Select`, etc.), `Field.Description`, and\n * validation errors (`Field.Errors` / `Field.ErrorList` + `Field.ErrorItem`)\n * with consistent spacing and ARIA wiring. Stack multiple fields with\n * `Field.Group`; use `Field.Set` + `Field.Legend` for radios / related\n * checkboxes that share one accessible name.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * Composition:\n * ```\n * Field.Group\n * └── Field.Item\n * ├── Field.LabelRow\n * │ ├── Field.Label (or Field.LabelText for control-less rows)\n * │ │ └── Field.Optional\n * │ └── Field.Help\n * │ ├── Field.HelpTrigger\n * │ └── Field.HelpContent\n * ├── Field.Control\n * │ └── (control)\n * ├── Field.Errors (or)\n * ├── Field.ErrorList\n * │ └── Field.ErrorItem\n * └── Field.Description\n * ```\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Field = {\n\t/**\n\t * A single form field. Provides message IDs and validation state to\n\t * `Field.Control`; rendered errors infer `\"error\"` validation.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * Applies generated field ARIA props and validation state to a single\n\t * focusable control. Accepts either a single React element child (cloned\n\t * via `Slot`) or a render-prop child that receives the ARIA props for\n\t * cases where `Slot` cannot reach the focusable element — for example a\n\t * `<label>`-wrapped native checkbox, or a third-party component that\n\t * needs the props placed manually on an inner input.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * // Element child — Slot splats id, name, and ARIA props onto <Input/>.\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.Label>API key</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * </Field.Item>\n\t * ```\n\t *\n\t * @example\n\t * ```tsx\n\t * // Render-prop child — caller spreads the props onto an inner element\n\t * // when the focusable target is nested (e.g. inside a <label>).\n\t * <Field.Item name=\"acceptTerms\">\n\t * <Field.Control>\n\t * {(controlProps) => (\n\t * <label>\n\t * Accept terms\n\t * <input type=\"checkbox\" {...controlProps} />\n\t * </label>\n\t * )}\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"You must accept the terms.\"]} />\n\t * </Field.Item>\n\t * ```\n\t */\n\tControl,\n\t/**\n\t * Layout container that stacks multiple `Field.Item`s vertically.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tGroup,\n\t/**\n\t * Semantic `<fieldset>` for related controls that share one accessible\n\t * name from `Field.Legend`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tSet: FieldSet,\n\t/**\n\t * Caption for `Field.Set`. Renders a semantic `<legend>`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tLegend,\n\t/**\n\t * The Mantle `Label`, exposed on `Field` for field composition. Inside a\n\t * `Field.Item`, `htmlFor` defaults to the same stable id that `Field.Control`\n\t * splats onto its focusable child — so the label-to-control association is\n\t * automatic from `Field.Item`'s required `name` and you don't need to thread\n\t * a matching `htmlFor` / `id` pair by hand. Pass an explicit `htmlFor` to\n\t * opt out (e.g. when the focusable element is rendered outside of\n\t * `Field.Control`).\n\t *\n\t * @see https://mantle.ngrok.com/components/label\n\t *\n\t * @example\n\t * ```tsx\n\t * // htmlFor is wired automatically from Field.Item's name.\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabel: FieldLabel,\n\t/**\n\t * Static, label-styled text for a `Field.Item` row that has no focusable\n\t * control to caption. Renders a `<p>` with the same typography as\n\t * `Field.Label`, so a read-only row composes cleanly alongside real form\n\t * fields without misrepresenting itself as a control caption.\n\t *\n\t * Use for derived / system-managed values (owner, created-at, computed\n\t * status) inside sheets or detail panels. For rows with a real control,\n\t * use `Field.Label` instead so the label-to-control association is wired.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Item name=\"owner\">\n\t * <Field.LabelText>Owner</Field.LabelText>\n\t * <CredentialOwnerCard owner={owner} />\n\t * <Field.Description>The user or service user that owns this API key.</Field.Description>\n\t * </Field.Item>\n\t * ```\n\t */\n\tLabelText,\n\t/**\n\t * Horizontal layout container for the label area of a field. Aligns a\n\t * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n\t * like a help-icon `Popover.Trigger` on a shared center line with `gap-1`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabelRow,\n\t/**\n\t * `Popover.Root` re-export for the help-affordance pattern. Pair with\n\t * `Field.HelpTrigger` and `Field.HelpContent` to drop a `?` button next to\n\t * a label without manually composing Popover + IconButton + QuestionIcon.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelp,\n\t/**\n\t * Trigger for a `Field.Help` popover — a ghost `IconButton` with a default\n\t * `QuestionIcon`. Requires a contextual `label`; pass `icon` to swap the\n\t * glyph, or other `IconButton` props (`size`, `appearance`, etc.) to customize.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpTrigger,\n\t/**\n\t * Body of a `Field.Help` popover. Re-exports `Popover.Content` so all\n\t * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n\t * work as expected.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpContent,\n\t/**\n\t * Inline \"(Optional)\" suffix to mark a field as optional. Default content\n\t * is `(Optional)`; pass children to translate or replace it. Place inside\n\t * the `<Field.Label>` so screen readers announce it as part of the accessible\n\t * name.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tOptional,\n\t/**\n\t * Helper / hint text rendered below the control in the muted body color.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * Convenience renderer for validation messages. Trims string messages,\n\t * filters empty values, and renders a `Field.ErrorList` with one\n\t * `Field.ErrorItem` for each remaining message.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrors: FieldErrors,\n\t/**\n\t * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>`.\n\t * Renders nothing when given no renderable children.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorList: FieldErrorList,\n\t/**\n\t * A single error message list item for a field. Renders an `<li>` in\n\t * `text-danger-600` and must be nested inside a `Field.ErrorList`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorItem: FieldErrorItem,\n} as const;\n\nexport {\n\t//,\n\tField,\n};\n","import { normalizeErrorMessages } from \"./error-helpers.js\";\n\n/**\n * Shapes commonly found in `field.state.meta.errors` from TanStack React Form\n * across its built-in validators (Standard Schema / Zod issues, raw strings,\n * thrown `Error` instances) plus the falsy slots Standard Schema can produce.\n */\ntype FieldError = { readonly message?: string | undefined } | string | null | undefined | false;\n\n/**\n * Reduce a TanStack React Form field's `meta.errors` array (or any array of\n * mixed string / `{ message }` / nullish error entries) to a clean `string[]`\n * for passing directly to `Field.Errors`' `messages` prop.\n *\n * Handles the shapes TanStack form yields for Zod, Standard Schema, and\n * thrown `Error` validators: items may be strings, objects with `.message`,\n * `undefined`, `null`, or `false`. Empty / whitespace-only messages are\n * dropped and duplicate messages are collapsed so callers don't have to filter\n * again.\n *\n * @example\n * ```tsx\n * <Field.Item>\n * <Field.Label htmlFor={field.name}>Email</Field.Label>\n * <Field.Control>\n * <Input id={field.name} value={field.state.value} />\n * </Field.Control>\n * <Field.Errors messages={toErrorMessages(field.state.meta.errors)} />\n * </Field.Item>\n * ```\n */\nconst toErrorMessages = (errors: readonly FieldError[] | null | undefined): string[] =>\n\tnormalizeErrorMessages(\n\t\terrors?.map((error) => (typeof error === \"string\" || !error ? error : error.message)),\n\t);\n\nexport {\n\t//,\n\ttoErrorMessages,\n};\n\nexport type {\n\t//,\n\tFieldError,\n};\n"],"mappings":"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"}
|
package/dist/flag.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"flag.js","names":[],"sources":["../src/components/flag/flag.tsx","../src/components/flag/country-code.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\nimport type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { CountryCode } from \"./country-code.js\";\n\nconst cdnOrigin = \"https://assets.ngrok.com\";\n\nconst sizes = [\"s\", \"m\", \"l\"] as const;\ntype Size = (typeof sizes)[number];\n\ntype Props = Omit<ComponentProps<\"div\">, \"children\"> & {\n\t/**\n\t * The country code for the flag to display\n\t * @example \"US\"\n\t */\n\tcode: CountryCode;\n\t/**\n\t * The size of flag to render, \"s\", \"m\", or \"l\"\n\t * @default \"l\"\n\t */\n\tsize?: Size;\n\t/**\n\t * A string providing a hint to the user agent as to how to best schedule the loading of the image to optimize page performance.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading\n\t * @default \"lazy\"\n\t */\n\tloading?: ComponentProps<\"img\">[\"loading\"];\n};\n\nconst borderRadiusVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"rounded-[0.0625rem]\",\n\t\t\tm: \"rounded-[0.09375rem]\",\n\t\t\tl: \"rounded-xs\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\nconst sizingVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"w-4 h-3\",\n\t\t\tm: \"w-5 h-3.75\",\n\t\t\tl: \"w-8 h-6\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\n/**\n * Renders a country flag from an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)\n * country code, served as an SVG from ngrok's CDN. Inspired by\n * [react-flagpack](https://flagpack.xyz/docs/development/react).\n *\n * **When to use**\n * - Showing the country associated with a region, IP, billing address, or locale.\n * - Inside a select option, list row, or status pill that needs a quick visual cue.\n *\n * **When not to use**\n * - As a stand-in for language. Flags ≠ languages — Brazilian Portuguese is\n * not \"Portugal\", Spanish is not just \"Spain\". Use a language label instead.\n * - As decoration where the country isn't meaningful to the user.\n *\n * **Sizing.** `\"s\"` (16×12), `\"m\"` (20×15), and `\"l\"` (32×24, default) match\n * common inline, list, and table contexts. Pick the size that matches its\n * neighbors so the flag doesn't dominate or disappear.\n *\n * **Accessibility.** The underlying `<img>` is given `alt=\"flag for {code}\"`.\n * If the country is decorative or already labeled in adjacent text, consider\n * passing `aria-hidden` via the wrapper `<div>` to avoid duplicate\n * announcements.\n *\n * **Loading.** Defaults to `loading=\"lazy\"`. Use `loading=\"eager\"` for flags\n * above the fold or in critical content.\n *\n * @see https://mantle.ngrok.com/components/flag#flag\n *\n * @example\n * ```tsx\n * import { Flag } from \"@ngrok/mantle/flag\";\n *\n * <Flag code=\"US\" />\n * <Flag code=\"JP\" size=\"m\" loading=\"eager\" />\n * <Flag code=\"CA\" size=\"s\" />\n *\n * // Inline next to a country label.\n * <span className=\"inline-flex items-center gap-2\">\n * <Flag code=\"GB\" size=\"s\" aria-hidden />\n * <span>United Kingdom</span>\n * </span>\n * ```\n */\nfunction Flag({\n\t//,\n\tclassName,\n\tcode,\n\tsize = \"l\",\n\tloading = \"lazy\",\n\t...props\n}: Props) {\n\tconst borderRadius = borderRadiusVariants({ size });\n\tconst sizing = sizingVariants({ size });\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"flag\"\n\t\t\tclassName={cx(\"flag relative overflow-hidden\", borderRadius, sizing, className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div aria-hidden className={cx(\"absolute inset-0 border border-[#000]/10\", borderRadius)} />\n\t\t\t<img\n\t\t\t\tclassName=\"h-full w-full block object-cover\"\n\t\t\t\tsrc={`${cdnOrigin}/flags/${size}/${code}.svg`}\n\t\t\t\talt={`flag for ${code}`}\n\t\t\t\tloading={loading}\n\t\t\t/>\n\t\t</div>\n\t);\n}\nFlag.displayName = \"Flag\";\n\nexport {\n\t//,\n\tFlag,\n};\n\nexport type {\n\t//,\n\tProps as FlagProps,\n};\n","/** All valid values for a flag\n * @see https://www.flagpack.xyz/docs/flag-index\n */\nconst countryCodes = [\n\t\"004\",\n\t\"008\",\n\t\"010\",\n\t\"016\",\n\t\"016\",\n\t\"020\",\n\t\"024\",\n\t\"028\",\n\t\"031\",\n\t\"032\",\n\t\"040\",\n\t\"044\",\n\t\"048\",\n\t\"050\",\n\t\"051\",\n\t\"052\",\n\t\"056\",\n\t\"060\",\n\t\"064\",\n\t\"068\",\n\t\"070\",\n\t\"072\",\n\t\"074\",\n\t\"076\",\n\t\"084\",\n\t\"086\",\n\t\"090\",\n\t\"092\",\n\t\"096\",\n\t\"100\",\n\t\"104\",\n\t\"108\",\n\t\"112\",\n\t\"116\",\n\t\"120\",\n\t\"124\",\n\t\"132\",\n\t\"136\",\n\t\"140\",\n\t\"144\",\n\t\"148\",\n\t\"152\",\n\t\"156\",\n\t\"158\",\n\t\"162\",\n\t\"166\",\n\t\"170\",\n\t\"174\",\n\t\"178\",\n\t\"180\",\n\t\"184\",\n\t\"188\",\n\t\"191\",\n\t\"192\",\n\t\"196\",\n\t\"203\",\n\t\"204\",\n\t\"208\",\n\t\"212\",\n\t\"214\",\n\t\"218\",\n\t\"222\",\n\t\"226\",\n\t\"231\",\n\t\"232\",\n\t\"233\",\n\t\"234\",\n\t\"238\",\n\t\"239\",\n\t\"242\",\n\t\"246\",\n\t\"248\",\n\t\"250\",\n\t\"254\",\n\t\"258\",\n\t\"260\",\n\t\"262\",\n\t\"266\",\n\t\"268\",\n\t\"270\",\n\t\"275\",\n\t\"276\",\n\t\"288\",\n\t\"292\",\n\t\"296\",\n\t\"300\",\n\t\"304\",\n\t\"308\",\n\t\"312\",\n\t\"316\",\n\t\"320\",\n\t\"324\",\n\t\"328\",\n\t\"332\",\n\t\"334\",\n\t\"336\",\n\t\"340\",\n\t\"344\",\n\t\"348\",\n\t\"352\",\n\t\"356\",\n\t\"360\",\n\t\"364\",\n\t\"368\",\n\t\"372\",\n\t\"376\",\n\t\"380\",\n\t\"384\",\n\t\"388\",\n\t\"392\",\n\t\"398\",\n\t\"400\",\n\t\"404\",\n\t\"408\",\n\t\"410\",\n\t\"414\",\n\t\"417\",\n\t\"418\",\n\t\"422\",\n\t\"426\",\n\t\"428\",\n\t\"430\",\n\t\"434\",\n\t\"438\",\n\t\"440\",\n\t\"442\",\n\t\"446\",\n\t\"450\",\n\t\"454\",\n\t\"458\",\n\t\"462\",\n\t\"466\",\n\t\"470\",\n\t\"474\",\n\t\"478\",\n\t\"480\",\n\t\"484\",\n\t\"492\",\n\t\"496\",\n\t\"498\",\n\t\"499\",\n\t\"500\",\n\t\"504\",\n\t\"508\",\n\t\"512\",\n\t\"516\",\n\t\"520\",\n\t\"524\",\n\t\"528\",\n\t\"531\",\n\t\"533\",\n\t\"534\",\n\t\"540\",\n\t\"548\",\n\t\"554\",\n\t\"558\",\n\t\"562\",\n\t\"566\",\n\t\"570\",\n\t\"574\",\n\t\"578\",\n\t\"580\",\n\t\"581\",\n\t\"583\",\n\t\"584\",\n\t\"585\",\n\t\"586\",\n\t\"591\",\n\t\"598\",\n\t\"600\",\n\t\"604\",\n\t\"608\",\n\t\"612\",\n\t\"616\",\n\t\"620\",\n\t\"624\",\n\t\"626\",\n\t\"630\",\n\t\"634\",\n\t\"638\",\n\t\"642\",\n\t\"643\",\n\t\"646\",\n\t\"652\",\n\t\"654\",\n\t\"659\",\n\t\"660\",\n\t\"662\",\n\t\"663\",\n\t\"666\",\n\t\"670\",\n\t\"674\",\n\t\"678\",\n\t\"682\",\n\t\"686\",\n\t\"688\",\n\t\"690\",\n\t\"694\",\n\t\"702\",\n\t\"703\",\n\t\"704\",\n\t\"705\",\n\t\"706\",\n\t\"710\",\n\t\"716\",\n\t\"724\",\n\t\"728\",\n\t\"729\",\n\t\"732\",\n\t\"740\",\n\t\"744\",\n\t\"748\",\n\t\"752\",\n\t\"756\",\n\t\"760\",\n\t\"762\",\n\t\"764\",\n\t\"768\",\n\t\"772\",\n\t\"776\",\n\t\"780\",\n\t\"784\",\n\t\"788\",\n\t\"792\",\n\t\"795\",\n\t\"796\",\n\t\"798\",\n\t\"800\",\n\t\"804\",\n\t\"807\",\n\t\"818\",\n\t\"831\",\n\t\"832\",\n\t\"833\",\n\t\"834\",\n\t\"836\",\n\t\"840\",\n\t\"850\",\n\t\"854\",\n\t\"858\",\n\t\"860\",\n\t\"862\",\n\t\"876\",\n\t\"882\",\n\t\"887\",\n\t\"894\",\n\t\"ABW\",\n\t\"AD\",\n\t\"AE\",\n\t\"AF\",\n\t\"AFG\",\n\t\"AFRUN\",\n\t\"AG\",\n\t\"AGO\",\n\t\"AI\",\n\t\"AIA\",\n\t\"AL\",\n\t\"ALA\",\n\t\"ALB\",\n\t\"AM\",\n\t\"AMS\",\n\t\"AND\",\n\t\"AO\",\n\t\"AQ\",\n\t\"AR\",\n\t\"ARE\",\n\t\"ARG\",\n\t\"ARM\",\n\t\"AS\",\n\t\"ASM\",\n\t\"AT\",\n\t\"ATA\",\n\t\"ATF\",\n\t\"ATG\",\n\t\"AU\",\n\t\"AUS\",\n\t\"AUT\",\n\t\"AW\",\n\t\"AX\",\n\t\"AZ\",\n\t\"AZE\",\n\t\"BA\",\n\t\"BB\",\n\t\"BD\",\n\t\"BDI\",\n\t\"BE\",\n\t\"BEL\",\n\t\"BEN\",\n\t\"BF\",\n\t\"BFA\",\n\t\"BG\",\n\t\"BGD\",\n\t\"BGR\",\n\t\"BH\",\n\t\"BHR\",\n\t\"BHS\",\n\t\"BI\",\n\t\"BIH\",\n\t\"BJ\",\n\t\"BL\",\n\t\"BLM\",\n\t\"BLR\",\n\t\"BLZ\",\n\t\"BM\",\n\t\"BMU\",\n\t\"BN\",\n\t\"BO\",\n\t\"BOL\",\n\t\"BQ-BO\",\n\t\"BQ-SA\",\n\t\"BQ-SE\",\n\t\"BR\",\n\t\"BRA\",\n\t\"BRB\",\n\t\"BRN\",\n\t\"BS\",\n\t\"BT\",\n\t\"BTN\",\n\t\"BV\",\n\t\"BVT\",\n\t\"BW\",\n\t\"BWA\",\n\t\"BY\",\n\t\"BZ\",\n\t\"CA\",\n\t\"CAF\",\n\t\"CAN\",\n\t\"CC\",\n\t\"CCK\",\n\t\"CD\",\n\t\"CF\",\n\t\"CG\",\n\t\"CH\",\n\t\"CHE\",\n\t\"CHL\",\n\t\"CHN\",\n\t\"CI\",\n\t\"CIV\",\n\t\"CK\",\n\t\"CL\",\n\t\"CM\",\n\t\"CMR\",\n\t\"CN\",\n\t\"CO\",\n\t\"COD\",\n\t\"COG\",\n\t\"COK\",\n\t\"COL\",\n\t\"COM\",\n\t\"CPV\",\n\t\"CR\",\n\t\"CRI\",\n\t\"CU\",\n\t\"CUB\",\n\t\"CUW\",\n\t\"CV\",\n\t\"CW\",\n\t\"CX\",\n\t\"CXR\",\n\t\"CY\",\n\t\"CYM\",\n\t\"CYP\",\n\t\"CZ\",\n\t\"CZE\",\n\t\"DE\",\n\t\"DEU\",\n\t\"DJ\",\n\t\"DJI\",\n\t\"DK\",\n\t\"DM\",\n\t\"DMA\",\n\t\"DNK\",\n\t\"DO\",\n\t\"DOM\",\n\t\"EC\",\n\t\"ECU\",\n\t\"EE\",\n\t\"EG\",\n\t\"EGY\",\n\t\"EH\",\n\t\"ER\",\n\t\"ERI\",\n\t\"ES\",\n\t\"ESH\",\n\t\"ESP\",\n\t\"EST\",\n\t\"ET\",\n\t\"ETH\",\n\t\"EU\",\n\t\"FI\",\n\t\"FIN\",\n\t\"FJ\",\n\t\"FJI\",\n\t\"FK\",\n\t\"FLK\",\n\t\"FM\",\n\t\"FO\",\n\t\"FR\",\n\t\"FRA\",\n\t\"FRO\",\n\t\"FSM\",\n\t\"GA\",\n\t\"GAB\",\n\t\"GB-ENG\",\n\t\"GB-NIR\",\n\t\"GB-SCT\",\n\t\"GB-UKM\",\n\t\"GB-WLS\",\n\t\"GB\",\n\t\"GBR\",\n\t\"GD\",\n\t\"GE\",\n\t\"GEO\",\n\t\"GF\",\n\t\"GG\",\n\t\"GGY\",\n\t\"GH\",\n\t\"GHA\",\n\t\"GI\",\n\t\"GIB\",\n\t\"GIN\",\n\t\"GL\",\n\t\"GLP\",\n\t\"GM\",\n\t\"GMB\",\n\t\"GN\",\n\t\"GNB\",\n\t\"GNQ\",\n\t\"GP\",\n\t\"GQ\",\n\t\"GR\",\n\t\"GRC\",\n\t\"GRD\",\n\t\"GRL\",\n\t\"GS\",\n\t\"GT\",\n\t\"GTM\",\n\t\"GU\",\n\t\"GUF\",\n\t\"GUM\",\n\t\"GUY\",\n\t\"GW\",\n\t\"GY\",\n\t\"HK\",\n\t\"HKG\",\n\t\"HM\",\n\t\"HMD\",\n\t\"HN\",\n\t\"HND\",\n\t\"HR\",\n\t\"HRV\",\n\t\"HT\",\n\t\"HTI\",\n\t\"HU\",\n\t\"HUN\",\n\t\"ID\",\n\t\"IDN\",\n\t\"IE\",\n\t\"IL\",\n\t\"IM\",\n\t\"IMN\",\n\t\"IN\",\n\t\"IND\",\n\t\"IO\",\n\t\"IOT\",\n\t\"IQ\",\n\t\"IR\",\n\t\"IRL\",\n\t\"IRN\",\n\t\"IRQ\",\n\t\"IS\",\n\t\"ISL\",\n\t\"ISR\",\n\t\"IT\",\n\t\"ITA\",\n\t\"JAM\",\n\t\"JE\",\n\t\"JEY\",\n\t\"JM\",\n\t\"JO\",\n\t\"JOR\",\n\t\"JP\",\n\t\"JPN\",\n\t\"KAZ\",\n\t\"KE\",\n\t\"KEN\",\n\t\"KG\",\n\t\"KGZ\",\n\t\"KH\",\n\t\"KHM\",\n\t\"KI\",\n\t\"KIR\",\n\t\"KM\",\n\t\"KN-SK\",\n\t\"KNA\",\n\t\"KOR\",\n\t\"KP\",\n\t\"KR\",\n\t\"KW\",\n\t\"KWT\",\n\t\"KY\",\n\t\"KZ\",\n\t\"LA\",\n\t\"LAO\",\n\t\"LB\",\n\t\"LBN\",\n\t\"LBR\",\n\t\"LBY\",\n\t\"LC\",\n\t\"LCA\",\n\t\"LI\",\n\t\"LIE\",\n\t\"LK\",\n\t\"LKA\",\n\t\"LR\",\n\t\"LS\",\n\t\"LSO\",\n\t\"LT\",\n\t\"LTU\",\n\t\"LU\",\n\t\"LUX\",\n\t\"LV\",\n\t\"LVA\",\n\t\"LY\",\n\t\"MA\",\n\t\"MAC\",\n\t\"MAF\",\n\t\"MAR\",\n\t\"MC\",\n\t\"MCO\",\n\t\"MD\",\n\t\"MDA\",\n\t\"MDG\",\n\t\"MDV\",\n\t\"ME\",\n\t\"MEX\",\n\t\"MF\",\n\t\"MG\",\n\t\"MH\",\n\t\"MHL\",\n\t\"MK\",\n\t\"MKD\",\n\t\"ML\",\n\t\"MLI\",\n\t\"MLT\",\n\t\"MM\",\n\t\"MMR\",\n\t\"MN\",\n\t\"MNE\",\n\t\"MNG\",\n\t\"MNP\",\n\t\"MO\",\n\t\"MOZ\",\n\t\"MP\",\n\t\"MQ\",\n\t\"MR\",\n\t\"MRT\",\n\t\"MS\",\n\t\"MSR\",\n\t\"MT\",\n\t\"MTQ\",\n\t\"MU\",\n\t\"MUS\",\n\t\"MV\",\n\t\"MW\",\n\t\"MWI\",\n\t\"MX\",\n\t\"MY\",\n\t\"MYS\",\n\t\"MZ\",\n\t\"NA\",\n\t\"NAM\",\n\t\"NC\",\n\t\"NCL\",\n\t\"NE\",\n\t\"NER\",\n\t\"NF\",\n\t\"NFK\",\n\t\"NG\",\n\t\"NGA\",\n\t\"NI\",\n\t\"NIC\",\n\t\"NIU\",\n\t\"NL\",\n\t\"NLD\",\n\t\"NO\",\n\t\"NOR\",\n\t\"NP\",\n\t\"NPL\",\n\t\"NR\",\n\t\"NRU\",\n\t\"NU\",\n\t\"NZ\",\n\t\"NZL\",\n\t\"OM\",\n\t\"OMN\",\n\t\"PA\",\n\t\"PAK\",\n\t\"PAN\",\n\t\"PCN\",\n\t\"PE\",\n\t\"PER\",\n\t\"PF\",\n\t\"PG\",\n\t\"PH\",\n\t\"PHL\",\n\t\"PK\",\n\t\"PL\",\n\t\"PLW\",\n\t\"PM\",\n\t\"PN\",\n\t\"PNG\",\n\t\"POL\",\n\t\"PR\",\n\t\"PRI\",\n\t\"PRK\",\n\t\"PRT\",\n\t\"PRY\",\n\t\"PS\",\n\t\"PSE\",\n\t\"PT\",\n\t\"PW\",\n\t\"PY\",\n\t\"PYF\",\n\t\"QA\",\n\t\"QAT\",\n\t\"RAINBOW\",\n\t\"RE\",\n\t\"REU\",\n\t\"RO\",\n\t\"ROU\",\n\t\"RS\",\n\t\"RU\",\n\t\"RUS\",\n\t\"RW\",\n\t\"RWA\",\n\t\"SA\",\n\t\"SAU\",\n\t\"SB\",\n\t\"SC\",\n\t\"SD\",\n\t\"SDN\",\n\t\"SE\",\n\t\"SEN\",\n\t\"SG\",\n\t\"SGP\",\n\t\"SGS\",\n\t\"SH\",\n\t\"SHN\",\n\t\"SI\",\n\t\"SJ\",\n\t\"SJM\",\n\t\"SK\",\n\t\"SL\",\n\t\"SLB\",\n\t\"SLE\",\n\t\"SLV\",\n\t\"SM\",\n\t\"SMR\",\n\t\"SN\",\n\t\"SO\",\n\t\"SOM\",\n\t\"SPM\",\n\t\"SR\",\n\t\"SRB\",\n\t\"SS\",\n\t\"SSD\",\n\t\"ST\",\n\t\"STP\",\n\t\"SUR\",\n\t\"SV\",\n\t\"SVK\",\n\t\"SVN\",\n\t\"SWE\",\n\t\"SWZ\",\n\t\"SX\",\n\t\"SXM\",\n\t\"SY\",\n\t\"SYC\",\n\t\"SYR\",\n\t\"SZ\",\n\t\"TC\",\n\t\"TCA\",\n\t\"TCD\",\n\t\"TD\",\n\t\"TF\",\n\t\"TG\",\n\t\"TGO\",\n\t\"TH\",\n\t\"THA\",\n\t\"TJ\",\n\t\"TJK\",\n\t\"TK\",\n\t\"TKL\",\n\t\"TKM\",\n\t\"TL\",\n\t\"TLS\",\n\t\"TM\",\n\t\"TN\",\n\t\"TO\",\n\t\"TON\",\n\t\"TR\",\n\t\"TT\",\n\t\"TTO\",\n\t\"TUN\",\n\t\"TUR\",\n\t\"TUV\",\n\t\"TV\",\n\t\"TW\",\n\t\"TWN\",\n\t\"TZ\",\n\t\"TZA\",\n\t\"UA\",\n\t\"UG\",\n\t\"UGA\",\n\t\"UKR\",\n\t\"UM\",\n\t\"UMI\",\n\t\"UNASUR\",\n\t\"URY\",\n\t\"US\",\n\t\"USA\",\n\t\"UY\",\n\t\"UZ\",\n\t\"UZB\",\n\t\"VA\",\n\t\"VAT\",\n\t\"VC\",\n\t\"VCT\",\n\t\"VE\",\n\t\"VEN\",\n\t\"VG\",\n\t\"VGB\",\n\t\"VI\",\n\t\"VIR\",\n\t\"VN\",\n\t\"VNM\",\n\t\"VU\",\n\t\"VUT\",\n\t\"WF\",\n\t\"WLF\",\n\t\"WS\",\n\t\"WSM\",\n\t\"YE\",\n\t\"YEM\",\n\t\"ZA\",\n\t\"ZAF\",\n\t\"ZM\",\n\t\"ZMB\",\n\t\"ZW\",\n\t\"ZWE\",\n] as const;\ntype CountryCode = (typeof countryCodes)[number];\n\n/**\n * Type Predicate: check if the given value is a valid country code\n */\nfunction isCountryCode(value: unknown): value is CountryCode {\n\treturn countryCodes.includes(value as CountryCode);\n}\n\nexport {\n\t//,\n\tisCountryCode,\n\tcountryCodes,\n};\n\nexport type {\n\t//,\n\tCountryCode,\n};\n"],"mappings":"sIAKA,MAwBM,EAAuB,EAAI,GAAI,CACpC,SAAU,CACT,KAAM,CACL,EAAG,sBACH,EAAG,uBACH,EAAG,YACJ,CACD,CACD,CAAC,EAEK,EAAiB,EAAI,GAAI,CAC9B,SAAU,CACT,KAAM,CACL,EAAG,UACH,EAAG,aACH,EAAG,SACJ,CACD,CACD,CAAC,EA6CD,SAAS,EAAK,CAEb,YACA,OACA,OAAO,IACP,UAAU,OACV,GAAG,GACM,CACT,IAAM,EAAe,EAAqB,CAAE,MAAK,CAAC,EAGlD,OACC,EAAC,MAAD,CACC,YAAU,OACV,UAAW,EAAG,gCAAiC,EALlC,EAAe,CAAE,MAAK,CAK+B,EAAG,CAAS,EAC9E,GAAI,WAHL,CAKC,EAAC,MAAD,CAAK,cAAA,GAAY,UAAW,EAAG,2CAA4C,CAAY,CAAI,CAAA,EAC3F,EAAC,MAAD,CACC,UAAU,mCACV,IAAK,kCAAsB,EAAK,GAAG,EAAK,MACxC,IAAK,YAAY,IACR,SACT,CAAA,CACG,GAEP,CACA,EAAK,YAAc,OCpHnB,MAAM,EAAe,ivFAgvBrB,EAMA,SAAS,EAAc,EAAsC,CAC5D,OAAO,EAAa,SAAS,CAAoB,CAClD"}
|
package/dist/hooks.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","names":[],"sources":["../src/hooks/use-breakpoint.tsx","../src/hooks/use-callback-ref.tsx","../src/hooks/use-debounced-callback.tsx","../src/hooks/use-random-stable-id.tsx","../src/hooks/use-scroll-behavior.tsx","../src/hooks/use-in-view.tsx","../src/hooks/use-undo-redo.tsx"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\n\n/**\n * Tailwind CSS breakpoints in descending order (largest → smallest).\n *\n * These correspond to Tailwind’s default `theme.screens` config and are used\n * to determine the current viewport size.\n *\n * @see https://tailwindcss.com/docs/screens\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\nconst tailwindBreakpoints = [\"2xl\", \"xl\", \"lg\", \"md\", \"sm\", \"xs\", \"2xs\"] as const;\n\n/**\n * A valid Tailwind CSS breakpoint identifier.\n *\n * @example\n * const bp: TailwindBreakpoint = \"md\"; // ≥48rem (768px)\n *\n * @example\n * \"2xl\" // ≥96rem (1536px)\n * \"xl\" // ≥80rem (1280px)\n * \"lg\" // ≥64rem (1024px)\n * \"md\" // ≥48rem (768px)\n * \"sm\" // ≥40rem (640px)\n * \"xs\" // ≥30rem (480px)\n * \"2xs\" // ≥22.5rem (360px)\n */\ntype TailwindBreakpoint = (typeof tailwindBreakpoints)[number];\n\n/**\n * Mantle’s breakpoint set, extending Tailwind’s with `\"default\"`.\n *\n * `\"default\"` represents the base (0px and up) viewport,\n * useful for defining fallbacks or mobile-first styles.\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\nconst breakpoints = [\"default\", ...tailwindBreakpoints] as const;\n\n/**\n * A valid Mantle breakpoint identifier.\n *\n * Includes Tailwind’s standard breakpoints plus `\"default\"` for 0px+.\n *\n * @example\n * const bp: Breakpoint = \"default\"; // ≥0px\n *\n * @example\n * \"default\" // ≥0rem (0px)\n * \"2xs\" // ≥22.5rem (360px)\n * \"xs\" // ≥30rem (480px)\n * \"sm\" // ≥40rem (640px)\n * \"md\" // ≥48rem (768px)\n * \"lg\" // ≥64rem (1024px)\n * \"xl\" // ≥80rem (1280px)\n * \"2xl\" // ≥96rem (1536px)\n */\ntype Breakpoint = (typeof breakpoints)[number];\n\n/**\n * React hook that returns the current breakpoint based on the viewport width.\n *\n * Uses a singleton subscription to a set of min-width media queries and returns\n * the largest matching breakpoint. Designed for React 18+ with\n * `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The current breakpoint that matches the viewport width.\n *\n * @example\n * const breakpoint = useBreakpoint();\n * if (breakpoint === \"lg\") {\n * // Do something for large screens and above\n * }\n */\nfunction useBreakpoint(): Breakpoint {\n\treturn useSyncExternalStore(\n\t\tsubscribeToBreakpointChanges,\n\t\tgetCurrentBreakpointSnapshot,\n\t\t() => \"default\", // SSR fallback\n\t);\n}\n\n/**\n * React hook that returns true if the current viewport width is below the specified breakpoint.\n *\n * This hook uses `window.matchMedia` with a max-width media query and leverages\n * `useSyncExternalStore` to stay compliant with React's concurrent rendering model.\n *\n * @param {TailwindBreakpoint} breakpoint - The breakpoint to check against (e.g., \"md\", \"lg\").\n *\n * @returns {boolean} `true` if the viewport width is below the breakpoint, otherwise `false`.\n *\n * @example\n * // Check if viewport is below medium (768px)\n * const isBelowMd = useIsBelowBreakpoint(\"md\");\n */\nfunction useIsBelowBreakpoint(breakpoint: TailwindBreakpoint): boolean {\n\treturn useSyncExternalStore(\n\t\tcreateBelowBreakpointSubscribe(breakpoint),\n\t\tcreateBelowBreakpointGetSnapshot(breakpoint),\n\t\t() => false, // SSR fallback - assume desktop\n\t);\n}\n\nexport {\n\t//,\n\tbreakpoints,\n\tuseBreakpoint,\n\tuseIsBelowBreakpoint,\n};\n\nexport type {\n\t//,\n\tBreakpoint,\n\tTailwindBreakpoint,\n};\n\n/**\n * A CSS media query string representing a minimum width in `rem` units.\n *\n * @example\n * const query: MinWidthQuery = \"(min-width: 48rem)\";\n *\n * @private\n */\ntype MinWidthQuery = `(min-width: ${number}rem)`;\n\n/**\n * A CSS media query string representing a maximum width in `rem` units.\n *\n * @example\n * const query: MaxWidthQuery = \"(max-width: 47.99rem)\";\n *\n * @private\n */\ntype MaxWidthQuery = `(max-width: ${number}rem)`;\n\n/**\n * Precomputed min-width media query strings for each Tailwind breakpoint.\n *\n * Using constants avoids template string work in hot paths and ensures type\n * safety against the `MinWidthQuery` template literal type.\n *\n * @remarks\n * These are expressed in `rem`. If your CSS breakpoints are in `px`, consider\n * aligning units to avoid JS/CSS drift when `html{font-size}` changes.\n *\n * @private\n */\nconst breakpointQueries = {\n\t\"2xl\": \"(min-width: 96rem)\" as const,\n\txl: \"(min-width: 80rem)\" as const,\n\tlg: \"(min-width: 64rem)\" as const,\n\tmd: \"(min-width: 48rem)\" as const,\n\tsm: \"(min-width: 40rem)\" as const,\n\txs: \"(min-width: 30rem)\" as const,\n\t\"2xs\": \"(min-width: 22.5rem)\" as const,\n} as const satisfies Record<TailwindBreakpoint, MinWidthQuery>;\n\n/**\n * Precomputed max-width media query strings used by `useIsBelowBreakpoint`.\n *\n * The `-0.01rem` offset avoids overlap at exact boundaries.\n *\n * @private\n */\nconst belowBreakpointQueries = {\n\t\"2xl\": \"(max-width: 95.99rem)\" as const, // 96 - 0.01\n\txl: \"(max-width: 79.99rem)\" as const, // 80 - 0.01\n\tlg: \"(max-width: 63.99rem)\" as const, // 64 - 0.01\n\tmd: \"(max-width: 47.99rem)\" as const, // 48 - 0.01\n\tsm: \"(max-width: 39.99rem)\" as const, // 40 - 0.01\n\txs: \"(max-width: 29.99rem)\" as const, // 30 - 0.01\n\t\"2xs\": \"(max-width: 22.49rem)\" as const, // 22.5 - 0.01\n} as const satisfies Record<TailwindBreakpoint, MaxWidthQuery>;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for min-width queries.\n *\n * Initialized on first access to remain SSR-safe (no `window` at import time).\n *\n * @private\n */\nlet minWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Lazily-initialized cache of `MediaQueryList` objects for max-width queries.\n *\n * Used by `useIsBelowBreakpoint`. Also SSR-safe by lazy access.\n *\n * @private\n */\nlet maxWidthMQLs: Record<TailwindBreakpoint, MediaQueryList> | null = null;\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` objects for min-width queries.\n *\n * @returns A record of `MediaQueryList` keyed by Tailwind breakpoint.\n * @private\n */\nfunction getMinWidthMQLs(): Record<TailwindBreakpoint, MediaQueryList> {\n\tif (!minWidthMQLs) {\n\t\tminWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(breakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(breakpointQueries.xl),\n\t\t\tlg: window.matchMedia(breakpointQueries.lg),\n\t\t\tmd: window.matchMedia(breakpointQueries.md),\n\t\t\tsm: window.matchMedia(breakpointQueries.sm),\n\t\t\txs: window.matchMedia(breakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(breakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn minWidthMQLs;\n}\n\n/**\n * Get (and lazily create) the cached `MediaQueryList` for a specific max-width breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"md\").\n * @returns The corresponding `MediaQueryList`.\n * @private\n */\nfunction getMaxWidthMQL(breakpoint: TailwindBreakpoint): MediaQueryList {\n\tif (!maxWidthMQLs) {\n\t\tmaxWidthMQLs = {\n\t\t\t\"2xl\": window.matchMedia(belowBreakpointQueries[\"2xl\"]),\n\t\t\txl: window.matchMedia(belowBreakpointQueries.xl),\n\t\t\tlg: window.matchMedia(belowBreakpointQueries.lg),\n\t\t\tmd: window.matchMedia(belowBreakpointQueries.md),\n\t\t\tsm: window.matchMedia(belowBreakpointQueries.sm),\n\t\t\txs: window.matchMedia(belowBreakpointQueries.xs),\n\t\t\t\"2xs\": window.matchMedia(belowBreakpointQueries[\"2xs\"]),\n\t\t};\n\t}\n\treturn maxWidthMQLs[breakpoint];\n}\n\n/**\n * Current breakpoint value used by the singleton store backing `useBreakpoint`.\n *\n * Initialized to `\"default\"` and updated on media-query change events.\n *\n * @private\n */\nlet currentBreakpointValue: Breakpoint = \"default\";\n\n/**\n * Set of component listeners subscribed to the singleton breakpoint store.\n *\n * Each listener is invoked when the current breakpoint value changes.\n *\n * @private\n */\nconst breakpointListeners = new Set<() => void>();\n\n/**\n * Flag indicating whether global media-query listeners are currently attached.\n *\n * Prevents duplicate registrations and enables full teardown when unused.\n *\n * @private\n */\nlet breakpointSubscriptionActive = false;\n\n/**\n * Compute the current breakpoint by checking cached min-width MQLs\n * from largest to smallest.\n *\n * @returns {Breakpoint} The largest matching breakpoint, or `\"default\"`.\n * @private\n */\nfunction getCurrentBreakpoint(): Breakpoint {\n\tconst mqls = getMinWidthMQLs();\n\tfor (const breakpoint of tailwindBreakpoints) {\n\t\tif (mqls[breakpoint].matches) {\n\t\t\treturn breakpoint;\n\t\t}\n\t}\n\treturn \"default\";\n}\n\n/**\n * Update the current breakpoint value and notify all listeners.\n *\n * Uses `requestAnimationFrame` to coalesce rapid resize events and minimize\n * re-renders during active window resizing.\n *\n * @private\n */\nlet breakpointUpdatePending = false;\nfunction updateCurrentBreakpoint() {\n\tif (!breakpointUpdatePending) {\n\t\tbreakpointUpdatePending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\tbreakpointUpdatePending = false;\n\t\t\tconst newBreakpoint = getCurrentBreakpoint();\n\t\t\tif (newBreakpoint !== currentBreakpointValue) {\n\t\t\t\tcurrentBreakpointValue = newBreakpoint;\n\t\t\t\tfor (const listener of breakpointListeners) {\n\t\t\t\t\tlistener();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\n/**\n * Subscribe a component to breakpoint changes (singleton pattern).\n *\n * Ensures only one set of MQL listeners exists app-wide. Also reconciles the\n * `useSyncExternalStore` initial snapshot/subscribe race by invoking the\n * subscriber once on mount.\n *\n * @param callback - Listener invoked when the breakpoint value may have changed.\n * @returns Cleanup function to unsubscribe the listener.\n * @private\n */\nfunction subscribeToBreakpointChanges(callback: () => void) {\n\tbreakpointListeners.add(callback);\n\n\t// Attach global listeners once\n\tif (!breakpointSubscriptionActive) {\n\t\tbreakpointSubscriptionActive = true;\n\t\tconst mqls = getMinWidthMQLs();\n\n\t\t// Initialize current value synchronously\n\t\tcurrentBreakpointValue = getCurrentBreakpoint();\n\n\t\t// Attach listeners to all breakpoint MQLs\n\t\tfor (const mql of Object.values(mqls)) {\n\t\t\tmql.addEventListener(\"change\", updateCurrentBreakpoint);\n\t\t}\n\t}\n\n\t// Reconcile initial getSnapshot vs subscribe ordering\n\tcallback();\n\n\t// Cleanup\n\treturn () => {\n\t\tbreakpointListeners.delete(callback);\n\n\t\t// Tear down global listeners when no one is listening\n\t\tif (breakpointListeners.size === 0 && breakpointSubscriptionActive) {\n\t\t\tbreakpointSubscriptionActive = false;\n\t\t\tconst mqls = getMinWidthMQLs();\n\t\t\tfor (const mql of Object.values(mqls)) {\n\t\t\t\tmql.removeEventListener(\"change\", updateCurrentBreakpoint);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Return the current breakpoint value from the singleton store.\n *\n * Used as the `getSnapshot` for `useSyncExternalStore`.\n *\n * @returns {Breakpoint} The latest computed breakpoint.\n * @private\n */\nfunction getCurrentBreakpointSnapshot(): Breakpoint {\n\treturn currentBreakpointValue;\n}\n\n/**\n * Cached `subscribe` functions keyed by breakpoint.\n *\n * Without caching, `useSyncExternalStore` receives a new function reference on\n * every render, causing it to tear down and re-attach the MQL listener each\n * time — the primary source of resize sluggishness.\n *\n * @private\n */\nconst belowBreakpointSubscribeCache = new Map<\n\tTailwindBreakpoint,\n\t(callback: () => void) => () => void\n>();\n\n/**\n * Get (or create and cache) a `subscribe` function for a specific \"below\" breakpoint.\n *\n * Uses a cached `MediaQueryList` and rAF-throttled change handler to avoid\n * bursty updates during resize.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable `subscribe` function suitable for `useSyncExternalStore`.\n * @private\n */\nfunction createBelowBreakpointSubscribe(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSubscribeCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = (callback: () => void) => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\n\t\t// rAF throttle the change callback during active resize\n\t\tlet pending = false;\n\t\tconst onChange = () => {\n\t\t\tif (!pending) {\n\t\t\t\tpending = true;\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tpending = false;\n\t\t\t\t\tcallback();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tmediaQuery.addEventListener(\"change\", onChange);\n\t\treturn () => {\n\t\t\tmediaQuery.removeEventListener(\"change\", onChange);\n\t\t};\n\t};\n\n\tbelowBreakpointSubscribeCache.set(breakpoint, cached);\n\treturn cached;\n}\n\n/**\n * Cached `getSnapshot` functions keyed by breakpoint.\n *\n * Ensures `useSyncExternalStore` receives a referentially stable function,\n * preventing unnecessary subscription churn.\n *\n * @private\n */\nconst belowBreakpointSnapshotCache = new Map<TailwindBreakpoint, () => boolean>();\n\n/**\n * Get (or create and cache) a `getSnapshot` function for a specific \"below\" breakpoint.\n *\n * Uses the cached `MediaQueryList` for the target breakpoint.\n *\n * @param breakpoint - Tailwind breakpoint identifier (e.g., \"lg\").\n * @returns A stable function that returns `true` when the viewport is below the breakpoint.\n * @private\n */\nfunction createBelowBreakpointGetSnapshot(breakpoint: TailwindBreakpoint) {\n\tlet cached = belowBreakpointSnapshotCache.get(breakpoint);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tcached = () => {\n\t\tconst mediaQuery = getMaxWidthMQL(breakpoint);\n\t\treturn mediaQuery.matches;\n\t};\n\n\tbelowBreakpointSnapshotCache.set(breakpoint, cached);\n\treturn cached;\n}\n","import { useEffect, useMemo, useRef } from \"react\";\n\n/**\n * Returns a memoized callback that always invokes the latest version of the\n * provided callback, while preserving a stable function identity across\n * renders.\n *\n * Use this when you need to pass a callback to a child component, an event\n * handler, or a hook dependency array, but the consumer should not re-run /\n * re-render simply because the callback's identity changed. The returned\n * function never changes reference, but internally always calls through to\n * the latest `callback` passed in.\n *\n * Most commonly used as an internal building block for other hooks (for\n * example, {@link useDebouncedCallback}). It is also re-exported publicly\n * for consumers that need the same pattern.\n *\n * @param callback - The callback to wrap. May be `undefined`, in which case\n * invoking the returned function is a no-op until a callback is provided\n * on a subsequent render.\n * @returns A stable function with the same signature as `callback` that\n * forwards its arguments to the most recent `callback` value.\n *\n * @example\n * // Pass a stable handler to a memoized child without re-rendering it\n * const onSelect = useCallbackRef((id: string) => {\n * // reads the latest `props.items` without being in deps\n * props.onSelectItem(id, props.items);\n * });\n *\n * return <MemoizedList onSelect={onSelect} />;\n */\nfunction useCallbackRef<T extends (...args: unknown[]) => unknown>(callback: T | undefined): T {\n\tconst callbackRef = useRef(callback);\n\n\tuseEffect(() => {\n\t\tcallbackRef.current = callback;\n\t});\n\n\treturn useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n\nexport {\n\t//,\n\tuseCallbackRef,\n};\n","import { useCallback, useEffect, useRef } from \"react\";\nimport { useCallbackRef } from \"./use-callback-ref.js\";\n\n/**\n * Options for {@link useDebouncedCallback}.\n */\ntype Options = {\n\t/**\n\t * The delay in milliseconds to wait between the last invocation and\n\t * actually running the callback.\n\t */\n\twaitMs: number;\n};\n\n/**\n * Returns a debounced version of the provided callback. Each call resets a\n * timer; the underlying callback only runs after `options.waitMs` of\n * inactivity has elapsed.\n *\n * Useful for limiting rapid invocations such as search-as-you-type inputs,\n * window resize handlers, or expensive button-press handlers. The pending\n * timer is automatically cleared on unmount.\n *\n * The debounced function always invokes the latest version of `callbackFn`,\n * so callers do not need to memoize it. The returned function's identity\n * only changes when `options.waitMs` changes, so it is safe to include in\n * dependency arrays.\n *\n * @param callbackFn - The function to debounce. The latest reference passed\n * on each render is always used when the timer fires.\n * @param options - Debounce options.\n * @param options.waitMs - Milliseconds of inactivity to wait before calling\n * `callbackFn`.\n * @returns A function with the same parameter list as `callbackFn` that\n * schedules (or reschedules) the underlying call.\n *\n * @example\n * // Debounce a search input by 300ms\n * const [query, setQuery] = useState(\"\");\n * const search = useDebouncedCallback((value: string) => {\n * fetchResults(value);\n * }, { waitMs: 300 });\n *\n * return (\n * <input\n * value={query}\n * onChange={(event) => {\n * setQuery(event.target.value);\n * search(event.target.value);\n * }}\n * />\n * );\n */\nfunction useDebouncedCallback<T extends (...args: unknown[]) => unknown>(\n\tcallbackFn: T,\n\toptions: Options,\n) {\n\tconst stableCallbackFn = useCallbackRef(callbackFn);\n\tconst debounceTimerRef = useRef(0);\n\tuseEffect(() => () => window.clearTimeout(debounceTimerRef.current), []);\n\n\treturn useCallback(\n\t\t(...args: Parameters<T>) => {\n\t\t\twindow.clearTimeout(debounceTimerRef.current);\n\t\t\tdebounceTimerRef.current = window.setTimeout(() => stableCallbackFn(...args), options.waitMs);\n\t\t},\n\t\t[stableCallbackFn, options.waitMs],\n\t);\n}\n\nexport {\n\t//,\n\tuseDebouncedCallback,\n};\n","import { useMemo } from \"react\";\n\n/**\n * React hook that returns a random, stable id (e.g. `\"mantle-a3f9k7q\"`)\n * suitable for DOM `id` attributes and `aria-*` references.\n *\n * Unlike React's built-in `useId`, the generated suffix does not contain\n * special characters (`:`). The default id is safe to use directly in CSS\n * selectors and `querySelector` calls; if you provide a custom `prefix`,\n * keep it selector-safe or escape the final id with `CSS.escape()` before\n * querying. The id is generated once for the lifetime of the component and\n * is stable across re-renders, but a new value is produced when `prefix`\n * changes.\n *\n * @param prefix - Optional string prepended to the generated suffix.\n * Whitespace-only or empty values fall back to `\"mantle\"`. Use a\n * selector-safe prefix if you plan to reference the id in CSS selectors\n * without escaping. Defaults to `\"mantle\"`.\n * @returns A string of the form `\"<prefix>-<7-char-random>\"`.\n *\n * @example\n * // Associate a label with a custom input\n * const id = useRandomStableId(\"email-input\");\n *\n * return (\n * <>\n * <label htmlFor={id}>Email</label>\n * <input id={id} type=\"email\" />\n * </>\n * );\n *\n * @example\n * // Use as an aria-controls reference\n * const panelId = useRandomStableId(\"panel\");\n *\n * return (\n * <>\n * <button aria-controls={panelId}>Toggle</button>\n * <div id={panelId}>Panel contents</div>\n * </>\n * );\n */\nconst useRandomStableId = (prefix = \"mantle\") => useMemo(() => randomStableId(prefix), [prefix]);\n\nexport {\n\t//,\n\tuseRandomStableId,\n};\n\nfunction randomStableId(prefix = \"mantle\") {\n\tconst safePrefix = prefix.trim() || \"mantle\";\n\treturn [safePrefix, randomPostfix()].join(\"-\");\n}\n\nfunction randomPostfix() {\n\treturn Math.random().toString(36).substring(2, 9);\n}\n","import { useMemo } from \"react\";\nimport { usePrefersReducedMotion } from \"./use-prefers-reduced-motion.js\";\n\n/**\n * `scroll-behavior` values:\n *\n * - `\"auto\"` — scrolling happens instantly (no animation).\n * - `\"smooth\"` — scrolling animates smoothly using a user-agent–defined easing and duration.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior#values\n */\nexport type ScrollBehavior = \"auto\" | \"smooth\";\n\n/**\n * React hook that returns a {@link ScrollBehavior} value (`\"auto\"` or\n * `\"smooth\"`) that respects the user's motion preference.\n *\n * Internally calls {@link usePrefersReducedMotion}: when reduced motion is\n * preferred, this returns `\"auto\"` (no animated scroll); otherwise it\n * returns `\"smooth\"`. Pair this with `window.scrollTo`,\n * `Element.scrollIntoView`, or any other scroll API that accepts a\n * `behavior` option to avoid forcing animations on users who have opted\n * out of motion. The conservative SSR default also prevents \"first paint\"\n * scroll animations.\n *\n * @returns `\"auto\"` when the user prefers reduced motion, otherwise\n * `\"smooth\"`.\n *\n * @example\n * // Scroll to the top of the page on a button click\n * const behavior = useScrollBehavior();\n *\n * return (\n * <button onClick={() => window.scrollTo({ top: 0, behavior })}>\n * Back to top\n * </button>\n * );\n *\n * @example\n * // Bring a referenced section into view\n * const behavior = useScrollBehavior();\n * const sectionRef = useRef<HTMLElement>(null);\n *\n * function focusSection() {\n * sectionRef.current?.scrollIntoView({ behavior, block: \"start\" });\n * }\n *\n * @see {@link usePrefersReducedMotion}\n * @see CSS `scroll-behavior` property (values: `\"auto\"`, `\"smooth\"`).\n */\nexport function useScrollBehavior(): ScrollBehavior {\n\tconst prefersReducedMotion = usePrefersReducedMotion();\n\n\treturn useMemo(() => (prefersReducedMotion ? \"auto\" : \"smooth\"), [prefersReducedMotion]);\n}\n","\"use client\";\n\nimport { type RefObject, useEffect, useState } from \"react\";\nimport type { InViewOptions, MarginType } from \"../utils/in-view.js\";\nimport { inView } from \"../utils/in-view.js\";\n\n/**\n * Options for the `useInView` hook.\n */\ntype UseInViewOptions = {\n\t/**\n\t * A ref to a scrollable container element to use as the intersection root.\n\t * Defaults to the browser viewport.\n\t */\n\troot?: RefObject<Element | null>;\n\n\t/**\n\t * Expand or contract the detected area from each side of the root's bounding box.\n\t * Uses the same syntax as the CSS `margin` shorthand (e.g. `\"10px\"`, `\"10% 20px\"`).\n\t */\n\tmargin?: MarginType;\n\n\t/**\n\t * How much of the element must be visible before it is considered in view.\n\t * - `\"some\"` (default): Any part of the element is visible.\n\t * - `\"all\"`: The entire element is visible.\n\t * - `number`: An intersection ratio between `0` and `1` (e.g. `0.5` for 50%).\n\t */\n\tamount?: \"some\" | \"all\" | number;\n\n\t/**\n\t * If `true`, stop observing once the element enters the viewport for the\n\t * first time. Useful for one-shot entrance animations.\n\t * Defaults to `false`.\n\t */\n\tonce?: boolean;\n\n\t/**\n\t * The initial visibility state returned before the observer has attached.\n\t * Defaults to `false`.\n\t */\n\tinitial?: boolean;\n};\n\n/**\n * React hook that tracks whether a DOM element is visible within the viewport\n * (or a scrollable container) using the `IntersectionObserver` API.\n *\n * @param ref - A ref attached to the element to observe.\n * @param options - Options controlling the scroll root, margin, threshold,\n * initial state, and one-time detection.\n * @returns `true` if the element is currently in view, otherwise `false`.\n *\n * @example\n * // Basic usage\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref);\n *\n * return <div ref={ref}>{isInView ? \"Visible!\" : \"Hidden\"}</div>;\n *\n * @example\n * // Trigger once when the element first enters the viewport\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { once: true });\n *\n * return (\n * <div\n * ref={ref}\n * style={{ opacity: isInView ? 1 : 0, transition: \"opacity 0.5s\" }}\n * />\n * );\n *\n * @example\n * // Require 50% of the element to be visible\n * const ref = useRef<HTMLDivElement>(null);\n * const isInView = useInView(ref, { amount: 0.5 });\n */\nfunction useInView(\n\tref: RefObject<Element | null>,\n\t{ root, margin, amount, once = false, initial = false }: UseInViewOptions = {},\n): boolean {\n\tconst [isInView, setInView] = useState(initial);\n\n\tuseEffect(() => {\n\t\tif (!ref.current || (once && isInView)) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction onEnter() {\n\t\t\tsetInView(true);\n\t\t\treturn once ? undefined : () => setInView(false);\n\t\t}\n\n\t\tconst options: InViewOptions = {\n\t\t\troot: (root && root.current) || undefined,\n\t\t\tmargin,\n\t\t\tamount,\n\t\t};\n\n\t\treturn inView(ref.current, onEnter, options);\n\t\t/**\n\t\t * Intentionally omit `isInView` from deps. The effect must only re-run\n\t\t * when the observation parameters change, not when visibility changes.\n\t\t * Including `isInView` would restart the observer (disconnect + reconnect)\n\t\t * on every enter/leave event, causing wasteful churn for the common\n\t\t * `once=false` case.\n\t\t */\n\t\t// oxlint-disable-next-line react-hooks/exhaustive-deps\n\t}, [root, ref, margin, once, amount]);\n\n\treturn isInView;\n}\n\nexport { useInView };\nexport type { UseInViewOptions };\n","import { useCallback, useMemo, useReducer } from \"react\";\n\ntype UndoRedoState<T> = {\n\tundoStack: T[];\n\tredoStack: T[];\n};\n\ntype UndoRedoAction<T> =\n\t| { type: \"push\"; snapshot: T }\n\t| { type: \"undo\"; current: T }\n\t| { type: \"redo\"; current: T };\n\nfunction undoRedoReducer<T>(state: UndoRedoState<T>, action: UndoRedoAction<T>): UndoRedoState<T> {\n\tswitch (action.type) {\n\t\tcase \"push\": {\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.snapshot],\n\t\t\t\tredoStack: [],\n\t\t\t};\n\t\t}\n\t\tcase \"undo\": {\n\t\t\tif (state.undoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst undoStack = state.undoStack.slice(0, -1);\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack,\n\t\t\t\tredoStack: [...state.redoStack, action.current],\n\t\t\t};\n\t\t}\n\t\tcase \"redo\": {\n\t\t\tif (state.redoStack.length === 0) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\tconst redoStack = state.redoStack.slice(0, -1);\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn state;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tundoStack: [...state.undoStack, action.current],\n\t\t\t\tredoStack,\n\t\t\t};\n\t\t}\n\t}\n}\n\ntype UseUndoRedoReturn<T> = {\n\t/** Whether there are actions to undo. */\n\tcanUndo: boolean;\n\t/** Whether there are actions to redo. */\n\tcanRedo: boolean;\n\t/** Push a snapshot onto the undo stack. Clears the redo stack. */\n\tpush: (snapshot: T) => void;\n\t/** Pop the last snapshot from the undo stack. Returns `undefined` if empty. */\n\tundo: (current: T) => T | undefined;\n\t/** Pop the last snapshot from the redo stack. Returns `undefined` if empty. */\n\tredo: (current: T) => T | undefined;\n};\n\n/**\n * Generic undo/redo hook backed by a reducer that maintains two history\n * stacks (undo and redo).\n *\n * The hook does not own your application state — instead it helps you\n * snapshot it. Call `push(snapshot)` *before* mutating state to capture\n * the current value, then call `undo(current)` or `redo(current)` to swap\n * `current` with the previous/next snapshot. Both `undo` and `redo` return\n * the snapshot to apply, or `undefined` if their stack is empty. Pushing a\n * new snapshot clears the redo stack, matching standard editor semantics.\n *\n * @typeParam T - The type of the value being snapshotted (e.g. a list of\n * items, a serialized form value, etc.).\n *\n * @returns An object with the current undo/redo capability flags and\n * actions:\n * - `canUndo`: `true` when there is at least one snapshot on the undo\n * stack.\n * - `canRedo`: `true` when there is at least one snapshot on the redo\n * stack.\n * - `push(snapshot)`: Push a snapshot onto the undo stack and clear the\n * redo stack. Call this *before* mutating state.\n * - `undo(current)`: Pop the latest undo snapshot and return it; returns\n * `undefined` when the undo stack is empty. The supplied `current` is\n * pushed onto the redo stack so you can redo back to it.\n * - `redo(current)`: Pop the latest redo snapshot and return it; returns\n * `undefined` when the redo stack is empty. The supplied `current` is\n * pushed onto the undo stack.\n *\n * @example\n * // Snapshot before mutating, then wire up keyboard shortcuts\n * const [items, setItems] = useState<string[]>([]);\n * const { push, undo, redo, canUndo, canRedo } = useUndoRedo<string[]>();\n *\n * function removeItem(item: string) {\n * push(items); // snapshot before mutation\n * setItems((prev) => prev.filter((entry) => entry !== item));\n * }\n *\n * function handleKeyDown(event: React.KeyboardEvent) {\n * const cmd = event.metaKey || event.ctrlKey;\n * if (cmd && event.key === \"z\" && !event.shiftKey) {\n * const previous = undo(items);\n * if (previous) {\n * setItems(previous);\n * }\n * }\n * if (cmd && ((event.shiftKey && event.key === \"z\") || event.key === \"y\")) {\n * const next = redo(items);\n * if (next) {\n * setItems(next);\n * }\n * }\n * }\n *\n * return (\n * <div tabIndex={0} onKeyDown={handleKeyDown}>\n * <button disabled={!canUndo} onClick={() => { const previous = undo(items); if (previous) setItems(previous); }}>Undo</button>\n * <button disabled={!canRedo} onClick={() => { const next = redo(items); if (next) setItems(next); }}>Redo</button>\n * </div>\n * );\n */\nfunction useUndoRedo<T>(): UseUndoRedoReturn<T> {\n\tconst [state, dispatch] = useReducer(undoRedoReducer<T>, {\n\t\tundoStack: [],\n\t\tredoStack: [],\n\t});\n\n\tconst push = useCallback((snapshot: T) => {\n\t\tdispatch({ type: \"push\", snapshot });\n\t}, []);\n\n\tconst undo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst previous = state.undoStack[state.undoStack.length - 1];\n\t\t\tif (previous === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"undo\", current });\n\t\t\treturn previous;\n\t\t},\n\t\t[state.undoStack],\n\t);\n\n\tconst redo = useCallback(\n\t\t(current: T): T | undefined => {\n\t\t\tconst next = state.redoStack[state.redoStack.length - 1];\n\t\t\tif (next === undefined) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tdispatch({ type: \"redo\", current });\n\t\t\treturn next;\n\t\t},\n\t\t[state.redoStack],\n\t);\n\n\treturn useMemo(\n\t\t() => ({\n\t\t\tcanUndo: state.undoStack.length > 0,\n\t\t\tcanRedo: state.redoStack.length > 0,\n\t\t\tpush,\n\t\t\tundo,\n\t\t\tredo,\n\t\t}),\n\t\t[state.undoStack.length, state.redoStack.length, push, undo, redo],\n\t);\n}\n\nexport {\n\t//,\n\tuseUndoRedo,\n};\n\nexport type {\n\t//,\n\tUseUndoRedoReturn,\n};\n"],"mappings":"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"}
|