@ecopages/radiant-ui 0.1.0-beta.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 (254) hide show
  1. package/README.md +70 -0
  2. package/dist/components/ui/alert/alert.css +27 -0
  3. package/dist/components/ui/alert/alert.d.ts +4 -0
  4. package/dist/components/ui/alert/alert.script.d.ts +25 -0
  5. package/dist/components/ui/alert/index.d.ts +2 -0
  6. package/dist/components/ui/alert/index.js +2 -0
  7. package/dist/components/ui/alert/index.js.map +7 -0
  8. package/dist/components/ui/breadcrumb/breadcrumb.css +41 -0
  9. package/dist/components/ui/breadcrumb/breadcrumb.d.ts +59 -0
  10. package/dist/components/ui/breadcrumb/breadcrumb.script.d.ts +40 -0
  11. package/dist/components/ui/breadcrumb/index.d.ts +2 -0
  12. package/dist/components/ui/breadcrumb/index.js +2 -0
  13. package/dist/components/ui/breadcrumb/index.js.map +7 -0
  14. package/dist/components/ui/button/button.d.ts +37 -0
  15. package/dist/components/ui/button/index.d.ts +1 -0
  16. package/dist/components/ui/button/index.js +2 -0
  17. package/dist/components/ui/button/index.js.map +7 -0
  18. package/dist/components/ui/carousel/carousel.css +170 -0
  19. package/dist/components/ui/carousel/carousel.d.ts +39 -0
  20. package/dist/components/ui/carousel/carousel.script.d.ts +113 -0
  21. package/dist/components/ui/carousel/index.d.ts +2 -0
  22. package/dist/components/ui/carousel/index.js +2 -0
  23. package/dist/components/ui/carousel/index.js.map +7 -0
  24. package/dist/components/ui/checkbox/checkbox.css +55 -0
  25. package/dist/components/ui/checkbox/checkbox.d.ts +4 -0
  26. package/dist/components/ui/checkbox/checkbox.script.d.ts +58 -0
  27. package/dist/components/ui/checkbox/index.d.ts +2 -0
  28. package/dist/components/ui/checkbox/index.js +2 -0
  29. package/dist/components/ui/checkbox/index.js.map +7 -0
  30. package/dist/components/ui/combobox/combobox.css +65 -0
  31. package/dist/components/ui/combobox/combobox.d.ts +53 -0
  32. package/dist/components/ui/combobox/combobox.script.d.ts +89 -0
  33. package/dist/components/ui/combobox/index.d.ts +2 -0
  34. package/dist/components/ui/combobox/index.js +2 -0
  35. package/dist/components/ui/combobox/index.js.map +7 -0
  36. package/dist/components/ui/dialog/dialog-registry.d.ts +34 -0
  37. package/dist/components/ui/dialog/dialog-registry.test.d.ts +1 -0
  38. package/dist/components/ui/dialog/dialog-types.d.ts +55 -0
  39. package/dist/components/ui/dialog/dialog.css +53 -0
  40. package/dist/components/ui/dialog/dialog.d.ts +36 -0
  41. package/dist/components/ui/dialog/dialog.script.d.ts +61 -0
  42. package/dist/components/ui/dialog/index.d.ts +4 -0
  43. package/dist/components/ui/dialog/index.js +2 -0
  44. package/dist/components/ui/dialog/index.js.map +7 -0
  45. package/dist/components/ui/disclosure/disclosure-group.script.d.ts +31 -0
  46. package/dist/components/ui/disclosure/disclosure.css +105 -0
  47. package/dist/components/ui/disclosure/disclosure.d.ts +35 -0
  48. package/dist/components/ui/disclosure/disclosure.script.d.ts +38 -0
  49. package/dist/components/ui/disclosure/index.d.ts +3 -0
  50. package/dist/components/ui/disclosure/index.js +2 -0
  51. package/dist/components/ui/disclosure/index.js.map +7 -0
  52. package/dist/components/ui/feed/feed.css +14 -0
  53. package/dist/components/ui/feed/feed.d.ts +12 -0
  54. package/dist/components/ui/feed/feed.script.d.ts +22 -0
  55. package/dist/components/ui/feed/index.d.ts +2 -0
  56. package/dist/components/ui/feed/index.js +2 -0
  57. package/dist/components/ui/feed/index.js.map +7 -0
  58. package/dist/components/ui/field/field-context.d.ts +20 -0
  59. package/dist/components/ui/field/field-description.d.ts +8 -0
  60. package/dist/components/ui/field/field-error.d.ts +9 -0
  61. package/dist/components/ui/field/field-ssr-hydration.test.d.ts +1 -0
  62. package/dist/components/ui/field/field.css +26 -0
  63. package/dist/components/ui/field/field.d.ts +4 -0
  64. package/dist/components/ui/field/field.script.d.ts +68 -0
  65. package/dist/components/ui/field/index.d.ts +5 -0
  66. package/dist/components/ui/field/index.js +2 -0
  67. package/dist/components/ui/field/index.js.map +7 -0
  68. package/dist/components/ui/form/control-protocol.d.ts +19 -0
  69. package/dist/components/ui/form/form-context.d.ts +27 -0
  70. package/dist/components/ui/form/form-field.test.d.ts +3 -0
  71. package/dist/components/ui/form/form-store.d.ts +53 -0
  72. package/dist/components/ui/form/form-store.test.d.ts +1 -0
  73. package/dist/components/ui/form/form.css +12 -0
  74. package/dist/components/ui/form/form.d.ts +5 -0
  75. package/dist/components/ui/form/form.script.d.ts +67 -0
  76. package/dist/components/ui/form/index.d.ts +7 -0
  77. package/dist/components/ui/form/index.js +2 -0
  78. package/dist/components/ui/form/index.js.map +7 -0
  79. package/dist/components/ui/form/resolvers.d.ts +3 -0
  80. package/dist/components/ui/form/types.d.ts +72 -0
  81. package/dist/components/ui/grid/grid.css +47 -0
  82. package/dist/components/ui/grid/grid.d.ts +7 -0
  83. package/dist/components/ui/grid/grid.script.d.ts +26 -0
  84. package/dist/components/ui/grid/index.d.ts +2 -0
  85. package/dist/components/ui/grid/index.js +2 -0
  86. package/dist/components/ui/grid/index.js.map +7 -0
  87. package/dist/components/ui/input/index.d.ts +1 -0
  88. package/dist/components/ui/input/index.js +2 -0
  89. package/dist/components/ui/input/index.js.map +7 -0
  90. package/dist/components/ui/input/input.css +32 -0
  91. package/dist/components/ui/input/input.d.ts +23 -0
  92. package/dist/components/ui/label/index.d.ts +1 -0
  93. package/dist/components/ui/label/index.js +2 -0
  94. package/dist/components/ui/label/index.js.map +7 -0
  95. package/dist/components/ui/label/label.css +8 -0
  96. package/dist/components/ui/label/label.d.ts +9 -0
  97. package/dist/components/ui/listbox/index.d.ts +2 -0
  98. package/dist/components/ui/listbox/index.js +2 -0
  99. package/dist/components/ui/listbox/index.js.map +7 -0
  100. package/dist/components/ui/listbox/listbox.css +23 -0
  101. package/dist/components/ui/listbox/listbox.d.ts +12 -0
  102. package/dist/components/ui/listbox/listbox.script.d.ts +40 -0
  103. package/dist/components/ui/menu-button/index.d.ts +2 -0
  104. package/dist/components/ui/menu-button/index.js +2 -0
  105. package/dist/components/ui/menu-button/index.js.map +7 -0
  106. package/dist/components/ui/menu-button/menu-button.css +43 -0
  107. package/dist/components/ui/menu-button/menu-button.d.ts +13 -0
  108. package/dist/components/ui/menu-button/menu-button.script.d.ts +64 -0
  109. package/dist/components/ui/menubar/index.d.ts +2 -0
  110. package/dist/components/ui/menubar/index.js +2 -0
  111. package/dist/components/ui/menubar/index.js.map +7 -0
  112. package/dist/components/ui/menubar/menubar.css +45 -0
  113. package/dist/components/ui/menubar/menubar.d.ts +16 -0
  114. package/dist/components/ui/menubar/menubar.script.d.ts +52 -0
  115. package/dist/components/ui/meter/index.d.ts +2 -0
  116. package/dist/components/ui/meter/index.js +2 -0
  117. package/dist/components/ui/meter/index.js.map +7 -0
  118. package/dist/components/ui/meter/meter.css +17 -0
  119. package/dist/components/ui/meter/meter.d.ts +4 -0
  120. package/dist/components/ui/meter/meter.script.d.ts +33 -0
  121. package/dist/components/ui/navigation-menu/index.d.ts +2 -0
  122. package/dist/components/ui/navigation-menu/index.js +2 -0
  123. package/dist/components/ui/navigation-menu/index.js.map +7 -0
  124. package/dist/components/ui/navigation-menu/navigation-menu.css +90 -0
  125. package/dist/components/ui/navigation-menu/navigation-menu.d.ts +28 -0
  126. package/dist/components/ui/navigation-menu/navigation-menu.script.d.ts +49 -0
  127. package/dist/components/ui/radio-group/index.d.ts +2 -0
  128. package/dist/components/ui/radio-group/index.js +2 -0
  129. package/dist/components/ui/radio-group/index.js.map +7 -0
  130. package/dist/components/ui/radio-group/radio-group.css +44 -0
  131. package/dist/components/ui/radio-group/radio-group.d.ts +12 -0
  132. package/dist/components/ui/radio-group/radio-group.script.d.ts +52 -0
  133. package/dist/components/ui/sidebar/index.d.ts +3 -0
  134. package/dist/components/ui/sidebar/index.js +2 -0
  135. package/dist/components/ui/sidebar/index.js.map +7 -0
  136. package/dist/components/ui/sidebar/sidebar-trigger.script.d.ts +53 -0
  137. package/dist/components/ui/sidebar/sidebar.css +362 -0
  138. package/dist/components/ui/sidebar/sidebar.d.ts +141 -0
  139. package/dist/components/ui/sidebar/sidebar.script.d.ts +140 -0
  140. package/dist/components/ui/sidebar/sidebar.test.d.ts +1 -0
  141. package/dist/components/ui/slider/index.d.ts +2 -0
  142. package/dist/components/ui/slider/index.js +2 -0
  143. package/dist/components/ui/slider/index.js.map +7 -0
  144. package/dist/components/ui/slider/slider.css +51 -0
  145. package/dist/components/ui/slider/slider.d.ts +7 -0
  146. package/dist/components/ui/slider/slider.script.d.ts +102 -0
  147. package/dist/components/ui/spinbutton/index.d.ts +2 -0
  148. package/dist/components/ui/spinbutton/index.js +2 -0
  149. package/dist/components/ui/spinbutton/index.js.map +7 -0
  150. package/dist/components/ui/spinbutton/spinbutton.css +19 -0
  151. package/dist/components/ui/spinbutton/spinbutton.d.ts +4 -0
  152. package/dist/components/ui/spinbutton/spinbutton.script.d.ts +64 -0
  153. package/dist/components/ui/switch/index.d.ts +2 -0
  154. package/dist/components/ui/switch/index.js +2 -0
  155. package/dist/components/ui/switch/index.js.map +7 -0
  156. package/dist/components/ui/switch/switch.css +47 -0
  157. package/dist/components/ui/switch/switch.d.ts +4 -0
  158. package/dist/components/ui/switch/switch.script.d.ts +51 -0
  159. package/dist/components/ui/tabs/index.d.ts +2 -0
  160. package/dist/components/ui/tabs/index.js +2 -0
  161. package/dist/components/ui/tabs/index.js.map +7 -0
  162. package/dist/components/ui/tabs/tabs.css +28 -0
  163. package/dist/components/ui/tabs/tabs.d.ts +12 -0
  164. package/dist/components/ui/tabs/tabs.script.d.ts +54 -0
  165. package/dist/components/ui/textarea/index.d.ts +1 -0
  166. package/dist/components/ui/textarea/index.js +2 -0
  167. package/dist/components/ui/textarea/index.js.map +7 -0
  168. package/dist/components/ui/textarea/textarea.css +33 -0
  169. package/dist/components/ui/textarea/textarea.d.ts +23 -0
  170. package/dist/components/ui/toast/index.d.ts +5 -0
  171. package/dist/components/ui/toast/index.js +2 -0
  172. package/dist/components/ui/toast/index.js.map +7 -0
  173. package/dist/components/ui/toast/toast-api.d.ts +29 -0
  174. package/dist/components/ui/toast/toast-context.d.ts +59 -0
  175. package/dist/components/ui/toast/toast-state.d.ts +25 -0
  176. package/dist/components/ui/toast/toast.css +315 -0
  177. package/dist/components/ui/toast/toast.d.ts +8 -0
  178. package/dist/components/ui/toast/toast.script.d.ts +91 -0
  179. package/dist/components/ui/toast/toast.test.d.ts +2 -0
  180. package/dist/components/ui/toast/toaster.script.d.ts +79 -0
  181. package/dist/components/ui/toolbar/index.d.ts +2 -0
  182. package/dist/components/ui/toolbar/index.js +2 -0
  183. package/dist/components/ui/toolbar/index.js.map +7 -0
  184. package/dist/components/ui/toolbar/toolbar.css +16 -0
  185. package/dist/components/ui/toolbar/toolbar.d.ts +4 -0
  186. package/dist/components/ui/toolbar/toolbar.script.d.ts +30 -0
  187. package/dist/components/ui/tooltip/index.d.ts +2 -0
  188. package/dist/components/ui/tooltip/index.js +2 -0
  189. package/dist/components/ui/tooltip/index.js.map +7 -0
  190. package/dist/components/ui/tooltip/tooltip.css +25 -0
  191. package/dist/components/ui/tooltip/tooltip.d.ts +4 -0
  192. package/dist/components/ui/tooltip/tooltip.script.d.ts +70 -0
  193. package/dist/components/ui/tree/index.d.ts +2 -0
  194. package/dist/components/ui/tree/index.js +2 -0
  195. package/dist/components/ui/tree/index.js.map +7 -0
  196. package/dist/components/ui/tree/tree.css +54 -0
  197. package/dist/components/ui/tree/tree.d.ts +13 -0
  198. package/dist/components/ui/tree/tree.script.d.ts +45 -0
  199. package/dist/components/ui/treegrid/index.d.ts +2 -0
  200. package/dist/components/ui/treegrid/index.js +2 -0
  201. package/dist/components/ui/treegrid/index.js.map +7 -0
  202. package/dist/components/ui/treegrid/treegrid.css +77 -0
  203. package/dist/components/ui/treegrid/treegrid.d.ts +14 -0
  204. package/dist/components/ui/treegrid/treegrid.script.d.ts +49 -0
  205. package/dist/components/ui/window-splitter/index.d.ts +2 -0
  206. package/dist/components/ui/window-splitter/index.js +2 -0
  207. package/dist/components/ui/window-splitter/index.js.map +7 -0
  208. package/dist/components/ui/window-splitter/window-splitter.css +35 -0
  209. package/dist/components/ui/window-splitter/window-splitter.d.ts +8 -0
  210. package/dist/components/ui/window-splitter/window-splitter.script.d.ts +49 -0
  211. package/dist/index.d.ts +36 -0
  212. package/dist/index.js +2 -0
  213. package/dist/index.js.map +7 -0
  214. package/dist/lib/focusable-elements.d.ts +2 -0
  215. package/dist/lib/radiant-view.d.ts +17 -0
  216. package/dist/lib/roving-tabindex.d.ts +27 -0
  217. package/dist/styles/components/button.css +115 -0
  218. package/dist/styles/radiant-ui-core.css +7 -0
  219. package/dist/styles/radiant-ui.css +10 -0
  220. package/dist/styles/styles.css +36 -0
  221. package/dist/styles/tailwind.css +41 -0
  222. package/dist/styles/themes/aurora.css +19 -0
  223. package/dist/styles/themes/default-compact-soft.css +19 -0
  224. package/dist/styles/themes/default.css +2 -0
  225. package/dist/styles/themes/glacier.css +19 -0
  226. package/dist/styles/tokens/colors/aurora.css +73 -0
  227. package/dist/styles/tokens/colors/basalt.css +36 -0
  228. package/dist/styles/tokens/colors/glacier.css +45 -0
  229. package/dist/styles/tokens/colors/palettes.css +3 -0
  230. package/dist/styles/tokens/elevation/default.css +22 -0
  231. package/dist/styles/tokens/elevation/flat.css +22 -0
  232. package/dist/styles/tokens/motion/default.css +19 -0
  233. package/dist/styles/tokens/motion/snappy.css +19 -0
  234. package/dist/styles/tokens/presets/colors/aurora.css +126 -0
  235. package/dist/styles/tokens/presets/colors/basalt.css +126 -0
  236. package/dist/styles/tokens/presets/colors/ember.css +134 -0
  237. package/dist/styles/tokens/presets/colors/glacier.css +130 -0
  238. package/dist/styles/tokens/presets/colors/index.css +4 -0
  239. package/dist/styles/tokens/presets/radius.css +45 -0
  240. package/dist/styles/tokens/presets/spacing.css +57 -0
  241. package/dist/styles/tokens/radius/default.css +34 -0
  242. package/dist/styles/tokens/radius/edgy.css +35 -0
  243. package/dist/styles/tokens/radius/sharp.css +2 -0
  244. package/dist/styles/tokens/radius/soft.css +34 -0
  245. package/dist/styles/tokens/semantic.css +80 -0
  246. package/dist/styles/tokens/spacing/compact.css +23 -0
  247. package/dist/styles/tokens/spacing/default.css +23 -0
  248. package/dist/styles/tokens/spacing/scale-bridge.css +17 -0
  249. package/dist/styles/tokens/spacing/wide.css +23 -0
  250. package/dist/styles/tokens/system.css +36 -0
  251. package/dist/styles/tokens/typography/default.css +37 -0
  252. package/dist/styles/utilities/sheen.css +7 -0
  253. package/dist/types.d.ts +14 -0
  254. package/package.json +371 -0
@@ -0,0 +1,52 @@
1
+ import { RadiantElement } from '@ecopages/radiant';
2
+ import type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';
3
+ export type RuiMenubarProps = {
4
+ label?: string;
5
+ };
6
+ export type RuiMenubarChangeDetail = {
7
+ value: string;
8
+ };
9
+ type RuiMenubarBindings = {
10
+ label: string;
11
+ };
12
+ /**
13
+ * `<rui-menubar>` — a horizontal menubar of menus.
14
+ *
15
+ * Implements the APG Menubar pattern: top-level items use `role="menuitem"` with
16
+ * `aria-haspopup` / `aria-expanded` when they own a nested `[role="menu"]`. Arrow
17
+ * keys move across the bar; Enter/Space/ArrowDown open the popup; Escape closes it.
18
+ *
19
+ * Expected markup (also produced by the JSX view helper):
20
+ * ```html
21
+ * <div class="rui-menubar__root" data-ref="menubar-root">
22
+ * <button role="menuitem" aria-haspopup="true" aria-expanded="false">File</button>
23
+ * <div role="menu" hidden>
24
+ * <button role="menuitem" data-value="new">New</button>
25
+ * </div>
26
+ * </div>
27
+ * ```
28
+ *
29
+ * @see https://www.w3.org/WAI/ARIA/apg/patterns/menubar/
30
+ * @element rui-menubar
31
+ * @fires rui-change
32
+ */
33
+ export declare class RuiMenubar extends RadiantElement<RuiMenubarBindings> {
34
+ label: string;
35
+ changeEvent: EventEmitter<RuiMenubarChangeDetail>;
36
+ private readonly resolvedAriaLabel;
37
+ private openRoot;
38
+ private getTopItems;
39
+ private getMenuFor;
40
+ private getMenuItems;
41
+ connectedCallback(): void;
42
+ private closeOpenMenu;
43
+ private openMenu;
44
+ onDocumentClick(event: MouseEvent): void;
45
+ onTopKeydown(event: KeyboardEvent): void;
46
+ onTopClick(event: Event): void;
47
+ onMenuKeydown(event: KeyboardEvent): void;
48
+ onMenuItemClick(event: Event): void;
49
+ private activateItem;
50
+ render(): import("@ecopages/jsx").JsxRenderable;
51
+ }
52
+ export {};
@@ -0,0 +1,2 @@
1
+ export { RuiMeter as RuiMeterElement, type RuiMeterProps } from './meter.script';
2
+ export { RuiMeter } from './meter';
@@ -0,0 +1,2 @@
1
+ import{RadiantElement as u,customElement as p,onUpdated as d,prop as i,state as R}from"@ecopages/radiant";var n=@p("rui-meter")class extends u{@i({type:Number,reflect:!0,defaultValue:0})value;@i({type:Number,defaultValue:0})min;@i({type:Number,defaultValue:100})max;@i({type:String,defaultValue:""})label;@R percent=0;resolvedAriaLabel=this.$.label.map(e=>e||void 0);@d(["value","min","max"])onRangeUpdated(){this.percent=this.max===this.min?0:Math.round((this.value-this.min)/(this.max-this.min)*100)}render(){return React.createElement("div",{class:"rui-meter"},this.label?React.createElement("span",{class:"rui-meter__label"},this.$.label):null,React.createElement("meter",{class:"rui-meter__bar",min:this.$.min,max:this.$.max,value:this.$.value,"aria-label":this.resolvedAriaLabel},this.$.percent,"%"),React.createElement("span",{class:"rui-meter__value","aria-hidden":"true"},this.$.percent,"%"))}};var b=Symbol.for("@ecopages/storybook-radiant.viewElement"),s=Symbol.for("@ecopages/storybook-radiant.scriptModule"),o=Symbol.for("@ecopages/storybook-radiant.scriptExport");function T(t,e){t[b]=e;let r=e[s];r&&(t[s]=r,t[o]=e[o]??e.name)}function m(t,e){let r=(a=>e(a));return T(r,t),r}import"./meter.css";var c=m(n,({slot:t,value:e,min:r,max:a,label:l})=>React.createElement("rui-meter",{slot:t,value:e,min:r,max:a,label:l}));export{c as RuiMeter,n as RuiMeterElement};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/components/ui/meter/meter.script.tsx", "../../../../src/lib/radiant-view.ts", "../../../../src/components/ui/meter/meter.tsx"],
4
+ "sourcesContent": ["import { RadiantElement, customElement, onUpdated, prop, state } from '@ecopages/radiant';\n\nexport type RuiMeterProps = {\n\tvalue?: number;\n\tmin?: number;\n\tmax?: number;\n\tlabel?: string;\n};\n\ntype RuiMeterBindings = {\n\tvalue: number;\n\tmin: number;\n\tmax: number;\n\tlabel: string;\n\tpercent: number;\n};\n\n/**\n * `<rui-meter>` \u2014 a graphical display of a numeric value within a range.\n *\n * Uses the native `<meter>` element, which maps to the APG Meter pattern.\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/meter/\n * @element rui-meter\n */\n@customElement('rui-meter')\nexport class RuiMeter extends RadiantElement<RuiMeterBindings> {\n\t@prop({ type: Number, reflect: true, defaultValue: 0 }) value: number;\n\t@prop({ type: Number, defaultValue: 0 }) min: number;\n\t@prop({ type: Number, defaultValue: 100 }) max: number;\n\t@prop({ type: String, defaultValue: '' }) label: string;\n\n\t@state percent = 0;\n\n\tprivate readonly resolvedAriaLabel = this.$.label.map((label) => label || undefined);\n\n\t@onUpdated(['value', 'min', 'max'])\n\tonRangeUpdated(): void {\n\t\tthis.percent = this.max === this.min ? 0 : Math.round(((this.value - this.min) / (this.max - this.min)) * 100);\n\t}\n\n\toverride render() {\n\t\treturn (\n\t\t\t<div class=\"rui-meter\">\n\t\t\t\t{this.label ? <span class=\"rui-meter__label\">{this.$.label}</span> : null}\n\t\t\t\t<meter\n\t\t\t\t\tclass=\"rui-meter__bar\"\n\t\t\t\t\tmin={this.$.min}\n\t\t\t\t\tmax={this.$.max}\n\t\t\t\t\tvalue={this.$.value}\n\t\t\t\t\taria-label={this.resolvedAriaLabel}\n\t\t\t\t>\n\t\t\t\t\t{this.$.percent}%\n\t\t\t\t</meter>\n\t\t\t\t<span class=\"rui-meter__value\" aria-hidden=\"true\">\n\t\t\t\t\t{this.$.percent}%\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\n\nconst RADIANT_VIEW_ELEMENT = Symbol.for('@ecopages/storybook-radiant.viewElement');\nconst RADIANT_SCRIPT_MODULE = Symbol.for('@ecopages/storybook-radiant.scriptModule');\nconst RADIANT_SCRIPT_EXPORT = Symbol.for('@ecopages/storybook-radiant.scriptExport');\n\nexport type RadiantViewComponent<TArgs = unknown> = ((args: TArgs) => JsxRenderable) & {\n\t[RADIANT_VIEW_ELEMENT]?: CustomElementConstructor;\n\t[RADIANT_SCRIPT_MODULE]?: string;\n\t[RADIANT_SCRIPT_EXPORT]?: string;\n};\n\nfunction linkViewToElement<TArgs>(\n\tview: RadiantViewComponent<TArgs>,\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n): void {\n\tview[RADIANT_VIEW_ELEMENT] = element;\n\n\tconst ssrModule = element[RADIANT_SCRIPT_MODULE];\n\tif (ssrModule) {\n\t\tview[RADIANT_SCRIPT_MODULE] = ssrModule;\n\t\tview[RADIANT_SCRIPT_EXPORT] = element[RADIANT_SCRIPT_EXPORT] ?? element.name;\n\t}\n}\n\n/** Link a JSX view export to its RadiantElement class (same symbols as the Storybook framework). */\nexport function defineRadiantView<TArgs>(\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n\trender: (args: TArgs) => JsxRenderable,\n): RadiantViewComponent<TArgs> {\n\tconst view = ((args: TArgs) => render(args)) as RadiantViewComponent<TArgs>;\n\tlinkViewToElement(view, element);\n\treturn view;\n}\n\n/** Re-copy SSR metadata from the linked element (e.g. after HMR). */\nexport function syncRadiantViewMetadata(view: RadiantViewComponent): void {\n\tconst element = view[RADIANT_VIEW_ELEMENT];\n\tif (element) {\n\t\tlinkViewToElement(view, element);\n\t}\n}\n", "import type { RadiantSlotProps } from '../../../types';\nimport { defineRadiantView } from '../../../lib/radiant-view';\nimport type { RuiMeterProps } from './meter.script';\nimport { RuiMeter as RuiMeterElement } from './meter.script';\nimport './meter.css';\n\nexport const RuiMeter = defineRadiantView(\n\tRuiMeterElement,\n\t({ slot, value, min, max, label }: RuiMeterProps & RadiantSlotProps) => (\n\t\t<rui-meter slot={slot} value={value} min={min} max={max} label={label} />\n\t),\n);\n"],
5
+ "mappings": "AAAA,OAAS,kBAAAA,EAAgB,iBAAAC,EAAe,aAAAC,EAAW,QAAAC,EAAM,SAAAC,MAAa,oBA0B/D,IAAMC,EADb,CAACJ,EAAc,WAAW,CACnB,cAAuBD,CAAiC,CAC9D,CAACG,EAAK,CAAE,KAAM,OAAQ,QAAS,GAAM,aAAc,CAAE,CAAC,CAAE,MACxD,CAACA,EAAK,CAAE,KAAM,OAAQ,aAAc,CAAE,CAAC,CAAE,IACzC,CAACA,EAAK,CAAE,KAAM,OAAQ,aAAc,GAAI,CAAC,CAAE,IAC3C,CAACA,EAAK,CAAE,KAAM,OAAQ,aAAc,EAAG,CAAC,CAAE,MAE1C,CAACC,EAAM,QAAU,EAEA,kBAAoB,KAAK,EAAE,MAAM,IAAKE,GAAUA,GAAS,MAAS,EAEnF,CAACJ,EAAU,CAAC,QAAS,MAAO,KAAK,CAAC,CAClC,gBAAuB,CACtB,KAAK,QAAU,KAAK,MAAQ,KAAK,IAAM,EAAI,KAAK,OAAQ,KAAK,MAAQ,KAAK,MAAQ,KAAK,IAAM,KAAK,KAAQ,GAAG,CAC9G,CAES,QAAS,CACjB,OACC,oBAAC,OAAI,MAAM,aACT,KAAK,MAAQ,oBAAC,QAAK,MAAM,oBAAoB,KAAK,EAAE,KAAM,EAAU,KACrE,oBAAC,SACA,MAAM,iBACN,IAAK,KAAK,EAAE,IACZ,IAAK,KAAK,EAAE,IACZ,MAAO,KAAK,EAAE,MACd,aAAY,KAAK,mBAEhB,KAAK,EAAE,QAAQ,GACjB,EACA,oBAAC,QAAK,MAAM,mBAAmB,cAAY,QACzC,KAAK,EAAE,QAAQ,GACjB,CACD,CAEF,CACD,EC1DA,IAAMK,EAAuB,OAAO,IAAI,yCAAyC,EAC3EC,EAAwB,OAAO,IAAI,0CAA0C,EAC7EC,EAAwB,OAAO,IAAI,0CAA0C,EAQnF,SAASC,EACRC,EACAC,EAIO,CACPD,EAAKJ,CAAoB,EAAIK,EAE7B,IAAMC,EAAYD,EAAQJ,CAAqB,EAC3CK,IACHF,EAAKH,CAAqB,EAAIK,EAC9BF,EAAKF,CAAqB,EAAIG,EAAQH,CAAqB,GAAKG,EAAQ,KAE1E,CAGO,SAASE,EACfF,EAIAG,EAC8B,CAC9B,IAAMJ,GAASK,GAAgBD,EAAOC,CAAI,GAC1C,OAAAN,EAAkBC,EAAMC,CAAO,EACxBD,CACR,CCnCA,MAAO,cAEA,IAAMM,EAAWC,EACvBD,EACA,CAAC,CAAE,KAAAE,EAAM,MAAAC,EAAO,IAAAC,EAAK,IAAAC,EAAK,MAAAC,CAAM,IAC/B,oBAAC,aAAU,KAAMJ,EAAM,MAAOC,EAAO,IAAKC,EAAK,IAAKC,EAAK,MAAOC,EAAO,CAEzE",
6
+ "names": ["RadiantElement", "customElement", "onUpdated", "prop", "state", "RuiMeter", "label", "RADIANT_VIEW_ELEMENT", "RADIANT_SCRIPT_MODULE", "RADIANT_SCRIPT_EXPORT", "linkViewToElement", "view", "element", "ssrModule", "defineRadiantView", "render", "args", "RuiMeter", "defineRadiantView", "slot", "value", "min", "max", "label"]
7
+ }
@@ -0,0 +1,17 @@
1
+ @reference '../../../styles/radiant-ui.css';
2
+
3
+ rui-meter {
4
+ @apply block;
5
+ }
6
+
7
+ @layer components {
8
+ .rui-meter {
9
+ @apply flex items-center gap-3 text-sm;
10
+ }
11
+ .rui-meter__bar {
12
+ @apply h-3 w-48;
13
+ }
14
+ .rui-meter__value {
15
+ @apply tabular-nums text-on-surface;
16
+ }
17
+ }
@@ -0,0 +1,4 @@
1
+ import type { RadiantSlotProps } from '../../../types';
2
+ import type { RuiMeterProps } from './meter.script';
3
+ import './meter.css';
4
+ export declare const RuiMeter: import("../../../lib/radiant-view").RadiantViewComponent<RuiMeterProps & RadiantSlotProps>;
@@ -0,0 +1,33 @@
1
+ import { RadiantElement } from '@ecopages/radiant';
2
+ export type RuiMeterProps = {
3
+ value?: number;
4
+ min?: number;
5
+ max?: number;
6
+ label?: string;
7
+ };
8
+ type RuiMeterBindings = {
9
+ value: number;
10
+ min: number;
11
+ max: number;
12
+ label: string;
13
+ percent: number;
14
+ };
15
+ /**
16
+ * `<rui-meter>` — a graphical display of a numeric value within a range.
17
+ *
18
+ * Uses the native `<meter>` element, which maps to the APG Meter pattern.
19
+ *
20
+ * @see https://www.w3.org/WAI/ARIA/apg/patterns/meter/
21
+ * @element rui-meter
22
+ */
23
+ export declare class RuiMeter extends RadiantElement<RuiMeterBindings> {
24
+ value: number;
25
+ min: number;
26
+ max: number;
27
+ label: string;
28
+ percent: number;
29
+ private readonly resolvedAriaLabel;
30
+ onRangeUpdated(): void;
31
+ render(): import("@ecopages/jsx").JsxRenderable;
32
+ }
33
+ export {};
@@ -0,0 +1,2 @@
1
+ export { RuiNavigationMenu, RuiNavigationMenuTrigger, RuiNavigationMenuLink, RuiNavigationMenuPanel, type RuiNavigationMenuTriggerProps, type RuiNavigationMenuLinkProps, type RuiNavigationMenuPanelProps, } from './navigation-menu';
2
+ export { RuiNavigationMenu as RuiNavigationMenuElement, type RuiNavigationMenuProps } from './navigation-menu.script';
@@ -0,0 +1,2 @@
1
+ var P=Symbol.for("@ecopages/storybook-radiant.viewElement"),b=Symbol.for("@ecopages/storybook-radiant.scriptModule"),R=Symbol.for("@ecopages/storybook-radiant.scriptExport");function A(n,e){n[P]=e;let t=e[b];t&&(n[b]=t,n[R]=e[R]??e.name)}function E(n,e){let t=(i=>e(i));return A(t,n),t}function L(...n){return n.filter(Boolean).join(" ")}function N(n,e,t){if(n!==void 0)return n;if(e)return t}function T({variant:n="filled",size:e="md",type:t="button",disabled:i,pressed:r,defaultPressed:o=!1,toggle:a=!1,class:l,slot:s,children:u,"on:click":v,...y}){let M=m=>{if(a&&r===void 0){let h=m.currentTarget,x=h.getAttribute("aria-pressed")!=="true";h.setAttribute("aria-pressed",String(x))}v?.(m)};return React.createElement("button",{type:t,slot:s,class:L("rui-button",`rui-button--${n}`,`rui-button--${e}`,l),disabled:i,"aria-pressed":N(r,a,o),"data-toggle":a&&r===void 0?"":void 0,"on:click":a||v?M:void 0,...y},u)}import{RadiantElement as w,customElement as D,onEvent as g,prop as H}from"@ecopages/radiant";var k=["a[href]","button:not([disabled])","input:not([disabled])","select:not([disabled])","textarea:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");function I(n){return n.getClientRects().length>0&&!n.closest("[hidden]")}function p(n){return Array.from(n.querySelectorAll(k)).filter(I)}function c(n,e){n.forEach((t,i)=>{t.tabIndex=i===e?0:-1})}function S(n,e){if(!n.length)return null;let t=Math.max(0,Math.min(n.length-1,e));return c(n,t),n[t]?.focus(),n[t]??null}function V(n,e){return n==="Home"?"first":n==="End"?"last":e==="horizontal"?n==="ArrowRight"?"next":n==="ArrowLeft"?"prev":null:n==="ArrowDown"?"next":n==="ArrowUp"?"prev":null}function f(n){let{items:e,current:t,key:i,orientation:r="horizontal",wrap:o=!0}=n;if(!e.length||!t)return{handled:!1};let a=e.indexOf(t);if(a<0)return{handled:!1};let l=V(i,r);if(!l)return{handled:!1};let s=a;l==="first"?s=0:l==="last"?s=e.length-1:l==="next"?s=o?(a+1)%e.length:Math.min(e.length-1,a+1):s=o?(a-1+e.length)%e.length:Math.max(0,a-1);let u=S(e,s);return u?{handled:!0,index:s,item:u}:{handled:!1}}var d=@D("rui-navigation-menu")class extends w{@H({type:String,defaultValue:""})label;resolvedAriaLabel=this.$.label.map(e=>e||void 0);openValue=null;connectedCallback(){super.connectedCallback(),queueMicrotask(()=>{this.syncPanels(),this.syncBarRovingTabindex()})}getBarItems(){return Array.from(this.querySelectorAll("[data-navigation-item]"))}syncBarRovingTabindex(){let e=this.getBarItems(),t=Math.max(0,e.findIndex(i=>i.tabIndex===0||i===document.activeElement));c(e,t)}isBarTrigger(e){return e.hasAttribute("data-navigation-trigger")}getTriggers(){return Array.from(this.querySelectorAll("[data-navigation-trigger]"))}getPanel(e){return this.querySelector(`[data-navigation-panel][data-value="${e}"]`)}getTrigger(e){return this.querySelector(`[data-navigation-trigger][data-value="${e}"]`)}getPanels(){return Array.from(this.querySelectorAll("[data-navigation-panel]"))}focusPanelEntry(e){let t=this.getPanel(e);if(!t){this.getTrigger(e)?.focus();return}let i=p(t);if(i.length>0){i[0].focus();return}t.hasAttribute("tabindex")||(t.tabIndex=-1),t.focus()}syncPanels(){for(let e of this.getPanels()){let t=e.getAttribute("data-value")??"",i=this.openValue===t;e.hidden=!i,e.dataset.state=i?"open":"closed",e.setAttribute("aria-hidden",String(!i));let r=this.getTrigger(t);r&&(r.setAttribute("aria-expanded",String(i)),e.setAttribute("role","region"),e.setAttribute("aria-labelledby",r.id||`${t}-trigger`),r.id||(r.id=`${t}-trigger`))}for(let e of this.getTriggers()){let t=e.getAttribute("data-value")??"",i=this.openValue===t;e.setAttribute("aria-expanded",String(i)),this.getPanel(t)?e.setAttribute("aria-haspopup","true"):e.removeAttribute("aria-haspopup")}}closeMenu(e=!1){let t=this.openValue;t&&(this.openValue=null,this.syncPanels(),e&&this.getTrigger(t)?.focus())}openPanel(e,t=!0){if(this.openValue===e){this.closeMenu(!0);return}this.openValue=e,this.syncPanels(),queueMicrotask(()=>{t?this.focusPanelEntry(e):this.getTrigger(e)?.focus()})}getEventElement(e){let t=e.target;return t instanceof Element?t:t instanceof Text?t.parentElement:null}isWithinOpenPanel(e){if(!this.openValue)return!1;let t=this.getPanel(this.openValue);return t?e.composedPath().some(i=>i instanceof Node&&t.contains(i)):!1}@g({document:!0,type:"click"})onDocumentClick(e){if(!this.openValue||this.isWithinOpenPanel(e))return;let t=this.getEventElement(e);t&&this.contains(t)||this.closeMenu()}@g({document:!0,type:"keydown"})onDocumentKeydown(e){if(e.key!=="Escape"||!this.openValue)return;let t=document.activeElement;t&&!this.contains(t)||(e.preventDefault(),this.closeMenu(!0))}@g({ref:"root",type:"keydown"})onRootKeydown(e){e.key==="Escape"&&this.openValue&&(e.preventDefault(),this.closeMenu(!0))}@g({selector:"[data-navigation-trigger]",type:"click"})onTriggerClick(e){let t=e.target.closest("[data-navigation-trigger]"),i=t?.getAttribute("data-value");!t||!i||(e.preventDefault(),this.openPanel(i))}@g({selector:"[data-navigation-item]",type:"keydown"})onBarItemKeydown(e){let t=e.target.closest("[data-navigation-item]");if(!t)return;let i=this.getBarItems(),r=this.isBarTrigger(t),o=t.getAttribute("data-value");if(e.key==="Escape"){this.openValue&&(e.preventDefault(),this.closeMenu(!0));return}if(r&&o&&(e.key==="Enter"||e.key===" ")){e.preventDefault(),this.openPanel(o);return}if(r&&o&&e.key==="ArrowDown"){e.preventDefault(),this.openValue===o?this.focusPanelEntry(o):this.openPanel(o);return}let a=f({items:i,current:t,key:e.key,orientation:"horizontal",wrap:!1});if(!a.handled)return;e.preventDefault();let l=a.item,s=l.getAttribute("data-value"),u=this.isBarTrigger(l);this.openValue&&(u&&s?this.openPanel(s):this.closeMenu(!1))}@g({selector:"[data-navigation-panel]",type:"keydown"})onPanelKeydown(e){let t=e.target;if(!(t instanceof Element))return;let i=t.closest("[data-navigation-panel]");if(!i||i.hidden)return;let r=i.getAttribute("data-value");if(!r||this.openValue!==r)return;let o=document.activeElement instanceof HTMLElement?document.activeElement:null;if(!o||!i.contains(o))return;if(e.key==="Escape"){e.preventDefault(),this.closeMenu(!0);return}if(e.key==="ArrowUp"&&o===p(i)[0]){e.preventDefault(),this.getTrigger(r)?.focus();return}let a=p(i);!a.length||!f({items:a,current:o,key:e.key,orientation:"vertical",wrap:!1}).handled||e.preventDefault()}render(){return React.createElement("nav",{class:"rui-navigation-menu","data-ref":"root","aria-label":this.resolvedAriaLabel},React.createElement("div",{class:"rui-navigation-menu__bar"},React.createElement("slot",{name:"triggers"})),React.createElement("div",{class:"rui-navigation-menu__panels"},React.createElement("slot",{name:"panels"})))}};import"./navigation-menu.css";function B(...n){return n.filter(Boolean).join(" ")}var C=E(d,({label:n,children:e,slot:t})=>React.createElement("rui-navigation-menu",{slot:t,label:n},e));function _({slot:n="triggers",value:e,children:t,variant:i="ghost",...r}){return React.createElement(T,{slot:n,variant:i,"data-navigation-item":!0,"data-navigation-trigger":!0,"data-value":e,...r},t)}function O({slot:n="triggers",href:e,children:t,class:i}){return React.createElement("a",{slot:n,href:e,"data-navigation-item":!0,class:B("rui-button","rui-button--ghost","rui-button--md",i)},t)}function J({slot:n="panels",value:e,children:t,class:i}){return React.createElement("div",{slot:n,class:i,"data-navigation-panel":!0,"data-value":e},t)}export{C as RuiNavigationMenu,d as RuiNavigationMenuElement,O as RuiNavigationMenuLink,J as RuiNavigationMenuPanel,_ as RuiNavigationMenuTrigger};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lib/radiant-view.ts", "../../../../src/components/ui/button/button.tsx", "../../../../src/components/ui/navigation-menu/navigation-menu.script.tsx", "../../../../src/lib/focusable-elements.ts", "../../../../src/lib/roving-tabindex.ts", "../../../../src/components/ui/navigation-menu/navigation-menu.tsx"],
4
+ "sourcesContent": ["import type { JsxRenderable } from '@ecopages/jsx';\n\nconst RADIANT_VIEW_ELEMENT = Symbol.for('@ecopages/storybook-radiant.viewElement');\nconst RADIANT_SCRIPT_MODULE = Symbol.for('@ecopages/storybook-radiant.scriptModule');\nconst RADIANT_SCRIPT_EXPORT = Symbol.for('@ecopages/storybook-radiant.scriptExport');\n\nexport type RadiantViewComponent<TArgs = unknown> = ((args: TArgs) => JsxRenderable) & {\n\t[RADIANT_VIEW_ELEMENT]?: CustomElementConstructor;\n\t[RADIANT_SCRIPT_MODULE]?: string;\n\t[RADIANT_SCRIPT_EXPORT]?: string;\n};\n\nfunction linkViewToElement<TArgs>(\n\tview: RadiantViewComponent<TArgs>,\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n): void {\n\tview[RADIANT_VIEW_ELEMENT] = element;\n\n\tconst ssrModule = element[RADIANT_SCRIPT_MODULE];\n\tif (ssrModule) {\n\t\tview[RADIANT_SCRIPT_MODULE] = ssrModule;\n\t\tview[RADIANT_SCRIPT_EXPORT] = element[RADIANT_SCRIPT_EXPORT] ?? element.name;\n\t}\n}\n\n/** Link a JSX view export to its RadiantElement class (same symbols as the Storybook framework). */\nexport function defineRadiantView<TArgs>(\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n\trender: (args: TArgs) => JsxRenderable,\n): RadiantViewComponent<TArgs> {\n\tconst view = ((args: TArgs) => render(args)) as RadiantViewComponent<TArgs>;\n\tlinkViewToElement(view, element);\n\treturn view;\n}\n\n/** Re-copy SSR metadata from the linked element (e.g. after HMR). */\nexport function syncRadiantViewMetadata(view: RadiantViewComponent): void {\n\tconst element = view[RADIANT_VIEW_ELEMENT];\n\tif (element) {\n\t\tlinkViewToElement(view, element);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\nimport type { RadiantSlotProps } from '../../../types';\n\nexport type RuiButtonVariant = 'filled' | 'outline' | 'destructive' | 'ghost';\nexport type RuiButtonSize = 'sm' | 'md' | 'lg';\n\nexport type RuiButtonProps = RadiantSlotProps & {\n\t/** Visual style. Default: `filled`. */\n\tvariant?: RuiButtonVariant;\n\t/** Control size. Default: `md`. */\n\tsize?: RuiButtonSize;\n\t/** Native button type. Default: `button`. */\n\ttype?: 'button' | 'submit' | 'reset';\n\t/** Disabled state. */\n\tdisabled?: boolean;\n\t/** Controlled pressed state for toggle buttons (`aria-pressed`). */\n\tpressed?: boolean;\n\t/** Initial pressed state when `toggle` is used without a controlled `pressed` value. */\n\tdefaultPressed?: boolean;\n\t/** Toggle `aria-pressed` on click when `pressed` is not controlled. */\n\ttoggle?: boolean;\n\t/** Extra class names appended after the variant/size classes. */\n\tclass?: string;\n\t/** Accessible name when the button has no visible text. */\n\t'aria-label'?: string;\n\t'on:click'?: (event: Event) => void;\n\tchildren?: JsxRenderable;\n};\n\nfunction cx(...parts: Array<string | false | null | undefined>): string {\n\treturn parts.filter(Boolean).join(' ');\n}\n\nfunction resolveAriaPressed(\n\tpressed: boolean | undefined,\n\ttoggle: boolean,\n\tdefaultPressed: boolean,\n): boolean | undefined {\n\tif (pressed !== undefined) {\n\t\treturn pressed;\n\t}\n\n\tif (toggle) {\n\t\treturn defaultPressed;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Presentational wrapper around a native `<button>`.\n *\n * No custom element and no controller \u2014 only CSS variants/sizes. Follows the\n * APG Button pattern by staying on the native control for activation and focus.\n *\n * Styles ship via the radiant-ui base stylesheet (`rui-button` classes).\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/button/\n */\nexport function RuiButton({\n\tvariant = 'filled',\n\tsize = 'md',\n\ttype = 'button',\n\tdisabled,\n\tpressed,\n\tdefaultPressed = false,\n\ttoggle = false,\n\tclass: className,\n\tslot,\n\tchildren,\n\t'on:click': onClick,\n\t...rest\n}: RuiButtonProps) {\n\tconst handleClick = (event: Event) => {\n\t\tif (toggle && pressed === undefined) {\n\t\t\tconst button = event.currentTarget as HTMLButtonElement;\n\t\t\tconst next = button.getAttribute('aria-pressed') !== 'true';\n\t\t\tbutton.setAttribute('aria-pressed', String(next));\n\t\t}\n\n\t\tonClick?.(event);\n\t};\n\n\treturn (\n\t\t<button\n\t\t\ttype={type}\n\t\t\tslot={slot}\n\t\t\tclass={cx('rui-button', `rui-button--${variant}`, `rui-button--${size}`, className)}\n\t\t\tdisabled={disabled}\n\t\t\taria-pressed={resolveAriaPressed(pressed, toggle, defaultPressed)}\n\t\t\tdata-toggle={toggle && pressed === undefined ? '' : undefined}\n\t\t\ton:click={toggle || onClick ? handleClick : undefined}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{children}\n\t\t</button>\n\t);\n}\n", "import { RadiantElement, customElement, onEvent, prop } from '@ecopages/radiant';\nimport { getFocusableElements } from '../../../lib/focusable-elements';\nimport { applyRovingTabindex, navigateRovingTabindex } from '../../../lib/roving-tabindex';\n\nexport type RuiNavigationMenuProps = {\n\tlabel?: string;\n};\n\ntype RuiNavigationMenuBindings = {\n\tlabel: string;\n};\n\n/**\n * `<rui-navigation-menu>` \u2014 a composition-first site navigation shell.\n *\n * Implements the APG Disclosure Navigation Menu interaction model: top-level\n * triggers open exclusive panels composed from other radiant-ui primitives.\n *\n * Mark triggers with `data-navigation-trigger` and `data-value`. Mark matching\n * panels with `data-navigation-panel` and the same `data-value`. Top-level bar\n * links and triggers should use `data-navigation-item` (added by the view helpers).\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/\n * @element rui-navigation-menu\n * @slot triggers - Top-level navigation triggers and plain links.\n * @slot panels - Disclosure panels composed from other primitives.\n */\n@customElement('rui-navigation-menu')\nexport class RuiNavigationMenu extends RadiantElement<RuiNavigationMenuBindings> {\n\t@prop({ type: String, defaultValue: '' }) label: string;\n\n\tprivate readonly resolvedAriaLabel = this.$.label.map((label) => label || undefined);\n\n\tprivate openValue: string | null = null;\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tqueueMicrotask(() => {\n\t\t\tthis.syncPanels();\n\t\t\tthis.syncBarRovingTabindex();\n\t\t});\n\t}\n\n\tprivate getBarItems(): HTMLElement[] {\n\t\treturn Array.from(this.querySelectorAll<HTMLElement>('[data-navigation-item]'));\n\t}\n\n\tprivate syncBarRovingTabindex(): void {\n\t\tconst items = this.getBarItems();\n\t\tconst activeIndex = Math.max(\n\t\t\t0,\n\t\t\titems.findIndex((item) => item.tabIndex === 0 || item === document.activeElement),\n\t\t);\n\t\tapplyRovingTabindex(items, activeIndex);\n\t}\n\n\tprivate isBarTrigger(item: HTMLElement): boolean {\n\t\treturn item.hasAttribute('data-navigation-trigger');\n\t}\n\n\tprivate getTriggers(): HTMLElement[] {\n\t\treturn Array.from(this.querySelectorAll<HTMLElement>('[data-navigation-trigger]'));\n\t}\n\n\tprivate getPanel(value: string): HTMLElement | null {\n\t\treturn this.querySelector<HTMLElement>(`[data-navigation-panel][data-value=\"${value}\"]`);\n\t}\n\n\tprivate getTrigger(value: string): HTMLElement | null {\n\t\treturn this.querySelector<HTMLElement>(`[data-navigation-trigger][data-value=\"${value}\"]`);\n\t}\n\n\tprivate getPanels(): HTMLElement[] {\n\t\treturn Array.from(this.querySelectorAll<HTMLElement>('[data-navigation-panel]'));\n\t}\n\n\tprivate focusPanelEntry(value: string): void {\n\t\tconst panel = this.getPanel(value);\n\t\tif (!panel) {\n\t\t\tthis.getTrigger(value)?.focus();\n\t\t\treturn;\n\t\t}\n\n\t\tconst focusables = getFocusableElements(panel);\n\t\tif (focusables.length > 0) {\n\t\t\tfocusables[0].focus();\n\t\t\treturn;\n\t\t}\n\n\t\tif (!panel.hasAttribute('tabindex')) {\n\t\t\tpanel.tabIndex = -1;\n\t\t}\n\n\t\tpanel.focus();\n\t}\n\n\tprivate syncPanels(): void {\n\t\tfor (const panel of this.getPanels()) {\n\t\t\tconst value = panel.getAttribute('data-value') ?? '';\n\t\t\tconst open = this.openValue === value;\n\t\t\tpanel.hidden = !open;\n\t\t\tpanel.dataset.state = open ? 'open' : 'closed';\n\t\t\tpanel.setAttribute('aria-hidden', String(!open));\n\n\t\t\tconst trigger = this.getTrigger(value);\n\t\t\tif (trigger) {\n\t\t\t\ttrigger.setAttribute('aria-expanded', String(open));\n\t\t\t\tpanel.setAttribute('role', 'region');\n\t\t\t\tpanel.setAttribute('aria-labelledby', trigger.id || `${value}-trigger`);\n\t\t\t\tif (!trigger.id) {\n\t\t\t\t\ttrigger.id = `${value}-trigger`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const trigger of this.getTriggers()) {\n\t\t\tconst value = trigger.getAttribute('data-value') ?? '';\n\t\t\tconst open = this.openValue === value;\n\t\t\ttrigger.setAttribute('aria-expanded', String(open));\n\t\t\tif (this.getPanel(value)) {\n\t\t\t\ttrigger.setAttribute('aria-haspopup', 'true');\n\t\t\t} else {\n\t\t\t\ttrigger.removeAttribute('aria-haspopup');\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate closeMenu(returnFocus = false): void {\n\t\tconst previous = this.openValue;\n\t\tif (!previous) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.openValue = null;\n\t\tthis.syncPanels();\n\n\t\tif (returnFocus) {\n\t\t\tthis.getTrigger(previous)?.focus();\n\t\t}\n\t}\n\n\tprivate openPanel(value: string, focusPanel = true): void {\n\t\tif (this.openValue === value) {\n\t\t\tthis.closeMenu(true);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.openValue = value;\n\t\tthis.syncPanels();\n\t\tqueueMicrotask(() => {\n\t\t\tif (focusPanel) {\n\t\t\t\tthis.focusPanelEntry(value);\n\t\t\t} else {\n\t\t\t\tthis.getTrigger(value)?.focus();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate getEventElement(event: Event): Element | null {\n\t\tconst target = event.target;\n\t\tif (target instanceof Element) {\n\t\t\treturn target;\n\t\t}\n\n\t\tif (target instanceof Text) {\n\t\t\treturn target.parentElement;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate isWithinOpenPanel(event: MouseEvent): boolean {\n\t\tif (!this.openValue) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst openPanel = this.getPanel(this.openValue);\n\t\tif (!openPanel) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn event.composedPath().some((node) => node instanceof Node && openPanel.contains(node));\n\t}\n\n\t@onEvent({ document: true, type: 'click' })\n\tonDocumentClick(event: MouseEvent): void {\n\t\tif (!this.openValue) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.isWithinOpenPanel(event)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst element = this.getEventElement(event);\n\t\tif (element && this.contains(element)) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.closeMenu();\n\t}\n\n\t@onEvent({ document: true, type: 'keydown' })\n\tonDocumentKeydown(event: KeyboardEvent): void {\n\t\tif (event.key !== 'Escape' || !this.openValue) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst active = document.activeElement;\n\t\tif (active && !this.contains(active)) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tthis.closeMenu(true);\n\t}\n\n\t@onEvent({ ref: 'root', type: 'keydown' })\n\tonRootKeydown(event: KeyboardEvent): void {\n\t\tif (event.key === 'Escape' && this.openValue) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.closeMenu(true);\n\t\t}\n\t}\n\n\t@onEvent({ selector: '[data-navigation-trigger]', type: 'click' })\n\tonTriggerClick(event: Event): void {\n\t\tconst trigger = (event.target as HTMLElement).closest<HTMLElement>('[data-navigation-trigger]');\n\t\tconst value = trigger?.getAttribute('data-value');\n\t\tif (!trigger || !value) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tthis.openPanel(value);\n\t}\n\n\t@onEvent({ selector: '[data-navigation-item]', type: 'keydown' })\n\tonBarItemKeydown(event: KeyboardEvent): void {\n\t\tconst item = (event.target as HTMLElement).closest<HTMLElement>('[data-navigation-item]');\n\t\tif (!item) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst barItems = this.getBarItems();\n\t\tconst isTrigger = this.isBarTrigger(item);\n\t\tconst value = item.getAttribute('data-value');\n\n\t\tif (event.key === 'Escape') {\n\t\t\tif (this.openValue) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.closeMenu(true);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (isTrigger && value && (event.key === 'Enter' || event.key === ' ')) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.openPanel(value);\n\t\t\treturn;\n\t\t}\n\n\t\tif (isTrigger && value && event.key === 'ArrowDown') {\n\t\t\tevent.preventDefault();\n\t\t\tif (this.openValue === value) {\n\t\t\t\tthis.focusPanelEntry(value);\n\t\t\t} else {\n\t\t\t\tthis.openPanel(value);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = navigateRovingTabindex({\n\t\t\titems: barItems,\n\t\t\tcurrent: item,\n\t\t\tkey: event.key,\n\t\t\torientation: 'horizontal',\n\t\t\twrap: false,\n\t\t});\n\n\t\tif (!result.handled) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\tconst nextItem = result.item;\n\t\tconst nextValue = nextItem.getAttribute('data-value');\n\t\tconst nextIsTrigger = this.isBarTrigger(nextItem);\n\n\t\tif (this.openValue) {\n\t\t\tif (nextIsTrigger && nextValue) {\n\t\t\t\tthis.openPanel(nextValue);\n\t\t\t} else {\n\t\t\t\tthis.closeMenu(false);\n\t\t\t}\n\t\t}\n\t}\n\n\t@onEvent({ selector: '[data-navigation-panel]', type: 'keydown' })\n\tonPanelKeydown(event: KeyboardEvent): void {\n\t\tconst target = event.target;\n\t\tif (!(target instanceof Element)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst panel = target.closest<HTMLElement>('[data-navigation-panel]');\n\t\tif (!panel || panel.hidden) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst value = panel.getAttribute('data-value');\n\t\tif (!value || this.openValue !== value) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst active = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n\t\tif (!active || !panel.contains(active)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === 'Escape') {\n\t\t\tevent.preventDefault();\n\t\t\tthis.closeMenu(true);\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === 'ArrowUp' && active === getFocusableElements(panel)[0]) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.getTrigger(value)?.focus();\n\t\t\treturn;\n\t\t}\n\n\t\tconst focusables = getFocusableElements(panel);\n\t\tif (!focusables.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = navigateRovingTabindex({\n\t\t\titems: focusables,\n\t\t\tcurrent: active,\n\t\t\tkey: event.key,\n\t\t\torientation: 'vertical',\n\t\t\twrap: false,\n\t\t});\n\n\t\tif (!result.handled) {\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t}\n\n\toverride render() {\n\t\treturn (\n\t\t\t<nav class=\"rui-navigation-menu\" data-ref=\"root\" aria-label={this.resolvedAriaLabel}>\n\t\t\t\t<div class=\"rui-navigation-menu__bar\">\n\t\t\t\t\t<slot name=\"triggers\"></slot>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"rui-navigation-menu__panels\">\n\t\t\t\t\t<slot name=\"panels\"></slot>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t);\n\t}\n}\n", "const FOCUSABLE_SELECTOR = [\n\t'a[href]',\n\t'button:not([disabled])',\n\t'input:not([disabled])',\n\t'select:not([disabled])',\n\t'textarea:not([disabled])',\n\t'[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\nfunction isVisible(element: HTMLElement): boolean {\n\treturn element.getClientRects().length > 0 && !element.closest('[hidden]');\n}\n\n/** Returns focusable descendants in DOM order, skipping hidden nodes. */\nexport function getFocusableElements(root: ParentNode): HTMLElement[] {\n\treturn Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(isVisible);\n}\n", "export type RovingOrientation = 'horizontal' | 'vertical';\n\nexport type RovingNavResult = { handled: false } | { handled: true; index: number; item: HTMLElement };\n\n/**\n * Apply the APG roving-tabindex pattern: one item is tabbable, the rest are `-1`.\n */\nexport function applyRovingTabindex(items: HTMLElement[], activeIndex: number): void {\n\titems.forEach((item, index) => {\n\t\titem.tabIndex = index === activeIndex ? 0 : -1;\n\t});\n}\n\n/**\n * Focus `items[index]` and update tabindexes. Returns the focused item, or null.\n */\nexport function focusRovingItem(items: HTMLElement[], index: number): HTMLElement | null {\n\tif (!items.length) return null;\n\tconst next = Math.max(0, Math.min(items.length - 1, index));\n\tapplyRovingTabindex(items, next);\n\titems[next]?.focus();\n\treturn items[next] ?? null;\n}\n\nfunction deltaForKey(key: string, orientation: RovingOrientation): 'prev' | 'next' | 'first' | 'last' | null {\n\tif (key === 'Home') return 'first';\n\tif (key === 'End') return 'last';\n\n\tif (orientation === 'horizontal') {\n\t\tif (key === 'ArrowRight') return 'next';\n\t\tif (key === 'ArrowLeft') return 'prev';\n\t\treturn null;\n\t}\n\n\tif (key === 'ArrowDown') return 'next';\n\tif (key === 'ArrowUp') return 'prev';\n\treturn null;\n}\n\n/**\n * Handle arrow / Home / End navigation for a flat roving-tabindex collection.\n * Does not activate the item \u2014 callers decide whether to select on move.\n */\nexport function navigateRovingTabindex(options: {\n\titems: HTMLElement[];\n\tcurrent: HTMLElement | null;\n\tkey: string;\n\torientation?: RovingOrientation;\n\twrap?: boolean;\n}): RovingNavResult {\n\tconst { items, current, key, orientation = 'horizontal', wrap = true } = options;\n\tif (!items.length || !current) return { handled: false };\n\n\tconst index = items.indexOf(current);\n\tif (index < 0) return { handled: false };\n\n\tconst delta = deltaForKey(key, orientation);\n\tif (!delta) return { handled: false };\n\n\tlet next = index;\n\tif (delta === 'first') next = 0;\n\telse if (delta === 'last') next = items.length - 1;\n\telse if (delta === 'next') next = wrap ? (index + 1) % items.length : Math.min(items.length - 1, index + 1);\n\telse next = wrap ? (index - 1 + items.length) % items.length : Math.max(0, index - 1);\n\n\tconst item = focusRovingItem(items, next);\n\tif (!item) return { handled: false };\n\treturn { handled: true, index: next, item };\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\nimport { defineRadiantView } from '../../../lib/radiant-view';\nimport type { RadiantSlotProps } from '../../../types';\nimport { RuiButton, type RuiButtonProps } from '../button/button';\nimport type { RuiNavigationMenuProps } from './navigation-menu.script';\nimport { RuiNavigationMenu as RuiNavigationMenuElement } from './navigation-menu.script';\nimport './navigation-menu.css';\n\nfunction cx(...parts: Array<string | false | null | undefined>): string {\n\treturn parts.filter(Boolean).join(' ');\n}\n\nexport const RuiNavigationMenu = defineRadiantView(\n\tRuiNavigationMenuElement,\n\t({ label, children, slot }: RuiNavigationMenuProps & RadiantSlotProps & { children: JsxRenderable }) => (\n\t\t<rui-navigation-menu slot={slot} label={label}>\n\t\t\t{children}\n\t\t</rui-navigation-menu>\n\t),\n);\n\nexport type RuiNavigationMenuTriggerProps = RadiantSlotProps &\n\tPick<RuiButtonProps, 'variant' | 'disabled' | 'class' | 'type'> & {\n\t\tvalue: string;\n\t\tchildren: JsxRenderable;\n\t};\n\n/** Top-level megamenu trigger slotted into `triggers` by default. */\nexport function RuiNavigationMenuTrigger({\n\tslot = 'triggers',\n\tvalue,\n\tchildren,\n\tvariant = 'ghost',\n\t...rest\n}: RuiNavigationMenuTriggerProps) {\n\treturn (\n\t\t<RuiButton\n\t\t\tslot={slot}\n\t\t\tvariant={variant}\n\t\t\tdata-navigation-item\n\t\t\tdata-navigation-trigger\n\t\t\tdata-value={value}\n\t\t\t{...rest}\n\t\t>\n\t\t\t{children}\n\t\t</RuiButton>\n\t);\n}\n\nexport type RuiNavigationMenuLinkProps = RadiantSlotProps & {\n\thref: string;\n\tchildren: JsxRenderable;\n\tclass?: string;\n};\n\n/** Plain navigation link slotted into `triggers` by default. */\nexport function RuiNavigationMenuLink({\n\tslot = 'triggers',\n\thref,\n\tchildren,\n\tclass: className,\n}: RuiNavigationMenuLinkProps) {\n\treturn (\n\t\t<a\n\t\t\tslot={slot}\n\t\t\thref={href}\n\t\t\tdata-navigation-item\n\t\t\tclass={cx('rui-button', 'rui-button--ghost', 'rui-button--md', className)}\n\t\t>\n\t\t\t{children}\n\t\t</a>\n\t);\n}\n\nexport type RuiNavigationMenuPanelProps = RadiantSlotProps & {\n\tvalue: string;\n\tchildren: JsxRenderable;\n\tclass?: string;\n};\n\n/** Megamenu panel slotted into `panels` by default. */\nexport function RuiNavigationMenuPanel({\n\tslot = 'panels',\n\tvalue,\n\tchildren,\n\tclass: className,\n}: RuiNavigationMenuPanelProps) {\n\treturn (\n\t\t<div slot={slot} class={className} data-navigation-panel data-value={value}>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["RADIANT_VIEW_ELEMENT", "RADIANT_SCRIPT_MODULE", "RADIANT_SCRIPT_EXPORT", "linkViewToElement", "view", "element", "ssrModule", "defineRadiantView", "render", "args", "cx", "parts", "resolveAriaPressed", "pressed", "toggle", "defaultPressed", "RuiButton", "variant", "size", "type", "disabled", "className", "slot", "children", "onClick", "rest", "handleClick", "event", "button", "next", "RadiantElement", "customElement", "onEvent", "prop", "FOCUSABLE_SELECTOR", "isVisible", "element", "getFocusableElements", "root", "applyRovingTabindex", "items", "activeIndex", "item", "index", "focusRovingItem", "next", "deltaForKey", "key", "orientation", "navigateRovingTabindex", "options", "current", "wrap", "delta", "RuiNavigationMenu", "customElement", "RadiantElement", "prop", "label", "items", "activeIndex", "item", "applyRovingTabindex", "value", "panel", "focusables", "getFocusableElements", "open", "trigger", "returnFocus", "previous", "focusPanel", "event", "target", "openPanel", "node", "onEvent", "element", "active", "barItems", "isTrigger", "result", "navigateRovingTabindex", "nextItem", "nextValue", "nextIsTrigger", "cx", "parts", "RuiNavigationMenu", "defineRadiantView", "label", "children", "slot", "RuiNavigationMenuTrigger", "value", "variant", "rest", "RuiButton", "RuiNavigationMenuLink", "href", "className", "RuiNavigationMenuPanel"]
7
+ }
@@ -0,0 +1,90 @@
1
+ @reference '../../../styles/radiant-ui.css';
2
+
3
+ rui-navigation-menu {
4
+ @apply block w-full;
5
+ }
6
+
7
+ @layer components {
8
+ .rui-navigation-menu {
9
+ @apply flex flex-col overflow-hidden rounded-container border border-border bg-surface shadow-sm;
10
+ }
11
+
12
+ .rui-navigation-menu__bar {
13
+ @apply flex flex-wrap items-center gap-1 border-b border-border bg-background px-3 py-2;
14
+ }
15
+
16
+ .rui-navigation-menu__bar .rui-button,
17
+ .rui-navigation-menu__bar a.rui-button {
18
+ @apply rounded-container no-underline;
19
+ }
20
+
21
+ .rui-navigation-menu [data-navigation-trigger] {
22
+ @apply relative;
23
+ }
24
+
25
+ .rui-navigation-menu [data-navigation-trigger][aria-expanded='true'] {
26
+ @apply bg-primary-container font-medium text-on-primary-container shadow-none;
27
+ @apply ring-2 ring-inset ring-primary/25;
28
+ }
29
+
30
+ .rui-navigation-menu__panels {
31
+ @apply bg-background;
32
+ }
33
+
34
+ .rui-navigation-menu__panels [data-navigation-panel] {
35
+ @apply block px-5 py-5 text-sm text-on-background;
36
+ }
37
+
38
+ .rui-navigation-menu__panels [data-navigation-panel][hidden] {
39
+ display: none;
40
+ }
41
+
42
+ .rui-navigation-menu__panels [data-navigation-panel] > p {
43
+ @apply m-0 leading-relaxed text-on-surface;
44
+ }
45
+
46
+ .rui-navigation-menu__panels [data-navigation-panel] rui-grid {
47
+ @apply max-w-3xl;
48
+ }
49
+
50
+ .rui-navigation-menu__panels [data-navigation-panel] rui-disclosure {
51
+ @apply mt-4 block border-t border-border pt-3;
52
+ }
53
+
54
+ .rui-navigation-menu__panels [data-navigation-panel] rui-disclosure + rui-disclosure {
55
+ @apply mt-1 border-t border-border pt-1;
56
+ }
57
+
58
+ .rui-navigation-menu__panels [data-navigation-panel] .rui-disclosure__panel:not([hidden]) {
59
+ display: block;
60
+ }
61
+
62
+ .rui-navigation-menu__megamenu {
63
+ @apply grid gap-6;
64
+ }
65
+
66
+ .rui-navigation-menu__link-columns {
67
+ @apply grid gap-6 sm:grid-cols-2;
68
+ }
69
+
70
+ .rui-navigation-menu__link-group-label {
71
+ @apply m-0 mb-2 text-xs font-semibold tracking-wide text-on-surface uppercase;
72
+ }
73
+
74
+ .rui-navigation-menu__link-list {
75
+ @apply m-0 list-none space-y-1 p-0;
76
+ }
77
+
78
+ .rui-navigation-menu__link-list a {
79
+ @apply block rounded-container px-2 py-1.5 font-medium text-link no-underline transition-colors duration-fast;
80
+ @apply hover:bg-surface hover:underline;
81
+ }
82
+
83
+ .rui-navigation-menu__link-list a:focus-visible {
84
+ @apply bg-surface ring-2 ring-focus-ring outline-hidden;
85
+ }
86
+
87
+ .rui-navigation-menu__disclosure-copy {
88
+ @apply m-0 text-on-surface;
89
+ }
90
+ }
@@ -0,0 +1,28 @@
1
+ import type { JsxRenderable } from '@ecopages/jsx';
2
+ import type { RadiantSlotProps } from '../../../types';
3
+ import { type RuiButtonProps } from '../button/button';
4
+ import type { RuiNavigationMenuProps } from './navigation-menu.script';
5
+ import './navigation-menu.css';
6
+ export declare const RuiNavigationMenu: import("../../../lib/radiant-view").RadiantViewComponent<RuiNavigationMenuProps & RadiantSlotProps & {
7
+ children: JsxRenderable;
8
+ }>;
9
+ export type RuiNavigationMenuTriggerProps = RadiantSlotProps & Pick<RuiButtonProps, 'variant' | 'disabled' | 'class' | 'type'> & {
10
+ value: string;
11
+ children: JsxRenderable;
12
+ };
13
+ /** Top-level megamenu trigger slotted into `triggers` by default. */
14
+ export declare function RuiNavigationMenuTrigger({ slot, value, children, variant, ...rest }: RuiNavigationMenuTriggerProps): JsxRenderable;
15
+ export type RuiNavigationMenuLinkProps = RadiantSlotProps & {
16
+ href: string;
17
+ children: JsxRenderable;
18
+ class?: string;
19
+ };
20
+ /** Plain navigation link slotted into `triggers` by default. */
21
+ export declare function RuiNavigationMenuLink({ slot, href, children, class: className, }: RuiNavigationMenuLinkProps): JsxRenderable;
22
+ export type RuiNavigationMenuPanelProps = RadiantSlotProps & {
23
+ value: string;
24
+ children: JsxRenderable;
25
+ class?: string;
26
+ };
27
+ /** Megamenu panel slotted into `panels` by default. */
28
+ export declare function RuiNavigationMenuPanel({ slot, value, children, class: className, }: RuiNavigationMenuPanelProps): JsxRenderable;
@@ -0,0 +1,49 @@
1
+ import { RadiantElement } from '@ecopages/radiant';
2
+ export type RuiNavigationMenuProps = {
3
+ label?: string;
4
+ };
5
+ type RuiNavigationMenuBindings = {
6
+ label: string;
7
+ };
8
+ /**
9
+ * `<rui-navigation-menu>` — a composition-first site navigation shell.
10
+ *
11
+ * Implements the APG Disclosure Navigation Menu interaction model: top-level
12
+ * triggers open exclusive panels composed from other radiant-ui primitives.
13
+ *
14
+ * Mark triggers with `data-navigation-trigger` and `data-value`. Mark matching
15
+ * panels with `data-navigation-panel` and the same `data-value`. Top-level bar
16
+ * links and triggers should use `data-navigation-item` (added by the view helpers).
17
+ *
18
+ * @see https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/
19
+ * @element rui-navigation-menu
20
+ * @slot triggers - Top-level navigation triggers and plain links.
21
+ * @slot panels - Disclosure panels composed from other primitives.
22
+ */
23
+ export declare class RuiNavigationMenu extends RadiantElement<RuiNavigationMenuBindings> {
24
+ label: string;
25
+ private readonly resolvedAriaLabel;
26
+ private openValue;
27
+ connectedCallback(): void;
28
+ private getBarItems;
29
+ private syncBarRovingTabindex;
30
+ private isBarTrigger;
31
+ private getTriggers;
32
+ private getPanel;
33
+ private getTrigger;
34
+ private getPanels;
35
+ private focusPanelEntry;
36
+ private syncPanels;
37
+ private closeMenu;
38
+ private openPanel;
39
+ private getEventElement;
40
+ private isWithinOpenPanel;
41
+ onDocumentClick(event: MouseEvent): void;
42
+ onDocumentKeydown(event: KeyboardEvent): void;
43
+ onRootKeydown(event: KeyboardEvent): void;
44
+ onTriggerClick(event: Event): void;
45
+ onBarItemKeydown(event: KeyboardEvent): void;
46
+ onPanelKeydown(event: KeyboardEvent): void;
47
+ render(): import("@ecopages/jsx").JsxRenderable;
48
+ }
49
+ export {};
@@ -0,0 +1,2 @@
1
+ export { RuiRadioGroup as RuiRadioGroupElement, type RuiRadioGroupProps, type RuiRadioGroupChangeDetail, } from './radio-group.script';
2
+ export { RuiRadioGroup, type RuiRadioOption } from './radio-group';
@@ -0,0 +1,2 @@
1
+ import{RadiantElement as R,customElement as c,event as m,onEvent as g,onUpdated as b,prop as n}from"@ecopages/radiant";var i=@c("rui-radio-group")class extends R{@n({type:String,reflect:!0,defaultValue:""})value;@n({type:String,defaultValue:""})name;@n({type:String,defaultValue:""})label;@n({type:Boolean,reflect:!0,defaultValue:!1})disabled;@m({name:"rui-change",bubbles:!0,composed:!0})changeEvent;resolvedAriaLabel=this.$.label.map(e=>e||void 0);resolvedAriaDisabled=this.$.disabled.map(e=>e?"true":void 0);connectedCallback(){super.connectedCallback(),this.syncRadios()}@b(["value","name","disabled"])syncRadios(){let e=this.querySelectorAll('input[type="radio"]'),t=this.name||this.getAttribute("name")||"rui-radio-group";for(let a of e)a.name=t,a.disabled=this.disabled||a.hasAttribute("data-disabled"),a.checked=this.value!==""&&a.value===this.value}@g({selector:'input[type="radio"]',type:"change"})onRadioChange(e){let t=e.target;t.checked&&(this.value=t.value,this.changeEvent.emit({value:this.value}))}render(){return React.createElement("div",{class:"rui-radio-group",role:"radiogroup","data-rui-control":!0,"data-rui-control-type":"text","aria-label":this.resolvedAriaLabel,"aria-disabled":this.resolvedAriaDisabled},React.createElement("slot",null))}};var v=Symbol.for("@ecopages/storybook-radiant.viewElement"),s=Symbol.for("@ecopages/storybook-radiant.scriptModule"),d=Symbol.for("@ecopages/storybook-radiant.scriptExport");function A(o,e){o[v]=e;let t=e[s];t&&(o[s]=t,o[d]=e[d]??e.name)}function l(o,e){let t=(a=>e(a));return A(t,o),t}import"./radio-group.css";var E=l(i,({slot:o,value:e,name:t,label:a,disabled:u,options:p})=>React.createElement("rui-radio-group",{slot:o,value:e,name:t,label:a,disabled:u},p.map(r=>React.createElement("label",{class:"rui-radio"},React.createElement("input",{type:"radio",class:"rui-radio__input",value:r.value,disabled:r.disabled,"data-disabled":r.disabled?"":void 0}),React.createElement("span",{class:"rui-radio__control","aria-hidden":"true"}),React.createElement("span",{class:"rui-radio__label"},r.label)))));export{E as RuiRadioGroup,i as RuiRadioGroupElement};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/components/ui/radio-group/radio-group.script.tsx", "../../../../src/lib/radiant-view.ts", "../../../../src/components/ui/radio-group/radio-group.tsx"],
4
+ "sourcesContent": ["import { RadiantElement, customElement, event, onEvent, onUpdated, prop } from '@ecopages/radiant';\nimport type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';\n\nexport type RuiRadioGroupProps = {\n\t/** Currently selected value. Reflects to markup. */\n\tvalue?: string;\n\t/** Form field name shared by all radios in the group. */\n\tname?: string;\n\t/** Accessible name for the group when no visible legend is slotted. */\n\tlabel?: string;\n\t/** Disable every radio in the group. Default: `false`. */\n\tdisabled?: boolean;\n};\n\nexport type RuiRadioGroupChangeDetail = {\n\tvalue: string;\n};\n\ntype RuiRadioGroupBindings = {\n\tlabel: string;\n\tdisabled: boolean;\n};\n\n/**\n * `<rui-radio-group>` \u2014 a set of radio buttons where only one option may\n * be selected at a time.\n *\n * Implements the WAI-ARIA APG Radio Group pattern using native\n * `<input type=\"radio\">` controls inside a `role=\"radiogroup\"` container.\n * Arrow-key navigation and Space activation are provided by the browser.\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/radio/\n *\n * Keyboard interaction (native radio group):\n * - `Tab` / `Shift+Tab`: move focus into and out of the group\n * - `Arrow` keys: move selection between radios\n * - `Space`: check the focused radio\n *\n * @element rui-radio-group\n * @slot - One or more `<label>` children each wrapping a radio input with a unique `value`.\n * @fires rui-change - Emitted after the selected value changes; `detail.value` holds the new value.\n */\n@customElement('rui-radio-group')\nexport class RuiRadioGroup extends RadiantElement<RuiRadioGroupBindings> {\n\t@prop({ type: String, reflect: true, defaultValue: '' }) value: string;\n\t@prop({ type: String, defaultValue: '' }) name: string;\n\t@prop({ type: String, defaultValue: '' }) label: string;\n\t@prop({ type: Boolean, reflect: true, defaultValue: false }) disabled: boolean;\n\n\t@event({ name: 'rui-change', bubbles: true, composed: true })\n\tchangeEvent: EventEmitter<RuiRadioGroupChangeDetail>;\n\n\tprivate readonly resolvedAriaLabel = this.$.label.map((label) => label || undefined);\n\tprivate readonly resolvedAriaDisabled = this.$.disabled.map((disabled) => (disabled ? 'true' : undefined));\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tthis.syncRadios();\n\t}\n\n\t@onUpdated(['value', 'name', 'disabled'])\n\tsyncRadios(): void {\n\t\tconst radios = this.querySelectorAll<HTMLInputElement>('input[type=\"radio\"]');\n\t\tconst groupName = this.name || this.getAttribute('name') || 'rui-radio-group';\n\t\tfor (const radio of radios) {\n\t\t\tradio.name = groupName;\n\t\t\tradio.disabled = this.disabled || radio.hasAttribute('data-disabled');\n\t\t\tradio.checked = this.value !== '' && radio.value === this.value;\n\t\t}\n\t}\n\n\t@onEvent({ selector: 'input[type=\"radio\"]', type: 'change' })\n\tonRadioChange(event: Event): void {\n\t\tconst input = event.target as HTMLInputElement;\n\t\tif (!input.checked) return;\n\t\tthis.value = input.value;\n\t\tthis.changeEvent.emit({ value: this.value });\n\t}\n\n\toverride render() {\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclass=\"rui-radio-group\"\n\t\t\t\trole=\"radiogroup\"\n\t\t\t\tdata-rui-control\n\t\t\t\tdata-rui-control-type=\"text\"\n\t\t\t\taria-label={this.resolvedAriaLabel}\n\t\t\t\taria-disabled={this.resolvedAriaDisabled}\n\t\t\t>\n\t\t\t\t<slot></slot>\n\t\t\t</div>\n\t\t);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\n\nconst RADIANT_VIEW_ELEMENT = Symbol.for('@ecopages/storybook-radiant.viewElement');\nconst RADIANT_SCRIPT_MODULE = Symbol.for('@ecopages/storybook-radiant.scriptModule');\nconst RADIANT_SCRIPT_EXPORT = Symbol.for('@ecopages/storybook-radiant.scriptExport');\n\nexport type RadiantViewComponent<TArgs = unknown> = ((args: TArgs) => JsxRenderable) & {\n\t[RADIANT_VIEW_ELEMENT]?: CustomElementConstructor;\n\t[RADIANT_SCRIPT_MODULE]?: string;\n\t[RADIANT_SCRIPT_EXPORT]?: string;\n};\n\nfunction linkViewToElement<TArgs>(\n\tview: RadiantViewComponent<TArgs>,\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n): void {\n\tview[RADIANT_VIEW_ELEMENT] = element;\n\n\tconst ssrModule = element[RADIANT_SCRIPT_MODULE];\n\tif (ssrModule) {\n\t\tview[RADIANT_SCRIPT_MODULE] = ssrModule;\n\t\tview[RADIANT_SCRIPT_EXPORT] = element[RADIANT_SCRIPT_EXPORT] ?? element.name;\n\t}\n}\n\n/** Link a JSX view export to its RadiantElement class (same symbols as the Storybook framework). */\nexport function defineRadiantView<TArgs>(\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n\trender: (args: TArgs) => JsxRenderable,\n): RadiantViewComponent<TArgs> {\n\tconst view = ((args: TArgs) => render(args)) as RadiantViewComponent<TArgs>;\n\tlinkViewToElement(view, element);\n\treturn view;\n}\n\n/** Re-copy SSR metadata from the linked element (e.g. after HMR). */\nexport function syncRadiantViewMetadata(view: RadiantViewComponent): void {\n\tconst element = view[RADIANT_VIEW_ELEMENT];\n\tif (element) {\n\t\tlinkViewToElement(view, element);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\nimport type { RadiantSlotProps } from '../../../types';\nimport { defineRadiantView } from '../../../lib/radiant-view';\nimport type { RuiRadioGroupProps } from './radio-group.script';\nimport { RuiRadioGroup as RuiRadioGroupElement } from './radio-group.script';\nimport './radio-group.css';\n\nexport type RuiRadioOption = {\n\tvalue: string;\n\tlabel: JsxRenderable;\n\tdisabled?: boolean;\n};\n\nexport const RuiRadioGroup = defineRadiantView(\n\tRuiRadioGroupElement,\n\t({\n\t\tslot,\n\t\tvalue,\n\t\tname,\n\t\tlabel,\n\t\tdisabled,\n\t\toptions,\n\t}: RuiRadioGroupProps &\n\t\tRadiantSlotProps & {\n\t\t\toptions: RuiRadioOption[];\n\t\t}) => (\n\t\t<rui-radio-group slot={slot} value={value} name={name} label={label} disabled={disabled}>\n\t\t\t{options.map((option) => (\n\t\t\t\t<label class=\"rui-radio\">\n\t\t\t\t\t<input\n\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\tclass=\"rui-radio__input\"\n\t\t\t\t\t\tvalue={option.value}\n\t\t\t\t\t\tdisabled={option.disabled}\n\t\t\t\t\t\tdata-disabled={option.disabled ? '' : undefined}\n\t\t\t\t\t/>\n\t\t\t\t\t<span class=\"rui-radio__control\" aria-hidden=\"true\"></span>\n\t\t\t\t\t<span class=\"rui-radio__label\">{option.label}</span>\n\t\t\t\t</label>\n\t\t\t))}\n\t\t</rui-radio-group>\n\t),\n);\n"],
5
+ "mappings": "AAAA,OAAS,kBAAAA,EAAgB,iBAAAC,EAAe,SAAAC,EAAO,WAAAC,EAAS,aAAAC,EAAW,QAAAC,MAAY,oBA2CxE,IAAMC,EADb,CAACL,EAAc,iBAAiB,CACzB,cAA4BD,CAAsC,CACxE,CAACK,EAAK,CAAE,KAAM,OAAQ,QAAS,GAAM,aAAc,EAAG,CAAC,CAAE,MACzD,CAACA,EAAK,CAAE,KAAM,OAAQ,aAAc,EAAG,CAAC,CAAE,KAC1C,CAACA,EAAK,CAAE,KAAM,OAAQ,aAAc,EAAG,CAAC,CAAE,MAC1C,CAACA,EAAK,CAAE,KAAM,QAAS,QAAS,GAAM,aAAc,EAAM,CAAC,CAAE,SAE7D,CAACH,EAAM,CAAE,KAAM,aAAc,QAAS,GAAM,SAAU,EAAK,CAAC,CAC5D,YAEiB,kBAAoB,KAAK,EAAE,MAAM,IAAKK,GAAUA,GAAS,MAAS,EAClE,qBAAuB,KAAK,EAAE,SAAS,IAAKC,GAAcA,EAAW,OAAS,MAAU,EAEhG,mBAA0B,CAClC,MAAM,kBAAkB,EACxB,KAAK,WAAW,CACjB,CAEA,CAACJ,EAAU,CAAC,QAAS,OAAQ,UAAU,CAAC,CACxC,YAAmB,CAClB,IAAMK,EAAS,KAAK,iBAAmC,qBAAqB,EACtEC,EAAY,KAAK,MAAQ,KAAK,aAAa,MAAM,GAAK,kBAC5D,QAAWC,KAASF,EACnBE,EAAM,KAAOD,EACbC,EAAM,SAAW,KAAK,UAAYA,EAAM,aAAa,eAAe,EACpEA,EAAM,QAAU,KAAK,QAAU,IAAMA,EAAM,QAAU,KAAK,KAE5D,CAEA,CAACR,EAAQ,CAAE,SAAU,sBAAuB,KAAM,QAAS,CAAC,CAC5D,cAAcD,EAAoB,CACjC,IAAMU,EAAQV,EAAM,OACfU,EAAM,UACX,KAAK,MAAQA,EAAM,MACnB,KAAK,YAAY,KAAK,CAAE,MAAO,KAAK,KAAM,CAAC,EAC5C,CAES,QAAS,CACjB,OACC,oBAAC,OACA,MAAM,kBACN,KAAK,aACL,mBAAgB,GAChB,wBAAsB,OACtB,aAAY,KAAK,kBACjB,gBAAe,KAAK,sBAEpB,oBAAC,WAAK,CACP,CAEF,CACD,EC3FA,IAAMC,EAAuB,OAAO,IAAI,yCAAyC,EAC3EC,EAAwB,OAAO,IAAI,0CAA0C,EAC7EC,EAAwB,OAAO,IAAI,0CAA0C,EAQnF,SAASC,EACRC,EACAC,EAIO,CACPD,EAAKJ,CAAoB,EAAIK,EAE7B,IAAMC,EAAYD,EAAQJ,CAAqB,EAC3CK,IACHF,EAAKH,CAAqB,EAAIK,EAC9BF,EAAKF,CAAqB,EAAIG,EAAQH,CAAqB,GAAKG,EAAQ,KAE1E,CAGO,SAASE,EACfF,EAIAG,EAC8B,CAC9B,IAAMJ,GAASK,GAAgBD,EAAOC,CAAI,GAC1C,OAAAN,EAAkBC,EAAMC,CAAO,EACxBD,CACR,CClCA,MAAO,oBAQA,IAAMM,EAAgBC,EAC5BD,EACA,CAAC,CACA,KAAAE,EACA,MAAAC,EACA,KAAAC,EACA,MAAAC,EACA,SAAAC,EACA,QAAAC,CACD,IAIC,oBAAC,mBAAgB,KAAML,EAAM,MAAOC,EAAO,KAAMC,EAAM,MAAOC,EAAO,SAAUC,GAC7EC,EAAQ,IAAKC,GACb,oBAAC,SAAM,MAAM,aACZ,oBAAC,SACA,KAAK,QACL,MAAM,mBACN,MAAOA,EAAO,MACd,SAAUA,EAAO,SACjB,gBAAeA,EAAO,SAAW,GAAK,OACvC,EACA,oBAAC,QAAK,MAAM,qBAAqB,cAAY,OAAO,EACpD,oBAAC,QAAK,MAAM,oBAAoBA,EAAO,KAAM,CAC9C,CACA,CACF,CAEF",
6
+ "names": ["RadiantElement", "customElement", "event", "onEvent", "onUpdated", "prop", "RuiRadioGroup", "label", "disabled", "radios", "groupName", "radio", "input", "RADIANT_VIEW_ELEMENT", "RADIANT_SCRIPT_MODULE", "RADIANT_SCRIPT_EXPORT", "linkViewToElement", "view", "element", "ssrModule", "defineRadiantView", "render", "args", "RuiRadioGroup", "defineRadiantView", "slot", "value", "name", "label", "disabled", "options", "option"]
7
+ }
@@ -0,0 +1,44 @@
1
+ @reference '../../../styles/radiant-ui.css';
2
+
3
+ rui-radio-group {
4
+ @apply block;
5
+ }
6
+
7
+ @layer components {
8
+ .rui-radio-group {
9
+ @apply flex flex-col gap-inline;
10
+ }
11
+
12
+ .rui-radio {
13
+ @apply inline-flex items-center gap-inline cursor-pointer text-sm text-on-background;
14
+ }
15
+
16
+ .rui-radio:has(input:disabled) {
17
+ @apply cursor-not-allowed opacity-disabled;
18
+ }
19
+
20
+ .rui-radio__input {
21
+ @apply sr-only;
22
+ }
23
+
24
+ .rui-radio__control {
25
+ @apply relative size-4 shrink-0 rounded-full border border-border bg-background;
26
+ }
27
+
28
+ .rui-radio__input:focus-visible + .rui-radio__control {
29
+ @apply ring-2 ring-focus-ring ring-offset-2;
30
+ }
31
+
32
+ .rui-radio__input:checked + .rui-radio__control {
33
+ @apply border-primary;
34
+ }
35
+
36
+ .rui-radio__input:checked + .rui-radio__control::after {
37
+ content: '';
38
+ @apply absolute left-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary;
39
+ }
40
+
41
+ .rui-radio__label {
42
+ @apply select-none;
43
+ }
44
+ }
@@ -0,0 +1,12 @@
1
+ import type { JsxRenderable } from '@ecopages/jsx';
2
+ import type { RadiantSlotProps } from '../../../types';
3
+ import type { RuiRadioGroupProps } from './radio-group.script';
4
+ import './radio-group.css';
5
+ export type RuiRadioOption = {
6
+ value: string;
7
+ label: JsxRenderable;
8
+ disabled?: boolean;
9
+ };
10
+ export declare const RuiRadioGroup: import("../../../lib/radiant-view").RadiantViewComponent<RuiRadioGroupProps & RadiantSlotProps & {
11
+ options: RuiRadioOption[];
12
+ }>;
@@ -0,0 +1,52 @@
1
+ import { RadiantElement } from '@ecopages/radiant';
2
+ import type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';
3
+ export type RuiRadioGroupProps = {
4
+ /** Currently selected value. Reflects to markup. */
5
+ value?: string;
6
+ /** Form field name shared by all radios in the group. */
7
+ name?: string;
8
+ /** Accessible name for the group when no visible legend is slotted. */
9
+ label?: string;
10
+ /** Disable every radio in the group. Default: `false`. */
11
+ disabled?: boolean;
12
+ };
13
+ export type RuiRadioGroupChangeDetail = {
14
+ value: string;
15
+ };
16
+ type RuiRadioGroupBindings = {
17
+ label: string;
18
+ disabled: boolean;
19
+ };
20
+ /**
21
+ * `<rui-radio-group>` — a set of radio buttons where only one option may
22
+ * be selected at a time.
23
+ *
24
+ * Implements the WAI-ARIA APG Radio Group pattern using native
25
+ * `<input type="radio">` controls inside a `role="radiogroup"` container.
26
+ * Arrow-key navigation and Space activation are provided by the browser.
27
+ *
28
+ * @see https://www.w3.org/WAI/ARIA/apg/patterns/radio/
29
+ *
30
+ * Keyboard interaction (native radio group):
31
+ * - `Tab` / `Shift+Tab`: move focus into and out of the group
32
+ * - `Arrow` keys: move selection between radios
33
+ * - `Space`: check the focused radio
34
+ *
35
+ * @element rui-radio-group
36
+ * @slot - One or more `<label>` children each wrapping a radio input with a unique `value`.
37
+ * @fires rui-change - Emitted after the selected value changes; `detail.value` holds the new value.
38
+ */
39
+ export declare class RuiRadioGroup extends RadiantElement<RuiRadioGroupBindings> {
40
+ value: string;
41
+ name: string;
42
+ label: string;
43
+ disabled: boolean;
44
+ changeEvent: EventEmitter<RuiRadioGroupChangeDetail>;
45
+ private readonly resolvedAriaLabel;
46
+ private readonly resolvedAriaDisabled;
47
+ connectedCallback(): void;
48
+ syncRadios(): void;
49
+ onRadioChange(event: Event): void;
50
+ render(): import("@ecopages/jsx").JsxRenderable;
51
+ }
52
+ export {};
@@ -0,0 +1,3 @@
1
+ export { RuiSidebar as RuiSidebarElement, type RuiSidebarProps, type RuiSidebarVariant, type RuiSidebarSide, type RuiSidebarCollapsible, type RuiSidebarState, type RuiSidebarToggleDetail, type RuiSidebarResizeDetail, } from './sidebar.script';
2
+ export { RuiSidebarTrigger as RuiSidebarTriggerElement, type RuiSidebarTriggerProps, type RuiSidebarTriggerPlacement, } from './sidebar-trigger.script';
3
+ export { RuiSidebar, RuiSidebarTrigger, RuiSidebarProvider, RuiSidebarHeader, RuiSidebarContent, RuiSidebarFooter, RuiSidebarSeparator, RuiSidebarGroup, RuiSidebarGroupLabel, RuiSidebarGroupAction, RuiSidebarGroupHeader, RuiSidebarMenu, RuiSidebarMenuItem, RuiSidebarMenuButton, RuiSidebarMenuAction, RuiSidebarInset, type RuiSidebarProviderProps, type RuiSidebarHeaderProps, type RuiSidebarContentProps, type RuiSidebarFooterProps, type RuiSidebarSeparatorProps, type RuiSidebarGroupProps, type RuiSidebarGroupLabelProps, type RuiSidebarGroupActionProps, type RuiSidebarGroupHeaderProps, type RuiSidebarMenuProps, type RuiSidebarMenuItemProps, type RuiSidebarMenuButtonProps, type RuiSidebarMenuActionProps, type RuiSidebarInsetProps, type RuiSidebarViewProps, type RuiSidebarTriggerViewProps, } from './sidebar';
@@ -0,0 +1,2 @@
1
+ import{RadiantElement as C,bound as u,customElement as L,event as f,onEvent as D,onUpdated as P,prop as o,query as m,state as W}from"@ecopages/radiant";var k=256,I=48,V=200,H=480,O=768,B="b",x=8,E=32;function z(i){return i.metaKey||i.ctrlKey}function N(){return typeof window<"u"&&typeof window.matchMedia=="function"}function R(i){return i==="left"||i==="right"}var p=@L("rui-sidebar")class extends C{@o({type:String,reflect:!0,defaultValue:"sidebar"})variant;@o({type:String,reflect:!0,defaultValue:"left"})side;@o({type:String,reflect:!0,defaultValue:"off"})collapsible;@o({type:Number,defaultValue:k})defaultWidth;@o({type:Number,reflect:!0,attribute:"width"})width;@o({type:Number,defaultValue:V})minWidth;@o({type:Number,defaultValue:H})maxWidth;@o({type:Boolean,defaultValue:!0})defaultOpen;@o({type:Boolean,attribute:"open"})open;@o({type:Number,defaultValue:O})mobileBreakpoint;@o({type:String,defaultValue:"Sidebar"})label;@m({ref:"root"})rootTarget;@m({ref:"pane"})paneTarget;@m({ref:"handle"})handleTarget;@m({ref:"scrim"})scrimTarget;@f({name:"rui-sidebar-toggle",bubbles:!0,composed:!0})toggleEvent;@f({name:"rui-sidebar-resize",bubbles:!0,composed:!0})resizeEvent;@f({name:"rui-sidebar-mobile-change",bubbles:!0,composed:!0})mobileChangeEvent;@W isMobile=!1;mediaQuery=null;mediaListener=e=>this.setMobile(e.matches);dragging=!1;dragStartCoord=0;dragStartSize=0;connectedCallback(){super.connectedCallback(),this.open===void 0&&(this.open=this.defaultOpen),this.ensureWidthInitialized(),this.setAttribute("role","complementary"),this.setAttribute("aria-label",this.label),this.syncHostAttributes(),queueMicrotask(()=>{this.open===void 0&&(this.open=this.defaultOpen),this.ensureWidthInitialized(),this.syncPaneWidthVar(),this.bindMobileMediaQuery()})}disconnectedCallback(){this.endDrag(),this.unbindMobileMediaQuery(),super.disconnectedCallback()}syncHostAttributes(){let e=this.isOpen()?"expanded":"collapsed";this.setAttribute("data-state",e),this.setAttribute("data-collapsible",this.collapsible),this.setAttribute("data-variant",this.variant),this.setAttribute("data-side",this.side),this.setAttribute("data-mobile",String(this.isMobile)),this.setAttribute("data-pane-width",String(this.paneWidth()))}isOpen(){return this.open!==!1}ensureWidthInitialized(){this.hasAttribute("width")||(this.width===void 0||this.width===0)&&(this.width=this.defaultWidth)}@P(["open","collapsible","variant","side","width","defaultWidth","defaultOpen","minWidth","maxWidth","isMobile"])onStateUpdated(){this.syncHostAttributes(),this.syncPaneWidthVar()}@P(["mobileBreakpoint"])onMobileBreakpointUpdated(){this.bindMobileMediaQuery()}unbindMobileMediaQuery(){this.mediaQuery?.removeEventListener("change",this.mediaListener),this.mediaQuery=null}bindMobileMediaQuery(){if(this.unbindMobileMediaQuery(),this.mobileBreakpoint<=0||!N()){this.setMobile(!1);return}this.mediaQuery=window.matchMedia(`(max-width: ${this.mobileBreakpoint-1}px)`),this.mediaQuery.addEventListener("change",this.mediaListener),this.setMobile(this.mediaQuery.matches)}setMobile(e){e!==this.isMobile&&(this.isMobile=e,this.mobileChangeEvent.emit({mobile:e}))}clampWidth(e){return Math.min(this.maxWidth,Math.max(this.minWidth,e))}paneWidth(){return this.isOpen()?this.width&&this.width>0?this.width:this.defaultWidth:this.isMobile?0:this.collapsible==="icon"?I:0}syncPaneWidthVar(e=this.paneWidth()){let t=this.rootTarget;t&&t.style.setProperty("--rui-sidebar-pane-width",`${e}px`),this.paneTarget&&(this.paneTarget.style.removeProperty("width"),this.paneTarget.style.removeProperty("height")),this.setAttribute("data-pane-width",String(e))}applyWidth(e,t){let r=this.clampWidth(e);this.width=r,this.syncPaneWidthVar(r),t&&this.resizeEvent.emit({width:r})}toggle(){this.setOpen(!this.isOpen())}setOpen(e){let t=this.isOpen();if(e===t){this.syncPaneWidthVar();return}this.open=e;let r=e?"expanded":"collapsed";this.setAttribute("data-state",r),this.syncPaneWidthVar(),this.toggleEvent.emit({open:e,state:r})}beginDrag(e){if(e.button!==0||this.collapsible!=="off")return;this.dragging=!0;let t=R(this.side);this.dragStartCoord=t?e.clientX:e.clientY,this.dragStartSize=this.paneWidth(),this.handleTarget?.setPointerCapture(e.pointerId),document.addEventListener("pointermove",this.onPointerMove),document.addEventListener("pointerup",this.onPointerUp),document.addEventListener("pointercancel",this.onPointerUp)}endDrag(){this.dragging&&(this.dragging=!1,document.removeEventListener("pointermove",this.onPointerMove),document.removeEventListener("pointerup",this.onPointerUp),document.removeEventListener("pointercancel",this.onPointerUp))}@u onPointerMove(e){if(!this.dragging)return;let r=R(this.side)?e.clientX:e.clientY,a=this.side==="right"?this.dragStartCoord-r:r-this.dragStartCoord;this.applyWidth(this.dragStartSize+a,!0)}@u onPointerUp(){this.endDrag()}@u onHandlePointerDown(e){e.preventDefault(),this.beginDrag(e)}@u onHandleKeydown(e){let t=e,r=this.paneWidth(),a=R(this.side),l=a?"ArrowLeft":"ArrowUp",d=a?"ArrowRight":"ArrowDown",s=r;if(t.key===l)s=r-(t.shiftKey?E:x);else if(t.key===d)s=r+(t.shiftKey?E:x);else if(t.key==="Home")s=this.minWidth;else if(t.key==="End")s=this.maxWidth;else return;e.preventDefault(),this.applyWidth(s,!0)}@u onScrimClick(){this.isMobile&&this.setOpen(!1)}@D({document:!0,type:"keydown"})onHostKeydown(e){let t=e;if(t.key==="Escape"&&this.isMobile&&this.isOpen()){t.preventDefault(),this.setOpen(!1);return}z(t)&&t.key.toLowerCase()===B&&(t.preventDefault(),this.toggle())}render(){let e=R(this.side),t=this.isOpen(),r=t?"expanded":"collapsed",a=this.collapsible==="off"&&t&&!this.isMobile,l=`${this.paneWidth()}px`,d=t||!this.isMobile&&this.collapsible==="icon"?void 0:"";return React.createElement("div",{class:"rui-sidebar",style:{"--rui-sidebar-pane-width":l},"data-ref":"root","data-state":r,"data-collapsible":this.collapsible,"data-variant":this.variant,"data-side":this.side,"data-mobile":String(this.isMobile)},React.createElement("button",{"data-ref":"scrim",type:"button",class:"rui-sidebar__scrim",tabindex:-1,"aria-label":"Close sidebar",hidden:!this.isMobile||!t,"on:click":this.onScrimClick}),React.createElement("div",{"data-ref":"pane",class:"rui-sidebar__pane","data-side":this.side,"data-variant":this.variant,"aria-label":this.$.label,inert:d},React.createElement("slot",null)),a?React.createElement("div",{"data-ref":"handle",class:"rui-sidebar__handle",role:"separator",tabindex:0,"aria-orientation":e?"vertical":"horizontal","aria-valuenow":this.paneWidth(),"aria-valuemin":this.minWidth,"aria-valuemax":this.maxWidth,"aria-label":`${this.label} resize handle`,"on:pointerdown":this.onHandlePointerDown,"on:keydown":this.onHandleKeydown},React.createElement("span",{class:"rui-sidebar__handle-grip","aria-hidden":"true"})):null)}};import{RadiantElement as G,bound as J,customElement as U,onUpdated as K,prop as b,query as Q}from"@ecopages/radiant";var c=@U("rui-sidebar-trigger")class extends G{@b({type:String,defaultValue:""})controls;@b({type:String,attribute:"button-label",defaultValue:"Toggle sidebar"})buttonLabel;@b({type:String,reflect:!0,attribute:"data-placement",defaultValue:""})placement;@b({type:String,defaultValue:"ghost"})variant;@b({type:String,defaultValue:"md"})size;@Q({ref:"button"})buttonTarget;sidebarListener=null;attachedSidebar=null;connectedCallback(){super.connectedCallback(),this.syncWithSidebar(),queueMicrotask(()=>this.syncWithSidebar())}disconnectedCallback(){this.detachFromSidebar(),super.disconnectedCallback()}@K(["controls","buttonLabel","placement"])onControlsUpdated(){this.detachFromSidebar(),this.syncWithSidebar(),this.applyState(this.attachedSidebar?this.readState(this.attachedSidebar):"expanded")}resolveSidebar(){let e=this.controls?.trim();if(e){let r=document.getElementById(e);if(r)return r}let t=this.closest("rui-sidebar");return t?.id?t:null}syncWithSidebar(){let e=this.resolveSidebar();if(e===this.attachedSidebar){e&&this.applyState(this.readState(e));return}this.detachFromSidebar(),e&&(this.attachedSidebar=e,this.sidebarListener=t=>{let r=t.detail;this.applyState(r.state)},e.addEventListener("rui-sidebar-toggle",this.sidebarListener),this.applyState(this.readState(e)))}detachFromSidebar(){this.attachedSidebar&&this.sidebarListener&&this.attachedSidebar.removeEventListener("rui-sidebar-toggle",this.sidebarListener),this.attachedSidebar=null,this.sidebarListener=null}readState(e){return e.getAttribute("data-state")??"expanded"}resolvedButtonLabel(){let e=this.getAttribute("data-button-label")?.trim();if(e)return e;let t=this.getAttribute("button-label")?.trim();return t||this.buttonLabel||"Toggle sidebar"}applyState(e){let t=this.buttonTarget;if(!t)return;let r=this.resolveSidebar(),a=this.resolvedButtonLabel();t.setAttribute("aria-expanded",String(e==="expanded")),t.setAttribute("data-sidebar-state",e),t.setAttribute("aria-label",a),r?.id?t.setAttribute("aria-controls",r.id):this.controls&&t.setAttribute("aria-controls",this.controls)}@J onClick(e){e.preventDefault();let t=this.resolveSidebar();t&&typeof t.toggle=="function"&&t.toggle()}placementClass(){return this.placement==="header"?"rui-sidebar__trigger--header":this.placement==="inset"?"rui-sidebar__trigger--inset":""}renderDefaultIcon(){let e=this.resolveSidebar(),t=e?this.readState(e):"expanded",r=this.placement==="header"||this.placement!=="inset"&&t==="expanded",a=this.placement==="inset"||this.placement!=="header"&&t==="collapsed";return React.createElement("span",{class:"rui-sidebar__trigger-icon","aria-hidden":"true"},r?React.createElement("svg",{class:"rui-sidebar__trigger-glyph rui-sidebar__trigger-glyph--collapse",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},React.createElement("path",{d:"M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),React.createElement("path",{d:"M9 3v18"}),React.createElement("path",{d:"m14 15 3-3-3-3"})):null,a?React.createElement("svg",{class:"rui-sidebar__trigger-glyph rui-sidebar__trigger-glyph--expand",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},React.createElement("path",{d:"M3 5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}),React.createElement("path",{d:"M9 3v18"}),React.createElement("path",{d:"m14 9-3 3 3 3"})):null)}render(){let e=this.resolveSidebar(),t=e?.id||this.controls||null,r=this.resolvedButtonLabel(),a=e?this.readState(e):"expanded";return React.createElement("button",{"data-ref":"button",type:"button",class:`rui-button rui-button--${this.variant} rui-button--${this.size} rui-sidebar__trigger ${this.placementClass()}`.trim(),"data-sidebar-state":a,"aria-expanded":String(a==="expanded"),"aria-controls":t||null,"aria-label":r,"on-native:click":this.onClick},React.createElement("slot",null,this.renderDefaultIcon()))}};var F=Symbol.for("@ecopages/storybook-radiant.viewElement"),T=Symbol.for("@ecopages/storybook-radiant.scriptModule"),M=Symbol.for("@ecopages/storybook-radiant.scriptExport");function $(i,e){i[F]=e;let t=e[T];t&&(i[T]=t,i[M]=e[M]??e.name)}function y(i,e){let t=(r=>e(r));return $(t,i),t}import"./sidebar.css";function n(...i){return i.filter(Boolean).join(" ")}function X({layout:i="default",sidebar:e,children:t,class:r}){return React.createElement("div",{class:n("rui-sidebar-provider",r),"data-layout":i},e,t)}function j({children:i,class:e,"aria-label":t}){return React.createElement("div",{class:n("rui-sidebar__header",e),"aria-label":t},i)}function Y({children:i,class:e,"aria-label":t}){return React.createElement("div",{class:n("rui-sidebar__content",e),"aria-label":t},i)}function q({children:i,class:e}){return React.createElement("div",{class:n("rui-sidebar__footer",e)},i)}function Z({class:i,"aria-label":e}){return React.createElement("hr",{role:"separator","aria-orientation":"horizontal","aria-label":e,class:n("rui-sidebar__separator",i)})}function ee({children:i,class:e,"aria-label":t}){return React.createElement("section",{class:n("rui-sidebar__group",e),"aria-label":t},i)}function _({children:i,class:e,id:t}){return React.createElement("h2",{id:t,class:n("rui-sidebar__group-label",e)},i)}function te({children:i,class:e,"aria-label":t}){return React.createElement("button",{type:"button","aria-label":t,class:n("rui-sidebar__group-action",e)},i)}function ie({label:i,action:e,class:t}){return React.createElement("div",{class:n("rui-sidebar__group-header",t)},React.createElement(_,null,i),e)}function re({children:i,class:e,"aria-label":t}){return React.createElement("ul",{role:"list",class:n("rui-sidebar__menu",e),"aria-label":t},i)}function ae({children:i,class:e}){return React.createElement("li",{class:n("rui-sidebar__menu-item",e)},i)}function A({children:i,class:e,isActive:t,as:r,href:a,type:l="button",tooltip:d,disabled:s,onClick:v}){let h=n("rui-sidebar__menu-button",t&&"rui-sidebar__menu-button--active",e),g=d,S=typeof i=="string"?void 0:d;return r==="button"||!r&&!a?React.createElement("button",{type:l,class:h,"aria-current":t?"page":void 0,disabled:s,title:g,"aria-label":S,"on:click":v},i):React.createElement("a",{href:a,class:h,"aria-current":t?"page":void 0,title:g,"aria-label":S},i)}function ne(i){let{class:e,...t}=i;return React.createElement(A,{class:n("rui-sidebar__menu-action",e),...t})}function se({children:i,class:e,id:t}){return React.createElement("main",{id:t,class:n("rui-sidebar__inset",e)},i)}var oe=y(p,({slot:i,id:e,variant:t,side:r,collapsible:a,defaultOpen:l,open:d,defaultWidth:s,width:v,mobileBreakpoint:h,label:g,class:S,children:w})=>React.createElement("rui-sidebar",{slot:i,id:e,class:S,variant:t,side:r,collapsible:a,"prop:defaultOpen":l,"prop:open":d,"prop:defaultWidth":s,"prop:width":v,"prop:mobileBreakpoint":h,label:g},w)),de=y(c,({slot:i,controls:e,triggerLabel:t,placement:r,variant:a,size:l,class:d,children:s})=>React.createElement("rui-sidebar-trigger",{slot:i,class:d,"prop:controls":e,"prop:buttonLabel":t??"Toggle sidebar","attr:data-button-label":t??"Toggle sidebar","prop:placement":r,"attr:data-placement":r,variant:a,size:l},s));export{oe as RuiSidebar,Y as RuiSidebarContent,p as RuiSidebarElement,q as RuiSidebarFooter,ee as RuiSidebarGroup,te as RuiSidebarGroupAction,ie as RuiSidebarGroupHeader,_ as RuiSidebarGroupLabel,j as RuiSidebarHeader,se as RuiSidebarInset,re as RuiSidebarMenu,ne as RuiSidebarMenuAction,A as RuiSidebarMenuButton,ae as RuiSidebarMenuItem,X as RuiSidebarProvider,Z as RuiSidebarSeparator,de as RuiSidebarTrigger,c as RuiSidebarTriggerElement};
2
+ //# sourceMappingURL=index.js.map