@seekalfred/primitives 0.7.1 → 0.7.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 +255 -5
- package/dist/alert/alert.d.ts +49 -4
- package/dist/alert/alert.js +66 -38
- package/dist/alert/alert.js.map +1 -1
- package/dist/alert/index.d.ts +2 -2
- package/dist/alert/index.js +2 -2
- package/dist/alert-dialog/alert-dialog.d.ts +31 -4
- package/dist/alert-dialog/alert-dialog.js +75 -26
- package/dist/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/announcement-bar/announcement-bar.d.ts +15 -4
- package/dist/announcement-bar/announcement-bar.js +31 -6
- package/dist/announcement-bar/announcement-bar.js.map +1 -1
- package/dist/avatar/avatar.d.ts +7 -0
- package/dist/avatar/avatar.js +33 -12
- package/dist/avatar/avatar.js.map +1 -1
- package/dist/badge/badge.d.ts +1 -1
- package/dist/bar-chart/bar-chart-series.d.ts +75 -0
- package/dist/bar-chart/bar-chart-series.js +401 -0
- package/dist/bar-chart/bar-chart-series.js.map +1 -0
- package/dist/bar-chart/bar-chart.d.ts +25 -1
- package/dist/bar-chart/bar-chart.js +26 -1
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/index.d.ts +2 -1
- package/dist/button/button.d.ts +1 -1
- package/dist/calendar/calendar.d.ts +1 -1
- package/dist/card/card.d.ts +22 -1
- package/dist/card/card.js +60 -7
- package/dist/card/card.js.map +1 -1
- package/dist/carousel/carousel.d.ts +21 -0
- package/dist/carousel/carousel.js +34 -8
- package/dist/carousel/carousel.js.map +1 -1
- package/dist/chip-group/chip-group.d.ts +11 -0
- package/dist/chip-group/chip-group.js +50 -34
- package/dist/chip-group/chip-group.js.map +1 -1
- package/dist/chip-group/index.d.ts +2 -2
- package/dist/copy-button/copy-button.d.ts +37 -5
- package/dist/copy-button/copy-button.js +35 -11
- package/dist/copy-button/copy-button.js.map +1 -1
- package/dist/donut-chart/donut-chart.d.ts +22 -0
- package/dist/donut-chart/donut-chart.js +35 -18
- package/dist/donut-chart/donut-chart.js.map +1 -1
- package/dist/donut-chart/index.d.ts +2 -2
- package/dist/empty-state/empty-state.d.ts +21 -0
- package/dist/empty-state/empty-state.js +16 -4
- package/dist/empty-state/empty-state.js.map +1 -1
- package/dist/empty-state/index.d.ts +2 -2
- package/dist/empty-state/index.js +2 -2
- package/dist/file-drop-zone/file-drop-zone.d.ts +29 -3
- package/dist/file-drop-zone/file-drop-zone.js +26 -8
- package/dist/file-drop-zone/file-drop-zone.js.map +1 -1
- package/dist/filter-bar/filter-bar.d.ts +4 -1
- package/dist/filter-bar/filter-bar.js +53 -9
- package/dist/filter-bar/filter-bar.js.map +1 -1
- package/dist/gauge/gauge.d.ts +18 -1
- package/dist/gauge/gauge.js +35 -21
- package/dist/gauge/gauge.js.map +1 -1
- package/dist/gauge/index.d.ts +2 -2
- package/dist/index.d.ts +15 -14
- package/dist/index.js +9 -9
- package/dist/input/input.d.ts +7 -0
- package/dist/input/input.js +7 -5
- package/dist/input/input.js.map +1 -1
- package/dist/lib/field-shell.js +6 -3
- package/dist/lib/field-shell.js.map +1 -1
- package/dist/lib/field-surface.js +22 -1
- package/dist/lib/field-surface.js.map +1 -1
- package/dist/lib/required-marker.js +20 -0
- package/dist/lib/required-marker.js.map +1 -0
- package/dist/lib/use-copy-feedback.js +17 -3
- package/dist/lib/use-copy-feedback.js.map +1 -1
- package/dist/line-chart/index.d.ts +2 -2
- package/dist/line-chart/line-chart.d.ts +144 -2
- package/dist/line-chart/line-chart.js +314 -46
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/money-input/index.d.ts +2 -2
- package/dist/money-input/money-input.d.ts +36 -1
- package/dist/money-input/money-input.js +30 -14
- package/dist/money-input/money-input.js.map +1 -1
- package/dist/morph-select/morph-select.d.ts +26 -1
- package/dist/morph-select/morph-select.js +28 -6
- package/dist/morph-select/morph-select.js.map +1 -1
- package/dist/multi-select/index.d.ts +2 -2
- package/dist/multi-select/index.js +2 -2
- package/dist/multi-select/multi-select.d.ts +74 -2
- package/dist/multi-select/multi-select.js +213 -39
- package/dist/multi-select/multi-select.js.map +1 -1
- package/dist/password-field/password-field.d.ts +16 -0
- package/dist/password-field/password-field.js +37 -8
- package/dist/password-field/password-field.js.map +1 -1
- package/dist/popover/index.d.ts +2 -2
- package/dist/popover/index.js +2 -2
- package/dist/popover/popover.d.ts +39 -2
- package/dist/popover/popover.js +29 -2
- package/dist/popover/popover.js.map +1 -1
- package/dist/progress/index.d.ts +2 -2
- package/dist/progress/index.js +2 -2
- package/dist/progress/progress.d.ts +68 -3
- package/dist/progress/progress.js +156 -39
- package/dist/progress/progress.js.map +1 -1
- package/dist/radio-group/index.d.ts +2 -2
- package/dist/radio-group/index.js +2 -2
- package/dist/radio-group/radio-group.d.ts +33 -3
- package/dist/radio-group/radio-group.js +109 -9
- package/dist/radio-group/radio-group.js.map +1 -1
- package/dist/scroll-area/scroll-area.js +4 -3
- package/dist/scroll-area/scroll-area.js.map +1 -1
- package/dist/scrub-input/scrub-input.d.ts +11 -1
- package/dist/scrub-input/scrub-input.js +22 -10
- package/dist/scrub-input/scrub-input.js.map +1 -1
- package/dist/search-field/search-field.d.ts +22 -1
- package/dist/search-field/search-field.js +22 -7
- package/dist/search-field/search-field.js.map +1 -1
- package/dist/select/select.d.ts +10 -1
- package/dist/select/select.js +11 -8
- package/dist/select/select.js.map +1 -1
- package/dist/separator/separator.d.ts +21 -9
- package/dist/separator/separator.js +33 -11
- package/dist/separator/separator.js.map +1 -1
- package/dist/sparkline/sparkline.d.ts +27 -2
- package/dist/sparkline/sparkline.js +115 -18
- package/dist/sparkline/sparkline.js.map +1 -1
- package/dist/stat-card/index.d.ts +2 -2
- package/dist/stat-card/index.js +2 -2
- package/dist/stat-card/stat-card.d.ts +65 -1
- package/dist/stat-card/stat-card.js +98 -25
- package/dist/stat-card/stat-card.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/table/index.d.ts +2 -2
- package/dist/table/index.js +2 -2
- package/dist/table/table.d.ts +115 -5
- package/dist/table/table.js +374 -94
- package/dist/table/table.js.map +1 -1
- package/dist/text-shimmer/text-shimmer.d.ts +18 -2
- package/dist/text-shimmer/text-shimmer.js +5 -2
- package/dist/text-shimmer/text-shimmer.js.map +1 -1
- package/dist/textarea/textarea.d.ts +7 -0
- package/dist/textarea/textarea.js +3 -1
- package/dist/textarea/textarea.js.map +1 -1
- package/dist/time-picker/time-picker.d.ts +36 -1
- package/dist/time-picker/time-picker.js +33 -5
- package/dist/time-picker/time-picker.js.map +1 -1
- package/dist/toast/toast.d.ts +2 -2
- package/dist/usage-meter/index.d.ts +2 -2
- package/dist/usage-meter/usage-meter.d.ts +30 -0
- package/dist/usage-meter/usage-meter.js +56 -38
- package/dist/usage-meter/usage-meter.js.map +1 -1
- package/package.json +3 -3
package/dist/gauge/gauge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gauge.js","names":[],"sources":["../../src/gauge/gauge.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { prefersReducedMotion, useIsomorphicLayoutEffect } from \"../lib/motion.js\";\nimport { live, MORPH, retarget, REVEAL, SMOOTH } from \"../lib/spring-tween.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * Gauge: one value against a range, as a ring open at the bottom with the\n * number at its centre. Use it for a score or a fill level; use Progress for a\n * task that finishes.\n *\n * The ring fills the first time it is seen, slowly and without overshoot, like\n * a ring closing. After that it springs to each new value with a little life\n * while the count follows without overshooting. A band that starts at\n * `from` sets the colour and names the state (\"Healthy\", \"At risk\"): the\n * highest band the value reaches wins, and it changes exactly as the count\n * crosses the threshold, so state never rests on colour alone. The label,\n * status and detail rise in when they change, from the side the value moved\n * toward.\n *\n * Plain SVG and CSS. One small spring tween writes the ring and the count\n * straight to the DOM. The ring is a `meter` for assistive technology.\n */\nexport type GaugeTone = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport interface GaugeThreshold {\n /** The band starts at this value (in the same unit as `value`). */\n from: number;\n tone: GaugeTone;\n /** Names the state. Shown under the number and announced with the value. */\n label: string;\n}\n\nexport interface GaugeProps extends Omit<ComponentPropsWithoutRef<\"figure\">, \"children\"> {\n value: number;\n /** @default 0 */\n min?: number;\n /** @default 100 */\n max?: number;\n /** What is measured. Names the meter. */\n label: string;\n /** A line under the label, such as \"Up 4 from last week\". */\n detail?: string;\n /** The colour when no band applies. @default \"primary\" */\n tone?: GaugeTone;\n /** Bands that set the tone and name the state. */\n thresholds?: GaugeThreshold[];\n}\n\n/** A 270 degree ring open at the bottom, drawn clockwise from its lower left end. Redrawn from the sweep every frame so the round cap stays exact. */\nconst RADIUS = 42;\nconst START = -135;\nconst SPAN = 270;\nconst clamp = (value: number, low: number, high: number) => Math.min(high, Math.max(low, value));\n\nfunction ringFor(sweep: number) {\n const end = START + SPAN * clamp(sweep, 0, 1);\n const at = (angle: number) =>\n `${(50 + RADIUS * Math.sin((angle * Math.PI) / 180)).toFixed(3)} ${(50 - RADIUS * Math.cos((angle * Math.PI) / 180)).toFixed(3)}`;\n return `M ${at(START)} A ${RADIUS} ${RADIUS} 0 ${end - START > 180 ? 1 : 0} 1 ${at(end)}`;\n}\nconst TRACK = ringFor(1);\n\nexport const Gauge = forwardRef<HTMLElement, GaugeProps>(function Gauge(\n { value, min = 0, max = 100, label, detail, tone = \"primary\", thresholds, className, ...props },\n ref,\n) {\n const safeMax = max > min ? max : min + 1;\n const percentage = clamp((value - min) / (safeMax - min), 0, 1);\n const displayValue = Math.round(percentage * 100);\n const bands = [...(thresholds ?? [])].sort((a, b) => a.from - b.from);\n const bandAt = (at: number) => bands.filter((band) => at >= band.from - 1e-6).pop();\n const band = bandAt(value);\n\n const figure = useRef<HTMLElement | null>(null);\n const refs = useMemo(() => mergeRefs(ref, figure), [ref]);\n const ring = useRef<SVGPathElement>(null);\n const digits = useRef<HTMLSpanElement>(null);\n const sizer = useRef<HTMLSpanElement>(null);\n const sweep = useRef(live(0));\n const count = useRef(live(0));\n\n const [seen, setSeen] = useState(false);\n const [filled, setFilled] = useState(false);\n // The band on screen: after the first fill it follows the number as it counts.\n const [shownBand, setShownBand] = useState(band);\n const [moved, setMoved] = useState({ value: displayValue, direction: 1 });\n if (moved.value !== displayValue) {\n setMoved({ value: displayValue, direction: displayValue < moved.value ? -1 : 1 });\n }\n\n const latest = useRef({ bandAt, min, span: safeMax - min, filled });\n useIsomorphicLayoutEffect(() => {\n latest.current = { bandAt, min, span: safeMax - min, filled };\n });\n const shownRef = useRef(shownBand);\n useIsomorphicLayoutEffect(() => {\n shownRef.current = shownBand;\n });\n\n /** One writer: the ring, its fade-in over the first sliver, and the count. */\n const paint = useCallback(() => {\n const to = clamp(sweep.current.value, 0, 1);\n ring.current?.setAttribute(\"d\", ringFor(to));\n if (ring.current) ring.current.style.opacity = String(clamp(to / 0.02, 0, 1));\n const shown = clamp(count.current.value, 0, 100);\n if (digits.current) digits.current.textContent = String(Math.round(shown));\n // After the first fill the state follows the number on screen, so the colour and label change as the count crosses a threshold.\n const { bandAt: pick, min: lo, span, filled: done } = latest.current;\n if (done) {\n const next = pick(lo + (shown / 100) * span);\n const current = shownRef.current;\n if (next?.from !== current?.from || next?.label !== current?.label) {\n shownRef.current = next;\n setShownBand(next);\n }\n }\n }, []);\n\n // The ring fills once half of it is in view.\n useEffect(() => {\n const node = figure.current;\n if (!node || prefersReducedMotion() || typeof IntersectionObserver === \"undefined\") {\n setSeen(true);\n return;\n }\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return;\n observer.disconnect();\n setSeen(true);\n },\n { threshold: 0.5 },\n );\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n // The first fill is slower and never overshoots; later values spring to place, the count a beat calmer.\n const bandRef = useRef(band);\n useIsomorphicLayoutEffect(() => {\n bandRef.current = band;\n });\n useEffect(() => {\n if (!seen) return;\n const first = !latest.current.filled;\n retarget(sweep.current, percentage, first ? REVEAL : MORPH, paint);\n retarget(\n count.current,\n percentage * 100,\n first ? REVEAL : SMOOTH,\n paint,\n 0,\n first\n ? () => {\n latest.current.filled = true;\n shownRef.current = bandRef.current;\n setShownBand(bandRef.current);\n setFilled(true);\n }\n : undefined,\n );\n }, [percentage, seen, paint]);\n useEffect(() => {\n const sweeping = sweep.current;\n const number = count.current;\n return () => {\n sweeping.stop();\n number.stop();\n };\n }, []);\n useIsomorphicLayoutEffect(paint, [paint]);\n\n // The digits sit right aligned in a box sized to the target number, so the ones column never jumps while counting and the group recentres when the number gains or loses a digit.\n useEffect(() => {\n const node = sizer.current;\n const box = digits.current;\n if (!node || !box || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (!entry) return;\n box.style.width = `${entry.borderBoxSize?.[0]?.inlineSize ?? node.offsetWidth}px`;\n });\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n const shown = filled ? shownBand : band;\n const activeTone = (filled ? shownBand : band)?.tone ?? tone;\n const clampedValue = clamp(value, min, safeMax);\n\n return (\n <figure\n ref={refs}\n {...props}\n data-slot=\"gauge\"\n data-tone={activeTone}\n className={cn(\"gauge\", className)}\n >\n <div\n data-slot=\"gauge-visual\"\n role=\"meter\"\n aria-label={label}\n aria-valuemin={min}\n aria-valuemax={safeMax}\n aria-valuenow={clampedValue}\n aria-valuetext={`${displayValue}%${band ? `, ${band.label}` : \"\"}`}\n className=\"gauge-visual\"\n >\n <svg\n viewBox=\"0 0 100 90\"\n aria-hidden=\"true\"\n focusable=\"false\"\n className=\"block size-full overflow-visible\"\n >\n <path d={TRACK} className=\"gauge-track\" />\n <path ref={ring} className=\"gauge-fill\" style={{ opacity: 0 }} />\n </svg>\n <div aria-hidden=\"true\" className=\"gauge-readout\">\n <span className=\"gauge-number\">\n <span ref={digits} className=\"gauge-digits\" />\n <span className=\"gauge-unit\">%</span>\n <span ref={sizer} className=\"gauge-sizer\">\n {displayValue}\n </span>\n </span>\n {thresholds ? (\n <span className=\"gauge-status\">\n <SwapText\n swapKey={filled ? (shown?.label ?? \"\") : \"\"}\n dir={moved.direction}\n className=\"block\"\n >\n {shown?.label}\n </SwapText>\n </span>\n ) : null}\n </div>\n </div>\n <figcaption className=\"grid min-w-0 gap-0.5\">\n <strong className=\"text-sm font-medium text-foreground\">\n <SwapText swapKey={label} className=\"block\">\n {label}\n </SwapText>\n </strong>\n {detail ? (\n <span className=\"text-xs tabular-nums text-text-secondary\">\n <SwapText swapKey={detail} dir={moved.direction} className=\"block\">\n {detail}\n </SwapText>\n </span>\n ) : null}\n </figcaption>\n </figure>\n );\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"gauge.js","names":[],"sources":["../../src/gauge/gauge.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentPropsWithoutRef,\n} from \"react\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { mergeRefs } from \"../lib/merge-refs.js\";\nimport { prefersReducedMotion, useIsomorphicLayoutEffect } from \"../lib/motion.js\";\nimport { live, MORPH, retarget, REVEAL, SMOOTH } from \"../lib/spring-tween.js\";\nimport { SwapText } from \"../lib/swap-text.js\";\n\n/**\n * Gauge: one value against a range, as a ring open at the bottom with the\n * number at its centre. Use it for a score or a fill level; use Progress for a\n * task that finishes.\n *\n * The ring fills the first time it is seen, slowly and without overshoot, like\n * a ring closing. After that it springs to each new value with a little life\n * while the count follows without overshooting. A band that starts at\n * `from` sets the colour and names the state (\"Healthy\", \"At risk\"): the\n * highest band the value reaches wins, and it changes exactly as the count\n * crosses the threshold, so state never rests on colour alone. The label,\n * status and detail rise in when they change, from the side the value moved\n * toward.\n *\n * A missing value (`null`) shows an empty ring, a dash and \"No data\", and is\n * read as an image named \"<label>: No data\" rather than a meter, since there\n * is nothing to measure. Size `sm` is the number alone in a small ring, for a\n * table cell or a card corner; the label and detail stay for assistive\n * technology.\n *\n * Plain SVG and CSS. One small spring tween writes the ring and the count\n * straight to the DOM. The ring is a `meter` for assistive technology.\n */\nexport type GaugeTone = \"primary\" | \"success\" | \"warning\" | \"danger\";\n\nexport type GaugeSize = \"sm\" | \"md\";\n\nexport interface GaugeThreshold {\n /** The band starts at this value (in the same unit as `value`). */\n from: number;\n tone: GaugeTone;\n /** Names the state. Shown under the number and announced with the value. */\n label: string;\n}\n\nexport interface GaugeProps extends Omit<ComponentPropsWithoutRef<\"figure\">, \"children\"> {\n /** The value. `null` (or a value that is not a finite number) is no data: an empty ring that reads `missingLabel`. */\n value: number | null;\n /** @default 0 */\n min?: number;\n /** @default 100 */\n max?: number;\n /** What is measured. Names the meter. */\n label: string;\n /** A line under the label, such as \"Up 4 from last week\". */\n detail?: string;\n /** The colour when no band applies. @default \"primary\" */\n tone?: GaugeTone;\n /** Bands that set the tone and name the state. */\n thresholds?: GaugeThreshold[];\n /**\n * `\"sm\"` is the number alone in a small ring (48px; set `--gauge-size` to\n * change it), coloured by the tone. The percent sign, the status line and\n * the caption are not drawn; the label, band and detail are still read.\n * @default \"md\"\n */\n size?: GaugeSize;\n /** Shown and read in place of the value when it is missing. @default \"No data\" */\n missingLabel?: string;\n}\n\n/** A 270 degree ring open at the bottom, drawn clockwise from its lower left end. Redrawn from the sweep every frame so the round cap stays exact. */\nconst RADIUS = 42;\nconst START = -135;\nconst SPAN = 270;\nconst clamp = (value: number, low: number, high: number) => Math.min(high, Math.max(low, value));\n\nfunction ringFor(sweep: number) {\n const end = START + SPAN * clamp(sweep, 0, 1);\n const at = (angle: number) =>\n `${(50 + RADIUS * Math.sin((angle * Math.PI) / 180)).toFixed(3)} ${(50 - RADIUS * Math.cos((angle * Math.PI) / 180)).toFixed(3)}`;\n return `M ${at(START)} A ${RADIUS} ${RADIUS} 0 ${end - START > 180 ? 1 : 0} 1 ${at(end)}`;\n}\nconst TRACK = ringFor(1);\n\nexport const Gauge = forwardRef<HTMLElement, GaugeProps>(function Gauge(\n {\n value: given,\n min = 0,\n max = 100,\n label,\n detail,\n tone = \"primary\",\n thresholds,\n size = \"md\",\n missingLabel = \"No data\",\n className,\n ...props\n },\n ref,\n) {\n const missing = typeof given !== \"number\" || !Number.isFinite(given);\n const value = missing ? min : given;\n const small = size === \"sm\";\n const safeMax = max > min ? max : min + 1;\n const percentage = clamp((value - min) / (safeMax - min), 0, 1);\n const displayValue = Math.round(percentage * 100);\n const bands = [...(thresholds ?? [])].sort((a, b) => a.from - b.from);\n const bandAt = (at: number) => bands.filter((band) => at >= band.from - 1e-6).pop();\n const band = missing ? undefined : bandAt(value);\n\n const figure = useRef<HTMLElement | null>(null);\n const refs = useMemo(() => mergeRefs(ref, figure), [ref]);\n const ring = useRef<SVGPathElement>(null);\n const digits = useRef<HTMLSpanElement>(null);\n const sizer = useRef<HTMLSpanElement>(null);\n const sweep = useRef(live(0));\n const count = useRef(live(0));\n\n const [seen, setSeen] = useState(false);\n const [filled, setFilled] = useState(false);\n // The band on screen: after the first fill it follows the number as it counts.\n const [shownBand, setShownBand] = useState(band);\n const [moved, setMoved] = useState({ value: displayValue, direction: 1 });\n if (moved.value !== displayValue) {\n setMoved({ value: displayValue, direction: displayValue < moved.value ? -1 : 1 });\n }\n\n const latest = useRef({ bandAt, min, span: safeMax - min, filled, missing });\n useIsomorphicLayoutEffect(() => {\n latest.current = { bandAt, min, span: safeMax - min, filled, missing };\n });\n const shownRef = useRef(shownBand);\n useIsomorphicLayoutEffect(() => {\n shownRef.current = shownBand;\n });\n\n /** One writer: the ring, its fade-in over the first sliver, and the count. */\n const paint = useCallback(() => {\n const to = clamp(sweep.current.value, 0, 1);\n ring.current?.setAttribute(\"d\", ringFor(to));\n if (ring.current) ring.current.style.opacity = String(clamp(to / 0.02, 0, 1));\n const shown = clamp(count.current.value, 0, 100);\n const { bandAt: pick, min: lo, span, filled: done, missing: empty } = latest.current;\n if (digits.current) digits.current.textContent = empty ? \"–\" : String(Math.round(shown));\n // After the first fill the state follows the number on screen, so the colour and label change as the count crosses a threshold.\n if (done && !empty) {\n const next = pick(lo + (shown / 100) * span);\n const current = shownRef.current;\n if (next?.from !== current?.from || next?.label !== current?.label) {\n shownRef.current = next;\n setShownBand(next);\n }\n }\n }, []);\n\n // The ring fills once half of it is in view.\n useEffect(() => {\n const node = figure.current;\n if (!node || prefersReducedMotion() || typeof IntersectionObserver === \"undefined\") {\n setSeen(true);\n return;\n }\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (!entry?.isIntersecting) return;\n observer.disconnect();\n setSeen(true);\n },\n { threshold: 0.5 },\n );\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n // The first fill is slower and never overshoots; later values spring to place, the count a beat calmer.\n const bandRef = useRef(band);\n useIsomorphicLayoutEffect(() => {\n bandRef.current = band;\n });\n useEffect(() => {\n if (!seen) return;\n const first = !latest.current.filled;\n retarget(sweep.current, percentage, first ? REVEAL : MORPH, paint);\n retarget(\n count.current,\n percentage * 100,\n first ? REVEAL : SMOOTH,\n paint,\n 0,\n first\n ? () => {\n latest.current.filled = true;\n shownRef.current = bandRef.current;\n setShownBand(bandRef.current);\n setFilled(true);\n }\n : undefined,\n );\n }, [percentage, seen, paint]);\n // A value that goes missing (or comes back) at the same percentage still repaints the digits.\n useIsomorphicLayoutEffect(paint, [missing, paint]);\n useEffect(() => {\n const sweeping = sweep.current;\n const number = count.current;\n return () => {\n sweeping.stop();\n number.stop();\n };\n }, []);\n useIsomorphicLayoutEffect(paint, [paint]);\n\n // The digits sit right aligned in a box sized to the target number, so the ones column never jumps while counting and the group recentres when the number gains or loses a digit.\n useEffect(() => {\n const node = sizer.current;\n const box = digits.current;\n if (!node || !box || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(([entry]) => {\n if (!entry) return;\n box.style.width = `${entry.borderBoxSize?.[0]?.inlineSize ?? node.offsetWidth}px`;\n });\n observer.observe(node);\n return () => observer.disconnect();\n }, []);\n\n const shown = missing ? undefined : filled ? shownBand : band;\n const activeTone = shown?.tone ?? tone;\n const clampedValue = clamp(value, min, safeMax);\n const reading = missing\n ? { role: \"img\", \"aria-label\": `${label}: ${missingLabel}` }\n : {\n role: \"meter\",\n \"aria-label\": label,\n \"aria-valuemin\": min,\n \"aria-valuemax\": safeMax,\n \"aria-valuenow\": clampedValue,\n \"aria-valuetext\": `${displayValue}%${band ? `, ${band.label}` : \"\"}`,\n };\n\n return (\n <figure\n ref={refs}\n {...props}\n data-slot=\"gauge\"\n data-tone={activeTone}\n data-size={small ? size : undefined}\n data-missing={missing || undefined}\n className={cn(\"gauge\", className)}\n >\n <div data-slot=\"gauge-visual\" {...reading} className=\"gauge-visual\">\n <svg\n viewBox=\"0 0 100 90\"\n aria-hidden=\"true\"\n focusable=\"false\"\n className=\"block size-full overflow-visible\"\n >\n <path d={TRACK} className=\"gauge-track\" />\n <path ref={ring} className=\"gauge-fill\" style={{ opacity: 0 }} />\n </svg>\n <div aria-hidden=\"true\" className=\"gauge-readout\">\n <span className=\"gauge-number\">\n <span ref={digits} className=\"gauge-digits\" />\n {small || missing ? null : <span className=\"gauge-unit\">%</span>}\n <span ref={sizer} className=\"gauge-sizer\">\n {missing ? \"–\" : displayValue}\n </span>\n </span>\n {!small && (thresholds || missing) ? (\n <span className=\"gauge-status\">\n <SwapText\n swapKey={missing ? missingLabel : filled ? (shown?.label ?? \"\") : \"\"}\n dir={moved.direction}\n className=\"block\"\n >\n {missing ? missingLabel : shown?.label}\n </SwapText>\n </span>\n ) : null}\n </div>\n </div>\n <figcaption className={small ? \"sr-only\" : \"grid min-w-0 gap-0.5\"}>\n <strong className=\"text-sm font-medium text-foreground\">\n <SwapText swapKey={label} className=\"block\">\n {label}\n </SwapText>\n </strong>\n {detail ? (\n <span className=\"text-xs tabular-nums text-text-secondary\">\n <SwapText swapKey={detail} dir={moved.direction} className=\"block\">\n {detail}\n </SwapText>\n </span>\n ) : null}\n </figcaption>\n </figure>\n );\n});\n"],"mappings":"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"}
|
package/dist/gauge/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Gauge, GaugeProps, GaugeThreshold, GaugeTone } from "./gauge.js";
|
|
2
|
-
export { Gauge, type GaugeProps, type GaugeThreshold, type GaugeTone };
|
|
1
|
+
import { Gauge, GaugeProps, GaugeSize, GaugeThreshold, GaugeTone } from "./gauge.js";
|
|
2
|
+
export { Gauge, type GaugeProps, type GaugeSize, type GaugeThreshold, type GaugeTone };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,11 +4,12 @@ import { ActionButton, ActionButtonProps } from "./action-button/action-button.j
|
|
|
4
4
|
import { ActivityDay, ActivityDayDetail, ActivityHeatmap, ActivityHeatmapProps } from "./activity-heatmap/activity-heatmap.js";
|
|
5
5
|
import { Dialog, DialogFooter, DialogFooterProps, DialogProps, DialogTrigger, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants } from "./dialog/dialog.js";
|
|
6
6
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogProps } from "./alert-dialog/alert-dialog.js";
|
|
7
|
-
import { Alert, AlertProps, alertVariants } from "./alert/alert.js";
|
|
7
|
+
import { Alert, AlertDestructiveIcon as DestructiveGlyph, AlertInfoIcon as InfoGlyph, AlertProps, AlertStatusIconProps as StatusIconProps, AlertSuccessIcon as SuccessGlyph, AlertWarningIcon as WarningGlyph, alertIconVariants, alertVariants } from "./alert/alert.js";
|
|
8
8
|
import { AnimatedCounter, AnimatedCounterProps } from "./animated-counter/animated-counter.js";
|
|
9
9
|
import { Announcement, AnnouncementAction, AnnouncementBar, AnnouncementBarProps, clearAnnouncementDismissal } from "./announcement-bar/announcement-bar.js";
|
|
10
10
|
import { Avatar, AvatarProps, avatarVariants } from "./avatar/avatar.js";
|
|
11
11
|
import { Badge, BadgeProps, badgeVariants } from "./badge/badge.js";
|
|
12
|
+
import { BarChartSeries, BarChartSeriesDatum, BarChartSeriesProps } from "./bar-chart/bar-chart-series.js";
|
|
12
13
|
import { BarChart, BarChartDatum, BarChartProps } from "./bar-chart/bar-chart.js";
|
|
13
14
|
import { BreadcrumbItem, BreadcrumbItemProps, Breadcrumbs, BreadcrumbsProps, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbsVariants } from "./breadcrumb/breadcrumb.js";
|
|
14
15
|
import { BrushChart, BrushChartAnnotation, BrushChartDatum, BrushChartProps } from "./brush-chart/brush-chart.js";
|
|
@@ -18,15 +19,15 @@ import { CardDecision, CardStack, CardStackProps } from "./card-stack/card-stack
|
|
|
18
19
|
import { Card, CardContent, CardContentProps, CardDescription, CardDescriptionProps, CardFooter, CardFooterProps, CardHeader, CardHeaderProps, CardProps, CardTitle, CardTitleProps, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardVariants } from "./card/card.js";
|
|
19
20
|
import { Carousel, CarouselProps } from "./carousel/carousel.js";
|
|
20
21
|
import { Checkbox, CheckboxProps, checkboxBoxVariants, checkboxVariants } from "./checkbox/checkbox.js";
|
|
21
|
-
import { ChipGroup, ChipGroupProps, ChipOption } from "./chip-group/chip-group.js";
|
|
22
|
+
import { ChipAttrs, ChipGroup, ChipGroupProps, ChipOption } from "./chip-group/chip-group.js";
|
|
22
23
|
import { ConfirmMorph, ConfirmMorphMode, ConfirmMorphProps, ConfirmMorphState } from "./confirm-morph/confirm-morph.js";
|
|
23
24
|
import { CopyButton, CopyButtonProps } from "./copy-button/copy-button.js";
|
|
24
25
|
import { Countdown, CountdownProps, CountdownUnit } from "./countdown/countdown.js";
|
|
25
26
|
import { datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants } from "./date-picker/picker-parts.js";
|
|
26
27
|
import { DateRangePicker, DateRangePickerMessages, DateRangePickerProps, DateRangePickerValue, DateRangePreset, defaultDateRangePresets } from "./date-picker/date-range-picker.js";
|
|
27
28
|
import { DatePicker, DatePickerProps } from "./date-picker/date-picker.js";
|
|
28
|
-
import { DonutChart, DonutChartDatum, DonutChartProps } from "./donut-chart/donut-chart.js";
|
|
29
|
-
import { EmptyState, EmptyStateProps, emptyStateActionVariants, emptyStateTextVariants, emptyStateVariants } from "./empty-state/empty-state.js";
|
|
29
|
+
import { DonutChart, DonutChartCenter, DonutChartDatum, DonutChartProps } from "./donut-chart/donut-chart.js";
|
|
30
|
+
import { EmptyState, EmptyStateProps, emptyStateActionVariants, emptyStateImageVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants } from "./empty-state/empty-state.js";
|
|
30
31
|
import { ExpandingButtonGroup, ExpandingButtonGroupItem, ExpandingButtonGroupProps, ExpandingButtonGroupSize, ExpandingButtonGroupTone } from "./expanding-button-group/expanding-button-group.js";
|
|
31
32
|
import { FileDropZone, FileDropZoneProps, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants } from "./file-drop-zone/file-drop-zone.js";
|
|
32
33
|
import { FilterBar, FilterBarCustomField, FilterBarField, FilterBarOption, FilterBarProps, FilterBarSelectField, filterBarChipVariants, filterBarRowVariants, filterBarVariants } from "./filter-bar/filter-bar.js";
|
|
@@ -37,12 +38,12 @@ import { InViewTitle, InViewTitleProps, InViewTitleVariant } from "./in-view-tit
|
|
|
37
38
|
import { Input, InputProps, inputVariants } from "./input/input.js";
|
|
38
39
|
import { Label, LabelProps, labelVariants } from "./label/label.js";
|
|
39
40
|
import { cn, cnAll } from "./lib/cn.js";
|
|
40
|
-
import { LINE_CHART_DRAW_MS, LineChart, LineChartDatum, LineChartProps, LineChartSeries } from "./line-chart/line-chart.js";
|
|
41
|
+
import { LINE_CHART_DRAW_MS, LineChart, LineChartBand, LineChartDatum, LineChartMarker, LineChartProps, LineChartReference, LineChartSeries, LineChartTone, LineChartTooltipContext } from "./line-chart/line-chart.js";
|
|
41
42
|
import { Mention, MentionChannel, MentionInput, MentionInputHandle, MentionInputProps, MentionKind, MentionPerson, MentionValue, mentionText, serializeMentions } from "./mention-input/mention-input.js";
|
|
42
43
|
import { Menu, MenuItem, MenuItemProps, MenuProps, MenuSeparator, MenuTrigger, menuItemVariants, menuPopoverVariants, menuSeparatorVariants, menuVariants } from "./menu/menu.js";
|
|
43
|
-
import { MoneyInput, MoneyInputDetails, MoneyInputProps } from "./money-input/money-input.js";
|
|
44
|
+
import { MoneyInput, MoneyInputDetails, MoneyInputProps, MoneyInputSize } from "./money-input/money-input.js";
|
|
44
45
|
import { MorphSelect, MorphSelectGroup, MorphSelectItem, MorphSelectOption, MorphSelectProps } from "./morph-select/morph-select.js";
|
|
45
|
-
import { MultiSelect, MultiSelectProps } from "./multi-select/multi-select.js";
|
|
46
|
+
import { MultiSelect, MultiSelectGroup, MultiSelectGroupProps, MultiSelectProps, multiSelectGroupHeaderVariants, multiSelectGroupVariants } from "./multi-select/multi-select.js";
|
|
46
47
|
import { NumberField, NumberFieldProps } from "./number-field/number-field.js";
|
|
47
48
|
import { OnboardingChecklist, OnboardingChecklistProps, OnboardingStep } from "./onboarding-checklist/onboarding-checklist.js";
|
|
48
49
|
import { PageHeader, PageHeaderProps, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants } from "./page-header/page-header.js";
|
|
@@ -50,9 +51,9 @@ import { PasswordField, PasswordFieldMessages, PasswordFieldProps, defaultPasswo
|
|
|
50
51
|
import { EstimateStrengthOptions, PasswordRule, PasswordRuleLabels, PasswordRuleOptions, PasswordStrength, PasswordStrengthLevels, PasswordStrengthMessages, PasswordStrengthMessagesInput, PasswordStrengthProps, PasswordStrengthResult, countCodePoints, createPasswordRules, defaultPasswordRules, defaultPasswordStrengthMessages, estimateStrength } from "./password-strength/password-strength.js";
|
|
51
52
|
import { PHONE_COUNTRIES, PhoneCountry, PhoneStatus, formatNational, formatPhoneNumber, parsePhoneNumber } from "./phone-input/phone-countries.js";
|
|
52
53
|
import { PhoneInput, PhoneInputDetails, PhoneInputProps } from "./phone-input/phone-input.js";
|
|
53
|
-
import { Popover, PopoverProps, PopoverTrigger, popoverVariants } from "./popover/popover.js";
|
|
54
|
-
import { Progress, ProgressProps, progressFillVariants, progressTrackVariants, progressVariants } from "./progress/progress.js";
|
|
55
|
-
import { Radio, RadioGroup, RadioGroupProps, RadioProps, radioGroupVariants, radioVariants } from "./radio-group/radio-group.js";
|
|
54
|
+
import { Popover, PopoverHoverTrigger, PopoverHoverTriggerProps, PopoverProps, PopoverTrigger, popoverVariants } from "./popover/popover.js";
|
|
55
|
+
import { Progress, ProgressProps, progressFillVariants, progressTargetVariants, progressTrackVariants, progressVariants } from "./progress/progress.js";
|
|
56
|
+
import { Radio, RadioGroup, RadioGroupProps, RadioGroupVariant, RadioProps, radioCardVariants, radioGroupVariants, radioVariants } from "./radio-group/radio-group.js";
|
|
56
57
|
import { Reaction, ReactionOption, Reactions, ReactionsProps } from "./reactions/reactions.js";
|
|
57
58
|
import { Ridgeline, RidgelineProps, RidgelineSeries } from "./ridgeline/ridgeline.js";
|
|
58
59
|
import { ScrollArea, ScrollAreaProps, scrollAreaRootVariants, scrollAreaVariants } from "./scroll-area/scroll-area.js";
|
|
@@ -74,13 +75,13 @@ import { Spinner, SpinnerProps, spinnerVariants } from "./spinner/spinner.js";
|
|
|
74
75
|
import { SplitBar, SplitBarProps, SplitSegment } from "./split-bar/split-bar.js";
|
|
75
76
|
import { SplitButton, SplitButtonAction, SplitButtonProps } from "./split-button/split-button.js";
|
|
76
77
|
import { SPARKLINE_DRAW_MS, Sparkline, SparklineProps, SparklineTone, sparklineVariants } from "./sparkline/sparkline.js";
|
|
77
|
-
import { StatCard, StatCardProps, StatCardTone, statCardHeaderVariants, statCardLabelVariants, statCardSubVariants, statCardValueVariants, statCardVariants } from "./stat-card/stat-card.js";
|
|
78
|
+
import { StatCard, StatCardChangeTone, StatCardProps, StatCardTone, StatCardTrend, statCardHeaderVariants, statCardIconVariants, statCardLabelVariants, statCardSkeletonVariants, statCardSubVariants, statCardValueVariants, statCardVariants } from "./stat-card/stat-card.js";
|
|
78
79
|
import { Stepper, StepperOrientation, StepperProps, StepperStatus, StepperStep } from "./stepper/stepper.js";
|
|
79
80
|
import { Streamgraph, StreamgraphDatum, StreamgraphProps, StreamgraphSeries } from "./streamgraph/streamgraph.js";
|
|
80
81
|
import { SwipeAction, SwipeActions, SwipeActionsProps, SwipeActionsRow, SwipeActionsRowProps } from "./swipe-actions/swipe-actions.js";
|
|
81
82
|
import "./swipe-actions/index.js";
|
|
82
83
|
import { Switch, SwitchProps, switchThumbVariants, switchTrackVariants } from "./switch/switch.js";
|
|
83
|
-
import { Column, RowKey, Table, TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableFooterVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableVariants } from "./table/table.js";
|
|
84
|
+
import { Column, RowKey, Table, TableProps, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableVariants } from "./table/table.js";
|
|
84
85
|
import { Tab, TabList, TabListProps, TabPanel, TabPanelProps, TabProps, Tabs, TabsProps, tabListVariants, tabPanelVariants, tabVariants, tabsVariants } from "./tabs/tabs.js";
|
|
85
86
|
import { TextShimmer, TextShimmerProps } from "./text-shimmer/text-shimmer.js";
|
|
86
87
|
import { TagInput, TagInputProps } from "./tag-input/tag-input.js";
|
|
@@ -92,6 +93,6 @@ import { TimePicker, TimePickerProps, timePickerItemVariants, timePickerListVari
|
|
|
92
93
|
import { ToastContent, ToastRegion, ToastRegionProps, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants } from "./toast/toast.js";
|
|
93
94
|
import { Tooltip, TooltipProps, TooltipTrigger, TooltipTriggerProps, tooltipVariants } from "./tooltip/tooltip.js";
|
|
94
95
|
import { Treemap, TreemapNode, TreemapProps } from "./treemap/treemap.js";
|
|
95
|
-
import { UsageMeter, UsageMeterProps, UsageMeterSegment } from "./usage-meter/usage-meter.js";
|
|
96
|
+
import { UsageMeter, UsageMeterProps, UsageMeterSegment, UsageMeterStatus } from "./usage-meter/usage-meter.js";
|
|
96
97
|
import { WaffleCategory, WaffleChart, WaffleChartProps } from "./waffle-chart/waffle-chart.js";
|
|
97
|
-
export { Accordion, AccordionItem, type AccordionItemProps, AccordionPanel, type AccordionPanelProps, type AccordionProps, AccordionTrigger, type AccordionTriggerProps, ActionButton, type ActionButtonProps, type ActivityDay, type ActivityDayDetail, ActivityHeatmap, type ActivityHeatmapProps, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, type AlertDialogProps, type AlertProps, AnimatedCounter, type AnimatedCounterProps, type Announcement, type AnnouncementAction, AnnouncementBar, type AnnouncementBarProps, Avatar, type AvatarProps, Badge, type BadgeProps, BarChart, type BarChartDatum, type BarChartProps, BellIcon, BreadcrumbItem, type BreadcrumbItemProps, Breadcrumbs, type BreadcrumbsProps, BrushChart, type BrushChartAnnotation, type BrushChartDatum, type BrushChartProps, Button, ButtonGroup, type ButtonGroupItem, type ButtonGroupMenu, type ButtonGroupMenuItem, type ButtonGroupOrientation, type ButtonGroupProps, type ButtonGroupSize, type ButtonGroupVariant, type ButtonProps, Calendar, type CalendarProps, CalendarRange, type CalendarRangeProps, Card, CardContent, type CardContentProps, type CardDecision, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardStack, type CardStackProps, CardTitle, type CardTitleProps, Carousel, type CarouselProps, Checkbox, type CheckboxProps, ChevronIcon, type ChevronIconProps, ChipGroup, type ChipGroupProps, type ChipOption, type Column, ConfirmMorph, type ConfirmMorphMode, type ConfirmMorphProps, type ConfirmMorphState, CopyButton, type CopyButtonProps, CopyCheckIcon, Countdown, type CountdownProps, type CountdownUnit, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerMessages, type DateRangePickerProps, type DateRangePickerValue, type DateRangePreset, Dialog, DialogFooter, type DialogFooterProps, type DialogProps, DialogTrigger, DonutChart, type DonutChartDatum, type DonutChartProps, EmptyState, type EmptyStateProps, type EstimateStrengthOptions, ExpandingButtonGroup, type ExpandingButtonGroupItem, type ExpandingButtonGroupProps, type ExpandingButtonGroupSize, type ExpandingButtonGroupTone, FileDropZone, type FileDropZoneProps, FilterBar, type FilterBarCustomField, type FilterBarField, type FilterBarOption, type FilterBarProps, type FilterBarSelectField, FloatingButtonGroup, type FloatingButtonGroupAction, type FloatingButtonGroupItem, type FloatingButtonGroupOrientation, type FloatingButtonGroupProps, type FloatingButtonGroupSeparator, type FloatingButtonGroupSize, type FloatingButtonGroupVariant, Gauge, type GaugeProps, type GaugeThreshold, type GaugeTone, HeartIcon, IconMorph, type IconMorphIconProps, type IconMorphName, type IconMorphProps, InViewTitle, type InViewTitleProps, type InViewTitleVariant, Input, type InputProps, LINE_CHART_DRAW_MS, Label, type LabelProps, LineChart, type LineChartDatum, type LineChartProps, type LineChartSeries, type Mention, type MentionChannel, MentionInput, type MentionInputHandle, type MentionInputProps, type MentionKind, type MentionPerson, type MentionValue, Menu, MenuIcon, MenuItem, type MenuItemProps, type MenuProps, MenuSeparator, MenuTrigger, MoneyInput, type MoneyInputDetails, type MoneyInputProps, MorphSelect, type MorphSelectGroup, type MorphSelectItem, type MorphSelectOption, type MorphSelectProps, MultiSelect, type MultiSelectProps, NumberField, type NumberFieldProps, OnboardingChecklist, type OnboardingChecklistProps, type OnboardingStep, PHONE_COUNTRIES, PageHeader, type PageHeaderProps, PasswordField, type PasswordFieldMessages, type PasswordFieldProps, type PasswordRule, type PasswordRuleLabels, type PasswordRuleOptions, PasswordStrength, type PasswordStrengthLevels, type PasswordStrengthMessages, type PasswordStrengthMessagesInput, type PasswordStrengthProps, type PasswordStrengthResult, type PhoneCountry, PhoneInput, type PhoneInputDetails, type PhoneInputProps, type PhoneStatus, type Platform, PlayPauseIcon, PlusCheckIcon, Popover, type PopoverProps, PopoverTrigger, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type Reaction, type ReactionOption, Reactions, type ReactionsProps, Ridgeline, type RidgelineProps, type RidgelineSeries, type RowKey, SPARKLINE_DRAW_MS, ScrollArea, type ScrollAreaProps, ScrubInput, type ScrubInputChangeDetails, type ScrubInputProps, type ScrubInputSource, SearchField, type SearchFieldProps, Select, SelectItem, type SelectItemProps, type SelectProps, Separator, type SeparatorProps, Sheet, type SheetProps, type ShortcutBinding, ShortcutKbd, type ShortcutKbdProps, ShortcutKeys, type ShortcutKeysProps, ShortcutRecorder, type ShortcutRecorderProps, type ShortcutToken, SideNav, type SideNavGroup, type SideNavProps, type SideNavSection, Skeleton, type SkeletonProps, Slider, type SliderMark, type SliderProps, type SliderValue, SlopeChart, type SlopeChartProps, type SlopeItem, Sparkline, type SparklineProps, type SparklineTone, Spinner, type SpinnerProps, SplitBar, type SplitBarProps, SplitButton, type SplitButtonAction, type SplitButtonProps, type SplitSegment, StatCard, type StatCardProps, type StatCardTone, Stepper, type StepperOrientation, type StepperProps, type StepperStatus, type StepperStep, Streamgraph, type StreamgraphDatum, type StreamgraphProps, type StreamgraphSeries, SunMoonIcon, type SwipeAction, SwipeActions, type SwipeActionsProps, SwipeActionsRow, type SwipeActionsRowProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, type TableProps, Tabs, type TabsProps, TagInput, type TagInputProps, TextMorph, type TextMorphProps, TextReveal, type TextRevealProps, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, type Theme, ThemeSwitch, type ThemeSwitchProps, type ThemeSwitchVariant, TimePicker, type TimePickerProps, type ToastContent, ToastRegion, type ToastRegionProps, Tooltip, type TooltipProps, TooltipTrigger, type TooltipTriggerProps, Treemap, type TreemapNode, type TreemapProps, UsageMeter, type UsageMeterProps, type UsageMeterSegment, type WaffleCategory, WaffleChart, type WaffleChartProps, alertVariants, avatarVariants, badgeVariants, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbsVariants, buttonVariants, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarVariants, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardVariants, checkboxBoxVariants, checkboxVariants, clearAnnouncementDismissal, cn, cnAll, countCodePoints, createColumns, createPasswordRules, datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants, defaultDateRangePresets, defaultPasswordFieldMessages, defaultPasswordRules, defaultPasswordStrengthMessages, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants, emptyStateActionVariants, emptyStateTextVariants, emptyStateVariants, estimateStrength, evaluateScrubExpression, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants, filterBarChipVariants, filterBarRowVariants, filterBarVariants, formatNational, formatPhoneNumber, formatShortcut, inputVariants, labelVariants, matchesShortcut, mentionText, menuItemVariants, menuPopoverVariants, menuSeparatorVariants, menuVariants, normalizeShortcut, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants, parsePhoneNumber, popoverVariants, progressFillVariants, progressTrackVariants, progressVariants, radioGroupVariants, radioVariants, scrollAreaRootVariants, scrollAreaVariants, selectItemVariants, selectPopoverVariants, selectTriggerVariants, selectVariants, separatorVariants, serializeMentions, sheetOverlayVariants, sheetPanelVariants, shortcutFromEvent, shortcutTokens, sideNavHeaderVariants, sideNavItemVariants, sideNavMenuVariants, sideNavVariants, skeletonVariants, sliderBarVariants, sliderFillVariants, sliderThumbVariants, sliderTrackVariants, sliderVariants, sparklineVariants, spinnerVariants, statCardHeaderVariants, statCardLabelVariants, statCardSubVariants, statCardValueVariants, statCardVariants, switchThumbVariants, switchTrackVariants, tabListVariants, tabPanelVariants, tabVariants, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableFooterVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableVariants, tabsVariants, textareaVariants, timePickerItemVariants, timePickerListVariants, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants, tooltipVariants, usePlatform, usePressedKeys };
|
|
98
|
+
export { Accordion, AccordionItem, type AccordionItemProps, AccordionPanel, type AccordionPanelProps, type AccordionProps, AccordionTrigger, type AccordionTriggerProps, ActionButton, type ActionButtonProps, type ActivityDay, type ActivityDayDetail, ActivityHeatmap, type ActivityHeatmapProps, Alert, DestructiveGlyph as AlertDestructiveIcon, AlertDialog, AlertDialogAction, AlertDialogCancel, type AlertDialogProps, InfoGlyph as AlertInfoIcon, type AlertProps, type StatusIconProps as AlertStatusIconProps, SuccessGlyph as AlertSuccessIcon, WarningGlyph as AlertWarningIcon, AnimatedCounter, type AnimatedCounterProps, type Announcement, type AnnouncementAction, AnnouncementBar, type AnnouncementBarProps, Avatar, type AvatarProps, Badge, type BadgeProps, BarChart, type BarChartDatum, type BarChartProps, type BarChartSeries, type BarChartSeriesDatum, type BarChartSeriesProps, BellIcon, BreadcrumbItem, type BreadcrumbItemProps, Breadcrumbs, type BreadcrumbsProps, BrushChart, type BrushChartAnnotation, type BrushChartDatum, type BrushChartProps, Button, ButtonGroup, type ButtonGroupItem, type ButtonGroupMenu, type ButtonGroupMenuItem, type ButtonGroupOrientation, type ButtonGroupProps, type ButtonGroupSize, type ButtonGroupVariant, type ButtonProps, Calendar, type CalendarProps, CalendarRange, type CalendarRangeProps, Card, CardContent, type CardContentProps, type CardDecision, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardStack, type CardStackProps, CardTitle, type CardTitleProps, Carousel, type CarouselProps, Checkbox, type CheckboxProps, ChevronIcon, type ChevronIconProps, type ChipAttrs, ChipGroup, type ChipGroupProps, type ChipOption, type Column, ConfirmMorph, type ConfirmMorphMode, type ConfirmMorphProps, type ConfirmMorphState, CopyButton, type CopyButtonProps, CopyCheckIcon, Countdown, type CountdownProps, type CountdownUnit, DatePicker, type DatePickerProps, DateRangePicker, type DateRangePickerMessages, type DateRangePickerProps, type DateRangePickerValue, type DateRangePreset, Dialog, DialogFooter, type DialogFooterProps, type DialogProps, DialogTrigger, DonutChart, type DonutChartCenter, type DonutChartDatum, type DonutChartProps, EmptyState, type EmptyStateProps, type EstimateStrengthOptions, ExpandingButtonGroup, type ExpandingButtonGroupItem, type ExpandingButtonGroupProps, type ExpandingButtonGroupSize, type ExpandingButtonGroupTone, FileDropZone, type FileDropZoneProps, FilterBar, type FilterBarCustomField, type FilterBarField, type FilterBarOption, type FilterBarProps, type FilterBarSelectField, FloatingButtonGroup, type FloatingButtonGroupAction, type FloatingButtonGroupItem, type FloatingButtonGroupOrientation, type FloatingButtonGroupProps, type FloatingButtonGroupSeparator, type FloatingButtonGroupSize, type FloatingButtonGroupVariant, Gauge, type GaugeProps, type GaugeThreshold, type GaugeTone, HeartIcon, IconMorph, type IconMorphIconProps, type IconMorphName, type IconMorphProps, InViewTitle, type InViewTitleProps, type InViewTitleVariant, Input, type InputProps, LINE_CHART_DRAW_MS, Label, type LabelProps, LineChart, type LineChartBand, type LineChartDatum, type LineChartMarker, type LineChartProps, type LineChartReference, type LineChartSeries, type LineChartTone, type LineChartTooltipContext, type Mention, type MentionChannel, MentionInput, type MentionInputHandle, type MentionInputProps, type MentionKind, type MentionPerson, type MentionValue, Menu, MenuIcon, MenuItem, type MenuItemProps, type MenuProps, MenuSeparator, MenuTrigger, MoneyInput, type MoneyInputDetails, type MoneyInputProps, type MoneyInputSize, MorphSelect, type MorphSelectGroup, type MorphSelectItem, type MorphSelectOption, type MorphSelectProps, MultiSelect, MultiSelectGroup, type MultiSelectGroupProps, type MultiSelectProps, NumberField, type NumberFieldProps, OnboardingChecklist, type OnboardingChecklistProps, type OnboardingStep, PHONE_COUNTRIES, PageHeader, type PageHeaderProps, PasswordField, type PasswordFieldMessages, type PasswordFieldProps, type PasswordRule, type PasswordRuleLabels, type PasswordRuleOptions, PasswordStrength, type PasswordStrengthLevels, type PasswordStrengthMessages, type PasswordStrengthMessagesInput, type PasswordStrengthProps, type PasswordStrengthResult, type PhoneCountry, PhoneInput, type PhoneInputDetails, type PhoneInputProps, type PhoneStatus, type Platform, PlayPauseIcon, PlusCheckIcon, Popover, PopoverHoverTrigger, type PopoverHoverTriggerProps, type PopoverProps, PopoverTrigger, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioGroupVariant, type RadioProps, type Reaction, type ReactionOption, Reactions, type ReactionsProps, Ridgeline, type RidgelineProps, type RidgelineSeries, type RowKey, SPARKLINE_DRAW_MS, ScrollArea, type ScrollAreaProps, ScrubInput, type ScrubInputChangeDetails, type ScrubInputProps, type ScrubInputSource, SearchField, type SearchFieldProps, Select, SelectItem, type SelectItemProps, type SelectProps, Separator, type SeparatorProps, Sheet, type SheetProps, type ShortcutBinding, ShortcutKbd, type ShortcutKbdProps, ShortcutKeys, type ShortcutKeysProps, ShortcutRecorder, type ShortcutRecorderProps, type ShortcutToken, SideNav, type SideNavGroup, type SideNavProps, type SideNavSection, Skeleton, type SkeletonProps, Slider, type SliderMark, type SliderProps, type SliderValue, SlopeChart, type SlopeChartProps, type SlopeItem, Sparkline, type SparklineProps, type SparklineTone, Spinner, type SpinnerProps, SplitBar, type SplitBarProps, SplitButton, type SplitButtonAction, type SplitButtonProps, type SplitSegment, StatCard, type StatCardChangeTone, type StatCardProps, type StatCardTone, type StatCardTrend, Stepper, type StepperOrientation, type StepperProps, type StepperStatus, type StepperStep, Streamgraph, type StreamgraphDatum, type StreamgraphProps, type StreamgraphSeries, SunMoonIcon, type SwipeAction, SwipeActions, type SwipeActionsProps, SwipeActionsRow, type SwipeActionsRowProps, Switch, type SwitchProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, type TableProps, Tabs, type TabsProps, TagInput, type TagInputProps, TextMorph, type TextMorphProps, TextReveal, type TextRevealProps, TextShimmer, type TextShimmerProps, Textarea, type TextareaProps, type Theme, ThemeSwitch, type ThemeSwitchProps, type ThemeSwitchVariant, TimePicker, type TimePickerProps, type ToastContent, ToastRegion, type ToastRegionProps, Tooltip, type TooltipProps, TooltipTrigger, type TooltipTriggerProps, Treemap, type TreemapNode, type TreemapProps, UsageMeter, type UsageMeterProps, type UsageMeterSegment, type UsageMeterStatus, type WaffleCategory, WaffleChart, type WaffleChartProps, alertIconVariants, alertVariants, avatarVariants, badgeVariants, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbsVariants, buttonVariants, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarVariants, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardVariants, checkboxBoxVariants, checkboxVariants, clearAnnouncementDismissal, cn, cnAll, countCodePoints, createColumns, createPasswordRules, datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants, defaultDateRangePresets, defaultPasswordFieldMessages, defaultPasswordRules, defaultPasswordStrengthMessages, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants, emptyStateActionVariants, emptyStateImageVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants, estimateStrength, evaluateScrubExpression, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants, filterBarChipVariants, filterBarRowVariants, filterBarVariants, formatNational, formatPhoneNumber, formatShortcut, inputVariants, labelVariants, matchesShortcut, mentionText, menuItemVariants, menuPopoverVariants, menuSeparatorVariants, menuVariants, multiSelectGroupHeaderVariants, multiSelectGroupVariants, normalizeShortcut, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants, parsePhoneNumber, popoverVariants, progressFillVariants, progressTargetVariants, progressTrackVariants, progressVariants, radioCardVariants, radioGroupVariants, radioVariants, scrollAreaRootVariants, scrollAreaVariants, selectItemVariants, selectPopoverVariants, selectTriggerVariants, selectVariants, separatorVariants, serializeMentions, sheetOverlayVariants, sheetPanelVariants, shortcutFromEvent, shortcutTokens, sideNavHeaderVariants, sideNavItemVariants, sideNavMenuVariants, sideNavVariants, skeletonVariants, sliderBarVariants, sliderFillVariants, sliderThumbVariants, sliderTrackVariants, sliderVariants, sparklineVariants, spinnerVariants, statCardHeaderVariants, statCardIconVariants, statCardLabelVariants, statCardSkeletonVariants, statCardSubVariants, statCardValueVariants, statCardVariants, switchThumbVariants, switchTrackVariants, tabListVariants, tabPanelVariants, tabVariants, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableVariants, tabsVariants, textareaVariants, timePickerItemVariants, timePickerListVariants, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants, tooltipVariants, usePlatform, usePressedKeys };
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { ActivityHeatmap } from "./activity-heatmap/activity-heatmap.js";
|
|
|
7
7
|
import { Dialog, DialogFooter, DialogTrigger, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants } from "./dialog/dialog.js";
|
|
8
8
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel } from "./alert-dialog/alert-dialog.js";
|
|
9
9
|
import { AnimatedCounter } from "./animated-counter/animated-counter.js";
|
|
10
|
-
import { Alert, alertVariants } from "./alert/alert.js";
|
|
10
|
+
import { Alert, AlertDestructiveIcon as DestructiveGlyph, AlertInfoIcon as InfoGlyph, AlertSuccessIcon as SuccessGlyph, AlertWarningIcon as WarningGlyph, alertIconVariants, alertVariants } from "./alert/alert.js";
|
|
11
11
|
import { AnnouncementBar, clearAnnouncementDismissal } from "./announcement-bar/announcement-bar.js";
|
|
12
12
|
import { Avatar, avatarVariants } from "./avatar/avatar.js";
|
|
13
13
|
import { Badge, badgeVariants } from "./badge/badge.js";
|
|
@@ -25,12 +25,12 @@ import { ChipGroup } from "./chip-group/chip-group.js";
|
|
|
25
25
|
import { ConfirmMorph } from "./confirm-morph/confirm-morph.js";
|
|
26
26
|
import { CopyButton } from "./copy-button/copy-button.js";
|
|
27
27
|
import { Countdown } from "./countdown/countdown.js";
|
|
28
|
-
import { Popover, PopoverTrigger, popoverVariants } from "./popover/popover.js";
|
|
28
|
+
import { Popover, PopoverHoverTrigger, PopoverTrigger, popoverVariants } from "./popover/popover.js";
|
|
29
29
|
import { datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants } from "./date-picker/picker-parts.js";
|
|
30
30
|
import { DateRangePicker, defaultDateRangePresets } from "./date-picker/date-range-picker.js";
|
|
31
31
|
import { DatePicker } from "./date-picker/date-picker.js";
|
|
32
32
|
import { DonutChart } from "./donut-chart/donut-chart.js";
|
|
33
|
-
import { EmptyState, emptyStateActionVariants, emptyStateTextVariants, emptyStateVariants } from "./empty-state/empty-state.js";
|
|
33
|
+
import { EmptyState, emptyStateActionVariants, emptyStateImageVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants } from "./empty-state/empty-state.js";
|
|
34
34
|
import { ExpandingButtonGroup } from "./expanding-button-group/expanding-button-group.js";
|
|
35
35
|
import { FileDropZone, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants } from "./file-drop-zone/file-drop-zone.js";
|
|
36
36
|
import { FilterBar, filterBarChipVariants, filterBarRowVariants, filterBarVariants } from "./filter-bar/filter-bar.js";
|
|
@@ -46,7 +46,7 @@ import { MentionInput, mentionText, serializeMentions } from "./mention-input/me
|
|
|
46
46
|
import { Select, SelectItem, selectItemVariants, selectPopoverVariants, selectTriggerVariants, selectVariants } from "./select/select.js";
|
|
47
47
|
import { MoneyInput } from "./money-input/money-input.js";
|
|
48
48
|
import { MorphSelect } from "./morph-select/morph-select.js";
|
|
49
|
-
import { MultiSelect } from "./multi-select/multi-select.js";
|
|
49
|
+
import { MultiSelect, MultiSelectGroup, multiSelectGroupHeaderVariants, multiSelectGroupVariants } from "./multi-select/multi-select.js";
|
|
50
50
|
import { NumberField } from "./number-field/number-field.js";
|
|
51
51
|
import { OnboardingChecklist } from "./onboarding-checklist/onboarding-checklist.js";
|
|
52
52
|
import { PageHeader, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants } from "./page-header/page-header.js";
|
|
@@ -55,8 +55,8 @@ import { PasswordStrength, countCodePoints, createPasswordRules, defaultPassword
|
|
|
55
55
|
import { ScrollArea, scrollAreaRootVariants, scrollAreaVariants } from "./scroll-area/scroll-area.js";
|
|
56
56
|
import { PHONE_COUNTRIES, formatNational, formatPhoneNumber, parsePhoneNumber } from "./phone-input/phone-countries.js";
|
|
57
57
|
import { PhoneInput } from "./phone-input/phone-input.js";
|
|
58
|
-
import { Progress, progressFillVariants, progressTrackVariants, progressVariants } from "./progress/progress.js";
|
|
59
|
-
import { Radio, RadioGroup, radioGroupVariants, radioVariants } from "./radio-group/radio-group.js";
|
|
58
|
+
import { Progress, progressFillVariants, progressTargetVariants, progressTrackVariants, progressVariants } from "./progress/progress.js";
|
|
59
|
+
import { Radio, RadioGroup, radioCardVariants, radioGroupVariants, radioVariants } from "./radio-group/radio-group.js";
|
|
60
60
|
import { Reactions } from "./reactions/reactions.js";
|
|
61
61
|
import { Ridgeline } from "./ridgeline/ridgeline.js";
|
|
62
62
|
import { evaluateScrubExpression } from "./scrub-input/evaluate.js";
|
|
@@ -74,12 +74,12 @@ import { Spinner, spinnerVariants } from "./spinner/spinner.js";
|
|
|
74
74
|
import { SplitBar } from "./split-bar/split-bar.js";
|
|
75
75
|
import { SplitButton } from "./split-button/split-button.js";
|
|
76
76
|
import { SPARKLINE_DRAW_MS, Sparkline, sparklineVariants } from "./sparkline/sparkline.js";
|
|
77
|
-
import { StatCard, statCardHeaderVariants, statCardLabelVariants, statCardSubVariants, statCardValueVariants, statCardVariants } from "./stat-card/stat-card.js";
|
|
77
|
+
import { StatCard, statCardHeaderVariants, statCardIconVariants, statCardLabelVariants, statCardSkeletonVariants, statCardSubVariants, statCardValueVariants, statCardVariants } from "./stat-card/stat-card.js";
|
|
78
78
|
import { Stepper } from "./stepper/stepper.js";
|
|
79
79
|
import { Streamgraph } from "./streamgraph/streamgraph.js";
|
|
80
80
|
import { SwipeActions, SwipeActionsRow } from "./swipe-actions/swipe-actions.js";
|
|
81
81
|
import { Switch, switchThumbVariants, switchTrackVariants } from "./switch/switch.js";
|
|
82
|
-
import { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableFooterVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableVariants } from "./table/table.js";
|
|
82
|
+
import { Table, createColumns, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableVariants } from "./table/table.js";
|
|
83
83
|
import { TextShimmer } from "./text-shimmer/text-shimmer.js";
|
|
84
84
|
import { TagInput } from "./tag-input/tag-input.js";
|
|
85
85
|
import { TextMorph } from "./text-morph/text-morph.js";
|
|
@@ -91,4 +91,4 @@ import { ToastRegion, toast, toastCloseVariants, toastQueue, toastRegionVariants
|
|
|
91
91
|
import { Treemap } from "./treemap/treemap.js";
|
|
92
92
|
import { UsageMeter } from "./usage-meter/usage-meter.js";
|
|
93
93
|
import { WaffleChart } from "./waffle-chart/waffle-chart.js";
|
|
94
|
-
export { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, ActionButton, ActivityHeatmap, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AnimatedCounter, AnnouncementBar, Avatar, Badge, BarChart, BellIcon, BreadcrumbItem, Breadcrumbs, BrushChart, Button, ButtonGroup, Calendar, CalendarRange, Card, CardContent, CardDescription, CardFooter, CardHeader, CardStack, CardTitle, Carousel, Checkbox, ChevronIcon, ChipGroup, ConfirmMorph, CopyButton, CopyCheckIcon, Countdown, DatePicker, DateRangePicker, Dialog, DialogFooter, DialogTrigger, DonutChart, EmptyState, ExpandingButtonGroup, FileDropZone, FilterBar, FloatingButtonGroup, Gauge, HeartIcon, IconMorph, InViewTitle, Input, LINE_CHART_DRAW_MS, Label, LineChart, MentionInput, Menu, MenuIcon, MenuItem, MenuSeparator, MenuTrigger, MoneyInput, MorphSelect, MultiSelect, NumberField, OnboardingChecklist, PHONE_COUNTRIES, PageHeader, PasswordField, PasswordStrength, PhoneInput, PlayPauseIcon, PlusCheckIcon, Popover, PopoverTrigger, Progress, Radio, RadioGroup, Reactions, Ridgeline, SPARKLINE_DRAW_MS, ScrollArea, ScrubInput, SearchField, Select, SelectItem, Separator, Sheet, ShortcutKbd, ShortcutKeys, ShortcutRecorder, SideNav, Skeleton, Slider, SlopeChart, Sparkline, Spinner, SplitBar, SplitButton, StatCard, Stepper, Streamgraph, SunMoonIcon, SwipeActions, SwipeActionsRow, Switch, Tab, TabList, TabPanel, Table, Tabs, TagInput, TextMorph, TextReveal, TextShimmer, Textarea, ThemeSwitch, TimePicker, ToastRegion, Tooltip, TooltipTrigger, Treemap, UsageMeter, WaffleChart, alertVariants, avatarVariants, badgeVariants, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbsVariants, buttonVariants, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarVariants, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardVariants, checkboxBoxVariants, checkboxVariants, clearAnnouncementDismissal, cn, cnAll, countCodePoints, createColumns, createPasswordRules, datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants, defaultDateRangePresets, defaultPasswordFieldMessages, defaultPasswordRules, defaultPasswordStrengthMessages, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants, emptyStateActionVariants, emptyStateTextVariants, emptyStateVariants, estimateStrength, evaluateScrubExpression, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants, filterBarChipVariants, filterBarRowVariants, filterBarVariants, formatNational, formatPhoneNumber, formatShortcut, inputVariants, labelVariants, matchesShortcut, mentionText, menuItemVariants, menuPopoverVariants, menuSeparatorVariants, menuVariants, normalizeShortcut, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants, parsePhoneNumber, popoverVariants, progressFillVariants, progressTrackVariants, progressVariants, radioGroupVariants, radioVariants, scrollAreaRootVariants, scrollAreaVariants, selectItemVariants, selectPopoverVariants, selectTriggerVariants, selectVariants, separatorVariants, serializeMentions, sheetOverlayVariants, sheetPanelVariants, shortcutFromEvent, shortcutTokens, sideNavHeaderVariants, sideNavItemVariants, sideNavMenuVariants, sideNavVariants, skeletonVariants, sliderBarVariants, sliderFillVariants, sliderThumbVariants, sliderTrackVariants, sliderVariants, sparklineVariants, spinnerVariants, statCardHeaderVariants, statCardLabelVariants, statCardSubVariants, statCardValueVariants, statCardVariants, switchThumbVariants, switchTrackVariants, tabListVariants, tabPanelVariants, tabVariants, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableFooterVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableVariants, tabsVariants, textareaVariants, timePickerItemVariants, timePickerListVariants, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants, tooltipVariants, usePlatform, usePressedKeys };
|
|
94
|
+
export { Accordion, AccordionItem, AccordionPanel, AccordionTrigger, ActionButton, ActivityHeatmap, Alert, DestructiveGlyph as AlertDestructiveIcon, AlertDialog, AlertDialogAction, AlertDialogCancel, InfoGlyph as AlertInfoIcon, SuccessGlyph as AlertSuccessIcon, WarningGlyph as AlertWarningIcon, AnimatedCounter, AnnouncementBar, Avatar, Badge, BarChart, BellIcon, BreadcrumbItem, Breadcrumbs, BrushChart, Button, ButtonGroup, Calendar, CalendarRange, Card, CardContent, CardDescription, CardFooter, CardHeader, CardStack, CardTitle, Carousel, Checkbox, ChevronIcon, ChipGroup, ConfirmMorph, CopyButton, CopyCheckIcon, Countdown, DatePicker, DateRangePicker, Dialog, DialogFooter, DialogTrigger, DonutChart, EmptyState, ExpandingButtonGroup, FileDropZone, FilterBar, FloatingButtonGroup, Gauge, HeartIcon, IconMorph, InViewTitle, Input, LINE_CHART_DRAW_MS, Label, LineChart, MentionInput, Menu, MenuIcon, MenuItem, MenuSeparator, MenuTrigger, MoneyInput, MorphSelect, MultiSelect, MultiSelectGroup, NumberField, OnboardingChecklist, PHONE_COUNTRIES, PageHeader, PasswordField, PasswordStrength, PhoneInput, PlayPauseIcon, PlusCheckIcon, Popover, PopoverHoverTrigger, PopoverTrigger, Progress, Radio, RadioGroup, Reactions, Ridgeline, SPARKLINE_DRAW_MS, ScrollArea, ScrubInput, SearchField, Select, SelectItem, Separator, Sheet, ShortcutKbd, ShortcutKeys, ShortcutRecorder, SideNav, Skeleton, Slider, SlopeChart, Sparkline, Spinner, SplitBar, SplitButton, StatCard, Stepper, Streamgraph, SunMoonIcon, SwipeActions, SwipeActionsRow, Switch, Tab, TabList, TabPanel, Table, Tabs, TagInput, TextMorph, TextReveal, TextShimmer, Textarea, ThemeSwitch, TimePicker, ToastRegion, Tooltip, TooltipTrigger, Treemap, UsageMeter, WaffleChart, alertIconVariants, alertVariants, avatarVariants, badgeVariants, breadcrumbItemVariants, breadcrumbLinkVariants, breadcrumbsVariants, buttonVariants, calendarCellVariants, calendarClearVariants, calendarGridVariants, calendarHeaderCellVariants, calendarHeaderVariants, calendarHeadingVariants, calendarLabelVariants, calendarMonthsVariants, calendarNavVariants, calendarVariants, cardContentVariants, cardDescriptionVariants, cardFooterVariants, cardHeaderVariants, cardTitleVariants, cardVariants, checkboxBoxVariants, checkboxVariants, clearAnnouncementDismissal, cn, cnAll, countCodePoints, createColumns, createPasswordRules, datePickerInputVariants, datePickerLabelVariants, datePickerSegmentVariants, datePickerTriggerVariants, datePickerVariants, defaultDateRangePresets, defaultPasswordFieldMessages, defaultPasswordRules, defaultPasswordStrengthMessages, dialogDescriptionVariants, dialogFooterVariants, dialogOverlayVariants, dialogPanelVariants, dialogTitleVariants, emptyStateActionVariants, emptyStateImageVariants, emptyStateTextVariants, emptyStateTitleVariants, emptyStateVariants, estimateStrength, evaluateScrubExpression, fileDropZoneHintVariants, fileDropZonePromptVariants, fileDropZoneVariants, filterBarChipVariants, filterBarRowVariants, filterBarVariants, formatNational, formatPhoneNumber, formatShortcut, inputVariants, labelVariants, matchesShortcut, mentionText, menuItemVariants, menuPopoverVariants, menuSeparatorVariants, menuVariants, multiSelectGroupHeaderVariants, multiSelectGroupVariants, normalizeShortcut, pageHeaderActionsVariants, pageHeaderBackVariants, pageHeaderDescriptionVariants, pageHeaderMetaVariants, pageHeaderRowVariants, pageHeaderTitleVariants, pageHeaderVariants, parsePhoneNumber, popoverVariants, progressFillVariants, progressTargetVariants, progressTrackVariants, progressVariants, radioCardVariants, radioGroupVariants, radioVariants, scrollAreaRootVariants, scrollAreaVariants, selectItemVariants, selectPopoverVariants, selectTriggerVariants, selectVariants, separatorVariants, serializeMentions, sheetOverlayVariants, sheetPanelVariants, shortcutFromEvent, shortcutTokens, sideNavHeaderVariants, sideNavItemVariants, sideNavMenuVariants, sideNavVariants, skeletonVariants, sliderBarVariants, sliderFillVariants, sliderThumbVariants, sliderTrackVariants, sliderVariants, sparklineVariants, spinnerVariants, statCardHeaderVariants, statCardIconVariants, statCardLabelVariants, statCardSkeletonVariants, statCardSubVariants, statCardValueVariants, statCardVariants, switchThumbVariants, switchTrackVariants, tabListVariants, tabPanelVariants, tabVariants, tableCardVariants, tableCellVariants, tableColumnVariants, tableEmptyVariants, tableExpandButtonVariants, tableFooterVariants, tableGroupRowVariants, tableHeaderVariants, tablePaginationVariants, tableRowVariants, tableScrollVariants, tableSelectionBarVariants, tableSortButtonVariants, tableVariants, tabsVariants, textareaVariants, timePickerItemVariants, timePickerListVariants, toast, toastCloseVariants, toastQueue, toastRegionVariants, toastVariants, tooltipVariants, usePlatform, usePressedKeys };
|
package/dist/input/input.d.ts
CHANGED
|
@@ -95,6 +95,13 @@ interface InputProps$1 extends Omit<InputProps, "className" | "style" | "size">
|
|
|
95
95
|
* closes like `description`. An empty or `undefined` value closes the row.
|
|
96
96
|
*/
|
|
97
97
|
error?: string;
|
|
98
|
+
/**
|
|
99
|
+
* The field must be filled: the input is `required` (announced by screen
|
|
100
|
+
* readers, and checked by native form validation) and the label shows the
|
|
101
|
+
* required marker. The same prop as PasswordField's.
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
104
|
+
isRequired?: boolean;
|
|
98
105
|
}
|
|
99
106
|
declare const Input$1: import("react").ForwardRefExoticComponent<InputProps$1 & import("react").RefAttributes<HTMLInputElement>>;
|
|
100
107
|
//#endregion
|
package/dist/input/input.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/cn.js";
|
|
3
|
-
import { fieldSurfaceVariants } from "../lib/field-surface.js";
|
|
3
|
+
import { fieldBoxSize, fieldSurfaceVariants, fieldTextSize } from "../lib/field-surface.js";
|
|
4
4
|
import { FieldShell, hasFieldProps, useFieldWiring } from "../lib/field-shell.js";
|
|
5
5
|
import { cva } from "class-variance-authority";
|
|
6
6
|
import { forwardRef } from "react";
|
|
@@ -54,9 +54,9 @@ const inputVariants = cva([
|
|
|
54
54
|
* a tablet in landscape got 14px and zoomed.
|
|
55
55
|
*/
|
|
56
56
|
size: {
|
|
57
|
-
sm:
|
|
58
|
-
md:
|
|
59
|
-
lg:
|
|
57
|
+
sm: [fieldBoxSize.sm, fieldTextSize.sm],
|
|
58
|
+
md: [fieldBoxSize.md, fieldTextSize.md],
|
|
59
|
+
lg: [fieldBoxSize.lg, fieldTextSize.lg]
|
|
60
60
|
},
|
|
61
61
|
hasStartIcon: { true: "" },
|
|
62
62
|
hasEndIcon: { true: "" }
|
|
@@ -161,7 +161,7 @@ const affixVariants = cva([
|
|
|
161
161
|
defaultVariants: { size: "md" }
|
|
162
162
|
});
|
|
163
163
|
const Input$1 = forwardRef(function Input$2(allProps, ref) {
|
|
164
|
-
const { className, size = "md", startIcon, endIcon, label, description, error, ...props } = allProps;
|
|
164
|
+
const { className, size = "md", startIcon, endIcon, label, description, error, isRequired, ...props } = allProps;
|
|
165
165
|
const field = useFieldWiring({
|
|
166
166
|
enabled: hasFieldProps(allProps),
|
|
167
167
|
id: props.id,
|
|
@@ -173,6 +173,7 @@ const Input$1 = forwardRef(function Input$2(allProps, ref) {
|
|
|
173
173
|
const input = /* @__PURE__ */ jsx(Input, {
|
|
174
174
|
ref,
|
|
175
175
|
...props,
|
|
176
|
+
...isRequired ? { required: true } : {},
|
|
176
177
|
...field.controlProps,
|
|
177
178
|
"data-slot": "input",
|
|
178
179
|
className: cn(inputVariants({
|
|
@@ -212,6 +213,7 @@ const Input$1 = forwardRef(function Input$2(allProps, ref) {
|
|
|
212
213
|
hintId: field.hintId,
|
|
213
214
|
error,
|
|
214
215
|
errorId: field.errorId,
|
|
216
|
+
required: isRequired,
|
|
215
217
|
children: control
|
|
216
218
|
});
|
|
217
219
|
});
|
package/dist/input/input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input.js","names":["Input","AriaInput"],"sources":["../../src/input/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { Input as AriaInput, type InputProps as AriaInputProps } from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { FieldShell, hasFieldProps, useFieldWiring } from \"../lib/field-shell.js\";\nimport { fieldSurfaceVariants } from \"../lib/field-surface.js\";\n\n/**\n * Input, ported from the legacy shadcn component onto React Aria's Input.\n *\n * Census: 25 files, 51 uses -- the busiest control in the app after Button.\n * Props are `onChange` 36, `value` 35, `placeholder` 33, `id` 23, `type` 21.\n *\n * EVERY ONE OF THOSE 51 CALL SITES MIGRATES UNCHANGED. React Aria's `Input`\n * takes NATIVE props -- `disabled`, `aria-invalid`, `onChange` with a real\n * event -- not the `isDisabled`/`onChange(value)` shape the rest of React\n * Aria uses. It reads `InputContext` when one is present, so the same\n * component is a bare styled input today and composes inside a `TextField`\n * the moment one is wrapped around it. There is no rename to schedule.\n *\n * That is also why this is not `TextField`. Wrapping 51 call sites in a\n * field they do not have, to get a `onChange(value: string)` they did not\n * ask for, would be the migration doing work on the app's behalf.\n *\n * `border-input` becomes `border-border`: in the legacy theme `--input` is\n * character-for-character `--border` on light (`oklch(0.922 0 0)`), and the\n * dark values differ only in alpha. A fourth token role that turns out to\n * be an existing one, after `popover`, `accent` and the scrim.\n */\nexport const inputVariants = cva(\n [\n fieldSurfaceVariants(),\n\n // type=\"file\" has one call site, which is not zero. Enough to keep it\n // from rendering as an unstyled user-agent button.\n \"file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"file:text-foreground\",\n ],\n {\n variants: {\n /**\n * Height and inline padding from the control scale, so `data-density`\n * moves a whole form at once. Same three names and the same tokens as\n * Button, because they sit in the same row: Button's `sm` is the app's\n * second most common at 167 call sites, and while the field was locked\n * to `md` the pair was 10px out of alignment with no supported fix.\n *\n * Type follows Button's sm rung, with one guard. `sm` is 14px, the\n * size of the body text a small field sits among (Button's sm label is\n * text-sm for the same reason). `md` and `lg` stay 16px.\n *\n * The guard: iOS Safari zooms the viewport when a focused field's text\n * is under 16px, so a coarse pointer (a touch screen) keeps 16px on\n * `sm` too. The switch is the input device, not the viewport width:\n * the legacy `text-base md:text-sm` changed size at a breakpoint that\n * has nothing to do with zoom, so a narrow desktop window got 16px and\n * a tablet in landscape got 14px and zoomed.\n */\n size: {\n sm: \"h-(--density-control-h-sm) px-(--density-control-pad-sm) text-sm pointer-coarse:text-base\",\n md: \"h-(--density-control-h-md) px-(--density-control-pad-md) text-base\",\n lg: \"h-(--density-control-h-lg) px-(--density-control-pad-lg) text-base\",\n },\n // Declared empty and filled by the compound variants below: the affix\n // inset depends on BOTH whether a slot is used and which rung it is on.\n hasStartIcon: { true: \"\" },\n hasEndIcon: { true: \"\" },\n },\n compoundVariants: [\n // The affix slots float ABOVE the field rather than sitting beside it\n // in a flex row, so the only thing keeping the value from running\n // underneath a glyph is this padding. It is the same three tokens that\n // place the glyph -- inline padding, icon box, control gap -- so the\n // text and the glyph move together across density AND size. A\n // hand-tuned `pl-9` at the call site can do neither, and the product\n // app has eighteen of those.\n {\n size: \"sm\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-sm)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"md\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-md)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"lg\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-lg)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"sm\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-sm)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"md\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-md)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"lg\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-lg)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n ],\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * An affix slot.\n *\n * `pointer-events-none` is load-bearing, not cosmetic: the slot is painted on\n * top of the field, so without it the glyph swallows the click that was meant\n * to focus the input. Which also fixes the slot's scope -- these are\n * DECORATIVE marks. An interactive trailing control (a password reveal, a\n * clear button) needs its own pointer events and its own accessible name, and\n * the census found no call site for one, so it is not built here.\n *\n * Logical properties throughout. The product app's eighteen hand-rolled\n * adornments are all `absolute left-*`, with `absolute start-*` at zero\n * occurrences, so every one of them puts the glyph on the wrong side under\n * RTL and lets the text run over it.\n */\nconst affixVariants = cva(\n [\n \"pointer-events-none absolute inset-y-0 flex items-center\",\n \"text-muted-foreground\",\n // Sized like Button's icon slots, and skipped when the caller sized the\n // glyph themselves. An svg with neither a width attribute nor a resolved\n // class renders at 0x0 and every position assertion still passes.\n \"[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n ],\n {\n variants: {\n side: { start: \"\", end: \"\" },\n size: { sm: \"\", md: \"\", lg: \"\" },\n },\n // The glyph's inset is the field's own inline padding, so it lines up with\n // where the value would have started. That makes it a pair of axes, not\n // one: a small field at the medium inset puts the glyph under the text.\n compoundVariants: [\n { side: \"start\", size: \"sm\", class: \"start-(--density-control-pad-sm)\" },\n { side: \"start\", size: \"md\", class: \"start-(--density-control-pad-md)\" },\n { side: \"start\", size: \"lg\", class: \"start-(--density-control-pad-lg)\" },\n { side: \"end\", size: \"sm\", class: \"end-(--density-control-pad-sm)\" },\n { side: \"end\", size: \"md\", class: \"end-(--density-control-pad-md)\" },\n { side: \"end\", size: \"lg\", class: \"end-(--density-control-pad-lg)\" },\n ],\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * A single-line text field.\n *\n * @example\n * <Input type=\"email\" placeholder=\"you@example.com\" value={v} onChange={e => set(e.target.value)} />\n * <Input aria-label=\"Search\" startIcon={<SearchIcon aria-hidden />} />\n */\nexport interface InputProps extends Omit<AriaInputProps, \"className\" | \"style\" | \"size\"> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Control scale. Height and inline padding come from the same\n * `--density-control-*` tokens as Button, so a field and a button on one\n * rung are the same height.\n *\n * Type does not scale with it: the field stays at 16px everywhere, because\n * iOS Safari zooms the viewport when a focused input's text is smaller.\n *\n * This REPLACES the native `size` attribute, which React Aria inherits from\n * `InputHTMLAttributes` as a character count. No call site in the census\n * used it; set a width with `className` instead.\n *\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Decorative glyph at the leading edge of the field.\n *\n * Mark it `aria-hidden` -- the field's label carries the accessible name,\n * and a second name source only makes it announce twice. It is sized at\n * `--icon-sm` unless it carries a `size-*` class of its own, positioned\n * from `--density-control-pad-md`, and the field's leading padding grows to\n * match so the value cannot run underneath it.\n *\n * The slot is `pointer-events: none`, so a click on the glyph focuses the\n * field. That makes it decorative by construction: an interactive\n * adornment -- a password reveal, a clear button -- is NOT this prop.\n *\n * Two named slots rather than one `icon` plus a position prop, matching\n * Button: a search field can legitimately carry a leading glyph AND a\n * trailing unit, which one slot cannot express.\n */\n startIcon?: ReactNode;\n /** Decorative glyph at the trailing edge. Same rules as {@link InputProps.startIcon}. */\n endIcon?: ReactNode;\n /**\n * A visible label above the field, tied to it with `htmlFor`. Passing any of\n * `label`, `description` or `error` (even as `undefined`) wraps the field;\n * with none of them the DOM is exactly the bare input. Do not also pass\n * `aria-label`: it wins over the label, so the visible name is not the\n * accessible one (WCAG 2.5.3). Ignored inside a React Aria `TextField`,\n * which supplies its own label and messages.\n */\n label?: ReactNode;\n /**\n * Helper text under the field, named by `aria-describedby`. It opens on a\n * spring when it appears after mount, changed words rise in and numbers roll\n * digit by digit; nothing animates on first render, and reduced motion swaps\n * it instantly. A string, because the copy is animated word by word.\n */\n description?: string;\n /**\n * Error text under the field. Sets `aria-invalid`, so the field takes its\n * invalid border, and is announced as an alert when it appears. Opens and\n * closes like `description`. An empty or `undefined` value closes the row.\n */\n error?: string;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(allProps, ref) {\n const {\n className,\n size = \"md\",\n startIcon,\n endIcon,\n label,\n description,\n error,\n ...props\n } = allProps;\n const field = useFieldWiring({\n enabled: hasFieldProps(allProps),\n id: props.id,\n describedBy: props[\"aria-describedby\"],\n invalid: props[\"aria-invalid\"],\n description,\n error,\n });\n const input = (\n <AriaInput\n // The ref goes on the INPUT, never on the wrapper span below. A ref\n // pointing at the wrapper is still non-null, so it satisfies the obvious\n // assertion while breaking `.focus()`, `.select()` and every\n // react-hook-form site -- but only at the call sites that pass an icon.\n // RefLandsOnTheInputNotTheWrapper is the guard.\n ref={ref}\n {...props}\n {...field.controlProps}\n data-slot=\"input\"\n className={cn(\n inputVariants({\n size,\n hasStartIcon: startIcon !== undefined,\n hasEndIcon: endIcon !== undefined,\n }),\n className,\n )}\n />\n );\n\n // With neither slot used there is no wrapper AT ALL, so the DOM is\n // byte-identical to what shipped before this prop existed. That is what\n // keeps this additive for the 97 call sites that pass no glyph, and\n // NoIconsLeaveDomUnchanged is the assertion holding it true.\n // With neither slot used there is no wrapper AT ALL, so the DOM is\n // byte-identical to what shipped before this prop existed. That is what\n // keeps this additive for the 97 call sites that pass no glyph, and\n // NoIconsLeaveDomUnchanged is the assertion holding it true.\n //\n // An overlay, not a flex row. Moving the border onto this wrapper would\n // take the painted surface off [data-slot=\"input\"] -- the selector the\n // escape hatch is built on -- and would force the focus ring onto\n // :focus-within and the invalid border onto :has(), when React Aria\n // already puts data-focus-visible and data-invalid on the input itself.\n const control =\n startIcon === undefined && endIcon === undefined ? (\n input\n ) : (\n <span data-slot=\"input-wrapper\" className=\"relative block w-full\">\n {input}\n {startIcon === undefined ? null : (\n <span data-slot=\"input-start-icon\" className={affixVariants({ side: \"start\", size })}>\n {startIcon}\n </span>\n )}\n {endIcon === undefined ? null : (\n <span data-slot=\"input-end-icon\" className={affixVariants({ side: \"end\", size })}>\n {endIcon}\n </span>\n )}\n </span>\n );\n\n // Without a field prop there is no field wrapper either, and the DOM is the bare input (or the icon wrapper).\n if (!field.active) return control;\n return (\n <FieldShell\n label={label}\n controlId={field.controlId}\n description={description}\n hintId={field.hintId}\n error={error}\n errorId={field.errorId}\n >\n {control}\n </FieldShell>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,gBAAgB,IAC3B;CACE,qBAAqB;CAIrB;CACA;AACF,GACA;CACE,UAAU;;;;;;;;;;;;;;;;;;;EAmBR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;EACN;EAGA,cAAc,EAAE,MAAM,GAAG;EACzB,YAAY,EAAE,MAAM,GAAG;CACzB;CACA,kBAAkB;EAQhB;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;CACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;;;;;;;;;;;;;;;;AAiBA,MAAM,gBAAgB,IACpB;CACE;CACA;CAIA;AACF,GACA;CACE,UAAU;EACR,MAAM;GAAE,OAAO;GAAI,KAAK;EAAG;EAC3B,MAAM;GAAE,IAAI;GAAI,IAAI;GAAI,IAAI;EAAG;CACjC;CAIA,kBAAkB;EAChB;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;EACnE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;EACnE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;CACrE;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;AAuEA,MAAaA,UAAQ,WAAyC,SAASA,QAAM,UAAU,KAAK;CAC1F,MAAM,EACJ,WACA,OAAO,MACP,WACA,SACA,OACA,aACA,OACA,GAAG,UACD;CACJ,MAAM,QAAQ,eAAe;EAC3B,SAAS,cAAc,QAAQ;EAC/B,IAAI,MAAM;EACV,aAAa,MAAM;EACnB,SAAS,MAAM;EACf;EACA;CACF,CAAC;CACD,MAAM,QACJ,oBAACC,OAAD;EAMO;EACL,GAAI;EACJ,GAAI,MAAM;EACV,aAAU;EACV,WAAW,GACT,cAAc;GACZ;GACA,cAAc,cAAc,KAAA;GAC5B,YAAY,YAAY,KAAA;EAC1B,CAAC,GACD,SACF;CACD,CAAA;CAiBH,MAAM,UACJ,cAAc,KAAA,KAAa,YAAY,KAAA,IACrC,QAEA,qBAAC,QAAD;EAAM,aAAU;EAAgB,WAAU;EAA1C,UAAA;GACG;GACA,cAAc,KAAA,IAAY,OACzB,oBAAC,QAAD;IAAM,aAAU;IAAmB,WAAW,cAAc;KAAE,MAAM;KAAS;IAAK,CAAC;IAChF,UAAA;GACG,CAAA;GAEP,YAAY,KAAA,IAAY,OACvB,oBAAC,QAAD;IAAM,aAAU;IAAiB,WAAW,cAAc;KAAE,MAAM;KAAO;IAAK,CAAC;IAC5E,UAAA;GACG,CAAA;EAEJ;;CAIV,IAAI,CAAC,MAAM,QAAQ,OAAO;CAC1B,OACE,oBAAC,YAAD;EACS;EACP,WAAW,MAAM;EACJ;EACb,QAAQ,MAAM;EACP;EACP,SAAS,MAAM;EAEd,UAAA;CACS,CAAA;AAEhB,CAAC"}
|
|
1
|
+
{"version":3,"file":"input.js","names":["Input","AriaInput"],"sources":["../../src/input/input.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport { Input as AriaInput, type InputProps as AriaInputProps } from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { FieldShell, hasFieldProps, useFieldWiring } from \"../lib/field-shell.js\";\nimport { fieldBoxSize, fieldSurfaceVariants, fieldTextSize } from \"../lib/field-surface.js\";\n\n/**\n * Input, ported from the legacy shadcn component onto React Aria's Input.\n *\n * Census: 25 files, 51 uses -- the busiest control in the app after Button.\n * Props are `onChange` 36, `value` 35, `placeholder` 33, `id` 23, `type` 21.\n *\n * EVERY ONE OF THOSE 51 CALL SITES MIGRATES UNCHANGED. React Aria's `Input`\n * takes NATIVE props -- `disabled`, `aria-invalid`, `onChange` with a real\n * event -- not the `isDisabled`/`onChange(value)` shape the rest of React\n * Aria uses. It reads `InputContext` when one is present, so the same\n * component is a bare styled input today and composes inside a `TextField`\n * the moment one is wrapped around it. There is no rename to schedule.\n *\n * That is also why this is not `TextField`. Wrapping 51 call sites in a\n * field they do not have, to get a `onChange(value: string)` they did not\n * ask for, would be the migration doing work on the app's behalf.\n *\n * `border-input` becomes `border-border`: in the legacy theme `--input` is\n * character-for-character `--border` on light (`oklch(0.922 0 0)`), and the\n * dark values differ only in alpha. A fourth token role that turns out to\n * be an existing one, after `popover`, `accent` and the scrim.\n */\nexport const inputVariants = cva(\n [\n fieldSurfaceVariants(),\n\n // type=\"file\" has one call site, which is not zero. Enough to keep it\n // from rendering as an unstyled user-agent button.\n \"file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium\",\n \"file:text-foreground\",\n ],\n {\n variants: {\n /**\n * Height and inline padding from the control scale, so `data-density`\n * moves a whole form at once. Same three names and the same tokens as\n * Button, because they sit in the same row: Button's `sm` is the app's\n * second most common at 167 call sites, and while the field was locked\n * to `md` the pair was 10px out of alignment with no supported fix.\n *\n * Type follows Button's sm rung, with one guard. `sm` is 14px, the\n * size of the body text a small field sits among (Button's sm label is\n * text-sm for the same reason). `md` and `lg` stay 16px.\n *\n * The guard: iOS Safari zooms the viewport when a focused field's text\n * is under 16px, so a coarse pointer (a touch screen) keeps 16px on\n * `sm` too. The switch is the input device, not the viewport width:\n * the legacy `text-base md:text-sm` changed size at a breakpoint that\n * has nothing to do with zoom, so a narrow desktop window got 16px and\n * a tablet in landscape got 14px and zoomed.\n */\n size: {\n sm: [fieldBoxSize.sm, fieldTextSize.sm],\n md: [fieldBoxSize.md, fieldTextSize.md],\n lg: [fieldBoxSize.lg, fieldTextSize.lg],\n },\n // Declared empty and filled by the compound variants below: the affix\n // inset depends on BOTH whether a slot is used and which rung it is on.\n hasStartIcon: { true: \"\" },\n hasEndIcon: { true: \"\" },\n },\n compoundVariants: [\n // The affix slots float ABOVE the field rather than sitting beside it\n // in a flex row, so the only thing keeping the value from running\n // underneath a glyph is this padding. It is the same three tokens that\n // place the glyph -- inline padding, icon box, control gap -- so the\n // text and the glyph move together across density AND size. A\n // hand-tuned `pl-9` at the call site can do neither, and the product\n // app has eighteen of those.\n {\n size: \"sm\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-sm)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"md\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-md)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"lg\",\n hasStartIcon: true,\n class:\n \"ps-[calc(var(--density-control-pad-lg)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"sm\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-sm)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"md\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-md)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n {\n size: \"lg\",\n hasEndIcon: true,\n class:\n \"pe-[calc(var(--density-control-pad-lg)_+_var(--icon-sm)_+_var(--density-control-gap))]\",\n },\n ],\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * An affix slot.\n *\n * `pointer-events-none` is load-bearing, not cosmetic: the slot is painted on\n * top of the field, so without it the glyph swallows the click that was meant\n * to focus the input. Which also fixes the slot's scope -- these are\n * DECORATIVE marks. An interactive trailing control (a password reveal, a\n * clear button) needs its own pointer events and its own accessible name, and\n * the census found no call site for one, so it is not built here.\n *\n * Logical properties throughout. The product app's eighteen hand-rolled\n * adornments are all `absolute left-*`, with `absolute start-*` at zero\n * occurrences, so every one of them puts the glyph on the wrong side under\n * RTL and lets the text run over it.\n */\nconst affixVariants = cva(\n [\n \"pointer-events-none absolute inset-y-0 flex items-center\",\n \"text-muted-foreground\",\n // Sized like Button's icon slots, and skipped when the caller sized the\n // glyph themselves. An svg with neither a width attribute nor a resolved\n // class renders at 0x0 and every position assertion still passes.\n \"[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-(--icon-sm)\",\n ],\n {\n variants: {\n side: { start: \"\", end: \"\" },\n size: { sm: \"\", md: \"\", lg: \"\" },\n },\n // The glyph's inset is the field's own inline padding, so it lines up with\n // where the value would have started. That makes it a pair of axes, not\n // one: a small field at the medium inset puts the glyph under the text.\n compoundVariants: [\n { side: \"start\", size: \"sm\", class: \"start-(--density-control-pad-sm)\" },\n { side: \"start\", size: \"md\", class: \"start-(--density-control-pad-md)\" },\n { side: \"start\", size: \"lg\", class: \"start-(--density-control-pad-lg)\" },\n { side: \"end\", size: \"sm\", class: \"end-(--density-control-pad-sm)\" },\n { side: \"end\", size: \"md\", class: \"end-(--density-control-pad-md)\" },\n { side: \"end\", size: \"lg\", class: \"end-(--density-control-pad-lg)\" },\n ],\n defaultVariants: { size: \"md\" },\n },\n);\n\n/**\n * A single-line text field.\n *\n * @example\n * <Input type=\"email\" placeholder=\"you@example.com\" value={v} onChange={e => set(e.target.value)} />\n * <Input aria-label=\"Search\" startIcon={<SearchIcon aria-hidden />} />\n */\nexport interface InputProps extends Omit<AriaInputProps, \"className\" | \"style\" | \"size\"> {\n /** Extra classes. Merged last, so they win conflicts with ours. */\n className?: string;\n /**\n * Control scale. Height and inline padding come from the same\n * `--density-control-*` tokens as Button, so a field and a button on one\n * rung are the same height.\n *\n * Type does not scale with it: the field stays at 16px everywhere, because\n * iOS Safari zooms the viewport when a focused input's text is smaller.\n *\n * This REPLACES the native `size` attribute, which React Aria inherits from\n * `InputHTMLAttributes` as a character count. No call site in the census\n * used it; set a width with `className` instead.\n *\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /**\n * Decorative glyph at the leading edge of the field.\n *\n * Mark it `aria-hidden` -- the field's label carries the accessible name,\n * and a second name source only makes it announce twice. It is sized at\n * `--icon-sm` unless it carries a `size-*` class of its own, positioned\n * from `--density-control-pad-md`, and the field's leading padding grows to\n * match so the value cannot run underneath it.\n *\n * The slot is `pointer-events: none`, so a click on the glyph focuses the\n * field. That makes it decorative by construction: an interactive\n * adornment -- a password reveal, a clear button -- is NOT this prop.\n *\n * Two named slots rather than one `icon` plus a position prop, matching\n * Button: a search field can legitimately carry a leading glyph AND a\n * trailing unit, which one slot cannot express.\n */\n startIcon?: ReactNode;\n /** Decorative glyph at the trailing edge. Same rules as {@link InputProps.startIcon}. */\n endIcon?: ReactNode;\n /**\n * A visible label above the field, tied to it with `htmlFor`. Passing any of\n * `label`, `description` or `error` (even as `undefined`) wraps the field;\n * with none of them the DOM is exactly the bare input. Do not also pass\n * `aria-label`: it wins over the label, so the visible name is not the\n * accessible one (WCAG 2.5.3). Ignored inside a React Aria `TextField`,\n * which supplies its own label and messages.\n */\n label?: ReactNode;\n /**\n * Helper text under the field, named by `aria-describedby`. It opens on a\n * spring when it appears after mount, changed words rise in and numbers roll\n * digit by digit; nothing animates on first render, and reduced motion swaps\n * it instantly. A string, because the copy is animated word by word.\n */\n description?: string;\n /**\n * Error text under the field. Sets `aria-invalid`, so the field takes its\n * invalid border, and is announced as an alert when it appears. Opens and\n * closes like `description`. An empty or `undefined` value closes the row.\n */\n error?: string;\n /**\n * The field must be filled: the input is `required` (announced by screen\n * readers, and checked by native form validation) and the label shows the\n * required marker. The same prop as PasswordField's.\n * @default false\n */\n isRequired?: boolean;\n}\n\nexport const Input = forwardRef<HTMLInputElement, InputProps>(function Input(allProps, ref) {\n const {\n className,\n size = \"md\",\n startIcon,\n endIcon,\n label,\n description,\n error,\n isRequired,\n ...props\n } = allProps;\n const field = useFieldWiring({\n enabled: hasFieldProps(allProps),\n id: props.id,\n describedBy: props[\"aria-describedby\"],\n invalid: props[\"aria-invalid\"],\n description,\n error,\n });\n const input = (\n <AriaInput\n // The ref goes on the INPUT, never on the wrapper span below. A ref\n // pointing at the wrapper is still non-null, so it satisfies the obvious\n // assertion while breaking `.focus()`, `.select()` and every\n // react-hook-form site -- but only at the call sites that pass an icon.\n // RefLandsOnTheInputNotTheWrapper is the guard.\n ref={ref}\n {...props}\n {...(isRequired ? { required: true } : {})}\n {...field.controlProps}\n data-slot=\"input\"\n className={cn(\n inputVariants({\n size,\n hasStartIcon: startIcon !== undefined,\n hasEndIcon: endIcon !== undefined,\n }),\n className,\n )}\n />\n );\n\n // With neither slot used there is no wrapper AT ALL, so the DOM is\n // byte-identical to what shipped before this prop existed. That is what\n // keeps this additive for the 97 call sites that pass no glyph, and\n // NoIconsLeaveDomUnchanged is the assertion holding it true.\n // With neither slot used there is no wrapper AT ALL, so the DOM is\n // byte-identical to what shipped before this prop existed. That is what\n // keeps this additive for the 97 call sites that pass no glyph, and\n // NoIconsLeaveDomUnchanged is the assertion holding it true.\n //\n // An overlay, not a flex row. Moving the border onto this wrapper would\n // take the painted surface off [data-slot=\"input\"] -- the selector the\n // escape hatch is built on -- and would force the focus ring onto\n // :focus-within and the invalid border onto :has(), when React Aria\n // already puts data-focus-visible and data-invalid on the input itself.\n const control =\n startIcon === undefined && endIcon === undefined ? (\n input\n ) : (\n <span data-slot=\"input-wrapper\" className=\"relative block w-full\">\n {input}\n {startIcon === undefined ? null : (\n <span data-slot=\"input-start-icon\" className={affixVariants({ side: \"start\", size })}>\n {startIcon}\n </span>\n )}\n {endIcon === undefined ? null : (\n <span data-slot=\"input-end-icon\" className={affixVariants({ side: \"end\", size })}>\n {endIcon}\n </span>\n )}\n </span>\n );\n\n // Without a field prop there is no field wrapper either, and the DOM is the bare input (or the icon wrapper).\n if (!field.active) return control;\n return (\n <FieldShell\n label={label}\n controlId={field.controlId}\n description={description}\n hintId={field.hintId}\n error={error}\n errorId={field.errorId}\n required={isRequired}\n >\n {control}\n </FieldShell>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAa,gBAAgB,IAC3B;CACE,qBAAqB;CAIrB;CACA;AACF,GACA;CACE,UAAU;;;;;;;;;;;;;;;;;;;EAmBR,MAAM;GACJ,IAAI,CAAC,aAAa,IAAI,cAAc,EAAE;GACtC,IAAI,CAAC,aAAa,IAAI,cAAc,EAAE;GACtC,IAAI,CAAC,aAAa,IAAI,cAAc,EAAE;EACxC;EAGA,cAAc,EAAE,MAAM,GAAG;EACzB,YAAY,EAAE,MAAM,GAAG;CACzB;CACA,kBAAkB;EAQhB;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,cAAc;GACd,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;EACA;GACE,MAAM;GACN,YAAY;GACZ,OACE;EACJ;CACF;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;;;;;;;;;;;;;;;;AAiBA,MAAM,gBAAgB,IACpB;CACE;CACA;CAIA;AACF,GACA;CACE,UAAU;EACR,MAAM;GAAE,OAAO;GAAI,KAAK;EAAG;EAC3B,MAAM;GAAE,IAAI;GAAI,IAAI;GAAI,IAAI;EAAG;CACjC;CAIA,kBAAkB;EAChB;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAS,MAAM;GAAM,OAAO;EAAmC;EACvE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;EACnE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;EACnE;GAAE,MAAM;GAAO,MAAM;GAAM,OAAO;EAAiC;CACrE;CACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CACF;AA8EA,MAAaA,UAAQ,WAAyC,SAASA,QAAM,UAAU,KAAK;CAC1F,MAAM,EACJ,WACA,OAAO,MACP,WACA,SACA,OACA,aACA,OACA,YACA,GAAG,UACD;CACJ,MAAM,QAAQ,eAAe;EAC3B,SAAS,cAAc,QAAQ;EAC/B,IAAI,MAAM;EACV,aAAa,MAAM;EACnB,SAAS,MAAM;EACf;EACA;CACF,CAAC;CACD,MAAM,QACJ,oBAACC,OAAD;EAMO;EACL,GAAI;EACJ,GAAK,aAAa,EAAE,UAAU,KAAK,IAAI,CAAC;EACxC,GAAI,MAAM;EACV,aAAU;EACV,WAAW,GACT,cAAc;GACZ;GACA,cAAc,cAAc,KAAA;GAC5B,YAAY,YAAY,KAAA;EAC1B,CAAC,GACD,SACF;CACD,CAAA;CAiBH,MAAM,UACJ,cAAc,KAAA,KAAa,YAAY,KAAA,IACrC,QAEA,qBAAC,QAAD;EAAM,aAAU;EAAgB,WAAU;EAA1C,UAAA;GACG;GACA,cAAc,KAAA,IAAY,OACzB,oBAAC,QAAD;IAAM,aAAU;IAAmB,WAAW,cAAc;KAAE,MAAM;KAAS;IAAK,CAAC;IAChF,UAAA;GACG,CAAA;GAEP,YAAY,KAAA,IAAY,OACvB,oBAAC,QAAD;IAAM,aAAU;IAAiB,WAAW,cAAc;KAAE,MAAM;KAAO;IAAK,CAAC;IAC5E,UAAA;GACG,CAAA;EAEJ;;CAIV,IAAI,CAAC,MAAM,QAAQ,OAAO;CAC1B,OACE,oBAAC,YAAD;EACS;EACP,WAAW,MAAM;EACJ;EACb,QAAQ,MAAM;EACP;EACP,SAAS,MAAM;EACf,UAAU;EAET,UAAA;CACS,CAAA;AAEhB,CAAC"}
|
package/dist/lib/field-shell.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Label as Label$1 } from "../label/label.js";
|
|
2
2
|
import { FieldMessage } from "./field-message.js";
|
|
3
|
+
import { RequiredMarker } from "./required-marker.js";
|
|
3
4
|
import { useId } from "react";
|
|
4
5
|
import { InputContext, LabelContext, useSlottedContext } from "react-aria-components";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -32,6 +33,8 @@ function useFieldWiring({ enabled, id, describedBy, invalid, description, error
|
|
|
32
33
|
const errorId = active && error ? `${controlId}-error` : void 0;
|
|
33
34
|
return {
|
|
34
35
|
active,
|
|
36
|
+
/** True inside a React Aria field, which supplies the label and its own messages. */
|
|
37
|
+
inside,
|
|
35
38
|
controlId,
|
|
36
39
|
hintId,
|
|
37
40
|
errorId,
|
|
@@ -47,15 +50,15 @@ function useFieldWiring({ enabled, id, describedBy, invalid, description, error
|
|
|
47
50
|
};
|
|
48
51
|
}
|
|
49
52
|
/** The wrapper: label above the control, then the helper row and the error row. Each row owns its top space, so a closed row costs nothing. */
|
|
50
|
-
function FieldShell({ label, controlId, description, hintId, error, errorId, wordExit, numbers, children }) {
|
|
53
|
+
function FieldShell({ label, controlId, description, hintId, error, errorId, wordExit, numbers, required = false, children }) {
|
|
51
54
|
return /* @__PURE__ */ jsxs("div", {
|
|
52
55
|
"data-slot": "field",
|
|
53
56
|
className: "grid min-w-0 font-sans",
|
|
54
57
|
children: [
|
|
55
|
-
label == null ? null : /* @__PURE__ */
|
|
58
|
+
label == null ? null : /* @__PURE__ */ jsxs(Label$1, {
|
|
56
59
|
htmlFor: controlId,
|
|
57
60
|
className: "mb-1.5",
|
|
58
|
-
children: label
|
|
61
|
+
children: [label, required ? /* @__PURE__ */ jsx(RequiredMarker, {}) : null]
|
|
59
62
|
}),
|
|
60
63
|
children,
|
|
61
64
|
/* @__PURE__ */ jsx(FieldMessage, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-shell.js","names":["Label"],"sources":["../../src/lib/field-shell.tsx"],"sourcesContent":["import { useId, type ReactNode } from \"react\";\nimport { InputContext, LabelContext, useSlottedContext } from \"react-aria-components\";\n\nimport { Label } from \"../label/label.js\";\nimport { FieldMessage, type WordExit } from \"./field-message.js\";\n\n/*\n * The label, helper text and error text around a text control, for Input and\n * Textarea. The first lib file that imports a sibling component (Label): the\n * layer rule allows primitives to use primitives, and a field's label is the\n * same Label everywhere else.\n */\n\n/**\n * True when any field prop was passed at all, even as `undefined`. Deciding by\n * presence, not value, is what keeps `error={maybeMessage}` from moving the\n * control between a wrapper and no wrapper when the message appears: that would\n * remount the control and drop focus and an uncontrolled value.\n */\nexport const hasFieldProps = (props: object) =>\n \"label\" in props || \"description\" in props || \"error\" in props;\n\n/** A control inside a React Aria `TextField` already has its label and messages supplied by the field. */\nfunction useInsideReactAriaField() {\n const label = useSlottedContext(LabelContext);\n const input = useSlottedContext(InputContext);\n return Object.keys(label ?? {}).length > 0 || Object.keys(input ?? {}).length > 0;\n}\n\n/**\n * The ids and aria wiring for a control with field props. `active` is false\n * when no field prop was passed, or inside a React Aria field, and then\n * `controlProps` is empty: the control's own props are untouched, and a bare\n * control has no generated `id`.\n */\nexport function useFieldWiring({\n enabled,\n id,\n describedBy,\n invalid,\n description,\n error,\n}: {\n enabled: boolean;\n id: string | undefined;\n describedBy: string | undefined;\n invalid: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined;\n description: string | undefined;\n error: string | undefined;\n}) {\n const generated = useId();\n const inside = useInsideReactAriaField();\n const active = enabled && !inside;\n const controlId = id ?? generated;\n const hintId = active && description ? `${controlId}-description` : undefined;\n const errorId = active && error ? `${controlId}-error` : undefined;\n return {\n active,\n controlId,\n hintId,\n errorId,\n controlProps: active\n ? {\n id: controlId,\n \"aria-invalid\": error ? true : invalid,\n \"aria-describedby\": [describedBy, hintId, errorId].filter(Boolean).join(\" \") || undefined,\n }\n : {},\n };\n}\n\n/** The wrapper: label above the control, then the helper row and the error row. Each row owns its top space, so a closed row costs nothing. */\nexport function FieldShell({\n label,\n controlId,\n description,\n hintId,\n error,\n errorId,\n wordExit,\n numbers,\n children,\n}: {\n label: ReactNode;\n controlId: string;\n description: string | undefined;\n hintId: string | undefined;\n error: string | undefined;\n errorId: string | undefined;\n wordExit?: WordExit;\n numbers?: boolean;\n children: ReactNode;\n}) {\n return (\n <div data-slot=\"field\" className=\"grid min-w-0 font-sans\">\n {label == null ? null : (\n // 6px, the gap Select and DatePicker keep between their label and control, so a labelled Input sits level with them.\n <Label htmlFor={controlId} className=\"mb-1.5\">\n {label}\n </Label>\n )}\n {children}\n <FieldMessage\n id={hintId}\n text={description}\n tone=\"description\"\n wordExit={wordExit}\n numbers={numbers}\n />\n <FieldMessage id={errorId} text={error} tone=\"error\" wordExit={wordExit} numbers={numbers} />\n </div>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"field-shell.js","names":["Label"],"sources":["../../src/lib/field-shell.tsx"],"sourcesContent":["import { useId, type ReactNode } from \"react\";\nimport { InputContext, LabelContext, useSlottedContext } from \"react-aria-components\";\n\nimport { Label } from \"../label/label.js\";\nimport { FieldMessage, type WordExit } from \"./field-message.js\";\nimport { RequiredMarker } from \"./required-marker.js\";\n\n/*\n * The label, helper text and error text around a text control, for Input and\n * Textarea. The first lib file that imports a sibling component (Label): the\n * layer rule allows primitives to use primitives, and a field's label is the\n * same Label everywhere else.\n */\n\n/**\n * True when any field prop was passed at all, even as `undefined`. Deciding by\n * presence, not value, is what keeps `error={maybeMessage}` from moving the\n * control between a wrapper and no wrapper when the message appears: that would\n * remount the control and drop focus and an uncontrolled value.\n */\nexport const hasFieldProps = (props: object) =>\n \"label\" in props || \"description\" in props || \"error\" in props;\n\n/** A control inside a React Aria `TextField` already has its label and messages supplied by the field. */\nfunction useInsideReactAriaField() {\n const label = useSlottedContext(LabelContext);\n const input = useSlottedContext(InputContext);\n return Object.keys(label ?? {}).length > 0 || Object.keys(input ?? {}).length > 0;\n}\n\n/**\n * The ids and aria wiring for a control with field props. `active` is false\n * when no field prop was passed, or inside a React Aria field, and then\n * `controlProps` is empty: the control's own props are untouched, and a bare\n * control has no generated `id`.\n */\nexport function useFieldWiring({\n enabled,\n id,\n describedBy,\n invalid,\n description,\n error,\n}: {\n enabled: boolean;\n id: string | undefined;\n describedBy: string | undefined;\n invalid: boolean | \"true\" | \"false\" | \"grammar\" | \"spelling\" | undefined;\n description: string | undefined;\n error: string | undefined;\n}) {\n const generated = useId();\n const inside = useInsideReactAriaField();\n const active = enabled && !inside;\n const controlId = id ?? generated;\n const hintId = active && description ? `${controlId}-description` : undefined;\n const errorId = active && error ? `${controlId}-error` : undefined;\n return {\n active,\n /** True inside a React Aria field, which supplies the label and its own messages. */\n inside,\n controlId,\n hintId,\n errorId,\n controlProps: active\n ? {\n id: controlId,\n \"aria-invalid\": error ? true : invalid,\n \"aria-describedby\": [describedBy, hintId, errorId].filter(Boolean).join(\" \") || undefined,\n }\n : {},\n };\n}\n\n/** The wrapper: label above the control, then the helper row and the error row. Each row owns its top space, so a closed row costs nothing. */\nexport function FieldShell({\n label,\n controlId,\n description,\n hintId,\n error,\n errorId,\n wordExit,\n numbers,\n required = false,\n children,\n}: {\n label: ReactNode;\n controlId: string;\n description: string | undefined;\n hintId: string | undefined;\n error: string | undefined;\n errorId: string | undefined;\n wordExit?: WordExit;\n numbers?: boolean;\n /**\n * Draws the required marker after the label. Decoration only (aria-hidden):\n * the control's own `required` is what a screen reader announces, so the\n * name stays \"Password\", not \"Password star\".\n */\n required?: boolean;\n children: ReactNode;\n}) {\n return (\n <div data-slot=\"field\" className=\"grid min-w-0 font-sans\">\n {label == null ? null : (\n // 6px, the gap Select and DatePicker keep between their label and control, so a labelled Input sits level with them.\n <Label htmlFor={controlId} className=\"mb-1.5\">\n {label}\n {required ? <RequiredMarker /> : null}\n </Label>\n )}\n {children}\n <FieldMessage\n id={hintId}\n text={description}\n tone=\"description\"\n wordExit={wordExit}\n numbers={numbers}\n />\n <FieldMessage id={errorId} text={error} tone=\"error\" wordExit={wordExit} numbers={numbers} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,MAAa,iBAAiB,UAC5B,WAAW,SAAS,iBAAiB,SAAS,WAAW;;AAG3D,SAAS,0BAA0B;CACjC,MAAM,QAAQ,kBAAkB,YAAY;CAC5C,MAAM,QAAQ,kBAAkB,YAAY;CAC5C,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;AAClF;;;;;;;AAQA,SAAgB,eAAe,EAC7B,SACA,IACA,aACA,SACA,aACA,SAQC;CACD,MAAM,YAAY,MAAM;CACxB,MAAM,SAAS,wBAAwB;CACvC,MAAM,SAAS,WAAW,CAAC;CAC3B,MAAM,YAAY,MAAM;CACxB,MAAM,SAAS,UAAU,cAAc,GAAG,UAAU,gBAAgB,KAAA;CACpE,MAAM,UAAU,UAAU,QAAQ,GAAG,UAAU,UAAU,KAAA;CACzD,OAAO;EACL;;EAEA;EACA;EACA;EACA;EACA,cAAc,SACV;GACE,IAAI;GACJ,gBAAgB,QAAQ,OAAO;GAC/B,oBAAoB;IAAC;IAAa;IAAQ;GAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA;EAClF,IACA,CAAC;CACP;AACF;;AAGA,SAAgB,WAAW,EACzB,OACA,WACA,aACA,QACA,OACA,SACA,UACA,SACA,WAAW,OACX,YAiBC;CACD,OACE,qBAAC,OAAD;EAAK,aAAU;EAAQ,WAAU;EAAjC,UAAA;GACG,SAAS,OAAO,OAEf,qBAACA,SAAD;IAAO,SAAS;IAAW,WAAU;IAArC,UAAA,CACG,OACA,WAAW,oBAAC,gBAAD,CAAiB,CAAA,IAAI,IAC5B;;GAER;GACD,oBAAC,cAAD;IACE,IAAI;IACJ,MAAM;IACN,MAAK;IACK;IACD;GACV,CAAA;GACD,oBAAC,cAAD;IAAc,IAAI;IAAS,MAAM;IAAO,MAAK;IAAkB;IAAmB;GAAU,CAAA;EACzF;;AAET"}
|
|
@@ -37,7 +37,28 @@ const fieldSurfaceVariants = cva([
|
|
|
37
37
|
"[&:has(:is(input,textarea,[role=spinbutton]):focus):not([data-invalid]):not(:where(.group[data-invalid]_*))]:border-foreground",
|
|
38
38
|
"data-[disabled]:cursor-not-allowed data-[disabled]:bg-muted data-[disabled]:opacity-(--opacity-disabled)"
|
|
39
39
|
]);
|
|
40
|
+
/**
|
|
41
|
+
* The control scale of a text entry box: height and inline padding from the
|
|
42
|
+
* `--density-control-*` tokens, the same three rungs as Button, so a field
|
|
43
|
+
* sits level with the buttons in its row. Input, Select and SearchField all
|
|
44
|
+
* read it, so the rungs cannot drift apart.
|
|
45
|
+
*/
|
|
46
|
+
const fieldBoxSize = {
|
|
47
|
+
sm: "h-(--density-control-h-sm) px-(--density-control-pad-sm)",
|
|
48
|
+
md: "h-(--density-control-h-md) px-(--density-control-pad-md)",
|
|
49
|
+
lg: "h-(--density-control-h-lg) px-(--density-control-pad-lg)"
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* The type rule that goes with `fieldBoxSize`: `sm` is 14px, except on a
|
|
53
|
+
* coarse pointer, where iOS would zoom a focused field under 16px; `md` and
|
|
54
|
+
* `lg` are 16px. See Input's `size` variant for the reasoning.
|
|
55
|
+
*/
|
|
56
|
+
const fieldTextSize = {
|
|
57
|
+
sm: "text-sm pointer-coarse:text-base",
|
|
58
|
+
md: "text-base",
|
|
59
|
+
lg: "text-base"
|
|
60
|
+
};
|
|
40
61
|
//#endregion
|
|
41
|
-
export { fieldSurfaceVariants };
|
|
62
|
+
export { fieldBoxSize, fieldSurfaceVariants, fieldTextSize };
|
|
42
63
|
|
|
43
64
|
//# sourceMappingURL=field-surface.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-surface.js","names":[],"sources":["../../src/lib/field-surface.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\n\n/**\n * The shared surface of a text entry control.\n *\n * Extracted at the Rule of Two, and for a reason the legacy demonstrates:\n * its `input.tsx` and `textarea.tsx` styled the same surface twice and had\n * already drifted. The input is `bg-transparent`, the textarea is\n * `bg-background`. The input focuses with `focus-visible:border-ring` plus a\n * 3px ring; the textarea uses a 2px ring with an offset. The input has\n * `aria-invalid` treatment, the textarea has none. None of those differences\n * is a decision anyone made -- they are two files edited at different times.\n *\n * Everything that must look identical between an Input and a Textarea lives\n * here. Only the box geometry differs, and that is the caller's variant.\n *\n * Every string is a STATIC literal. Tailwind scans source text, so a class\n * assembled at runtime is invisible to it and would never be emitted.\n */\nexport const fieldSurfaceVariants = cva([\n \"w-full min-w-0\",\n\n // The reset in @seekalfred/styles is OPT-IN, so a consumer may load none.\n // A bare <input> keeps the user-agent border, background and Arial face,\n // and content-box would add the padding on top of the width.\n \"box-border font-sans\",\n\n \"rounded-control border-(length:--border-width) border-border\",\n \"bg-surface text-foreground\",\n \"shadow-surface\",\n\n // --color-muted-foreground is 5.25:1 on the page, so the placeholder is\n // legible rather than the usual near-invisible grey. It is still text and\n // the contrast contract holds it to the 4.5 floor.\n \"placeholder:text-muted-foreground\",\n \"selection:bg-primary selection:text-primary-foreground\",\n\n // Only the two properties that change, on the settle curve: the border darkens\n // on hover and focus, and the background turns muted when disabled. The focus\n // outline is not animated (it switches between none and solid).\n \"motion-safe:transition-[border-color,background-color] motion-safe:duration-(--duration-quick) motion-safe:ease-settle\",\n\n // outline-solid is load-bearing. `outline-none` sets BOTH\n // outline-style:none and --tw-outline-style:none, and the width utility\n // resolves its style from that same variable -- so a focus rule can apply\n // a width and a colour while faithfully re-applying none, and paint\n // nothing. Button shipped exactly that.\n //\n // A text field shows focus on its own border (below), not a separate ring:\n // UX decision (Oct 2026). The outline comes back only under forced colours,\n // where a border colour is overridden and would leave no focus indicator.\n \"outline-none\",\n \"forced-colors:data-[focus-visible]:outline-solid\",\n \"forced-colors:data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"forced-colors:data-[focus-visible]:outline-offset-(--focus-ring-offset)\",\n\n // React Aria sets data-invalid from the native `aria-invalid` attribute,\n // so this costs no API surface and works both bare and inside a\n // TextField. destructive-strong rather than destructive: the fill token\n // is 2.44:1-class and cannot describe a boundary (WCAG 1.4.11).\n //\n // The border CHANGES COLOUR only. Colour alone is not a state cue\n // (WCAG 1.4.1), which is why an invalid field must also carry a message --\n // that is the consumer's job, and the migration table says so.\n \"data-[invalid]:border-destructive-strong\",\n\n // Hover and focus darken the border to border-strong, in addition to the\n // outline ring above (which stays: forced-colours drops a border colour, and\n // WCAG 2.4.7 wants a visible indicator). The conditions sit inside :where(),\n // which adds no specificity, so the invalid border always wins by specificity\n // rather than by the order Tailwind happens to emit utilities in -- on an\n // Input through data-[invalid], on a Select or DatePicker trigger through\n // group-data-[invalid], because their ROOT carries the state. A disabled field\n // does not darken: React Aria's TextArea still reports hover while disabled.\n \"[&:where([data-hovered]:not([data-disabled]))]:border-border-strong\",\n // Focus turns the border itself dark, same width, no gap. An invalid field\n // keeps its red border while focused.\n \"data-[focus-visible]:not-data-[invalid]:not-group-data-[invalid]:border-foreground\",\n // A mouse click into a text box is not \"focus-visible\" to React Aria, but the\n // border must still show focus: key off real focus on the input itself, or on\n // the input, textarea or date segment inside a wrapping box.\n \"[&:is(input,textarea):focus:not([data-invalid])]:border-foreground\",\n \"[&:has(:is(input,textarea,[role=spinbutton]):focus):not([data-invalid]):not(:where(.group[data-invalid]_*))]:border-foreground\",\n\n \"data-[disabled]:cursor-not-allowed data-[disabled]:bg-muted data-[disabled]:opacity-(--opacity-disabled)\",\n]);\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,MAAa,uBAAuB,IAAI;CACtC;CAKA;CAEA;CACA;CACA;CAKA;CACA;CAKA;CAWA;CACA;CACA;CACA;CAUA;CAUA;CAGA;CAIA;CACA;CAEA;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"field-surface.js","names":[],"sources":["../../src/lib/field-surface.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\n\n/**\n * The shared surface of a text entry control.\n *\n * Extracted at the Rule of Two, and for a reason the legacy demonstrates:\n * its `input.tsx` and `textarea.tsx` styled the same surface twice and had\n * already drifted. The input is `bg-transparent`, the textarea is\n * `bg-background`. The input focuses with `focus-visible:border-ring` plus a\n * 3px ring; the textarea uses a 2px ring with an offset. The input has\n * `aria-invalid` treatment, the textarea has none. None of those differences\n * is a decision anyone made -- they are two files edited at different times.\n *\n * Everything that must look identical between an Input and a Textarea lives\n * here. Only the box geometry differs, and that is the caller's variant.\n *\n * Every string is a STATIC literal. Tailwind scans source text, so a class\n * assembled at runtime is invisible to it and would never be emitted.\n */\nexport const fieldSurfaceVariants = cva([\n \"w-full min-w-0\",\n\n // The reset in @seekalfred/styles is OPT-IN, so a consumer may load none.\n // A bare <input> keeps the user-agent border, background and Arial face,\n // and content-box would add the padding on top of the width.\n \"box-border font-sans\",\n\n \"rounded-control border-(length:--border-width) border-border\",\n \"bg-surface text-foreground\",\n \"shadow-surface\",\n\n // --color-muted-foreground is 5.25:1 on the page, so the placeholder is\n // legible rather than the usual near-invisible grey. It is still text and\n // the contrast contract holds it to the 4.5 floor.\n \"placeholder:text-muted-foreground\",\n \"selection:bg-primary selection:text-primary-foreground\",\n\n // Only the two properties that change, on the settle curve: the border darkens\n // on hover and focus, and the background turns muted when disabled. The focus\n // outline is not animated (it switches between none and solid).\n \"motion-safe:transition-[border-color,background-color] motion-safe:duration-(--duration-quick) motion-safe:ease-settle\",\n\n // outline-solid is load-bearing. `outline-none` sets BOTH\n // outline-style:none and --tw-outline-style:none, and the width utility\n // resolves its style from that same variable -- so a focus rule can apply\n // a width and a colour while faithfully re-applying none, and paint\n // nothing. Button shipped exactly that.\n //\n // A text field shows focus on its own border (below), not a separate ring:\n // UX decision (Oct 2026). The outline comes back only under forced colours,\n // where a border colour is overridden and would leave no focus indicator.\n \"outline-none\",\n \"forced-colors:data-[focus-visible]:outline-solid\",\n \"forced-colors:data-[focus-visible]:outline-(length:--focus-ring-width)\",\n \"forced-colors:data-[focus-visible]:outline-offset-(--focus-ring-offset)\",\n\n // React Aria sets data-invalid from the native `aria-invalid` attribute,\n // so this costs no API surface and works both bare and inside a\n // TextField. destructive-strong rather than destructive: the fill token\n // is 2.44:1-class and cannot describe a boundary (WCAG 1.4.11).\n //\n // The border CHANGES COLOUR only. Colour alone is not a state cue\n // (WCAG 1.4.1), which is why an invalid field must also carry a message --\n // that is the consumer's job, and the migration table says so.\n \"data-[invalid]:border-destructive-strong\",\n\n // Hover and focus darken the border to border-strong, in addition to the\n // outline ring above (which stays: forced-colours drops a border colour, and\n // WCAG 2.4.7 wants a visible indicator). The conditions sit inside :where(),\n // which adds no specificity, so the invalid border always wins by specificity\n // rather than by the order Tailwind happens to emit utilities in -- on an\n // Input through data-[invalid], on a Select or DatePicker trigger through\n // group-data-[invalid], because their ROOT carries the state. A disabled field\n // does not darken: React Aria's TextArea still reports hover while disabled.\n \"[&:where([data-hovered]:not([data-disabled]))]:border-border-strong\",\n // Focus turns the border itself dark, same width, no gap. An invalid field\n // keeps its red border while focused.\n \"data-[focus-visible]:not-data-[invalid]:not-group-data-[invalid]:border-foreground\",\n // A mouse click into a text box is not \"focus-visible\" to React Aria, but the\n // border must still show focus: key off real focus on the input itself, or on\n // the input, textarea or date segment inside a wrapping box.\n \"[&:is(input,textarea):focus:not([data-invalid])]:border-foreground\",\n \"[&:has(:is(input,textarea,[role=spinbutton]):focus):not([data-invalid]):not(:where(.group[data-invalid]_*))]:border-foreground\",\n\n \"data-[disabled]:cursor-not-allowed data-[disabled]:bg-muted data-[disabled]:opacity-(--opacity-disabled)\",\n]);\n\n/**\n * The control scale of a text entry box: height and inline padding from the\n * `--density-control-*` tokens, the same three rungs as Button, so a field\n * sits level with the buttons in its row. Input, Select and SearchField all\n * read it, so the rungs cannot drift apart.\n */\nexport const fieldBoxSize = {\n sm: \"h-(--density-control-h-sm) px-(--density-control-pad-sm)\",\n md: \"h-(--density-control-h-md) px-(--density-control-pad-md)\",\n lg: \"h-(--density-control-h-lg) px-(--density-control-pad-lg)\",\n} as const;\n\n/**\n * The type rule that goes with `fieldBoxSize`: `sm` is 14px, except on a\n * coarse pointer, where iOS would zoom a focused field under 16px; `md` and\n * `lg` are 16px. See Input's `size` variant for the reasoning.\n */\nexport const fieldTextSize = {\n sm: \"text-sm pointer-coarse:text-base\",\n md: \"text-base\",\n lg: \"text-base\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,MAAa,uBAAuB,IAAI;CACtC;CAKA;CAEA;CACA;CACA;CAKA;CACA;CAKA;CAWA;CACA;CACA;CACA;CAUA;CAUA;CAGA;CAIA;CACA;CAEA;AACF,CAAC;;;;;;;AAQD,MAAa,eAAe;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;;;;;;AAOA,MAAa,gBAAgB;CAC3B,IAAI;CACJ,IAAI;CACJ,IAAI;AACN"}
|