@oods/components-vue 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ported.cjs CHANGED
@@ -4,6 +4,11 @@ var componentContracts = require('@oods/component-contracts');
4
4
  var vue = require('vue');
5
5
 
6
6
  // src/ported.ts
7
+ function statusIcon(name) {
8
+ return vue.h("svg", { ...componentContracts.STATUS_ICON_SVG_ATTRS }, componentContracts.STATUS_ICON_SHAPES[name].map((shape) => vue.h(shape.tag, { ...shape.attrs })));
9
+ }
10
+
11
+ // src/primitives.ts
7
12
  var toneProp = String;
8
13
  var emphasisProp = String;
9
14
  var sizeProp = String;
@@ -91,8 +96,8 @@ var Badge = vue.defineComponent({
91
96
  "--cmp-badge-text": `var(--sys-status-${palette}-text)`
92
97
  }
93
98
  }, [
94
- props.icon || slots.icon ? vue.h("span", { class: "oods-badge-icon", "aria-hidden": "true" }, [slotOrValue(slots.icon, props.icon)]) : null,
95
- slotOrValue(slots.default, props.content ?? statusLabel(props.status))
99
+ props.icon || slots.icon ? vue.h("span", { class: "oods-badge__icon", "aria-hidden": "true" }, [slotOrValue(slots.icon, props.icon)]) : null,
100
+ vue.h("span", { class: "oods-badge__label" }, [slotOrValue(slots.default, props.content ?? statusLabel(props.status))])
96
101
  ]);
97
102
  };
98
103
  }
@@ -116,7 +121,7 @@ vue.defineComponent({
116
121
  return () => {
117
122
  const tone = resolveTone(props.tone, props.status, props.domain);
118
123
  const palette = tokenTone(tone);
119
- return vue.h("section", {
124
+ return vue.h("div", {
120
125
  class: "oods-banner",
121
126
  "data-oods-component": "Banner",
122
127
  "data-status": props.status,
@@ -131,20 +136,20 @@ vue.defineComponent({
131
136
  "--cmp-banner-text": `var(--sys-status-${palette}-text)`
132
137
  }
133
138
  }, [
134
- vue.h("div", { class: "oods-banner-content" }, [
135
- props.title || props.status || slots.title ? vue.h("strong", { class: "oods-banner-title" }, [
139
+ vue.h("div", { class: "oods-banner__content" }, [
140
+ props.title || props.status || slots.title ? vue.h("strong", { class: "oods-banner__title" }, [
136
141
  slotOrValue(slots.title, props.title || statusLabel(props.status))
137
142
  ]) : null,
138
- props.detail ? vue.h("p", { class: "oods-banner-detail" }, props.detail) : null,
139
- slots.default || props.content ? vue.h(slots.default ? "div" : "p", { class: "oods-banner-body" }, [slotOrValue(slots.default, props.content)]) : null,
140
- slots.actions ? vue.h("div", { class: "oods-banner-actions" }, slots.actions()) : null
143
+ props.detail ? vue.h("p", { class: "oods-banner__detail" }, props.detail) : null,
144
+ slots.default || props.content ? vue.h(slots.default ? "div" : "p", { class: "oods-banner__body" }, [slotOrValue(slots.default, props.content)]) : null,
145
+ slots.actions ? vue.h("div", { class: "oods-banner__actions" }, slots.actions()) : null
141
146
  ]),
142
147
  props.dismissLabel ? vue.h("button", {
143
148
  type: "button",
144
- class: "oods-banner-dismiss",
149
+ class: "oods-banner-dismiss oods-banner__dismiss",
145
150
  "aria-label": props.dismissLabel,
146
151
  onClick: () => emit("dismiss")
147
- }, [vue.h("span", { "aria-hidden": "true" }, "\xD7")]) : null
152
+ }, [statusIcon("x")]) : null
148
153
  ]);
149
154
  };
150
155
  }
@@ -154,7 +159,7 @@ vue.defineComponent({
154
159
  props: {
155
160
  content: { type: [String, Number], default: "" },
156
161
  intent: { type: String, default: "neutral" },
157
- size: { type: sizeProp, default: "md" },
162
+ size: { type: String, default: "md" },
158
163
  disabled: Boolean,
159
164
  type: { type: String, default: "button" }
160
165
  },
@@ -181,6 +186,83 @@ vue.defineComponent({
181
186
  }, [slotOrValue(slots.default, props.content)]);
182
187
  }
183
188
  });
189
+ var canShowModal = () => typeof HTMLDialogElement !== "undefined" && typeof HTMLDialogElement.prototype.showModal === "function";
190
+ vue.defineComponent({
191
+ name: "OodsDialog",
192
+ props: {
193
+ id: String,
194
+ open: Boolean,
195
+ modal: { type: Boolean, default: true },
196
+ title: { type: String, default: "" },
197
+ description: String,
198
+ dismissLabel: { type: String, default: "Close" },
199
+ size: { type: String, default: "md" },
200
+ actions: { type: [String, Number, Object, Array], default: void 0 }
201
+ },
202
+ emits: {
203
+ close: () => true
204
+ },
205
+ setup(props, { emit, slots }) {
206
+ const generatedId = vue.useId().replace(/[^\w-]/g, "");
207
+ const dialogId = vue.computed(() => props.id || `oods-dialog-${generatedId}`);
208
+ const element = vue.ref(null);
209
+ const mounted = vue.ref(false);
210
+ const managed = vue.computed(() => props.modal && mounted.value && canShowModal());
211
+ const sync = () => {
212
+ const dialog = element.value;
213
+ if (!dialog || !managed.value) return;
214
+ if (props.open && !dialog.open) dialog.showModal();
215
+ else if (!props.open && dialog.open) dialog.close();
216
+ };
217
+ vue.onMounted(() => {
218
+ mounted.value = true;
219
+ });
220
+ vue.watch([() => props.open, managed], sync, { flush: "post" });
221
+ const requestClose = (event) => {
222
+ event.preventDefault();
223
+ emit("close");
224
+ };
225
+ return () => {
226
+ const titleId = `${dialogId.value}-title`;
227
+ const descriptionId = `${dialogId.value}-description`;
228
+ const actions = slotOrValue(slots.actions, props.actions);
229
+ return vue.h("dialog", {
230
+ ref: element,
231
+ id: dialogId.value,
232
+ class: "oods-dialog",
233
+ "data-oods-component": "Dialog",
234
+ "data-size": props.size,
235
+ "aria-labelledby": titleId,
236
+ "aria-describedby": props.description ? descriptionId : void 0,
237
+ open: managed.value ? void 0 : props.open,
238
+ onKeydown: (event) => {
239
+ if (event.key === "Escape" && !event.defaultPrevented) requestClose(event);
240
+ },
241
+ onCancel: requestClose,
242
+ // The browser closed it (a close request it would not let be cancelled) while open is still true. A close event
243
+ // from moving a mounted dialog into the top layer finds it open again, and is not reported.
244
+ onClose: () => {
245
+ if (props.open && !element.value?.open) emit("close");
246
+ }
247
+ }, [
248
+ vue.h("div", { class: "oods-dialog__header" }, [
249
+ vue.h("div", { class: "oods-dialog__heading" }, [
250
+ vue.h("h2", { id: titleId, class: "oods-dialog__title" }, props.title),
251
+ props.description ? vue.h("p", { id: descriptionId, class: "oods-dialog__description" }, props.description) : null
252
+ ]),
253
+ vue.h("button", {
254
+ type: "button",
255
+ class: "oods-dialog__close",
256
+ "aria-label": props.dismissLabel,
257
+ onClick: () => emit("close")
258
+ }, [statusIcon("x")])
259
+ ]),
260
+ slots.default ? vue.h("div", { class: "oods-dialog__body" }, slots.default()) : null,
261
+ actions !== void 0 && actions !== null && actions !== "" ? vue.h("div", { class: "oods-dialog__footer" }, [actions]) : null
262
+ ]);
263
+ };
264
+ }
265
+ });
184
266
  var SAFE_CARD_ELEMENTS = /* @__PURE__ */ new Set(["div", "article", "section", "aside"]);
185
267
  vue.defineComponent({
186
268
  name: "OodsCard",
@@ -355,7 +437,9 @@ var Input = vue.defineComponent({
355
437
  name: "OodsInput",
356
438
  props: {
357
439
  ...textFieldProps,
358
- type: { type: String, default: "text" }
440
+ type: { type: String, default: "text" },
441
+ /** A class for the input element itself, as React's inputClassName; the field's own class stays on its frame. */
442
+ inputClass: String
359
443
  },
360
444
  emits: {
361
445
  "update:modelValue": (_value) => true,
@@ -373,7 +457,7 @@ var Input = vue.defineComponent({
373
457
  };
374
458
  return () => renderField("Input", props, slots, metadata, vue.h("input", {
375
459
  id: metadata.controlId.value,
376
- class: "oods-field-control",
460
+ class: props.inputClass ? ["oods-field-control", props.inputClass] : "oods-field-control",
377
461
  type: props.type,
378
462
  name: props.name,
379
463
  value: props.type === "datetime-local" ? componentContracts.dateTimeInputValue(currentValue.value) : currentValue.value,
@@ -573,82 +657,75 @@ vue.defineComponent({
573
657
  };
574
658
  }
575
659
  });
576
-
577
- // src/ported-core.ts
578
- var STATUS_METADATA = {
579
- subscription: {
580
- future: {
581
- description: "Subscription is scheduled but not yet active.",
582
- tone: "info",
583
- icon: "\u23F2"
584
- },
585
- trialing: {
586
- description: "Subscription is in a trial period before billing begins.",
587
- tone: "accent",
588
- icon: "\u2605"
589
- },
590
- active: {
591
- description: "Subscription is paid and service is provisioned.",
592
- tone: "success",
593
- icon: "\u2714\uFE0E"
594
- },
595
- paused: {
596
- description: "Billing paused temporarily by finance or customer request.",
597
- tone: "neutral",
598
- icon: "\u23F8"
599
- },
600
- pending_cancellation: {
601
- description: "Subscription will cancel at period end but remains active now.",
602
- tone: "info",
603
- icon: "\u2026"
604
- },
605
- past_due: {
606
- description: "Renewal payment failed; smart retries ongoing and access retained during the grace window.",
607
- tone: "critical",
608
- icon: "\u26A0\uFE0E"
609
- },
610
- unpaid: {
611
- description: "Payment retries exhausted; service access revoked.",
612
- tone: "critical",
613
- icon: "\u2A2F"
614
- },
615
- terminated: {
616
- description: "Subscription ended; service access revoked and billing stopped.",
617
- tone: "neutral",
618
- icon: "\u2205"
619
- }
660
+ vue.defineComponent({
661
+ name: "OodsSwitch",
662
+ props: {
663
+ id: String,
664
+ label: String,
665
+ modelValue: { type: Boolean, default: void 0 },
666
+ checked: { type: Boolean, default: void 0 },
667
+ defaultChecked: Boolean,
668
+ required: Boolean,
669
+ disabled: Boolean,
670
+ help: String,
671
+ validation: Object,
672
+ size: { type: String, default: "md" }
620
673
  },
621
- invoice: {
622
- draft: {
623
- description: "Invoice is editable and not yet finalized.",
624
- tone: "neutral",
625
- icon: "\u270E"
626
- },
627
- posted: {
628
- description: "Invoice finalized with terms before collection.",
629
- tone: "info",
630
- icon: "\u2026"
631
- },
632
- paid: {
633
- description: "Invoice collected successfully in full.",
634
- tone: "success",
635
- icon: "\u2714\uFE0E"
636
- },
637
- past_due: {
638
- description: "Invoice is unpaid past its due date.",
639
- tone: "critical",
640
- icon: "\u2A2F"
641
- },
642
- void: {
643
- description: "Invoice canceled and no longer payable.",
644
- tone: "neutral",
645
- icon: "\u2205"
646
- }
674
+ emits: {
675
+ "update:modelValue": (_value) => true,
676
+ change: (_value) => true
677
+ },
678
+ setup(props, { emit, slots }) {
679
+ const internalChecked = vue.ref(props.defaultChecked);
680
+ const currentChecked = vue.computed(() => props.modelValue ?? props.checked ?? internalChecked.value);
681
+ const metadata = useFieldMetadata("Switch", props, slots);
682
+ const toggle = () => {
683
+ const next = !currentChecked.value;
684
+ if (props.modelValue === void 0 && props.checked === void 0) internalChecked.value = next;
685
+ emit("update:modelValue", next);
686
+ emit("change", next);
687
+ };
688
+ return () => {
689
+ const label = slots.label?.() ?? props.label;
690
+ const help = slots.help?.() ?? props.help;
691
+ const validation = slots.validation?.() ?? props.validation?.message;
692
+ const controlId = metadata.controlId.value;
693
+ return vue.h("div", {
694
+ class: "oods-field oods-switch",
695
+ style: validationStyle(props.validation),
696
+ "data-oods-component": "Switch",
697
+ "data-size": props.size,
698
+ "data-validation-state": props.validation?.state
699
+ }, [
700
+ vue.h("div", { class: "oods-switch__row" }, [
701
+ vue.h("button", {
702
+ id: controlId,
703
+ type: "button",
704
+ role: "switch",
705
+ class: "oods-switch__control",
706
+ "aria-checked": currentChecked.value ? "true" : "false",
707
+ "aria-labelledby": `${controlId}-label`,
708
+ "aria-describedby": metadata.describedBy.value,
709
+ "aria-required": props.required ? "true" : void 0,
710
+ "aria-invalid": props.validation?.state === "error" ? "true" : void 0,
711
+ disabled: props.disabled,
712
+ onClick: toggle
713
+ }, [vue.h("span", { class: "oods-switch__thumb", "aria-hidden": "true" })]),
714
+ vue.h("label", { id: `${controlId}-label`, class: "oods-field-label oods-switch__label", for: controlId }, [
715
+ label,
716
+ props.required ? vue.h("span", { class: "oods-field-required", "aria-hidden": "true" }, "*") : null
717
+ ])
718
+ ]),
719
+ help ? vue.h("p", { id: metadata.helpId.value, class: "oods-field-help" }, help) : null,
720
+ validation ? vue.h("p", {
721
+ id: metadata.validationId.value,
722
+ class: "oods-field-error",
723
+ role: props.validation?.state === "error" ? "alert" : void 0
724
+ }, validation) : null
725
+ ]);
726
+ };
647
727
  }
648
- };
649
- var STATUS_ALIASES = {
650
- subscription: { delinquent: "unpaid" }
651
- };
728
+ });
652
729
  function isRecord(value) {
653
730
  return typeof value === "object" && value !== null && !Array.isArray(value);
654
731
  }
@@ -665,18 +742,13 @@ function statusLabel2(status) {
665
742
  return status.split(/[_-]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
666
743
  }
667
744
  function getPortedStatusPresentation(domain, status) {
668
- const normalizedDomain = domain.toLowerCase();
669
- const normalizedStatus = status.toLowerCase();
670
- const alias = STATUS_ALIASES[normalizedDomain]?.[normalizedStatus];
671
- const metadata = STATUS_METADATA[normalizedDomain]?.[alias ?? normalizedStatus];
672
- if (!metadata) {
673
- return {
674
- label: statusLabel2(status || "Unknown"),
675
- description: "Status not found in registry; falling back to the requested token set.",
676
- tone: "neutral"
677
- };
678
- }
679
- return { ...metadata, label: statusLabel2(status) };
745
+ const presentation = componentContracts.getStatusPresentation(domain.toLowerCase(), status);
746
+ return {
747
+ label: statusLabel2(status || "Unknown"),
748
+ description: presentation.description,
749
+ tone: presentation.tone,
750
+ icon: componentContracts.resolveStatusIcon(presentation.iconName)
751
+ };
680
752
  }
681
753
  function formatPrice(amountCents, amount, currency) {
682
754
  const normalizedAmount = amount;
@@ -820,11 +892,10 @@ var StatusBadge = vue.defineComponent({
820
892
  domain: props.domain,
821
893
  tone,
822
894
  emphasis: props.variant === "solid" ? "solid" : props.emphasis,
823
- icon: props.showIcon ? presentation.icon : void 0,
824
895
  title: stringValue(attrs.title) ?? presentation.description,
825
896
  "aria-label": ariaLabel,
826
897
  "data-oods-component": "StatusBadge"
827
- }, slots);
898
+ }, props.showIcon && presentation.icon && !slots.icon ? { ...slots, icon: () => statusIcon(presentation.icon) } : slots);
828
899
  };
829
900
  }
830
901
  });
@@ -907,12 +978,12 @@ var timelineProps = {
907
978
  };
908
979
  function renderTimelineEvent(event, index, showActorId, showReason) {
909
980
  return vue.h("li", { key: `${event.timestamp ?? "event"}-${index}` }, [
910
- vue.h("article", { "data-timeline-event": "true" }, [
911
- vue.h("p", { "data-timeline-label": "true" }, event.label),
981
+ vue.h("article", { class: "oods-timeline__event", "data-timeline-event": "true" }, [
982
+ vue.h("p", { class: "oods-timeline__label", "data-timeline-label": "true" }, event.label),
912
983
  event.timestamp ? vue.h("time", { "data-timeline-time": "true", datetime: event.timestamp }, componentContracts.formatDateTime(event.timestamp)) : null,
913
- event.detail ? vue.h("p", { "data-timeline-detail": "true" }, event.detail) : null,
914
- showActorId && event.actorId ? vue.h("p", { "data-timeline-actor": "true" }, `Actor: ${event.actorId}`) : null,
915
- showReason && event.reason ? vue.h("p", { "data-timeline-reason": "true" }, `Reason: ${event.reason}`) : null
984
+ event.detail ? vue.h("p", { class: "oods-timeline__detail", "data-timeline-detail": "true" }, event.detail) : null,
985
+ showActorId && event.actorId ? vue.h("p", { class: "oods-timeline__actor", "data-timeline-actor": "true" }, `Actor: ${event.actorId}`) : null,
986
+ showReason && event.reason ? vue.h("p", { class: "oods-timeline__reason", "data-timeline-reason": "true" }, `Reason: ${event.reason}`) : null
916
987
  ])
917
988
  ]);
918
989
  }
@@ -930,16 +1001,16 @@ function timelineComponent(configuration) {
930
1001
  const slottedEvents = slots.default?.();
931
1002
  return vue.h("div", {
932
1003
  ...attrs,
933
- class: mergedClass("oods-timeline", attrs.class),
1004
+ class: mergedClass(`oods-timeline oods-${configuration.timelineType}-timeline`, attrs.class),
934
1005
  role: "log",
935
1006
  "aria-label": stringValue(attrs["aria-label"]) ?? title,
936
1007
  "data-oods-component": configuration.componentId,
937
1008
  "data-timeline-type": configuration.timelineType
938
1009
  }, [
939
- vue.h("h2", { "data-timeline-title": "true" }, title),
940
- props.status ? vue.h("p", { "data-timeline-current": "true" }, `Current status: ${statusLabel2(props.status)}`) : null,
1010
+ vue.h("h2", { class: "oods-timeline__title", "data-timeline-title": "true" }, title),
1011
+ props.status ? vue.h("p", { class: "oods-timeline__current", "data-timeline-current": "true" }, `Current status: ${statusLabel2(props.status)}`) : null,
941
1012
  props.allowedTransitions?.length ? vue.h("p", { "data-timeline-transitions": "true" }, `Allowed transitions: ${props.allowedTransitions.join(", ")}`) : null,
942
- vue.h("ol", { "data-timeline-events": "true" }, slottedEvents?.length ? slottedEvents : events.length ? events.map((event, index) => renderTimelineEvent(
1013
+ vue.h("ol", { class: "oods-timeline__events", "data-timeline-events": "true" }, slottedEvents?.length ? slottedEvents : events.length ? events.map((event, index) => renderTimelineEvent(
943
1014
  event,
944
1015
  index,
945
1016
  props.showActorId,
@@ -1095,8 +1166,7 @@ var SearchInput = vue.defineComponent({
1095
1166
  updateValue("");
1096
1167
  emit("clear");
1097
1168
  };
1098
- const submit = (event) => {
1099
- event.preventDefault();
1169
+ const searchNow = () => {
1100
1170
  if (!props.disabled) {
1101
1171
  if (timer !== void 0) clearTimeout(timer);
1102
1172
  emitSearch(currentValue.value);
@@ -1105,14 +1175,13 @@ var SearchInput = vue.defineComponent({
1105
1175
  return () => {
1106
1176
  const id = props.id ?? `oods-search-${generatedId.replace(/:/g, "")}`;
1107
1177
  const ariaLabel = stringValue(attrs["aria-label"]) ?? props.label ?? props.placeholder;
1108
- return vue.h("form", {
1178
+ return vue.h("div", {
1109
1179
  ...attrs,
1110
1180
  class: mergedClass("oods-search-input", attrs.class),
1111
1181
  role: "search",
1112
1182
  "aria-label": ariaLabel,
1113
1183
  "data-oods-component": "SearchInput",
1114
- "data-behavioral": "search",
1115
- onSubmit: submit
1184
+ "data-behavioral": "search"
1116
1185
  }, [
1117
1186
  vue.h(Input, {
1118
1187
  id,
@@ -1121,19 +1190,25 @@ var SearchInput = vue.defineComponent({
1121
1190
  value: currentValue.value,
1122
1191
  placeholder: props.placeholder,
1123
1192
  disabled: props.disabled,
1193
+ inputClass: "oods-search-input__control",
1124
1194
  "aria-label": props.label ? void 0 : ariaLabel,
1125
1195
  onInput: (value) => updateValue(value),
1126
1196
  onKeydown: (event) => {
1127
1197
  if (event.key === "Escape") clear();
1198
+ if (event.key === "Enter") {
1199
+ event.preventDefault();
1200
+ searchNow();
1201
+ }
1128
1202
  }
1129
1203
  }),
1130
1204
  props.clearable && currentValue.value ? vue.h("button", {
1131
1205
  type: "button",
1206
+ class: "oods-search-input__clear",
1132
1207
  "data-search-clear": "true",
1133
1208
  "aria-label": "Clear search",
1134
1209
  disabled: props.disabled,
1135
1210
  onClick: clear
1136
- }, "\xD7") : null
1211
+ }, [statusIcon("x")]) : null
1137
1212
  ]);
1138
1213
  };
1139
1214
  }
@@ -1280,17 +1355,18 @@ var RelativeTimestamp = vue.defineComponent({
1280
1355
  props.createdAt
1281
1356
  ) ?? "";
1282
1357
  if (props.hideWhenEmpty && (!datetime || Number.isNaN(Date.parse(datetime)))) return null;
1358
+ const absolute = componentContracts.formatDateTime(datetime, { timeZone: props.timezone });
1283
1359
  const content = firstDefined(
1284
1360
  props.relative,
1285
1361
  props.label,
1286
1362
  props.text,
1287
- props.now === void 0 ? componentContracts.formatDateTime(datetime, { timeZone: props.timezone }) : relativeTimestampLabel(datetime, props.now)
1363
+ !absolute ? "Unknown time" : props.now === void 0 ? absolute : relativeTimestampLabel(datetime, props.now)
1288
1364
  ) ?? "";
1289
1365
  return vue.h("time", {
1290
1366
  ...attrs,
1291
1367
  class: mergedClass("oods-relative-timestamp", attrs.class),
1292
1368
  datetime: datetime || void 0,
1293
- title: stringValue(attrs.title) ?? componentContracts.formatDateTime(datetime, { timeZone: props.timezone }),
1369
+ title: stringValue(attrs.title) ?? absolute,
1294
1370
  "data-oods-component": "RelativeTimestamp"
1295
1371
  }, content);
1296
1372
  };
package/dist/ported.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as vue from 'vue';
2
2
  import { PropType, VNode } from 'vue';
3
+ import { StatusIconName } from '@oods/component-contracts';
3
4
 
4
5
  type ComponentTone = 'neutral' | 'info' | 'accent' | 'positive' | 'success' | 'warning' | 'critical' | 'danger';
5
6
  type ComponentEmphasis = 'subtle' | 'solid';
@@ -21,7 +22,7 @@ type PaginationItem = {
21
22
  type StatusMetadata = {
22
23
  description: string;
23
24
  tone: ComponentTone;
24
- icon?: string;
25
+ icon?: StatusIconName;
25
26
  };
26
27
  type StatusPresentation = StatusMetadata & {
27
28
  label: string;
package/dist/ported.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as vue from 'vue';
2
2
  import { PropType, VNode } from 'vue';
3
+ import { StatusIconName } from '@oods/component-contracts';
3
4
 
4
5
  type ComponentTone = 'neutral' | 'info' | 'accent' | 'positive' | 'success' | 'warning' | 'critical' | 'danger';
5
6
  type ComponentEmphasis = 'subtle' | 'solid';
@@ -21,7 +22,7 @@ type PaginationItem = {
21
22
  type StatusMetadata = {
22
23
  description: string;
23
24
  tone: ComponentTone;
24
- icon?: string;
25
+ icon?: StatusIconName;
25
26
  };
26
27
  type StatusPresentation = StatusMetadata & {
27
28
  label: string;