@vielzeug/refine 1.5.0 → 1.5.2

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 (246) hide show
  1. package/dist/async.cjs +9 -9
  2. package/dist/async.cjs.map +1 -1
  3. package/dist/async.js +30 -31
  4. package/dist/async.js.map +1 -1
  5. package/dist/button.cjs +6 -6
  6. package/dist/button.cjs.map +1 -1
  7. package/dist/button.js +29 -30
  8. package/dist/button.js.map +1 -1
  9. package/dist/calendar.cjs +44 -44
  10. package/dist/calendar.cjs.map +1 -1
  11. package/dist/calendar.js +115 -117
  12. package/dist/calendar.js.map +1 -1
  13. package/dist/checkbox-group.cjs +7 -7
  14. package/dist/checkbox-group.cjs.map +1 -1
  15. package/dist/checkbox-group.js +71 -73
  16. package/dist/checkbox-group.js.map +1 -1
  17. package/dist/checkbox.cjs +3 -3
  18. package/dist/checkbox.cjs.map +1 -1
  19. package/dist/checkbox.js +28 -29
  20. package/dist/checkbox.js.map +1 -1
  21. package/dist/code-window.cjs +7 -7
  22. package/dist/code-window.cjs.map +1 -1
  23. package/dist/code-window.js +17 -18
  24. package/dist/code-window.js.map +1 -1
  25. package/dist/combobox.cjs +1 -1
  26. package/dist/combobox.cjs.map +1 -1
  27. package/dist/combobox.js +11 -12
  28. package/dist/combobox.js.map +1 -1
  29. package/dist/custom-elements.json +3581 -3581
  30. package/dist/datagrid.cjs +66 -66
  31. package/dist/datagrid.cjs.map +1 -1
  32. package/dist/datagrid.js +267 -268
  33. package/dist/datagrid.js.map +1 -1
  34. package/dist/date-picker.cjs +11 -11
  35. package/dist/date-picker.cjs.map +1 -1
  36. package/dist/date-picker.js +8 -9
  37. package/dist/date-picker.js.map +1 -1
  38. package/dist/file-input.cjs +6 -6
  39. package/dist/file-input.cjs.map +1 -1
  40. package/dist/file-input.js +50 -51
  41. package/dist/file-input.js.map +1 -1
  42. package/dist/grid.cjs +1 -1
  43. package/dist/grid.cjs.map +1 -1
  44. package/dist/grid.js +47 -48
  45. package/dist/grid.js.map +1 -1
  46. package/dist/icon.cjs +1 -1
  47. package/dist/icon.cjs.map +1 -1
  48. package/dist/icon.js +26 -27
  49. package/dist/icon.js.map +1 -1
  50. package/dist/input.cjs +20 -20
  51. package/dist/input.cjs.map +1 -1
  52. package/dist/input.js +98 -100
  53. package/dist/input.js.map +1 -1
  54. package/dist/layout/navbar/navbar.css.cjs +1 -1
  55. package/dist/layout/navbar/navbar.css.cjs.map +1 -1
  56. package/dist/layout/navbar/navbar.css.js +1 -1
  57. package/dist/layout/navbar/navbar.css.js.map +1 -1
  58. package/dist/layout/navbar/navbar.d.ts +1 -0
  59. package/dist/layout/navbar/navbar.d.ts.map +1 -1
  60. package/dist/message-composer.cjs +18 -18
  61. package/dist/message-composer.cjs.map +1 -1
  62. package/dist/message-composer.js +113 -115
  63. package/dist/message-composer.js.map +1 -1
  64. package/dist/navbar.cjs +16 -13
  65. package/dist/navbar.cjs.map +1 -1
  66. package/dist/navbar.js +84 -79
  67. package/dist/navbar.js.map +1 -1
  68. package/dist/otp-input.cjs +4 -4
  69. package/dist/otp-input.cjs.map +1 -1
  70. package/dist/otp-input.js +31 -32
  71. package/dist/otp-input.js.map +1 -1
  72. package/dist/progress.cjs +13 -13
  73. package/dist/progress.cjs.map +1 -1
  74. package/dist/progress.js +45 -46
  75. package/dist/progress.js.map +1 -1
  76. package/dist/radio-group.cjs +5 -5
  77. package/dist/radio-group.cjs.map +1 -1
  78. package/dist/radio-group.js +83 -85
  79. package/dist/radio-group.js.map +1 -1
  80. package/dist/radio.cjs +3 -3
  81. package/dist/radio.cjs.map +1 -1
  82. package/dist/radio.js +27 -28
  83. package/dist/radio.js.map +1 -1
  84. package/dist/rating.cjs +4 -4
  85. package/dist/rating.cjs.map +1 -1
  86. package/dist/rating.js +30 -31
  87. package/dist/rating.js.map +1 -1
  88. package/dist/refine.cjs +8 -5
  89. package/dist/refine.cjs.map +1 -1
  90. package/dist/refine.iife.js +8 -5
  91. package/dist/refine.iife.js.map +1 -1
  92. package/dist/refine.js +8 -5
  93. package/dist/refine.js.map +1 -1
  94. package/dist/select.cjs +4 -4
  95. package/dist/select.cjs.map +1 -1
  96. package/dist/select.js +88 -89
  97. package/dist/select.js.map +1 -1
  98. package/dist/sidebar.cjs +11 -11
  99. package/dist/sidebar.cjs.map +1 -1
  100. package/dist/sidebar.js +97 -98
  101. package/dist/sidebar.js.map +1 -1
  102. package/dist/skeleton.cjs +3 -3
  103. package/dist/skeleton.cjs.map +1 -1
  104. package/dist/skeleton.js +23 -24
  105. package/dist/skeleton.js.map +1 -1
  106. package/dist/slider.cjs +3 -3
  107. package/dist/slider.cjs.map +1 -1
  108. package/dist/slider.js +65 -66
  109. package/dist/slider.js.map +1 -1
  110. package/dist/switch.cjs +3 -3
  111. package/dist/switch.cjs.map +1 -1
  112. package/dist/switch.js +23 -24
  113. package/dist/switch.js.map +1 -1
  114. package/dist/tab-panel.cjs +7 -7
  115. package/dist/tab-panel.cjs.map +1 -1
  116. package/dist/tab-panel.js +21 -23
  117. package/dist/tab-panel.js.map +1 -1
  118. package/dist/testing.cjs +1 -1
  119. package/dist/testing.cjs.map +1 -1
  120. package/dist/testing.js +4 -5
  121. package/dist/testing.js.map +1 -1
  122. package/dist/textarea.cjs +13 -13
  123. package/dist/textarea.cjs.map +1 -1
  124. package/dist/textarea.js +92 -94
  125. package/dist/textarea.js.map +1 -1
  126. package/dist/time-picker.cjs +9 -9
  127. package/dist/time-picker.cjs.map +1 -1
  128. package/dist/time-picker.js +47 -48
  129. package/dist/time-picker.js.map +1 -1
  130. package/package.json +1 -1
  131. package/dist/ore/dist/_dev.cjs +0 -2
  132. package/dist/ore/dist/_dev.cjs.map +0 -1
  133. package/dist/ore/dist/_dev.js +0 -12
  134. package/dist/ore/dist/_dev.js.map +0 -1
  135. package/dist/ore/dist/base-element.cjs +0 -2
  136. package/dist/ore/dist/base-element.cjs.map +0 -1
  137. package/dist/ore/dist/base-element.js +0 -158
  138. package/dist/ore/dist/base-element.js.map +0 -1
  139. package/dist/ore/dist/context.cjs +0 -2
  140. package/dist/ore/dist/context.cjs.map +0 -1
  141. package/dist/ore/dist/context.js +0 -11
  142. package/dist/ore/dist/context.js.map +0 -1
  143. package/dist/ore/dist/define.cjs +0 -2
  144. package/dist/ore/dist/define.cjs.map +0 -1
  145. package/dist/ore/dist/define.js +0 -27
  146. package/dist/ore/dist/define.js.map +0 -1
  147. package/dist/ore/dist/directives/classMap.cjs +0 -1
  148. package/dist/ore/dist/directives/classMap.js +0 -1
  149. package/dist/ore/dist/directives/each.cjs +0 -1
  150. package/dist/ore/dist/directives/each.js +0 -5
  151. package/dist/ore/dist/directives/live.cjs +0 -2
  152. package/dist/ore/dist/directives/live.cjs.map +0 -1
  153. package/dist/ore/dist/directives/live.js +0 -6
  154. package/dist/ore/dist/directives/live.js.map +0 -1
  155. package/dist/ore/dist/directives/model.cjs +0 -1
  156. package/dist/ore/dist/directives/model.js +0 -3
  157. package/dist/ore/dist/directives/raw.cjs +0 -2
  158. package/dist/ore/dist/directives/raw.cjs.map +0 -1
  159. package/dist/ore/dist/directives/raw.js +0 -38
  160. package/dist/ore/dist/directives/raw.js.map +0 -1
  161. package/dist/ore/dist/directives/styleMap.cjs +0 -2
  162. package/dist/ore/dist/directives/styleMap.cjs.map +0 -1
  163. package/dist/ore/dist/directives/styleMap.js +0 -20
  164. package/dist/ore/dist/directives/styleMap.js.map +0 -1
  165. package/dist/ore/dist/directives/when.cjs +0 -2
  166. package/dist/ore/dist/directives/when.cjs.map +0 -1
  167. package/dist/ore/dist/directives/when.js +0 -38
  168. package/dist/ore/dist/directives/when.js.map +0 -1
  169. package/dist/ore/dist/directives.cjs +0 -1
  170. package/dist/ore/dist/directives.js +0 -8
  171. package/dist/ore/dist/errors.cjs +0 -3
  172. package/dist/ore/dist/errors.cjs.map +0 -1
  173. package/dist/ore/dist/errors.js +0 -50
  174. package/dist/ore/dist/errors.js.map +0 -1
  175. package/dist/ore/dist/forms/context.cjs +0 -2
  176. package/dist/ore/dist/forms/context.cjs.map +0 -1
  177. package/dist/ore/dist/forms/context.js +0 -6
  178. package/dist/ore/dist/forms/context.js.map +0 -1
  179. package/dist/ore/dist/forms/field.cjs +0 -2
  180. package/dist/ore/dist/forms/field.cjs.map +0 -1
  181. package/dist/ore/dist/forms/field.js +0 -42
  182. package/dist/ore/dist/forms/field.js.map +0 -1
  183. package/dist/ore/dist/forms.cjs +0 -1
  184. package/dist/ore/dist/forms.js +0 -3
  185. package/dist/ore/dist/observers/intersection-observe.cjs +0 -2
  186. package/dist/ore/dist/observers/intersection-observe.cjs.map +0 -1
  187. package/dist/ore/dist/observers/intersection-observe.js +0 -12
  188. package/dist/ore/dist/observers/intersection-observe.js.map +0 -1
  189. package/dist/ore/dist/observers/media-observe.cjs +0 -1
  190. package/dist/ore/dist/observers/media-observe.js +0 -1
  191. package/dist/ore/dist/observers/mutation-observe.cjs +0 -1
  192. package/dist/ore/dist/observers/mutation-observe.js +0 -1
  193. package/dist/ore/dist/observers/resize-observe.cjs +0 -2
  194. package/dist/ore/dist/observers/resize-observe.cjs.map +0 -1
  195. package/dist/ore/dist/observers/resize-observe.js +0 -20
  196. package/dist/ore/dist/observers/resize-observe.js.map +0 -1
  197. package/dist/ore/dist/observers.cjs +0 -1
  198. package/dist/ore/dist/observers.js +0 -5
  199. package/dist/ore/dist/props.cjs +0 -2
  200. package/dist/ore/dist/props.cjs.map +0 -1
  201. package/dist/ore/dist/props.js +0 -56
  202. package/dist/ore/dist/props.js.map +0 -1
  203. package/dist/ore/dist/runtime.cjs +0 -2
  204. package/dist/ore/dist/runtime.cjs.map +0 -1
  205. package/dist/ore/dist/runtime.js +0 -25
  206. package/dist/ore/dist/runtime.js.map +0 -1
  207. package/dist/ore/dist/testing/flush.cjs +0 -2
  208. package/dist/ore/dist/testing/flush.cjs.map +0 -1
  209. package/dist/ore/dist/testing/flush.js +0 -11
  210. package/dist/ore/dist/testing/flush.js.map +0 -1
  211. package/dist/ore/dist/testing/mount.cjs +0 -2
  212. package/dist/ore/dist/testing/mount.cjs.map +0 -1
  213. package/dist/ore/dist/testing/mount.js +0 -94
  214. package/dist/ore/dist/testing/mount.js.map +0 -1
  215. package/dist/ore/dist/testing/query.cjs +0 -2
  216. package/dist/ore/dist/testing/query.cjs.map +0 -1
  217. package/dist/ore/dist/testing/query.js +0 -12
  218. package/dist/ore/dist/testing/query.js.map +0 -1
  219. package/dist/ore/dist/testing/render-hook.cjs +0 -1
  220. package/dist/ore/dist/testing/render-hook.js +0 -3
  221. package/dist/ore/dist/testing/testing.cjs +0 -1
  222. package/dist/ore/dist/testing/testing.js +0 -4
  223. package/dist/ore/dist/testing/wait.cjs +0 -1
  224. package/dist/ore/dist/testing/wait.js +0 -1
  225. package/dist/ore/dist/testing.cjs +0 -1
  226. package/dist/ore/dist/testing.js +0 -6
  227. package/dist/ore/dist/types/bindings.cjs +0 -2
  228. package/dist/ore/dist/types/bindings.cjs.map +0 -1
  229. package/dist/ore/dist/types/bindings.js +0 -15
  230. package/dist/ore/dist/types/bindings.js.map +0 -1
  231. package/dist/ore/dist/types.cjs +0 -2
  232. package/dist/ore/dist/types.cjs.map +0 -1
  233. package/dist/ore/dist/types.js +0 -15
  234. package/dist/ore/dist/types.js.map +0 -1
  235. package/dist/ore/dist/utils/css.cjs +0 -2
  236. package/dist/ore/dist/utils/css.cjs.map +0 -1
  237. package/dist/ore/dist/utils/css.js +0 -18
  238. package/dist/ore/dist/utils/css.js.map +0 -1
  239. package/dist/ore/dist/utils/dom.cjs +0 -2
  240. package/dist/ore/dist/utils/dom.cjs.map +0 -1
  241. package/dist/ore/dist/utils/dom.js +0 -43
  242. package/dist/ore/dist/utils/dom.js.map +0 -1
  243. package/dist/ore/dist/utils/id.cjs +0 -2
  244. package/dist/ore/dist/utils/id.cjs.map +0 -1
  245. package/dist/ore/dist/utils/id.js +0 -4
  246. package/dist/ore/dist/utils/id.js.map +0 -1
package/dist/sidebar.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { coarsePointerMixin as e, reducedMotionMixin as t } from "./styles/mixins/accessibility.css.js";
2
2
  import { computeSafeRel as n } from "./utils/link.js";
3
- import { resizeObserver as r } from "./ore/dist/observers/resize-observe.js";
4
- import "./ore/dist/observers.js";
5
- import i from "./layout/sidebar/sidebar-group.css.js";
6
- import a from "./layout/sidebar/sidebar-item.css.js";
7
- import o from "./layout/sidebar/sidebar.css.js";
8
- import { bind as s, createContext as c, define as l, getHost as u, html as d, inject as f, onMounted as p, prop as m, provide as h, useEmit as g, useSlots as _ } from "@vielzeug/ore";
9
- import { computed as v, signal as y, watch as b } from "@vielzeug/ripple";
3
+ import r from "./layout/sidebar/sidebar-group.css.js";
4
+ import i from "./layout/sidebar/sidebar-item.css.js";
5
+ import a from "./layout/sidebar/sidebar.css.js";
6
+ import { bind as o, createContext as s, define as c, getHost as l, html as u, inject as d, onMounted as f, prop as p, provide as m, useEmit as h, useSlots as g } from "@vielzeug/ore";
7
+ import { computed as _, signal as v, watch as y } from "@vielzeug/ripple";
8
+ import { resizeObserver as b } from "@vielzeug/ore/observers";
10
9
  //#region src/layout/sidebar/sidebar.ts
11
10
  var x = (e) => {
12
11
  let t = String(e ?? "").trim();
@@ -22,24 +21,24 @@ var x = (e) => {
22
21
  }, C = (e) => {
23
22
  let t = S(e)?.clientWidth ?? 0;
24
23
  return t > 0 ? t : e.offsetWidth;
25
- }, w = c("SidebarContext"), T = "ore-sidebar";
26
- l(T, {
24
+ }, w = s("SidebarContext"), T = "ore-sidebar";
25
+ c(T, {
27
26
  props: {
28
- "bottom-nav-at": m.string(),
29
- collapsed: m.bool(!1),
30
- collapsible: m.bool(!1),
31
- "container-breakpoints": m.bool(!1),
32
- "default-collapsed": m.bool(!1),
33
- label: m.string("Sidebar navigation"),
34
- responsive: m.string(),
35
- variant: m.string()
27
+ "bottom-nav-at": p.string(),
28
+ collapsed: p.bool(!1),
29
+ collapsible: p.bool(!1),
30
+ "container-breakpoints": p.bool(!1),
31
+ "default-collapsed": p.bool(!1),
32
+ label: p.string("Sidebar navigation"),
33
+ responsive: p.string(),
34
+ variant: p.string()
36
35
  },
37
36
  setup(e) {
38
- let t = u(), n = g(), i = _(), a = () => i.has("header").value, o = () => i.has("footer").value, c = () => i.has("logo").value, l = y(t.hasAttribute("collapsed")), f = y(l.value ? t.hasAttribute("collapsed") : e["default-collapsed"].value), m = y(!1), T = y(!1), E = y([]), D = y(!1), O = y(!1), k = y(x(e.responsive.value)), A = y(!!String(e.responsive.value ?? "").trim()), j = y(!1), M = y(!1), N = y(x(e["bottom-nav-at"].value)), P = y(!1), F = () => f.value, I = v(() => m.value ? "bottom-nav" : f.value ? "collapsed" : "default"), L = () => {
37
+ let t = l(), n = h(), r = g(), i = () => r.has("header").value, a = () => r.has("footer").value, s = () => r.has("logo").value, c = v(t.hasAttribute("collapsed")), d = v(c.value ? t.hasAttribute("collapsed") : e["default-collapsed"].value), p = v(!1), T = v(!1), E = v([]), D = v(!1), O = v(!1), k = v(x(e.responsive.value)), A = v(!!String(e.responsive.value ?? "").trim()), j = v(!1), M = v(!1), N = v(x(e["bottom-nav-at"].value)), P = v(!1), F = () => d.value, I = _(() => p.value ? "bottom-nav" : d.value ? "collapsed" : "default"), L = () => {
39
38
  let t = e["container-breakpoints"].value, n = t ? O.value : D.value || O.value, r = t ? M.value : j.value || M.value;
40
- T.value || (m.value = r), !r && !T.value && B(!1, "responsive"), A.value && z(n, "responsive");
39
+ T.value || (p.value = r), !r && !T.value && B(!1, "responsive"), A.value && z(n, "responsive");
41
40
  }, R = () => {
42
- let e = i.elements().value.filter((e) => e instanceof HTMLElement && e.tagName.toLowerCase() === "ore-sidebar-item").map((e, t) => {
41
+ let e = r.elements().value.filter((e) => e instanceof HTMLElement && e.tagName.toLowerCase() === "ore-sidebar-item").map((e, t) => {
43
42
  let n = e.querySelector(":scope > [slot=\"icon\"]") ?? e.querySelector("[slot=\"icon\"]"), r = n?.tagName.toLowerCase() === "ore-icon" ? n.getAttribute("name") : null, i = n?.querySelector("ore-icon")?.getAttribute("name") ?? null, a = (e.textContent ?? "").trim();
44
43
  return {
45
44
  active: e.hasAttribute("active"),
@@ -52,20 +51,20 @@ l(T, {
52
51
  });
53
52
  E.value = e;
54
53
  };
55
- h(w, {
56
- collapsed: v(() => !m.value && f.value),
57
- mobileOpen: v(() => m.value && T.value),
54
+ m(w, {
55
+ collapsed: _(() => !p.value && d.value),
56
+ mobileOpen: _(() => p.value && T.value),
58
57
  mode: I,
59
58
  variant: e.variant
60
59
  });
61
60
  let z = (e, t) => {
62
- F() !== e && (l.value || (f.value = e), n("collapsed-change", {
61
+ F() !== e && (c.value || (d.value = e), n("collapsed-change", {
63
62
  collapsed: e,
64
63
  source: t
65
64
  }));
66
65
  }, B = (e, t) => {
67
66
  let r = !!e;
68
- if (r && !m.value && (m.value = !0), !m.value && !r) {
67
+ if (r && !p.value && (p.value = !0), !p.value && !r) {
69
68
  T.value &&= !1;
70
69
  return;
71
70
  }
@@ -76,70 +75,70 @@ l(T, {
76
75
  }, V = () => {
77
76
  z(!F(), "toggle");
78
77
  }, H = t;
79
- return H.setCollapsed = (e) => z(!!e, "api"), H.toggle = V, H.openMobile = () => B(!0, "api"), H.closeMobile = () => B(!1, "api"), H.toggleMobile = () => B(!T.value, "toggle"), s({ attr: {
80
- "data-bottom-nav": () => m.value ? !0 : void 0,
81
- "data-collapsed": () => F() && !m.value ? !0 : void 0,
82
- "data-mobile-open": () => m.value && T.value ? !0 : void 0,
78
+ return H.setCollapsed = (e) => z(!!e, "api"), H.toggle = V, H.openMobile = () => B(!0, "api"), H.closeMobile = () => B(!1, "api"), H.toggleMobile = () => B(!T.value, "toggle"), o({ attr: {
79
+ "data-bottom-nav": () => p.value ? !0 : void 0,
80
+ "data-collapsed": () => F() && !p.value ? !0 : void 0,
81
+ "data-mobile-open": () => p.value && T.value ? !0 : void 0,
83
82
  "data-preview-mode": () => P.value ? !0 : void 0
84
- } }), p(() => {
83
+ } }), f(() => {
85
84
  t.setAttribute("data-no-transition", "");
86
- let n = !1, a = () => {
85
+ let n = !1, i = () => {
87
86
  n || (n = !0, t.removeAttribute("data-no-transition"));
88
87
  };
89
- requestAnimationFrame(() => requestAnimationFrame(a));
90
- let o, s, c = /* @__PURE__ */ new Map(), u = new MutationObserver(() => {
91
- !t.hasAttribute("collapsed") && !l.value || (l.value = !0, f.value = t.hasAttribute("collapsed"));
88
+ requestAnimationFrame(() => requestAnimationFrame(i));
89
+ let a, o, s = /* @__PURE__ */ new Map(), l = new MutationObserver(() => {
90
+ !t.hasAttribute("collapsed") && !c.value || (c.value = !0, d.value = t.hasAttribute("collapsed"));
92
91
  });
93
- u.observe(t, {
92
+ l.observe(t, {
94
93
  attributeFilter: ["collapsed"],
95
94
  attributes: !0
96
- }), b(e.responsive, (n) => {
97
- o?.(), o = void 0;
95
+ }), y(e.responsive, (n) => {
96
+ a?.(), a = void 0;
98
97
  let r = String(n ?? "").trim();
99
98
  A.value = !!r, k.value = x(r), D.value = !1;
100
99
  let i = C(t);
101
100
  if (O.value = i > 0 && k.value != null ? i <= k.value : !1, L(), e["container-breakpoints"].value && k.value != null || !r || typeof window.matchMedia != "function") return;
102
- let a = window.matchMedia(r), s = (e) => {
101
+ let o = window.matchMedia(r), s = (e) => {
103
102
  D.value = e.matches, L();
104
103
  };
105
- D.value = a.matches, L(), a.addEventListener("change", s), o = () => {
106
- a.removeEventListener("change", s);
104
+ D.value = o.matches, L(), o.addEventListener("change", s), a = () => {
105
+ o.removeEventListener("change", s);
107
106
  };
108
- }, { immediate: !0 }), b(e["bottom-nav-at"], (n) => {
109
- s?.(), s = void 0;
107
+ }, { immediate: !0 }), y(e["bottom-nav-at"], (n) => {
108
+ o?.(), o = void 0;
110
109
  let r = String(n ?? "").trim();
111
110
  N.value = x(r), j.value = !1;
112
111
  let i = C(t);
113
112
  if (M.value = i > 0 && N.value != null ? i <= N.value : !1, L(), e["container-breakpoints"].value && N.value != null || !r || typeof window.matchMedia != "function") return;
114
- let a = window.matchMedia(r), o = (e) => {
113
+ let a = window.matchMedia(r), s = (e) => {
115
114
  j.value = e.matches, L();
116
115
  };
117
- j.value = a.matches, L(), a.addEventListener("change", o), s = () => {
118
- a.removeEventListener("change", o);
116
+ j.value = a.matches, L(), a.addEventListener("change", s), o = () => {
117
+ a.removeEventListener("change", s);
119
118
  };
120
119
  }, { immediate: !0 });
121
- let d = typeof ResizeObserver == "function" ? (() => {
122
- let e = r(t), n = t.parentElement, i = S(t), o = n ? r(n) : void 0, s = i && i !== n ? r(i) : void 0, c;
123
- return b(v(() => [
120
+ let u = typeof ResizeObserver == "function" ? (() => {
121
+ let e = b(t), n = t.parentElement, r = S(t), a = n ? b(n) : void 0, o = r && r !== n ? b(r) : void 0, s;
122
+ return y(_(() => [
124
123
  e.value.width,
125
124
  e.value.height,
125
+ a?.value.width,
126
+ a?.value.height,
126
127
  o?.value.width,
127
- o?.value.height,
128
- s?.value.width,
129
- s?.value.height
128
+ o?.value.height
130
129
  ]), () => {
131
- c !== void 0 && cancelAnimationFrame(c), c = requestAnimationFrame(() => {
132
- let e = S(t), n = C(t), r = O.value, i = M.value, o = e?.clientWidth ?? 0;
133
- P.value = o > 0 && o < window.innerWidth, O.value = n > 0 && k.value != null ? n <= k.value : !1, M.value = n > 0 && N.value != null ? n <= N.value : !1, (r !== O.value || i !== M.value) && L(), a();
130
+ s !== void 0 && cancelAnimationFrame(s), s = requestAnimationFrame(() => {
131
+ let e = S(t), n = C(t), r = O.value, a = M.value, o = e?.clientWidth ?? 0;
132
+ P.value = o > 0 && o < window.innerWidth, O.value = n > 0 && k.value != null ? n <= k.value : !1, M.value = n > 0 && N.value != null ? n <= N.value : !1, (r !== O.value || a !== M.value) && L(), i();
134
133
  });
135
134
  });
136
- })() : void 0, p = (e) => {
135
+ })() : void 0, f = (e) => {
137
136
  let t = new Set(e);
138
- for (let [e, n] of c) t.has(e) || (n.disconnect(), c.delete(e));
137
+ for (let [e, n] of s) t.has(e) || (n.disconnect(), s.delete(e));
139
138
  for (let t of e) {
140
- if (c.has(t)) continue;
139
+ if (s.has(t)) continue;
141
140
  let e = new MutationObserver(() => {
142
- m.value && R();
141
+ p.value && R();
143
142
  });
144
143
  e.observe(t, {
145
144
  attributeFilter: [
@@ -148,28 +147,28 @@ l(T, {
148
147
  "href"
149
148
  ],
150
149
  attributes: !0
151
- }), c.set(t, e);
150
+ }), s.set(t, e);
152
151
  }
153
152
  };
154
- return b(i.elements(), (e) => {
153
+ return y(r.elements(), (e) => {
155
154
  let t = e.filter((e) => e instanceof HTMLElement && e.tagName.toLowerCase() === "ore-sidebar-item");
156
- p(t), R();
155
+ f(t), R();
157
156
  }, { immediate: !0 }), () => {
158
- u.disconnect(), o?.(), s?.(), d?.dispose();
159
- for (let e of c.values()) e.disconnect();
160
- c.clear();
157
+ l.disconnect(), a?.(), o?.(), u?.dispose();
158
+ for (let e of s.values()) e.disconnect();
159
+ s.clear();
161
160
  };
162
- }), d`
161
+ }), u`
163
162
  <button
164
163
  class="mobile-backdrop"
165
164
  part="mobile-backdrop"
166
165
  type="button"
167
166
  aria-label="Close sidebar"
168
- ?hidden=${() => !m.value || !T.value}
167
+ ?hidden=${() => !p.value || !T.value}
169
168
  @click=${() => B(!1, "toggle")}></button>
170
169
  <nav aria-label="${e.label}" part="nav">
171
- <div class="sidebar-header" part="header" ?hidden=${() => !a() && !e.collapsible.value}>
172
- <span class="sidebar-logo" ?hidden=${() => !c()}>
170
+ <div class="sidebar-header" part="header" ?hidden=${() => !i() && !e.collapsible.value}>
171
+ <span class="sidebar-logo" ?hidden=${() => !s()}>
173
172
  <slot name="logo"></slot>
174
173
  </span>
175
174
  <span class="sidebar-header-content">
@@ -191,15 +190,15 @@ l(T, {
191
190
  <div class="sidebar-content" part="content">
192
191
  <slot></slot>
193
192
  </div>
194
- <div class="sidebar-footer" part="footer" ?hidden=${() => !o()}>
193
+ <div class="sidebar-footer" part="footer" ?hidden=${() => !a()}>
195
194
  <slot name="footer"></slot>
196
195
  </div>
197
196
  </nav>
198
197
 
199
- <div class="bottom-bar" part="bottom-bar" ?hidden=${() => !m.value}>
198
+ <div class="bottom-bar" part="bottom-bar" ?hidden=${() => !p.value}>
200
199
  ${() => E.value.map((e) => {
201
200
  let t = `bottom-tab${e.active ? " bottom-tab-active" : ""}`;
202
- return e.href && !e.disabled ? d`
201
+ return e.href && !e.disabled ? u`
203
202
  <a
204
203
  class="${t}"
205
204
  href="${e.href}"
@@ -210,7 +209,7 @@ l(T, {
210
209
  </span>
211
210
  <span class="bottom-tab-label">${e.label}</span>
212
211
  </a>
213
- ` : d`
212
+ ` : u`
214
213
  <button
215
214
  class="${t}"
216
215
  type="button"
@@ -231,15 +230,15 @@ l(T, {
231
230
  styles: [
232
231
  e,
233
232
  t,
234
- o
233
+ a
235
234
  ]
236
235
  });
237
236
  var E = "ore-sidebar-group";
238
- l(E, {
237
+ c(E, {
239
238
  props: {
240
- collapsible: m.bool(!1),
241
- "default-open": m.bool(!0),
242
- label: m.string(),
239
+ collapsible: p.bool(!1),
240
+ "default-open": p.bool(!0),
241
+ label: p.string(),
243
242
  open: {
244
243
  default: void 0,
245
244
  parse: (e) => e == null ? void 0 : e === "" || e === "true",
@@ -247,16 +246,16 @@ l(E, {
247
246
  }
248
247
  },
249
248
  setup(e) {
250
- let t = _(), n = () => t.has("icon").value, r = f(w);
251
- s({ attr: {
249
+ let t = g(), n = () => t.has("icon").value, r = d(w);
250
+ o({ attr: {
252
251
  "sidebar-bottom-nav": () => r?.mode.value === "bottom-nav" && !r?.mobileOpen.value ? !0 : void 0,
253
252
  "sidebar-collapsed": () => r?.collapsed.value ? !0 : void 0
254
253
  } });
255
- let i = () => e.open.value !== void 0, a = y(e["default-open"].value), o = v(() => e.collapsible.value ? i() ? e.open.value ?? !1 : a.value : !0);
256
- return b(e.open, (e) => {
254
+ let i = () => e.open.value !== void 0, a = v(e["default-open"].value), s = _(() => e.collapsible.value ? i() ? e.open.value ?? !1 : a.value : !0);
255
+ return y(e.open, (e) => {
257
256
  e !== void 0 && (a.value = e);
258
- }), s({ attr: { open: () => o.value ? !0 : void 0 } }), d`
259
- <details class="group" part="group" ?open=${o}>
257
+ }), o({ attr: { open: () => s.value ? !0 : void 0 } }), u`
258
+ <details class="group" part="group" ?open=${s}>
260
259
  <summary
261
260
  class="group-header"
262
261
  part="group-header"
@@ -278,24 +277,24 @@ l(E, {
278
277
  </details>
279
278
  `;
280
279
  },
281
- styles: [t, i]
280
+ styles: [t, r]
282
281
  });
283
282
  var D = "ore-sidebar-item";
284
- l(D, {
283
+ c(D, {
285
284
  props: {
286
- active: m.bool(!1),
287
- disabled: m.bool(!1),
288
- href: m.string(),
289
- rel: m.string(),
290
- target: m.string()
285
+ active: p.bool(!1),
286
+ disabled: p.bool(!1),
287
+ href: p.string(),
288
+ rel: p.string(),
289
+ target: p.string()
291
290
  },
292
291
  setup(e) {
293
- let t = _(), r = () => t.has("icon").value, i = () => t.has("end").value, a = f(w);
294
- s({ attr: {
292
+ let t = g(), r = () => t.has("icon").value, i = () => t.has("end").value, a = d(w);
293
+ o({ attr: {
295
294
  "sidebar-bottom-nav": () => a?.mode.value === "bottom-nav" && !a?.mobileOpen.value ? !0 : void 0,
296
295
  "sidebar-collapsed": () => a?.collapsed.value ? !0 : void 0
297
296
  } });
298
- let o = () => !!e.href.value && !e.disabled.value, c = v(() => n(e.rel.value, e.target.value)), l = () => d`
297
+ let s = () => !!e.href.value && !e.disabled.value, c = _(() => n(e.rel.value, e.target.value)), l = () => u`
299
298
  <span class="item-icon" part="item-icon" ?hidden=${() => !r()} aria-hidden="true">
300
299
  <slot name="icon"></slot>
301
300
  </span>
@@ -304,8 +303,8 @@ l(D, {
304
303
  <slot name="end"></slot>
305
304
  </span>
306
305
  `;
307
- return d`
308
- ${() => o() ? d`
306
+ return u`
307
+ ${() => s() ? u`
309
308
  <a
310
309
  class="item"
311
310
  part="item"
@@ -315,7 +314,7 @@ l(D, {
315
314
  aria-current="${() => e.active.value ? "page" : null}">
316
315
  ${l()}
317
316
  </a>
318
- ` : e.disabled.value ? d`
317
+ ` : e.disabled.value ? u`
319
318
  <div
320
319
  class="item"
321
320
  part="item"
@@ -324,7 +323,7 @@ l(D, {
324
323
  aria-current="${() => e.active.value ? "page" : null}">
325
324
  ${l()}
326
325
  </div>
327
- ` : d`
326
+ ` : u`
328
327
  <button
329
328
  class="item"
330
329
  part="item"
@@ -336,7 +335,7 @@ l(D, {
336
335
  `}
337
336
  `;
338
337
  },
339
- styles: [e, a]
338
+ styles: [e, i]
340
339
  });
341
340
  //#endregion
342
341
  export { w as SIDEBAR_CTX, E as SIDEBAR_GROUP_TAG, D as SIDEBAR_ITEM_TAG, T as SIDEBAR_TAG };
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.js","names":[],"sources":["../src/layout/sidebar/sidebar.ts"],"sourcesContent":["import {\n createContext,\n define,\n html,\n inject,\n prop,\n bind,\n getHost,\n onMounted,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { resizeObserver } from '@vielzeug/ore/observers';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\n\nimport '../../content/icon/icon';\nimport { coarsePointerMixin, reducedMotionMixin } from '../../styles';\nimport { computeSafeRel } from '../../utils';\nimport groupStyles from './sidebar-group.css?inline';\nimport itemStyles from './sidebar-item.css?inline';\nimport sidebarStyles from './sidebar.css?inline';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\ntype SidebarVariant = 'floating' | 'inset';\ntype SidebarCollapseSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMobileSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMode = 'bottom-nav' | 'collapsed' | 'default';\n\ntype BottomNavItem = {\n active: boolean;\n disabled: boolean;\n href?: string;\n iconName?: string;\n label: string;\n source: HTMLElement;\n};\n\nconst parseMaxWidthPx = (query: string | undefined): number | undefined => {\n const value = String(query ?? '').trim();\n\n if (!value) return undefined;\n\n const match = /max-width\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)px/i.exec(value);\n\n if (!match) return undefined;\n\n const parsed = Number.parseFloat(match[1]);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nconst resolveContainerElement = (el: HTMLElement): HTMLElement | null => {\n let container = el.parentElement;\n\n while (container?.tagName.toLowerCase() === 'ore-grid-item') {\n container = container.parentElement;\n }\n\n return container;\n};\n\nconst readContainerWidth = (el: HTMLElement): number => {\n const parentWidth = resolveContainerElement(el)?.clientWidth ?? 0;\n\n if (parentWidth > 0) return parentWidth;\n\n return el.offsetWidth;\n};\n\n/** Context provided by `ore-sidebar` to its `ore-sidebar-group` and `ore-sidebar-item` children. */\nexport type SidebarContext = {\n collapsed: Readable<boolean>;\n mobileOpen: Readable<boolean>;\n mode: Readable<SidebarMode>;\n variant: Readable<SidebarVariant | undefined>;\n};\n\n/** Injection key for the sidebar context. */\nexport const SIDEBAR_CTX = createContext<SidebarContext>('SidebarContext');\n\n// ─── ore-sidebar styles ──────────────────────────────────────────────────────\n\n/** ore-sidebar element interface */\nexport type SidebarElement = HTMLElement &\n OreSidebarProps & {\n /** Close the drawer in bottom-nav mode. */\n closeMobile(): void;\n /** Open the drawer in bottom-nav mode. */\n openMobile(): void;\n /** Set collapsed state imperatively. */\n setCollapsed(next: boolean): void;\n /** Toggle between collapsed and expanded. */\n toggle(): void;\n /** Toggle the drawer in bottom-nav mode. */\n toggleMobile(): void;\n };\n\n/** Sidebar component properties */\n\nexport type OreSidebarEvents = {\n 'collapsed-change': { collapsed: boolean; source: SidebarCollapseSource };\n 'mobile-open-change': { open: boolean; source: SidebarMobileSource };\n};\n\nexport type OreSidebarGroupEvents = {\n 'open-change': { open: boolean };\n};\n\nexport type OreSidebarProps = {\n /** CSS media query that switches the sidebar to bottom navigation mode */\n 'bottom-nav-at'?: string;\n /** Controlled collapsed state */\n collapsed?: boolean;\n /** Whether the sidebar supports collapsing */\n collapsible?: boolean;\n /** Evaluate responsive and bottom-nav breakpoints against container width only. */\n 'container-breakpoints'?: boolean;\n /** Initial collapsed state in uncontrolled mode */\n 'default-collapsed'?: boolean;\n /**\n * Accessible label for the navigation landmark.\n * Use to distinguish multiple navigation regions on a page.\n * @default 'Sidebar navigation'\n */\n label?: string;\n /**\n * CSS media query that, when it matches, automatically collapses the sidebar.\n * Unset by default — no automatic collapse.\n * @example 'responsive=\"(max-width: 768px)\"'\n */\n responsive?: string;\n /** Visual style variant */\n variant?: SidebarVariant;\n};\n\n/**\n * `ore-sidebar` — A collapsible navigation sidebar with group and item support.\n *\n * @element ore-sidebar\n * @element ore-sidebar-group - Labelled group of navigation items\n * @element ore-sidebar-item - Individual navigation link or button\n *\n * @attr {boolean} collapsed - Controlled collapsed state\n * @attr {boolean} default-collapsed - Initial collapsed state for uncontrolled sidebars\n * @attr {boolean} collapsible - Show the collapse toggle button\n * @attr {string} variant - Visual variant: 'floating' | 'inset'\n * @attr {string} label - Accessible aria-label for the nav landmark\n *\n * @fires collapsed-change - Fired when collapsed state changes. detail: { collapsed: boolean; source: string }\n * @fires mobile-open-change - Fired when mobile overlay open state changes. detail: { open: boolean; source: string }\n *\n * @slot header - Branding or logo content above the nav\n * @slot - Navigation content (ore-sidebar-group / ore-sidebar-item)\n * @slot footer - Footer content below the nav (user info, settings, etc.)\n *\n * @cssprop --sidebar-width - Expanded sidebar width (default: 16rem)\n * @cssprop --sidebar-collapsed-width - Collapsed sidebar width (default: 3.5rem)\n * @cssprop --sidebar-bg - Sidebar background color\n * @cssprop --sidebar-border-color - Border color\n *\n * @part mobile-backdrop - Backdrop shown for mobile overlays.\n * @part nav - Navigation container.\n * @part header - Header container.\n * @part toggle-btn - Shadow part for the `toggle-btn` element.\n * @part content - Content container.\n * @part footer - Footer container.\n * @part bottom-bar - Bottom bar container.\n * @part group - Group container.\n * @part group-header - Group header container.\n * @part group-icon - Group icon container.\n * @part group-label - Group label container.\n * @part group-items - Group items container.\n * @part item-icon - Leading item icon container.\n * @part item-label - Item label container.\n * @part item-end - Trailing item content container.\n * @part item - Item root element.\n * @example\n * ```html\n * <ore-sidebar collapsible label=\"App navigation\">\n * <span slot=\"header\">My App</span>\n * <ore-sidebar-group label=\"Main\">\n * <ore-sidebar-item href=\"/dashboard\" active>Dashboard</ore-sidebar-item>\n * <ore-sidebar-item href=\"/settings\">Settings</ore-sidebar-item>\n * </ore-sidebar-group>\n * </ore-sidebar>\n *\n * <!-- Auto-collapse on mobile -->\n * <ore-sidebar collapsible responsive=\"(max-width: 768px)\">...</ore-sidebar>\n * ```\n */\nexport const SIDEBAR_TAG = 'ore-sidebar' as const;\ndefine<OreSidebarProps>(SIDEBAR_TAG, {\n props: {\n 'bottom-nav-at': prop.string(),\n collapsed: prop.bool(false),\n collapsible: prop.bool(false),\n 'container-breakpoints': prop.bool(false),\n 'default-collapsed': prop.bool(false),\n label: prop.string('Sidebar navigation'),\n responsive: prop.string(),\n variant: prop.string<SidebarVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSidebarEvents>();\n const slots = useSlots();\n\n const hasHeader = () => slots.has('header').value;\n const hasFooter = () => slots.has('footer').value;\n const hasLogo = () => slots.has('logo').value;\n\n const isControlled = signal(el.hasAttribute('collapsed'));\n const collapsedState = signal(isControlled.value ? el.hasAttribute('collapsed') : props['default-collapsed'].value);\n const isBottomNav = signal(false);\n const isMobileOpen = signal(false);\n const bottomNavItems = signal<BottomNavItem[]>([]);\n const responsiveMediaMatches = signal(false);\n const responsiveSizeMatches = signal(false);\n const responsiveMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props.responsive.value));\n const hasResponsiveQuery = signal(Boolean(String(props.responsive.value ?? '').trim()));\n const bottomNavMediaMatches = signal(false);\n const bottomNavSizeMatches = signal(false);\n const bottomNavMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props['bottom-nav-at'].value));\n const isPreviewMode = signal(false);\n\n const isCollapsed = () => collapsedState.value;\n const mode = computed<SidebarMode>(() => {\n if (isBottomNav.value) return 'bottom-nav';\n\n return collapsedState.value ? 'collapsed' : 'default';\n });\n\n const applyResponsiveState = () => {\n const useContainerBreakpoints = props['container-breakpoints'].value;\n const responsiveMatched = useContainerBreakpoints\n ? responsiveSizeMatches.value\n : responsiveMediaMatches.value || responsiveSizeMatches.value;\n const bottomMatched = useContainerBreakpoints\n ? bottomNavSizeMatches.value\n : bottomNavMediaMatches.value || bottomNavSizeMatches.value;\n\n // If the mobile drawer is currently open, stay in bottom-nav mode\n // regardless of the responsive match. This prevents the drawer from\n // disappearing mid-animation or if forced open via the API on desktop.\n if (!isMobileOpen.value) {\n isBottomNav.value = bottomMatched;\n }\n\n if (!bottomMatched && !isMobileOpen.value) {\n setMobileOpen(false, 'responsive');\n }\n\n if (hasResponsiveQuery.value) {\n setCollapsed(responsiveMatched, 'responsive');\n }\n };\n\n const readBottomNavItems = () => {\n const next = slots\n .elements()\n .value.filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n )\n .map((el, index) => {\n const iconSlotEl =\n (el.querySelector(':scope > [slot=\"icon\"]') as HTMLElement | null) ??\n (el.querySelector('[slot=\"icon\"]') as HTMLElement | null);\n const directIconName =\n iconSlotEl?.tagName.toLowerCase() === 'ore-icon' ? iconSlotEl.getAttribute('name') : null;\n const nestedIconName = iconSlotEl?.querySelector('ore-icon')?.getAttribute('name') ?? null;\n const rawLabel = (el.textContent ?? '').trim();\n\n return {\n active: el.hasAttribute('active'),\n disabled: el.hasAttribute('disabled'),\n href: el.getAttribute('href') ?? undefined,\n iconName: directIconName ?? nestedIconName ?? undefined,\n label: rawLabel || `Item ${index + 1}`,\n source: el,\n } satisfies BottomNavItem;\n });\n\n bottomNavItems.value = next;\n };\n\n provide(SIDEBAR_CTX, {\n collapsed: computed(() => !isBottomNav.value && collapsedState.value) as Readable<boolean>,\n mobileOpen: computed(() => isBottomNav.value && isMobileOpen.value) as Readable<boolean>,\n mode: mode as Readable<SidebarMode>,\n variant: props.variant,\n });\n\n const setCollapsed = (next: boolean, source: SidebarCollapseSource) => {\n if (isCollapsed() === next) return;\n\n if (!isControlled.value) {\n collapsedState.value = next;\n }\n\n emit('collapsed-change', { collapsed: next, source });\n };\n\n const setMobileOpen = (next: boolean, source: SidebarMobileSource) => {\n const open = Boolean(next);\n\n if (open && !isBottomNav.value) {\n isBottomNav.value = true;\n }\n\n if (!isBottomNav.value && !open) {\n if (isMobileOpen.value) {\n isMobileOpen.value = false;\n }\n\n return;\n }\n\n if (isMobileOpen.value === open) return;\n\n isMobileOpen.value = open;\n\n // If closing, re-evaluate responsive state to potentially exit forced bottom-nav mode\n if (!open) {\n applyResponsiveState();\n }\n\n emit('mobile-open-change', { open, source });\n };\n\n const doToggle = () => {\n setCollapsed(!isCollapsed(), 'toggle');\n };\n\n const sidebarEl = el as SidebarElement;\n\n sidebarEl.setCollapsed = (next) => setCollapsed(Boolean(next), 'api');\n sidebarEl.toggle = doToggle;\n sidebarEl.openMobile = () => setMobileOpen(true, 'api');\n sidebarEl.closeMobile = () => setMobileOpen(false, 'api');\n sidebarEl.toggleMobile = () => setMobileOpen(!isMobileOpen.value, 'toggle');\n\n bind({\n attr: {\n 'data-bottom-nav': () => (isBottomNav.value ? true : undefined),\n 'data-collapsed': () => (isCollapsed() && !isBottomNav.value ? true : undefined),\n 'data-mobile-open': () => (isBottomNav.value && isMobileOpen.value ? true : undefined),\n 'data-preview-mode': () => (isPreviewMode.value ? true : undefined),\n },\n });\n\n onMounted(() => {\n // Suppress transitions during initial layout so the sidebar doesn't\n // animate from a collapsed/0 state before the first ResizeObserver fires.\n el.setAttribute('data-no-transition', '');\n\n let transitionUnlocked = false;\n const unlockTransition = () => {\n if (transitionUnlocked) return;\n\n transitionUnlocked = true;\n el.removeAttribute('data-no-transition');\n };\n\n // Fallback: unlock after two frames in case ResizeObserver doesn't fire.\n requestAnimationFrame(() => requestAnimationFrame(unlockTransition));\n\n let mediaCleanup: (() => void) | undefined;\n let bottomNavCleanup: (() => void) | undefined;\n const itemObservers = new Map<HTMLElement, MutationObserver>();\n const observer = new MutationObserver(() => {\n if (!el.hasAttribute('collapsed') && !isControlled.value) return;\n\n isControlled.value = true;\n collapsedState.value = el.hasAttribute('collapsed');\n });\n\n observer.observe(el, {\n attributeFilter: ['collapsed'],\n attributes: true,\n });\n\n watch(\n props.responsive,\n (query) => {\n mediaCleanup?.();\n mediaCleanup = undefined;\n\n const mediaQuery = String(query ?? '').trim();\n\n hasResponsiveQuery.value = Boolean(mediaQuery);\n responsiveMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n responsiveMediaMatches.value = false;\n\n const width = readContainerWidth(el);\n\n responsiveSizeMatches.value =\n width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n applyResponsiveState();\n\n // For parseable max-width queries, keep behavior container-driven.\n // This avoids preview viewport controls being overridden by window width.\n if (props['container-breakpoints'].value && responsiveMaxWidthPx.value != null) {\n return;\n }\n\n if (!mediaQuery) {\n return;\n }\n\n if (typeof window.matchMedia !== 'function') {\n return;\n }\n\n const mql = window.matchMedia(mediaQuery);\n const onChange = (event: MediaQueryListEvent) => {\n responsiveMediaMatches.value = event.matches;\n applyResponsiveState();\n };\n\n responsiveMediaMatches.value = mql.matches;\n applyResponsiveState();\n mql.addEventListener('change', onChange);\n\n mediaCleanup = () => {\n mql.removeEventListener('change', onChange);\n };\n },\n { immediate: true },\n );\n\n watch(\n props['bottom-nav-at'],\n (query) => {\n bottomNavCleanup?.();\n bottomNavCleanup = undefined;\n\n const mediaQuery = String(query ?? '').trim();\n\n bottomNavMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n bottomNavMediaMatches.value = false;\n\n const width = readContainerWidth(el);\n\n bottomNavSizeMatches.value =\n width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n applyResponsiveState();\n\n // For parseable max-width queries, keep behavior container-driven.\n // This avoids preview viewport controls being overridden by window width.\n if (props['container-breakpoints'].value && bottomNavMaxWidthPx.value != null) {\n return;\n }\n\n if (!mediaQuery) {\n return;\n }\n\n if (typeof window.matchMedia !== 'function') {\n return;\n }\n\n const mql = window.matchMedia(mediaQuery);\n const onChange = (event: MediaQueryListEvent) => {\n bottomNavMediaMatches.value = event.matches;\n applyResponsiveState();\n };\n\n bottomNavMediaMatches.value = mql.matches;\n applyResponsiveState();\n\n mql.addEventListener('change', onChange);\n bottomNavCleanup = () => {\n mql.removeEventListener('change', onChange);\n };\n },\n { immediate: true },\n );\n\n const stopResizeEffect =\n typeof ResizeObserver === 'function'\n ? (() => {\n const hostSize = resizeObserver(el);\n const wrapperEl = el.parentElement;\n const containerEl = resolveContainerElement(el);\n const wrapperSize = wrapperEl ? resizeObserver(wrapperEl) : undefined;\n const parentSize = containerEl && containerEl !== wrapperEl ? resizeObserver(containerEl) : undefined;\n let rafId: number | undefined;\n\n const onResize = () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n\n rafId = requestAnimationFrame(() => {\n const resolvedContainer = resolveContainerElement(el);\n const width = readContainerWidth(el);\n const responsiveWasMatched = responsiveSizeMatches.value;\n const bottomNavWasMatched = bottomNavSizeMatches.value;\n const parentWidth = resolvedContainer?.clientWidth ?? 0;\n\n isPreviewMode.value = parentWidth > 0 && parentWidth < window.innerWidth;\n\n responsiveSizeMatches.value =\n width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n bottomNavSizeMatches.value =\n width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n\n if (\n responsiveWasMatched !== responsiveSizeMatches.value ||\n bottomNavWasMatched !== bottomNavSizeMatches.value\n ) {\n applyResponsiveState();\n }\n\n unlockTransition();\n });\n };\n\n return watch(\n computed(() => [\n hostSize.value.width,\n hostSize.value.height,\n wrapperSize?.value.width,\n wrapperSize?.value.height,\n parentSize?.value.width,\n parentSize?.value.height,\n ]),\n onResize,\n );\n })()\n : undefined;\n\n const bindItemObservers = (items: HTMLElement[]) => {\n const set = new Set(items);\n\n for (const [item, cleanup] of itemObservers) {\n if (set.has(item)) continue;\n\n cleanup.disconnect();\n itemObservers.delete(item);\n }\n\n for (const item of items) {\n if (itemObservers.has(item)) continue;\n\n const itemObserver = new MutationObserver(() => {\n // Only update if in bottom-nav mode to minimize re-renders\n if (isBottomNav.value) {\n readBottomNavItems();\n }\n });\n\n // Only watch attributes that affect bottom-nav rendering; skip childList/subtree/characterData\n itemObserver.observe(item, {\n attributeFilter: ['active', 'disabled', 'href'],\n attributes: true,\n });\n itemObservers.set(item, itemObserver);\n }\n };\n\n watch(\n slots.elements(),\n (elements) => {\n const directItems = elements.filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n );\n\n bindItemObservers(directItems);\n readBottomNavItems();\n },\n { immediate: true },\n );\n\n return () => {\n observer.disconnect();\n mediaCleanup?.();\n bottomNavCleanup?.();\n stopResizeEffect?.dispose();\n\n for (const itemObserver of itemObservers.values()) {\n itemObserver.disconnect();\n }\n\n itemObservers.clear();\n };\n });\n\n return html`\n <button\n class=\"mobile-backdrop\"\n part=\"mobile-backdrop\"\n type=\"button\"\n aria-label=\"Close sidebar\"\n ?hidden=${() => !isBottomNav.value || !isMobileOpen.value}\n @click=${() => setMobileOpen(false, 'toggle')}></button>\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <div class=\"sidebar-header\" part=\"header\" ?hidden=${() => !hasHeader() && !props.collapsible.value}>\n <span class=\"sidebar-logo\" ?hidden=${() => !hasLogo()}>\n <slot name=\"logo\"></slot>\n </span>\n <span class=\"sidebar-header-content\">\n <slot name=\"header\"></slot>\n </span>\n <button\n class=\"toggle-btn\"\n part=\"toggle-btn\"\n type=\"button\"\n ?hidden=${() => !props.collapsible.value}\n aria-label=\"${() => (isCollapsed() ? 'Expand sidebar' : 'Collapse sidebar')}\"\n aria-expanded=\"${() => !isCollapsed()}\"\n @click=\"${doToggle}\">\n <span class=\"toggle-icon\" aria-hidden=\"true\">\n <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </button>\n </div>\n <div class=\"sidebar-content\" part=\"content\">\n <slot></slot>\n </div>\n <div class=\"sidebar-footer\" part=\"footer\" ?hidden=${() => !hasFooter()}>\n <slot name=\"footer\"></slot>\n </div>\n </nav>\n\n <div class=\"bottom-bar\" part=\"bottom-bar\" ?hidden=${() => !isBottomNav.value}>\n ${() =>\n bottomNavItems.value.map((item) => {\n const className = `bottom-tab${item.active ? ' bottom-tab-active' : ''}`;\n\n if (item.href && !item.disabled) {\n return html`\n <a\n class=\"${className}\"\n href=\"${item.href}\"\n aria-current=\"${item.active ? 'page' : null}\"\n data-active=\"${item.active ? 'true' : null}\">\n <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n <ore-icon :name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n </span>\n <span class=\"bottom-tab-label\">${item.label}</span>\n </a>\n `;\n }\n\n return html`\n <button\n class=\"${className}\"\n type=\"button\"\n ?disabled=${item.disabled}\n aria-current=\"${item.active ? 'page' : null}\"\n data-active=\"${item.active ? 'true' : null}\"\n @click=${() => item.source.click()}>\n <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n <ore-icon :name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n </span>\n <span class=\"bottom-tab-label\">${item.label}</span>\n </button>\n `;\n })}\n </div>\n `;\n },\n styles: [coarsePointerMixin, reducedMotionMixin, sidebarStyles],\n});\n\n// ─── ore-sidebar-group styles ────────────────────────────────────────────────\n\n/** Sidebar group properties */\nexport type OreSidebarGroupProps = {\n /** Whether this group can be collapsed */\n collapsible?: boolean;\n /** Initial open state in uncontrolled mode */\n 'default-open'?: boolean;\n /** Accessible label for the group */\n label?: string;\n /** Controlled open state */\n open?: boolean;\n};\n\n/**\n * `ore-sidebar-group` — A labelled section within `ore-sidebar`.\n *\n * @element ore-sidebar-group\n *\n * @attr {string} label - Group label text\n * @attr {boolean} collapsible - Whether this group can be toggled open/closed\n * @attr {boolean} open - Controlled expanded state\n * @attr {boolean} default-open - Initial expanded state in uncontrolled mode\n *\n * @fires open-change - Fired when the group open state changes (collapsible groups only). detail: { open: boolean }\n *\n * @slot - Navigation items (`ore-sidebar-item`)\n * @slot icon - Icon displayed before the label\n *\n * @example\n * ```html\n * <ore-sidebar-group label=\"Main\" collapsible open>\n * <ore-sidebar-item href=\"/home\">Home</ore-sidebar-item>\n * </ore-sidebar-group>\n * ```\n */\nexport const SIDEBAR_GROUP_TAG = 'ore-sidebar-group' as const;\ndefine<OreSidebarGroupProps>(SIDEBAR_GROUP_TAG, {\n props: {\n collapsible: prop.bool(false),\n 'default-open': prop.bool(true),\n label: prop.string(),\n open: {\n default: undefined as boolean | undefined,\n parse: (value: string | null) => (value == null ? undefined : value === '' || value === 'true'),\n reflect: false,\n },\n },\n setup(props) {\n const slots = useSlots();\n\n const hasIcon = () => slots.has('icon').value;\n const sidebarCtx = inject(SIDEBAR_CTX);\n\n bind({\n attr: {\n 'sidebar-bottom-nav': () =>\n sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n 'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n },\n });\n\n const isControlled = () => props.open.value !== undefined;\n const openState = signal(props['default-open'].value);\n const isOpen = computed(() => {\n if (!props.collapsible.value) return true;\n\n if (isControlled()) return props.open.value ?? false;\n\n return openState.value;\n });\n\n watch(props.open, (value) => {\n if (value === undefined) return;\n\n openState.value = value;\n });\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n },\n });\n\n return html`\n <details class=\"group\" part=\"group\" ?open=${isOpen}>\n <summary\n class=\"group-header\"\n part=\"group-header\"\n aria-expanded=\"${() => (props.collapsible.value ? String(props.open.value) : null)}\"\n @click=${(e: MouseEvent) => {\n if (!props.collapsible.value) {\n e.preventDefault();\n }\n }}>\n <span class=\"group-icon\" part=\"group-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"group-label\" part=\"group-label\">${props.label}</span>\n <span class=\"chevron\" ?hidden=${() => !props.collapsible.value} aria-hidden=\"true\">\n <ore-icon name=\"chevron-right\" size=\"12\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </summary>\n <div class=\"group-items\" part=\"group-items\" role=\"list\">\n <slot></slot>\n </div>\n </details>\n `;\n },\n styles: [reducedMotionMixin, groupStyles],\n});\n\n// ─── ore-sidebar-item styles ─────────────────────────────────────────────────\n\n/** Sidebar item properties */\nexport type OreSidebarItemProps = {\n /** Whether this item represents the current page/section */\n active?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Navigation href — renders an `<a>` when set, otherwise a `<button>` */\n href?: string;\n /**\n * Relationship of the linked URL (`rel` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n rel?: string;\n /**\n * Browsing context for the link (`target` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n target?: string;\n};\n\n/**\n * `ore-sidebar-item` — An individual navigation item in a `ore-sidebar`.\n *\n * Renders as an `<a>` when `href` is provided, otherwise as a `<button>`.\n * Marks the active page via `aria-current=\"page\"` when the `active` attribute is set.\n *\n * @element ore-sidebar-item\n *\n * @attr {string} href - Link URL; renders an anchor when set\n * @attr {boolean} active - Marks the item as the current page\n * @attr {boolean} disabled - Disables the item\n * @attr {string} rel - Anchor `rel` attribute (links only)\n * @attr {string} target - Anchor `target` attribute (links only)\n *\n * @slot - Label text\n * @slot icon - Leading icon\n * @slot end - Trailing content (badge, shortcut, arrow, etc.)\n *\n * @cssprop --sidebar-item-color - Default text color\n * @cssprop --sidebar-item-hover-bg - Hover background\n * @cssprop --sidebar-item-hover-color - Hover text color\n * @cssprop --sidebar-item-active-bg - Active background\n * @cssprop --sidebar-item-active-color - Active text color\n * @cssprop --sidebar-item-indicator - Active indicator bar color\n *\n * @part item - The inner anchor or button element\n * @part item-icon - The icon wrapper\n * @part item-label - The label wrapper\n * @part item-end - The trailing content wrapper\n *\n * @example\n * ```html\n * <ore-sidebar-item href=\"/dashboard\" active>\n * <span slot=\"icon\">🏠</span>\n * Dashboard\n * </ore-sidebar-item>\n *\n * <ore-sidebar-item href=\"/users\">\n * <span slot=\"icon\">👤</span>\n * Users\n * <ore-badge slot=\"end\" color=\"primary\">3</ore-badge>\n * </ore-sidebar-item>\n * ```\n */\nexport const SIDEBAR_ITEM_TAG = 'ore-sidebar-item' as const;\ndefine<OreSidebarItemProps>(SIDEBAR_ITEM_TAG, {\n props: {\n active: prop.bool(false),\n disabled: prop.bool(false),\n href: prop.string(),\n rel: prop.string(),\n target: prop.string(),\n },\n setup(props) {\n const slots = useSlots();\n\n const hasIcon = () => slots.has('icon').value;\n const hasEnd = () => slots.has('end').value;\n const sidebarCtx = inject(SIDEBAR_CTX);\n\n bind({\n attr: {\n 'sidebar-bottom-nav': () =>\n sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n 'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n },\n });\n\n const isLink = () => !!props.href.value && !props.disabled.value;\n\n // Prevent reverse tabnapping: auto-inject noopener + noreferrer for _blank links.\n const effectiveRel = computed(() => computeSafeRel(props.rel.value, props.target.value));\n\n const renderItemContent = () => html`\n <span class=\"item-icon\" part=\"item-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"item-label\" part=\"item-label\"><slot></slot></span>\n <span class=\"item-end\" part=\"item-end\" ?hidden=${() => !hasEnd()}>\n <slot name=\"end\"></slot>\n </span>\n `;\n\n return html`\n ${() => {\n if (isLink()) {\n return html`\n <a\n class=\"item\"\n part=\"item\"\n href=\"${props.href}\"\n :rel=\"${effectiveRel}\"\n :target=\"${props.target}\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </a>\n `;\n }\n\n if (props.disabled.value) {\n return html`\n <div\n class=\"item\"\n part=\"item\"\n aria-disabled=\"true\"\n tabindex=\"-1\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </div>\n `;\n }\n\n return html`\n <button\n class=\"item\"\n part=\"item\"\n type=\"button\"\n ?disabled=\"${props.disabled}\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </button>\n `;\n }}\n `;\n },\n styles: [coarsePointerMixin, itemStyles],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"sidebar.js","names":[],"sources":["../src/layout/sidebar/sidebar.ts"],"sourcesContent":["import {\n createContext,\n define,\n html,\n inject,\n prop,\n bind,\n getHost,\n onMounted,\n provide,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { resizeObserver } from '@vielzeug/ore/observers';\nimport { computed, type Readable, signal, watch } from '@vielzeug/ripple';\n\nimport '../../content/icon/icon';\nimport { coarsePointerMixin, reducedMotionMixin } from '../../styles';\nimport { computeSafeRel } from '../../utils';\nimport groupStyles from './sidebar-group.css?inline';\nimport itemStyles from './sidebar-item.css?inline';\nimport sidebarStyles from './sidebar.css?inline';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\ntype SidebarVariant = 'floating' | 'inset';\ntype SidebarCollapseSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMobileSource = 'api' | 'responsive' | 'toggle';\ntype SidebarMode = 'bottom-nav' | 'collapsed' | 'default';\n\ntype BottomNavItem = {\n active: boolean;\n disabled: boolean;\n href?: string;\n iconName?: string;\n label: string;\n source: HTMLElement;\n};\n\nconst parseMaxWidthPx = (query: string | undefined): number | undefined => {\n const value = String(query ?? '').trim();\n\n if (!value) return undefined;\n\n const match = /max-width\\s*:\\s*([0-9]+(?:\\.[0-9]+)?)px/i.exec(value);\n\n if (!match) return undefined;\n\n const parsed = Number.parseFloat(match[1]);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nconst resolveContainerElement = (el: HTMLElement): HTMLElement | null => {\n let container = el.parentElement;\n\n while (container?.tagName.toLowerCase() === 'ore-grid-item') {\n container = container.parentElement;\n }\n\n return container;\n};\n\nconst readContainerWidth = (el: HTMLElement): number => {\n const parentWidth = resolveContainerElement(el)?.clientWidth ?? 0;\n\n if (parentWidth > 0) return parentWidth;\n\n return el.offsetWidth;\n};\n\n/** Context provided by `ore-sidebar` to its `ore-sidebar-group` and `ore-sidebar-item` children. */\nexport type SidebarContext = {\n collapsed: Readable<boolean>;\n mobileOpen: Readable<boolean>;\n mode: Readable<SidebarMode>;\n variant: Readable<SidebarVariant | undefined>;\n};\n\n/** Injection key for the sidebar context. */\nexport const SIDEBAR_CTX = createContext<SidebarContext>('SidebarContext');\n\n// ─── ore-sidebar styles ──────────────────────────────────────────────────────\n\n/** ore-sidebar element interface */\nexport type SidebarElement = HTMLElement &\n OreSidebarProps & {\n /** Close the drawer in bottom-nav mode. */\n closeMobile(): void;\n /** Open the drawer in bottom-nav mode. */\n openMobile(): void;\n /** Set collapsed state imperatively. */\n setCollapsed(next: boolean): void;\n /** Toggle between collapsed and expanded. */\n toggle(): void;\n /** Toggle the drawer in bottom-nav mode. */\n toggleMobile(): void;\n };\n\n/** Sidebar component properties */\n\nexport type OreSidebarEvents = {\n 'collapsed-change': { collapsed: boolean; source: SidebarCollapseSource };\n 'mobile-open-change': { open: boolean; source: SidebarMobileSource };\n};\n\nexport type OreSidebarGroupEvents = {\n 'open-change': { open: boolean };\n};\n\nexport type OreSidebarProps = {\n /** CSS media query that switches the sidebar to bottom navigation mode */\n 'bottom-nav-at'?: string;\n /** Controlled collapsed state */\n collapsed?: boolean;\n /** Whether the sidebar supports collapsing */\n collapsible?: boolean;\n /** Evaluate responsive and bottom-nav breakpoints against container width only. */\n 'container-breakpoints'?: boolean;\n /** Initial collapsed state in uncontrolled mode */\n 'default-collapsed'?: boolean;\n /**\n * Accessible label for the navigation landmark.\n * Use to distinguish multiple navigation regions on a page.\n * @default 'Sidebar navigation'\n */\n label?: string;\n /**\n * CSS media query that, when it matches, automatically collapses the sidebar.\n * Unset by default — no automatic collapse.\n * @example 'responsive=\"(max-width: 768px)\"'\n */\n responsive?: string;\n /** Visual style variant */\n variant?: SidebarVariant;\n};\n\n/**\n * `ore-sidebar` — A collapsible navigation sidebar with group and item support.\n *\n * @element ore-sidebar\n * @element ore-sidebar-group - Labelled group of navigation items\n * @element ore-sidebar-item - Individual navigation link or button\n *\n * @attr {boolean} collapsed - Controlled collapsed state\n * @attr {boolean} default-collapsed - Initial collapsed state for uncontrolled sidebars\n * @attr {boolean} collapsible - Show the collapse toggle button\n * @attr {string} variant - Visual variant: 'floating' | 'inset'\n * @attr {string} label - Accessible aria-label for the nav landmark\n *\n * @fires collapsed-change - Fired when collapsed state changes. detail: { collapsed: boolean; source: string }\n * @fires mobile-open-change - Fired when mobile overlay open state changes. detail: { open: boolean; source: string }\n *\n * @slot header - Branding or logo content above the nav\n * @slot - Navigation content (ore-sidebar-group / ore-sidebar-item)\n * @slot footer - Footer content below the nav (user info, settings, etc.)\n *\n * @cssprop --sidebar-width - Expanded sidebar width (default: 16rem)\n * @cssprop --sidebar-collapsed-width - Collapsed sidebar width (default: 3.5rem)\n * @cssprop --sidebar-bg - Sidebar background color\n * @cssprop --sidebar-border-color - Border color\n *\n * @part mobile-backdrop - Backdrop shown for mobile overlays.\n * @part nav - Navigation container.\n * @part header - Header container.\n * @part toggle-btn - Shadow part for the `toggle-btn` element.\n * @part content - Content container.\n * @part footer - Footer container.\n * @part bottom-bar - Bottom bar container.\n * @part group - Group container.\n * @part group-header - Group header container.\n * @part group-icon - Group icon container.\n * @part group-label - Group label container.\n * @part group-items - Group items container.\n * @part item-icon - Leading item icon container.\n * @part item-label - Item label container.\n * @part item-end - Trailing item content container.\n * @part item - Item root element.\n * @example\n * ```html\n * <ore-sidebar collapsible label=\"App navigation\">\n * <span slot=\"header\">My App</span>\n * <ore-sidebar-group label=\"Main\">\n * <ore-sidebar-item href=\"/dashboard\" active>Dashboard</ore-sidebar-item>\n * <ore-sidebar-item href=\"/settings\">Settings</ore-sidebar-item>\n * </ore-sidebar-group>\n * </ore-sidebar>\n *\n * <!-- Auto-collapse on mobile -->\n * <ore-sidebar collapsible responsive=\"(max-width: 768px)\">...</ore-sidebar>\n * ```\n */\nexport const SIDEBAR_TAG = 'ore-sidebar' as const;\ndefine<OreSidebarProps>(SIDEBAR_TAG, {\n props: {\n 'bottom-nav-at': prop.string(),\n collapsed: prop.bool(false),\n collapsible: prop.bool(false),\n 'container-breakpoints': prop.bool(false),\n 'default-collapsed': prop.bool(false),\n label: prop.string('Sidebar navigation'),\n responsive: prop.string(),\n variant: prop.string<SidebarVariant>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreSidebarEvents>();\n const slots = useSlots();\n\n const hasHeader = () => slots.has('header').value;\n const hasFooter = () => slots.has('footer').value;\n const hasLogo = () => slots.has('logo').value;\n\n const isControlled = signal(el.hasAttribute('collapsed'));\n const collapsedState = signal(isControlled.value ? el.hasAttribute('collapsed') : props['default-collapsed'].value);\n const isBottomNav = signal(false);\n const isMobileOpen = signal(false);\n const bottomNavItems = signal<BottomNavItem[]>([]);\n const responsiveMediaMatches = signal(false);\n const responsiveSizeMatches = signal(false);\n const responsiveMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props.responsive.value));\n const hasResponsiveQuery = signal(Boolean(String(props.responsive.value ?? '').trim()));\n const bottomNavMediaMatches = signal(false);\n const bottomNavSizeMatches = signal(false);\n const bottomNavMaxWidthPx = signal<number | undefined>(parseMaxWidthPx(props['bottom-nav-at'].value));\n const isPreviewMode = signal(false);\n\n const isCollapsed = () => collapsedState.value;\n const mode = computed<SidebarMode>(() => {\n if (isBottomNav.value) return 'bottom-nav';\n\n return collapsedState.value ? 'collapsed' : 'default';\n });\n\n const applyResponsiveState = () => {\n const useContainerBreakpoints = props['container-breakpoints'].value;\n const responsiveMatched = useContainerBreakpoints\n ? responsiveSizeMatches.value\n : responsiveMediaMatches.value || responsiveSizeMatches.value;\n const bottomMatched = useContainerBreakpoints\n ? bottomNavSizeMatches.value\n : bottomNavMediaMatches.value || bottomNavSizeMatches.value;\n\n // If the mobile drawer is currently open, stay in bottom-nav mode\n // regardless of the responsive match. This prevents the drawer from\n // disappearing mid-animation or if forced open via the API on desktop.\n if (!isMobileOpen.value) {\n isBottomNav.value = bottomMatched;\n }\n\n if (!bottomMatched && !isMobileOpen.value) {\n setMobileOpen(false, 'responsive');\n }\n\n if (hasResponsiveQuery.value) {\n setCollapsed(responsiveMatched, 'responsive');\n }\n };\n\n const readBottomNavItems = () => {\n const next = slots\n .elements()\n .value.filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n )\n .map((el, index) => {\n const iconSlotEl =\n (el.querySelector(':scope > [slot=\"icon\"]') as HTMLElement | null) ??\n (el.querySelector('[slot=\"icon\"]') as HTMLElement | null);\n const directIconName =\n iconSlotEl?.tagName.toLowerCase() === 'ore-icon' ? iconSlotEl.getAttribute('name') : null;\n const nestedIconName = iconSlotEl?.querySelector('ore-icon')?.getAttribute('name') ?? null;\n const rawLabel = (el.textContent ?? '').trim();\n\n return {\n active: el.hasAttribute('active'),\n disabled: el.hasAttribute('disabled'),\n href: el.getAttribute('href') ?? undefined,\n iconName: directIconName ?? nestedIconName ?? undefined,\n label: rawLabel || `Item ${index + 1}`,\n source: el,\n } satisfies BottomNavItem;\n });\n\n bottomNavItems.value = next;\n };\n\n provide(SIDEBAR_CTX, {\n collapsed: computed(() => !isBottomNav.value && collapsedState.value) as Readable<boolean>,\n mobileOpen: computed(() => isBottomNav.value && isMobileOpen.value) as Readable<boolean>,\n mode: mode as Readable<SidebarMode>,\n variant: props.variant,\n });\n\n const setCollapsed = (next: boolean, source: SidebarCollapseSource) => {\n if (isCollapsed() === next) return;\n\n if (!isControlled.value) {\n collapsedState.value = next;\n }\n\n emit('collapsed-change', { collapsed: next, source });\n };\n\n const setMobileOpen = (next: boolean, source: SidebarMobileSource) => {\n const open = Boolean(next);\n\n if (open && !isBottomNav.value) {\n isBottomNav.value = true;\n }\n\n if (!isBottomNav.value && !open) {\n if (isMobileOpen.value) {\n isMobileOpen.value = false;\n }\n\n return;\n }\n\n if (isMobileOpen.value === open) return;\n\n isMobileOpen.value = open;\n\n // If closing, re-evaluate responsive state to potentially exit forced bottom-nav mode\n if (!open) {\n applyResponsiveState();\n }\n\n emit('mobile-open-change', { open, source });\n };\n\n const doToggle = () => {\n setCollapsed(!isCollapsed(), 'toggle');\n };\n\n const sidebarEl = el as SidebarElement;\n\n sidebarEl.setCollapsed = (next) => setCollapsed(Boolean(next), 'api');\n sidebarEl.toggle = doToggle;\n sidebarEl.openMobile = () => setMobileOpen(true, 'api');\n sidebarEl.closeMobile = () => setMobileOpen(false, 'api');\n sidebarEl.toggleMobile = () => setMobileOpen(!isMobileOpen.value, 'toggle');\n\n bind({\n attr: {\n 'data-bottom-nav': () => (isBottomNav.value ? true : undefined),\n 'data-collapsed': () => (isCollapsed() && !isBottomNav.value ? true : undefined),\n 'data-mobile-open': () => (isBottomNav.value && isMobileOpen.value ? true : undefined),\n 'data-preview-mode': () => (isPreviewMode.value ? true : undefined),\n },\n });\n\n onMounted(() => {\n // Suppress transitions during initial layout so the sidebar doesn't\n // animate from a collapsed/0 state before the first ResizeObserver fires.\n el.setAttribute('data-no-transition', '');\n\n let transitionUnlocked = false;\n const unlockTransition = () => {\n if (transitionUnlocked) return;\n\n transitionUnlocked = true;\n el.removeAttribute('data-no-transition');\n };\n\n // Fallback: unlock after two frames in case ResizeObserver doesn't fire.\n requestAnimationFrame(() => requestAnimationFrame(unlockTransition));\n\n let mediaCleanup: (() => void) | undefined;\n let bottomNavCleanup: (() => void) | undefined;\n const itemObservers = new Map<HTMLElement, MutationObserver>();\n const observer = new MutationObserver(() => {\n if (!el.hasAttribute('collapsed') && !isControlled.value) return;\n\n isControlled.value = true;\n collapsedState.value = el.hasAttribute('collapsed');\n });\n\n observer.observe(el, {\n attributeFilter: ['collapsed'],\n attributes: true,\n });\n\n watch(\n props.responsive,\n (query) => {\n mediaCleanup?.();\n mediaCleanup = undefined;\n\n const mediaQuery = String(query ?? '').trim();\n\n hasResponsiveQuery.value = Boolean(mediaQuery);\n responsiveMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n responsiveMediaMatches.value = false;\n\n const width = readContainerWidth(el);\n\n responsiveSizeMatches.value =\n width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n applyResponsiveState();\n\n // For parseable max-width queries, keep behavior container-driven.\n // This avoids preview viewport controls being overridden by window width.\n if (props['container-breakpoints'].value && responsiveMaxWidthPx.value != null) {\n return;\n }\n\n if (!mediaQuery) {\n return;\n }\n\n if (typeof window.matchMedia !== 'function') {\n return;\n }\n\n const mql = window.matchMedia(mediaQuery);\n const onChange = (event: MediaQueryListEvent) => {\n responsiveMediaMatches.value = event.matches;\n applyResponsiveState();\n };\n\n responsiveMediaMatches.value = mql.matches;\n applyResponsiveState();\n mql.addEventListener('change', onChange);\n\n mediaCleanup = () => {\n mql.removeEventListener('change', onChange);\n };\n },\n { immediate: true },\n );\n\n watch(\n props['bottom-nav-at'],\n (query) => {\n bottomNavCleanup?.();\n bottomNavCleanup = undefined;\n\n const mediaQuery = String(query ?? '').trim();\n\n bottomNavMaxWidthPx.value = parseMaxWidthPx(mediaQuery);\n bottomNavMediaMatches.value = false;\n\n const width = readContainerWidth(el);\n\n bottomNavSizeMatches.value =\n width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n applyResponsiveState();\n\n // For parseable max-width queries, keep behavior container-driven.\n // This avoids preview viewport controls being overridden by window width.\n if (props['container-breakpoints'].value && bottomNavMaxWidthPx.value != null) {\n return;\n }\n\n if (!mediaQuery) {\n return;\n }\n\n if (typeof window.matchMedia !== 'function') {\n return;\n }\n\n const mql = window.matchMedia(mediaQuery);\n const onChange = (event: MediaQueryListEvent) => {\n bottomNavMediaMatches.value = event.matches;\n applyResponsiveState();\n };\n\n bottomNavMediaMatches.value = mql.matches;\n applyResponsiveState();\n\n mql.addEventListener('change', onChange);\n bottomNavCleanup = () => {\n mql.removeEventListener('change', onChange);\n };\n },\n { immediate: true },\n );\n\n const stopResizeEffect =\n typeof ResizeObserver === 'function'\n ? (() => {\n const hostSize = resizeObserver(el);\n const wrapperEl = el.parentElement;\n const containerEl = resolveContainerElement(el);\n const wrapperSize = wrapperEl ? resizeObserver(wrapperEl) : undefined;\n const parentSize = containerEl && containerEl !== wrapperEl ? resizeObserver(containerEl) : undefined;\n let rafId: number | undefined;\n\n const onResize = () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n\n rafId = requestAnimationFrame(() => {\n const resolvedContainer = resolveContainerElement(el);\n const width = readContainerWidth(el);\n const responsiveWasMatched = responsiveSizeMatches.value;\n const bottomNavWasMatched = bottomNavSizeMatches.value;\n const parentWidth = resolvedContainer?.clientWidth ?? 0;\n\n isPreviewMode.value = parentWidth > 0 && parentWidth < window.innerWidth;\n\n responsiveSizeMatches.value =\n width > 0 && responsiveMaxWidthPx.value != null ? width <= responsiveMaxWidthPx.value : false;\n bottomNavSizeMatches.value =\n width > 0 && bottomNavMaxWidthPx.value != null ? width <= bottomNavMaxWidthPx.value : false;\n\n if (\n responsiveWasMatched !== responsiveSizeMatches.value ||\n bottomNavWasMatched !== bottomNavSizeMatches.value\n ) {\n applyResponsiveState();\n }\n\n unlockTransition();\n });\n };\n\n return watch(\n computed(() => [\n hostSize.value.width,\n hostSize.value.height,\n wrapperSize?.value.width,\n wrapperSize?.value.height,\n parentSize?.value.width,\n parentSize?.value.height,\n ]),\n onResize,\n );\n })()\n : undefined;\n\n const bindItemObservers = (items: HTMLElement[]) => {\n const set = new Set(items);\n\n for (const [item, cleanup] of itemObservers) {\n if (set.has(item)) continue;\n\n cleanup.disconnect();\n itemObservers.delete(item);\n }\n\n for (const item of items) {\n if (itemObservers.has(item)) continue;\n\n const itemObserver = new MutationObserver(() => {\n // Only update if in bottom-nav mode to minimize re-renders\n if (isBottomNav.value) {\n readBottomNavItems();\n }\n });\n\n // Only watch attributes that affect bottom-nav rendering; skip childList/subtree/characterData\n itemObserver.observe(item, {\n attributeFilter: ['active', 'disabled', 'href'],\n attributes: true,\n });\n itemObservers.set(item, itemObserver);\n }\n };\n\n watch(\n slots.elements(),\n (elements) => {\n const directItems = elements.filter(\n (el): el is HTMLElement => el instanceof HTMLElement && el.tagName.toLowerCase() === 'ore-sidebar-item',\n );\n\n bindItemObservers(directItems);\n readBottomNavItems();\n },\n { immediate: true },\n );\n\n return () => {\n observer.disconnect();\n mediaCleanup?.();\n bottomNavCleanup?.();\n stopResizeEffect?.dispose();\n\n for (const itemObserver of itemObservers.values()) {\n itemObserver.disconnect();\n }\n\n itemObservers.clear();\n };\n });\n\n return html`\n <button\n class=\"mobile-backdrop\"\n part=\"mobile-backdrop\"\n type=\"button\"\n aria-label=\"Close sidebar\"\n ?hidden=${() => !isBottomNav.value || !isMobileOpen.value}\n @click=${() => setMobileOpen(false, 'toggle')}></button>\n <nav aria-label=\"${props.label}\" part=\"nav\">\n <div class=\"sidebar-header\" part=\"header\" ?hidden=${() => !hasHeader() && !props.collapsible.value}>\n <span class=\"sidebar-logo\" ?hidden=${() => !hasLogo()}>\n <slot name=\"logo\"></slot>\n </span>\n <span class=\"sidebar-header-content\">\n <slot name=\"header\"></slot>\n </span>\n <button\n class=\"toggle-btn\"\n part=\"toggle-btn\"\n type=\"button\"\n ?hidden=${() => !props.collapsible.value}\n aria-label=\"${() => (isCollapsed() ? 'Expand sidebar' : 'Collapse sidebar')}\"\n aria-expanded=\"${() => !isCollapsed()}\"\n @click=\"${doToggle}\">\n <span class=\"toggle-icon\" aria-hidden=\"true\">\n <ore-icon name=\"chevron-left\" size=\"16\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </button>\n </div>\n <div class=\"sidebar-content\" part=\"content\">\n <slot></slot>\n </div>\n <div class=\"sidebar-footer\" part=\"footer\" ?hidden=${() => !hasFooter()}>\n <slot name=\"footer\"></slot>\n </div>\n </nav>\n\n <div class=\"bottom-bar\" part=\"bottom-bar\" ?hidden=${() => !isBottomNav.value}>\n ${() =>\n bottomNavItems.value.map((item) => {\n const className = `bottom-tab${item.active ? ' bottom-tab-active' : ''}`;\n\n if (item.href && !item.disabled) {\n return html`\n <a\n class=\"${className}\"\n href=\"${item.href}\"\n aria-current=\"${item.active ? 'page' : null}\"\n data-active=\"${item.active ? 'true' : null}\">\n <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n <ore-icon :name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n </span>\n <span class=\"bottom-tab-label\">${item.label}</span>\n </a>\n `;\n }\n\n return html`\n <button\n class=\"${className}\"\n type=\"button\"\n ?disabled=${item.disabled}\n aria-current=\"${item.active ? 'page' : null}\"\n data-active=\"${item.active ? 'true' : null}\"\n @click=${() => item.source.click()}>\n <span class=\"bottom-tab-icon\" aria-hidden=\"true\" ?hidden=${() => !item.iconName}>\n <ore-icon :name=\"${item.iconName}\" size=\"18\" stroke-width=\"2\"></ore-icon>\n </span>\n <span class=\"bottom-tab-label\">${item.label}</span>\n </button>\n `;\n })}\n </div>\n `;\n },\n styles: [coarsePointerMixin, reducedMotionMixin, sidebarStyles],\n});\n\n// ─── ore-sidebar-group styles ────────────────────────────────────────────────\n\n/** Sidebar group properties */\nexport type OreSidebarGroupProps = {\n /** Whether this group can be collapsed */\n collapsible?: boolean;\n /** Initial open state in uncontrolled mode */\n 'default-open'?: boolean;\n /** Accessible label for the group */\n label?: string;\n /** Controlled open state */\n open?: boolean;\n};\n\n/**\n * `ore-sidebar-group` — A labelled section within `ore-sidebar`.\n *\n * @element ore-sidebar-group\n *\n * @attr {string} label - Group label text\n * @attr {boolean} collapsible - Whether this group can be toggled open/closed\n * @attr {boolean} open - Controlled expanded state\n * @attr {boolean} default-open - Initial expanded state in uncontrolled mode\n *\n * @fires open-change - Fired when the group open state changes (collapsible groups only). detail: { open: boolean }\n *\n * @slot - Navigation items (`ore-sidebar-item`)\n * @slot icon - Icon displayed before the label\n *\n * @example\n * ```html\n * <ore-sidebar-group label=\"Main\" collapsible open>\n * <ore-sidebar-item href=\"/home\">Home</ore-sidebar-item>\n * </ore-sidebar-group>\n * ```\n */\nexport const SIDEBAR_GROUP_TAG = 'ore-sidebar-group' as const;\ndefine<OreSidebarGroupProps>(SIDEBAR_GROUP_TAG, {\n props: {\n collapsible: prop.bool(false),\n 'default-open': prop.bool(true),\n label: prop.string(),\n open: {\n default: undefined as boolean | undefined,\n parse: (value: string | null) => (value == null ? undefined : value === '' || value === 'true'),\n reflect: false,\n },\n },\n setup(props) {\n const slots = useSlots();\n\n const hasIcon = () => slots.has('icon').value;\n const sidebarCtx = inject(SIDEBAR_CTX);\n\n bind({\n attr: {\n 'sidebar-bottom-nav': () =>\n sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n 'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n },\n });\n\n const isControlled = () => props.open.value !== undefined;\n const openState = signal(props['default-open'].value);\n const isOpen = computed(() => {\n if (!props.collapsible.value) return true;\n\n if (isControlled()) return props.open.value ?? false;\n\n return openState.value;\n });\n\n watch(props.open, (value) => {\n if (value === undefined) return;\n\n openState.value = value;\n });\n\n bind({\n attr: {\n open: () => (isOpen.value ? true : undefined),\n },\n });\n\n return html`\n <details class=\"group\" part=\"group\" ?open=${isOpen}>\n <summary\n class=\"group-header\"\n part=\"group-header\"\n aria-expanded=\"${() => (props.collapsible.value ? String(props.open.value) : null)}\"\n @click=${(e: MouseEvent) => {\n if (!props.collapsible.value) {\n e.preventDefault();\n }\n }}>\n <span class=\"group-icon\" part=\"group-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"group-label\" part=\"group-label\">${props.label}</span>\n <span class=\"chevron\" ?hidden=${() => !props.collapsible.value} aria-hidden=\"true\">\n <ore-icon name=\"chevron-right\" size=\"12\" stroke-width=\"2\" aria-hidden=\"true\"></ore-icon>\n </span>\n </summary>\n <div class=\"group-items\" part=\"group-items\" role=\"list\">\n <slot></slot>\n </div>\n </details>\n `;\n },\n styles: [reducedMotionMixin, groupStyles],\n});\n\n// ─── ore-sidebar-item styles ─────────────────────────────────────────────────\n\n/** Sidebar item properties */\nexport type OreSidebarItemProps = {\n /** Whether this item represents the current page/section */\n active?: boolean;\n /** Whether this item is disabled */\n disabled?: boolean;\n /** Navigation href — renders an `<a>` when set, otherwise a `<button>` */\n href?: string;\n /**\n * Relationship of the linked URL (`rel` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n rel?: string;\n /**\n * Browsing context for the link (`target` attribute on the inner `<a>`).\n * Only applies when `href` is set.\n */\n target?: string;\n};\n\n/**\n * `ore-sidebar-item` — An individual navigation item in a `ore-sidebar`.\n *\n * Renders as an `<a>` when `href` is provided, otherwise as a `<button>`.\n * Marks the active page via `aria-current=\"page\"` when the `active` attribute is set.\n *\n * @element ore-sidebar-item\n *\n * @attr {string} href - Link URL; renders an anchor when set\n * @attr {boolean} active - Marks the item as the current page\n * @attr {boolean} disabled - Disables the item\n * @attr {string} rel - Anchor `rel` attribute (links only)\n * @attr {string} target - Anchor `target` attribute (links only)\n *\n * @slot - Label text\n * @slot icon - Leading icon\n * @slot end - Trailing content (badge, shortcut, arrow, etc.)\n *\n * @cssprop --sidebar-item-color - Default text color\n * @cssprop --sidebar-item-hover-bg - Hover background\n * @cssprop --sidebar-item-hover-color - Hover text color\n * @cssprop --sidebar-item-active-bg - Active background\n * @cssprop --sidebar-item-active-color - Active text color\n * @cssprop --sidebar-item-indicator - Active indicator bar color\n *\n * @part item - The inner anchor or button element\n * @part item-icon - The icon wrapper\n * @part item-label - The label wrapper\n * @part item-end - The trailing content wrapper\n *\n * @example\n * ```html\n * <ore-sidebar-item href=\"/dashboard\" active>\n * <span slot=\"icon\">🏠</span>\n * Dashboard\n * </ore-sidebar-item>\n *\n * <ore-sidebar-item href=\"/users\">\n * <span slot=\"icon\">👤</span>\n * Users\n * <ore-badge slot=\"end\" color=\"primary\">3</ore-badge>\n * </ore-sidebar-item>\n * ```\n */\nexport const SIDEBAR_ITEM_TAG = 'ore-sidebar-item' as const;\ndefine<OreSidebarItemProps>(SIDEBAR_ITEM_TAG, {\n props: {\n active: prop.bool(false),\n disabled: prop.bool(false),\n href: prop.string(),\n rel: prop.string(),\n target: prop.string(),\n },\n setup(props) {\n const slots = useSlots();\n\n const hasIcon = () => slots.has('icon').value;\n const hasEnd = () => slots.has('end').value;\n const sidebarCtx = inject(SIDEBAR_CTX);\n\n bind({\n attr: {\n 'sidebar-bottom-nav': () =>\n sidebarCtx?.mode.value === 'bottom-nav' && !sidebarCtx?.mobileOpen.value ? true : undefined,\n 'sidebar-collapsed': () => (sidebarCtx?.collapsed.value ? true : undefined),\n },\n });\n\n const isLink = () => !!props.href.value && !props.disabled.value;\n\n // Prevent reverse tabnapping: auto-inject noopener + noreferrer for _blank links.\n const effectiveRel = computed(() => computeSafeRel(props.rel.value, props.target.value));\n\n const renderItemContent = () => html`\n <span class=\"item-icon\" part=\"item-icon\" ?hidden=${() => !hasIcon()} aria-hidden=\"true\">\n <slot name=\"icon\"></slot>\n </span>\n <span class=\"item-label\" part=\"item-label\"><slot></slot></span>\n <span class=\"item-end\" part=\"item-end\" ?hidden=${() => !hasEnd()}>\n <slot name=\"end\"></slot>\n </span>\n `;\n\n return html`\n ${() => {\n if (isLink()) {\n return html`\n <a\n class=\"item\"\n part=\"item\"\n href=\"${props.href}\"\n :rel=\"${effectiveRel}\"\n :target=\"${props.target}\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </a>\n `;\n }\n\n if (props.disabled.value) {\n return html`\n <div\n class=\"item\"\n part=\"item\"\n aria-disabled=\"true\"\n tabindex=\"-1\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </div>\n `;\n }\n\n return html`\n <button\n class=\"item\"\n part=\"item\"\n type=\"button\"\n ?disabled=\"${props.disabled}\"\n aria-current=\"${() => (props.active.value ? 'page' : null)}\">\n ${renderItemContent()}\n </button>\n `;\n }}\n `;\n },\n styles: [coarsePointerMixin, itemStyles],\n});\n"],"mappings":"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"}
package/dist/skeleton.cjs CHANGED
@@ -1,10 +1,10 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./shared/prop-bundles.cjs"),n=require("./utils/css.cjs"),r=require("./ore/dist/observers/intersection-observe.cjs");require("./ore/dist/observers.cjs");const i=require("./feedback/skeleton/skeleton.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple");var s=`ore-skeleton`;(0,a.define)(s,{props:{...t.sizableBundle,animated:a.prop.bool(!0),height:a.prop.string(),lines:a.prop.number(1),radius:a.prop.string(),striped:a.prop.bool(!1),variant:a.prop.oneOf([`rect`,`circle`,`text`],`rect`),width:a.prop.string()},setup(e){let t=(0,a.getHost)(),i=(0,o.signal)(!1),s=()=>{let t=Math.floor(Number(e.lines.value));return Number.isFinite(t)&&t>0?t:1},c=()=>e.variant.value===`text`?s():1;return(0,o.watch)((0,o.computed)(()=>`${e.width.value??``}|${e.height.value??``}|${e.radius.value??``}|${e.animated.value===!1?`0`:`1`}`),()=>{let r=n.safeCSSLength(e.width.value),i=n.safeCSSLength(e.height.value),a=n.safeCSSLength(e.radius.value);r?t.style.setProperty(`--skeleton-width`,r):t.style.removeProperty(`--skeleton-width`),i?t.style.setProperty(`--skeleton-height`,i):t.style.removeProperty(`--skeleton-height`),a?t.style.setProperty(`--skeleton-radius`,a):t.style.removeProperty(`--skeleton-radius`);let o=t.getAttribute(`animated`)!==`false`&&e.animated.value!==!1;t.setAttribute(`data-animated`,o?`true`:`false`)},{immediate:!0}),(0,a.bind)({attr:{"data-paused":()=>i.value?!0:void 0}}),(0,a.onMounted)(()=>{(0,o.watch)(r.intersectionObserver(t,{threshold:0}),e=>{let t=typeof e==`object`&&e&&`isIntersecting`in e?!e.isIntersecting:!1;i.value=t})}),a.html`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./shared/prop-bundles.cjs"),n=require("./utils/css.cjs"),r=require("./feedback/skeleton/skeleton.css.cjs");let i=require("@vielzeug/ore"),a=require("@vielzeug/ripple"),o=require("@vielzeug/ore/observers");var s=`ore-skeleton`;(0,i.define)(s,{props:{...t.sizableBundle,animated:i.prop.bool(!0),height:i.prop.string(),lines:i.prop.number(1),radius:i.prop.string(),striped:i.prop.bool(!1),variant:i.prop.oneOf([`rect`,`circle`,`text`],`rect`),width:i.prop.string()},setup(e){let t=(0,i.getHost)(),r=(0,a.signal)(!1),s=()=>{let t=Math.floor(Number(e.lines.value));return Number.isFinite(t)&&t>0?t:1},c=()=>e.variant.value===`text`?s():1;return(0,a.watch)((0,a.computed)(()=>`${e.width.value??``}|${e.height.value??``}|${e.radius.value??``}|${e.animated.value===!1?`0`:`1`}`),()=>{let r=n.safeCSSLength(e.width.value),i=n.safeCSSLength(e.height.value),a=n.safeCSSLength(e.radius.value);r?t.style.setProperty(`--skeleton-width`,r):t.style.removeProperty(`--skeleton-width`),i?t.style.setProperty(`--skeleton-height`,i):t.style.removeProperty(`--skeleton-height`),a?t.style.setProperty(`--skeleton-radius`,a):t.style.removeProperty(`--skeleton-radius`);let o=t.getAttribute(`animated`)!==`false`&&e.animated.value!==!1;t.setAttribute(`data-animated`,o?`true`:`false`)},{immediate:!0}),(0,i.bind)({attr:{"data-paused":()=>r.value?!0:void 0}}),(0,i.onMounted)(()=>{(0,a.watch)((0,o.intersectionObserver)(t,{threshold:0}),e=>{let t=typeof e==`object`&&e&&`isIntersecting`in e?!e.isIntersecting:!1;r.value=t})}),i.html`
2
2
  <div class="stack" part="stack">
3
- ${()=>Array.from({length:c()},(t,n)=>{let r=e.variant.value===`text`&&c()>1&&n===c()-1;return a.html`<div
3
+ ${()=>Array.from({length:c()},(t,n)=>{let r=e.variant.value===`text`&&c()>1&&n===c()-1;return i.html`<div
4
4
  class="bone"
5
5
  part="bone"
6
6
  aria-hidden="true"
7
7
  :data-last="${()=>r?`true`:null}"></div>`})}
8
8
  </div>
9
- `},styles:[e.reducedMotionMixin,i.default]}),exports.SKELETON_TAG=s;
9
+ `},styles:[e.reducedMotionMixin,r.default]}),exports.SKELETON_TAG=s;
10
10
  //# sourceMappingURL=skeleton.cjs.map