@ngrok/mantle 0.73.3 → 0.73.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/dist/accordion.d.ts +7 -9
- package/dist/accordion.js +1 -1
- package/dist/accordion.js.map +1 -1
- package/dist/agent.json +1 -1
- package/dist/alert-dialog.d.ts +33 -38
- package/dist/alert-dialog.js +1 -1
- package/dist/alert-dialog.js.map +1 -1
- package/dist/alert.d.ts +9 -11
- package/dist/alert.js +1 -1
- package/dist/alert.js.map +1 -1
- package/dist/{anchor-2stEauOz.js → anchor-CcTY5SIz.js} +2 -2
- package/dist/{anchor-2stEauOz.js.map → anchor-CcTY5SIz.js.map} +1 -1
- package/dist/anchor.d.ts +2 -3
- package/dist/anchor.js +1 -1
- package/dist/{as-child-CpZKMqTE.d.ts → as-child-uN_018tj.d.ts} +1 -1
- package/dist/badge.d.ts +3 -4
- package/dist/badge.js +1 -1
- package/dist/badge.js.map +1 -1
- package/dist/{booleanish-CBGdPL3Q.js → booleanish-BfvnW6vy.js} +1 -1
- package/dist/{booleanish-CBGdPL3Q.js.map → booleanish-BfvnW6vy.js.map} +1 -1
- package/dist/{browser-only-QPyyfLaB.js → browser-only-BSl_hruR.js} +1 -1
- package/dist/{browser-only-QPyyfLaB.js.map → browser-only-BSl_hruR.js.map} +1 -1
- package/dist/browser-only.js +1 -1
- package/dist/{button-POMJ-20y.js → button-BAxneEMu.js} +2 -2
- package/dist/{button-POMJ-20y.js.map → button-BAxneEMu.js.map} +1 -1
- package/dist/{button-DbHFERMB.d.ts → button-BYZOBUgj.d.ts} +16 -19
- package/dist/{button-GokecthL.js → button-uMIZVKit.js} +2 -2
- package/dist/{button-GokecthL.js.map → button-uMIZVKit.js.map} +1 -1
- package/dist/button.d.ts +4 -4
- package/dist/button.js +1 -1
- package/dist/calendar.d.ts +1 -2
- package/dist/calendar.js +1 -1
- package/dist/calendar.js.map +1 -1
- package/dist/card.d.ts +6 -7
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/checkbox.d.ts +3 -4
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/code-block.d.ts +17 -19
- package/dist/code-block.js +1 -1
- package/dist/code-block.js.map +1 -1
- package/dist/code-block_highlight-utils.d.ts +1 -1
- package/dist/code-block_highlight-utils.js +1 -1
- package/dist/code.d.ts +2 -3
- package/dist/code.js +1 -1
- package/dist/code.js.map +1 -1
- package/dist/color.d.ts +2 -2
- package/dist/color.js.map +1 -1
- package/dist/combobox.d.ts +11 -13
- package/dist/combobox.js +1 -1
- package/dist/combobox.js.map +1 -1
- package/dist/command.d.ts +133 -220
- package/dist/command.js +1 -1
- package/dist/command.js.map +1 -1
- package/dist/{compose-refs-DZ3cPi47.js → compose-refs-Cjf2gfB8.js} +1 -1
- package/dist/{compose-refs-DZ3cPi47.js.map → compose-refs-Cjf2gfB8.js.map} +1 -1
- package/dist/{copy-to-clipboard-CNMRyck4.js → copy-to-clipboard-Baw30q9O.js} +2 -2
- package/dist/{copy-to-clipboard-CNMRyck4.js.map → copy-to-clipboard-Baw30q9O.js.map} +1 -1
- package/dist/{cx-D1HYnpvA.js → cx-CBSnSC36.js} +1 -1
- package/dist/{cx-D1HYnpvA.js.map → cx-CBSnSC36.js.map} +1 -1
- package/dist/cx.js +1 -1
- package/dist/data-table.d.ts +13 -15
- package/dist/data-table.js +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/{deep-non-nullable-Xu7ckQM6.d.ts → deep-non-nullable-BxRoySYR.d.ts} +1 -1
- package/dist/description-list.d.ts +5 -6
- package/dist/description-list.js +1 -1
- package/dist/description-list.js.map +1 -1
- package/dist/{dialog-B1KCB7JT.js → dialog-Dn-brQBw.js} +2 -2
- package/dist/{dialog-B1KCB7JT.js.map → dialog-Dn-brQBw.js.map} +1 -1
- package/dist/dialog.d.ts +14 -17
- package/dist/dialog.js +1 -1
- package/dist/{direction-D9IZ1wW6.d.ts → direction-CcTY0FmA.d.ts} +2 -2
- package/dist/{direction-HqPHXGIs.js → direction-Wa9W2F61.js} +1 -1
- package/dist/{direction-HqPHXGIs.js.map → direction-Wa9W2F61.js.map} +1 -1
- package/dist/{dropdown-menu-CvOiQUSZ.d.ts → dropdown-menu-BgYk4L8o.d.ts} +22 -24
- package/dist/{dropdown-menu-DY4w933w.js → dropdown-menu-C3YZJBkV.js} +2 -2
- package/dist/{dropdown-menu-DY4w933w.js.map → dropdown-menu-C3YZJBkV.js.map} +1 -1
- package/dist/dropdown-menu.d.ts +1 -1
- package/dist/dropdown-menu.js +1 -1
- package/dist/empty.d.ts +7 -8
- package/dist/empty.js +1 -1
- package/dist/empty.js.map +1 -1
- package/dist/{field-context-B7Z1cmZW.js → field-context-4k1kI7Bo.js} +2 -2
- package/dist/{field-context-B7Z1cmZW.js.map → field-context-4k1kI7Bo.js.map} +1 -1
- package/dist/field.d.ts +23 -25
- package/dist/field.js +1 -1
- package/dist/field.js.map +1 -1
- package/dist/flag.d.ts +1 -2
- package/dist/flag.js +1 -1
- package/dist/flag.js.map +1 -1
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +1 -1
- package/dist/hooks.js.map +1 -1
- package/dist/hover-card.d.ts +4 -6
- package/dist/hover-card.js +1 -1
- package/dist/hover-card.js.map +1 -1
- package/dist/{icon-bWc5yC3-.js → icon-C8bYBIHW.js} +2 -2
- package/dist/{icon-bWc5yC3-.js.map → icon-C8bYBIHW.js.map} +1 -1
- package/dist/{icon-button-ZKN0sRIJ.js → icon-button-C_Ht_g1C.js} +2 -2
- package/dist/{icon-button-ZKN0sRIJ.js.map → icon-button-C_Ht_g1C.js.map} +1 -1
- package/dist/{icon-button-BDTb-lxs.d.ts → icon-button-ntupABbM.d.ts} +6 -8
- package/dist/{icon-BJ7q2RXZ.d.ts → icon-n49kOh4_.d.ts} +3 -4
- package/dist/icon.d.ts +3 -3
- package/dist/icon.js +1 -1
- package/dist/icons.d.ts +9 -10
- package/dist/icons.js +1 -1
- package/dist/icons.js.map +1 -1
- package/dist/{in-view-BUgyu-Tk.d.ts → in-view-BC3wmz-a.d.ts} +1 -1
- package/dist/{in-view-CeVqeGbv.js → in-view-C2DpZ6s0.js} +1 -1
- package/dist/{in-view-CeVqeGbv.js.map → in-view-C2DpZ6s0.js.map} +1 -1
- package/dist/{index-BhlxYL_y.d.ts → index-BL5WVva_.d.ts} +3 -6
- package/dist/{index-CWXKBva-.d.ts → index-DBZ3eRsl.d.ts} +5 -7
- package/dist/{index-DS_4n2eb.d.ts → index-DorCusfG.d.ts} +1 -1
- package/dist/{index-BbZBDzPh.d.ts → index-L3NmbHi5.d.ts} +1 -1
- package/dist/input.d.ts +7 -8
- package/dist/input.js +1 -1
- package/dist/input.js.map +1 -1
- package/dist/{is-input-CtUHJGgL.js → is-input-CXmS0OFN.js} +1 -1
- package/dist/{is-input-CtUHJGgL.js.map → is-input-CXmS0OFN.js.map} +1 -1
- package/dist/{kbd-CbMxDL9E.js → kbd-Bv6tefdB.js} +2 -2
- package/dist/{kbd-CbMxDL9E.js.map → kbd-Bv6tefdB.js.map} +1 -1
- package/dist/kbd.d.ts +1 -2
- package/dist/kbd.js +1 -1
- package/dist/{label-x6FcOpxc.js → label-DhIUmTN2.js} +2 -2
- package/dist/{label-x6FcOpxc.js.map → label-DhIUmTN2.js.map} +1 -1
- package/dist/label.d.ts +2 -4
- package/dist/label.js +1 -1
- package/dist/llms.txt +1 -1
- package/dist/main.d.ts +1 -2
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/media-object.d.ts +4 -5
- package/dist/media-object.js +1 -1
- package/dist/media-object.js.map +1 -1
- package/dist/multi-select.d.ts +16 -18
- package/dist/multi-select.js +1 -1
- package/dist/multi-select.js.map +1 -1
- package/dist/otp-input.d.ts +6 -7
- package/dist/otp-input.js +1 -1
- package/dist/otp-input.js.map +1 -1
- package/dist/pagination.d.ts +7 -9
- package/dist/pagination.js +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/{popover-CoZxokw_.js → popover-DponNBot.js} +2 -2
- package/dist/{popover-CoZxokw_.js.map → popover-DponNBot.js.map} +1 -1
- package/dist/popover.d.ts +6 -7
- package/dist/popover.js +1 -1
- package/dist/primitive-Cn3h4DJg.js +2 -0
- package/dist/primitive-Cn3h4DJg.js.map +1 -0
- package/dist/{primitive-qkxTYBUY.d.ts → primitive-D_-h74Kt.d.ts} +2 -3
- package/dist/progress.d.ts +4 -5
- package/dist/progress.js +1 -1
- package/dist/progress.js.map +1 -1
- package/dist/radio-group.d.ts +18 -20
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.js.map +1 -1
- package/dist/{resolve-pre-rendered-props-BfWe69-w.js → resolve-pre-rendered-props-C-vrNxH1.js} +8 -8
- package/dist/resolve-pre-rendered-props-C-vrNxH1.js.map +1 -0
- package/dist/{resolve-pre-rendered-props-BONSCwYA.d.ts → resolve-pre-rendered-props-DxJ9-DAl.d.ts} +1 -1
- package/dist/sandboxed-on-click.d.ts +3 -4
- package/dist/sandboxed-on-click.js +1 -1
- package/dist/sandboxed-on-click.js.map +1 -1
- package/dist/{select-SZFFzYs0.d.ts → select-C15-XvRT.d.ts} +15 -16
- package/dist/select-Cxc9VmP8.js +2 -0
- package/dist/select-Cxc9VmP8.js.map +1 -0
- package/dist/select.d.ts +1 -1
- package/dist/select.js +1 -1
- package/dist/separator-Bqjy77rG.js +2 -0
- package/dist/separator-Bqjy77rG.js.map +1 -0
- package/dist/separator.d.ts +3 -5
- package/dist/separator.js +1 -1
- package/dist/sheet.d.ts +15 -19
- package/dist/sheet.js +1 -1
- package/dist/sheet.js.map +1 -1
- package/dist/skeleton.d.ts +4 -6
- package/dist/skeleton.js +1 -1
- package/dist/skeleton.js.map +1 -1
- package/dist/skip-to-main-link.d.ts +1 -2
- package/dist/skip-to-main-link.js +1 -1
- package/dist/skip-to-main-link.js.map +1 -1
- package/dist/slider.d.ts +1 -2
- package/dist/slider.js +1 -1
- package/dist/slider.js.map +1 -1
- package/dist/{slot-D_ZUrdEW.js → slot-CV5fmqFr.js} +2 -2
- package/dist/{slot-D_ZUrdEW.js.map → slot-CV5fmqFr.js.map} +1 -1
- package/dist/slot.d.ts +1 -1
- package/dist/slot.js +1 -1
- package/dist/{sort-mXo37xN2.js → sort-BPX2Fk9t.js} +2 -2
- package/dist/{sort-mXo37xN2.js.map → sort-BPX2Fk9t.js.map} +1 -1
- package/dist/split-button.d.ts +10 -12
- package/dist/split-button.js +1 -1
- package/dist/split-button.js.map +1 -1
- package/dist/{svg-only-7gYlsX8f.js → svg-only-Cz1cby8y.js} +2 -2
- package/dist/{svg-only-7gYlsX8f.js.map → svg-only-Cz1cby8y.js.map} +1 -1
- package/dist/{svg-only-D4uqM1OC.d.ts → svg-only-f6ToFLH0.d.ts} +3 -4
- package/dist/switch.d.ts +3 -5
- package/dist/switch.js +1 -1
- package/dist/switch.js.map +1 -1
- package/dist/{table-CjSQkfZe.d.ts → table-BWD9IlIN.d.ts} +10 -12
- package/dist/{table-CHd39aT-.js → table-eyoUW2Uv.js} +2 -2
- package/dist/{table-CHd39aT-.js.map → table-eyoUW2Uv.js.map} +1 -1
- package/dist/table.d.ts +1 -1
- package/dist/table.js +1 -1
- package/dist/tabs.d.ts +6 -9
- package/dist/tabs.js +1 -1
- package/dist/tabs.js.map +1 -1
- package/dist/text-area.d.ts +2 -3
- package/dist/text-area.js +1 -1
- package/dist/text-area.js.map +1 -1
- package/dist/theme-provider-MMwxHEfw.js +2 -0
- package/dist/theme-provider-MMwxHEfw.js.map +1 -0
- package/dist/theme.d.ts +9 -10
- package/dist/theme.js +1 -1
- package/dist/theme.js.map +1 -1
- package/dist/{themes-FPux5kIu.d.ts → themes-CYNpplwN.d.ts} +1 -1
- package/dist/toast-CR3MVChj.js +2 -0
- package/dist/toast-CR3MVChj.js.map +1 -0
- package/dist/toast.d.ts +8 -10
- package/dist/toast.js +1 -1
- package/dist/tooltip.d.ts +4 -6
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.js.map +1 -1
- package/dist/{traffic-policy-file-BwHHdhWJ.js → traffic-policy-file-0g5RXFqu.js} +1 -1
- package/dist/{traffic-policy-file-BwHHdhWJ.js.map → traffic-policy-file-0g5RXFqu.js.map} +1 -1
- package/dist/{types-QKZ5fvaQ.d.ts → types-BvUzforF.d.ts} +1 -1
- package/dist/types-D85fCNV3.js +2 -0
- package/dist/{types-884RJJqm.js.map → types-D85fCNV3.js.map} +1 -1
- package/dist/types.d.ts +6 -6
- package/dist/types.js +1 -1
- package/dist/use-copy-to-clipboard-BLpquU9d.js +2 -0
- package/dist/{use-copy-to-clipboard-CTgtLjUg.js.map → use-copy-to-clipboard-BLpquU9d.js.map} +1 -1
- package/dist/{use-isomorphic-layout-effect-CNSD0lhi.js → use-isomorphic-layout-effect-DdTRtMY-.js} +1 -1
- package/dist/{use-isomorphic-layout-effect-CNSD0lhi.js.map → use-isomorphic-layout-effect-DdTRtMY-.js.map} +1 -1
- package/dist/{use-matches-media-query-CojcYxlA.js → use-matches-media-query-CMSxHR9n.js} +1 -1
- package/dist/{use-matches-media-query-CojcYxlA.js.map → use-matches-media-query-CMSxHR9n.js.map} +1 -1
- package/dist/{use-prefers-reduced-motion-Bpx8G3UT.js → use-prefers-reduced-motion-CWIoFA6W.js} +2 -2
- package/dist/{use-prefers-reduced-motion-Bpx8G3UT.js.map → use-prefers-reduced-motion-CWIoFA6W.js.map} +1 -1
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/{validation-BYME8rWN.js → validation-DCyx-ceH.js} +1 -1
- package/dist/{validation-BYME8rWN.js.map → validation-DCyx-ceH.js.map} +1 -1
- package/dist/{validation-CBSOmooP.d.ts → validation-xyX_6kph.d.ts} +1 -1
- package/dist/{variant-props-BZbM__kQ.d.ts → variant-props-CVymuSfa.d.ts} +2 -2
- package/dist/{with-style-props-xzZLnIrF.d.ts → with-style-props-CyImx7vd.d.ts} +1 -1
- package/package.json +6 -6
- package/dist/primitive-tXm_8n_t.js +0 -2
- package/dist/primitive-tXm_8n_t.js.map +0 -1
- package/dist/resolve-pre-rendered-props-BfWe69-w.js.map +0 -1
- package/dist/select-B7orOUPj.js +0 -2
- package/dist/select-B7orOUPj.js.map +0 -1
- package/dist/separator-awchG4LI.js +0 -2
- package/dist/separator-awchG4LI.js.map +0 -1
- package/dist/theme-provider-BFcnjeME.js +0 -2
- package/dist/theme-provider-BFcnjeME.js.map +0 -1
- package/dist/toast-CGnquSKO.js +0 -2
- package/dist/toast-CGnquSKO.js.map +0 -1
- package/dist/types-884RJJqm.js +0 -2
- package/dist/use-copy-to-clipboard-CTgtLjUg.js +0 -2
package/dist/field.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","names":[],"sources":["../src/components/field/error-helpers.ts","../src/components/field/field.tsx","../src/components/field/field-error-messages.ts"],"sourcesContent":["import { Children, Fragment, isValidElement, type ReactNode } from \"react\";\n\n/**\n * A validation message accepted by `Field.Errors`. Non-string absence values\n * are allowed so consumers can pass mapped validator output directly while\n * still rendering only real strings.\n */\ntype FieldErrorMessage = string | null | undefined | false;\n\ntype RenderableContentProps = { children?: ReactNode };\n\n/**\n * Options for checking a manual `Field.ErrorList` subtree.\n */\ntype HasRenderableErrorListChildrenOptions = {\n\t/**\n\t * The list children to inspect before rendering or wiring ARIA IDs.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * The local `Field.ErrorItem` component type from `field.tsx`. Passed in\n\t * (rather than imported) to avoid a circular dependency between\n\t * `field.tsx` and this helpers module.\n\t */\n\terrorItemType: unknown;\n};\n\n/**\n * Normalizes validator output into display-ready message strings without\n * coupling `Field.Errors` to a specific form library's error object shape.\n */\nconst normalizeErrorMessages = (messages: readonly FieldErrorMessage[] | undefined) => {\n\tconst normalizedMessages: string[] = [];\n\tconst seenMessages = new Set<string>();\n\n\tfor (const message of messages ?? []) {\n\t\tif (typeof message !== \"string\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalizedMessage = message.trim();\n\t\tif (normalizedMessage.length === 0 || seenMessages.has(normalizedMessage)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tseenMessages.add(normalizedMessage);\n\t\tnormalizedMessages.push(normalizedMessage);\n\t}\n\n\treturn normalizedMessages;\n};\n\n/**\n * Returns `true` when the supplied children would produce visible content in\n * a `Field.ErrorItem` — i.e. they are not `null`, `undefined`, `false`, or a\n * whitespace-only string. Used by both `Field.ErrorItem`'s render guard and\n * the `Field.ErrorList` walker so an empty item is identified consistently.\n */\nconst isErrorItemRenderable = (children: ReactNode): boolean => {\n\t// Booleans (including `true`) render nothing in React, so a `cond && expr`\n\t// pattern that resolves to `true` would otherwise count as renderable here.\n\tif (children == null || typeof children === \"boolean\") {\n\t\treturn false;\n\t}\n\tif (typeof children === \"string\" && children.trim().length === 0) {\n\t\treturn false;\n\t}\n\treturn true;\n};\n\n/**\n * Empty-detection walker for `Field.ErrorList`. Recurses through Fragments so\n * error items wrapped in conditional `<>…</>` still register, applies\n * `Field.ErrorItem`'s render guard so empty items do not count as content,\n * and treats any other child (custom component, host element, etc.) as\n * opaque-and-therefore-renderable.\n */\nconst hasRenderableErrorListChildren = ({\n\tchildren,\n\terrorItemType,\n}: HasRenderableErrorListChildrenOptions): boolean => {\n\tlet found = false;\n\n\tChildren.forEach(children, (child) => {\n\t\tif (found || child == null || typeof child === \"boolean\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof child === \"string\") {\n\t\t\tif (child.trim().length > 0) {\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!isValidElement<RenderableContentProps>(child)) {\n\t\t\tfound = true;\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === errorItemType) {\n\t\t\tfound = isErrorItemRenderable(child.props.children);\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === Fragment) {\n\t\t\tfound = hasRenderableErrorListChildren({\n\t\t\t\tchildren: child.props.children,\n\t\t\t\terrorItemType,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tfound = true;\n\t});\n\n\treturn found;\n};\n\nexport {\n\t//,\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n};\nexport type {\n\t//,\n\tFieldErrorMessage,\n};\n","import { QuestionIcon } from \"@phosphor-icons/react/Question\";\nimport {\n\tcloneElement,\n\ttype ComponentRef,\n\ttype ComponentProps,\n\tforwardRef,\n\tisValidElement,\n\ttype ReactElement,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseId,\n\tuseMemo,\n\tuseState,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/use-isomorphic-layout-effect.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { IconButton, type IconButtonProps } from \"../button/icon-button.js\";\nimport { Label } from \"../label/label.js\";\nimport { Popover } from \"../popover/index.js\";\nimport { Slot } from \"../slot/index.js\";\nimport {\n\tFieldControlContext,\n\tFieldItemContext,\n\tresolveFieldControlAriaProps,\n\ttype FieldControlAriaProps,\n} from \"./field-context.js\";\nimport {\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n\ttype FieldErrorMessage,\n} from \"./error-helpers.js\";\nimport { FieldValidationProvider, resolveValidation, type WithValidation } from \"./validation.js\";\n\n/**\n * Renders a semantic `<fieldset>` for grouping related controls under a\n * single accessible name. Resets the default browser fieldset chrome\n * (border, padding, `min-width` quirk) so it composes cleanly with\n * `Field.Legend` and `Field.Group`. Always renders a real `<fieldset>` so\n * the grouping semantics cannot be accidentally removed.\n *\n * Reach for `Field.Set` when the grouping carries semantic weight — most\n * commonly a `RadioGroup` (where the legend names the question the radios\n * answer) or a set of related checkboxes. For laying out unrelated fields\n * with consistent spacing, prefer `Field.Group` on its own.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst FieldSet = forwardRef<ComponentRef<\"fieldset\">, ComponentProps<\"fieldset\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<fieldset\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-set\"\n\t\t\t\tclassName={cx(\"flex w-full min-w-0 flex-col gap-4 border-0 p-0\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nFieldSet.displayName = \"FieldSet\";\n\n/**\n * The caption for a `Field.Set`. Always renders a semantic `<legend>` styled\n * to match the `Label` component so a fieldset reads like a section header,\n * and gives screen readers an accessible name for the surrounding group\n * (e.g. \"Notification frequency, group, Daily\").\n *\n * **Spacing.** Has a default `mb-1.5` so the legend sits 6px above the next\n * sibling — matching the figma. We use a margin (not the parent `Field.Set`'s\n * flex `gap`) because `<legend>` has special browser rendering inside a\n * `<fieldset>` that ignores the parent's flex `gap`. Override the default\n * with any `mb-*` utility on `Field.Legend`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst Legend = forwardRef<ComponentRef<\"legend\">, ComponentProps<\"legend\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<legend\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-legend\"\n\t\t\t\t// `mb-1.5` (not the parent's `gap-*`) drives the Legend ↔ next-sibling\n\t\t\t\t// spacing because `<legend>` has special browser rendering inside a\n\t\t\t\t// `<fieldset>` that ignores the parent's flex `gap`. Pairs with\n\t\t\t\t// RadioGroup.Item's own `py-1` for a 10px text-bottom-to-radio rhythm\n\t\t\t\t// matching the figma. Override with any `mb-*` utility on Field.Legend.\n\t\t\t\tclassName={cx(\"text-strong mb-1.5 text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLegend.displayName = \"FieldLegend\";\n\n/**\n * Caption for a `Field.Item`. Renders the Mantle `Label` with the same\n * `htmlFor`, click-to-focus, disabled, and typography behavior — but inside a\n * `Field.Item`, the label-to-control association is automatic: `Field.Item`\n * generates a stable control id, `Field.Control` splats that id onto its\n * focusable child, and `Field.Label` consumes the same id as the default\n * `htmlFor`. The required `name` on `Field.Item` is the single source of truth\n * for the control's form name — no matching `htmlFor` / `id` pair, no separate\n * `useId()` call.\n *\n * Pass an explicit `htmlFor` to opt out — for example when the focusable\n * element is rendered outside of `Field.Control` and the auto-generated id\n * never lands on it.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * // htmlFor is wired automatically from Field.Item's name.\n * <Field.Item name=\"apiKey\">\n * <Field.Label>API key</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * </Field.Item>\n *\n * // Opt out with an explicit htmlFor when needed.\n * <Field.Item name=\"legacy\">\n * <Field.Label htmlFor=\"legacy-control\">Legacy field</Field.Label>\n * <input id=\"legacy-control\" />\n * </Field.Item>\n * ```\n */\nconst FieldLabel = forwardRef<ComponentRef<\"label\">, ComponentProps<typeof Label>>(\n\t({ htmlFor, ...props }, ref) => {\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn <Label ref={ref} htmlFor={htmlFor ?? context?.controlId} {...props} />;\n\t},\n);\nFieldLabel.displayName = \"FieldLabel\";\n\n/**\n * Static, label-styled text for a `Field.Item` row that does **not** caption a\n * focusable form control. Renders a `<p>` (not a `<label>`) with the same\n * typography as `Field.Label`, so a read-only row inside a sheet or details\n * panel composes cleanly next to real form fields without misrepresenting\n * itself as a control caption.\n *\n * **When to use**\n * - A `Field.Item` row that displays a derived or system-managed value\n * (owner, created-at, computed status) where there is no `<input>`,\n * `<select>`, `<button>`, or other focusable target to label.\n * - Read-only summary rows inside a sheet or detail panel that should\n * visually align with sibling `Field.Item`s but have no editable control.\n * - Anywhere you would otherwise hand-roll a `<p>` styled to mimic\n * `Field.Label` typography — prefer this so intent is explicit at the call site.\n *\n * **When not to use**\n * - The row has a focusable control (input, select, checkbox, switch,\n * button trigger). Use `Field.Label` so the click-to-focus and\n * accessible-name association are wired correctly.\n * - For body copy, section headings, or any text whose typography happens\n * to look similar by accident — use the appropriate heading or `<p>`\n * directly. `Field.LabelText` exists specifically to slot into the\n * `Field.Label` position of a `Field.Item`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Item name=\"owner\">\n * <Field.LabelText>Owner</Field.LabelText>\n * <CredentialOwnerCard owner={owner} />\n * <Field.Description>The user or service user that owns this API key.</Field.Description>\n * </Field.Item>\n * ```\n */\nconst LabelText = forwardRef<ComponentRef<\"p\">, ComponentProps<\"p\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-text\"\n\t\t\t\tclassName={cx(\"text-strong text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelText.displayName = \"FieldLabelText\";\n\n/**\n * Horizontal layout container for the label area of a field. Aligns a\n * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n * like a help-icon `Popover.Trigger` on a shared center line with a tight\n * `gap-1`. Center-alignment is used (not baseline) so SVG icon buttons —\n * which have no text baseline — sit visually centered next to the label\n * text rather than dropping to the box bottom.\n *\n * Use this when the label needs sibling decorations that can't live inside\n * the `<Field.Label>` itself (e.g. an interactive help button — clicking inside a\n * `<label>` would forward focus to the associated control). For a label\n * with only an `(Optional)` suffix, place `Field.Optional` directly inside\n * the `<Field.Label>` instead — no `LabelRow` needed.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst LabelRow = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-row\"\n\t\t\t\tclassName={cx(\"flex items-center gap-1\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelRow.displayName = \"FieldLabelRow\";\n\n/**\n * `Popover.Root` re-export for the help-affordance pattern. Pair with\n * `Field.HelpTrigger` (renders a default question-mark `IconButton`) and\n * `Field.HelpContent` (the popover body) to drop a help button into a\n * `Field.LabelRow` without manually wiring `Popover` + `IconButton` +\n * `QuestionIcon`. All `Popover.Root` props are forwarded — pass `modal`,\n * `defaultOpen`, etc. as needed.\n *\n * Popover (not Tooltip) so the affordance is reachable on touch devices.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Help = Popover.Root;\n\n/**\n * Props for the default help popover trigger. A contextual label is required\n * so repeated help affordances do not all share the same accessible name.\n */\ntype FieldHelpTriggerProps = Partial<Omit<IconButtonProps, \"icon\" | \"label\">> &\n\tPick<IconButtonProps, \"label\"> & {\n\t\t/**\n\t\t * The icon to render inside the trigger button. Defaults to a Phosphor\n\t\t * `QuestionIcon` so the most common case only needs a contextual label.\n\t\t */\n\t\ticon?: ReactNode;\n\t};\n\n/**\n * The trigger for a `Field.Help` popover — a `Popover.Trigger` wired to a\n * ghost-appearance `IconButton` with a default Phosphor `QuestionIcon`.\n * Requires a contextual screen-reader label, and accepts `icon` or other\n * `IconButton` props for visual customization.\n *\n * Pre-styled with `text-body` (matching the figma) so the icon reads as\n * subtle metadata at rest; `IconButton`'s ghost `hover:text-strong` still\n * brightens it on interaction. Carries a default `-my-0.5` so the 24px\n * `xs` button keeps a full click target while contributing only 20px to\n * the `Field.LabelRow` flex line — matching the label's text line-height\n * so the label text is not pushed off-center.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpTrigger = forwardRef<ComponentRef<\"button\">, FieldHelpTriggerProps>(\n\t(\n\t\t{\n\t\t\tappearance = \"ghost\",\n\t\t\tclassName,\n\t\t\ticon = <QuestionIcon />,\n\t\t\tlabel,\n\t\t\tsize = \"xs\",\n\t\t\ttype = \"button\",\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Popover.Trigger asChild>\n\t\t\t<IconButton\n\t\t\t\tref={ref}\n\t\t\t\tappearance={appearance}\n\t\t\t\t// `-my-0.5` keeps the 24px (`size-6`) `xs` IconButton click target while\n\t\t\t\t// trimming 4px (2px each side) off its flex-line contribution so the row\n\t\t\t\t// height matches the label's 20px line-height. Without this the trigger\n\t\t\t\t// drives the LabelRow to 24px and pushes the label text down 2px.\n\t\t\t\tclassName={cx(\"text-body -my-0.5\", className)}\n\t\t\t\ticon={icon}\n\t\t\t\tlabel={label}\n\t\t\t\tsize={size}\n\t\t\t\ttype={type}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</Popover.Trigger>\n\t),\n);\nHelpTrigger.displayName = \"FieldHelpTrigger\";\n\n/**\n * The popover body for a `Field.Help`. Wraps `Popover.Content` so all\n * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n * work as expected, and overrides the inherited `data-slot` to\n * `field-help-content` so consumers can target it as part of a `Field`\n * subtree without colliding with other popovers.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpContent = forwardRef<ComponentRef<\"div\">, ComponentProps<typeof Popover.Content>>(\n\t(props, ref) => <Popover.Content ref={ref} data-slot=\"field-help-content\" {...props} />,\n);\nHelpContent.displayName = \"FieldHelpContent\";\n\n/**\n * Inline \"(Optional)\" suffix to mark a field as optional. Defaults to the\n * literal string `(Optional)` so the common case is `<Field.Optional />` with\n * no children — pass children to translate or replace the text. Renders a\n * `<span>` in `text-muted` at `text-sm` / `font-normal` so it reads as\n * secondary metadata next to the bolder Label text.\n *\n * Place inside the `<Field.Label>` so screen readers announce it as part of the\n * accessible name (e.g. \"Email, Optional, edit text\"). Pair with a small\n * `gap` on the label's flex layout, or rely on the natural inline spacing.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Optional = forwardRef<ComponentRef<\"span\">, ComponentProps<\"span\"> & WithAsChild>(\n\t({ asChild, children, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"span\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-optional\"\n\t\t\t\tclassName={cx(\"text-muted text-sm font-normal font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children ?? \"(Optional)\"}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nOptional.displayName = \"FieldOptional\";\n\n/**\n * Layout container that stacks multiple `Field.Item`s vertically with\n * `gap-4` between them. This is the default way to compose multiple fields\n * — most forms only need a `Field.Group` of `Field.Item`s. Reach for\n * `Field.Set` + `Field.Legend` only when the grouping carries semantic\n * weight (e.g. a `RadioGroup` or related checkboxes).\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Group = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-group\"\n\t\t\t\tclassName={cx(\"flex w-full flex-col gap-4\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nGroup.displayName = \"FieldGroup\";\n\n/**\n * A single form field — `Label`, a control (`Input`, `Select`, `Checkbox`,\n * etc.), and any `Field.Description`, `Field.Errors`, or `Field.ErrorList` siblings stacked\n * vertically with a consistent `gap-1.5` so help and error messaging sit\n * tightly under the input.\n *\n * Renders a plain `<div>` — the `<label htmlFor>` ↔ control association\n * already provides the right semantics for a single field, so no implicit\n * `role` is added. `Field.Item` owns the contextual description/error IDs\n * that `Field.Control` applies to the focusable control. Rendered errors\n * infer an `\"error\"` validation state unless `validation` is supplied as an\n * explicit override.\n *\n * **Single-slot constraint.** A `Field.Item` owns one description ID and one\n * errors ID, so render at most one `Field.Description` and one\n * `Field.Errors` *or* `Field.ErrorList` (not both) per item. A second instance\n * would duplicate the slot `id` in the DOM. Pass multiple messages to\n * `Field.Errors`, or multiple `Field.ErrorItem` children to `Field.ErrorList`,\n * instead.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\ntype FieldItemProps = ComponentProps<\"div\"> &\n\tWithAsChild &\n\tWithValidation & {\n\t\t/**\n\t\t * Form-value name for the field. Required so `Field.Control` can splat\n\t\t * it onto the focusable child while `Field.Item` owns the stable\n\t\t * generated control id used by `Field.Label`'s `htmlFor`.\n\t\t */\n\t\tname: string;\n\t};\n\nconst Item = forwardRef<ComponentRef<\"div\">, FieldItemProps>(\n\t({ asChild, children, className, name, validation: validationProp, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\t\tconst controlId = useId();\n\t\tconst descriptionId = useId();\n\t\tconst errorId = useId();\n\t\tconst [hasErrors, setHasErrors] = useState(false);\n\t\tconst validation = resolveValidation(validationProp ?? (hasErrors ? \"error\" : undefined));\n\n\t\tconst registerError = useCallback(() => {\n\t\t\tsetHasErrors(true);\n\n\t\t\treturn () => {\n\t\t\t\tsetHasErrors(false);\n\t\t\t};\n\t\t}, []);\n\n\t\tconst context = useMemo(\n\t\t\t() => ({\n\t\t\t\tcontrolId,\n\t\t\t\tdescriptionId,\n\t\t\t\terrorId,\n\t\t\t\thasErrors,\n\t\t\t\tname,\n\t\t\t\tregisterError,\n\t\t\t\tvalidation,\n\t\t\t}),\n\t\t\t[controlId, descriptionId, errorId, hasErrors, name, registerError, validation],\n\t\t);\n\n\t\treturn (\n\t\t\t<FieldItemContext.Provider value={context}>\n\t\t\t\t<FieldValidationProvider validation={validation}>\n\t\t\t\t\t<Comp\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tdata-slot=\"field-item\"\n\t\t\t\t\t\tdata-validation={validation}\n\t\t\t\t\t\tclassName={cx(\"flex w-full flex-col gap-1.5\", className)}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Comp>\n\t\t\t\t</FieldValidationProvider>\n\t\t\t</FieldItemContext.Provider>\n\t\t);\n\t},\n);\nItem.displayName = \"FieldItem\";\n\ntype FieldControlSlotProps = Omit<\n\tComponentProps<typeof Slot>,\n\t\"aria-describedby\" | \"aria-errormessage\" | \"aria-invalid\" | \"children\"\n>;\n\n/**\n * Element-child form of `Field.Control`. Renders via `Slot`, so it accepts\n * any HTML/Slot props and a forwarded ref — those land on the single child\n * element along with the generated ARIA props.\n */\ntype FieldControlElementProps = FieldControlSlotProps & {\n\t/**\n\t * A single control element to receive the field ARIA props.\n\t */\n\tchildren: ReactElement;\n};\n\n/**\n * Render-prop form of `Field.Control`. The caller owns the rendered element,\n * so `Field.Control` itself renders nothing — extra DOM props and `ref` have\n * no element to attach to and are intentionally not part of this variant.\n * Slot props are marked `never` so passing e.g. `className` alongside a\n * render-prop child is a type error rather than a silently ignored prop.\n */\ntype FieldControlRenderProps = {\n\t/**\n\t * A render function that places the field ARIA props onto a control of\n\t * the caller's choosing. Used for compound controls or wrappers where\n\t * `Slot` cannot reach the focusable element.\n\t */\n\tchildren: (props: FieldControlAriaProps) => ReactNode;\n} & { [K in keyof FieldControlSlotProps]?: never };\n\n/**\n * Props for `Field.Control`. A discriminated union over how the caller\n * supplies the focusable element:\n *\n * - `FieldControlElementProps` — pass a single React element child and\n * `Field.Control` clones the generated ARIA props onto it via `Slot`.\n * Accepts the full Slot prop surface plus a forwarded ref.\n * - `FieldControlRenderProps` — pass a render function that receives the\n * ARIA props and places them on a control of the caller's choosing. The\n * caller owns the rendered element, so DOM/Slot props and `ref` are\n * excluded from this variant at the type level.\n *\n * @example\n * ```tsx\n * // Element form — Slot splats id, name, and ARIA props onto <Input/>\n * <Field.Item name=\"email\">\n * <Field.Control>\n * <Input type=\"email\" />\n * </Field.Control>\n * </Field.Item>\n *\n * // Render-prop form — caller spreads the props onto its own element\n * <Field.Item name=\"acceptTerms\">\n * <Field.Control>\n * {(controlProps) => (\n * <label>\n * Accept terms\n * <input type=\"checkbox\" {...controlProps} />\n * </label>\n * )}\n * </Field.Control>\n * </Field.Item>\n * ```\n */\ntype FieldControlProps = FieldControlElementProps | FieldControlRenderProps;\n\n/**\n * Applies `Field.Item` description, error, and validation state to a single\n * focusable control. It always behaves like an `asChild` slot: pass one child\n * element to receive the generated ARIA props, or use a function child to\n * place those props manually. Mantle compound controls that consume\n * `FieldControlContext` can be wrapped at the root when their docs show that\n * composition; otherwise use the render-prop form to place the generated props\n * on the actual focusable element.\n *\n * `Field.Item` owns the full control contract — `id`, `name`, `aria-*`, and\n * `validation` all flow down from the surrounding `Field.Item` and overwrite\n * anything passed on the child. To override these values, set them on\n * `Field.Item` itself (e.g. `<Field.Item validation=\"error\">`); to opt out of\n * the contract entirely, render your control without `Field.Control`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Control = forwardRef<HTMLElement, FieldControlProps>(({ children, ...props }, ref) => {\n\tconst context = useContext(FieldItemContext);\n\t// Field.Item owns id, name, aria-*, and validation — `cloneElement` below\n\t// overwrites whatever the child supplied, and the resolver no longer reads\n\t// child-side overrides. To override any of these, set them on Field.Item.\n\tconst controlState = resolveFieldControlAriaProps({ context });\n\n\tif (typeof children === \"function\") {\n\t\treturn (\n\t\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t\t{children(controlState.ariaProps)}\n\t\t\t\t</FieldControlContext.Provider>\n\t\t\t</FieldValidationProvider>\n\t\t);\n\t}\n\n\tinvariant(\n\t\tisValidElement<FieldControlAriaProps>(children),\n\t\t\"Field.Control expects a single React element child (or a render-prop function). Got a non-element value (string, array, fragment, null, or undefined). Wrap the control in a single element, or use the function child form: <Field.Control>{(props) => <YourControl {...props} />}</Field.Control>.\",\n\t);\n\n\t// Both `cloneElement` and `FieldControlContext` flow the same resolved\n\t// props. `cloneElement` covers the simple case (Input, native input) where\n\t// the direct child is the focusable element. `FieldControlContext` covers\n\t// compound widgets like Select / MultiSelect, where the direct child is a\n\t// context provider (e.g. `Select.Root`) that does not forward ARIA props\n\t// to its inner focusable trigger — that trigger reads the context itself.\n\treturn (\n\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t<Slot ref={ref} {...props}>\n\t\t\t\t\t{cloneElement(children, controlState.ariaProps)}\n\t\t\t\t</Slot>\n\t\t\t</FieldControlContext.Provider>\n\t\t</FieldValidationProvider>\n\t);\n});\nControl.displayName = \"FieldControl\";\n\n/**\n * Helper / hint text. Renders a `<p>` in the muted body color so it reads\n * as secondary to the bolder content above it. Use inside `Field.Item`, below\n * the control, to clarify expected format or constraints for that single field.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single description\n * slot ID and applies it via context, so a second `Field.Description` would\n * duplicate that `id` in the DOM.\n *\n * **Auto-tighten.** When this description sits directly after rendered\n * `Field.Errors` or `Field.ErrorList` output, the parent's `gap-1.5`\n * collapses via a matching negative top margin so error list + helper read as\n * one tight block. Pass any margin utility (`mt-1`, `mt-0`, etc.) to override\n * — the rule's specificity is flattened to `(0,1,0)` so a single user class wins.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Description = forwardRef<ComponentRef<\"p\">, Omit<ComponentProps<\"p\">, \"id\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-description\"\n\t\t\t\tid={context?.descriptionId}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-body text-sm leading-4\",\n\t\t\t\t\t// When this description sits directly after a Field.ErrorList\n\t\t\t\t\t// sibling, collapse the parent's gap-1.5 with a matching negative\n\t\t\t\t\t// top margin so the list + helper read as one tight block.\n\t\t\t\t\t// Wrapping the matched selector in :where() flattens its specificity\n\t\t\t\t\t// to (0,1,0) so a user-supplied margin utility (mt-2, mt-0, etc.)\n\t\t\t\t\t// passed on Field.Description still overrides cleanly.\n\t\t\t\t\t\"[:where([data-slot=field-error-list]+&)]:-mt-1.5\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nDescription.displayName = \"FieldDescription\";\n\n/**\n * A single error message list item for a field. Renders an `<li>` in\n * `text-danger-600` so it stands out from a sibling `Field.Description`.\n * Must be rendered inside a `Field.ErrorList`. Empty or blank children render\n * nothing so message-less validator results do not produce empty list items.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorItem = forwardRef<ComponentRef<\"li\">, ComponentProps<\"li\">>(\n\t({ children, className, ...props }, ref) => {\n\t\tif (!isErrorItemRenderable(children)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<li\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-error\"\n\t\t\t\tclassName={cx(\"text-danger-600 text-sm leading-4\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</li>\n\t\t);\n\t},\n);\nFieldErrorItem.displayName = \"FieldErrorItem\";\n\n/**\n * Props for the `Field.Errors` convenience renderer. It owns its generated\n * children, so use `Field.ErrorList` / `Field.ErrorItem` directly when custom\n * list contents or polymorphic list markup are needed.\n */\ntype FieldErrorsProps = Omit<ComponentProps<\"ul\">, \"children\" | \"id\"> & {\n\t/**\n\t * Validation messages to render. Strings are trimmed, and empty, nullish,\n\t * or false values are ignored before rendering the list.\n\t */\n\tmessages?: readonly FieldErrorMessage[];\n};\n\n/**\n * Convenience renderer for string validation messages. Trims each message,\n * filters empty values, and renders a semantic `Field.ErrorList` containing\n * one `Field.ErrorItem` per remaining message.\n *\n * Accepts strings directly so product code can map any validation library's\n * error shape into messages without coupling Mantle to that library.\n * Deliberately does not support `asChild` because it owns the generated list\n * items; use `Field.ErrorList` with `asChild` for custom list markup.\n *\n * **At most one per `Field.Item`.** `Field.Errors` renders a `Field.ErrorList`\n * under the hood, and `Field.Item` owns a single errors slot ID. Use either\n * `Field.Errors` *or* `Field.ErrorList` per item, not both, and pass multiple\n * messages to one `Field.Errors` instead of rendering it twice.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrors = forwardRef<ComponentRef<\"ul\">, FieldErrorsProps>(\n\t({ messages, ...props }, ref) => (\n\t\t<FieldErrorList ref={ref} {...props}>\n\t\t\t{normalizeErrorMessages(messages).map((message, index) => (\n\t\t\t\t<FieldErrorItem key={index}>{message}</FieldErrorItem>\n\t\t\t))}\n\t\t</FieldErrorList>\n\t),\n);\nFieldErrors.displayName = \"FieldErrors\";\n\n/**\n * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>` with\n * `role=\"list\"` so a list of validation errors is announced as a list by\n * screen readers, including Safari/VoiceOver combinations that drop list\n * semantics when list styling is removed. Renders nothing when no children are\n * passed, or when all `Field.ErrorItem` children are empty.\n *\n * The list strips its default browser styling (`list-none`, `p-0`, `m-0`) and\n * stacks items as a flex column with no gap so consecutive errors read as a\n * single tight block.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single errors slot ID\n * and applies it via context. Use either `Field.ErrorList` *or* `Field.Errors`\n * per item, not both, and put multiple `Field.ErrorItem` children inside the\n * single list instead of rendering two `Field.ErrorList`s.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorList = forwardRef<\n\tComponentRef<\"ul\">,\n\tOmit<ComponentProps<\"ul\">, \"id\"> & WithAsChild\n>(({ asChild, children, className, ...props }, ref) => {\n\tconst hasRenderableChildren = hasRenderableErrorListChildren({\n\t\tchildren,\n\t\terrorItemType: FieldErrorItem,\n\t});\n\tconst context = useContext(FieldItemContext);\n\tconst registerError = context?.registerError;\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!hasRenderableChildren || registerError == null) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn registerError();\n\t}, [hasRenderableChildren, registerError]);\n\n\tif (!hasRenderableChildren) {\n\t\treturn null;\n\t}\n\n\tconst Comp = asChild ? Slot : \"ul\";\n\n\treturn (\n\t\t<Comp\n\t\t\tref={ref}\n\t\t\tdata-slot=\"field-error-list\"\n\t\t\tid={context?.errorId}\n\t\t\trole=\"list\"\n\t\t\tclassName={cx(\"m-0 flex w-full flex-col list-none p-0\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n});\nFieldErrorList.displayName = \"FieldErrorList\";\n\n/**\n * Compound component for semantic, accessible form fields. Composes a\n * `Field.Label`, control (`Input`, `Select`, etc.), `Field.Description`, and\n * validation errors (`Field.Errors` / `Field.ErrorList` + `Field.ErrorItem`)\n * with consistent spacing and ARIA wiring. Stack multiple fields with\n * `Field.Group`; use `Field.Set` + `Field.Legend` for radios / related\n * checkboxes that share one accessible name.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * Composition:\n * ```\n * Field.Group\n * └── Field.Item\n * ├── Field.LabelRow\n * │ ├── Field.Label (or Field.LabelText for control-less rows)\n * │ │ └── Field.Optional\n * │ └── Field.Help\n * │ ├── Field.HelpTrigger\n * │ └── Field.HelpContent\n * ├── Field.Control\n * │ └── (control)\n * ├── Field.Errors (or)\n * ├── Field.ErrorList\n * │ └── Field.ErrorItem\n * └── Field.Description\n * ```\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Field = {\n\t/**\n\t * A single form field. Provides message IDs and validation state to\n\t * `Field.Control`; rendered errors infer `\"error\"` validation.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * Applies generated field ARIA props and validation state to a single\n\t * focusable control. Accepts either a single React element child (cloned\n\t * via `Slot`) or a render-prop child that receives the ARIA props for\n\t * cases where `Slot` cannot reach the focusable element — for example a\n\t * `<label>`-wrapped native checkbox, or a third-party component that\n\t * needs the props placed manually on an inner input.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * // Element child — Slot splats id, name, and ARIA props onto <Input/>.\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.Label>API key</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * </Field.Item>\n\t * ```\n\t *\n\t * @example\n\t * ```tsx\n\t * // Render-prop child — caller spreads the props onto an inner element\n\t * // when the focusable target is nested (e.g. inside a <label>).\n\t * <Field.Item name=\"acceptTerms\">\n\t * <Field.Control>\n\t * {(controlProps) => (\n\t * <label>\n\t * Accept terms\n\t * <input type=\"checkbox\" {...controlProps} />\n\t * </label>\n\t * )}\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"You must accept the terms.\"]} />\n\t * </Field.Item>\n\t * ```\n\t */\n\tControl,\n\t/**\n\t * Layout container that stacks multiple `Field.Item`s vertically.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tGroup,\n\t/**\n\t * Semantic `<fieldset>` for related controls that share one accessible\n\t * name from `Field.Legend`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tSet: FieldSet,\n\t/**\n\t * Caption for `Field.Set`. Renders a semantic `<legend>`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tLegend,\n\t/**\n\t * The Mantle `Label`, exposed on `Field` for field composition. Inside a\n\t * `Field.Item`, `htmlFor` defaults to the same stable id that `Field.Control`\n\t * splats onto its focusable child — so the label-to-control association is\n\t * automatic from `Field.Item`'s required `name` and you don't need to thread\n\t * a matching `htmlFor` / `id` pair by hand. Pass an explicit `htmlFor` to\n\t * opt out (e.g. when the focusable element is rendered outside of\n\t * `Field.Control`).\n\t *\n\t * @see https://mantle.ngrok.com/components/label\n\t *\n\t * @example\n\t * ```tsx\n\t * // htmlFor is wired automatically from Field.Item's name.\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabel: FieldLabel,\n\t/**\n\t * Static, label-styled text for a `Field.Item` row that has no focusable\n\t * control to caption. Renders a `<p>` with the same typography as\n\t * `Field.Label`, so a read-only row composes cleanly alongside real form\n\t * fields without misrepresenting itself as a control caption.\n\t *\n\t * Use for derived / system-managed values (owner, created-at, computed\n\t * status) inside sheets or detail panels. For rows with a real control,\n\t * use `Field.Label` instead so the label-to-control association is wired.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Item name=\"owner\">\n\t * <Field.LabelText>Owner</Field.LabelText>\n\t * <CredentialOwnerCard owner={owner} />\n\t * <Field.Description>The user or service user that owns this API key.</Field.Description>\n\t * </Field.Item>\n\t * ```\n\t */\n\tLabelText,\n\t/**\n\t * Horizontal layout container for the label area of a field. Aligns a\n\t * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n\t * like a help-icon `Popover.Trigger` on a shared center line with `gap-1`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabelRow,\n\t/**\n\t * `Popover.Root` re-export for the help-affordance pattern. Pair with\n\t * `Field.HelpTrigger` and `Field.HelpContent` to drop a `?` button next to\n\t * a label without manually composing Popover + IconButton + QuestionIcon.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelp,\n\t/**\n\t * Trigger for a `Field.Help` popover — a ghost `IconButton` with a default\n\t * `QuestionIcon`. Requires a contextual `label`; pass `icon` to swap the\n\t * glyph, or other `IconButton` props (`size`, `appearance`, etc.) to customize.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpTrigger,\n\t/**\n\t * Body of a `Field.Help` popover. Re-exports `Popover.Content` so all\n\t * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n\t * work as expected.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpContent,\n\t/**\n\t * Inline \"(Optional)\" suffix to mark a field as optional. Default content\n\t * is `(Optional)`; pass children to translate or replace it. Place inside\n\t * the `<Field.Label>` so screen readers announce it as part of the accessible\n\t * name.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tOptional,\n\t/**\n\t * Helper / hint text rendered below the control in the muted body color.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * Convenience renderer for validation messages. Trims string messages,\n\t * filters empty values, and renders a `Field.ErrorList` with one\n\t * `Field.ErrorItem` for each remaining message.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrors: FieldErrors,\n\t/**\n\t * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>`.\n\t * Renders nothing when given no renderable children.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorList: FieldErrorList,\n\t/**\n\t * A single error message list item for a field. Renders an `<li>` in\n\t * `text-danger-600` and must be nested inside a `Field.ErrorList`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorItem: FieldErrorItem,\n} as const;\n\nexport {\n\t//,\n\tField,\n};\n","import { normalizeErrorMessages } from \"./error-helpers.js\";\n\n/**\n * Shapes commonly found in `field.state.meta.errors` from TanStack React Form\n * across its built-in validators (Standard Schema / Zod issues, raw strings,\n * thrown `Error` instances) plus the falsy slots Standard Schema can produce.\n */\ntype FieldError = { readonly message?: string | undefined } | string | null | undefined | false;\n\n/**\n * Reduce a TanStack React Form field's `meta.errors` array (or any array of\n * mixed string / `{ message }` / nullish error entries) to a clean `string[]`\n * for passing directly to `Field.Errors`' `messages` prop.\n *\n * Handles the shapes TanStack form yields for Zod, Standard Schema, and\n * thrown `Error` validators: items may be strings, objects with `.message`,\n * `undefined`, `null`, or `false`. Empty / whitespace-only messages are\n * dropped and duplicate messages are collapsed so callers don't have to filter\n * again.\n *\n * @example\n * ```tsx\n * <Field.Item>\n * <Field.Label htmlFor={field.name}>Email</Field.Label>\n * <Field.Control>\n * <Input id={field.name} value={field.state.value} />\n * </Field.Control>\n * <Field.Errors messages={toErrorMessages(field.state.meta.errors)} />\n * </Field.Item>\n * ```\n */\nconst toErrorMessages = (errors: readonly FieldError[] | null | undefined): string[] =>\n\tnormalizeErrorMessages(\n\t\terrors?.map((error) => (typeof error === \"string\" || !error ? error : error.message)),\n\t);\n\nexport {\n\t//,\n\ttoErrorMessages,\n};\n\nexport type {\n\t//,\n\tFieldError,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field.js","names":[],"sources":["../src/components/field/error-helpers.ts","../src/components/field/field.tsx","../src/components/field/field-error-messages.ts"],"sourcesContent":["import { Children, Fragment, isValidElement, type ReactNode } from \"react\";\n\n/**\n * A validation message accepted by `Field.Errors`. Non-string absence values\n * are allowed so consumers can pass mapped validator output directly while\n * still rendering only real strings.\n */\ntype FieldErrorMessage = string | null | undefined | false;\n\ntype RenderableContentProps = { children?: ReactNode };\n\n/**\n * Options for checking a manual `Field.ErrorList` subtree.\n */\ntype HasRenderableErrorListChildrenOptions = {\n\t/**\n\t * The list children to inspect before rendering or wiring ARIA IDs.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * The local `Field.ErrorItem` component type from `field.tsx`. Passed in\n\t * (rather than imported) to avoid a circular dependency between\n\t * `field.tsx` and this helpers module.\n\t */\n\terrorItemType: unknown;\n};\n\n/**\n * Normalizes validator output into display-ready message strings without\n * coupling `Field.Errors` to a specific form library's error object shape.\n */\nconst normalizeErrorMessages = (messages: readonly FieldErrorMessage[] | undefined) => {\n\tconst normalizedMessages: string[] = [];\n\tconst seenMessages = new Set<string>();\n\n\tfor (const message of messages ?? []) {\n\t\tif (typeof message !== \"string\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalizedMessage = message.trim();\n\t\tif (normalizedMessage.length === 0 || seenMessages.has(normalizedMessage)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tseenMessages.add(normalizedMessage);\n\t\tnormalizedMessages.push(normalizedMessage);\n\t}\n\n\treturn normalizedMessages;\n};\n\n/**\n * Returns `true` when the supplied children would produce visible content in\n * a `Field.ErrorItem` — i.e. they are not `null`, `undefined`, `false`, or a\n * whitespace-only string. Used by both `Field.ErrorItem`'s render guard and\n * the `Field.ErrorList` walker so an empty item is identified consistently.\n */\nconst isErrorItemRenderable = (children: ReactNode): boolean => {\n\t// Booleans (including `true`) render nothing in React, so a `cond && expr`\n\t// pattern that resolves to `true` would otherwise count as renderable here.\n\tif (children == null || typeof children === \"boolean\") {\n\t\treturn false;\n\t}\n\tif (typeof children === \"string\" && children.trim().length === 0) {\n\t\treturn false;\n\t}\n\treturn true;\n};\n\n/**\n * Empty-detection walker for `Field.ErrorList`. Recurses through Fragments so\n * error items wrapped in conditional `<>…</>` still register, applies\n * `Field.ErrorItem`'s render guard so empty items do not count as content,\n * and treats any other child (custom component, host element, etc.) as\n * opaque-and-therefore-renderable.\n */\nconst hasRenderableErrorListChildren = ({\n\tchildren,\n\terrorItemType,\n}: HasRenderableErrorListChildrenOptions): boolean => {\n\tlet found = false;\n\n\tChildren.forEach(children, (child) => {\n\t\tif (found || child == null || typeof child === \"boolean\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (typeof child === \"string\") {\n\t\t\tif (child.trim().length > 0) {\n\t\t\t\tfound = true;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!isValidElement<RenderableContentProps>(child)) {\n\t\t\tfound = true;\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === errorItemType) {\n\t\t\tfound = isErrorItemRenderable(child.props.children);\n\t\t\treturn;\n\t\t}\n\n\t\tif (child.type === Fragment) {\n\t\t\tfound = hasRenderableErrorListChildren({\n\t\t\t\tchildren: child.props.children,\n\t\t\t\terrorItemType,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tfound = true;\n\t});\n\n\treturn found;\n};\n\nexport {\n\t//,\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n};\nexport type {\n\t//,\n\tFieldErrorMessage,\n};\n","import { QuestionIcon } from \"@phosphor-icons/react/Question\";\nimport {\n\tcloneElement,\n\ttype ComponentRef,\n\ttype ComponentProps,\n\tforwardRef,\n\tisValidElement,\n\ttype ReactElement,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseId,\n\tuseMemo,\n\tuseState,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { useIsomorphicLayoutEffect } from \"../../hooks/use-isomorphic-layout-effect.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { IconButton, type IconButtonProps } from \"../button/icon-button.js\";\nimport { Label } from \"../label/label.js\";\nimport { Popover } from \"../popover/index.js\";\nimport { Slot } from \"../slot/index.js\";\nimport {\n\tFieldControlContext,\n\tFieldItemContext,\n\tresolveFieldControlAriaProps,\n\ttype FieldControlAriaProps,\n} from \"./field-context.js\";\nimport {\n\thasRenderableErrorListChildren,\n\tisErrorItemRenderable,\n\tnormalizeErrorMessages,\n\ttype FieldErrorMessage,\n} from \"./error-helpers.js\";\nimport { FieldValidationProvider, resolveValidation, type WithValidation } from \"./validation.js\";\n\n/**\n * Renders a semantic `<fieldset>` for grouping related controls under a\n * single accessible name. Resets the default browser fieldset chrome\n * (border, padding, `min-width` quirk) so it composes cleanly with\n * `Field.Legend` and `Field.Group`. Always renders a real `<fieldset>` so\n * the grouping semantics cannot be accidentally removed.\n *\n * Reach for `Field.Set` when the grouping carries semantic weight — most\n * commonly a `RadioGroup` (where the legend names the question the radios\n * answer) or a set of related checkboxes. For laying out unrelated fields\n * with consistent spacing, prefer `Field.Group` on its own.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst FieldSet = forwardRef<ComponentRef<\"fieldset\">, ComponentProps<\"fieldset\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<fieldset\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-set\"\n\t\t\t\tclassName={cx(\"flex w-full min-w-0 flex-col gap-4 border-0 p-0\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nFieldSet.displayName = \"FieldSet\";\n\n/**\n * The caption for a `Field.Set`. Always renders a semantic `<legend>` styled\n * to match the `Label` component so a fieldset reads like a section header,\n * and gives screen readers an accessible name for the surrounding group\n * (e.g. \"Notification frequency, group, Daily\").\n *\n * **Spacing.** Has a default `mb-1.5` so the legend sits 6px above the next\n * sibling — matching the figma. We use a margin (not the parent `Field.Set`'s\n * flex `gap`) because `<legend>` has special browser rendering inside a\n * `<fieldset>` that ignores the parent's flex `gap`. Override the default\n * with any `mb-*` utility on `Field.Legend`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Set>\n * <Field.Legend>Notification frequency</Field.Legend>\n * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n * </RadioGroup.Root>\n * </Field.Set>\n * ```\n */\nconst Legend = forwardRef<ComponentRef<\"legend\">, ComponentProps<\"legend\">>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<legend\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-legend\"\n\t\t\t\t// `mb-1.5` (not the parent's `gap-*`) drives the Legend ↔ next-sibling\n\t\t\t\t// spacing because `<legend>` has special browser rendering inside a\n\t\t\t\t// `<fieldset>` that ignores the parent's flex `gap`. Pairs with\n\t\t\t\t// RadioGroup.Item's own `py-1` for a 10px text-bottom-to-radio rhythm\n\t\t\t\t// matching the figma. Override with any `mb-*` utility on Field.Legend.\n\t\t\t\tclassName={cx(\"text-strong mb-1.5 text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLegend.displayName = \"FieldLegend\";\n\n/**\n * Caption for a `Field.Item`. Renders the Mantle `Label` with the same\n * `htmlFor`, click-to-focus, disabled, and typography behavior — but inside a\n * `Field.Item`, the label-to-control association is automatic: `Field.Item`\n * generates a stable control id, `Field.Control` splats that id onto its\n * focusable child, and `Field.Label` consumes the same id as the default\n * `htmlFor`. The required `name` on `Field.Item` is the single source of truth\n * for the control's form name — no matching `htmlFor` / `id` pair, no separate\n * `useId()` call.\n *\n * Pass an explicit `htmlFor` to opt out — for example when the focusable\n * element is rendered outside of `Field.Control` and the auto-generated id\n * never lands on it.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * // htmlFor is wired automatically from Field.Item's name.\n * <Field.Item name=\"apiKey\">\n * <Field.Label>API key</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * </Field.Item>\n *\n * // Opt out with an explicit htmlFor when needed.\n * <Field.Item name=\"legacy\">\n * <Field.Label htmlFor=\"legacy-control\">Legacy field</Field.Label>\n * <input id=\"legacy-control\" />\n * </Field.Item>\n * ```\n */\nconst FieldLabel = forwardRef<ComponentRef<\"label\">, ComponentProps<typeof Label>>(\n\t({ htmlFor, ...props }, ref) => {\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn <Label ref={ref} htmlFor={htmlFor ?? context?.controlId} {...props} />;\n\t},\n);\nFieldLabel.displayName = \"FieldLabel\";\n\n/**\n * Static, label-styled text for a `Field.Item` row that does **not** caption a\n * focusable form control. Renders a `<p>` (not a `<label>`) with the same\n * typography as `Field.Label`, so a read-only row inside a sheet or details\n * panel composes cleanly next to real form fields without misrepresenting\n * itself as a control caption.\n *\n * **When to use**\n * - A `Field.Item` row that displays a derived or system-managed value\n * (owner, created-at, computed status) where there is no `<input>`,\n * `<select>`, `<button>`, or other focusable target to label.\n * - Read-only summary rows inside a sheet or detail panel that should\n * visually align with sibling `Field.Item`s but have no editable control.\n * - Anywhere you would otherwise hand-roll a `<p>` styled to mimic\n * `Field.Label` typography — prefer this so intent is explicit at the call site.\n *\n * **When not to use**\n * - The row has a focusable control (input, select, checkbox, switch,\n * button trigger). Use `Field.Label` so the click-to-focus and\n * accessible-name association are wired correctly.\n * - For body copy, section headings, or any text whose typography happens\n * to look similar by accident — use the appropriate heading or `<p>`\n * directly. `Field.LabelText` exists specifically to slot into the\n * `Field.Label` position of a `Field.Item`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Item name=\"owner\">\n * <Field.LabelText>Owner</Field.LabelText>\n * <CredentialOwnerCard owner={owner} />\n * <Field.Description>The user or service user that owns this API key.</Field.Description>\n * </Field.Item>\n * ```\n */\nconst LabelText = forwardRef<ComponentRef<\"p\">, ComponentProps<\"p\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-text\"\n\t\t\t\tclassName={cx(\"text-strong text-sm font-medium font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelText.displayName = \"FieldLabelText\";\n\n/**\n * Horizontal layout container for the label area of a field. Aligns a\n * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n * like a help-icon `Popover.Trigger` on a shared center line with a tight\n * `gap-1`. Center-alignment is used (not baseline) so SVG icon buttons —\n * which have no text baseline — sit visually centered next to the label\n * text rather than dropping to the box bottom.\n *\n * Use this when the label needs sibling decorations that can't live inside\n * the `<Field.Label>` itself (e.g. an interactive help button — clicking inside a\n * `<label>` would forward focus to the associated control). For a label\n * with only an `(Optional)` suffix, place `Field.Optional` directly inside\n * the `<Field.Label>` instead — no `LabelRow` needed.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst LabelRow = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-label-row\"\n\t\t\t\tclassName={cx(\"flex items-center gap-1\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nLabelRow.displayName = \"FieldLabelRow\";\n\n/**\n * `Popover.Root` re-export for the help-affordance pattern. Pair with\n * `Field.HelpTrigger` (renders a default question-mark `IconButton`) and\n * `Field.HelpContent` (the popover body) to drop a help button into a\n * `Field.LabelRow` without manually wiring `Popover` + `IconButton` +\n * `QuestionIcon`. All `Popover.Root` props are forwarded — pass `modal`,\n * `defaultOpen`, etc. as needed.\n *\n * Popover (not Tooltip) so the affordance is reachable on touch devices.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Help = Popover.Root;\n\nconst defaultHelpTriggerIcon = <QuestionIcon />;\n\n/**\n * Props for the default help popover trigger. A contextual label is required\n * so repeated help affordances do not all share the same accessible name.\n */\ntype FieldHelpTriggerProps = Partial<Omit<IconButtonProps, \"icon\" | \"label\">> &\n\tPick<IconButtonProps, \"label\"> & {\n\t\t/**\n\t\t * The icon to render inside the trigger button. Defaults to a Phosphor\n\t\t * `QuestionIcon` so the most common case only needs a contextual label.\n\t\t */\n\t\ticon?: ReactNode;\n\t};\n\n/**\n * The trigger for a `Field.Help` popover — a `Popover.Trigger` wired to a\n * ghost-appearance `IconButton` with a default Phosphor `QuestionIcon`.\n * Requires a contextual screen-reader label, and accepts `icon` or other\n * `IconButton` props for visual customization.\n *\n * Pre-styled with `text-body` (matching the figma) so the icon reads as\n * subtle metadata at rest; `IconButton`'s ghost `hover:text-strong` still\n * brightens it on interaction. Carries a default `-my-0.5` so the 24px\n * `xs` button keeps a full click target while contributing only 20px to\n * the `Field.LabelRow` flex line — matching the label's text line-height\n * so the label text is not pushed off-center.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpTrigger = forwardRef<ComponentRef<\"button\">, FieldHelpTriggerProps>(\n\t(\n\t\t{\n\t\t\tappearance = \"ghost\",\n\t\t\tclassName,\n\t\t\ticon = defaultHelpTriggerIcon,\n\t\t\tlabel,\n\t\t\tsize = \"xs\",\n\t\t\ttype = \"button\",\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Popover.Trigger asChild>\n\t\t\t<IconButton\n\t\t\t\tref={ref}\n\t\t\t\tappearance={appearance}\n\t\t\t\t// `-my-0.5` keeps the 24px (`size-6`) `xs` IconButton click target while\n\t\t\t\t// trimming 4px (2px each side) off its flex-line contribution so the row\n\t\t\t\t// height matches the label's 20px line-height. Without this the trigger\n\t\t\t\t// drives the LabelRow to 24px and pushes the label text down 2px.\n\t\t\t\tclassName={cx(\"text-body -my-0.5\", className)}\n\t\t\t\ticon={icon}\n\t\t\t\tlabel={label}\n\t\t\t\tsize={size}\n\t\t\t\ttype={type}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</Popover.Trigger>\n\t),\n);\nHelpTrigger.displayName = \"FieldHelpTrigger\";\n\n/**\n * The popover body for a `Field.Help`. Wraps `Popover.Content` so all\n * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n * work as expected, and overrides the inherited `data-slot` to\n * `field-help-content` so consumers can target it as part of a `Field`\n * subtree without colliding with other popovers.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst HelpContent = forwardRef<ComponentRef<\"div\">, ComponentProps<typeof Popover.Content>>(\n\t(props, ref) => <Popover.Content ref={ref} data-slot=\"field-help-content\" {...props} />,\n);\nHelpContent.displayName = \"FieldHelpContent\";\n\n/**\n * Inline \"(Optional)\" suffix to mark a field as optional. Defaults to the\n * literal string `(Optional)` so the common case is `<Field.Optional />` with\n * no children — pass children to translate or replace the text. Renders a\n * `<span>` in `text-muted` at `text-sm` / `font-normal` so it reads as\n * secondary metadata next to the bolder Label text.\n *\n * Place inside the `<Field.Label>` so screen readers announce it as part of the\n * accessible name (e.g. \"Email, Optional, edit text\"). Pair with a small\n * `gap` on the label's flex layout, or rely on the natural inline spacing.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Optional = forwardRef<ComponentRef<\"span\">, ComponentProps<\"span\"> & WithAsChild>(\n\t({ asChild, children, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"span\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-optional\"\n\t\t\t\tclassName={cx(\"text-muted text-sm font-normal font-sans\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children ?? \"(Optional)\"}\n\t\t\t</Comp>\n\t\t);\n\t},\n);\nOptional.displayName = \"FieldOptional\";\n\n/**\n * Layout container that stacks multiple `Field.Item`s vertically with\n * `gap-4` between them. This is the default way to compose multiple fields\n * — most forms only need a `Field.Group` of `Field.Item`s. Reach for\n * `Field.Set` + `Field.Legend` only when the grouping carries semantic\n * weight (e.g. a `RadioGroup` or related checkboxes).\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Group = forwardRef<ComponentRef<\"div\">, ComponentProps<\"div\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-group\"\n\t\t\t\tclassName={cx(\"flex w-full flex-col gap-4\", className)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nGroup.displayName = \"FieldGroup\";\n\n/**\n * A single form field — `Label`, a control (`Input`, `Select`, `Checkbox`,\n * etc.), and any `Field.Description`, `Field.Errors`, or `Field.ErrorList` siblings stacked\n * vertically with a consistent `gap-1.5` so help and error messaging sit\n * tightly under the input.\n *\n * Renders a plain `<div>` — the `<label htmlFor>` ↔ control association\n * already provides the right semantics for a single field, so no implicit\n * `role` is added. `Field.Item` owns the contextual description/error IDs\n * that `Field.Control` applies to the focusable control. Rendered errors\n * infer an `\"error\"` validation state unless `validation` is supplied as an\n * explicit override.\n *\n * **Single-slot constraint.** A `Field.Item` owns one description ID and one\n * errors ID, so render at most one `Field.Description` and one\n * `Field.Errors` *or* `Field.ErrorList` (not both) per item. A second instance\n * would duplicate the slot `id` in the DOM. Pass multiple messages to\n * `Field.Errors`, or multiple `Field.ErrorItem` children to `Field.ErrorList`,\n * instead.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\ntype FieldItemProps = ComponentProps<\"div\"> &\n\tWithAsChild &\n\tWithValidation & {\n\t\t/**\n\t\t * Form-value name for the field. Required so `Field.Control` can splat\n\t\t * it onto the focusable child while `Field.Item` owns the stable\n\t\t * generated control id used by `Field.Label`'s `htmlFor`.\n\t\t */\n\t\tname: string;\n\t};\n\nconst Item = forwardRef<ComponentRef<\"div\">, FieldItemProps>(\n\t({ asChild, children, className, name, validation: validationProp, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"div\";\n\t\tconst controlId = useId();\n\t\tconst descriptionId = useId();\n\t\tconst errorId = useId();\n\t\tconst [hasErrors, setHasErrors] = useState(false);\n\t\tconst validation = resolveValidation(validationProp ?? (hasErrors ? \"error\" : undefined));\n\n\t\tconst registerError = useCallback(() => {\n\t\t\tsetHasErrors(true);\n\n\t\t\treturn () => {\n\t\t\t\tsetHasErrors(false);\n\t\t\t};\n\t\t}, []);\n\n\t\tconst context = useMemo(\n\t\t\t() => ({\n\t\t\t\tcontrolId,\n\t\t\t\tdescriptionId,\n\t\t\t\terrorId,\n\t\t\t\thasErrors,\n\t\t\t\tname,\n\t\t\t\tregisterError,\n\t\t\t\tvalidation,\n\t\t\t}),\n\t\t\t[controlId, descriptionId, errorId, hasErrors, name, registerError, validation],\n\t\t);\n\n\t\treturn (\n\t\t\t<FieldItemContext.Provider value={context}>\n\t\t\t\t<FieldValidationProvider validation={validation}>\n\t\t\t\t\t<Comp\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tdata-slot=\"field-item\"\n\t\t\t\t\t\tdata-validation={validation}\n\t\t\t\t\t\tclassName={cx(\"flex w-full flex-col gap-1.5\", className)}\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Comp>\n\t\t\t\t</FieldValidationProvider>\n\t\t\t</FieldItemContext.Provider>\n\t\t);\n\t},\n);\nItem.displayName = \"FieldItem\";\n\ntype FieldControlSlotProps = Omit<\n\tComponentProps<typeof Slot>,\n\t\"aria-describedby\" | \"aria-errormessage\" | \"aria-invalid\" | \"children\"\n>;\n\n/**\n * Element-child form of `Field.Control`. Renders via `Slot`, so it accepts\n * any HTML/Slot props and a forwarded ref — those land on the single child\n * element along with the generated ARIA props.\n */\ntype FieldControlElementProps = FieldControlSlotProps & {\n\t/**\n\t * A single control element to receive the field ARIA props.\n\t */\n\tchildren: ReactElement;\n};\n\n/**\n * Render-prop form of `Field.Control`. The caller owns the rendered element,\n * so `Field.Control` itself renders nothing — extra DOM props and `ref` have\n * no element to attach to and are intentionally not part of this variant.\n * Slot props are marked `never` so passing e.g. `className` alongside a\n * render-prop child is a type error rather than a silently ignored prop.\n */\ntype FieldControlRenderProps = {\n\t/**\n\t * A render function that places the field ARIA props onto a control of\n\t * the caller's choosing. Used for compound controls or wrappers where\n\t * `Slot` cannot reach the focusable element.\n\t */\n\tchildren: (props: FieldControlAriaProps) => ReactNode;\n} & { [K in keyof FieldControlSlotProps]?: never };\n\n/**\n * Props for `Field.Control`. A discriminated union over how the caller\n * supplies the focusable element:\n *\n * - `FieldControlElementProps` — pass a single React element child and\n * `Field.Control` clones the generated ARIA props onto it via `Slot`.\n * Accepts the full Slot prop surface plus a forwarded ref.\n * - `FieldControlRenderProps` — pass a render function that receives the\n * ARIA props and places them on a control of the caller's choosing. The\n * caller owns the rendered element, so DOM/Slot props and `ref` are\n * excluded from this variant at the type level.\n *\n * @example\n * ```tsx\n * // Element form — Slot splats id, name, and ARIA props onto <Input/>\n * <Field.Item name=\"email\">\n * <Field.Control>\n * <Input type=\"email\" />\n * </Field.Control>\n * </Field.Item>\n *\n * // Render-prop form — caller spreads the props onto its own element\n * <Field.Item name=\"acceptTerms\">\n * <Field.Control>\n * {(controlProps) => (\n * <label>\n * Accept terms\n * <input type=\"checkbox\" {...controlProps} />\n * </label>\n * )}\n * </Field.Control>\n * </Field.Item>\n * ```\n */\ntype FieldControlProps = FieldControlElementProps | FieldControlRenderProps;\n\n/**\n * Applies `Field.Item` description, error, and validation state to a single\n * focusable control. It always behaves like an `asChild` slot: pass one child\n * element to receive the generated ARIA props, or use a function child to\n * place those props manually. Mantle compound controls that consume\n * `FieldControlContext` can be wrapped at the root when their docs show that\n * composition; otherwise use the render-prop form to place the generated props\n * on the actual focusable element.\n *\n * `Field.Item` owns the full control contract — `id`, `name`, `aria-*`, and\n * `validation` all flow down from the surrounding `Field.Item` and overwrite\n * anything passed on the child. To override these values, set them on\n * `Field.Item` itself (e.g. `<Field.Item validation=\"error\">`); to opt out of\n * the contract entirely, render your control without `Field.Control`.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Control = forwardRef<HTMLElement, FieldControlProps>(({ children, ...props }, ref) => {\n\tconst context = useContext(FieldItemContext);\n\t// Field.Item owns id, name, aria-*, and validation — `cloneElement` below\n\t// overwrites whatever the child supplied, and the resolver no longer reads\n\t// child-side overrides. To override any of these, set them on Field.Item.\n\tconst controlState = resolveFieldControlAriaProps({ context });\n\n\tif (typeof children === \"function\") {\n\t\treturn (\n\t\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t\t{children(controlState.ariaProps)}\n\t\t\t\t</FieldControlContext.Provider>\n\t\t\t</FieldValidationProvider>\n\t\t);\n\t}\n\n\tinvariant(\n\t\tisValidElement<FieldControlAriaProps>(children),\n\t\t\"Field.Control expects a single React element child (or a render-prop function). Got a non-element value (string, array, fragment, null, or undefined). Wrap the control in a single element, or use the function child form: <Field.Control>{(props) => <YourControl {...props} />}</Field.Control>.\",\n\t);\n\n\t// Both `cloneElement` and `FieldControlContext` flow the same resolved\n\t// props. `cloneElement` covers the simple case (Input, native input) where\n\t// the direct child is the focusable element. `FieldControlContext` covers\n\t// compound widgets like Select / MultiSelect, where the direct child is a\n\t// context provider (e.g. `Select.Root`) that does not forward ARIA props\n\t// to its inner focusable trigger — that trigger reads the context itself.\n\treturn (\n\t\t<FieldValidationProvider validation={controlState.validation}>\n\t\t\t<FieldControlContext.Provider value={context ? controlState.ariaProps : null}>\n\t\t\t\t<Slot ref={ref} {...props}>\n\t\t\t\t\t{cloneElement(children, controlState.ariaProps)}\n\t\t\t\t</Slot>\n\t\t\t</FieldControlContext.Provider>\n\t\t</FieldValidationProvider>\n\t);\n});\nControl.displayName = \"FieldControl\";\n\n/**\n * Helper / hint text. Renders a `<p>` in the muted body color so it reads\n * as secondary to the bolder content above it. Use inside `Field.Item`, below\n * the control, to clarify expected format or constraints for that single field.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single description\n * slot ID and applies it via context, so a second `Field.Description` would\n * duplicate that `id` in the DOM.\n *\n * **Auto-tighten.** When this description sits directly after rendered\n * `Field.Errors` or `Field.ErrorList` output, the parent's `gap-1.5`\n * collapses via a matching negative top margin so error list + helper read as\n * one tight block. Pass any margin utility (`mt-1`, `mt-0`, etc.) to override\n * — the rule's specificity is flattened to `(0,1,0)` so a single user class wins.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Description = forwardRef<ComponentRef<\"p\">, Omit<ComponentProps<\"p\">, \"id\"> & WithAsChild>(\n\t({ asChild, className, ...props }, ref) => {\n\t\tconst Comp = asChild ? Slot : \"p\";\n\t\tconst context = useContext(FieldItemContext);\n\n\t\treturn (\n\t\t\t<Comp\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-description\"\n\t\t\t\tid={context?.descriptionId}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-body text-sm leading-4\",\n\t\t\t\t\t// When this description sits directly after a Field.ErrorList\n\t\t\t\t\t// sibling, collapse the parent's gap-1.5 with a matching negative\n\t\t\t\t\t// top margin so the list + helper read as one tight block.\n\t\t\t\t\t// Wrapping the matched selector in :where() flattens its specificity\n\t\t\t\t\t// to (0,1,0) so a user-supplied margin utility (mt-2, mt-0, etc.)\n\t\t\t\t\t// passed on Field.Description still overrides cleanly.\n\t\t\t\t\t\"[:where([data-slot=field-error-list]+&)]:-mt-1.5\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nDescription.displayName = \"FieldDescription\";\n\n/**\n * A single error message list item for a field. Renders an `<li>` in\n * `text-danger-600` so it stands out from a sibling `Field.Description`.\n * Must be rendered inside a `Field.ErrorList`. Empty or blank children render\n * nothing so message-less validator results do not produce empty list items.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorItem = forwardRef<ComponentRef<\"li\">, ComponentProps<\"li\">>(\n\t({ children, className, ...props }, ref) => {\n\t\tif (!isErrorItemRenderable(children)) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<li\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"field-error\"\n\t\t\t\tclassName={cx(\"text-danger-600 text-sm leading-4\", className)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</li>\n\t\t);\n\t},\n);\nFieldErrorItem.displayName = \"FieldErrorItem\";\n\n/**\n * Props for the `Field.Errors` convenience renderer. It owns its generated\n * children, so use `Field.ErrorList` / `Field.ErrorItem` directly when custom\n * list contents or polymorphic list markup are needed.\n */\ntype FieldErrorsProps = Omit<ComponentProps<\"ul\">, \"children\" | \"id\"> & {\n\t/**\n\t * Validation messages to render. Strings are trimmed, and empty, nullish,\n\t * or false values are ignored before rendering the list.\n\t */\n\tmessages?: readonly FieldErrorMessage[];\n};\n\n/**\n * Convenience renderer for string validation messages. Trims each message,\n * filters empty values, and renders a semantic `Field.ErrorList` containing\n * one `Field.ErrorItem` per remaining message.\n *\n * Accepts strings directly so product code can map any validation library's\n * error shape into messages without coupling Mantle to that library.\n * Deliberately does not support `asChild` because it owns the generated list\n * items; use `Field.ErrorList` with `asChild` for custom list markup.\n *\n * **At most one per `Field.Item`.** `Field.Errors` renders a `Field.ErrorList`\n * under the hood, and `Field.Item` owns a single errors slot ID. Use either\n * `Field.Errors` *or* `Field.ErrorList` per item, not both, and pass multiple\n * messages to one `Field.Errors` instead of rendering it twice.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrors = forwardRef<ComponentRef<\"ul\">, FieldErrorsProps>(\n\t({ messages, ...props }, ref) => (\n\t\t<FieldErrorList ref={ref} {...props}>\n\t\t\t{normalizeErrorMessages(messages).map((message) => (\n\t\t\t\t<FieldErrorItem key={message}>{message}</FieldErrorItem>\n\t\t\t))}\n\t\t</FieldErrorList>\n\t),\n);\nFieldErrors.displayName = \"FieldErrors\";\n\n/**\n * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>` with\n * `role=\"list\"` so a list of validation errors is announced as a list by\n * screen readers, including Safari/VoiceOver combinations that drop list\n * semantics when list styling is removed. Renders nothing when no children are\n * passed, or when all `Field.ErrorItem` children are empty.\n *\n * The list strips its default browser styling (`list-none`, `p-0`, `m-0`) and\n * stacks items as a flex column with no gap so consecutive errors read as a\n * single tight block.\n *\n * **At most one per `Field.Item`.** `Field.Item` owns a single errors slot ID\n * and applies it via context. Use either `Field.ErrorList` *or* `Field.Errors`\n * per item, not both, and put multiple `Field.ErrorItem` children inside the\n * single list instead of rendering two `Field.ErrorList`s.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"username\">\n * <Field.Label>Username</Field.Label>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.ErrorList>\n * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n * </Field.ErrorList>\n * <Field.Description>Pick something memorable.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst FieldErrorList = forwardRef<\n\tComponentRef<\"ul\">,\n\tOmit<ComponentProps<\"ul\">, \"id\"> & WithAsChild\n>(({ asChild, children, className, ...props }, ref) => {\n\tconst hasRenderableChildren = hasRenderableErrorListChildren({\n\t\tchildren,\n\t\terrorItemType: FieldErrorItem,\n\t});\n\tconst context = useContext(FieldItemContext);\n\tconst registerError = context?.registerError;\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!hasRenderableChildren || registerError == null) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn registerError();\n\t}, [hasRenderableChildren, registerError]);\n\n\tif (!hasRenderableChildren) {\n\t\treturn null;\n\t}\n\n\tconst Comp = asChild ? Slot : \"ul\";\n\n\treturn (\n\t\t<Comp\n\t\t\tref={ref}\n\t\t\tdata-slot=\"field-error-list\"\n\t\t\tid={context?.errorId}\n\t\t\trole=\"list\"\n\t\t\tclassName={cx(\"m-0 flex w-full flex-col list-none p-0\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Comp>\n\t);\n});\nFieldErrorList.displayName = \"FieldErrorList\";\n\n/**\n * Compound component for semantic, accessible form fields. Composes a\n * `Field.Label`, control (`Input`, `Select`, etc.), `Field.Description`, and\n * validation errors (`Field.Errors` / `Field.ErrorList` + `Field.ErrorItem`)\n * with consistent spacing and ARIA wiring. Stack multiple fields with\n * `Field.Group`; use `Field.Set` + `Field.Legend` for radios / related\n * checkboxes that share one accessible name.\n *\n * @see https://mantle.ngrok.com/components/field\n *\n * @example\n * Composition:\n * ```\n * Field.Group\n * └── Field.Item\n * ├── Field.LabelRow\n * │ ├── Field.Label (or Field.LabelText for control-less rows)\n * │ │ └── Field.Optional\n * │ └── Field.Help\n * │ ├── Field.HelpTrigger\n * │ └── Field.HelpContent\n * ├── Field.Control\n * │ └── (control)\n * ├── Field.Errors (or)\n * ├── Field.ErrorList\n * │ └── Field.ErrorItem\n * └── Field.Description\n * ```\n *\n * @example\n * ```tsx\n * <Field.Group>\n * <Field.Item name=\"apiKey\">\n * <Field.LabelRow>\n * <Field.Label>\n * API key <Field.Optional />\n * </Field.Label>\n * <Field.Help>\n * <Field.HelpTrigger label=\"What is an API key?\" />\n * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n * </Field.Help>\n * </Field.LabelRow>\n * <Field.Control>\n * <Input />\n * </Field.Control>\n * <Field.Errors messages={[\"API key is required.\"]} />\n * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n * </Field.Item>\n * </Field.Group>\n * ```\n */\nconst Field = {\n\t/**\n\t * A single form field. Provides message IDs and validation state to\n\t * `Field.Control`; rendered errors infer `\"error\"` validation.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * Applies generated field ARIA props and validation state to a single\n\t * focusable control. Accepts either a single React element child (cloned\n\t * via `Slot`) or a render-prop child that receives the ARIA props for\n\t * cases where `Slot` cannot reach the focusable element — for example a\n\t * `<label>`-wrapped native checkbox, or a third-party component that\n\t * needs the props placed manually on an inner input.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * // Element child — Slot splats id, name, and ARIA props onto <Input/>.\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.Label>API key</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * </Field.Item>\n\t * ```\n\t *\n\t * @example\n\t * ```tsx\n\t * // Render-prop child — caller spreads the props onto an inner element\n\t * // when the focusable target is nested (e.g. inside a <label>).\n\t * <Field.Item name=\"acceptTerms\">\n\t * <Field.Control>\n\t * {(controlProps) => (\n\t * <label>\n\t * Accept terms\n\t * <input type=\"checkbox\" {...controlProps} />\n\t * </label>\n\t * )}\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"You must accept the terms.\"]} />\n\t * </Field.Item>\n\t * ```\n\t */\n\tControl,\n\t/**\n\t * Layout container that stacks multiple `Field.Item`s vertically.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tGroup,\n\t/**\n\t * Semantic `<fieldset>` for related controls that share one accessible\n\t * name from `Field.Legend`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tSet: FieldSet,\n\t/**\n\t * Caption for `Field.Set`. Renders a semantic `<legend>`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Set>\n\t * <Field.Legend>Notification frequency</Field.Legend>\n\t * <RadioGroup.Root name=\"frequency\" defaultValue=\"daily\">\n\t * <RadioGroup.Item value=\"daily\" id=\"freq-daily\">…</RadioGroup.Item>\n\t * <RadioGroup.Item value=\"weekly\" id=\"freq-weekly\">…</RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * </Field.Set>\n\t * ```\n\t */\n\tLegend,\n\t/**\n\t * The Mantle `Label`, exposed on `Field` for field composition. Inside a\n\t * `Field.Item`, `htmlFor` defaults to the same stable id that `Field.Control`\n\t * splats onto its focusable child — so the label-to-control association is\n\t * automatic from `Field.Item`'s required `name` and you don't need to thread\n\t * a matching `htmlFor` / `id` pair by hand. Pass an explicit `htmlFor` to\n\t * opt out (e.g. when the focusable element is rendered outside of\n\t * `Field.Control`).\n\t *\n\t * @see https://mantle.ngrok.com/components/label\n\t *\n\t * @example\n\t * ```tsx\n\t * // htmlFor is wired automatically from Field.Item's name.\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabel: FieldLabel,\n\t/**\n\t * Static, label-styled text for a `Field.Item` row that has no focusable\n\t * control to caption. Renders a `<p>` with the same typography as\n\t * `Field.Label`, so a read-only row composes cleanly alongside real form\n\t * fields without misrepresenting itself as a control caption.\n\t *\n\t * Use for derived / system-managed values (owner, created-at, computed\n\t * status) inside sheets or detail panels. For rows with a real control,\n\t * use `Field.Label` instead so the label-to-control association is wired.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Item name=\"owner\">\n\t * <Field.LabelText>Owner</Field.LabelText>\n\t * <CredentialOwnerCard owner={owner} />\n\t * <Field.Description>The user or service user that owns this API key.</Field.Description>\n\t * </Field.Item>\n\t * ```\n\t */\n\tLabelText,\n\t/**\n\t * Horizontal layout container for the label area of a field. Aligns a\n\t * `<Field.Label>` (which may contain `Field.Optional`) with adjacent affordances\n\t * like a help-icon `Popover.Trigger` on a shared center line with `gap-1`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tLabelRow,\n\t/**\n\t * `Popover.Root` re-export for the help-affordance pattern. Pair with\n\t * `Field.HelpTrigger` and `Field.HelpContent` to drop a `?` button next to\n\t * a label without manually composing Popover + IconButton + QuestionIcon.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelp,\n\t/**\n\t * Trigger for a `Field.Help` popover — a ghost `IconButton` with a default\n\t * `QuestionIcon`. Requires a contextual `label`; pass `icon` to swap the\n\t * glyph, or other `IconButton` props (`size`, `appearance`, etc.) to customize.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpTrigger,\n\t/**\n\t * Body of a `Field.Help` popover. Re-exports `Popover.Content` so all\n\t * positioning / sizing options (`side`, `align`, `preferredWidth`, etc.)\n\t * work as expected.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tHelpContent,\n\t/**\n\t * Inline \"(Optional)\" suffix to mark a field as optional. Default content\n\t * is `(Optional)`; pass children to translate or replace it. Place inside\n\t * the `<Field.Label>` so screen readers announce it as part of the accessible\n\t * name.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tOptional,\n\t/**\n\t * Helper / hint text rendered below the control in the muted body color.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tDescription,\n\t/**\n\t * Convenience renderer for validation messages. Trims string messages,\n\t * filters empty values, and renders a `Field.ErrorList` with one\n\t * `Field.ErrorItem` for each remaining message.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"apiKey\">\n\t * <Field.LabelRow>\n\t * <Field.Label>\n\t * API key <Field.Optional />\n\t * </Field.Label>\n\t * <Field.Help>\n\t * <Field.HelpTrigger label=\"What is an API key?\" />\n\t * <Field.HelpContent>Copy this from the dashboard.</Field.HelpContent>\n\t * </Field.Help>\n\t * </Field.LabelRow>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.Errors messages={[\"API key is required.\"]} />\n\t * <Field.Description>You can find this in the ngrok dashboard.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrors: FieldErrors,\n\t/**\n\t * Wraps one or more `Field.ErrorItem` children in a semantic `<ul>`.\n\t * Renders nothing when given no renderable children.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorList: FieldErrorList,\n\t/**\n\t * A single error message list item for a field. Renders an `<li>` in\n\t * `text-danger-600` and must be nested inside a `Field.ErrorList`.\n\t *\n\t * @see https://mantle.ngrok.com/components/field\n\t *\n\t * @example\n\t * ```tsx\n\t * <Field.Group>\n\t * <Field.Item name=\"username\">\n\t * <Field.Label>Username</Field.Label>\n\t * <Field.Control>\n\t * <Input />\n\t * </Field.Control>\n\t * <Field.ErrorList>\n\t * <Field.ErrorItem>Must be at least 3 characters.</Field.ErrorItem>\n\t * <Field.ErrorItem>Use letters, numbers, hyphens, or underscores.</Field.ErrorItem>\n\t * </Field.ErrorList>\n\t * <Field.Description>Pick something memorable.</Field.Description>\n\t * </Field.Item>\n\t * </Field.Group>\n\t * ```\n\t */\n\tErrorItem: FieldErrorItem,\n} as const;\n\nexport {\n\t//,\n\tField,\n};\n","import { normalizeErrorMessages } from \"./error-helpers.js\";\n\n/**\n * Shapes commonly found in `field.state.meta.errors` from TanStack React Form\n * across its built-in validators (Standard Schema / Zod issues, raw strings,\n * thrown `Error` instances) plus the falsy slots Standard Schema can produce.\n */\ntype FieldError = { readonly message?: string | undefined } | string | null | undefined | false;\n\n/**\n * Reduce a TanStack React Form field's `meta.errors` array (or any array of\n * mixed string / `{ message }` / nullish error entries) to a clean `string[]`\n * for passing directly to `Field.Errors`' `messages` prop.\n *\n * Handles the shapes TanStack form yields for Zod, Standard Schema, and\n * thrown `Error` validators: items may be strings, objects with `.message`,\n * `undefined`, `null`, or `false`. Empty / whitespace-only messages are\n * dropped and duplicate messages are collapsed so callers don't have to filter\n * again.\n *\n * @example\n * ```tsx\n * <Field.Item>\n * <Field.Label htmlFor={field.name}>Email</Field.Label>\n * <Field.Control>\n * <Input id={field.name} value={field.state.value} />\n * </Field.Control>\n * <Field.Errors messages={toErrorMessages(field.state.meta.errors)} />\n * </Field.Item>\n * ```\n */\nconst toErrorMessages = (errors: readonly FieldError[] | null | undefined): string[] =>\n\tnormalizeErrorMessages(\n\t\terrors?.map((error) => (typeof error === \"string\" || !error ? error : error.message)),\n\t);\n\nexport {\n\t//,\n\ttoErrorMessages,\n};\n\nexport type {\n\t//,\n\tFieldError,\n};\n"],"mappings":"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"}
|
package/dist/flag.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ComponentProps } from "react";
|
|
2
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
2
|
|
|
4
3
|
//#region src/components/flag/country-code.d.ts
|
|
5
4
|
/** All valid values for a flag
|
|
@@ -82,7 +81,7 @@ declare function Flag({
|
|
|
82
81
|
size,
|
|
83
82
|
loading,
|
|
84
83
|
...props
|
|
85
|
-
}: Props):
|
|
84
|
+
}: Props): import("react/jsx-runtime").JSX.Element;
|
|
86
85
|
declare namespace Flag {
|
|
87
86
|
var displayName: string;
|
|
88
87
|
}
|
package/dist/flag.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-
|
|
1
|
+
import{t as e}from"./cx-CBSnSC36.js";import{jsx as t,jsxs as n}from"react/jsx-runtime";import{cva as r}from"class-variance-authority";const i=r(``,{variants:{size:{s:`rounded-[0.0625rem]`,m:`rounded-[0.09375rem]`,l:`rounded-xs`}}}),a=r(``,{variants:{size:{s:`w-4 h-3`,m:`w-5 h-3.75`,l:`w-8 h-6`}}});function o({className:r,code:o,size:s=`l`,loading:c=`lazy`,...l}){let u=i({size:s});return n(`div`,{"data-slot":`flag`,className:e(`flag relative overflow-hidden`,u,a({size:s}),r),...l,children:[t(`div`,{"aria-hidden":!0,className:e(`absolute inset-0 border border-[#000]/10`,u)}),t(`img`,{className:`h-full w-full block object-cover`,src:`https://assets.ngrok.com/flags/${s}/${o}.svg`,alt:`flag for ${o}`,loading:c})]})}o.displayName=`Flag`;const s=`004.008.010.016.016.020.024.028.031.032.040.044.048.050.051.052.056.060.064.068.070.072.074.076.084.086.090.092.096.100.104.108.112.116.120.124.132.136.140.144.148.152.156.158.162.166.170.174.178.180.184.188.191.192.196.203.204.208.212.214.218.222.226.231.232.233.234.238.239.242.246.248.250.254.258.260.262.266.268.270.275.276.288.292.296.300.304.308.312.316.320.324.328.332.334.336.340.344.348.352.356.360.364.368.372.376.380.384.388.392.398.400.404.408.410.414.417.418.422.426.428.430.434.438.440.442.446.450.454.458.462.466.470.474.478.480.484.492.496.498.499.500.504.508.512.516.520.524.528.531.533.534.540.548.554.558.562.566.570.574.578.580.581.583.584.585.586.591.598.600.604.608.612.616.620.624.626.630.634.638.642.643.646.652.654.659.660.662.663.666.670.674.678.682.686.688.690.694.702.703.704.705.706.710.716.724.728.729.732.740.744.748.752.756.760.762.764.768.772.776.780.784.788.792.795.796.798.800.804.807.818.831.832.833.834.836.840.850.854.858.860.862.876.882.887.894.ABW.AD.AE.AF.AFG.AFRUN.AG.AGO.AI.AIA.AL.ALA.ALB.AM.AMS.AND.AO.AQ.AR.ARE.ARG.ARM.AS.ASM.AT.ATA.ATF.ATG.AU.AUS.AUT.AW.AX.AZ.AZE.BA.BB.BD.BDI.BE.BEL.BEN.BF.BFA.BG.BGD.BGR.BH.BHR.BHS.BI.BIH.BJ.BL.BLM.BLR.BLZ.BM.BMU.BN.BO.BOL.BQ-BO.BQ-SA.BQ-SE.BR.BRA.BRB.BRN.BS.BT.BTN.BV.BVT.BW.BWA.BY.BZ.CA.CAF.CAN.CC.CCK.CD.CF.CG.CH.CHE.CHL.CHN.CI.CIV.CK.CL.CM.CMR.CN.CO.COD.COG.COK.COL.COM.CPV.CR.CRI.CU.CUB.CUW.CV.CW.CX.CXR.CY.CYM.CYP.CZ.CZE.DE.DEU.DJ.DJI.DK.DM.DMA.DNK.DO.DOM.EC.ECU.EE.EG.EGY.EH.ER.ERI.ES.ESH.ESP.EST.ET.ETH.EU.FI.FIN.FJ.FJI.FK.FLK.FM.FO.FR.FRA.FRO.FSM.GA.GAB.GB-ENG.GB-NIR.GB-SCT.GB-UKM.GB-WLS.GB.GBR.GD.GE.GEO.GF.GG.GGY.GH.GHA.GI.GIB.GIN.GL.GLP.GM.GMB.GN.GNB.GNQ.GP.GQ.GR.GRC.GRD.GRL.GS.GT.GTM.GU.GUF.GUM.GUY.GW.GY.HK.HKG.HM.HMD.HN.HND.HR.HRV.HT.HTI.HU.HUN.ID.IDN.IE.IL.IM.IMN.IN.IND.IO.IOT.IQ.IR.IRL.IRN.IRQ.IS.ISL.ISR.IT.ITA.JAM.JE.JEY.JM.JO.JOR.JP.JPN.KAZ.KE.KEN.KG.KGZ.KH.KHM.KI.KIR.KM.KN-SK.KNA.KOR.KP.KR.KW.KWT.KY.KZ.LA.LAO.LB.LBN.LBR.LBY.LC.LCA.LI.LIE.LK.LKA.LR.LS.LSO.LT.LTU.LU.LUX.LV.LVA.LY.MA.MAC.MAF.MAR.MC.MCO.MD.MDA.MDG.MDV.ME.MEX.MF.MG.MH.MHL.MK.MKD.ML.MLI.MLT.MM.MMR.MN.MNE.MNG.MNP.MO.MOZ.MP.MQ.MR.MRT.MS.MSR.MT.MTQ.MU.MUS.MV.MW.MWI.MX.MY.MYS.MZ.NA.NAM.NC.NCL.NE.NER.NF.NFK.NG.NGA.NI.NIC.NIU.NL.NLD.NO.NOR.NP.NPL.NR.NRU.NU.NZ.NZL.OM.OMN.PA.PAK.PAN.PCN.PE.PER.PF.PG.PH.PHL.PK.PL.PLW.PM.PN.PNG.POL.PR.PRI.PRK.PRT.PRY.PS.PSE.PT.PW.PY.PYF.QA.QAT.RAINBOW.RE.REU.RO.ROU.RS.RU.RUS.RW.RWA.SA.SAU.SB.SC.SD.SDN.SE.SEN.SG.SGP.SGS.SH.SHN.SI.SJ.SJM.SK.SL.SLB.SLE.SLV.SM.SMR.SN.SO.SOM.SPM.SR.SRB.SS.SSD.ST.STP.SUR.SV.SVK.SVN.SWE.SWZ.SX.SXM.SY.SYC.SYR.SZ.TC.TCA.TCD.TD.TF.TG.TGO.TH.THA.TJ.TJK.TK.TKL.TKM.TL.TLS.TM.TN.TO.TON.TR.TT.TTO.TUN.TUR.TUV.TV.TW.TWN.TZ.TZA.UA.UG.UGA.UKR.UM.UMI.UNASUR.URY.US.USA.UY.UZ.UZB.VA.VAT.VC.VCT.VE.VEN.VG.VGB.VI.VIR.VN.VNM.VU.VUT.WF.WLF.WS.WSM.YE.YEM.ZA.ZAF.ZM.ZMB.ZW.ZWE`.split(`.`);function c(e){return s.includes(e)}export{o as Flag,s as countryCodes,c as isCountryCode};
|
|
2
2
|
//# sourceMappingURL=flag.js.map
|
package/dist/flag.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flag.js","names":[],"sources":["../src/components/flag/flag.tsx","../src/components/flag/country-code.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\nimport type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { CountryCode } from \"./country-code.js\";\n\nconst cdnOrigin = \"https://assets.ngrok.com\";\n\nconst sizes = [\"s\", \"m\", \"l\"] as const;\ntype Size = (typeof sizes)[number];\n\ntype Props = Omit<ComponentProps<\"div\">, \"children\"> & {\n\t/**\n\t * The country code for the flag to display\n\t * @example \"US\"\n\t */\n\tcode: CountryCode;\n\t/**\n\t * The size of flag to render, \"s\", \"m\", or \"l\"\n\t * @default \"l\"\n\t */\n\tsize?: Size;\n\t/**\n\t * A string providing a hint to the user agent as to how to best schedule the loading of the image to optimize page performance.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading\n\t * @default \"lazy\"\n\t */\n\tloading?: ComponentProps<\"img\">[\"loading\"];\n};\n\nconst borderRadiusVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"rounded-[0.0625rem]\",\n\t\t\tm: \"rounded-[0.09375rem]\",\n\t\t\tl: \"rounded-xs\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\nconst sizingVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"w-4 h-3\",\n\t\t\tm: \"w-5 h-3.75\",\n\t\t\tl: \"w-8 h-6\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\n/**\n * Renders a country flag from an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)\n * country code, served as an SVG from ngrok's CDN. Inspired by\n * [react-flagpack](https://flagpack.xyz/docs/development/react).\n *\n * **When to use**\n * - Showing the country associated with a region, IP, billing address, or locale.\n * - Inside a select option, list row, or status pill that needs a quick visual cue.\n *\n * **When not to use**\n * - As a stand-in for language. Flags ≠ languages — Brazilian Portuguese is\n * not \"Portugal\", Spanish is not just \"Spain\". Use a language label instead.\n * - As decoration where the country isn't meaningful to the user.\n *\n * **Sizing.** `\"s\"` (16×12), `\"m\"` (20×15), and `\"l\"` (32×24, default) match\n * common inline, list, and table contexts. Pick the size that matches its\n * neighbors so the flag doesn't dominate or disappear.\n *\n * **Accessibility.** The underlying `<img>` is given `alt=\"flag for {code}\"`.\n * If the country is decorative or already labeled in adjacent text, consider\n * passing `aria-hidden` via the wrapper `<div>` to avoid duplicate\n * announcements.\n *\n * **Loading.** Defaults to `loading=\"lazy\"`. Use `loading=\"eager\"` for flags\n * above the fold or in critical content.\n *\n * @see https://mantle.ngrok.com/components/flag#flag\n *\n * @example\n * ```tsx\n * import { Flag } from \"@ngrok/mantle/flag\";\n *\n * <Flag code=\"US\" />\n * <Flag code=\"JP\" size=\"m\" loading=\"eager\" />\n * <Flag code=\"CA\" size=\"s\" />\n *\n * // Inline next to a country label.\n * <span className=\"inline-flex items-center gap-2\">\n * <Flag code=\"GB\" size=\"s\" aria-hidden />\n * <span>United Kingdom</span>\n * </span>\n * ```\n */\nfunction Flag({\n\t//,\n\tclassName,\n\tcode,\n\tsize = \"l\",\n\tloading = \"lazy\",\n\t...props\n}: Props) {\n\tconst borderRadius = borderRadiusVariants({ size });\n\tconst sizing = sizingVariants({ size });\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"flag\"\n\t\t\tclassName={cx(\"flag relative overflow-hidden\", borderRadius, sizing, className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div aria-hidden className={cx(\"absolute inset-0 border border-[#000]/10\", borderRadius)} />\n\t\t\t<img\n\t\t\t\tclassName=\"h-full w-full block object-cover\"\n\t\t\t\tsrc={`${cdnOrigin}/flags/${size}/${code}.svg`}\n\t\t\t\talt={`flag for ${code}`}\n\t\t\t\tloading={loading}\n\t\t\t/>\n\t\t</div>\n\t);\n}\nFlag.displayName = \"Flag\";\n\nexport {\n\t//,\n\tFlag,\n};\n\nexport type {\n\t//,\n\tProps as FlagProps,\n};\n","/** All valid values for a flag\n * @see https://www.flagpack.xyz/docs/flag-index\n */\nconst countryCodes = [\n\t\"004\",\n\t\"008\",\n\t\"010\",\n\t\"016\",\n\t\"016\",\n\t\"020\",\n\t\"024\",\n\t\"028\",\n\t\"031\",\n\t\"032\",\n\t\"040\",\n\t\"044\",\n\t\"048\",\n\t\"050\",\n\t\"051\",\n\t\"052\",\n\t\"056\",\n\t\"060\",\n\t\"064\",\n\t\"068\",\n\t\"070\",\n\t\"072\",\n\t\"074\",\n\t\"076\",\n\t\"084\",\n\t\"086\",\n\t\"090\",\n\t\"092\",\n\t\"096\",\n\t\"100\",\n\t\"104\",\n\t\"108\",\n\t\"112\",\n\t\"116\",\n\t\"120\",\n\t\"124\",\n\t\"132\",\n\t\"136\",\n\t\"140\",\n\t\"144\",\n\t\"148\",\n\t\"152\",\n\t\"156\",\n\t\"158\",\n\t\"162\",\n\t\"166\",\n\t\"170\",\n\t\"174\",\n\t\"178\",\n\t\"180\",\n\t\"184\",\n\t\"188\",\n\t\"191\",\n\t\"192\",\n\t\"196\",\n\t\"203\",\n\t\"204\",\n\t\"208\",\n\t\"212\",\n\t\"214\",\n\t\"218\",\n\t\"222\",\n\t\"226\",\n\t\"231\",\n\t\"232\",\n\t\"233\",\n\t\"234\",\n\t\"238\",\n\t\"239\",\n\t\"242\",\n\t\"246\",\n\t\"248\",\n\t\"250\",\n\t\"254\",\n\t\"258\",\n\t\"260\",\n\t\"262\",\n\t\"266\",\n\t\"268\",\n\t\"270\",\n\t\"275\",\n\t\"276\",\n\t\"288\",\n\t\"292\",\n\t\"296\",\n\t\"300\",\n\t\"304\",\n\t\"308\",\n\t\"312\",\n\t\"316\",\n\t\"320\",\n\t\"324\",\n\t\"328\",\n\t\"332\",\n\t\"334\",\n\t\"336\",\n\t\"340\",\n\t\"344\",\n\t\"348\",\n\t\"352\",\n\t\"356\",\n\t\"360\",\n\t\"364\",\n\t\"368\",\n\t\"372\",\n\t\"376\",\n\t\"380\",\n\t\"384\",\n\t\"388\",\n\t\"392\",\n\t\"398\",\n\t\"400\",\n\t\"404\",\n\t\"408\",\n\t\"410\",\n\t\"414\",\n\t\"417\",\n\t\"418\",\n\t\"422\",\n\t\"426\",\n\t\"428\",\n\t\"430\",\n\t\"434\",\n\t\"438\",\n\t\"440\",\n\t\"442\",\n\t\"446\",\n\t\"450\",\n\t\"454\",\n\t\"458\",\n\t\"462\",\n\t\"466\",\n\t\"470\",\n\t\"474\",\n\t\"478\",\n\t\"480\",\n\t\"484\",\n\t\"492\",\n\t\"496\",\n\t\"498\",\n\t\"499\",\n\t\"500\",\n\t\"504\",\n\t\"508\",\n\t\"512\",\n\t\"516\",\n\t\"520\",\n\t\"524\",\n\t\"528\",\n\t\"531\",\n\t\"533\",\n\t\"534\",\n\t\"540\",\n\t\"548\",\n\t\"554\",\n\t\"558\",\n\t\"562\",\n\t\"566\",\n\t\"570\",\n\t\"574\",\n\t\"578\",\n\t\"580\",\n\t\"581\",\n\t\"583\",\n\t\"584\",\n\t\"585\",\n\t\"586\",\n\t\"591\",\n\t\"598\",\n\t\"600\",\n\t\"604\",\n\t\"608\",\n\t\"612\",\n\t\"616\",\n\t\"620\",\n\t\"624\",\n\t\"626\",\n\t\"630\",\n\t\"634\",\n\t\"638\",\n\t\"642\",\n\t\"643\",\n\t\"646\",\n\t\"652\",\n\t\"654\",\n\t\"659\",\n\t\"660\",\n\t\"662\",\n\t\"663\",\n\t\"666\",\n\t\"670\",\n\t\"674\",\n\t\"678\",\n\t\"682\",\n\t\"686\",\n\t\"688\",\n\t\"690\",\n\t\"694\",\n\t\"702\",\n\t\"703\",\n\t\"704\",\n\t\"705\",\n\t\"706\",\n\t\"710\",\n\t\"716\",\n\t\"724\",\n\t\"728\",\n\t\"729\",\n\t\"732\",\n\t\"740\",\n\t\"744\",\n\t\"748\",\n\t\"752\",\n\t\"756\",\n\t\"760\",\n\t\"762\",\n\t\"764\",\n\t\"768\",\n\t\"772\",\n\t\"776\",\n\t\"780\",\n\t\"784\",\n\t\"788\",\n\t\"792\",\n\t\"795\",\n\t\"796\",\n\t\"798\",\n\t\"800\",\n\t\"804\",\n\t\"807\",\n\t\"818\",\n\t\"831\",\n\t\"832\",\n\t\"833\",\n\t\"834\",\n\t\"836\",\n\t\"840\",\n\t\"850\",\n\t\"854\",\n\t\"858\",\n\t\"860\",\n\t\"862\",\n\t\"876\",\n\t\"882\",\n\t\"887\",\n\t\"894\",\n\t\"ABW\",\n\t\"AD\",\n\t\"AE\",\n\t\"AF\",\n\t\"AFG\",\n\t\"AFRUN\",\n\t\"AG\",\n\t\"AGO\",\n\t\"AI\",\n\t\"AIA\",\n\t\"AL\",\n\t\"ALA\",\n\t\"ALB\",\n\t\"AM\",\n\t\"AMS\",\n\t\"AND\",\n\t\"AO\",\n\t\"AQ\",\n\t\"AR\",\n\t\"ARE\",\n\t\"ARG\",\n\t\"ARM\",\n\t\"AS\",\n\t\"ASM\",\n\t\"AT\",\n\t\"ATA\",\n\t\"ATF\",\n\t\"ATG\",\n\t\"AU\",\n\t\"AUS\",\n\t\"AUT\",\n\t\"AW\",\n\t\"AX\",\n\t\"AZ\",\n\t\"AZE\",\n\t\"BA\",\n\t\"BB\",\n\t\"BD\",\n\t\"BDI\",\n\t\"BE\",\n\t\"BEL\",\n\t\"BEN\",\n\t\"BF\",\n\t\"BFA\",\n\t\"BG\",\n\t\"BGD\",\n\t\"BGR\",\n\t\"BH\",\n\t\"BHR\",\n\t\"BHS\",\n\t\"BI\",\n\t\"BIH\",\n\t\"BJ\",\n\t\"BL\",\n\t\"BLM\",\n\t\"BLR\",\n\t\"BLZ\",\n\t\"BM\",\n\t\"BMU\",\n\t\"BN\",\n\t\"BO\",\n\t\"BOL\",\n\t\"BQ-BO\",\n\t\"BQ-SA\",\n\t\"BQ-SE\",\n\t\"BR\",\n\t\"BRA\",\n\t\"BRB\",\n\t\"BRN\",\n\t\"BS\",\n\t\"BT\",\n\t\"BTN\",\n\t\"BV\",\n\t\"BVT\",\n\t\"BW\",\n\t\"BWA\",\n\t\"BY\",\n\t\"BZ\",\n\t\"CA\",\n\t\"CAF\",\n\t\"CAN\",\n\t\"CC\",\n\t\"CCK\",\n\t\"CD\",\n\t\"CF\",\n\t\"CG\",\n\t\"CH\",\n\t\"CHE\",\n\t\"CHL\",\n\t\"CHN\",\n\t\"CI\",\n\t\"CIV\",\n\t\"CK\",\n\t\"CL\",\n\t\"CM\",\n\t\"CMR\",\n\t\"CN\",\n\t\"CO\",\n\t\"COD\",\n\t\"COG\",\n\t\"COK\",\n\t\"COL\",\n\t\"COM\",\n\t\"CPV\",\n\t\"CR\",\n\t\"CRI\",\n\t\"CU\",\n\t\"CUB\",\n\t\"CUW\",\n\t\"CV\",\n\t\"CW\",\n\t\"CX\",\n\t\"CXR\",\n\t\"CY\",\n\t\"CYM\",\n\t\"CYP\",\n\t\"CZ\",\n\t\"CZE\",\n\t\"DE\",\n\t\"DEU\",\n\t\"DJ\",\n\t\"DJI\",\n\t\"DK\",\n\t\"DM\",\n\t\"DMA\",\n\t\"DNK\",\n\t\"DO\",\n\t\"DOM\",\n\t\"EC\",\n\t\"ECU\",\n\t\"EE\",\n\t\"EG\",\n\t\"EGY\",\n\t\"EH\",\n\t\"ER\",\n\t\"ERI\",\n\t\"ES\",\n\t\"ESH\",\n\t\"ESP\",\n\t\"EST\",\n\t\"ET\",\n\t\"ETH\",\n\t\"EU\",\n\t\"FI\",\n\t\"FIN\",\n\t\"FJ\",\n\t\"FJI\",\n\t\"FK\",\n\t\"FLK\",\n\t\"FM\",\n\t\"FO\",\n\t\"FR\",\n\t\"FRA\",\n\t\"FRO\",\n\t\"FSM\",\n\t\"GA\",\n\t\"GAB\",\n\t\"GB-ENG\",\n\t\"GB-NIR\",\n\t\"GB-SCT\",\n\t\"GB-UKM\",\n\t\"GB-WLS\",\n\t\"GB\",\n\t\"GBR\",\n\t\"GD\",\n\t\"GE\",\n\t\"GEO\",\n\t\"GF\",\n\t\"GG\",\n\t\"GGY\",\n\t\"GH\",\n\t\"GHA\",\n\t\"GI\",\n\t\"GIB\",\n\t\"GIN\",\n\t\"GL\",\n\t\"GLP\",\n\t\"GM\",\n\t\"GMB\",\n\t\"GN\",\n\t\"GNB\",\n\t\"GNQ\",\n\t\"GP\",\n\t\"GQ\",\n\t\"GR\",\n\t\"GRC\",\n\t\"GRD\",\n\t\"GRL\",\n\t\"GS\",\n\t\"GT\",\n\t\"GTM\",\n\t\"GU\",\n\t\"GUF\",\n\t\"GUM\",\n\t\"GUY\",\n\t\"GW\",\n\t\"GY\",\n\t\"HK\",\n\t\"HKG\",\n\t\"HM\",\n\t\"HMD\",\n\t\"HN\",\n\t\"HND\",\n\t\"HR\",\n\t\"HRV\",\n\t\"HT\",\n\t\"HTI\",\n\t\"HU\",\n\t\"HUN\",\n\t\"ID\",\n\t\"IDN\",\n\t\"IE\",\n\t\"IL\",\n\t\"IM\",\n\t\"IMN\",\n\t\"IN\",\n\t\"IND\",\n\t\"IO\",\n\t\"IOT\",\n\t\"IQ\",\n\t\"IR\",\n\t\"IRL\",\n\t\"IRN\",\n\t\"IRQ\",\n\t\"IS\",\n\t\"ISL\",\n\t\"ISR\",\n\t\"IT\",\n\t\"ITA\",\n\t\"JAM\",\n\t\"JE\",\n\t\"JEY\",\n\t\"JM\",\n\t\"JO\",\n\t\"JOR\",\n\t\"JP\",\n\t\"JPN\",\n\t\"KAZ\",\n\t\"KE\",\n\t\"KEN\",\n\t\"KG\",\n\t\"KGZ\",\n\t\"KH\",\n\t\"KHM\",\n\t\"KI\",\n\t\"KIR\",\n\t\"KM\",\n\t\"KN-SK\",\n\t\"KNA\",\n\t\"KOR\",\n\t\"KP\",\n\t\"KR\",\n\t\"KW\",\n\t\"KWT\",\n\t\"KY\",\n\t\"KZ\",\n\t\"LA\",\n\t\"LAO\",\n\t\"LB\",\n\t\"LBN\",\n\t\"LBR\",\n\t\"LBY\",\n\t\"LC\",\n\t\"LCA\",\n\t\"LI\",\n\t\"LIE\",\n\t\"LK\",\n\t\"LKA\",\n\t\"LR\",\n\t\"LS\",\n\t\"LSO\",\n\t\"LT\",\n\t\"LTU\",\n\t\"LU\",\n\t\"LUX\",\n\t\"LV\",\n\t\"LVA\",\n\t\"LY\",\n\t\"MA\",\n\t\"MAC\",\n\t\"MAF\",\n\t\"MAR\",\n\t\"MC\",\n\t\"MCO\",\n\t\"MD\",\n\t\"MDA\",\n\t\"MDG\",\n\t\"MDV\",\n\t\"ME\",\n\t\"MEX\",\n\t\"MF\",\n\t\"MG\",\n\t\"MH\",\n\t\"MHL\",\n\t\"MK\",\n\t\"MKD\",\n\t\"ML\",\n\t\"MLI\",\n\t\"MLT\",\n\t\"MM\",\n\t\"MMR\",\n\t\"MN\",\n\t\"MNE\",\n\t\"MNG\",\n\t\"MNP\",\n\t\"MO\",\n\t\"MOZ\",\n\t\"MP\",\n\t\"MQ\",\n\t\"MR\",\n\t\"MRT\",\n\t\"MS\",\n\t\"MSR\",\n\t\"MT\",\n\t\"MTQ\",\n\t\"MU\",\n\t\"MUS\",\n\t\"MV\",\n\t\"MW\",\n\t\"MWI\",\n\t\"MX\",\n\t\"MY\",\n\t\"MYS\",\n\t\"MZ\",\n\t\"NA\",\n\t\"NAM\",\n\t\"NC\",\n\t\"NCL\",\n\t\"NE\",\n\t\"NER\",\n\t\"NF\",\n\t\"NFK\",\n\t\"NG\",\n\t\"NGA\",\n\t\"NI\",\n\t\"NIC\",\n\t\"NIU\",\n\t\"NL\",\n\t\"NLD\",\n\t\"NO\",\n\t\"NOR\",\n\t\"NP\",\n\t\"NPL\",\n\t\"NR\",\n\t\"NRU\",\n\t\"NU\",\n\t\"NZ\",\n\t\"NZL\",\n\t\"OM\",\n\t\"OMN\",\n\t\"PA\",\n\t\"PAK\",\n\t\"PAN\",\n\t\"PCN\",\n\t\"PE\",\n\t\"PER\",\n\t\"PF\",\n\t\"PG\",\n\t\"PH\",\n\t\"PHL\",\n\t\"PK\",\n\t\"PL\",\n\t\"PLW\",\n\t\"PM\",\n\t\"PN\",\n\t\"PNG\",\n\t\"POL\",\n\t\"PR\",\n\t\"PRI\",\n\t\"PRK\",\n\t\"PRT\",\n\t\"PRY\",\n\t\"PS\",\n\t\"PSE\",\n\t\"PT\",\n\t\"PW\",\n\t\"PY\",\n\t\"PYF\",\n\t\"QA\",\n\t\"QAT\",\n\t\"RAINBOW\",\n\t\"RE\",\n\t\"REU\",\n\t\"RO\",\n\t\"ROU\",\n\t\"RS\",\n\t\"RU\",\n\t\"RUS\",\n\t\"RW\",\n\t\"RWA\",\n\t\"SA\",\n\t\"SAU\",\n\t\"SB\",\n\t\"SC\",\n\t\"SD\",\n\t\"SDN\",\n\t\"SE\",\n\t\"SEN\",\n\t\"SG\",\n\t\"SGP\",\n\t\"SGS\",\n\t\"SH\",\n\t\"SHN\",\n\t\"SI\",\n\t\"SJ\",\n\t\"SJM\",\n\t\"SK\",\n\t\"SL\",\n\t\"SLB\",\n\t\"SLE\",\n\t\"SLV\",\n\t\"SM\",\n\t\"SMR\",\n\t\"SN\",\n\t\"SO\",\n\t\"SOM\",\n\t\"SPM\",\n\t\"SR\",\n\t\"SRB\",\n\t\"SS\",\n\t\"SSD\",\n\t\"ST\",\n\t\"STP\",\n\t\"SUR\",\n\t\"SV\",\n\t\"SVK\",\n\t\"SVN\",\n\t\"SWE\",\n\t\"SWZ\",\n\t\"SX\",\n\t\"SXM\",\n\t\"SY\",\n\t\"SYC\",\n\t\"SYR\",\n\t\"SZ\",\n\t\"TC\",\n\t\"TCA\",\n\t\"TCD\",\n\t\"TD\",\n\t\"TF\",\n\t\"TG\",\n\t\"TGO\",\n\t\"TH\",\n\t\"THA\",\n\t\"TJ\",\n\t\"TJK\",\n\t\"TK\",\n\t\"TKL\",\n\t\"TKM\",\n\t\"TL\",\n\t\"TLS\",\n\t\"TM\",\n\t\"TN\",\n\t\"TO\",\n\t\"TON\",\n\t\"TR\",\n\t\"TT\",\n\t\"TTO\",\n\t\"TUN\",\n\t\"TUR\",\n\t\"TUV\",\n\t\"TV\",\n\t\"TW\",\n\t\"TWN\",\n\t\"TZ\",\n\t\"TZA\",\n\t\"UA\",\n\t\"UG\",\n\t\"UGA\",\n\t\"UKR\",\n\t\"UM\",\n\t\"UMI\",\n\t\"UNASUR\",\n\t\"URY\",\n\t\"US\",\n\t\"USA\",\n\t\"UY\",\n\t\"UZ\",\n\t\"UZB\",\n\t\"VA\",\n\t\"VAT\",\n\t\"VC\",\n\t\"VCT\",\n\t\"VE\",\n\t\"VEN\",\n\t\"VG\",\n\t\"VGB\",\n\t\"VI\",\n\t\"VIR\",\n\t\"VN\",\n\t\"VNM\",\n\t\"VU\",\n\t\"VUT\",\n\t\"WF\",\n\t\"WLF\",\n\t\"WS\",\n\t\"WSM\",\n\t\"YE\",\n\t\"YEM\",\n\t\"ZA\",\n\t\"ZAF\",\n\t\"ZM\",\n\t\"ZMB\",\n\t\"ZW\",\n\t\"ZWE\",\n] as const;\ntype CountryCode = (typeof countryCodes)[number];\n\n/**\n * Type Predicate: check if the given value is a valid country code\n */\nfunction isCountryCode(value: unknown): value is CountryCode {\n\treturn countryCodes.includes(value as CountryCode);\n}\n\nexport {\n\t//,\n\tisCountryCode,\n\tcountryCodes,\n};\n\nexport type {\n\t//,\n\tCountryCode,\n};\n"],"mappings":"sIAKA,MAwBM,EAAuB,EAAI,GAAI,CACpC,SAAU,CACT,KAAM,CACL,EAAG,sBACH,EAAG,uBACH,EAAG,aACH,CACD,CACD,CAAC,CAEI,EAAiB,EAAI,GAAI,CAC9B,SAAU,CACT,KAAM,CACL,EAAG,UACH,EAAG,aACH,EAAG,UACH,CACD,CACD,CAAC,CA6CF,SAAS,EAAK,CAEb,YACA,OACA,OAAO,IACP,UAAU,OACV,GAAG,GACM,CACT,IAAM,EAAe,EAAqB,CAAE,OAAM,CAAC,CAGnD,OACC,EAAC,MAAD,CACC,YAAU,OACV,UAAW,EAAG,gCAAiC,EALlC,EAAe,CAAE,OAAM,CAK+B,CAAE,EAAU,CAC/E,GAAI,WAHL,CAKC,EAAC,MAAD,CAAK,cAAA,GAAY,UAAW,EAAG,2CAA4C,EAAa,CAAI,CAAA,CAC5F,EAAC,MAAD,CACC,UAAU,mCACV,IAAK,kCAAsB,EAAK,GAAG,EAAK,MACxC,IAAK,YAAY,IACR,UACR,CAAA,CACG,GAGR,EAAK,YAAc,OCpHnB,MAAM,EAAe,kvFAgvBpB,CAMD,SAAS,EAAc,EAAsC,CAC5D,OAAO,EAAa,SAAS,EAAqB"}
|
|
1
|
+
{"version":3,"file":"flag.js","names":[],"sources":["../src/components/flag/flag.tsx","../src/components/flag/country-code.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\nimport type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { CountryCode } from \"./country-code.js\";\n\nconst cdnOrigin = \"https://assets.ngrok.com\";\n\nconst sizes = [\"s\", \"m\", \"l\"] as const;\ntype Size = (typeof sizes)[number];\n\ntype Props = Omit<ComponentProps<\"div\">, \"children\"> & {\n\t/**\n\t * The country code for the flag to display\n\t * @example \"US\"\n\t */\n\tcode: CountryCode;\n\t/**\n\t * The size of flag to render, \"s\", \"m\", or \"l\"\n\t * @default \"l\"\n\t */\n\tsize?: Size;\n\t/**\n\t * A string providing a hint to the user agent as to how to best schedule the loading of the image to optimize page performance.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading\n\t * @default \"lazy\"\n\t */\n\tloading?: ComponentProps<\"img\">[\"loading\"];\n};\n\nconst borderRadiusVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"rounded-[0.0625rem]\",\n\t\t\tm: \"rounded-[0.09375rem]\",\n\t\t\tl: \"rounded-xs\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\nconst sizingVariants = cva(\"\", {\n\tvariants: {\n\t\tsize: {\n\t\t\ts: \"w-4 h-3\",\n\t\t\tm: \"w-5 h-3.75\",\n\t\t\tl: \"w-8 h-6\",\n\t\t} as const satisfies Record<Size, string>,\n\t},\n});\n\n/**\n * Renders a country flag from an [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)\n * country code, served as an SVG from ngrok's CDN. Inspired by\n * [react-flagpack](https://flagpack.xyz/docs/development/react).\n *\n * **When to use**\n * - Showing the country associated with a region, IP, billing address, or locale.\n * - Inside a select option, list row, or status pill that needs a quick visual cue.\n *\n * **When not to use**\n * - As a stand-in for language. Flags ≠ languages — Brazilian Portuguese is\n * not \"Portugal\", Spanish is not just \"Spain\". Use a language label instead.\n * - As decoration where the country isn't meaningful to the user.\n *\n * **Sizing.** `\"s\"` (16×12), `\"m\"` (20×15), and `\"l\"` (32×24, default) match\n * common inline, list, and table contexts. Pick the size that matches its\n * neighbors so the flag doesn't dominate or disappear.\n *\n * **Accessibility.** The underlying `<img>` is given `alt=\"flag for {code}\"`.\n * If the country is decorative or already labeled in adjacent text, consider\n * passing `aria-hidden` via the wrapper `<div>` to avoid duplicate\n * announcements.\n *\n * **Loading.** Defaults to `loading=\"lazy\"`. Use `loading=\"eager\"` for flags\n * above the fold or in critical content.\n *\n * @see https://mantle.ngrok.com/components/flag#flag\n *\n * @example\n * ```tsx\n * import { Flag } from \"@ngrok/mantle/flag\";\n *\n * <Flag code=\"US\" />\n * <Flag code=\"JP\" size=\"m\" loading=\"eager\" />\n * <Flag code=\"CA\" size=\"s\" />\n *\n * // Inline next to a country label.\n * <span className=\"inline-flex items-center gap-2\">\n * <Flag code=\"GB\" size=\"s\" aria-hidden />\n * <span>United Kingdom</span>\n * </span>\n * ```\n */\nfunction Flag({\n\t//,\n\tclassName,\n\tcode,\n\tsize = \"l\",\n\tloading = \"lazy\",\n\t...props\n}: Props) {\n\tconst borderRadius = borderRadiusVariants({ size });\n\tconst sizing = sizingVariants({ size });\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"flag\"\n\t\t\tclassName={cx(\"flag relative overflow-hidden\", borderRadius, sizing, className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div aria-hidden className={cx(\"absolute inset-0 border border-[#000]/10\", borderRadius)} />\n\t\t\t<img\n\t\t\t\tclassName=\"h-full w-full block object-cover\"\n\t\t\t\tsrc={`${cdnOrigin}/flags/${size}/${code}.svg`}\n\t\t\t\talt={`flag for ${code}`}\n\t\t\t\tloading={loading}\n\t\t\t/>\n\t\t</div>\n\t);\n}\nFlag.displayName = \"Flag\";\n\nexport {\n\t//,\n\tFlag,\n};\n\nexport type {\n\t//,\n\tProps as FlagProps,\n};\n","/** All valid values for a flag\n * @see https://www.flagpack.xyz/docs/flag-index\n */\nconst countryCodes = [\n\t\"004\",\n\t\"008\",\n\t\"010\",\n\t\"016\",\n\t\"016\",\n\t\"020\",\n\t\"024\",\n\t\"028\",\n\t\"031\",\n\t\"032\",\n\t\"040\",\n\t\"044\",\n\t\"048\",\n\t\"050\",\n\t\"051\",\n\t\"052\",\n\t\"056\",\n\t\"060\",\n\t\"064\",\n\t\"068\",\n\t\"070\",\n\t\"072\",\n\t\"074\",\n\t\"076\",\n\t\"084\",\n\t\"086\",\n\t\"090\",\n\t\"092\",\n\t\"096\",\n\t\"100\",\n\t\"104\",\n\t\"108\",\n\t\"112\",\n\t\"116\",\n\t\"120\",\n\t\"124\",\n\t\"132\",\n\t\"136\",\n\t\"140\",\n\t\"144\",\n\t\"148\",\n\t\"152\",\n\t\"156\",\n\t\"158\",\n\t\"162\",\n\t\"166\",\n\t\"170\",\n\t\"174\",\n\t\"178\",\n\t\"180\",\n\t\"184\",\n\t\"188\",\n\t\"191\",\n\t\"192\",\n\t\"196\",\n\t\"203\",\n\t\"204\",\n\t\"208\",\n\t\"212\",\n\t\"214\",\n\t\"218\",\n\t\"222\",\n\t\"226\",\n\t\"231\",\n\t\"232\",\n\t\"233\",\n\t\"234\",\n\t\"238\",\n\t\"239\",\n\t\"242\",\n\t\"246\",\n\t\"248\",\n\t\"250\",\n\t\"254\",\n\t\"258\",\n\t\"260\",\n\t\"262\",\n\t\"266\",\n\t\"268\",\n\t\"270\",\n\t\"275\",\n\t\"276\",\n\t\"288\",\n\t\"292\",\n\t\"296\",\n\t\"300\",\n\t\"304\",\n\t\"308\",\n\t\"312\",\n\t\"316\",\n\t\"320\",\n\t\"324\",\n\t\"328\",\n\t\"332\",\n\t\"334\",\n\t\"336\",\n\t\"340\",\n\t\"344\",\n\t\"348\",\n\t\"352\",\n\t\"356\",\n\t\"360\",\n\t\"364\",\n\t\"368\",\n\t\"372\",\n\t\"376\",\n\t\"380\",\n\t\"384\",\n\t\"388\",\n\t\"392\",\n\t\"398\",\n\t\"400\",\n\t\"404\",\n\t\"408\",\n\t\"410\",\n\t\"414\",\n\t\"417\",\n\t\"418\",\n\t\"422\",\n\t\"426\",\n\t\"428\",\n\t\"430\",\n\t\"434\",\n\t\"438\",\n\t\"440\",\n\t\"442\",\n\t\"446\",\n\t\"450\",\n\t\"454\",\n\t\"458\",\n\t\"462\",\n\t\"466\",\n\t\"470\",\n\t\"474\",\n\t\"478\",\n\t\"480\",\n\t\"484\",\n\t\"492\",\n\t\"496\",\n\t\"498\",\n\t\"499\",\n\t\"500\",\n\t\"504\",\n\t\"508\",\n\t\"512\",\n\t\"516\",\n\t\"520\",\n\t\"524\",\n\t\"528\",\n\t\"531\",\n\t\"533\",\n\t\"534\",\n\t\"540\",\n\t\"548\",\n\t\"554\",\n\t\"558\",\n\t\"562\",\n\t\"566\",\n\t\"570\",\n\t\"574\",\n\t\"578\",\n\t\"580\",\n\t\"581\",\n\t\"583\",\n\t\"584\",\n\t\"585\",\n\t\"586\",\n\t\"591\",\n\t\"598\",\n\t\"600\",\n\t\"604\",\n\t\"608\",\n\t\"612\",\n\t\"616\",\n\t\"620\",\n\t\"624\",\n\t\"626\",\n\t\"630\",\n\t\"634\",\n\t\"638\",\n\t\"642\",\n\t\"643\",\n\t\"646\",\n\t\"652\",\n\t\"654\",\n\t\"659\",\n\t\"660\",\n\t\"662\",\n\t\"663\",\n\t\"666\",\n\t\"670\",\n\t\"674\",\n\t\"678\",\n\t\"682\",\n\t\"686\",\n\t\"688\",\n\t\"690\",\n\t\"694\",\n\t\"702\",\n\t\"703\",\n\t\"704\",\n\t\"705\",\n\t\"706\",\n\t\"710\",\n\t\"716\",\n\t\"724\",\n\t\"728\",\n\t\"729\",\n\t\"732\",\n\t\"740\",\n\t\"744\",\n\t\"748\",\n\t\"752\",\n\t\"756\",\n\t\"760\",\n\t\"762\",\n\t\"764\",\n\t\"768\",\n\t\"772\",\n\t\"776\",\n\t\"780\",\n\t\"784\",\n\t\"788\",\n\t\"792\",\n\t\"795\",\n\t\"796\",\n\t\"798\",\n\t\"800\",\n\t\"804\",\n\t\"807\",\n\t\"818\",\n\t\"831\",\n\t\"832\",\n\t\"833\",\n\t\"834\",\n\t\"836\",\n\t\"840\",\n\t\"850\",\n\t\"854\",\n\t\"858\",\n\t\"860\",\n\t\"862\",\n\t\"876\",\n\t\"882\",\n\t\"887\",\n\t\"894\",\n\t\"ABW\",\n\t\"AD\",\n\t\"AE\",\n\t\"AF\",\n\t\"AFG\",\n\t\"AFRUN\",\n\t\"AG\",\n\t\"AGO\",\n\t\"AI\",\n\t\"AIA\",\n\t\"AL\",\n\t\"ALA\",\n\t\"ALB\",\n\t\"AM\",\n\t\"AMS\",\n\t\"AND\",\n\t\"AO\",\n\t\"AQ\",\n\t\"AR\",\n\t\"ARE\",\n\t\"ARG\",\n\t\"ARM\",\n\t\"AS\",\n\t\"ASM\",\n\t\"AT\",\n\t\"ATA\",\n\t\"ATF\",\n\t\"ATG\",\n\t\"AU\",\n\t\"AUS\",\n\t\"AUT\",\n\t\"AW\",\n\t\"AX\",\n\t\"AZ\",\n\t\"AZE\",\n\t\"BA\",\n\t\"BB\",\n\t\"BD\",\n\t\"BDI\",\n\t\"BE\",\n\t\"BEL\",\n\t\"BEN\",\n\t\"BF\",\n\t\"BFA\",\n\t\"BG\",\n\t\"BGD\",\n\t\"BGR\",\n\t\"BH\",\n\t\"BHR\",\n\t\"BHS\",\n\t\"BI\",\n\t\"BIH\",\n\t\"BJ\",\n\t\"BL\",\n\t\"BLM\",\n\t\"BLR\",\n\t\"BLZ\",\n\t\"BM\",\n\t\"BMU\",\n\t\"BN\",\n\t\"BO\",\n\t\"BOL\",\n\t\"BQ-BO\",\n\t\"BQ-SA\",\n\t\"BQ-SE\",\n\t\"BR\",\n\t\"BRA\",\n\t\"BRB\",\n\t\"BRN\",\n\t\"BS\",\n\t\"BT\",\n\t\"BTN\",\n\t\"BV\",\n\t\"BVT\",\n\t\"BW\",\n\t\"BWA\",\n\t\"BY\",\n\t\"BZ\",\n\t\"CA\",\n\t\"CAF\",\n\t\"CAN\",\n\t\"CC\",\n\t\"CCK\",\n\t\"CD\",\n\t\"CF\",\n\t\"CG\",\n\t\"CH\",\n\t\"CHE\",\n\t\"CHL\",\n\t\"CHN\",\n\t\"CI\",\n\t\"CIV\",\n\t\"CK\",\n\t\"CL\",\n\t\"CM\",\n\t\"CMR\",\n\t\"CN\",\n\t\"CO\",\n\t\"COD\",\n\t\"COG\",\n\t\"COK\",\n\t\"COL\",\n\t\"COM\",\n\t\"CPV\",\n\t\"CR\",\n\t\"CRI\",\n\t\"CU\",\n\t\"CUB\",\n\t\"CUW\",\n\t\"CV\",\n\t\"CW\",\n\t\"CX\",\n\t\"CXR\",\n\t\"CY\",\n\t\"CYM\",\n\t\"CYP\",\n\t\"CZ\",\n\t\"CZE\",\n\t\"DE\",\n\t\"DEU\",\n\t\"DJ\",\n\t\"DJI\",\n\t\"DK\",\n\t\"DM\",\n\t\"DMA\",\n\t\"DNK\",\n\t\"DO\",\n\t\"DOM\",\n\t\"EC\",\n\t\"ECU\",\n\t\"EE\",\n\t\"EG\",\n\t\"EGY\",\n\t\"EH\",\n\t\"ER\",\n\t\"ERI\",\n\t\"ES\",\n\t\"ESH\",\n\t\"ESP\",\n\t\"EST\",\n\t\"ET\",\n\t\"ETH\",\n\t\"EU\",\n\t\"FI\",\n\t\"FIN\",\n\t\"FJ\",\n\t\"FJI\",\n\t\"FK\",\n\t\"FLK\",\n\t\"FM\",\n\t\"FO\",\n\t\"FR\",\n\t\"FRA\",\n\t\"FRO\",\n\t\"FSM\",\n\t\"GA\",\n\t\"GAB\",\n\t\"GB-ENG\",\n\t\"GB-NIR\",\n\t\"GB-SCT\",\n\t\"GB-UKM\",\n\t\"GB-WLS\",\n\t\"GB\",\n\t\"GBR\",\n\t\"GD\",\n\t\"GE\",\n\t\"GEO\",\n\t\"GF\",\n\t\"GG\",\n\t\"GGY\",\n\t\"GH\",\n\t\"GHA\",\n\t\"GI\",\n\t\"GIB\",\n\t\"GIN\",\n\t\"GL\",\n\t\"GLP\",\n\t\"GM\",\n\t\"GMB\",\n\t\"GN\",\n\t\"GNB\",\n\t\"GNQ\",\n\t\"GP\",\n\t\"GQ\",\n\t\"GR\",\n\t\"GRC\",\n\t\"GRD\",\n\t\"GRL\",\n\t\"GS\",\n\t\"GT\",\n\t\"GTM\",\n\t\"GU\",\n\t\"GUF\",\n\t\"GUM\",\n\t\"GUY\",\n\t\"GW\",\n\t\"GY\",\n\t\"HK\",\n\t\"HKG\",\n\t\"HM\",\n\t\"HMD\",\n\t\"HN\",\n\t\"HND\",\n\t\"HR\",\n\t\"HRV\",\n\t\"HT\",\n\t\"HTI\",\n\t\"HU\",\n\t\"HUN\",\n\t\"ID\",\n\t\"IDN\",\n\t\"IE\",\n\t\"IL\",\n\t\"IM\",\n\t\"IMN\",\n\t\"IN\",\n\t\"IND\",\n\t\"IO\",\n\t\"IOT\",\n\t\"IQ\",\n\t\"IR\",\n\t\"IRL\",\n\t\"IRN\",\n\t\"IRQ\",\n\t\"IS\",\n\t\"ISL\",\n\t\"ISR\",\n\t\"IT\",\n\t\"ITA\",\n\t\"JAM\",\n\t\"JE\",\n\t\"JEY\",\n\t\"JM\",\n\t\"JO\",\n\t\"JOR\",\n\t\"JP\",\n\t\"JPN\",\n\t\"KAZ\",\n\t\"KE\",\n\t\"KEN\",\n\t\"KG\",\n\t\"KGZ\",\n\t\"KH\",\n\t\"KHM\",\n\t\"KI\",\n\t\"KIR\",\n\t\"KM\",\n\t\"KN-SK\",\n\t\"KNA\",\n\t\"KOR\",\n\t\"KP\",\n\t\"KR\",\n\t\"KW\",\n\t\"KWT\",\n\t\"KY\",\n\t\"KZ\",\n\t\"LA\",\n\t\"LAO\",\n\t\"LB\",\n\t\"LBN\",\n\t\"LBR\",\n\t\"LBY\",\n\t\"LC\",\n\t\"LCA\",\n\t\"LI\",\n\t\"LIE\",\n\t\"LK\",\n\t\"LKA\",\n\t\"LR\",\n\t\"LS\",\n\t\"LSO\",\n\t\"LT\",\n\t\"LTU\",\n\t\"LU\",\n\t\"LUX\",\n\t\"LV\",\n\t\"LVA\",\n\t\"LY\",\n\t\"MA\",\n\t\"MAC\",\n\t\"MAF\",\n\t\"MAR\",\n\t\"MC\",\n\t\"MCO\",\n\t\"MD\",\n\t\"MDA\",\n\t\"MDG\",\n\t\"MDV\",\n\t\"ME\",\n\t\"MEX\",\n\t\"MF\",\n\t\"MG\",\n\t\"MH\",\n\t\"MHL\",\n\t\"MK\",\n\t\"MKD\",\n\t\"ML\",\n\t\"MLI\",\n\t\"MLT\",\n\t\"MM\",\n\t\"MMR\",\n\t\"MN\",\n\t\"MNE\",\n\t\"MNG\",\n\t\"MNP\",\n\t\"MO\",\n\t\"MOZ\",\n\t\"MP\",\n\t\"MQ\",\n\t\"MR\",\n\t\"MRT\",\n\t\"MS\",\n\t\"MSR\",\n\t\"MT\",\n\t\"MTQ\",\n\t\"MU\",\n\t\"MUS\",\n\t\"MV\",\n\t\"MW\",\n\t\"MWI\",\n\t\"MX\",\n\t\"MY\",\n\t\"MYS\",\n\t\"MZ\",\n\t\"NA\",\n\t\"NAM\",\n\t\"NC\",\n\t\"NCL\",\n\t\"NE\",\n\t\"NER\",\n\t\"NF\",\n\t\"NFK\",\n\t\"NG\",\n\t\"NGA\",\n\t\"NI\",\n\t\"NIC\",\n\t\"NIU\",\n\t\"NL\",\n\t\"NLD\",\n\t\"NO\",\n\t\"NOR\",\n\t\"NP\",\n\t\"NPL\",\n\t\"NR\",\n\t\"NRU\",\n\t\"NU\",\n\t\"NZ\",\n\t\"NZL\",\n\t\"OM\",\n\t\"OMN\",\n\t\"PA\",\n\t\"PAK\",\n\t\"PAN\",\n\t\"PCN\",\n\t\"PE\",\n\t\"PER\",\n\t\"PF\",\n\t\"PG\",\n\t\"PH\",\n\t\"PHL\",\n\t\"PK\",\n\t\"PL\",\n\t\"PLW\",\n\t\"PM\",\n\t\"PN\",\n\t\"PNG\",\n\t\"POL\",\n\t\"PR\",\n\t\"PRI\",\n\t\"PRK\",\n\t\"PRT\",\n\t\"PRY\",\n\t\"PS\",\n\t\"PSE\",\n\t\"PT\",\n\t\"PW\",\n\t\"PY\",\n\t\"PYF\",\n\t\"QA\",\n\t\"QAT\",\n\t\"RAINBOW\",\n\t\"RE\",\n\t\"REU\",\n\t\"RO\",\n\t\"ROU\",\n\t\"RS\",\n\t\"RU\",\n\t\"RUS\",\n\t\"RW\",\n\t\"RWA\",\n\t\"SA\",\n\t\"SAU\",\n\t\"SB\",\n\t\"SC\",\n\t\"SD\",\n\t\"SDN\",\n\t\"SE\",\n\t\"SEN\",\n\t\"SG\",\n\t\"SGP\",\n\t\"SGS\",\n\t\"SH\",\n\t\"SHN\",\n\t\"SI\",\n\t\"SJ\",\n\t\"SJM\",\n\t\"SK\",\n\t\"SL\",\n\t\"SLB\",\n\t\"SLE\",\n\t\"SLV\",\n\t\"SM\",\n\t\"SMR\",\n\t\"SN\",\n\t\"SO\",\n\t\"SOM\",\n\t\"SPM\",\n\t\"SR\",\n\t\"SRB\",\n\t\"SS\",\n\t\"SSD\",\n\t\"ST\",\n\t\"STP\",\n\t\"SUR\",\n\t\"SV\",\n\t\"SVK\",\n\t\"SVN\",\n\t\"SWE\",\n\t\"SWZ\",\n\t\"SX\",\n\t\"SXM\",\n\t\"SY\",\n\t\"SYC\",\n\t\"SYR\",\n\t\"SZ\",\n\t\"TC\",\n\t\"TCA\",\n\t\"TCD\",\n\t\"TD\",\n\t\"TF\",\n\t\"TG\",\n\t\"TGO\",\n\t\"TH\",\n\t\"THA\",\n\t\"TJ\",\n\t\"TJK\",\n\t\"TK\",\n\t\"TKL\",\n\t\"TKM\",\n\t\"TL\",\n\t\"TLS\",\n\t\"TM\",\n\t\"TN\",\n\t\"TO\",\n\t\"TON\",\n\t\"TR\",\n\t\"TT\",\n\t\"TTO\",\n\t\"TUN\",\n\t\"TUR\",\n\t\"TUV\",\n\t\"TV\",\n\t\"TW\",\n\t\"TWN\",\n\t\"TZ\",\n\t\"TZA\",\n\t\"UA\",\n\t\"UG\",\n\t\"UGA\",\n\t\"UKR\",\n\t\"UM\",\n\t\"UMI\",\n\t\"UNASUR\",\n\t\"URY\",\n\t\"US\",\n\t\"USA\",\n\t\"UY\",\n\t\"UZ\",\n\t\"UZB\",\n\t\"VA\",\n\t\"VAT\",\n\t\"VC\",\n\t\"VCT\",\n\t\"VE\",\n\t\"VEN\",\n\t\"VG\",\n\t\"VGB\",\n\t\"VI\",\n\t\"VIR\",\n\t\"VN\",\n\t\"VNM\",\n\t\"VU\",\n\t\"VUT\",\n\t\"WF\",\n\t\"WLF\",\n\t\"WS\",\n\t\"WSM\",\n\t\"YE\",\n\t\"YEM\",\n\t\"ZA\",\n\t\"ZAF\",\n\t\"ZM\",\n\t\"ZMB\",\n\t\"ZW\",\n\t\"ZWE\",\n] as const;\ntype CountryCode = (typeof countryCodes)[number];\n\n/**\n * Type Predicate: check if the given value is a valid country code\n */\nfunction isCountryCode(value: unknown): value is CountryCode {\n\treturn countryCodes.includes(value as CountryCode);\n}\n\nexport {\n\t//,\n\tisCountryCode,\n\tcountryCodes,\n};\n\nexport type {\n\t//,\n\tCountryCode,\n};\n"],"mappings":"sIAKA,MAwBM,EAAuB,EAAI,GAAI,CACpC,SAAU,CACT,KAAM,CACL,EAAG,sBACH,EAAG,uBACH,EAAG,YACJ,CACD,CACD,CAAC,EAEK,EAAiB,EAAI,GAAI,CAC9B,SAAU,CACT,KAAM,CACL,EAAG,UACH,EAAG,aACH,EAAG,SACJ,CACD,CACD,CAAC,EA6CD,SAAS,EAAK,CAEb,YACA,OACA,OAAO,IACP,UAAU,OACV,GAAG,GACM,CACT,IAAM,EAAe,EAAqB,CAAE,MAAK,CAAC,EAGlD,OACC,EAAC,MAAD,CACC,YAAU,OACV,UAAW,EAAG,gCAAiC,EALlC,EAAe,CAAE,MAAK,CAK+B,EAAG,CAAS,EAC9E,GAAI,WAHL,CAKC,EAAC,MAAD,CAAK,cAAA,GAAY,UAAW,EAAG,2CAA4C,CAAY,CAAI,CAAA,EAC3F,EAAC,MAAD,CACC,UAAU,mCACV,IAAK,kCAAsB,EAAK,GAAG,EAAK,MACxC,IAAK,YAAY,IACR,SACT,CAAA,CACG,GAEP,CACA,EAAK,YAAc,OCpHnB,MAAM,EAAe,ivFAgvBrB,EAMA,SAAS,EAAc,EAAsC,CAC5D,OAAO,EAAa,SAAS,CAAoB,CAClD"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as MarginType, o as useComposedRefs, s as copyToClipboard } from "./in-view-
|
|
2
|
-
import { RefObject,
|
|
1
|
+
import { n as MarginType, o as useComposedRefs, s as copyToClipboard } from "./in-view-BC3wmz-a.js";
|
|
2
|
+
import { RefObject, useEffect } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/hooks/use-breakpoint.d.ts
|
|
5
5
|
/**
|
|
@@ -282,7 +282,7 @@ declare function useIsHydrated(): boolean;
|
|
|
282
282
|
*
|
|
283
283
|
* return <div ref={ref}>Width: {width}</div>;
|
|
284
284
|
*/
|
|
285
|
-
declare const useIsomorphicLayoutEffect: typeof
|
|
285
|
+
declare const useIsomorphicLayoutEffect: typeof useEffect;
|
|
286
286
|
//#endregion
|
|
287
287
|
//#region src/hooks/use-matches-media-query.d.ts
|
|
288
288
|
/**
|
package/dist/hooks.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./use-matches-media-query-
|
|
1
|
+
import{t as e}from"./use-matches-media-query-CMSxHR9n.js";import{r as t}from"./browser-only-BSl_hruR.js";import{n}from"./compose-refs-Cjf2gfB8.js";import{t as r}from"./use-copy-to-clipboard-BLpquU9d.js";import{t as i}from"./use-isomorphic-layout-effect-DdTRtMY-.js";import{n as a,t as o}from"./use-prefers-reduced-motion-CWIoFA6W.js";import{t as s}from"./in-view-C2DpZ6s0.js";import{useCallback as c,useEffect as l,useMemo as u,useReducer as d,useRef as f,useState as p,useSyncExternalStore as m}from"react";const h=[`2xl`,`xl`,`lg`,`md`,`sm`,`xs`,`2xs`],g=[`default`,...h];function _(){return m(j,M,()=>`default`)}function v(e){return m(P(e),I(e),()=>!1)}const y={"2xl":`(min-width: 96rem)`,xl:`(min-width: 80rem)`,lg:`(min-width: 64rem)`,md:`(min-width: 48rem)`,sm:`(min-width: 40rem)`,xs:`(min-width: 30rem)`,"2xs":`(min-width: 22.5rem)`},b={"2xl":`(max-width: 95.99rem)`,xl:`(max-width: 79.99rem)`,lg:`(max-width: 63.99rem)`,md:`(max-width: 47.99rem)`,sm:`(max-width: 39.99rem)`,xs:`(max-width: 29.99rem)`,"2xs":`(max-width: 22.49rem)`};let x=null,S=null;function C(){return x||={"2xl":window.matchMedia(y[`2xl`]),xl:window.matchMedia(y.xl),lg:window.matchMedia(y.lg),md:window.matchMedia(y.md),sm:window.matchMedia(y.sm),xs:window.matchMedia(y.xs),"2xs":window.matchMedia(y[`2xs`])},x}function w(e){return S||={"2xl":window.matchMedia(b[`2xl`]),xl:window.matchMedia(b.xl),lg:window.matchMedia(b.lg),md:window.matchMedia(b.md),sm:window.matchMedia(b.sm),xs:window.matchMedia(b.xs),"2xs":window.matchMedia(b[`2xs`])},S[e]}let T=`default`;const E=new Set;let D=!1;function O(){let e=C();for(let t of h)if(e[t].matches)return t;return`default`}let k=!1;function A(){k||(k=!0,requestAnimationFrame(()=>{k=!1;let e=O();if(e!==T){T=e;for(let e of E)e()}}))}function j(e){if(E.add(e),!D){D=!0;let e=C();T=O();for(let t of Object.values(e))t.addEventListener(`change`,A)}return e(),()=>{if(E.delete(e),E.size===0&&D){D=!1;let e=C();for(let t of Object.values(e))t.removeEventListener(`change`,A)}}}function M(){return T}const N=new Map;function P(e){let t=N.get(e);return t||(t=t=>{let n=w(e),r=!1,i=()=>{r||(r=!0,requestAnimationFrame(()=>{r=!1,t()}))};return n.addEventListener(`change`,i),()=>{n.removeEventListener(`change`,i)}},N.set(e,t),t)}const F=new Map;function I(e){let t=F.get(e);return t||(t=()=>w(e).matches,F.set(e,t),t)}function L(e){let t=f(e);return l(()=>{t.current=e}),u(()=>((...e)=>t.current?.(...e)),[])}function R(e,t){let n=L(e),r=f(0);return l(()=>()=>window.clearTimeout(r.current),[]),c((...e)=>{window.clearTimeout(r.current),r.current=window.setTimeout(()=>n(...e),t.waitMs)},[n,t.waitMs])}const z=(e=`mantle`)=>u(()=>B(e),[e]);function B(e=`mantle`){return[e.trim()||`mantle`,V()].join(`-`)}function V(){return Math.random().toString(36).substring(2,9)}function H(){let e=a();return u(()=>e?`auto`:`smooth`,[e])}function U(e,{root:t,margin:n,amount:r,once:i=!1,initial:a=!1}={}){let[o,c]=p(a);return l(()=>{if(!e.current||i&&o)return;function a(){return c(!0),i?void 0:()=>c(!1)}let l={root:t&&t.current||void 0,margin:n,amount:r};return s(e.current,a,l)},[t,e,n,i,r]),o}function W(e,t){switch(t.type){case`push`:return{undoStack:[...e.undoStack,t.snapshot],redoStack:[]};case`undo`:{if(e.undoStack.length===0)return e;let n=e.undoStack.slice(0,-1);return e.undoStack[e.undoStack.length-1]===void 0?e:{undoStack:n,redoStack:[...e.redoStack,t.current]}}case`redo`:{if(e.redoStack.length===0)return e;let n=e.redoStack.slice(0,-1);return e.redoStack[e.redoStack.length-1]===void 0?e:{undoStack:[...e.undoStack,t.current],redoStack:n}}}}function G(){let[e,t]=d(W,{undoStack:[],redoStack:[]}),n=c(e=>{t({type:`push`,snapshot:e})},[]),r=c(n=>{let r=e.undoStack[e.undoStack.length-1];if(r!==void 0)return t({type:`undo`,current:n}),r},[e.undoStack]),i=c(n=>{let r=e.redoStack[e.redoStack.length-1];if(r!==void 0)return t({type:`redo`,current:n}),r},[e.redoStack]);return u(()=>({canUndo:e.undoStack.length>0,canRedo:e.redoStack.length>0,push:n,undo:r,redo:i}),[e.undoStack.length,e.redoStack.length,n,r,i])}export{g as breakpoints,o as getPrefersReducedMotion,_ as useBreakpoint,L as useCallbackRef,n as useComposedRefs,r as useCopyToClipboard,R as useDebouncedCallback,U as useInView,v as useIsBelowBreakpoint,t as useIsHydrated,i as useIsomorphicLayoutEffect,e as useMatchesMediaQuery,a as usePrefersReducedMotion,z as useRandomStableId,H as useScrollBehavior,G as useUndoRedo};
|
|
2
2
|
//# sourceMappingURL=hooks.js.map
|