@mortenbrudvik/waveui 0.9.0 → 0.10.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.
Files changed (105) hide show
  1. package/README.md +425 -104
  2. package/dist/components/input/Calendar.cjs +2 -0
  3. package/dist/components/input/Calendar.cjs.map +1 -0
  4. package/dist/components/input/Calendar.mjs +352 -0
  5. package/dist/components/input/Calendar.mjs.map +1 -0
  6. package/dist/components/input/Calendar.views.cjs +2 -0
  7. package/dist/components/input/Calendar.views.cjs.map +1 -0
  8. package/dist/components/input/Calendar.views.mjs +194 -0
  9. package/dist/components/input/Calendar.views.mjs.map +1 -0
  10. package/dist/components/input/ColorArea.cjs +1 -1
  11. package/dist/components/input/ColorArea.cjs.map +1 -1
  12. package/dist/components/input/ColorArea.mjs +18 -18
  13. package/dist/components/input/ColorArea.mjs.map +1 -1
  14. package/dist/components/input/Combobox.cjs +1 -1
  15. package/dist/components/input/Combobox.cjs.map +1 -1
  16. package/dist/components/input/Combobox.mjs +232 -156
  17. package/dist/components/input/Combobox.mjs.map +1 -1
  18. package/dist/components/input/Combobox.text.cjs +2 -0
  19. package/dist/components/input/Combobox.text.cjs.map +1 -0
  20. package/dist/components/input/Combobox.text.mjs +24 -0
  21. package/dist/components/input/Combobox.text.mjs.map +1 -0
  22. package/dist/components/input/DatePicker.cjs +1 -1
  23. package/dist/components/input/DatePicker.cjs.map +1 -1
  24. package/dist/components/input/DatePicker.mjs +203 -288
  25. package/dist/components/input/DatePicker.mjs.map +1 -1
  26. package/dist/components/input/Dropdown.cjs +1 -1
  27. package/dist/components/input/Dropdown.cjs.map +1 -1
  28. package/dist/components/input/Dropdown.mjs +135 -109
  29. package/dist/components/input/Dropdown.mjs.map +1 -1
  30. package/dist/components/input/Listbox.cjs +2 -0
  31. package/dist/components/input/Listbox.cjs.map +1 -0
  32. package/dist/components/input/Listbox.mjs +134 -0
  33. package/dist/components/input/Listbox.mjs.map +1 -0
  34. package/dist/components/input/Option.cjs +1 -1
  35. package/dist/components/input/Option.cjs.map +1 -1
  36. package/dist/components/input/Option.mjs +158 -97
  37. package/dist/components/input/Option.mjs.map +1 -1
  38. package/dist/components/input/SwatchPicker.cjs +1 -1
  39. package/dist/components/input/SwatchPicker.cjs.map +1 -1
  40. package/dist/components/input/SwatchPicker.context.cjs +2 -0
  41. package/dist/components/input/SwatchPicker.context.cjs.map +1 -0
  42. package/dist/components/input/SwatchPicker.context.mjs +35 -0
  43. package/dist/components/input/SwatchPicker.context.mjs.map +1 -0
  44. package/dist/components/input/SwatchPicker.mjs +131 -103
  45. package/dist/components/input/SwatchPicker.mjs.map +1 -1
  46. package/dist/components/input/SwatchPicker.swatches.cjs +2 -0
  47. package/dist/components/input/SwatchPicker.swatches.cjs.map +1 -0
  48. package/dist/components/input/SwatchPicker.swatches.mjs +207 -0
  49. package/dist/components/input/SwatchPicker.swatches.mjs.map +1 -0
  50. package/dist/components/input/TagPicker.cjs +1 -1
  51. package/dist/components/input/TagPicker.cjs.map +1 -1
  52. package/dist/components/input/TagPicker.mjs +144 -139
  53. package/dist/components/input/TagPicker.mjs.map +1 -1
  54. package/dist/components/input/TimePicker.cjs +1 -1
  55. package/dist/components/input/TimePicker.cjs.map +1 -1
  56. package/dist/components/input/TimePicker.mjs +77 -77
  57. package/dist/components/input/TimePicker.mjs.map +1 -1
  58. package/dist/components/input/dateUtils.cjs +1 -1
  59. package/dist/components/input/dateUtils.cjs.map +1 -1
  60. package/dist/components/input/dateUtils.mjs +114 -96
  61. package/dist/components/input/dateUtils.mjs.map +1 -1
  62. package/dist/components/input/pickerLabels.cjs +2 -0
  63. package/dist/components/input/pickerLabels.cjs.map +1 -0
  64. package/dist/components/input/pickerLabels.mjs +16 -0
  65. package/dist/components/input/pickerLabels.mjs.map +1 -0
  66. package/dist/components/input/pickerValues.cjs +2 -0
  67. package/dist/components/input/pickerValues.cjs.map +1 -0
  68. package/dist/components/input/pickerValues.mjs +24 -0
  69. package/dist/components/input/pickerValues.mjs.map +1 -0
  70. package/dist/components/table/useGridNavigation.cjs +1 -1
  71. package/dist/components/table/useGridNavigation.cjs.map +1 -1
  72. package/dist/components/table/useGridNavigation.mjs +67 -70
  73. package/dist/components/table/useGridNavigation.mjs.map +1 -1
  74. package/dist/hooks/useActiveDescendant.cjs +2 -0
  75. package/dist/hooks/useActiveDescendant.cjs.map +1 -0
  76. package/dist/hooks/useActiveDescendant.mjs +56 -0
  77. package/dist/hooks/useActiveDescendant.mjs.map +1 -0
  78. package/dist/hooks/useListbox.cjs +1 -1
  79. package/dist/hooks/useListbox.cjs.map +1 -1
  80. package/dist/hooks/useListbox.mjs +250 -210
  81. package/dist/hooks/useListbox.mjs.map +1 -1
  82. package/dist/hooks/useRovingGrid.cjs +2 -0
  83. package/dist/hooks/useRovingGrid.cjs.map +1 -0
  84. package/dist/hooks/useRovingGrid.mjs +69 -0
  85. package/dist/hooks/useRovingGrid.mjs.map +1 -0
  86. package/dist/index.cjs +1 -1
  87. package/dist/index.d.cts +2147 -155
  88. package/dist/index.d.ts +2147 -155
  89. package/dist/index.mjs +107 -101
  90. package/dist/lib/classNames.cjs +1 -1
  91. package/dist/lib/classNames.cjs.map +1 -1
  92. package/dist/lib/classNames.mjs +84 -48
  93. package/dist/lib/classNames.mjs.map +1 -1
  94. package/dist/lib/date.cjs +2 -0
  95. package/dist/lib/date.cjs.map +1 -0
  96. package/dist/lib/date.mjs +44 -0
  97. package/dist/lib/date.mjs.map +1 -0
  98. package/dist/lib/focus.cjs +1 -1
  99. package/dist/lib/focus.cjs.map +1 -1
  100. package/dist/lib/focus.mjs +5 -2
  101. package/dist/lib/focus.mjs.map +1 -1
  102. package/dist/lib/layers.cjs.map +1 -1
  103. package/dist/lib/layers.mjs.map +1 -1
  104. package/dist/styles.css +1 -1
  105. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwatchPicker.swatches.cjs","names":["CheckIcon","cn","unwrapButtonGlyph","useSwatchPickerContext","motionSafeTransition","focusRing","composeEventHandlers","swatchPickerClassNames","forcedColors","slotRendersContent","renderSlot","colorSwatchClassNames","getCheckColors","imageSwatchClassNames","useId","AddIcon","emptySwatchClassNames","require_runtime","require_cn","require_dev","require_slot","require_composeEventHandlers","require_classNames","require_useId","require_styles","require_Button_slots","require_icons","require_SwatchPicker_context","require_colorUtils","react","react_jsx_runtime","sizeMap","glyphSizeMap","shapeMap","SwatchCheck","colors","SwatchSlash","warnUnnamedSwatch","kind","value","fallback","useSwatchIcon","icon","useSwatchIconWarning","button","glyph","useSwatchContext","context","size","shape","outlineOffset","spacing","SwatchGridCell","selected","swatchBaseClasses","SwatchRadio","sizeProp","shapeProp","ariaLabel","ariaLabelledBy","rest","selectedValue","isSelected","isTab","focusMode","isGrid","layout","register","named","fallbackKind","defaultName","getTabIndex","onClick","select","rootClassName","paintClassName","keepsColors","className","style","paint","checkColors","iconClassName","disabled","ColorSwatch","color","borderColor","ImageSwatch","src","EmptySwatch","cellValue","content","control"],"sources":["../../../src/components/input/SwatchPicker.swatches.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n colorSwatchClassNames,\n emptySwatchClassNames,\n imageSwatchClassNames,\n swatchPickerClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { AddIcon, CheckIcon } from '../../lib/icons';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\nimport type { Slot } from '../../lib/slot';\nimport { focusRing, forcedColors, motionSafeTransition } from '../../lib/styles';\nimport type { Shape } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { unwrapButtonGlyph, type UnwrappedButton } from '../button/Button.slots';\nimport { useSwatchPickerContext, type SwatchPickerSize } from './SwatchPicker.context';\nimport { getCheckColors, type CheckColors } from './colorUtils';\n\n/*\n * The swatch kinds a `SwatchPicker` renders `items` through and a consumer can render as children\n * (D18, D21): `ColorSwatch`, `ImageSwatch` and `EmptySwatch`. Every swatch reads\n * `SwatchPickerContext` and puts its `ref`, `className`, `style`, name and rest props on its own\n * `<button>` (an explicit exception to C-ROUTING: there is no separate root, so a wrapping\n * Tooltip's ARIA and handlers reach the focused element without extra wiring).\n */\n\nconst sizeMap: Record<SwatchPickerSize, string> = {\n 'extra-small': 'w-5 h-5',\n small: 'w-6 h-6',\n medium: 'w-8 h-8',\n large: 'w-10 h-10',\n};\n\nconst glyphSizeMap: Record<SwatchPickerSize, number> = {\n 'extra-small': 10,\n small: 12,\n medium: 16,\n large: 20,\n};\n\nconst shapeMap: Record<Shape, string> = {\n circular: 'rounded-full',\n square: 'rounded-none',\n rounded: 'rounded',\n};\n\n/**\n * The check glyph of the selected swatch: black or white by the swatch's luminance, drawn over a\n * halo in the other color so it stays visible on any swatch (C-TOKENS exception for\n * user-supplied colors, `input-pickers#16`). Without `colors` (an image has no single luminance)\n * it is the theme's foreground glyph over a background halo.\n */\nfunction SwatchCheck({ colors, size }: { colors: CheckColors | null; size: number }) {\n return (\n <span aria-hidden=\"true\" className=\"pointer-events-none grid\">\n <CheckIcon\n size={size}\n strokeWidth={4}\n className={cn('col-start-1 row-start-1', !colors && 'text-background')}\n style={colors ? { color: colors.halo } : undefined}\n />\n <CheckIcon\n size={size}\n strokeWidth={2}\n className={cn('col-start-1 row-start-1', !colors && 'text-foreground')}\n style={colors ? { color: colors.glyph } : undefined}\n />\n </span>\n );\n}\n\n/**\n * The diagonal slash of a disabled swatch, drawn like the check glyph (a halo line under a glyph\n * line), so the state does not rely on the swatch color or its opacity.\n */\nfunction SwatchSlash({ colors }: { colors: CheckColors | null }) {\n return (\n <svg\n data-wave-swatch-slash=\"\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className=\"pointer-events-none absolute inset-0 h-full w-full\"\n >\n <line\n x1=\"5\"\n y1=\"19\"\n x2=\"19\"\n y2=\"5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth={4}\n className={colors ? undefined : 'text-background'}\n style={colors ? { color: colors.halo } : undefined}\n />\n <line\n x1=\"5\"\n y1=\"19\"\n x2=\"19\"\n y2=\"5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth={2}\n className={colors ? undefined : 'text-foreground'}\n style={colors ? { color: colors.glyph } : undefined}\n />\n </svg>\n );\n}\n\n/** Warns once per swatch kind (not per value: `<Kind>:unnamed`, e.g. `ColorSwatch:unnamed`). */\nfunction warnUnnamedSwatch(kind: string, value: string, fallback: string): void {\n warnOnce(\n `${kind}:unnamed`,\n `${kind}: swatch \"${value}\" has no accessible name, so it is announced by its ${fallback}. ` +\n 'Pass `aria-label`, or wrap it in a Tooltip with `relationship=\"label\"`.',\n );\n}\n\n/**\n * A swatch's `icon` as a glyph inside its wired button (C-SLOTS): a `<button>` or `Button` is\n * unwrapped (its children become the glyph) with a one-time warning (`<Kind>:icon-button`).\n */\nfunction useSwatchIcon(kind: string, icon: Slot<'span'> | undefined): Slot<'span'> | undefined {\n const { glyph, button } = unwrapButtonGlyph(icon);\n useSwatchIconWarning(kind, button);\n return glyph;\n}\n\n/** The one-time `<Kind>:icon-button` warning for an unwrapped button. */\nfunction useSwatchIconWarning(kind: string, button: UnwrappedButton | null): void {\n React.useEffect(() => {\n if (button) {\n warnOnce(\n `${kind}:icon-button`,\n `${kind}: \\`icon\\` received ${button}; its children render as the glyph of the swatch ` +\n 'and its props were dropped (buttons cannot be nested). Pass icon content instead, ' +\n 'e.g. `icon={<MyIcon />}`.',\n );\n }\n }, [button, kind]);\n}\n\n/** The picker's context with this swatch's own `size` and `shape` applied over the picker's. */\nfunction useSwatchContext(kind: string, size?: SwatchPickerSize, shape?: Shape) {\n const context = useSwatchPickerContext(kind);\n return { ...context, size: size ?? context.size, shape: shape ?? context.shape };\n}\n\n/**\n * Focus outline offset: 4px, clear of a selected swatch's ring band (ring and offset, 4px); 2px at\n * `spacing=\"small\"` so it does not cover the neighbour (D22), where it lies over that band.\n */\nfunction outlineOffset(spacing: 'small' | 'medium'): string {\n return spacing === 'small' ? 'focus-visible:outline-offset-2' : 'focus-visible:outline-offset-4';\n}\n\n/**\n * The cell around a swatch's button in the grid layout: it carries only the role and, for a swatch\n * with a value, `aria-selected` (a `gridcell` role on the button would replace its button role,\n * which `aria-pressed` needs). Every consumer prop stays on the button.\n */\nfunction SwatchGridCell({ selected, children }: { selected?: boolean; children: React.ReactNode }) {\n return (\n <div role=\"gridcell\" aria-selected={selected} className=\"flex shrink-0\">\n {children}\n </div>\n );\n}\n\n/** The classes every swatch kind shares: size, shape, box, motion, focus ring and disabled look. */\nfunction swatchBaseClasses(\n size: SwatchPickerSize,\n shape: Shape,\n spacing: 'small' | 'medium',\n): string {\n return cn(\n sizeMap[size],\n shapeMap[shape],\n // The padding is set here (C-NATIVE).\n 'relative flex shrink-0 items-center justify-center border-2 p-0',\n motionSafeTransition,\n focusRing,\n outlineOffset(spacing),\n 'disabled:cursor-not-allowed disabled:opacity-50',\n );\n}\n\n/** Properties for the ColorSwatch component. */\nexport interface ColorSwatchProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value' | 'color'\n> {\n /** Unique identifier for the swatch (the value the picker selects and a form submits). */\n value: string;\n /** CSS color value (e.g., hex, rgb) used as the swatch background (a runtime user color). */\n color: string;\n /**\n * Decorative glyph (`aria-hidden`) shown while the swatch is not selected; the check replaces it\n * while selected. A `<button>` or `Button` passed here is not nested: its children become the\n * glyph and a one-time development warning is logged.\n */\n icon?: Slot<'span'>;\n /**\n * CSS color of the swatch's border, for a color close to the page background (set by hand, as\n * in Fluent). In forced colors the system border color replaces it.\n */\n borderColor?: string;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /**\n * Ref to the swatch button: `role=\"radio\"` in the row layout, inside its cell in the grid\n * layout, a toggle button in tab mode.\n */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/** What `ColorSwatch` and `ImageSwatch` do differently. */\ninterface SwatchRadioProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value' | 'color'\n> {\n kind: 'ColorSwatch' | 'ImageSwatch';\n /** The kind's stable root class, named by the module that sets its `displayName` (P3-00). */\n rootClassName: string;\n /** The kind's stable `icon` part class (ColorSwatch only). */\n iconClassName?: string;\n value: string;\n /** What names the swatch when it has no name: 'color value' or 'value' (the warning's text). */\n fallbackKind: string;\n /** The accessible name of an unnamed swatch. */\n defaultName: string;\n /** The luminance-picked glyph colors; `null`: the theme's foreground over a background halo. */\n checkColors: CheckColors | null;\n /** The swatch's own background, border color and image (they win over a consumer `style`). */\n paint: Record<string, string>;\n /** Classes of the image swatch's covering background. */\n paintClassName?: string;\n /** A color swatch keeps its colors in forced colors (the color is the content). */\n keepsColors: boolean;\n icon?: Slot<'span'>;\n size?: SwatchPickerSize;\n shape?: Shape;\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/** The radio button shared by `ColorSwatch` and `ImageSwatch`. */\nconst SwatchRadio = ({\n kind,\n rootClassName,\n iconClassName,\n value,\n fallbackKind,\n defaultName,\n checkColors,\n paint,\n paintClassName,\n keepsColors,\n icon,\n size: sizeProp,\n shape: shapeProp,\n className,\n style,\n onClick,\n disabled,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ref,\n ...rest\n}: SwatchRadioProps) => {\n const {\n value: selectedValue,\n select,\n size,\n shape,\n layout,\n focusMode,\n spacing,\n getTabIndex,\n register,\n } = useSwatchContext(kind, sizeProp, shapeProp);\n const isSelected = selectedValue === value;\n const isTab = focusMode === 'tab';\n const isGrid = layout === 'grid' && !isTab;\n const glyph = useSwatchIcon(kind, icon);\n\n React.useLayoutEffect(() => register(value), [register, value]);\n\n const named = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n React.useEffect(() => {\n if (!named) warnUnnamedSwatch(kind, value, fallbackKind);\n }, [named, kind, value, fallbackKind]);\n\n const button = (\n <button\n type=\"button\"\n // The grid layout: a plain button inside its gridcell, pressed while selected (D20); tab\n // mode (D19): a toggle button of a group, `aria-pressed` always present.\n role={isGrid || isTab ? undefined : 'radio'}\n {...rest}\n ref={ref}\n disabled={disabled}\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : defaultName)}\n aria-labelledby={ariaLabelledBy}\n aria-checked={isGrid || isTab ? undefined : isSelected}\n aria-pressed={isTab ? isSelected : isGrid ? isSelected || undefined : undefined}\n data-roving-value={value}\n data-selected={isSelected ? '' : undefined}\n tabIndex={getTabIndex(value)}\n onClick={composeEventHandlers(onClick, () => select(value))}\n className={cn(\n rootClassName,\n // Every swatch in a picker carries the picker's part class, children included (0.8).\n swatchPickerClassNames.swatch,\n swatchBaseClasses(size, shape, spacing),\n // A `borderColor` arrives as a variable, so the forced-colors edge below still wins.\n 'border-[color:var(--wave-swatch-border,transparent)]',\n paintClassName,\n // User colors are the content: keep them (and the check glyph) in forced colors, with a\n // Highlight outline, which an opted-out element would otherwise draw in author colors.\n keepsColors &&\n 'forced-colors:forced-color-adjust-none forced-colors:focus-visible:outline-[Highlight]',\n forcedColors.border,\n // An image stays in forced colors, so its selection needs a sign of its own.\n isSelected && !keepsColors && 'forced-colors:border-[Highlight]',\n isSelected\n ? cn(\n 'ring-2 ring-foreground ring-offset-2 ring-offset-background',\n keepsColors && 'forced-colors:ring-[Highlight]',\n )\n : 'not-disabled:not-aria-disabled:hover:border-stroke-hover',\n className,\n )}\n style={{ ...style, ...paint }}\n >\n {isSelected ? (\n <SwatchCheck colors={checkColors} size={glyphSizeMap[size]} />\n ) : (\n glyph != null &&\n slotRendersContent(glyph) &&\n renderSlot(glyph, 'span', cn(iconClassName, 'pointer-events-none inline-flex'), {\n 'aria-hidden': true,\n style: checkColors ? { color: checkColors.glyph } : undefined,\n })\n )}\n {disabled && <SwatchSlash colors={checkColors} />}\n </button>\n );\n return isGrid ? <SwatchGridCell selected={isSelected}>{button}</SwatchGridCell> : button;\n};\nSwatchRadio.displayName = 'SwatchRadio';\n\n// D18: swatches read SwatchPickerContext; their own ref/className/style/rest go straight to the\n// button (an explicit exception to C-ROUTING's root/control split).\n/**\n * One color swatch of a `SwatchPicker`, read from `items` or rendered directly as a child.\n * Outside a `SwatchPicker` it throws in development and renders inertly in production.\n *\n * **Naming**: give it `aria-label`, or wrap it in a `Tooltip` with `relationship=\"label\"` (its\n * `aria-labelledby` reaches this element, since every rest prop lands on the swatch's own\n * button). Without either it is named by its `color` value and a development warning is logged.\n *\n * **Disabled**: `disabled` is native (out of the arrow keys and the tab order, never selected);\n * the swatch is dimmed and crossed by a diagonal slash, so the state does not rely on its color.\n *\n * @example\n * <SwatchPicker aria-label=\"Accent color\">\n * <ColorSwatch value=\"red\" color=\"#d13438\" aria-label=\"Red\" />\n * </SwatchPicker>\n */\nexport const ColorSwatch = ({ color, borderColor, ...rest }: ColorSwatchProps) => {\n return (\n <SwatchRadio\n {...rest}\n kind=\"ColorSwatch\"\n rootClassName={colorSwatchClassNames.root}\n iconClassName={colorSwatchClassNames.icon}\n fallbackKind=\"color value\"\n defaultName={color}\n checkColors={getCheckColors(color)}\n keepsColors\n paint={{\n backgroundColor: color,\n ...(borderColor !== undefined && { '--wave-swatch-border': borderColor }),\n }}\n />\n );\n};\nColorSwatch.displayName = 'ColorSwatch';\n\n/** Properties for the ImageSwatch component. */\nexport interface ImageSwatchProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n /** Unique identifier for the swatch (the value the picker selects and a form submits). */\n value: string;\n /** URL of the image (drawn as a covering background image). */\n src: string;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /**\n * Ref to the swatch button: `role=\"radio\"` in the row layout, inside its cell in the grid\n * layout, a toggle button in tab mode.\n */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * One image swatch of a `SwatchPicker`: a pattern or texture drawn as a covering background\n * image. Outside a `SwatchPicker` it throws in development and renders inertly in production.\n *\n * **Naming**: give it `aria-label`, or wrap it in a `Tooltip` with `relationship=\"label\"`.\n * Without either it is named by its `value` and a development warning is logged.\n *\n * **Selected and disabled**: an image has no single luminance, so the check and the disabled slash\n * are the theme's foreground glyph over a background halo. Unlike `ColorSwatch` it does not opt\n * out of forced colors (a background image stays).\n *\n * @example\n * <SwatchPicker aria-label=\"Pattern\">\n * <ImageSwatch value=\"dots\" src=\"/dots.png\" aria-label=\"Dots\" />\n * </SwatchPicker>\n */\nexport const ImageSwatch = ({ src, ...rest }: ImageSwatchProps) => {\n return (\n <SwatchRadio\n {...rest}\n kind=\"ImageSwatch\"\n rootClassName={imageSwatchClassNames.root}\n fallbackKind=\"value\"\n defaultName={rest.value}\n checkColors={null}\n keepsColors={false}\n paintClassName=\"bg-cover bg-center bg-no-repeat\"\n paint={{ backgroundImage: `url(${JSON.stringify(src)})` }}\n />\n );\n};\nImageSwatch.displayName = 'ImageSwatch';\n\n/** Properties for the EmptySwatch component. */\nexport interface EmptySwatchProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * Accessible name of the button.\n * @default 'Add color'\n */\n 'aria-label'?: string;\n /**\n * Decorative glyph (`aria-hidden`). `null` and `undefined` keep the plus glyph; `false` or\n * anything that renders nothing shows none. A `<button>` or `Button` passed here is not nested:\n * its children become the glyph and a one-time development warning is logged.\n * @default a plus glyph\n */\n icon?: Slot<'span'>;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /** Ref to the button. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * An \"add\" button inside a `SwatchPicker` (for example to open a color dialog): it has no value\n * and is never selected. In the row layout it is a plain button with its own tab stop, outside\n * the radio group's arrow order, and arrow keys pressed on it do nothing. In the grid layout it\n * is a cell like the others, in the arrow order (without `aria-selected`). Outside a\n * `SwatchPicker` it throws in development and renders inertly in production.\n *\n * @example\n * <SwatchPicker aria-label=\"Accent color\" items={items}>\n * <EmptySwatch onClick={openColorDialog} />\n * </SwatchPicker>\n */\nexport const EmptySwatch = ({\n icon,\n size: sizeProp,\n shape: shapeProp,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ref,\n ...rest\n}: EmptySwatchProps) => {\n const { size, shape, layout, focusMode, spacing, getTabIndex } = useSwatchContext(\n 'EmptySwatch',\n sizeProp,\n shapeProp,\n );\n // Tab mode has no grid cells: the button is a tab stop of its own, like in the row layout.\n const isGrid = layout === 'grid' && focusMode !== 'tab';\n // The grid's roving keys address cells by value: an EmptySwatch, which has none, gets its own\n // (never selected, never submitted).\n const cellValue = useId('wave-empty-swatch');\n const { glyph, button } = unwrapButtonGlyph(icon);\n useSwatchIconWarning('EmptySwatch', button);\n // The optional-indicator rule: `null`/`undefined` keep the plus, anything that renders nothing\n // hides it; an unwrapped button whose children render nothing keeps the plus too.\n const content =\n icon == null || (button !== null && !slotRendersContent(glyph)) ? (\n <AddIcon size={glyphSizeMap[size]} />\n ) : (\n glyph\n );\n\n const control = (\n <button\n type=\"button\"\n {...rest}\n ref={ref}\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : 'Add color')}\n aria-labelledby={ariaLabelledBy}\n // The row layout's root skips its arrow handling for events from here.\n data-wave-empty-swatch=\"\"\n {...(isGrid && { 'data-roving-value': cellValue, tabIndex: getTabIndex(cellValue) })}\n className={cn(\n emptySwatchClassNames.root,\n swatchPickerClassNames.swatch,\n swatchBaseClasses(size, shape, spacing),\n 'border-dashed border-stroke-accessible bg-transparent text-foreground',\n forcedColors.control,\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n className,\n )}\n >\n {slotRendersContent(content) &&\n renderSlot(\n content,\n 'span',\n cn(emptySwatchClassNames.icon, 'pointer-events-none inline-flex'),\n {\n 'aria-hidden': true,\n },\n )}\n </button>\n );\n return isGrid ? <SwatchGridCell>{control}</SwatchGridCell> : control;\n};\nEmptySwatch.displayName = 'EmptySwatch';\n"],"mappings":"uhBA4BA,IAAM+B,EAA4C,CAChD,cAAe,UACf,MAAO,UACP,OAAQ,UACR,MAAO,WACT,EAEMC,EAAiD,CACrD,cAAe,GACf,MAAO,GACP,OAAQ,GACR,MAAO,EACT,EAEMC,EAAkC,CACtC,SAAU,eACV,OAAQ,eACR,QAAS,SACX,EAQA,SAASC,EAAY,CAAE,SAAQ,QAAsD,CACnF,OACE,EAAAJ,EAAA,KAAA,CAAC,OAAD,CAAM,cAAY,OAAO,UAAU,2BAAnC,SAAA,EACE,EAAAA,EAAA,IAAA,CAAC9B,EAAAA,UAAD,CACQ,OACN,YAAa,EACb,UAAWC,EAAAA,GAAG,0BAA2B,CAACkC,GAAU,iBAAiB,EACrE,MAAOA,EAAS,CAAE,MAAOA,EAAO,IAAK,EAAI,IAAA,EAC1C,CAAA,GACD,EAAAL,EAAA,IAAA,CAAC9B,EAAAA,UAAD,CACQ,OACN,YAAa,EACb,UAAWC,EAAAA,GAAG,0BAA2B,CAACkC,GAAU,iBAAiB,EACrE,MAAOA,EAAS,CAAE,MAAOA,EAAO,KAAM,EAAI,IAAA,EAC3C,CAAA,CACG,GAEV,CAMA,SAASC,EAAY,CAAE,UAA0C,CAC/D,OACE,EAAAN,EAAA,KAAA,CAAC,MAAD,CACE,yBAAuB,GACvB,cAAY,OACZ,QAAQ,YACR,KAAK,OACL,UAAU,qDALZ,SAAA,EAOE,EAAAA,EAAA,IAAA,CAAC,OAAD,CACE,GAAG,IACH,GAAG,KACH,GAAG,KACH,GAAG,IACH,OAAO,eACP,cAAc,QACd,YAAa,EACb,UAAWK,EAAS,IAAA,GAAY,kBAChC,MAAOA,EAAS,CAAE,MAAOA,EAAO,IAAK,EAAI,IAAA,EAC1C,CAAA,GACD,EAAAL,EAAA,IAAA,CAAC,OAAD,CACE,GAAG,IACH,GAAG,KACH,GAAG,KACH,GAAG,IACH,OAAO,eACP,cAAc,QACd,YAAa,EACb,UAAWK,EAAS,IAAA,GAAY,kBAChC,MAAOA,EAAS,CAAE,MAAOA,EAAO,KAAM,EAAI,IAAA,EAC3C,CAAA,CACE,GAET,CAGA,SAASE,EAAkB,EAAc,EAAe,EAAwB,CAC9ElB,EAAA,SACE,GAAGmB,EAAK,UACR,GAAGA,EAAK,YAAYC,EAAM,sDAAsDC,EAAS,8EAE3F,CACF,CAMA,SAASC,EAAc,EAAc,EAA0D,CAC7F,GAAM,CAAE,QAAO,UAAWvC,EAAAA,kBAAkBwC,CAAI,EAEhD,OADAC,EAAqBL,EAAMM,CAAM,EAC1BC,CACT,CAGA,SAASF,EAAqB,EAAc,EAAsC,CAChFd,EAAM,cAAgB,CAChBe,GACFzB,EAAA,SACE,GAAGmB,EAAK,cACR,GAAGA,EAAK,sBAAsBM,EAAO,+JAGvC,CAEJ,EAAG,CAACA,EAAQN,CAAI,CAAC,CACnB,CAGA,SAASQ,EAAiB,EAAc,EAAyB,EAAe,CAC9E,IAAMC,EAAU5C,EAAAA,uBAAuBmC,CAAI,EAC3C,MAAO,CAAE,GAAGS,EAAS,KAAMC,GAAQD,EAAQ,KAAM,MAAOE,GAASF,EAAQ,KAAM,CACjF,CAMA,SAASG,EAAc,EAAqC,CAC1D,OAAOC,IAAY,QAAU,iCAAmC,gCAClE,CAOA,SAASC,EAAe,CAAE,WAAU,YAA+D,CACjG,OACE,EAAAtB,EAAA,IAAA,CAAC,MAAD,CAAK,KAAK,WAAW,gBAAeuB,EAAU,UAAU,gBACrD,UACE,CAAA,CAET,CAGA,SAASC,EACP,EACA,EACA,EACQ,CACR,OAAOrD,EAAAA,GACL8B,EAAQiB,GACRf,EAASgB,GAET,kEACA7C,EAAAA,qBACAC,EAAAA,UACA6C,EAAcC,CAAO,EACrB,iDACF,CACF,CAqEA,IAAMI,GAAe,CACnB,OACA,gBACA,gBACA,QACA,eACA,cACA,cACA,QACA,iBACA,cACA,OACA,KAAMC,EACN,MAAOC,EACP,YACA,QACA,UACA,WACA,aAAcC,EACd,kBAAmBC,EACnB,MACA,GAAGC,KACmB,CACtB,GAAM,CACJ,MAAOC,EACP,SACA,OACA,QACA,SACA,YACA,UACA,cACA,YACEf,EAAiBR,EAAMkB,EAAUC,CAAS,EACxCK,EAAaD,IAAkBtB,EAC/BwB,EAAQC,IAAc,MACtBC,EAASC,IAAW,QAAU,CAACH,EAC/BlB,EAAQJ,EAAcH,EAAMI,CAAI,EAEtCb,EAAM,oBAAsBsC,EAAS5B,CAAK,EAAG,CAAC4B,EAAU5B,CAAK,CAAC,EAE9D,IAAM6B,EAAQV,IAAc,IAAA,IAAaC,IAAmB,IAAA,GAC5D9B,EAAM,cAAgB,CACfuC,GAAO/B,EAAkBC,EAAMC,EAAO8B,CAAY,CACzD,EAAG,CAACD,EAAO9B,EAAMC,EAAO8B,CAAY,CAAC,EAErC,IAAMzB,GACJ,EAAAd,EAAA,KAAA,CAAC,SAAD,CACE,KAAK,SAGL,KAAMmC,GAAUF,EAAQ,IAAA,GAAY,QACpC,GAAIH,EACC,MACK,WACV,aAAYF,IAAcC,EAAiB,IAAA,GAAYW,GACvD,kBAAiBX,EACjB,eAAcM,GAAUF,EAAQ,IAAA,GAAYD,EAC5C,eAAcC,EAAQD,EAAaG,GAASH,GAA0B,IAAA,GACtE,oBAAmBvB,EACnB,gBAAeuB,EAAa,GAAK,IAAA,GACjC,SAAUS,EAAYhC,CAAK,EAC3B,QAASjC,EAAAA,qBAAqBkE,MAAeC,EAAOlC,CAAK,CAAC,EAC1D,UAAWtC,EAAAA,GACTyE,EAEAnE,EAAAA,uBAAuB,OACvB+C,EAAkBN,EAAMC,EAAOE,CAAO,EAEtC,uDACAwB,EAGAC,GACE,yFACFpE,EAAAA,aAAa,OAEbsD,GAAc,CAACc,GAAe,mCAC9Bd,EACI7D,EAAAA,GACE,8DACA2E,GAAe,gCACjB,EACA,2DACJC,CACF,EACA,MAAO,CAAE,GAAGC,EAAO,GAAGC,CAAM,EAvC9B,SAAA,CAyCGjB,GACC,EAAAhC,EAAA,IAAA,CAACI,EAAD,CAAa,OAAQ8C,EAAa,KAAMhD,EAAagB,EAAQ,CAAA,EAE7DH,GAAS,MACTpC,EAAAA,mBAAmBoC,CAAK,GACxBnC,EAAAA,WAAWmC,EAAO,OAAQ5C,EAAAA,GAAGgF,EAAe,iCAAiC,EAAG,CAC9E,cAAe,GACf,MAAOD,EAAc,CAAE,MAAOA,EAAY,KAAM,EAAI,IAAA,EACtD,CAAC,EAEFE,IAAY,EAAApD,EAAA,IAAA,CAACM,EAAD,CAAa,OAAQ4C,CAAc,CAAA,CAC1C,IAEV,OAAOf,GAAS,EAAAnC,EAAA,IAAA,CAACsB,EAAD,CAAgB,SAAUU,EAAa,SAAAlB,CAAuB,CAAA,EAAIA,CACpF,EACA,EAAY,YAAc,cAoB1B,IAAauC,GAAe,CAAE,QAAO,cAAa,GAAGvB,MAEjD,EAAA9B,EAAA,IAAA,CAACyB,EAAD,CACE,GAAIK,EACJ,KAAK,cACL,cAAejD,EAAAA,sBAAsB,KACrC,cAAeA,EAAAA,sBAAsB,KACrC,aAAa,cACb,YAAayE,EACb,YAAaxE,EAAAA,eAAewE,CAAK,EACjC,YAAA,GACA,MAAO,CACL,gBAAiBA,EACjB,GAAIC,IAAgB,IAAA,IAAa,CAAE,uBAAwBA,CAAY,CACzE,CACD,CAAA,EAGL,EAAY,YAAc,cA4C1B,IAAaC,GAAe,CAAE,MAAK,GAAG1B,MAElC,EAAA9B,EAAA,IAAA,CAACyB,EAAD,CACE,GAAIK,EACJ,KAAK,cACL,cAAe/C,EAAAA,sBAAsB,KACrC,aAAa,QACb,YAAa+C,EAAK,MAClB,YAAa,KACb,YAAa,GACb,eAAe,kCACf,MAAO,CAAE,gBAAiB,OAAO,KAAK,UAAU2B,CAAG,EAAE,EAAG,CACzD,CAAA,EAGL,EAAY,YAAc,cA0C1B,IAAaC,GAAe,CAC1B,OACA,KAAMhC,EACN,MAAOC,EACP,YACA,aAAcC,EACd,kBAAmBC,EACnB,MACA,GAAGC,KACmB,CACtB,GAAM,CAAE,OAAM,QAAO,SAAQ,YAAW,UAAS,eAAgBd,EAC/D,cACAU,EACAC,CACF,EAEMQ,EAASC,IAAW,QAAUF,IAAc,MAG5CyB,EAAY3E,EAAAA,MAAM,mBAAmB,EACrC,CAAE,QAAO,UAAWZ,EAAAA,kBAAkBwC,CAAI,EAChDC,EAAqB,cAAeC,CAAM,EAG1C,IAAM8C,EACJhD,GAAQ,MAASE,IAAW,MAAQ,CAACnC,EAAAA,mBAAmBoC,CAAK,GAC3D,EAAAf,EAAA,IAAA,CAACf,EAAAA,QAAD,CAAS,KAAMiB,EAAagB,EAAQ,CAAA,EAEpCH,EAGE8C,GACJ,EAAA7D,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,GAAI8B,EACC,MACL,aAAYF,IAAcC,EAAiB,IAAA,GAAY,aACvD,kBAAiBA,EAEjB,yBAAuB,GACvB,GAAKM,GAAU,CAAE,oBAAqBwB,EAAW,SAAUlB,EAAYkB,CAAS,CAAE,EAClF,UAAWxF,EAAAA,GACTe,EAAAA,sBAAsB,KACtBT,EAAAA,uBAAuB,OACvB+C,EAAkBN,EAAMC,EAAOE,CAAO,EACtC,wEACA3C,EAAAA,aAAa,QACb,uDACAqE,CACF,EAEC,SAAApE,EAAAA,mBAAmBiF,CAAO,GACzBhF,EAAAA,WACEgF,EACA,OACAzF,EAAAA,GAAGe,EAAAA,sBAAsB,KAAM,iCAAiC,EAChE,CACE,cAAe,EACjB,CACF,CACI,CAAA,EAEV,OAAOiD,GAAS,EAAAnC,EAAA,IAAA,CAACsB,EAAD,CAAA,SAAiBuC,CAAwB,CAAA,EAAIA,CAC/D,EACA,EAAY,YAAc"}
@@ -0,0 +1,207 @@
1
+ "use client";
2
+ import { cn as e } from "../../lib/cn.mjs";
3
+ import { warnOnce as t } from "../../lib/dev.mjs";
4
+ import { renderSlot as n, slotRendersContent as r } from "../../lib/slot.mjs";
5
+ import { composeEventHandlers as i } from "../../lib/composeEventHandlers.mjs";
6
+ import { colorSwatchClassNames as a, emptySwatchClassNames as o, imageSwatchClassNames as s, swatchPickerClassNames as c } from "../../lib/classNames.mjs";
7
+ import { useId as l } from "../../hooks/useId.mjs";
8
+ import { focusRing as u, forcedColors as d, motionSafeTransition as f } from "../../lib/styles.mjs";
9
+ import { unwrapButtonGlyph as p } from "../button/Button.slots.mjs";
10
+ import { AddIcon as m, CheckIcon as h } from "../../lib/icons.mjs";
11
+ import { useSwatchPickerContext as g } from "./SwatchPicker.context.mjs";
12
+ import { getCheckColors as _ } from "./colorUtils.mjs";
13
+ import * as v from "react";
14
+ import { jsx as y, jsxs as b } from "react/jsx-runtime";
15
+ //#region src/components/input/SwatchPicker.swatches.tsx
16
+ var x = {
17
+ "extra-small": "w-5 h-5",
18
+ small: "w-6 h-6",
19
+ medium: "w-8 h-8",
20
+ large: "w-10 h-10"
21
+ }, S = {
22
+ "extra-small": 10,
23
+ small: 12,
24
+ medium: 16,
25
+ large: 20
26
+ }, C = {
27
+ circular: "rounded-full",
28
+ square: "rounded-none",
29
+ rounded: "rounded"
30
+ };
31
+ function w({ colors: t, size: n }) {
32
+ return /* @__PURE__ */ b("span", {
33
+ "aria-hidden": "true",
34
+ className: "pointer-events-none grid",
35
+ children: [/* @__PURE__ */ y(h, {
36
+ size: n,
37
+ strokeWidth: 4,
38
+ className: e("col-start-1 row-start-1", !t && "text-background"),
39
+ style: t ? { color: t.halo } : void 0
40
+ }), /* @__PURE__ */ y(h, {
41
+ size: n,
42
+ strokeWidth: 2,
43
+ className: e("col-start-1 row-start-1", !t && "text-foreground"),
44
+ style: t ? { color: t.glyph } : void 0
45
+ })]
46
+ });
47
+ }
48
+ function T({ colors: e }) {
49
+ return /* @__PURE__ */ b("svg", {
50
+ "data-wave-swatch-slash": "",
51
+ "aria-hidden": "true",
52
+ viewBox: "0 0 24 24",
53
+ fill: "none",
54
+ className: "pointer-events-none absolute inset-0 h-full w-full",
55
+ children: [/* @__PURE__ */ y("line", {
56
+ x1: "5",
57
+ y1: "19",
58
+ x2: "19",
59
+ y2: "5",
60
+ stroke: "currentColor",
61
+ strokeLinecap: "round",
62
+ strokeWidth: 4,
63
+ className: e ? void 0 : "text-background",
64
+ style: e ? { color: e.halo } : void 0
65
+ }), /* @__PURE__ */ y("line", {
66
+ x1: "5",
67
+ y1: "19",
68
+ x2: "19",
69
+ y2: "5",
70
+ stroke: "currentColor",
71
+ strokeLinecap: "round",
72
+ strokeWidth: 2,
73
+ className: e ? void 0 : "text-foreground",
74
+ style: e ? { color: e.glyph } : void 0
75
+ })]
76
+ });
77
+ }
78
+ function E(e, n, r) {
79
+ t(`${e}:unnamed`, `${e}: swatch "${n}" has no accessible name, so it is announced by its ${r}. Pass \`aria-label\`, or wrap it in a Tooltip with \`relationship="label"\`.`);
80
+ }
81
+ function D(e, t) {
82
+ let { glyph: n, button: r } = p(t);
83
+ return O(e, r), n;
84
+ }
85
+ function O(e, n) {
86
+ v.useEffect(() => {
87
+ n && t(`${e}:icon-button`, `${e}: \`icon\` received ${n}; its children render as the glyph of the swatch and its props were dropped (buttons cannot be nested). Pass icon content instead, e.g. \`icon={<MyIcon />}\`.`);
88
+ }, [n, e]);
89
+ }
90
+ function k(e, t, n) {
91
+ let r = g(e);
92
+ return {
93
+ ...r,
94
+ size: t ?? r.size,
95
+ shape: n ?? r.shape
96
+ };
97
+ }
98
+ function A(e) {
99
+ return e === "small" ? "focus-visible:outline-offset-2" : "focus-visible:outline-offset-4";
100
+ }
101
+ function j({ selected: e, children: t }) {
102
+ return /* @__PURE__ */ y("div", {
103
+ role: "gridcell",
104
+ "aria-selected": e,
105
+ className: "flex shrink-0",
106
+ children: t
107
+ });
108
+ }
109
+ function M(t, n, r) {
110
+ return e(x[t], C[n], "relative flex shrink-0 items-center justify-center border-2 p-0", f, u, A(r), "disabled:cursor-not-allowed disabled:opacity-50");
111
+ }
112
+ var N = ({ kind: t, rootClassName: a, iconClassName: o, value: s, fallbackKind: l, defaultName: u, checkColors: f, paint: p, paintClassName: m, keepsColors: h, icon: g, size: _, shape: x, className: C, style: O, onClick: A, disabled: N, "aria-label": P, "aria-labelledby": F, ref: I, ...L }) => {
113
+ let { value: R, select: z, size: B, shape: V, layout: H, focusMode: U, spacing: W, getTabIndex: G, register: K } = k(t, _, x), q = R === s, J = U === "tab", Y = H === "grid" && !J, X = D(t, g);
114
+ v.useLayoutEffect(() => K(s), [K, s]);
115
+ let Z = P !== void 0 || F !== void 0;
116
+ v.useEffect(() => {
117
+ Z || E(t, s, l);
118
+ }, [
119
+ Z,
120
+ t,
121
+ s,
122
+ l
123
+ ]);
124
+ let Q = /* @__PURE__ */ b("button", {
125
+ type: "button",
126
+ role: Y || J ? void 0 : "radio",
127
+ ...L,
128
+ ref: I,
129
+ disabled: N,
130
+ "aria-label": P ?? (F ? void 0 : u),
131
+ "aria-labelledby": F,
132
+ "aria-checked": Y || J ? void 0 : q,
133
+ "aria-pressed": J ? q : Y && q || void 0,
134
+ "data-roving-value": s,
135
+ "data-selected": q ? "" : void 0,
136
+ tabIndex: G(s),
137
+ onClick: i(A, () => z(s)),
138
+ className: e(a, c.swatch, M(B, V, W), "border-[color:var(--wave-swatch-border,transparent)]", m, h && "forced-colors:forced-color-adjust-none forced-colors:focus-visible:outline-[Highlight]", d.border, q && !h && "forced-colors:border-[Highlight]", q ? e("ring-2 ring-foreground ring-offset-2 ring-offset-background", h && "forced-colors:ring-[Highlight]") : "not-disabled:not-aria-disabled:hover:border-stroke-hover", C),
139
+ style: {
140
+ ...O,
141
+ ...p
142
+ },
143
+ children: [q ? /* @__PURE__ */ y(w, {
144
+ colors: f,
145
+ size: S[B]
146
+ }) : X != null && r(X) && n(X, "span", e(o, "pointer-events-none inline-flex"), {
147
+ "aria-hidden": !0,
148
+ style: f ? { color: f.glyph } : void 0
149
+ }), N && /* @__PURE__ */ y(T, { colors: f })]
150
+ });
151
+ return Y ? /* @__PURE__ */ y(j, {
152
+ selected: q,
153
+ children: Q
154
+ }) : Q;
155
+ };
156
+ N.displayName = "SwatchRadio";
157
+ var P = ({ color: e, borderColor: t, ...n }) => /* @__PURE__ */ y(N, {
158
+ ...n,
159
+ kind: "ColorSwatch",
160
+ rootClassName: a.root,
161
+ iconClassName: a.icon,
162
+ fallbackKind: "color value",
163
+ defaultName: e,
164
+ checkColors: _(e),
165
+ keepsColors: !0,
166
+ paint: {
167
+ backgroundColor: e,
168
+ ...t !== void 0 && { "--wave-swatch-border": t }
169
+ }
170
+ });
171
+ P.displayName = "ColorSwatch";
172
+ var F = ({ src: e, ...t }) => /* @__PURE__ */ y(N, {
173
+ ...t,
174
+ kind: "ImageSwatch",
175
+ rootClassName: s.root,
176
+ fallbackKind: "value",
177
+ defaultName: t.value,
178
+ checkColors: null,
179
+ keepsColors: !1,
180
+ paintClassName: "bg-cover bg-center bg-no-repeat",
181
+ paint: { backgroundImage: `url(${JSON.stringify(e)})` }
182
+ });
183
+ F.displayName = "ImageSwatch";
184
+ var I = ({ icon: t, size: i, shape: a, className: s, "aria-label": u, "aria-labelledby": f, ref: h, ...g }) => {
185
+ let { size: _, shape: v, layout: b, focusMode: x, spacing: C, getTabIndex: w } = k("EmptySwatch", i, a), T = b === "grid" && x !== "tab", E = l("wave-empty-swatch"), { glyph: D, button: A } = p(t);
186
+ O("EmptySwatch", A);
187
+ let N = t == null || A !== null && !r(D) ? /* @__PURE__ */ y(m, { size: S[_] }) : D, P = /* @__PURE__ */ y("button", {
188
+ type: "button",
189
+ ...g,
190
+ ref: h,
191
+ "aria-label": u ?? (f ? void 0 : "Add color"),
192
+ "aria-labelledby": f,
193
+ "data-wave-empty-swatch": "",
194
+ ...T && {
195
+ "data-roving-value": E,
196
+ tabIndex: w(E)
197
+ },
198
+ className: e(o.root, c.swatch, M(_, v, C), "border-dashed border-stroke-accessible bg-transparent text-foreground", d.control, "not-disabled:not-aria-disabled:hover:bg-subtle-hover", s),
199
+ children: r(N) && n(N, "span", e(o.icon, "pointer-events-none inline-flex"), { "aria-hidden": !0 })
200
+ });
201
+ return T ? /* @__PURE__ */ y(j, { children: P }) : P;
202
+ };
203
+ I.displayName = "EmptySwatch";
204
+ //#endregion
205
+ export { P as ColorSwatch, I as EmptySwatch, F as ImageSwatch };
206
+
207
+ //# sourceMappingURL=SwatchPicker.swatches.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SwatchPicker.swatches.mjs","names":["useId","useId$1","React","sizeMap","glyphSizeMap","shapeMap","SwatchCheck","CheckIcon","cn","colors","SwatchSlash","warnUnnamedSwatch","kind","value","fallback","useSwatchIcon","unwrapButtonGlyph","icon","useSwatchIconWarning","button","glyph","warnOnce","useSwatchContext","context","useSwatchPickerContext","size","shape","outlineOffset","spacing","SwatchGridCell","selected","swatchBaseClasses","motionSafeTransition","focusRing","SwatchRadio","sizeProp","shapeProp","ariaLabel","ariaLabelledBy","rest","selectedValue","isSelected","isTab","focusMode","isGrid","layout","register","named","fallbackKind","defaultName","getTabIndex","composeEventHandlers","onClick","select","rootClassName","swatchPickerClassNames","paintClassName","keepsColors","forcedColors","className","style","paint","checkColors","slotRendersContent","renderSlot","iconClassName","disabled","ColorSwatch","colorSwatchClassNames","color","getCheckColors","borderColor","ImageSwatch","imageSwatchClassNames","src","EmptySwatch","cellValue","content","AddIcon","control","emptySwatchClassNames"],"sources":["../../../src/components/input/SwatchPicker.swatches.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n colorSwatchClassNames,\n emptySwatchClassNames,\n imageSwatchClassNames,\n swatchPickerClassNames,\n} from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { warnOnce } from '../../lib/dev';\nimport { AddIcon, CheckIcon } from '../../lib/icons';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\nimport type { Slot } from '../../lib/slot';\nimport { focusRing, forcedColors, motionSafeTransition } from '../../lib/styles';\nimport type { Shape } from '../../lib/types';\nimport { useId } from '../../hooks/useId';\nimport { unwrapButtonGlyph, type UnwrappedButton } from '../button/Button.slots';\nimport { useSwatchPickerContext, type SwatchPickerSize } from './SwatchPicker.context';\nimport { getCheckColors, type CheckColors } from './colorUtils';\n\n/*\n * The swatch kinds a `SwatchPicker` renders `items` through and a consumer can render as children\n * (D18, D21): `ColorSwatch`, `ImageSwatch` and `EmptySwatch`. Every swatch reads\n * `SwatchPickerContext` and puts its `ref`, `className`, `style`, name and rest props on its own\n * `<button>` (an explicit exception to C-ROUTING: there is no separate root, so a wrapping\n * Tooltip's ARIA and handlers reach the focused element without extra wiring).\n */\n\nconst sizeMap: Record<SwatchPickerSize, string> = {\n 'extra-small': 'w-5 h-5',\n small: 'w-6 h-6',\n medium: 'w-8 h-8',\n large: 'w-10 h-10',\n};\n\nconst glyphSizeMap: Record<SwatchPickerSize, number> = {\n 'extra-small': 10,\n small: 12,\n medium: 16,\n large: 20,\n};\n\nconst shapeMap: Record<Shape, string> = {\n circular: 'rounded-full',\n square: 'rounded-none',\n rounded: 'rounded',\n};\n\n/**\n * The check glyph of the selected swatch: black or white by the swatch's luminance, drawn over a\n * halo in the other color so it stays visible on any swatch (C-TOKENS exception for\n * user-supplied colors, `input-pickers#16`). Without `colors` (an image has no single luminance)\n * it is the theme's foreground glyph over a background halo.\n */\nfunction SwatchCheck({ colors, size }: { colors: CheckColors | null; size: number }) {\n return (\n <span aria-hidden=\"true\" className=\"pointer-events-none grid\">\n <CheckIcon\n size={size}\n strokeWidth={4}\n className={cn('col-start-1 row-start-1', !colors && 'text-background')}\n style={colors ? { color: colors.halo } : undefined}\n />\n <CheckIcon\n size={size}\n strokeWidth={2}\n className={cn('col-start-1 row-start-1', !colors && 'text-foreground')}\n style={colors ? { color: colors.glyph } : undefined}\n />\n </span>\n );\n}\n\n/**\n * The diagonal slash of a disabled swatch, drawn like the check glyph (a halo line under a glyph\n * line), so the state does not rely on the swatch color or its opacity.\n */\nfunction SwatchSlash({ colors }: { colors: CheckColors | null }) {\n return (\n <svg\n data-wave-swatch-slash=\"\"\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className=\"pointer-events-none absolute inset-0 h-full w-full\"\n >\n <line\n x1=\"5\"\n y1=\"19\"\n x2=\"19\"\n y2=\"5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth={4}\n className={colors ? undefined : 'text-background'}\n style={colors ? { color: colors.halo } : undefined}\n />\n <line\n x1=\"5\"\n y1=\"19\"\n x2=\"19\"\n y2=\"5\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeWidth={2}\n className={colors ? undefined : 'text-foreground'}\n style={colors ? { color: colors.glyph } : undefined}\n />\n </svg>\n );\n}\n\n/** Warns once per swatch kind (not per value: `<Kind>:unnamed`, e.g. `ColorSwatch:unnamed`). */\nfunction warnUnnamedSwatch(kind: string, value: string, fallback: string): void {\n warnOnce(\n `${kind}:unnamed`,\n `${kind}: swatch \"${value}\" has no accessible name, so it is announced by its ${fallback}. ` +\n 'Pass `aria-label`, or wrap it in a Tooltip with `relationship=\"label\"`.',\n );\n}\n\n/**\n * A swatch's `icon` as a glyph inside its wired button (C-SLOTS): a `<button>` or `Button` is\n * unwrapped (its children become the glyph) with a one-time warning (`<Kind>:icon-button`).\n */\nfunction useSwatchIcon(kind: string, icon: Slot<'span'> | undefined): Slot<'span'> | undefined {\n const { glyph, button } = unwrapButtonGlyph(icon);\n useSwatchIconWarning(kind, button);\n return glyph;\n}\n\n/** The one-time `<Kind>:icon-button` warning for an unwrapped button. */\nfunction useSwatchIconWarning(kind: string, button: UnwrappedButton | null): void {\n React.useEffect(() => {\n if (button) {\n warnOnce(\n `${kind}:icon-button`,\n `${kind}: \\`icon\\` received ${button}; its children render as the glyph of the swatch ` +\n 'and its props were dropped (buttons cannot be nested). Pass icon content instead, ' +\n 'e.g. `icon={<MyIcon />}`.',\n );\n }\n }, [button, kind]);\n}\n\n/** The picker's context with this swatch's own `size` and `shape` applied over the picker's. */\nfunction useSwatchContext(kind: string, size?: SwatchPickerSize, shape?: Shape) {\n const context = useSwatchPickerContext(kind);\n return { ...context, size: size ?? context.size, shape: shape ?? context.shape };\n}\n\n/**\n * Focus outline offset: 4px, clear of a selected swatch's ring band (ring and offset, 4px); 2px at\n * `spacing=\"small\"` so it does not cover the neighbour (D22), where it lies over that band.\n */\nfunction outlineOffset(spacing: 'small' | 'medium'): string {\n return spacing === 'small' ? 'focus-visible:outline-offset-2' : 'focus-visible:outline-offset-4';\n}\n\n/**\n * The cell around a swatch's button in the grid layout: it carries only the role and, for a swatch\n * with a value, `aria-selected` (a `gridcell` role on the button would replace its button role,\n * which `aria-pressed` needs). Every consumer prop stays on the button.\n */\nfunction SwatchGridCell({ selected, children }: { selected?: boolean; children: React.ReactNode }) {\n return (\n <div role=\"gridcell\" aria-selected={selected} className=\"flex shrink-0\">\n {children}\n </div>\n );\n}\n\n/** The classes every swatch kind shares: size, shape, box, motion, focus ring and disabled look. */\nfunction swatchBaseClasses(\n size: SwatchPickerSize,\n shape: Shape,\n spacing: 'small' | 'medium',\n): string {\n return cn(\n sizeMap[size],\n shapeMap[shape],\n // The padding is set here (C-NATIVE).\n 'relative flex shrink-0 items-center justify-center border-2 p-0',\n motionSafeTransition,\n focusRing,\n outlineOffset(spacing),\n 'disabled:cursor-not-allowed disabled:opacity-50',\n );\n}\n\n/** Properties for the ColorSwatch component. */\nexport interface ColorSwatchProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value' | 'color'\n> {\n /** Unique identifier for the swatch (the value the picker selects and a form submits). */\n value: string;\n /** CSS color value (e.g., hex, rgb) used as the swatch background (a runtime user color). */\n color: string;\n /**\n * Decorative glyph (`aria-hidden`) shown while the swatch is not selected; the check replaces it\n * while selected. A `<button>` or `Button` passed here is not nested: its children become the\n * glyph and a one-time development warning is logged.\n */\n icon?: Slot<'span'>;\n /**\n * CSS color of the swatch's border, for a color close to the page background (set by hand, as\n * in Fluent). In forced colors the system border color replaces it.\n */\n borderColor?: string;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /**\n * Ref to the swatch button: `role=\"radio\"` in the row layout, inside its cell in the grid\n * layout, a toggle button in tab mode.\n */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/** What `ColorSwatch` and `ImageSwatch` do differently. */\ninterface SwatchRadioProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value' | 'color'\n> {\n kind: 'ColorSwatch' | 'ImageSwatch';\n /** The kind's stable root class, named by the module that sets its `displayName` (P3-00). */\n rootClassName: string;\n /** The kind's stable `icon` part class (ColorSwatch only). */\n iconClassName?: string;\n value: string;\n /** What names the swatch when it has no name: 'color value' or 'value' (the warning's text). */\n fallbackKind: string;\n /** The accessible name of an unnamed swatch. */\n defaultName: string;\n /** The luminance-picked glyph colors; `null`: the theme's foreground over a background halo. */\n checkColors: CheckColors | null;\n /** The swatch's own background, border color and image (they win over a consumer `style`). */\n paint: Record<string, string>;\n /** Classes of the image swatch's covering background. */\n paintClassName?: string;\n /** A color swatch keeps its colors in forced colors (the color is the content). */\n keepsColors: boolean;\n icon?: Slot<'span'>;\n size?: SwatchPickerSize;\n shape?: Shape;\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/** The radio button shared by `ColorSwatch` and `ImageSwatch`. */\nconst SwatchRadio = ({\n kind,\n rootClassName,\n iconClassName,\n value,\n fallbackKind,\n defaultName,\n checkColors,\n paint,\n paintClassName,\n keepsColors,\n icon,\n size: sizeProp,\n shape: shapeProp,\n className,\n style,\n onClick,\n disabled,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ref,\n ...rest\n}: SwatchRadioProps) => {\n const {\n value: selectedValue,\n select,\n size,\n shape,\n layout,\n focusMode,\n spacing,\n getTabIndex,\n register,\n } = useSwatchContext(kind, sizeProp, shapeProp);\n const isSelected = selectedValue === value;\n const isTab = focusMode === 'tab';\n const isGrid = layout === 'grid' && !isTab;\n const glyph = useSwatchIcon(kind, icon);\n\n React.useLayoutEffect(() => register(value), [register, value]);\n\n const named = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n React.useEffect(() => {\n if (!named) warnUnnamedSwatch(kind, value, fallbackKind);\n }, [named, kind, value, fallbackKind]);\n\n const button = (\n <button\n type=\"button\"\n // The grid layout: a plain button inside its gridcell, pressed while selected (D20); tab\n // mode (D19): a toggle button of a group, `aria-pressed` always present.\n role={isGrid || isTab ? undefined : 'radio'}\n {...rest}\n ref={ref}\n disabled={disabled}\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : defaultName)}\n aria-labelledby={ariaLabelledBy}\n aria-checked={isGrid || isTab ? undefined : isSelected}\n aria-pressed={isTab ? isSelected : isGrid ? isSelected || undefined : undefined}\n data-roving-value={value}\n data-selected={isSelected ? '' : undefined}\n tabIndex={getTabIndex(value)}\n onClick={composeEventHandlers(onClick, () => select(value))}\n className={cn(\n rootClassName,\n // Every swatch in a picker carries the picker's part class, children included (0.8).\n swatchPickerClassNames.swatch,\n swatchBaseClasses(size, shape, spacing),\n // A `borderColor` arrives as a variable, so the forced-colors edge below still wins.\n 'border-[color:var(--wave-swatch-border,transparent)]',\n paintClassName,\n // User colors are the content: keep them (and the check glyph) in forced colors, with a\n // Highlight outline, which an opted-out element would otherwise draw in author colors.\n keepsColors &&\n 'forced-colors:forced-color-adjust-none forced-colors:focus-visible:outline-[Highlight]',\n forcedColors.border,\n // An image stays in forced colors, so its selection needs a sign of its own.\n isSelected && !keepsColors && 'forced-colors:border-[Highlight]',\n isSelected\n ? cn(\n 'ring-2 ring-foreground ring-offset-2 ring-offset-background',\n keepsColors && 'forced-colors:ring-[Highlight]',\n )\n : 'not-disabled:not-aria-disabled:hover:border-stroke-hover',\n className,\n )}\n style={{ ...style, ...paint }}\n >\n {isSelected ? (\n <SwatchCheck colors={checkColors} size={glyphSizeMap[size]} />\n ) : (\n glyph != null &&\n slotRendersContent(glyph) &&\n renderSlot(glyph, 'span', cn(iconClassName, 'pointer-events-none inline-flex'), {\n 'aria-hidden': true,\n style: checkColors ? { color: checkColors.glyph } : undefined,\n })\n )}\n {disabled && <SwatchSlash colors={checkColors} />}\n </button>\n );\n return isGrid ? <SwatchGridCell selected={isSelected}>{button}</SwatchGridCell> : button;\n};\nSwatchRadio.displayName = 'SwatchRadio';\n\n// D18: swatches read SwatchPickerContext; their own ref/className/style/rest go straight to the\n// button (an explicit exception to C-ROUTING's root/control split).\n/**\n * One color swatch of a `SwatchPicker`, read from `items` or rendered directly as a child.\n * Outside a `SwatchPicker` it throws in development and renders inertly in production.\n *\n * **Naming**: give it `aria-label`, or wrap it in a `Tooltip` with `relationship=\"label\"` (its\n * `aria-labelledby` reaches this element, since every rest prop lands on the swatch's own\n * button). Without either it is named by its `color` value and a development warning is logged.\n *\n * **Disabled**: `disabled` is native (out of the arrow keys and the tab order, never selected);\n * the swatch is dimmed and crossed by a diagonal slash, so the state does not rely on its color.\n *\n * @example\n * <SwatchPicker aria-label=\"Accent color\">\n * <ColorSwatch value=\"red\" color=\"#d13438\" aria-label=\"Red\" />\n * </SwatchPicker>\n */\nexport const ColorSwatch = ({ color, borderColor, ...rest }: ColorSwatchProps) => {\n return (\n <SwatchRadio\n {...rest}\n kind=\"ColorSwatch\"\n rootClassName={colorSwatchClassNames.root}\n iconClassName={colorSwatchClassNames.icon}\n fallbackKind=\"color value\"\n defaultName={color}\n checkColors={getCheckColors(color)}\n keepsColors\n paint={{\n backgroundColor: color,\n ...(borderColor !== undefined && { '--wave-swatch-border': borderColor }),\n }}\n />\n );\n};\nColorSwatch.displayName = 'ColorSwatch';\n\n/** Properties for the ImageSwatch component. */\nexport interface ImageSwatchProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'value'\n> {\n /** Unique identifier for the swatch (the value the picker selects and a form submits). */\n value: string;\n /** URL of the image (drawn as a covering background image). */\n src: string;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /**\n * Ref to the swatch button: `role=\"radio\"` in the row layout, inside its cell in the grid\n * layout, a toggle button in tab mode.\n */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * One image swatch of a `SwatchPicker`: a pattern or texture drawn as a covering background\n * image. Outside a `SwatchPicker` it throws in development and renders inertly in production.\n *\n * **Naming**: give it `aria-label`, or wrap it in a `Tooltip` with `relationship=\"label\"`.\n * Without either it is named by its `value` and a development warning is logged.\n *\n * **Selected and disabled**: an image has no single luminance, so the check and the disabled slash\n * are the theme's foreground glyph over a background halo. Unlike `ColorSwatch` it does not opt\n * out of forced colors (a background image stays).\n *\n * @example\n * <SwatchPicker aria-label=\"Pattern\">\n * <ImageSwatch value=\"dots\" src=\"/dots.png\" aria-label=\"Dots\" />\n * </SwatchPicker>\n */\nexport const ImageSwatch = ({ src, ...rest }: ImageSwatchProps) => {\n return (\n <SwatchRadio\n {...rest}\n kind=\"ImageSwatch\"\n rootClassName={imageSwatchClassNames.root}\n fallbackKind=\"value\"\n defaultName={rest.value}\n checkColors={null}\n keepsColors={false}\n paintClassName=\"bg-cover bg-center bg-no-repeat\"\n paint={{ backgroundImage: `url(${JSON.stringify(src)})` }}\n />\n );\n};\nImageSwatch.displayName = 'ImageSwatch';\n\n/** Properties for the EmptySwatch component. */\nexport interface EmptySwatchProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /**\n * Accessible name of the button.\n * @default 'Add color'\n */\n 'aria-label'?: string;\n /**\n * Decorative glyph (`aria-hidden`). `null` and `undefined` keep the plus glyph; `false` or\n * anything that renders nothing shows none. A `<button>` or `Button` passed here is not nested:\n * its children become the glyph and a one-time development warning is logged.\n * @default a plus glyph\n */\n icon?: Slot<'span'>;\n /**\n * Size of the swatch (20, 24, 32 or 40px).\n * @default the picker's\n */\n size?: SwatchPickerSize;\n /**\n * Shape of the swatch.\n * @default the picker's\n */\n shape?: Shape;\n /** Ref to the button. */\n ref?: React.Ref<HTMLButtonElement>;\n}\n\n/**\n * An \"add\" button inside a `SwatchPicker` (for example to open a color dialog): it has no value\n * and is never selected. In the row layout it is a plain button with its own tab stop, outside\n * the radio group's arrow order, and arrow keys pressed on it do nothing. In the grid layout it\n * is a cell like the others, in the arrow order (without `aria-selected`). Outside a\n * `SwatchPicker` it throws in development and renders inertly in production.\n *\n * @example\n * <SwatchPicker aria-label=\"Accent color\" items={items}>\n * <EmptySwatch onClick={openColorDialog} />\n * </SwatchPicker>\n */\nexport const EmptySwatch = ({\n icon,\n size: sizeProp,\n shape: shapeProp,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n ref,\n ...rest\n}: EmptySwatchProps) => {\n const { size, shape, layout, focusMode, spacing, getTabIndex } = useSwatchContext(\n 'EmptySwatch',\n sizeProp,\n shapeProp,\n );\n // Tab mode has no grid cells: the button is a tab stop of its own, like in the row layout.\n const isGrid = layout === 'grid' && focusMode !== 'tab';\n // The grid's roving keys address cells by value: an EmptySwatch, which has none, gets its own\n // (never selected, never submitted).\n const cellValue = useId('wave-empty-swatch');\n const { glyph, button } = unwrapButtonGlyph(icon);\n useSwatchIconWarning('EmptySwatch', button);\n // The optional-indicator rule: `null`/`undefined` keep the plus, anything that renders nothing\n // hides it; an unwrapped button whose children render nothing keeps the plus too.\n const content =\n icon == null || (button !== null && !slotRendersContent(glyph)) ? (\n <AddIcon size={glyphSizeMap[size]} />\n ) : (\n glyph\n );\n\n const control = (\n <button\n type=\"button\"\n {...rest}\n ref={ref}\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : 'Add color')}\n aria-labelledby={ariaLabelledBy}\n // The row layout's root skips its arrow handling for events from here.\n data-wave-empty-swatch=\"\"\n {...(isGrid && { 'data-roving-value': cellValue, tabIndex: getTabIndex(cellValue) })}\n className={cn(\n emptySwatchClassNames.root,\n swatchPickerClassNames.swatch,\n swatchBaseClasses(size, shape, spacing),\n 'border-dashed border-stroke-accessible bg-transparent text-foreground',\n forcedColors.control,\n 'not-disabled:not-aria-disabled:hover:bg-subtle-hover',\n className,\n )}\n >\n {slotRendersContent(content) &&\n renderSlot(\n content,\n 'span',\n cn(emptySwatchClassNames.icon, 'pointer-events-none inline-flex'),\n {\n 'aria-hidden': true,\n },\n )}\n </button>\n );\n return isGrid ? <SwatchGridCell>{control}</SwatchGridCell> : control;\n};\nEmptySwatch.displayName = 'EmptySwatch';\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../lib/direction.cjs"),c=require("../../hooks/useMergedRefs.cjs"),ee=require("../../hooks/useIsClient.cjs"),te=require("../../lib/aria.cjs"),l=require("../../hooks/useFieldControl.cjs"),ne=require("../../hooks/useAnnounce.cjs"),u=require("../../lib/styles.cjs"),d=require("../../lib/icons.cjs"),re=require("./inputLook.cjs"),ie=require("./Input.cjs"),ae=require("../../hooks/useFormReset.cjs"),oe=require("../internal/HiddenInput.cjs"),se=require("../../hooks/useListbox.cjs"),f=require("./Option.cjs"),p=require("../../hooks/usePreserveFocus.cjs");let m=require("react");m=e.__toESM(m,1);let h=require("react/jsx-runtime");var ce=e=>`Remove ${e}`,le=e=>`Selected: ${e.join(`, `)}`,ue=(e,t)=>`${e} added, ${t} selected`,de=(e,t)=>`${e} removed, ${t} selected`,fe=[`medium`,`large`,`extra-large`],pe={medium:{control:`gap-1 px-2 py-1.5`,tag:`px-2 py-0.5 text-body-1`,input:`py-0.5 text-body-1`},large:{control:`gap-1.5 px-2.5 py-2`,tag:`px-2 py-1 text-body-1`,input:`py-1 text-body-1`},"extra-large":{control:`gap-1.5 px-3 py-2.5`,tag:`px-2.5 py-1 text-body-2`,input:`py-1 text-body-2`}},g=[];function me(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function he({label:e,disabled:n,onClick:r,onKeyDown:a,getFallback:o}){let s=m.useRef(null);return p.usePreserveFocus(s,o),(0,h.jsx)(`button`,{ref:s,type:`button`,"data-wave-tagpicker-remove":``,disabled:n,"aria-label":e,className:t.cn(i.tagPickerClassNames.removeButton,`ms-0.5 inline-flex rounded-sm bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground disabled:cursor-not-allowed`,u.focusRing),onClick:r,onKeyDown:a,children:(0,h.jsx)(d.DismissIcon,{size:12})})}var _=e=>{let{options:d,value:p,defaultValue:_,onValueChange:ge,onChange:v,open:_e,defaultOpen:ve,onOpenChange:ye,placeholder:be=`Select...`,disabled:y=!1,size:xe,appearance:Se,name:Ce,form:b,required:x,autoComplete:we=`off`,autoCapitalize:Te,autoCorrect:Ee,maxLength:De,readOnly:S,labels:C,inputMode:Oe,spellCheck:ke,enterKeyHint:w,autoFocus:Ae,tabIndex:je,id:Me,"aria-label":Ne,"aria-labelledby":Pe,"aria-describedby":Fe,"aria-invalid":Ie,"aria-required":Le,"aria-errormessage":Re,"aria-details":ze,onFocus:Be,onBlur:Ve,onKeyDown:He,onKeyUp:Ue,controlRef:We,className:Ge,ref:Ke,...qe}=e;v!==void 0&&n.warnDeprecated(`TagPicker`,`onChange`,`onValueChange`);let T=l.useFieldContext(),Je=(x??T?.required??!1)&&!S,E=l.useFieldControl({id:Me,"aria-label":Ne,"aria-labelledby":Pe,"aria-describedby":Fe,"aria-invalid":Ie,"aria-required":Le??x}),Ye=ie.isInvalidLook(!1,E[`aria-invalid`]),{size:D,appearance:O}=re.useInputLook(xe,Se,{sizes:fe,defaultSize:`medium`}),k=pe[D],[A,j]=a.useControllable(p,_??g,e=>{let t=[...e];ge?.(t),v?.(t)}),M=!y&&!S,[N,P]=a.useControllable(_e,(ve??!1)&&M,ye),Xe=ee.useIsClient(),F=N&&M&&Xe,[I,L]=m.useState(``),[Ze,Qe]=m.useState(M);Ze!==M&&(Qe(M),M||L(``));let R=!M&&N;m.useEffect(()=>{R&&P(!1)},[R,P]);let z=ne.useAnnounce(),B=m.useRef(null),V=m.useRef(null),H=o.useId(`tagpicker-summary`),U=m.useMemo(()=>{let e=new Map;for(let t of d)e.has(t.value)||e.set(t.value,t.label);return e},[d]),W=e=>U.get(e)??e,$e=m.useMemo(()=>{let e=new Set(A);return d.filter(t=>!e.has(t.value)).map(e=>({value:e.value,label:e.label}))},[d,A]),et=m.useMemo(()=>I?e=>e.label.toLowerCase().includes(I.toLowerCase()):void 0,[I]),G=A.filter(e=>!U.has(e)).join(`\0`);m.useEffect(()=>{G&&n.warnOnce(`TagPicker:unknown-value`,`TagPicker: the selected value(s) ${G.split(`\0`).map(e=>`"${e}"`).join(`, `)} match no option; the raw value is shown as the tag label.`)},[G]);let tt=()=>V.current,K=()=>V.current?.focus(),nt=e=>{if(!M||A.includes(e))return;let t=[...A,e];j(t),L(``),z((C?.added??ue)(W(e),t.length))},q=e=>{if(!M)return;let t=A.filter(t=>t!==e);j(t),z((C?.removed??de)(W(e),t.length)),K()},J=se.useListbox({open:F,onOpenChange:e=>P(e),mode:`editable`,multiple:!0,selectedValues:A,onSelect:e=>nt(e),items:$e,filter:et,autoHighlight:I?`first`:!1,idPrefix:`tagpicker-listbox`,onClearDraft:I?()=>L(``):void 0}),Y=F&&J.items.length>0,X=C?.noMatches??`No matches`,Z=F&&(Y||I!==``),rt=Z&&!Y,{layerId:it,setReference:at,surfaceRef:Q,floatingProps:ot}=f.useListboxPopup({open:F,surfaceOpen:Z,onDismiss:()=>P(!1),rootRef:B,anchorRef:V}),st=c.useMergedRefs(B,Ke),ct=c.useMergedRefs(V,We);ae.useFormReset(V,()=>{let e=_??g;j(t=>me(t,e)?t:[...e]),L(``)},b);let $=e=>Array.from(e.closest(`[data-wave-tagpicker-control]`)?.querySelectorAll(`[data-wave-tagpicker-remove]`)??[]),lt=e=>{if(M){if(e.key===`Escape`&&F&&!Z&&!e.nativeEvent.isComposing){P(!1);return}if(e.key===`Backspace`&&I===``&&A.length>0){e.preventDefault(),$(e.currentTarget).at(-1)?.focus();return}J.onKeyDown(e)}},ut=(e,t)=>{if(!M)return;let n=$(e.currentTarget),r=n.indexOf(e.currentTarget);if(e.key===`Backspace`||e.key===`Delete`){e.preventDefault(),q(t);return}if(e.key===`Escape`){e.preventDefault(),K();return}let i=s.getArrowIntent(e.key,{orientation:`horizontal`,dir:s.getDirection(e.currentTarget)});i===`prev`&&r>0?(e.preventDefault(),n[r-1].focus()):i===`next`&&(e.preventDefault(),r<n.length-1?n[r+1].focus():K())},dt=E[`aria-label`]===void 0?E[`aria-labelledby`]??T?.labelId:E[`aria-labelledby`];return(0,h.jsxs)(`div`,{"data-size":D,"data-appearance":O,...qe,ref:st,className:t.cn(i.tagPickerClassNames.root,`relative`,Ge),children:[(0,h.jsxs)(`div`,{ref:at,"data-wave-tagpicker-control":``,role:`group`,"aria-disabled":y||void 0,className:t.cn(i.tagPickerClassNames.control,`flex flex-wrap items-center`,k.control,u.inputAppearanceClasses[O],u.inputFocusWithin,Ye&&`border-destructive`,y&&`cursor-not-allowed opacity-50`),onClick:e=>{y||e.target.closest(`button`)||(K(),!F&&M&&P(!0))},children:[A.length>0&&(0,h.jsx)(`div`,{role:`list`,"aria-label":C?.selected??`Selected`,className:t.cn(i.tagPickerClassNames.group,`flex flex-wrap items-center gap-1`),children:A.map(e=>{let n=W(e);return(0,h.jsxs)(`div`,{role:`listitem`,className:t.cn(i.tagPickerClassNames.tag,`inline-flex items-center gap-1 rounded bg-muted text-foreground`,k.tag),children:[n,!S&&(0,h.jsx)(he,{label:(C?.remove??ce)(n),disabled:y,onClick:()=>q(e),onKeyDown:t=>ut(t,e),getFallback:tt})]},e)})}),A.length>0&&(0,h.jsx)(`span`,{id:H,hidden:!0,children:(C?.summary??le)(A.map(W))}),(0,h.jsx)(`input`,{type:`text`,autoComplete:we,...E,...J.getComboboxProps(),"aria-expanded":Y,"aria-describedby":te.joinIds(E[`aria-describedby`],A.length>0?H:void 0),"aria-errormessage":Re,"aria-details":ze,ref:ct,disabled:y,readOnly:S,placeholder:A.length===0?be:``,autoCapitalize:Te,autoCorrect:Ee,maxLength:De,inputMode:Oe,spellCheck:ke,enterKeyHint:w,autoFocus:Ae,tabIndex:je,value:I,onChange:e=>{M&&(L(e.target.value),F||P(!0))},onKeyDown:r.composeEventHandlers(He,lt),onKeyUp:r.composeEventHandlers(Ue,J.onKeyUp),onFocus:Be,onBlur:Ve,className:t.cn(i.tagPickerClassNames.input,`min-w-15 flex-1 bg-transparent text-foreground placeholder:text-muted-foreground focus:outline-hidden`,k.input)})]}),(0,h.jsx)(`span`,{role:`status`,className:`sr-only`,children:rt&&X}),(0,h.jsx)(f.ListboxSurface,{listbox:J,layerId:it,surfaceRef:Q,floatingProps:ot,open:F,expanded:Y,showCheck:!1,listboxClassName:i.tagPickerClassNames.listbox,surfaceClassName:i.tagPickerClassNames.surface,emptyContent:I===``?void 0:(0,h.jsx)(`div`,{"aria-hidden":`true`,className:t.cn(i.tagPickerClassNames.emptyMessage,`px-3 py-1.5 text-body-1 text-muted-foreground`),children:X}),"aria-label":E[`aria-label`],"aria-labelledby":dt,children:Y&&J.items.map(e=>(0,h.jsx)(f.Option,{value:e.value,label:e.label,className:i.tagPickerClassNames.option,children:e.label},e.value))}),(0,h.jsx)(oe.HiddenInput,{name:Ce,form:b,disabled:y,value:A,type:`text`,required:Je,onInvalid:K})]})};_.displayName=`TagPicker`,exports.TagPicker=_;
1
+ "use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useControllable.cjs"),o=require("../../hooks/useId.cjs"),s=require("../../lib/direction.cjs"),c=require("../../hooks/useMergedRefs.cjs"),ee=require("../../hooks/useIsClient.cjs"),te=require("../../lib/aria.cjs"),l=require("../../hooks/useFieldControl.cjs"),ne=require("../../hooks/useAnnounce.cjs"),re=require("../../hooks/useListbox.cjs"),u=require("../../lib/styles.cjs"),d=require("../../lib/icons.cjs"),ie=require("./inputLook.cjs"),ae=require("./Input.cjs"),oe=require("../../hooks/useFormReset.cjs"),se=require("../internal/HiddenInput.cjs"),f=require("./Option.cjs"),p=require("./pickerLabels.cjs"),m=require("./pickerValues.cjs"),h=require("../../hooks/usePreserveFocus.cjs");let g=require("react");g=e.__toESM(g,1);let _=require("react/jsx-runtime");var ce=e=>`Remove ${e}`,le=e=>`Selected: ${e.join(`, `)}`;function ue(e,t){return e.label.toLowerCase().includes(t.toLowerCase())}var de=[`medium`,`large`,`extra-large`],fe={medium:{control:`gap-1 px-2 py-1.5`,tag:`px-2 py-0.5 text-body-1`,input:`py-0.5 text-body-1`},large:{control:`gap-1.5 px-2.5 py-2`,tag:`px-2 py-1 text-body-1`,input:`py-1 text-body-1`},"extra-large":{control:`gap-1.5 px-3 py-2.5`,tag:`px-2.5 py-1 text-body-2`,input:`py-1 text-body-2`}};function pe({label:e,disabled:n,onClick:r,onKeyDown:a,getFallback:o}){let s=g.useRef(null);return h.usePreserveFocus(s,o),(0,_.jsx)(`button`,{ref:s,type:`button`,"data-wave-tagpicker-remove":``,disabled:n,"aria-label":e,className:t.cn(i.tagPickerClassNames.removeButton,`ms-0.5 inline-flex rounded-sm bg-transparent p-0 text-muted-foreground not-disabled:not-aria-disabled:hover:text-foreground disabled:cursor-not-allowed`,u.focusRing),onClick:r,onKeyDown:a,children:(0,_.jsx)(d.DismissIcon,{size:12})})}var v=e=>{let{options:d,value:h,defaultValue:v,onValueChange:me,onChange:y,open:he,defaultOpen:ge,onOpenChange:_e,placeholder:ve=`Select...`,filter:b,query:ye,defaultQuery:be,onQueryChange:xe,disabled:x=!1,size:Se,appearance:Ce,name:we,form:S,required:C,autoComplete:Te=`off`,autoCapitalize:Ee,autoCorrect:De,maxLength:Oe,readOnly:w,labels:T,inputMode:ke,spellCheck:Ae,enterKeyHint:je,autoFocus:Me,tabIndex:Ne,id:Pe,"aria-label":Fe,"aria-labelledby":Ie,"aria-describedby":Le,"aria-invalid":Re,"aria-required":ze,"aria-errormessage":Be,"aria-details":Ve,onFocus:He,onBlur:Ue,onKeyDown:We,onKeyUp:Ge,controlRef:Ke,className:qe,ref:Je,...Ye}=e;y!==void 0&&n.warnDeprecated(`TagPicker`,`onChange`,`onValueChange`);let E=l.useFieldContext(),Xe=(C??E?.required??!1)&&!w,D=l.useFieldControl({id:Pe,"aria-label":Fe,"aria-labelledby":Ie,"aria-describedby":Le,"aria-invalid":Re,"aria-required":ze??C}),Ze=ae.isInvalidLook(!1,D[`aria-invalid`]),{size:O,appearance:k}=ie.useInputLook(Se,Ce,{sizes:de,defaultSize:`medium`}),A=fe[O],[j,M]=a.useControllable(h,v??m.EMPTY_VALUES,e=>{let t=[...e];me?.(t),y?.(t)}),N=!x&&!w,[P,F]=a.useControllable(he,(ge??!1)&&N,_e),Qe=ee.useIsClient(),I=P&&N&&Qe,[$e,L]=a.useControllable(ye,N?be??``:``,xe),R=N?$e:``,[z,B]=g.useState(N?`unlocked`:`mounted-locked`);N&&z!==`unlocked`?B(`unlocked`):!N&&z===`unlocked`&&B(`locked`),g.useEffect(()=>{z===`locked`&&L(``)},[z,L]);let V=!N&&P;g.useEffect(()=>{V&&F(!1)},[V,F]),ne.useAnnounce();let H=g.useRef(null),U=g.useRef(null),W=o.useId(`tagpicker-summary`),G=g.useMemo(()=>{let e=new Map;for(let t of d)e.has(t.value)||e.set(t.value,t.label);return e},[d]),K=e=>G.get(e)??e,et=g.useMemo(()=>{let e=new Set(j);return d.filter(t=>!e.has(t.value)).map(e=>({value:e.value,label:e.label}))},[d,j]),tt=g.useMemo(()=>R?e=>(b??ue)(e,R):void 0,[R,b]),q=j.filter(e=>!G.has(e)).join(`\0`);g.useEffect(()=>{q&&n.warnOnce(`TagPicker:unknown-value`,`TagPicker: the selected value(s) ${q.split(`\0`).map(e=>`"${e}"`).join(`, `)} match no option; the raw value is shown as the tag label.`)},[q]);let nt=()=>U.current,J=()=>U.current?.focus(),rt=e=>{if(!N||j.includes(e))return;let t=[...j,e];M(t),L(``),p.announceToggle(T,K(e),!0,t.length)},Y=e=>{if(!N)return;let t=j.filter(t=>t!==e);M(t),p.announceToggle(T,K(e),!1,t.length),J()},X=re.useListbox({open:I,onOpenChange:e=>F(e),mode:`editable`,multiselect:!0,selectedValues:j,onSelect:e=>rt(e),items:et,filter:tt,autoHighlight:R?`first`:!1,idPrefix:`tagpicker-listbox`,onClearDraft:R?()=>L(``):void 0}),Z=I&&X.items.length>0,Q=T?.noMatches??`No matches`,$=I&&(Z||R!==``),it=$&&!Z,{layerId:at,setReference:ot,surfaceRef:st,floatingProps:ct}=f.useListboxPopup({open:I,surfaceOpen:$,onDismiss:()=>F(!1),rootRef:H,anchorRef:U}),lt=c.useMergedRefs(H,Je),ut=c.useMergedRefs(U,Ke);oe.useFormReset(U,()=>{let e=v??m.EMPTY_VALUES;M(t=>m.sameValues(t,e)?t:[...e]),L(``)},S);let dt=e=>Array.from(e.closest(`[data-wave-tagpicker-control]`)?.querySelectorAll(`[data-wave-tagpicker-remove]`)??[]),ft=e=>{if(N){if(e.key===`Escape`&&I&&!$&&!e.nativeEvent.isComposing){F(!1);return}if(e.key===`Backspace`&&R===``&&j.length>0){e.preventDefault(),dt(e.currentTarget).at(-1)?.focus();return}X.onKeyDown(e)}},pt=(e,t)=>{if(!N)return;let n=dt(e.currentTarget),r=n.indexOf(e.currentTarget);if(e.key===`Backspace`||e.key===`Delete`){e.preventDefault(),Y(t);return}if(e.key===`Escape`){e.preventDefault(),J();return}let i=s.getArrowIntent(e.key,{orientation:`horizontal`,dir:s.getDirection(e.currentTarget)});i===`prev`&&r>0?(e.preventDefault(),n[r-1].focus()):i===`next`&&(e.preventDefault(),r<n.length-1?n[r+1].focus():J())},mt=D[`aria-label`]===void 0?D[`aria-labelledby`]??E?.labelId:D[`aria-labelledby`];return(0,_.jsxs)(`div`,{"data-size":O,"data-appearance":k,...Ye,ref:lt,className:t.cn(i.tagPickerClassNames.root,`relative`,qe),children:[(0,_.jsxs)(`div`,{ref:ot,"data-wave-tagpicker-control":``,role:`group`,"aria-disabled":x||void 0,className:t.cn(i.tagPickerClassNames.control,`flex flex-wrap items-center`,A.control,u.inputAppearanceClasses[k],u.inputFocusWithin,Ze&&`border-destructive`,x&&`cursor-not-allowed opacity-50`),onClick:e=>{x||e.target.closest(`button`)||(J(),!I&&N&&F(!0))},children:[j.length>0&&(0,_.jsx)(`div`,{role:`list`,"aria-label":T?.selected??`Selected`,className:t.cn(i.tagPickerClassNames.group,`flex flex-wrap items-center gap-1`),children:j.map(e=>{let n=K(e);return(0,_.jsxs)(`div`,{role:`listitem`,className:t.cn(i.tagPickerClassNames.tag,`inline-flex items-center gap-1 rounded bg-muted text-foreground`,A.tag),children:[n,!w&&(0,_.jsx)(pe,{label:(T?.remove??ce)(n),disabled:x,onClick:()=>Y(e),onKeyDown:t=>pt(t,e),getFallback:nt})]},e)})}),j.length>0&&(0,_.jsx)(`span`,{id:W,hidden:!0,children:(T?.summary??le)(j.map(K))}),(0,_.jsx)(`input`,{type:`text`,autoComplete:Te,...D,...X.getComboboxProps(),"aria-expanded":Z,"aria-describedby":te.joinIds(D[`aria-describedby`],j.length>0?W:void 0),"aria-errormessage":Be,"aria-details":Ve,ref:ut,disabled:x,readOnly:w,placeholder:j.length===0?ve:``,autoCapitalize:Ee,autoCorrect:De,maxLength:Oe,inputMode:ke,spellCheck:Ae,enterKeyHint:je,autoFocus:Me,tabIndex:Ne,value:R,onChange:e=>{N&&(L(e.target.value),I||F(!0))},onKeyDown:r.composeEventHandlers(We,ft),onKeyUp:r.composeEventHandlers(Ge,X.onKeyUp),onFocus:He,onBlur:Ue,className:t.cn(i.tagPickerClassNames.input,`min-w-15 flex-1 bg-transparent text-foreground placeholder:text-muted-foreground focus:outline-hidden`,A.input)})]}),(0,_.jsx)(`span`,{role:`status`,className:`sr-only`,children:it&&Q}),(0,_.jsx)(f.ListboxSurface,{listbox:X,layerId:at,surfaceRef:st,floatingProps:ct,open:I,expanded:Z,showCheck:!1,listClassName:i.tagPickerClassNames.listbox,surfaceClassName:i.tagPickerClassNames.surface,emptyContent:R===``?void 0:(0,_.jsx)(`div`,{"aria-hidden":`true`,className:t.cn(i.tagPickerClassNames.emptyMessage,`px-3 py-1.5 text-body-1 text-muted-foreground`),children:Q}),"aria-label":D[`aria-label`],"aria-labelledby":mt,children:Z&&X.items.map(e=>(0,_.jsx)(f.Option,{value:e.value,label:e.label,className:i.tagPickerClassNames.option,children:e.label},e.value))}),(0,_.jsx)(se.HiddenInput,{name:we,form:S,disabled:x,value:j,type:`text`,required:Xe,onInvalid:J})]})};v.displayName=`TagPicker`,exports.TagPicker=v;
2
2
  //# sourceMappingURL=TagPicker.cjs.map