@oods/components-react 0.4.0 → 0.4.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
@@ -1,10 +1,10 @@
1
- import { Badge, Select, Input, Checkbox, Text } from './chunk-OFTMKX3W.js';
2
- export { AuditTimeline, Badge, Banner, Button, CancellationSummary, Card, Checkbox, DatePicker, Dialog, Input, PaginationBar, PriceBadge, RelativeTimestamp, SearchInput, Select, StatusBadge, StatusTimeline, Switch, Text, Textarea } from './chunk-OFTMKX3W.js';
1
+ import { Badge, StatusIcon, Select, Input, Checkbox, Text } from './chunk-ICXOX5B3.js';
2
+ export { AuditTimeline, Badge, Banner, Button, CancellationSummary, Card, Checkbox, DatePicker, Dialog, Input, PaginationBar, PriceBadge, RelativeTimestamp, SearchInput, Select, StatusBadge, StatusTimeline, Switch, Text, Textarea } from './chunk-ICXOX5B3.js';
3
3
  export { Table } from './chunk-XEX22E24.js';
4
4
  import './chunk-2VEQWKGK.js';
5
- import * as React3 from 'react';
5
+ import * as React4 from 'react';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { vizPreviewLayers, svgCarriesTitle, formatPriceAmount, formatPriceCode, formatReferenceLabel, summaryValue, formatDateTime, formatReadOnlyValue, billingSummary, formatBillingAmount, billingAmountText, BILLING_MINOR_UNITS, billingAmountMessage, parseBillingAmount, billingIntervalMessage, BILLING_INTERVALS, billingCycle, auditSummary, initialSort, ariaSort, nextSort, traitEventRows, recipeItemLabels, DEFAULT_COLOR_STATES, geoFieldMapping, vizSummaryRows, vizControlFields, VIZ_CONTROL_TITLES, vizFieldValue, billingPaymentSummary, billingPaymentRows, editVizIntent } from '@oods/component-contracts';
7
+ import { vizPreviewLayers, svgCarriesTitle, formatPriceAmount, formatPriceCode, formatReferenceLabel, ownershipPhrase, summaryValue, formatDateTime, formatReadOnlyValue, billingSummary, formatBillingAmount, billingAmountText, BILLING_MINOR_UNITS, billingAmountMessage, parseBillingAmount, billingIntervalMessage, BILLING_INTERVALS, billingCycle, auditSummary, initialSort, ariaSort, nextSort, traitEventRows, recipeItemLabels, DEFAULT_COLOR_STATES, geoFieldMapping, vizSummaryRows, vizControlFields, VIZ_CONTROL_TITLES, vizFieldValue, billingPaymentSummary, billingPaymentRows, editVizIntent } from '@oods/component-contracts';
8
8
 
9
9
  var classes = (...values) => values.filter(Boolean).join(" ");
10
10
  var GAP_VALUES = {
@@ -19,7 +19,7 @@ var maxColumns = (columns) => {
19
19
  const count = Number(columns);
20
20
  return Number.isFinite(count) && count > 0 ? count : void 0;
21
21
  };
22
- var Grid = React3.forwardRef(
22
+ var Grid = React4.forwardRef(
23
23
  ({
24
24
  columns = "auto-fit",
25
25
  minColumnWidth = "16rem",
@@ -49,7 +49,7 @@ var Grid = React3.forwardRef(
49
49
  )
50
50
  );
51
51
  Grid.displayName = "OODS.Grid";
52
- var Stack = React3.forwardRef(
52
+ var Stack = React4.forwardRef(
53
53
  ({
54
54
  direction = "column",
55
55
  gap = "md",
@@ -95,7 +95,7 @@ var partitionForOverflow = (items, visibleCount, selectedId) => {
95
95
  overflowItems: items.filter((item) => !visibleIds.has(item.id))
96
96
  };
97
97
  };
98
- var Tabs = React3.forwardRef(
98
+ var Tabs = React4.forwardRef(
99
99
  ({
100
100
  items,
101
101
  selectedId,
@@ -109,22 +109,22 @@ var Tabs = React3.forwardRef(
109
109
  "aria-label": ariaLabelAttribute,
110
110
  ...rest
111
111
  }, ref) => {
112
- const instanceId = React3.useId().replaceAll(":", "");
112
+ const instanceId = React4.useId().replaceAll(":", "");
113
113
  const controlled = selectedId !== void 0;
114
114
  const firstEnabled = items.find((item) => !item.disabled && !item.isDisabled)?.id ?? "";
115
- const [internalSelectedId, setInternalSelectedId] = React3.useState(
115
+ const [internalSelectedId, setInternalSelectedId] = React4.useState(
116
116
  defaultSelectedId ?? firstEnabled
117
117
  );
118
118
  const activeId = controlled ? selectedId : internalSelectedId;
119
- const [focusedId, setFocusedId] = React3.useState(activeId);
120
- const [visibleCount, setVisibleCount] = React3.useState(items.length);
121
- const [menuOpen, setMenuOpen] = React3.useState(false);
122
- const listRef = React3.useRef(null);
123
- const tabRefs = React3.useRef(/* @__PURE__ */ new Map());
124
- const itemWidths = React3.useRef(/* @__PURE__ */ new Map());
125
- const focusRequestedByUser = React3.useRef(false);
126
- React3.useEffect(() => setFocusedId(activeId), [activeId]);
127
- const select = React3.useCallback(
119
+ const [focusedId, setFocusedId] = React4.useState(activeId);
120
+ const [visibleCount, setVisibleCount] = React4.useState(items.length);
121
+ const [menuOpen, setMenuOpen] = React4.useState(false);
122
+ const listRef = React4.useRef(null);
123
+ const tabRefs = React4.useRef(/* @__PURE__ */ new Map());
124
+ const itemWidths = React4.useRef(/* @__PURE__ */ new Map());
125
+ const focusRequestedByUser = React4.useRef(false);
126
+ React4.useEffect(() => setFocusedId(activeId), [activeId]);
127
+ const select = React4.useCallback(
128
128
  (id) => {
129
129
  const item = items.find((candidate) => candidate.id === id);
130
130
  if (!item || item.disabled || item.isDisabled) return;
@@ -136,7 +136,7 @@ var Tabs = React3.forwardRef(
136
136
  },
137
137
  [controlled, items, onChange, onUpdate]
138
138
  );
139
- const measure = React3.useCallback(() => {
139
+ const measure = React4.useCallback(() => {
140
140
  const list = listRef.current;
141
141
  if (!list || items.length < 2) return;
142
142
  const available = list.offsetWidth;
@@ -160,7 +160,7 @@ var Tabs = React3.forwardRef(
160
160
  }
161
161
  setVisibleCount(Math.max(1, count));
162
162
  }, [items.length]);
163
- React3.useLayoutEffect(() => {
163
+ React4.useLayoutEffect(() => {
164
164
  measure();
165
165
  const list = listRef.current;
166
166
  if (!list || typeof ResizeObserver === "undefined") return void 0;
@@ -188,7 +188,7 @@ var Tabs = React3.forwardRef(
188
188
  if (!nextId) return;
189
189
  select(nextId);
190
190
  };
191
- React3.useEffect(() => {
191
+ React4.useEffect(() => {
192
192
  if (focusRequestedByUser.current && visibleItems.some((item) => item.id === focusedId)) {
193
193
  focusRequestedByUser.current = false;
194
194
  tabRefs.current.get(focusedId)?.focus();
@@ -251,40 +251,44 @@ var Tabs = React3.forwardRef(
251
251
  "aria-label": ariaLabel ?? ariaLabelAttribute,
252
252
  children: [
253
253
  visibleItems.map(renderTab),
254
- overflowItems.length ? /* @__PURE__ */ jsxs("div", { className: "oods-tabs__overflow", children: [
255
- /* @__PURE__ */ jsx(
256
- "button",
257
- {
258
- type: "button",
259
- className: "tabs__overflow-trigger",
260
- "aria-label": `${overflowLabel} tabs`,
261
- "aria-haspopup": "menu",
262
- "aria-expanded": menuOpen,
263
- "data-tabs-overflow-trigger": "true",
264
- onClick: () => setMenuOpen((open) => !open),
265
- children: overflowLabel
266
- }
267
- ),
268
- menuOpen ? /* @__PURE__ */ jsx("div", { className: "tabs__overflow-menu", role: "menu", children: overflowItems.map((item) => /* @__PURE__ */ jsx(
269
- "button",
270
- {
271
- type: "button",
272
- role: "menuitem",
273
- disabled: item.disabled || item.isDisabled,
274
- "aria-current": item.id === activeId ? "true" : void 0,
275
- className: classes2(
276
- "tabs__overflow-item",
277
- item.id === activeId && "tabs__overflow-item--selected"
278
- ),
279
- onClick: () => {
280
- select(item.id);
281
- setMenuOpen(false);
254
+ overflowItems.length ? (
255
+ // s224-m01 (#2542 ruling 2): the overflow markup is Vue's too: both class families, the trigger's data
256
+ // attribute and aria-current="true" on an item.
257
+ /* @__PURE__ */ jsxs("div", { className: "oods-tabs__overflow oods-tabs-overflow", children: [
258
+ /* @__PURE__ */ jsx(
259
+ "button",
260
+ {
261
+ type: "button",
262
+ className: "tabs__overflow-trigger oods-tabs-overflow-trigger",
263
+ "aria-label": `${overflowLabel} tabs`,
264
+ "aria-haspopup": "menu",
265
+ "aria-expanded": menuOpen,
266
+ "data-tabs-overflow-trigger": "true",
267
+ onClick: () => setMenuOpen((open) => !open),
268
+ children: overflowLabel
269
+ }
270
+ ),
271
+ menuOpen ? /* @__PURE__ */ jsx("div", { className: "tabs__overflow-menu oods-tabs-overflow-menu", role: "menu", children: overflowItems.map((item) => /* @__PURE__ */ jsx(
272
+ "button",
273
+ {
274
+ type: "button",
275
+ role: "menuitem",
276
+ disabled: item.disabled || item.isDisabled,
277
+ "aria-current": item.id === activeId ? "true" : void 0,
278
+ className: classes2(
279
+ "tabs__overflow-item",
280
+ item.id === activeId && "tabs__overflow-item--selected"
281
+ ),
282
+ onClick: () => {
283
+ select(item.id);
284
+ setMenuOpen(false);
285
+ },
286
+ children: item.label
282
287
  },
283
- children: item.label
284
- },
285
- item.id
286
- )) }) : null
287
- ] }) : null
288
+ item.id
289
+ )) }) : null
290
+ ] })
291
+ ) : null
288
292
  ]
289
293
  }
290
294
  ),
@@ -310,11 +314,75 @@ var Tabs = React3.forwardRef(
310
314
  }
311
315
  );
312
316
  Tabs.displayName = "OODS.Tabs";
317
+ var SegmentedControl = React4.forwardRef(
318
+ ({
319
+ id,
320
+ label,
321
+ options,
322
+ value,
323
+ defaultValue,
324
+ name,
325
+ size = "md",
326
+ disabled,
327
+ className,
328
+ style,
329
+ onChange,
330
+ onValueChange,
331
+ onUpdate,
332
+ ...rest
333
+ }, ref) => {
334
+ const handleChange = (event) => {
335
+ onChange?.(event);
336
+ if (event.defaultPrevented) return;
337
+ onValueChange?.(event.currentTarget.value);
338
+ onUpdate?.(event.currentTarget.value);
339
+ };
340
+ return /* @__PURE__ */ jsxs(
341
+ "div",
342
+ {
343
+ className: className ? `oods-field oods-segmented-control ${className}` : "oods-field oods-segmented-control",
344
+ style,
345
+ "data-oods-component": "SegmentedControl",
346
+ "data-size": size,
347
+ children: [
348
+ /* @__PURE__ */ jsx("span", { id: `${id}-label`, className: "oods-field-label", children: label }),
349
+ /* @__PURE__ */ jsx(
350
+ "div",
351
+ {
352
+ ref,
353
+ id,
354
+ role: "radiogroup",
355
+ "aria-labelledby": `${id}-label`,
356
+ className: "oods-segmented-control__track",
357
+ ...rest,
358
+ children: options.map((option) => /* @__PURE__ */ jsxs("label", { className: "oods-segmented-control__option", children: [
359
+ /* @__PURE__ */ jsx(
360
+ "input",
361
+ {
362
+ type: "radio",
363
+ className: "oods-segmented-control__input",
364
+ name: name || id,
365
+ value: option.value,
366
+ ...value === void 0 ? { defaultChecked: option.value === defaultValue } : { checked: option.value === value },
367
+ disabled: disabled || option.disabled,
368
+ onChange: handleChange
369
+ }
370
+ ),
371
+ /* @__PURE__ */ jsx("span", { className: "oods-segmented-control__label", children: option.label })
372
+ ] }, option.value))
373
+ }
374
+ )
375
+ ]
376
+ }
377
+ );
378
+ }
379
+ );
380
+ SegmentedControl.displayName = "OODS.SegmentedControl";
313
381
  var classes3 = (...values) => values.filter(Boolean).join(" ");
314
382
  var firstText = (...values) => values.find((value) => typeof value === "string" && value.trim().length > 0);
315
383
  function childContent(children) {
316
- const flatten = (value) => React3.Children.toArray(value).flatMap((node) => {
317
- if (React3.isValidElement(node) && node.type === React3.Fragment) {
384
+ const flatten = (value) => React4.Children.toArray(value).flatMap((node) => {
385
+ if (React4.isValidElement(node) && node.type === React4.Fragment) {
318
386
  return flatten(node.props.children);
319
387
  }
320
388
  return [node];
@@ -335,7 +403,7 @@ function notEcho(supporting, heading) {
335
403
  if (!supporting || !heading) return supporting;
336
404
  return supporting.trim() === heading.trim() ? void 0 : supporting;
337
405
  }
338
- var DetailHeader = React3.forwardRef(
406
+ var DetailHeader = React4.forwardRef(
339
407
  ({ title, label, text, subtitle, sublabel, description, metadata, meta, level, as, children, className, ...rest }, ref) => {
340
408
  const Heading = headingElement(as, level, 2);
341
409
  const content = childContent(children);
@@ -350,7 +418,7 @@ var DetailHeader = React3.forwardRef(
350
418
  }
351
419
  );
352
420
  DetailHeader.displayName = "OODS.DetailHeader";
353
- var CardHeader = React3.forwardRef(
421
+ var CardHeader = React4.forwardRef(
354
422
  ({ title, label, text, supporting, supportingText, subtitle, description, level, as, children, className, ...rest }, ref) => {
355
423
  const Heading = headingElement(as, level, 2);
356
424
  const content = childContent(children);
@@ -363,7 +431,7 @@ var CardHeader = React3.forwardRef(
363
431
  }
364
432
  );
365
433
  CardHeader.displayName = "OODS.CardHeader";
366
- var ColorSwatch = React3.forwardRef(
434
+ var ColorSwatch = React4.forwardRef(
367
435
  ({ color, value, state, label, children, className, style, ...rest }, ref) => {
368
436
  const resolvedColor = firstText(color, value, state);
369
437
  const content = childContent(children);
@@ -388,7 +456,7 @@ var ColorSwatch = React3.forwardRef(
388
456
  }
389
457
  );
390
458
  ColorSwatch.displayName = "OODS.ColorSwatch";
391
- var ColorizedBadge = React3.forwardRef(
459
+ var ColorizedBadge = React4.forwardRef(
392
460
  ({ label, text, state, value, status, color, hue, swatch, variant, tone, emphasis, children, className, style, ...rest }, ref) => {
393
461
  const content = childContent(children);
394
462
  const resolvedLabel = content.scalar ?? firstText(label, text, state, value) ?? "Color";
@@ -418,7 +486,7 @@ var ColorizedBadge = React3.forwardRef(
418
486
  }
419
487
  );
420
488
  ColorizedBadge.displayName = "OODS.ColorizedBadge";
421
- var VizAreaPreview = React3.forwardRef(
489
+ var VizAreaPreview = React4.forwardRef(
422
490
  ({ width = 640, height = 360, svg, svgNarrow, svgWide, svgDark, svgDarkNarrow, svgDarkWide, svgHc, svgHcNarrow, svgHcWide, title, description, children, className, style, ...rest }, ref) => {
423
491
  const content = childContent(children);
424
492
  if (svg !== void 0) {
@@ -487,7 +555,7 @@ var descriptorLabel = (descriptor) => firstText(
487
555
  typeof descriptor.field === "string" ? descriptor.field : void 0
488
556
  ) ?? "Filter";
489
557
  function createPanelSection(component, className, panelType, defaultTitle) {
490
- const Panel = React3.forwardRef(
558
+ const Panel = React4.forwardRef(
491
559
  ({ title, label, heading, name, subtitle, description, metadata, summary: summary2, text, body, emptyMessage, children, className: consumerClassName, ...rest }, ref) => {
492
560
  const content = childContent(children);
493
561
  const authored = content.authored || content.scalar !== void 0;
@@ -520,7 +588,7 @@ var ClassificationPanel = createPanelSection("ClassificationPanel", "oods-classi
520
588
  var AddressCollectionPanel = createPanelSection("AddressCollectionPanel", "oods-address-collection-panel", "address", "Addresses");
521
589
  var MembershipPanel = createPanelSection("MembershipPanel", "oods-membership-panel", "membership", "Membership");
522
590
  var PreferencePanel = createPanelSection("PreferencePanel", "oods-preference-panel", "preference", "Preferences");
523
- var FilterPanel = React3.forwardRef(
591
+ var FilterPanel = React4.forwardRef(
524
592
  ({ filters, activeFilters, mode, collapsible = true, children, className, ...rest }, ref) => {
525
593
  const content = childContent(children);
526
594
  const authored = content.authored || content.scalar !== void 0;
@@ -554,7 +622,7 @@ var FilterPanel = React3.forwardRef(
554
622
  }
555
623
  );
556
624
  FilterPanel.displayName = "OODS.FilterPanel";
557
- var PriceSummary = React3.forwardRef(
625
+ var PriceSummary = React4.forwardRef(
558
626
  ({
559
627
  title,
560
628
  label,
@@ -627,7 +695,7 @@ var normalizeTagItems = (value) => {
627
695
  }
628
696
  return items.filter((item) => item.length > 0);
629
697
  };
630
- var TagManager = React3.forwardRef(
698
+ var TagManager = React4.forwardRef(
631
699
  ({ title, label, heading, name, description, subtitle, hint, tags, value, children, className, onSubmit, ...rest }, ref) => {
632
700
  const content = childContent(children);
633
701
  const authored = content.authored || content.scalar !== void 0;
@@ -673,10 +741,12 @@ var asCount = (value) => {
673
741
  return void 0;
674
742
  };
675
743
  function createBadgeFamily(options) {
676
- const consumed = /* @__PURE__ */ new Set([...options.labelKeys, ...options.statusKeys, "variant", "tone", "emphasis"]);
677
- const Family = React3.forwardRef((allProps, ref) => {
744
+ const consumed = /* @__PURE__ */ new Set([...options.labelKeys, ...options.statusKeys, "variant", "tone", "emphasis", ...options.booleanProps ? ["hideWhenFalse"] : []]);
745
+ const Family = React4.forwardRef((allProps, ref) => {
678
746
  const { children, className, ...rest } = allProps;
679
747
  const record = rest;
748
+ const flag = options.booleanProps?.map((key) => record[key]).find((value) => typeof value === "boolean");
749
+ if (record.hideWhenFalse === true && flag === false) return null;
680
750
  const scalar = (key) => {
681
751
  const value = record[key];
682
752
  if (typeof value === "boolean" && options.booleanProps?.includes(key)) return String(value);
@@ -734,7 +804,7 @@ var PreferenceSummaryBadge = createBadgeFamily({
734
804
  labelKeys: ["label", "text", "namespace", "value"],
735
805
  statusKeys: ["status", "state", "version"]
736
806
  });
737
- var RoleBadgeList = React3.forwardRef(
807
+ var RoleBadgeList = React4.forwardRef(
738
808
  ({ roles, badges, roleLabels, value, variant, tone, label, text, children, className, ...rest }, ref) => {
739
809
  const content = childContent(children);
740
810
  const authored = content.authored || content.scalar !== void 0;
@@ -754,7 +824,7 @@ var RoleBadgeList = React3.forwardRef(
754
824
  }
755
825
  );
756
826
  RoleBadgeList.displayName = "OODS.RoleBadgeList";
757
- var TagPills = React3.forwardRef(
827
+ var TagPills = React4.forwardRef(
758
828
  ({ tags, value, maxVisible, overflowLabel, children, className, ...rest }, ref) => {
759
829
  const content = childContent(children);
760
830
  const authored = content.authored || content.scalar !== void 0;
@@ -806,7 +876,7 @@ var normalizeTimelineItems = (raw) => {
806
876
  };
807
877
  function createTimelineFamily(options) {
808
878
  const consumed = /* @__PURE__ */ new Set(["title", "label", "heading", "name", ...options.eventKeys]);
809
- const Family = React3.forwardRef((allProps, ref) => {
879
+ const Family = React4.forwardRef((allProps, ref) => {
810
880
  const { children, className, ...rest } = allProps;
811
881
  const record = rest;
812
882
  const text = (key) => {
@@ -871,7 +941,7 @@ var PreferenceTimeline = createTimelineFamily({
871
941
  timelineType: "preference",
872
942
  eventKeys: ["events", "changes", "history"]
873
943
  });
874
- var AuditEvent = React3.forwardRef(
944
+ var AuditEvent = React4.forwardRef(
875
945
  ({
876
946
  label,
877
947
  title,
@@ -957,7 +1027,7 @@ var addressRecord = (form) => {
957
1027
  };
958
1028
  return { street: read("street"), city: read("city"), region: read("region"), postalCode: read("postalCode") };
959
1029
  };
960
- var AddressEditor = React3.forwardRef(
1030
+ var AddressEditor = React4.forwardRef(
961
1031
  ({
962
1032
  title,
963
1033
  label,
@@ -1015,8 +1085,8 @@ var AddressEditor = React3.forwardRef(
1015
1085
  }
1016
1086
  );
1017
1087
  AddressEditor.displayName = "OODS.AddressEditor";
1018
- var PreferenceEditor = React3.forwardRef(
1019
- ({ title, label, heading, name, description, subtitle, hint, namespaces, namespace, document, json, value, children, className, onSubmit, ...rest }, ref) => {
1088
+ var PreferenceEditor = React4.forwardRef(
1089
+ ({ title, label, heading, name, description, subtitle, hint, namespaces, namespace, document: document2, json, value, children, className, onSubmit, ...rest }, ref) => {
1020
1090
  const content = childContent(children);
1021
1091
  const authored = content.authored || content.scalar !== void 0;
1022
1092
  const resolvedTitle = firstText(title, label, heading, name) ?? "Preference Editor";
@@ -1043,7 +1113,7 @@ var PreferenceEditor = React3.forwardRef(
1043
1113
  ] }),
1044
1114
  /* @__PURE__ */ jsxs("label", { "data-form-control": "textarea", children: [
1045
1115
  /* @__PURE__ */ jsx("span", { children: "Preference Document" }),
1046
- /* @__PURE__ */ jsx("textarea", { name: "preferenceDocument", defaultValue: firstScalar(document, json, value) ?? "" })
1116
+ /* @__PURE__ */ jsx("textarea", { name: "preferenceDocument", defaultValue: firstScalar(document2, json, value) ?? "" })
1047
1117
  ] })
1048
1118
  ] }) })
1049
1119
  ]
@@ -1052,7 +1122,7 @@ var PreferenceEditor = React3.forwardRef(
1052
1122
  }
1053
1123
  );
1054
1124
  PreferenceEditor.displayName = "OODS.PreferenceEditor";
1055
- var RoleAssignmentForm = React3.forwardRef(
1125
+ var RoleAssignmentForm = React4.forwardRef(
1056
1126
  ({ title, label, heading, name, description, subtitle, hint, roles, availableRoles, role, defaultRoleId, assignee, member, children, className, onSubmit, ...rest }, ref) => {
1057
1127
  const content = childContent(children);
1058
1128
  const authored = content.authored || content.scalar !== void 0;
@@ -1089,7 +1159,7 @@ var RoleAssignmentForm = React3.forwardRef(
1089
1159
  }
1090
1160
  );
1091
1161
  RoleAssignmentForm.displayName = "OODS.RoleAssignmentForm";
1092
- var StatusSelector = React3.forwardRef(
1162
+ var StatusSelector = React4.forwardRef(
1093
1163
  ({ label, title, help, options, states, value, status, children, className, onChange, onValueChange, onUpdate, ...rest }, ref) => {
1094
1164
  const content = childContent(children);
1095
1165
  const authored = content.authored || content.scalar !== void 0;
@@ -1131,7 +1201,7 @@ var StatusSelector = React3.forwardRef(
1131
1201
  }
1132
1202
  );
1133
1203
  StatusSelector.displayName = "OODS.StatusSelector";
1134
- var TagInput = React3.forwardRef(
1204
+ var TagInput = React4.forwardRef(
1135
1205
  ({ title, label, heading, name, description, subtitle, hint, tags, value, placeholder, children, className, onChange, onValueChange, onUpdate, ...rest }, ref) => {
1136
1206
  const content = childContent(children);
1137
1207
  const authored = content.authored || content.scalar !== void 0;
@@ -1178,7 +1248,7 @@ var TagInput = React3.forwardRef(
1178
1248
  }
1179
1249
  );
1180
1250
  TagInput.displayName = "OODS.TagInput";
1181
- var TemplatePicker = React3.forwardRef(
1251
+ var TemplatePicker = React4.forwardRef(
1182
1252
  ({ title, label, heading, name, description, subtitle, hint, templates, options, templateId, value, channels, channel, children, className, ...rest }, ref) => {
1183
1253
  const content = childContent(children);
1184
1254
  const authored = content.authored || content.scalar !== void 0;
@@ -1216,14 +1286,14 @@ var truncateLabel = (value, maxLength) => {
1216
1286
  const limit = typeof maxLength === "number" ? maxLength : Number(maxLength);
1217
1287
  return !Number.isFinite(limit) || limit <= 0 || value.length <= limit ? value : `${value.slice(0, Math.max(0, limit - 1)).trimEnd()}...`;
1218
1288
  };
1219
- var InlineLabel = React3.forwardRef(
1289
+ var InlineLabel = React4.forwardRef(
1220
1290
  ({ label, text, value, maxLength, children, className, ...rest }, ref) => {
1221
1291
  const content = childContent(children);
1222
1292
  return /* @__PURE__ */ jsx("span", { ref, className: classes3("oods-inline-label", className), "data-oods-component": "InlineLabel", ...rest, children: content.authored || content.scalar !== void 0 ? children : truncateLabel(firstText(label, text, value) ?? "", maxLength) });
1223
1293
  }
1224
1294
  );
1225
1295
  InlineLabel.displayName = "OODS.InlineLabel";
1226
- var LabelCell = React3.forwardRef(
1296
+ var LabelCell = React4.forwardRef(
1227
1297
  ({ label, text, value, description, subtitle, sublabel, supporting, truncate, maxLength, children, className, ...rest }, ref) => {
1228
1298
  const content = childContent(children);
1229
1299
  const limit = truncate ? maxLength ?? 40 : maxLength;
@@ -1236,7 +1306,7 @@ var LabelCell = React3.forwardRef(
1236
1306
  }
1237
1307
  );
1238
1308
  LabelCell.displayName = "OODS.LabelCell";
1239
- var FormLabelGroup = React3.forwardRef(
1309
+ var FormLabelGroup = React4.forwardRef(
1240
1310
  ({ label, text, title, placeholder, hint, description, htmlFor, for: forId, inputId, children, className, ...rest }, ref) => {
1241
1311
  const detail = firstText(placeholder, hint, description);
1242
1312
  return /* @__PURE__ */ jsxs("label", { ref, className: classes3("oods-form-label-group", className), "data-oods-component": "FormLabelGroup", htmlFor: htmlFor ?? forId ?? inputId, ...rest, children: [
@@ -1255,7 +1325,7 @@ var ClassificationBadge = createBadgeFamily({
1255
1325
  labelKeys: ["label", "text", "category", "value"],
1256
1326
  statusKeys: ["status", "state", "mode"]
1257
1327
  });
1258
- var ClassificationEditor = React3.forwardRef(
1328
+ var ClassificationEditor = React4.forwardRef(
1259
1329
  ({ title, label, heading, name, description, subtitle, hint, category, primaryCategory, tags, modes, mode, classificationMode, children, className, onSubmit, ...rest }, ref) => {
1260
1330
  const content = childContent(children);
1261
1331
  const tagText = typeof tags === "string" ? tags : tags === void 0 ? "" : JSON.stringify(tags);
@@ -1301,7 +1371,7 @@ var OwnerBadge = createBadgeFamily({
1301
1371
  labelKeys: ["label", "text", "owner", "ownerType", "value"],
1302
1372
  statusKeys: ["status", "state"]
1303
1373
  });
1304
- var OwnershipSummary = React3.forwardRef(
1374
+ var OwnershipSummary = React4.forwardRef(
1305
1375
  ({ title, label, heading, name, ownerLabel, ownerId, owner_id, ownerType, owner_type, role, ownershipRole, summary: summary2, text, description, children, className, ...rest }, ref) => {
1306
1376
  const content = childContent(children);
1307
1377
  const terms = [["Owner", ownerId === void 0 && owner_id === void 0 && ownerLabel === void 0 ? void 0 : formatReferenceLabel(ownerId ?? owner_id, ownerLabel, "Owner")], ["Owner Type", firstScalar(ownerType, owner_type)], ["Role", firstScalar(role, ownershipRole)]].filter((entry) => entry[1] !== void 0);
@@ -1316,7 +1386,7 @@ var OwnershipSummary = React3.forwardRef(
1316
1386
  }
1317
1387
  );
1318
1388
  OwnershipSummary.displayName = "OODS.OwnershipSummary";
1319
- var TagSummary = React3.forwardRef(
1389
+ var TagSummary = React4.forwardRef(
1320
1390
  ({ title, label, heading, name, tagCount, count, tags, summary: summary2, text, description, children, className, ...rest }, ref) => {
1321
1391
  const content = childContent(children);
1322
1392
  const tagText = Array.isArray(tags) ? normalizeTagItems(tags).join(", ") || void 0 : firstText(tags);
@@ -1332,11 +1402,12 @@ var TagSummary = React3.forwardRef(
1332
1402
  }
1333
1403
  );
1334
1404
  TagSummary.displayName = "OODS.TagSummary";
1335
- var OwnershipMeta = React3.forwardRef(
1336
- ({ title, label, heading, name, ownerType, owner_type, role, ownershipRole, children, className, ...rest }, ref) => {
1405
+ var OwnershipMeta = React4.forwardRef(
1406
+ ({ title, label, heading, name, ownerType, owner_type, role, ownershipRole, ownerLabel, children, className, ...rest }, ref) => {
1337
1407
  const content = childContent(children);
1338
1408
  const terms = [["Owner Type", firstScalar(ownerType, owner_type)], ["Role", firstScalar(role, ownershipRole)]].filter((entry) => entry[1] !== void 0);
1339
- return /* @__PURE__ */ jsx("div", { ref, className: classes3("oods-ownership-meta", className), "data-oods-component": "OwnershipMeta", "data-meta-type": "ownership", ...rest, children: content.authored || content.scalar !== void 0 ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
1409
+ const phrase = ownerLabel !== void 0 ? ownershipPhrase(ownerLabel, firstScalar(ownerType, owner_type), firstScalar(role, ownershipRole)) : void 0;
1410
+ return /* @__PURE__ */ jsx("div", { ref, className: classes3("oods-ownership-meta", className), "data-oods-component": "OwnershipMeta", "data-meta-type": "ownership", ...rest, children: content.authored || content.scalar !== void 0 ? children : phrase ? /* @__PURE__ */ jsx("span", { "data-meta-item": "true", children: phrase }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1340
1411
  /* @__PURE__ */ jsx("span", { "data-meta-title": "true", children: firstText(title, label, heading, name) ?? "Ownership" }),
1341
1412
  terms.map(([term, value]) => /* @__PURE__ */ jsxs("span", { "data-meta-item": "true", children: [
1342
1413
  /* @__PURE__ */ jsxs("strong", { children: [
@@ -1370,9 +1441,10 @@ var CancellationBadge = createBadgeFamily({
1370
1441
  booleanProps: ["cancelAtPeriodEnd", "isCancelled", "value"],
1371
1442
  booleanLabels: ["Cancellation scheduled", "No cancellation scheduled"]
1372
1443
  });
1373
- var ArchiveSummary = React3.forwardRef(
1374
- ({ title, label, heading, name, isArchived, archived, status, archivedAt, reason, archiveReason, summary: summary2, text, description, children, className, ...rest }, ref) => {
1444
+ var ArchiveSummary = React4.forwardRef(
1445
+ ({ title, label, heading, name, isArchived, archived, status, archivedAt, reason, archiveReason, summary: summary2, text, description, hideWhenDefault, children, className, ...rest }, ref) => {
1375
1446
  const content = childContent(children);
1447
+ if (hideWhenDefault === true && (isArchived ?? archived ?? status) === false && !archivedAt && !firstText(reason, archiveReason) && !content.authored && content.scalar === void 0) return null;
1376
1448
  const terms = [["Archived", summaryValue(isArchived ?? archived ?? status)], ["Archived At", archivedAt ? formatDateTime(archivedAt) : void 0], ["Reason", firstText(reason, archiveReason)]].filter((entry) => entry[1] !== void 0);
1377
1449
  const fallback = firstText(summary2, text, description);
1378
1450
  return /* @__PURE__ */ jsxs("section", { ref, className: classes3("oods-archive-summary", className), "data-oods-component": "ArchiveSummary", "data-summary-type": "archive", ...rest, children: [
@@ -1385,7 +1457,7 @@ var ArchiveSummary = React3.forwardRef(
1385
1457
  }
1386
1458
  );
1387
1459
  ArchiveSummary.displayName = "OODS.ArchiveSummary";
1388
- var PriceCardMeta = React3.forwardRef(
1460
+ var PriceCardMeta = React4.forwardRef(
1389
1461
  ({ title, label, heading, name, model, pricingModel, interval, billingInterval, children, className, ...rest }, ref) => {
1390
1462
  const content = childContent(children);
1391
1463
  const terms = [["Model", formatPriceCode(firstText(model, pricingModel))], ["Interval", formatPriceCode(firstText(interval, billingInterval))]].filter((entry) => entry[1] !== void 0);
@@ -1403,12 +1475,12 @@ var PriceCardMeta = React3.forwardRef(
1403
1475
  }
1404
1476
  );
1405
1477
  PriceCardMeta.displayName = "OODS.PriceCardMeta";
1406
- var CancellationForm = React3.forwardRef(
1478
+ var CancellationForm = React4.forwardRef(
1407
1479
  ({ title, label, heading, name, description, subtitle, hint, allowedReasons, reasonCode, reason, cancellationReason, embedded, reasonHelp, codeHelp, children, className, onSubmit, ...rest }, ref) => {
1408
1480
  const content = childContent(children);
1409
1481
  const choices = normalizeSelectOptions(allowedReasons ?? ["no_longer_needed", "budget", "duplicate"]);
1410
1482
  if (reasonCode && !choices.some((choice) => choice.value === reasonCode)) choices.unshift({ value: reasonCode, label: reasonCode });
1411
- return React3.createElement(embedded ? "fieldset" : "form", {
1483
+ return React4.createElement(embedded ? "fieldset" : "form", {
1412
1484
  ...rest,
1413
1485
  ref,
1414
1486
  className: classes3("oods-cancellation-form", className),
@@ -1440,11 +1512,11 @@ function BillingSummaryBadge({ id, amount, currency, minorUnits, interval, showI
1440
1512
  return /* @__PURE__ */ jsx("span", { id, className: `oods-billing-summary ${className ?? ""}`.trim(), "data-oods-component": "BillingSummaryBadge", children: showInterval ? billingSummary(amount, currency, minorUnits, interval) : formatBillingAmount(amount, currency, minorUnits) });
1441
1513
  }
1442
1514
  function BillingAmountInput({ id, amount, currency = "usd", minorUnits = BILLING_MINOR_UNITS, label = "Billing amount", name, disabled, className, help, onChange }) {
1443
- const generatedId = React3.useId();
1515
+ const generatedId = React4.useId();
1444
1516
  const controlId = id ?? `billing-amount-${generatedId}`;
1445
- const [text, setText] = React3.useState(() => billingAmountText(amount, minorUnits));
1446
- const [error, setError] = React3.useState(() => billingAmountMessage(amount, minorUnits));
1447
- React3.useEffect(() => {
1517
+ const [text, setText] = React4.useState(() => billingAmountText(amount, minorUnits));
1518
+ const [error, setError] = React4.useState(() => billingAmountMessage(amount, minorUnits));
1519
+ React4.useEffect(() => {
1448
1520
  setText(billingAmountText(amount, minorUnits));
1449
1521
  setError(billingAmountMessage(amount, minorUnits));
1450
1522
  }, [amount, minorUnits]);
@@ -1478,10 +1550,10 @@ function BillingAmountInput({ id, amount, currency = "usd", minorUnits = BILLING
1478
1550
  ] });
1479
1551
  }
1480
1552
  function BillingIntervalSelector({ id, interval, intervals = BILLING_INTERVALS, label = "Billing interval", name, disabled, className, help, onChange }) {
1481
- const generatedId = React3.useId();
1553
+ const generatedId = React4.useId();
1482
1554
  const controlId = id ?? `billing-interval-${generatedId}`;
1483
- const [value, setValue] = React3.useState(interval ?? "");
1484
- React3.useEffect(() => {
1555
+ const [value, setValue] = React4.useState(interval ?? "");
1556
+ React4.useEffect(() => {
1485
1557
  setValue(interval ?? "");
1486
1558
  }, [interval]);
1487
1559
  const error = billingIntervalMessage(value || void 0, intervals);
@@ -1589,8 +1661,8 @@ function AuditSummaryCard({ id, title = "Audit summary", showTransitionCount = t
1589
1661
  ] });
1590
1662
  }
1591
1663
  function SortIndicator({ id, label = "Sort", onChange, "data-oods-action": action, ...values }) {
1592
- const [state, setState] = React3.useState(() => initialSort(values));
1593
- React3.useEffect(() => setState(initialSort(values)), [values.sortField, values.sortDirection, values.sortActive, values.defaultSortField, values.defaultSortDirection]);
1664
+ const [state, setState] = React4.useState(() => initialSort(values));
1665
+ React4.useEffect(() => setState(initialSort(values)), [values.sortField, values.sortDirection, values.sortActive, values.defaultSortField, values.defaultSortDirection]);
1594
1666
  const sort = ariaSort(state);
1595
1667
  return /* @__PURE__ */ jsx("table", { id, className: "oods-sort-indicator", "data-oods-component": "SortIndicator", "aria-label": label, children: /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("th", { scope: "col", "aria-sort": sort, children: /* @__PURE__ */ jsx("button", { type: "button", "data-oods-action": action, "aria-label": `${label} ${state.field}`, onClick: () => {
1596
1668
  const next = nextSort(state, values.triStateSort);
@@ -1598,14 +1670,15 @@ function SortIndicator({ id, label = "Sort", onChange, "data-oods-action": actio
1598
1670
  onChange?.(next);
1599
1671
  }, children: `${state.field}: ${sort}` }) }) }) }) });
1600
1672
  }
1601
- var TimelineEntryLabel = React3.forwardRef(({ compact = true, maxLength, ...props }, ref) => /* @__PURE__ */ jsx(InlineLabel, { ...props, ref, maxLength: maxLength ?? (compact ? 40 : void 0), "data-oods-component": "TimelineEntryLabel", "data-timeline-label": "true", "data-compact": compact }));
1673
+ var TimelineEntryLabel = React4.forwardRef(({ compact = true, maxLength, ...props }, ref) => /* @__PURE__ */ jsx(InlineLabel, { ...props, ref, maxLength: maxLength ?? (compact ? 40 : void 0), "data-oods-component": "TimelineEntryLabel", "data-timeline-label": "true", "data-compact": compact }));
1602
1674
  TimelineEntryLabel.displayName = "OODS.TimelineEntryLabel";
1603
1675
  function eventRecipe(id, kind, title) {
1604
1676
  return function TraitEvent({ id: elementId, title: heading = title, ...values }) {
1605
1677
  const rows = traitEventRows(kind, values);
1678
+ if (!rows.length) return null;
1606
1679
  return /* @__PURE__ */ jsxs("article", { id: elementId, className: "oods-trait-recipe", "data-oods-component": id, "aria-label": heading, children: [
1607
1680
  /* @__PURE__ */ jsx("h2", { children: heading }),
1608
- rows.length ? /* @__PURE__ */ jsx("ol", { children: rows.map((row, index) => /* @__PURE__ */ jsxs("li", { children: [
1681
+ /* @__PURE__ */ jsx("ol", { children: rows.map((row, index) => /* @__PURE__ */ jsxs("li", { children: [
1609
1682
  /* @__PURE__ */ jsx("strong", { children: row.title }),
1610
1683
  /* @__PURE__ */ jsx("p", { children: row.at ? /* @__PURE__ */ jsx("time", { dateTime: row.at, children: row.time }) : row.time }),
1611
1684
  row.actor && /* @__PURE__ */ jsxs("p", { children: [
@@ -1620,7 +1693,7 @@ function eventRecipe(id, kind, title) {
1620
1693
  "Code: ",
1621
1694
  row.code
1622
1695
  ] })
1623
- ] }, index)) }) : /* @__PURE__ */ jsx("p", { children: "No events recorded." })
1696
+ ] }, index)) })
1624
1697
  ] });
1625
1698
  };
1626
1699
  }
@@ -1641,9 +1714,9 @@ function CommunicationDetailPanel({ id, title = "Communication", channels = [],
1641
1714
  ] });
1642
1715
  }
1643
1716
  function ColorStatePicker({ id, title = "Color state", colorStates = DEFAULT_COLOR_STATES, value, disabled, onChange }) {
1644
- const generatedId = React3.useId();
1645
- const [selected, setSelected] = React3.useState(value ?? colorStates[0] ?? "");
1646
- React3.useEffect(() => setSelected(value ?? colorStates[0] ?? ""), [value, colorStates]);
1717
+ const generatedId = React4.useId();
1718
+ const [selected, setSelected] = React4.useState(value ?? colorStates[0] ?? "");
1719
+ React4.useEffect(() => setSelected(value ?? colorStates[0] ?? ""), [value, colorStates]);
1647
1720
  return /* @__PURE__ */ jsxs("fieldset", { id, className: "oods-trait-recipe", "data-oods-component": "ColorStatePicker", children: [
1648
1721
  /* @__PURE__ */ jsx("legend", { children: title }),
1649
1722
  /* @__PURE__ */ jsx(Select, { id: `${id ?? generatedId}-state`, label: "Color state", name: "color_state", value: selected, disabled, options: [...!colorStates.includes(selected) ? [{ value: selected, label: selected || "Choose state", disabled: true }] : [], ...colorStates.map((value2) => ({ value: value2, label: formatReadOnlyValue(value2, "string", true) }))], onValueChange: (next) => {
@@ -1665,9 +1738,9 @@ function StatusColorLegend({ id, title = "Status colors", colorStates = DEFAULT_
1665
1738
  ] });
1666
1739
  }
1667
1740
  function GeoFieldMappingForm({ id, title = "Geographic fields", embedded = false, disabled, onChange, ...values }) {
1668
- const generatedId = React3.useId();
1669
- const [value, setValue] = React3.useState(() => geoFieldMapping(values));
1670
- React3.useEffect(() => setValue(geoFieldMapping(values)), [values.latitude, values.longitude, values.identifier, values.autoDetect]);
1741
+ const generatedId = React4.useId();
1742
+ const [value, setValue] = React4.useState(() => geoFieldMapping(values));
1743
+ React4.useEffect(() => setValue(geoFieldMapping(values)), [values.latitude, values.longitude, values.identifier, values.autoDetect]);
1671
1744
  const update = (patch) => {
1672
1745
  const next = { ...value, ...patch };
1673
1746
  setValue(next);
@@ -1701,11 +1774,11 @@ function GeocodablePreview({ id, title = "Geographic data", resolution, requires
1701
1774
  }
1702
1775
  function controls(id) {
1703
1776
  const Component = ({ id: htmlId, title = VIZ_CONTROL_TITLES[id], value, channel = "x", disabled, onChange }) => {
1704
- const generatedId = React3.useId();
1705
- const [current, setCurrent] = React3.useState(value ?? {});
1706
- const [drafts, setDrafts] = React3.useState({});
1707
- const [errors, setErrors] = React3.useState({});
1708
- React3.useEffect(() => {
1777
+ const generatedId = React4.useId();
1778
+ const [current, setCurrent] = React4.useState(value ?? {});
1779
+ const [drafts, setDrafts] = React4.useState({});
1780
+ const [errors, setErrors] = React4.useState({});
1781
+ React4.useEffect(() => {
1709
1782
  setCurrent(value ?? {});
1710
1783
  setDrafts({});
1711
1784
  setErrors({});
@@ -1779,5 +1852,214 @@ var VizLinePreview = preview("VizLinePreview", "line");
1779
1852
  var VizMarkPreview = preview("VizMarkPreview", "bar");
1780
1853
  var VizPointPreview = preview("VizPointPreview", "scatter");
1781
1854
  var VizScatterPreview = preview("VizScatterPreview", "scatter");
1855
+ var classes4 = (...values) => values.filter(Boolean).join(" ");
1856
+ var Combobox = React4.forwardRef(
1857
+ ({
1858
+ id,
1859
+ label,
1860
+ options = [],
1861
+ value,
1862
+ defaultValue = "",
1863
+ placeholder,
1864
+ name,
1865
+ required,
1866
+ disabled,
1867
+ help,
1868
+ validation,
1869
+ size = "md",
1870
+ className,
1871
+ style,
1872
+ onValueChange,
1873
+ onUpdate,
1874
+ onKeyDown,
1875
+ onBlur,
1876
+ onClick,
1877
+ "aria-describedby": nativeDescription,
1878
+ ...rest
1879
+ }, ref) => {
1880
+ const [internalValue, setInternalValue] = React4.useState(defaultValue);
1881
+ const [query, setQuery] = React4.useState(null);
1882
+ const [open, setOpen] = React4.useState(false);
1883
+ const [active, setActive] = React4.useState(-1);
1884
+ const rootRef = React4.useRef(null);
1885
+ const listboxRef = React4.useRef(null);
1886
+ const chosenValue = value ?? internalValue;
1887
+ const chosen = options.find((option) => option.value === chosenValue);
1888
+ const text = query ?? chosen?.label ?? "";
1889
+ const needle = (query ?? "").trim().toLowerCase();
1890
+ const matches = options.map((option) => needle === "" || option.label.toLowerCase().includes(needle));
1891
+ const matchCount = matches.filter(Boolean).length;
1892
+ const reachable = options.flatMap((option, index) => matches[index] && !option.disabled ? [index] : []);
1893
+ const optionId = (index) => `${id}-option-${index}`;
1894
+ const validationId = validation?.id ?? `${id}-validation`;
1895
+ const describedBy = [nativeDescription, help ? `${id}-help` : void 0, validation?.message ? validationId : void 0].filter(Boolean).join(" ") || void 0;
1896
+ const tone = validation ? validation.state === "error" ? "critical" : validation.state : void 0;
1897
+ const close = () => {
1898
+ setOpen(false);
1899
+ setActive(-1);
1900
+ };
1901
+ const emit = (next) => {
1902
+ if (value === void 0) setInternalValue(next);
1903
+ onValueChange?.(next);
1904
+ onUpdate?.(next);
1905
+ };
1906
+ const pick = (index) => {
1907
+ const option = options[index];
1908
+ if (!option || option.disabled) return;
1909
+ setQuery(null);
1910
+ close();
1911
+ if (option.value !== chosenValue) emit(option.value);
1912
+ };
1913
+ React4.useEffect(() => {
1914
+ if (!open) return void 0;
1915
+ const outside = (event) => {
1916
+ if (!rootRef.current?.contains(event.target)) close();
1917
+ };
1918
+ document.addEventListener("pointerdown", outside);
1919
+ return () => document.removeEventListener("pointerdown", outside);
1920
+ }, [open]);
1921
+ React4.useEffect(() => {
1922
+ if (!open || active < 0) return;
1923
+ const element = listboxRef.current?.children[active];
1924
+ element?.scrollIntoView?.({ block: "nearest" });
1925
+ }, [open, active]);
1926
+ const handleKeyDown = (event) => {
1927
+ onKeyDown?.(event);
1928
+ if (event.defaultPrevented || disabled || event.nativeEvent.isComposing) return;
1929
+ const first = reachable[0] ?? -1;
1930
+ const last = reachable[reachable.length - 1] ?? -1;
1931
+ const at = reachable.indexOf(active);
1932
+ switch (event.key) {
1933
+ case "ArrowDown":
1934
+ event.preventDefault();
1935
+ setOpen(true);
1936
+ setActive(!open || at === -1 ? first : reachable[(at + 1) % reachable.length]);
1937
+ return;
1938
+ case "ArrowUp":
1939
+ event.preventDefault();
1940
+ setOpen(true);
1941
+ setActive(!open || at <= 0 ? last : reachable[at - 1]);
1942
+ return;
1943
+ case "Home":
1944
+ case "End":
1945
+ if (!open) return;
1946
+ event.preventDefault();
1947
+ setActive(event.key === "Home" ? first : last);
1948
+ return;
1949
+ case "Enter":
1950
+ if (!open) return;
1951
+ event.preventDefault();
1952
+ if (active >= 0) pick(active);
1953
+ return;
1954
+ case "Escape":
1955
+ if (open) {
1956
+ event.preventDefault();
1957
+ close();
1958
+ return;
1959
+ }
1960
+ if (text === "" && chosenValue === "") return;
1961
+ event.preventDefault();
1962
+ setQuery(null);
1963
+ if (chosenValue !== "") emit("");
1964
+ return;
1965
+ case "Tab":
1966
+ if (open) close();
1967
+ return;
1968
+ }
1969
+ };
1970
+ return /* @__PURE__ */ jsxs(
1971
+ "div",
1972
+ {
1973
+ ref: rootRef,
1974
+ className: classes4("oods-field", "oods-combobox", className),
1975
+ style: {
1976
+ ...tone ? {
1977
+ "--cmp-input-message-border": `var(--sys-status-${tone}-border)`,
1978
+ "--cmp-input-message-text": `var(--sys-status-${tone}-text)`
1979
+ } : {},
1980
+ ...style
1981
+ },
1982
+ "data-oods-component": "Combobox",
1983
+ "data-size": size,
1984
+ "data-validation-state": validation?.state,
1985
+ children: [
1986
+ /* @__PURE__ */ jsxs("label", { id: `${id}-label`, className: "oods-field-label", htmlFor: id, children: [
1987
+ label,
1988
+ required ? /* @__PURE__ */ jsx("span", { className: "oods-field-required", "aria-hidden": "true", children: "*" }) : null
1989
+ ] }),
1990
+ /* @__PURE__ */ jsxs("div", { className: "oods-combobox__control", children: [
1991
+ /* @__PURE__ */ jsx(
1992
+ "input",
1993
+ {
1994
+ ...rest,
1995
+ ref,
1996
+ id,
1997
+ type: "text",
1998
+ role: "combobox",
1999
+ className: "oods-field-control oods-combobox__input",
2000
+ value: text,
2001
+ placeholder,
2002
+ autoComplete: "off",
2003
+ "aria-autocomplete": "list",
2004
+ "aria-expanded": open,
2005
+ "aria-controls": `${id}-listbox`,
2006
+ "aria-activedescendant": open && active >= 0 ? optionId(active) : void 0,
2007
+ "aria-describedby": describedBy,
2008
+ "aria-invalid": validation?.state === "error" || void 0,
2009
+ required,
2010
+ disabled,
2011
+ onChange: (event) => {
2012
+ setQuery(event.currentTarget.value);
2013
+ setOpen(true);
2014
+ setActive(-1);
2015
+ },
2016
+ onKeyDown: handleKeyDown,
2017
+ onClick: (event) => {
2018
+ onClick?.(event);
2019
+ if (!event.defaultPrevented && !disabled) setOpen(true);
2020
+ },
2021
+ onBlur: (event) => {
2022
+ onBlur?.(event);
2023
+ setQuery(null);
2024
+ close();
2025
+ }
2026
+ }
2027
+ ),
2028
+ /* @__PURE__ */ jsx("span", { className: "oods-combobox__chevron", "aria-hidden": "true", children: /* @__PURE__ */ jsx(StatusIcon, { name: "chevron-down" }) }),
2029
+ /* @__PURE__ */ jsxs("div", { className: "oods-combobox__popup", hidden: !open, onMouseDown: (event) => event.preventDefault(), children: [
2030
+ /* @__PURE__ */ jsx("ul", { ref: listboxRef, id: `${id}-listbox`, className: "oods-combobox__listbox", role: "listbox", "aria-labelledby": `${id}-label`, children: options.map((option, index) => /* @__PURE__ */ jsxs(
2031
+ "li",
2032
+ {
2033
+ id: optionId(index),
2034
+ className: "oods-combobox__option",
2035
+ role: "option",
2036
+ "aria-selected": option.value === chosenValue,
2037
+ "aria-disabled": option.disabled || void 0,
2038
+ "data-value": option.value,
2039
+ "data-active": index === active ? "true" : void 0,
2040
+ hidden: !matches[index],
2041
+ onClick: () => pick(index),
2042
+ onPointerMove: () => {
2043
+ if (!option.disabled && index !== active) setActive(index);
2044
+ },
2045
+ children: [
2046
+ /* @__PURE__ */ jsx("span", { className: "oods-combobox__option-label", children: option.label }),
2047
+ /* @__PURE__ */ jsx("span", { className: "oods-combobox__check", "aria-hidden": "true", children: /* @__PURE__ */ jsx(StatusIcon, { name: "check" }) })
2048
+ ]
2049
+ },
2050
+ option.value
2051
+ )) }),
2052
+ /* @__PURE__ */ jsx("p", { className: "oods-combobox__empty", role: "status", children: open && matchCount === 0 ? "No matches" : "" })
2053
+ ] })
2054
+ ] }),
2055
+ name ? /* @__PURE__ */ jsx("input", { type: "hidden", name, value: chosenValue }) : null,
2056
+ help ? /* @__PURE__ */ jsx("p", { id: `${id}-help`, className: "oods-field-help", children: help }) : null,
2057
+ validation?.message ? /* @__PURE__ */ jsx("p", { id: validationId, className: "oods-field-error", role: validation.state === "error" ? "alert" : void 0, children: validation.message }) : null
2058
+ ]
2059
+ }
2060
+ );
2061
+ }
2062
+ );
2063
+ Combobox.displayName = "OODS.Combobox";
1782
2064
 
1783
- export { AddressCollectionPanel, AddressEditor, AddressSummaryBadge, AddressValidationTimeline, ArchiveEvent, ArchivePill, ArchiveSummary, ArchivedRowOverlay, AuditEvent, AuditSummaryCard, BillingAmountInput, BillingCardMeta, BillingIntervalSelector, BillingSummaryBadge, CancellationBadge, CancellationEvent, CancellationForm, CardHeader, ClassificationBadge, ClassificationEditor, ClassificationPanel, ColorStatePicker, ColorSwatch, ColorizedBadge, CommunicationDetailPanel, CycleProgressCard, DetailHeader, FilterPanel, FormLabelGroup, GeoFieldMappingForm, GeoResolutionBadge, GeocodablePreview, Grid, InlineLabel, LabelCell, MembershipAuditTimeline, MembershipPanel, MessageEventTimeline, MessageStatusBadge, OwnerBadge, OwnershipMeta, OwnershipSummary, PaymentEventTimeline, PaymentTimeline, PreferenceEditor, PreferencePanel, PreferenceSummaryBadge, PreferenceTimeline, PriceCardMeta, PriceSummary, RoleAssignmentForm, RoleBadgeList, SortIndicator, Stack, StateTransitionEvent, StatusColorLegend, StatusSelector, Tabs, TagInput, TagManager, TagPills, TagSummary, TemplatePicker, TimelineEntryLabel, VizAreaControls, VizAreaPreview, VizAxisControls, VizAxisSummary, VizColorControls, VizColorLegendConfig, VizEncodingBadge, VizGraphPreview, VizHeatmapControls, VizHeatmapPreview, VizLineControls, VizLinePreview, VizMarkControls, VizMarkPreview, VizOpacityControls, VizOpacitySummary, VizPointControls, VizPointPreview, VizRoleBadge, VizScaleControls, VizScaleSummary, VizScatterControls, VizScatterPreview, VizShapeControls, VizShapeLegend, VizSizeControls, VizSizeSummary };
2065
+ export { AddressCollectionPanel, AddressEditor, AddressSummaryBadge, AddressValidationTimeline, ArchiveEvent, ArchivePill, ArchiveSummary, ArchivedRowOverlay, AuditEvent, AuditSummaryCard, BillingAmountInput, BillingCardMeta, BillingIntervalSelector, BillingSummaryBadge, CancellationBadge, CancellationEvent, CancellationForm, CardHeader, ClassificationBadge, ClassificationEditor, ClassificationPanel, ColorStatePicker, ColorSwatch, ColorizedBadge, Combobox, CommunicationDetailPanel, CycleProgressCard, DetailHeader, FilterPanel, FormLabelGroup, GeoFieldMappingForm, GeoResolutionBadge, GeocodablePreview, Grid, InlineLabel, LabelCell, MembershipAuditTimeline, MembershipPanel, MessageEventTimeline, MessageStatusBadge, OwnerBadge, OwnershipMeta, OwnershipSummary, PaymentEventTimeline, PaymentTimeline, PreferenceEditor, PreferencePanel, PreferenceSummaryBadge, PreferenceTimeline, PriceCardMeta, PriceSummary, RoleAssignmentForm, RoleBadgeList, SegmentedControl, SortIndicator, Stack, StateTransitionEvent, StatusColorLegend, StatusSelector, Tabs, TagInput, TagManager, TagPills, TagSummary, TemplatePicker, TimelineEntryLabel, VizAreaControls, VizAreaPreview, VizAxisControls, VizAxisSummary, VizColorControls, VizColorLegendConfig, VizEncodingBadge, VizGraphPreview, VizHeatmapControls, VizHeatmapPreview, VizLineControls, VizLinePreview, VizMarkControls, VizMarkPreview, VizOpacityControls, VizOpacitySummary, VizPointControls, VizPointPreview, VizRoleBadge, VizScaleControls, VizScaleSummary, VizScatterControls, VizScatterPreview, VizShapeControls, VizShapeLegend, VizSizeControls, VizSizeSummary };