@particle-academy/react-fancy 5.57.0 → 5.58.0

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/CHANGELOG.md CHANGED
@@ -11,6 +11,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.58.0] - 2026-10-22
15
+
16
+ ### Added
17
+
18
+ - **`MultiSwitch` per-option colour.** An option in `list` can carry
19
+ `color` (any kit `Color`, including `brand`). While that option is
20
+ selected, the thumb and the switch's border take its colour, e.g. a green
21
+ "Assign" against a red "Unassign". **Nothing to do for an existing switch:**
22
+ without `color` the thumb is the same blue, the border the same token, and
23
+ the thumb's class string is byte-identical to 5.57.0.
24
+ - Light hues (`amber`, `yellow`, `lime`) get dark label text so the selected
25
+ label stays readable; the rest get white, as before.
26
+ - The thumb now carries `data-react-fancy-multi-switch-thumb` and, when
27
+ coloured, `data-color`.
28
+ - A caller's own border classes in `className` still win over the colour.
29
+ - New exported type `MultiSwitchOption` (an `InputOption` plus `color`).
30
+ - Verified in Chrome in light, `.dark` and `[data-theme="dark"]`.
31
+
14
32
  ## [5.57.0] - 2026-10-22
15
33
 
16
34
  ### Added
@@ -11,6 +11,35 @@ var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
11
11
  var react = require('react');
12
12
  var jsxRuntime = require('react/jsx-runtime');
13
13
 
14
+ // src/components/inputs/MultiSwitch/MultiSwitch.colors.ts
15
+ var multiSwitchColorClasses = {
16
+ // The host's colour, from CSS variables -- no dark: variant, because a
17
+ // host that themes per mode scopes the variables themselves.
18
+ brand: { thumb: "bg-brand", text: "text-brand-contrast", border: "border-brand" },
19
+ slate: { thumb: "bg-slate-600 dark:bg-slate-500", text: "text-white", border: "border-slate-500 dark:border-slate-400" },
20
+ gray: { thumb: "bg-gray-600 dark:bg-gray-500", text: "text-white", border: "border-gray-500 dark:border-gray-400" },
21
+ zinc: { thumb: "bg-zinc-600 dark:bg-zinc-500", text: "text-white", border: "border-zinc-500 dark:border-zinc-400" },
22
+ neutral: { thumb: "bg-neutral-600 dark:bg-neutral-500", text: "text-white", border: "border-neutral-500 dark:border-neutral-400" },
23
+ stone: { thumb: "bg-stone-600 dark:bg-stone-500", text: "text-white", border: "border-stone-500 dark:border-stone-400" },
24
+ red: { thumb: "bg-red-600 dark:bg-red-500", text: "text-white", border: "border-red-500 dark:border-red-400" },
25
+ orange: { thumb: "bg-orange-600 dark:bg-orange-500", text: "text-white", border: "border-orange-500 dark:border-orange-400" },
26
+ amber: { thumb: "bg-amber-400 dark:bg-amber-300", text: "text-amber-950", border: "border-amber-500 dark:border-amber-400" },
27
+ yellow: { thumb: "bg-yellow-400 dark:bg-yellow-300", text: "text-yellow-950", border: "border-yellow-500 dark:border-yellow-400" },
28
+ lime: { thumb: "bg-lime-400 dark:bg-lime-300", text: "text-lime-950", border: "border-lime-500 dark:border-lime-400" },
29
+ green: { thumb: "bg-green-600 dark:bg-green-500", text: "text-white", border: "border-green-500 dark:border-green-400" },
30
+ emerald: { thumb: "bg-emerald-600 dark:bg-emerald-500", text: "text-white", border: "border-emerald-500 dark:border-emerald-400" },
31
+ teal: { thumb: "bg-teal-600 dark:bg-teal-500", text: "text-white", border: "border-teal-500 dark:border-teal-400" },
32
+ cyan: { thumb: "bg-cyan-600 dark:bg-cyan-500", text: "text-white", border: "border-cyan-500 dark:border-cyan-400" },
33
+ sky: { thumb: "bg-sky-600 dark:bg-sky-500", text: "text-white", border: "border-sky-500 dark:border-sky-400" },
34
+ blue: { thumb: "bg-blue-600 dark:bg-blue-500", text: "text-white", border: "border-blue-500 dark:border-blue-400" },
35
+ indigo: { thumb: "bg-indigo-600 dark:bg-indigo-500", text: "text-white", border: "border-indigo-500 dark:border-indigo-400" },
36
+ violet: { thumb: "bg-violet-600 dark:bg-violet-500", text: "text-white", border: "border-violet-500 dark:border-violet-400" },
37
+ purple: { thumb: "bg-purple-600 dark:bg-purple-500", text: "text-white", border: "border-purple-500 dark:border-purple-400" },
38
+ fuchsia: { thumb: "bg-fuchsia-600 dark:bg-fuchsia-500", text: "text-white", border: "border-fuchsia-500 dark:border-fuchsia-400" },
39
+ pink: { thumb: "bg-pink-600 dark:bg-pink-500", text: "text-white", border: "border-pink-500 dark:border-pink-400" },
40
+ rose: { thumb: "bg-rose-600 dark:bg-rose-500", text: "text-white", border: "border-rose-500 dark:border-rose-400" }
41
+ };
42
+ var BORDER_DEFAULT = "border-[color:var(--fancy-border-strong,var(--color-zinc-300))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))]";
14
43
  var sizeClasses = {
15
44
  xs: "px-2 py-1 text-xs",
16
45
  sm: "px-2.5 py-1.5 text-sm",
@@ -53,6 +82,8 @@ function MultiSwitch({
53
82
  const selectedIndex = resolvedOptions.findIndex(
54
83
  (o) => o.value === value
55
84
  );
85
+ const selectedColor = resolvedOptions[selectedIndex]?.color;
86
+ const colorClasses = selectedColor ? multiSwitchColorClasses[selectedColor] : void 0;
56
87
  const updateIndicator = react.useCallback(() => {
57
88
  const container = containerRef.current;
58
89
  const activeItem = itemRefs.current[selectedIndex];
@@ -83,7 +114,8 @@ function MultiSwitch({
83
114
  if (interactive && !e.currentTarget.contains(e.relatedTarget)) exitEdit();
84
115
  },
85
116
  className: chunkZU5Q77OT_cjs.cn(
86
- "relative inline-flex rounded-lg border border-[color:var(--fancy-border-strong,var(--color-zinc-300))] bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]",
117
+ "relative inline-flex rounded-lg border bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]",
118
+ colorClasses ? colorClasses.border : BORDER_DEFAULT,
87
119
  dirty && "ring-2 ring-amber-400/50",
88
120
  error && "ring-2 ring-red-500/50",
89
121
  disabled && "opacity-50 cursor-not-allowed",
@@ -93,7 +125,9 @@ function MultiSwitch({
93
125
  indicator && /* @__PURE__ */ jsxRuntime.jsx(
94
126
  "span",
95
127
  {
96
- className: "absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out",
128
+ "data-react-fancy-multi-switch-thumb": "",
129
+ "data-color": selectedColor,
130
+ className: colorClasses ? `absolute top-0 bottom-0 rounded-lg ${colorClasses.thumb} transition-all duration-200 ease-out` : "absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out",
97
131
  style: { left: indicator.left, width: indicator.width }
98
132
  }
99
133
  ),
@@ -121,7 +155,7 @@ function MultiSwitch({
121
155
  className: chunkZU5Q77OT_cjs.cn(
122
156
  "relative z-10 font-medium transition-colors duration-200",
123
157
  sizeClasses[size],
124
- isSelected ? "text-white" : "text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]",
158
+ isSelected ? colorClasses?.text ?? "text-white" : "text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]",
125
159
  (disabled || option.disabled) && "cursor-not-allowed"
126
160
  ),
127
161
  children: option.label
@@ -154,5 +188,5 @@ function MultiSwitch({
154
188
  MultiSwitch.displayName = "MultiSwitch";
155
189
 
156
190
  exports.MultiSwitch = MultiSwitch;
157
- //# sourceMappingURL=chunk-WUG646R4.cjs.map
158
- //# sourceMappingURL=chunk-WUG646R4.cjs.map
191
+ //# sourceMappingURL=chunk-IB673TEG.cjs.map
192
+ //# sourceMappingURL=chunk-IB673TEG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/inputs/MultiSwitch/MultiSwitch.colors.ts","../src/components/inputs/MultiSwitch/MultiSwitch.tsx"],"names":["useId","resolveOption","useFieldMode","useInlineEdit","useControllableState","useRef","useMemo","composeRefs","useState","useCallback","useEffect","DisplayValue","jsxs","cn","jsx","Field"],"mappings":"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","file":"chunk-IB673TEG.cjs","sourcesContent":["// Literal Tailwind class strings for every color in the v4 palette so the\n// scanner can detect them in the published dist (template-built names are\n// invisible to Tailwind's JIT). Shades follow badgeSolid: 600 / dark 500 for\n// the thumb, with dark label text on the light hues (amber, yellow, lime).\nimport type { Color } from \"../../../utils/types\";\n\nexport type MultiSwitchColorClasses = {\n /** The selected thumb's fill. */\n thumb: string;\n /** The selected option's label, readable on the thumb. */\n text: string;\n /** The container border while this option is selected. */\n border: string;\n};\n\nexport const multiSwitchColorClasses: Record<Color, MultiSwitchColorClasses> = {\n // The host's colour, from CSS variables -- no dark: variant, because a\n // host that themes per mode scopes the variables themselves.\n brand: { thumb: \"bg-brand\", text: \"text-brand-contrast\", border: \"border-brand\" },\n slate: { thumb: \"bg-slate-600 dark:bg-slate-500\", text: \"text-white\", border: \"border-slate-500 dark:border-slate-400\" },\n gray: { thumb: \"bg-gray-600 dark:bg-gray-500\", text: \"text-white\", border: \"border-gray-500 dark:border-gray-400\" },\n zinc: { thumb: \"bg-zinc-600 dark:bg-zinc-500\", text: \"text-white\", border: \"border-zinc-500 dark:border-zinc-400\" },\n neutral: { thumb: \"bg-neutral-600 dark:bg-neutral-500\", text: \"text-white\", border: \"border-neutral-500 dark:border-neutral-400\" },\n stone: { thumb: \"bg-stone-600 dark:bg-stone-500\", text: \"text-white\", border: \"border-stone-500 dark:border-stone-400\" },\n red: { thumb: \"bg-red-600 dark:bg-red-500\", text: \"text-white\", border: \"border-red-500 dark:border-red-400\" },\n orange: { thumb: \"bg-orange-600 dark:bg-orange-500\", text: \"text-white\", border: \"border-orange-500 dark:border-orange-400\" },\n amber: { thumb: \"bg-amber-400 dark:bg-amber-300\", text: \"text-amber-950\", border: \"border-amber-500 dark:border-amber-400\" },\n yellow: { thumb: \"bg-yellow-400 dark:bg-yellow-300\", text: \"text-yellow-950\", border: \"border-yellow-500 dark:border-yellow-400\" },\n lime: { thumb: \"bg-lime-400 dark:bg-lime-300\", text: \"text-lime-950\", border: \"border-lime-500 dark:border-lime-400\" },\n green: { thumb: \"bg-green-600 dark:bg-green-500\", text: \"text-white\", border: \"border-green-500 dark:border-green-400\" },\n emerald: { thumb: \"bg-emerald-600 dark:bg-emerald-500\", text: \"text-white\", border: \"border-emerald-500 dark:border-emerald-400\" },\n teal: { thumb: \"bg-teal-600 dark:bg-teal-500\", text: \"text-white\", border: \"border-teal-500 dark:border-teal-400\" },\n cyan: { thumb: \"bg-cyan-600 dark:bg-cyan-500\", text: \"text-white\", border: \"border-cyan-500 dark:border-cyan-400\" },\n sky: { thumb: \"bg-sky-600 dark:bg-sky-500\", text: \"text-white\", border: \"border-sky-500 dark:border-sky-400\" },\n blue: { thumb: \"bg-blue-600 dark:bg-blue-500\", text: \"text-white\", border: \"border-blue-500 dark:border-blue-400\" },\n indigo: { thumb: \"bg-indigo-600 dark:bg-indigo-500\", text: \"text-white\", border: \"border-indigo-500 dark:border-indigo-400\" },\n violet: { thumb: \"bg-violet-600 dark:bg-violet-500\", text: \"text-white\", border: \"border-violet-500 dark:border-violet-400\" },\n purple: { thumb: \"bg-purple-600 dark:bg-purple-500\", text: \"text-white\", border: \"border-purple-500 dark:border-purple-400\" },\n fuchsia: { thumb: \"bg-fuchsia-600 dark:bg-fuchsia-500\", text: \"text-white\", border: \"border-fuchsia-500 dark:border-fuchsia-400\" },\n pink: { thumb: \"bg-pink-600 dark:bg-pink-500\", text: \"text-white\", border: \"border-pink-500 dark:border-pink-400\" },\n rose: { thumb: \"bg-rose-600 dark:bg-rose-500\", text: \"text-white\", border: \"border-rose-500 dark:border-rose-400\" },\n};\n","import { useRef, useState, useEffect, useCallback, useId, useMemo, type Ref } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { composeRefs } from \"../../../utils/compose-refs\";\nimport { useControllableState } from \"../../../hooks/use-controllable-state\";\nimport { Field } from \"../Field\";\nimport { useFieldMode } from \"../mode/FieldMode.context\";\nimport { DisplayValue } from \"../mode/DisplayValue\";\nimport { useInlineEdit } from \"../mode/useInlineEdit\";\nimport { resolveOption } from \"../inputs.utils\";\nimport type { Color, Size } from \"../../../utils/types\";\nimport type { MultiSwitchProps } from \"./MultiSwitch.types\";\nimport { multiSwitchColorClasses } from \"./MultiSwitch.colors\";\n\nconst BORDER_DEFAULT =\n \"border-[color:var(--fancy-border-strong,var(--color-zinc-300))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))]\";\n\nconst sizeClasses: Record<Size, string> = {\n xs: \"px-2 py-1 text-xs\",\n sm: \"px-2.5 py-1.5 text-sm\",\n md: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-2.5 text-base\",\n xl: \"px-5 py-3 text-lg\",\n};\n\nexport function MultiSwitch<V = string>({\n size = \"md\",\n dirty,\n error,\n label,\n labelHidden,\n description,\n required,\n disabled,\n className,\n id,\n name,\n list,\n value: controlledValue,\n defaultValue,\n onValueChange,\n linear,\n mode,\n ...rest\n}: MultiSwitchProps<V>) {\n const reactId = useId();\n // A `<label for>` cannot name a div[role=\"radiogroup\"], so the group points at\n // the label instead. Needs an id the label and the group both agree on.\n const labelId = label ? `${id ?? reactId}-label` : undefined;\n\n // resolveOption hands an object option back as-is, so `color` survives it.\n const resolvedOptions = list.map(resolveOption) as Array<\n ReturnType<typeof resolveOption<V>> & { color?: Color }\n >;\n const fallback = defaultValue ?? resolvedOptions[0]?.value;\n const resolvedMode = useFieldMode(mode);\n const { showControl, interactive, enterEdit, exitEdit } = useInlineEdit(resolvedMode, disabled);\n const [value, setValue] = useControllableState(controlledValue, fallback as V, onValueChange);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const externalRef = (rest as { ref?: Ref<HTMLDivElement> }).ref;\n const containerSetRef = useMemo(() => composeRefs(externalRef, containerRef), [externalRef]);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null);\n\n const selectedIndex = resolvedOptions.findIndex(\n (o) => o.value === value,\n );\n const selectedColor = resolvedOptions[selectedIndex]?.color;\n const colorClasses = selectedColor ? multiSwitchColorClasses[selectedColor] : undefined;\n\n const updateIndicator = useCallback(() => {\n const container = containerRef.current;\n const activeItem = itemRefs.current[selectedIndex];\n if (!container || !activeItem) {\n setIndicator(null);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const itemRect = activeItem.getBoundingClientRect();\n setIndicator({\n left: itemRect.left - containerRect.left,\n width: itemRect.width,\n });\n }, [selectedIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n const control = !showControl ? (\n <DisplayValue size={size} interactive={interactive} onActivate={enterEdit}>\n {resolvedOptions.find((o) => o.value === value)?.label}\n </DisplayValue>\n ) : (\n <div\n {...rest}\n // React 19 passes `ref` to a function component as a plain prop, so a\n // caller's ref (Tooltip's anchor, or anyone's) arrives in `rest`. Spread\n // after `ref={containerRef}` it REPLACED the ref the thumb is measured\n // from, and the selected thumb never rendered. Feed both instead.\n ref={containerSetRef}\n data-react-fancy-multi-switch=\"\"\n role=\"radiogroup\"\n id={id}\n aria-labelledby={labelId}\n onBlur={(e) => {\n if (interactive && !e.currentTarget.contains(e.relatedTarget as Node)) exitEdit();\n }}\n className={cn(\n \"relative inline-flex rounded-lg border bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n colorClasses ? colorClasses.border : BORDER_DEFAULT,\n dirty && \"ring-2 ring-amber-400/50\",\n error && \"ring-2 ring-red-500/50\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {indicator && (\n <span\n data-react-fancy-multi-switch-thumb=\"\"\n data-color={selectedColor}\n className={\n colorClasses\n ? `absolute top-0 bottom-0 rounded-lg ${colorClasses.thumb} transition-all duration-200 ease-out`\n : \"absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out\"\n }\n style={{ left: indicator.left, width: indicator.width }}\n />\n )}\n {resolvedOptions.map((option, index) => {\n const isSelected = option.value === value;\n return (\n <button\n key={String(option.value)}\n ref={(el) => { itemRefs.current[index] = el; }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n disabled={disabled || option.disabled}\n autoFocus={interactive && (selectedIndex === -1 ? index === 0 : isSelected)}\n onClick={() => {\n if (linear) {\n const nextIndex = (selectedIndex + 1) % resolvedOptions.length;\n setValue(resolvedOptions[nextIndex].value as V);\n } else {\n setValue(option.value as V);\n }\n }}\n className={cn(\n \"relative z-10 font-medium transition-colors duration-200\",\n sizeClasses[size],\n isSelected\n ? (colorClasses?.text ?? \"text-white\")\n : \"text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]\",\n (disabled || option.disabled) && \"cursor-not-allowed\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n {name && <input type=\"hidden\" name={name} value={String(value)} />}\n </div>\n );\n\n if (label || error || description) {\n return (\n <Field\n label={label}\n labelHidden={labelHidden}\n labelId={labelId}\n description={description}\n error={error}\n required={required}\n htmlFor={id}\n size={size}\n >\n {control}\n </Field>\n );\n }\n\n return control;\n}\n\nMultiSwitch.displayName = \"MultiSwitch\";\n"]}
@@ -9,6 +9,35 @@ import { cn } from './chunk-MMW2JGKZ.js';
9
9
  import { useId, useRef, useMemo, useState, useCallback, useEffect } from 'react';
10
10
  import { jsx, jsxs } from 'react/jsx-runtime';
11
11
 
12
+ // src/components/inputs/MultiSwitch/MultiSwitch.colors.ts
13
+ var multiSwitchColorClasses = {
14
+ // The host's colour, from CSS variables -- no dark: variant, because a
15
+ // host that themes per mode scopes the variables themselves.
16
+ brand: { thumb: "bg-brand", text: "text-brand-contrast", border: "border-brand" },
17
+ slate: { thumb: "bg-slate-600 dark:bg-slate-500", text: "text-white", border: "border-slate-500 dark:border-slate-400" },
18
+ gray: { thumb: "bg-gray-600 dark:bg-gray-500", text: "text-white", border: "border-gray-500 dark:border-gray-400" },
19
+ zinc: { thumb: "bg-zinc-600 dark:bg-zinc-500", text: "text-white", border: "border-zinc-500 dark:border-zinc-400" },
20
+ neutral: { thumb: "bg-neutral-600 dark:bg-neutral-500", text: "text-white", border: "border-neutral-500 dark:border-neutral-400" },
21
+ stone: { thumb: "bg-stone-600 dark:bg-stone-500", text: "text-white", border: "border-stone-500 dark:border-stone-400" },
22
+ red: { thumb: "bg-red-600 dark:bg-red-500", text: "text-white", border: "border-red-500 dark:border-red-400" },
23
+ orange: { thumb: "bg-orange-600 dark:bg-orange-500", text: "text-white", border: "border-orange-500 dark:border-orange-400" },
24
+ amber: { thumb: "bg-amber-400 dark:bg-amber-300", text: "text-amber-950", border: "border-amber-500 dark:border-amber-400" },
25
+ yellow: { thumb: "bg-yellow-400 dark:bg-yellow-300", text: "text-yellow-950", border: "border-yellow-500 dark:border-yellow-400" },
26
+ lime: { thumb: "bg-lime-400 dark:bg-lime-300", text: "text-lime-950", border: "border-lime-500 dark:border-lime-400" },
27
+ green: { thumb: "bg-green-600 dark:bg-green-500", text: "text-white", border: "border-green-500 dark:border-green-400" },
28
+ emerald: { thumb: "bg-emerald-600 dark:bg-emerald-500", text: "text-white", border: "border-emerald-500 dark:border-emerald-400" },
29
+ teal: { thumb: "bg-teal-600 dark:bg-teal-500", text: "text-white", border: "border-teal-500 dark:border-teal-400" },
30
+ cyan: { thumb: "bg-cyan-600 dark:bg-cyan-500", text: "text-white", border: "border-cyan-500 dark:border-cyan-400" },
31
+ sky: { thumb: "bg-sky-600 dark:bg-sky-500", text: "text-white", border: "border-sky-500 dark:border-sky-400" },
32
+ blue: { thumb: "bg-blue-600 dark:bg-blue-500", text: "text-white", border: "border-blue-500 dark:border-blue-400" },
33
+ indigo: { thumb: "bg-indigo-600 dark:bg-indigo-500", text: "text-white", border: "border-indigo-500 dark:border-indigo-400" },
34
+ violet: { thumb: "bg-violet-600 dark:bg-violet-500", text: "text-white", border: "border-violet-500 dark:border-violet-400" },
35
+ purple: { thumb: "bg-purple-600 dark:bg-purple-500", text: "text-white", border: "border-purple-500 dark:border-purple-400" },
36
+ fuchsia: { thumb: "bg-fuchsia-600 dark:bg-fuchsia-500", text: "text-white", border: "border-fuchsia-500 dark:border-fuchsia-400" },
37
+ pink: { thumb: "bg-pink-600 dark:bg-pink-500", text: "text-white", border: "border-pink-500 dark:border-pink-400" },
38
+ rose: { thumb: "bg-rose-600 dark:bg-rose-500", text: "text-white", border: "border-rose-500 dark:border-rose-400" }
39
+ };
40
+ var BORDER_DEFAULT = "border-[color:var(--fancy-border-strong,var(--color-zinc-300))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))]";
12
41
  var sizeClasses = {
13
42
  xs: "px-2 py-1 text-xs",
14
43
  sm: "px-2.5 py-1.5 text-sm",
@@ -51,6 +80,8 @@ function MultiSwitch({
51
80
  const selectedIndex = resolvedOptions.findIndex(
52
81
  (o) => o.value === value
53
82
  );
83
+ const selectedColor = resolvedOptions[selectedIndex]?.color;
84
+ const colorClasses = selectedColor ? multiSwitchColorClasses[selectedColor] : void 0;
54
85
  const updateIndicator = useCallback(() => {
55
86
  const container = containerRef.current;
56
87
  const activeItem = itemRefs.current[selectedIndex];
@@ -81,7 +112,8 @@ function MultiSwitch({
81
112
  if (interactive && !e.currentTarget.contains(e.relatedTarget)) exitEdit();
82
113
  },
83
114
  className: cn(
84
- "relative inline-flex rounded-lg border border-[color:var(--fancy-border-strong,var(--color-zinc-300))] bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]",
115
+ "relative inline-flex rounded-lg border bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]",
116
+ colorClasses ? colorClasses.border : BORDER_DEFAULT,
85
117
  dirty && "ring-2 ring-amber-400/50",
86
118
  error && "ring-2 ring-red-500/50",
87
119
  disabled && "opacity-50 cursor-not-allowed",
@@ -91,7 +123,9 @@ function MultiSwitch({
91
123
  indicator && /* @__PURE__ */ jsx(
92
124
  "span",
93
125
  {
94
- className: "absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out",
126
+ "data-react-fancy-multi-switch-thumb": "",
127
+ "data-color": selectedColor,
128
+ className: colorClasses ? `absolute top-0 bottom-0 rounded-lg ${colorClasses.thumb} transition-all duration-200 ease-out` : "absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out",
95
129
  style: { left: indicator.left, width: indicator.width }
96
130
  }
97
131
  ),
@@ -119,7 +153,7 @@ function MultiSwitch({
119
153
  className: cn(
120
154
  "relative z-10 font-medium transition-colors duration-200",
121
155
  sizeClasses[size],
122
- isSelected ? "text-white" : "text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]",
156
+ isSelected ? colorClasses?.text ?? "text-white" : "text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]",
123
157
  (disabled || option.disabled) && "cursor-not-allowed"
124
158
  ),
125
159
  children: option.label
@@ -152,5 +186,5 @@ function MultiSwitch({
152
186
  MultiSwitch.displayName = "MultiSwitch";
153
187
 
154
188
  export { MultiSwitch };
155
- //# sourceMappingURL=chunk-KUJ5XRBD.js.map
156
- //# sourceMappingURL=chunk-KUJ5XRBD.js.map
189
+ //# sourceMappingURL=chunk-YUNOVQQJ.js.map
190
+ //# sourceMappingURL=chunk-YUNOVQQJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/inputs/MultiSwitch/MultiSwitch.colors.ts","../src/components/inputs/MultiSwitch/MultiSwitch.tsx"],"names":[],"mappings":"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","file":"chunk-YUNOVQQJ.js","sourcesContent":["// Literal Tailwind class strings for every color in the v4 palette so the\n// scanner can detect them in the published dist (template-built names are\n// invisible to Tailwind's JIT). Shades follow badgeSolid: 600 / dark 500 for\n// the thumb, with dark label text on the light hues (amber, yellow, lime).\nimport type { Color } from \"../../../utils/types\";\n\nexport type MultiSwitchColorClasses = {\n /** The selected thumb's fill. */\n thumb: string;\n /** The selected option's label, readable on the thumb. */\n text: string;\n /** The container border while this option is selected. */\n border: string;\n};\n\nexport const multiSwitchColorClasses: Record<Color, MultiSwitchColorClasses> = {\n // The host's colour, from CSS variables -- no dark: variant, because a\n // host that themes per mode scopes the variables themselves.\n brand: { thumb: \"bg-brand\", text: \"text-brand-contrast\", border: \"border-brand\" },\n slate: { thumb: \"bg-slate-600 dark:bg-slate-500\", text: \"text-white\", border: \"border-slate-500 dark:border-slate-400\" },\n gray: { thumb: \"bg-gray-600 dark:bg-gray-500\", text: \"text-white\", border: \"border-gray-500 dark:border-gray-400\" },\n zinc: { thumb: \"bg-zinc-600 dark:bg-zinc-500\", text: \"text-white\", border: \"border-zinc-500 dark:border-zinc-400\" },\n neutral: { thumb: \"bg-neutral-600 dark:bg-neutral-500\", text: \"text-white\", border: \"border-neutral-500 dark:border-neutral-400\" },\n stone: { thumb: \"bg-stone-600 dark:bg-stone-500\", text: \"text-white\", border: \"border-stone-500 dark:border-stone-400\" },\n red: { thumb: \"bg-red-600 dark:bg-red-500\", text: \"text-white\", border: \"border-red-500 dark:border-red-400\" },\n orange: { thumb: \"bg-orange-600 dark:bg-orange-500\", text: \"text-white\", border: \"border-orange-500 dark:border-orange-400\" },\n amber: { thumb: \"bg-amber-400 dark:bg-amber-300\", text: \"text-amber-950\", border: \"border-amber-500 dark:border-amber-400\" },\n yellow: { thumb: \"bg-yellow-400 dark:bg-yellow-300\", text: \"text-yellow-950\", border: \"border-yellow-500 dark:border-yellow-400\" },\n lime: { thumb: \"bg-lime-400 dark:bg-lime-300\", text: \"text-lime-950\", border: \"border-lime-500 dark:border-lime-400\" },\n green: { thumb: \"bg-green-600 dark:bg-green-500\", text: \"text-white\", border: \"border-green-500 dark:border-green-400\" },\n emerald: { thumb: \"bg-emerald-600 dark:bg-emerald-500\", text: \"text-white\", border: \"border-emerald-500 dark:border-emerald-400\" },\n teal: { thumb: \"bg-teal-600 dark:bg-teal-500\", text: \"text-white\", border: \"border-teal-500 dark:border-teal-400\" },\n cyan: { thumb: \"bg-cyan-600 dark:bg-cyan-500\", text: \"text-white\", border: \"border-cyan-500 dark:border-cyan-400\" },\n sky: { thumb: \"bg-sky-600 dark:bg-sky-500\", text: \"text-white\", border: \"border-sky-500 dark:border-sky-400\" },\n blue: { thumb: \"bg-blue-600 dark:bg-blue-500\", text: \"text-white\", border: \"border-blue-500 dark:border-blue-400\" },\n indigo: { thumb: \"bg-indigo-600 dark:bg-indigo-500\", text: \"text-white\", border: \"border-indigo-500 dark:border-indigo-400\" },\n violet: { thumb: \"bg-violet-600 dark:bg-violet-500\", text: \"text-white\", border: \"border-violet-500 dark:border-violet-400\" },\n purple: { thumb: \"bg-purple-600 dark:bg-purple-500\", text: \"text-white\", border: \"border-purple-500 dark:border-purple-400\" },\n fuchsia: { thumb: \"bg-fuchsia-600 dark:bg-fuchsia-500\", text: \"text-white\", border: \"border-fuchsia-500 dark:border-fuchsia-400\" },\n pink: { thumb: \"bg-pink-600 dark:bg-pink-500\", text: \"text-white\", border: \"border-pink-500 dark:border-pink-400\" },\n rose: { thumb: \"bg-rose-600 dark:bg-rose-500\", text: \"text-white\", border: \"border-rose-500 dark:border-rose-400\" },\n};\n","import { useRef, useState, useEffect, useCallback, useId, useMemo, type Ref } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { composeRefs } from \"../../../utils/compose-refs\";\nimport { useControllableState } from \"../../../hooks/use-controllable-state\";\nimport { Field } from \"../Field\";\nimport { useFieldMode } from \"../mode/FieldMode.context\";\nimport { DisplayValue } from \"../mode/DisplayValue\";\nimport { useInlineEdit } from \"../mode/useInlineEdit\";\nimport { resolveOption } from \"../inputs.utils\";\nimport type { Color, Size } from \"../../../utils/types\";\nimport type { MultiSwitchProps } from \"./MultiSwitch.types\";\nimport { multiSwitchColorClasses } from \"./MultiSwitch.colors\";\n\nconst BORDER_DEFAULT =\n \"border-[color:var(--fancy-border-strong,var(--color-zinc-300))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))]\";\n\nconst sizeClasses: Record<Size, string> = {\n xs: \"px-2 py-1 text-xs\",\n sm: \"px-2.5 py-1.5 text-sm\",\n md: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-2.5 text-base\",\n xl: \"px-5 py-3 text-lg\",\n};\n\nexport function MultiSwitch<V = string>({\n size = \"md\",\n dirty,\n error,\n label,\n labelHidden,\n description,\n required,\n disabled,\n className,\n id,\n name,\n list,\n value: controlledValue,\n defaultValue,\n onValueChange,\n linear,\n mode,\n ...rest\n}: MultiSwitchProps<V>) {\n const reactId = useId();\n // A `<label for>` cannot name a div[role=\"radiogroup\"], so the group points at\n // the label instead. Needs an id the label and the group both agree on.\n const labelId = label ? `${id ?? reactId}-label` : undefined;\n\n // resolveOption hands an object option back as-is, so `color` survives it.\n const resolvedOptions = list.map(resolveOption) as Array<\n ReturnType<typeof resolveOption<V>> & { color?: Color }\n >;\n const fallback = defaultValue ?? resolvedOptions[0]?.value;\n const resolvedMode = useFieldMode(mode);\n const { showControl, interactive, enterEdit, exitEdit } = useInlineEdit(resolvedMode, disabled);\n const [value, setValue] = useControllableState(controlledValue, fallback as V, onValueChange);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const externalRef = (rest as { ref?: Ref<HTMLDivElement> }).ref;\n const containerSetRef = useMemo(() => composeRefs(externalRef, containerRef), [externalRef]);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null);\n\n const selectedIndex = resolvedOptions.findIndex(\n (o) => o.value === value,\n );\n const selectedColor = resolvedOptions[selectedIndex]?.color;\n const colorClasses = selectedColor ? multiSwitchColorClasses[selectedColor] : undefined;\n\n const updateIndicator = useCallback(() => {\n const container = containerRef.current;\n const activeItem = itemRefs.current[selectedIndex];\n if (!container || !activeItem) {\n setIndicator(null);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const itemRect = activeItem.getBoundingClientRect();\n setIndicator({\n left: itemRect.left - containerRect.left,\n width: itemRect.width,\n });\n }, [selectedIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n const control = !showControl ? (\n <DisplayValue size={size} interactive={interactive} onActivate={enterEdit}>\n {resolvedOptions.find((o) => o.value === value)?.label}\n </DisplayValue>\n ) : (\n <div\n {...rest}\n // React 19 passes `ref` to a function component as a plain prop, so a\n // caller's ref (Tooltip's anchor, or anyone's) arrives in `rest`. Spread\n // after `ref={containerRef}` it REPLACED the ref the thumb is measured\n // from, and the selected thumb never rendered. Feed both instead.\n ref={containerSetRef}\n data-react-fancy-multi-switch=\"\"\n role=\"radiogroup\"\n id={id}\n aria-labelledby={labelId}\n onBlur={(e) => {\n if (interactive && !e.currentTarget.contains(e.relatedTarget as Node)) exitEdit();\n }}\n className={cn(\n \"relative inline-flex rounded-lg border bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n colorClasses ? colorClasses.border : BORDER_DEFAULT,\n dirty && \"ring-2 ring-amber-400/50\",\n error && \"ring-2 ring-red-500/50\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {indicator && (\n <span\n data-react-fancy-multi-switch-thumb=\"\"\n data-color={selectedColor}\n className={\n colorClasses\n ? `absolute top-0 bottom-0 rounded-lg ${colorClasses.thumb} transition-all duration-200 ease-out`\n : \"absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out\"\n }\n style={{ left: indicator.left, width: indicator.width }}\n />\n )}\n {resolvedOptions.map((option, index) => {\n const isSelected = option.value === value;\n return (\n <button\n key={String(option.value)}\n ref={(el) => { itemRefs.current[index] = el; }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n disabled={disabled || option.disabled}\n autoFocus={interactive && (selectedIndex === -1 ? index === 0 : isSelected)}\n onClick={() => {\n if (linear) {\n const nextIndex = (selectedIndex + 1) % resolvedOptions.length;\n setValue(resolvedOptions[nextIndex].value as V);\n } else {\n setValue(option.value as V);\n }\n }}\n className={cn(\n \"relative z-10 font-medium transition-colors duration-200\",\n sizeClasses[size],\n isSelected\n ? (colorClasses?.text ?? \"text-white\")\n : \"text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]\",\n (disabled || option.disabled) && \"cursor-not-allowed\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n {name && <input type=\"hidden\" name={name} value={String(value)} />}\n </div>\n );\n\n if (label || error || description) {\n return (\n <Field\n label={label}\n labelHidden={labelHidden}\n labelId={labelId}\n description={description}\n error={error}\n required={required}\n htmlFor={id}\n size={size}\n >\n {control}\n </Field>\n );\n }\n\n return control;\n}\n\nMultiSwitch.displayName = \"MultiSwitch\";\n"]}
package/dist/index.cjs CHANGED
@@ -5,7 +5,7 @@ var chunkIR6JSQ4O_cjs = require('./chunk-IR6JSQ4O.cjs');
5
5
  require('./chunk-O5IO7TCO.cjs');
6
6
  var chunk6MDZQIMZ_cjs = require('./chunk-6MDZQIMZ.cjs');
7
7
  require('./chunk-QGPMVFZJ.cjs');
8
- var chunkWUG646R4_cjs = require('./chunk-WUG646R4.cjs');
8
+ var chunkIB673TEG_cjs = require('./chunk-IB673TEG.cjs');
9
9
  var chunkH7ELUIF6_cjs = require('./chunk-H7ELUIF6.cjs');
10
10
  require('./chunk-HXLSEBAL.cjs');
11
11
  var chunkZ4UXLQSK_cjs = require('./chunk-Z4UXLQSK.cjs');
@@ -235,7 +235,7 @@ Object.defineProperty(exports, "FormProvider", {
235
235
  });
236
236
  Object.defineProperty(exports, "MultiSwitch", {
237
237
  enumerable: true,
238
- get: function () { return chunkWUG646R4_cjs.MultiSwitch; }
238
+ get: function () { return chunkIB673TEG_cjs.MultiSwitch; }
239
239
  });
240
240
  Object.defineProperty(exports, "RadioGroup", {
241
241
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -9,7 +9,7 @@ export { CheckboxGroup, CheckboxGroupProps } from './checkbox-group.cjs';
9
9
  export { RadioGroup, RadioGroupProps } from './radio-group.cjs';
10
10
  export { Switch, SwitchProps } from './switch.cjs';
11
11
  export { Slider, SliderProps } from './slider.cjs';
12
- export { MultiSwitch, MultiSwitchProps } from './multi-switch.cjs';
12
+ export { MultiSwitch, MultiSwitchOption, MultiSwitchProps } from './multi-switch.cjs';
13
13
  export { DatePicker, DatePickerProps } from './date-picker.cjs';
14
14
  export { A as AffixPosition, F as FieldMode, I as InputAffixProps, a as InputBaseProps, b as InputOption, c as InputOptionGroup } from './inputs.types-duxPKadC.cjs';
15
15
  export { D as DisplayValue, a as DisplayValueProps, F as FieldModeContext, b as FieldModeContextValue, c as Form, d as FormProps, e as FormProvider, f as FormProviderProps, u as useFieldMode } from './FieldMode.context-CU5h1CyF.cjs';
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { CheckboxGroup, CheckboxGroupProps } from './checkbox-group.js';
9
9
  export { RadioGroup, RadioGroupProps } from './radio-group.js';
10
10
  export { Switch, SwitchProps } from './switch.js';
11
11
  export { Slider, SliderProps } from './slider.js';
12
- export { MultiSwitch, MultiSwitchProps } from './multi-switch.js';
12
+ export { MultiSwitch, MultiSwitchOption, MultiSwitchProps } from './multi-switch.js';
13
13
  export { DatePicker, DatePickerProps } from './date-picker.js';
14
14
  export { A as AffixPosition, F as FieldMode, I as InputAffixProps, a as InputBaseProps, b as InputOption, c as InputOptionGroup } from './inputs.types-DzGcqcPf.js';
15
15
  export { D as DisplayValue, a as DisplayValueProps, F as FieldModeContext, b as FieldModeContextValue, c as Form, d as FormProps, e as FormProvider, f as FormProviderProps, u as useFieldMode } from './FieldMode.context-Bl41F2WF.js';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ export { VirtualList } from './chunk-Z4CW3U6C.js';
3
3
  import './chunk-VXHFR5MV.js';
4
4
  export { Form, FormProvider } from './chunk-PQWQ5K6J.js';
5
5
  import './chunk-SHDSKHCC.js';
6
- export { MultiSwitch } from './chunk-KUJ5XRBD.js';
6
+ export { MultiSwitch } from './chunk-YUNOVQQJ.js';
7
7
  export { RadioGroup } from './chunk-4FH2JHUY.js';
8
8
  import './chunk-GNHQVPZP.js';
9
9
  export { Slider } from './chunk-NVXTHTJI.js';
package/dist/inputs.cjs CHANGED
@@ -3,7 +3,7 @@
3
3
  require('./chunk-O5IO7TCO.cjs');
4
4
  var chunk6MDZQIMZ_cjs = require('./chunk-6MDZQIMZ.cjs');
5
5
  require('./chunk-QGPMVFZJ.cjs');
6
- var chunkWUG646R4_cjs = require('./chunk-WUG646R4.cjs');
6
+ var chunkIB673TEG_cjs = require('./chunk-IB673TEG.cjs');
7
7
  var chunkH7ELUIF6_cjs = require('./chunk-H7ELUIF6.cjs');
8
8
  require('./chunk-HXLSEBAL.cjs');
9
9
  var chunkZ4UXLQSK_cjs = require('./chunk-Z4UXLQSK.cjs');
@@ -45,7 +45,7 @@ Object.defineProperty(exports, "FormProvider", {
45
45
  });
46
46
  Object.defineProperty(exports, "MultiSwitch", {
47
47
  enumerable: true,
48
- get: function () { return chunkWUG646R4_cjs.MultiSwitch; }
48
+ get: function () { return chunkIB673TEG_cjs.MultiSwitch; }
49
49
  });
50
50
  Object.defineProperty(exports, "RadioGroup", {
51
51
  enumerable: true,
package/dist/inputs.d.cts CHANGED
@@ -7,7 +7,7 @@ export { CheckboxGroup, CheckboxGroupProps } from './checkbox-group.cjs';
7
7
  export { RadioGroup, RadioGroupProps } from './radio-group.cjs';
8
8
  export { Switch, SwitchProps } from './switch.cjs';
9
9
  export { Slider, SliderProps, SliderRangeProps, SliderSingleProps } from './slider.cjs';
10
- export { MultiSwitch, MultiSwitchProps } from './multi-switch.cjs';
10
+ export { MultiSwitch, MultiSwitchOption, MultiSwitchProps } from './multi-switch.cjs';
11
11
  export { DatePicker, DatePickerProps, DatePickerRangeProps, DatePickerSingleProps } from './date-picker.cjs';
12
12
  export { A as AffixPosition, F as FieldMode, I as InputAffixProps, a as InputBaseProps, b as InputOption, c as InputOptionGroup } from './inputs.types-duxPKadC.cjs';
13
13
  export { D as DisplayValue, a as DisplayValueProps, F as FieldModeContext, b as FieldModeContextValue, c as Form, d as FormProps, e as FormProvider, f as FormProviderProps, u as useFieldMode } from './FieldMode.context-CU5h1CyF.cjs';
package/dist/inputs.d.ts CHANGED
@@ -7,7 +7,7 @@ export { CheckboxGroup, CheckboxGroupProps } from './checkbox-group.js';
7
7
  export { RadioGroup, RadioGroupProps } from './radio-group.js';
8
8
  export { Switch, SwitchProps } from './switch.js';
9
9
  export { Slider, SliderProps, SliderRangeProps, SliderSingleProps } from './slider.js';
10
- export { MultiSwitch, MultiSwitchProps } from './multi-switch.js';
10
+ export { MultiSwitch, MultiSwitchOption, MultiSwitchProps } from './multi-switch.js';
11
11
  export { DatePicker, DatePickerProps, DatePickerRangeProps, DatePickerSingleProps } from './date-picker.js';
12
12
  export { A as AffixPosition, F as FieldMode, I as InputAffixProps, a as InputBaseProps, b as InputOption, c as InputOptionGroup } from './inputs.types-DzGcqcPf.js';
13
13
  export { D as DisplayValue, a as DisplayValueProps, F as FieldModeContext, b as FieldModeContextValue, c as Form, d as FormProps, e as FormProvider, f as FormProviderProps, u as useFieldMode } from './FieldMode.context-Bl41F2WF.js';
package/dist/inputs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import './chunk-VXHFR5MV.js';
2
2
  export { Form, FormProvider } from './chunk-PQWQ5K6J.js';
3
3
  import './chunk-SHDSKHCC.js';
4
- export { MultiSwitch } from './chunk-KUJ5XRBD.js';
4
+ export { MultiSwitch } from './chunk-YUNOVQQJ.js';
5
5
  export { RadioGroup } from './chunk-4FH2JHUY.js';
6
6
  import './chunk-GNHQVPZP.js';
7
7
  export { Slider } from './chunk-NVXTHTJI.js';
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkWUG646R4_cjs = require('./chunk-WUG646R4.cjs');
3
+ var chunkIB673TEG_cjs = require('./chunk-IB673TEG.cjs');
4
4
  require('./chunk-I27K6NLX.cjs');
5
5
  require('./chunk-P53432AK.cjs');
6
6
  require('./chunk-QF7CD4JH.cjs');
@@ -14,7 +14,7 @@ require('./chunk-ZU5Q77OT.cjs');
14
14
 
15
15
  Object.defineProperty(exports, "MultiSwitch", {
16
16
  enumerable: true,
17
- get: function () { return chunkWUG646R4_cjs.MultiSwitch; }
17
+ get: function () { return chunkIB673TEG_cjs.MultiSwitch; }
18
18
  });
19
19
  //# sourceMappingURL=multi-switch.cjs.map
20
20
  //# sourceMappingURL=multi-switch.cjs.map
@@ -1,8 +1,20 @@
1
1
  import * as react from 'react';
2
2
  import { HTMLAttributes } from 'react';
3
+ import { C as Color } from './types-DJI492iY.cjs';
3
4
  import { a as InputBaseProps, b as InputOption } from './inputs.types-duxPKadC.cjs';
4
- import './types-DJI492iY.cjs';
5
5
 
6
+ /**
7
+ * An option, optionally with its own `color`: while it is selected the thumb
8
+ * and the container border take that colour (a green "Assign" against a red
9
+ * "Unassign"). An option without one keeps the default blue thumb.
10
+ */
11
+ type MultiSwitchOption<V = string> = InputOption<V> | {
12
+ value: V;
13
+ label: string;
14
+ disabled?: boolean;
15
+ description?: string;
16
+ color?: Color;
17
+ };
6
18
  /**
7
19
  * The container's DOM attributes are part of the API because the component
8
20
  * already spreads its rest props onto that container — `style`, `data-*` and
@@ -13,7 +25,7 @@ import './types-DJI492iY.cjs';
13
25
  * and admitting both would offer a handler that never fires.
14
26
  */
15
27
  interface MultiSwitchProps<V = string> extends InputBaseProps, Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
16
- list: InputOption<V>[];
28
+ list: MultiSwitchOption<V>[];
17
29
  value?: V;
18
30
  defaultValue?: V;
19
31
  onValueChange?: (value: V) => void;
@@ -25,4 +37,4 @@ declare namespace MultiSwitch {
25
37
  var displayName: string;
26
38
  }
27
39
 
28
- export { MultiSwitch, type MultiSwitchProps };
40
+ export { MultiSwitch, type MultiSwitchOption, type MultiSwitchProps };
@@ -1,8 +1,20 @@
1
1
  import * as react from 'react';
2
2
  import { HTMLAttributes } from 'react';
3
+ import { C as Color } from './types-DJI492iY.js';
3
4
  import { a as InputBaseProps, b as InputOption } from './inputs.types-DzGcqcPf.js';
4
- import './types-DJI492iY.js';
5
5
 
6
+ /**
7
+ * An option, optionally with its own `color`: while it is selected the thumb
8
+ * and the container border take that colour (a green "Assign" against a red
9
+ * "Unassign"). An option without one keeps the default blue thumb.
10
+ */
11
+ type MultiSwitchOption<V = string> = InputOption<V> | {
12
+ value: V;
13
+ label: string;
14
+ disabled?: boolean;
15
+ description?: string;
16
+ color?: Color;
17
+ };
6
18
  /**
7
19
  * The container's DOM attributes are part of the API because the component
8
20
  * already spreads its rest props onto that container — `style`, `data-*` and
@@ -13,7 +25,7 @@ import './types-DJI492iY.js';
13
25
  * and admitting both would offer a handler that never fires.
14
26
  */
15
27
  interface MultiSwitchProps<V = string> extends InputBaseProps, Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
16
- list: InputOption<V>[];
28
+ list: MultiSwitchOption<V>[];
17
29
  value?: V;
18
30
  defaultValue?: V;
19
31
  onValueChange?: (value: V) => void;
@@ -25,4 +37,4 @@ declare namespace MultiSwitch {
25
37
  var displayName: string;
26
38
  }
27
39
 
28
- export { MultiSwitch, type MultiSwitchProps };
40
+ export { MultiSwitch, type MultiSwitchOption, type MultiSwitchProps };
@@ -1,4 +1,4 @@
1
- export { MultiSwitch } from './chunk-KUJ5XRBD.js';
1
+ export { MultiSwitch } from './chunk-YUNOVQQJ.js';
2
2
  import './chunk-SV5BW3IA.js';
3
3
  import './chunk-WX5XYDVN.js';
4
4
  import './chunk-5WQ6FPSP.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.57.0",
3
+ "version": "5.58.0",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/inputs/MultiSwitch/MultiSwitch.tsx"],"names":[],"mappings":"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","file":"chunk-KUJ5XRBD.js","sourcesContent":["import { useRef, useState, useEffect, useCallback, useId, useMemo, type Ref } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { composeRefs } from \"../../../utils/compose-refs\";\nimport { useControllableState } from \"../../../hooks/use-controllable-state\";\nimport { Field } from \"../Field\";\nimport { useFieldMode } from \"../mode/FieldMode.context\";\nimport { DisplayValue } from \"../mode/DisplayValue\";\nimport { useInlineEdit } from \"../mode/useInlineEdit\";\nimport { resolveOption } from \"../inputs.utils\";\nimport type { Size } from \"../../../utils/types\";\nimport type { MultiSwitchProps } from \"./MultiSwitch.types\";\n\nconst sizeClasses: Record<Size, string> = {\n xs: \"px-2 py-1 text-xs\",\n sm: \"px-2.5 py-1.5 text-sm\",\n md: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-2.5 text-base\",\n xl: \"px-5 py-3 text-lg\",\n};\n\nexport function MultiSwitch<V = string>({\n size = \"md\",\n dirty,\n error,\n label,\n labelHidden,\n description,\n required,\n disabled,\n className,\n id,\n name,\n list,\n value: controlledValue,\n defaultValue,\n onValueChange,\n linear,\n mode,\n ...rest\n}: MultiSwitchProps<V>) {\n const reactId = useId();\n // A `<label for>` cannot name a div[role=\"radiogroup\"], so the group points at\n // the label instead. Needs an id the label and the group both agree on.\n const labelId = label ? `${id ?? reactId}-label` : undefined;\n\n const resolvedOptions = list.map(resolveOption);\n const fallback = defaultValue ?? resolvedOptions[0]?.value;\n const resolvedMode = useFieldMode(mode);\n const { showControl, interactive, enterEdit, exitEdit } = useInlineEdit(resolvedMode, disabled);\n const [value, setValue] = useControllableState(controlledValue, fallback as V, onValueChange);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const externalRef = (rest as { ref?: Ref<HTMLDivElement> }).ref;\n const containerSetRef = useMemo(() => composeRefs(externalRef, containerRef), [externalRef]);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null);\n\n const selectedIndex = resolvedOptions.findIndex(\n (o) => o.value === value,\n );\n\n const updateIndicator = useCallback(() => {\n const container = containerRef.current;\n const activeItem = itemRefs.current[selectedIndex];\n if (!container || !activeItem) {\n setIndicator(null);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const itemRect = activeItem.getBoundingClientRect();\n setIndicator({\n left: itemRect.left - containerRect.left,\n width: itemRect.width,\n });\n }, [selectedIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n const control = !showControl ? (\n <DisplayValue size={size} interactive={interactive} onActivate={enterEdit}>\n {resolvedOptions.find((o) => o.value === value)?.label}\n </DisplayValue>\n ) : (\n <div\n {...rest}\n // React 19 passes `ref` to a function component as a plain prop, so a\n // caller's ref (Tooltip's anchor, or anyone's) arrives in `rest`. Spread\n // after `ref={containerRef}` it REPLACED the ref the thumb is measured\n // from, and the selected thumb never rendered. Feed both instead.\n ref={containerSetRef}\n data-react-fancy-multi-switch=\"\"\n role=\"radiogroup\"\n id={id}\n aria-labelledby={labelId}\n onBlur={(e) => {\n if (interactive && !e.currentTarget.contains(e.relatedTarget as Node)) exitEdit();\n }}\n className={cn(\n \"relative inline-flex rounded-lg border border-[color:var(--fancy-border-strong,var(--color-zinc-300))] bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n dirty && \"ring-2 ring-amber-400/50\",\n error && \"ring-2 ring-red-500/50\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {indicator && (\n <span\n className=\"absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out\"\n style={{ left: indicator.left, width: indicator.width }}\n />\n )}\n {resolvedOptions.map((option, index) => {\n const isSelected = option.value === value;\n return (\n <button\n key={String(option.value)}\n ref={(el) => { itemRefs.current[index] = el; }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n disabled={disabled || option.disabled}\n autoFocus={interactive && (selectedIndex === -1 ? index === 0 : isSelected)}\n onClick={() => {\n if (linear) {\n const nextIndex = (selectedIndex + 1) % resolvedOptions.length;\n setValue(resolvedOptions[nextIndex].value as V);\n } else {\n setValue(option.value as V);\n }\n }}\n className={cn(\n \"relative z-10 font-medium transition-colors duration-200\",\n sizeClasses[size],\n isSelected\n ? \"text-white\"\n : \"text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]\",\n (disabled || option.disabled) && \"cursor-not-allowed\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n {name && <input type=\"hidden\" name={name} value={String(value)} />}\n </div>\n );\n\n if (label || error || description) {\n return (\n <Field\n label={label}\n labelHidden={labelHidden}\n labelId={labelId}\n description={description}\n error={error}\n required={required}\n htmlFor={id}\n size={size}\n >\n {control}\n </Field>\n );\n }\n\n return control;\n}\n\nMultiSwitch.displayName = \"MultiSwitch\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/inputs/MultiSwitch/MultiSwitch.tsx"],"names":["useId","resolveOption","useFieldMode","useInlineEdit","useControllableState","useRef","useMemo","composeRefs","useState","useCallback","useEffect","DisplayValue","jsxs","cn","jsx","Field"],"mappings":"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","file":"chunk-WUG646R4.cjs","sourcesContent":["import { useRef, useState, useEffect, useCallback, useId, useMemo, type Ref } from \"react\";\nimport { cn } from \"../../../utils/cn\";\nimport { composeRefs } from \"../../../utils/compose-refs\";\nimport { useControllableState } from \"../../../hooks/use-controllable-state\";\nimport { Field } from \"../Field\";\nimport { useFieldMode } from \"../mode/FieldMode.context\";\nimport { DisplayValue } from \"../mode/DisplayValue\";\nimport { useInlineEdit } from \"../mode/useInlineEdit\";\nimport { resolveOption } from \"../inputs.utils\";\nimport type { Size } from \"../../../utils/types\";\nimport type { MultiSwitchProps } from \"./MultiSwitch.types\";\n\nconst sizeClasses: Record<Size, string> = {\n xs: \"px-2 py-1 text-xs\",\n sm: \"px-2.5 py-1.5 text-sm\",\n md: \"px-3 py-2 text-sm\",\n lg: \"px-4 py-2.5 text-base\",\n xl: \"px-5 py-3 text-lg\",\n};\n\nexport function MultiSwitch<V = string>({\n size = \"md\",\n dirty,\n error,\n label,\n labelHidden,\n description,\n required,\n disabled,\n className,\n id,\n name,\n list,\n value: controlledValue,\n defaultValue,\n onValueChange,\n linear,\n mode,\n ...rest\n}: MultiSwitchProps<V>) {\n const reactId = useId();\n // A `<label for>` cannot name a div[role=\"radiogroup\"], so the group points at\n // the label instead. Needs an id the label and the group both agree on.\n const labelId = label ? `${id ?? reactId}-label` : undefined;\n\n const resolvedOptions = list.map(resolveOption);\n const fallback = defaultValue ?? resolvedOptions[0]?.value;\n const resolvedMode = useFieldMode(mode);\n const { showControl, interactive, enterEdit, exitEdit } = useInlineEdit(resolvedMode, disabled);\n const [value, setValue] = useControllableState(controlledValue, fallback as V, onValueChange);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const externalRef = (rest as { ref?: Ref<HTMLDivElement> }).ref;\n const containerSetRef = useMemo(() => composeRefs(externalRef, containerRef), [externalRef]);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null);\n\n const selectedIndex = resolvedOptions.findIndex(\n (o) => o.value === value,\n );\n\n const updateIndicator = useCallback(() => {\n const container = containerRef.current;\n const activeItem = itemRefs.current[selectedIndex];\n if (!container || !activeItem) {\n setIndicator(null);\n return;\n }\n const containerRect = container.getBoundingClientRect();\n const itemRect = activeItem.getBoundingClientRect();\n setIndicator({\n left: itemRect.left - containerRect.left,\n width: itemRect.width,\n });\n }, [selectedIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n const control = !showControl ? (\n <DisplayValue size={size} interactive={interactive} onActivate={enterEdit}>\n {resolvedOptions.find((o) => o.value === value)?.label}\n </DisplayValue>\n ) : (\n <div\n {...rest}\n // React 19 passes `ref` to a function component as a plain prop, so a\n // caller's ref (Tooltip's anchor, or anyone's) arrives in `rest`. Spread\n // after `ref={containerRef}` it REPLACED the ref the thumb is measured\n // from, and the selected thumb never rendered. Feed both instead.\n ref={containerSetRef}\n data-react-fancy-multi-switch=\"\"\n role=\"radiogroup\"\n id={id}\n aria-labelledby={labelId}\n onBlur={(e) => {\n if (interactive && !e.currentTarget.contains(e.relatedTarget as Node)) exitEdit();\n }}\n className={cn(\n \"relative inline-flex rounded-lg border border-[color:var(--fancy-border-strong,var(--color-zinc-300))] bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n dirty && \"ring-2 ring-amber-400/50\",\n error && \"ring-2 ring-red-500/50\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className,\n )}\n >\n {indicator && (\n <span\n className=\"absolute top-0 bottom-0 rounded-lg bg-blue-600 transition-all duration-200 ease-out\"\n style={{ left: indicator.left, width: indicator.width }}\n />\n )}\n {resolvedOptions.map((option, index) => {\n const isSelected = option.value === value;\n return (\n <button\n key={String(option.value)}\n ref={(el) => { itemRefs.current[index] = el; }}\n type=\"button\"\n role=\"radio\"\n aria-checked={isSelected}\n disabled={disabled || option.disabled}\n autoFocus={interactive && (selectedIndex === -1 ? index === 0 : isSelected)}\n onClick={() => {\n if (linear) {\n const nextIndex = (selectedIndex + 1) % resolvedOptions.length;\n setValue(resolvedOptions[nextIndex].value as V);\n } else {\n setValue(option.value as V);\n }\n }}\n className={cn(\n \"relative z-10 font-medium transition-colors duration-200\",\n sizeClasses[size],\n isSelected\n ? \"text-white\"\n : \"text-[color:var(--fancy-text-subtle,var(--color-zinc-600))] hover:text-[color:var(--fancy-text,var(--color-zinc-900))] dark:text-[color:var(--fancy-text-subtle-dark,var(--color-zinc-400))] dark:hover:text-[color:var(--fancy-text-dark,var(--color-zinc-100))]\",\n (disabled || option.disabled) && \"cursor-not-allowed\",\n )}\n >\n {option.label}\n </button>\n );\n })}\n {name && <input type=\"hidden\" name={name} value={String(value)} />}\n </div>\n );\n\n if (label || error || description) {\n return (\n <Field\n label={label}\n labelHidden={labelHidden}\n labelId={labelId}\n description={description}\n error={error}\n required={required}\n htmlFor={id}\n size={size}\n >\n {control}\n </Field>\n );\n }\n\n return control;\n}\n\nMultiSwitch.displayName = \"MultiSwitch\";\n"]}