@geomak/ui 5.5.0 → 5.5.1

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.cjs CHANGED
@@ -2175,9 +2175,9 @@ var FIELD_SIZE = {
2175
2175
  lg: { control: "h-control-lg", text: "text-sm", padX: "px-3.5", gap: "gap-2.5" }
2176
2176
  };
2177
2177
  var FOCUS_WITHIN = "focus-within:outline-none focus-within:border-accent focus-within:ring-[3px] focus-within:ring-focus-ring";
2178
- var FOCUS_VISIBLE = "focus-visible:outline-none focus-visible:border-accent focus-visible:ring-[3px] focus-visible:ring-focus-ring";
2178
+ var FOCUS_ELEMENT = "focus:outline-none focus:border-accent focus:ring-[3px] focus:ring-focus-ring data-[state=open]:border-accent data-[state=open]:ring-[3px] data-[state=open]:ring-focus-ring";
2179
2179
  var FOCUS_WITHIN_ERROR = "focus-within:border-status-error focus-within:ring-focus-ring-error";
2180
- var FOCUS_VISIBLE_ERROR = "focus-visible:border-status-error focus-visible:ring-focus-ring-error";
2180
+ var FOCUS_ELEMENT_ERROR = "focus:border-status-error focus:ring-focus-ring-error data-[state=open]:border-status-error data-[state=open]:ring-focus-ring-error";
2181
2181
  function fieldShell({
2182
2182
  size = "md",
2183
2183
  hasError = false,
@@ -2196,8 +2196,8 @@ function fieldShell({
2196
2196
  // hover (only when interactive + no error)
2197
2197
  disabled ? "bg-surface-raised text-foreground-muted cursor-not-allowed" : hasError ? "" : "hover:border-border-strong",
2198
2198
  // focus
2199
- focusWithin ? FOCUS_WITHIN : FOCUS_VISIBLE,
2200
- hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_VISIBLE_ERROR : "",
2199
+ focusWithin ? FOCUS_WITHIN : FOCUS_ELEMENT,
2200
+ hasError ? focusWithin ? FOCUS_WITHIN_ERROR : FOCUS_ELEMENT_ERROR : "",
2201
2201
  // placeholder colour for native inputs
2202
2202
  "placeholder:text-foreground-muted"
2203
2203
  ].filter(Boolean).join(" ");
@@ -2232,7 +2232,9 @@ function Field({
2232
2232
  style: { width: horizontal ? labelWidth : void 0, ...labelStyle },
2233
2233
  className: [
2234
2234
  "text-sm font-medium text-foreground select-none",
2235
- horizontal ? "mt-2 flex-shrink-0" : ""
2235
+ // In horizontal layout the label must not wrap onto
2236
+ // multiple lines (e.g. "Report date", "Select option").
2237
+ horizontal ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""
2236
2238
  ].filter(Boolean).join(" "),
2237
2239
  children: [
2238
2240
  label,
@@ -2278,14 +2280,24 @@ var SearchInput = React8__default.default.forwardRef(function SearchInput2({ val
2278
2280
  ) });
2279
2281
  });
2280
2282
  var SearchInput_default = SearchInput;
2281
- function DropdownPill({ value, hasSiblings = false }) {
2282
- return /* @__PURE__ */ jsxRuntime.jsx(
2283
- "div",
2284
- {
2285
- 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`,
2286
- children: value
2287
- }
2288
- );
2283
+ function Tag({ children, onRemove, removeLabel, disabled }) {
2284
+ return /* @__PURE__ */ jsxRuntime.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: [
2285
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }),
2286
+ onRemove && /* @__PURE__ */ jsxRuntime.jsx(
2287
+ "button",
2288
+ {
2289
+ type: "button",
2290
+ disabled,
2291
+ onClick: (e) => {
2292
+ e.stopPropagation();
2293
+ onRemove();
2294
+ },
2295
+ "aria-label": removeLabel ?? "Remove",
2296
+ 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",
2297
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
2298
+ }
2299
+ )
2300
+ ] });
2289
2301
  }
2290
2302
  function Dropdown({
2291
2303
  isMultiselect = false,
@@ -2302,7 +2314,6 @@ function Dropdown({
2302
2314
  items = [],
2303
2315
  labelStyle = {},
2304
2316
  placeholder,
2305
- showSelectedCount = false,
2306
2317
  size = "md"
2307
2318
  }) {
2308
2319
  const [open, setOpen] = React8.useState(false);
@@ -2330,6 +2341,17 @@ function Dropdown({
2330
2341
  setOpen(false);
2331
2342
  }
2332
2343
  };
2344
+ const removeSelected = (key) => {
2345
+ if (isMultiselect) {
2346
+ const next = selectedItems.filter((it) => it !== key);
2347
+ setSelectedItems(next);
2348
+ onChange?.({ target: { value: next, id: htmlFor, name } });
2349
+ } else {
2350
+ setSelectedItems([]);
2351
+ onChange?.({ target: { value: "", id: htmlFor, name } });
2352
+ }
2353
+ };
2354
+ const labelFor = (key) => innerItems.find((it) => it.key === key)?.label ?? String(key);
2333
2355
  const onSearchChange = (e) => {
2334
2356
  const term = e.target.value;
2335
2357
  setSearchTerm(term);
@@ -2340,16 +2362,16 @@ function Dropdown({
2340
2362
  );
2341
2363
  };
2342
2364
  const isSelected = (key) => Array.isArray(value) ? value.includes(key) : value === key;
2343
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [
2365
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2344
2366
  /* @__PURE__ */ jsxRuntime.jsxs(
2345
2367
  "div",
2346
2368
  {
2347
- className: `flex ${layout === "vertical" ? "flex-col" : "flex-row items-center gap-2"}`,
2369
+ className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
2348
2370
  children: [
2349
2371
  label && /* @__PURE__ */ jsxRuntime.jsx(
2350
2372
  "label",
2351
2373
  {
2352
- className: "text-sm font-medium ml-1 max-content select-none text-foreground",
2374
+ className: `text-sm font-medium select-none text-foreground ${layout === "horizontal" ? "mt-2 flex-shrink-0 whitespace-nowrap" : ""}`,
2353
2375
  htmlFor,
2354
2376
  style: labelStyle,
2355
2377
  children: label
@@ -2366,7 +2388,7 @@ function Dropdown({
2366
2388
  "aria-invalid": hasError || void 0,
2367
2389
  "aria-describedby": hasError ? errorId : void 0,
2368
2390
  style,
2369
- className: `flex items-center justify-between cursor-pointer select-none ${fieldShell({ size, hasError, disabled })}`,
2391
+ 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 })}`,
2370
2392
  tabIndex: disabled ? -1 : 0,
2371
2393
  onKeyDown: (e) => {
2372
2394
  if (disabled) return;
@@ -2379,18 +2401,25 @@ function Dropdown({
2379
2401
  /* @__PURE__ */ jsxRuntime.jsx(
2380
2402
  "div",
2381
2403
  {
2382
- className: `${!style?.width ? "min-w-[200px]" : ""} flex items-center gap-1 overflow-hidden`,
2383
- children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2384
- value.slice(0, 1).map((val) => /* @__PURE__ */ jsxRuntime.jsx(
2385
- DropdownPill,
2386
- {
2387
- hasSiblings: value.length > 1,
2388
- value: innerItems.find((it) => it.key === val)?.label
2389
- },
2390
- String(val)
2391
- )),
2392
- showSelectedCount && value.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(DropdownPill, { value: `+${value.length - 1} more` })
2393
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(DropdownPill, { value: innerItems.find((it) => it.key === value)?.label })
2404
+ className: `${!style?.width ? "min-w-[200px]" : ""} flex flex-wrap items-center gap-1.5`,
2405
+ children: !value || Array.isArray(value) && value.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-muted text-sm", children: placeholder }) : Array.isArray(value) ? value.map((val) => /* @__PURE__ */ jsxRuntime.jsx(
2406
+ Tag,
2407
+ {
2408
+ disabled,
2409
+ removeLabel: `Remove ${labelFor(val)}`,
2410
+ onRemove: () => removeSelected(val),
2411
+ children: labelFor(val)
2412
+ },
2413
+ String(val)
2414
+ )) : /* @__PURE__ */ jsxRuntime.jsx(
2415
+ Tag,
2416
+ {
2417
+ disabled,
2418
+ removeLabel: `Remove ${labelFor(value)}`,
2419
+ onRemove: () => removeSelected(value),
2420
+ children: labelFor(value)
2421
+ }
2422
+ )
2394
2423
  }
2395
2424
  ),
2396
2425
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, className: "h-4 w-4", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" }) }) })
@@ -3584,74 +3613,54 @@ function Checkbox({
3584
3613
  name,
3585
3614
  htmlFor,
3586
3615
  errorMessage,
3587
- disabled = false
3616
+ disabled = false,
3617
+ layout = "horizontal",
3618
+ labelPosition = "right"
3588
3619
  }) {
3589
3620
  const isChecked = checked ?? value ?? false;
3621
+ const labelFirst = labelPosition === "left";
3622
+ const box = /* @__PURE__ */ jsxRuntime.jsx(
3623
+ CheckboxPrimitive__namespace.Root,
3624
+ {
3625
+ id: htmlFor,
3626
+ name,
3627
+ checked: isChecked,
3628
+ disabled,
3629
+ onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
3630
+ className: [
3631
+ "relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
3632
+ "rounded-sm border transition-colors duration-150",
3633
+ "border-border-strong bg-surface",
3634
+ "data-[state=checked]:bg-accent data-[state=checked]:border-accent",
3635
+ // Focus halo matches the field tokens for a consistent look.
3636
+ "focus:outline-none focus-visible:ring-[3px] focus-visible:ring-focus-ring",
3637
+ "disabled:cursor-not-allowed"
3638
+ ].join(" "),
3639
+ "aria-label": typeof label === "string" ? label : void 0,
3640
+ children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxPrimitive__namespace.Indicator, { className: "flex items-center justify-center data-[state=checked]:animate-check-pop", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "11", height: "9", viewBox: "0 0 11 9", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 4.5L4 7.5L10 1", stroke: "white", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) })
3641
+ }
3642
+ );
3643
+ const labelEl = label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label });
3590
3644
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
3591
- /* @__PURE__ */ jsxRuntime.jsxs(
3645
+ /* @__PURE__ */ jsxRuntime.jsx(
3592
3646
  "label",
3593
3647
  {
3594
3648
  htmlFor,
3595
3649
  className: [
3596
- "inline-flex items-center gap-2.5",
3650
+ "inline-flex",
3651
+ layout === "vertical" ? "flex-col items-start gap-1.5" : "flex-row items-center gap-2.5",
3597
3652
  disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
3598
3653
  ].join(" "),
3599
- children: [
3600
- /* @__PURE__ */ jsxRuntime.jsx(
3601
- CheckboxPrimitive__namespace.Root,
3602
- {
3603
- id: htmlFor,
3604
- name,
3605
- checked: isChecked,
3606
- disabled,
3607
- onCheckedChange: (c) => onChange?.({ target: { checked: !!c, id: htmlFor, name } }),
3608
- className: [
3609
- // Box
3610
- "relative flex h-[18px] w-[18px] flex-shrink-0 items-center justify-center",
3611
- "rounded-sm border transition-colors duration-150",
3612
- // Unchecked
3613
- "border-border-strong bg-surface",
3614
- // Checked
3615
- "data-[state=checked]:bg-accent data-[state=checked]:border-accent",
3616
- // Focus
3617
- "focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1",
3618
- // Disabled
3619
- "disabled:cursor-not-allowed"
3620
- ].join(" "),
3621
- "aria-label": typeof label === "string" ? label : void 0,
3622
- children: /* @__PURE__ */ jsxRuntime.jsx(
3623
- CheckboxPrimitive__namespace.Indicator,
3624
- {
3625
- className: "flex items-center justify-center data-[state=checked]:animate-check-pop",
3626
- children: /* @__PURE__ */ jsxRuntime.jsx(
3627
- "svg",
3628
- {
3629
- width: "11",
3630
- height: "9",
3631
- viewBox: "0 0 11 9",
3632
- fill: "none",
3633
- "aria-hidden": "true",
3634
- children: /* @__PURE__ */ jsxRuntime.jsx(
3635
- "path",
3636
- {
3637
- d: "M1 4.5L4 7.5L10 1",
3638
- stroke: "white",
3639
- strokeWidth: "1.8",
3640
- strokeLinecap: "round",
3641
- strokeLinejoin: "round"
3642
- }
3643
- )
3644
- }
3645
- )
3646
- }
3647
- )
3648
- }
3649
- ),
3650
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground-secondary select-none leading-snug", children: label })
3651
- ]
3654
+ children: labelFirst ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3655
+ labelEl,
3656
+ box
3657
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3658
+ box,
3659
+ labelEl
3660
+ ] })
3652
3661
  }
3653
3662
  ),
3654
- errorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-status-error pl-[26px]", children: errorMessage })
3663
+ errorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-status-error mt-0.5", children: errorMessage })
3655
3664
  ] });
3656
3665
  }
3657
3666
  var DOT_SIZE = {
@@ -3757,12 +3766,12 @@ function Switch({
3757
3766
  id,
3758
3767
  checked,
3759
3768
  onCheckedChange: (c) => onChange?.({ target: { checked: c } }),
3760
- 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",
3769
+ 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",
3761
3770
  children: /* @__PURE__ */ jsxRuntime.jsx(
3762
3771
  SwitchPrimitive__namespace.Thumb,
3763
3772
  {
3764
- 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]",
3765
- children: checkedIcon && uncheckedIcon ? checked ? checkedIcon : uncheckedIcon : null
3773
+ 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]",
3774
+ children: checkedIcon && uncheckedIcon ? checked ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: checkedIcon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center justify-center w-3 h-3", children: uncheckedIcon }) : null
3766
3775
  }
3767
3776
  )
3768
3777
  }
@@ -3783,8 +3792,13 @@ function AutoComplete({
3783
3792
  emptyText = "No results found",
3784
3793
  loadingText = "Searching\u2026",
3785
3794
  size = "md",
3786
- icon
3795
+ icon,
3796
+ errorMessage,
3797
+ required,
3798
+ htmlFor
3787
3799
  }) {
3800
+ const errorId = React8.useId();
3801
+ const hasError = errorMessage != null;
3788
3802
  const [term, setTerm] = React8.useState("");
3789
3803
  const [open, setOpen] = React8.useState(false);
3790
3804
  const [asyncItems, setAsyncItems] = React8.useState([]);
@@ -3831,78 +3845,82 @@ function AutoComplete({
3831
3845
  onItemClick?.(item.value);
3832
3846
  setOpen(false);
3833
3847
  };
3834
- return /* @__PURE__ */ jsxRuntime.jsxs(
3835
- "div",
3848
+ return /* @__PURE__ */ jsxRuntime.jsx(
3849
+ Field,
3836
3850
  {
3837
- className: `flex ${layout === "vertical" ? "flex-col gap-1.5" : "flex-row items-start gap-3"}`,
3838
- style,
3839
- children: [
3840
- label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: `text-sm font-medium text-foreground select-none ${layout === "horizontal" ? "mt-2 flex-shrink-0" : ""}`, children: label }),
3841
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
3842
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${fieldShell({ size, disabled, focusWithin: true })}`, children: [
3843
- /* @__PURE__ */ jsxRuntime.jsx(
3844
- "input",
3845
- {
3846
- disabled,
3847
- value: term,
3848
- onChange: (e) => {
3849
- setTerm(e.target.value);
3850
- setOpen(true);
3851
- },
3852
- onFocus: () => setOpen(true),
3853
- type: "text",
3854
- name,
3855
- className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
3856
- style: inputStyle,
3857
- placeholder: placeholder ?? "",
3858
- autoComplete: "off",
3859
- "aria-haspopup": "listbox",
3860
- "aria-expanded": open,
3861
- "aria-autocomplete": "list",
3862
- "aria-busy": loading || void 0
3863
- }
3864
- ),
3865
- loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 w-4 h-4 flex-shrink-0 flex items-center justify-center text-accent", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs", spinnerColor: "currentColor" }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.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" }) }) })
3866
- ] }) }),
3867
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3868
- Popover__namespace.Content,
3851
+ label,
3852
+ htmlFor,
3853
+ errorId,
3854
+ errorMessage,
3855
+ layout,
3856
+ required,
3857
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open: open && !disabled, onOpenChange: (o) => !disabled && setOpen(o), children: [
3858
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${fieldShell({ size, hasError, disabled, focusWithin: true })}`, style, children: [
3859
+ /* @__PURE__ */ jsxRuntime.jsx(
3860
+ "input",
3869
3861
  {
3870
- align: "start",
3871
- sideOffset: 4,
3872
- onOpenAutoFocus: (e) => e.preventDefault(),
3873
- 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",
3874
- children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full w-full flex items-center justify-center gap-2 py-4 text-sm text-foreground-secondary", children: [
3875
- /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs" }),
3876
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingText })
3877
- ] }) : foundItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full flex flex-col items-center justify-center py-4 text-sm text-foreground-secondary", children: emptyText }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", children: foundItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
3878
- "div",
3879
- {
3880
- role: "option",
3881
- tabIndex: 0,
3882
- 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",
3883
- onClick: () => handleSelect(item),
3884
- onKeyDown: (e) => {
3885
- if (e.key === "Enter" || e.key === " ") {
3886
- e.preventDefault();
3887
- handleSelect(item);
3888
- }
3889
- },
3890
- children: [
3891
- item.icon,
3892
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3893
- item.label,
3894
- " (",
3895
- item.value,
3896
- ")"
3897
- ] })
3898
- ]
3899
- },
3900
- item.key
3901
- )) })
3862
+ id: htmlFor,
3863
+ disabled,
3864
+ value: term,
3865
+ onChange: (e) => {
3866
+ setTerm(e.target.value);
3867
+ setOpen(true);
3868
+ },
3869
+ onFocus: () => setOpen(true),
3870
+ type: "text",
3871
+ name,
3872
+ className: "min-w-0 flex-1 bg-transparent outline-none disabled:cursor-not-allowed placeholder:text-foreground-muted",
3873
+ style: inputStyle,
3874
+ placeholder: placeholder ?? "",
3875
+ autoComplete: "off",
3876
+ "aria-haspopup": "listbox",
3877
+ "aria-expanded": open,
3878
+ "aria-autocomplete": "list",
3879
+ "aria-busy": loading || void 0,
3880
+ "aria-invalid": hasError || void 0,
3881
+ "aria-describedby": hasError ? errorId : void 0
3902
3882
  }
3903
- ) })
3904
- ] }) })
3905
- ]
3883
+ ),
3884
+ loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 w-4 h-4 flex-shrink-0 flex items-center justify-center text-accent", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs", spinnerColor: "currentColor" }) }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 flex-shrink-0 text-foreground-muted", children: icon ?? /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.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" }) }) })
3885
+ ] }) }),
3886
+ /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
3887
+ Popover__namespace.Content,
3888
+ {
3889
+ align: "start",
3890
+ sideOffset: 4,
3891
+ onOpenAutoFocus: (e) => e.preventDefault(),
3892
+ 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",
3893
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full w-full flex items-center justify-center gap-2 py-4 text-sm text-foreground-secondary", children: [
3894
+ /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { inline: true, size: "xs" }),
3895
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: loadingText })
3896
+ ] }) : foundItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full flex flex-col items-center justify-center py-4 text-sm text-foreground-secondary", children: emptyText }) : /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", children: foundItems.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
3897
+ "div",
3898
+ {
3899
+ role: "option",
3900
+ tabIndex: 0,
3901
+ 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",
3902
+ onClick: () => handleSelect(item),
3903
+ onKeyDown: (e) => {
3904
+ if (e.key === "Enter" || e.key === " ") {
3905
+ e.preventDefault();
3906
+ handleSelect(item);
3907
+ }
3908
+ },
3909
+ children: [
3910
+ item.icon,
3911
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
3912
+ item.label,
3913
+ " (",
3914
+ item.value,
3915
+ ")"
3916
+ ] })
3917
+ ]
3918
+ },
3919
+ item.key
3920
+ )) })
3921
+ }
3922
+ ) })
3923
+ ] })
3906
3924
  }
3907
3925
  );
3908
3926
  }
@@ -4982,27 +5000,13 @@ function TagsInput({
4982
5000
  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`,
4983
5001
  onClick: () => inputRef.current?.focus(),
4984
5002
  children: [
4985
- tags.map((tag, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
4986
- "span",
5003
+ tags.map((tag, idx) => /* @__PURE__ */ jsxRuntime.jsx(
5004
+ Tag,
4987
5005
  {
4988
- 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",
4989
- children: [
4990
- tag,
4991
- /* @__PURE__ */ jsxRuntime.jsx(
4992
- "button",
4993
- {
4994
- type: "button",
4995
- disabled,
4996
- onClick: (e) => {
4997
- e.stopPropagation();
4998
- removeTag(idx);
4999
- },
5000
- "aria-label": `Remove ${tag}`,
5001
- 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",
5002
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "10", height: "10", viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 5L5 15M5 5l10 10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
5003
- }
5004
- )
5005
- ]
5006
+ disabled,
5007
+ removeLabel: `Remove ${tag}`,
5008
+ onRemove: () => removeTag(idx),
5009
+ children: tag
5006
5010
  },
5007
5011
  `${tag}-${idx}`
5008
5012
  )),
@@ -5236,9 +5240,9 @@ function Rating({
5236
5240
  /* @__PURE__ */ jsxRuntime.jsx(
5237
5241
  "span",
5238
5242
  {
5239
- className: "absolute inset-0 overflow-hidden",
5243
+ className: "absolute inset-y-0 left-0 overflow-hidden",
5240
5244
  style: { width: `${fillFraction * 100}%` },
5241
- children: icon(true)
5245
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `block absolute inset-y-0 left-0 ${ICON_SIZE[size]} max-w-none`, children: icon(true) })
5242
5246
  }
5243
5247
  )
5244
5248
  ]