@ecopages/radiant-ui 0.1.0-rc.7 → 0.1.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 (238) hide show
  1. package/README.md +11 -3
  2. package/dist/components/ui/alert/alert.d.ts +2 -4
  3. package/dist/components/ui/alert/alert.script.d.ts +25 -15
  4. package/dist/components/ui/autocomplete/autocomplete.css +1 -2
  5. package/dist/components/ui/autocomplete/autocomplete.d.ts +8 -3
  6. package/dist/components/ui/autocomplete/autocomplete.script.d.ts +29 -4
  7. package/dist/components/ui/avatar/avatar.css +10 -8
  8. package/dist/components/ui/avatar/avatar.d.ts +3 -1
  9. package/dist/components/ui/breadcrumb/breadcrumb.d.ts +11 -11
  10. package/dist/components/ui/breadcrumb/breadcrumb.script.d.ts +10 -10
  11. package/dist/components/ui/calendar/calendar.css +10 -5
  12. package/dist/components/ui/calendar/calendar.script.d.ts +24 -21
  13. package/dist/components/ui/calendar/index.js +1 -1
  14. package/dist/components/ui/calendar/index.js.map +3 -3
  15. package/dist/components/ui/carousel/carousel-autoplay.d.ts +22 -0
  16. package/dist/components/ui/carousel/carousel-swipe.d.ts +17 -0
  17. package/dist/components/ui/carousel/carousel-window.d.ts +63 -0
  18. package/dist/components/ui/carousel/carousel.css +71 -18
  19. package/dist/components/ui/carousel/carousel.d.ts +8 -4
  20. package/dist/components/ui/carousel/carousel.script.d.ts +73 -40
  21. package/dist/components/ui/carousel/index.js +1 -1
  22. package/dist/components/ui/carousel/index.js.map +4 -4
  23. package/dist/components/ui/checkbox/checkbox.d.ts +11 -0
  24. package/dist/components/ui/checkbox/checkbox.script.d.ts +31 -8
  25. package/dist/components/ui/checkbox/index.js +1 -1
  26. package/dist/components/ui/checkbox/index.js.map +4 -4
  27. package/dist/components/ui/checkbox-group/checkbox-group.d.ts +4 -2
  28. package/dist/components/ui/checkbox-group/checkbox-group.script.d.ts +39 -20
  29. package/dist/components/ui/checkbox-group/index.js +1 -1
  30. package/dist/components/ui/checkbox-group/index.js.map +4 -4
  31. package/dist/components/ui/combobox/combobox.css +9 -1
  32. package/dist/components/ui/combobox/combobox.d.ts +12 -4
  33. package/dist/components/ui/combobox/combobox.script.d.ts +74 -25
  34. package/dist/components/ui/combobox/index.d.ts +2 -2
  35. package/dist/components/ui/combobox/index.js +1 -1
  36. package/dist/components/ui/combobox/index.js.map +4 -4
  37. package/dist/components/ui/cycle-toggle/cycle-toggle.d.ts +6 -2
  38. package/dist/components/ui/cycle-toggle/cycle-toggle.script.d.ts +35 -4
  39. package/dist/components/ui/cycle-toggle/index.js +1 -1
  40. package/dist/components/ui/cycle-toggle/index.js.map +3 -3
  41. package/dist/components/ui/date-field/date-field.css +13 -17
  42. package/dist/components/ui/date-field/date-field.d.ts +10 -8
  43. package/dist/components/ui/date-field/date-field.script.d.ts +35 -52
  44. package/dist/components/ui/date-field/index.js +1 -1
  45. package/dist/components/ui/date-field/index.js.map +4 -4
  46. package/dist/components/ui/date-input/date-input-segment-dom.d.ts +24 -0
  47. package/dist/components/ui/date-input/date-input.css +50 -0
  48. package/dist/components/ui/date-input/date-input.d.ts +8 -0
  49. package/dist/components/ui/date-input/date-input.script.d.ts +137 -0
  50. package/dist/components/ui/date-input/index.d.ts +2 -0
  51. package/dist/components/ui/date-input/index.js +2 -0
  52. package/dist/components/ui/date-input/index.js.map +7 -0
  53. package/dist/components/ui/date-range-picker/date-range-picker.css +18 -19
  54. package/dist/components/ui/date-range-picker/date-range-picker.d.ts +11 -9
  55. package/dist/components/ui/date-range-picker/date-range-picker.script.d.ts +42 -51
  56. package/dist/components/ui/date-range-picker/index.js +1 -1
  57. package/dist/components/ui/date-range-picker/index.js.map +4 -4
  58. package/dist/components/ui/dialog/dialog.css +18 -14
  59. package/dist/components/ui/dialog/dialog.d.ts +6 -0
  60. package/dist/components/ui/dialog/dialog.script.d.ts +43 -10
  61. package/dist/components/ui/dialog/index.js +1 -1
  62. package/dist/components/ui/dialog/index.js.map +4 -4
  63. package/dist/components/ui/disclosure/disclosure-group.script.d.ts +19 -3
  64. package/dist/components/ui/disclosure/disclosure.css +3 -6
  65. package/dist/components/ui/disclosure/disclosure.d.ts +23 -7
  66. package/dist/components/ui/disclosure/disclosure.script.d.ts +31 -7
  67. package/dist/components/ui/disclosure/index.d.ts +1 -1
  68. package/dist/components/ui/disclosure/index.js +1 -1
  69. package/dist/components/ui/disclosure/index.js.map +4 -4
  70. package/dist/components/ui/field/field-description.d.ts +1 -0
  71. package/dist/components/ui/field/field-error.d.ts +2 -2
  72. package/dist/components/ui/field/field.d.ts +4 -4
  73. package/dist/components/ui/field/field.script.d.ts +54 -24
  74. package/dist/components/ui/field/index.js +1 -1
  75. package/dist/components/ui/field/index.js.map +4 -4
  76. package/dist/components/ui/form/control-protocol.d.ts +38 -1
  77. package/dist/components/ui/form/form-context.d.ts +3 -0
  78. package/dist/components/ui/form/form.d.ts +6 -0
  79. package/dist/components/ui/form/form.script.d.ts +29 -12
  80. package/dist/components/ui/form/index.d.ts +2 -1
  81. package/dist/components/ui/form/index.js +1 -1
  82. package/dist/components/ui/form/index.js.map +4 -4
  83. package/dist/components/ui/grid/grid.d.ts +4 -3
  84. package/dist/components/ui/grid/grid.script.d.ts +19 -11
  85. package/dist/components/ui/hover-card/hover-card.css +12 -101
  86. package/dist/components/ui/hover-card/hover-card.d.ts +7 -2
  87. package/dist/components/ui/hover-card/hover-card.script.d.ts +36 -5
  88. package/dist/components/ui/hover-card/index.js +1 -1
  89. package/dist/components/ui/hover-card/index.js.map +4 -4
  90. package/dist/components/ui/input/index.js +1 -1
  91. package/dist/components/ui/input/index.js.map +4 -4
  92. package/dist/components/ui/input/input.css +1 -1
  93. package/dist/components/ui/knob/index.js +1 -1
  94. package/dist/components/ui/knob/index.js.map +3 -3
  95. package/dist/components/ui/knob/knob.css +6 -1
  96. package/dist/components/ui/knob/knob.d.ts +4 -4
  97. package/dist/components/ui/knob/knob.script.d.ts +55 -20
  98. package/dist/components/ui/label/index.js +1 -1
  99. package/dist/components/ui/label/index.js.map +4 -4
  100. package/dist/components/ui/label/label.d.ts +2 -1
  101. package/dist/components/ui/listbox/index.d.ts +2 -2
  102. package/dist/components/ui/listbox/index.js +1 -1
  103. package/dist/components/ui/listbox/index.js.map +4 -4
  104. package/dist/components/ui/listbox/listbox.css +14 -0
  105. package/dist/components/ui/listbox/listbox.d.ts +16 -2
  106. package/dist/components/ui/listbox/listbox.script.d.ts +55 -12
  107. package/dist/components/ui/menu-button/index.js +1 -1
  108. package/dist/components/ui/menu-button/index.js.map +4 -4
  109. package/dist/components/ui/menu-button/menu-button.d.ts +2 -2
  110. package/dist/components/ui/menu-button/menu-button.script.d.ts +30 -27
  111. package/dist/components/ui/menubar/index.js +1 -1
  112. package/dist/components/ui/menubar/index.js.map +4 -4
  113. package/dist/components/ui/menubar/menubar.script.d.ts +41 -15
  114. package/dist/components/ui/meter/index.js +1 -1
  115. package/dist/components/ui/meter/index.js.map +3 -3
  116. package/dist/components/ui/meter/meter.css +27 -2
  117. package/dist/components/ui/meter/meter.script.d.ts +19 -14
  118. package/dist/components/ui/navigation-menu/index.d.ts +1 -1
  119. package/dist/components/ui/navigation-menu/index.js +1 -1
  120. package/dist/components/ui/navigation-menu/index.js.map +4 -4
  121. package/dist/components/ui/navigation-menu/navigation-menu.css +32 -34
  122. package/dist/components/ui/navigation-menu/navigation-menu.d.ts +34 -5
  123. package/dist/components/ui/navigation-menu/navigation-menu.script.d.ts +93 -12
  124. package/dist/components/ui/number-field/index.js +1 -1
  125. package/dist/components/ui/number-field/index.js.map +4 -4
  126. package/dist/components/ui/number-field/number-field.css +1 -1
  127. package/dist/components/ui/number-field/number-field.d.ts +8 -19
  128. package/dist/components/ui/number-field/number-field.script.d.ts +30 -9
  129. package/dist/components/ui/pagination/index.d.ts +1 -1
  130. package/dist/components/ui/pagination/index.js +1 -1
  131. package/dist/components/ui/pagination/index.js.map +3 -3
  132. package/dist/components/ui/pagination/pagination.css +50 -13
  133. package/dist/components/ui/pagination/pagination.d.ts +33 -9
  134. package/dist/components/ui/pagination/pagination.script.d.ts +29 -9
  135. package/dist/components/ui/popover/index.js +1 -1
  136. package/dist/components/ui/popover/index.js.map +4 -4
  137. package/dist/components/ui/popover/popover.d.ts +17 -1
  138. package/dist/components/ui/popover/popover.script.d.ts +57 -9
  139. package/dist/components/ui/radio-group/index.js +1 -1
  140. package/dist/components/ui/radio-group/index.js.map +4 -4
  141. package/dist/components/ui/radio-group/radio-group.d.ts +2 -2
  142. package/dist/components/ui/radio-group/radio-group.script.d.ts +35 -16
  143. package/dist/components/ui/select/index.d.ts +2 -2
  144. package/dist/components/ui/select/index.js +1 -1
  145. package/dist/components/ui/select/index.js.map +4 -4
  146. package/dist/components/ui/select/select.css +8 -6
  147. package/dist/components/ui/select/select.d.ts +18 -9
  148. package/dist/components/ui/select/select.script.d.ts +74 -26
  149. package/dist/components/ui/shared/calendar-popover-behavior.d.ts +27 -0
  150. package/dist/components/ui/shared/control-toggle.css +8 -4
  151. package/dist/components/ui/shared/field-label.d.ts +5 -0
  152. package/dist/components/ui/shared/listbox-host-controller.d.ts +41 -0
  153. package/dist/components/ui/shared/listbox-option.d.ts +4 -0
  154. package/dist/components/ui/shared/multi-value.d.ts +23 -1
  155. package/dist/components/ui/shared/numeric-range.d.ts +8 -0
  156. package/dist/components/ui/shared/popover.css +10 -99
  157. package/dist/components/ui/sidebar/index.d.ts +2 -1
  158. package/dist/components/ui/sidebar/index.js +1 -1
  159. package/dist/components/ui/sidebar/index.js.map +4 -4
  160. package/dist/components/ui/sidebar/sidebar-trigger.d.ts +12 -0
  161. package/dist/components/ui/sidebar/sidebar-trigger.script.d.ts +52 -31
  162. package/dist/components/ui/sidebar/sidebar.css +67 -61
  163. package/dist/components/ui/sidebar/sidebar.d.ts +9 -4
  164. package/dist/components/ui/sidebar/sidebar.script.d.ts +42 -20
  165. package/dist/components/ui/slider/index.js +1 -1
  166. package/dist/components/ui/slider/index.js.map +4 -4
  167. package/dist/components/ui/slider/slider.css +5 -5
  168. package/dist/components/ui/slider/slider.d.ts +20 -10
  169. package/dist/components/ui/slider/slider.script.d.ts +103 -27
  170. package/dist/components/ui/switch/index.js +1 -1
  171. package/dist/components/ui/switch/index.js.map +4 -4
  172. package/dist/components/ui/switch/switch.css +28 -22
  173. package/dist/components/ui/switch/switch.d.ts +13 -0
  174. package/dist/components/ui/switch/switch.script.d.ts +34 -8
  175. package/dist/components/ui/table/index.js +1 -1
  176. package/dist/components/ui/table/index.js.map +4 -4
  177. package/dist/components/ui/table/table.d.ts +9 -7
  178. package/dist/components/ui/table/table.script.d.ts +55 -12
  179. package/dist/components/ui/tabs/tabs.css +18 -12
  180. package/dist/components/ui/tabs/tabs.d.ts +7 -4
  181. package/dist/components/ui/tabs/tabs.script.d.ts +39 -9
  182. package/dist/components/ui/tag-group/index.js +1 -1
  183. package/dist/components/ui/tag-group/index.js.map +4 -4
  184. package/dist/components/ui/tag-group/tag-group.d.ts +19 -7
  185. package/dist/components/ui/tag-group/tag-group.script.d.ts +58 -10
  186. package/dist/components/ui/textarea/index.js +1 -1
  187. package/dist/components/ui/textarea/index.js.map +4 -4
  188. package/dist/components/ui/textarea/textarea.css +1 -1
  189. package/dist/components/ui/toast/index.js +1 -1
  190. package/dist/components/ui/toast/index.js.map +4 -4
  191. package/dist/components/ui/toast/toast.css +35 -32
  192. package/dist/components/ui/toast/toast.script.d.ts +17 -31
  193. package/dist/components/ui/toast/toaster.script.d.ts +24 -12
  194. package/dist/components/ui/toc/toc.script.d.ts +19 -8
  195. package/dist/components/ui/toolbar/toolbar.d.ts +5 -0
  196. package/dist/components/ui/toolbar/toolbar.script.d.ts +24 -4
  197. package/dist/components/ui/tooltip/index.js +1 -1
  198. package/dist/components/ui/tooltip/index.js.map +4 -4
  199. package/dist/components/ui/tooltip/tooltip.css +14 -94
  200. package/dist/components/ui/tooltip/tooltip.d.ts +7 -0
  201. package/dist/components/ui/tooltip/tooltip.script.d.ts +36 -6
  202. package/dist/components/ui/tree/tree.d.ts +4 -3
  203. package/dist/components/ui/tree/tree.script.d.ts +28 -15
  204. package/dist/components/ui/treegrid/treegrid.d.ts +5 -3
  205. package/dist/components/ui/treegrid/treegrid.script.d.ts +33 -14
  206. package/dist/components/ui/window-splitter/index.d.ts +1 -1
  207. package/dist/components/ui/window-splitter/index.js +1 -1
  208. package/dist/components/ui/window-splitter/index.js.map +3 -3
  209. package/dist/components/ui/window-splitter/window-splitter.d.ts +10 -1
  210. package/dist/components/ui/window-splitter/window-splitter.script.d.ts +26 -8
  211. package/dist/index.d.ts +2 -0
  212. package/dist/index.js +1 -1
  213. package/dist/index.js.map +4 -4
  214. package/dist/lib/icons/check.d.ts +3 -0
  215. package/dist/lib/icons/chevron-down.d.ts +0 -1
  216. package/dist/lib/icons/index.d.ts +2 -0
  217. package/dist/lib/icons/x.d.ts +5 -0
  218. package/dist/lib/intl-date/index.d.ts +4 -2
  219. package/dist/lib/intl-date/segment-editing.d.ts +34 -0
  220. package/dist/lib/intl-date/segments.d.ts +26 -4
  221. package/dist/lib/non-empty.d.ts +6 -0
  222. package/dist/lib/unique-id.d.ts +11 -0
  223. package/dist/lib/viewport/breakpoints.d.ts +6 -0
  224. package/dist/lib/viewport/mobile-layout.d.ts +15 -0
  225. package/dist/styles/primitives.css +14 -11
  226. package/dist/styles/radiant-ui-core.css +10 -0
  227. package/dist/styles/radiant-ui.css +40 -11
  228. package/dist/styles/style-dependencies.json +38 -13
  229. package/dist/styles/styles.css +485 -252
  230. package/dist/styles/tailwind.css +40 -101
  231. package/dist/styles/tokens/presets/colors/aurora.css +2 -0
  232. package/dist/styles/tokens/presets/colors/basalt.css +2 -0
  233. package/dist/styles/tokens/presets/colors/ember.css +2 -0
  234. package/dist/styles/tokens/presets/colors/glacier.css +2 -0
  235. package/dist/styles/tokens/semantic.css +1 -0
  236. package/dist/styles/tokens/system.css +11 -3
  237. package/dist/styles/tokens/typography/default.css +8 -0
  238. package/package.json +27 -13
package/README.md CHANGED
@@ -28,22 +28,30 @@ pnpm run storybook
28
28
 
29
29
  Open the URL Storybook prints (default port `6006`).
30
30
 
31
+ ### Checking layout and styles
32
+
33
+ - **Automated (CI-friendly):** `pnpm run test:storybook` runs each story’s `play` function in a real browser (Vitest + Playwright). Layout helpers live in `.storybook/layout-assertions.ts` (overflow, `--text-control-input` font size, popover viewport bounds) — see `Components/DateRangePicker` → **NarrowLayout**. Input typography uses the `--text-control-input` token in `tokens/typography/default.css` (16px below `640px`, `--text-control` at `sm` and up).
34
+ - **Manual:** run `pnpm run storybook` and use the browser’s responsive mode or resize the preview; no third-party visual service required.
35
+ - **Pixel snapshots (optional):** Vitest browser mode supports Playwright `toHaveScreenshot()` with baselines committed in the repo if you want image diffs without Chromatic.
36
+
31
37
  Useful scripts:
32
38
 
33
39
  ```bash
34
40
  pnpm run test # Vitest (storybook + unit browser projects)
35
41
  pnpm run test:storybook # Story interaction/render tests (CI)
36
- pnpm run test:ssr:smoke # Local SSR smoke (6 stories × client/ssr-static/ssr-hydrate)
37
- pnpm run test:ssr # Full Components/* SSR matrix (nightly)
42
+ pnpm run test:ssr:smoke # SSR smoke (6 stories × client/ssr-static/ssr-hydrate; runs on PRs)
43
+ pnpm run test:ssr # Full Components/* SSR matrix (run on demand)
38
44
  pnpm run typecheck
39
45
  pnpm run lint
40
46
  pnpm run build:lib # generate exports + build JS/types + compile CSS
41
47
  ```
42
48
 
43
- `test:storybook` runs stories through the Vitest addon (no Storybook dev server). `test:ssr:smoke` and `test:ssr` spawn Storybook, visit stories in Playwright, and fail on `.radiant-ssr-error` banners or disallowed page errors. Empty mounts fail only for stories listed in `scripts/storybook-ssr-harness.ts` (`expectsMount` / `allowEmptyMount`).
49
+ `test:storybook` runs stories through the Vitest addon (no Storybook dev server). `test:ssr:smoke` and `test:ssr` spawn Storybook, visit stories in Playwright, and fail on `.radiant-ssr-error` banners or disallowed page errors. For stories expected to mount, the harness waits briefly for content or an SSR error banner before checking the result. Empty mounts fail only for stories listed in `scripts/storybook-ssr-harness.ts` (`expectsMount` / `allowEmptyMount`).
44
50
 
45
51
  Published CSS under `dist/` is **already compiled** (Tailwind `@apply` resolved). Theme and token values remain CSS custom properties so apps can swap themes at runtime. The package does not minify CSS.
46
52
 
53
+ Component entries register their nested custom elements as well as their own host. The package's `sideEffects` list preserves source `*.script.ts` / `*.script.tsx` registration modules during the library build and built `index.js` entries during consumer bundling. Removing those source side effects can leave nested Derived Trees as empty tags during SSR. `build:lib` runs `test:package` against isolated imports of the built date compositions and sidebar trigger to verify registration and server-rendered markup.
54
+
47
55
  ## Using radiant-ui
48
56
 
49
57
  ```ts
@@ -30,12 +30,10 @@ export type RuiAlertDescriptionProps = JsxElementProps<HTMLDivElement>;
30
30
  export declare function RuiAlertDescription({ children, class: className, ...props }: RuiAlertDescriptionProps): import("@ecopages/jsx").JsxRenderable;
31
31
  export type RuiAlertComponentProps = JsxElementProps<HTMLDivElement> & RuiAlertProps;
32
32
  /**
33
- * Status alert with optional dismiss control.
33
+ * Status alert with optional dismiss control. Stamps `<rui-alert>` and the inner
34
+ * `role="alert"` surface; appends `[data-alert-close]` when `dismissible`.
34
35
  *
35
36
  * @remarks
36
- * Importable JSX helper around `<rui-alert>`. Owns the `role="alert"` surface and
37
- * BEM classes; the host owns dismiss (`rui-close` / `dismiss()`).
38
- *
39
37
  * Variant tones map to semantic theme roles (`info`, `success`, `warning`, `error`)
40
38
  * via `.rui-alert--*` — not palette steps. See `alert.css` and DESIGN.md status roles.
41
39
  *
@@ -23,16 +23,25 @@ export type RuiAlertCloseDetail = {
23
23
  reason: 'dismiss';
24
24
  };
25
25
  /**
26
- * `<rui-alert>` — a brief, important message that attracts attention
27
- * without interrupting the user's task.
26
+ * `<rui-alert>` — status message host with optional dismiss.
28
27
  *
29
- * Compose with the `RuiAlert` view (surface + optional dismiss control) and
30
- * `RuiAlertIcon` / `RuiAlertTitle` / `RuiAlertDescription` as needed.
28
+ * The custom element is a behavior host: it does not render the composed tree.
29
+ * Import the script and place light-DOM children that match the contract below,
30
+ * or use the `RuiAlert` view helpers which stamp the same targets.
31
31
  *
32
32
  * Prefer injecting or revealing alerts at the moment they become relevant;
33
33
  * static copy that is always present should not use `role="alert"`.
34
34
  *
35
- * @summary Status message host; optional dismiss removes the element.
35
+ * ## Light-DOM contract
36
+ *
37
+ * Optional:
38
+ * - `[data-alert-close]` — dismiss control. Click calls `dismiss()` when `dismissible` is set.
39
+ *
40
+ * The host does not query alert content or the `role="alert"` surface. Authors own
41
+ * that markup (or use `RuiAlert`, which stamps it). Do not rely on BEM class names
42
+ * for behavior.
43
+ *
44
+ * Nested hosts: none.
36
45
  *
37
46
  * @see https://www.w3.org/WAI/ARIA/apg/patterns/alert/
38
47
  *
@@ -40,22 +49,23 @@ export type RuiAlertCloseDetail = {
40
49
  *
41
50
  * @attr {('info'|'success'|'warning'|'error')} variant - Visual tone. Default: `info`.
42
51
  * @attr {('inline'|'banner')} layout - Layout mode. Default: `inline`.
43
- * @attr {boolean} dismissible - Show dismiss control (via the view). Default: `false`.
52
+ * @attr {boolean} dismissible - Show dismiss control. Default: `false`.
44
53
  * @attr {string} close-label - Accessible name for dismiss. Default: `Dismiss`.
45
54
  *
46
- * @slot - Alert content. Prefer the `RuiAlert` view so the `role="alert"` surface
47
- * and BEM classes stay in sync with `variant` / `layout` / `dismissible`.
48
- *
49
55
  * @fires rui-close - Emitted when the alert is dismissed; then the host is removed.
50
56
  *
51
57
  * @remarks
52
- * Styling classes live on the JSX view helpers (`@cssclass`). This element owns
53
- * dismiss behavior — default `render()` is a passthrough slot so prop updates do
54
- * not rebuild the composed light-DOM surface.
58
+ * Minimum headless tree with dismiss:
59
+ *
60
+ * ```html
61
+ * <rui-alert dismissible close-label="Dismiss">
62
+ * <div role="alert">Your session will expire soon.</div>
63
+ * <button type="button" data-alert-close aria-label="Dismiss"></button>
64
+ * </rui-alert>
65
+ * ```
55
66
  *
56
- * **Why a custom element?** Dismiss emits `rui-close` and removes the host from
57
- * the DOM without re-projecting slot content. A presentational-only wrapper would
58
- * need equivalent lifecycle wiring; the CE keeps that behavior self-contained.
67
+ * BEM classes are presentation-only; see view `@cssclass`. Dismiss emits `rui-close`
68
+ * and removes the host without re-building the composed surface.
59
69
  */
60
70
  export declare class RuiAlert extends RadiantElement {
61
71
  variant: RuiAlertVariant;
@@ -15,11 +15,10 @@
15
15
  background-color: var(--color-background, var(--background));
16
16
  padding-inline: var(--spacing-control-x, var(--space-control-x));
17
17
  padding-block: var(--spacing-control-y, var(--space-control-y));
18
- font-size: var(--text-sm, var(--text-sm));
19
- line-height: var(--tw-leading, var(--text-sm--line-height, calc(1.25 / 0.875)));
20
18
  color: var(--color-on-background, var(--on-background));
21
19
  --tw-outline-style: none;
22
20
  outline-style: none;
21
+ font-size: var(--text-control-input);
23
22
  }
24
23
  .rui-autocomplete__input:focus-visible {
25
24
  --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
@@ -5,21 +5,26 @@ export type RuiAutocompleteInputProps = JsxElementProps<HTMLInputElement> & {
5
5
  placeholder?: string;
6
6
  disabled?: boolean;
7
7
  };
8
- /** Search field paired with `RuiAutocomplete` via `data-autocomplete-input`.
8
+ /** Search field paired with `RuiAutocomplete`. Stamps `[data-autocomplete-input]`.
9
9
  *
10
10
  * @cssclass rui-autocomplete__input - Bordered search input.
11
11
  */
12
12
  export declare function RuiAutocompleteInput({ placeholder, class: className, disabled, ...props }: RuiAutocompleteInputProps): JsxRenderable;
13
13
  export type RuiAutocompleteCollectionProps = JsxElementProps<HTMLDivElement>;
14
- /** Wrapper around the filterable collection inside `RuiAutocomplete`.
14
+ /** Wrapper around the filterable collection. Stamps `[data-autocomplete-collection]`.
15
15
  *
16
16
  * @cssclass rui-autocomplete__collection - Scrollable filterable region.
17
17
  */
18
18
  export declare function RuiAutocompleteCollection({ children, class: className, ...props }: RuiAutocompleteCollectionProps): JsxRenderable;
19
19
  export type RuiAutocompleteEmptyProps = JsxElementProps<HTMLDivElement>;
20
- /** Shown when filtering yields no visible items.
20
+ /** No-results state. Stamps `[data-autocomplete-empty]`; host toggles `hidden`.
21
21
  *
22
22
  * @cssclass rui-autocomplete__empty - No-results state.
23
23
  */
24
24
  export declare function RuiAutocompleteEmpty({ children, class: className, ...props }: RuiAutocompleteEmptyProps): JsxRenderable;
25
+ /**
26
+ * Filter host view. Wraps children in `[data-ref="root"]` (presentation only).
27
+ *
28
+ * @cssclass rui-autocomplete - Filter host root.
29
+ */
25
30
  export declare function RuiAutocomplete({ children, ...props }: JsxCustomElementAttributes<RuiAutocompleteElement, RuiAutocompleteProps>): JsxRenderable;
@@ -9,9 +9,32 @@ export type RuiAutocompleteProps = {
9
9
  /**
10
10
  * `<rui-autocomplete>` — filters a composed collection from a text input.
11
11
  *
12
- * Wrap a search field (`data-autocomplete-input`) and a collection
13
- * (`data-autocomplete-collection` or default slot) containing `[role="option"]`,
14
- * `[role="menuitem"]`, or `[data-tag]` items.
12
+ * The custom element is a behavior host: it does not render filter markup.
13
+ * Import the script and place light-DOM children that match the contract below,
14
+ * or use `RuiAutocomplete` and its helpers, which stamp the same targets.
15
+ *
16
+ * ## Light-DOM contract
17
+ *
18
+ * Required (one of):
19
+ * - `[data-autocomplete-input]` — search field inside this host. Host listens for `input`.
20
+ * - External `[data-autocomplete-input]` on an ancestor `rui-combobox` or `rui-select`
21
+ * when this host does not contain the input.
22
+ *
23
+ * Collection (one of):
24
+ * - `[data-autocomplete-collection]` — wrapper around filterable items.
25
+ * - The host element itself — when no collection wrapper is provided.
26
+ *
27
+ * Per item inside the collection:
28
+ * - `[role="option"]`, `[role="menuitem"]`, or `[data-tag]` — filterable rows. Host
29
+ * toggles `hidden` based on the query. Text match uses `data-label` or trimmed
30
+ * `textContent`.
31
+ *
32
+ * Optional:
33
+ * - `[data-autocomplete-empty]` — no-results state. Host toggles `hidden` when matches exist.
34
+ * - `[data-label]` on items — filter text; falls back to trimmed `textContent`.
35
+ *
36
+ * Nested hosts: filterable items are often `rui-listbox` options or `rui-tag` chips;
37
+ * this host only queries the role / data-tag selectors above, not listbox internals.
15
38
  *
16
39
  * @remarks When nested in `rui-combobox`, the combobox input acts as the filter
17
40
  * field. `rui-select` uses a dedicated search input inside the popup instead.
@@ -23,7 +46,9 @@ export type RuiAutocompleteProps = {
23
46
  * @attr {string} sensitivity - Filter sensitivity: `base` (case-insensitive contains), `case`, or `accent`. Default: `base`.
24
47
  * @attr {string} input-value - Controlled filter query; when unset, reads from the composed input. Default: `''`.
25
48
  *
26
- * @cssclass rui-autocomplete - Filter host.
49
+ * @remarks
50
+ * `[data-ref="root"]` on the view is presentation only; the host does not query it.
51
+ * BEM classes live on the view; the host never queries them.
27
52
  */
28
53
  export declare class RuiAutocomplete extends RadiantElement {
29
54
  sensitivity: TextFilterSensitivity;
@@ -2,33 +2,35 @@
2
2
  @layer properties;
3
3
  @layer components {
4
4
  .rui-avatar {
5
+ --rui-avatar-size: var(--space-10);
6
+ --rui-avatar-radius: var(--radius-pill);
7
+ --rui-avatar-surface: var(--surface-container);
5
8
  position: relative;
6
9
  display: inline-flex;
7
10
  flex-shrink: 0;
8
11
  align-items: center;
9
12
  justify-content: center;
10
13
  overflow: hidden;
11
- border-radius: var(--radius-pill, var(--radius-pill));
12
- background-color: var(--color-surface-container, var(--surface-container));
13
14
  --tw-font-weight: var(--font-weight-medium, var(--weight-medium));
14
15
  font-weight: var(--font-weight-medium, var(--weight-medium));
15
16
  color: var(--color-on-surface, var(--on-surface));
17
+ inline-size: var(--rui-avatar-size);
18
+ block-size: var(--rui-avatar-size);
19
+ border-radius: var(--rui-avatar-radius);
20
+ background-color: var(--rui-avatar-surface);
16
21
  }
17
22
  .rui-avatar--sm {
18
- width: var(--spacing-8, var(--space-8));
19
- height: var(--spacing-8, var(--space-8));
23
+ --rui-avatar-size: var(--space-8);
20
24
  font-size: var(--text-xs, var(--text-xs));
21
25
  line-height: var(--tw-leading, var(--text-xs--line-height, calc(1 / 0.75)));
22
26
  }
23
27
  .rui-avatar--md {
24
- width: calc(var(--spacing, 0.25rem) * 10);
25
- height: calc(var(--spacing, 0.25rem) * 10);
28
+ --rui-avatar-size: var(--space-10);
26
29
  font-size: var(--text-sm, var(--text-sm));
27
30
  line-height: var(--tw-leading, var(--text-sm--line-height, calc(1.25 / 0.875)));
28
31
  }
29
32
  .rui-avatar--lg {
30
- width: calc(var(--spacing, 0.25rem) * 12);
31
- height: calc(var(--spacing, 0.25rem) * 12);
33
+ --rui-avatar-size: var(--space-12);
32
34
  font-size: var(--text-body, var(--text-body));
33
35
  }
34
36
  .rui-avatar__image {
@@ -15,7 +15,9 @@ export type RuiAvatarProps = JsxElementProps<HTMLSpanElement> & {
15
15
  * @remarks When `src` is omitted or fails to load, initials derived from `alt`
16
16
  * (or the explicit `fallback`) are shown in a `role="img"` span. There is no
17
17
  * runtime image-error listener — pass `fallback` for reliable SSR of the
18
- * fallback state.
18
+ * fallback state. Override `--rui-avatar-size`, `--rui-avatar-radius`, and
19
+ * `--rui-avatar-surface` on `.rui-avatar`. Size modifiers set `--rui-avatar-size`
20
+ * (`sm` `--space-8`, `md` `--space-10`, `lg` `--space-12`).
19
21
  *
20
22
  * @cssclass rui-avatar - Avatar root; `role="img"` when image-less.
21
23
  * @cssclass rui-avatar--sm - Small size.
@@ -3,23 +3,23 @@ import type { RuiBreadcrumb as RuiBreadcrumbElement, RuiBreadcrumbProps } from '
3
3
  import './breadcrumb.script';
4
4
  export type RuiBreadcrumbViewProps = JsxCustomElementAttributes<RuiBreadcrumbElement, RuiBreadcrumbProps>;
5
5
  /**
6
- * Landmark wrapper for a breadcrumb trail. Set `separator` once here (e.g. `/`
7
- * or `>`); empty `RuiBreadcrumbSeparator` nodes pick it up via CSS — no context.
8
- * Pass children into a separator to override for that instance.
6
+ * Landmark wrapper for a breadcrumb trail. Stamps `<nav class="rui-breadcrumb">`.
9
7
  *
10
8
  * @cssclass rui-breadcrumb - `<nav>` landmark root.
9
+ *
10
+ * @remarks `separator` sets `--rui-breadcrumb-separator` for empty separators.
11
11
  */
12
12
  export declare function RuiBreadcrumb({ children, label, separator, ...props }: RuiBreadcrumbViewProps): import("@ecopages/jsx").JsxRenderable;
13
13
  export type RuiBreadcrumbListProps = JsxElementProps<HTMLOListElement>;
14
14
  /**
15
- * Ordered list of breadcrumb items and separators.
15
+ * Ordered list of breadcrumb items and separators. Stamps `<ol class="rui-breadcrumb__list">`.
16
16
  *
17
17
  * @cssclass rui-breadcrumb__list - Ordered list row.
18
18
  */
19
19
  export declare function RuiBreadcrumbList({ children, class: className, ...props }: RuiBreadcrumbListProps): import("@ecopages/jsx").JsxRenderable;
20
20
  export type RuiBreadcrumbItemProps = JsxElementProps<HTMLLIElement>;
21
21
  /**
22
- * Single crumb (`<li>`).
22
+ * Single crumb list item. Stamps `<li class="rui-breadcrumb__item">`.
23
23
  *
24
24
  * @cssclass rui-breadcrumb__item - List item wrapping a crumb link/page.
25
25
  */
@@ -28,25 +28,25 @@ export type RuiBreadcrumbLinkProps = JsxElementProps<HTMLAnchorElement> & {
28
28
  href: string;
29
29
  };
30
30
  /**
31
- * Linked ancestor page.
31
+ * Linked ancestor page. Stamps `<a class="rui-breadcrumb__link">`.
32
32
  *
33
33
  * @cssclass rui-breadcrumb__link - Crumb link.
34
34
  */
35
35
  export declare function RuiBreadcrumbLink({ children, href, class: className, ...props }: RuiBreadcrumbLinkProps): import("@ecopages/jsx").JsxRenderable;
36
36
  export type RuiBreadcrumbPageProps = JsxElementProps<HTMLSpanElement>;
37
37
  /**
38
- * Current page (non-link).
38
+ * Current page (non-link). Stamps `<span class="rui-breadcrumb__page" aria-current="page">`.
39
39
  *
40
40
  * @cssclass rui-breadcrumb__page - Current page span (`aria-current="page"`).
41
41
  */
42
42
  export declare function RuiBreadcrumbPage({ children, class: className, ...props }: RuiBreadcrumbPageProps): import("@ecopages/jsx").JsxRenderable;
43
43
  export type RuiBreadcrumbSeparatorProps = JsxElementProps<HTMLLIElement>;
44
44
  /**
45
- * Visual separator between crumbs. Renders as a presentational list item.
46
- * With no children, uses the glyph from `RuiBreadcrumb`’s `separator` prop
47
- * (CSS custom property). With children, those replace the default glyph.
45
+ * Visual separator between crumbs. Stamps presentational `<li class="rui-breadcrumb__separator">`.
48
46
  *
49
47
  * @cssclass rui-breadcrumb__separator - Presentational separator (`aria-hidden`).
48
+ *
49
+ * @remarks With no children, uses the glyph from `RuiBreadcrumb`'s `separator` prop.
50
50
  */
51
51
  export declare function RuiBreadcrumbSeparator({ children, class: className, ...props }: RuiBreadcrumbSeparatorProps): import("@ecopages/jsx").JsxRenderable;
52
52
  export type RuiBreadcrumbEllipsisProps = JsxElementProps<HTMLSpanElement> & {
@@ -54,7 +54,7 @@ export type RuiBreadcrumbEllipsisProps = JsxElementProps<HTMLSpanElement> & {
54
54
  label?: string;
55
55
  };
56
56
  /**
57
- * Collapsed middle segment indicator.
57
+ * Collapsed middle segment indicator. Stamps `<span class="rui-breadcrumb__ellipsis">`.
58
58
  *
59
59
  * @cssclass rui-breadcrumb__ellipsis - Collapsed segment indicator (`aria-hidden`).
60
60
  * @cssclass rui-breadcrumb__ellipsis-label - Screen-reader label for the collapsed segment.
@@ -10,20 +10,20 @@ export type RuiBreadcrumbProps = {
10
10
  separator?: string;
11
11
  };
12
12
  /**
13
- * `<rui-breadcrumb>` — a trail of links to ancestor pages in hierarchical order.
13
+ * `<rui-breadcrumb>` — navigation landmark for a hierarchical page trail.
14
14
  *
15
- * Implements the WAI-ARIA APG Breadcrumb pattern: a `<nav>` landmark containing
16
- * an ordered list of links, with `aria-current="page"` on the current page item.
17
- *
18
- * Compose with the JSX helpers (`RuiBreadcrumbList`, `RuiBreadcrumbItem`,
19
- * `RuiBreadcrumbLink`, `RuiBreadcrumbPage`, `RuiBreadcrumbSeparator`,
20
- * `RuiBreadcrumbEllipsis`).
15
+ * The custom element holds `label` and `separator` props; it does not query
16
+ * authored children. Use `RuiBreadcrumb` and the breadcrumb helpers, which stamp
17
+ * the `<nav>` landmark and list structure.
21
18
  *
22
19
  * @see https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/
23
- *
24
- * Keyboard interaction: standard link navigation (`Tab`, `Enter`).
25
- *
26
20
  * @element rui-breadcrumb
21
+ * @attr {string} label - Accessible name for the navigation landmark. Default: `Breadcrumb`.
22
+ * @attr {string} separator - Glyph for empty `RuiBreadcrumbSeparator` nodes (CSS custom property). Default: `/`.
23
+ *
24
+ * @remarks
25
+ * No light-DOM query contract — keyboard interaction is standard link navigation.
26
+ * BEM classes live on the view helpers.
27
27
  */
28
28
  export declare class RuiBreadcrumb extends RadiantElement {
29
29
  label: string;
@@ -5,6 +5,7 @@ rui-calendar {
5
5
  }
6
6
  @layer components {
7
7
  .rui-calendar {
8
+ max-width: 100%;
8
9
  border-radius: var(--radius-container, var(--radius-container));
9
10
  border-style: var(--tw-border-style);
10
11
  border-width: 1px;
@@ -32,15 +33,15 @@ rui-calendar {
32
33
  }
33
34
  }
34
35
  .rui-calendar__month-panel {
35
- width: calc(var(--spacing, 0.25rem) * 64);
36
36
  flex-shrink: 0;
37
+ width: min(var(--rui-calendar-month-width, 16rem), calc(100vw - 1rem));
37
38
  }
38
39
  .rui-calendar__header {
39
40
  margin-bottom: var(--spacing-2, var(--space-2));
40
- display: flex;
41
+ display: grid;
42
+ grid-template-columns: 2rem 1fr 2rem;
41
43
  align-items: center;
42
- justify-content: space-between;
43
- gap: var(--spacing-inline, var(--space-inline));
44
+ gap: 0px;
44
45
  }
45
46
  .rui-calendar__nav-spacer {
46
47
  display: inline-flex;
@@ -49,7 +50,11 @@ rui-calendar {
49
50
  flex-shrink: 0;
50
51
  }
51
52
  .rui-calendar__month {
52
- flex: 1;
53
+ min-width: 0px;
54
+ overflow: hidden;
55
+ text-overflow: ellipsis;
56
+ white-space: nowrap;
57
+ padding-inline: var(--spacing-1, var(--space-1));
53
58
  text-align: center;
54
59
  --tw-font-weight: var(--font-weight-medium, var(--weight-medium));
55
60
  font-weight: var(--font-weight-medium, var(--weight-medium));
@@ -30,15 +30,34 @@ type MonthPanel = {
30
30
  /**
31
31
  * `<rui-calendar>` — locale-aware month grid(s) for picking dates.
32
32
  *
33
+ * Derived Tree: the host `render()` paints the month grid. Authored children are
34
+ * not the inner calendar. Parent hosts (`rui-date-field`, `rui-date-range-picker`)
35
+ * embed `<rui-calendar>` and query day targets when opening the popup.
36
+ *
33
37
  * Supports single, multiple, and range selection. Value format:
34
38
  * - single: `YYYY-MM-DD`
35
39
  * - multiple: comma-separated ISO dates
36
40
  * - range: `YYYY-MM-DD/YYYY-MM-DD`
37
41
  *
38
- * @see https://react-aria.adobe.com/Calendar
42
+ * ## Light-DOM contract
39
43
  *
40
- * @element rui-calendar
44
+ * Generated by `render()` (do not author manually):
45
+ * - `[data-ref="root"]` — application root. Host sets `role="application"`,
46
+ * `aria-label`, and `aria-multiselectable` when `selection-mode="multiple"`.
47
+ * - `[data-calendar-prev-month]` / `[data-calendar-next-month]` — paging controls.
48
+ * - `[data-calendar-grid]` — month grid (`role="grid"`).
49
+ * - `[data-calendar-day]` — day buttons. Host sets `data-iso`, roving `tabIndex`,
50
+ * `aria-selected`, `aria-current`, `disabled`, and range `data-range-*` attrs.
51
+ * - `[data-calendar-today]` — jump to today.
52
+ *
53
+ * Parent-queried on nested calendars:
54
+ * - `[data-calendar-day][data-iso="…"]` — focus target when a date-field popup opens.
55
+ * - `[data-calendar-day][tabindex="0"]` — roving focus fallback.
56
+ *
57
+ * Nested hosts: none.
41
58
  *
59
+ * @see https://react-aria.adobe.com/Calendar
60
+ * @element rui-calendar
42
61
  * @attr {string} value - Selected date(s) in the mode-specific ISO format. Default: `''`.
43
62
  * @attr {string} min - Earliest selectable ISO date. Default: `''`.
44
63
  * @attr {string} max - Latest selectable ISO date. Default: `''`.
@@ -47,29 +66,12 @@ type MonthPanel = {
47
66
  * @attr {('single'|'multiple'|'range')} selection-mode - Selection mode. Default: `single`.
48
67
  * @attr {number} visible-months - Month grids shown side by side. Default: `1`.
49
68
  * @attr {('visible'|'single')} page-behavior - Whether paging moves by all visible months or one month. Default: `visible`.
50
- *
51
69
  * @fires rui-change - Emitted when the selection changes; detail carries `value`, plus `start` / `end` for ranges.
52
70
  *
53
- * @cssclass rui-calendar - Root surface (`role="application"`).
54
- * @cssclass rui-calendar--multi - Multi-month root modifier.
55
- * @cssclass rui-calendar__months - Row of month panels.
56
- * @cssclass rui-calendar__month-panel - Single month grid column.
57
- * @cssclass rui-calendar__header - Month title row with paging controls.
58
- * @cssclass rui-calendar__nav - Prev / next month button.
59
- * @cssclass rui-calendar__nav-spacer - Placeholder where a nav button is absent.
60
- * @cssclass rui-calendar__month - Month title.
61
- * @cssclass rui-calendar__weekdays - Weekday header row.
62
- * @cssclass rui-calendar__weekday - Weekday label.
63
- * @cssclass rui-calendar__grid - Month grid (`role="grid"`).
64
- * @cssclass rui-calendar__week - Grid row.
65
- * @cssclass rui-calendar__day - Day cell button (`role="gridcell"`).
66
- * @cssclass rui-calendar__footer - Footer row with the today button.
67
- * @cssclass rui-calendar__today - "Today" jump button.
68
- *
69
71
  * @remarks
70
72
  * Arrow keys move the focused day, PageUp / PageDown page the months (Shift
71
- * adds ±12), and Enter / Space select the focused day. Disabled or out-of-range
72
- * days are skipped while navigating.
73
+ * adds ±12), and Enter / Space select the focused day. BEM classes are
74
+ * presentation-only; behavior keys off the `data-calendar-*` targets above.
73
75
  */
74
76
  export declare class RuiCalendar extends RadiantElement {
75
77
  value: string;
@@ -112,6 +114,7 @@ export declare class RuiCalendar extends RadiantElement {
112
114
  private previewRange;
113
115
  private clearRangePreview;
114
116
  private initialize;
117
+ constructor();
115
118
  protected onConnected(): void;
116
119
  onPropsUpdated(): void;
117
120
  onPrevMonth(event: Event): void;
@@ -1,2 +1,2 @@
1
- import{jsx as p,jsxs as ge}from"@ecopages/jsx/jsx-runtime";import{RadiantElement as ft,customElement as Rt,event as St,onEvent as F,onUpdated as At,prop as S,state as A}from"@ecopages/radiant";function Se(t){if(!t)return;let e=t.split(",").map(n=>n.trim()).filter(Boolean);return e.length>1?e:e[0]}function q(t){if(t==null)return null;let e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;let n=Number(e[1]),r=Number(e[2])-1,a=Number(e[3]),i=new Date(n,r,a);return i.getFullYear()!==n||i.getMonth()!==r||i.getDate()!==a?null:i}function L(t){let e=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),r=String(t.getDate()).padStart(2,"0");return`${e}-${n}-${r}`}function ne(t,e,n){return!(e&&t<e||n&&t>n)}function T(t,e){return t.localeCompare(e)}function O(t,e){return T(t,e)<=0?{start:t,end:e}:{start:e,end:t}}function C(t){if(!t)return null;let[e,n]=t.split("/");return!e||!n?null:O(e,n)}function re(t){if(!t)return"";let e=O(t.start,t.end);return`${e.start}/${e.end}`}function G(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean).sort(T):[]}function ae(t){return[...new Set(t)].sort(T).join(",")}function ie(t,e){let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),[...n].sort(T)}function Ae(t,e){let n=O(e.start,e.end);return T(t,n.start)>=0&&T(t,n.end)<=0}function oe(t,e,n){if(e==="single"){let f=n.singleIso===t;return{isSelected:f,isRangeStart:f,isRangeEnd:f,isRangeMiddle:!1}}if(e==="multiple"){let f=n.multipleIsos?.includes(t)??!1;return{isSelected:f,isRangeStart:f,isRangeEnd:f,isRangeMiddle:!1}}let r=n.range;if(!r)return{isSelected:!1,isRangeStart:!1,isRangeEnd:!1,isRangeMiddle:!1};let a=O(r.start,r.end),i=Ae(t,a),o=t===a.start,c=t===a.end;return{isSelected:i,isRangeStart:o,isRangeEnd:c,isRangeMiddle:i&&!o&&!c}}function se(t,e,n){return e.anchor?{committed:O(e.anchor,n),draft:{anchor:null,hover:null}}:{committed:t,draft:{anchor:n,hover:n}}}function J(t){let e=pt(t);try{let r=new Intl.Locale(e).weekInfo;if(r?.firstDay!=null)return r.firstDay===7?0:r.firstDay}catch{}return e.startsWith("en-US")?0:1}function pt(t){return Array.isArray(t)?t[0]??navigator.language:t??navigator.language}function vt(t){return new Date(t.getFullYear(),t.getMonth(),t.getDate())}function yt(t,e){return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()}function bt(t){let e=t.selectionMode??"single",n=t.value??"";if(e==="multiple")return{mode:e,multipleIsos:G(n)};if(e==="range"){let r=C(n);if(t.rangeDraft?.anchor){let a=t.rangeDraft.hover??t.rangeDraft.anchor;return{mode:e,range:_t(t.rangeDraft.anchor,a)}}return{mode:e,range:r}}return{mode:e,singleIso:n||void 0}}function _t(t,e){return t.localeCompare(e)<=0?{start:t,end:e}:{start:e,end:t}}function le(t,e,n){let r=J(n.locale),a=vt(n.today??new Date),i=bt(n),c=(new Date(t,e,1).getDay()-r+7)%7,Y=new Date(t,e,1-c),f=[],g=new Date(Y);for(let k=0;k<6;k+=1){let D=[];for(let z=0;z<7;z+=1){let P=L(g),x=oe(P,i.mode,{singleIso:i.singleIso,multipleIsos:i.multipleIsos,range:i.range});D.push({date:new Date(g),iso:P,inMonth:g.getMonth()===e,isToday:yt(g,a),isSelected:x.isSelected,isDisabled:!ne(P,n.min,n.max),isRangeStart:x.isRangeStart,isRangeEnd:x.isRangeEnd,isRangeMiddle:x.isRangeMiddle}),g.setDate(g.getDate()+1)}if(f.push(D),k>=4&&g.getMonth()!==e&&g.getDate()>7)break}return f}function N(t,e,n){let r=new Date(t,e+n,1);return{year:r.getFullYear(),month:r.getMonth()}}function ce(t,e,n){let r=Math.max(1,Math.min(n,12));return Array.from({length:r},(a,i)=>{let o=N(t,e,i);return{year:o.year,month:o.month,offset:i}})}var ke=new Map;function Mt(t,e){return`${JSON.stringify(t??null)}|${JSON.stringify(e)}`}function ue(t,e){let n=Mt(t,e),r=ke.get(n);if(r)return r;let a=new Intl.DateTimeFormat(t,e);return ke.set(n,a),a}function de(t,e){return ue(e,{month:"long",year:"numeric"}).format(t)}function he(t,e){let n=ue(t,{weekday:"narrow"}),r=[];for(let a=0;a<7;a+=1){let i=(e+a)%7,o=new Date(2024,0,i===0?7:i);r.push(n.format(o))}return r}function fe(t){return new Intl.RelativeTimeFormat(t,{numeric:"auto"}).format(0,"day")}var Ee,Le,Te,Fe,Ye,Pe,Ve,Oe,Ce,Ge,ze,je,$e,Be,He,Ue,We,Ke,qe,Je,Ne,Qe,Xe,Ze,et,tt,nt,rt,at,it,ot,st,lt,ct,ut,dt;function wt(t,e,n,r,a,i){var o,c,Y,f,g,k,D,z=Symbol.metadata||Symbol.for("Symbol.metadata"),P=Object.defineProperty,x=Object.create,me=[x(null),x(null)],pe=e.length;function B(s,b,v){return function(l,u){b&&(u=l,l=t);for(var _=0;_<s.length;_++)u=s[_].apply(l,v?[u]:[]);return v?u:l}}function I(s,b,v,l){if(typeof s!="function"&&(l||s!==void 0))throw new TypeError(b+" must "+(v||"be")+" a function"+(l?"":" or undefined"));return s}function ve(s,b,v,l,u,_,E,y,M,w,be){function Q(h){if(!be(h))throw new TypeError("Attempted to access private element on non-instance")}var X=[].concat(b[0]),_e=b[3],Z=!E,j=u===1,Me=u===3,we=u===4,H=u===2;function U(h,V,Ie){return function(K,Re){return V&&(Re=K,K=s),Ie&&Ie(K),d[h].call(K,Re)}}if(!Z){var d={},ee=[],R=Me?"get":we||j?"set":"value";if(M?(w||j?d={get:ht(function(){return _e(this)},l,"get"),set:function(h){b[4](this,h)}}:d[R]=_e,w||ht(d[R],l,H?"":R)):w||(d=Object.getOwnPropertyDescriptor(s,l)),!w&&!M){if((c=me[+y][l])&&(c^u)!==7)throw Error("Decorating two elements with the same name ("+d[R].name+") is not supported yet");me[+y][l]=u<3?1:u}}for(var m=s,W=X.length-1;W>=0;W-=v?2:1){var De=I(X[W],"A decorator","be",!0),xe=v?X[W-1]:void 0,te={},$={kind:["field","accessor","method","getter","setter","class"][u],name:l,metadata:o,addInitializer:function(h,V){if(h.v)throw new TypeError("attempted to call addInitializer after decoration was finished");I(V,"An initializer","be",!0),_.push(V)}.bind(null,te)};if(Z)c=De.call(xe,m,$),te.v=1,I(c,"class decorators","return")&&(m=c);else if($.static=y,$.private=M,c=$.access={has:M?be.bind():function(h){return l in h}},we||(c.get=M?H?function(h){return Q(h),d.value}:U("get",0,Q):function(h){return h[l]}),H||Me||(c.set=M?U("set",0,Q):function(h,V){h[l]=V}),m=De.call(xe,j?{get:d.get,set:d.set}:d[R],$),te.v=1,j){if(typeof m=="object"&&m)(c=I(m.get,"accessor.get"))&&(d.get=c),(c=I(m.set,"accessor.set"))&&(d.set=c),(c=I(m.init,"accessor.init"))&&ee.unshift(c);else if(m!==void 0)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else I(m,(w?"field":"method")+" decorators","return")&&(w?ee.unshift(m):d[R]=m)}return u<2&&E.push(B(ee,y,1),B(_,y,0)),w||Z||(M?j?E.splice(-1,0,U("get",y),U("set",y)):E.push(H?d[R]:I.call.bind(d[R])):P(s,l,d)),m}function ye(s){return P(s,z,{configurable:!0,enumerable:!0,value:o})}return i!==void 0&&(o=i[z]),o=x(o??null),g=[],k=function(s){s&&g.push(B(s))},D=function(s,b){for(var v=0;v<n.length;v++){var l=n[v],u=l[1],_=7&u;if((8&u)==s&&!_==b){var E=l[2],y=!!l[3],M=16&u;ve(s?t:t.prototype,l,M,y?"#"+E:Dt(E),_,_<2?[]:s?f=f||[]:Y=Y||[],g,!!s,y,b,s&&y?function(w){return It(w)===t}:a)}}},D(8,0),D(0,0),D(8,1),D(0,1),k(Y),k(f),c=g,pe||ye(t),{e:c,get c(){var s=[];return pe&&[ye(t=ve(t,[e],r,t.name,5,s)),B(s,1)]}}}function Dt(t){var e=xt(t,"string");return typeof e=="symbol"?e:e+""}function xt(t,e){if(typeof t!="object"||!t)return t;var n=t[Symbol.toPrimitive];if(n!==void 0){var r=n.call(t,e||"default");if(typeof r!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(e==="string"?String:Number)(t)}function ht(t,e,n){typeof e=="symbol"&&(e=(e=e.description)?"["+e+"]":"");try{Object.defineProperty(t,"name",{configurable:!0,value:n?n+" "+e:e})}catch{}return t}function It(t){if(Object(t)!==t)throw TypeError("right-hand side of 'in' should be an object, got "+(t!==null?typeof t:"null"));return t}var mt,gt=class extends ft{static{({e:[Te,Fe,Ye,Pe,Ve,Oe,Ce,Ge,ze,je,$e,Be,He,Ue,We,Ke,qe,Je,Ne,Qe,Xe,Ze,et,tt,nt,rt,at,it,ot,st,lt,ct,ut,dt,Ee],c:[mt,Le]}=wt(this,[Rt("rui-calendar")],[[S({type:String,reflect:!0,defaultValue:""}),0,"value"],[S({type:String,defaultValue:""}),0,"min"],[S({type:String,defaultValue:""}),0,"max"],[S({type:Boolean,reflect:!0,defaultValue:!1}),0,"disabled"],[S({type:String,defaultValue:""}),0,"locale"],[S({type:String,attribute:"selection-mode",defaultValue:"single"}),0,"selectionMode"],[S({type:Number,attribute:"visible-months",defaultValue:1}),0,"visibleMonths"],[S({type:String,attribute:"page-behavior",defaultValue:"visible"}),0,"pageBehavior"],[St({name:"rui-change",bubbles:!0,composed:!0}),0,"changeEvent"],[A,0,"viewYear"],[A,0,"viewMonth"],[A,0,"focusedIso"],[A,0,"weekdayLabels"],[A,0,"monthPanels"],[A,0,"todayLabel"],[A,0,"rangeAnchor"],[A,0,"rangeHover"],[At(["value","min","max","disabled","locale","selectionMode","visibleMonths","pageBehavior"]),2,"onPropsUpdated"],[F({selector:"[data-calendar-prev-month]",type:"click"}),2,"onPrevMonth"],[F({selector:"[data-calendar-next-month]",type:"click"}),2,"onNextMonth"],[F({selector:"[data-calendar-today]",type:"click"}),2,"onTodayClick"],[F({selector:"[data-calendar-day]",type:"click"}),2,"onDayClick"],[F({selector:"[data-calendar-day]",type:"pointerenter"}),2,"onDayPointerEnter"],[F({selector:"[data-calendar-grid]",type:"pointerleave"}),2,"onGridPointerLeave"],[F({selector:"[data-calendar-day]",type:"keydown"}),2,"onDayKeydown"]],0,void 0,ft))}constructor(...e){super(...e),dt(this)}value=(Ee(this),Te(this));min=(Fe(this),Ye(this));max=(Pe(this),Ve(this));disabled=(Oe(this),Ce(this));locale=(Ge(this),ze(this));selectionMode=(je(this),$e(this));visibleMonths=(Be(this),He(this));pageBehavior=(Ue(this),We(this));changeEvent=(Ke(this),qe(this));viewYear=(Je(this),Ne(this,new Date().getFullYear()));viewMonth=(Qe(this),Xe(this,new Date().getMonth()));focusedIso=(Ze(this),et(this,""));weekdayLabels=(tt(this),nt(this,[]));monthPanels=(rt(this),at(this,[]));todayLabel=(it(this),ot(this,""));rangeAnchor=(st(this),lt(this,null));rangeHover=(ct(this),ut(this,null));get resolvedLocale(){return Se(this.locale)}get pageDelta(){return this.pageBehavior==="single"?1:Math.max(1,Math.min(this.visibleMonths,12))}get monthOptions(){return{locale:this.resolvedLocale,selectionMode:this.selectionMode,value:this.value??"",rangeDraft:{anchor:this.rangeAnchor,hover:this.rangeHover},min:this.min||void 0,max:this.max||void 0}}syncViewFromValue(){let e=this.selectionMode==="range"?C(this.value)?.start??"":this.selectionMode==="multiple"?G(this.value)[0]??"":this.value,n=q(e);if(n){this.viewYear=n.getFullYear(),this.viewMonth=n.getMonth(),this.focusedIso=e;return}let r=new Date;this.viewYear=r.getFullYear(),this.viewMonth=r.getMonth(),this.focusedIso=L(r)}refreshGrid(){this.weekdayLabels=he(this.resolvedLocale,J(this.resolvedLocale)),this.monthPanels=ce(this.viewYear,this.viewMonth,this.visibleMonths).map(e=>{let n=new Date(e.year,e.month,1);return{year:e.year,month:e.month,label:de(n,this.resolvedLocale),weeks:le(e.year,e.month,this.monthOptions)}}),this.todayLabel=fe(this.resolvedLocale)}moveMonth(e){let n=N(this.viewYear,this.viewMonth,e);this.viewYear=n.year,this.viewMonth=n.month,this.refreshGrid()}getFlatDays(){return this.monthPanels.flatMap(e=>e.weeks.flat())}moveFocusedDay(e){let n=this.getFlatDays().filter(o=>!o.isDisabled);if(!n.length)return;let r=n.findIndex(o=>o.iso===this.focusedIso),a=r<0?Math.max(0,n.findIndex(o=>o.inMonth)):(r+e+n.length)%n.length,i=n[a];if(i){if(!this.isMonthVisible(i.date)){this.viewYear=i.date.getFullYear(),this.viewMonth=i.date.getMonth(),this.focusedIso=i.iso,this.refreshGrid(),this.focusFocusedDay();return}this.focusedIso=i.iso,this.focusDayInCurrentGrid(i.iso)}}isMonthVisible(e){let n=this.viewYear*12+this.viewMonth,r=n+this.visibleMonths-1,a=e.getFullYear()*12+e.getMonth();return a>=n&&a<=r}focusDayInCurrentGrid(e){let n=this.querySelector('[data-calendar-day][tabindex="0"]'),r=Array.from(this.querySelectorAll(`[data-calendar-day][data-iso="${e}"]:not(:disabled)`)),a=r.find(i=>!i.hasAttribute("data-outside"))??r[0];a&&(n&&n!==a&&(n.tabIndex=-1),a.tabIndex=0,a.focus())}focusFocusedDay(){requestAnimationFrame(()=>{this.focusDayInCurrentGrid(this.focusedIso)})}moveFocusedMonth(e){let n=q(this.focusedIso)??new Date(this.viewYear,this.viewMonth,1),r=new Date(n.getFullYear(),n.getMonth()+e,1),a=new Date(r.getFullYear(),r.getMonth()+1,0).getDate(),i=new Date(r.getFullYear(),r.getMonth(),Math.min(n.getDate(),a));this.viewYear=i.getFullYear(),this.viewMonth=i.getMonth(),this.focusedIso=L(i),this.refreshGrid(),this.focusFocusedDay()}isIsoAllowed(e){return!(this.min&&e<this.min||this.max&&e>this.max)}emitChange(e,n={}){this.changeEvent.emit({value:e,...n})}selectSingle(e){!this.isIsoAllowed(e)||e===this.value||(this.value=e,this.emitChange(e),this.refreshGrid())}selectMultiple(e){if(!this.isIsoAllowed(e))return;let n=ae(ie(G(this.value),e));n!==this.value&&(this.value=n,this.emitChange(n),this.refreshGrid())}selectRange(e){if(!this.isIsoAllowed(e))return;let n=se(C(this.value),{anchor:this.rangeAnchor,hover:this.rangeHover},e);if(this.rangeAnchor=n.draft.anchor,this.rangeHover=n.draft.hover,n.committed){let r=re(n.committed);r!==this.value&&(this.value=r,this.emitChange(r,{start:n.committed.start,end:n.committed.end}))}this.refreshGrid()}selectIso(e){if(this.selectionMode==="multiple"){this.selectMultiple(e);return}if(this.selectionMode==="range"){this.selectRange(e);return}this.selectSingle(e)}previewRange(e){this.selectionMode!=="range"||!this.rangeAnchor||this.disabled||this.rangeHover!==e&&(this.rangeHover=e,this.refreshGrid())}clearRangePreview(){this.rangeHover&&(this.rangeHover=this.rangeAnchor,this.refreshGrid())}initialize(){this.syncViewFromValue(),this.refreshGrid()}onConnected(){this.initialize()}onPropsUpdated(){this.selectionMode!=="range"&&(this.rangeAnchor=null,this.rangeHover=null),this.syncViewFromValue(),this.refreshGrid()}onPrevMonth(e){e.preventDefault(),this.moveMonth(-this.pageDelta)}onNextMonth(e){e.preventDefault(),this.moveMonth(this.pageDelta)}onTodayClick(e){e.preventDefault(),this.selectIso(L(new Date))}onDayClick(e){let n=e.target.closest("[data-calendar-day]"),r=n?.getAttribute("data-iso");!r||n?.disabled||this.disabled||this.selectIso(r)}onDayPointerEnter(e){let n=e.target.closest("[data-calendar-day]"),r=n?.getAttribute("data-iso");!r||n?.disabled||this.previewRange(r)}onGridPointerLeave(){this.clearRangePreview()}onDayKeydown(e){if(this.disabled)return;let n=e.target.getAttribute("data-iso");if(n&&(this.focusedIso=n),e.key==="ArrowLeft"){e.preventDefault(),this.moveFocusedDay(-1);return}if(e.key==="ArrowRight"){e.preventDefault(),this.moveFocusedDay(1);return}if(e.key==="ArrowUp"){e.preventDefault(),this.moveFocusedDay(-7);return}if(e.key==="ArrowDown"){e.preventDefault(),this.moveFocusedDay(7);return}if(e.key==="PageUp"){e.preventDefault(),this.moveFocusedMonth(e.shiftKey?-12:-this.pageDelta);return}if(e.key==="PageDown"){e.preventDefault(),this.moveFocusedMonth(e.shiftKey?12:this.pageDelta);return}if(e.key==="Enter"||e.key===" "){e.preventDefault();let r=e.target,a=r.getAttribute("data-iso");a&&!r.disabled&&this.selectIso(a)}}dayDataAttributes(e){return{"data-range-start":e.isRangeStart?"true":void 0,"data-range-end":e.isRangeEnd?"true":void 0,"data-range-middle":e.isRangeMiddle?"true":void 0}}render(){let e=this.monthPanels.length,n=e>1;return ge("div",{class:`rui-calendar${n?" rui-calendar--multi":""}`,"data-ref":"root",role:"application","aria-label":"Calendar","aria-multiselectable":this.selectionMode==="multiple"?"true":void 0,children:[p("div",{class:"rui-calendar__months",children:this.monthPanels.map((r,a)=>ge("div",{class:"rui-calendar__month-panel","data-calendar-month-panel":!0,children:[ge("div",{class:"rui-calendar__header",children:[a===0?p("button",{type:"button",class:"rui-calendar__nav","data-calendar-prev-month":!0,"aria-label":"Previous month",disabled:this.disabled,children:"\u2039"}):p("span",{class:"rui-calendar__nav-spacer","aria-hidden":"true"}),p("div",{class:"rui-calendar__month","aria-live":"polite",children:r.label}),a===e-1?p("button",{type:"button",class:"rui-calendar__nav","data-calendar-next-month":!0,"aria-label":"Next month",disabled:this.disabled,children:"\u203A"}):p("span",{class:"rui-calendar__nav-spacer","aria-hidden":"true"})]}),a===0?p("div",{class:"rui-calendar__weekdays",role:"row",children:this.weekdayLabels.map(i=>p("div",{class:"rui-calendar__weekday",role:"columnheader","aria-hidden":"true",children:i}))}):null,p("div",{class:"rui-calendar__grid",role:"grid","data-calendar-grid":!0,children:r.weeks.map(i=>p("div",{class:"rui-calendar__week",role:"row",children:i.map(o=>p("button",{type:"button",class:"rui-calendar__day","data-calendar-day":!0,"data-iso":o.iso,role:"gridcell",disabled:this.disabled||o.isDisabled,tabIndex:o.iso===this.focusedIso?0:-1,"aria-selected":o.isSelected?"true":"false","aria-current":o.isToday?"date":void 0,"data-outside":o.inMonth?void 0:"true",...this.dayDataAttributes(o),children:o.date.getDate()}))}))})]}))}),p("div",{class:"rui-calendar__footer",children:p("button",{type:"button",class:"rui-calendar__today","data-calendar-today":!0,disabled:this.disabled,children:this.todayLabel})})]})}static{Le()}};import{jsx as kt}from"@ecopages/jsx/jsx-runtime";function Et({children:t,...e}){return kt("rui-calendar",{...e,children:t})}export{Et as RuiCalendar,mt as RuiCalendarElement};
1
+ import{jsx as p,jsxs as ge}from"@ecopages/jsx/jsx-runtime";import{RadiantElement as ft,customElement as St,event as Rt,onEvent as F,onUpdated as At,prop as R,registerSsrPreparationCallback as kt,state as A}from"@ecopages/radiant";function Re(t){if(!t)return;let e=t.split(",").map(n=>n.trim()).filter(Boolean);return e.length>1?e:e[0]}function N(t){if(t==null)return null;let e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(t.trim());if(!e)return null;let n=Number(e[1]),r=Number(e[2])-1,a=Number(e[3]),i=new Date(n,r,a);return i.getFullYear()!==n||i.getMonth()!==r||i.getDate()!==a?null:i}function L(t){let e=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),r=String(t.getDate()).padStart(2,"0");return`${e}-${n}-${r}`}function ne(t,e,n){return!(e&&t<e||n&&t>n)}function T(t,e){return t.localeCompare(e)}function O(t,e){return T(t,e)<=0?{start:t,end:e}:{start:e,end:t}}function C(t){if(!t)return null;let[e,n]=t.split("/");return!e||!n?null:O(e,n)}function re(t){if(!t)return"";let e=O(t.start,t.end);return`${e.start}/${e.end}`}function G(t){return t?t.split(",").map(e=>e.trim()).filter(Boolean).sort(T):[]}function ae(t){return[...new Set(t)].sort(T).join(",")}function ie(t,e){let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),[...n].sort(T)}function Ae(t,e){let n=O(e.start,e.end);return T(t,n.start)>=0&&T(t,n.end)<=0}function se(t,e,n){if(e==="single"){let f=n.singleIso===t;return{isSelected:f,isRangeStart:f,isRangeEnd:f,isRangeMiddle:!1}}if(e==="multiple"){let f=n.multipleIsos?.includes(t)??!1;return{isSelected:f,isRangeStart:f,isRangeEnd:f,isRangeMiddle:!1}}let r=n.range;if(!r)return{isSelected:!1,isRangeStart:!1,isRangeEnd:!1,isRangeMiddle:!1};let a=O(r.start,r.end),i=Ae(t,a),s=t===a.start,c=t===a.end;return{isSelected:i,isRangeStart:s,isRangeEnd:c,isRangeMiddle:i&&!s&&!c}}function oe(t,e,n){return e.anchor?{committed:O(e.anchor,n),draft:{anchor:null,hover:null}}:{committed:t,draft:{anchor:n,hover:n}}}function q(t){let e=pt(t);try{let r=new Intl.Locale(e).weekInfo;if(r?.firstDay!=null)return r.firstDay===7?0:r.firstDay}catch{}return e.startsWith("en-US")?0:1}function pt(t){return Array.isArray(t)?t[0]??navigator.language:t??navigator.language}function vt(t){return new Date(t.getFullYear(),t.getMonth(),t.getDate())}function yt(t,e){return t.getFullYear()===e.getFullYear()&&t.getMonth()===e.getMonth()&&t.getDate()===e.getDate()}function bt(t){let e=t.selectionMode??"single",n=t.value??"";if(e==="multiple")return{mode:e,multipleIsos:G(n)};if(e==="range"){let r=C(n);if(t.rangeDraft?.anchor){let a=t.rangeDraft.hover??t.rangeDraft.anchor;return{mode:e,range:_t(t.rangeDraft.anchor,a)}}return{mode:e,range:r}}return{mode:e,singleIso:n||void 0}}function _t(t,e){return t.localeCompare(e)<=0?{start:t,end:e}:{start:e,end:t}}function le(t,e,n){let r=q(n.locale),a=vt(n.today??new Date),i=bt(n),c=(new Date(t,e,1).getDay()-r+7)%7,Y=new Date(t,e,1-c),f=[],g=new Date(Y);for(let k=0;k<6;k+=1){let w=[];for(let z=0;z<7;z+=1){let P=L(g),x=se(P,i.mode,{singleIso:i.singleIso,multipleIsos:i.multipleIsos,range:i.range});w.push({date:new Date(g),iso:P,inMonth:g.getMonth()===e,isToday:yt(g,a),isSelected:x.isSelected,isDisabled:!ne(P,n.min,n.max),isRangeStart:x.isRangeStart,isRangeEnd:x.isRangeEnd,isRangeMiddle:x.isRangeMiddle}),g.setDate(g.getDate()+1)}if(f.push(w),k>=4&&g.getMonth()!==e&&g.getDate()>7)break}return f}function J(t,e,n){let r=new Date(t,e+n,1);return{year:r.getFullYear(),month:r.getMonth()}}function ce(t,e,n){let r=Math.max(1,Math.min(n,12));return Array.from({length:r},(a,i)=>{let s=J(t,e,i);return{year:s.year,month:s.month,offset:i}})}var ke=new Map;function Mt(t,e){return`${JSON.stringify(t??null)}|${JSON.stringify(e)}`}function ue(t,e){let n=Mt(t,e),r=ke.get(n);if(r)return r;let a=new Intl.DateTimeFormat(t,e);return ke.set(n,a),a}function de(t,e){return ue(e,{month:"long",year:"numeric"}).format(t)}function he(t,e){let n=ue(t,{weekday:"narrow"}),r=[];for(let a=0;a<7;a+=1){let i=(e+a)%7,s=new Date(2024,0,i===0?7:i);r.push(n.format(s))}return r}function fe(t){return new Intl.RelativeTimeFormat(t,{numeric:"auto"}).format(0,"day")}var Ee,Le,Te,Fe,Ye,Pe,Ve,Oe,Ce,Ge,ze,je,Be,$e,He,Ue,We,Ke,Ne,qe,Je,Qe,Xe,Ze,et,tt,nt,rt,at,it,st,ot,lt,ct,ut,dt;function Dt(t,e,n,r,a,i){var s,c,Y,f,g,k,w,z=Symbol.metadata||Symbol.for("Symbol.metadata"),P=Object.defineProperty,x=Object.create,me=[x(null),x(null)],pe=e.length;function $(o,b,v){return function(l,u){b&&(u=l,l=t);for(var _=0;_<o.length;_++)u=o[_].apply(l,v?[u]:[]);return v?u:l}}function I(o,b,v,l){if(typeof o!="function"&&(l||o!==void 0))throw new TypeError(b+" must "+(v||"be")+" a function"+(l?"":" or undefined"));return o}function ve(o,b,v,l,u,_,E,y,M,D,be){function Q(h){if(!be(h))throw new TypeError("Attempted to access private element on non-instance")}var X=[].concat(b[0]),_e=b[3],Z=!E,j=u===1,Me=u===3,De=u===4,H=u===2;function U(h,V,Ie){return function(K,Se){return V&&(Se=K,K=o),Ie&&Ie(K),d[h].call(K,Se)}}if(!Z){var d={},ee=[],S=Me?"get":De||j?"set":"value";if(M?(D||j?d={get:ht(function(){return _e(this)},l,"get"),set:function(h){b[4](this,h)}}:d[S]=_e,D||ht(d[S],l,H?"":S)):D||(d=Object.getOwnPropertyDescriptor(o,l)),!D&&!M){if((c=me[+y][l])&&(c^u)!==7)throw Error("Decorating two elements with the same name ("+d[S].name+") is not supported yet");me[+y][l]=u<3?1:u}}for(var m=o,W=X.length-1;W>=0;W-=v?2:1){var we=I(X[W],"A decorator","be",!0),xe=v?X[W-1]:void 0,te={},B={kind:["field","accessor","method","getter","setter","class"][u],name:l,metadata:s,addInitializer:function(h,V){if(h.v)throw new TypeError("attempted to call addInitializer after decoration was finished");I(V,"An initializer","be",!0),_.push(V)}.bind(null,te)};if(Z)c=we.call(xe,m,B),te.v=1,I(c,"class decorators","return")&&(m=c);else if(B.static=y,B.private=M,c=B.access={has:M?be.bind():function(h){return l in h}},De||(c.get=M?H?function(h){return Q(h),d.value}:U("get",0,Q):function(h){return h[l]}),H||Me||(c.set=M?U("set",0,Q):function(h,V){h[l]=V}),m=we.call(xe,j?{get:d.get,set:d.set}:d[S],B),te.v=1,j){if(typeof m=="object"&&m)(c=I(m.get,"accessor.get"))&&(d.get=c),(c=I(m.set,"accessor.set"))&&(d.set=c),(c=I(m.init,"accessor.init"))&&ee.unshift(c);else if(m!==void 0)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else I(m,(D?"field":"method")+" decorators","return")&&(D?ee.unshift(m):d[S]=m)}return u<2&&E.push($(ee,y,1),$(_,y,0)),D||Z||(M?j?E.splice(-1,0,U("get",y),U("set",y)):E.push(H?d[S]:I.call.bind(d[S])):P(o,l,d)),m}function ye(o){return P(o,z,{configurable:!0,enumerable:!0,value:s})}return i!==void 0&&(s=i[z]),s=x(s??null),g=[],k=function(o){o&&g.push($(o))},w=function(o,b){for(var v=0;v<n.length;v++){var l=n[v],u=l[1],_=7&u;if((8&u)==o&&!_==b){var E=l[2],y=!!l[3],M=16&u;ve(o?t:t.prototype,l,M,y?"#"+E:wt(E),_,_<2?[]:o?f=f||[]:Y=Y||[],g,!!o,y,b,o&&y?function(D){return It(D)===t}:a)}}},w(8,0),w(0,0),w(8,1),w(0,1),k(Y),k(f),c=g,pe||ye(t),{e:c,get c(){var o=[];return pe&&[ye(t=ve(t,[e],r,t.name,5,o)),$(o,1)]}}}function wt(t){var e=xt(t,"string");return typeof e=="symbol"?e:e+""}function xt(t,e){if(typeof t!="object"||!t)return t;var n=t[Symbol.toPrimitive];if(n!==void 0){var r=n.call(t,e||"default");if(typeof r!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(e==="string"?String:Number)(t)}function ht(t,e,n){typeof e=="symbol"&&(e=(e=e.description)?"["+e+"]":"");try{Object.defineProperty(t,"name",{configurable:!0,value:n?n+" "+e:e})}catch{}return t}function It(t){if(Object(t)!==t)throw TypeError("right-hand side of 'in' should be an object, got "+(t!==null?typeof t:"null"));return t}var mt,gt=class extends ft{static{({e:[Te,Fe,Ye,Pe,Ve,Oe,Ce,Ge,ze,je,Be,$e,He,Ue,We,Ke,Ne,qe,Je,Qe,Xe,Ze,et,tt,nt,rt,at,it,st,ot,lt,ct,ut,dt,Ee],c:[mt,Le]}=Dt(this,[St("rui-calendar")],[[R({type:String,reflect:!0,defaultValue:""}),0,"value"],[R({type:String,defaultValue:""}),0,"min"],[R({type:String,defaultValue:""}),0,"max"],[R({type:Boolean,reflect:!0,defaultValue:!1}),0,"disabled"],[R({type:String,defaultValue:""}),0,"locale"],[R({type:String,attribute:"selection-mode",defaultValue:"single"}),0,"selectionMode"],[R({type:Number,attribute:"visible-months",defaultValue:1}),0,"visibleMonths"],[R({type:String,attribute:"page-behavior",defaultValue:"visible"}),0,"pageBehavior"],[Rt({name:"rui-change",bubbles:!0,composed:!0}),0,"changeEvent"],[A,0,"viewYear"],[A,0,"viewMonth"],[A,0,"focusedIso"],[A,0,"weekdayLabels"],[A,0,"monthPanels"],[A,0,"todayLabel"],[A,0,"rangeAnchor"],[A,0,"rangeHover"],[At(["value","min","max","disabled","locale","selectionMode","visibleMonths","pageBehavior"]),2,"onPropsUpdated"],[F({selector:"[data-calendar-prev-month]",type:"click"}),2,"onPrevMonth"],[F({selector:"[data-calendar-next-month]",type:"click"}),2,"onNextMonth"],[F({selector:"[data-calendar-today]",type:"click"}),2,"onTodayClick"],[F({selector:"[data-calendar-day]",type:"click"}),2,"onDayClick"],[F({selector:"[data-calendar-day]",type:"pointerenter"}),2,"onDayPointerEnter"],[F({selector:"[data-calendar-grid]",type:"pointerleave"}),2,"onGridPointerLeave"],[F({selector:"[data-calendar-day]",type:"keydown"}),2,"onDayKeydown"]],0,void 0,ft))}value=(Ee(this),Te(this));min=(Fe(this),Ye(this));max=(Pe(this),Ve(this));disabled=(Oe(this),Ce(this));locale=(Ge(this),ze(this));selectionMode=(je(this),Be(this));visibleMonths=($e(this),He(this));pageBehavior=(Ue(this),We(this));changeEvent=(Ke(this),Ne(this));viewYear=(qe(this),Je(this,new Date().getFullYear()));viewMonth=(Qe(this),Xe(this,new Date().getMonth()));focusedIso=(Ze(this),et(this,""));weekdayLabels=(tt(this),nt(this,[]));monthPanels=(rt(this),at(this,[]));todayLabel=(it(this),st(this,""));rangeAnchor=(ot(this),lt(this,null));rangeHover=(ct(this),ut(this,null));get resolvedLocale(){return Re(this.locale)}get pageDelta(){return this.pageBehavior==="single"?1:Math.max(1,Math.min(this.visibleMonths,12))}get monthOptions(){return{locale:this.resolvedLocale,selectionMode:this.selectionMode,value:this.value??"",rangeDraft:{anchor:this.rangeAnchor,hover:this.rangeHover},min:this.min||void 0,max:this.max||void 0}}syncViewFromValue(){let e=this.selectionMode==="range"?C(this.value)?.start??"":this.selectionMode==="multiple"?G(this.value)[0]??"":this.value,n=N(e);if(n){this.viewYear=n.getFullYear(),this.viewMonth=n.getMonth(),this.focusedIso=e;return}let r=new Date;this.viewYear=r.getFullYear(),this.viewMonth=r.getMonth(),this.focusedIso=L(r)}refreshGrid(){this.weekdayLabels=he(this.resolvedLocale,q(this.resolvedLocale)),this.monthPanels=ce(this.viewYear,this.viewMonth,this.visibleMonths).map(e=>{let n=new Date(e.year,e.month,1);return{year:e.year,month:e.month,label:de(n,this.resolvedLocale),weeks:le(e.year,e.month,this.monthOptions)}}),this.todayLabel=fe(this.resolvedLocale)}moveMonth(e){let n=J(this.viewYear,this.viewMonth,e);this.viewYear=n.year,this.viewMonth=n.month,this.refreshGrid()}getFlatDays(){return this.monthPanels.flatMap(e=>e.weeks.flat())}moveFocusedDay(e){let n=this.getFlatDays().filter(s=>!s.isDisabled);if(!n.length)return;let r=n.findIndex(s=>s.iso===this.focusedIso),a=r<0?Math.max(0,n.findIndex(s=>s.inMonth)):(r+e+n.length)%n.length,i=n[a];if(i){if(!this.isMonthVisible(i.date)){this.viewYear=i.date.getFullYear(),this.viewMonth=i.date.getMonth(),this.focusedIso=i.iso,this.refreshGrid(),this.focusFocusedDay();return}this.focusedIso=i.iso,this.focusDayInCurrentGrid(i.iso)}}isMonthVisible(e){let n=this.viewYear*12+this.viewMonth,r=n+this.visibleMonths-1,a=e.getFullYear()*12+e.getMonth();return a>=n&&a<=r}focusDayInCurrentGrid(e){let n=this.querySelector('[data-calendar-day][tabindex="0"]'),r=Array.from(this.querySelectorAll(`[data-calendar-day][data-iso="${e}"]:not(:disabled)`)),a=r.find(i=>!i.hasAttribute("data-outside"))??r[0];a&&(n&&n!==a&&(n.tabIndex=-1),a.tabIndex=0,a.focus())}focusFocusedDay(){requestAnimationFrame(()=>{this.focusDayInCurrentGrid(this.focusedIso)})}moveFocusedMonth(e){let n=N(this.focusedIso)??new Date(this.viewYear,this.viewMonth,1),r=new Date(n.getFullYear(),n.getMonth()+e,1),a=new Date(r.getFullYear(),r.getMonth()+1,0).getDate(),i=new Date(r.getFullYear(),r.getMonth(),Math.min(n.getDate(),a));this.viewYear=i.getFullYear(),this.viewMonth=i.getMonth(),this.focusedIso=L(i),this.refreshGrid(),this.focusFocusedDay()}isIsoAllowed(e){return!(this.min&&e<this.min||this.max&&e>this.max)}emitChange(e,n={}){this.changeEvent.emit({value:e,...n})}selectSingle(e){!this.isIsoAllowed(e)||e===this.value||(this.value=e,this.emitChange(e),this.refreshGrid())}selectMultiple(e){if(!this.isIsoAllowed(e))return;let n=ae(ie(G(this.value),e));n!==this.value&&(this.value=n,this.emitChange(n),this.refreshGrid())}selectRange(e){if(!this.isIsoAllowed(e))return;let n=oe(C(this.value),{anchor:this.rangeAnchor,hover:this.rangeHover},e);if(this.rangeAnchor=n.draft.anchor,this.rangeHover=n.draft.hover,n.committed){let r=re(n.committed);r!==this.value&&(this.value=r,this.emitChange(r,{start:n.committed.start,end:n.committed.end}))}this.refreshGrid()}selectIso(e){if(this.selectionMode==="multiple"){this.selectMultiple(e);return}if(this.selectionMode==="range"){this.selectRange(e);return}this.selectSingle(e)}previewRange(e){this.selectionMode!=="range"||!this.rangeAnchor||this.disabled||this.rangeHover!==e&&(this.rangeHover=e,this.refreshGrid())}clearRangePreview(){this.rangeHover&&(this.rangeHover=this.rangeAnchor,this.refreshGrid())}initialize(){this.syncViewFromValue(),this.refreshGrid()}constructor(){super(),dt(this),kt(this,()=>this.initialize())}onConnected(){this.initialize()}onPropsUpdated(){this.selectionMode!=="range"&&(this.rangeAnchor=null,this.rangeHover=null),this.syncViewFromValue(),this.refreshGrid()}onPrevMonth(e){e.preventDefault(),this.moveMonth(-this.pageDelta)}onNextMonth(e){e.preventDefault(),this.moveMonth(this.pageDelta)}onTodayClick(e){e.preventDefault(),this.selectIso(L(new Date))}onDayClick(e){let n=e.target.closest("[data-calendar-day]"),r=n?.getAttribute("data-iso");!r||n?.disabled||this.disabled||this.selectIso(r)}onDayPointerEnter(e){let n=e.target.closest("[data-calendar-day]"),r=n?.getAttribute("data-iso");!r||n?.disabled||this.previewRange(r)}onGridPointerLeave(){this.clearRangePreview()}onDayKeydown(e){if(this.disabled)return;let n=e.target.getAttribute("data-iso");if(n&&(this.focusedIso=n),e.key==="ArrowLeft"){e.preventDefault(),this.moveFocusedDay(-1);return}if(e.key==="ArrowRight"){e.preventDefault(),this.moveFocusedDay(1);return}if(e.key==="ArrowUp"){e.preventDefault(),this.moveFocusedDay(-7);return}if(e.key==="ArrowDown"){e.preventDefault(),this.moveFocusedDay(7);return}if(e.key==="PageUp"){e.preventDefault(),this.moveFocusedMonth(e.shiftKey?-12:-this.pageDelta);return}if(e.key==="PageDown"){e.preventDefault(),this.moveFocusedMonth(e.shiftKey?12:this.pageDelta);return}if(e.key==="Enter"||e.key===" "){e.preventDefault();let r=e.target,a=r.getAttribute("data-iso");a&&!r.disabled&&this.selectIso(a)}}dayDataAttributes(e){return{"data-range-start":e.isRangeStart?"true":void 0,"data-range-end":e.isRangeEnd?"true":void 0,"data-range-middle":e.isRangeMiddle?"true":void 0}}render(){let e=this.monthPanels.length,n=e>1;return ge("div",{class:`rui-calendar${n?" rui-calendar--multi":""}`,"data-ref":"root",role:"application","aria-label":"Calendar","aria-multiselectable":this.selectionMode==="multiple"?"true":void 0,children:[p("div",{class:"rui-calendar__months",children:this.monthPanels.map((r,a)=>ge("div",{class:"rui-calendar__month-panel","data-calendar-month-panel":!0,children:[ge("div",{class:"rui-calendar__header",children:[a===0?p("button",{type:"button",class:"rui-calendar__nav","data-calendar-prev-month":!0,"aria-label":"Previous month",disabled:this.disabled,children:"\u2039"}):p("span",{class:"rui-calendar__nav-spacer","aria-hidden":"true"}),p("div",{class:"rui-calendar__month","aria-live":"polite",children:r.label}),a===e-1?p("button",{type:"button",class:"rui-calendar__nav","data-calendar-next-month":!0,"aria-label":"Next month",disabled:this.disabled,children:"\u203A"}):p("span",{class:"rui-calendar__nav-spacer","aria-hidden":"true"})]}),a===0?p("div",{class:"rui-calendar__weekdays",role:"row",children:this.weekdayLabels.map(i=>p("div",{class:"rui-calendar__weekday",role:"columnheader","aria-hidden":"true",children:i}))}):null,p("div",{class:"rui-calendar__grid",role:"grid","data-calendar-grid":!0,children:r.weeks.map(i=>p("div",{class:"rui-calendar__week",role:"row",children:i.map(s=>p("button",{type:"button",class:"rui-calendar__day","data-calendar-day":!0,"data-iso":s.iso,role:"gridcell",disabled:this.disabled||s.isDisabled,tabIndex:s.iso===this.focusedIso?0:-1,"aria-selected":s.isSelected?"true":"false","aria-current":s.isToday?"date":void 0,"data-outside":s.inMonth?void 0:"true",...this.dayDataAttributes(s),children:s.date.getDate()}))}))})]}))}),p("div",{class:"rui-calendar__footer",children:p("button",{type:"button",class:"rui-calendar__today","data-calendar-today":!0,disabled:this.disabled,children:this.todayLabel})})]})}static{Le()}};import{jsx as Et}from"@ecopages/jsx/jsx-runtime";function Lt({children:t,...e}){return Et("rui-calendar",{...e,children:t})}export{Lt as RuiCalendar,mt as RuiCalendarElement};
2
2
  //# sourceMappingURL=index.js.map