@ngrok/mantle 0.76.2 → 0.76.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/accordion.d.ts +1 -2
- package/dist/accordion.js +1 -2
- package/dist/agent.json +1 -1
- package/dist/alert-dialog.d.ts +4 -45
- package/dist/alert-dialog.js +1 -2
- package/dist/alert.d.ts +2 -3
- package/dist/alert.js +1 -2
- package/dist/anchor-CcTY5SIz.js +1 -2
- package/dist/anchor.d.ts +1 -2
- package/dist/as-child-uN_018tj.d.ts +1 -2
- package/dist/badge.d.ts +1 -2
- package/dist/badge.js +1 -2
- package/dist/booleanish-BfvnW6vy.js +1 -2
- package/dist/browser-only-BSl_hruR.js +1 -2
- package/dist/browser-only.d.ts +1 -2
- package/dist/button-BAxneEMu.js +1 -2
- package/dist/{button-uMIZVKit.js → button-BfMn3PgP.js} +1 -2
- package/dist/button-mfYak6Rx.d.ts +71 -0
- package/dist/button.d.ts +3 -3
- package/dist/button.js +1 -1
- package/dist/calendar.d.ts +2 -3
- package/dist/calendar.js +1 -2
- package/dist/card.d.ts +1 -2
- package/dist/card.js +1 -2
- package/dist/checkbox.d.ts +30 -2
- package/dist/checkbox.js +1 -2
- package/dist/code-block.d.ts +1 -2
- package/dist/code-block.js +2 -3
- package/dist/code-block_highlight-utils.js +1 -1
- package/dist/code.d.ts +1 -2
- package/dist/code.js +1 -2
- package/dist/color.js +1 -2
- package/dist/combobox.d.ts +1 -2
- package/dist/combobox.js +1 -2
- package/dist/command.d.ts +3 -4
- package/dist/command.js +1 -2
- package/dist/compose-refs-Cjf2gfB8.js +1 -2
- package/dist/copy-to-clipboard-Baw30q9O.js +1 -2
- package/dist/cx-CBSnSC36.js +1 -2
- package/dist/cx.d.ts +1 -2
- package/dist/data-table.d.ts +124 -45
- package/dist/data-table.js +1 -2
- package/dist/description-list.d.ts +1 -2
- package/dist/description-list.js +1 -2
- package/dist/{dialog-DR2V7zsR.js → dialog-ebkUwitP.js} +1 -2
- package/dist/dialog.d.ts +2 -3
- package/dist/dialog.js +1 -1
- package/dist/direction-CcTY0FmA.d.ts +1 -2
- package/dist/direction-Wa9W2F61.js +1 -2
- package/dist/{dropdown-menu-C3YZJBkV.js → dropdown-menu-BHyYWtrH.js} +1 -2
- package/dist/dropdown-menu-BqdyTFLu.d.ts +1 -2
- package/dist/dropdown-menu.js +1 -1
- package/dist/empty.d.ts +1 -2
- package/dist/empty.js +1 -2
- package/dist/field-context-4k1kI7Bo.js +1 -2
- package/dist/field.d.ts +3 -4
- package/dist/field.js +1 -2
- package/dist/flag.d.ts +1 -2
- package/dist/flag.js +1 -2
- package/dist/hooks.d.ts +1 -2
- package/dist/hooks.js +1 -2
- package/dist/hover-card.d.ts +1 -2
- package/dist/hover-card.js +1 -2
- package/dist/icon-C8bYBIHW.js +1 -2
- package/dist/{icon-button-ntupABbM.d.ts → icon-button-D7hs6bX2.d.ts} +52 -44
- package/dist/{icon-button-C_Ht_g1C.js → icon-button-DUNHVWpb.js} +1 -2
- package/dist/icon-n49kOh4_.d.ts +1 -2
- package/dist/icons.d.ts +1 -2
- package/dist/icons.js +1 -2
- package/dist/in-view-BC3wmz-a.d.ts +1 -2
- package/dist/in-view-C2DpZ6s0.js +1 -2
- package/dist/{index-L3NmbHi5.d.ts → index-Bed_XLWa.d.ts} +16 -2
- package/dist/{index-BL5WVva_.d.ts → index-CJbKEKr2.d.ts} +4 -3
- package/dist/{index-DBZ3eRsl.d.ts → index-CTU6apE6.d.ts} +2 -3
- package/dist/index-DorCusfG.d.ts +1 -2
- package/dist/input.d.ts +4 -5
- package/dist/input.js +1 -2
- package/dist/is-input-CXmS0OFN.js +1 -2
- package/dist/kbd-Bv6tefdB.js +1 -2
- package/dist/kbd.d.ts +1 -2
- package/dist/label-DhIUmTN2.js +1 -2
- package/dist/label.d.ts +1 -2
- package/dist/llms.txt +1 -1
- package/dist/main.d.ts +1 -2
- package/dist/main.js +1 -2
- package/dist/mantle.css +191 -14
- package/dist/media-object.d.ts +1 -2
- package/dist/media-object.js +1 -2
- package/dist/multi-select.d.ts +1 -2
- package/dist/multi-select.js +1 -2
- package/dist/otp-input.d.ts +1 -2
- package/dist/otp-input.js +1 -2
- package/dist/pagination.d.ts +2 -3
- package/dist/pagination.js +1 -2
- package/dist/popover-DponNBot.js +1 -2
- package/dist/popover.d.ts +1 -2
- package/dist/primitive-Cn3h4DJg.js +1 -2
- package/dist/primitive-FoWela9a.d.ts +1 -2
- package/dist/progress.d.ts +1 -2
- package/dist/progress.js +1 -2
- package/dist/qr-code.d.ts +1 -2
- package/dist/qr-code.js +1 -2
- package/dist/radio-group.d.ts +1 -2
- package/dist/radio-group.js +1 -2
- package/dist/{resolve-pre-rendered-props-C-vrNxH1.js → resolve-pre-rendered-props-D9nlC6xE.js} +2 -3
- package/dist/resolve-pre-rendered-props-DxJ9-DAl.d.ts +1 -2
- package/dist/sandboxed-on-click.d.ts +2 -2
- package/dist/sandboxed-on-click.js +1 -2
- package/dist/select-C15-XvRT.d.ts +1 -2
- package/dist/{select-Cxc9VmP8.js → select-g0E_TsXr.js} +1 -2
- package/dist/select.js +1 -1
- package/dist/{separator-Bqjy77rG.js → separator-BXFUCWFa.js} +1 -2
- package/dist/separator.d.ts +1 -2
- package/dist/separator.js +1 -1
- package/dist/sheet.d.ts +3 -4
- package/dist/sheet.js +1 -2
- package/dist/skeleton.d.ts +1 -2
- package/dist/skeleton.js +1 -2
- package/dist/skip-to-main-link.d.ts +1 -2
- package/dist/skip-to-main-link.js +1 -2
- package/dist/slider.d.ts +1 -2
- package/dist/slider.js +1 -2
- package/dist/slot-CV5fmqFr.js +1 -2
- package/dist/slot.d.ts +1 -1
- package/dist/sort-BPX2Fk9t.js +1 -2
- package/dist/split-button.d.ts +5 -6
- package/dist/split-button.js +1 -2
- package/dist/svg-only-Cz1cby8y.js +1 -2
- package/dist/svg-only-f6ToFLH0.d.ts +1 -2
- package/dist/switch.d.ts +1 -2
- package/dist/switch.js +1 -2
- package/dist/table-BWD9IlIN.d.ts +1 -2
- package/dist/table-DWy_oNta.js +1 -0
- package/dist/table.js +1 -1
- package/dist/tabs.d.ts +1 -2
- package/dist/tabs.js +1 -2
- package/dist/text-area.d.ts +1 -2
- package/dist/text-area.js +1 -2
- package/dist/theme-provider-MMwxHEfw.js +1 -2
- package/dist/theme.d.ts +4 -5
- package/dist/theme.js +1 -2
- package/dist/themes-CYNpplwN.d.ts +1 -2
- package/dist/toast-CR3MVChj.js +1 -2
- package/dist/toast.d.ts +1 -2
- package/dist/tooltip.d.ts +1 -2
- package/dist/tooltip.js +1 -2
- package/dist/traffic-policy-file-0g5RXFqu.js +1 -2
- package/dist/types-BvUzforF.d.ts +1 -2
- package/dist/types-D85fCNV3.js +1 -2
- package/dist/types.d.ts +1 -3
- package/dist/use-copy-to-clipboard-BLpquU9d.js +1 -2
- package/dist/use-isomorphic-layout-effect-DdTRtMY-.js +1 -2
- package/dist/use-matches-media-query-CMSxHR9n.js +1 -2
- package/dist/use-prefers-reduced-motion-CWIoFA6W.js +1 -2
- package/dist/utils.d.ts +1 -2
- package/dist/utils.js +1 -2
- package/dist/validation-DCyx-ceH.js +1 -2
- package/dist/validation-xyX_6kph.d.ts +1 -2
- package/dist/well.d.ts +1 -2
- package/dist/well.js +1 -2
- package/dist/with-style-props-CyImx7vd.d.ts +1 -2
- package/package.json +22 -22
- package/dist/accordion.js.map +0 -1
- package/dist/alert-dialog.js.map +0 -1
- package/dist/alert.js.map +0 -1
- package/dist/anchor-CcTY5SIz.js.map +0 -1
- package/dist/badge.js.map +0 -1
- package/dist/booleanish-BfvnW6vy.js.map +0 -1
- package/dist/browser-only-BSl_hruR.js.map +0 -1
- package/dist/button-BAxneEMu.js.map +0 -1
- package/dist/button-BYZOBUgj.d.ts +0 -172
- package/dist/button-uMIZVKit.js.map +0 -1
- package/dist/calendar.js.map +0 -1
- package/dist/card.js.map +0 -1
- package/dist/checkbox.js.map +0 -1
- package/dist/code-block.js.map +0 -1
- package/dist/code.js.map +0 -1
- package/dist/color.js.map +0 -1
- package/dist/combobox.js.map +0 -1
- package/dist/command.js.map +0 -1
- package/dist/compose-refs-Cjf2gfB8.js.map +0 -1
- package/dist/copy-to-clipboard-Baw30q9O.js.map +0 -1
- package/dist/cx-CBSnSC36.js.map +0 -1
- package/dist/data-table.js.map +0 -1
- package/dist/deep-non-nullable-BxRoySYR.d.ts +0 -8
- package/dist/description-list.js.map +0 -1
- package/dist/dialog-DR2V7zsR.js.map +0 -1
- package/dist/direction-Wa9W2F61.js.map +0 -1
- package/dist/dropdown-menu-C3YZJBkV.js.map +0 -1
- package/dist/empty.js.map +0 -1
- package/dist/field-context-4k1kI7Bo.js.map +0 -1
- package/dist/field.js.map +0 -1
- package/dist/flag.js.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/hover-card.js.map +0 -1
- package/dist/icon-C8bYBIHW.js.map +0 -1
- package/dist/icon-button-C_Ht_g1C.js.map +0 -1
- package/dist/icons.js.map +0 -1
- package/dist/in-view-C2DpZ6s0.js.map +0 -1
- package/dist/input.js.map +0 -1
- package/dist/is-input-CXmS0OFN.js.map +0 -1
- package/dist/kbd-Bv6tefdB.js.map +0 -1
- package/dist/label-DhIUmTN2.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/media-object.js.map +0 -1
- package/dist/multi-select.js.map +0 -1
- package/dist/otp-input.js.map +0 -1
- package/dist/pagination.js.map +0 -1
- package/dist/popover-DponNBot.js.map +0 -1
- package/dist/primitive-Cn3h4DJg.js.map +0 -1
- package/dist/progress.js.map +0 -1
- package/dist/qr-code.js.map +0 -1
- package/dist/radio-group.js.map +0 -1
- package/dist/resolve-pre-rendered-props-C-vrNxH1.js.map +0 -1
- package/dist/sandboxed-on-click.js.map +0 -1
- package/dist/select-Cxc9VmP8.js.map +0 -1
- package/dist/separator-Bqjy77rG.js.map +0 -1
- package/dist/sheet.js.map +0 -1
- package/dist/skeleton.js.map +0 -1
- package/dist/skip-to-main-link.js.map +0 -1
- package/dist/slider.js.map +0 -1
- package/dist/slot-CV5fmqFr.js.map +0 -1
- package/dist/sort-BPX2Fk9t.js.map +0 -1
- package/dist/split-button.js.map +0 -1
- package/dist/svg-only-Cz1cby8y.js.map +0 -1
- package/dist/switch.js.map +0 -1
- package/dist/table-eyoUW2Uv.js +0 -2
- package/dist/table-eyoUW2Uv.js.map +0 -1
- package/dist/tabs.js.map +0 -1
- package/dist/text-area.js.map +0 -1
- package/dist/theme-provider-MMwxHEfw.js.map +0 -1
- package/dist/theme.js.map +0 -1
- package/dist/toast-CR3MVChj.js.map +0 -1
- package/dist/tooltip.js.map +0 -1
- package/dist/traffic-policy-file-0g5RXFqu.js.map +0 -1
- package/dist/types-D85fCNV3.js.map +0 -1
- package/dist/use-copy-to-clipboard-BLpquU9d.js.map +0 -1
- package/dist/use-isomorphic-layout-effect-DdTRtMY-.js.map +0 -1
- package/dist/use-matches-media-query-CMSxHR9n.js.map +0 -1
- package/dist/use-prefers-reduced-motion-CWIoFA6W.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/validation-DCyx-ceH.js.map +0 -1
- package/dist/variant-props-CVymuSfa.d.ts +0 -13
- package/dist/well.js.map +0 -1
package/dist/progress.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"progress.js","names":["defaultMax","ProgressContext","Root","Indicator","clsx"],"sources":["../src/components/progress/math.ts","../src/components/progress/progress-donut.tsx","../src/components/progress/progress-bar.tsx"],"sourcesContent":["/**\n * Clamp a value between a minimum and maximum value.\n */\nfunction clamp(value: number, { min, max }: { min: number; max: number }): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Check if a value is a number.\n */\nfunction isNumber(value: unknown): value is number {\n\treturn typeof value === \"number\";\n}\n\n/**\n * Check if a value is a valid number within the range of 0 to `max`.\n */\nfunction isValidValueNumber(value: unknown, max: number): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value <= max && value >= 0;\n}\n\n/**\n * Check if a value is a valid number greater than 0.\n */\nfunction isValidMaxNumber(value: unknown): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value > 0;\n}\n\nexport {\n\t//,\n\tclamp,\n\tisNumber,\n\tisValidValueNumber,\n\tisValidMaxNumber,\n};\n","import clsx from \"clsx\";\nimport { createContext, useContext, useId, useMemo } from \"react\";\nimport type { ComponentProps, HTMLAttributes } from \"react\";\nimport { $cssProperties } from \"../../types/index.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { clamp, isNumber, isValidMaxNumber, isValidValueNumber } from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\ntype RemValue = `${number}rem`;\ntype StrokeWidth = number | RemValue;\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tstrokeWidth: StrokeWidth;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tstrokeWidth: \"0.25rem\",\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext = createContext<ProgressContextValue>(defaultContextValue);\n\ntype SvgAttributes = Omit<\n\tHTMLAttributes<SVGElement>,\n\t\"viewBox\" | \"role\" | \"aria-valuemax\" | \"aria-valuemin\" | \"aria-valuenow\" | \"width\" | \"height\"\n>;\n\ntype Props = SvgAttributes & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The width of the progress bar stroke.\n\t * Note, we clamp the stroke width to a minimum of 1px and max of 12px since\n\t * it is proportional to the viewbox size (0 0 32 32).\n\t *\n\t * @default 0.25rem (4px)\n\t */\n\tstrokeWidth?: StrokeWidth;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate.\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n\t/**\n\t * Controls the rotation speed of the indeterminate spinner state.\n\t *\n\t * Accepts a Tailwind `animation-duration-*` utility (e.g. `animation-duration-[2s]`).\n\t *\n\t * This prop is applied in addition to `animate-spin` to control the speed of the indeterminate spinner.\n\t * @default `animation-duration-[15s]`\n\t */\n\tindeterminateRotationSpeed?: `animation-duration-${string}`;\n};\n\n/**\n * A simple circular progress bar which shows the completion progress of a task.\n *\n * The indicator color is inherited via `currentColor`. Override the default\n * (`accent-600`) by setting the `ProgressDonut.Indicator`'s text color.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut\n *\n * @example\n * ```tsx\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator />\n * </ProgressDonut.Root>\n *\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator color=\"text-danger-600\" />\n * </ProgressDonut.Root>\n * ```\n */\nconst Root = ({\n\tchildren,\n\tclassName,\n\tmax: _max = defaultMax,\n\tstrokeWidth: _strokeWidth = 4,\n\tvalue: _value,\n\tindeterminateRotationSpeed,\n\t...props\n}: Props) => {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max) ? _value : _value == null ? 0 : \"indeterminate\"\n\t) satisfies ValueType;\n\tconst strokeWidthPx = deriveStrokeWidthPx(_strokeWidth ?? defaultContextValue.strokeWidth);\n\tconst valueNow = isNumber(value) ? value : undefined;\n\tconst radius = calcRadius(strokeWidthPx);\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tstrokeWidth: strokeWidthPx,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, strokeWidthPx, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<svg\n\t\t\t\tdata-slot=\"progress-donut\"\n\t\t\t\taria-valuemax={max}\n\t\t\t\taria-valuemin={0}\n\t\t\t\taria-valuenow={valueNow}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"size-6 text-gray-200 dark:text-gray-300\",\n\t\t\t\t\tvalue === \"indeterminate\" && [\n\t\t\t\t\t\t\"animate-spin\",\n\t\t\t\t\t\t// Default duration only if consumer hasn't set one.\n\t\t\t\t\t\t// Without this guard, both our `[15s]` and consumer overrides (e.g. `[2s]`)\n\t\t\t\t\t\t// end up in the DOM. Since tw-animate-css utilities aren't currently deduped by\n\t\t\t\t\t\t// tailwind-merge, whichever class Tailwind happened to emit last wins,\n\t\t\t\t\t\t// which isn't reliable.\n\t\t\t\t\t\tindeterminateRotationSpeed ?? \"animation-duration-[15s]\",\n\t\t\t\t\t],\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-max={max}\n\t\t\t\tdata-min={0}\n\t\t\t\tdata-value={valueNow}\n\t\t\t\theight=\"100%\"\n\t\t\t\trole=\"progressbar\"\n\t\t\t\twidth=\"100%\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<circle\n\t\t\t\t\tclassName=\"[r:var(--radius)]\"\n\t\t\t\t\tcx=\"50%\"\n\t\t\t\t\tcy=\"50%\"\n\t\t\t\t\tfill=\"transparent\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\t\tstyle={$cssProperties({ \"--radius\": radius })}\n\t\t\t\t/>\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t</ProgressContext.Provider>\n\t);\n};\nRoot.displayName = \"ProgressDonut\";\n\n/**\n * Length (value) of the progress indicator tail when the progress bar is indeterminate.\n */\nconst indeterminateTailPercent = 0.6;\n\ntype ProgressDonutIndicatorProps = Omit<ComponentProps<\"g\">, \"children\">;\n\n/**\n * The indicator for the circular progress bar.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut-indicator\n *\n * @example\n * ```tsx\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator />\n * </ProgressDonut.Root>\n *\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator color=\"text-danger-600\" />\n * </ProgressDonut.Root>\n * ```\n */\nconst Indicator = ({ className, ...props }: ProgressDonutIndicatorProps) => {\n\tconst gradientId = useId();\n\tconst ctx = useContext(ProgressContext) ?? defaultContextValue;\n\tconst percentage =\n\t\t(ctx.value === \"indeterminate\" ? indeterminateTailPercent : ctx.value / ctx.max) * 100;\n\tconst strokeWidthPx = deriveStrokeWidthPx(ctx.strokeWidth);\n\tconst radius = calcRadius(strokeWidthPx);\n\n\treturn (\n\t\t<g data-slot=\"progress-donut-indicator\" className={cx(\"text-accent-600\", className)} {...props}>\n\t\t\t{ctx.value === \"indeterminate\" && (\n\t\t\t\t<defs>\n\t\t\t\t\t<linearGradient id={gradientId}>\n\t\t\t\t\t\t<stop className=\"stop-opacity-100 stop-color-current\" offset=\"0%\" />\n\t\t\t\t\t\t<stop className=\"stop-opacity-0 stop-color-current\" offset=\"95%\" />\n\t\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t)}\n\t\t\t<circle\n\t\t\t\tclassName={clsx(\n\t\t\t\t\t\"[r:var(--radius)]\", // set the circle radius to be the value of the calc'd CSS variable set on the style\n\t\t\t\t\t\"origin-center\",\n\t\t\t\t)}\n\t\t\t\tcx=\"50%\"\n\t\t\t\tcy=\"50%\"\n\t\t\t\tfill=\"transparent\"\n\t\t\t\tpathLength={100}\n\t\t\t\tstroke={ctx.value === \"indeterminate\" ? `url(#${gradientId})` : \"currentColor\"}\n\t\t\t\tstrokeDasharray={100}\n\t\t\t\tstrokeDashoffset={100 - percentage}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\tstyle={$cssProperties({ \"--radius\": radius })}\n\t\t\t\ttransform=\"rotate(-90)\" // rotate -90 degrees so it starts from the top\n\t\t\t/>\n\t\t</g>\n\t);\n};\nIndicator.displayName = \"ProgressDonutIndicator\";\n\n/**\n * A simple circular progress bar which shows the completion progress of a task.\n *\n * The indicator color is inherited via `currentColor`. Override the default\n * (`accent-600`) by setting the `ProgressDonut.Indicator`'s text color.\n *\n * @see https://mantle.ngrok.com/components/progress\n *\n * @example\n * Composition:\n * ```\n * ProgressDonut.Root\n * └── ProgressDonut.Indicator\n * ```\n *\n * @example\n * ```tsx\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator />\n * </ProgressDonut.Root>\n *\n * <ProgressDonut.Root value={60}>\n * <ProgressDonut.Indicator color=\"text-danger-600\" />\n * </ProgressDonut.Root>\n * ```\n */\nconst ProgressDonut = {\n\t/**\n\t * A simple circular progress bar which shows the completion progress of a task.\n\t *\n\t * The indicator color is inherited via `currentColor`. Override the default\n\t * (`accent-600`) by setting the `ProgressDonut.Indicator`'s text color.\n\t *\n\t * @see https://mantle.ngrok.com/components/progress#api-progress-donut-root\n\t *\n\t * @example\n\t * ```tsx\n\t * <ProgressDonut.Root value={60}>\n\t * <ProgressDonut.Indicator />\n\t * </ProgressDonut.Root>\n\t *\n\t * <ProgressDonut.Root value={60}>\n\t * <ProgressDonut.Indicator color=\"text-danger-600\" />\n\t * </ProgressDonut.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The indicator for the circular progress bar.\n\t *\n\t * @see https://mantle.ngrok.com/components/progress#api-progress-donut-indicator\n\t *\n\t * @example\n\t * ```tsx\n\t * <ProgressDonut.Root value={60}>\n\t * <ProgressDonut.Indicator />\n\t * </ProgressDonut.Root>\n\t *\n\t * <ProgressDonut.Root value={60}>\n\t * <ProgressDonut.Indicator color=\"text-danger-600\" />\n\t * </ProgressDonut.Root>\n\t * ```\n\t */\n\tIndicator,\n} as const;\n\nexport {\n\t//,\n\tProgressDonut,\n};\n\n/**\n * Derive the stroke width in pixels as a number value or pixels/rem from a string value.\n * Note, this function clamps the stroke width to a minimum of 1 and max of 12 since\n * it is proportional to the viewbox size (0 0 32 32).\n *\n * @example\n * ```tsx\n * const strokeWidth1 = deriveStrokeWidthPx(8);\n * // Returns: 8\n *\n * const strokeWidth2 = deriveStrokeWidthPx(\"0.5rem\");\n * // Returns: 8 (0.5 * 16)\n *\n * const strokeWidth3 = deriveStrokeWidthPx(20);\n * // Returns: 12 (clamped to maximum)\n * ```\n */\nexport function deriveStrokeWidthPx(strokeWidth: number | string | undefined | null): number {\n\tlet value = 4;\n\tif (strokeWidth == null) {\n\t\treturn value;\n\t}\n\n\tif (typeof strokeWidth === \"number\") {\n\t\tvalue = strokeWidth;\n\t} else if (strokeWidth.endsWith(\"rem\")) {\n\t\tvalue = Number(strokeWidth.replace(\"rem\", \"\")) * 16;\n\t} else {\n\t\tvalue = Number(strokeWidth);\n\t}\n\n\tconst stroke = Number.isNaN(value) ? 4 : value;\n\treturn clamp(stroke, { min: 1, max: 12 });\n}\n\n/**\n * Calculate the radius of the progress donut and indicator based on the stroke\n * width in pixels.\n */\nfunction calcRadius(strokeWidthPx: number) {\n\treturn `calc(50% - ${strokeWidthPx / 2}px)` as const;\n}\n","\"use client\";\n\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\n\nimport { type ComponentProps, createContext, useContext, useMemo } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { isNumber, isValidMaxNumber, isValidValueNumber } from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext = createContext<ProgressContextValue>(defaultContextValue);\n\ntype RootProps = ComponentProps<\"div\"> & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate. (for now there is no visual difference than 0)\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.\n *\n * A horizontal progress bar that shows the completion progress of a task.\n * Use this component for linear progress indication.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * <ProgressBar.Root value={75} max={100}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Indeterminate progress\n * <ProgressBar.Root value=\"indeterminate\">\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nfunction Root({ className, children, max: _max = defaultMax, value: _value, ...props }: RootProps) {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max) ? _value : _value == null ? 0 : \"indeterminate\"\n\t) satisfies ValueType;\n\n\tconst valueNow = isNumber(value) ? value : undefined;\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<ProgressPrimitive.Root\n\t\t\t\tdata-slot=\"progress-bar\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"bg-base-hover dark:bg-base shadow-inner relative h-3 w-full overflow-hidden rounded-md\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tvalue={valueNow}\n\t\t\t\tmax={max}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ProgressPrimitive.Root>\n\t\t</ProgressContext.Provider>\n\t);\n}\nRoot.displayName = \"Root\";\n\ntype IndicatorProps = ComponentProps<typeof ProgressPrimitive.Indicator>;\n\n/**\n * Displays the progress indicator, which visually represents the completion progress of a task.\n *\n * The visual indicator that shows the actual progress within the progress bar.\n * This component should be used inside a ProgressBar.Root component.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar-indicator\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Custom styled indicator\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator className=\"bg-success-600\" />\n * </ProgressBar.Root>\n * ```\n */\nfunction Indicator({ className, style, ...props }: IndicatorProps) {\n\tconst ctx = useContext(ProgressContext);\n\tconst { max } = ctx;\n\tconst value = ctx.value === \"indeterminate\" ? 0 : ctx.value;\n\tconst translatePercent = ((max - value) / max) * 100;\n\n\treturn (\n\t\t<ProgressPrimitive.Indicator\n\t\t\tdata-slot=\"progress-bar-indicator\"\n\t\t\tclassName={cx(\"bg-accent-600 h-full w-full flex-1 transition-all\", className)}\n\t\t\tstyle={{ ...style, transform: `translateX(-${translatePercent}%)` }}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nIndicator.displayName = \"Indicator\";\n\n/**\n * Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.\n *\n * A horizontal progress bar that shows the completion progress of a task.\n * Use this component for linear progress indication.\n *\n * @see https://mantle.ngrok.com/components/progress\n *\n * @example\n * Composition:\n * ```\n * ProgressBar.Root\n * └── ProgressBar.Indicator\n * ```\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * <ProgressBar.Root value={75} max={100}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Indeterminate progress\n * <ProgressBar.Root value=\"indeterminate\">\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nconst ProgressBar = {\n\t/**\n\t * Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.\n\t *\n\t * A horizontal progress bar that shows the completion progress of a task.\n\t * Use this component for linear progress indication.\n\t *\n\t * @see https://mantle.ngrok.com/components/progress#api-progress-bar\n\t *\n\t * @example\n\t * ```tsx\n\t * <ProgressBar.Root value={60}>\n\t * <ProgressBar.Indicator />\n\t * </ProgressBar.Root>\n\t *\n\t * <ProgressBar.Root value={75} max={100}>\n\t * <ProgressBar.Indicator />\n\t * </ProgressBar.Root>\n\t *\n\t * // Indeterminate progress\n\t * <ProgressBar.Root value=\"indeterminate\">\n\t * <ProgressBar.Indicator />\n\t * </ProgressBar.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * Displays the progress indicator, which visually represents the completion progress of a task.\n\t *\n\t * The visual indicator that shows the actual progress within the progress bar.\n\t * This component should be used inside a ProgressBar.Root component.\n\t *\n\t * @see https://mantle.ngrok.com/components/progress#api-progress-bar-indicator\n\t *\n\t * @example\n\t * ```tsx\n\t * <ProgressBar.Root value={60}>\n\t * <ProgressBar.Indicator />\n\t * </ProgressBar.Root>\n\t *\n\t * // Custom styled indicator\n\t * <ProgressBar.Root value={60}>\n\t * <ProgressBar.Indicator className=\"bg-success-600\" />\n\t * </ProgressBar.Root>\n\t * ```\n\t */\n\tIndicator,\n} as const;\n\nexport {\n\t//,\n\tProgressBar,\n};\n"],"mappings":"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"}
|
package/dist/qr-code.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"qr-code.js","names":[],"sources":["../src/components/qr-code/qr-code.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { createContext, forwardRef, useContext, useMemo } from \"react\";\nimport invariant from \"tiny-invariant\";\nimport { encode } from \"uqr\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { Slot } from \"../slot/index.js\";\n\n/**\n * The encoded geometry shared from `QrCode.Root` to the SVG rendering parts.\n */\ntype QrCodeContextValue = {\n\t/** The `d` attribute for the QR `Pattern` path. */\n\tpath: string;\n\t/** The width/height of the (square) QR `Frame` viewBox. */\n\tdimension: number;\n};\n\nconst QrCodeContext = createContext<QrCodeContextValue | null>(null);\n\n/**\n * Validates sizing props before they reach `uqr` or SVG coordinate math.\n *\n * @throws When `pixelSize` is not a finite positive number, or `quietZone` is\n * not a non-negative integer.\n *\n * @example\n * ```ts\n * assertValidRootProps(10, 4);\n * ```\n */\nfunction assertValidRootProps(pixelSize: number, quietZone: number): void {\n\tinvariant(\n\t\tNumber.isFinite(pixelSize) && pixelSize > 0,\n\t\t\"`QrCode.Root` pixelSize must be a finite number greater than 0.\",\n\t);\n\tinvariant(\n\t\tNumber.isInteger(quietZone) && quietZone >= 0,\n\t\t\"`QrCode.Root` quietZone must be a non-negative integer.\",\n\t);\n}\n\n/**\n * Reads the QR code context provided by `QrCode.Root`. Throws a clear error when\n * a part is rendered outside of a `QrCode.Root`.\n *\n * @example\n * ```tsx\n * const { dimension, path } = useQrCodeContext();\n * ```\n */\nfunction useQrCodeContext(): QrCodeContextValue {\n\tconst context = useContext(QrCodeContext);\n\tinvariant(\n\t\tcontext,\n\t\t\"`QrCode.Frame` and `QrCode.Pattern` must be rendered inside a `QrCode.Root`.\",\n\t);\n\treturn context;\n}\n\n/**\n * Builds the SVG `path` `d` attribute for a QR code by emitting one square\n * (`M x,y h s v s h-s z`) per dark module in the encoded grid, scaled by\n * `pixelSize`. Returns an empty string when there are no dark modules.\n *\n * @example\n * ```ts\n * buildPath([[true, false], [false, true]], 10);\n * // \"M0,0h10v10h-10zM10,10h10v10h-10z\"\n * ```\n */\nfunction buildPath(modules: ReadonlyArray<ReadonlyArray<boolean>>, pixelSize: number): string {\n\tconst rects: string[] = [];\n\tmodules.forEach((columns, row) => {\n\t\tcolumns.forEach((isDark, col) => {\n\t\t\tif (isDark) {\n\t\t\t\tconst x = col * pixelSize;\n\t\t\t\tconst y = row * pixelSize;\n\t\t\t\trects.push(`M${x},${y}h${pixelSize}v${pixelSize}h-${pixelSize}z`);\n\t\t\t}\n\t\t});\n\t});\n\treturn rects.join(\"\");\n}\n\n/**\n * QR error correction level — the share of the code that can be damaged or\n * obscured while staying scannable: `\"L\"` ~7%, `\"M\"` ~15%, `\"Q\"` ~25%, `\"H\"`\n * ~30%. Higher levels produce a denser code.\n */\ntype QrCodeErrorCorrection = \"L\" | \"M\" | \"Q\" | \"H\";\n\n/**\n * Props for `QrCode.Root`, the provider and positioned tile that encodes the QR\n * value for child parts.\n */\ntype QrCodeRootProps = ComponentProps<\"div\"> &\n\tWithAsChild & {\n\t\t/** The string to encode (e.g. a URL or `otpauth://` MFA URI). */\n\t\tvalue: string;\n\t\t/**\n\t\t * The error correction level. Defaults to `\"L\"`. Use `\"H\"` when an\n\t\t * `Overlay` covers center modules so the code stays scannable.\n\t\t */\n\t\tecc?: QrCodeErrorCorrection;\n\t\t/** The pixel size of each module, affecting internal resolution. */\n\t\tpixelSize?: number;\n\t\t/**\n\t\t * Width of the quiet zone — the light-module margin baked into the encoded\n\t\t * grid around the code, not cosmetic CSS padding. Defaults to `4`, the QR\n\t\t * spec's recommended margin for reliable scanning. Lower values tighten the\n\t\t * surrounding whitespace but can hurt scannability; avoid `0`.\n\t\t */\n\t\tquietZone?: number;\n\t};\n\n/**\n * The root container of a QR code. Encodes `value` (via the dependency-free\n * `uqr` encoder) and renders a positioned white tile around the QR `Frame`,\n * sharing the encoded path with the other parts via context.\n *\n * Set the error correction level via `ecc`. When you place a logo in an\n * `Overlay`, use `ecc=\"H\"` so the covered modules can still be recovered by a\n * scanner. Tighten the surrounding whitespace with `quietZone` (defaults to the\n * spec-recommended `4` light modules).\n *\n * The default styling is black modules on a white tile in every theme (never\n * theme-aware tokens). Consumers can override those styles, but inverting a QR\n * code's colors makes it unreliable for many scanners.\n *\n * @see https://mantle.ngrok.com/components/qr-code\n *\n * @example\n * ```tsx\n * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n * <QrCode.Frame>\n * <QrCode.Pattern />\n * </QrCode.Frame>\n * <QrCode.Overlay>\n * <NgrokLettermarkIcon className=\"size-7\" />\n * </QrCode.Overlay>\n * </QrCode.Root>\n * ```\n */\nconst Root = forwardRef<HTMLDivElement, QrCodeRootProps>(\n\t(\n\t\t{ value, ecc = \"L\", pixelSize = 10, quietZone = 4, asChild, className, children, ...props },\n\t\tref,\n\t) => {\n\t\tassertValidRootProps(pixelSize, quietZone);\n\n\t\t// The quiet zone is the QR spec's required margin (light modules on each\n\t\t// side). It's part of the code itself — the scannable margin — not cosmetic\n\t\t// padding. The spec recommends 4; lowering it tightens the whitespace at\n\t\t// the cost of scannability.\n\t\tconst encoded = useMemo(\n\t\t\t() => encode(value, { ecc, border: quietZone }),\n\t\t\t[value, ecc, quietZone],\n\t\t);\n\t\tconst path = useMemo(() => buildPath(encoded.data, pixelSize), [encoded, pixelSize]);\n\t\tconst context = useMemo<QrCodeContextValue>(\n\t\t\t() => ({ path, dimension: encoded.size * pixelSize }),\n\t\t\t[path, encoded.size, pixelSize],\n\t\t);\n\n\t\tconst Comp = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<QrCodeContext.Provider value={context}>\n\t\t\t\t<Comp\n\t\t\t\t\tref={ref}\n\t\t\t\t\t{...props}\n\t\t\t\t\tdata-slot=\"qr-code\"\n\t\t\t\t\tclassName={cx(\"relative inline-flex bg-static-white text-static-black\", className)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</Comp>\n\t\t\t</QrCodeContext.Provider>\n\t\t);\n\t},\n);\nRoot.displayName = \"QrCode\";\n\n/**\n * Props for `QrCode.Frame`, the fixed SVG element that sizes the encoded QR\n * pattern with its `viewBox`.\n */\ntype QrCodeFrameProps = ComponentProps<\"svg\">;\n\n/**\n * The `svg` frame that holds the QR `Pattern`. Defaults to a square `size-48`\n * and scales the encoded pattern to fit via its `viewBox`, so resize the whole\n * code by passing a different size to `className` (e.g. `className=\"size-64\"`).\n *\n * Does not support `asChild`: the QR pattern must live inside an `svg`, so the\n * frame element is fixed and cannot be swapped.\n *\n * @see https://mantle.ngrok.com/components/qr-code\n *\n * @example\n * ```tsx\n * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n * <QrCode.Frame>\n * <QrCode.Pattern />\n * </QrCode.Frame>\n * <QrCode.Overlay>\n * <NgrokLettermarkIcon className=\"size-7\" />\n * </QrCode.Overlay>\n * </QrCode.Root>\n * ```\n */\nconst Frame = forwardRef<SVGSVGElement, QrCodeFrameProps>(\n\t({ className, children, ...props }, ref) => {\n\t\tconst { dimension } = useQrCodeContext();\n\n\t\treturn (\n\t\t\t<svg\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t\tdata-slot=\"qr-code-frame\"\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tviewBox={`0 0 ${dimension} ${dimension}`}\n\t\t\t\tshapeRendering=\"crispEdges\"\n\t\t\t\tclassName={cx(\"block size-48\", className)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t);\n\t},\n);\nFrame.displayName = \"QrCodeFrame\";\n\n/**\n * Props for `QrCode.Pattern`, the fixed SVG `path` element that renders the\n * encoded dark modules.\n */\ntype QrCodePatternProps = ComponentProps<\"path\">;\n\n/**\n * The encoded QR modules, rendered as a single `path` inside the `Frame`.\n * Defaults to black fill (`fill-static-black`) so the code stays scannable in\n * every theme.\n *\n * Does not support `asChild`: the modules are a fixed `path` and cannot be\n * swapped for another element.\n *\n * @see https://mantle.ngrok.com/components/qr-code\n *\n * @example\n * ```tsx\n * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n * <QrCode.Frame>\n * <QrCode.Pattern />\n * </QrCode.Frame>\n * <QrCode.Overlay>\n * <NgrokLettermarkIcon className=\"size-7\" />\n * </QrCode.Overlay>\n * </QrCode.Root>\n * ```\n */\nconst Pattern = forwardRef<SVGPathElement, QrCodePatternProps>(({ className, ...props }, ref) => {\n\tconst { path } = useQrCodeContext();\n\n\treturn (\n\t\t<path\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t\tdata-slot=\"qr-code-pattern\"\n\t\t\td={path}\n\t\t\tclassName={cx(\"fill-static-black\", className)}\n\t\t/>\n\t);\n});\nPattern.displayName = \"QrCodePattern\";\n\n/**\n * Props for `QrCode.Overlay`, the optional centered logo container rendered on\n * top of the QR pattern.\n */\ntype QrCodeOverlayProps = ComponentProps<\"div\"> & WithAsChild;\n\n/**\n * An overlay centered on top of the QR code, typically holding a brand logo\n * (e.g. `NgrokLettermarkIcon`). Renders a white, rounded \"punch-out\" so the\n * logo stays legible over the modules beneath it. Because the overlay hides the\n * center modules, use a higher `ecc` (e.g. `\"H\"`) on the `Root`.\n *\n * @see https://mantle.ngrok.com/components/qr-code\n *\n * @example\n * ```tsx\n * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n * <QrCode.Frame>\n * <QrCode.Pattern />\n * </QrCode.Frame>\n * <QrCode.Overlay>\n * <NgrokLettermarkIcon className=\"size-7\" />\n * </QrCode.Overlay>\n * </QrCode.Root>\n * ```\n */\nconst Overlay = forwardRef<HTMLDivElement, QrCodeOverlayProps>(\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\t{...props}\n\t\t\t\tdata-slot=\"qr-code-overlay\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-md bg-static-white text-static-black p-1.5\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t/>\n\t\t);\n\t},\n);\nOverlay.displayName = \"QrCodeOverlay\";\n\n/**\n * A QR code. Compose `QrCode.Root` with a `QrCode.Frame` wrapping a\n * `QrCode.Pattern`, and optionally a `QrCode.Overlay` for a centered logo.\n * Encoding is handled by the dependency-free `uqr` library; the render logic is\n * owned by mantle (no headless runtime).\n *\n * `Root` and `Overlay` support the `asChild` prop for polymorphic composition.\n * `Frame` and `Pattern` render fixed SVG elements and do not.\n *\n * @see https://mantle.ngrok.com/components/qr-code\n *\n * @example\n * Composition:\n * ```\n * QrCode.Root\n * ├── QrCode.Frame\n * │ └── QrCode.Pattern\n * └── QrCode.Overlay\n * ```\n *\n * @example\n * ```tsx\n * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n * <QrCode.Frame>\n * <QrCode.Pattern />\n * </QrCode.Frame>\n * <QrCode.Overlay>\n * <NgrokLettermarkIcon className=\"size-7\" />\n * </QrCode.Overlay>\n * </QrCode.Root>\n * ```\n */\nconst QrCode = {\n\t/**\n\t * The root container of a QR code. Encodes `value` and renders a positioned\n\t * white tile. Set `ecc` (e.g. `\"H\"` when using an `Overlay`).\n\t *\n\t * @see https://mantle.ngrok.com/components/qr-code\n\t *\n\t * @example\n\t * ```tsx\n\t * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n\t * <QrCode.Frame>\n\t * <QrCode.Pattern />\n\t * </QrCode.Frame>\n\t * <QrCode.Overlay>\n\t * <NgrokLettermarkIcon className=\"size-7\" />\n\t * </QrCode.Overlay>\n\t * </QrCode.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The `svg` frame that holds the QR `Pattern`. Defaults to `size-48`; resize\n\t * the whole code by passing a different size to `className`.\n\t *\n\t * @see https://mantle.ngrok.com/components/qr-code\n\t *\n\t * @example\n\t * ```tsx\n\t * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n\t * <QrCode.Frame>\n\t * <QrCode.Pattern />\n\t * </QrCode.Frame>\n\t * <QrCode.Overlay>\n\t * <NgrokLettermarkIcon className=\"size-7\" />\n\t * </QrCode.Overlay>\n\t * </QrCode.Root>\n\t * ```\n\t */\n\tFrame,\n\t/**\n\t * The encoded QR modules, rendered as a `path` inside the `Frame`. Defaults\n\t * to black fill so the code stays scannable in every theme.\n\t *\n\t * @see https://mantle.ngrok.com/components/qr-code\n\t *\n\t * @example\n\t * ```tsx\n\t * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n\t * <QrCode.Frame>\n\t * <QrCode.Pattern />\n\t * </QrCode.Frame>\n\t * <QrCode.Overlay>\n\t * <NgrokLettermarkIcon className=\"size-7\" />\n\t * </QrCode.Overlay>\n\t * </QrCode.Root>\n\t * ```\n\t */\n\tPattern,\n\t/**\n\t * An overlay centered on top of the QR code, typically holding a brand logo.\n\t * Renders a white rounded \"punch-out\" so the logo stays legible. Use a higher\n\t * `ecc` on the `Root` when an overlay is present.\n\t *\n\t * @see https://mantle.ngrok.com/components/qr-code\n\t *\n\t * @example\n\t * ```tsx\n\t * <QrCode.Root value=\"https://ngrok.com\" ecc=\"H\">\n\t * <QrCode.Frame>\n\t * <QrCode.Pattern />\n\t * </QrCode.Frame>\n\t * <QrCode.Overlay>\n\t * <NgrokLettermarkIcon className=\"size-7\" />\n\t * </QrCode.Overlay>\n\t * </QrCode.Root>\n\t * ```\n\t */\n\tOverlay,\n} as const;\n\nexport {\n\t//,\n\tbuildPath,\n\tQrCode,\n};\n\nexport type {\n\t//,\n\tQrCodeErrorCorrection,\n\tQrCodeFrameProps,\n\tQrCodeOverlayProps,\n\tQrCodePatternProps,\n\tQrCodeRootProps,\n};\n"],"mappings":"6PAoBA,MAAM,EAAgB,EAAyC,IAAI,EAanE,SAAS,EAAqB,EAAmB,EAAyB,CACzE,EACC,OAAO,SAAS,CAAS,GAAK,EAAY,EAC1C,iEACD,EACA,EACC,OAAO,UAAU,CAAS,GAAK,GAAa,EAC5C,yDACD,CACD,CAWA,SAAS,GAAuC,CAC/C,IAAM,EAAU,EAAW,CAAa,EAKxC,OAJA,EACC,EACA,8EACD,EACO,CACR,CAaA,SAAS,EAAU,EAAgD,EAA2B,CAC7F,IAAM,EAAkB,CAAC,EAUzB,OATA,EAAQ,SAAS,EAAS,IAAQ,CACjC,EAAQ,SAAS,EAAQ,IAAQ,CAChC,GAAI,EAAQ,CACX,IAAM,EAAI,EAAM,EACV,EAAI,EAAM,EAChB,EAAM,KAAK,IAAI,EAAE,GAAG,EAAE,GAAG,EAAU,GAAG,EAAU,IAAI,EAAU,EAAE,CACjE,CACD,CAAC,CACF,CAAC,EACM,EAAM,KAAK,EAAE,CACrB,CA6DA,MAAM,EAAO,GAEX,CAAE,QAAO,MAAM,IAAK,YAAY,GAAI,YAAY,EAAG,UAAS,YAAW,WAAU,GAAG,GACpF,IACI,CACJ,EAAqB,EAAW,CAAS,EAMzC,IAAM,EAAU,MACT,EAAO,EAAO,CAAE,MAAK,OAAQ,CAAU,CAAC,EAC9C,CAAC,EAAO,EAAK,CAAS,CACvB,EACM,EAAO,MAAc,EAAU,EAAQ,KAAM,CAAS,EAAG,CAAC,EAAS,CAAS,CAAC,EAC7E,EAAU,OACR,CAAE,OAAM,UAAW,EAAQ,KAAO,CAAU,GACnD,CAAC,EAAM,EAAQ,KAAM,CAAS,CAC/B,EAEM,EAAO,EAAU,EAAO,MAE9B,OACC,EAAC,EAAc,SAAf,CAAwB,MAAO,WAC9B,EAAC,EAAD,CACM,MACL,GAAI,EACJ,YAAU,UACV,UAAW,EAAG,yDAA0D,CAAS,EAEhF,UACI,CAAA,CACiB,CAAA,CAE1B,CACD,EACA,EAAK,YAAc,SA8BnB,MAAM,EAAQ,GACZ,CAAE,YAAW,WAAU,GAAG,GAAS,IAAQ,CAC3C,GAAM,CAAE,aAAc,EAAiB,EAEvC,OACC,EAAC,MAAD,CACM,MACL,GAAI,EACJ,YAAU,gBACV,MAAM,6BACN,QAAS,OAAO,EAAU,GAAG,IAC7B,eAAe,aACf,UAAW,EAAG,gBAAiB,CAAS,EAEvC,UACG,CAAA,CAEP,CACD,EACA,EAAM,YAAc,cA8BpB,MAAM,EAAU,GAAgD,CAAE,YAAW,GAAG,GAAS,IAAQ,CAChG,GAAM,CAAE,QAAS,EAAiB,EAElC,OACC,EAAC,OAAD,CACM,MACL,GAAI,EACJ,YAAU,kBACV,EAAG,EACH,UAAW,EAAG,oBAAqB,CAAS,CAC5C,CAAA,CAEH,CAAC,EACD,EAAQ,YAAc,gBA4BtB,MAAM,EAAU,GACd,CAAE,UAAS,YAAW,GAAG,GAAS,IAIjC,EAHY,EAAU,EAAO,MAG7B,CACM,MACL,GAAI,EACJ,YAAU,kBACV,UAAW,EACV,kJACA,CACD,CACA,CAAA,CAGJ,EACA,EAAQ,YAAc,gBAkCtB,MAAM,EAAS,CAmBd,OAmBA,QAmBA,UAoBA,SACD"}
|
package/dist/radio-group.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"radio-group.js","names":["HeadlessRadioGroup","HeadlessRadio","clsx"],"sources":["../src/components/radio-group/radio-group.tsx"],"sourcesContent":["\"use client\";\n\nimport { Radio as HeadlessRadio, RadioGroup as HeadlessRadioGroup } from \"@headlessui/react\";\nimport type {\n\tRadioGroupProps as HeadlessRadioGroupProps,\n\tRadioProps as HeadlessRadioProps,\n} from \"@headlessui/react\";\nimport clsx from \"clsx\";\nimport {\n\tChildren,\n\tcloneElement,\n\tcreateContext,\n\tforwardRef,\n\tisValidElement,\n\tuseContext,\n\tuseRef,\n} from \"react\";\nimport type { ComponentRef, HTMLAttributes, PropsWithChildren, ReactNode } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { FieldControlContext } from \"../field/field-context.js\";\nimport { isInput } from \"../input/is-input.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype RadioGroupProps = PropsWithChildren<Omit<HeadlessRadioGroupProps, \"as\" | \"children\">>;\n\n/**\n * A group of radio items. It manages the state of the children radios. Unstyled and simple.\n * Used as the root component for grouping related radio items where only one can be selected.\n *\n * The recommended Field composition is `Field.Set` + `Field.Legend` + `RadioGroup.Root`,\n * which uses fieldset semantics so all radios share a single accessible name from the\n * legend. As an alternative, when individual items render inside a `Field.Control`,\n * each item picks up `aria-invalid` and `aria-errormessage` from `FieldControlContext`.\n * Note: `aria-describedby` is owned by Headless UI's Radio primitive and does not\n * propagate through `FieldControlContext`, so helper text wired via `Field.Description`\n * will not be associated automatically in that alternative composition.\n *\n * @see https://mantle.ngrok.com/components/radio-group#radiogrouproot\n *\n * @example\n * ```tsx\n * <RadioGroup value={value} onValueChange={setValue}>\n * <RadioGroup.Item value=\"option1\">\n * <RadioGroup.Indicator />\n * <span>Option 1</span>\n * </RadioGroup.Item>\n * <RadioGroup.Item value=\"option2\">\n * <RadioGroup.Indicator />\n * <span>Option 2</span>\n * </RadioGroup.Item>\n * </RadioGroup>\n * ```\n */\nconst Root = forwardRef<ComponentRef<typeof HeadlessRadioGroup>, RadioGroupProps>((props, ref) => (\n\t<HeadlessRadioGroup data-slot=\"radio-group\" {...props} ref={ref} />\n));\nRoot.displayName = \"RadioGroup\";\n\n/**\n * The shape of the radio state context.\n */\ntype RadioStateContextValue = {\n\tautofocus: boolean;\n\tchecked: boolean;\n\tdisabled: boolean;\n\tfocus: boolean;\n\thover: boolean;\n};\n\n/**\n * The radio state. It's used to pass the state of the radio to its children components.\n * It's used internally by the radio components to manage the state/style of the radio items.\n * Used in place of css classes to avoid specificity issues and slightly improve performance.\n */\nconst RadioStateContext = createContext<RadioStateContextValue>({\n\tautofocus: false,\n\tchecked: false,\n\tdisabled: false,\n\tfocus: false,\n\thover: false,\n});\n\ntype RadioItemProps = Omit<HeadlessRadioProps, \"children\"> & PropsWithChildren;\n\n/**\n * A simple radio item that can be used inside a radio group. The \"conventional\" use-case.\n * Must be a child of `RadioGroup`.\n *\n * When rendered inside `Field.Control` (an alternative to the recommended\n * `Field.Set` / `Field.Legend` composition), picks up `aria-invalid` and\n * `aria-errormessage` from `FieldControlContext`. `aria-describedby` is owned\n * by Headless UI's Radio primitive and does not propagate.\n *\n * @see https://mantle.ngrok.com/components/radio-group#radiogroupitem\n *\n * @example\n * ```tsx\n * <RadioGroup value={value} onValueChange={setValue}>\n * <RadioGroup.Item value=\"option1\">\n * <RadioGroup.Indicator />\n * <span>Option 1</span>\n * </RadioGroup.Item>\n * </RadioGroup>\n * ```\n */\nconst Item = forwardRef<ComponentRef<\"div\">, RadioItemProps>(\n\t({ children, className, ...props }, ref) => {\n\t\tconst fieldControl = useContext(FieldControlContext);\n\t\treturn (\n\t\t\t<HeadlessRadio\n\t\t\t\tdata-slot=\"radio-group-item\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"group/radio cursor-pointer aria-disabled:cursor-default [&_label]:cursor-inherit flex gap-2 py-1 text-sm focus:outline-hidden\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tas=\"div\"\n\t\t\t\t{...props}\n\t\t\t\t{...(fieldControl\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"aria-describedby\": fieldControl[\"aria-describedby\"],\n\t\t\t\t\t\t\t\"aria-errormessage\": fieldControl[\"aria-errormessage\"],\n\t\t\t\t\t\t\t\"aria-invalid\": fieldControl[\"aria-invalid\"],\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined)}\n\t\t\t\tref={ref}\n\t\t\t>\n\t\t\t\t{(ctx) => <RadioStateContext.Provider value={ctx}>{children}</RadioStateContext.Provider>}\n\t\t\t</HeadlessRadio>\n\t\t);\n\t},\n);\nItem.displayName = \"RadioItem\";\n\ntype RadioIndicatorProps = Omit<HTMLAttributes<HTMLDivElement>, \"children\"> & {\n\tchildren?: ReactNode | ((context: RadioStateContextValue) => ReactNode);\n};\n\n/**\n * The default radio indicator.\n * @private\n */\nconst DefaultRadioIndicator = ({ checked, disabled, focus, hover }: RadioStateContextValue) => (\n\t<span\n\t\tclassName={cx(\n\t\t\t\"border-form flex size-4 items-center justify-center rounded-full border shrink-0\",\n\t\t\tdisabled && \"cursor-default opacity-50\",\n\t\t\tchecked && \"border-accent-600 bg-accent-600\",\n\t\t\tfocus && !disabled && \"border-accent-600 ring-focus-accent ring-4\",\n\t\t\thover && \"border-accent-600\",\n\t\t)}\n\t>\n\t\t{checked && <span className=\"size-2 rounded-full bg-white shrink-0\" />}\n\t</span>\n);\n\n/**\n * The selection indicator for any radio item.\n * Use it as a child of `RadioGroup.Item`, `RadioGroup.ListItem`, or `RadioGroup.Card`.\n * By default, it's a circle that changes color when checked.\n * You can customize the indicator by passing children:\n * - a different component\n * - a render-props function that receives the radio state context and should return a component.\n *\n * @see https://mantle.ngrok.com/components/radio-group#radiogroupindicator\n *\n * @example\n * ```tsx\n * <RadioGroup.Item value=\"option1\">\n * <RadioGroup.Indicator />\n * <span>Option 1</span>\n * </RadioGroup.Item>\n * ```\n */\nconst Indicator = ({ children, className, ...props }: RadioIndicatorProps) => {\n\tconst ctx = useContext(RadioStateContext);\n\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"radio-group-indicator\"\n\t\t\tclassName={cx(\n\t\t\t\t\"radio-indicator inline-flex size-5 select-none items-center justify-center shrink-0\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children == null ? (\n\t\t\t\t<DefaultRadioIndicator {...ctx} />\n\t\t\t) : typeof children === \"function\" ? (\n\t\t\t\tchildren(ctx)\n\t\t\t) : (\n\t\t\t\tchildren\n\t\t\t)}\n\t\t</div>\n\t);\n};\nIndicator.displayName = \"RadioIndicator\";\n\n/**\n * A group of radio list items. Use RadioGroup.ListItem as direct children.\n */\nconst List = forwardRef<ComponentRef<typeof Root>, RadioGroupProps>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<Root\n\t\t\t\tdata-slot=\"radio-group-list\"\n\t\t\t\tclassName={clsx(\"-space-y-px\", className)}\n\t\t\t\t{...props}\n\t\t\t\tref={ref}\n\t\t\t/>\n\t\t);\n\t},\n);\nList.displayName = \"RadioGroupList\";\n\ntype RadioListItemProps = RadioItemProps;\n\n/**\n * A radio list item that is used inside a `RadioGroup.List`.\n *\n * When rendered inside `Field.Control` (an alternative to the recommended\n * `Field.Set` / `Field.Legend` composition), picks up `aria-invalid` and\n * `aria-errormessage` from `FieldControlContext`. `aria-describedby` is owned\n * by Headless UI's Radio primitive and does not propagate.\n */\nconst ListItem = forwardRef<ComponentRef<\"div\">, RadioListItemProps>(\n\t({ children, className, ...props }, ref) => {\n\t\tconst fieldControl = useContext(FieldControlContext);\n\t\treturn (\n\t\t\t<HeadlessRadio\n\t\t\t\tas=\"div\"\n\t\t\t\tdata-slot=\"radio-group-list-item\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"group/radio border-form [&_label]:cursor-inherit relative flex select-none gap-2 border px-3 py-2 text-sm\",\n\t\t\t\t\t\"cursor-pointer aria-disabled:cursor-default focus:outline-hidden\",\n\t\t\t\t\t\"focus-visible:ring-focus-accent not-aria-disabled:focus-visible:border-accent-600 focus-visible:ring-4\",\n\t\t\t\t\t\"first-of-type:rounded-tl-md first-of-type:rounded-tr-md last-of-type:rounded-bl-md last-of-type:rounded-br-md\",\n\t\t\t\t\t\"aria-disabled:border-form/50 not-aria-disabled:hover:z-1 not-aria-disabled:hover:border-accent-600\",\n\t\t\t\t\t\"aria-checked:z-1 aria-checked:border-accent-500/40 aria-checked:bg-accent-500/10 dark-high-contrast:aria-checked:border-accent-400 high-contrast:aria-checked:border-accent-400 not-aria-disabled:hover:aria-checked:border-accent-600\",\n\t\t\t\t\t\"has-[.radio-indicator:first-child]:pl-2 has-[.radio-indicator:last-child]:pr-2\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t\t{...(fieldControl\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"aria-describedby\": fieldControl[\"aria-describedby\"],\n\t\t\t\t\t\t\t\"aria-errormessage\": fieldControl[\"aria-errormessage\"],\n\t\t\t\t\t\t\t\"aria-invalid\": fieldControl[\"aria-invalid\"],\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined)}\n\t\t\t>\n\t\t\t\t{(ctx) => <RadioStateContext.Provider value={ctx}>{children}</RadioStateContext.Provider>}\n\t\t\t</HeadlessRadio>\n\t\t);\n\t},\n);\nListItem.displayName = \"RadioListItem\";\n\ntype RadioItemContentProps = HTMLAttributes<HTMLDivElement> & WithAsChild;\n\ntype RadioCardProps = RadioItemProps;\n\n/**\n * A radio card item. Use it as a child of `RadioGroup`\n *\n * When rendered inside `Field.Control` (an alternative to the recommended\n * `Field.Set` / `Field.Legend` composition), picks up `aria-invalid` and\n * `aria-errormessage` from `FieldControlContext`. `aria-describedby` is owned\n * by Headless UI's Radio primitive and does not propagate.\n */\nconst Card = forwardRef<ComponentRef<\"div\">, RadioCardProps>(\n\t({ children, className, ...props }, ref) => {\n\t\tconst fieldControl = useContext(FieldControlContext);\n\t\treturn (\n\t\t\t<HeadlessRadio\n\t\t\t\tas=\"div\"\n\t\t\t\tdata-slot=\"radio-group-card\"\n\t\t\t\tclassName={clsx(\n\t\t\t\t\t\"group/radio border-card bg-card [&_label]:cursor-inherit relative rounded-md border p-4 text-sm\",\n\t\t\t\t\t\"cursor-pointer aria-disabled:cursor-default focus:outline-hidden\",\n\t\t\t\t\t\"focus-visible:ring-focus-accent not-aria-disabled:focus-visible:border-accent-600 focus-visible:ring-4\",\n\t\t\t\t\t\"first-of-type:rounded-tl-md first-of-type:rounded-tr-md last-of-type:rounded-bl-md last-of-type:rounded-br-md\",\n\t\t\t\t\t\"aria-disabled:border-form/50 not-aria-disabled:hover:z-1 not-aria-disabled:hover:border-accent-600\",\n\t\t\t\t\t\"aria-checked:z-1 aria-checked:border-accent-600/50 aria-checked:bg-accent-500/10 not-aria-disabled:hover:aria-checked:border-accent-600 dark-high-contrast:aria-checked:border-accent-600 high-contrast:aria-checked:border-accent-600\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t\t{...(fieldControl\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"aria-describedby\": fieldControl[\"aria-describedby\"],\n\t\t\t\t\t\t\t\"aria-errormessage\": fieldControl[\"aria-errormessage\"],\n\t\t\t\t\t\t\t\"aria-invalid\": fieldControl[\"aria-invalid\"],\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined)}\n\t\t\t\tref={ref}\n\t\t\t>\n\t\t\t\t{(ctx) => <RadioStateContext.Provider value={ctx}>{children}</RadioStateContext.Provider>}\n\t\t\t</HeadlessRadio>\n\t\t);\n\t},\n);\nCard.displayName = \"RadioCard\";\n\n/**\n * The content of any radio item. Use it to wrap any labels, descriptions, or content of a radio item.\n * Use it as a child of `RadioGroup.Item`, `RadioGroup.ListItem`, or `RadioGroup.Card`.\n */\nconst ItemContent = ({ asChild = false, children, className, ...props }: RadioItemContentProps) => {\n\tconst ctx = useContext(RadioStateContext);\n\tconst Component = asChild ? Slot : \"div\";\n\n\treturn (\n\t\t<Component\n\t\t\tdata-slot=\"radio-group-item-content\"\n\t\t\tclassName={clsx(\"min-w-0 flex-1\", ctx.disabled && \"opacity-50\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</Component>\n\t);\n};\nItemContent.displayName = \"RadioItemContent\";\n\n/**\n * An inline group of radio buttons. Use RadioGroup.Button as direct children.\n */\nconst ButtonGroup = forwardRef<ComponentRef<typeof Root>, RadioGroupProps>(\n\t({ className, ...props }, ref) => {\n\t\treturn (\n\t\t\t<Root\n\t\t\t\tdata-slot=\"radio-group-button-group\"\n\t\t\t\tclassName={clsx(\"flex flex-row flex-nowrap -space-x-px\", className)}\n\t\t\t\t{...props}\n\t\t\t\tref={ref}\n\t\t\t/>\n\t\t);\n\t},\n);\nButtonGroup.displayName = \"RadioButtonGroup\";\n\ntype RadioButtonProps = RadioItemProps;\n\n/**\n * A radio button that is used inside a `RadioGroup.ButtonGroup`.\n *\n * When rendered inside `Field.Control` (an alternative to the recommended\n * `Field.Set` / `Field.Legend` composition), picks up `aria-invalid` and\n * `aria-errormessage` from `FieldControlContext`. `aria-describedby` is owned\n * by Headless UI's Radio primitive and does not propagate.\n */\nconst Button = forwardRef<ComponentRef<\"div\">, RadioButtonProps>(\n\t({ children, className, ...props }, ref) => {\n\t\tconst fieldControl = useContext(FieldControlContext);\n\t\treturn (\n\t\t\t<HeadlessRadio\n\t\t\t\tas=\"div\"\n\t\t\t\tdata-slot=\"radio-group-button\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"group/radio border-form [&_label]:cursor-inherit relative flex flex-1 select-none items-center justify-center gap-2 border px-3 text-sm\",\n\t\t\t\t\t\"h-9\",\n\t\t\t\t\t\"focus-visible:ring-focus-accent not-aria-disabled:focus-visible:border-accent-600 focus-visible:ring-4\",\n\t\t\t\t\t\"cursor-pointer aria-disabled:cursor-default focus:outline-hidden\",\n\t\t\t\t\t\"first-of-type:rounded-bl-md first-of-type:rounded-tl-md last-of-type:rounded-br-md last-of-type:rounded-tr-md\",\n\t\t\t\t\t\"not-aria-disabled:hover:z-1 not-aria-disabled:hover:border-accent-600 aria-disabled:opacity-50\",\n\t\t\t\t\t\"aria-checked:z-1 aria-checked:border-accent-600/40 aria-checked:bg-accent-500/10 not-aria-disabled:hover:aria-checked:border-accent-600\",\n\t\t\t\t\t\"has-[.radio-indicator:first-child]:pl-2 has-[.radio-indicator:last-child]:pr-2\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t\t{...(fieldControl\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"aria-describedby\": fieldControl[\"aria-describedby\"],\n\t\t\t\t\t\t\t\"aria-errormessage\": fieldControl[\"aria-errormessage\"],\n\t\t\t\t\t\t\t\"aria-invalid\": fieldControl[\"aria-invalid\"],\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined)}\n\t\t\t>\n\t\t\t\t{(ctx) => <RadioStateContext.Provider value={ctx}>{children}</RadioStateContext.Provider>}\n\t\t\t</HeadlessRadio>\n\t\t);\n\t},\n);\nButton.displayName = \"RadioButton\";\n\ntype RadioInputSandboxProps = HTMLAttributes<HTMLDivElement>;\n\n/**\n * A sandbox container for input elements composed within radio group items.\n * It prevents the default behavior of the radio group when clicking on the input element or accepting keyboard input.\n */\nconst InputSandbox = ({ children, onClick, onKeyDown, ...props }: RadioInputSandboxProps) => {\n\tconst ref = useRef<HTMLDivElement>(null);\n\tconst ctx = useContext(RadioStateContext);\n\n\tconst singleChild = Children.only(children);\n\n\t// Prevent the child input from receiving focus when the parent radio group item is disabled or unchecked.\n\tconst shouldPreventTabIndex = ctx.disabled || !ctx.checked;\n\n\treturn (\n\t\t<div\n\t\t\trole=\"none\"\n\t\t\tdata-slot=\"radio-group-input-sandbox\"\n\t\t\tref={ref}\n\t\t\tonKeyDown={(event) => {\n\t\t\t\tif (ctx.disabled) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (event.key) {\n\t\t\t\t\tcase \"Enter\":\n\t\t\t\t\tcase \"Tab\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\t\t\t\tonKeyDown?.(event);\n\t\t\t}}\n\t\t\tonClick={(event) => {\n\t\t\t\tif (ctx.disabled) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst target = event.target;\n\t\t\t\tif (isInput(target)) {\n\t\t\t\t\twindow.requestAnimationFrame(() => {\n\t\t\t\t\t\ttarget.focus();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tonClick?.(event);\n\t\t\t}}\n\t\t\t{...props}\n\t\t>\n\t\t\t{isValidElement<HTMLInputElement>(singleChild)\n\t\t\t\t? cloneElement(singleChild, {\n\t\t\t\t\t\tdisabled: ctx.disabled || singleChild.props.disabled,\n\t\t\t\t\t\ttabIndex: shouldPreventTabIndex ? -1 : singleChild.props.tabIndex,\n\t\t\t\t\t})\n\t\t\t\t: null}\n\t\t</div>\n\t);\n};\nInputSandbox.displayName = \"RadioInputSandbox\";\n\n/**\n * A group of radio items. It manages the state of the children radios.\n *\n * @see https://mantle.ngrok.com/components/radio-group#radiogrouproot\n *\n * @example\n * Composition:\n * ```\n * # Default radios\n * RadioGroup.Root\n * └── RadioGroup.Item\n * ├── RadioGroup.Indicator\n * └── RadioGroup.ItemContent\n *\n * # List layout with descriptions\n * RadioGroup.List\n * └── RadioGroup.ListItem\n * ├── RadioGroup.Indicator\n * └── RadioGroup.ItemContent\n *\n * # Segmented button group\n * RadioGroup.ButtonGroup\n * └── RadioGroup.Button\n *\n * # Card-style radios\n * RadioGroup.Root\n * └── RadioGroup.Card\n * └── RadioGroup.Indicator\n * ```\n *\n * @example\n * ```tsx\n * <RadioGroup value={value} onValueChange={setValue}>\n * <RadioGroup.Item value=\"option1\">\n * <RadioGroup.Indicator />\n * <span>Option 1</span>\n * </RadioGroup.Item>\n * <RadioGroup.Item value=\"option2\">\n * <RadioGroup.Indicator />\n * <span>Option 2</span>\n * </RadioGroup.Item>\n * </RadioGroup>\n * ```\n */\nconst RadioGroup = {\n\t/**\n\t * A radio button that is used inside a RadioGroup.ButtonGroup for inline grouped radio options.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupbutton\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"option1\">\n\t * <RadioGroup.ButtonGroup>\n\t * <RadioGroup.Button value=\"option1\">Option 1</RadioGroup.Button>\n\t * <RadioGroup.Button value=\"option2\">Option 2</RadioGroup.Button>\n\t * <RadioGroup.Button value=\"option3\">Option 3</RadioGroup.Button>\n\t * </RadioGroup.ButtonGroup>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tButton,\n\t/**\n\t * An inline group of radio buttons. Use RadioGroup.Button as direct children for horizontal radio layouts.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupbuttongroup\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"small\">\n\t * <Label htmlFor=\"size-group\">Size</Label>\n\t * <RadioGroup.ButtonGroup>\n\t * <RadioGroup.Button value=\"small\">Small</RadioGroup.Button>\n\t * <RadioGroup.Button value=\"medium\">Medium</RadioGroup.Button>\n\t * <RadioGroup.Button value=\"large\">Large</RadioGroup.Button>\n\t * </RadioGroup.ButtonGroup>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tButtonGroup,\n\t/**\n\t * A radio card item with enhanced styling. Use it as a child of RadioGroup for card-based radio options.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupcard\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"basic\">\n\t * <div className=\"space-y-3\">\n\t * <RadioGroup.Card value=\"basic\">\n\t * <RadioGroup.ItemContent>\n\t * <Text weight=\"strong\">Basic Plan</Text>\n\t * <Text>$10/month</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.Card>\n\t * <RadioGroup.Card value=\"pro\">\n\t * <RadioGroup.ItemContent>\n\t * <Text weight=\"strong\">Pro Plan</Text>\n\t * <Text>$25/month</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.Card>\n\t * </div>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tCard,\n\t/**\n\t * The selection indicator for any radio item. Shows the checked state with customizable appearance.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupindicator\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Item value=\"option1\">\n\t * <RadioGroup.Indicator />\n\t * <span>Option 1</span>\n\t * </RadioGroup.Item>\n\t * ```\n\t */\n\tIndicator,\n\t/**\n\t * A sandbox container for input elements composed within radio group items. Prevents default radio behavior.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupinputsandbox\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"custom\">\n\t * <RadioGroup.Item value=\"custom\">\n\t * <RadioGroup.Indicator />\n\t * <RadioGroup.ItemContent>\n\t * <Text>Custom amount</Text>\n\t * <RadioGroup.InputSandbox>\n\t * <Input type=\"number\" placeholder=\"Enter amount\" />\n\t * </RadioGroup.InputSandbox>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tInputSandbox,\n\t/**\n\t * A simple radio item that can be used inside a radio group. The conventional use-case for basic radio options.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Item value=\"option1\">\n\t * <RadioGroup.Indicator />\n\t * <span>Option 1</span>\n\t * </RadioGroup.Item>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * The content wrapper for any radio item. Use it to wrap labels, descriptions, or content of a radio item.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogroupitemcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"option1\">\n\t * <RadioGroup.Item value=\"option1\">\n\t * <RadioGroup.Indicator />\n\t * <RadioGroup.ItemContent>\n\t * <Text weight=\"strong\">Option 1</Text>\n\t * <Text size=\"sm\">Description for option 1</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tItemContent,\n\t/**\n\t * A group of radio list items with connected borders. Use RadioGroup.ListItem as direct children.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogrouplist\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"option1\">\n\t * <RadioGroup.List>\n\t * <RadioGroup.ListItem value=\"option1\">\n\t * <RadioGroup.ItemContent>\n\t * <Text>Option 1</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.ListItem>\n\t * <RadioGroup.ListItem value=\"option2\">\n\t * <RadioGroup.ItemContent>\n\t * <Text>Option 2</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.ListItem>\n\t * </RadioGroup.List>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tList,\n\t/**\n\t * A radio list item that is used inside a RadioGroup.List for connected list-style radio options.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogrouplistitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root defaultValue=\"item1\">\n\t * <RadioGroup.List>\n\t * <RadioGroup.ListItem value=\"item1\">\n\t * <RadioGroup.ItemContent>\n\t * <Text>List Item 1</Text>\n\t * <Text size=\"sm\" className=\"text-muted\">First option</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.ListItem>\n\t * <RadioGroup.ListItem value=\"item2\">\n\t * <RadioGroup.ItemContent>\n\t * <Text>List Item 2</Text>\n\t * <Text size=\"sm\" className=\"text-muted\">Second option</Text>\n\t * </RadioGroup.ItemContent>\n\t * </RadioGroup.ListItem>\n\t * </RadioGroup.List>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tListItem,\n\t/**\n\t * The root radio group component. Manages the state of the children radios where only one can be selected.\n\t *\n\t * @see https://mantle.ngrok.com/components/radio-group#radiogrouproot\n\t *\n\t * @example\n\t * ```tsx\n\t * <RadioGroup.Root value={value} onValueChange={setValue}>\n\t * <RadioGroup.Item value=\"option1\">\n\t * <RadioGroup.Indicator />\n\t * <span>Option 1</span>\n\t * </RadioGroup.Item>\n\t * </RadioGroup.Root>\n\t * ```\n\t */\n\tRoot,\n} as const;\n\nexport {\n\t//\n\tRadioGroup,\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-pre-rendered-props-C-vrNxH1.js","names":[],"sources":["../src/components/code-block/mantle-code.ts","../src/components/code-block/line-numbers.ts","../src/components/code-block/decorate-highlighted-html.ts","../src/components/code-block/fold-range-utils.ts","../src/components/code-block/compute-json-fold-ranges.ts","../src/components/code-block/compute-fold-ranges.ts","../src/components/code-block/indentation.ts","../src/components/code-block/normalize-indentation.ts","../src/components/code-block/supported-languages.ts","../src/components/code-block/parse-line-options.ts","../src/components/code-block/resolve-pre-rendered-props.ts"],"sourcesContent":["import type { SupportedLanguage } from \"../code-block/supported-languages.js\";\nimport type { LineRange } from \"../code-block/line-numbers.js\";\nimport type { Indentation } from \"../code-block/indentation.js\";\n\n/** Languages that represent shell/terminal commands. */\nconst shellLanguages = new Set<SupportedLanguage>([\"bash\", \"sh\", \"shell\"]);\n\n/** Returns the default `showLineNumbers` value for a given language and code string. Single-line shell snippets default to `false`; everything else defaults to `true`. */\nfunction defaultShowLineNumbers(language: SupportedLanguage, code: string): boolean {\n\tif (shellLanguages.has(language) && !code.trim().includes(\"\\n\")) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nconst mantleCodeBlockValueBrand: unique symbol = Symbol(\"MantleCodeBlockValue\");\n\n/**\n * The value produced by `mantleCode()`. Contains pre-rendered Shiki HTML (injected\n * by the Vite plugin at build time) and the original code string for the copy button.\n *\n * `~preHtml` is required at render time. Runtime syntax highlighting is intentionally\n * unsupported; only placeholder substitution for interpolated values is performed.\n */\ntype MantleCodeBlockValue = {\n\t/**\n\t * Nominal type brand to prevent accidental use of plain objects.\n\t */\n\t[mantleCodeBlockValueBrand]: true;\n\t/**\n\t * The language used for syntax highlighting.\n\t */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * The original code string (used by the copy button).\n\t */\n\tcode: string;\n\t/**\n\t * Fully pre-rendered Shiki HTML injected by the Vite plugin or server highlighter.\n\t * This must be present for rendering.\n\t *\n\t * **Security:** This HTML is injected via `dangerouslySetInnerHTML`. It must\n\t * come from a trusted source (Shiki output from the Vite plugin or\n\t * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input.\n\t */\n\t\"~preHtml\"?: string | undefined;\n\t/**\n\t * Runtime values used to replace `SHIKI_VAL_N` placeholders in `~preHtml`.\n\t * This enables interpolated template expressions while preserving build-time highlighting.\n\t */\n\t\"~preVals\"?: unknown[] | undefined;\n\t/**\n\t * Placeholder token prefix used by the Vite transform for interpolated values.\n\t * When omitted, CodeBlock falls back to the legacy `SHIKI_VAL_<n>` format.\n\t */\n\t\"~preValToken\"?: string | undefined;\n\t/**\n\t * Optional default for line-number rendering when this value is displayed.\n\t */\n\t\"~showLineNumbers\"?: boolean | undefined;\n\t/**\n\t * Optional default highlighted line numbers/ranges when this value is displayed.\n\t */\n\t\"~highlightLines\"?: (LineRange | number)[] | undefined;\n\t/**\n\t * Optional default start line number when line numbers are displayed.\n\t * @default 1\n\t */\n\t\"~lineNumberStart\"?: number | undefined;\n};\n\n/** Maps each key starting with `OldPrefix` to `NewPrefix`, leaving other keys unchanged. */\ntype ReplacePrefix<T, OldPrefix extends string, NewPrefix extends string> = {\n\t[K in keyof T as K extends `${OldPrefix}${infer Rest}` ? `${NewPrefix}${Rest}` : K]: T[K];\n};\n\n/** Public input shape for `createMantleCodeBlockValue`, with `~`-prefixed keys renamed to unprefixed. */\ntype MantleCodeBlockValueInput = ReplacePrefix<\n\tOmit<MantleCodeBlockValue, typeof mantleCodeBlockValueBrand>,\n\t\"~\",\n\t\"\"\n>;\n\n/** Options for configuring line numbers, highlights, and indentation in `mantleCode()`. */\ntype MantleCodeOptions = {\n\t/** Line numbers or ranges to visually highlight in the code block. */\n\thighlightLines?: (LineRange | number)[] | undefined;\n\t/** The indentation style to use when normalizing the code string. */\n\tindentation?: Indentation | undefined;\n\t/**\n\t * The starting line number when line numbers are displayed.\n\t * @default 1\n\t */\n\tlineNumberStart?: number | undefined;\n\t/**\n\t * Whether to show line numbers in the code block. Defaults to `true` for most\n\t * languages, but `false` for single-line shell snippets (`bash`, `sh`, `shell`).\n\t */\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Creates a `MantleCodeBlockValue` for use with `CodeBlock.Code`.\n *\n * **Security:** The `preHtml` field is rendered via `dangerouslySetInnerHTML`.\n * Only pass HTML produced by Shiki (via the Vite plugin or\n * `createMantleServerSyntaxHighlighter`). Never pass unsanitized user input as `preHtml`.\n */\nfunction createMantleCodeBlockValue({\n\tpreHtml,\n\tpreValToken,\n\tpreVals,\n\thighlightLines,\n\tlineNumberStart,\n\tshowLineNumbers,\n\tcode,\n\tlanguage,\n}: MantleCodeBlockValueInput): MantleCodeBlockValue {\n\treturn {\n\t\t[mantleCodeBlockValueBrand]: true,\n\t\tlanguage,\n\t\tcode,\n\t\t\"~preHtml\": preHtml,\n\t\t\"~preValToken\": preValToken,\n\t\t\"~preVals\": preVals,\n\t\t\"~highlightLines\": highlightLines,\n\t\t\"~lineNumberStart\": lineNumberStart,\n\t\t\"~showLineNumbers\": showLineNumbers,\n\t};\n}\n\n/** Joins a `TemplateStringsArray` and its interpolated values into a single code string. */\nfunction buildCodeFromTemplate(strings: TemplateStringsArray, values: unknown[]): string {\n\tlet code = \"\";\n\tfor (let index = 0; index < strings.length; index += 1) {\n\t\tcode += strings[index] ?? \"\";\n\t\tif (index < values.length) {\n\t\t\tcode += String(values[index]);\n\t\t}\n\t}\n\treturn code;\n}\n\n/**\n * Tagged template literal for Shiki syntax highlighting.\n *\n * Returns a `MantleCodeBlockValue` that `CodeBlock.Code` renders.\n * The Vite transform plugin rewrites calls to this function at build time,\n * inlining pre-rendered Shiki HTML so that no highlighting work happens in the browser.\n * Configure it via `mantleCodeBlockPlugins()` in `vite.config.ts`.\n *\n * Interpolated template expressions are supported via placeholder substitution.\n *\n * Line numbers are shown by default (`showLineNumbers` defaults to `true`),\n * except for single-line shell snippets (`bash`, `sh`, `shell`) where they default to `false`.\n *\n * @example\n * ```tsx\n * // Static string (line numbers shown by default)\n * mantleCode(\"typescript\")`const x: string = \"hello\";`\n * // Interpolated string\n * mantleCode(\"typescript\")`const greeting = \"Hello, ${name}!\";`\n * // Disable line numbers\n * mantleCode(\"typescript\", { showLineNumbers: false })`const x = 1;`\n * // Single-line shell — line numbers hidden by default\n * mantleCode(\"bash\")`npm install @ngrok/mantle`\n * ```\n */\nfunction mantleCode(\n\tlanguage: SupportedLanguage,\n\toptions: MantleCodeOptions = {},\n): (strings: TemplateStringsArray, ...values: unknown[]) => MantleCodeBlockValue {\n\tconst { showLineNumbers, highlightLines, lineNumberStart } = options;\n\n\treturn (strings, ...values) => {\n\t\tconst code = buildCodeFromTemplate(strings, values);\n\n\t\treturn createMantleCodeBlockValue({\n\t\t\tlanguage,\n\t\t\tcode,\n\t\t\tpreHtml: undefined,\n\t\t\tpreVals: values.length > 0 ? values : undefined,\n\t\t\thighlightLines,\n\t\t\tlineNumberStart,\n\t\t\tshowLineNumbers: showLineNumbers ?? defaultShowLineNumbers(language, code),\n\t\t});\n\t};\n}\n\nexport { defaultShowLineNumbers, mantleCode };\nexport { createMantleCodeBlockValue };\nexport type { MantleCodeBlockValue, MantleCodeOptions };\n","/**\n * A line range is a string in the format of `start-end` where `start` and `end` are line numbers.\n */\nexport type LineRange = `${number}-${number}`;\n\nconst MAX_EXPANDED_LINE_RANGE_LENGTH = 1_000;\n\n/**\n * Given a list of line ranges and numbers, resolves them into a unique list of line numbers as a set.\n *\n * @example\n * ```tsx\n * const highlightedLines = resolveLineNumbers(1, \"3-5\", 7, \"10-12\");\n * // Returns: Set {1, 3, 4, 5, 7, 10, 11, 12}\n *\n * const singleLine = resolveLineNumbers(42);\n * // Returns: Set {42}\n * ```\n */\nexport function resolveLineNumbers(...items: (LineRange | number)[]): Set<number> {\n\tconst lineNumberSet = new Set<number>();\n\n\tfor (const item of items) {\n\t\tif (typeof item === \"number\") {\n\t\t\tif (!isPositiveLineNumber(item)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// only support integer line numbers\n\t\t\tconst int = Math.floor(item);\n\t\t\tlineNumberSet.add(int);\n\t\t} else {\n\t\t\tconst separatorIndex = item.indexOf(\"-\");\n\t\t\tconst startPart = item.slice(0, separatorIndex);\n\t\t\tconst endPart = item.slice(separatorIndex + 1);\n\t\t\tlet start = Number.parseInt(startPart, 10);\n\t\t\tlet end = Number.parseInt(endPart, 10);\n\n\t\t\t// ignore invalid ranges that don't contain valid line numbers\n\t\t\tif (!isPositiveLineNumber(start) || !isPositiveLineNumber(end)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// swap start and end if they are backwards\n\t\t\tif (start > end) {\n\t\t\t\t[start, end] = [end, start];\n\t\t\t}\n\n\t\t\tif (end - start + 1 > MAX_EXPANDED_LINE_RANGE_LENGTH) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// add all line numbers in the range, inclusive\n\t\t\tfor (let i = start; i <= end; i++) {\n\t\t\t\tlineNumberSet.add(i);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lineNumberSet;\n}\n\n/**\n * Type Predicate: checks if a value is a positive, finite integer.\n */\nconst isPositiveLineNumber = (value: number | undefined): value is number =>\n\tvalue != null && !Number.isNaN(value) && value > 0 && Number.isFinite(value);\n","import type { LineRange } from \"./line-numbers.js\";\nimport { resolveLineNumbers } from \"./line-numbers.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport type { FoldableRange } from \"./compute-json-fold-ranges.js\";\n\n/** Removes trailing `\\n` and `\\r` characters from the end of a string. */\nfunction trimTrailingNewlines(input: string): string {\n\tlet end = input.length;\n\twhile (end > 0 && (input.charCodeAt(end - 1) === 10 || input.charCodeAt(end - 1) === 13)) {\n\t\tend -= 1;\n\t}\n\treturn end === input.length ? input : input.slice(0, end);\n}\n\n/** Splits Shiki-highlighted HTML into per-line content, unwrapping `<span class=\"line\">` wrappers. */\nfunction splitHighlightedHtmlIntoLines(html: string): string[] {\n\tconst normalizedHtml = trimTrailingNewlines(html).replaceAll(\"\\r\\n\", \"\\n\").replaceAll(\"\\r\", \"\\n\");\n\tconst shikiLines = normalizedHtml.split(\"\\n\");\n\tconst linePrefix = '<span class=\"line\">';\n\tconst lineSuffix = \"</span>\";\n\n\tfor (let i = 0; i < shikiLines.length; i++) {\n\t\tconst line = shikiLines[i] ?? \"\";\n\t\tif (line.startsWith(linePrefix) && line.endsWith(lineSuffix)) {\n\t\t\tshikiLines[i] = line.slice(linePrefix.length, line.length - lineSuffix.length);\n\t\t}\n\t}\n\n\treturn shikiLines;\n}\n\n/** Inline caret SVG used by the fold toggle button. Mirrors `CaretDown` from Phosphor at a small size. */\nconst FOLD_CARET_SVG =\n\t'<svg class=\"mantle-code-fold-caret\" viewBox=\"0 0 16 16\" aria-hidden=\"true\" focusable=\"false\"><path fill=\"currentColor\" fill-rule=\"evenodd\" d=\"M3.22 5.97a.75.75 0 0 1 1.06 0L8 9.69l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L3.22 7.03a.75.75 0 0 1 0-1.06Z\"/></svg>';\n\n/**\n * Encodes public fold IDs for safe HTML attribute storage and for the\n * runtime's space-separated region sets. Built-in strategies use numeric\n * strings, but custom strategies may use descriptive IDs with spaces or\n * quotes.\n */\nfunction encodeFoldRegionId(id: string): string {\n\treturn encodeURIComponent(id);\n}\n\n/** Input for {@link decorateHighlightedHtml}. */\ntype DecorateHighlightedHtmlInput = {\n\t/**\n\t * Optional list of foldable ranges, typically produced by\n\t * {@link import(\"./compute-json-fold-ranges.js\").computeJsonFoldRanges}.\n\t *\n\t * When non-empty, every line gets a fold gutter slot; opener lines render a\n\t * semantic `<button>` toggle, descendant content lines carry\n\t * `data-fold-regions` so the runtime can hide them in O(region size) on\n\t * collapse.\n\t */\n\tfoldableRanges?: FoldableRange[] | undefined;\n\thighlightLines?: (LineRange | number)[] | undefined;\n\thtml: string;\n\tlineNumberStart?: number | undefined;\n\tshowLineNumbers?: boolean | undefined;\n};\n\n/**\n * Wraps each line of Shiki-highlighted HTML in Mantle's line-number, fold,\n * and line-highlight markup, producing the final HTML rendered by `CodeBlock.Code`.\n */\nfunction decorateHighlightedHtml({\n\tfoldableRanges,\n\thighlightLines,\n\thtml,\n\tlineNumberStart = 1,\n\tshowLineNumbers = false,\n}: DecorateHighlightedHtmlInput): string {\n\tconst highlightedLineNumbers = resolveLineNumbers(...(highlightLines ?? []));\n\tconst lines = splitHighlightedHtmlIntoLines(html);\n\n\t// Build per-line fold metadata so each line can announce its parent fold\n\t// regions and opener lines can render a toggle. Indexing up front keeps\n\t// the per-line loop O(1) for fold lookups, even on 1000+ line inputs.\n\t// Fold ranges are *buffer-relative* (1-indexed positions in the original\n\t// code), independent of `lineNumberStart` which only affects display.\n\tconst openerIdByBufferLine = new Map<number, string>();\n\tconst regionsByBufferLine = new Map<number, string[]>();\n\tconst hasFolds = foldableRanges != null && foldableRanges.length > 0;\n\n\tif (hasFolds && foldableRanges != null) {\n\t\tfor (const range of foldableRanges) {\n\t\t\tconst encodedId = encodeFoldRegionId(range.id);\n\t\t\topenerIdByBufferLine.set(range.startLine, encodedId);\n\t\t\tfor (let bufferLine = range.startLine + 1; bufferLine < range.endLine; bufferLine += 1) {\n\t\t\t\tlet regions = regionsByBufferLine.get(bufferLine);\n\t\t\t\tif (regions == null) {\n\t\t\t\t\tregions = [];\n\t\t\t\t\tregionsByBufferLine.set(bufferLine, regions);\n\t\t\t\t}\n\t\t\t\tregions.push(encodedId);\n\t\t\t}\n\t\t}\n\t}\n\n\tlet output = \"\";\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i] ?? \"\";\n\t\tconst bufferLineNumber = i + 1;\n\t\tconst displayedLineNumber = lineNumberStart + i;\n\t\tconst lineClassName = cx(\n\t\t\t\"mantle-code-line\",\n\t\t\thighlightedLineNumbers.has(displayedLineNumber) && \"mantle-code-line-highlighted\",\n\t\t);\n\n\t\tconst lineNumberHtml = showLineNumbers\n\t\t\t? `<span class=\"mantle-code-line-number\" data-slot=\"line-number\">${displayedLineNumber}</span>`\n\t\t\t: \"\";\n\n\t\tlet foldGutterHtml = \"\";\n\t\tlet foldRegionsAttribute = \"\";\n\t\tlet trailingEllipsisHtml = \"\";\n\t\tif (hasFolds) {\n\t\t\t// Opener lines render a real semantic <button> in the gutter.\n\t\t\t// Non-opener lines reserve gutter space via CSS — see the\n\t\t\t// `:has(.mantle-code-fold-toggle)` rule in mantle.css. Skipping\n\t\t\t// per-line spacer markup is what keeps HTML overhead near zero\n\t\t\t// for large JSON blocks.\n\t\t\tconst openerId = openerIdByBufferLine.get(bufferLineNumber);\n\t\t\tif (openerId != null) {\n\t\t\t\tfoldGutterHtml = `<button type=\"button\" class=\"mantle-code-fold-toggle\" data-slot=\"fold-toggle\" data-fold-line=\"${openerId}\" aria-expanded=\"true\" aria-label=\"Toggle code folding\">${FOLD_CARET_SVG}</button>`;\n\t\t\t\ttrailingEllipsisHtml =\n\t\t\t\t\t'<span class=\"mantle-code-fold-ellipsis\" data-slot=\"fold-ellipsis\" aria-hidden=\"true\">⋯</span>';\n\t\t\t}\n\n\t\t\tconst regions = regionsByBufferLine.get(bufferLineNumber);\n\t\t\tif (regions != null && regions.length > 0) {\n\t\t\t\tfoldRegionsAttribute = ` data-fold-regions=\"${regions.join(\" \")}\"`;\n\t\t\t}\n\t\t}\n\n\t\tconst renderedContent = line === \"\" ? \" \" : line;\n\t\tconst contentHtml = `<span class=\"mantle-code-line-content\" data-slot=\"line-content\">${renderedContent}${trailingEllipsisHtml}</span>`;\n\n\t\toutput += `<span class=\"${lineClassName}\" data-line-number=\"${displayedLineNumber}\"${foldRegionsAttribute}>${lineNumberHtml}${foldGutterHtml}${contentHtml}</span>`;\n\t}\n\treturn output;\n}\n\nexport { decorateHighlightedHtml };\nexport type { DecorateHighlightedHtmlInput };\n","/**\n * Shared types and helpers used by every fold-range computer\n * (`computeFoldRanges`, `computeJsonFoldRanges`). Kept in its own module so\n * the legacy raw-source parser and the token-driven parser can share a\n * single dedup/finalize pass without taking a dependency on each other.\n */\n\n/**\n * A foldable region in a code block. Lines `startLine + 1` through\n * `endLine - 1` are hidden when the region is collapsed; the opener and\n * closer lines remain visible.\n */\ntype FoldableRange = {\n\t/**\n\t * Stable identifier for the fold region within a code block. Equal to the\n\t * stringified `startLine` (unique by construction after dedup), encoded\n\t * into `data-fold-line` on the toggle button and `data-fold-regions` on\n\t * each descendant line so the runtime delegated handler can resolve\n\t * toggles by attribute lookup. Custom strategies should provide non-empty\n\t * IDs that are unique within the code block; the decorator URI-encodes\n\t * them before rendering so spaces and quotes remain safe.\n\t */\n\tid: string;\n\t/** 1-based line number of the line that contains the opening token. */\n\tstartLine: number;\n\t/** 1-based line number of the line that contains the matching closing token. */\n\tendLine: number;\n};\n\n/**\n * Sorts ranges by `startLine` ascending (with `endLine` descending as a\n * tiebreak so the largest span wins on a shared opener line) and keeps at\n * most one range per opener line. Mutates and returns the input.\n */\nfunction finalizeFoldRanges(ranges: FoldableRange[]): FoldableRange[] {\n\tif (ranges.length <= 1) {\n\t\treturn ranges;\n\t}\n\tranges.sort((a, b) => {\n\t\tif (a.startLine !== b.startLine) {\n\t\t\treturn a.startLine - b.startLine;\n\t\t}\n\t\treturn b.endLine - a.endLine;\n\t});\n\n\tconst filtered: FoldableRange[] = [];\n\tlet lastStartLine = -1;\n\tfor (const range of ranges) {\n\t\tif (range.startLine === lastStartLine) {\n\t\t\tcontinue;\n\t\t}\n\t\tfiltered.push(range);\n\t\tlastStartLine = range.startLine;\n\t}\n\treturn filtered;\n}\n\nexport { finalizeFoldRanges };\nexport type { FoldableRange };\n","import { finalizeFoldRanges, type FoldableRange } from \"./fold-range-utils.js\";\n\ntype JsonBracketStackEntry = {\n\topener: 123 | 91;\n\tline: number;\n};\n\n/**\n * Computes foldable ranges for a JSON source string. Each multi-line `{...}`\n * or `[...]` produces one range whose opener and closer lines remain visible\n * when collapsed (matching VS Code's folding behavior).\n *\n * The parser is intentionally permissive: it skips over unmatched/invalid\n * bracket sequences instead of throwing, so a partially valid JSON snippet\n * still gets the folds it can. Strings, escape sequences, and unicode\n * escapes are handled correctly so brackets inside string literals don't\n * open spurious folds.\n *\n * Runs in a single pass over the source (O(n) chars). At most one fold range\n * per opener line is emitted — when several brackets open on the same line,\n * only the outermost (largest range) survives, so a single click collapses\n * the whole sub-tree without rendering stacked toggles.\n *\n * @example\n * ```ts\n * computeJsonFoldRanges(`{\\n \"a\": [\\n 1\\n ]\\n}`);\n * // => [\n * // { id: \"1\", startLine: 1, endLine: 5 },\n * // { id: \"2\", startLine: 2, endLine: 4 },\n * // ]\n * ```\n */\nfunction computeJsonFoldRanges(code: string): FoldableRange[] {\n\tconst length = code.length;\n\tif (length === 0) {\n\t\treturn [];\n\t}\n\n\tconst stack: JsonBracketStackEntry[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tlet line = 1;\n\tlet index = 0;\n\n\twhile (index < length) {\n\t\tconst character = code.charCodeAt(index);\n\n\t\tif (character === 10) {\n\t\t\t// '\\n'\n\t\t\tline += 1;\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 13) {\n\t\t\t// '\\r' — treat \\r\\n and bare \\r as a line break\n\t\t\tline += 1;\n\t\t\tindex += 1;\n\t\t\tif (index < length && code.charCodeAt(index) === 10) {\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 34) {\n\t\t\t// '\"' — skip over string contents (including escaped quotes)\n\t\t\tindex += 1;\n\t\t\twhile (index < length) {\n\t\t\t\tconst stringChar = code.charCodeAt(index);\n\t\t\t\tif (stringChar === 92) {\n\t\t\t\t\t// '\\\\' — skip the next char unconditionally; do not advance line on escaped \\n\n\t\t\t\t\tindex += 2;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (stringChar === 34) {\n\t\t\t\t\tindex += 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (stringChar === 10 || stringChar === 13) {\n\t\t\t\t\t// Unterminated string spanning a line — bail without advancing further into it.\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 123 || character === 91) {\n\t\t\t// '{' or '['\n\t\t\tstack.push({ opener: character, line });\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === 125 || character === 93) {\n\t\t\t// '}' or ']'\n\t\t\tconst matchingOpener = character === 125 ? 123 : 91;\n\t\t\tconst top = stack[stack.length - 1];\n\t\t\tif (top?.opener === matchingOpener) {\n\t\t\t\tstack.pop();\n\t\t\t\tif (top.line !== line) {\n\t\t\t\t\tranges.push({ id: String(top.line), startLine: top.line, endLine: line });\n\t\t\t\t}\n\t\t\t} else if (top != null) {\n\t\t\t\t// Mismatched closer: the active bracket sequence is structurally\n\t\t\t\t// invalid, so prevent any containing opener from pairing later.\n\t\t\t\tstack.length = 0;\n\t\t\t}\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tindex += 1;\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\nexport { computeJsonFoldRanges };\nexport type { FoldableRange };\n","import { finalizeFoldRanges, type FoldableRange } from \"./fold-range-utils.js\";\nimport type { SupportedLanguage } from \"./supported-languages.js\";\n\n/**\n * A single TextMate scope name attached to part of a {@link FoldToken}.\n *\n * Mirrors the shape produced by Shiki's `includeExplanation: 'scopeName'`\n * option without taking a runtime dependency on Shiki, so this module can be\n * unit-tested with hand-written fixtures.\n */\ntype FoldScope = {\n\tscopeName: string;\n};\n\n/**\n * One sub-explanation within a {@link FoldToken}. A single Shiki token may\n * cover content with several scope sets — for example an interpolation\n * boundary inside a template literal — so its `explanation` is an array.\n */\ntype FoldExplanation = {\n\tcontent: string;\n\tscopes: FoldScope[];\n};\n\n/**\n * Minimal token shape consumed by {@link computeFoldRanges}. Compatible with\n * `ThemedToken` from `@shikijs/types` when `includeExplanation: 'scopeName'`\n * is enabled.\n */\ntype FoldToken = {\n\tcontent: string;\n\texplanation?: FoldExplanation[];\n};\n\n/**\n * One line of {@link FoldToken}s, as returned by Shiki's\n * `codeToTokens`/`tokens` transformer hook.\n */\ntype FoldLine = FoldToken[];\n\n/**\n * Folding strategy applied to a language. Picked by {@link foldStrategyFor}\n * based on how the language naturally delimits blocks:\n *\n * - `bracket` — `{}`/`[]` pairs (C-family, JSON, CSS, Rust, Go, …).\n * - `indentation` — significant whitespace (Python, YAML).\n * - `tag` — element open/close tags (HTML, XML).\n * - `none` — plain text and other languages without a useful folding model.\n */\ntype FoldStrategy = \"bracket\" | \"indentation\" | \"tag\" | \"none\";\n\n/** Returns the {@link FoldStrategy} used for the given supported language. */\nfunction foldStrategyFor(language: SupportedLanguage): FoldStrategy {\n\tswitch (language) {\n\t\tcase \"python\":\n\t\tcase \"py\":\n\t\tcase \"yaml\":\n\t\tcase \"yml\":\n\t\t\treturn \"indentation\";\n\t\tcase \"html\":\n\t\tcase \"xml\":\n\t\t\treturn \"tag\";\n\t\tcase \"bash\":\n\t\tcase \"sh\":\n\t\tcase \"shell\":\n\t\tcase \"plain\":\n\t\tcase \"plaintext\":\n\t\tcase \"text\":\n\t\tcase \"txt\":\n\t\t\t// Shell languages use keyword pairs (`if … fi`, `do … done`, etc.)\n\t\t\t// rather than brackets; folding `{}` would catch only brace\n\t\t\t// expansions, which aren't useful blocks. Until we model the\n\t\t\t// keyword pairs, opt out so we don't pay the per-token scope cost.\n\t\t\treturn \"none\";\n\t\tdefault:\n\t\t\treturn \"bracket\";\n\t}\n}\n\n/** Input for {@link computeFoldRanges}. */\ntype ComputeFoldRangesInput = {\n\t/** Resolved supported language; controls which strategy runs. */\n\tlanguage: SupportedLanguage;\n\t/**\n\t * Tokens produced by Shiki for the same code that will be rendered.\n\t * Must include scope explanations (i.e. tokenized with\n\t * `includeExplanation: 'scopeName'` or `true`) so string and comment\n\t * regions can be ignored.\n\t */\n\ttokens: FoldLine[];\n};\n\n/**\n * Computes foldable ranges for a tokenized code block. Dispatches to the\n * right strategy for the given language, so callers don't need to know how\n * a particular grammar models block boundaries.\n *\n * The bracket strategy uses TextMate scopes to distinguish real punctuation\n * from `{`/`[` characters that appear inside strings, comments, or regular\n * expressions — this is what lets one parser cover JS, TS, Go, Rust, JSON,\n * CSS, and friends without per-language string/comment logic.\n *\n * Returns ranges sorted by `startLine` ascending; at most one range per\n * opener line survives so the gutter renders a single toggle even when\n * multiple constructs open on the same line (`{\"a\":[`).\n */\nfunction computeFoldRanges({ language, tokens }: ComputeFoldRangesInput): FoldableRange[] {\n\tconst strategy = foldStrategyFor(language);\n\tswitch (strategy) {\n\t\tcase \"bracket\":\n\t\t\treturn computeBracketFoldRanges(tokens);\n\t\tcase \"indentation\":\n\t\t\treturn computeIndentationFoldRanges(tokens);\n\t\tcase \"tag\":\n\t\t\treturn computeTagFoldRanges(tokens);\n\t\tcase \"none\":\n\t\t\treturn [];\n\t}\n}\n\n/**\n * Returns true when a token's innermost scope means it represents inert\n * content — string body, comment body, regex body, or character escape —\n * and therefore any `{`/`[`/`<` characters inside it should be ignored.\n *\n * Checking the innermost scope (last entry) keeps template-literal\n * interpolations foldable: `${ ... }` punctuation lives under\n * `punctuation.definition.template-expression.*`, not `string.*`, so the\n * embedded expression isn't filtered out even though `string.template`\n * appears earlier in the scope chain.\n */\nfunction isInertScope(scopes: FoldScope[]): boolean {\n\tif (scopes.length === 0) {\n\t\treturn false;\n\t}\n\tconst innermost = scopes[scopes.length - 1]?.scopeName ?? \"\";\n\treturn (\n\t\tinnermost === \"string\" ||\n\t\tinnermost === \"comment\" ||\n\t\tinnermost.startsWith(\"string.\") ||\n\t\tinnermost.startsWith(\"comment.\") ||\n\t\tinnermost.startsWith(\"constant.character.escape\")\n\t);\n}\n\n/**\n * Yields explanation pieces of a token, or one fallback piece with no\n * scopes when the token wasn't tokenized with `includeExplanation`.\n */\nfunction explanationsOf(token: FoldToken): readonly FoldExplanation[] {\n\tif (token.explanation != null && token.explanation.length > 0) {\n\t\treturn token.explanation;\n\t}\n\treturn [{ content: token.content, scopes: [] }];\n}\n\n/**\n * Reconstructs non-inert line text without losing Shiki-owned whitespace.\n * Explanation pieces can omit leading spaces, so use the full token content\n * whenever every explanation piece is visible.\n */\nfunction visibleTextForLine(line: FoldLine): string {\n\tlet visible = \"\";\n\tfor (const token of line) {\n\t\tconst explanations = explanationsOf(token);\n\t\tlet hasInert = false;\n\t\tfor (const explanation of explanations) {\n\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\thasInert = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!hasInert) {\n\t\t\tvisible += token.content;\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const explanation of explanations) {\n\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvisible += explanation.content;\n\t\t}\n\t}\n\treturn visible;\n}\n\n/**\n * Returns the count of leading whitespace characters on a line, or `-1`\n * for blank lines. Reads only the first token's content — Shiki emits\n * leading whitespace as its own token, so a full-line concat is wasted\n * work for the indentation strategy.\n */\nfunction leadingIndentOfLine(line: FoldLine | undefined): number {\n\tif (line == null || line.length === 0) {\n\t\treturn -1;\n\t}\n\tlet column = 0;\n\tfor (const token of line) {\n\t\tconst content = token.content;\n\t\tfor (let charIndex = 0; charIndex < content.length; charIndex += 1) {\n\t\t\tconst character = content.charCodeAt(charIndex);\n\t\t\tif (character === 32 || character === 9) {\n\t\t\t\tcolumn += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn column;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/**\n * Bracket-pair folding strategy. Walks every token, skips inert (string,\n * comment, escape) regions, and pairs `{`/`[` openers with `}`/`]` closers\n * via a single stack pass.\n *\n * Parens (`(`/`)`) are intentionally not folded — function call argument\n * lists are usually short and folding them creates more noise than value.\n */\nfunction computeBracketFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst stack: number[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tfor (let lineIndex = 0; lineIndex < tokens.length; lineIndex += 1) {\n\t\tconst line = tokens[lineIndex];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst lineNumber = lineIndex + 1;\n\n\t\tfor (const token of line) {\n\t\t\tif (!hasBracketChar(token.content)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const explanation of explanationsOf(token)) {\n\t\t\t\tif (isInertScope(explanation.scopes)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst content = explanation.content;\n\t\t\t\tfor (let charIndex = 0; charIndex < content.length; charIndex += 1) {\n\t\t\t\t\tconst character = content.charCodeAt(charIndex);\n\t\t\t\t\tif (character === 123 || character === 91) {\n\t\t\t\t\t\tstack.push(lineNumber);\n\t\t\t\t\t} else if (character === 125 || character === 93) {\n\t\t\t\t\t\tconst startLine = stack.pop();\n\t\t\t\t\t\tif (startLine != null && startLine !== lineNumber) {\n\t\t\t\t\t\t\tranges.push({ id: String(startLine), startLine, endLine: lineNumber });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/**\n * Pre-filter: returns true if `content` contains any of `{`, `}`, `[`, `]`.\n * Most tokens in non-JSON code are identifiers/whitespace/operators that\n * never participate in bracket folding, so this collapses ~95% of the per-\n * character scan to a single `String.prototype.indexOf` per token.\n */\nfunction hasBracketChar(content: string): boolean {\n\tfor (let i = 0; i < content.length; i += 1) {\n\t\tconst character = content.charCodeAt(i);\n\t\tif (character === 123 || character === 125 || character === 91 || character === 93) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Indentation-based folding strategy for languages where blocks are defined\n * by leading whitespace (Python, YAML).\n *\n * For each non-blank line, finds the maximal run of following lines that are\n * either blank or more deeply indented than the opener. The opener stays\n * visible; descendant lines collapse. The \"closer\" line (`endLine`) is the\n * first line at or below the opener's indent — purely a sentinel so the\n * decorator's `startLine + 1 .. endLine - 1` hide loop covers the body.\n *\n * A tab is treated as one column. Mixed tabs/spaces compare consistently\n * because we compare the count of leading whitespace characters; if a file\n * mixes the two within a single block, indent comparisons may misfire, but\n * neither Python nor YAML idiomatically mixes them.\n */\nfunction computeIndentationFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst indents: number[] = Array.from({ length: tokens.length });\n\tfor (let i = 0; i < tokens.length; i += 1) {\n\t\tindents[i] = leadingIndentOfLine(tokens[i]);\n\t}\n\n\tconst ranges: FoldableRange[] = [];\n\tfor (let openerIndex = 0; openerIndex < indents.length; openerIndex += 1) {\n\t\tconst indent = indents[openerIndex] ?? -1;\n\t\tif (indent < 0) {\n\t\t\tcontinue;\n\t\t}\n\t\tlet lastChild = -1;\n\t\tlet scan = openerIndex + 1;\n\t\twhile (scan < indents.length) {\n\t\t\tconst next = indents[scan] ?? -1;\n\t\t\tif (next < 0) {\n\t\t\t\tscan += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (next > indent) {\n\t\t\t\tlastChild = scan;\n\t\t\t\tscan += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tif (lastChild > openerIndex) {\n\t\t\t// endLine plays the role of the \"closer\": the first line that is\n\t\t\t// not folded. `lastChild + 2` converts the 0-indexed last child\n\t\t\t// to a 1-indexed sentinel one past it.\n\t\t\tranges.push({\n\t\t\t\tid: String(openerIndex + 1),\n\t\t\t\tstartLine: openerIndex + 1,\n\t\t\t\tendLine: lastChild + 2,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/**\n * Tag-pair folding strategy for HTML and XML.\n *\n * Reconstructs each line's visible text from non-inert tokens, then scans\n * tag patterns with a small linear scanner. Self-closing tags (`<br/>`, `<img />`)\n * and known void HTML elements (`<br>`, `<img>`, `<input>`, …) don't push\n * onto the stack. Stack-based matching emits one range per line with an\n * unmatched opener and a matching closer on a later line.\n *\n * Multi-line tags (an opener whose `>` is on a different line than the\n * `<`) are deliberately not folded in v1 — they're rare and would require\n * cross-line state.\n */\nfunction computeTagFoldRanges(tokens: FoldLine[]): FoldableRange[] {\n\tconst stack: { name: string; line: number }[] = [];\n\tconst ranges: FoldableRange[] = [];\n\n\tfor (let lineIndex = 0; lineIndex < tokens.length; lineIndex += 1) {\n\t\tconst line = tokens[lineIndex];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst lineNumber = lineIndex + 1;\n\t\tconst visible = visibleTextForLine(line);\n\n\t\tconst matches = extractTagMatches(visible);\n\t\tfor (const match of matches) {\n\t\t\tif (match.kind === \"open\") {\n\t\t\t\tstack.push({ name: match.name, line: lineNumber });\n\t\t\t} else {\n\t\t\t\tconst top = stack.length > 0 ? stack[stack.length - 1] : undefined;\n\t\t\t\tif (top != null && top.name.toLowerCase() === match.name.toLowerCase()) {\n\t\t\t\t\tstack.pop();\n\t\t\t\t\tif (top.line !== lineNumber) {\n\t\t\t\t\t\tranges.push({\n\t\t\t\t\t\t\tid: String(top.line),\n\t\t\t\t\t\t\tstartLine: top.line,\n\t\t\t\t\t\t\tendLine: lineNumber,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn finalizeFoldRanges(ranges);\n}\n\n/** HTML elements whose tags don't have a closing counterpart. */\nconst VOID_HTML_ELEMENTS = new Set<string>([\n\t\"area\",\n\t\"base\",\n\t\"br\",\n\t\"col\",\n\t\"embed\",\n\t\"hr\",\n\t\"img\",\n\t\"input\",\n\t\"link\",\n\t\"meta\",\n\t\"param\",\n\t\"source\",\n\t\"track\",\n\t\"wbr\",\n]);\n\n/**\n * Extracts open/close tag matches from a single line's visible text.\n *\n * Only tags that both open and close on this line are considered; we skip\n * partial tags (an unmatched `<` with no `>`) so multi-line tags don't\n * register as openers.\n */\nfunction extractTagMatches(line: string): { name: string; kind: \"open\" | \"close\" }[] {\n\tconst matches: { name: string; kind: \"open\" | \"close\" }[] = [];\n\tlet index = 0;\n\n\twhile (index < line.length) {\n\t\tconst tagStart = line.indexOf(\"<\", index);\n\t\tif (tagStart === -1) {\n\t\t\tbreak;\n\t\t}\n\n\t\tlet cursor = skipHtmlWhitespace(line, tagStart + 1);\n\t\tconst isClose = line.charCodeAt(cursor) === 47;\n\t\tif (isClose) {\n\t\t\tcursor = skipHtmlWhitespace(line, cursor + 1);\n\t\t}\n\n\t\tif (!isTagNameStart(line.charCodeAt(cursor))) {\n\t\t\tindex = tagStart + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst nameStart = cursor;\n\t\tcursor += 1;\n\t\twhile (cursor < line.length && isTagNameContinue(line.charCodeAt(cursor))) {\n\t\t\tcursor += 1;\n\t\t}\n\t\tconst name = line.slice(nameStart, cursor);\n\t\tconst tagEnd = findTagEnd(line, cursor);\n\t\tif (tagEnd === -1) {\n\t\t\tindex = tagStart + 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isClose) {\n\t\t\tmatches.push({ name, kind: \"close\" });\n\t\t\tindex = tagEnd + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst selfClosing = tagEndsSelfClosing(line, tagEnd);\n\t\tif (selfClosing || VOID_HTML_ELEMENTS.has(name.toLowerCase())) {\n\t\t\tindex = tagEnd + 1;\n\t\t\tcontinue;\n\t\t}\n\t\tmatches.push({ name, kind: \"open\" });\n\t\tindex = tagEnd + 1;\n\t}\n\treturn matches;\n}\n\n/** Returns true for whitespace accepted inside a tag opener. */\nfunction isHtmlWhitespace(character: number): boolean {\n\treturn (\n\t\tcharacter === 9 ||\n\t\tcharacter === 10 ||\n\t\tcharacter === 11 ||\n\t\tcharacter === 12 ||\n\t\tcharacter === 13 ||\n\t\tcharacter === 32\n\t);\n}\n\n/** Skips HTML whitespace starting at `index`. */\nfunction skipHtmlWhitespace(line: string, index: number): number {\n\tlet cursor = index;\n\twhile (cursor < line.length && isHtmlWhitespace(line.charCodeAt(cursor))) {\n\t\tcursor += 1;\n\t}\n\treturn cursor;\n}\n\n/** Returns true when `character` can start an HTML/XML tag name. */\nfunction isTagNameStart(character: number): boolean {\n\treturn (character >= 65 && character <= 90) || (character >= 97 && character <= 122);\n}\n\n/** Returns true when `character` can continue an HTML/XML tag name. */\nfunction isTagNameContinue(character: number): boolean {\n\treturn (\n\t\tisTagNameStart(character) ||\n\t\t(character >= 48 && character <= 57) ||\n\t\tcharacter === 45 ||\n\t\tcharacter === 58 ||\n\t\tcharacter === 95\n\t);\n}\n\n/** Finds the closing `>` for a tag, ignoring `>` inside quoted attributes. */\nfunction findTagEnd(line: string, index: number): number {\n\tlet quote: number | undefined;\n\tfor (let cursor = index; cursor < line.length; cursor += 1) {\n\t\tconst character = line.charCodeAt(cursor);\n\t\tif (quote != null) {\n\t\t\tif (character === quote) {\n\t\t\t\tquote = undefined;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 34 || character === 39) {\n\t\t\tquote = character;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === 62) {\n\t\t\treturn cursor;\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Returns true when the tag ending at `tagEnd` has a trailing `/`. */\nfunction tagEndsSelfClosing(line: string, tagEnd: number): boolean {\n\tlet cursor = tagEnd - 1;\n\twhile (cursor >= 0 && isHtmlWhitespace(line.charCodeAt(cursor))) {\n\t\tcursor -= 1;\n\t}\n\treturn cursor >= 0 && line.charCodeAt(cursor) === 47;\n}\n\nexport {\n\t//,\n\tcomputeFoldRanges,\n\tfoldStrategyFor,\n};\n\nexport type {\n\t//,\n\tComputeFoldRangesInput,\n\tFoldExplanation,\n\tFoldLine,\n\tFoldScope,\n\tFoldStrategy,\n\tFoldToken,\n};\n","import type { SupportedLanguage } from \"./supported-languages.js\";\n\nconst indentations = [\"tabs\", \"spaces\"] as const;\ntype Indentation = (typeof indentations)[number];\n\n/**\n * Type Predicate: checks if the given value is a valid indentation type.\n */\nfunction isIndentation(input: unknown): input is Indentation {\n\treturn indentations.includes(input as Indentation);\n}\n\n/**\n * Infers the indentation type based on the language and preferred indentation.\n *\n * @param language - The language to check.\n * @param preferredIndentation - The preferred indentation type (overrides what is detected).\n */\nfunction inferIndentation(\n\tlanguage: SupportedLanguage,\n\tpreferredIndentation: Indentation | undefined,\n) {\n\t// if the user has a preferred indentation, use that regardless of the language\n\tif (preferredIndentation) {\n\t\treturn preferredIndentation;\n\t}\n\n\tif (isTabIndentedLanguage(language)) {\n\t\treturn \"tabs\";\n\t}\n\n\tif (isSpaceIndentedLanguage(language)) {\n\t\treturn \"spaces\";\n\t}\n\n\treturn \"spaces\";\n}\n\nexport {\n\t//,\n\tindentations,\n\tinferIndentation,\n\tisIndentation,\n};\n\nexport type {\n\t//,\n\tIndentation,\n};\n\n/**\n * Languages that require or strongly prefer tabs\n */\nconst tabIndentedLanguages = [\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"jsx\",\n\t\"ts\",\n\t\"tsx\",\n\t\"typescript\",\n\t\"xml\",\n] as const satisfies SupportedLanguage[];\n\nconst tabIndentedLanguageSet = new Set<string>(tabIndentedLanguages);\n\n/**\n * Languages that require or strongly prefer spaces\n */\nconst spaceIndentedLanguages = [\n\t\"python\",\n\t\"py\",\n\t\"yaml\",\n\t\"yml\",\n\t\"ruby\",\n\t\"rb\",\n] as const satisfies SupportedLanguage[];\n\nconst spaceIndentedLanguageSet = new Set<string>(spaceIndentedLanguages);\n\ntype TabIndentedLanguage = (typeof tabIndentedLanguages)[number];\ntype SpaceIndentedLanguage = (typeof spaceIndentedLanguages)[number];\n\n/**\n * Type Predicate: checks if the given value is a required/preferred tab-indented language.\n */\nfunction isTabIndentedLanguage(value: SupportedLanguage): value is TabIndentedLanguage {\n\treturn tabIndentedLanguageSet.has(value);\n}\n\n/**\n * Type Predicate: checks if the given value is a required/preferred space-indented language.\n */\nfunction isSpaceIndentedLanguage(value: SupportedLanguage): value is SpaceIndentedLanguage {\n\treturn spaceIndentedLanguageSet.has(value);\n}\n","import type { Indentation } from \"./indentation.js\";\n\ntype Options = {\n\t/**\n\t * The indentation type to use. Can be either \"tabs\" or \"spaces\".\n\t * @default \"spaces\"\n\t */\n\tindentation?: Indentation;\n};\n\n/**\n * Trim any leading and trailing whitespace/empty lines, convert leading\n * indentation to the given options.indentation\n */\nfunction normalizeIndentation(value: string, options?: Options): string {\n\tconst indentation = options?.indentation ?? \"spaces\";\n\tconst normalizedLineEndings = value.replace(/\\r\\n?/g, \"\\n\");\n\tconst trimmed = normalizedLineEndings.trim();\n\n\tif (trimmed === \"\") {\n\t\treturn \"\";\n\t}\n\n\tconst minIndent = findMinIndent(normalizedLineEndings);\n\tconst lines = trimmed.split(\"\\n\");\n\tconst normalizedLines = Array.from<string>({ length: lines.length });\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i];\n\t\tif (line == null) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst dedentedLine = startsWithNonWhitespace(line) ? line : line.slice(minIndent);\n\t\tnormalizedLines[i] = normalizeLeadingIndentation(dedentedLine, indentation);\n\t}\n\n\treturn normalizedLines.join(\"\\n\");\n}\n\nexport {\n\t//,\n\tnormalizeIndentation,\n};\n\n/**\n * Rewrites only the leading indentation of a non-empty line into the requested\n * indentation style, leaving the rest of the line untouched.\n */\nfunction normalizeLeadingIndentation(line: string, indentation: Indentation): string {\n\tlet indentEnd = 0;\n\twhile (indentEnd < line.length) {\n\t\tconst character = line[indentEnd];\n\t\tif (character !== \" \" && character !== \"\\t\") {\n\t\t\tbreak;\n\t\t}\n\t\tindentEnd += 1;\n\t}\n\n\tif (indentEnd === 0 || indentEnd === line.length) {\n\t\treturn line;\n\t}\n\n\tconst leadingWhitespace = line.slice(0, indentEnd);\n\tconst normalizedLeadingWhitespace =\n\t\tindentation === \"spaces\"\n\t\t\t? leadingWhitespace.replace(/\\t/g, \" \")\n\t\t\t: leadingWhitespace.replace(/ {2}/g, \"\\t\");\n\n\treturn normalizedLeadingWhitespace + line.slice(indentEnd);\n}\n\n/**\n * Returns true when a line begins with visible content instead of indentation.\n */\nfunction startsWithNonWhitespace(line: string): boolean {\n\tconst firstCharacter = line[0];\n\treturn firstCharacter != null && firstCharacter !== \" \" && firstCharacter !== \"\\t\";\n}\n\n/**\n * Find the shortest indentation of a multiline string.\n */\nfunction findMinIndent(value: string): number {\n\tlet minIndent = Number.POSITIVE_INFINITY;\n\tlet indent = 0;\n\tlet atLineStart = true;\n\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst char = value[i];\n\n\t\tif (atLineStart) {\n\t\t\tif (char === \" \" || char === \"\\t\") {\n\t\t\t\tindent += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\t\tindent = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (indent < minIndent) {\n\t\t\t\tminIndent = indent;\n\t\t\t\tif (minIndent === 0) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tatLineStart = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"\\n\" || char === \"\\r\") {\n\t\t\tatLineStart = true;\n\t\t\tindent = 0;\n\t\t}\n\t}\n\n\treturn minIndent === Number.POSITIVE_INFINITY ? 0 : minIndent;\n}\n","/**\n * List of supported languages for syntax highlighting.\n * @private\n */\nexport const supportedLanguages = [\n\t\"bash\",\n\t\"cs\",\n\t\"csharp\",\n\t\"css\",\n\t\"go\",\n\t\"html\",\n\t\"java\",\n\t\"javascript\",\n\t\"js\",\n\t\"json\",\n\t\"jsx\",\n\t\"plain\",\n\t\"plaintext\",\n\t\"py\",\n\t\"python\",\n\t\"rb\",\n\t\"ruby\",\n\t\"rust\",\n\t\"sh\",\n\t\"shell\",\n\t\"text\",\n\t\"ts\",\n\t\"tsx\",\n\t\"txt\",\n\t\"typescript\",\n\t\"xml\",\n\t\"yaml\",\n\t\"yml\",\n] as const;\n\n/**\n * Supported languages for syntax highlighting.\n */\ntype SupportedLanguage = (typeof supportedLanguages)[number];\nconst supportedLanguageSet = new Set<SupportedLanguage>(supportedLanguages);\nconst defaultLanguage = \"text\" satisfies SupportedLanguage;\n\n/**\n * Parses a markdown code block (```) language class into a SupportedLanguage.\n * Defaults to \"text\" if no supported language is found.\n */\nfunction parseLanguage(\n\tvalue: `language-${string}` | `lang-${string}` | (string & {}) | undefined,\n): SupportedLanguage {\n\tconst trimmed = value?.trim() ?? \"\";\n\tif (!trimmed) {\n\t\treturn defaultLanguage;\n\t}\n\n\t// remove leading \"language-\" and \"lang-\" prefixes\n\t// find first '-' and slice from there\n\tconst prefixSeparatorIndex = trimmed.indexOf(\"-\");\n\tconst maybeLanguage =\n\t\tprefixSeparatorIndex === -1 ? trimmed : trimmed.slice(prefixSeparatorIndex + 1);\n\n\treturn isSupportedLanguage(maybeLanguage) ? maybeLanguage : defaultLanguage;\n}\n\n/**\n * Type Predicate: checks if an arbitrary value is a supported syntax highlighting language.\n */\nconst isSupportedLanguage = (value: unknown): value is SupportedLanguage => {\n\treturn typeof value === \"string\" && supportedLanguageSet.has(value as SupportedLanguage);\n};\n\nexport {\n\t//,\n\tisSupportedLanguage,\n\tparseLanguage,\n};\n\nexport type { SupportedLanguage };\n","import type { LineRange } from \"./line-numbers.js\";\n\n/** Parses a boolean or `\"true\"`/`\"false\"` string into a boolean. Returns `undefined` for unrecognized values. */\nfunction parseCodeBlockShowLineNumbers(value: unknown): boolean | undefined {\n\tif (typeof value === \"boolean\") {\n\t\treturn value;\n\t}\n\tif (typeof value === \"string\") {\n\t\tif (value === \"true\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (value === \"false\") {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Parses a positive integer (or its string representation) for the starting line number. Returns `undefined` for invalid values. */\nfunction parseCodeBlockLineNumberStart(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n\t\treturn Math.floor(value);\n\t}\n\tif (typeof value === \"string\" && /^\\d+$/.test(value)) {\n\t\tconst parsed = Number.parseInt(value, 10);\n\t\treturn parsed > 0 ? parsed : undefined;\n\t}\n\treturn undefined;\n}\n\n/**\n * Parses a single highlight-line entry into either a positive integer line\n * number or a `\"start-end\"` {@link LineRange} string. Accepts a number, a\n * decimal-digit string (e.g. `\"3\"`), or a range string (e.g. `\"5-9\"`); any\n * other shape — including non-positive bounds — yields `undefined` so callers\n * can drop the entry. Whitespace around string inputs is tolerated.\n *\n * @example\n * parseSingle(3); // 3\n * parseSingle(\"5-9\"); // \"5-9\"\n * parseSingle(\"0\"); // undefined\n * parseSingle(\"foo\"); // undefined\n */\nfunction parseSingle(item: unknown): LineRange | number | undefined {\n\tif (typeof item === \"number\") {\n\t\treturn Number.isFinite(item) && item > 0 ? Math.floor(item) : undefined;\n\t}\n\tif (typeof item === \"string\") {\n\t\tconst trimmed = item.trim();\n\t\tif (/^\\d+$/.test(trimmed)) {\n\t\t\tconst parsed = Number.parseInt(trimmed, 10);\n\t\t\treturn parsed > 0 ? parsed : undefined;\n\t\t}\n\t\tif (/^\\d+-\\d+$/.test(trimmed)) {\n\t\t\tconst [startStr, endStr] = trimmed.split(\"-\");\n\t\t\tconst start = Number.parseInt(startStr ?? \"\", 10);\n\t\t\tconst end = Number.parseInt(endStr ?? \"\", 10);\n\t\t\tif (start > 0 && end > 0) {\n\t\t\t\treturn trimmed as LineRange;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Parses highlight line specifications from an array or comma-separated string (e.g. `[1, \"3-5\"]` or `\"1,3-5\"`). Returns `undefined` when no valid entries are found. */\nfunction parseCodeBlockHighlightLines(value: unknown): (LineRange | number)[] | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst parsed: (LineRange | number)[] = [];\n\t\tconst segments = value.split(\",\");\n\t\tfor (const segment of segments) {\n\t\t\tconst maybe = parseSingle(segment);\n\t\t\tif (maybe != null) {\n\t\t\t\tparsed.push(maybe);\n\t\t\t}\n\t\t}\n\t\treturn parsed.length > 0 ? parsed : undefined;\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn undefined;\n\t}\n\tconst parsed: (LineRange | number)[] = [];\n\tfor (const item of value) {\n\t\tconst maybe = parseSingle(item);\n\t\tif (maybe != null) {\n\t\t\tparsed.push(maybe);\n\t\t}\n\t}\n\treturn parsed.length > 0 ? parsed : undefined;\n}\n\nexport {\n\t//,\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n};\n","import type { SupportedLanguage } from \"./supported-languages.js\";\nimport { isSupportedLanguage } from \"./supported-languages.js\";\nimport { parseBooleanish } from \"../../types/booleanish.js\";\nimport { type Indentation, isIndentation } from \"./indentation.js\";\nimport {\n\tparseCodeBlockHighlightLines,\n\tparseCodeBlockLineNumberStart,\n\tparseCodeBlockShowLineNumbers,\n} from \"./parse-line-options.js\";\n\nconst modes = [\n\t//,\n\t\"cli\",\n\t\"file\",\n\t\"traffic-policy\",\n] as const;\n/** The visual mode preset for a code block (determines header icon). */\ntype Mode = (typeof modes)[number];\n\n/** User-facing input shape for code block metadata (metastring key-value pairs). */\ntype MetaInput = {\n\tcollapsible?: boolean | undefined;\n\tdisableCopy?: boolean | undefined;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\n/** Resolved code block metadata with defaults applied. */\ntype Meta = {\n\tcollapsible: boolean;\n\tdisableCopy: boolean;\n\tindentation?: Indentation | undefined;\n\tmode?: Mode | undefined;\n\ttitle?: string | undefined;\n};\n\nconst defaultMeta = {\n\tcollapsible: false,\n\tdisableCopy: false,\n\tindentation: undefined,\n\tmode: undefined,\n\ttitle: undefined,\n} as const satisfies Meta;\n\n/** The type of the default metadata constant. */\ntype DefaultMeta = typeof defaultMeta;\n\n/** Parses a code fence metastring (e.g. `title=\"example\" collapsible`) into a structured `Meta` object. */\nfunction parseMetastring(input: string | undefined): Meta {\n\tconst metastring = input?.trim() ?? \"\";\n\tif (!metastring) {\n\t\treturn defaultMeta;\n\t}\n\n\tconst metaJson: Record<string, unknown> = {};\n\tconst tokens = tokenizeMetastring(metastring);\n\tfor (const token of tokens) {\n\t\tconst separatorIndex = token.indexOf(\"=\");\n\t\tconst key = separatorIndex === -1 ? token : token.slice(0, separatorIndex);\n\t\tconst value = separatorIndex === -1 ? undefined : token.slice(separatorIndex + 1);\n\n\t\tif (!key) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeValue(value);\n\t\tmetaJson[key] = normalized ?? true;\n\t}\n\n\treturn parseMetaJson(metaJson);\n}\n\n/** Strips surrounding double-quotes and trims whitespace from a metastring value. */\nfunction normalizeValue(value: string | undefined) {\n\tif (value == null) {\n\t\treturn undefined;\n\t}\n\tconst trimmed = value.trim();\n\tconst lastIndex = trimmed.length - 1;\n\tif (lastIndex >= 1 && trimmed.charCodeAt(0) === 34 && trimmed.charCodeAt(lastIndex) === 34) {\n\t\treturn trimmed.slice(1, lastIndex);\n\t}\n\treturn trimmed;\n}\n\n/** Splits a metastring into whitespace-delimited tokens, respecting double-quoted segments. */\nfunction tokenizeMetastring(value: string | undefined): string[] {\n\tconst input = value?.trim() ?? \"\";\n\tconst result: string[] = [];\n\n\tlet current = \"\";\n\tlet inQuotes = false;\n\n\tfor (let i = 0; i < input.length; i++) {\n\t\tconst char = input[i] ?? \"\";\n\t\tif (!inQuotes && isMetastringWhitespace(char)) {\n\t\t\tif (current) {\n\t\t\t\tresult.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else if (char === '\"') {\n\t\t\tinQuotes = !inQuotes;\n\t\t\tcurrent += char;\n\t\t} else {\n\t\t\tcurrent += char;\n\t\t}\n\t}\n\n\tif (current) {\n\t\tresult.push(current);\n\t}\n\n\treturn result;\n}\n\n/** Returns `true` for the ASCII whitespace characters a metastring may use to separate tokens. */\nfunction isMetastringWhitespace(char: string): boolean {\n\treturn char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\";\n}\n\n/** Type predicate: checks if a value is a valid code block `Mode`. */\nfunction isMode(input: unknown): input is Mode {\n\treturn input === \"cli\" || input === \"file\" || input === \"traffic-policy\";\n}\n\n/** Converts a raw key-value record (from tokenized metastring) into a validated `Meta` object. */\nfunction parseMetaJson(input: Record<string, unknown>): Meta {\n\tconst {\n\t\tcollapsible = defaultMeta.collapsible,\n\t\tdisableCopy = defaultMeta.disableCopy,\n\t\tindentation = defaultMeta.indentation,\n\t\tmode = defaultMeta.mode,\n\t\ttitle = defaultMeta.title,\n\t} = input;\n\n\treturn {\n\t\tcollapsible:\n\t\t\ttypeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t: defaultMeta.collapsible,\n\t\tdisableCopy:\n\t\t\ttypeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t: defaultMeta.disableCopy,\n\t\tindentation: isIndentation(indentation) ? indentation : defaultMeta.indentation,\n\t\tmode: isMode(mode) ? mode : defaultMeta.mode,\n\t\ttitle: typeof title === \"string\" ? title.trim() : defaultMeta.title,\n\t};\n}\n\n/** Props that the rehype plugin attaches to `<pre>` elements for pre-rendered code blocks. */\ntype ResolvePreRenderedCodeBlockPropsInput = {\n\tcollapsible?: unknown;\n\tdisableCopy?: unknown;\n\tmantleCode?: unknown;\n\tmantleCollapsible?: unknown;\n\tmantleDisableCopy?: unknown;\n\tmantleHighlightLines?: unknown;\n\tmantleLanguage?: unknown;\n\tmantleLineNumberStart?: unknown;\n\tmantleMode?: unknown;\n\tmantlePreHtml?: unknown;\n\tmantleShowLineNumbers?: unknown;\n\tmantleTitle?: unknown;\n\tmode?: unknown;\n\ttitle?: unknown;\n};\n\n/** Combined input type for a `<pre>` element that may carry both metastring and pre-rendered props. */\ntype CodeBlockPreElementInput = MetaInput & ResolvePreRenderedCodeBlockPropsInput;\n\ntype PreRenderedCodeBlockPropKey = keyof ResolvePreRenderedCodeBlockPropsInput;\n\n/** Normalized code block props extracted from pre-rendered `<pre>` element attributes. */\ntype ResolvedPreRenderedCodeBlockProps = {\n\tcode: string | undefined;\n\tcollapsible: boolean | undefined;\n\tdisableCopy: boolean | undefined;\n\thighlightLines: (number | `${number}-${number}`)[] | undefined;\n\tlanguage: SupportedLanguage | undefined;\n\tlineNumberStart: number | undefined;\n\tmode: Mode | undefined;\n\tpreHtml: string | undefined;\n\trawLanguage: unknown;\n\tshowLineNumbers: boolean | undefined;\n\ttitle: string | undefined;\n};\n\n/** Result of {@link resolvePreRenderedCodeBlockProps}: extracted Mantle props and remaining pass-through props. */\ntype ResolvePreRenderedCodeBlockPropsResult<T extends Record<string, unknown>> = {\n\tmantleCode: ResolvedPreRenderedCodeBlockProps | undefined;\n\tprops: Omit<T, PreRenderedCodeBlockPropKey>;\n};\n\n/**\n * Extracts and normalizes `mantle*` props from a `<pre>` element's attributes,\n * separating them from pass-through props. Returns `undefined` for the Mantle\n * payload when no pre-rendered attributes are present.\n */\nfunction resolvePreRenderedCodeBlockProps<\n\tT extends ResolvePreRenderedCodeBlockPropsInput & Record<string, unknown>,\n>(input: T): ResolvePreRenderedCodeBlockPropsResult<T> {\n\tconst {\n\t\tcollapsible,\n\t\tdisableCopy,\n\t\tmantleCode,\n\t\tmantleCollapsible,\n\t\tmantleDisableCopy,\n\t\tmantleHighlightLines,\n\t\tmantleLanguage,\n\t\tmantleLineNumberStart,\n\t\tmantleMode,\n\t\tmantlePreHtml,\n\t\tmantleShowLineNumbers,\n\t\tmantleTitle,\n\t\tmode,\n\t\ttitle,\n\t\t...props\n\t} = input;\n\n\tconst hasPayload =\n\t\tmantleLanguage != null ||\n\t\tmantleCode != null ||\n\t\tmantlePreHtml != null ||\n\t\tmantleShowLineNumbers != null ||\n\t\tmantleHighlightLines != null ||\n\t\tmantleLineNumberStart != null ||\n\t\tmantleCollapsible != null ||\n\t\tmantleDisableCopy != null ||\n\t\tmantleMode != null ||\n\t\tmantleTitle != null;\n\n\tif (!hasPayload) {\n\t\treturn {\n\t\t\tmantleCode: undefined,\n\t\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t\t};\n\t}\n\n\treturn {\n\t\tmantleCode: {\n\t\t\tcode: typeof mantleCode === \"string\" ? mantleCode : undefined,\n\t\t\tcollapsible:\n\t\t\t\t(typeof mantleCollapsible === \"string\" || typeof mantleCollapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleCollapsible)\n\t\t\t\t\t: undefined) ??\n\t\t\t\t(typeof collapsible === \"string\" || typeof collapsible === \"boolean\"\n\t\t\t\t\t? parseBooleanish(collapsible)\n\t\t\t\t\t: undefined),\n\t\t\tdisableCopy:\n\t\t\t\ttypeof mantleDisableCopy === \"string\" || typeof mantleDisableCopy === \"boolean\"\n\t\t\t\t\t? parseBooleanish(mantleDisableCopy)\n\t\t\t\t\t: typeof disableCopy === \"string\" || typeof disableCopy === \"boolean\"\n\t\t\t\t\t\t? parseBooleanish(disableCopy)\n\t\t\t\t\t\t: undefined,\n\t\t\thighlightLines: parseCodeBlockHighlightLines(mantleHighlightLines),\n\t\t\tlanguage:\n\t\t\t\ttypeof mantleLanguage === \"string\" && isSupportedLanguage(mantleLanguage)\n\t\t\t\t\t? mantleLanguage\n\t\t\t\t\t: undefined,\n\t\t\tlineNumberStart: parseCodeBlockLineNumberStart(mantleLineNumberStart),\n\t\t\tmode: isMode(mantleMode) ? mantleMode : isMode(mode) ? mode : undefined,\n\t\t\tpreHtml: typeof mantlePreHtml === \"string\" ? mantlePreHtml : undefined,\n\t\t\trawLanguage: mantleLanguage,\n\t\t\tshowLineNumbers: parseCodeBlockShowLineNumbers(mantleShowLineNumbers),\n\t\t\ttitle:\n\t\t\t\ttypeof mantleTitle === \"string\"\n\t\t\t\t\t? mantleTitle.trim()\n\t\t\t\t\t: typeof title === \"string\"\n\t\t\t\t\t\t? title.trim()\n\t\t\t\t\t\t: undefined,\n\t\t},\n\t\tprops: props as Omit<T, PreRenderedCodeBlockPropKey>,\n\t};\n}\n\nexport { resolvePreRenderedCodeBlockProps };\nexport {\n\t//,\n\tdefaultMeta,\n\tnormalizeValue,\n\tparseMetastring,\n\ttokenizeMetastring,\n};\n\nexport type {\n\tCodeBlockPreElementInput,\n\tDefaultMeta,\n\tMeta,\n\tMetaInput,\n\tMode,\n\tResolvePreRenderedCodeBlockPropsInput,\n\tResolvePreRenderedCodeBlockPropsResult,\n\tResolvedPreRenderedCodeBlockProps,\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sandboxed-on-click.js","names":[],"sources":["../src/components/sandboxed-on-click/sandboxed-on-click.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ComponentProps, ComponentRef, HTMLAttributes, MouseEventHandler } from \"react\";\nimport { forwardRef } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype BaseProps = {\n\t/**\n\t * Only call `event.preventDefault()` in the `onClick` handler if the user\n\t * has not set `allowClickEventDefault` to `true`. This allows the user to\n\t * control whether or not the default behavior of the click event should be\n\t * allowed.\n\t *\n\t * This is useful for links or buttons that should navigate or perform some\n\t * action on click.\n\t *\n\t * @default false\n\t */\n\tallowClickEventDefault?: boolean;\n};\n\ntype EventProps = BaseProps & {\n\t/**\n\t * The click event handler.\n\t */\n\tonClick?: MouseEventHandler<HTMLElement>;\n};\n\n/**\n * Props for the sandboxed onClick container. Spread this on the element you want\n * to prevent the click event from bubbling out of.\n *\n * @see https://mantle.ngrok.com/components/sandboxed-on-click#sandboxedonclick\n */\nconst sandboxedOnClickProps = ({ allowClickEventDefault = false, onClick }: EventProps = {}) =>\n\t({\n\t\t/**\n\t\t * Marking an element with the role presentation indicates to assistive\n\t\t * technology that this element should be ignored; it exists to support the\n\t\t * web application and is not meant for humans to interact with directly.\n\t\t *\n\t\t * @see https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/65be35b0f6c6cf8b79e9a748cb657a64b78c6535/docs/rules/no-noninteractive-element-interactions.md#case-this-element-is-catching-bubbled-events-from-elements-that-it-contains\n\t\t * @see https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/presentation_role\n\t\t */\n\t\trole: \"presentation\",\n\t\tonClick: (event) => {\n\t\t\t/**\n\t\t\t * we _always_ want to stop propagation to prevent the event from bubbling\n\t\t\t * out of the sandboxed container\n\t\t\t */\n\t\t\tevent.stopPropagation();\n\n\t\t\t/**\n\t\t\t * Only call `event.preventDefault()` if the user has not set\n\t\t\t * `allowClickEventDefault` to true. This allows the user to control\n\t\t\t * whether or not the default behavior of the click event should be\n\t\t\t * allowed.\n\t\t\t *\n\t\t\t * This is useful for links or buttons that should navigate or perform\n\t\t\t * some action on click.\n\t\t\t */\n\t\t\tif (!allowClickEventDefault) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t\tonClick?.(event);\n\t\t},\n\t}) as const satisfies HTMLAttributes<HTMLElement>;\n\ntype Props = ComponentProps<\"div\"> & WithAsChild & BaseProps;\n\n/**\n * A container that prevents the click event from bubbling out of it.\n *\n * @see https://mantle.ngrok.com/components/sandboxed-on-click#sandboxedonclick\n *\n * @example\n * ```tsx\n * <TableRow onClick={() => navigate(\"/somewhere\")}>\n * <TableRowCell>\n * <SandboxedOnClick allowClickEventDefault>\n * <Anchor href=\"https://ngrok.com/docs\">\n * See ngrok docs\n * </Anchor>\n * </SandboxedOnClick>\n * </TableRowCell>\n * </TableRow>\n */\nconst SandboxedOnClick = forwardRef<ComponentRef<\"div\">, Props>(\n\t(\n\t\t{\n\t\t\t//,\n\t\t\tallowClickEventDefault = false,\n\t\t\tasChild = false,\n\t\t\tchildren,\n\t\t\tonClick,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t\t{...sandboxedOnClickProps({ allowClickEventDefault, onClick })}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nSandboxedOnClick.displayName = \"SandboxedOnClick\";\n\nexport {\n\t//,\n\tSandboxedOnClick,\n\tsandboxedOnClickProps,\n};\n"],"mappings":"kHAmCA,MAAM,GAAyB,CAAE,yBAAyB,GAAO,WAAwB,CAAC,KACxF,CASA,KAAM,eACN,QAAU,GAAU,CAKnB,EAAM,gBAAgB,EAWjB,GACJ,EAAM,eAAe,EAEtB,IAAU,CAAK,CAChB,CACD,GAqBK,EAAmB,GAEvB,CAEC,yBAAyB,GACzB,UAAU,GACV,WACA,UACA,GAAG,GAEJ,IAKC,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,GAAI,EACJ,GAAI,EAAsB,CAAE,yBAAwB,SAAQ,CAAC,EAE5D,UACS,CAAA,CAGd,EACA,EAAiB,YAAc"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"select-Cxc9VmP8.js","names":[],"sources":["../src/components/select/select.tsx"],"sourcesContent":["\"use client\";\n\nimport { CaretDownIcon } from \"@phosphor-icons/react/CaretDown\";\nimport { CaretUpIcon } from \"@phosphor-icons/react/CaretUp\";\nimport { CheckIcon } from \"@phosphor-icons/react/Check\";\nimport * as SelectPrimitive from \"@radix-ui/react-select\";\nimport type {\n\tComponentProps,\n\tComponentPropsWithoutRef,\n\tComponentRef,\n\tFocusEvent,\n\tPropsWithChildren,\n\tReactNode,\n\tRef,\n\tSelectHTMLAttributes,\n} from \"react\";\nimport { createContext, forwardRef, useContext, useMemo } from \"react\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { FieldControlContext } from \"../field/field-context.js\";\nimport { parseValidation, useFieldValidation } from \"../field/validation.js\";\nimport type { WithValidation } from \"../field/validation.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport { Separator } from \"../separator/separator.js\";\n\ntype WithAriaInvalid = Pick<SelectHTMLAttributes<HTMLSelectElement>, \"aria-invalid\">;\ntype SelectContextType = WithValidation &\n\tWithAriaInvalid & {\n\t\t/**\n\t\t * Ref for the trigger button.\n\t\t */\n\t\tref?: Ref<HTMLButtonElement>;\n\t\t/**\n\t\t * Event handler called when Select blurs.\n\t\t * @note this is a no-op for now until we can guarantee that it works identically to a native select onBlur\n\t\t */\n\t\tonBlur?: (event: FocusEvent<HTMLButtonElement>) => void;\n\t} & Pick<ComponentProps<\"button\">, \"id\">;\n\nconst SelectContext = createContext<SelectContextType>({});\n\ntype SelectProps = PropsWithChildren & {\n\tautoComplete?: string;\n\tdefaultOpen?: boolean;\n\tdefaultValue?: string;\n\tdir?: \"ltr\" | \"rtl\";\n\tdisabled?: boolean;\n\tform?: string;\n\tid?: string;\n\tname?: string;\n\t/**\n\t * Event handler called when Select blurs.\n\t * @note this is a no-op for now until we can guarantee that it works identically to a native select onBlur\n\t */\n\tonBlur?: (event: FocusEvent<HTMLButtonElement>) => void;\n\t/**\n\t * Event handler called when the value changes.\n\t * @deprecated Use `onValueChange` instead.\n\t */\n\tonChange?: (value: string) => void;\n\tonOpenChange?(open: boolean): void;\n\tonValueChange?(value: string): void;\n\topen?: boolean;\n\trequired?: boolean;\n\tvalue?: string;\n} & WithValidation &\n\tWithAriaInvalid;\n\n/**\n * Displays a list of options for the user to pick from—triggered by a button.\n *\n * Use Select for a small, finite list of options (~2-15) where the user picks exactly one\n * and search/filtering is unnecessary. For larger lists or async/searchable data, use\n * Combobox. For picking multiple options, use MultiSelect.\n *\n * Pass `validation` here when the entire select has an explicit state. That\n * root state is forwarded to `Select.Trigger` and takes precedence over the\n * ambient `validation` from `Field.Item`. Note: rendered `Field.Errors` /\n * `Field.ErrorList` set `aria-invalid=\"true\"` on the trigger via\n * `Field.Control`'s wiring, which still forces the trigger into the error\n * state — suppress the inferred error by passing `validation` on `Field.Item`\n * if a non-error `Select.Root` state needs to win in that case.\n *\n * @see https://mantle.ngrok.com/components/select#selectroot\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Root = forwardRef<HTMLButtonElement, SelectProps>(\n\t(\n\t\t{\n\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\tchildren,\n\t\t\tid,\n\t\t\tvalidation,\n\t\t\tonBlur,\n\t\t\tonValueChange,\n\t\t\tonChange,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst contextValue = useMemo(\n\t\t\t() => ({\n\t\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\t\tid,\n\t\t\t\tvalidation,\n\t\t\t\tonBlur,\n\t\t\t\tref,\n\t\t\t}),\n\t\t\t[_ariaInvalid, id, validation, onBlur, ref],\n\t\t);\n\t\treturn (\n\t\t\t<SelectPrimitive.Root\n\t\t\t\t{...props}\n\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\tonChange?.(value);\n\t\t\t\t\tonValueChange?.(value);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<SelectContext.Provider value={contextValue}>{children}</SelectContext.Provider>\n\t\t\t</SelectPrimitive.Root>\n\t\t);\n\t},\n);\nRoot.displayName = \"Select\";\n\n/**\n * A group of related options within a select menu. Similar to an html `<optgroup>` element.\n * Use in conjunction with Select.Label to ensure good accessibility via automatic labelling.\n *\n * @see https://mantle.ngrok.com/components/select#selectgroup\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Group = forwardRef<\n\tComponentRef<typeof SelectPrimitive.Group>,\n\tComponentPropsWithoutRef<typeof SelectPrimitive.Group>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Group\n\t\tref={ref}\n\t\tdata-slot=\"select-group\"\n\t\tclassName={cx(\"space-y-px\", className)}\n\t\t{...props}\n\t/>\n));\nGroup.displayName = \"SelectGroup\";\n\n/**\n * The part that reflects the selected value. By default the selected item's text will be rendered. if you require more control, you can instead control the select and pass your own children. It should not be styled to ensure correct positioning. An optional placeholder prop is also available for when the select has no value.\n *\n * @see https://mantle.ngrok.com/components/select#selectvalue\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Value = SelectPrimitive.Value;\nValue.displayName = \"SelectValue\";\n\ntype SelectTriggerProps = ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> &\n\tWithAriaInvalid &\n\tWithValidation;\n\n/**\n * The button that toggles the select. The Select.Content will position itself adjacent to the trigger.\n * When composing with `Field.Item`, wrap `Select.Root` in `Field.Control` —\n * the generated `id`, `name`, and `aria-invalid` flow onto `Select.Root` (so\n * the hidden form input gets the field name), and the trigger reads\n * `aria-describedby` / `aria-errormessage` from `FieldControlContext`.\n *\n * @see https://mantle.ngrok.com/components/select#selecttrigger\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Trigger = forwardRef<ComponentRef<typeof SelectPrimitive.Trigger>, SelectTriggerProps>(\n\t(\n\t\t{\n\t\t\t\"aria-invalid\": ariaInValidProp,\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tid: propId,\n\t\t\tvalidation: propValidation,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst ctx = useContext(SelectContext);\n\t\tconst fieldControl = useContext(FieldControlContext);\n\t\tconst fieldValidation = useFieldValidation();\n\t\tconst rawAriaInvalid = fieldControl\n\t\t\t? fieldControl[\"aria-invalid\"]\n\t\t\t: (ctx[\"aria-invalid\"] ?? ariaInValidProp);\n\t\t// Explicit Select props win over ambient Field validation. This lets\n\t\t// Field.Control override Field.Item while preserving Select.Root as the\n\t\t// highest-precedence select-level state.\n\t\tconst rawValidation = ctx.validation ?? propValidation ?? fieldValidation;\n\t\tconst { ariaInvalid, validation } = parseValidation({\n\t\t\t\"aria-invalid\": rawAriaInvalid,\n\t\t\tvalidation: rawValidation,\n\t\t});\n\t\tconst id = fieldControl ? fieldControl.id : (ctx.id ?? propId);\n\n\t\treturn (\n\t\t\t<SelectPrimitive.Trigger\n\t\t\t\tdata-slot=\"select-trigger\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"h-9 text-sm\",\n\t\t\t\t\t\"border-form bg-form text-strong font-sans placeholder:text-placeholder hover:bg-form-hover hover:text-strong flex w-full items-center justify-between gap-1.5 rounded-md border px-3 py-2 disabled:pointer-events-none disabled:opacity-50 [&>span]:line-clamp-1 [&>span]:text-left\",\n\t\t\t\t\t\"hover:border-neutral-400\",\n\t\t\t\t\t\"focus:outline-hidden focus:ring-4 aria-expanded:ring-4\",\n\t\t\t\t\t\"focus:border-accent-600 focus:ring-focus-accent aria-expanded:border-accent-600 aria-expanded:ring-focus-accent\",\n\t\t\t\t\t\"data-validation-success:border-success-600 data-validation-success:focus:border-success-600 data-validation-success:focus:ring-focus-success data-validation-success:aria-expanded:border-success-600 data-validation-success:aria-expanded:ring-focus-success\",\n\t\t\t\t\t\"data-validation-warning:border-warning-600 data-validation-warning:focus:border-warning-600 data-validation-warning:focus:ring-focus-warning data-validation-warning:aria-expanded:border-warning-600 data-validation-warning:aria-expanded:ring-focus-warning\",\n\t\t\t\t\t\"data-validation-error:border-danger-600 data-validation-error:focus:border-danger-600 data-validation-error:focus:ring-focus-danger data-validation-error:aria-expanded:border-danger-600 data-validation-error:aria-expanded:ring-focus-danger\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-validation={validation || undefined}\n\t\t\t\tid={id}\n\t\t\t\tref={composeRefs(ref, ctx.ref)}\n\t\t\t\t{...props}\n\t\t\t\t{...(fieldControl\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"aria-describedby\": fieldControl[\"aria-describedby\"],\n\t\t\t\t\t\t\t\"aria-errormessage\": fieldControl[\"aria-errormessage\"],\n\t\t\t\t\t\t}\n\t\t\t\t\t: undefined)}\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<SelectPrimitive.Icon asChild>\n\t\t\t\t\t<Icon svg={<CaretDownIcon weight=\"bold\" />} className=\"size-4\" />\n\t\t\t\t</SelectPrimitive.Icon>\n\t\t\t</SelectPrimitive.Trigger>\n\t\t);\n\t},\n);\nTrigger.displayName = \"SelectTrigger\";\n\n/**\n * The button that scrolls the select content up.\n * @private\n */\nconst SelectScrollUpButton = forwardRef<\n\tComponentRef<typeof SelectPrimitive.ScrollUpButton>,\n\tComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.ScrollUpButton\n\t\tref={ref}\n\t\tclassName={cx(\"flex cursor-default items-center justify-center py-1\", className)}\n\t\t{...props}\n\t>\n\t\t<Icon svg={<CaretUpIcon weight=\"bold\" />} className=\"size-4\" />\n\t</SelectPrimitive.ScrollUpButton>\n));\nSelectScrollUpButton.displayName = \"SelectScrollUpButton\";\n\n/**\n * The button that scrolls the select content down.\n * @private\n */\nconst SelectScrollDownButton = forwardRef<\n\tComponentRef<typeof SelectPrimitive.ScrollDownButton>,\n\tComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.ScrollDownButton\n\t\tref={ref}\n\t\tclassName={cx(\"flex cursor-default items-center justify-center py-1\", className)}\n\t\t{...props}\n\t>\n\t\t<Icon svg={<CaretDownIcon weight=\"bold\" />} className=\"size-4\" />\n\t</SelectPrimitive.ScrollDownButton>\n));\nSelectScrollDownButton.displayName = \"SelectScrollDownButton\";\n\ntype SelectContentProps = ComponentPropsWithoutRef<typeof SelectPrimitive.Content> & {\n\t/**\n\t * The width of the content. Defaults to the width of the trigger.\n\t * If set to \"content\", the content will use the intrinsic content width; it will be the width of the longest/widest item.\n\t * @default \"trigger\"\n\t */\n\twidth?: \"trigger\" | \"content\";\n};\n\n/**\n * The component that pops out when the select is open as a portal adjacent to the trigger button.\n * It contains a scrolling viewport of the select items.\n *\n * @see https://mantle.ngrok.com/components/select#selectcontent\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Content = forwardRef<ComponentRef<typeof SelectPrimitive.Content>, SelectContentProps>(\n\t({ className, children, position = \"popper\", width = \"trigger\", ...props }, ref) => (\n\t\t<SelectPrimitive.Portal>\n\t\t\t<SelectPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"select-content\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"border-popover data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 relative z-50 max-h-96 min-w-32 overflow-hidden rounded-md border shadow-md\",\n\t\t\t\t\t\"bg-popover font-sans\",\n\t\t\t\t\tposition === \"popper\" &&\n\t\t\t\t\t\t\"data-side-bottom:translate-y-2 data-side-left:-translate-x-2 data-side-right:translate-x-2 data-side-top:-translate-y-2 max-h-(--radix-select-content-available-height)\",\n\t\t\t\t\twidth === \"trigger\" && \"w-(--radix-select-trigger-width)\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tposition={position}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<SelectScrollUpButton />\n\t\t\t\t<SelectPrimitive.Viewport\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"p-1 space-y-px\",\n\t\t\t\t\t\tposition === \"popper\" && \"h-(--radix-select-trigger-height) w-full\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</SelectPrimitive.Viewport>\n\t\t\t\t<SelectScrollDownButton />\n\t\t\t</SelectPrimitive.Content>\n\t\t</SelectPrimitive.Portal>\n\t),\n);\nContent.displayName = \"SelectContent\";\n\n/**\n * Used to render the label of a group. It won't be focusable using arrow keys.\n *\n * @see https://mantle.ngrok.com/components/select#selectlabel\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Label = forwardRef<\n\tComponentRef<typeof SelectPrimitive.Label>,\n\tComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n\t<SelectPrimitive.Label\n\t\tref={ref}\n\t\tdata-slot=\"select-label\"\n\t\tclassName={cx(\"px-2 py-1.5 text-sm font-medium\", className)}\n\t\t{...props}\n\t/>\n));\nLabel.displayName = \"SelectLabel\";\n\ntype SelectItemProps = ComponentPropsWithoutRef<typeof SelectPrimitive.Item> & {\n\ticon?: ReactNode;\n};\n\n/**\n * An option within a select menu. Similar to an html `<option>` element.\n * Has a required `value` prop that will be passed to the `onChange` handler of the `Select` component when this item is selected.\n * Displays the children as the option's text.\n *\n * @see https://mantle.ngrok.com/components/select#selectitem\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Item = forwardRef<ComponentRef<typeof SelectPrimitive.Item>, SelectItemProps>(\n\t({ className, children, icon, ...props }, ref) => (\n\t\t<SelectPrimitive.Item\n\t\t\tref={ref}\n\t\t\tdata-slot=\"select-item\"\n\t\t\tclassName={cx(\n\t\t\t\t\"relative flex gap-2 w-full cursor-pointer select-none items-center rounded-md py-1.5 pl-2 pr-8 text-strong text-sm outline-hidden\",\n\t\t\t\t\"focus:bg-active-menu-item\",\n\t\t\t\t\"data-disabled:pointer-events-none data-disabled:opacity-50\",\n\t\t\t\t\"data-state-checked:bg-selected-menu-item\",\n\t\t\t\t\"focus:data-state-checked:bg-active-selected-menu-item\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{icon && <Icon svg={icon} />}\n\t\t\t<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n\t\t\t<SelectPrimitive.ItemIndicator className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n\t\t\t\t<Icon svg={<CheckIcon weight=\"bold\" />} className=\"size-4 text-accent-600\" />\n\t\t\t</SelectPrimitive.ItemIndicator>\n\t\t</SelectPrimitive.Item>\n\t),\n);\nItem.displayName = \"SelectItem\";\n\n/**\n * Used to visually separate items or groups of items in the select content.\n *\n * @see https://mantle.ngrok.com/components/select#selectseparator\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst SelectSeparatorComponent = forwardRef<\n\tComponentRef<typeof Separator>,\n\tComponentPropsWithoutRef<typeof Separator>\n>(({ className, ...props }, ref) => (\n\t<Separator\n\t\tref={ref}\n\t\tdata-slot=\"select-separator\"\n\t\tclassName={cx(\"-mx-1 my-1 h-px w-auto\", className)}\n\t\t{...props}\n\t/>\n));\nSelectSeparatorComponent.displayName = \"SelectSeparator\";\n\n/**\n * Displays a list of options for the user to pick from—triggered by a button.\n *\n * Use Select for a small, finite list of options (~2-15) where the user picks exactly one\n * and search/filtering is unnecessary. For larger lists or async/searchable data, use\n * Combobox. For picking multiple options, use MultiSelect.\n *\n * @see https://mantle.ngrok.com/components/select\n *\n * @example\n * Composition:\n * ```\n * Select.Root\n * ├── Select.Trigger\n * │ └── Select.Value\n * └── Select.Content\n * ├── Select.Group\n * │ ├── Select.Label\n * │ └── Select.Item\n * └── Select.Separator\n * ```\n *\n * @example\n * ```tsx\n * <Select.Root>\n * <Select.Trigger>\n * <Select.Value placeholder=\"Select a fruit\" />\n * </Select.Trigger>\n * <Select.Content>\n * <Select.Group>\n * <Select.Label>Fruits</Select.Label>\n * <Select.Item value=\"apple\">Apple</Select.Item>\n * <Select.Item value=\"banana\">Banana</Select.Item>\n * <Select.Item value=\"cherry\">Cherry</Select.Item>\n * </Select.Group>\n * <Select.Separator />\n * <Select.Group>\n * <Select.Label>Veggies</Select.Label>\n * <Select.Item value=\"carrot\">Carrot</Select.Item>\n * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n * </Select.Group>\n * </Select.Content>\n * </Select.Root>\n * ```\n */\nconst Select = {\n\t/**\n\t * Displays a list of options for the user to pick from—triggered by a button.\n\t *\n\t * Use Select for a small, finite list of options (~2-15) where the user picks exactly one\n\t * and search/filtering is unnecessary. For larger lists or async/searchable data, use\n\t * Combobox. For picking multiple options, use MultiSelect.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The component that pops out when the select is open as a portal adjacent to the trigger button.\n\t * It contains a scrolling viewport of the select items.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * A group of related options within a select menu. Similar to an html `<optgroup>` element.\n\t * Use in conjunction with Select.Label to ensure good accessibility via automatic labelling.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectgroup\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tGroup,\n\t/**\n\t * An option within a select menu. Similar to an html `<option>` element.\n\t * Has a required `value` prop that will be passed to the `onChange` handler of the `Select` component when this item is selected.\n\t * Displays the children as the option's text.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectitem\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tItem,\n\t/**\n\t * Used to render the label of a group. It won't be focusable using arrow keys.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectlabel\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tLabel,\n\t/**\n\t * Used to visually separate items or groups of items in the select content.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectseparator\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tSeparator: SelectSeparatorComponent,\n\t/**\n\t * The button that toggles the select. The Select.Content will position itself adjacent to the trigger.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selecttrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tTrigger,\n\t/**\n\t * The part that reflects the selected value. By default the selected item's text will be rendered. if you require more control, you can instead control the select and pass your own children. It should not be styled to ensure correct positioning. An optional placeholder prop is also available for when the select has no value.\n\t *\n\t * @see https://mantle.ngrok.com/components/select#selectvalue\n\t *\n\t * @example\n\t * ```tsx\n\t * <Select.Root>\n\t * <Select.Trigger>\n\t * <Select.Value placeholder=\"Select a fruit\" />\n\t * </Select.Trigger>\n\t * <Select.Content>\n\t * <Select.Group>\n\t * <Select.Label>Fruits</Select.Label>\n\t * <Select.Item value=\"apple\">Apple</Select.Item>\n\t * <Select.Item value=\"banana\">Banana</Select.Item>\n\t * <Select.Item value=\"cherry\">Cherry</Select.Item>\n\t * </Select.Group>\n\t * <Select.Separator />\n\t * <Select.Group>\n\t * <Select.Label>Veggies</Select.Label>\n\t * <Select.Item value=\"carrot\">Carrot</Select.Item>\n\t * <Select.Item value=\"cucumber\">Cucumber</Select.Item>\n\t * </Select.Group>\n\t * </Select.Content>\n\t * </Select.Root>\n\t * ```\n\t */\n\tValue,\n} as const;\n\nexport {\n\t//,\n\tSelect,\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"separator-Bqjy77rG.js","names":[],"sources":["../src/components/separator/separator.tsx"],"sourcesContent":["import type { ComponentProps, ComponentRef, HTMLAttributes } from \"react\";\nimport { createContext, forwardRef, useContext } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Slot } from \"../slot/index.js\";\n\nconst orientations = [\"horizontal\", \"vertical\"] as const;\ntype Orientation = (typeof orientations)[number];\n\ntype SeparatorGroupContextShape = {\n\torientation?: Orientation;\n};\n\nconst SeparatorGroupContext = createContext<SeparatorGroupContextShape>({});\n\n// Module-level constant so the Provider value identity is stable across renders.\nconst horizontalSeparatorGroupContextValue: SeparatorGroupContextShape = {\n\torientation: \"horizontal\",\n};\n\n/**\n * A container to layout a group of horizontal separators and other children.\n * Overrides all children `Separator`s to be `orientation=\"horizontal\"`.\n *\n * @see https://mantle.ngrok.com/components/separator\n *\n * @example\n * ```tsx\n * <HorizontalSeparatorGroup>\n * <Separator />\n * <h3>ngrok mantle</h3>\n * <Separator />\n * </HorizontalSeparatorGroup>\n *\n * <HorizontalSeparatorGroup>\n * <h3>ngrok mantle</h3>\n * <Separator />\n * </HorizontalSeparatorGroup>\n *\n * <HorizontalSeparatorGroup>\n * <Separator />\n * <h3>ngrok mantle</h3>\n * </HorizontalSeparatorGroup>\n * ```\n */\nconst HorizontalSeparatorGroup = ({\n\tclassName,\n\tchildren,\n\tasChild,\n\t...props\n}: HTMLAttributes<HTMLDivElement> & WithAsChild) => {\n\tconst Comp = asChild ? Slot : \"div\";\n\n\treturn (\n\t\t<SeparatorGroupContext.Provider value={horizontalSeparatorGroupContextValue}>\n\t\t\t<Comp\n\t\t\t\tdata-slot=\"horizontal-separator-group\"\n\t\t\t\tdata-horizontal-separator-group\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"group flex items-center gap-2 [&_*:not([data-separator])]:shrink-0\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Comp>\n\t\t</SeparatorGroupContext.Provider>\n\t);\n};\nHorizontalSeparatorGroup.displayName = \"HorizontalSeparatorGroup\";\n\ntype SeparatorProps = ComponentProps<\"div\"> &\n\tWithAsChild & {\n\t\t/**\n\t\t * Either `horizontal` or `vertical`.\n\t\t *\n\t\t * @default \"horizontal\"\n\t\t */\n\t\torientation?: Orientation;\n\t\t/**\n\t\t * If `true`, the separator will be rendered with all accessibility-related attributes and role=\"separator\".\n\t\t * If `false`, the separator is purely decorative and all accessibility-related attributes\n\t\t * are updated so that that the rendered element is removed from the accessibility tree.\n\t\t *\n\t\t * @default false\n\t\t */\n\t\tsemantic?: boolean;\n\t};\n\n/**\n * Visually or semantically separates content.\n *\n * @see https://mantle.ngrok.com/components/separator\n *\n * @example\n * ```tsx\n * <Separator className=\"my-4\" />\n *\n * <Separator className=\"my-4\" semantic />\n *\n * <div className=\"flex h-5 items-center gap-4 text-sm\">\n * Blog\n * <Separator orientation=\"vertical\" />\n * Docs\n * <Separator orientation=\"vertical\" />\n * Source\n * </div>\n * ```\n */\nconst Separator = forwardRef<ComponentRef<\"div\">, SeparatorProps>(\n\t(\n\t\t{\n\t\t\tasChild = false,\n\t\t\tchildren,\n\t\t\tclassName,\n\t\t\torientation: propOrientation,\n\t\t\tsemantic = false,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\t\tconst ctx = useContext(SeparatorGroupContext);\n\t\t// Prefer the orientation from the context if it's set, else fallback to the prop and then to \"horizontal\".\n\t\tconst orientation =\n\t\t\tctx.orientation ?? (isOrientation(propOrientation) ? propOrientation : \"horizontal\");\n\t\t// `aria-orientation` defaults to `horizontal` so we only need it if `orientation` is vertical\n\t\tconst ariaOrientation = orientation === \"vertical\" ? orientation : undefined;\n\t\tconst semanticProps = semantic\n\t\t\t? { \"aria-orientation\": ariaOrientation, role: \"separator\" }\n\t\t\t: { role: \"none\" };\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tdata-slot=\"separator\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"separator\",\n\t\t\t\t\t\"dark-high-contrast:bg-black high-contrast:bg-black bg-gray-500/20 dark:bg-gray-600/20\",\n\t\t\t\t\torientation === \"horizontal\"\n\t\t\t\t\t\t? \"h-px w-full group-data-horizontal-separator-group:flex-1\"\n\t\t\t\t\t\t: \"h-full w-px\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tdata-orientation={orientation}\n\t\t\t\tdata-separator\n\t\t\t\t{...semanticProps}\n\t\t\t\tref={ref}\n\t\t\t\t{...(asChild ? { children } : {})} // only pass children if asChild is true\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nSeparator.displayName = \"Separator\";\n\nexport {\n\t//,\n\tHorizontalSeparatorGroup,\n\tSeparator,\n};\n\nfunction isOrientation(value: unknown): value is Orientation {\n\treturn typeof value === \"string\" && orientations.includes(value as Orientation);\n}\n"],"mappings":"qLAMA,MAAM,EAAe,CAAC,aAAc,UAAU,EAOxC,EAAwB,EAA0C,CAAC,CAAC,EAGpE,EAAmE,CACxE,YAAa,YACd,EA2BM,GAA4B,CACjC,YACA,WACA,UACA,GAAG,KACgD,CACnD,IAAM,EAAO,EAAU,EAAO,MAE9B,OACC,EAAC,EAAsB,SAAvB,CAAgC,MAAO,WACtC,EAAC,EAAD,CACC,YAAU,6BACV,kCAAA,GACA,UAAW,EACV,qEACA,CACD,EACA,GAAI,EAEH,UACI,CAAA,CACyB,CAAA,CAElC,EACA,EAAyB,YAAc,2BAwCvC,MAAM,EAAY,GAEhB,CACC,UAAU,GACV,WACA,YACA,YAAa,EACb,WAAW,GACX,GAAG,GAEJ,IACI,CACJ,IAAM,EAAY,EAAU,EAAO,MAG7B,EAFM,EAAW,CAGpB,CAAC,CAAC,cAAgB,EAAc,CAAe,EAAI,EAAkB,cAGlE,EAAgB,EACnB,CAAE,mBAFmB,IAAgB,WAAa,EAAc,IAAA,GAEzB,KAAM,WAAY,EACzD,CAAE,KAAM,MAAO,EAElB,OACC,EAAC,EAAD,CACC,YAAU,YACV,UAAW,EACV,YACA,wFACA,IAAgB,aACb,2DACA,cACH,CACD,EACA,mBAAkB,EAClB,iBAAA,GACA,GAAI,EACC,MACL,GAAK,EAAU,CAAE,UAAS,EAAI,CAAC,EAC/B,GAAI,CACJ,CAAA,CAEH,CACD,EACA,EAAU,YAAc,YAQxB,SAAS,EAAc,EAAsC,CAC5D,OAAO,OAAO,GAAU,UAAY,EAAa,SAAS,CAAoB,CAC/E"}
|