@geomak/ui 5.5.0 → 5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9,12 +9,12 @@ import { useReducedMotion, AnimatePresence, motion } from 'framer-motion';
9
9
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
10
10
  import * as TabsPrimitive from '@radix-ui/react-tabs';
11
11
  import * as Accordion from '@radix-ui/react-accordion';
12
- import * as ToggleGroup from '@radix-ui/react-toggle-group';
13
12
  import * as ContextMenuPrimitive from '@radix-ui/react-context-menu';
14
13
  import * as Popover from '@radix-ui/react-popover';
15
14
  import * as SwitchPrimitive from '@radix-ui/react-switch';
16
15
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
17
16
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
17
+ import * as ToggleGroup from '@radix-ui/react-toggle-group';
18
18
  import * as SliderPrimitive from '@radix-ui/react-slider';
19
19
 
20
20
  var Moon = ({ color = "gray" }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", fill: color, viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: color, className: "w-8 h-8", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" }) });
@@ -1143,38 +1143,6 @@ function Tree({
1143
1143
  item.key
1144
1144
  )) });
1145
1145
  }
1146
- function ToggleButton({ items, onChange, activeKey }) {
1147
- return /* @__PURE__ */ jsx(
1148
- ToggleGroup.Root,
1149
- {
1150
- type: "single",
1151
- value: activeKey,
1152
- onValueChange: (val) => {
1153
- if (val) onChange(val);
1154
- },
1155
- className: "flex items-center",
1156
- children: items.map((item, index) => /* @__PURE__ */ jsx(
1157
- ToggleGroup.Item,
1158
- {
1159
- value: item.key,
1160
- "aria-label": typeof item.label === "string" ? item.label : item.key,
1161
- className: [
1162
- // Semantic tokens handle both light and dark modes via
1163
- // CSS vars — no `dark:` variants needed.
1164
- index === 0 && "rounded-l-lg border-r border-border",
1165
- index === items.length - 1 && "rounded-r-lg border-l border-border",
1166
- "p-2 cursor-pointer transition-colors duration-150 text-foreground-secondary",
1167
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
1168
- "bg-surface hover:bg-surface-raised",
1169
- "data-[state=on]:bg-accent data-[state=on]:text-accent-fg"
1170
- ].filter(Boolean).join(" "),
1171
- children: item.icon ?? item.label
1172
- },
1173
- item.key
1174
- ))
1175
- }
1176
- );
1177
- }
1178
1146
  var NotificationContext = createContext({
1179
1147
  open: () => void 0,
1180
1148
  close: () => void 0
@@ -1576,6 +1544,10 @@ var TOGGLE_POSITION_CLASS = {
1576
1544
  function ScalableContainer({
1577
1545
  width = "100%",
1578
1546
  height = "auto",
1547
+ expandedWidth = "100%",
1548
+ expandedHeight = "100%",
1549
+ expanded,
1550
+ onExpandedChange,
1579
1551
  children,
1580
1552
  assignClassOnClick,
1581
1553
  expandIcon,
@@ -1583,27 +1555,32 @@ function ScalableContainer({
1583
1555
  togglePosition = "top-right"
1584
1556
  }) {
1585
1557
  const containerRef = useRef(null);
1586
- const [isScaled, setScaled] = useState(false);
1558
+ const [internalScaled, setInternalScaled] = useState(false);
1559
+ const isScaled = expanded ?? internalScaled;
1587
1560
  const reduced = useReducedMotion();
1588
1561
  const onToggle = () => {
1589
1562
  const next = !isScaled;
1590
- setScaled(next);
1591
- requestAnimationFrame(() => containerRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }));
1563
+ if (expanded === void 0) setInternalScaled(next);
1564
+ onExpandedChange?.(next);
1565
+ if (next) {
1566
+ window.setTimeout(
1567
+ () => containerRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }),
1568
+ reduced ? 0 : 340
1569
+ );
1570
+ }
1592
1571
  };
1593
1572
  const wrapperClass = isScaled ? assignClassOnClick : void 0;
1594
1573
  return /* @__PURE__ */ jsxs(
1595
1574
  motion.div,
1596
1575
  {
1597
1576
  ref: containerRef,
1598
- layout: true,
1599
1577
  animate: {
1600
- width: isScaled ? "100%" : width,
1601
- height: isScaled ? "100%" : height
1578
+ width: isScaled ? expandedWidth : width,
1579
+ height: isScaled ? expandedHeight : height
1602
1580
  },
1603
1581
  transition: reduced ? { duration: 0 } : {
1604
1582
  width: { type: "tween", duration: 0.32, ease: [0.16, 1, 0.3, 1] },
1605
- height: { type: "tween", duration: 0.32, ease: [0.16, 1, 0.3, 1] },
1606
- layout: { duration: 0.32, ease: [0.16, 1, 0.3, 1] }
1583
+ height: { type: "tween", duration: 0.32, ease: [0.16, 1, 0.3, 1] }
1607
1584
  },
1608
1585
  className: [
1609
1586
  "relative rounded-lg overflow-hidden",
@@ -2139,10 +2116,10 @@ var FIELD_SIZE = {
2139
2116
  md: { control: "h-control-md", text: "text-sm", padX: "px-3", gap: "gap-2" },
2140
2117
  lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
2141
2118
  };
2142
- var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent focus-within:ring-[3px] focus-within:ring-focus-ring";
2143
- var FOCUS_VISIBLE = "focus-visible:outline-none focus-visible:border-accent focus-visible:ring-[3px] focus-visible:ring-focus-ring";
2144
- var FOCUS_WITHIN_ERROR = "focus-within:border-status-error focus-within:ring-focus-ring-error";
2145
- var FOCUS_VISIBLE_ERROR = "focus-visible:border-status-error focus-visible:ring-focus-ring-error";
2119
+ var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent";
2120
+ var FOCUS_ELEMENT = "focus:outline-none focus:border-accent data-[state=open]:border-accent";
2121
+ var FOCUS_WITHIN_ERROR = "focus-within:border-status-error";
2122
+ var FOCUS_ELEMENT_ERROR = "focus:border-status-error data-[state=open]:border-status-error";
2146
2123
  function fieldShell({
2147
2124
  size = "md",
2148
2125
  hasError = false,
@@ -2161,8 +2138,8 @@ function fieldShell({
2161
2138
  // hover (only when interactive + no error)
2162
2139
  disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
2163
2140
  // focus
2164
- focusWithin ? FOCUS_WITHIN : FOCUS_VISIBLE,
2165
- hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_VISIBLE_ERROR : "",
2141
+ focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
2142
+ hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
2166
2143
  // placeholder colour for native inputs
2167
2144
  "placeholder:text-foreground-muted"
2168
2145
  ].filter(Boolean).join(" ");
@@ -2197,7 +2174,9 @@ function Field({
2197
2174
  style: { width: horizontal ? labelWidth : void 0, ...labelStyle },
2198
2175
  className: [
2199
2176
  "text-sm font-medium text-foreground select-none",
2200
- horizontal ? "mt-2 flex-shrink-0" : ""
2177
+ // In horizontal layout the label must not wrap onto
2178
+ // multiple lines (e.g. "Report date", "Select option").
2179
+ horizontal ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""
2201
2180
  ].filter(Boolean).join(" "),
2202
2181
  children: [
2203
2182
  label,
@@ -2243,14 +2222,24 @@ var SearchInput = React8.forwardRef(function SearchInput2({ value, onChange, dis
2243
2222
  ) });
2244
2223
  });
2245
2224
  var SearchInput_default = SearchInput;
2246
- function DropdownPill({ value, hasSiblings = false }) {
2247
- return /* @__PURE__ */ jsx(
2248
- "div",
2249
- {
2250
- className: `bg-accent text-accent-fg text-sm text-ellipsis ${hasSiblings ? "w-24" : "w-max"} p-1 px-2 rounded-lg whitespace-nowrap overflow-hidden`,
2251
- children: value
2252
- }
2253
- );
2225
+ function Tag({ children, onRemove, removeLabel, disabled }) {
2226
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-md border border-border bg-surface-raised text-foreground text-xs pl-2 pr-1 py-0.5 max-w-full", children: [
2227
+ /* @__PURE__ */ jsx("span", { className: "truncate", children }),
2228
+ onRemove && /* @__PURE__ */ jsx(
2229
+ "button",
2230
+ {
2231
+ type: "button",
2232
+ disabled,
2233
+ onClick: (e) => {
2234
+ e.stopPropagation();
2235
+ onRemove();
2236
+ },
2237
+ "aria-label": removeLabel ?? "Remove",
2238
+ className: "inline-flex items-center justify-center w-4 h-4 flex-shrink-0 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent disabled:cursor-not-allowed",
2239
+ children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
2240
+ }
2241
+ )
2242
+ ] });
2254
2243
  }
2255
2244
  function Dropdown({
2256
2245
  isMultiselect = false,
@@ -2267,7 +2256,6 @@ function Dropdown({
2267
2256
  items = [],
2268
2257
  labelStyle = {},
2269
2258
  placeholder,
2270
- showSelectedCount = false,
2271
2259
  size = "md"
2272
2260
  }) {
2273
2261
  const [open, setOpen] = useState(false);
@@ -2295,6 +2283,17 @@ function Dropdown({
2295
2283
  setOpen(false);
2296
2284
  }
2297
2285
  };
2286
+ const removeSelected = (key) => {
2287
+ if (isMultiselect) {
2288
+ const next = selectedItems.filter((it) => it !== key);
2289
+ setSelectedItems(next);
2290
+ onChange?.({ target: { value: next, id: htmlFor, name } });
2291
+ } else {
2292
+ setSelectedItems([]);
2293
+ onChange?.({ target: { value: "", id: htmlFor, name } });
2294
+ }
2295
+ };
2296
+ const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
2298
2297
  const onSearchChange = (e) => {
2299
2298
  const term = e.target.value;
2300
2299
  setSearchTerm(term);
@@ -2305,16 +2304,16 @@ function Dropdown({
2305
2304
  );
2306
2305
  };
2307
2306
  const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
2308
- return /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
2307
+ return /* @__PURE__ */ jsxs("div", { children: [
2309
2308
  /* @__PURE__ */ jsxs(
2310
2309
  "div",
2311
2310
  {
2312
- className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`,
2311
+ className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
2313
2312
  children: [
2314
2313
  label && /* @__PURE__ */ jsx(
2315
2314
  "label",
2316
2315
  {
2317
- className: "text-sm font-medium ml-1 max-content select-none text-foreground",
2316
+ className: `text-sm font-medium select-none text-foreground ${layout === "horizontal" ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""}`,
2318
2317
  htmlFor,
2319
2318
  style: labelStyle,
2320
2319
  children: label
@@ -2331,7 +2330,7 @@ function Dropdown({
2331
2330
  "aria-invalid": hasError || void 0,
2332
2331
  "aria-describedby": hasError ? errorId : void 0,
2333
2332
  style,
2334
- className: `flex items-center justify-between cursor-pointer select-none ${fieldShell({ size, hasError, disabled })}`,
2333
+ className: `flex items-center justify-between gap-1 cursor-pointer select-none min-h-[36px] px-3 py-1.5 ${fieldShell({ size, hasError, disabled, sized: false })}`,
2335
2334
  tabIndex: disabled ? -1 : 0,
2336
2335
  onKeyDown: (e) => {
2337
2336
  if (disabled) return;
@@ -2344,18 +2343,25 @@ function Dropdown({
2344
2343
  /* @__PURE__ */ jsx(
2345
2344
  "div",
2346
2345
  {
2347
- className: `${!style?.width ? "min-w-[200px]" : ""} flex items-center gap-1 overflow-hidden`,
2348
- children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxs(Fragment, { children: [
2349
- value.slice(0, 1).map((val) => /* @__PURE__ */ jsx(
2350
- DropdownPill,
2351
- {
2352
- hasSiblings: value.length > 1,
2353
- value: innerItems.find((it) => it.key === val)?.label
2354
- },
2355
- String(val)
2356
- )),
2357
- showSelectedCount && value.length > 1 && /* @__PURE__ */ jsx(DropdownPill, { value: `+${value.length - 1} more` })
2358
- ] }) : /* @__PURE__ */ jsx(DropdownPill, { value: innerItems.find((it) => it.key === value)?.label })
2346
+ className: `${!style?.width ? "min-w-[200px]" : ""} flex flex-wrap items-center gap-1.5`,
2347
+ children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? value.map((val) => /* @__PURE__ */ jsx(
2348
+ Tag,
2349
+ {
2350
+ disabled,
2351
+ removeLabel: `Remove ${labelFor(val)}`,
2352
+ onRemove: () => removeSelected(val),
2353
+ children: labelFor(val)
2354
+ },
2355
+ String(val)
2356
+ )) : /* @__PURE__ */ jsx(
2357
+ Tag,
2358
+ {
2359
+ disabled,
2360
+ removeLabel: `Remove ${labelFor(value)}`,
2361
+ onRemove: () => removeSelected(value),
2362
+ children: labelFor(value)
2363
+ }
2364
+ )
2359
2365
  }
2360
2366
  ),
2361
2367
  /* @__PURE__ */ jsx("div", { className: `flex-shrink-0 ml-2 text-foreground-muted transition-transform duration-200 ${open ? "rotate-180" : "rotate-0"}`, "aria-hidden": "true", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
@@ -3549,74 +3555,54 @@ function Checkbox({
3549
3555
  name,
3550
3556
  htmlFor,
3551
3557
  errorMessage,
3552
- disabled = false
3558
+ disabled = false,
3559
+ layout = "horizontal",
3560
+ labelPosition = "right"
3553
3561
  }) {
3554
3562
  const isChecked = checked ?? value ?? false;
3563
+ const labelFirst = labelPosition === "left";
3564
+ const box = /* @__PURE__ */ jsx(
3565
+ CheckboxPrimitive.Root,
3566
+ {
3567
+ id: htmlFor,
3568
+ name,
3569
+ checked: isChecked,
3570
+ disabled,
3571
+ onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
3572
+ className: [
3573
+ "relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
3574
+ "rounded-sm border transition-colors duration-150",
3575
+ "border-border-strong bg-surface",
3576
+ "data-[state=checked]:bg-accent data-[state=checked]:border-accent",
3577
+ // Focus halo matches the field tokens for a consistent look.
3578
+ "focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
3579
+ "disabled:cursor-not-allowed"
3580
+ ].join(" "),
3581
+ "aria-label": typeof label === "string" ? label : void 0,
3582
+ children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center data-[state=checked]:animate-check-pop", children: /* @__PURE__ */ jsx("svg", { width: "11", height: "9", viewBox: "0 0 11 9", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M1 4.5L4 7.5L10 1", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
3583
+ }
3584
+ );
3585
+ const labelEl = label && /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label });
3555
3586
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
3556
- /* @__PURE__ */ jsxs(
3587
+ /* @__PURE__ */ jsx(
3557
3588
  "label",
3558
3589
  {
3559
3590
  htmlFor,
3560
3591
  className: [
3561
- "inline-flex items-center gap-2.5",
3592
+ "inline-flex",
3593
+ layout === "vertical" ? "flex-col items-start gap-1.5" : "flex-row items-center gap-2.5",
3562
3594
  disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
3563
3595
  ].join(" "),
3564
- children: [
3565
- /* @__PURE__ */ jsx(
3566
- CheckboxPrimitive.Root,
3567
- {
3568
- id: htmlFor,
3569
- name,
3570
- checked: isChecked,
3571
- disabled,
3572
- onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
3573
- className: [
3574
- // Box
3575
- "relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
3576
- "rounded-sm border transition-colors duration-150",
3577
- // Unchecked
3578
- "border-border-strong bg-surface",
3579
- // Checked
3580
- "data-[state=checked]:bg-accent data-[state=checked]:border-accent",
3581
- // Focus
3582
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1",
3583
- // Disabled
3584
- "disabled:cursor-not-allowed"
3585
- ].join(" "),
3586
- "aria-label": typeof label === "string" ? label : void 0,
3587
- children: /* @__PURE__ */ jsx(
3588
- CheckboxPrimitive.Indicator,
3589
- {
3590
- className: "flex items-center justify-center data-[state=checked]:animate-check-pop",
3591
- children: /* @__PURE__ */ jsx(
3592
- "svg",
3593
- {
3594
- width: "11",
3595
- height: "9",
3596
- viewBox: "0 0 11 9",
3597
- fill: "none",
3598
- "aria-hidden": "true",
3599
- children: /* @__PURE__ */ jsx(
3600
- "path",
3601
- {
3602
- d: "M1 4.5L4 7.5L10 1",
3603
- stroke: "white",
3604
- strokeWidth: "1.8",
3605
- strokeLinecap: "round",
3606
- strokeLinejoin: "round"
3607
- }
3608
- )
3609
- }
3610
- )
3611
- }
3612
- )
3613
- }
3614
- ),
3615
- label && /* @__PURE__ */ jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label })
3616
- ]
3596
+ children: labelFirst ? /* @__PURE__ */ jsxs(Fragment, { children: [
3597
+ labelEl,
3598
+ box
3599
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3600
+ box,
3601
+ labelEl
3602
+ ] })
3617
3603
  }
3618
3604
  ),
3619
- errorMessage && /* @__PURE__ */ jsx("span", { className: "text-xs text-status-error pl-[26px]", children: errorMessage })
3605
+ errorMessage && /* @__PURE__ */ jsx("span", { className: "text-xs text-status-error mt-0.5", children: errorMessage })
3620
3606
  ] });
3621
3607
  }
3622
3608
  var DOT_SIZE = {
@@ -3722,12 +3708,12 @@ function Switch({
3722
3708
  id,
3723
3709
  checked,
3724
3710
  onCheckedChange: (c) => onChange?.({ target: { checked: c } }),
3725
- className: "relative inline-flex h-6 w-14 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-2",
3711
+ className: "relative inline-flex h-6 w-11 flex-shrink-0 items-center rounded-full bg-foreground-secondary data-[state=checked]:bg-accent transition-colors focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
3726
3712
  children: /* @__PURE__ */ jsx(
3727
3713
  SwitchPrimitive.Thumb,
3728
3714
  {
3729
- className: "pointer-events-none inline-flex h-8 w-8 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[-4px]",
3730
- children: checkedIcon && uncheckedIcon ? checked ? checkedIcon : uncheckedIcon : null
3715
+ className: "pointer-events-none flex h-5 w-5 items-center justify-center rounded-full bg-background text-foreground shadow transition-transform duration-200 data-[state=checked]:translate-x-[22px] data-[state=unchecked]:translate-x-[2px]",
3716
+ children: checkedIcon && uncheckedIcon ? checked ? /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-3 h-3", children: checkedIcon }) : /* @__PURE__ */ jsx("span", { className: "flex items-center justify-center w-3 h-3", children: uncheckedIcon }) : null
3731
3717
  }
3732
3718
  )
3733
3719
  }
@@ -3748,8 +3734,13 @@ function AutoComplete({
3748
3734
  emptyText = "No results found",
3749
3735
  loadingText = "Searching\u2026",
3750
3736
  size = "md",
3751
- icon
3737
+ icon,
3738
+ errorMessage,
3739
+ required,
3740
+ htmlFor
3752
3741
  }) {
3742
+ const errorId = useId();
3743
+ const hasError = errorMessage != null;
3753
3744
  const [term, setTerm] = useState("");
3754
3745
  const [open, setOpen] = useState(false);
3755
3746
  const [asyncItems, setAsyncItems] = useState([]);
@@ -3796,78 +3787,82 @@ function AutoComplete({
3796
3787
  onItemClick?.(item.value);
3797
3788
  setOpen(false);
3798
3789
  };
3799
- return /* @__PURE__ */ jsxs(
3800
- "div",
3790
+ return /* @__PURE__ */ jsx(
3791
+ Field,
3801
3792
  {
3802
- className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
3803
- style,
3804
- children: [
3805
- label && /* @__PURE__ */ jsx("label", { className: `text-sm font-medium text-foreground select-none ${layout === "horizontal" ? "mt-2 flex-shrink-0" : ""}`, children: label }),
3806
- /* @__PURE__ */ jsx("div", { className: "flex flex-col min-w-0 flex-1", children: /* @__PURE__ */ jsxs(Popover.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
3807
- /* @__PURE__ */ jsx(Popover.Anchor, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: `flex items-center ${fieldShell({ size, disabled, focusWithin: true })}`, children: [
3808
- /* @__PURE__ */ jsx(
3809
- "input",
3810
- {
3811
- disabled,
3812
- value: term,
3813
- onChange: (e) => {
3814
- setTerm(e.target.value);
3815
- setOpen(true);
3816
- },
3817
- onFocus: () => setOpen(true),
3818
- type: "text",
3819
- name,
3820
- className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
3821
- style: inputStyle,
3822
- placeholder: placeholder ?? "",
3823
- autoComplete: "off",
3824
- "aria-haspopup": "listbox",
3825
- "aria-expanded": open,
3826
- "aria-autocomplete": "list",
3827
- "aria-busy": loading || void 0
3828
- }
3829
- ),
3830
- loading ? /* @__PURE__ */ jsx("span", { className: "ml-2 w-4 h-4 flex-shrink-0 flex items-center justify-center text-accent", "aria-hidden": "true", children: /* @__PURE__ */ jsx(LoadingSpinner, { inline: true, size: "xs", spinnerColor: "currentColor" }) }) : /* @__PURE__ */ jsx("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) }) })
3831
- ] }) }),
3832
- /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
3833
- Popover.Content,
3793
+ label,
3794
+ htmlFor,
3795
+ errorId,
3796
+ errorMessage,
3797
+ layout,
3798
+ required,
3799
+ children: /* @__PURE__ */ jsxs(Popover.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
3800
+ /* @__PURE__ */ jsx(Popover.Anchor, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: `flex items-center ${fieldShell({ size, hasError, disabled, focusWithin: true })}`, style, children: [
3801
+ /* @__PURE__ */ jsx(
3802
+ "input",
3834
3803
  {
3835
- align: "start",
3836
- sideOffset: 4,
3837
- onOpenAutoFocus: (e) => e.preventDefault(),
3838
- className: "w-64 bg-surface border border-border rounded-lg mt-1 shadow-md z-50 overflow-y-auto max-h-36 animate-in fade-in-0 zoom-in-95",
3839
- children: loading ? /* @__PURE__ */ jsxs("div", { className: "h-full w-full flex items-center justify-center gap-2 py-4 text-sm text-foreground-secondary", children: [
3840
- /* @__PURE__ */ jsx(LoadingSpinner, { inline: true, size: "xs" }),
3841
- /* @__PURE__ */ jsx("span", { children: loadingText })
3842
- ] }) : foundItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "h-full w-full flex flex-col items-center justify-center py-4 text-sm text-foreground-secondary", children: emptyText }) : /* @__PURE__ */ jsx("div", { role: "listbox", children: foundItems.map((item) => /* @__PURE__ */ jsxs(
3843
- "div",
3844
- {
3845
- role: "option",
3846
- tabIndex: 0,
3847
- className: "text-sm flex items-center gap-2 p-2 transition-colors duration-150 hover:bg-surface-raised cursor-pointer text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3848
- onClick: () => handleSelect(item),
3849
- onKeyDown: (e) => {
3850
- if (e.key === "Enter" || e.key === " ") {
3851
- e.preventDefault();
3852
- handleSelect(item);
3853
- }
3854
- },
3855
- children: [
3856
- item.icon,
3857
- /* @__PURE__ */ jsxs("span", { children: [
3858
- item.label,
3859
- " (",
3860
- item.value,
3861
- ")"
3862
- ] })
3863
- ]
3864
- },
3865
- item.key
3866
- )) })
3804
+ id: htmlFor,
3805
+ disabled,
3806
+ value: term,
3807
+ onChange: (e) => {
3808
+ setTerm(e.target.value);
3809
+ setOpen(true);
3810
+ },
3811
+ onFocus: () => setOpen(true),
3812
+ type: "text",
3813
+ name,
3814
+ className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
3815
+ style: inputStyle,
3816
+ placeholder: placeholder ?? "",
3817
+ autoComplete: "off",
3818
+ "aria-haspopup": "listbox",
3819
+ "aria-expanded": open,
3820
+ "aria-autocomplete": "list",
3821
+ "aria-busy": loading || void 0,
3822
+ "aria-invalid": hasError || void 0,
3823
+ "aria-describedby": hasError ? errorId : void 0
3867
3824
  }
3868
- ) })
3869
- ] }) })
3870
- ]
3825
+ ),
3826
+ loading ? /* @__PURE__ */ jsx("span", { className: "ml-2 w-4 h-4 flex-shrink-0 flex items-center justify-center text-accent", "aria-hidden": "true", children: /* @__PURE__ */ jsx(LoadingSpinner, { inline: true, size: "xs", spinnerColor: "currentColor" }) }) : /* @__PURE__ */ jsx("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", className: "w-4 h-4", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M10.5 3.75a6.75 6.75 0 100 13.5 6.75 6.75 0 000-13.5zM2.25 10.5a8.25 8.25 0 1114.59 5.28l4.69 4.69a.75.75 0 11-1.06 1.06l-4.69-4.69A8.25 8.25 0 012.25 10.5z", clipRule: "evenodd" }) }) })
3827
+ ] }) }),
3828
+ /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
3829
+ Popover.Content,
3830
+ {
3831
+ align: "start",
3832
+ sideOffset: 4,
3833
+ onOpenAutoFocus: (e) => e.preventDefault(),
3834
+ className: "w-64 bg-surface border border-border rounded-lg mt-1 shadow-md z-50 overflow-y-auto max-h-36 animate-in fade-in-0 zoom-in-95",
3835
+ children: loading ? /* @__PURE__ */ jsxs("div", { className: "h-full w-full flex items-center justify-center gap-2 py-4 text-sm text-foreground-secondary", children: [
3836
+ /* @__PURE__ */ jsx(LoadingSpinner, { inline: true, size: "xs" }),
3837
+ /* @__PURE__ */ jsx("span", { children: loadingText })
3838
+ ] }) : foundItems.length === 0 ? /* @__PURE__ */ jsx("div", { className: "h-full w-full flex flex-col items-center justify-center py-4 text-sm text-foreground-secondary", children: emptyText }) : /* @__PURE__ */ jsx("div", { role: "listbox", children: foundItems.map((item) => /* @__PURE__ */ jsxs(
3839
+ "div",
3840
+ {
3841
+ role: "option",
3842
+ tabIndex: 0,
3843
+ className: "text-sm flex items-center gap-2 p-2 transition-colors duration-150 hover:bg-surface-raised cursor-pointer text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
3844
+ onClick: () => handleSelect(item),
3845
+ onKeyDown: (e) => {
3846
+ if (e.key === "Enter" || e.key === " ") {
3847
+ e.preventDefault();
3848
+ handleSelect(item);
3849
+ }
3850
+ },
3851
+ children: [
3852
+ item.icon,
3853
+ /* @__PURE__ */ jsxs("span", { children: [
3854
+ item.label,
3855
+ " (",
3856
+ item.value,
3857
+ ")"
3858
+ ] })
3859
+ ]
3860
+ },
3861
+ item.key
3862
+ )) })
3863
+ }
3864
+ ) })
3865
+ ] })
3871
3866
  }
3872
3867
  );
3873
3868
  }
@@ -4947,27 +4942,13 @@ function TagsInput({
4947
4942
  className: `flex flex-wrap items-center gap-1.5 min-h-[36px] ${fieldShell({ size, hasError, disabled, focusWithin: true, sized: false })} px-2 py-1.5`,
4948
4943
  onClick: () => inputRef.current?.focus(),
4949
4944
  children: [
4950
- tags.map((tag, idx) => /* @__PURE__ */ jsxs(
4951
- "span",
4945
+ tags.map((tag, idx) => /* @__PURE__ */ jsx(
4946
+ Tag,
4952
4947
  {
4953
- className: "inline-flex items-center gap-1 rounded-md bg-surface-raised text-foreground text-xs pl-2 pr-1 py-0.5 border border-border",
4954
- children: [
4955
- tag,
4956
- /* @__PURE__ */ jsx(
4957
- "button",
4958
- {
4959
- type: "button",
4960
- disabled,
4961
- onClick: (e) => {
4962
- e.stopPropagation();
4963
- removeTag(idx);
4964
- },
4965
- "aria-label": `Remove ${tag}`,
4966
- className: "inline-flex items-center justify-center w-4 h-4 rounded text-foreground-muted hover:text-status-error hover:bg-surface transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-accent",
4967
- children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
4968
- }
4969
- )
4970
- ]
4948
+ disabled,
4949
+ removeLabel: `Remove ${tag}`,
4950
+ onRemove: () => removeTag(idx),
4951
+ children: tag
4971
4952
  },
4972
4953
  `${tag}-${idx}`
4973
4954
  )),
@@ -5201,9 +5182,9 @@ function Rating({
5201
5182
  /* @__PURE__ */ jsx(
5202
5183
  "span",
5203
5184
  {
5204
- className: "absolute inset-0 overflow-hidden",
5185
+ className: "absolute inset-y-0 left-0 overflow-hidden",
5205
5186
  style: { width: `${fillFraction * 100}%` },
5206
- children: icon(true)
5187
+ children: /* @__PURE__ */ jsx("span", { className: `block absolute inset-y-0 left-0 ${ICON_SIZE[size]} max-w-none`, children: icon(true) })
5207
5188
  }
5208
5189
  )
5209
5190
  ]
@@ -5642,6 +5623,6 @@ function ColorPicker({
5642
5623
  ] });
5643
5624
  }
5644
5625
 
5645
- export { AppShell, AutoComplete, Avatar, Box, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ColorPicker, ContextMenu, DateRangePicker, Drawer, Dropdown, FadingBase, Field, FileInput, Flex, Grid2 as Grid, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, Modal, NotificationProvider, NumberInput, OpaqueGridCard, OtpInput, Password, Portal, RadioGroup, Rating, ScalableContainer, SearchInput_default as SearchInput, SegmentedControl, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Slider, Switch, Table, Tabs, TagsInput, DatePicker as Temporal, TextArea, TextInput, ThemeProvider, ThemeSwitch, TimePicker, ToggleButton, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Typography, Wizard, fieldShell, useNotification };
5626
+ export { AppShell, AutoComplete, Avatar, Box, Button, Catalog, CatalogCarousel, CatalogGrid, Checkbox, ColorPicker, ContextMenu, DateRangePicker, Drawer, Dropdown, FadingBase, Field, FileInput, Flex, Grid2 as Grid, GridCard, icons_default as Icon, IconButton, List2 as List, LoadingSpinner, Modal, NotificationProvider, NumberInput, OpaqueGridCard, OtpInput, Password, Portal, RadioGroup, Rating, ScalableContainer, SearchInput_default as SearchInput, SegmentedControl, Sidebar, SkeletonBox, SkeletonCard, SkeletonCircle, SkeletonText, Slider, Switch, Table, Tabs, TagsInput, DatePicker as Temporal, TextArea, TextInput, ThemeProvider, ThemeSwitch, TimePicker, Tooltip, TooltipProvider, TopBar, Tree, TreeSelect, Typography, Wizard, fieldShell, useNotification };
5646
5627
  //# sourceMappingURL=index.js.map
5647
5628
  //# sourceMappingURL=index.js.map