@viax.io/uxm 4.40.1 → 4.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +78 -19
  3. package/dist/studio/index.cjs.map +1 -1
  4. package/dist/studio/index.d.ts +3 -2
  5. package/dist/studio/index.d.ts.map +1 -1
  6. package/dist/studio/index.js.map +1 -1
  7. package/dist/studio/lib/registry/composite/list-item.cjs +22 -5
  8. package/dist/studio/lib/registry/composite/list-item.cjs.map +1 -1
  9. package/dist/studio/lib/registry/composite/list-item.d.ts.map +1 -1
  10. package/dist/studio/lib/registry/composite/list-item.js +22 -5
  11. package/dist/studio/lib/registry/composite/list-item.js.map +1 -1
  12. package/dist/ui/app-sidebar/app-sidebar.css +0 -1
  13. package/dist/ui/app-top-bar/app-top-bar.css +0 -1
  14. package/dist/ui/avatar/avatar.css +0 -1
  15. package/dist/ui/back-link/back-link.css +0 -1
  16. package/dist/ui/badge/badge.css +0 -1
  17. package/dist/ui/banner/banner.css +0 -1
  18. package/dist/ui/breadcrumb/breadcrumb.css +0 -1
  19. package/dist/ui/bulk-action-bar/bulk-action-bar.css +0 -1
  20. package/dist/ui/button/button.css +0 -1
  21. package/dist/ui/button-group/button-group.css +0 -1
  22. package/dist/ui/button-icon/button-icon.css +0 -1
  23. package/dist/ui/button-with-icon/button-with-icon.css +0 -1
  24. package/dist/ui/calendar/calendar.css +0 -1
  25. package/dist/ui/card/card.css +0 -1
  26. package/dist/ui/checkbox/checkbox.css +0 -1
  27. package/dist/ui/chip/chip.css +0 -1
  28. package/dist/ui/cluster/cluster.css +0 -1
  29. package/dist/ui/code-editor/code-editor.css +0 -1
  30. package/dist/ui/color-input/color-input.css +0 -1
  31. package/dist/ui/component-row/component-row.css +0 -1
  32. package/dist/ui/config-component-row/config-component-row.css +0 -1
  33. package/dist/ui/config-segment-item/config-segment-item.css +0 -1
  34. package/dist/ui/currency-input/currency-input.css +0 -1
  35. package/dist/ui/data-table/data-table.css +0 -1
  36. package/dist/ui/date-input/date-input.css +0 -1
  37. package/dist/ui/detail-section/detail-section.css +0 -1
  38. package/dist/ui/dialog/dialog.css +0 -1
  39. package/dist/ui/disclosure/disclosure.css +0 -1
  40. package/dist/ui/divider/divider.css +0 -1
  41. package/dist/ui/editable-cell/editable-cell.css +0 -1
  42. package/dist/ui/empty-state/empty-state.css +0 -1
  43. package/dist/ui/error-page/error-page.css +0 -1
  44. package/dist/ui/explorer-list-item/explorer-list-item.css +0 -1
  45. package/dist/ui/explorer-section/explorer-section.css +0 -1
  46. package/dist/ui/file-upload/file-upload.css +0 -1
  47. package/dist/ui/filter-tabs/filter-tabs.css +0 -1
  48. package/dist/ui/form-field/form-field.css +0 -1
  49. package/dist/ui/icon/icon.css +0 -1
  50. package/dist/ui/icon-button/icon-button.css +0 -1
  51. package/dist/ui/icon-tile/icon-tile.css +0 -1
  52. package/dist/ui/inline-action/inline-action.css +0 -1
  53. package/dist/ui/inline-filter/inline-filter.css +0 -1
  54. package/dist/ui/input/input.css +0 -1
  55. package/dist/ui/input-with-icon/input-with-icon.css +0 -1
  56. package/dist/ui/language-switcher/language-switcher.css +0 -1
  57. package/dist/ui/lifecycle-connector/lifecycle-connector.css +0 -1
  58. package/dist/ui/lifecycle-drop-slot/lifecycle-drop-slot.css +0 -1
  59. package/dist/ui/lifecycle-edge-label/lifecycle-edge-label.css +0 -1
  60. package/dist/ui/lifecycle-group-box/lifecycle-group-box.css +0 -1
  61. package/dist/ui/lifecycle-minimap/lifecycle-minimap.css +0 -1
  62. package/dist/ui/lifecycle-node-card/lifecycle-node-card.css +0 -1
  63. package/dist/ui/lifecycle-terminal/lifecycle-terminal.css +0 -1
  64. package/dist/ui/lifecycle-zoom-control/lifecycle-zoom-control.css +0 -1
  65. package/dist/ui/link/link.css +0 -1
  66. package/dist/ui/list/list-item-preview.cjs +9 -4
  67. package/dist/ui/list/list-item-preview.cjs.map +1 -1
  68. package/dist/ui/list/list-item-preview.d.ts.map +1 -1
  69. package/dist/ui/list/list-item-preview.js +10 -5
  70. package/dist/ui/list/list-item-preview.js.map +1 -1
  71. package/dist/ui/list/list.cjs +9 -1
  72. package/dist/ui/list/list.cjs.map +1 -1
  73. package/dist/ui/list/list.css +39 -1
  74. package/dist/ui/list/list.d.ts +32 -1
  75. package/dist/ui/list/list.d.ts.map +1 -1
  76. package/dist/ui/list/list.js +8 -1
  77. package/dist/ui/list/list.js.map +1 -1
  78. package/dist/ui/listbox/listbox.css +0 -1
  79. package/dist/ui/loader/loader.css +0 -1
  80. package/dist/ui/menu/menu.css +0 -1
  81. package/dist/ui/meta-row/meta-row.css +0 -1
  82. package/dist/ui/modal/modal.css +0 -1
  83. package/dist/ui/number-input/number-input.css +0 -1
  84. package/dist/ui/number-stepper/number-stepper.css +0 -1
  85. package/dist/ui/option-list/option-list.css +0 -1
  86. package/dist/ui/page-header/page-header.css +0 -1
  87. package/dist/ui/page-shell/page-shell.css +0 -1
  88. package/dist/ui/password-input/password-input.css +0 -1
  89. package/dist/ui/phone-input/phone-input.css +0 -1
  90. package/dist/ui/pill-select/pill-select.css +0 -1
  91. package/dist/ui/popover/popover.css +0 -1
  92. package/dist/ui/progress-bar/progress-bar.css +0 -1
  93. package/dist/ui/property-field/property-field.css +0 -1
  94. package/dist/ui/radio-group/radio-group.css +0 -1
  95. package/dist/ui/range-slider/range-slider.css +0 -1
  96. package/dist/ui/responsive-grid/responsive-grid.css +0 -1
  97. package/dist/ui/search-dropdown/search-dropdown.css +0 -1
  98. package/dist/ui/section-header/section-header.css +0 -1
  99. package/dist/ui/segment-card/segment-card.css +0 -1
  100. package/dist/ui/segment-row/segment-row.css +0 -1
  101. package/dist/ui/side-flexpane/side-flexpane.css +0 -1
  102. package/dist/ui/sidebar-nav-item/sidebar-nav-item.css +0 -1
  103. package/dist/ui/sidebar-nav-trigger/sidebar-nav-trigger.css +0 -1
  104. package/dist/ui/slider/slider.css +0 -1
  105. package/dist/ui/stack/stack.css +0 -1
  106. package/dist/ui/stat-card/stat-card.css +0 -1
  107. package/dist/ui/tabs/tabs.css +0 -1
  108. package/dist/ui/tabs-underline/tabs-underline.css +0 -1
  109. package/dist/ui/tag/tag.css +0 -1
  110. package/dist/ui/thumbnail/thumbnail.css +0 -1
  111. package/dist/ui/time-input/time-input.css +0 -1
  112. package/dist/ui/timeline-entry/timeline-entry.css +0 -1
  113. package/dist/ui/toast/toast.css +0 -1
  114. package/dist/ui/toggle-switch/toggle-switch.css +0 -1
  115. package/dist/ui/tooltip/tooltip.css +0 -1
  116. package/dist/ui/type-overview-card/type-overview-card.css +0 -1
  117. package/dist/ui/view-switcher/view-switcher.css +0 -1
  118. package/package.json +3 -1
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── list ── */
3
2
  .uxm-list {
4
3
  background-color: var(--color-card);
@@ -56,6 +55,26 @@
56
55
  which owns the accent-tile treatment. The studio icon knobs are forwarded
57
56
  into IconTile's var namespace via `LIST_ITEM_ICON_TILE_STYLE`, so the tile
58
57
  pattern is defined once instead of being re-implemented here. */
58
+ /* Media slot — the alternative leading position for a thumbnail / avatar /
59
+ bare <img>, rendered as-is (no IconTile, no accent fill, no colour of its
60
+ own: the media brings its own frame). The row still owns the geometry, so
61
+ every leading element lands on the same grid whichever slot filled it. */
62
+ }
63
+ .uxm-list-item__media {
64
+ align-items: center;
65
+ box-sizing: border-box;
66
+ display: inline-flex;
67
+ /* Never let a long title squeeze the media out of square. */
68
+ flex-shrink: 0;
69
+ height: var(--uxm-list-item-media-size, 36px);
70
+ justify-content: center;
71
+ width: var(--uxm-list-item-media-size, 36px);
72
+ /* Only for a bare <img> passed straight in — without this it would
73
+ stretch to the box. `Thumbnail`'s own `--cover` / `--contain` rule is
74
+ more specific, so its fit choice still wins. */
75
+ }
76
+ .uxm-list-item__media img {
77
+ object-fit: cover;
59
78
  }
60
79
  .uxm-list-item__content {
61
80
  display: flex;
@@ -74,4 +93,23 @@
74
93
  .uxm-list-item__trailing {
75
94
  color: var(--uxm-list-item-chevron-color, var(--color-text-muted));
76
95
  font-size: calc(12px * var(--type-scale, 1));
96
+ }
97
+
98
+ /* Media fallback stretch, at (0,2,0) on purpose — same reasoning as
99
+ `avatar.scss`'s double-class size presets: a single-class selector here
100
+ (`.uxm-list-item__media > *`) TIES with a child atom's own size rule
101
+ (`.uxm-thumbnail`, also 0,1,0) and then loses or wins on nothing but the
102
+ `styles.css` import order, which is alphabetical — `Avatar` (line 7) would
103
+ obey the slot and `Thumbnail` (line 94) would ignore it. Two classes settle
104
+ it for every child regardless of order. The slot is always rendered inside a
105
+ row, so the descendant selector costs nothing.
106
+
107
+ Atoms with a size var of their own are ALSO handled by the forwarding in
108
+ `LIST_ITEM_MEDIA_STYLE` (list.tsx) — that path is what makes their border /
109
+ radius / inner glyph scale with the row instead of merely being clamped to
110
+ its box. Both resolve to the same size; this rule is the floor for a bare
111
+ <img>, <svg>, or a consumer's own node. */
112
+ .uxm-list-item .uxm-list-item__media > * {
113
+ height: 100%;
114
+ width: 100%;
77
115
  }
@@ -8,6 +8,21 @@ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, CSSProperties, HTMLAtt
8
8
  * constant so the studio preview can reuse the exact same forwarding.
9
9
  */
10
10
  export declare const LIST_ITEM_ICON_TILE_STYLE: CSSProperties;
11
+ /**
12
+ * Forward the row's media-size knob into the size vars of the atoms that
13
+ * plausibly fill the `media` slot, so each one sizes itself through its OWN
14
+ * machinery — frame, border, radius and inner glyph / initials all scale with
15
+ * it — instead of being stretched from the outside. Mirrors
16
+ * `LIST_ITEM_ICON_TILE_STYLE` above, and is the only order-independent fix:
17
+ * both `Thumbnail` (`.uxm-thumbnail`, 0,1,0 but imported AFTER list in
18
+ * `styles.css`) and `Avatar` (double-class size presets at 0,2,0, deliberately
19
+ * so per its own note) would otherwise win or lose the cascade against a slot
20
+ * rule purely on stylesheet order. The generic `> *` stretch in `list.scss`
21
+ * stays as the fallback for a bare `<img>` / `<svg>` or any atom with no size
22
+ * var of its own; both mechanisms resolve to the same number. Kept as a module
23
+ * constant so the studio preview can reuse the exact same forwarding.
24
+ */
25
+ export declare const LIST_ITEM_MEDIA_STYLE: CSSProperties;
11
26
  export interface ListProps extends HTMLAttributes<HTMLDivElement> {
12
27
  children: ReactNode;
13
28
  }
@@ -25,6 +40,22 @@ export declare function List({ children, className, ...rest }: ListProps): impor
25
40
  export interface ListItemProps {
26
41
  /** Leading icon — typically <Icon ... /> from @modo/uxm/ui. */
27
42
  icon?: ReactNode;
43
+ /** Leading media rendered as-is (a <Thumbnail>, <img>, avatar…) — NOT
44
+ * wrapped in the accent `IconTile` the `icon` slot uses. Mutually
45
+ * exclusive with `icon`: when both are passed, `media` wins. The slot
46
+ * box is `--uxm-list-item-media-size` (36px) square; a `Thumbnail` or
47
+ * `Avatar` gets that size forwarded into its own size var (see
48
+ * `LIST_ITEM_MEDIA_STYLE`) and anything else is stretched to fill, so
49
+ * rows stay on one leading grid either way.
50
+ *
51
+ * Prefer decorative media in a row whose title already names the thing
52
+ * (`alt=""`): the slot sits INSIDE the row's `<button>`/`<a>`, so a
53
+ * described image is concatenated into the row's accessible name.
54
+ *
55
+ * Note: this shadows the native `media` attribute of `<a>` for the
56
+ * anchor form of the row — pass it through `className`/a wrapper if
57
+ * you genuinely need the HTML attribute. */
58
+ media?: ReactNode;
28
59
  /** Secondary text shown under the title (e.g. a value). */
29
60
  value?: ReactNode;
30
61
  /** Trailing content — meta text, chevron icon, or a custom node. */
@@ -49,6 +80,6 @@ export interface ListItemProps {
49
80
  type AnchorRest = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof ListItemProps>;
50
81
  type ButtonRest = Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof ListItemProps>;
51
82
  type DivRest = Omit<HTMLAttributes<HTMLDivElement>, keyof ListItemProps>;
52
- export declare function ListItem({ icon, value, trailing, children, interactive, active, disabled, href, className, ...rest }: ListItemProps & (AnchorRest | ButtonRest | DivRest)): import("react").JSX.Element;
83
+ export declare function ListItem({ icon, media, value, trailing, children, interactive, active, disabled, href, className, ...rest }: ListItemProps & (AnchorRest | ButtonRest | DivRest)): import("react").JSX.Element;
53
84
  export {};
54
85
  //# sourceMappingURL=list.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/ui/list/list.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAC;AAEf;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,EAMjC,aAAa,CAAC;AAEnB,MAAM,WAAW,SAAU,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC/D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAM/D;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,qBAAqB;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB;;0DAEsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;sEACkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;yCAEqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,UAAU,GAAG,IAAI,CACpB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,aAAa,CACpB,CAAC;AACF,KAAK,UAAU,GAAG,IAAI,CACpB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,aAAa,CACpB,CAAC;AACF,KAAK,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,aAAa,CAAC,CAAC;AAEzE,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACR,EAAE,aAAa,GAAG,CAAC,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,+BA0DrD"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/ui/list/list.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAC;AAEf;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,EAMjC,aAAa,CAAC;AAEnB;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,EAI7B,aAAa,CAAC;AAEnB,MAAM,WAAW,SAAU,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC/D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EAAE,SAAS,+BAM/D;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;iDAc6C;IAC7C,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,qBAAqB;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB;;0DAEsD;IACtD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;sEACkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;yCAEqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,UAAU,GAAG,IAAI,CACpB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,aAAa,CACpB,CAAC;AACF,KAAK,UAAU,GAAG,IAAI,CACpB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,aAAa,CACpB,CAAC;AACF,KAAK,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,MAAM,aAAa,CAAC,CAAC;AAEzE,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,SAAS,EACT,GAAG,IAAI,EACR,EAAE,aAAa,GAAG,CAAC,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,+BAoErD"}
@@ -8,11 +8,17 @@ const LIST_ITEM_ICON_TILE_STYLE = {
8
8
  "--uxm-icon-tile-radius": "var(--uxm-list-item-icon-radius, 6px)",
9
9
  "--uxm-icon-tile-icon-size": "calc(var(--uxm-list-item-icon-size, 24px) * 0.6)"
10
10
  };
11
+ const LIST_ITEM_MEDIA_STYLE = {
12
+ "--uxm-thumbnail-size": "var(--uxm-list-item-media-size, 36px)",
13
+ "--uxm-avatar-size": "var(--uxm-list-item-media-size, 36px)",
14
+ "--uxm-avatar-small-size": "var(--uxm-list-item-media-size, 36px)"
15
+ };
11
16
  function List({ children, className, ...rest }) {
12
17
  return /* @__PURE__ */ jsx("div", { className: cn("uxm-list", className), ...rest, children });
13
18
  }
14
19
  function ListItem({
15
20
  icon,
21
+ media,
16
22
  value,
17
23
  trailing,
18
24
  children,
@@ -30,7 +36,7 @@ function ListItem({
30
36
  );
31
37
  const isInteractive = interactive || href !== void 0;
32
38
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
33
- icon && /* @__PURE__ */ jsx(IconTile, { className: "uxm-list-item__icon", style: LIST_ITEM_ICON_TILE_STYLE, children: icon }),
39
+ media ? /* @__PURE__ */ jsx("span", { className: "uxm-list-item__media", style: LIST_ITEM_MEDIA_STYLE, children: media }) : icon && /* @__PURE__ */ jsx(IconTile, { className: "uxm-list-item__icon", style: LIST_ITEM_ICON_TILE_STYLE, children: icon }),
34
40
  /* @__PURE__ */ jsxs("span", { className: "uxm-list-item__content", children: [
35
41
  /* @__PURE__ */ jsx("span", { className: "uxm-list-item__title", children }),
36
42
  value !== void 0 && value !== null && /* @__PURE__ */ jsx("span", { className: "uxm-list-item__value", children: value })
@@ -74,6 +80,7 @@ function ListItem({
74
80
  }
75
81
  export {
76
82
  LIST_ITEM_ICON_TILE_STYLE,
83
+ LIST_ITEM_MEDIA_STYLE,
77
84
  List,
78
85
  ListItem
79
86
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/list/list.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport { IconTile } from '../icon-tile';\n\nimport type {\n AnchorHTMLAttributes,\n ButtonHTMLAttributes,\n CSSProperties,\n HTMLAttributes,\n ReactNode,\n} from 'react';\n\n/**\n * Forward the studio icon knobs (projected as `--uxm-list-item-icon-*` on the\n * row) into the `IconTile` atom's own var namespace, so the accent-tile\n * pattern lives in one place — the `IconTile` atom — instead of being\n * re-implemented in `list.scss`. The glyph tracks the tile at 0.6× (the\n * row-icon proportion used across the design system). Kept as a module\n * constant so the studio preview can reuse the exact same forwarding.\n */\nexport const LIST_ITEM_ICON_TILE_STYLE = {\n '--uxm-icon-tile-bg': 'var(--uxm-list-item-icon-bg, var(--color-accent))',\n '--uxm-icon-tile-color': 'var(--uxm-list-item-icon-color, var(--color-card))',\n '--uxm-icon-tile-size': 'var(--uxm-list-item-icon-size, 24px)',\n '--uxm-icon-tile-radius': 'var(--uxm-list-item-icon-radius, 6px)',\n '--uxm-icon-tile-icon-size': 'calc(var(--uxm-list-item-icon-size, 24px) * 0.6)',\n} as CSSProperties;\n\nexport interface ListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n}\n\nexport function List({ children, className, ...rest }: ListProps) {\n return (\n <div className={cn('uxm-list', className)} {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * ListItem renders as one of three element types depending on `interactive`:\n * - `<div>` (default) — display row, no state styling, not focusable\n * - `<button>` — interactive without navigation; emits click events\n * - `<a>` — interactive with navigation; pass `href`\n *\n * The state knobs (hover / focus / active / disabled) in the `list-item`\n * registry only paint when the row renders as button or anchor — the CSS\n * scopes them to element-type selectors so display-only divs stay inert.\n */\nexport interface ListItemProps {\n /** Leading icon — typically <Icon ... /> from @modo/uxm/ui. */\n icon?: ReactNode;\n /** Secondary text shown under the title (e.g. a value). */\n value?: ReactNode;\n /** Trailing content — meta text, chevron icon, or a custom node. */\n trailing?: ReactNode;\n /** Primary label. */\n children: ReactNode;\n /** Render as a clickable element. When false (default), renders as a\n * static `<div>` with no state styling. When true, renders as\n * `<button>` (or `<a>` if `href` is also passed). */\n interactive?: boolean;\n /** Show the selected/active treatment (only meaningful when\n * `interactive` is true). Adds the `--active` modifier class. */\n active?: boolean;\n /** Disable interaction — only meaningful when `interactive`.\n * Forwards to the native `disabled` attribute on `<button>`, or\n * sets `aria-disabled` on `<a>`. */\n disabled?: boolean;\n /** Navigate to this URL on click. Implies `interactive`. */\n href?: string;\n className?: string;\n}\n\ntype AnchorRest = Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ListItemProps\n>;\ntype ButtonRest = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ListItemProps\n>;\ntype DivRest = Omit<HTMLAttributes<HTMLDivElement>, keyof ListItemProps>;\n\nexport function ListItem({\n icon,\n value,\n trailing,\n children,\n interactive,\n active,\n disabled,\n href,\n className,\n ...rest\n}: ListItemProps & (AnchorRest | ButtonRest | DivRest)) {\n const classes = cn(\n 'uxm-list-item',\n active && 'uxm-list-item--active',\n className,\n );\n const isInteractive = interactive || href !== undefined;\n const inner = (\n <>\n {icon && (\n <IconTile className=\"uxm-list-item__icon\" style={LIST_ITEM_ICON_TILE_STYLE}>\n {icon}\n </IconTile>\n )}\n <span className=\"uxm-list-item__content\">\n <span className=\"uxm-list-item__title\">{children}</span>\n {value !== undefined && value !== null && (\n <span className=\"uxm-list-item__value\">{value}</span>\n )}\n </span>\n {trailing && <span className=\"uxm-list-item__trailing\">{trailing}</span>}\n </>\n );\n\n if (href !== undefined) {\n return (\n <a\n href={href}\n className={classes}\n {...(disabled ? { 'aria-disabled': true as const, tabIndex: -1 } : {})}\n {...(rest as AnchorRest)}\n >\n {inner}\n </a>\n );\n }\n if (isInteractive) {\n return (\n <button\n type=\"button\"\n className={classes}\n disabled={disabled}\n aria-pressed={active}\n {...(rest as ButtonRest)}\n >\n {inner}\n </button>\n );\n }\n return (\n <div\n className={classes}\n {...(disabled ? { 'aria-disabled': true as const } : {})}\n {...(rest as DivRest)}\n >\n {inner}\n </div>\n );\n}\n"],"mappings":"AAkCI,SAsEA,UAtEA,KA4EE,YA5EF;AAlCJ,SAAS,UAAU;AAEnB,SAAS,gBAAgB;AAkBlB,MAAM,4BAA4B;AAAA,EACvC,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,6BAA6B;AAC/B;AAMO,SAAS,KAAK,EAAE,UAAU,WAAW,GAAG,KAAK,GAAc;AAChE,SACE,oBAAC,SAAI,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,MAC5C,UACH;AAEJ;AA+CO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,QAAM,UAAU;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACA,QAAM,gBAAgB,eAAe,SAAS;AAC9C,QAAM,QACJ,iCACG;AAAA,YACC,oBAAC,YAAS,WAAU,uBAAsB,OAAO,2BAC9C,gBACH;AAAA,IAEF,qBAAC,UAAK,WAAU,0BACd;AAAA,0BAAC,UAAK,WAAU,wBAAwB,UAAS;AAAA,MAChD,UAAU,UAAa,UAAU,QAChC,oBAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,OAElD;AAAA,IACC,YAAY,oBAAC,UAAK,WAAU,2BAA2B,oBAAS;AAAA,KACnE;AAGF,MAAI,SAAS,QAAW;AACtB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,QACV,GAAI,WAAW,EAAE,iBAAiB,MAAe,UAAU,GAAG,IAAI,CAAC;AAAA,QACnE,GAAI;AAAA,QAEJ;AAAA;AAAA,IACH;AAAA,EAEJ;AACA,MAAI,eAAe;AACjB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW;AAAA,QACX;AAAA,QACA,gBAAc;AAAA,QACb,GAAI;AAAA,QAEJ;AAAA;AAAA,IACH;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,MACV,GAAI,WAAW,EAAE,iBAAiB,KAAc,IAAI,CAAC;AAAA,MACrD,GAAI;AAAA,MAEJ;AAAA;AAAA,EACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/list/list.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport { IconTile } from '../icon-tile';\n\nimport type {\n AnchorHTMLAttributes,\n ButtonHTMLAttributes,\n CSSProperties,\n HTMLAttributes,\n ReactNode,\n} from 'react';\n\n/**\n * Forward the studio icon knobs (projected as `--uxm-list-item-icon-*` on the\n * row) into the `IconTile` atom's own var namespace, so the accent-tile\n * pattern lives in one place — the `IconTile` atom — instead of being\n * re-implemented in `list.scss`. The glyph tracks the tile at 0.6× (the\n * row-icon proportion used across the design system). Kept as a module\n * constant so the studio preview can reuse the exact same forwarding.\n */\nexport const LIST_ITEM_ICON_TILE_STYLE = {\n '--uxm-icon-tile-bg': 'var(--uxm-list-item-icon-bg, var(--color-accent))',\n '--uxm-icon-tile-color': 'var(--uxm-list-item-icon-color, var(--color-card))',\n '--uxm-icon-tile-size': 'var(--uxm-list-item-icon-size, 24px)',\n '--uxm-icon-tile-radius': 'var(--uxm-list-item-icon-radius, 6px)',\n '--uxm-icon-tile-icon-size': 'calc(var(--uxm-list-item-icon-size, 24px) * 0.6)',\n} as CSSProperties;\n\n/**\n * Forward the row's media-size knob into the size vars of the atoms that\n * plausibly fill the `media` slot, so each one sizes itself through its OWN\n * machinery — frame, border, radius and inner glyph / initials all scale with\n * it — instead of being stretched from the outside. Mirrors\n * `LIST_ITEM_ICON_TILE_STYLE` above, and is the only order-independent fix:\n * both `Thumbnail` (`.uxm-thumbnail`, 0,1,0 but imported AFTER list in\n * `styles.css`) and `Avatar` (double-class size presets at 0,2,0, deliberately\n * so per its own note) would otherwise win or lose the cascade against a slot\n * rule purely on stylesheet order. The generic `> *` stretch in `list.scss`\n * stays as the fallback for a bare `<img>` / `<svg>` or any atom with no size\n * var of its own; both mechanisms resolve to the same number. Kept as a module\n * constant so the studio preview can reuse the exact same forwarding.\n */\nexport const LIST_ITEM_MEDIA_STYLE = {\n '--uxm-thumbnail-size': 'var(--uxm-list-item-media-size, 36px)',\n '--uxm-avatar-size': 'var(--uxm-list-item-media-size, 36px)',\n '--uxm-avatar-small-size': 'var(--uxm-list-item-media-size, 36px)',\n} as CSSProperties;\n\nexport interface ListProps extends HTMLAttributes<HTMLDivElement> {\n children: ReactNode;\n}\n\nexport function List({ children, className, ...rest }: ListProps) {\n return (\n <div className={cn('uxm-list', className)} {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * ListItem renders as one of three element types depending on `interactive`:\n * - `<div>` (default) — display row, no state styling, not focusable\n * - `<button>` — interactive without navigation; emits click events\n * - `<a>` — interactive with navigation; pass `href`\n *\n * The state knobs (hover / focus / active / disabled) in the `list-item`\n * registry only paint when the row renders as button or anchor — the CSS\n * scopes them to element-type selectors so display-only divs stay inert.\n */\nexport interface ListItemProps {\n /** Leading icon — typically <Icon ... /> from @modo/uxm/ui. */\n icon?: ReactNode;\n /** Leading media rendered as-is (a <Thumbnail>, <img>, avatar…) — NOT\n * wrapped in the accent `IconTile` the `icon` slot uses. Mutually\n * exclusive with `icon`: when both are passed, `media` wins. The slot\n * box is `--uxm-list-item-media-size` (36px) square; a `Thumbnail` or\n * `Avatar` gets that size forwarded into its own size var (see\n * `LIST_ITEM_MEDIA_STYLE`) and anything else is stretched to fill, so\n * rows stay on one leading grid either way.\n *\n * Prefer decorative media in a row whose title already names the thing\n * (`alt=\"\"`): the slot sits INSIDE the row's `<button>`/`<a>`, so a\n * described image is concatenated into the row's accessible name.\n *\n * Note: this shadows the native `media` attribute of `<a>` for the\n * anchor form of the row — pass it through `className`/a wrapper if\n * you genuinely need the HTML attribute. */\n media?: ReactNode;\n /** Secondary text shown under the title (e.g. a value). */\n value?: ReactNode;\n /** Trailing content — meta text, chevron icon, or a custom node. */\n trailing?: ReactNode;\n /** Primary label. */\n children: ReactNode;\n /** Render as a clickable element. When false (default), renders as a\n * static `<div>` with no state styling. When true, renders as\n * `<button>` (or `<a>` if `href` is also passed). */\n interactive?: boolean;\n /** Show the selected/active treatment (only meaningful when\n * `interactive` is true). Adds the `--active` modifier class. */\n active?: boolean;\n /** Disable interaction — only meaningful when `interactive`.\n * Forwards to the native `disabled` attribute on `<button>`, or\n * sets `aria-disabled` on `<a>`. */\n disabled?: boolean;\n /** Navigate to this URL on click. Implies `interactive`. */\n href?: string;\n className?: string;\n}\n\ntype AnchorRest = Omit<\n AnchorHTMLAttributes<HTMLAnchorElement>,\n keyof ListItemProps\n>;\ntype ButtonRest = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof ListItemProps\n>;\ntype DivRest = Omit<HTMLAttributes<HTMLDivElement>, keyof ListItemProps>;\n\nexport function ListItem({\n icon,\n media,\n value,\n trailing,\n children,\n interactive,\n active,\n disabled,\n href,\n className,\n ...rest\n}: ListItemProps & (AnchorRest | ButtonRest | DivRest)) {\n const classes = cn(\n 'uxm-list-item',\n active && 'uxm-list-item--active',\n className,\n );\n const isInteractive = interactive || href !== undefined;\n const inner = (\n <>\n {/* Leading slot. `media` renders as-is so a product photo / avatar\n keeps its own frame; `icon` keeps the accent IconTile treatment.\n `media` wins when both are passed — a row has one leading grid\n position, and the as-is rendering is the more specific intent. */}\n {media ? (\n <span className=\"uxm-list-item__media\" style={LIST_ITEM_MEDIA_STYLE}>\n {media}\n </span>\n ) : (\n icon && (\n <IconTile className=\"uxm-list-item__icon\" style={LIST_ITEM_ICON_TILE_STYLE}>\n {icon}\n </IconTile>\n )\n )}\n <span className=\"uxm-list-item__content\">\n <span className=\"uxm-list-item__title\">{children}</span>\n {value !== undefined && value !== null && (\n <span className=\"uxm-list-item__value\">{value}</span>\n )}\n </span>\n {trailing && <span className=\"uxm-list-item__trailing\">{trailing}</span>}\n </>\n );\n\n if (href !== undefined) {\n return (\n <a\n href={href}\n className={classes}\n {...(disabled ? { 'aria-disabled': true as const, tabIndex: -1 } : {})}\n {...(rest as AnchorRest)}\n >\n {inner}\n </a>\n );\n }\n if (isInteractive) {\n return (\n <button\n type=\"button\"\n className={classes}\n disabled={disabled}\n aria-pressed={active}\n {...(rest as ButtonRest)}\n >\n {inner}\n </button>\n );\n }\n return (\n <div\n className={classes}\n {...(disabled ? { 'aria-disabled': true as const } : {})}\n {...(rest as DivRest)}\n >\n {inner}\n </div>\n );\n}\n"],"mappings":"AAsDI,SAuFA,UAvFA,KAuGE,YAvGF;AAtDJ,SAAS,UAAU;AAEnB,SAAS,gBAAgB;AAkBlB,MAAM,4BAA4B;AAAA,EACvC,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,6BAA6B;AAC/B;AAgBO,MAAM,wBAAwB;AAAA,EACnC,wBAAwB;AAAA,EACxB,qBAAqB;AAAA,EACrB,2BAA2B;AAC7B;AAMO,SAAS,KAAK,EAAE,UAAU,WAAW,GAAG,KAAK,GAAc;AAChE,SACE,oBAAC,SAAI,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,MAC5C,UACH;AAEJ;AA+DO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,QAAM,UAAU;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACA,QAAM,gBAAgB,eAAe,SAAS;AAC9C,QAAM,QACJ,iCAKG;AAAA,YACC,oBAAC,UAAK,WAAU,wBAAuB,OAAO,uBAC3C,iBACH,IAEA,QACE,oBAAC,YAAS,WAAU,uBAAsB,OAAO,2BAC9C,gBACH;AAAA,IAGJ,qBAAC,UAAK,WAAU,0BACd;AAAA,0BAAC,UAAK,WAAU,wBAAwB,UAAS;AAAA,MAChD,UAAU,UAAa,UAAU,QAChC,oBAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,OAElD;AAAA,IACC,YAAY,oBAAC,UAAK,WAAU,2BAA2B,oBAAS;AAAA,KACnE;AAGF,MAAI,SAAS,QAAW;AACtB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,QACV,GAAI,WAAW,EAAE,iBAAiB,MAAe,UAAU,GAAG,IAAI,CAAC;AAAA,QACnE,GAAI;AAAA,QAEJ;AAAA;AAAA,IACH;AAAA,EAEJ;AACA,MAAI,eAAe;AACjB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW;AAAA,QACX;AAAA,QACA,gBAAc;AAAA,QACb,GAAI;AAAA,QAEJ;AAAA;AAAA,IACH;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,MACV,GAAI,WAAW,EAAE,iBAAiB,KAAc,IAAI,CAAC;AAAA,MACrD,GAAI;AAAA,MAEJ;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── listbox ────────────────────────────────────────────────────────────────
3
2
  Generic dropdown surface — uses Popover as the panel positioning shell
4
3
  and layers chrome (panel, search, list, options, footer) on top.
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── loader ── */
3
2
  @keyframes uxm-loader-spin {
4
3
  to {
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── menu ─────────────────────────────────────────────────────────────────────
3
2
  Action / dropdown menu — a list of commands invoked from a consumer-owned
4
3
  trigger. The `.uxm-menu` wrapper lives in-page around the trigger; the
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── meta-row ── */
3
2
  .uxm-meta-row {
4
3
  align-items: center;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── modal ──────────────────────────────────────────────────────────────────
3
2
  Modal (surface — themable through UXM)
4
3
 
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* Number Input — typing-only numeric field. Same architectural shape
3
2
  as Text Input: the root `<input class="uxm-number-input">` IS the
4
3
  visible surface (no positioning wrapper), so the `--state-*` forced
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── NumberStepper ──
3
2
  Numeric input + explicit ± step buttons + optional unit suffix. The
4
3
  browser's native spinner is unconditionally suppressed so the
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── option-list ── */
3
2
  .uxm-option-list {
4
3
  background-color: var(--uxm-option-list-background, var(--color-surface));
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── page-header ── */
3
2
  /* PageHeader — defaults match the `page-header` registry entry. Each
4
3
  knob (titleColor, titleSize, metaColor, metaSize, iconBg, iconColor,
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── page-shell ── */
3
2
  .uxm-page-shell {
4
3
  background-color: var(--uxm-page-shell-bg, var(--color-surface));
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* Password Input — mirrors DateInput's inner-styled-atom shape. Root
3
2
  `.uxm-password-input` is a positioning wrapper; the visible field lives
4
3
  on `.uxm-password-input__input`. The trailing element is a real
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* Phone Input — leading country picker + national number text input.
3
2
  Layout: flag/dial-code button on the LEFT (the country is read first,
4
3
  left-to-right with the phone number that follows). Popover below opens
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  .uxm-pill-select {
3
2
  position: relative;
4
3
  width: 100%;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── popover ────────────────────────────────────────────────────────────────
3
2
  Bare positioned panel — no chrome of its own. Consumers (Listbox,
4
3
  PhoneInput country picker, future menus) layer their visual treatment
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── Progress Bar ──
3
2
  Determinate progress (linear track+fill or circular ring). The root is
4
3
  layout-only; every themeable property reads a `--uxm-progress-bar-*` custom
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── property-field ── */
3
2
  /* PropertyGrid — auto-fill grid wrapper. Owns row/column gap only;
4
3
  the field-shape knobs (label/value colour and size) live on the
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── radio-group ── */
3
2
  .uxm-radio {
4
3
  align-items: center;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── range-slider ── */
3
2
  /* ── RangeSlider ──
4
3
  Dual-thumb range. Two `<input type="range">` are absolutely positioned
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ResponsiveGrid — moved from monolithic styles.css */
3
2
  .uxm-responsive-grid {
4
3
  display: grid;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── SearchDropdown ──
3
2
  Combobox: trigger button + Listbox popover. SearchDropdown is a thin
4
3
  wrapper over the shared Listbox atom — Listbox owns the popover
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── section-header ── */
3
2
  /* ── SectionHeader ──
4
3
  Small uppercase label for grouping fields in dense settings panels.
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── segment-card ── */
3
2
  .uxm-segment-card {
4
3
  background-color: var(--uxm-segment-card-background, var(--color-card));
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── segment-row ── */
3
2
  .uxm-segment-row {
4
3
  align-items: stretch;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── side-flexpane ── */
3
2
  .uxm-side-flexpane {
4
3
  background-color: var(--uxm-side-flexpane-background-color, var(--color-card));
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── sidebar-nav-item ── */
3
2
  .uxm-sidebar-nav-item {
4
3
  align-items: center;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── sidebar-nav-trigger ──────────────────────────────────────────────────────
3
2
  A rail row that OPENS something rather than navigating to it. Sibling of
4
3
  `sidebar-nav-item`, deliberately not a variant of it: that one is an `<a>`
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── slider ── */
3
2
  /* ── Slider ──
4
3
  Native <input type="range"> with themable track + thumb. The track's
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* Stack — moved from monolithic styles.css */
3
2
  .uxm-stack {
4
3
  display: flex;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── stat-card ── */
3
2
  /* StatCard — root IS the visible card; bg/border/radius/padding land
4
3
  directly on root via REAL_CSS_PROPS. Inner __value/__label sizes and
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── tabs ── */
3
2
  /* Tabs (label + optional icon, splits the width between tabs) */
4
3
  .uxm-tabs {
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── tabs-underline ── */
3
2
  /* Tabs Underline (page-nav style — text labels with an animated bar under the active tab) */
4
3
  .uxm-tabs-underline {
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── tag ── */
3
2
  .uxm-tag {
4
3
  align-items: center;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── thumbnail ── */
3
2
  /* Thumbnail — bounded image frame. Root IS the visible frame: bg / border /
4
3
  radius / size land directly. `--uxm-thumbnail-size` drives both width and
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* Time Input — same inner-styled-atom shape as DateInput. Root
3
2
  `.uxm-time-input` is a positioning wrapper; the visible field is
4
3
  `.uxm-time-input__input`. In `data-format="12h"` mode an AM/PM <select>
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── timeline-entry ── */
3
2
  .uxm-timeline-entry {
4
3
  display: flex;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── toast ──────────────────────────────────────────────────────────────────
3
2
  Toaster mounts a positioned container that holds the toast stack.
4
3
  Position presets are layout-only; visual styling (background, border,
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── toggle-switch ── */
3
2
  .uxm-toggle-switch {
4
3
  align-items: center;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── tooltip ── */
3
2
  .uxm-tooltip {
4
3
  display: inline-block;
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── type-overview-card ── */
3
2
  /* TypeOverviewCard — registry knobs (bg, border, radius, padding,
4
3
  accent*, icon*, label*, value*) all wired via `--uxm-typeoverview-*`
@@ -1,4 +1,3 @@
1
- @charset "UTF-8";
2
1
  /* ── view-switcher ── */
3
2
  /* View Switcher (icon-only segmented) */
4
3
  .uxm-view-switcher {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viax.io/uxm",
3
- "version": "4.40.1",
3
+ "version": "4.41.0",
4
4
  "description": "Viax UXM — React 19 UI primitives and design tokens.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -69,6 +69,7 @@
69
69
  "check:drift": "node scripts/check-state-var-drift.mjs && npm run check:type-scale && npm run check:tokens",
70
70
  "test": "vitest run",
71
71
  "test:watch": "vitest",
72
+ "test:coverage": "vitest run --coverage",
72
73
  "test:ci": "vitest run --reporter=default --reporter=junit --outputFile=junit-report.xml",
73
74
  "audit:report": "npm audit --registry=https://registry.npmjs.org",
74
75
  "audit:ci": "npm audit --registry=https://registry.npmjs.org --audit-level=critical",
@@ -112,6 +113,7 @@
112
113
  "@types/react": "^19.0.0",
113
114
  "@types/react-dom": "^19.0.0",
114
115
  "@vitejs/plugin-react": "^6.1.1",
116
+ "@vitest/coverage-v8": "^5.0.0",
115
117
  "axe-core": "^4.13.0",
116
118
  "commitizen": "^4.3.1",
117
119
  "cz-conventional-changelog": "^3.3.0",