@ngrok/mantle 0.76.2 → 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 +30 -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 +3 -4
- 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 +124 -45
- 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 +3 -4
- 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-BL5WVva_.d.ts → index-CJbKEKr2.d.ts} +4 -3
- 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 +4 -5
- 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 +191 -14
- 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 +2 -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 +3 -4
- 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/slot.d.ts +1 -1
- 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 -0
- package/dist/table.js +1 -1
- 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 +4 -5
- 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 +22 -22
- 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-BYZOBUgj.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-eyoUW2Uv.js +0 -2
- package/dist/table-eyoUW2Uv.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
package/dist/sheet.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sheet.js","names":["SheetPrimitive.Root","SheetPrimitive.Trigger","SheetPrimitive.Close","SheetPrimitive.Portal","SheetPrimitive.Overlay","SheetPrimitive.Content","SheetPrimitive.Title","SheetPrimitive.Description"],"sources":["../src/components/sheet/sheet.tsx"],"sourcesContent":["import { XIcon } from \"@phosphor-icons/react/X\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport type { ComponentPropsWithoutRef, ComponentRef, HTMLAttributes } from \"react\";\nimport { forwardRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { IconButton, type IconButtonProps } from \"../button/icon-button.js\";\nimport * as SheetPrimitive from \"../dialog/primitive.js\";\n\n/**\n * The root component for a `Sheet`. Should compose the `Sheet.Trigger` and `Sheet.Content`.\n * Acts as a stateful provider for the Sheet's open/closed state.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetroot\n *\n * @example\n * ```tsx\n * // Triggering a stateful sheet\n * <Sheet.Root>\n * <Sheet.Trigger asChild>\n * <Button type=\"button\" appearance=\"filled\">\n * Open Sheet\n * </Button>\n * </Sheet.Trigger>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Root = SheetPrimitive.Root;\nRoot.displayName = \"Sheet\";\n\n/**\n * The button trigger for a `Sheet`. Should be rendered as a child of the `Sheet` component.\n * Renders an unstyled button by default, but can be customized with the `asChild` prop.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheettrigger\n *\n * @example\n * ```tsx\n * <Sheet.Root>\n * <Sheet.Trigger asChild>\n * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n * </Sheet.Trigger>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>Sheet content.</p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Trigger = SheetPrimitive.Trigger;\nTrigger.displayName = \"SheetTrigger\";\n\n/**\n * The close button for a `Sheet`. Should be rendered as a child of the `Sheet.Content` component.\n * Usually contained within the `Sheet.Footer` component.\n * Renders an unstyled button by default, but can be customized with the `asChild` prop.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetclose\n *\n * @example\n * ```tsx\n * <Sheet.Root>\n * <Sheet.Trigger asChild>\n * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n * </Sheet.Trigger>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>Sheet content.</p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">Save</Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Close = SheetPrimitive.Close;\nClose.displayName = \"SheetClose\";\n\n/**\n * The portal for a sheet. Should be rendered as a child of the `Sheet` component.\n * Renders a portal that the `SheetOverlay` and `Sheet.Content` is rendered into.\n *\n * @private\n */\nconst SheetPortal = SheetPrimitive.Portal;\nSheetPortal.displayName = \"SheetPortal\";\n\n/**\n * The overlay backdrop for a sheet. Should be rendered as a child of the `SheetPortal` component.\n *\n * You likely don't need to use this component directly, as it is used internally by the `Sheet.Content` component.\n *\n * @private\n */\nconst SheetOverlay = forwardRef<\n\tComponentRef<typeof SheetPrimitive.Overlay>,\n\tComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Overlay\n\t\tdata-slot=\"sheet-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-40 backdrop-blur-xs\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t\tref={ref}\n\t/>\n));\nSheetOverlay.displayName = SheetPrimitive.Overlay.displayName;\n\nconst SheetVariants = cva(\n\t\"bg-dialog border-dialog inset-y-0 h-full w-full fixed z-40 flex flex-col shadow-lg outline-hidden transition ease-in-out focus-within:outline-hidden data-state-closed:duration-100 data-state-closed:animate-out data-state-open:duration-100 data-state-open:animate-in\",\n\t{\n\t\tvariants: {\n\t\t\t/**\n\t\t\t * The side of the screen the sheet should slide in from.\n\t\t\t */\n\t\t\tside: {\n\t\t\t\tleft: \"data-state-closed:slide-out-to-left data-state-open:slide-in-from-left left-0 border-r\",\n\t\t\t\tright:\n\t\t\t\t\t\"data-state-closed:slide-out-to-right data-state-open:slide-in-from-right right-0 border-l\",\n\t\t\t},\n\t\t},\n\t\tdefaultVariants: {\n\t\t\tside: \"right\",\n\t\t},\n\t},\n);\n\ntype SheetContentProps = ComponentPropsWithoutRef<typeof SheetPrimitive.Content> &\n\tVariantProps<typeof SheetVariants> & {\n\t\t/**\n\t\t * The preferred width of the `Sheet.Content` as a tailwind `max-w-` class.\n\t\t *\n\t\t * By default, a `Sheet`'s content width is responsive with a default\n\t\t * preferred width: the maximum width of the `Sheet.Content` when the window\n\t\t * viewport is larger than the mobile breakpoint (`sm`).\n\t\t *\n\t\t * @default `sm:max-w-[30rem]`\n\t\t */\n\t\tpreferredWidth?: `sm:max-w-${string}`;\n\t};\n\n/**\n * The main container for a `Sheet`. Should be rendered as a child of the `Sheet` component.\n * Renders on top of the overlay backdrop.\n * Should contain the `Sheet.Header`, `Sheet.Body`, and `Sheet.Footer`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetcontent\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Content = forwardRef<ComponentRef<\"div\">, SheetContentProps>(\n\t({ children, className, preferredWidth = \"sm:max-w-[30rem]\", side = \"right\", ...props }, ref) => (\n\t\t<SheetPortal>\n\t\t\t<SheetOverlay />\n\t\t\t<SheetPrimitive.Content\n\t\t\t\tdata-slot=\"sheet-content\"\n\t\t\t\tdata-mantle-modal-content\n\t\t\t\tclassName={cx(SheetVariants({ side }), preferredWidth, className)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</SheetPrimitive.Content>\n\t\t</SheetPortal>\n\t),\n);\nContent.displayName = SheetPrimitive.Content.displayName;\n\ntype SheetCloseIconButtonProps = Partial<Omit<IconButtonProps, \"icon\">>;\n\n/**\n * An icon button that closes the `Sheet` when clicked.\n * Should be rendered within the `Sheet.Header` as a child of `Sheet.Actions`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetcloseiconbutton\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst CloseIconButton = ({\n\tsize = \"md\",\n\ttype = \"button\",\n\tlabel = \"Close Sheet\",\n\tappearance = \"ghost\",\n\t...props\n}: SheetCloseIconButtonProps) => (\n\t<SheetPrimitive.Close asChild>\n\t\t<IconButton\n\t\t\tdata-slot=\"sheet-close-icon-button\"\n\t\t\tappearance={appearance}\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</SheetPrimitive.Close>\n);\nCloseIconButton.displayName = \"SheetCloseIconButton\";\n\n/**\n * The body container for a `Sheet`. This is where you would typically place the main content of the sheet, such as forms or text.\n * Should be rendered as a child of `Sheet.Content`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetbody\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Body = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tdata-slot=\"sheet-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 = \"SheetBody\";\n\n/**\n * The header container for a `Sheet`. This is where you would typically place the title, description, and actions.\n * Should be rendered as a child of `Sheet.Content`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetheader\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Header = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tdata-slot=\"sheet-header\"\n\t\tclassName={cx(\n\t\t\t\"border-dialog-muted flex shrink-0 flex-col gap-2 border-b py-4 pl-6 pr-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);\nHeader.displayName = \"SheetHeader\";\n\n/**\n * The footer container for a `Sheet`. This is where you would typically place close and submit buttons.\n * Should be rendered as a child of `Sheet.Content`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetfooter\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Footer = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tdata-slot=\"sheet-footer\"\n\t\tclassName={cx(\n\t\t\t\"border-dialog-muted flex shrink-0 justify-end gap-2 border-t px-6 py-2.5\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t/>\n);\nFooter.displayName = \"SheetFooter\";\n\n/**\n * The title for a `Sheet`. Typically rendered as a child of `Sheet.TitleGroup`.\n * Defaults to an `h2` element, but can be changed via the `asChild` prop.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheettitle\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Title = forwardRef<\n\tComponentRef<typeof SheetPrimitive.Title>,\n\tComponentPropsWithoutRef<typeof SheetPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Title\n\t\tdata-slot=\"sheet-title\"\n\t\tref={ref}\n\t\tclassName={cx(\"text-strong flex-1 truncate text-lg font-medium\", className)}\n\t\t{...props}\n\t/>\n));\nTitle.displayName = SheetPrimitive.Title.displayName;\n\n/**\n * A group container for the title and actions of a sheet. Typically rendered as a child of `Sheet.Header`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheettitlegroup\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst TitleGroup = forwardRef<ComponentRef<\"div\">, HTMLAttributes<HTMLDivElement>>(\n\t({ children, className, ...props }, ref) => (\n\t\t<div\n\t\t\tdata-slot=\"sheet-title-group\"\n\t\t\tclassName={cx(\"flex items-center justify-between gap-2\", className)}\n\t\t\t{...props}\n\t\t\tref={ref}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t),\n);\nTitleGroup.displayName = \"SheetTitleGroup\";\n\n/**\n * A description for a sheet. Typically rendered as a child of `Sheet.Header`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetdescription\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Description = forwardRef<\n\tComponentRef<typeof SheetPrimitive.Description>,\n\tComponentPropsWithoutRef<typeof SheetPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<SheetPrimitive.Description\n\t\tdata-slot=\"sheet-description\"\n\t\tref={ref}\n\t\tclassName={cx(\"text-body text-sm\", className)}\n\t\t{...props}\n\t/>\n));\nDescription.displayName = SheetPrimitive.Description.displayName;\n\n/**\n * A group container for the actions of a `Sheet`. Typically rendered as a child of `Sheet.TitleGroup`.\n *\n * @see https://mantle.ngrok.com/components/sheet#sheetactions\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Actions = forwardRef<ComponentRef<\"div\">, HTMLAttributes<HTMLDivElement>>(\n\t({ children, className, ...props }, ref) => (\n\t\t<div\n\t\t\tdata-slot=\"sheet-actions\"\n\t\t\tclassName={cx(\"flex h-full items-center gap-2\", className)}\n\t\t\t{...props}\n\t\t\tref={ref}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t),\n);\nActions.displayName = \"SheetActions\";\n\n/**\n * A container that overlays the current view from the edge of the screen.\n * It is a lightweight way of allowing users to complete a task without losing\n * contextual information of the view beneath it. Use Sheet for side-panel\n * content that slides in from any edge — filter panels, detail/inspector\n * views, navigation drawers, mobile menus. For a centered modal that\n * interrupts the user, use `Dialog` (or `AlertDialog` for destructive\n * confirmations).\n *\n * @see https://mantle.ngrok.com/components/sheet\n *\n * @example\n * Composition:\n * ```\n * Sheet.Root\n * ├── Sheet.Trigger\n * └── Sheet.Content\n * ├── Sheet.Header\n * │ ├── Sheet.TitleGroup\n * │ │ ├── Sheet.Title\n * │ │ └── Sheet.Actions\n * │ └── Sheet.Description\n * ├── Sheet.Body\n * └── Sheet.Footer\n * └── Sheet.Close\n * ```\n *\n * @example\n * ```tsx\n * // Triggering a stateful sheet\n * <Sheet.Root>\n * <Sheet.Trigger asChild>\n * <Button type=\"button\" appearance=\"filled\">\n * Open Sheet\n * </Button>\n * </Sheet.Trigger>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n *\n * @example\n * ```tsx\n * // Sheet without a trigger (e.g. router controlled)\n * <Sheet open opOpenChange={() => onClose()}>\n * <Sheet.Content>\n * <Sheet.Header>\n * <Sheet.TitleGroup>\n * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n * <Sheet.Actions>\n * <IconButton\n * appearance=\"ghost\"\n * type=\"button\"\n * icon={<TrashSimple />}\n * label=\"Delete\"\n * />\n * <Separator orientation=\"vertical\" className=\"h-[80%]\" />\n * <Sheet.CloseIconButton />\n * </Sheet.Actions>\n * </Sheet.TitleGroup>\n * <Sheet.Description>\n * This action cannot be undone. This will permanently delete your account and remove your data from our servers.\n * </Sheet.Description>\n * </Sheet.Header>\n * <Sheet.Body>\n * <p>\n * Consequat do voluptate culpa fugiat consequat nostrud duis\n * aliqua minim. Tempor voluptate cillum elit velit. Voluptate\n * aliqua ipsum aliqua dolore in nisi ea fugiat aliqua velit\n * proident amet.\n * </p>\n * </Sheet.Body>\n * <Sheet.Footer>\n * <Sheet.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Sheet.Close>\n * <Button type=\"button\" appearance=\"filled\">\n * Save\n * </Button>\n * </Sheet.Footer>\n * </Sheet.Content>\n * </Sheet.Root>\n * ```\n */\nconst Sheet = {\n\t/**\n\t * The root component for a `Sheet`. Should compose the `Sheet.Trigger` and `Sheet.Content`.\n\t * Acts as a stateful provider for the Sheet's open/closed state.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * A group container for the actions of a `Sheet`. Typically rendered as a child of `Sheet.TitleGroup`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetactions\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tActions,\n\t/**\n\t * The body container for a `Sheet`. This is where you would typically place the main content of the sheet, such as forms or text.\n\t * Should be rendered as a child of `Sheet.Content`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetbody\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tBody,\n\t/**\n\t * The close button for a `Sheet`. Should be rendered as a child of the `Sheet.Content` component.\n\t * Usually contained within the `Sheet.Footer` component.\n\t * Renders an unstyled button by default, but can be customized with the `asChild` prop.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetclose\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tClose,\n\t/**\n\t * An icon button that closes the `Sheet` when clicked.\n\t * Should be rendered within the `Sheet.Header` as a child of `Sheet.Actions`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetcloseiconbutton\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tCloseIconButton,\n\t/**\n\t * The main container for a `Sheet`. Should be rendered as a child of the `Sheet` component.\n\t * Renders on top of the overlay backdrop.\n\t * Should contain the `Sheet.Header`, `Sheet.Body`, and `Sheet.Footer`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * A description for a sheet. Typically rendered as a child of `Sheet.Header`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetdescription\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * The footer container for a `Sheet`. This is where you would typically place close and submit buttons.\n\t * Should be rendered as a child of `Sheet.Content`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetfooter\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tFooter,\n\t/**\n\t * The header container for a `Sheet`. This is where you would typically place the title, description, and actions.\n\t * Should be rendered as a child of `Sheet.Content`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheetheader\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tHeader,\n\t/**\n\t * The title for a `Sheet`. Typically rendered as a child of `Sheet.TitleGroup`.\n\t * Defaults to an `h2` element, but can be changed via the `asChild` prop.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheettitle\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tTitle,\n\t/**\n\t * A group container for the title and actions of a sheet. Typically rendered as a child of `Sheet.Header`.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheettitlegroup\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tTitleGroup,\n\t/**\n\t * The button trigger for a `Sheet`. Should be rendered as a child of the `Sheet` component.\n\t * Renders an unstyled button by default, but can be customized with the `asChild` prop.\n\t *\n\t * @see https://mantle.ngrok.com/components/sheet#sheettrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Sheet.Root>\n\t * <Sheet.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"filled\">Open Sheet</Button>\n\t * </Sheet.Trigger>\n\t * <Sheet.Content>\n\t * <Sheet.Header>\n\t * <Sheet.TitleGroup>\n\t * <Sheet.Title>Are you absolutely sure?</Sheet.Title>\n\t * <Sheet.Actions>\n\t * <Sheet.CloseIconButton />\n\t * </Sheet.Actions>\n\t * </Sheet.TitleGroup>\n\t * <Sheet.Description>\n\t * This action cannot be undone.\n\t * </Sheet.Description>\n\t * </Sheet.Header>\n\t * <Sheet.Body>\n\t * <p>Sheet content.</p>\n\t * </Sheet.Body>\n\t * <Sheet.Footer>\n\t * <Sheet.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Sheet.Close>\n\t * <Button type=\"button\" appearance=\"filled\">Save</Button>\n\t * </Sheet.Footer>\n\t * </Sheet.Content>\n\t * </Sheet.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tSheet,\n};\n"],"mappings":"qVAyGA,MAAM,EAAOA,EACb,EAAK,YAAc,QAuCnB,MAAM,EAAUC,EAChB,EAAQ,YAAc,eAwCtB,MAAM,EAAQC,EACd,EAAM,YAAc,aAQpB,MAAM,EAAcC,EACpB,EAAY,YAAc,cAS1B,MAAM,EAAe,GAGlB,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACC,EAAD,CACC,YAAU,gBACV,UAAW,EACV,iKACA,CACD,EACA,GAAI,EACC,KACL,CAAA,CACD,EACD,EAAa,YAAA,EAAqC,YAElD,MAAM,EAAgB,EACrB,4QACA,CACC,SAAU,CAIT,KAAM,CACL,KAAM,yFACN,MACC,2FACF,CACD,EACA,gBAAiB,CAChB,KAAM,OACP,CACD,CACD,EAkEM,EAAU,GACd,CAAE,WAAU,YAAW,iBAAiB,mBAAoB,OAAO,QAAS,GAAG,GAAS,IACxF,EAAC,EAAD,CAAA,SAAA,CACC,EAAC,EAAD,CAAe,CAAA,EACf,EAACC,EAAD,CACC,YAAU,gBACV,4BAAA,GACA,UAAW,EAAG,EAAc,CAAE,MAAK,CAAC,EAAG,EAAgB,CAAS,EAC3D,MACL,GAAI,EAEH,UACsB,CAAA,CACZ,CAAA,CAAA,CAEf,EACA,EAAQ,YAAA,EAAqC,YAqD7C,MAAM,GAAmB,CACxB,OAAO,KACP,OAAO,SACP,QAAQ,cACR,aAAa,QACb,GAAG,KAEH,EAACH,EAAD,CAAsB,QAAA,YACrB,EAAC,EAAD,CACC,YAAU,0BACE,aACZ,KAAM,EAAC,EAAD,CAAQ,CAAA,EACP,QACD,OACA,OACN,GAAI,CACJ,CAAA,CACoB,CAAA,EAEvB,EAAgB,YAAc,uBAmD9B,MAAM,GAAQ,CAAE,YAAW,GAAG,KAC7B,EAAC,MAAD,CACC,YAAU,aACV,UAAW,EACV,yEACA,CACD,EACA,GAAI,CACJ,CAAA,EAEF,EAAK,YAAc,YAmDnB,MAAM,GAAU,CAAE,YAAW,GAAG,KAC/B,EAAC,MAAD,CACC,YAAU,eACV,UAAW,EACV,2EACA,0BACA,CACD,EACA,GAAI,CACJ,CAAA,EAEF,EAAO,YAAc,cAmDrB,MAAM,GAAU,CAAE,YAAW,GAAG,KAC/B,EAAC,MAAD,CACC,YAAU,eACV,UAAW,EACV,2EACA,CACD,EACA,GAAI,CACJ,CAAA,EAEF,EAAO,YAAc,cAmDrB,MAAM,EAAQ,GAGX,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACI,EAAD,CACC,YAAU,cACL,MACL,UAAW,EAAG,kDAAmD,CAAS,EAC1E,GAAI,CACJ,CAAA,CACD,EACD,EAAM,YAAA,EAAmC,YAkDzC,MAAM,EAAa,GACjB,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,MAAD,CACC,YAAU,oBACV,UAAW,EAAG,0CAA2C,CAAS,EAClE,GAAI,EACC,MAEJ,UACG,CAAA,CAEP,EACA,EAAW,YAAc,kBAkDzB,MAAM,EAAc,GAGjB,CAAE,YAAW,GAAG,GAAS,IAC3B,EAACC,EAAD,CACC,YAAU,oBACL,MACL,UAAW,EAAG,oBAAqB,CAAS,EAC5C,GAAI,CACJ,CAAA,CACD,EACD,EAAY,YAAA,EAAyC,YAkDrD,MAAM,EAAU,GACd,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,MAAD,CACC,YAAU,gBACV,UAAW,EAAG,iCAAkC,CAAS,EACzD,GAAI,EACC,MAEJ,UACG,CAAA,CAEP,EACA,EAAQ,YAAc,eAwHtB,MAAM,EAAQ,CAsCb,OAqCA,UAsCA,OAuCA,QAsCA,kBAuCA,UAqCA,cAsCA,SAsCA,SAsCA,QAqCA,aAsCA,SACD"}
|
package/dist/skeleton.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skeleton.js","names":[],"sources":["../src/components/skeleton/skeleton.tsx"],"sourcesContent":["import { type ComponentProps, type ComponentRef, forwardRef } from \"react\";\nimport type { SelfClosingWithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype Props = Exclude<ComponentProps<\"div\">, \"children\"> & SelfClosingWithAsChild;\n\n/**\n * A skeleton is a placeholder for content that is loading. By rendering a\n * neutral block where real content will eventually appear, you give the\n * user an early sense of layout and reduce both perceived loading time\n * and Cumulative Layout Shift (CLS).\n *\n * **When to use**\n * - Async-loaded content where the eventual shape is predictable (lists,\n * cards, tables, avatars).\n * - On initial page load, before data has resolved.\n *\n * **When not to use**\n * - For very short fetches (< 200 ms) — a flash of skeleton is more\n * distracting than helpful.\n * - To convey error or empty states. Use {@link https://mantle.ngrok.com/components/empty Empty} instead.\n * - As a permanent decorative shape.\n *\n * **Sizing.** Default height is `1rem`. Override `className` with `h-*`,\n * `w-*`, and `rounded-*` utilities to match the real content's dimensions\n * — the more closely the skeleton matches, the less layout shift on swap.\n *\n * **Accessibility.** Skeletons are decorative and convey no semantic\n * meaning to assistive tech. If the underlying region is loading, also\n * announce it to screen readers — e.g. wrap in an element with\n * `role=\"status\"` and a visually-hidden \"Loading…\" label.\n *\n * @see https://mantle.ngrok.com/components/skeleton\n *\n * @example\n * ```tsx\n * import { Skeleton } from \"@ngrok/mantle/skeleton\";\n *\n * // Text-line placeholder.\n * <Skeleton className=\"w-1/2\" />\n *\n * // Avatar placeholder.\n * <Skeleton className=\"h-12 w-12 rounded-full\" />\n *\n * // Announce loading state to assistive tech.\n * <div role=\"status\" aria-live=\"polite\">\n * <span className=\"sr-only\">Loading profile…</span>\n * <Skeleton className=\"h-12 w-12 rounded-full\" />\n * </div>\n * ```\n */\nconst Skeleton = forwardRef<ComponentRef<\"div\">, Props>(\n\t({ asChild = false, className, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tdata-slot=\"skeleton\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"dark-high-contrast:bg-black/30 high-contrast:bg-black/30 h-4 animate-pulse rounded-md bg-gray-300/25 dark:bg-gray-950/10\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nSkeleton.displayName = \"Skeleton\";\n\nexport {\n\t//,\n\tSkeleton,\n};\n"],"mappings":"kJAoDA,MAAM,EAAW,GACf,CAAE,UAAU,GAAO,YAAW,GAAG,GAAS,IAIzC,EAHiB,EAAU,EAAO,MAGlC,CACC,YAAU,WACV,UAAW,EACV,2HACA,CACD,EACK,MACL,GAAI,CACJ,CAAA,CAGJ,EACA,EAAS,YAAc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skip-to-main-link.js","names":[],"sources":["../src/components/skip-to-main-link/skip-to-main-link.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { Anchor } from \"../anchor/anchor.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype SkipToMainLinkProps = Omit<ComponentProps<\"a\">, \"href\"> & {\n\t/**\n\t * The id of the target element to focus when the link is activated.\n\t * Must match the `id` on the `<Main>` (or any focusable landmark) you\n\t * want keyboard users to be sent to.\n\t *\n\t * @default \"main\"\n\t */\n\ttargetId?: string;\n};\n\n/**\n * A visually-hidden-until-focused \"skip link\" that lets keyboard users jump\n * past repeated navigation and land directly on the page's main content\n * landmark. When activated, it updates the URL hash and focuses the element\n * identified by `targetId` (defaulting to `\"main\"`) without scrolling. It\n * still renders a plain anchor with `href=\"#${targetId}\"` to preserve link\n * semantics, support copy-link / no-JavaScript fallback behavior, and avoid\n * any router dependency in React Router, Next.js, or plain HTML.\n *\n * Pair with the `<Main>` component (or any element with a matching `id`\n * and `tabIndex={-1}`) so it can receive focus.\n *\n * @see https://mantle.ngrok.com/components/skip-to-main-link\n *\n * @example\n * ```tsx\n * <SkipToMainLink />\n * <Header />\n * <Main>\n * <h1>Page title</h1>\n * </Main>\n * ```\n */\nconst SkipToMainLink = ({\n\tchildren = \"Skip to main content\",\n\tclassName,\n\tonClick,\n\ttargetId = \"main\",\n\t...props\n}: SkipToMainLinkProps) => {\n\treturn (\n\t\t<Anchor\n\t\t\t{...props}\n\t\t\tdata-slot=\"skip-to-main-link\"\n\t\t\thref={`#${targetId}`}\n\t\t\tonClick={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\twindow.history.replaceState(null, \"\", `#${targetId}`);\n\t\t\t\tdocument.getElementById(targetId)?.focus({ preventScroll: true });\n\t\t\t\tonClick?.(event);\n\t\t\t}}\n\t\t\tclassName={cx(\n\t\t\t\t\"not-focus:sr-only bg-card fixed top-2 left-2 z-max px-4 py-2 shadow-lg\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Anchor>\n\t);\n};\nSkipToMainLink.displayName = \"SkipToMainLink\";\n\nexport {\n\t//,\n\tSkipToMainLink,\n};\n"],"mappings":"iHAsCA,MAAM,GAAkB,CACvB,WAAW,uBACX,YACA,UACA,WAAW,OACX,GAAG,KAGF,EAAC,EAAD,CACC,GAAI,EACJ,YAAU,oBACV,KAAM,IAAI,IACV,QAAU,GAAU,CACnB,EAAM,eAAe,EACrB,OAAO,QAAQ,aAAa,KAAM,GAAI,IAAI,GAAU,EACpD,SAAS,eAAe,CAAQ,CAAC,EAAE,MAAM,CAAE,cAAe,EAAK,CAAC,EAChE,IAAU,CAAK,CAChB,EACA,UAAW,EACV,yEACA,CACD,EAEC,UACM,CAAA,EAGV,EAAe,YAAc"}
|
package/dist/slider.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"slider.js","names":[],"sources":["../src/components/slider/slider.tsx"],"sourcesContent":["\"use client\";\n\nimport * as SliderPrimitive from \"@radix-ui/react-slider\";\nimport type { ComponentProps } from \"react\";\nimport { useContext } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { FieldControlContext } from \"../field/field-context.js\";\n\ntype SliderBaseProps = Omit<ComponentProps<typeof SliderPrimitive.Root>, \"defaultValue\" | \"value\">;\n\n/**\n * Value props for the {@link Slider} component. Either both `defaultValue` and\n * `value` must be the same type (both `number` or both `number[]`), or only one\n * may be provided.\n */\ntype SliderValueProps =\n\t| {\n\t\t\t/**\n\t\t\t * The value of the slider when initially rendered. Use when you do not need\n\t\t\t * to control the state of the slider.\n\t\t\t */\n\t\t\tdefaultValue?: number;\n\t\t\t/**\n\t\t\t * The controlled value of the slider. Must be used with `onValueChange`.\n\t\t\t */\n\t\t\tvalue?: number;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * The values of the slider when initially rendered. Use when you do not need\n\t\t\t * to control the state of the slider. Pass an array to create a range slider\n\t\t\t * with multiple thumbs.\n\t\t\t */\n\t\t\tdefaultValue?: number[];\n\t\t\t/**\n\t\t\t * The controlled values of the slider. Must be used with `onValueChange`.\n\t\t\t * Pass an array to create a range slider with multiple thumbs.\n\t\t\t */\n\t\t\tvalue?: number[];\n\t };\n\n/**\n * Props for the {@link Slider} component.\n */\ntype SliderProps = SliderBaseProps &\n\tSliderValueProps & {\n\t\t/**\n\t\t * The color of the slider range. Accepts any Tailwind `bg-*` class.\n\t\t * @default \"bg-accent-500\"\n\t\t */\n\t\tcolor?: `bg-${string}`;\n\t\t/**\n\t\t * Whether to show tick marks along the track at each `step` interval.\n\t\t * @default false\n\t\t */\n\t\tshowTicks?: boolean;\n\t};\n\n/**\n * An input where the user selects a value from within a given range.\n *\n * When composing with `Field.Item`, wrap `Slider` in `Field.Control`.\n * `Field.Control` flows `aria-invalid`, `aria-describedby`, and\n * `aria-errormessage` onto each thumb via `FieldControlContext`. Because\n * slider thumbs are ARIA slider widgets rather than native labelable controls,\n * pass `aria-label` or `aria-labelledby` to `Slider`; Mantle forwards those\n * labels to the rendered thumb(s).\n *\n * @see https://mantle.ngrok.com/components/slider\n *\n * @example\n * ```tsx\n * // single thumb\n * <Slider\n * aria-label=\"Volume\"\n * defaultValue={75}\n * max={100}\n * step={1}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // range\n * <Slider\n * aria-label=\"Price\"\n * defaultValue={[25, 50]}\n * max={100}\n * step={5}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // multiple thumbs\n * <Slider\n * aria-label=\"Breakpoint\"\n * defaultValue={[10, 20, 70]}\n * max={100}\n * step={10}\n * />\n * ```\n */\nfunction Slider({\n\t\"aria-describedby\": ariaDescribedBy,\n\t\"aria-errormessage\": ariaErrorMessage,\n\t\"aria-invalid\": ariaInvalid,\n\t\"aria-label\": ariaLabel,\n\t\"aria-labelledby\": ariaLabelledBy,\n\tclassName,\n\tcolor = \"bg-accent-600\",\n\tdefaultValue,\n\tid,\n\tmax = 100,\n\tmin = 0,\n\tminStepsBetweenThumbs = 1,\n\tname,\n\tstep = 1,\n\tshowTicks = false,\n\tvalue,\n\t...props\n}: SliderProps) {\n\tconst fieldControl = useContext(FieldControlContext);\n\tconst normalizedValue = value != null ? (Array.isArray(value) ? value : [value]) : undefined;\n\tconst normalizedDefaultValue =\n\t\tdefaultValue != null\n\t\t\t? Array.isArray(defaultValue)\n\t\t\t\t? defaultValue\n\t\t\t\t: [defaultValue]\n\t\t\t: undefined;\n\tconst values = normalizedValue ?? normalizedDefaultValue ?? [min];\n\tconst tickCount = computeTickCount(showTicks, min, max, step);\n\n\treturn (\n\t\t<SliderPrimitive.Root\n\t\t\tdata-slot=\"slider\"\n\t\t\tdefaultValue={normalizedDefaultValue}\n\t\t\tvalue={normalizedValue}\n\t\t\t{...(fieldControl\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\t\"aria-describedby\": ariaDescribedBy,\n\t\t\t\t\t\t\"aria-errormessage\": ariaErrorMessage,\n\t\t\t\t\t\t\"aria-invalid\": ariaInvalid,\n\t\t\t\t\t\tid,\n\t\t\t\t\t})}\n\t\t\tmin={min}\n\t\t\tminStepsBetweenThumbs={minStepsBetweenThumbs}\n\t\t\tmax={max}\n\t\t\tname={name}\n\t\t\tstep={step}\n\t\t\tclassName={cx(\n\t\t\t\t\"[--slider-thumb-size:--spacing(4.5)]\",\n\t\t\t\t\"data-orientation-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-orientation-vertical:h-full data-orientation-vertical:w-auto data-orientation-vertical:flex-col\",\n\t\t\t\ttickCount > 0 && \"mb-3\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<SliderPrimitive.Track\n\t\t\t\tdata-slot=\"slider-track\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"bg-neutral-300 rounded-full relative grow overflow-hidden\",\n\t\t\t\t\t\"data-orientation-horizontal:h-1.5 data-orientation-horizontal:w-full\",\n\t\t\t\t\t\"data-orientation-vertical:w-1.5 data-orientation-vertical:h-full\",\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<SliderPrimitive.Range\n\t\t\t\t\tdata-slot=\"slider-range\"\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"absolute select-none data-orientation-horizontal:h-full data-orientation-vertical:w-full\",\n\t\t\t\t\t\tcolor,\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</SliderPrimitive.Track>\n\t\t\t{Array.from({ length: values.length }, (_, index) => (\n\t\t\t\t<SliderPrimitive.Thumb\n\t\t\t\t\tdata-slot=\"slider-thumb\"\n\t\t\t\t\tkey={index}\n\t\t\t\t\taria-describedby={fieldControl?.[\"aria-describedby\"] ?? ariaDescribedBy}\n\t\t\t\t\taria-errormessage={fieldControl?.[\"aria-errormessage\"] ?? ariaErrorMessage}\n\t\t\t\t\taria-invalid={fieldControl?.[\"aria-invalid\"] ?? ariaInvalid}\n\t\t\t\t\taria-label={resolveThumbAriaLabel({\n\t\t\t\t\t\tariaLabel,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\tthumbCount: values.length,\n\t\t\t\t\t})}\n\t\t\t\t\taria-labelledby={ariaLabelledBy}\n\t\t\t\t\t// Only the first thumb receives the field-generated id so\n\t\t\t\t\t// Field.Label's htmlFor lands on a unique element. Range/\n\t\t\t\t\t// multi-thumb sliders share the surrounding aria wiring.\n\t\t\t\t\tid={index === 0 ? fieldControl?.id : undefined}\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"bg-card border-card relative size-(--slider-thumb-size) rounded-full border\",\n\t\t\t\t\t\t\"shadow-md transition-[color,box-shadow]\",\n\t\t\t\t\t\t\"after:absolute after:-inset-2\",\n\t\t\t\t\t\t\"focus-visible:ring-3 focus-visible:ring-accent-500/20 focus-visible:outline-hidden\",\n\t\t\t\t\t\t\"block shrink-0 cursor-pointer select-none\",\n\t\t\t\t\t\t\"data-disabled:pointer-events-none data-disabled:cursor-default\",\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t))}\n\t\t\t{tickCount > 0 && (\n\t\t\t\t<div\n\t\t\t\t\tdata-slot=\"slider-ticks\"\n\t\t\t\t\tclassName=\"absolute top-full mt-1.5 flex w-full justify-between px-[calc(var(--slider-thumb-size)/2)]\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t{Array.from({ length: tickCount }, (_, index) => (\n\t\t\t\t\t\t<span key={index} data-slot=\"slider-tick\" className=\"bg-card-border h-1.5 w-px\" />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</SliderPrimitive.Root>\n\t);\n}\n\nexport { Slider };\nexport type { SliderProps };\n\n// MARK: - Private\n\n/**\n * Compute the number of tick marks to render based on the slider's range and step.\n * Returns 0 if ticks are disabled or if the step/range is invalid.\n */\nfunction computeTickCount(showTicks: boolean, min: number, max: number, step: number): number {\n\tconst range = max - min;\n\tif (!showTicks || !Number.isFinite(range) || !Number.isFinite(step) || step <= 0 || range <= 0) {\n\t\treturn 0;\n\t}\n\treturn Math.floor(range / step) + 1;\n}\n\nfunction resolveThumbAriaLabel({\n\tariaLabel,\n\tindex,\n\tthumbCount,\n}: {\n\tariaLabel?: string;\n\tindex: number;\n\tthumbCount: number;\n}): string | undefined {\n\tif (!ariaLabel) {\n\t\treturn undefined;\n\t}\n\n\tif (thumbCount === 1) {\n\t\treturn ariaLabel;\n\t}\n\n\tif (thumbCount === 2) {\n\t\treturn `${index === 0 ? \"Minimum\" : \"Maximum\"} ${ariaLabel}`;\n\t}\n\n\treturn `${ariaLabel} ${index + 1} of ${thumbCount}`;\n}\n"],"mappings":"8MAuGA,SAAS,EAAO,CACf,mBAAoB,EACpB,oBAAqB,EACrB,eAAgB,EAChB,aAAc,EACd,kBAAmB,EACnB,YACA,QAAQ,gBACR,eACA,KACA,MAAM,IACN,MAAM,EACN,wBAAwB,EACxB,OACA,OAAO,EACP,YAAY,GACZ,QACA,GAAG,GACY,CACf,IAAM,EAAe,EAAW,CAAmB,EAC7C,EAAkB,GAAS,KAAkD,IAAA,GAA1C,MAAM,QAAQ,CAAK,EAAI,EAAQ,CAAC,CAAK,EACxE,EACL,GAAgB,KAIb,IAAA,GAHA,MAAM,QAAQ,CAAY,EACzB,EACA,CAAC,CAAY,EAEZ,EAAS,GAAmB,GAA0B,CAAC,CAAG,EAC1D,EAAY,EAAiB,EAAW,EAAK,EAAK,CAAI,EAE5D,OACC,EAAC,EAAgB,KAAjB,CACC,YAAU,SACV,aAAc,EACd,MAAO,EACP,GAAK,EACF,CAAC,EACD,CACA,mBAAoB,EACpB,oBAAqB,EACrB,eAAgB,EAChB,IACD,EACG,MACkB,wBAClB,MACC,OACA,OACN,UAAW,EACV,uCACA,4NACA,EAAY,GAAK,OACjB,CACD,EACA,GAAI,WAvBL,CAyBC,EAAC,EAAgB,MAAjB,CACC,YAAU,eACV,UAAW,EACV,4DACA,uEACA,kEACD,WAEA,EAAC,EAAgB,MAAjB,CACC,YAAU,eACV,UAAW,EACV,2FACA,CACD,CACA,CAAA,CACqB,CAAA,EACtB,MAAM,KAAK,CAAE,OAAQ,EAAO,MAAO,GAAI,EAAG,IAC1C,EAAC,EAAgB,MAAjB,CACC,YAAU,eAEV,mBAAkB,IAAe,qBAAuB,EACxD,oBAAmB,IAAe,sBAAwB,EAC1D,eAAc,IAAe,iBAAmB,EAChD,aAAY,EAAsB,CACjC,YACA,QACA,WAAY,EAAO,MACpB,CAAC,EACD,kBAAiB,EAIjB,GAAI,IAAU,EAAI,GAAc,GAAK,IAAA,GACrC,UAAW,EACV,8EACA,0CACA,gCACA,qFACA,4CACA,gEACD,CACA,EAtBK,CAsBL,CACD,EACA,EAAY,GACZ,EAAC,MAAD,CACC,YAAU,eACV,UAAU,6FACV,cAAY,gBAEX,MAAM,KAAK,CAAE,OAAQ,CAAU,GAAI,EAAG,IACtC,EAAC,OAAD,CAAkB,YAAU,cAAc,UAAU,2BAA6B,EAAtE,CAAsE,CACjF,CACG,CAAA,CAEe,GAExB,CAWA,SAAS,EAAiB,EAAoB,EAAa,EAAa,EAAsB,CAC7F,IAAM,EAAQ,EAAM,EAIpB,MAHI,CAAC,GAAa,CAAC,OAAO,SAAS,CAAK,GAAK,CAAC,OAAO,SAAS,CAAI,GAAK,GAAQ,GAAK,GAAS,EACrF,EAED,KAAK,MAAM,EAAQ,CAAI,EAAI,CACnC,CAEA,SAAS,EAAsB,CAC9B,YACA,QACA,cAKsB,CACjB,KAYL,OARI,IAAe,EACX,EAGJ,IAAe,EACX,GAAG,IAAU,EAAI,UAAY,UAAU,GAAG,IAG3C,GAAG,EAAU,GAAG,EAAQ,EAAE,MAAM,GACxC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"slot-CV5fmqFr.js","names":["Slot","RadixSlot"],"sources":["../src/components/slot/slot.tsx"],"sourcesContent":["import { Slot as RadixSlot } from \"@radix-ui/react-slot\";\nimport { Children, type ComponentProps, cloneElement, forwardRef, isValidElement } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype Props = ComponentProps<typeof RadixSlot>;\n\n/**\n * Merges its props onto its immediate child. This is useful for creating\n * components that can be rendered as different elements. Automatically merges\n * className props using `cx` for proper Tailwind class handling.\n *\n * @see https://mantle.ngrok.com/components/slot\n *\n * @example\n * ```tsx\n * <Slot className=\"custom-class\">\n * <a href=\"/\">Home</a>\n * </Slot>\n * ```\n */\nconst Slot = forwardRef<HTMLElement, Props>(function Slot(\n\t{ children, className, ...props },\n\tforwardedRef,\n) {\n\tif (!isValidElement<{ className?: string }>(children)) {\n\t\treturn Children.only(children);\n\t}\n\n\treturn (\n\t\t<RadixSlot ref={forwardedRef} {...props}>\n\t\t\t{cloneElement(children, {\n\t\t\t\t...children.props,\n\t\t\t\t/**\n\t\t\t\t * ClassName merge precedence (highest → lowest):\n\t\t\t\t *\n\t\t\t\t * 1. Child element’s own `className` ← most specific / closest to the DOM\n\t\t\t\t * 2. Slot’s `className` ← passed from the parent component\n\t\t\t\t * 3. Component’s internal base styles ← applied earlier inside the component\n\t\t\t\t *\n\t\t\t\t * We intentionally merge in this order so the child can fully override\n\t\t\t\t * parent + base styles when using `asChild`, preserving the “most specific wins”\n\t\t\t\t * behavior while still letting the component define sensible defaults.\n\t\t\t\t */\n\t\t\t\tclassName: cx(className, children.props.className),\n\t\t\t})}\n\t\t</RadixSlot>\n\t);\n});\n\nexport {\n\t//,\n\tSlot,\n};\n"],"mappings":"gNAoBA,MAAMA,EAAO,EAA+B,SAC3C,CAAE,WAAU,YAAW,GAAG,GAC1B,EACC,CAKD,OAJK,EAAuC,CAAQ,EAKnD,EAACC,EAAD,CAAW,IAAK,EAAc,GAAI,WAChC,EAAa,EAAU,CACvB,GAAG,EAAS,MAYZ,UAAW,EAAG,EAAW,EAAS,MAAM,SAAS,CAClD,CAAC,CACS,CAAA,EApBJ,EAAS,KAAK,CAAQ,CAsB/B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sort-BPX2Fk9t.js","names":[],"sources":["../src/components/icons/sort.tsx"],"sourcesContent":["import { SortAscendingIcon } from \"@phosphor-icons/react/SortAscending\";\nimport { SortDescendingIcon } from \"@phosphor-icons/react/SortDescending\";\nimport {\n\t$timeSortingDirection,\n\ttype AlphanumericSortingDirection,\n\ttype SortingDirection,\n\ttype SortingMode,\n\ttype TimeSortingDirection,\n} from \"../../utils/sorting/direction.js\";\nimport type { SvgAttributes } from \"../icon/types.js\";\n\ntype Props = SvgAttributes &\n\t(\n\t\t| {\n\t\t\t\tmode: Extract<SortingMode, \"alphanumeric\">;\n\t\t\t\t/**\n\t\t\t\t * Sort by alphanumeric order in \"ascending\" (asc) or \"descending\" (desc) order.\n\t\t\t\t * @example \"asc\" for A-Z, 0-9\n\t\t\t\t * @example \"desc\" for Z-A, 0-9\n\t\t\t\t */\n\t\t\t\tdirection: AlphanumericSortingDirection;\n\t\t }\n\t\t| {\n\t\t\t\tmode: Extract<SortingMode, \"time\">;\n\t\t\t\t/**\n\t\t\t\t * Sort by time in \"newest-to-oldest\" (descending, desc) or \"oldest-to-newest\" (ascending, asc) order.\n\t\t\t\t * @example \"newest-to-oldest\" for newest first (aka descending, desc)\n\t\t\t\t * @example \"oldest-to-newest\" for oldest first (aka ascending, asc)\n\t\t\t\t */\n\t\t\t\tdirection: TimeSortingDirection | SortingDirection;\n\t\t }\n\t);\n\n/**\n * A sorting icon that can be used to indicate the sorting direction of a table column or list.\n * It is aware of the sorting mode (alphanumeric or time) and the sorting direction (ascending or descending).\n */\nconst SortIcon = ({ mode, direction, ...props }: Props) => {\n\tswitch (mode) {\n\t\tcase \"alphanumeric\": {\n\t\t\tswitch (direction) {\n\t\t\t\tcase \"asc\":\n\t\t\t\t\treturn <SortAscendingIcon {...props} />;\n\t\t\t\tcase \"desc\":\n\t\t\t\t\treturn <SortDescendingIcon {...props} />;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Invalid alphanumeric sorting direction given: \"${direction}\"`);\n\t\t\t}\n\t\t}\n\t\tcase \"time\": {\n\t\t\tconst timeSortingDirection = $timeSortingDirection(direction);\n\n\t\t\tswitch (timeSortingDirection) {\n\t\t\t\tcase \"oldest-to-newest\":\n\t\t\t\t\treturn <SortDescendingIcon {...props} />;\n\t\t\t\tcase \"newest-to-oldest\":\n\t\t\t\t\treturn <SortAscendingIcon {...props} />;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Invalid time sorting direction given: \"${direction}\"`);\n\t\t\t}\n\t\t}\n\t}\n};\nSortIcon.displayName = \"SortIcon\";\n\nexport {\n\t//,\n\tSortIcon,\n};\n"],"mappings":"sOAqCA,MAAM,GAAY,CAAE,OAAM,YAAW,GAAG,KAAmB,CAC1D,OAAQ,EAAR,CACC,IAAK,eACJ,OAAQ,EAAR,CACC,IAAK,MACJ,OAAO,EAAC,EAAD,CAAmB,GAAI,CAAQ,CAAA,EACvC,IAAK,OACJ,OAAO,EAAC,EAAD,CAAoB,GAAI,CAAQ,CAAA,EACxC,QACC,MAAU,MAAM,kDAAkD,EAAU,EAAE,CAChF,CAED,IAAK,OAGJ,OAF6B,EAAsB,CAExB,EAA3B,CACC,IAAK,mBACJ,OAAO,EAAC,EAAD,CAAoB,GAAI,CAAQ,CAAA,EACxC,IAAK,mBACJ,OAAO,EAAC,EAAD,CAAmB,GAAI,CAAQ,CAAA,EACvC,QACC,MAAU,MAAM,0CAA0C,EAAU,EAAE,CACxE,CAEF,CACD,EACA,EAAS,YAAc"}
|
package/dist/split-button.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"split-button.js","names":[],"sources":["../src/components/split-button/split-button.tsx"],"sourcesContent":["import { CaretDownIcon } from \"@phosphor-icons/react/CaretDown\";\nimport { forwardRef, type ComponentProps, type ComponentRef, type ReactNode } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Button } from \"../button/button.js\";\nimport { IconButton } from \"../button/icon-button.js\";\nimport { DropdownMenu } from \"../dropdown-menu/dropdown-menu.js\";\nimport { Icon } from \"../icon/icon.js\";\n\ntype RootProps = ComponentProps<typeof DropdownMenu.Root> & ComponentProps<\"div\">;\n\nconst Root = forwardRef<ComponentRef<\"div\">, RootProps>(\n\t({ className, children, dir, open, defaultOpen, onOpenChange, modal, ...props }, ref) => {\n\t\treturn (\n\t\t\t<DropdownMenu.Root\n\t\t\t\tdir={dir}\n\t\t\t\topen={open}\n\t\t\t\tdefaultOpen={defaultOpen}\n\t\t\t\tonOpenChange={onOpenChange}\n\t\t\t\tmodal={modal}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tdata-slot=\"split-button\"\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"flex flex-row [&>*:first-child]:rounded-r-none [&>*:last-child]:rounded-l-none [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:not(:first-child)]:-ml-px [&>*:focus]:relative [&>*:focus]:z-10 [&>*:hover]:relative [&>*:hover]:z-10 *:active:scale-100!\",\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</div>\n\t\t\t</DropdownMenu.Root>\n\t\t);\n\t},\n);\nRoot.displayName = \"SplitButton\";\n\ntype PrimaryActionProps = Omit<ComponentProps<typeof Button>, \"appearance\" | \"type\" | \"priority\"> &\n\tPick<ComponentProps<\"button\">, \"type\">;\n\nconst PrimaryAction = forwardRef<ComponentRef<\"button\">, PrimaryActionProps>(\n\t({ type = \"button\", ...props }, ref) => {\n\t\treturn <Button appearance=\"outlined\" priority=\"neutral\" ref={ref} type={type} {...props} />;\n\t},\n);\nPrimaryAction.displayName = \"SplitButtonPrimaryAction\";\n\ntype MenuTriggerProps = Omit<\n\tComponentProps<typeof IconButton>,\n\t\"appearance\" | \"size\" | \"asChild\" | \"icon\"\n> &\n\tPick<ComponentProps<\"button\">, \"type\"> & {\n\t\ticon?: ReactNode;\n\t};\n\nconst MenuTrigger = forwardRef<ComponentRef<\"button\">, MenuTriggerProps>(\n\t({ icon, type = \"button\", ...props }, ref) => {\n\t\treturn (\n\t\t\t<DropdownMenu.Trigger asChild className=\"group\">\n\t\t\t\t<IconButton\n\t\t\t\t\ticon={\n\t\t\t\t\t\ticon ?? (\n\t\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\t\tsvg={\n\t\t\t\t\t\t\t\t\t<CaretDownIcon\n\t\t\t\t\t\t\t\t\t\tweight=\"bold\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"size-4 group-data-[state=open]:-rotate-180 transition-transform ease-out duration-150\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t\tappearance=\"outlined\"\n\t\t\t\t\tref={ref}\n\t\t\t\t\ttype={type}\n\t\t\t\t\t{...props}\n\t\t\t\t/>\n\t\t\t</DropdownMenu.Trigger>\n\t\t);\n\t},\n);\nMenuTrigger.displayName = \"SplitButtonMenuTrigger\";\n\nconst MenuContent = forwardRef<\n\tComponentRef<typeof DropdownMenu.Content>,\n\tComponentProps<typeof DropdownMenu.Content>\n>(({ align = \"end\", ...props }, ref) => {\n\treturn <DropdownMenu.Content align={align} ref={ref} {...props} />;\n});\nMenuContent.displayName = \"SplitButtonMenuContent\";\n\nconst MenuItem = forwardRef<\n\tComponentRef<typeof DropdownMenu.Item>,\n\tComponentProps<typeof DropdownMenu.Item>\n>(({ className, ...props }, ref) => {\n\treturn <DropdownMenu.Item className={cx(\"gap-2\", className)} ref={ref} {...props} />;\n});\nMenuItem.displayName = \"SplitButtonMenuItem\";\n\n/**\n * A button group which provides a default action with one click while revealing\n * related alternatives through a dropdown menu. Best for when users typically\n * want one action but occasionally need variants.\n *\n * @see https://mantle.ngrok.com/components/split-button#splitbuttonroot\n *\n * @example\n * Composition:\n * ```\n * SplitButton.Root\n * ├── SplitButton.PrimaryAction\n * ├── SplitButton.MenuTrigger\n * └── SplitButton.MenuContent\n * └── SplitButton.MenuItem\n * ```\n *\n * @example\n * ```tsx\n * <SplitButton.Root>\n * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n * Copy page\n * </SplitButton.PrimaryAction>\n * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n * <SplitButton.MenuContent>\n * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n * <Icon svg={<CopyIcon />} />\n * Copy page\n * </SplitButton.MenuItem>\n * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n * <a href={markdownUrl} target=\"_blank\">\n * <Icon svg={<FileTextIcon />} />\n * View as Markdown\n * </a>\n * </SplitButton.MenuItem>\n * </SplitButton.MenuContent>\n * </SplitButton.Root>\n * ```\n */\nconst SplitButton = {\n\t/**\n\t * A button group which provides a default action with one click while revealing\n\t * related alternatives through a dropdown menu. Best for when users typically\n\t * want one action but occasionally need variants.\n\t *\n\t * @see https://mantle.ngrok.com/components/split-button#splitbuttonroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <SplitButton.Root>\n\t * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n\t * Copy page\n\t * </SplitButton.PrimaryAction>\n\t * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n\t * <SplitButton.MenuContent>\n\t * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n\t * Copy page\n\t * <Icon svg={<CopyIcon />} />\n\t * </SplitButton.MenuItem>\n\t * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n\t * <a href={markdownUrl} target=\"_blank\">\n\t * View as Markdown\n\t * <Icon svg={<FileTextIcon />} />\n\t * </a>\n\t * </SplitButton.MenuItem>\n\t * </SplitButton.MenuContent>\n\t * </SplitButton.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The most common action users can trigger with a single click.\n\t *\n\t * @see https://mantle.ngrok.com/components/split-button#splitbuttonprimaryaction\n\t *\n\t * @example\n\t * ```tsx\n\t * <SplitButton.Root>\n\t * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n\t * Copy page\n\t * </SplitButton.PrimaryAction>\n\t * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n\t * <SplitButton.MenuContent>\n\t * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n\t * Copy page\n\t * <Icon svg={<CopyIcon />} />\n\t * </SplitButton.MenuItem>\n\t * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n\t * <a href={markdownUrl} target=\"_blank\">\n\t * View as Markdown\n\t * <Icon svg={<FileTextIcon />} />\n\t * </a>\n\t * </SplitButton.MenuItem>\n\t * </SplitButton.MenuContent>\n\t * </SplitButton.Root>\n\t * ```\n\t */\n\tPrimaryAction,\n\t/**\n\t * The button that opens the split button dropdown menu.\n\t *\n\t * @see https://mantle.ngrok.com/components/split-button#splitbuttonmenutrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <SplitButton.Root>\n\t * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n\t * Copy page\n\t * </SplitButton.PrimaryAction>\n\t * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n\t * <SplitButton.MenuContent>\n\t * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n\t * Copy page\n\t * <Icon svg={<CopyIcon />} />\n\t * </SplitButton.MenuItem>\n\t * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n\t * <a href={markdownUrl} target=\"_blank\">\n\t * View as Markdown\n\t * <Icon svg={<FileTextIcon />} />\n\t * </a>\n\t * </SplitButton.MenuItem>\n\t * </SplitButton.MenuContent>\n\t * </SplitButton.Root>\n\t * ```\n\t */\n\tMenuTrigger,\n\t/**\n\t * The container for the split button dropdown menu content. Appears in a\n\t * portal with scrolling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/split-button#splitbuttonmenucontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <SplitButton.Root>\n\t * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n\t * Copy page\n\t * </SplitButton.PrimaryAction>\n\t * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n\t * <SplitButton.MenuContent>\n\t * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n\t * Copy page\n\t * <Icon svg={<CopyIcon />} />\n\t * </SplitButton.MenuItem>\n\t * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n\t * <a href={markdownUrl} target=\"_blank\">\n\t * View as Markdown\n\t * <Icon svg={<FileTextIcon />} />\n\t * </a>\n\t * </SplitButton.MenuItem>\n\t * </SplitButton.MenuContent>\n\t * </SplitButton.Root>\n\t * ```\n\t */\n\tMenuContent,\n\t/**\n\t * A standard item in the split button dropdown menu that can be selected or\n\t * activated.\n\t *\n\t * @see https://mantle.ngrok.com/components/split-button#splitbuttonmenuitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <SplitButton.Root>\n\t * <SplitButton.PrimaryAction icon={<CopyIcon />} onClick={copyMarkdownPage}>\n\t * Copy page\n\t * </SplitButton.PrimaryAction>\n\t * <SplitButton.MenuTrigger label=\"Open doc actions menu\" />\n\t * <SplitButton.MenuContent>\n\t * <SplitButton.MenuItem onClick={copyMarkdownPage}>\n\t * Copy page\n\t * <Icon svg={<CopyIcon />} />\n\t * </SplitButton.MenuItem>\n\t * <SplitButton.MenuItem asChild onClick={copyMarkdownPage}>\n\t * <a href={markdownUrl} target=\"_blank\">\n\t * View as Markdown\n\t * <Icon svg={<FileTextIcon />} />\n\t * </a>\n\t * </SplitButton.MenuItem>\n\t * </SplitButton.MenuContent>\n\t * </SplitButton.Root>\n\t * ```\n\t */\n\tMenuItem,\n} as const;\n\nexport { SplitButton };\n"],"mappings":"yVAUA,MAAM,EAAO,GACX,CAAE,YAAW,WAAU,MAAK,OAAM,cAAa,eAAc,QAAO,GAAG,GAAS,IAE/E,EAAC,EAAa,KAAd,CACM,MACC,OACO,cACC,eACP,iBAEP,EAAC,MAAD,CACC,YAAU,eACV,UAAW,EACV,sQACA,CACD,EACK,MACL,GAAI,EAEH,UACG,CAAA,CACa,CAAA,CAGtB,EACA,EAAK,YAAc,cAKnB,MAAM,EAAgB,GACpB,CAAE,OAAO,SAAU,GAAG,GAAS,IACxB,EAAC,EAAD,CAAQ,WAAW,WAAW,SAAS,UAAe,MAAW,OAAM,GAAI,CAAQ,CAAA,CAE5F,EACA,EAAc,YAAc,2BAU5B,MAAM,EAAc,GAClB,CAAE,OAAM,OAAO,SAAU,GAAG,GAAS,IAEpC,EAAC,EAAa,QAAd,CAAsB,QAAA,GAAQ,UAAU,iBACvC,EAAC,EAAD,CACC,KACC,GACC,EAAC,EAAD,CACC,IACC,EAAC,EAAD,CACC,OAAO,OACP,UAAU,uFACV,CAAA,CAEF,CAAA,EAGH,WAAW,WACN,MACC,OACN,GAAI,CACJ,CAAA,CACoB,CAAA,CAGzB,EACA,EAAY,YAAc,yBAE1B,MAAM,EAAc,GAGjB,CAAE,QAAQ,MAAO,GAAG,GAAS,IACxB,EAAC,EAAa,QAAd,CAA6B,QAAY,MAAK,GAAI,CAAQ,CAAA,CACjE,EACD,EAAY,YAAc,yBAE1B,MAAM,EAAW,GAGd,CAAE,YAAW,GAAG,GAAS,IACpB,EAAC,EAAa,KAAd,CAAmB,UAAW,EAAG,QAAS,CAAS,EAAQ,MAAK,GAAI,CAAQ,CAAA,CACnF,EACD,EAAS,YAAc,sBAyCvB,MAAM,EAAc,CA8BnB,OA4BA,gBA4BA,cA6BA,cA6BA,UACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"svg-only-Cz1cby8y.js","names":[],"sources":["../src/components/icon/svg-only.tsx"],"sourcesContent":["import type { ComponentRef, ReactNode } from \"react\";\nimport { Children, cloneElement, forwardRef, isValidElement } from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { SvgAttributes } from \"./types.js\";\n\ntype SvgOnlyProps = Omit<SvgAttributes, \"children\"> & {\n\t/**\n\t * A single SVG icon element.\n\t */\n\tsvg: ReactNode;\n};\n\n/**\n * Accepts a single SVG icon element and decorates it with `shrink-0` class.\n * You probably want to use the `Icon` component instead.\n *\n * @see https://mantle.ngrok.com/components/icon\n *\n * @example\n * ```tsx\n * import { ShrimpIcon } from \"@phosphor-icons/react/Shrimp\";\n *\n * <SvgOnly svg={<ShrimpIcon />} />\n * ```\n */\nconst SvgOnly = forwardRef<ComponentRef<\"svg\">, SvgOnlyProps>(\n\t({ className, style, svg, ...props }, ref) => {\n\t\tinvariant(\n\t\t\tisValidElement<SvgAttributes>(svg) && Children.only(svg),\n\t\t\t\"SvgOnly must be passed a single SVG icon as a JSX tag.\",\n\t\t);\n\n\t\treturn cloneElement(svg, {\n\t\t\t\"data-slot\": \"svg-only\",\n\t\t\t...props,\n\t\t\tclassName: cx(\n\t\t\t\t\"shrink-0\", // the SvgOnly base classes\n\t\t\t\tclassName, // the SvgOnly className\n\t\t\t\tsvg.props.className, // the svg className\n\t\t\t),\n\t\t\tstyle: { ...style, ...svg.props.style },\n\t\t\tref,\n\t\t});\n\t},\n);\nSvgOnly.displayName = \"SvgOnly\";\n\nexport {\n\t//,\n\tSvgOnly,\n};\n\nexport type {\n\t//,\n\tSvgOnlyProps,\n};\n"],"mappings":"0JA0BA,MAAM,EAAU,GACd,CAAE,YAAW,QAAO,MAAK,GAAG,GAAS,KACrC,EACC,EAA8B,CAAG,GAAK,EAAS,KAAK,CAAG,EACvD,wDACD,EAEO,EAAa,EAAK,CACxB,YAAa,WACb,GAAG,EACH,UAAW,EACV,WACA,EACA,EAAI,MAAM,SACX,EACA,MAAO,CAAE,GAAG,EAAO,GAAG,EAAI,MAAM,KAAM,EACtC,KACD,CAAC,EAEH,EACA,EAAQ,YAAc"}
|
package/dist/switch.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"switch.js","names":["SwitchPrimitiveRoot","SwitchPrimitiveThumb","clsx"],"sources":["../src/components/switch/switch.tsx"],"sourcesContent":["import { Root as SwitchPrimitiveRoot, Thumb as SwitchPrimitiveThumb } from \"@radix-ui/react-switch\";\nimport clsx from \"clsx\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { parseBooleanish } from \"../../types/booleanish.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { parseValidation, useFieldValidation } from \"../field/validation.js\";\nimport type { WithValidation } from \"../field/validation.js\";\n\ntype SwitchProps = ComponentPropsWithoutRef<typeof SwitchPrimitiveRoot> &\n\tWithValidation & {\n\t\t/**\n\t\t * Makes the switch immutable, meaning the user can not edit the control.\n\t\t */\n\t\treadOnly?: boolean;\n\t};\n\n/**\n * A form control that allows the user to toggle between checked and not checked.\n *\n * @see https://mantle.ngrok.com/components/switch\n *\n * @example\n * ```tsx\n * <form>\n * <Label htmlFor=\"airplane-mode\" className=\"flex items-center gap-2\">\n * Airplane Mode\n * <Switch name=\"airplane-mode\" id=\"airplane-mode\" />\n * </Label>\n * </form>\n * ```\n */\nconst Switch = forwardRef<ComponentRef<typeof SwitchPrimitiveRoot>, SwitchProps>(\n\t(\n\t\t{\n\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\t\"aria-readonly\": _ariaReadOnly,\n\t\t\tclassName,\n\t\t\treadOnly: _readOnly,\n\t\t\tonClick,\n\t\t\tvalidation: _validation,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst readOnly = parseBooleanish(_readOnly ?? _ariaReadOnly);\n\t\tconst fieldValidation = useFieldValidation();\n\t\tconst { ariaInvalid, validation } = parseValidation({\n\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\tvalidation: _validation ?? fieldValidation,\n\t\t});\n\n\t\treturn (\n\t\t\t<SwitchPrimitiveRoot\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\taria-readonly={readOnly}\n\t\t\t\tdata-slot=\"switch\"\n\t\t\t\tdata-validation={validation || undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full outline-hidden\",\n\t\t\t\t\t\"disabled:cursor-default disabled:opacity-50\",\n\t\t\t\t\t\"focus-visible:border-accent-600 focus-visible:ring-focus-accent focus-visible:outline-hidden focus-visible:ring-4\",\n\t\t\t\t\t\"data-state-checked:bg-accent-600 data-state-unchecked:bg-gray-400\",\n\t\t\t\t\t\"data-validation-success:data-state-checked:bg-success-600 focus-visible:data-validation-success:ring-focus-success\",\n\t\t\t\t\t\"data-validation-warning:data-state-checked:bg-warning-600 focus-visible:data-validation-warning:ring-focus-warning\",\n\t\t\t\t\t\"data-validation-error:data-state-checked:bg-danger-600 focus-visible:data-validation-error:ring-focus-danger\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\tif (readOnly) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t}}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<SwitchPrimitiveThumb\n\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\"pointer-events-none block size-4 rounded-full bg-[#fff] shadow-md ring-0 transition-transform\",\n\t\t\t\t\t\t\"data-state-checked:translate-x-4.5 data-state-unchecked:translate-x-0.5\",\n\t\t\t\t\t)}\n\t\t\t\t/>\n\t\t\t</SwitchPrimitiveRoot>\n\t\t);\n\t},\n);\nSwitch.displayName = \"Switch\";\n\nexport {\n\t//\n\tSwitch,\n};\n"],"mappings":"oRAgCA,MAAM,EAAS,GAEb,CACC,eAAgB,EAChB,gBAAiB,EACjB,YACA,SAAU,EACV,UACA,WAAY,EACZ,GAAG,GAEJ,IACI,CACJ,IAAM,EAAW,EAAgB,GAAa,CAAa,EACrD,EAAkB,EAAmB,EACrC,CAAE,cAAa,cAAe,EAAgB,CACnD,eAAgB,EAChB,WAAY,GAAe,CAC5B,CAAC,EAED,OACC,EAACA,EAAD,CACC,eAAc,EACd,gBAAe,EACf,YAAU,SACV,kBAAiB,GAAc,IAAA,GAC/B,UAAW,EACV,4FACA,8CACA,oHACA,oEACA,qHACA,qHACA,+GACA,CACD,EACA,QAAU,GAAU,CACnB,GAAI,EAAU,CACb,EAAM,eAAe,EACrB,EAAM,gBAAgB,EACtB,MACD,CACA,IAAU,CAAK,CAChB,EACK,MACL,GAAI,WAEJ,EAACC,EAAD,CACC,UAAWC,EACV,gGACA,yEACD,CACA,CAAA,CACmB,CAAA,CAEvB,CACD,EACA,EAAO,YAAc"}
|
package/dist/table-eyoUW2Uv.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./cx-CBSnSC36.js";import{t}from"./compose-refs-Cjf2gfB8.js";import{forwardRef as n,useLayoutEffect as r,useMemo as i,useRef as a,useState as o}from"react";import{jsx as s}from"react/jsx-runtime";const c=n(({children:n,className:r,...i},a)=>{let o=v();return s(`div`,{"data-slot":`table`,className:e(`group/table relative w-full overflow-hidden rounded-lg border border-card bg-white dark:bg-gray-100`,r),"data-sticky-active":o.state.hasOverflow&&!o.state.scrolledToEnd||void 0,"data-x-overflow":o.state.hasOverflow,"data-x-scroll-end":o.state.hasOverflow&&o.state.scrolledToEnd,...i,children:s(`div`,{className:e(`scrollbar scroll-fade-x overflow-x-auto overflow-y-clip overscroll-x-none`,`has-data-mantle-table-sticky-right:[--_fade-right:black]`),"data-scroll-left":o.state.hasOverflow&&!o.state.scrolledToStart||void 0,"data-scroll-right":o.state.hasOverflow&&!o.state.scrolledToEnd||void 0,ref:t(o.ref,a),children:n})})});c.displayName=`TableRoot`;const l=n(({children:t,className:n,...r},i)=>s(`table`,{"data-slot":`table-element`,ref:i,className:e(`table-auto border-separate border-spacing-0 caption-bottom w-full min-w-full text-left`,n),...r,children:t}));l.displayName=`TableElement`;const u=n(({children:t,className:n,...r},i)=>s(`thead`,{"data-slot":`table-head`,ref:i,className:e(`[&>tr:last-child>*]:border-b [&>tr:last-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-muted bg-base`,`[&>tr]:bg-base`,n),...r,children:t}));u.displayName=`TableHead`;const d=n(({children:t,className:n,...r},i)=>s(`tbody`,{"data-slot":`table-body`,className:e(`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`text-body`,`[&>tr]:bg-card [&>tr]:not-only:hover:bg-card-hover`,n),ref:i,...r,children:t}));d.displayName=`TableBody`;const f=n(({children:t,className:n,...r},i)=>s(`tfoot`,{"data-slot":`table-foot`,ref:i,className:e(`font-medium text-body`,`[&>tr:first-child>*]:border-t [&>tr:first-child>*]:border-card-muted`,`[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted`,`[&>tr]:bg-gray-50/50 [&>tr]:hover:bg-card-hover`,n),...r,children:t}));f.displayName=`TableFoot`;const p=n(({children:t,className:n,...r},i)=>s(`tr`,{"data-slot":`table-row`,ref:i,className:e(n),...r,children:t}));p.displayName=`TableRow`;const m=n(({children:t,className:n,...r},i)=>s(`th`,{"data-slot":`table-header`,ref:i,className:e(`h-11 px-4 text-left align-middle text-sm font-medium [&:has([role=checkbox])]:pr-0`,n),...r,children:t}));m.displayName=`TableHeader`;const h=n(({children:t,className:n,...r},i)=>s(`td`,{"data-slot":`table-cell`,ref:i,className:e(`p-3 align-middle [&:has([role=checkbox])]:pr-0 font-mono text-mono`,n),...r,children:t}));h.displayName=`TableCell`;const g=n(({children:t,className:n,...r},i)=>s(`caption`,{"data-slot":`table-caption`,ref:i,className:e(`py-4 text-sm text-gray-500`,`border-t border-card-muted`,n),...r,children:t}));g.displayName=`TableCaption`;const _={Body:d,Caption:g,Cell:h,Element:l,Foot:f,Head:u,Header:m,Root:c,Row:p};function v(){let e=a(null),[t,n]=o({hasOverflow:!1,scrolledToStart:!0,scrolledToEnd:!1});return r(()=>{let t=e.current;if(!t)return;let r=0,i=()=>{let e=t.scrollWidth>t.clientWidth,r=t.scrollLeft<1,i=Math.abs(t.scrollWidth-t.scrollLeft-t.clientWidth)<1;n(t=>t.hasOverflow!==e||t.scrolledToStart!==r||t.scrolledToEnd!==i?{hasOverflow:e,scrolledToStart:r,scrolledToEnd:i}:t)},a=()=>{r===0&&(r=requestAnimationFrame(()=>{r=0,i()}))},o=new ResizeObserver(a);o.observe(t);let s=new MutationObserver(a);return s.observe(t,{childList:!0,subtree:!0}),t.addEventListener(`scroll`,a,{passive:!0}),i(),()=>{cancelAnimationFrame(r),o.disconnect(),s.disconnect(),t.removeEventListener(`scroll`,a)}},[]),i(()=>({ref:e,state:t}),[t])}export{_ as t};
|
|
2
|
-
//# sourceMappingURL=table-eyoUW2Uv.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"table-eyoUW2Uv.js","names":[],"sources":["../src/components/table/table.tsx"],"sourcesContent":["import type { ComponentProps, ComponentRef } from \"react\";\nimport { forwardRef, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * The `<Table.Root>` is the root container element for all `Table`s.\n * It provides styling and additional functionality, such as horizontal overflow\n * detection.\n *\n * Must be used as the parent of a `<Table.Element>`.\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tableroot\n */\nconst Root = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\">>(\n\t({ children, className, ...props }, ref) => {\n\t\tconst horizontalOverflow = useHorizontalOverflowObserver<ComponentRef<\"div\">>();\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tdata-slot=\"table\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"group/table relative w-full overflow-hidden rounded-lg border border-card bg-white dark:bg-gray-100\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-sticky-active={\n\t\t\t\t\t(horizontalOverflow.state.hasOverflow && !horizontalOverflow.state.scrolledToEnd) ||\n\t\t\t\t\tundefined\n\t\t\t\t}\n\t\t\t\tdata-x-overflow={horizontalOverflow.state.hasOverflow}\n\t\t\t\tdata-x-scroll-end={\n\t\t\t\t\thorizontalOverflow.state.hasOverflow && horizontalOverflow.state.scrolledToEnd\n\t\t\t\t}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"scrollbar scroll-fade-x overflow-x-auto overflow-y-clip overscroll-x-none\",\n\t\t\t\t\t\t// When the table contains a sticky right column (e.g., DataTable.ActionCell\n\t\t\t\t\t\t// / DataTable.ActionHeader), suppress the container's right-side fade so the\n\t\t\t\t\t\t// pinned column stays fully opaque. The pinned column provides its own\n\t\t\t\t\t\t// left-side gradient for the scroll-under effect.\n\t\t\t\t\t\t\"has-data-mantle-table-sticky-right:[--_fade-right:black]\",\n\t\t\t\t\t)}\n\t\t\t\t\tdata-scroll-left={\n\t\t\t\t\t\t(horizontalOverflow.state.hasOverflow && !horizontalOverflow.state.scrolledToStart) ||\n\t\t\t\t\t\tundefined\n\t\t\t\t\t}\n\t\t\t\t\tdata-scroll-right={\n\t\t\t\t\t\t(horizontalOverflow.state.hasOverflow && !horizontalOverflow.state.scrolledToEnd) ||\n\t\t\t\t\t\tundefined\n\t\t\t\t\t}\n\t\t\t\t\tref={composeRefs(horizontalOverflow.ref, ref)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t},\n);\nRoot.displayName = \"TableRoot\";\n\n/**\n * The `<Table.Element>` is a structured way to display data in rows and columns. The API\n * matches the HTML `<table>` element 1:1.\n *\n * Permitted content in this order:\n * 1. optional: `<Table.Caption>`\n * 2. 0 or more: `<colgroup>` elements\n * 3. optional: `<Table.Head>`\n * 4. either one of the following:\n * - 0 or more: `<Table.Body>`\n * - 0 or more: `<Table.Row>`\n * 5. optional: `<Table.Foot>`\n *\n * @description\n * Establishes a table formatting context. Elements inside the `<Table.Element>`\n * generate rectangular boxes. Each box occupies a number of table cells\n * according to the following rules:\n * 1. The row boxes fill the table in the source code order from top to bottom.\n * Each row box occupies one row of cells.\n * 2. A row group box occupies one or more row boxes.\n * 3. Column boxes are placed next to each other in source code order.\n * Depending on the value of the dir attribute, the columns are laid in\n * left-to-right or right-to-left direction. A column box occupies one or\n * more columns of table cells.\n * 4. A column group box occupies one or more column boxes.\n * 5. A cell box may span over multiple rows and columns. User agents trim\n * cells to fit in the available number of rows and columns.\n * Table cells do have padding. Boxes that make up a table do not have margins.\n * For more in depth information, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table).\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tableelement\n */\nconst Element = forwardRef<ComponentRef<\"table\">, ComponentProps<\"table\">>(\n\t({ children, className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<table\n\t\t\t\tdata-slot=\"table-element\"\n\t\t\t\tref={ref}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"table-auto border-separate border-spacing-0 caption-bottom w-full min-w-full text-left\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</table>\n\t\t);\n\t},\n);\nElement.displayName = \"TableElement\";\n\n/**\n * The `<Table.Head>` is a container for the table's column headers.\n * Encapsulates a set of `<Table.Row>`s, indicating that they comprise the head\n * of a table with information about the table's columns. This is usually in the\n * form of column headers (`<Table.Header>`).\n *\n * Must be used as a child of a `<Table.Element>`. It should only come after any\n * `<Table.Caption>` or `<colgroup>` and before any `<Table.Body>` or `<Table.Foot>`.\n *\n * Permitted Content:\n * 1. 0 or more: `<Table.Row>`\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tableheader\n */\nconst Head = forwardRef<ComponentRef<\"thead\">, ComponentProps<\"thead\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<thead\n\t\t\tdata-slot=\"table-head\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\n\t\t\t\t//,\n\t\t\t\t// In border-separate, <tr>/<thead> borders don't render, so apply\n\t\t\t\t// dividers directly to cells.\n\t\t\t\t\"[&>tr:last-child>*]:border-b [&>tr:last-child>*]:border-card-muted\",\n\t\t\t\t\"[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted\",\n\t\t\t\t\"text-muted bg-base\",\n\t\t\t\t\"[&>tr]:bg-base\", // Row styling\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</thead>\n\t),\n);\nHead.displayName = \"TableHead\";\n\n/**\n * The `<Table.Body>` encapsulates a set of `<Table.Row>`s, indicating that they\n * comprise the body of a table's (main) data.\n *\n * Must be used as a child of a `<Table.Element>` and only come after any\n * `<Table.Caption>`, `<colgroup>`, or `<Table.Head>`.\n *\n * Permitted Content:\n * 1. 0 or more: `<Table.Row>`\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tablebody\n */\nconst Body = forwardRef<ComponentRef<\"tbody\">, ComponentProps<\"tbody\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<tbody\n\t\t\tdata-slot=\"table-body\"\n\t\t\tclassName={cx(\n\t\t\t\t//,\n\t\t\t\t// In border-separate, <tr>/<tbody> borders don't render, so apply\n\t\t\t\t// dividers directly to cells.\n\t\t\t\t\"[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted\",\n\t\t\t\t\"text-body\",\n\t\t\t\t\"[&>tr]:bg-card [&>tr]:not-only:hover:bg-card-hover\", // Body row styling\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{children}\n\t\t</tbody>\n\t),\n);\nBody.displayName = \"TableBody\";\n\n/**\n * The `<Table.Foot>` encapsulates a set of `<Table.Row>`s, indicating that they\n * comprise the foot of a table with information about the table's columns. This\n * is usually a summary of the columns, e.g., a sum of the given numbers in a\n * column.\n *\n * Must be used as a child of a `<Table.Element>` and only come after any\n * `<Table.Caption>`, `<colgroup>`, `<Table.Head>`, and `<Table.Body>`.\n *\n * Permitted Content:\n * 1. 0 or more: `<Table.Row>` elements\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tablefoot\n */\nconst Foot = forwardRef<ComponentRef<\"tfoot\">, ComponentProps<\"tfoot\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<tfoot\n\t\t\tdata-slot=\"table-foot\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\n\t\t\t\t//,\n\t\t\t\t\"font-medium text-body\",\n\t\t\t\t// In border-separate, <tr>/<tfoot> borders don't render, so apply\n\t\t\t\t// dividers directly to cells.\n\t\t\t\t\"[&>tr:first-child>*]:border-t [&>tr:first-child>*]:border-card-muted\",\n\t\t\t\t\"[&>tr+tr>*]:border-t [&>tr+tr>*]:border-card-muted\",\n\t\t\t\t\"[&>tr]:bg-gray-50/50 [&>tr]:hover:bg-card-hover\", // Row styling\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</tfoot>\n\t),\n);\nFoot.displayName = \"TableFoot\";\n\n/**\n * The `<Table.Row>` defines a row of cells in a table. The row's cells can then\n * be established using a mix of `<Table.Cell>` and `<Table.Header>` components.\n *\n * Must be used as a child of a `<Table.Head>`, `<Table.Body>`, or `<Table.Foot>`.\n *\n * Permitted Content:\n * 1. 0 or more: `<Table.Header>` or `<Table.Cell>`\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tablerow\n */\nconst Row = forwardRef<ComponentRef<\"tr\">, ComponentProps<\"tr\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<tr\n\t\t\tdata-slot=\"table-row\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\n\t\t\t\t// This could be removed, or simplified\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</tr>\n\t),\n);\nRow.displayName = \"TableRow\";\n\n/**\n * The `<Table.Header>` defines a cell as the header of a group of table cells\n * and may be used as a child of a `<Table.Row>`. The exact nature of this group\n * is defined by the scope and headers attributes.\n *\n * Must be used as a child of a `<Table.Row>`.\n *\n * Permitted Content:\n * 1. Flow content, but with no header, footer, sectioning content, or heading\n * content descendants.\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tableheader\n */\nconst Header = forwardRef<ComponentRef<\"th\">, ComponentProps<\"th\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<th\n\t\t\tdata-slot=\"table-header\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\n\t\t\t\t\"h-11 px-4 text-left align-middle text-sm font-medium [&:has([role=checkbox])]:pr-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</th>\n\t),\n);\nHeader.displayName = \"TableHeader\";\n\n/**\n * The `<Table.Cell>` defines a cell of a table that contains data and may be\n * used as a child of a `<Table.Row>`.\n *\n * Must be used as a child of a `<Table.Row>`.\n *\n * Permitted Content:\n * 1. Flow content\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tablecell\n */\nconst Cell = forwardRef<ComponentRef<\"td\">, ComponentProps<\"td\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<td\n\t\t\tdata-slot=\"table-cell\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\n\t\t\t\t\"p-3 align-middle [&:has([role=checkbox])]:pr-0 font-mono text-mono\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</td>\n\t),\n);\nCell.displayName = \"TableCell\";\n\n/**\n * The optional `<Table.Caption>` specifies the caption (or title) of a table,\n * providing the table an accessible description.\n *\n * If used, must be the first child of a `<Table.Element>`.\n *\n * Permitted Content:\n * 1. Flow content\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n *\n * @see https://mantle.ngrok.com/components/table#tablecaption\n */\nconst Caption = forwardRef<ComponentRef<\"caption\">, ComponentProps<\"caption\">>(\n\t({ children, className, ...props }, ref) => (\n\t\t<caption\n\t\t\tdata-slot=\"table-caption\"\n\t\t\tref={ref}\n\t\t\tclassName={cx(\"py-4 text-sm text-gray-500\", \"border-t border-card-muted\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</caption>\n\t),\n);\nCaption.displayName = \"TableCaption\";\n\n/**\n * Use `Table` for STATIC, layout-driven tabular data — read-only data dumps,\n * simple key/value displays, plain markup tables. The API matches the HTML\n * `<table>` element 1:1, with no built-in sorting, filtering, or pagination.\n *\n * For INTERACTIVE tabular data with sorting / filtering / pagination / row\n * selection, use `DataTable` (built on TanStack Table) instead.\n *\n * @see https://mantle.ngrok.com/components/table\n *\n * @example\n * Composition:\n * ```\n * Table.Root\n * └── Table.Element\n * ├── Table.Caption\n * ├── Table.Head\n * │ └── Table.Row\n * │ └── Table.Header\n * ├── Table.Body\n * │ └── Table.Row\n * │ └── Table.Cell\n * └── Table.Foot\n * ```\n *\n * @example\n * ```tsx\n * <Table.Root>\n * <Table.Element>\n * <Table.Caption>A list of your recent invoices.</Table.Caption>\n * <Table.Head>\n * <Table.Row>\n * <Table.Header className=\"w-25\">Invoice</Table.Header>\n * <Table.Header>Status</Table.Header>\n * <Table.Header>Method</Table.Header>\n * <Table.Header className=\"text-right\">Amount</Table.Header>\n * </Table.Row>\n * </Table.Head>\n * <Table.Body>\n * {invoices.map((invoice) => (\n * <Table.Row key={invoice.invoice}>\n * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n * </Table.Row>\n * ))}\n * </Table.Body>\n * <Table.Foot>\n * <Table.Row>\n * <Table.Cell colSpan={3}>Total</Table.Cell>\n * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n * </Table.Row>\n * </Table.Foot>\n * </Table.Element>\n * </Table.Root>\n * ```\n */\nconst Table = {\n\t/**\n\t * The body section of the table. Encapsulates a set of table rows comprising the body of a table's main data.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tablebody\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tBody,\n\t/**\n\t * An optional caption that specifies the caption (or title) of a table, providing an accessible description.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tablecaption\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tCaption,\n\t/**\n\t * A cell that contains data and may be used as a child of a table row.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tablecell\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tCell,\n\t/**\n\t * A structured way to display data in rows and columns. The API matches the HTML table element 1:1.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tableelement\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tElement,\n\t/**\n\t * The foot section of a table. Encapsulates a set of table rows comprising the foot with summary information.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tablefoot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tFoot,\n\t/**\n\t * The head section of a table. Contains the table's column headers information.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tableheader\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tHead,\n\t/**\n\t * A cell that defines the header of a group of table cells as a child of a table row.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tableheader\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tHeader,\n\t/**\n\t * The root container element for all tables. Provides styling and additional functionality like horizontal overflow detection.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tableroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * Defines a row of cells in a table. Contains a mix of table cells and table headers.\n\t *\n\t * @see https://mantle.ngrok.com/components/table#tablerow\n\t *\n\t * @example\n\t * ```tsx\n\t * <Table.Root>\n\t * <Table.Element>\n\t * <Table.Caption>A list of your recent invoices.</Table.Caption>\n\t * <Table.Head>\n\t * <Table.Row>\n\t * <Table.Header className=\"w-25\">Invoice</Table.Header>\n\t * <Table.Header>Status</Table.Header>\n\t * <Table.Header>Method</Table.Header>\n\t * <Table.Header className=\"text-right\">Amount</Table.Header>\n\t * </Table.Row>\n\t * </Table.Head>\n\t * <Table.Body>\n\t * {invoices.map((invoice) => (\n\t * <Table.Row key={invoice.invoice}>\n\t * <Table.Cell className=\"font-medium\">{invoice.invoice}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentStatus}</Table.Cell>\n\t * <Table.Cell>{invoice.paymentMethod}</Table.Cell>\n\t * <Table.Cell className=\"text-right\">{invoice.totalAmount}</Table.Cell>\n\t * </Table.Row>\n\t * ))}\n\t * </Table.Body>\n\t * <Table.Foot>\n\t * <Table.Row>\n\t * <Table.Cell colSpan={3}>Total</Table.Cell>\n\t * <Table.Cell className=\"text-right\">$2,500.00</Table.Cell>\n\t * </Table.Row>\n\t * </Table.Foot>\n\t * </Table.Element>\n\t * </Table.Root>\n\t * ```\n\t */\n\tRow,\n} as const;\n\nexport {\n\t//,\n\tTable,\n};\n\n/**\n * A custom hook that observes the horizontal overflow of an element and determines\n * if it has overflow and if it is scrolled to the end.\n *\n * @private\n */\nfunction useHorizontalOverflowObserver<T extends HTMLElement>() {\n\tconst ref = useRef<T | null>(null);\n\tconst [state, setState] = useState({\n\t\thasOverflow: false,\n\t\tscrolledToStart: true,\n\t\tscrolledToEnd: false,\n\t});\n\n\tuseLayoutEffect(() => {\n\t\tconst element = ref.current;\n\t\tif (!element) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet frameId = 0;\n\n\t\tconst checkState = () => {\n\t\t\tconst hasOverflow = element.scrollWidth > element.clientWidth;\n\t\t\tconst scrolledToStart = element.scrollLeft < 1;\n\t\t\tconst scrolledToEnd =\n\t\t\t\tMath.abs(element.scrollWidth - element.scrollLeft - element.clientWidth) < 1;\n\n\t\t\tsetState((previous) => {\n\t\t\t\tif (\n\t\t\t\t\tprevious.hasOverflow !== hasOverflow ||\n\t\t\t\t\tprevious.scrolledToStart !== scrolledToStart ||\n\t\t\t\t\tprevious.scrolledToEnd !== scrolledToEnd\n\t\t\t\t) {\n\t\t\t\t\treturn { hasOverflow, scrolledToStart, scrolledToEnd };\n\t\t\t\t}\n\t\t\t\treturn previous; // No state change\n\t\t\t});\n\t\t};\n\n\t\t// Coalesce rapid-fire events (scroll, mutation, resize) into a single\n\t\t// layout read per animation frame to avoid redundant work.\n\t\tconst scheduleCheck = () => {\n\t\t\tif (frameId === 0) {\n\t\t\t\tframeId = requestAnimationFrame(() => {\n\t\t\t\t\tframeId = 0;\n\t\t\t\t\tcheckState();\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tconst resizeObserver = new ResizeObserver(scheduleCheck);\n\t\tresizeObserver.observe(element);\n\n\t\tconst mutationObserver = new MutationObserver(scheduleCheck);\n\t\tmutationObserver.observe(element, { childList: true, subtree: true });\n\n\t\telement.addEventListener(\"scroll\", scheduleCheck, { passive: true });\n\n\t\tcheckState();\n\n\t\treturn () => {\n\t\t\tcancelAnimationFrame(frameId);\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t\telement.removeEventListener(\"scroll\", scheduleCheck);\n\t\t};\n\t}, []);\n\n\treturn useMemo(() => ({ ref, state }), [state]);\n}\n"],"mappings":"sNA+CA,MAAM,EAAO,GACX,CAAE,WAAU,YAAW,GAAG,GAAS,IAAQ,CAC3C,IAAM,EAAqB,EAAmD,EAE9E,OACC,EAAC,MAAD,CACC,YAAU,QACV,UAAW,EACV,sGACA,CACD,EACA,qBACE,EAAmB,MAAM,aAAe,CAAC,EAAmB,MAAM,eACnE,IAAA,GAED,kBAAiB,EAAmB,MAAM,YAC1C,oBACC,EAAmB,MAAM,aAAe,EAAmB,MAAM,cAElE,GAAI,WAEJ,EAAC,MAAD,CACC,UAAW,EACV,4EAKA,0DACD,EACA,mBACE,EAAmB,MAAM,aAAe,CAAC,EAAmB,MAAM,iBACnE,IAAA,GAED,oBACE,EAAmB,MAAM,aAAe,CAAC,EAAmB,MAAM,eACnE,IAAA,GAED,IAAK,EAAY,EAAmB,IAAK,CAAG,EAE3C,UACG,CAAA,CACD,CAAA,CAEP,CACD,EACA,EAAK,YAAc,YAmEnB,MAAM,EAAU,GACd,CAAE,WAAU,YAAW,GAAG,GAAS,IAElC,EAAC,QAAD,CACC,YAAU,gBACL,MACL,UAAW,EACV,yFACA,CACD,EACA,GAAI,EAEH,UACK,CAAA,CAGV,EACA,EAAQ,YAAc,eAiDtB,MAAM,EAAO,GACX,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,QAAD,CACC,YAAU,aACL,MACL,UAAW,EAIV,qEACA,qDACA,qBACA,iBACA,CACD,EACA,GAAI,EAEH,UACK,CAAA,CAET,EACA,EAAK,YAAc,YA+CnB,MAAM,EAAO,GACX,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,QAAD,CACC,YAAU,aACV,UAAW,EAIV,qDACA,YACA,qDACA,CACD,EACK,MACL,GAAI,EAEH,UACK,CAAA,CAET,EACA,EAAK,YAAc,YAiDnB,MAAM,EAAO,GACX,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,QAAD,CACC,YAAU,aACL,MACL,UAAW,EAEV,wBAGA,uEACA,qDACA,kDACA,CACD,EACA,GAAI,EAEH,UACK,CAAA,CAET,EACA,EAAK,YAAc,YA8CnB,MAAM,EAAM,GACV,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,KAAD,CACC,YAAU,YACL,MACL,UAAW,EAEV,CACD,EACA,GAAI,EAEH,UACE,CAAA,CAEN,EACA,EAAI,YAAc,WAgDlB,MAAM,EAAS,GACb,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,KAAD,CACC,YAAU,eACL,MACL,UAAW,EACV,qFACA,CACD,EACA,GAAI,EAEH,UACE,CAAA,CAEN,EACA,EAAO,YAAc,cA8CrB,MAAM,EAAO,GACX,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,KAAD,CACC,YAAU,aACL,MACL,UAAW,EACV,qEACA,CACD,EACA,GAAI,EAEH,UACE,CAAA,CAEN,EACA,EAAK,YAAc,YA8CnB,MAAM,EAAU,GACd,CAAE,WAAU,YAAW,GAAG,GAAS,IACnC,EAAC,UAAD,CACC,YAAU,gBACL,MACL,UAAW,EAAG,6BAA8B,6BAA8B,CAAS,EACnF,GAAI,EAEH,UACO,CAAA,CAEX,EACA,EAAQ,YAAc,eA4DtB,MAAM,EAAQ,CAuCb,OAuCA,UAuCA,OAuCA,UAuCA,OAuCA,OAuCA,SAuCA,OAuCA,KACD,EAaA,SAAS,GAAuD,CAC/D,IAAM,EAAM,EAAiB,IAAI,EAC3B,CAAC,EAAO,GAAY,EAAS,CAClC,YAAa,GACb,gBAAiB,GACjB,cAAe,EAChB,CAAC,EAyDD,OAvDA,MAAsB,CACrB,IAAM,EAAU,EAAI,QACpB,GAAI,CAAC,EACJ,OAGD,IAAI,EAAU,EAER,MAAmB,CACxB,IAAM,EAAc,EAAQ,YAAc,EAAQ,YAC5C,EAAkB,EAAQ,WAAa,EACvC,EACL,KAAK,IAAI,EAAQ,YAAc,EAAQ,WAAa,EAAQ,WAAW,EAAI,EAE5E,EAAU,GAER,EAAS,cAAgB,GACzB,EAAS,kBAAoB,GAC7B,EAAS,gBAAkB,EAEpB,CAAE,cAAa,kBAAiB,eAAc,EAE/C,CACP,CACF,EAIM,MAAsB,CACvB,IAAY,IACf,EAAU,0BAA4B,CACrC,EAAU,EACV,EAAW,CACZ,CAAC,EAEH,EAEM,EAAiB,IAAI,eAAe,CAAa,EACvD,EAAe,QAAQ,CAAO,EAE9B,IAAM,EAAmB,IAAI,iBAAiB,CAAa,EAO3D,OANA,EAAiB,QAAQ,EAAS,CAAE,UAAW,GAAM,QAAS,EAAK,CAAC,EAEpE,EAAQ,iBAAiB,SAAU,EAAe,CAAE,QAAS,EAAK,CAAC,EAEnE,EAAW,MAEE,CACZ,qBAAqB,CAAO,EAC5B,EAAe,WAAW,EAC1B,EAAiB,WAAW,EAC5B,EAAQ,oBAAoB,SAAU,CAAa,CACpD,CACD,EAAG,CAAC,CAAC,EAEE,OAAe,CAAE,MAAK,OAAM,GAAI,CAAC,CAAK,CAAC,CAC/C"}
|
package/dist/tabs.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tabs.js","names":["Root","TabsPrimitiveRoot","List","TabsPrimitiveList","clsx","Trigger","TabsPrimitiveTrigger","Content","TabsPrimitiveContent"],"sources":["../src/components/tabs/tabs.tsx"],"sourcesContent":["import {\n\tContent as TabsPrimitiveContent,\n\tList as TabsPrimitiveList,\n\tRoot as TabsPrimitiveRoot,\n\tTrigger as TabsPrimitiveTrigger,\n} from \"@radix-ui/react-tabs\";\nimport { cva } from \"class-variance-authority\";\nimport clsx from \"clsx\";\nimport type { ComponentPropsWithoutRef, ComponentRef, HTMLAttributes } from \"react\";\nimport {\n\tChildren,\n\tcloneElement,\n\tcreateContext,\n\tforwardRef,\n\tisValidElement,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { parseBooleanish } from \"../../types/booleanish.js\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { getPrefersReducedMotion } from \"../../hooks/use-prefers-reduced-motion.js\";\nimport type { ScrollBehavior } from \"../../hooks/use-scroll-behavior.js\";\n\ntype Orientation = \"horizontal\" | \"vertical\";\ntype Appearance = \"classic\" | \"pill\";\n\ntype TabsStateContextValue = {\n\torientation: Orientation;\n\tappearance: Appearance;\n};\n\nconst TabsStateContext = createContext<TabsStateContextValue>({\n\torientation: \"horizontal\",\n\tappearance: \"classic\",\n});\n\n/**\n * A set of layered sections of content—known as tab panels—that are displayed one at a time.\n * The root component that provides context for all tab components.\n *\n * @see https://mantle.ngrok.com/components/tabs#tabsroot\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * <Tabs.Content value=\"account\">\n * <p>Make changes to your account here.</p>\n * </Tabs.Content>\n * <Tabs.Content value=\"password\">\n * <p>Change your password here.</p>\n * </Tabs.Content>\n * </Tabs.Root>\n * ```\n */\nconst Root = forwardRef<\n\tComponentRef<typeof TabsPrimitiveRoot>,\n\tComponentPropsWithoutRef<typeof TabsPrimitiveRoot> & {\n\t\t/**\n\t\t * The appearance of the tabs. Classic appearance shows the tab\n\t\t * list with an underline; pill appearance shows each tab as a pill.\n\t\t * @default \"classic\"\n\t\t */\n\t\tappearance?: \"classic\" | \"pill\";\n\t}\n>(({ className, children, orientation = \"horizontal\", appearance = \"classic\", ...props }, ref) => {\n\tconst contextValue = useMemo(() => ({ orientation, appearance }), [orientation, appearance]);\n\treturn (\n\t\t<TabsPrimitiveRoot\n\t\t\tdata-slot=\"tabs\"\n\t\t\tclassName={cx(\n\t\t\t\t\"flex gap-4\",\n\t\t\t\torientation === \"horizontal\" ? \"flex-col\" : \"flex-row\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\torientation={orientation}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t<TabsStateContext.Provider value={contextValue}>{children}</TabsStateContext.Provider>\n\t\t</TabsPrimitiveRoot>\n\t);\n});\nRoot.displayName = \"Tabs\";\n\n/**\n * Variants for the List component\n */\nconst listVariants = cva(\"flex\", {\n\tvariants: {\n\t\torientation: {\n\t\t\thorizontal:\n\t\t\t\t\"scroll-fade-x flex-row items-center overflow-x-auto overscroll-x-none w-full min-w-0 pt-1 -mt-1 px-1 -mx-1\",\n\t\t\tvertical: \"flex-col items-end gap-3.5 self-stretch\",\n\t\t} as const satisfies Record<Orientation, string>,\n\t\tappearance: {\n\t\t\tclassic: \"\",\n\t\t\tpill: \"\",\n\t\t} as const satisfies Record<Appearance, string>,\n\t},\n\tcompoundVariants: [\n\t\t{\n\t\t\torientation: \"horizontal\",\n\t\t\tappearance: \"pill\",\n\t\t\t// pb-1 -mb-1 gives the focus ring space below (ring-4 is box-shadow, clipped by overflow).\n\t\t\tclassName: \"gap-1 pb-1 -mb-1\",\n\t\t},\n\t\t{\n\t\t\torientation: \"horizontal\",\n\t\t\tappearance: \"classic\",\n\t\t\tclassName: \"gap-6\",\n\t\t},\n\t\t{\n\t\t\torientation: \"vertical\",\n\t\t\tappearance: \"classic\",\n\t\t\tclassName: \"border-r border-gray-200\",\n\t\t},\n\t],\n});\n\n/**\n * Contains the triggers that are aligned along the edge of the active content.\n * The container for tab triggers that provides the visual layout for tab navigation.\n *\n * @see https://mantle.ngrok.com/components/tabs#tabslist\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * <Tabs.Content value=\"account\">\n * <p>Make changes to your account here.</p>\n * </Tabs.Content>\n * </Tabs.Root>\n * ```\n */\nconst List = forwardRef<\n\tComponentRef<typeof TabsPrimitiveList>,\n\tComponentPropsWithoutRef<typeof TabsPrimitiveList>\n>(({ className, ...props }, ref) => {\n\tconst { orientation, appearance } = useContext(TabsStateContext);\n\tconst scrollRef = useRef<ComponentRef<typeof TabsPrimitiveList>>(null);\n\n\tuseEffect(() => {\n\t\tconst element = scrollRef.current;\n\t\tif (!element || orientation !== \"horizontal\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tlet maxScrollLeft = 0;\n\n\t\tconst updateShadows = () => {\n\t\t\telement.toggleAttribute(\"data-scroll-left\", element.scrollLeft > 0);\n\t\t\telement.toggleAttribute(\n\t\t\t\t\"data-scroll-right\",\n\t\t\t\tMath.ceil(element.scrollLeft) < maxScrollLeft - 1,\n\t\t\t);\n\t\t};\n\n\t\tconst handleResize = () => {\n\t\t\tmaxScrollLeft = element.scrollWidth - element.clientWidth;\n\t\t\tupdateShadows();\n\t\t};\n\n\t\t// passive: true — lets the browser optimize scroll performance by guaranteeing\n\t\t// we won't call preventDefault() inside this handler.\n\t\telement.addEventListener(\"scroll\", updateShadows, {\n\t\t\tpassive: true,\n\t\t\tsignal: abortController.signal,\n\t\t});\n\n\t\t// ResizeObserver alone won't catch scrollWidth changes caused by content\n\t\t// mutations (e.g. font loading, badge count changes) when the list container\n\t\t// itself doesn't resize. MutationObserver covers those cases.\n\t\tconst mutationObserver = new MutationObserver(handleResize);\n\t\tmutationObserver.observe(element, {\n\t\t\tchildList: true,\n\t\t\tsubtree: true, // subtree catches badge/label content changes inside triggers\n\t\t});\n\n\t\t// When Radix moves focus via arrow keys it calls element.focus(), which doesn't\n\t\t// always scroll the target into view inside an overflow container. We handle it\n\t\t// explicitly here via event delegation so every trigger gets this behavior with\n\t\t// a single listener rather than one per trigger.\n\t\telement.addEventListener(\n\t\t\t\"focusin\",\n\t\t\t(event) => {\n\t\t\t\tif (event.target instanceof Element && event.target !== element) {\n\t\t\t\t\tconst scrollBehavior: ScrollBehavior = getPrefersReducedMotion() ? \"auto\" : \"smooth\";\n\t\t\t\t\tevent.target.scrollIntoView({\n\t\t\t\t\t\tbehavior: scrollBehavior,\n\t\t\t\t\t\t// \"center\" rather than \"nearest\" so the focused tab lands in the middle\n\t\t\t\t\t\t// of the visible area, giving the user context on both sides.\n\t\t\t\t\t\tinline: \"center\",\n\t\t\t\t\t\tblock: \"nearest\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ signal: abortController.signal },\n\t\t);\n\t\tconst resizeObserver = new ResizeObserver(handleResize);\n\t\tresizeObserver.observe(element);\n\t\thandleResize();\n\n\t\treturn () => {\n\t\t\tabortController.abort();\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t};\n\t}, [orientation]);\n\n\treturn (\n\t\t<TabsPrimitiveList\n\t\t\taria-orientation={orientation}\n\t\t\tdata-slot=\"tabs-list\"\n\t\t\tclassName={cx(listVariants({ orientation, appearance }), className)}\n\t\t\tref={composeRefs(scrollRef, ref)}\n\t\t\t{...props}\n\t\t/>\n\t);\n});\nList.displayName = \"TabsList\";\n\ntype TabsTriggerProps = ComponentPropsWithoutRef<typeof TabsPrimitiveTrigger>;\n\n/**\n * Variants for the TabsTriggerDecoration component\n */\nconst triggerDecorationVariants = cva(\"absolute z-0\", {\n\tvariants: {\n\t\torientation: {\n\t\t\thorizontal: \"bottom-0 left-0 right-0 h-0.75\",\n\t\t\tvertical: \"-right-px bottom-0 top-0 w-0.75\",\n\t\t} as const satisfies Record<Orientation, string>,\n\t\tappearance: {\n\t\t\tclassic: \"group-data-state-active/tab-trigger:bg-neutral-950\",\n\t\t\tpill: \"hidden\",\n\t\t} as const satisfies Record<Appearance, string>,\n\t},\n});\n\nconst TabsTriggerDecoration = () => {\n\tconst { orientation, appearance } = useContext(TabsStateContext);\n\n\treturn (\n\t\t<span aria-hidden className={clsx(triggerDecorationVariants({ orientation, appearance }))} />\n\t);\n};\nTabsTriggerDecoration.displayName = \"TabsTriggerDecoration\";\n\n/**\n * Variants for the Trigger component\n */\nconst triggerVariants = cva(\n\tcx(\n\t\t\"group/tab-trigger relative flex cursor-pointer items-center gap-1 whitespace-nowrap py-3 text-sm font-medium text-gray-600\",\n\t\t\"ring-focus-accent outline-hidden\",\n\t\t\"aria-disabled:cursor-default aria-disabled:opacity-50\",\n\t\t\"focus-visible:ring-4\",\n\t\t\"[&>svg]:shrink-0 [&>svg]:size-5\",\n\t\t\"not-aria-disabled:hover:text-gray-900\",\n\t),\n\t{\n\t\tvariants: {\n\t\t\torientation: {\n\t\t\t\thorizontal: \"rounded-tl-md rounded-tr-md\",\n\t\t\t\tvertical: \"rounded-bl-md rounded-tl-md pr-3\",\n\t\t\t} as const satisfies Record<Orientation, string>,\n\t\t\tappearance: {\n\t\t\t\tclassic: cx(\n\t\t\t\t\t\"not-aria-disabled:hover:data-state-active:text-strong\",\n\t\t\t\t\t\"data-state-active:text-strong\",\n\t\t\t\t),\n\t\t\t\tpill: cx(\n\t\t\t\t\t\"not-aria-disabled:hover:data-state-active:text-strong\",\n\t\t\t\t\t\"not-aria-disabled:hover:data-state-active:bg-neutral-500/15\",\n\t\t\t\t\t\"data-state-active:text-strong\",\n\t\t\t\t\t\"data-state-active:bg-neutral-500/15\",\n\t\t\t\t\t\"rounded-full py-2 px-3\",\n\t\t\t\t),\n\t\t\t} as const satisfies Record<Appearance, string>,\n\t\t},\n\t},\n);\n\n/**\n * The button that activates its associated content.\n * A clickable tab trigger that switches between different tab content panels.\n *\n * @see https://mantle.ngrok.com/components/tabs#tabstrigger\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * <Tabs.Content value=\"account\">\n * <p>Make changes to your account here.</p>\n * </Tabs.Content>\n * </Tabs.Root>\n * ```\n */\nconst Trigger = forwardRef<ComponentRef<typeof TabsPrimitiveTrigger>, TabsTriggerProps>(\n\t(\n\t\t{\n\t\t\t\"aria-disabled\": _ariaDisabled,\n\t\t\tasChild = false,\n\t\t\tchildren,\n\t\t\tclassName,\n\t\t\tdisabled: _disabled,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst { orientation, appearance } = useContext(TabsStateContext);\n\t\tconst disabled = parseBooleanish(_ariaDisabled ?? _disabled);\n\n\t\tconst tabsTriggerProps = {\n\t\t\t\"aria-disabled\": _ariaDisabled ?? _disabled,\n\t\t\tclassName: cx(triggerVariants({ orientation, appearance }), className),\n\t\t\tdisabled,\n\t\t\t...props,\n\t\t};\n\n\t\tif (asChild) {\n\t\t\tconst singleChild = Children.only(children);\n\t\t\tinvariant(\n\t\t\t\tisValidElement<TabsTriggerProps>(singleChild),\n\t\t\t\t\"When using `asChild`, TabsTrigger must be passed a single child as a JSX tag.\",\n\t\t\t);\n\t\t\tconst grandchildren = singleChild.props?.children;\n\n\t\t\tconst cloneProps = disabled\n\t\t\t\t? /**\n\t\t\t\t\t * When disabled, prevent anchor/link children from being clickable by\n\t\t\t\t\t * removing their href/to props!\n\t\t\t\t\t * This is necessary because `<a>` doesn't support the `disabled`\n\t\t\t\t\t * attribute and would be navigable. We could use `pointer-events-none`\n\t\t\t\t\t * instead, but don't by default because it would also prevent tooltip\n\t\t\t\t\t * interactions, which may be surprising.\n\t\t\t\t\t */\n\t\t\t\t\t{ href: undefined, to: undefined }\n\t\t\t\t: /**\n\t\t\t\t\t * when NOT disabled, allow keyboard navigation to the trigger,\n\t\t\t\t\t * even for asChild anchors/links\n\t\t\t\t\t */\n\t\t\t\t\t{ tabIndex: 0 };\n\n\t\t\treturn (\n\t\t\t\t<TabsPrimitiveTrigger asChild data-slot=\"tabs-trigger\" {...tabsTriggerProps} ref={ref}>\n\t\t\t\t\t{cloneElement(\n\t\t\t\t\t\tdisabled ? <button type=\"button\" /> : singleChild,\n\t\t\t\t\t\tcloneProps,\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<TabsTriggerDecoration />\n\t\t\t\t\t\t\t{grandchildren}\n\t\t\t\t\t\t</>,\n\t\t\t\t\t)}\n\t\t\t\t</TabsPrimitiveTrigger>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<TabsPrimitiveTrigger data-slot=\"tabs-trigger\" ref={ref} {...tabsTriggerProps}>\n\t\t\t\t<TabsTriggerDecoration />\n\t\t\t\t{children}\n\t\t\t</TabsPrimitiveTrigger>\n\t\t);\n\t},\n);\nTrigger.displayName = \"TabsTrigger\";\n\n/**\n * A badge component that can be used inside tab triggers to display additional information.\n * Typically used to show counts or status indicators within tab headers.\n *\n * @see https://mantle.ngrok.com/components/tabs#tabsbadge\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">\n * Account <Tabs.Badge>5</Tabs.Badge>\n * </Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * </Tabs.Root>\n * ```\n */\nconst Badge = ({ className, children, ...props }: HTMLAttributes<HTMLSpanElement>) => (\n\t<span\n\t\tdata-slot=\"tabs-badge\"\n\t\tclassName={cx(\n\t\t\t\"rounded-full bg-neutral-500/20 px-1.5 text-xs font-medium text-gray-600\",\n\t\t\t\"group-data-state-active/tab-trigger:bg-neutral-950/10 group-data-state-active/tab-trigger:text-strong group-hover/tab-trigger:group-enabled/tab-trigger:group-data-state-active/tab-trigger:text-strong\",\n\t\t\t\"group-hover/tab-trigger:group-enabled/tab-trigger:text-gray-700\",\n\t\t\tclassName,\n\t\t)}\n\t\t{...props}\n\t>\n\t\t{children}\n\t</span>\n);\nBadge.displayName = \"TabBadge\";\n\n/**\n * Contains the content associated with each trigger.\n * The content panel that displays when its corresponding tab trigger is active.\n *\n * @see https://mantle.ngrok.com/components/tabs#tabscontent\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * <Tabs.Content value=\"account\">\n * <p>Make changes to your account here.</p>\n * </Tabs.Content>\n * <Tabs.Content value=\"password\">\n * <p>Change your password here.</p>\n * </Tabs.Content>\n * </Tabs.Root>\n * ```\n */\nconst Content = forwardRef<\n\tComponentRef<typeof TabsPrimitiveContent>,\n\tComponentPropsWithoutRef<typeof TabsPrimitiveContent>\n>(({ className, ...props }, ref) => (\n\t<TabsPrimitiveContent\n\t\tref={ref}\n\t\tdata-slot=\"tabs-content\"\n\t\tclassName={cx(\"focus-visible:ring-focus-accent outline-hidden focus-visible:ring-4\", className)}\n\t\t{...props}\n\t/>\n));\nContent.displayName = \"TabsContent\";\n\n/**\n * A set of layered sections of content—known as tab panels—that are displayed one at a time.\n * The root component that provides context for all tab components.\n *\n * @see https://mantle.ngrok.com/components/tabs\n *\n * @example\n * Composition:\n * ```\n * Tabs.Root\n * ├── Tabs.List\n * │ └── Tabs.Trigger\n * │ └── Tabs.Badge\n * └── Tabs.Content\n * ```\n *\n * @example\n * ```tsx\n * <Tabs.Root defaultValue=\"account\">\n * <Tabs.List>\n * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n * </Tabs.List>\n * <Tabs.Content value=\"account\">\n * <p>Make changes to your account here.</p>\n * </Tabs.Content>\n * <Tabs.Content value=\"password\">\n * <p>Change your password here.</p>\n * </Tabs.Content>\n * </Tabs.Root>\n * ```\n */\nconst Tabs = {\n\t/**\n\t * The root container of the tabs component that provides context for all tab components.\n\t * A set of layered sections of content—known as tab panels—that are displayed one at a time.\n\t *\n\t * @see https://mantle.ngrok.com/components/tabs#tabsroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Tabs.Root defaultValue=\"account\">\n\t * <Tabs.List>\n\t * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n\t * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n\t * </Tabs.List>\n\t * <Tabs.Content value=\"account\">\n\t * <p>Make changes to your account here.</p>\n\t * </Tabs.Content>\n\t * </Tabs.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * Contains the content associated with each trigger.\n\t * The content panel that displays when its corresponding tab trigger is active.\n\t *\n\t * @see https://mantle.ngrok.com/components/tabs#tabscontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Tabs.Root defaultValue=\"account\">\n\t * <Tabs.List>\n\t * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n\t * </Tabs.List>\n\t * <Tabs.Content value=\"account\">\n\t * <p>Make changes to your account here.</p>\n\t * </Tabs.Content>\n\t * </Tabs.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * Contains the triggers that are aligned along the edge of the active content.\n\t * The container for tab triggers that provides the visual layout for tab navigation.\n\t *\n\t * @see https://mantle.ngrok.com/components/tabs#tabslist\n\t *\n\t * @example\n\t * ```tsx\n\t * <Tabs.Root defaultValue=\"account\">\n\t * <Tabs.List>\n\t * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n\t * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n\t * </Tabs.List>\n\t * </Tabs.Root>\n\t * ```\n\t */\n\tList,\n\t/**\n\t * The button that activates its associated content.\n\t * A clickable tab trigger that switches between different tab content panels.\n\t *\n\t * @see https://mantle.ngrok.com/components/tabs#tabstrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Tabs.Root defaultValue=\"account\">\n\t * <Tabs.List>\n\t * <Tabs.Trigger value=\"account\">Account</Tabs.Trigger>\n\t * <Tabs.Trigger value=\"password\">Password</Tabs.Trigger>\n\t * </Tabs.List>\n\t * </Tabs.Root>\n\t * ```\n\t */\n\tTrigger,\n\t/**\n\t * A badge component that can be used inside tab triggers to display additional information.\n\t * Typically used to show counts or status indicators within tab headers.\n\t *\n\t * @see https://mantle.ngrok.com/components/tabs#tabsbadge\n\t *\n\t * @example\n\t * ```tsx\n\t * <Tabs.Root defaultValue=\"account\">\n\t * <Tabs.List>\n\t * <Tabs.Trigger value=\"account\">\n\t * Account <Tabs.Badge>5</Tabs.Badge>\n\t * </Tabs.Trigger>\n\t * </Tabs.List>\n\t * </Tabs.Root>\n\t * ```\n\t */\n\tBadge,\n} as const;\n\nexport {\n\t//\n\tTabs,\n};\n"],"mappings":"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"}
|
package/dist/text-area.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"text-area.js","names":[],"sources":["../src/components/text-area/text-area.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps, ComponentRef } from \"react\";\nimport { forwardRef, useRef, useState } from \"react\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { parseValidation, useFieldValidation } from \"../field/validation.js\";\nimport type { WithValidation } from \"../field/validation.js\";\n\ntype Props = ComponentProps<\"textarea\"> &\n\tWithValidation & {\n\t\t/**\n\t\t * The visual style of the textarea.\n\t\t */\n\t\tappearance?: \"monospaced\";\n\t};\n\n/**\n * A multi-line plain-text editing control, useful when you want to allow users\n * to enter a sizeable amount of free-form text, for example a comment on a\n * review or feedback form.\n *\n * @see https://mantle.ngrok.com/components/text-area\n *\n * @example\n * ```tsx\n * <form>\n * <div>\n * <Label htmlFor=\"feedback\">Feedback:</Label>\n * <TextArea\n * id=\"feedback\"\n * name=\"feedback\"\n * placeholder=\"Enter your feedback here\"\n * />\n * </div>\n * </form>\n * ```\n */\nconst TextArea = forwardRef<ComponentRef<\"textarea\">, Props>(\n\t(\n\t\t{\n\t\t\tappearance,\n\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\tclassName,\n\t\t\tonDragEnter,\n\t\t\tonDragLeave,\n\t\t\tonDropCapture,\n\t\t\tvalidation: _validation,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst fieldValidation = useFieldValidation();\n\t\tconst { ariaInvalid, validation } = parseValidation({\n\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\tvalidation: _validation ?? fieldValidation,\n\t\t});\n\t\tconst [isDragOver, setIsDragOver] = useState(false);\n\t\tconst innerRef = useRef<ComponentRef<\"textarea\">>(null);\n\n\t\treturn (\n\t\t\t<textarea\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tdata-validation={validation || undefined}\n\t\t\t\tdata-slot=\"text-area\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\tappearance === \"monospaced\" &&\n\t\t\t\t\t\t\"pointer-coarse:text-[0.9375rem] font-mono text-[0.8125rem]\",\n\t\t\t\t\t\"border-input bg-form data-drag-over:border-dashed data-drag-over:ring-4 pointer-coarse:py-[calc(theme(spacing[2.5])-1px)] pointer-coarse:text-base flex min-h-24 w-full rounded-md border px-3 py-[calc(theme(spacing[2])-1px)] focus-visible:outline-hidden focus-visible:ring-4 disabled:pointer-events-none disabled:opacity-50\",\n\t\t\t\t\t\"placeholder:text-placeholder data-drag-over:border-dashed\",\n\t\t\t\t\t\"border-form text-strong ring-focus-accent focus:border-accent-600 data-drag-over:border-accent-600\",\n\t\t\t\t\t\"data-validation-error:border-danger-600 data-validation-error:ring-focus-danger data-validation-error:focus-visible:border-danger-600 data-validation-error:data-drag-over:border-danger-600\",\n\t\t\t\t\t\"data-validation-success:border-success-600 data-validation-success:ring-focus-success data-validation-success:focus-visible:border-success-600 data-validation-success:data-drag-over:border-success-600\",\n\t\t\t\t\t\"data-validation-warning:border-warning-600 data-validation-warning:ring-focus-warning data-validation-warning:focus-visible:border-warning-600 data-validation-warning:data-drag-over:border-warning-600\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-drag-over={isDragOver}\n\t\t\t\tonDragEnter={(event) => {\n\t\t\t\t\tsetIsDragOver(true);\n\t\t\t\t\tonDragEnter?.(event);\n\t\t\t\t}}\n\t\t\t\tonDragLeave={(event) => {\n\t\t\t\t\tsetIsDragOver(false);\n\t\t\t\t\tonDragLeave?.(event);\n\t\t\t\t}}\n\t\t\t\tonDropCapture={(event) => {\n\t\t\t\t\tsetIsDragOver(false);\n\t\t\t\t\tinnerRef.current?.focus();\n\t\t\t\t\tonDropCapture?.(event);\n\t\t\t\t}}\n\t\t\t\tref={composeRefs(innerRef, ref)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nTextArea.displayName = \"TextArea\";\n\nexport {\n\t//,\n\tTextArea,\n};\n\nexport type {\n\t//,\n\tProps as TextAreaProps,\n};\n"],"mappings":"mOAsCA,MAAM,EAAW,GAEf,CACC,aACA,eAAgB,EAChB,YACA,cACA,cACA,gBACA,WAAY,EACZ,GAAG,GAEJ,IACI,CACJ,IAAM,EAAkB,EAAmB,EACrC,CAAE,cAAa,cAAe,EAAgB,CACnD,eAAgB,EAChB,WAAY,GAAe,CAC5B,CAAC,EACK,CAAC,EAAY,GAAiB,EAAS,EAAK,EAC5C,EAAW,EAAiC,IAAI,EAEtD,OACC,EAAC,WAAD,CACC,eAAc,EACd,kBAAiB,GAAc,IAAA,GAC/B,YAAU,YACV,UAAW,EACV,IAAe,cACd,6DACD,qUACA,4DACA,qGACA,+LACA,2MACA,2MACA,CACD,EACA,iBAAgB,EAChB,YAAc,GAAU,CACvB,EAAc,EAAI,EAClB,IAAc,CAAK,CACpB,EACA,YAAc,GAAU,CACvB,EAAc,EAAK,EACnB,IAAc,CAAK,CACpB,EACA,cAAgB,GAAU,CACzB,EAAc,EAAK,EACnB,EAAS,SAAS,MAAM,EACxB,IAAgB,CAAK,CACtB,EACA,IAAK,EAAY,EAAU,CAAG,EAC9B,GAAI,CACJ,CAAA,CAEH,CACD,EACA,EAAS,YAAc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme-provider-MMwxHEfw.js","names":[],"sources":["../src/components/theme/themes.ts","../src/components/theme/theme-provider.tsx"],"sourcesContent":["/**\n * resolvedThemes is a tuple of valid themes that have been resolved from \"system\" to a specific theme.\n */\nconst resolvedThemes = [\"light\", \"dark\", \"light-high-contrast\", \"dark-high-contrast\"] as const;\n\n/**\n * ResolvedTheme is a type that represents a theme that has been resolved from \"system\" to a specific theme.\n */\ntype ResolvedTheme = (typeof resolvedThemes)[number];\n\n/**\n * themes is a tuple of valid themes.\n */\nconst themes = [\"system\", ...resolvedThemes] as const;\n\n/**\n * Theme is a string literal type that represents a valid theme.\n */\ntype Theme = (typeof themes)[number];\n\n/**\n * $theme is a helper which translates the Theme type into a string literal type.\n */\nconst $theme = <T extends Theme = Theme>(value: T) => value;\n\n/**\n * Type predicate that checks if a value is a valid theme.\n */\nfunction isTheme(value: unknown): value is Theme {\n\tif (typeof value !== \"string\") {\n\t\treturn false;\n\t}\n\n\treturn themes.includes(value as Theme);\n}\n\n/**\n * $resolvedTheme is a helper which translates the ResolvedTheme type into a string literal type.\n */\nconst $resolvedTheme = <T extends ResolvedTheme = ResolvedTheme>(value: T) => value;\n\n/**\n * Type predicate that checks if a value is a valid resolved theme.\n */\nfunction isResolvedTheme(value: unknown): value is ResolvedTheme {\n\tif (typeof value !== \"string\") {\n\t\treturn false;\n\t}\n\n\treturn resolvedThemes.includes(value as ResolvedTheme);\n}\n\nexport {\n\t//,\n\tthemes,\n\tresolvedThemes,\n\t$resolvedTheme,\n\t$theme,\n\tisResolvedTheme,\n\tisTheme,\n};\n\nexport type {\n\t//,\n\tTheme,\n\tResolvedTheme,\n};\n","\"use client\";\n\nimport type { PropsWithChildren } from \"react\";\nimport { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { useMatchesMediaQuery } from \"../../hooks/use-matches-media-query.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { canUseDOM } from \"../browser-only/browser-only.js\";\nimport {\n\ttype ResolvedTheme,\n\ttype Theme,\n\tisResolvedTheme,\n\tisTheme,\n\tresolvedThemes,\n\tthemes,\n} from \"./themes.js\";\n\n/**\n * prefersDarkModeMediaQuery is the media query used to detect if the user prefers dark mode.\n */\nconst prefersDarkModeMediaQuery = \"(prefers-color-scheme: dark)\";\n\n/**\n * prefersHighContrastMediaQuery is the media query used to detect if the user prefers high contrast mode.\n */\nconst prefersHighContrastMediaQuery = \"(prefers-contrast: more)\";\n\n/**\n * THEME_STORAGE_KEY is the key used to store the theme in cookies.\n */\nconst THEME_STORAGE_KEY = \"mantle-ui-theme\";\n\n/**\n * DEFAULT_THEME is the initial theme to apply if no value is found in storage.\n * {@link themes}\n */\nconst DEFAULT_THEME = \"system\" satisfies Theme;\n\n/**\n * ThemeProviderState is the shape of the state returned by the ThemeProviderContext.\n */\ntype ThemeProviderState = [theme: Theme, setTheme: (theme: Theme) => void];\n\n/**\n * Initial state for the ThemeProviderContext.\n */\nconst initialState: ThemeProviderState = [\"system\", () => null];\n\n/**\n * ThemeProviderContext is a React Context that provides the current theme and a function to set the theme.\n */\nconst ThemeProviderContext = createContext<ThemeProviderState | null>(initialState);\n\ntype ThemeProviderProps = PropsWithChildren;\n\n/**\n * ThemeProvider is a React Context Provider that provides the current theme and a function to set the theme.\n *\n * @see https://mantle.ngrok.com/components/theme-provider#themeprovider\n *\n * @example\n * ```tsx\n * <ThemeProvider defaultTheme=\"system\" storageKey=\"app-theme\">\n * <App />\n * </ThemeProvider>\n * ```\n */\nfunction ThemeProvider({ children }: ThemeProviderProps) {\n\t// Init once from cookie and apply immediately to avoid flashes\n\tconst [theme, setTheme] = useState<Theme>(() => {\n\t\tconst storedTheme = getStoredTheme({\n\t\t\tcookie: canUseDOM() ? document.cookie : null,\n\t\t});\n\t\tapplyThemeToHtml(storedTheme);\n\t\treturn storedTheme;\n\t});\n\n\tconst broadcastChannelRef = useRef<BroadcastChannel | null>(null);\n\n\tuseEffect(() => {\n\t\tfunction syncThemeFromCookie(next?: Theme) {\n\t\t\tconst newTheme = next ?? getStoredTheme({ cookie: document.cookie });\n\t\t\tsetTheme(newTheme);\n\t\t\tapplyThemeToHtml(newTheme);\n\t\t}\n\n\t\t// initial sync in case defaultTheme or storageKey changed\n\t\tsyncThemeFromCookie();\n\n\t\t// add cross-tab listeners (prefer broadcast channel, use localStorage as fallback)\n\t\ttry {\n\t\t\tif (\"BroadcastChannel\" in window) {\n\t\t\t\tbroadcastChannelRef.current = new BroadcastChannel(THEME_STORAGE_KEY);\n\t\t\t\tbroadcastChannelRef.current.addEventListener(\"message\", (event) => {\n\t\t\t\t\tconst value: unknown = event?.data?.theme;\n\t\t\t\t\tif (isTheme(value)) {\n\t\t\t\t\t\tsyncThemeFromCookie(value);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} catch {\n\t\t\t// silently swallow errors\n\t\t}\n\n\t\tfunction onStorage(event: StorageEvent) {\n\t\t\tif (event.key === `${THEME_STORAGE_KEY}__ping`) {\n\t\t\t\tsyncThemeFromCookie();\n\t\t\t}\n\t\t}\n\t\twindow.addEventListener(\"storage\", onStorage);\n\n\t\t// add media query listeners for system theme changes\n\t\tconst prefersDarkMql = window.matchMedia(prefersDarkModeMediaQuery);\n\t\tconst prefersHighContrastMql = window.matchMedia(prefersHighContrastMediaQuery);\n\n\t\tfunction onChange() {\n\t\t\tsyncThemeFromCookie();\n\t\t}\n\n\t\tfunction onVisibilityChange() {\n\t\t\tif (document.visibilityState === \"visible\") {\n\t\t\t\tsyncThemeFromCookie();\n\t\t\t}\n\t\t}\n\n\t\tprefersDarkMql.addEventListener(\"change\", onChange);\n\t\tprefersHighContrastMql.addEventListener(\"change\", onChange);\n\n\t\t// pageshow fires on bfcache restore (event.persisted === true) and some restore-from-freeze cases.\n\t\twindow.addEventListener(\"pageshow\", onChange);\n\n\t\t// visibilitychange to handle coming back to a tab\n\t\tdocument.addEventListener(\"visibilitychange\", onVisibilityChange);\n\n\t\t// don't forget to clean up your slop!\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"storage\", onStorage);\n\t\t\tprefersDarkMql.removeEventListener(\"change\", onChange);\n\t\t\tprefersHighContrastMql.removeEventListener(\"change\", onChange);\n\t\t\twindow.removeEventListener(\"pageshow\", onChange);\n\t\t\tdocument.removeEventListener(\"visibilitychange\", onVisibilityChange);\n\n\t\t\ttry {\n\t\t\t\tbroadcastChannelRef.current?.close();\n\t\t\t} catch {\n\t\t\t\t// silently swallow errors\n\t\t\t}\n\t\t\tbroadcastChannelRef.current = null;\n\t\t};\n\t}, []);\n\n\tconst value: ThemeProviderState = useMemo(\n\t\t() => [\n\t\t\ttheme,\n\t\t\t(next: Theme) => {\n\t\t\t\tsetCookie(next);\n\t\t\t\tsetTheme(next);\n\t\t\t\tapplyThemeToHtml(next);\n\t\t\t\tnotifyOtherTabs(next, {\n\t\t\t\t\tbroadcastChannel: broadcastChannelRef.current,\n\t\t\t\t\tpingKey: `${THEME_STORAGE_KEY}__ping`,\n\t\t\t\t});\n\t\t\t},\n\t\t],\n\t\t[theme],\n\t);\n\n\treturn <ThemeProviderContext.Provider value={value}>{children}</ThemeProviderContext.Provider>;\n}\nThemeProvider.displayName = \"ThemeProvider\";\n\n/**\n * useTheme returns the current theme and a function to set the theme.\n *\n * @note This function will throw an error if used outside of a ThemeProvider context tree.\n */\nfunction useTheme() {\n\tconst context = useContext(ThemeProviderContext);\n\n\tinvariant(context, \"useTheme must be used within a ThemeProvider\");\n\n\treturn context;\n}\n\n/**\n * Applies the given theme to the `<html>` element.\n */\nfunction applyThemeToHtml(theme: Theme) {\n\tif (!canUseDOM()) {\n\t\treturn;\n\t}\n\n\tconst html = window.document.documentElement;\n\n\tconst prefersDarkMode = window.matchMedia(prefersDarkModeMediaQuery).matches;\n\tconst prefersHighContrast = window.matchMedia(prefersHighContrastMediaQuery).matches;\n\n\tconst resolvedTheme = resolveTheme(theme, {\n\t\tprefersDarkMode,\n\t\tprefersHighContrast,\n\t});\n\n\tconst htmlTheme = html.dataset.theme;\n\tconst htmlAppliedTheme = html.dataset.appliedTheme;\n\n\tconst currentTheme = isTheme(htmlTheme) ? htmlTheme : undefined;\n\tconst currentResolvedTheme = isResolvedTheme(htmlAppliedTheme) ? htmlAppliedTheme : undefined;\n\n\tif (currentTheme === theme && currentResolvedTheme === resolvedTheme) {\n\t\t// nothing to do: input theme and resolved class already match\n\t\treturn;\n\t}\n\n\t// Clear any stale theme class, then apply the new one\n\thtml.classList.remove(...resolvedThemes); // ✅ remove all potential theme classes\n\thtml.classList.add(resolvedTheme);\n\thtml.dataset.theme = theme;\n\thtml.dataset.appliedTheme = resolvedTheme;\n}\n\n/**\n * Read the theme and applied theme from the `<html>` element.\n */\nfunction readThemeFromHtmlElement() {\n\tif (!canUseDOM()) {\n\t\treturn {\n\t\t\tappliedTheme: undefined,\n\t\t\ttheme: undefined,\n\t\t};\n\t}\n\n\tconst htmlElement = window.document.documentElement;\n\tconst theme = isTheme(htmlElement.dataset.theme) ? htmlElement.dataset.theme : undefined;\n\tconst appliedTheme = isResolvedTheme(htmlElement.dataset.appliedTheme)\n\t\t? htmlElement.dataset.appliedTheme\n\t\t: undefined;\n\n\treturn {\n\t\tappliedTheme,\n\t\ttheme,\n\t};\n}\n\n/**\n * If the theme is \"system\", it will resolve the theme based on the user's media query preferences, otherwise it will return the theme as is.\n * This will mirror the result that gets applied to the <html> element.\n */\nfunction resolveTheme(\n\ttheme: Theme,\n\t{\n\t\tprefersDarkMode,\n\t\tprefersHighContrast,\n\t}: { prefersDarkMode: boolean; prefersHighContrast: boolean },\n) {\n\tif (theme === \"system\") {\n\t\treturn determineThemeFromMediaQuery({\n\t\t\tprefersDarkMode,\n\t\t\tprefersHighContrast,\n\t\t});\n\t}\n\n\treturn theme;\n}\n\n/**\n * If the theme is \"system\", it will resolve the theme based on the user's media query preferences, otherwise it will return the theme as is.\n * This will mirror the result that gets applied to the <html> element.\n */\nfunction useAppliedTheme() {\n\tconst themeContext = useContext(ThemeProviderContext);\n\tconst theme = themeContext != null ? themeContext[0] : \"system\";\n\n\tconst prefersDarkMode = useMatchesMediaQuery(prefersDarkModeMediaQuery);\n\tconst prefersHighContrast = useMatchesMediaQuery(prefersHighContrastMediaQuery);\n\n\treturn resolveTheme(theme, { prefersDarkMode, prefersHighContrast });\n}\n\n/**\n * determineThemeFromMediaQuery returns the theme that should be used based on the user's media query preferences.\n * @private\n *\n * @example\n * ```tsx\n * const theme = determineThemeFromMediaQuery({\n * prefersDarkMode: true,\n * prefersHighContrast: false\n * });\n * // Returns: \"dark\"\n *\n * const themeWithContrast = determineThemeFromMediaQuery({\n * prefersDarkMode: false,\n * prefersHighContrast: true\n * });\n * // Returns: \"light-high-contrast\"\n * ```\n */\nexport function determineThemeFromMediaQuery({\n\tprefersDarkMode,\n\tprefersHighContrast,\n}: {\n\tprefersDarkMode: boolean;\n\tprefersHighContrast: boolean;\n}): ResolvedTheme {\n\tif (prefersHighContrast) {\n\t\treturn prefersDarkMode ? \"dark-high-contrast\" : \"light-high-contrast\";\n\t}\n\n\treturn prefersDarkMode ? \"dark\" : \"light\";\n}\n\n/**\n * The FOUC-prevention bootstrap. This entire function is stringified and inlined\n * into a blocking `<script>` in the document head; it runs synchronously before\n * React mounts (and before first paint) so the resolved theme class is on\n * `<html>` by the time the browser paints, avoiding a light→dark (or vice-versa)\n * flash.\n *\n * Resolution order:\n * 1. Read the stored preference: cookie first, then `localStorage` (legacy fallback).\n * 2. Validate it against the configured `themes`; fall back to `defaultTheme` otherwise.\n * 3. If the preference is `\"system\"`, resolve against the OS media queries\n * (`prefers-color-scheme`, `prefers-contrast`).\n * 4. Apply the resolved class to `<html>` and refresh the cookie so subsequent\n * SSRs see the same value.\n *\n * Why nested helpers: this function is serialized verbatim into the inlined\n * script, so it must be hermetic — every helper it calls has to travel with it.\n * Hoisting them to module scope would leave dangling references in the inlined\n * source. All catches are intentionally swallowing to keep the script crash-free\n * in environments where cookies / `localStorage` / `matchMedia` throw (sandboxed\n * iframes, privacy modes, SSR-style polyfills).\n *\n * @param args.storageKey Cookie + localStorage key for the persisted theme.\n * @param args.defaultTheme Theme to use when no valid preference is stored.\n * @param args.themes Allowed `Theme` values (used to validate stored input).\n * @param args.resolvedThemes Allowed `ResolvedTheme` class names applied to `<html>`.\n * @param args.prefersDarkModeMediaQuery Media query string for OS dark-mode detection.\n * @param args.prefersHighContrastMediaQuery Media query string for OS high-contrast detection.\n */\nfunction preventThemeFlash(args: {\n\tstorageKey: string;\n\tdefaultTheme: Theme;\n\tthemes: readonly Theme[];\n\tresolvedThemes: readonly ResolvedTheme[];\n\tprefersDarkModeMediaQuery: string;\n\tprefersHighContrastMediaQuery: string;\n}) {\n\tconst {\n\t\tstorageKey,\n\t\tdefaultTheme,\n\t\tthemes,\n\t\tresolvedThemes,\n\t\tprefersDarkModeMediaQuery,\n\t\tprefersHighContrastMediaQuery,\n\t} = args;\n\n\tfunction isTheme(value: unknown): value is Theme {\n\t\treturn typeof value === \"string\" && themes.includes(value as Theme);\n\t}\n\n\t// Nested helpers below must stay inside `preventThemeFlash` so they are\n\t// included when the function is stringified into the inlined FOUC-prevention\n\t// script. Hoisting them would leave dangling references at runtime.\n\t// oxlint-disable-next-line unicorn/consistent-function-scoping\n\tfunction getThemeFromCookie(name: string): string | null {\n\t\tconst cookie = document.cookie;\n\t\tif (!cookie) {\n\t\t\treturn null;\n\t\t}\n\n\t\ttry {\n\t\t\tconst cookies = cookie.split(\";\");\n\t\t\tconst themeCookie = cookies.find((c) => c.trim().startsWith(`${name}=`));\n\t\t\tconst cookieValue = themeCookie?.split(\"=\")[1];\n\t\t\tconst storedTheme = cookieValue ? decodeURIComponent(cookieValue) : null;\n\t\t\treturn storedTheme;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t// oxlint-disable-next-line unicorn/consistent-function-scoping -- stringified into the inlined FOUC script; see note above.\n\tfunction buildCookie(name: string, val: string): string {\n\t\tconst expires = new Date();\n\t\texpires.setFullYear(expires.getFullYear() + 1);\n\t\tconst hostname = window.location.hostname;\n\t\tconst protocol = window.location.protocol;\n\t\tconst domainAttribute =\n\t\t\thostname === \"ngrok.com\" || hostname.endsWith(\".ngrok.com\") ? \"; domain=.ngrok.com\" : \"\";\n\t\tconst secureAttribute = protocol === \"https:\" ? \"; Secure\" : \"\";\n\t\treturn `${name}=${encodeURIComponent(val)}; expires=${expires.toUTCString()}; path=/${domainAttribute}; SameSite=Lax${secureAttribute}`;\n\t}\n\n\tfunction writeCookie(name: string, val: string): void {\n\t\ttry {\n\t\t\tdocument.cookie = buildCookie(name, val);\n\t\t} catch {\n\t\t\t// silently swallow errors\n\t\t}\n\t}\n\n\t// oxlint-disable-next-line unicorn/consistent-function-scoping -- stringified into the inlined FOUC script; see note above.\n\tfunction resolveThemeValue(\n\t\ttheme: Theme,\n\t\tisDark: boolean,\n\t\tisHighContrast: boolean,\n\t): ResolvedTheme {\n\t\tif (theme === \"system\") {\n\t\t\tif (isHighContrast) {\n\t\t\t\treturn isDark ? \"dark-high-contrast\" : \"light-high-contrast\";\n\t\t\t}\n\t\t\treturn isDark ? \"dark\" : \"light\";\n\t\t}\n\t\treturn theme;\n\t}\n\n\t// 1) Read preference: cookie first, fallback to localStorage (migration support)\n\tlet cookieTheme: string | null = null;\n\tlet lsTheme: string | null = null;\n\tlet storedTheme: Theme | null = null;\n\n\ttry {\n\t\tcookieTheme = getThemeFromCookie(storageKey);\n\t} catch {\n\t\t// silently swallow errors\n\t}\n\n\tif (isTheme(cookieTheme)) {\n\t\tstoredTheme = cookieTheme;\n\t} else {\n\t\ttry {\n\t\t\tlsTheme = window.localStorage?.getItem(storageKey) ?? null;\n\t\t} catch {\n\t\t\t// silently swallow errors\n\t\t}\n\t\tif (isTheme(lsTheme)) {\n\t\t\tstoredTheme = lsTheme;\n\t\t}\n\t}\n\n\tconst preference = isTheme(storedTheme) ? storedTheme : defaultTheme;\n\n\t// 2) Resolve theme based on media queries\n\tconst isDark = matchMedia(prefersDarkModeMediaQuery).matches;\n\tconst isHighContrast = matchMedia(prefersHighContrastMediaQuery).matches;\n\tconst resolvedTheme = resolveThemeValue(preference, isDark, isHighContrast);\n\n\tconst html = document.documentElement;\n\t// 3) Apply theme to DOM (same order as applyThemeToHtml)\n\tif (html.dataset.appliedTheme !== resolvedTheme || html.dataset.theme !== preference) {\n\t\t// Remove all theme classes\n\t\tfor (const themeClass of resolvedThemes as readonly string[]) {\n\t\t\thtml.classList.remove(themeClass);\n\t\t}\n\t\t// Add resolved theme class\n\t\thtml.classList.add(resolvedTheme);\n\t\t// Set data attributes\n\t\thtml.dataset.theme = preference;\n\t\thtml.dataset.appliedTheme = resolvedTheme;\n\t}\n\n\t// 4) Handle persistence/migration synchronously to prevent FOUC\n\tconst hadValidCookie = isTheme(cookieTheme);\n\ttry {\n\t\tif (isTheme(lsTheme) && !hadValidCookie) {\n\t\t\t// Migrate from localStorage to cookie\n\t\t\twriteCookie(storageKey, lsTheme);\n\t\t\ttry {\n\t\t\t\twindow.localStorage.removeItem(storageKey);\n\t\t\t} catch {\n\t\t\t\t// silently swallow errors\n\t\t\t}\n\t\t} else if (!hadValidCookie) {\n\t\t\t// Set default cookie if none existed\n\t\t\twriteCookie(storageKey, preference);\n\t\t}\n\t} catch {\n\t\t// silently swallow errors\n\t}\n}\n\n/**\n * preventWrongThemeFlashScriptContent generates a script that prevents the wrong theme from flashing on initial page load.\n * It checks cookies for a stored theme, and if none is found, it sets the default theme.\n * It also applies the correct theme to the `<html>` element based on the user's media query preferences.\n */\nfunction preventWrongThemeFlashScriptContent() {\n\tconst args = {\n\t\tstorageKey: THEME_STORAGE_KEY,\n\t\tdefaultTheme: DEFAULT_THEME,\n\t\tthemes,\n\t\tresolvedThemes,\n\t\tprefersDarkModeMediaQuery,\n\t\tprefersHighContrastMediaQuery,\n\t} as const satisfies Parameters<typeof preventThemeFlash>[0];\n\n\treturn `(${preventThemeFlash.toString()})(${JSON.stringify(args)})`;\n}\n\nexport type PreventWrongThemeFlashScriptProps = {\n\t/**\n\t * An optional CSP nonce to allowlist this inline script. Using this can help\n\t * you to avoid using the CSP `unsafe-inline` directive, which disables\n\t * XSS protection and would allowlist all inline scripts or styles.\n\t *\n\t * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/nonce\n\t */\n\tnonce?: string;\n};\n\n/**\n * Renders an inline script that prevents Flash of Unstyled Content (FOUC) or the\n * wrong theme flashing on first paint.\n *\n * This is the preferred building block for SSR apps. Pair it with\n * {@link preloadFontLink} HTTP `Link` headers in your server entry so font fetches\n * begin before HTML is parsed. For client-only apps without header control, pair\n * it with {@link PreloadFont} elements in `<head>` instead.\n *\n * Place this as early as possible in the `<head>`.\n *\n * @example\n * ```tsx\n * // entry.server.tsx — send font preloads as HTTP headers (preferred for SSR)\n * headers.set(\"Link\", [\n * `<${assetsCdnOrigin}>; rel=preconnect; crossorigin`,\n * preloadFontLink(\"roobert\"),\n * preloadFontLink(\"jetbrains-mono\"),\n * ].join(\", \"));\n *\n * // root.tsx — only the FOUC script in <head>\n * <head>\n * <PreventWrongThemeFlashScript nonce={nonce} />\n * </head>\n * ```\n *\n * @param nonce - Optional CSP nonce to allowlist the inline script under a strict CSP.\n * @returns {JSX.Element} A script tag injected before first paint.\n * @see preloadFontLink\n * @see PreloadFont\n * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce\n */\nconst PreventWrongThemeFlashScript = ({ nonce }: PreventWrongThemeFlashScriptProps) => (\n\t<script\n\t\tdangerouslySetInnerHTML={{\n\t\t\t__html: preventWrongThemeFlashScriptContent(),\n\t\t}}\n\t\tnonce={nonce}\n\t\tsuppressHydrationWarning\n\t/>\n);\nPreventWrongThemeFlashScript.displayName = \"PreventWrongThemeFlashScript\";\n\ntype InitialThemeProps = {\n\tclassName: string;\n\t\"data-applied-theme\": ResolvedTheme;\n\t\"data-theme\": Theme;\n};\n\ntype UseInitialHtmlThemePropsOptions = {\n\tclassName?: string;\n\t/**\n\t * Theme cookie string for SSR theme resolution. Pass only the theme cookie\n\t * pair (via {@link extractThemeCookie}) rather than the full raw `Cookie`\n\t * header to avoid leaking sensitive cookies in serialized loader data.\n\t */\n\tssrCookie?: string;\n};\n\n/**\n * useInitialHtmlThemeProps returns the initial props that should be applied to the <html> element to prevent react hydration errors.\n */\nfunction useInitialHtmlThemeProps(props: UseInitialHtmlThemePropsOptions = {}): InitialThemeProps {\n\tconst { className = \"\", ssrCookie } = props ?? {};\n\n\treturn useMemo(() => {\n\t\tlet initialTheme: Theme;\n\t\tlet resolvedTheme: ResolvedTheme;\n\n\t\tif (!canUseDOM()) {\n\t\t\tinitialTheme = getStoredTheme({ cookie: ssrCookie });\n\t\t\tresolvedTheme = resolveTheme(initialTheme, {\n\t\t\t\t// During SSR we can't detect media queries, so assume light/no high contrast.\n\t\t\t\t// The inline script will correct this before paint for \"system\" theme users.\n\t\t\t\tprefersDarkMode: false,\n\t\t\t\tprefersHighContrast: false,\n\t\t\t});\n\t\t} else {\n\t\t\tconst prefersDarkMode = window.matchMedia(prefersDarkModeMediaQuery).matches;\n\t\t\tconst prefersHighContrast = window.matchMedia(prefersHighContrastMediaQuery).matches;\n\t\t\tinitialTheme = getStoredTheme({ cookie: document.cookie });\n\t\t\tresolvedTheme = resolveTheme(initialTheme, {\n\t\t\t\tprefersDarkMode,\n\t\t\t\tprefersHighContrast,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tclassName: cx(className, resolvedTheme),\n\t\t\t\"data-applied-theme\": resolvedTheme,\n\t\t\t\"data-theme\": initialTheme,\n\t\t};\n\t}, [className, ssrCookie]);\n}\n\ntype GetStoredThemeOptions = {\n\t/**\n\t * raw Cookie header (SSR) or document.cookie (client)\n\t */\n\tcookie: string | null | undefined;\n};\n\n/**\n * Returns the persisted UI theme from a Cookie header string.\n *\n * Looks for a cookie named by {@link THEME_STORAGE_KEY} and returns its value **iff**\n * it’s a valid `Theme` per `isTheme`. Otherwise, falls back to\n * {@link DEFAULT_THEME}. This function never throws; malformed encodings or\n * missing cookies quietly return the default.\n *\n * @example\n * getStoredTheme({ cookie: `${THEME_STORAGE_KEY}=dark; session=abc` }) // \"dark\"\n * @example\n * getStoredTheme({ cookie: \"\" }) // DEFAULT_THEME\n */\nfunction getStoredTheme({ cookie }: GetStoredThemeOptions): Theme {\n\tif (!cookie) {\n\t\treturn DEFAULT_THEME;\n\t}\n\n\ttry {\n\t\tconst cookies = cookie.split(\";\");\n\t\tconst themeCookie = cookies.find((cookieStr) =>\n\t\t\tcookieStr.trim().startsWith(`${THEME_STORAGE_KEY}=`),\n\t\t);\n\t\tconst cookieValue = themeCookie?.split(\"=\")[1];\n\t\tconst storedTheme = cookieValue ? globalThis.decodeURIComponent(cookieValue) : null;\n\n\t\treturn isTheme(storedTheme) ? storedTheme : DEFAULT_THEME;\n\t} catch {\n\t\treturn DEFAULT_THEME;\n\t}\n}\n\n/**\n * Extract just the mantle theme cookie from a raw `Cookie` header string.\n *\n * Use this in SSR loaders to safely pass the theme cookie to\n * {@link useInitialHtmlThemeProps} without exposing the full `Cookie` header\n * (which may contain HttpOnly/session cookies) in serialized loader data.\n *\n * @example\n * ```ts\n * // app/root.tsx loader\n * export const loader = async ({ request }: Route.LoaderArgs) => {\n * const themeCookie = extractThemeCookie(request.headers.get(\"Cookie\"));\n * return { themeCookie };\n * };\n * ```\n *\n * @param cookieHeader - The raw `Cookie` header string from the request, or null/undefined.\n * @returns The `mantle-ui-theme=<value>` cookie string, or undefined if not found.\n */\nfunction extractThemeCookie(cookieHeader: string | null | undefined): string | undefined {\n\tif (!cookieHeader) {\n\t\treturn undefined;\n\t}\n\n\treturn cookieHeader\n\t\t.split(\";\")\n\t\t.map((part) => part.trim())\n\t\t.find((part) => part.startsWith(`${THEME_STORAGE_KEY}=`));\n}\n\nexport {\n\tPreventWrongThemeFlashScript,\n\tThemeProvider,\n\t//,\n\textractThemeCookie,\n\tgetStoredTheme,\n\tpreventWrongThemeFlashScriptContent,\n\treadThemeFromHtmlElement,\n\tuseAppliedTheme,\n\tuseInitialHtmlThemeProps,\n\tuseTheme,\n};\n\n/**\n * Notifies other open tabs (same origin) that the theme changed.\n *\n * Prefers a shared {@link BroadcastChannel} for immediate, reliable delivery.\n * Falls back to writing a unique “ping” value to `localStorage`, which triggers\n * the cross-tab `storage` event. Both mechanisms only work across the same origin.\n *\n * Uses a timestamp to ensure the storage value always changes so the event fires.\n *\n * @remarks\n * - Same-origin only: BroadcastChannel and the `storage` event do not cross subdomains\n * or different schemes/ports. For cross-subdomain sync, use a postMessage hub or server push.\n * - This function is fire-and-forget and intentionally swallows errors.\n * - Receivers should re-read the cookie/source of truth and then apply the theme;\n * don’t trust the payload blindly.\n *\n * @example\n * // Sender (inside your setter)\n * notifyOtherTabs(nextTheme, {\n * broadcastChannel: broadcastChannelRef.current,\n * pingKey: `${storageKey}__ping`,\n * });\n *\n * @example\n * // Receiver (setup once per tab)\n * const bc = new BroadcastChannel(storageKey);\n * bc.onmessage = () => syncThemeFromCookie();\n * window.addEventListener('storage', (e) => {\n * if (e.key === `${storageKey}__ping`) syncThemeFromCookie();\n * });\n */\nfunction notifyOtherTabs(\n\ttheme: Theme,\n\toptions: {\n\t\tbroadcastChannel: BroadcastChannel | null;\n\t\tpingKey: `${string}__ping`;\n\t},\n) {\n\tconst { broadcastChannel, pingKey } = options;\n\n\t// first try BroadcastChannel\n\ttry {\n\t\tif (broadcastChannel) {\n\t\t\t// BroadcastChannel.postMessage has no `targetOrigin` parameter (unlike Window.postMessage); the rule can't distinguish the two.\n\t\t\t// oxlint-disable unicorn/require-post-message-target-origin\n\t\t\tbroadcastChannel.postMessage({\n\t\t\t\ttheme,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t\t// oxlint-enable unicorn/require-post-message-target-origin\n\t\t\treturn;\n\t\t}\n\t} catch {\n\t\t// silently swallow errors\n\t}\n\n\t// fallback to storage event: write a \"ping\" key (not the real storageKey)\n\ttry {\n\t\tlocalStorage.setItem(pingKey, JSON.stringify({ theme, timestamp: Date.now() }));\n\t} catch {\n\t\t// silently swallow errors\n\t}\n}\n\nfunction buildThemeCookie(value: string) {\n\tconst expires = new Date();\n\texpires.setFullYear(expires.getFullYear() + 1); // 1 year expiration\n\n\t// Only set .ngrok.com domain for ngrok domains, otherwise let it default to current domain\n\tconst { hostname, protocol } = window.location;\n\tconst domainAttribute =\n\t\thostname === \"ngrok.com\" || hostname.endsWith(\".ngrok.com\") ? \"; domain=.ngrok.com\" : \"\";\n\tconst secureAttribute = protocol === \"https:\" ? \"; Secure\" : \"\";\n\n\treturn `${THEME_STORAGE_KEY}=${encodeURIComponent(value)}; expires=${expires.toUTCString()}; path=/${domainAttribute}; SameSite=Lax${secureAttribute}` as const;\n}\n\n/**\n * Sets a cookie with appropriate domain for the current hostname.\n * Uses .ngrok.com for ngrok domains, otherwise no domain (current domain only).\n */\nfunction setCookie(value: string) {\n\tif (!canUseDOM()) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\tdocument.cookie = buildThemeCookie(value);\n\t} catch {\n\t\t// silently swallow errors\n\t}\n}\n"],"mappings":"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"}
|