@viax.io/uxm 4.36.0 → 4.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +74 -31
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.ts +3 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/previews/index.cjs +3 -0
  7. package/dist/previews/index.cjs.map +1 -1
  8. package/dist/previews/index.d.ts +3 -2
  9. package/dist/previews/index.d.ts.map +1 -1
  10. package/dist/previews/index.js +2 -0
  11. package/dist/previews/index.js.map +1 -1
  12. package/dist/studio/index.cjs.map +1 -1
  13. package/dist/studio/index.d.ts +2 -2
  14. package/dist/studio/index.js.map +1 -1
  15. package/dist/studio/lib/registry/app.cjs +52 -0
  16. package/dist/studio/lib/registry/app.cjs.map +1 -1
  17. package/dist/studio/lib/registry/app.d.ts.map +1 -1
  18. package/dist/studio/lib/registry/app.js +52 -0
  19. package/dist/studio/lib/registry/app.js.map +1 -1
  20. package/dist/studio/lib/registry/buttons.cjs +2 -2
  21. package/dist/studio/lib/registry/buttons.cjs.map +1 -1
  22. package/dist/studio/lib/registry/buttons.js +2 -2
  23. package/dist/studio/lib/registry/buttons.js.map +1 -1
  24. package/dist/studio/lib/registry/composite.cjs +1 -1
  25. package/dist/studio/lib/registry/composite.cjs.map +1 -1
  26. package/dist/studio/lib/registry/composite.js +1 -1
  27. package/dist/studio/lib/registry/composite.js.map +1 -1
  28. package/dist/studio/lib/registry/diagram.cjs +1 -1
  29. package/dist/studio/lib/registry/diagram.cjs.map +1 -1
  30. package/dist/studio/lib/registry/diagram.js +1 -1
  31. package/dist/studio/lib/registry/diagram.js.map +1 -1
  32. package/dist/studio/lib/registry/display.cjs +2 -2
  33. package/dist/studio/lib/registry/display.cjs.map +1 -1
  34. package/dist/studio/lib/registry/display.js +2 -2
  35. package/dist/studio/lib/registry/display.js.map +1 -1
  36. package/dist/studio/lib/registry/feedback.cjs +3 -3
  37. package/dist/studio/lib/registry/feedback.cjs.map +1 -1
  38. package/dist/studio/lib/registry/feedback.js +3 -3
  39. package/dist/studio/lib/registry/feedback.js.map +1 -1
  40. package/dist/studio/lib/registry/inputs.cjs +12 -12
  41. package/dist/studio/lib/registry/inputs.cjs.map +1 -1
  42. package/dist/studio/lib/registry/inputs.js +12 -12
  43. package/dist/studio/lib/registry/inputs.js.map +1 -1
  44. package/dist/studio/lib/types.cjs.map +1 -1
  45. package/dist/studio/persistence/generate-css.cjs +15 -0
  46. package/dist/studio/persistence/generate-css.cjs.map +1 -1
  47. package/dist/studio/persistence/generate-css.d.ts.map +1 -1
  48. package/dist/studio/persistence/generate-css.js +15 -0
  49. package/dist/studio/persistence/generate-css.js.map +1 -1
  50. package/dist/studio/shell/canvas.cjs +1 -0
  51. package/dist/studio/shell/canvas.cjs.map +1 -1
  52. package/dist/studio/shell/canvas.d.ts.map +1 -1
  53. package/dist/studio/shell/canvas.js +2 -0
  54. package/dist/studio/shell/canvas.js.map +1 -1
  55. package/dist/ui/bulk-action-bar/bulk-action-bar.css +3 -0
  56. package/dist/ui/calendar/calendar.cjs +3 -1
  57. package/dist/ui/calendar/calendar.cjs.map +1 -1
  58. package/dist/ui/calendar/calendar.css +2 -1
  59. package/dist/ui/calendar/calendar.d.ts +6 -2
  60. package/dist/ui/calendar/calendar.d.ts.map +1 -1
  61. package/dist/ui/calendar/calendar.js +3 -1
  62. package/dist/ui/calendar/calendar.js.map +1 -1
  63. package/dist/ui/currency-input/currency-input.cjs +3 -1
  64. package/dist/ui/currency-input/currency-input.cjs.map +1 -1
  65. package/dist/ui/currency-input/currency-input.d.ts +4 -2
  66. package/dist/ui/currency-input/currency-input.d.ts.map +1 -1
  67. package/dist/ui/currency-input/currency-input.js +3 -1
  68. package/dist/ui/currency-input/currency-input.js.map +1 -1
  69. package/dist/ui/date-input/date-input.cjs +2 -1
  70. package/dist/ui/date-input/date-input.cjs.map +1 -1
  71. package/dist/ui/date-input/date-input.css +1 -1
  72. package/dist/ui/date-input/date-input.d.ts +11 -1
  73. package/dist/ui/date-input/date-input.d.ts.map +1 -1
  74. package/dist/ui/date-input/date-input.js +2 -1
  75. package/dist/ui/date-input/date-input.js.map +1 -1
  76. package/dist/ui/editable-cell/editable-cell.cjs +20 -6
  77. package/dist/ui/editable-cell/editable-cell.cjs.map +1 -1
  78. package/dist/ui/editable-cell/editable-cell.d.ts +24 -1
  79. package/dist/ui/editable-cell/editable-cell.d.ts.map +1 -1
  80. package/dist/ui/editable-cell/editable-cell.js +20 -6
  81. package/dist/ui/editable-cell/editable-cell.js.map +1 -1
  82. package/dist/ui/file-upload/file-upload.cjs +36 -9
  83. package/dist/ui/file-upload/file-upload.cjs.map +1 -1
  84. package/dist/ui/file-upload/file-upload.d.ts +46 -4
  85. package/dist/ui/file-upload/file-upload.d.ts.map +1 -1
  86. package/dist/ui/file-upload/file-upload.js +36 -9
  87. package/dist/ui/file-upload/file-upload.js.map +1 -1
  88. package/dist/ui/index.cjs +12 -2
  89. package/dist/ui/index.cjs.map +1 -1
  90. package/dist/ui/index.d.ts +5 -1
  91. package/dist/ui/index.d.ts.map +1 -1
  92. package/dist/ui/index.js +7 -1
  93. package/dist/ui/index.js.map +1 -1
  94. package/dist/ui/input/input.cjs +8 -4
  95. package/dist/ui/input/input.cjs.map +1 -1
  96. package/dist/ui/input/input.css +4 -0
  97. package/dist/ui/input/input.d.ts.map +1 -1
  98. package/dist/ui/input/input.js +8 -4
  99. package/dist/ui/input/input.js.map +1 -1
  100. package/dist/ui/language-switcher/index.cjs +29 -0
  101. package/dist/ui/language-switcher/index.cjs.map +1 -0
  102. package/dist/ui/language-switcher/index.d.ts +3 -0
  103. package/dist/ui/language-switcher/index.d.ts.map +1 -0
  104. package/dist/ui/language-switcher/index.js +5 -0
  105. package/dist/ui/language-switcher/index.js.map +1 -0
  106. package/dist/ui/language-switcher/language-switcher-preview.cjs +137 -0
  107. package/dist/ui/language-switcher/language-switcher-preview.cjs.map +1 -0
  108. package/dist/ui/language-switcher/language-switcher-preview.d.ts +3 -0
  109. package/dist/ui/language-switcher/language-switcher-preview.d.ts.map +1 -0
  110. package/dist/ui/language-switcher/language-switcher-preview.js +113 -0
  111. package/dist/ui/language-switcher/language-switcher-preview.js.map +1 -0
  112. package/dist/ui/language-switcher/language-switcher.cjs +127 -0
  113. package/dist/ui/language-switcher/language-switcher.cjs.map +1 -0
  114. package/dist/ui/language-switcher/language-switcher.css +95 -0
  115. package/dist/ui/language-switcher/language-switcher.d.ts +73 -0
  116. package/dist/ui/language-switcher/language-switcher.d.ts.map +1 -0
  117. package/dist/ui/language-switcher/language-switcher.js +103 -0
  118. package/dist/ui/language-switcher/language-switcher.js.map +1 -0
  119. package/dist/ui/locale/index.cjs +33 -0
  120. package/dist/ui/locale/index.cjs.map +1 -0
  121. package/dist/ui/locale/index.d.ts +3 -0
  122. package/dist/ui/locale/index.d.ts.map +1 -0
  123. package/dist/ui/locale/index.js +7 -0
  124. package/dist/ui/locale/index.js.map +1 -0
  125. package/dist/ui/locale/locale.cjs +43 -0
  126. package/dist/ui/locale/locale.cjs.map +1 -0
  127. package/dist/ui/locale/locale.d.ts +49 -0
  128. package/dist/ui/locale/locale.d.ts.map +1 -0
  129. package/dist/ui/locale/locale.js +17 -0
  130. package/dist/ui/locale/locale.js.map +1 -0
  131. package/dist/ui/page-shell/page-shell.cjs.map +1 -1
  132. package/dist/ui/page-shell/page-shell.d.ts +1 -1
  133. package/dist/ui/page-shell/page-shell.d.ts.map +1 -1
  134. package/dist/ui/page-shell/page-shell.js.map +1 -1
  135. package/dist/ui/range-slider/range-slider.cjs +7 -3
  136. package/dist/ui/range-slider/range-slider.cjs.map +1 -1
  137. package/dist/ui/range-slider/range-slider.d.ts +17 -1
  138. package/dist/ui/range-slider/range-slider.d.ts.map +1 -1
  139. package/dist/ui/range-slider/range-slider.js +7 -3
  140. package/dist/ui/range-slider/range-slider.js.map +1 -1
  141. package/dist/ui/stat-card/stat-card.cjs +1 -1
  142. package/dist/ui/stat-card/stat-card.cjs.map +1 -1
  143. package/dist/ui/stat-card/stat-card.css +4 -0
  144. package/dist/ui/stat-card/stat-card.js +1 -1
  145. package/dist/ui/stat-card/stat-card.js.map +1 -1
  146. package/dist/ui/styles.css +2 -1
  147. package/dist/ui/toast/toast.css +3 -1
  148. package/package.json +4 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/page-shell/page-shell.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type PageShellVariant = 'standard' | 'canvas';\n\nexport interface PageShellProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Layout variant — controls the content area only. The sidebar and top bar\n * always render whatever you pass.\n *\n * - `standard`: padded, scrollable content area for normal product pages.\n * - `canvas`: full-bleed, non-scrolling content area for diagram surfaces\n * and lifecycle modelers. Pass a lighter context-specific top bar\n * (Back + title + diagram actions) instead of the full AppTopBar.\n */\n variant?: PageShellVariant;\n /** Left navigation. Typically <AppSidebar /> from @viax.io/uxm/ui. */\n sidebar?: ReactNode;\n /** Top header — anything you want, or omit/null to render no header. */\n topBar?: ReactNode;\n /** Page content. */\n children: ReactNode;\n}\n\nexport function PageShell({\n variant = 'standard',\n sidebar,\n topBar,\n children,\n className,\n ...rest\n}: PageShellProps) {\n return (\n <div className={cn('uxm-page-shell', `uxm-page-shell--${variant}`, className)} {...rest}>\n {sidebar && <div className=\"uxm-page-shell__sidebar\">{sidebar}</div>}\n <div className=\"uxm-page-shell__body\">\n {topBar && <div className=\"uxm-page-shell__top-bar\">{topBar}</div>}\n <main className=\"uxm-page-shell__content\">{children}</main>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCkB;AAnClB,qBAAmB;AAyBZ,SAAS,UAAU;AAAA,EACxB,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,SACE,6CAAC,SAAI,eAAW,mBAAG,kBAAkB,mBAAmB,OAAO,IAAI,SAAS,GAAI,GAAG,MAChF;AAAA,eAAW,4CAAC,SAAI,WAAU,2BAA2B,mBAAQ;AAAA,IAC9D,6CAAC,SAAI,WAAU,wBACZ;AAAA,gBAAU,4CAAC,SAAI,WAAU,2BAA2B,kBAAO;AAAA,MAC5D,4CAAC,UAAK,WAAU,2BAA2B,UAAS;AAAA,OACtD;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/page-shell/page-shell.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type PageShellVariant = 'standard' | 'canvas';\n\nexport interface PageShellProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Layout variant — controls the content area only. The sidebar and top bar\n * always render whatever you pass.\n *\n * - `standard`: padded, scrollable content area for normal product pages.\n * - `canvas`: full-bleed, non-scrolling content area for diagram surfaces\n * and lifecycle modelers. Pass a lighter context-specific top bar\n * (Back + title + diagram actions) instead of the full AppTopBar.\n */\n variant?: PageShellVariant;\n /** Left navigation. Typically <AppSidebar /> from @viax/uxm/ui. */\n sidebar?: ReactNode;\n /** Top header — anything you want, or omit/null to render no header. */\n topBar?: ReactNode;\n /** Page content. */\n children: ReactNode;\n}\n\nexport function PageShell({\n variant = 'standard',\n sidebar,\n topBar,\n children,\n className,\n ...rest\n}: PageShellProps) {\n return (\n <div className={cn('uxm-page-shell', `uxm-page-shell--${variant}`, className)} {...rest}>\n {sidebar && <div className=\"uxm-page-shell__sidebar\">{sidebar}</div>}\n <div className=\"uxm-page-shell__body\">\n {topBar && <div className=\"uxm-page-shell__top-bar\">{topBar}</div>}\n <main className=\"uxm-page-shell__content\">{children}</main>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmCkB;AAnClB,qBAAmB;AAyBZ,SAAS,UAAU;AAAA,EACxB,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,SACE,6CAAC,SAAI,eAAW,mBAAG,kBAAkB,mBAAmB,OAAO,IAAI,SAAS,GAAI,GAAG,MAChF;AAAA,eAAW,4CAAC,SAAI,WAAU,2BAA2B,mBAAQ;AAAA,IAC9D,6CAAC,SAAI,WAAU,wBACZ;AAAA,gBAAU,4CAAC,SAAI,WAAU,2BAA2B,kBAAO;AAAA,MAC5D,4CAAC,UAAK,WAAU,2BAA2B,UAAS;AAAA,OACtD;AAAA,KACF;AAEJ;","names":[]}
@@ -11,7 +11,7 @@ export interface PageShellProps extends HTMLAttributes<HTMLDivElement> {
11
11
  * (Back + title + diagram actions) instead of the full AppTopBar.
12
12
  */
13
13
  variant?: PageShellVariant;
14
- /** Left navigation. Typically <AppSidebar /> from @viax.io/uxm/ui. */
14
+ /** Left navigation. Typically <AppSidebar /> from @viax/uxm/ui. */
15
15
  sidebar?: ReactNode;
16
16
  /** Top header — anything you want, or omit/null to render no header. */
17
17
  topBar?: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"page-shell.d.ts","sourceRoot":"","sources":["../../../src/ui/page-shell/page-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,cAAc,CAAC;IACpE;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,sEAAsE;IACtE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAoB,EACpB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,2CAUhB"}
1
+ {"version":3,"file":"page-shell.d.ts","sourceRoot":"","sources":["../../../src/ui/page-shell/page-shell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,cAAe,SAAQ,cAAc,CAAC,cAAc,CAAC;IACpE;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,mEAAmE;IACnE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAoB,EACpB,OAAO,EACP,MAAM,EACN,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,2CAUhB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/page-shell/page-shell.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type PageShellVariant = 'standard' | 'canvas';\n\nexport interface PageShellProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Layout variant — controls the content area only. The sidebar and top bar\n * always render whatever you pass.\n *\n * - `standard`: padded, scrollable content area for normal product pages.\n * - `canvas`: full-bleed, non-scrolling content area for diagram surfaces\n * and lifecycle modelers. Pass a lighter context-specific top bar\n * (Back + title + diagram actions) instead of the full AppTopBar.\n */\n variant?: PageShellVariant;\n /** Left navigation. Typically <AppSidebar /> from @viax.io/uxm/ui. */\n sidebar?: ReactNode;\n /** Top header — anything you want, or omit/null to render no header. */\n topBar?: ReactNode;\n /** Page content. */\n children: ReactNode;\n}\n\nexport function PageShell({\n variant = 'standard',\n sidebar,\n topBar,\n children,\n className,\n ...rest\n}: PageShellProps) {\n return (\n <div className={cn('uxm-page-shell', `uxm-page-shell--${variant}`, className)} {...rest}>\n {sidebar && <div className=\"uxm-page-shell__sidebar\">{sidebar}</div>}\n <div className=\"uxm-page-shell__body\">\n {topBar && <div className=\"uxm-page-shell__top-bar\">{topBar}</div>}\n <main className=\"uxm-page-shell__content\">{children}</main>\n </div>\n </div>\n );\n}\n"],"mappings":"AAmCkB,cACZ,YADY;AAnClB,SAAS,UAAU;AAyBZ,SAAS,UAAU;AAAA,EACxB,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,SACE,qBAAC,SAAI,WAAW,GAAG,kBAAkB,mBAAmB,OAAO,IAAI,SAAS,GAAI,GAAG,MAChF;AAAA,eAAW,oBAAC,SAAI,WAAU,2BAA2B,mBAAQ;AAAA,IAC9D,qBAAC,SAAI,WAAU,wBACZ;AAAA,gBAAU,oBAAC,SAAI,WAAU,2BAA2B,kBAAO;AAAA,MAC5D,oBAAC,UAAK,WAAU,2BAA2B,UAAS;AAAA,OACtD;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/page-shell/page-shell.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type PageShellVariant = 'standard' | 'canvas';\n\nexport interface PageShellProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Layout variant — controls the content area only. The sidebar and top bar\n * always render whatever you pass.\n *\n * - `standard`: padded, scrollable content area for normal product pages.\n * - `canvas`: full-bleed, non-scrolling content area for diagram surfaces\n * and lifecycle modelers. Pass a lighter context-specific top bar\n * (Back + title + diagram actions) instead of the full AppTopBar.\n */\n variant?: PageShellVariant;\n /** Left navigation. Typically <AppSidebar /> from @viax/uxm/ui. */\n sidebar?: ReactNode;\n /** Top header — anything you want, or omit/null to render no header. */\n topBar?: ReactNode;\n /** Page content. */\n children: ReactNode;\n}\n\nexport function PageShell({\n variant = 'standard',\n sidebar,\n topBar,\n children,\n className,\n ...rest\n}: PageShellProps) {\n return (\n <div className={cn('uxm-page-shell', `uxm-page-shell--${variant}`, className)} {...rest}>\n {sidebar && <div className=\"uxm-page-shell__sidebar\">{sidebar}</div>}\n <div className=\"uxm-page-shell__body\">\n {topBar && <div className=\"uxm-page-shell__top-bar\">{topBar}</div>}\n <main className=\"uxm-page-shell__content\">{children}</main>\n </div>\n </div>\n );\n}\n"],"mappings":"AAmCkB,cACZ,YADY;AAnClB,SAAS,UAAU;AAyBZ,SAAS,UAAU;AAAA,EACxB,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,SACE,qBAAC,SAAI,WAAW,GAAG,kBAAkB,mBAAmB,OAAO,IAAI,SAAS,GAAI,GAAG,MAChF;AAAA,eAAW,oBAAC,SAAI,WAAU,2BAA2B,mBAAQ;AAAA,IAC9D,qBAAC,SAAI,WAAU,wBACZ;AAAA,gBAAU,oBAAC,SAAI,WAAU,2BAA2B,kBAAO;AAAA,MAC5D,oBAAC,UAAK,WAAU,2BAA2B,UAAS;AAAA,OACtD;AAAA,KACF;AAEJ;","names":[]}
@@ -36,7 +36,9 @@ function RangeSlider({
36
36
  unit,
37
37
  className,
38
38
  style,
39
- "aria-label": ariaLabel
39
+ "aria-label": ariaLabel,
40
+ startLabel,
41
+ endLabel
40
42
  }) {
41
43
  const [start, end] = value;
42
44
  const range = max - min;
@@ -54,6 +56,8 @@ function RangeSlider({
54
56
  ["--uxm-range-slider-end"]: `${endPct}%`
55
57
  };
56
58
  const showAnyValues = showStart || showEnd || showRange;
59
+ const resolvedStartLabel = startLabel ?? (ariaLabel ? `${ariaLabel} (start)` : "Range start");
60
+ const resolvedEndLabel = endLabel ?? (ariaLabel ? `${ariaLabel} (end)` : "Range end");
57
61
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: (0, import_helpers.cn)("uxm-range-slider", className), style: mergedStyle, children: [
58
62
  showAnyValues && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "uxm-range-slider__values", children: [
59
63
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "uxm-range-slider__value uxm-range-slider__value--start", children: showStart ? `${start}${unit ?? ""}` : "" }),
@@ -72,7 +76,7 @@ function RangeSlider({
72
76
  step,
73
77
  disabled,
74
78
  onChange: (e) => handleStart(Number(e.target.value)),
75
- "aria-label": ariaLabel ? `${ariaLabel} (start)` : "Range start"
79
+ "aria-label": resolvedStartLabel
76
80
  }
77
81
  ),
78
82
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -86,7 +90,7 @@ function RangeSlider({
86
90
  step,
87
91
  disabled,
88
92
  onChange: (e) => handleEnd(Number(e.target.value)),
89
- "aria-label": ariaLabel ? `${ariaLabel} (end)` : "Range end"
93
+ "aria-label": resolvedEndLabel
90
94
  }
91
95
  )
92
96
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/range-slider/range-slider.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { CSSProperties } from 'react';\n\nexport interface RangeSliderProps {\n /** [start, end] — start ≤ end always (the atom clamps on drag). */\n value: [number, number];\n onChange: (value: [number, number]) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Disable both thumbs and dim the wrapper via the shared --uxm-slider-disabled-opacity var. */\n disabled?: boolean;\n /** Show the start thumb's value above the slider (left-aligned). */\n showStart?: boolean;\n /** Show the end thumb's value above the slider (right-aligned). */\n showEnd?: boolean;\n /** Show the range (end − start) above the slider (centred). */\n showRange?: boolean;\n /** Optional unit shown alongside displayed values (e.g. \"px\"). */\n unit?: string;\n className?: string;\n style?: CSSProperties;\n 'aria-label'?: string;\n}\n\n/**\n * Dual-thumb range slider — selects a sub-range [start, end] within\n * [min, max]. Built from two overlapped `<input type=\"range\">`\n * elements; each input's thumb is independently focusable, draggable,\n * and keyboard-navigable. The track is a shared CSS gradient that\n * paints the filled portion between the two thumbs.\n *\n * Shares the `<Slider>` atom's theming surface — `--uxm-slider-track-\n * color`, `--uxm-slider-accent-color`, `--uxm-slider-thumb-*`, etc.\n * — so editor saves on the Slider registry flow into both single and\n * range modes uniformly. Adds two range-specific gradient stops\n * (`--uxm-range-slider-start` / `-end`) that the atom computes inline\n * from the current value.\n *\n * Display options: `showStart` / `showEnd` / `showRange` toggle the\n * value labels above the slider. Off by default so the bare atom is\n * a pure track-and-thumbs control; consumers (or the editor preview)\n * opt in.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showStart = false,\n showEnd = false,\n showRange = false,\n unit,\n className,\n style,\n 'aria-label': ariaLabel,\n}: RangeSliderProps) {\n const [start, end] = value;\n const range = max - min;\n const startPct = range > 0 ? ((start - min) / range) * 100 : 0;\n const endPct = range > 0 ? ((end - min) / range) * 100 : 100;\n\n // Clamp on drag so start can never overtake end (and vice versa).\n // Without this, dragging the start thumb past the end would silently\n // swap the tuple semantics — surprising for consumers that read\n // `value[0]` as \"the lower bound.\"\n const handleStart = (next: number) => {\n onChange([Math.min(next, end), end]);\n };\n const handleEnd = (next: number) => {\n onChange([start, Math.max(next, start)]);\n };\n\n const mergedStyle = {\n ...style,\n ['--uxm-range-slider-start' as string]: `${startPct}%`,\n ['--uxm-range-slider-end' as string]: `${endPct}%`,\n };\n\n const showAnyValues = showStart || showEnd || showRange;\n\n return (\n <div className={cn('uxm-range-slider', className)} style={mergedStyle}>\n {showAnyValues && (\n <div className=\"uxm-range-slider__values\">\n <span className=\"uxm-range-slider__value uxm-range-slider__value--start\">\n {showStart ? `${start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--range\">\n {showRange ? `${end - start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--end\">\n {showEnd ? `${end}${unit ?? ''}` : ''}\n </span>\n </div>\n )}\n <div className=\"uxm-range-slider__track\">\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--start\"\n value={start}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleStart(Number(e.target.value))}\n aria-label={ariaLabel ? `${ariaLabel} (start)` : 'Range start'}\n />\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--end\"\n value={end}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleEnd(Number(e.target.value))}\n aria-label={ariaLabel ? `${ariaLabel} (end)` : 'Range end'}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuFQ;AAvFR,qBAAmB;AA6CZ,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAChB,GAAqB;AACnB,QAAM,CAAC,OAAO,GAAG,IAAI;AACrB,QAAM,QAAQ,MAAM;AACpB,QAAM,WAAW,QAAQ,KAAM,QAAQ,OAAO,QAAS,MAAM;AAC7D,QAAM,SAAS,QAAQ,KAAM,MAAM,OAAO,QAAS,MAAM;AAMzD,QAAM,cAAc,CAAC,SAAiB;AACpC,aAAS,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EACrC;AACA,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS,CAAC,OAAO,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACzC;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,CAAC,0BAAoC,GAAG,GAAG,QAAQ;AAAA,IACnD,CAAC,wBAAkC,GAAG,GAAG,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,aAAa,WAAW;AAE9C,SACE,6CAAC,SAAI,eAAW,mBAAG,oBAAoB,SAAS,GAAG,OAAO,aACvD;AAAA,qBACC,6CAAC,SAAI,WAAU,4BACb;AAAA,kDAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,KAAK,GAAG,QAAQ,EAAE,KAAK,IACzC;AAAA,MACA,4CAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAC/C;AAAA,MACA,4CAAC,UAAK,WAAU,wDACb,oBAAU,GAAG,GAAG,GAAG,QAAQ,EAAE,KAAK,IACrC;AAAA,OACF;AAAA,IAEF,6CAAC,SAAI,WAAU,2BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,YAAY,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACnD,cAAY,YAAY,GAAG,SAAS,aAAa;AAAA;AAAA,MACnD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,UAAU,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACjD,cAAY,YAAY,GAAG,SAAS,WAAW;AAAA;AAAA,MACjD;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/range-slider/range-slider.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { CSSProperties } from 'react';\n\nexport interface RangeSliderProps {\n /** [start, end] — start ≤ end always (the atom clamps on drag). */\n value: [number, number];\n onChange: (value: [number, number]) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Disable both thumbs and dim the wrapper via the shared --uxm-slider-disabled-opacity var. */\n disabled?: boolean;\n /** Show the start thumb's value above the slider (left-aligned). */\n showStart?: boolean;\n /** Show the end thumb's value above the slider (right-aligned). */\n showEnd?: boolean;\n /** Show the range (end − start) above the slider (centred). */\n showRange?: boolean;\n /** Optional unit shown alongside displayed values (e.g. \"px\"). */\n unit?: string;\n className?: string;\n style?: CSSProperties;\n /**\n * Names the control as a whole. Each thumb derives its own name from this\n * by appending `\" (start)\"` / `\" (end)\"` — English word order baked in, so\n * translate via `startLabel` / `endLabel` instead of relying on the suffix.\n */\n 'aria-label'?: string;\n /**\n * Accessible name for the lower thumb, used verbatim. Defaults to\n * `` `${aria-label} (start)` `` when `aria-label` is set, else\n * `\"Range start\"`.\n */\n startLabel?: string;\n /**\n * Accessible name for the upper thumb, used verbatim. Defaults to\n * `` `${aria-label} (end)` `` when `aria-label` is set, else `\"Range end\"`.\n */\n endLabel?: string;\n}\n\n/**\n * Dual-thumb range slider — selects a sub-range [start, end] within\n * [min, max]. Built from two overlapped `<input type=\"range\">`\n * elements; each input's thumb is independently focusable, draggable,\n * and keyboard-navigable. The track is a shared CSS gradient that\n * paints the filled portion between the two thumbs.\n *\n * Shares the `<Slider>` atom's theming surface — `--uxm-slider-track-\n * color`, `--uxm-slider-accent-color`, `--uxm-slider-thumb-*`, etc.\n * — so editor saves on the Slider registry flow into both single and\n * range modes uniformly. Adds two range-specific gradient stops\n * (`--uxm-range-slider-start` / `-end`) that the atom computes inline\n * from the current value.\n *\n * Display options: `showStart` / `showEnd` / `showRange` toggle the\n * value labels above the slider. Off by default so the bare atom is\n * a pure track-and-thumbs control; consumers (or the editor preview)\n * opt in.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showStart = false,\n showEnd = false,\n showRange = false,\n unit,\n className,\n style,\n 'aria-label': ariaLabel,\n startLabel,\n endLabel,\n}: RangeSliderProps) {\n const [start, end] = value;\n const range = max - min;\n const startPct = range > 0 ? ((start - min) / range) * 100 : 0;\n const endPct = range > 0 ? ((end - min) / range) * 100 : 100;\n\n // Clamp on drag so start can never overtake end (and vice versa).\n // Without this, dragging the start thumb past the end would silently\n // swap the tuple semantics — surprising for consumers that read\n // `value[0]` as \"the lower bound.\"\n const handleStart = (next: number) => {\n onChange([Math.min(next, end), end]);\n };\n const handleEnd = (next: number) => {\n onChange([start, Math.max(next, start)]);\n };\n\n const mergedStyle = {\n ...style,\n ['--uxm-range-slider-start' as string]: `${startPct}%`,\n ['--uxm-range-slider-end' as string]: `${endPct}%`,\n };\n\n const showAnyValues = showStart || showEnd || showRange;\n\n // Two thumbs on one control need two distinct names, and the composed\n // default only works in English — \"(start)\" trailing a noun is not how\n // every language qualifies it. `startLabel` / `endLabel` therefore replace\n // the whole name rather than the suffix.\n const resolvedStartLabel = startLabel ?? (ariaLabel ? `${ariaLabel} (start)` : 'Range start');\n const resolvedEndLabel = endLabel ?? (ariaLabel ? `${ariaLabel} (end)` : 'Range end');\n\n return (\n <div className={cn('uxm-range-slider', className)} style={mergedStyle}>\n {showAnyValues && (\n <div className=\"uxm-range-slider__values\">\n <span className=\"uxm-range-slider__value uxm-range-slider__value--start\">\n {showStart ? `${start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--range\">\n {showRange ? `${end - start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--end\">\n {showEnd ? `${end}${unit ?? ''}` : ''}\n </span>\n </div>\n )}\n <div className=\"uxm-range-slider__track\">\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--start\"\n value={start}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleStart(Number(e.target.value))}\n aria-label={resolvedStartLabel}\n />\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--end\"\n value={end}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleEnd(Number(e.target.value))}\n aria-label={resolvedEndLabel}\n />\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgHQ;AAhHR,qBAAmB;AA6DZ,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,OAAO,GAAG,IAAI;AACrB,QAAM,QAAQ,MAAM;AACpB,QAAM,WAAW,QAAQ,KAAM,QAAQ,OAAO,QAAS,MAAM;AAC7D,QAAM,SAAS,QAAQ,KAAM,MAAM,OAAO,QAAS,MAAM;AAMzD,QAAM,cAAc,CAAC,SAAiB;AACpC,aAAS,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EACrC;AACA,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS,CAAC,OAAO,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACzC;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,CAAC,0BAAoC,GAAG,GAAG,QAAQ;AAAA,IACnD,CAAC,wBAAkC,GAAG,GAAG,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,aAAa,WAAW;AAM9C,QAAM,qBAAqB,eAAe,YAAY,GAAG,SAAS,aAAa;AAC/E,QAAM,mBAAmB,aAAa,YAAY,GAAG,SAAS,WAAW;AAEzE,SACE,6CAAC,SAAI,eAAW,mBAAG,oBAAoB,SAAS,GAAG,OAAO,aACvD;AAAA,qBACC,6CAAC,SAAI,WAAU,4BACb;AAAA,kDAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,KAAK,GAAG,QAAQ,EAAE,KAAK,IACzC;AAAA,MACA,4CAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAC/C;AAAA,MACA,4CAAC,UAAK,WAAU,wDACb,oBAAU,GAAG,GAAG,GAAG,QAAQ,EAAE,KAAK,IACrC;AAAA,OACF;AAAA,IAEF,6CAAC,SAAI,WAAU,2BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,YAAY,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACnD,cAAY;AAAA;AAAA,MACd;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,UAAU,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACjD,cAAY;AAAA;AAAA,MACd;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -18,7 +18,23 @@ export interface RangeSliderProps {
18
18
  unit?: string;
19
19
  className?: string;
20
20
  style?: CSSProperties;
21
+ /**
22
+ * Names the control as a whole. Each thumb derives its own name from this
23
+ * by appending `" (start)"` / `" (end)"` — English word order baked in, so
24
+ * translate via `startLabel` / `endLabel` instead of relying on the suffix.
25
+ */
21
26
  'aria-label'?: string;
27
+ /**
28
+ * Accessible name for the lower thumb, used verbatim. Defaults to
29
+ * `` `${aria-label} (start)` `` when `aria-label` is set, else
30
+ * `"Range start"`.
31
+ */
32
+ startLabel?: string;
33
+ /**
34
+ * Accessible name for the upper thumb, used verbatim. Defaults to
35
+ * `` `${aria-label} (end)` `` when `aria-label` is set, else `"Range end"`.
36
+ */
37
+ endLabel?: string;
22
38
  }
23
39
  /**
24
40
  * Dual-thumb range slider — selects a sub-range [start, end] within
@@ -39,5 +55,5 @@ export interface RangeSliderProps {
39
55
  * a pure track-and-thumbs control; consumers (or the editor preview)
40
56
  * opt in.
41
57
  */
42
- export declare function RangeSlider({ value, onChange, min, max, step, disabled, showStart, showEnd, showRange, unit, className, style, 'aria-label': ariaLabel, }: RangeSliderProps): import("react/jsx-runtime").JSX.Element;
58
+ export declare function RangeSlider({ value, onChange, min, max, step, disabled, showStart, showEnd, showRange, unit, className, style, 'aria-label': ariaLabel, startLabel, endLabel, }: RangeSliderProps): import("react/jsx-runtime").JSX.Element;
43
59
  //# sourceMappingURL=range-slider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"range-slider.d.ts","sourceRoot":"","sources":["../../../src/ui/range-slider/range-slider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,GAAO,EACP,GAAS,EACT,IAAQ,EACR,QAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,SAAiB,EACjB,IAAI,EACJ,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,GACxB,EAAE,gBAAgB,2CAkElB"}
1
+ {"version":3,"file":"range-slider.d.ts","sourceRoot":"","sources":["../../../src/ui/range-slider/range-slider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,QAAQ,EACR,GAAO,EACP,GAAS,EACT,IAAQ,EACR,QAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,SAAiB,EACjB,IAAI,EACJ,SAAS,EACT,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,UAAU,EACV,QAAQ,GACT,EAAE,gBAAgB,2CAyElB"}
@@ -13,7 +13,9 @@ function RangeSlider({
13
13
  unit,
14
14
  className,
15
15
  style,
16
- "aria-label": ariaLabel
16
+ "aria-label": ariaLabel,
17
+ startLabel,
18
+ endLabel
17
19
  }) {
18
20
  const [start, end] = value;
19
21
  const range = max - min;
@@ -31,6 +33,8 @@ function RangeSlider({
31
33
  ["--uxm-range-slider-end"]: `${endPct}%`
32
34
  };
33
35
  const showAnyValues = showStart || showEnd || showRange;
36
+ const resolvedStartLabel = startLabel ?? (ariaLabel ? `${ariaLabel} (start)` : "Range start");
37
+ const resolvedEndLabel = endLabel ?? (ariaLabel ? `${ariaLabel} (end)` : "Range end");
34
38
  return /* @__PURE__ */ jsxs("div", { className: cn("uxm-range-slider", className), style: mergedStyle, children: [
35
39
  showAnyValues && /* @__PURE__ */ jsxs("div", { className: "uxm-range-slider__values", children: [
36
40
  /* @__PURE__ */ jsx("span", { className: "uxm-range-slider__value uxm-range-slider__value--start", children: showStart ? `${start}${unit ?? ""}` : "" }),
@@ -49,7 +53,7 @@ function RangeSlider({
49
53
  step,
50
54
  disabled,
51
55
  onChange: (e) => handleStart(Number(e.target.value)),
52
- "aria-label": ariaLabel ? `${ariaLabel} (start)` : "Range start"
56
+ "aria-label": resolvedStartLabel
53
57
  }
54
58
  ),
55
59
  /* @__PURE__ */ jsx(
@@ -63,7 +67,7 @@ function RangeSlider({
63
67
  step,
64
68
  disabled,
65
69
  onChange: (e) => handleEnd(Number(e.target.value)),
66
- "aria-label": ariaLabel ? `${ariaLabel} (end)` : "Range end"
70
+ "aria-label": resolvedEndLabel
67
71
  }
68
72
  )
69
73
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/range-slider/range-slider.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { CSSProperties } from 'react';\n\nexport interface RangeSliderProps {\n /** [start, end] — start ≤ end always (the atom clamps on drag). */\n value: [number, number];\n onChange: (value: [number, number]) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Disable both thumbs and dim the wrapper via the shared --uxm-slider-disabled-opacity var. */\n disabled?: boolean;\n /** Show the start thumb's value above the slider (left-aligned). */\n showStart?: boolean;\n /** Show the end thumb's value above the slider (right-aligned). */\n showEnd?: boolean;\n /** Show the range (end − start) above the slider (centred). */\n showRange?: boolean;\n /** Optional unit shown alongside displayed values (e.g. \"px\"). */\n unit?: string;\n className?: string;\n style?: CSSProperties;\n 'aria-label'?: string;\n}\n\n/**\n * Dual-thumb range slider — selects a sub-range [start, end] within\n * [min, max]. Built from two overlapped `<input type=\"range\">`\n * elements; each input's thumb is independently focusable, draggable,\n * and keyboard-navigable. The track is a shared CSS gradient that\n * paints the filled portion between the two thumbs.\n *\n * Shares the `<Slider>` atom's theming surface — `--uxm-slider-track-\n * color`, `--uxm-slider-accent-color`, `--uxm-slider-thumb-*`, etc.\n * — so editor saves on the Slider registry flow into both single and\n * range modes uniformly. Adds two range-specific gradient stops\n * (`--uxm-range-slider-start` / `-end`) that the atom computes inline\n * from the current value.\n *\n * Display options: `showStart` / `showEnd` / `showRange` toggle the\n * value labels above the slider. Off by default so the bare atom is\n * a pure track-and-thumbs control; consumers (or the editor preview)\n * opt in.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showStart = false,\n showEnd = false,\n showRange = false,\n unit,\n className,\n style,\n 'aria-label': ariaLabel,\n}: RangeSliderProps) {\n const [start, end] = value;\n const range = max - min;\n const startPct = range > 0 ? ((start - min) / range) * 100 : 0;\n const endPct = range > 0 ? ((end - min) / range) * 100 : 100;\n\n // Clamp on drag so start can never overtake end (and vice versa).\n // Without this, dragging the start thumb past the end would silently\n // swap the tuple semantics — surprising for consumers that read\n // `value[0]` as \"the lower bound.\"\n const handleStart = (next: number) => {\n onChange([Math.min(next, end), end]);\n };\n const handleEnd = (next: number) => {\n onChange([start, Math.max(next, start)]);\n };\n\n const mergedStyle = {\n ...style,\n ['--uxm-range-slider-start' as string]: `${startPct}%`,\n ['--uxm-range-slider-end' as string]: `${endPct}%`,\n };\n\n const showAnyValues = showStart || showEnd || showRange;\n\n return (\n <div className={cn('uxm-range-slider', className)} style={mergedStyle}>\n {showAnyValues && (\n <div className=\"uxm-range-slider__values\">\n <span className=\"uxm-range-slider__value uxm-range-slider__value--start\">\n {showStart ? `${start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--range\">\n {showRange ? `${end - start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--end\">\n {showEnd ? `${end}${unit ?? ''}` : ''}\n </span>\n </div>\n )}\n <div className=\"uxm-range-slider__track\">\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--start\"\n value={start}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleStart(Number(e.target.value))}\n aria-label={ariaLabel ? `${ariaLabel} (start)` : 'Range start'}\n />\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--end\"\n value={end}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleEnd(Number(e.target.value))}\n aria-label={ariaLabel ? `${ariaLabel} (end)` : 'Range end'}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"AAuFQ,SACE,KADF;AAvFR,SAAS,UAAU;AA6CZ,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAChB,GAAqB;AACnB,QAAM,CAAC,OAAO,GAAG,IAAI;AACrB,QAAM,QAAQ,MAAM;AACpB,QAAM,WAAW,QAAQ,KAAM,QAAQ,OAAO,QAAS,MAAM;AAC7D,QAAM,SAAS,QAAQ,KAAM,MAAM,OAAO,QAAS,MAAM;AAMzD,QAAM,cAAc,CAAC,SAAiB;AACpC,aAAS,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EACrC;AACA,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS,CAAC,OAAO,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACzC;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,CAAC,0BAAoC,GAAG,GAAG,QAAQ;AAAA,IACnD,CAAC,wBAAkC,GAAG,GAAG,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,aAAa,WAAW;AAE9C,SACE,qBAAC,SAAI,WAAW,GAAG,oBAAoB,SAAS,GAAG,OAAO,aACvD;AAAA,qBACC,qBAAC,SAAI,WAAU,4BACb;AAAA,0BAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,KAAK,GAAG,QAAQ,EAAE,KAAK,IACzC;AAAA,MACA,oBAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAC/C;AAAA,MACA,oBAAC,UAAK,WAAU,wDACb,oBAAU,GAAG,GAAG,GAAG,QAAQ,EAAE,KAAK,IACrC;AAAA,OACF;AAAA,IAEF,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,YAAY,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACnD,cAAY,YAAY,GAAG,SAAS,aAAa;AAAA;AAAA,MACnD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,UAAU,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACjD,cAAY,YAAY,GAAG,SAAS,WAAW;AAAA;AAAA,MACjD;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/range-slider/range-slider.tsx"],"sourcesContent":["import { cn } from '@/helpers';\n\nimport type { CSSProperties } from 'react';\n\nexport interface RangeSliderProps {\n /** [start, end] — start ≤ end always (the atom clamps on drag). */\n value: [number, number];\n onChange: (value: [number, number]) => void;\n min?: number;\n max?: number;\n step?: number;\n /** Disable both thumbs and dim the wrapper via the shared --uxm-slider-disabled-opacity var. */\n disabled?: boolean;\n /** Show the start thumb's value above the slider (left-aligned). */\n showStart?: boolean;\n /** Show the end thumb's value above the slider (right-aligned). */\n showEnd?: boolean;\n /** Show the range (end − start) above the slider (centred). */\n showRange?: boolean;\n /** Optional unit shown alongside displayed values (e.g. \"px\"). */\n unit?: string;\n className?: string;\n style?: CSSProperties;\n /**\n * Names the control as a whole. Each thumb derives its own name from this\n * by appending `\" (start)\"` / `\" (end)\"` — English word order baked in, so\n * translate via `startLabel` / `endLabel` instead of relying on the suffix.\n */\n 'aria-label'?: string;\n /**\n * Accessible name for the lower thumb, used verbatim. Defaults to\n * `` `${aria-label} (start)` `` when `aria-label` is set, else\n * `\"Range start\"`.\n */\n startLabel?: string;\n /**\n * Accessible name for the upper thumb, used verbatim. Defaults to\n * `` `${aria-label} (end)` `` when `aria-label` is set, else `\"Range end\"`.\n */\n endLabel?: string;\n}\n\n/**\n * Dual-thumb range slider — selects a sub-range [start, end] within\n * [min, max]. Built from two overlapped `<input type=\"range\">`\n * elements; each input's thumb is independently focusable, draggable,\n * and keyboard-navigable. The track is a shared CSS gradient that\n * paints the filled portion between the two thumbs.\n *\n * Shares the `<Slider>` atom's theming surface — `--uxm-slider-track-\n * color`, `--uxm-slider-accent-color`, `--uxm-slider-thumb-*`, etc.\n * — so editor saves on the Slider registry flow into both single and\n * range modes uniformly. Adds two range-specific gradient stops\n * (`--uxm-range-slider-start` / `-end`) that the atom computes inline\n * from the current value.\n *\n * Display options: `showStart` / `showEnd` / `showRange` toggle the\n * value labels above the slider. Off by default so the bare atom is\n * a pure track-and-thumbs control; consumers (or the editor preview)\n * opt in.\n */\nexport function RangeSlider({\n value,\n onChange,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n showStart = false,\n showEnd = false,\n showRange = false,\n unit,\n className,\n style,\n 'aria-label': ariaLabel,\n startLabel,\n endLabel,\n}: RangeSliderProps) {\n const [start, end] = value;\n const range = max - min;\n const startPct = range > 0 ? ((start - min) / range) * 100 : 0;\n const endPct = range > 0 ? ((end - min) / range) * 100 : 100;\n\n // Clamp on drag so start can never overtake end (and vice versa).\n // Without this, dragging the start thumb past the end would silently\n // swap the tuple semantics — surprising for consumers that read\n // `value[0]` as \"the lower bound.\"\n const handleStart = (next: number) => {\n onChange([Math.min(next, end), end]);\n };\n const handleEnd = (next: number) => {\n onChange([start, Math.max(next, start)]);\n };\n\n const mergedStyle = {\n ...style,\n ['--uxm-range-slider-start' as string]: `${startPct}%`,\n ['--uxm-range-slider-end' as string]: `${endPct}%`,\n };\n\n const showAnyValues = showStart || showEnd || showRange;\n\n // Two thumbs on one control need two distinct names, and the composed\n // default only works in English — \"(start)\" trailing a noun is not how\n // every language qualifies it. `startLabel` / `endLabel` therefore replace\n // the whole name rather than the suffix.\n const resolvedStartLabel = startLabel ?? (ariaLabel ? `${ariaLabel} (start)` : 'Range start');\n const resolvedEndLabel = endLabel ?? (ariaLabel ? `${ariaLabel} (end)` : 'Range end');\n\n return (\n <div className={cn('uxm-range-slider', className)} style={mergedStyle}>\n {showAnyValues && (\n <div className=\"uxm-range-slider__values\">\n <span className=\"uxm-range-slider__value uxm-range-slider__value--start\">\n {showStart ? `${start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--range\">\n {showRange ? `${end - start}${unit ?? ''}` : ''}\n </span>\n <span className=\"uxm-range-slider__value uxm-range-slider__value--end\">\n {showEnd ? `${end}${unit ?? ''}` : ''}\n </span>\n </div>\n )}\n <div className=\"uxm-range-slider__track\">\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--start\"\n value={start}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleStart(Number(e.target.value))}\n aria-label={resolvedStartLabel}\n />\n <input\n type=\"range\"\n className=\"uxm-range-slider__input uxm-range-slider__input--end\"\n value={end}\n min={min}\n max={max}\n step={step}\n disabled={disabled}\n onChange={(e) => handleEnd(Number(e.target.value))}\n aria-label={resolvedEndLabel}\n />\n </div>\n </div>\n );\n}\n"],"mappings":"AAgHQ,SACE,KADF;AAhHR,SAAS,UAAU;AA6DZ,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,OAAO,GAAG,IAAI;AACrB,QAAM,QAAQ,MAAM;AACpB,QAAM,WAAW,QAAQ,KAAM,QAAQ,OAAO,QAAS,MAAM;AAC7D,QAAM,SAAS,QAAQ,KAAM,MAAM,OAAO,QAAS,MAAM;AAMzD,QAAM,cAAc,CAAC,SAAiB;AACpC,aAAS,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EACrC;AACA,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS,CAAC,OAAO,KAAK,IAAI,MAAM,KAAK,CAAC,CAAC;AAAA,EACzC;AAEA,QAAM,cAAc;AAAA,IAClB,GAAG;AAAA,IACH,CAAC,0BAAoC,GAAG,GAAG,QAAQ;AAAA,IACnD,CAAC,wBAAkC,GAAG,GAAG,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,aAAa,WAAW;AAM9C,QAAM,qBAAqB,eAAe,YAAY,GAAG,SAAS,aAAa;AAC/E,QAAM,mBAAmB,aAAa,YAAY,GAAG,SAAS,WAAW;AAEzE,SACE,qBAAC,SAAI,WAAW,GAAG,oBAAoB,SAAS,GAAG,OAAO,aACvD;AAAA,qBACC,qBAAC,SAAI,WAAU,4BACb;AAAA,0BAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,KAAK,GAAG,QAAQ,EAAE,KAAK,IACzC;AAAA,MACA,oBAAC,UAAK,WAAU,0DACb,sBAAY,GAAG,MAAM,KAAK,GAAG,QAAQ,EAAE,KAAK,IAC/C;AAAA,MACA,oBAAC,UAAK,WAAU,wDACb,oBAAU,GAAG,GAAG,GAAG,QAAQ,EAAE,KAAK,IACrC;AAAA,OACF;AAAA,IAEF,qBAAC,SAAI,WAAU,2BACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,YAAY,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACnD,cAAY;AAAA;AAAA,MACd;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,CAAC,MAAM,UAAU,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,UACjD,cAAY;AAAA;AAAA,MACd;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -50,7 +50,7 @@ function StatCard({
50
50
  glyph: "arrow-up",
51
51
  size: 12,
52
52
  strokeWidth: 2.5,
53
- style: { transform: trendDirection === "down" ? "rotate(180deg)" : void 0 }
53
+ className: "uxm-stat-card__trend-icon"
54
54
  }
55
55
  ),
56
56
  trend
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n style={{ transform: trendDirection === 'down' ? 'rotate(180deg)' : undefined }}\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBM;AAxBN,qBAAmB;AACnB,kBAAqB;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,6CAAC,SAAI,eAAW,mBAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,gDAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,OAAO,EAAE,WAAW,mBAAmB,SAAS,mBAAmB,OAAU;AAAA;AAAA,YAC/E;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n className=\"uxm-stat-card__trend-icon\"\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBM;AAxBN,qBAAmB;AACnB,kBAAqB;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,6CAAC,SAAI,eAAW,mBAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,gDAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,6CAAC,SAAI,WAAU,sBACb;AAAA,kDAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,WAAU;AAAA;AAAA,YACZ;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -41,6 +41,10 @@
41
41
  }
42
42
  .uxm-stat-card__trend--down {
43
43
  color: var(--uxm-stat-card-trend-down-color, var(--color-danger-text));
44
+ /* One `arrow-up` glyph serves both directions — flip it for `down`. */
45
+ }
46
+ .uxm-stat-card__trend--down .uxm-stat-card__trend-icon {
47
+ transform: rotate(180deg);
44
48
  }
45
49
  .uxm-stat-card__trend--neutral {
46
50
  color: var(--color-text-muted);
@@ -27,7 +27,7 @@ function StatCard({
27
27
  glyph: "arrow-up",
28
28
  size: 12,
29
29
  strokeWidth: 2.5,
30
- style: { transform: trendDirection === "down" ? "rotate(180deg)" : void 0 }
30
+ className: "uxm-stat-card__trend-icon"
31
31
  }
32
32
  ),
33
33
  trend
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n style={{ transform: trendDirection === 'down' ? 'rotate(180deg)' : undefined }}\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAwBM,cAII,YAJJ;AAxBN,SAAS,UAAU;AACnB,SAAS,YAAY;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,qBAAC,SAAI,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,wBAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,OAAO,EAAE,WAAW,mBAAmB,SAAS,mBAAmB,OAAU;AAAA;AAAA,YAC/E;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/ui/stat-card/stat-card.tsx"],"sourcesContent":["import { cn } from '@/helpers';\nimport { Icon } from '@/ui/icon';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type StatCardTrend = 'up' | 'down' | 'neutral';\n\nexport interface StatCardProps extends HTMLAttributes<HTMLDivElement> {\n label: ReactNode;\n value: ReactNode;\n trend?: ReactNode;\n trendDirection?: StatCardTrend;\n}\n\nexport function StatCard({\n label,\n value,\n trend,\n trendDirection = 'neutral',\n className,\n ...rest\n}: StatCardProps) {\n return (\n <div className={cn('uxm-stat-card', className)} {...rest}>\n <p className=\"uxm-stat-card__label\">{label}</p>\n <div className=\"uxm-stat-card__row\">\n <span className=\"uxm-stat-card__value\">{value}</span>\n {trend && (\n <span\n className={cn(\n 'uxm-stat-card__trend',\n `uxm-stat-card__trend--${trendDirection}`,\n )}\n >\n {trendDirection !== 'neutral' && (\n <Icon\n glyph=\"arrow-up\"\n size={12}\n strokeWidth={2.5}\n className=\"uxm-stat-card__trend-icon\"\n />\n )}\n {trend}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAwBM,cAII,YAJJ;AAxBN,SAAS,UAAU;AACnB,SAAS,YAAY;AAad,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,GAAG;AACL,GAAkB;AAChB,SACE,qBAAC,SAAI,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,MAClD;AAAA,wBAAC,OAAE,WAAU,wBAAwB,iBAAM;AAAA,IAC3C,qBAAC,SAAI,WAAU,sBACb;AAAA,0BAAC,UAAK,WAAU,wBAAwB,iBAAM;AAAA,MAC7C,SACC;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,yBAAyB,cAAc;AAAA,UACzC;AAAA,UAEC;AAAA,+BAAmB,aAClB;AAAA,cAAC;AAAA;AAAA,gBACC,OAAM;AAAA,gBACN,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb,WAAU;AAAA;AAAA,YACZ;AAAA,YAED;AAAA;AAAA;AAAA,MACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -1,4 +1,4 @@
1
- /* @viax.io/uxm — default styles aggregator.
1
+ /* @viax/uxm — default styles aggregator.
2
2
  Each @import below pulls a single component's CSS from its folder.
3
3
  Cascade order matches the original monolithic styles.css. */
4
4
 
@@ -48,6 +48,7 @@
48
48
  @import "./inline-filter/inline-filter.css";
49
49
  @import "./input-with-icon/input-with-icon.css";
50
50
  @import "./input/input.css";
51
+ @import "./language-switcher/language-switcher.css";
51
52
  @import "./lifecycle-connector/lifecycle-connector.css";
52
53
  @import "./lifecycle-drop-slot/lifecycle-drop-slot.css";
53
54
  @import "./lifecycle-edge-label/lifecycle-edge-label.css";
@@ -163,7 +163,9 @@
163
163
  }
164
164
  .uxm-toast__close:hover {
165
165
  opacity: 1;
166
- background-color: rgba(0, 0, 0, 0.06);
166
+ /* Tint from the toast's own text colour so the fill reads on every
167
+ variant and in both themes (a black literal vanished on dark). */
168
+ background-color: var(--uxm-toast-close-hover-background-color, color-mix(in srgb, currentColor 10%, transparent));
167
169
  }
168
170
  .uxm-toast__close:focus-visible {
169
171
  opacity: 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viax.io/uxm",
3
- "version": "4.36.0",
3
+ "version": "4.37.1",
4
4
  "description": "Viax UXM — React 19 UI primitives and design tokens.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -65,7 +65,6 @@
65
65
  "test:ci": "echo 'no tests yet' && exit 0",
66
66
  "test:coverage": "echo 'no coverage yet' && exit 0",
67
67
  "commit": "cz",
68
- "prepare": "husky",
69
68
  "prepublishOnly": "npm run build",
70
69
  "check:type-scale": "node scripts/sweep-type-scale.mjs --check",
71
70
  "verify:type-scale": "node scripts/verify-type-scale.mjs origin/master"
@@ -92,7 +91,7 @@
92
91
  "@semantic-release/commit-analyzer": "^13.0.1",
93
92
  "@semantic-release/exec": "^7.1.0",
94
93
  "@semantic-release/git": "^10.0.1",
95
- "@semantic-release/github": "^12.0.9",
94
+ "@semantic-release/gitlab": "^13.3.2",
96
95
  "@semantic-release/npm": "^13.1.5",
97
96
  "@semantic-release/release-notes-generator": "^14.1.1",
98
97
  "@tailwindcss/cli": "^4.0.0",
@@ -126,9 +125,9 @@
126
125
  },
127
126
  "repository": {
128
127
  "type": "git",
129
- "url": "https://github.com/viax-io/uxm.git"
128
+ "url": "https://gitlab.viax.tech/services-viax/uxm.git"
130
129
  },
131
130
  "engines": {
132
- "node": ">=22.14.0"
131
+ "node": ">=20"
133
132
  }
134
133
  }