@treeui/vue 0.19.0 → 0.20.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 (69) hide show
  1. package/dist/components/TAppShell.cjs.map +1 -1
  2. package/dist/components/TAppShell.js.map +1 -1
  3. package/dist/components/TAppShell.vue.d.ts +4 -0
  4. package/dist/components/TAppShell.vue.d.ts.map +1 -1
  5. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs +1 -1
  6. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  7. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js +55 -44
  8. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  9. package/dist/components/TButton.cjs.map +1 -1
  10. package/dist/components/TButton.js.map +1 -1
  11. package/dist/components/TButton.vue.d.ts.map +1 -1
  12. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs +1 -1
  13. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  14. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js +36 -32
  15. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  16. package/dist/components/TCard.cjs.map +1 -1
  17. package/dist/components/TCard.js.map +1 -1
  18. package/dist/components/TCard.vue.d.ts +8 -0
  19. package/dist/components/TCard.vue.d.ts.map +1 -1
  20. package/dist/components/TCard.vue_vue_type_script_setup_true_lang.cjs +1 -1
  21. package/dist/components/TCard.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  22. package/dist/components/TCard.vue_vue_type_script_setup_true_lang.js +7 -2
  23. package/dist/components/TCard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  24. package/dist/components/TLink.cjs.map +1 -1
  25. package/dist/components/TLink.js.map +1 -1
  26. package/dist/components/TLink.vue.d.ts +8 -0
  27. package/dist/components/TLink.vue.d.ts.map +1 -1
  28. package/dist/components/TLink.vue_vue_type_script_setup_true_lang.cjs +1 -1
  29. package/dist/components/TLink.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  30. package/dist/components/TLink.vue_vue_type_script_setup_true_lang.js +5 -1
  31. package/dist/components/TLink.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/components/TPopover.cjs.map +1 -1
  33. package/dist/components/TPopover.js.map +1 -1
  34. package/dist/components/TPopover.vue.d.ts +4 -1
  35. package/dist/components/TPopover.vue.d.ts.map +1 -1
  36. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.cjs +1 -1
  37. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  38. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.js +3 -1
  39. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/TStack.cjs.map +1 -1
  41. package/dist/components/TStack.js.map +1 -1
  42. package/dist/components/TStack.vue.d.ts +9 -0
  43. package/dist/components/TStack.vue.d.ts.map +1 -1
  44. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.cjs +1 -1
  45. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  46. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.js +3 -1
  47. package/dist/components/TStack.vue_vue_type_script_setup_true_lang.js.map +1 -1
  48. package/dist/components/TSteps.vue.d.ts +1 -1
  49. package/dist/components/TSteps.vue.d.ts.map +1 -1
  50. package/dist/components/TTable.cjs.map +1 -1
  51. package/dist/components/TTable.js.map +1 -1
  52. package/dist/components/TTable.vue.d.ts +16 -0
  53. package/dist/components/TTable.vue.d.ts.map +1 -1
  54. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.cjs +1 -1
  55. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  56. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.js +29 -9
  57. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/TText.cjs.map +1 -1
  59. package/dist/components/TText.js.map +1 -1
  60. package/dist/components/TText.vue.d.ts +9 -0
  61. package/dist/components/TText.vue.d.ts.map +1 -1
  62. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs +1 -1
  63. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  64. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js +2 -0
  65. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js.map +1 -1
  66. package/dist/components/index.d.ts +4 -4
  67. package/dist/components/index.d.ts.map +1 -1
  68. package/dist/style.css +1 -1
  69. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  import { useControllableOpen as e } from "../composables/useControllableOpen.js";
2
2
  import { treeSidebarInjectionKey as t } from "./sidebar.js";
3
3
  import { Transition as n, computed as r, createBlock as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createVNode as c, defineComponent as l, guardReactiveProps as u, mergeProps as d, nextTick as f, normalizeClass as ee, normalizeProps as p, onBeforeUnmount as te, onMounted as ne, openBlock as m, provide as re, ref as h, renderSlot as g, resolveDynamicComponent as ie, toRef as _, unref as v, useAttrs as ae, watch as y, withCtx as b } from "vue";
4
- import { createId as x, focusFirst as S, focusLast as oe, getFocusableElements as se, isEscapeKey as ce } from "@treeui/utils";
4
+ import { createId as oe, focusFirst as x, focusLast as S, getFocusableElements as se, isEscapeKey as ce } from "@treeui/utils";
5
5
  import { getTreeIcon as C, treeIconDefaults as w } from "@treeui/icons";
6
6
  //#region src/components/TAppShell.vue?vue&type=script&setup=true&lang.ts
7
7
  var le = [
@@ -11,23 +11,26 @@ var le = [
11
11
  ], ue = {
12
12
  key: 1,
13
13
  class: "t-app-shell__header-start"
14
- }, de = { class: "t-app-shell__header-content" }, fe = ["id", "aria-label"], pe = {
14
+ }, de = { class: "t-app-shell__header-content" }, fe = {
15
+ key: 2,
16
+ class: "t-app-shell__header-end"
17
+ }, pe = ["id", "aria-label"], me = {
15
18
  key: 0,
16
19
  class: "t-app-shell__sidebar-header"
17
- }, me = { class: "t-app-shell__sidebar-body" }, he = {
20
+ }, he = { class: "t-app-shell__sidebar-body" }, ge = {
18
21
  key: 1,
19
22
  class: "t-app-shell__sidebar-footer"
20
- }, ge = [
23
+ }, _e = [
21
24
  "aria-label",
22
25
  "aria-expanded",
23
26
  "aria-controls"
24
- ], _e = { class: "t-app-shell__main" }, ve = {
27
+ ], ve = { class: "t-app-shell__main" }, ye = {
25
28
  key: 0,
26
29
  class: "t-app-shell__overlay"
27
- }, ye = ["id", "aria-label"], be = { class: "t-app-shell__drawer-topbar" }, xe = ["aria-label"], Se = { class: "t-app-shell__drawer-body" }, Ce = {
30
+ }, be = ["id", "aria-label"], xe = { class: "t-app-shell__drawer-topbar" }, Se = ["aria-label"], Ce = { class: "t-app-shell__drawer-body" }, we = {
28
31
  key: 0,
29
32
  class: "t-app-shell__sidebar-header"
30
- }, we = { class: "t-app-shell__sidebar-body" }, Te = {
33
+ }, Te = { class: "t-app-shell__sidebar-body" }, Ee = {
31
34
  key: 1,
32
35
  class: "t-app-shell__sidebar-footer"
33
36
  }, T = /*@__PURE__*/ l({
@@ -102,39 +105,39 @@ var le = [
102
105
  "immersive-change"
103
106
  ],
104
107
  setup(l, { emit: T }) {
105
- let Ee = r(() => C("x")), De = r(() => C("menu")), E = l, D = T, O = ae(), k = x("t-app-shell-sidebar"), { value: A, setValue: Oe } = e(_(E, "collapsed"), E.defaultCollapsed, (e) => {
108
+ let De = r(() => C("x")), Oe = r(() => C("menu")), E = l, D = T, O = ae(), k = oe("t-app-shell-sidebar"), { value: A, setValue: ke } = e(_(E, "collapsed"), E.defaultCollapsed, (e) => {
106
109
  D("update:collapsed", e), D("collapse-change", e);
107
110
  }), { value: j, setValue: M } = e(_(E, "sidebarOpen"), E.defaultSidebarOpen, (e) => {
108
111
  D("update:sidebarOpen", e), D("sidebar-open-change", e);
109
- }), { value: N, setValue: ke } = e(_(E, "immersive"), E.defaultImmersive, (e) => {
112
+ }), { value: N, setValue: Ae } = e(_(E, "immersive"), E.defaultImmersive, (e) => {
110
113
  D("update:immersive", e), D("immersive-change", e);
111
114
  }), P = () => {
112
- ke(!N.value);
115
+ Ae(!N.value);
113
116
  }, F = h(!1), I = null, L = (e) => {
114
117
  F.value = e.matches;
115
118
  }, R = () => {
116
119
  typeof window > "u" || typeof window.matchMedia != "function" || (z(), I = window.matchMedia(`(max-width: ${E.breakpoint})`), F.value = I.matches, I.addEventListener?.("change", L));
117
120
  }, z = () => {
118
121
  I?.removeEventListener?.("change", L), I = null;
119
- }, B = r(() => E.mobile ?? F.value), V = r(() => !B.value && E.collapsible && E.showCollapseButton), H = r(() => !B.value && A.value), Ae = r(() => C((E.side === "right" ? H.value : !H.value) ? "panel-left" : "panel-right")), U = h(null), W = h(null), G = "", K = !1, q = () => {
122
+ }, B = r(() => E.mobile ?? F.value), V = r(() => !B.value && E.collapsible && E.showCollapseButton), H = r(() => !B.value && A.value), je = r(() => C((E.side === "right" ? H.value : !H.value) ? "panel-left" : "panel-right")), U = h(null), W = h(null), G = "", K = !1, q = () => {
120
123
  typeof document > "u" || K || (G = document.body.style.overflow, document.body.style.overflow = "hidden", K = !0);
121
124
  }, J = () => {
122
125
  typeof document > "u" || !K || (document.body.style.overflow = G, K = !1);
123
126
  }, Y = () => {
124
127
  f(() => {
125
- U.value && (S(U.value) || U.value.focus());
128
+ U.value && (x(U.value) || U.value.focus());
126
129
  });
127
- }, je = () => {
130
+ }, Me = () => {
128
131
  W.value = typeof document > "u" ? null : document.activeElement, M(!0);
129
132
  }, X = () => {
130
133
  M(!1);
131
134
  }, Z = () => {
132
- j.value ? X() : je();
135
+ j.value ? X() : Me();
133
136
  }, Q = () => {
134
- E.collapsible && Oe(!A.value);
135
- }, Me = () => {
137
+ E.collapsible && ke(!A.value);
138
+ }, Ne = () => {
136
139
  E.closeOnOverlay && X();
137
- }, Ne = (e) => {
140
+ }, Pe = (e) => {
138
141
  if (ce(e) && E.closeOnEscape) {
139
142
  e.preventDefault(), X();
140
143
  return;
@@ -146,8 +149,8 @@ var le = [
146
149
  return;
147
150
  }
148
151
  let n = t[0], r = t[t.length - 1], i = document.activeElement;
149
- e.shiftKey && i === n && (e.preventDefault(), oe(U.value)), !e.shiftKey && i === r && (e.preventDefault(), S(U.value));
150
- }, Pe = (e, t) => {
152
+ e.shiftKey && i === n && (e.preventDefault(), S(U.value)), !e.shiftKey && i === r && (e.preventDefault(), x(U.value));
153
+ }, Fe = (e, t) => {
151
154
  if (e && B.value) {
152
155
  q(), Y();
153
156
  return;
@@ -157,7 +160,11 @@ var le = [
157
160
  }));
158
161
  };
159
162
  y(j, (e, t) => {
160
- Pe(e, !!t);
163
+ Fe(e, !!t);
164
+ }), y(N, (e) => {
165
+ !j.value || !B.value || (e ? (J(), f(() => {
166
+ W.value?.focus();
167
+ })) : (q(), Y()));
161
168
  }), y(B, (e) => {
162
169
  j.value && (e ? (q(), Y()) : J());
163
170
  }), y(() => E.breakpoint, () => {
@@ -167,7 +174,7 @@ var le = [
167
174
  }), te(() => {
168
175
  z(), J();
169
176
  }), re(t, { collapsed: H });
170
- let Fe = r(() => [
177
+ let Ie = r(() => [
171
178
  "t-app-shell",
172
179
  `t-app-shell--${E.side}`,
173
180
  {
@@ -177,10 +184,10 @@ var le = [
177
184
  "is-immersive": N.value
178
185
  },
179
186
  O.class
180
- ]), Ie = r(() => [{
187
+ ]), Le = r(() => [{
181
188
  "--tree-app-shell-sidebar-width": E.sidebarWidth,
182
189
  "--tree-app-shell-collapsed-width": E.collapsedWidth
183
- }, O.style]), Le = r(() => {
190
+ }, O.style]), Re = r(() => {
184
191
  let { class: e, style: t, ...n } = O;
185
192
  return n;
186
193
  }), $ = r(() => ({
@@ -193,13 +200,16 @@ var le = [
193
200
  toggleCollapsed: Q,
194
201
  toggleImmersive: P
195
202
  }));
196
- return (e, t) => (m(), i(ie(l.as), d(Le.value, {
197
- class: Fe.value,
198
- style: Ie.value,
203
+ return (e, t) => (m(), i(ie(l.as), d(Re.value, {
204
+ class: Ie.value,
205
+ style: Le.value,
199
206
  "data-mobile": B.value ? "true" : "false"
200
207
  }), {
201
208
  default: b(() => [
202
- s("header", { class: ee(["t-app-shell__header", { "has-start": !!e.$slots["header-start"] }]) }, [
209
+ s("header", { class: ee(["t-app-shell__header", {
210
+ "has-start": !!e.$slots["header-start"],
211
+ "has-end": !!e.$slots["header-end"]
212
+ }]) }, [
203
213
  B.value && l.showMenuButton ? (m(), o("button", {
204
214
  key: 0,
205
215
  type: "button",
@@ -208,12 +218,13 @@ var le = [
208
218
  "aria-expanded": v(j),
209
219
  "aria-controls": v(k),
210
220
  onClick: Z
211
- }, [g(e.$slots, "menu-icon", { sidebarOpen: v(j) }, () => [c(v(De), d(v(w), {
221
+ }, [g(e.$slots, "menu-icon", { sidebarOpen: v(j) }, () => [c(v(Oe), d(v(w), {
212
222
  size: 24,
213
223
  "aria-hidden": "true"
214
224
  }), null, 16)])], 8, le)) : a("", !0),
215
225
  e.$slots["header-start"] ? (m(), o("div", ue, [g(e.$slots, "header-start", p(u($.value)))])) : a("", !0),
216
- s("div", de, [g(e.$slots, "header", p(u($.value)))])
226
+ s("div", de, [g(e.$slots, "header", p(u($.value)))]),
227
+ e.$slots["header-end"] ? (m(), o("div", fe, [g(e.$slots, "header-end", p(u($.value)))])) : a("", !0)
217
228
  ], 2),
218
229
  B.value ? a("", !0) : (m(), o("aside", {
219
230
  key: 0,
@@ -221,9 +232,9 @@ var le = [
221
232
  class: "t-app-shell__sidebar",
222
233
  "aria-label": l.sidebarLabel
223
234
  }, [
224
- e.$slots["sidebar-header"] ? (m(), o("div", pe, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
225
- s("div", me, [g(e.$slots, "sidebar", p(u($.value)))]),
226
- e.$slots["sidebar-footer"] || V.value ? (m(), o("div", he, [g(e.$slots, "sidebar-footer", p(u($.value))), V.value ? (m(), o("button", {
235
+ e.$slots["sidebar-header"] ? (m(), o("div", me, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
236
+ s("div", he, [g(e.$slots, "sidebar", p(u($.value)))]),
237
+ e.$slots["sidebar-footer"] || V.value ? (m(), o("div", ge, [g(e.$slots, "sidebar-footer", p(u($.value))), V.value ? (m(), o("button", {
227
238
  key: 0,
228
239
  type: "button",
229
240
  class: "t-app-shell__collapse-button",
@@ -231,19 +242,19 @@ var le = [
231
242
  "aria-expanded": !v(A),
232
243
  "aria-controls": v(k),
233
244
  onClick: Q
234
- }, [g(e.$slots, "collapse-icon", { collapsed: H.value }, () => [c(v(Ae), d(v(w), { "aria-hidden": "true" }), null, 16)])], 8, ge)) : a("", !0)])) : a("", !0)
235
- ], 8, fe)),
236
- s("main", _e, [g(e.$slots, "default", {
245
+ }, [g(e.$slots, "collapse-icon", { collapsed: H.value }, () => [c(v(je), d(v(w), { "aria-hidden": "true" }), null, 16)])], 8, _e)) : a("", !0)])) : a("", !0)
246
+ ], 8, pe)),
247
+ s("main", ve, [g(e.$slots, "default", {
237
248
  mobile: B.value,
238
249
  collapsed: H.value,
239
250
  immersive: v(N),
240
251
  toggleImmersive: P
241
252
  })]),
242
253
  c(n, { name: "t-app-shell-fade" }, {
243
- default: b(() => [B.value && v(j) && !v(N) ? (m(), o("div", ve, [s("div", {
254
+ default: b(() => [B.value && v(j) && !v(N) ? (m(), o("div", ye, [s("div", {
244
255
  class: "t-app-shell__backdrop",
245
256
  "aria-hidden": "true",
246
- onClick: Me
257
+ onClick: Ne
247
258
  }), s("aside", {
248
259
  id: v(k),
249
260
  ref_key: "surfaceRef",
@@ -253,17 +264,17 @@ var le = [
253
264
  "aria-modal": "true",
254
265
  "aria-label": l.sidebarLabel,
255
266
  tabindex: "-1",
256
- onKeydown: Ne
257
- }, [s("div", be, [s("button", {
267
+ onKeydown: Pe
268
+ }, [s("div", xe, [s("button", {
258
269
  type: "button",
259
270
  class: "t-app-shell__drawer-close",
260
271
  "aria-label": l.closeLabel,
261
272
  onClick: X
262
- }, [c(v(Ee), p(u(v(w))), null, 16)], 8, xe)]), s("div", Se, [
263
- e.$slots["sidebar-header"] ? (m(), o("div", Ce, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
264
- s("div", we, [g(e.$slots, "sidebar", p(u($.value)))]),
265
- e.$slots["sidebar-footer"] ? (m(), o("div", Te, [g(e.$slots, "sidebar-footer", p(u($.value)))])) : a("", !0)
266
- ])], 40, ye)])) : a("", !0)]),
273
+ }, [c(v(De), p(u(v(w))), null, 16)], 8, Se)]), s("div", Ce, [
274
+ e.$slots["sidebar-header"] ? (m(), o("div", we, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
275
+ s("div", Te, [g(e.$slots, "sidebar", p(u($.value)))]),
276
+ e.$slots["sidebar-footer"] ? (m(), o("div", Ee, [g(e.$slots, "sidebar-footer", p(u($.value)))])) : a("", !0)
277
+ ])], 40, be)])) : a("", !0)]),
267
278
  _: 3
268
279
  })
269
280
  ]),
@@ -1 +1 @@
1
- {"version":3,"file":"TAppShell.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TAppShell.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSidebarSide } from './TSidebar.vue';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\nconst MenuIcon = computed(() => getTreeIcon('menu'));\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n side?: TSidebarSide;\n sidebarWidth?: string;\n collapsedWidth?: string;\n collapsible?: boolean;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n mobile?: boolean;\n breakpoint?: string;\n sidebarOpen?: boolean;\n defaultSidebarOpen?: boolean;\n /**\n * Hide the shell chrome (header and sidebar) so the content fills the\n * viewport. The default slot stays mounted across the toggle.\n */\n immersive?: boolean;\n defaultImmersive?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showMenuButton?: boolean;\n /** Render the built-in collapse toggle in the sidebar footer (desktop). */\n showCollapseButton?: boolean;\n menuLabel?: string;\n closeLabel?: string;\n sidebarLabel?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'div',\n side: 'left',\n sidebarWidth: '17.5rem',\n collapsedWidth: '4.75rem',\n collapsible: false,\n collapsed: undefined,\n defaultCollapsed: false,\n mobile: undefined,\n breakpoint: '768px',\n sidebarOpen: undefined,\n defaultSidebarOpen: false,\n immersive: undefined,\n defaultImmersive: false,\n closeOnEscape: true,\n closeOnOverlay: true,\n showMenuButton: true,\n showCollapseButton: true,\n menuLabel: 'Open menu',\n closeLabel: 'Close menu',\n sidebarLabel: 'Sidebar',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n 'update:sidebarOpen': [value: boolean];\n 'sidebar-open-change': [value: boolean];\n 'update:immersive': [value: boolean];\n 'immersive-change': [value: boolean];\n}>();\n\nexport interface AppShellSlotProps {\n mobile: boolean;\n collapsed: boolean;\n sidebarOpen: boolean;\n immersive: boolean;\n toggleSidebar: () => void;\n closeSidebar: () => void;\n toggleCollapsed: () => void;\n toggleImmersive: () => void;\n}\n\ndefineSlots<{\n header?: (props: AppShellSlotProps) => unknown;\n /** Header region over the sidebar rail; the `header` slot then aligns with the content panel. */\n 'header-start'?: (props: AppShellSlotProps) => unknown;\n /** Pinned above the sidebar body, inset to line up with nav item icons. */\n 'sidebar-header'?: (props: AppShellSlotProps) => unknown;\n sidebar?: (props: AppShellSlotProps) => unknown;\n /** Pinned to the bottom of the sidebar, inset to line up with nav item icons. */\n 'sidebar-footer'?: (props: AppShellSlotProps) => unknown;\n /**\n * Immersive hides the chrome, so the content is the only place an exit\n * control can live — `immersive` and `toggleImmersive` are passed through.\n */\n default?: (\n props: Pick<AppShellSlotProps, 'mobile' | 'collapsed' | 'immersive' | 'toggleImmersive'>,\n ) => unknown;\n 'menu-icon'?: (props: { sidebarOpen: boolean }) => unknown;\n 'collapse-icon'?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebarId = createId('t-app-shell-sidebar');\n\nconst { value: isCollapsed, setValue: setCollapsed } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst { value: isSidebarOpen, setValue: setSidebarOpen } = useControllableOpen(\n toRef(props, 'sidebarOpen'),\n props.defaultSidebarOpen,\n (value) => {\n emit('update:sidebarOpen', value);\n emit('sidebar-open-change', value);\n },\n);\n\nconst { value: isImmersive, setValue: setImmersive } = useControllableOpen(\n toRef(props, 'immersive'),\n props.defaultImmersive,\n (value) => {\n emit('update:immersive', value);\n emit('immersive-change', value);\n },\n);\n\nconst toggleImmersive = () => {\n setImmersive(!isImmersive.value);\n};\n\n// Auto responsive detection when `mobile` is not explicitly controlled.\nconst autoMobile = ref(false);\nlet mediaQuery: MediaQueryList | null = null;\n\nconst onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {\n autoMobile.value = event.matches;\n};\n\nconst setupMediaQuery = () => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return;\n }\n\n teardownMediaQuery();\n mediaQuery = window.matchMedia(`(max-width: ${props.breakpoint})`);\n autoMobile.value = mediaQuery.matches;\n mediaQuery.addEventListener?.('change', onMediaChange);\n};\n\nconst teardownMediaQuery = () => {\n mediaQuery?.removeEventListener?.('change', onMediaChange);\n mediaQuery = null;\n};\n\nconst isMobile = computed(() => props.mobile ?? autoMobile.value);\n\n// Collapsing is desktop-only, so the built-in toggle follows the same rule.\nconst showCollapseToggle = computed(\n () => !isMobile.value && props.collapsible && props.showCollapseButton,\n);\n\n// Collapse is a desktop-only concept; the mobile drawer always shows the\n// expanded sidebar, so descendants and slots see `collapsed: false` there.\nconst effectiveCollapsed = computed(() =>\n isMobile.value ? false : isCollapsed.value,\n);\n\n// The glyph points the way the rail will move: collapsing a left sidebar folds\n// it left, expanding it pushes right (mirrored for a right-anchored sidebar).\nconst CollapseIcon = computed(() => {\n const pointsStart = props.side === 'right' ? effectiveCollapsed.value : !effectiveCollapsed.value;\n return getTreeIcon(pointsStart ? 'panel-left' : 'panel-right');\n});\n\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nlet previousBodyOverflow = '';\nlet bodyLocked = false;\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined' || bodyLocked) {\n return;\n }\n\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n bodyLocked = true;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || !bodyLocked) {\n return;\n }\n\n document.body.style.overflow = previousBodyOverflow;\n bodyLocked = false;\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openSidebar = () => {\n previousFocusedElement.value =\n typeof document === 'undefined'\n ? null\n : (document.activeElement as HTMLElement | null);\n setSidebarOpen(true);\n};\n\nconst closeSidebar = () => {\n setSidebarOpen(false);\n};\n\nconst toggleSidebar = () => {\n if (isSidebarOpen.value) {\n closeSidebar();\n } else {\n openSidebar();\n }\n};\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setCollapsed(!isCollapsed.value);\n};\n\nconst onOverlayClick = () => {\n if (props.closeOnOverlay) {\n closeSidebar();\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeSidebar();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\n// The off-canvas drawer only exists in mobile mode; keep body-scroll lock and\n// focus handling in sync with both the open flag and the responsive mode.\nconst syncOverlayState = (open: boolean, wasOpen: boolean) => {\n if (open && isMobile.value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (wasOpen) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n};\n\nwatch(isSidebarOpen, (value, previousValue) => {\n syncOverlayState(value, Boolean(previousValue));\n});\n\nwatch(isMobile, (mobile) => {\n if (!isSidebarOpen.value) {\n return;\n }\n\n // Leaving mobile removes the drawer from the DOM, so release the lock and\n // restore focus; re-entering mobile while \"open\" re-arms the overlay.\n if (mobile) {\n lockBodyScroll();\n focusSurface();\n } else {\n unlockBodyScroll();\n }\n});\n\nwatch(\n () => props.breakpoint,\n () => {\n if (typeof window !== 'undefined') {\n setupMediaQuery();\n }\n },\n);\n\nonMounted(() => {\n setupMediaQuery();\n});\n\nonBeforeUnmount(() => {\n teardownMediaQuery();\n unlockBodyScroll();\n});\n\nprovide(treeSidebarInjectionKey, {\n collapsed: effectiveCollapsed,\n});\n\nconst rootClasses = computed(() => [\n 't-app-shell',\n `t-app-shell--${props.side}`,\n {\n 'is-mobile': isMobile.value,\n 'is-collapsed':\n !isMobile.value && props.collapsible && isCollapsed.value,\n 'is-sidebar-open': isMobile.value && isSidebarOpen.value,\n 'is-immersive': isImmersive.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-app-shell-sidebar-width': props.sidebarWidth,\n '--tree-app-shell-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst slotProps = computed<AppShellSlotProps>(() => ({\n mobile: isMobile.value,\n collapsed: effectiveCollapsed.value,\n sidebarOpen: isSidebarOpen.value,\n immersive: isImmersive.value,\n toggleSidebar,\n closeSidebar,\n toggleCollapsed,\n toggleImmersive,\n}));\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-mobile=\"isMobile ? 'true' : 'false'\"\n >\n <header\n class=\"t-app-shell__header\"\n :class=\"{ 'has-start': Boolean($slots['header-start']) }\"\n >\n <button\n v-if=\"isMobile && showMenuButton\"\n type=\"button\"\n class=\"t-app-shell__menu-button\"\n :aria-label=\"menuLabel\"\n :aria-expanded=\"isSidebarOpen\"\n :aria-controls=\"sidebarId\"\n @click=\"toggleSidebar\"\n >\n <slot\n name=\"menu-icon\"\n :sidebar-open=\"isSidebarOpen\"\n >\n <MenuIcon\n v-bind=\"treeIconDefaults\"\n :size=\"24\"\n aria-hidden=\"true\"\n />\n </slot>\n </button>\n\n <div\n v-if=\"$slots['header-start']\"\n class=\"t-app-shell__header-start\"\n >\n <slot\n name=\"header-start\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__header-content\">\n <slot\n name=\"header\"\n v-bind=\"slotProps\"\n />\n </div>\n </header>\n\n <aside\n v-if=\"!isMobile\"\n :id=\"sidebarId\"\n class=\"t-app-shell__sidebar\"\n :aria-label=\"sidebarLabel\"\n >\n <div\n v-if=\"$slots['sidebar-header']\"\n class=\"t-app-shell__sidebar-header\"\n >\n <slot\n name=\"sidebar-header\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__sidebar-body\">\n <slot\n name=\"sidebar\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div\n v-if=\"$slots['sidebar-footer'] || showCollapseToggle\"\n class=\"t-app-shell__sidebar-footer\"\n >\n <slot\n name=\"sidebar-footer\"\n v-bind=\"slotProps\"\n />\n\n <button\n v-if=\"showCollapseToggle\"\n type=\"button\"\n class=\"t-app-shell__collapse-button\"\n :aria-label=\"isCollapsed ? expandLabel : collapseLabel\"\n :aria-expanded=\"!isCollapsed\"\n :aria-controls=\"sidebarId\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"collapse-icon\"\n :collapsed=\"effectiveCollapsed\"\n >\n <CollapseIcon\n v-bind=\"treeIconDefaults\"\n aria-hidden=\"true\"\n />\n </slot>\n </button>\n </div>\n </aside>\n\n <main class=\"t-app-shell__main\">\n <slot\n :mobile=\"isMobile\"\n :collapsed=\"effectiveCollapsed\"\n :immersive=\"isImmersive\"\n :toggle-immersive=\"toggleImmersive\"\n />\n </main>\n\n <transition name=\"t-app-shell-fade\">\n <div\n v-if=\"isMobile && isSidebarOpen && !isImmersive\"\n class=\"t-app-shell__overlay\"\n >\n <div\n class=\"t-app-shell__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <aside\n :id=\"sidebarId\"\n ref=\"surfaceRef\"\n class=\"t-app-shell__drawer\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"sidebarLabel\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n >\n <div class=\"t-app-shell__drawer-topbar\">\n <button\n type=\"button\"\n class=\"t-app-shell__drawer-close\"\n :aria-label=\"closeLabel\"\n @click=\"closeSidebar\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n <div class=\"t-app-shell__drawer-body\">\n <div\n v-if=\"$slots['sidebar-header']\"\n class=\"t-app-shell__sidebar-header\"\n >\n <slot\n name=\"sidebar-header\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__sidebar-body\">\n <slot\n name=\"sidebar\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div\n v-if=\"$slots['sidebar-footer']\"\n class=\"t-app-shell__sidebar-footer\"\n >\n <slot\n name=\"sidebar-footer\"\n v-bind=\"slotProps\"\n />\n </div>\n </div>\n </aside>\n </div>\n </transition>\n </component>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BA,IAAM,KAAY,QAAe,EAAY,GAAG,CAAC,GAC3C,KAAW,QAAe,EAAY,MAAM,CAAC,GAE7C,IAAQ,GAwDR,IAAO,GAwCP,IAAQ,GAAS,GACjB,IAAY,EAAS,qBAAqB,GAE1C,EAAE,OAAO,GAAa,UAAU,OAAiB,EACrD,EAAM,GAAO,WAAW,GACxB,EAAM,mBACL,MAAU;GAET,AADA,EAAK,oBAAoB,CAAK,GAC9B,EAAK,mBAAmB,CAAK;EAC/B,CACF,GAEM,EAAE,OAAO,GAAe,UAAU,MAAmB,EACzD,EAAM,GAAO,aAAa,GAC1B,EAAM,qBACL,MAAU;GAET,AADA,EAAK,sBAAsB,CAAK,GAChC,EAAK,uBAAuB,CAAK;EACnC,CACF,GAEM,EAAE,OAAO,GAAa,UAAU,OAAiB,EACrD,EAAM,GAAO,WAAW,GACxB,EAAM,mBACL,MAAU;GAET,AADA,EAAK,oBAAoB,CAAK,GAC9B,EAAK,oBAAoB,CAAK;EAChC,CACF,GAEM,UAAwB;GAC5B,GAAa,CAAC,EAAY,KAAK;EACjC,GAGM,IAAa,EAAI,EAAK,GACxB,IAAoC,MAElC,KAAiB,MAAgD;GACrE,EAAW,QAAQ,EAAM;EAC3B,GAEM,UAAwB;GACxB,OAAO,SAAW,OAAe,OAAO,OAAO,cAAe,eAIlE,EAAmB,GACnB,IAAa,OAAO,WAAW,eAAe,EAAM,WAAW,EAAE,GACjE,EAAW,QAAQ,EAAW,SAC9B,EAAW,mBAAmB,UAAU,CAAa;EACvD,GAEM,UAA2B;GAE/B,AADA,GAAY,sBAAsB,UAAU,CAAa,GACzD,IAAa;EACf,GAEM,IAAW,QAAe,EAAM,UAAU,EAAW,KAAK,GAG1D,IAAqB,QACnB,CAAC,EAAS,SAAS,EAAM,eAAe,EAAM,kBACtD,GAIM,IAAqB,QACzB,GAAS,SAAgB,EAAY,KACvC,GAIM,KAAe,QAEZ,GADa,EAAM,SAAS,UAAU,EAAmB,QAAQ,CAAC,EAAmB,SAC3D,eAAe,aAAa,CAC9D,GAEK,IAAa,EAAwB,IAAI,GACzC,IAAyB,EAAwB,IAAI,GACvD,IAAuB,IACvB,IAAa,IAEX,UAAuB;GACvB,OAAO,WAAa,OAAe,MAIvC,IAAuB,SAAS,KAAK,MAAM,UAC3C,SAAS,KAAK,MAAM,WAAW,UAC/B,IAAa;EACf,GAEM,UAAyB;GACzB,OAAO,WAAa,OAAe,CAAC,MAIxC,SAAS,KAAK,MAAM,WAAW,GAC/B,IAAa;EACf,GAEM,UAAqB;GACzB,QAAe;IACR,EAAW,UAIA,EAAW,EAAW,KACjC,KACH,EAAW,MAAM,MAAM;GAE3B,CAAC;EACH,GAEM,WAAoB;GAKxB,AAJA,EAAuB,QACrB,OAAO,WAAa,MAChB,OACC,SAAS,eAChB,EAAe,EAAI;EACrB,GAEM,UAAqB;GACzB,EAAe,EAAK;EACtB,GAEM,UAAsB;GAC1B,AAAI,EAAc,QAChB,EAAa,IAEb,GAAY;EAEhB,GAEM,UAAwB;GACvB,EAAM,eAIX,GAAa,CAAC,EAAY,KAAK;EACjC,GAEM,WAAuB;GAC3B,AAAI,EAAM,kBACR,EAAa;EAEjB,GAEM,MAAa,MAAyB;GAC1C,IAAI,GAAY,CAAK,KAAK,EAAM,eAAe;IAE7C,AADA,EAAM,eAAe,GACrB,EAAa;IACb;GACF;GAEA,IAAI,EAAM,QAAQ,SAAS,CAAC,EAAW,OACrC;GAGF,IAAM,IAAY,GAAqB,EAAW,KAAK;GAEvD,IAAI,CAAC,EAAU,QAAQ;IAErB,AADA,EAAM,eAAe,GACrB,EAAW,MAAM,MAAM;IACvB;GACF;GAEA,IAAM,IAAQ,EAAU,IAClB,IAAO,EAAU,EAAU,SAAS,IACpC,IAAgB,SAAS;GAO/B,AALI,EAAM,YAAY,MAAkB,MACtC,EAAM,eAAe,GACrB,GAAU,EAAW,KAAK,IAGxB,CAAC,EAAM,YAAY,MAAkB,MACvC,EAAM,eAAe,GACrB,EAAW,EAAW,KAAK;EAE/B,GAIM,MAAoB,GAAe,MAAqB;GAC5D,IAAI,KAAQ,EAAS,OAAO;IAE1B,AADA,EAAe,GACf,EAAa;IACb;GACF;GAEA,AAAI,MACF,EAAiB,GACjB,QAAe;IACb,EAAuB,OAAO,MAAM;GACtC,CAAC;EAEL;EAuCA,AArCA,EAAM,IAAgB,GAAO,MAAkB;GAC7C,GAAiB,GAAO,EAAQ,CAAc;EAChD,CAAC,GAED,EAAM,IAAW,MAAW;GACrB,EAAc,UAMf,KACF,EAAe,GACf,EAAa,KAEb,EAAiB;EAErB,CAAC,GAED,QACQ,EAAM,kBACN;GACJ,AAAI,OAAO,SAAW,OACpB,EAAgB;EAEpB,CACF,GAEA,SAAgB;GACd,EAAgB;EAClB,CAAC,GAED,SAAsB;GAEpB,AADA,EAAmB,GACnB,EAAiB;EACnB,CAAC,GAED,GAAQ,GAAyB,EAC/B,WAAW,EACb,CAAC;EAED,IAAM,KAAc,QAAe;GACjC;GACA,gBAAgB,EAAM;GACtB;IACE,aAAa,EAAS;IACtB,gBACE,CAAC,EAAS,SAAS,EAAM,eAAe,EAAY;IACtD,mBAAmB,EAAS,SAAS,EAAc;IACnD,gBAAgB,EAAY;GAC9B;GACA,EAAM;EACR,CAAC,GAEK,KAAY,QAAe,CAC/B;GACE,kCAAkC,EAAM;GACxC,oCAAoC,EAAM;EAC5C,GACA,EAAM,KACR,CAAC,GAEK,KAAY,QAAe;GAC/B,IAAM,EAAE,OAAO,GAAQ,OAAO,GAAQ,GAAG,MAAS;GAClD,OAAO;EACT,CAAC,GAEK,IAAY,SAAmC;GACnD,QAAQ,EAAS;GACjB,WAAW,EAAmB;GAC9B,aAAa,EAAc;GAC3B,WAAW,EAAY;GACvB;GACA;GACA;GACA;EACF,EAAE;yBAIA,EA8KY,GA7KL,EAAA,EAAE,GADT,EAEU,GA4KE,OA5KO;GAChB,OAAO,GAAA;GACP,OAAO,GAAA;GACP,eAAa,EAAA,QAAQ,SAAA;;oBA2Cb;IAzCT,EAyCS,UAAA,EAxCP,OAAK,GAAA,CAAC,uBAAqB,EAAA,aACJ,EAAQA,EAAAA,OAAM,gBAAA,CAAA,CAAA,EAAA,GAAA;KAG7B,EAAA,SAAY,EAAA,kBAAA,EAAA,GADpB,EAmBS,UAAA;;MAjBP,MAAK;MACL,OAAM;MACL,cAAY,EAAA;MACZ,iBAAe,EAAA,CAAA;MACf,iBAAe,EAAA,CAAA;MACf,SAAO;SAER,EASO,EAAA,QAAA,aAAA,EAPJ,aAAc,EAAA,CAAA,EAAa,SAOvB,CALL,EAIE,EAAA,EAAA,GAJF,EACU,EAGR,CAAA,GAHwB;MACvB,MAAM;MACP,eAAY;;KAMVA,EAAAA,OAAM,mBAAA,EAAA,GADd,EAQM,OARN,IAQM,CAJJ,EAGE,EAAA,QAAA,gBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAIrB,EAKM,OALN,IAKM,CAJJ,EAGE,EAAA,QAAA,UAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA;;IAMd,EAAA,qBAAA,EAAA,GADT,EAoDQ,SAAA;;KAlDL,IAAI,EAAA,CAAA;KACL,OAAM;KACL,cAAY,EAAA;;KAGLA,EAAAA,OAAM,qBAAA,EAAA,GADd,EAQM,OARN,IAQM,CAJJ,EAGE,EAAA,QAAA,kBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;KAIrB,EAKM,OALN,IAKM,CAJJ,EAGE,EAAA,QAAA,WAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA;KAKbA,EAAAA,OAAM,qBAAsB,EAAA,SAAA,EAAA,GADpC,EA4BM,OA5BN,IA4BM,CAxBJ,EAGE,EAAA,QAAA,kBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,GAIX,EAAA,SAAA,EAAA,GADR,EAkBS,UAAA;;MAhBP,MAAK;MACL,OAAM;MACL,cAAY,EAAA,CAAA,IAAc,EAAA,cAAc,EAAA;MACxC,iBAAa,CAAG,EAAA,CAAA;MAChB,iBAAe,EAAA,CAAA;MACf,SAAO;SAER,EAQO,EAAA,QAAA,iBAAA,EANJ,WAAW,EAAA,MAAkB,SAMzB,CAJL,EAGE,EAAA,EAAA,GAHF,EACU,EAER,CAAA,GAFwB,EACxB,eAAY,OAAM,CAAA,GAAA,MAAA,EAAA,CAAA,CAAA,CAAA,GAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;IAO5B,EAOO,QAPP,IAOO,CANL,EAKE,EAAA,QAAA,WAAA;KAJC,QAAQ,EAAA;KACR,WAAW,EAAA;KACX,WAAW,EAAA,CAAA;KACO;;IAIvB,EA4Da,GAAA,EA5DD,MAAK,mBAAkB,GAAA;uBAEzB,EAAA,SAAY,EAAA,CAAA,KAAa,CAAK,EAAA,CAAA,KAAA,EAAA,GADtC,EA0DM,OA1DN,IA0DM,CAtDJ,EAIE,OAAA;MAHA,OAAM;MACN,eAAY;MACX,SAAO;SAEV,EAgDQ,SAAA;MA/CL,IAAI,EAAA,CAAA;eACD;MAAJ,KAAI;MACJ,OAAM;MACN,MAAK;MACL,cAAW;MACV,cAAY,EAAA;MACb,UAAS;MACC;SAEV,EASM,OATN,IASM,CARJ,EAOS,UAAA;MANP,MAAK;MACL,OAAM;MACL,cAAY,EAAA;MACZ,SAAO;SAER,EAAuC,EAAA,EAAA,GAAA,EAAA,EAApB,EAAA,CAAA,CAAgB,CAAA,GAAA,MAAA,EAAA,CAAA,GAAA,GAAA,EAAA,CAAA,CAAA,GAGvC,EA2BM,OA3BN,IA2BM;MAzBIA,EAAAA,OAAM,qBAAA,EAAA,GADd,EAQM,OARN,IAQM,CAJJ,EAGE,EAAA,QAAA,kBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;MAIrB,EAKM,OALN,IAKM,CAJJ,EAGE,EAAA,QAAA,WAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA;MAKbA,EAAAA,OAAM,qBAAA,EAAA,GADd,EAQM,OARN,IAQM,CAJJ,EAGE,EAAA,QAAA,kBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA"}
1
+ {"version":3,"file":"TAppShell.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TAppShell.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n createId,\n focusFirst,\n focusLast,\n getFocusableElements,\n isEscapeKey,\n} from '@treeui/utils';\nimport { getTreeIcon, treeIconDefaults } from '@treeui/icons';\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSidebarSide } from './TSidebar.vue';\nimport { treeSidebarInjectionKey } from './sidebar';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\nconst MenuIcon = computed(() => getTreeIcon('menu'));\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n side?: TSidebarSide;\n sidebarWidth?: string;\n collapsedWidth?: string;\n collapsible?: boolean;\n collapsed?: boolean;\n defaultCollapsed?: boolean;\n mobile?: boolean;\n breakpoint?: string;\n sidebarOpen?: boolean;\n defaultSidebarOpen?: boolean;\n /**\n * Hide the shell chrome (header and sidebar) so the content fills the\n * viewport. The default slot stays mounted across the toggle.\n */\n immersive?: boolean;\n defaultImmersive?: boolean;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showMenuButton?: boolean;\n /** Render the built-in collapse toggle in the sidebar footer (desktop). */\n showCollapseButton?: boolean;\n menuLabel?: string;\n closeLabel?: string;\n sidebarLabel?: string;\n collapseLabel?: string;\n expandLabel?: string;\n }>(),\n {\n as: 'div',\n side: 'left',\n sidebarWidth: '17.5rem',\n collapsedWidth: '4.75rem',\n collapsible: false,\n collapsed: undefined,\n defaultCollapsed: false,\n mobile: undefined,\n breakpoint: '768px',\n sidebarOpen: undefined,\n defaultSidebarOpen: false,\n immersive: undefined,\n defaultImmersive: false,\n closeOnEscape: true,\n closeOnOverlay: true,\n showMenuButton: true,\n showCollapseButton: true,\n menuLabel: 'Open menu',\n closeLabel: 'Close menu',\n sidebarLabel: 'Sidebar',\n collapseLabel: 'Collapse sidebar',\n expandLabel: 'Expand sidebar',\n },\n);\n\nconst emit = defineEmits<{\n 'update:collapsed': [value: boolean];\n 'collapse-change': [value: boolean];\n 'update:sidebarOpen': [value: boolean];\n 'sidebar-open-change': [value: boolean];\n 'update:immersive': [value: boolean];\n 'immersive-change': [value: boolean];\n}>();\n\nexport interface AppShellSlotProps {\n mobile: boolean;\n collapsed: boolean;\n sidebarOpen: boolean;\n immersive: boolean;\n toggleSidebar: () => void;\n closeSidebar: () => void;\n toggleCollapsed: () => void;\n toggleImmersive: () => void;\n}\n\ndefineSlots<{\n header?: (props: AppShellSlotProps) => unknown;\n /** Header region over the sidebar rail; the `header` slot then aligns with the content panel. */\n 'header-start'?: (props: AppShellSlotProps) => unknown;\n /** Trailing header region, pinned to the far end of the row (actions, controls). */\n 'header-end'?: (props: AppShellSlotProps) => unknown;\n /** Pinned above the sidebar body, inset to line up with nav item icons. */\n 'sidebar-header'?: (props: AppShellSlotProps) => unknown;\n sidebar?: (props: AppShellSlotProps) => unknown;\n /** Pinned to the bottom of the sidebar, inset to line up with nav item icons. */\n 'sidebar-footer'?: (props: AppShellSlotProps) => unknown;\n /**\n * Immersive hides the chrome, so the content is the only place an exit\n * control can live — `immersive` and `toggleImmersive` are passed through.\n */\n default?: (\n props: Pick<AppShellSlotProps, 'mobile' | 'collapsed' | 'immersive' | 'toggleImmersive'>,\n ) => unknown;\n 'menu-icon'?: (props: { sidebarOpen: boolean }) => unknown;\n 'collapse-icon'?: (props: { collapsed: boolean }) => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst sidebarId = createId('t-app-shell-sidebar');\n\nconst { value: isCollapsed, setValue: setCollapsed } = useControllableOpen(\n toRef(props, 'collapsed'),\n props.defaultCollapsed,\n (value) => {\n emit('update:collapsed', value);\n emit('collapse-change', value);\n },\n);\n\nconst { value: isSidebarOpen, setValue: setSidebarOpen } = useControllableOpen(\n toRef(props, 'sidebarOpen'),\n props.defaultSidebarOpen,\n (value) => {\n emit('update:sidebarOpen', value);\n emit('sidebar-open-change', value);\n },\n);\n\nconst { value: isImmersive, setValue: setImmersive } = useControllableOpen(\n toRef(props, 'immersive'),\n props.defaultImmersive,\n (value) => {\n emit('update:immersive', value);\n emit('immersive-change', value);\n },\n);\n\nconst toggleImmersive = () => {\n setImmersive(!isImmersive.value);\n};\n\n// Auto responsive detection when `mobile` is not explicitly controlled.\nconst autoMobile = ref(false);\nlet mediaQuery: MediaQueryList | null = null;\n\nconst onMediaChange = (event: MediaQueryListEvent | MediaQueryList) => {\n autoMobile.value = event.matches;\n};\n\nconst setupMediaQuery = () => {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return;\n }\n\n teardownMediaQuery();\n mediaQuery = window.matchMedia(`(max-width: ${props.breakpoint})`);\n autoMobile.value = mediaQuery.matches;\n mediaQuery.addEventListener?.('change', onMediaChange);\n};\n\nconst teardownMediaQuery = () => {\n mediaQuery?.removeEventListener?.('change', onMediaChange);\n mediaQuery = null;\n};\n\nconst isMobile = computed(() => props.mobile ?? autoMobile.value);\n\n// Collapsing is desktop-only, so the built-in toggle follows the same rule.\nconst showCollapseToggle = computed(\n () => !isMobile.value && props.collapsible && props.showCollapseButton,\n);\n\n// Collapse is a desktop-only concept; the mobile drawer always shows the\n// expanded sidebar, so descendants and slots see `collapsed: false` there.\nconst effectiveCollapsed = computed(() =>\n isMobile.value ? false : isCollapsed.value,\n);\n\n// The glyph points the way the rail will move: collapsing a left sidebar folds\n// it left, expanding it pushes right (mirrored for a right-anchored sidebar).\nconst CollapseIcon = computed(() => {\n const pointsStart = props.side === 'right' ? effectiveCollapsed.value : !effectiveCollapsed.value;\n return getTreeIcon(pointsStart ? 'panel-left' : 'panel-right');\n});\n\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nlet previousBodyOverflow = '';\nlet bodyLocked = false;\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined' || bodyLocked) {\n return;\n }\n\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n bodyLocked = true;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || !bodyLocked) {\n return;\n }\n\n document.body.style.overflow = previousBodyOverflow;\n bodyLocked = false;\n};\n\nconst focusSurface = () => {\n nextTick(() => {\n if (!surfaceRef.value) {\n return;\n }\n\n const focused = focusFirst(surfaceRef.value);\n if (!focused) {\n surfaceRef.value.focus();\n }\n });\n};\n\nconst openSidebar = () => {\n previousFocusedElement.value =\n typeof document === 'undefined'\n ? null\n : (document.activeElement as HTMLElement | null);\n setSidebarOpen(true);\n};\n\nconst closeSidebar = () => {\n setSidebarOpen(false);\n};\n\nconst toggleSidebar = () => {\n if (isSidebarOpen.value) {\n closeSidebar();\n } else {\n openSidebar();\n }\n};\n\nconst toggleCollapsed = () => {\n if (!props.collapsible) {\n return;\n }\n\n setCollapsed(!isCollapsed.value);\n};\n\nconst onOverlayClick = () => {\n if (props.closeOnOverlay) {\n closeSidebar();\n }\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeSidebar();\n return;\n }\n\n if (event.key !== 'Tab' || !surfaceRef.value) {\n return;\n }\n\n const focusable = getFocusableElements(surfaceRef.value);\n\n if (!focusable.length) {\n event.preventDefault();\n surfaceRef.value.focus();\n return;\n }\n\n const first = focusable[0];\n const last = focusable[focusable.length - 1];\n const activeElement = document.activeElement as HTMLElement | null;\n\n if (event.shiftKey && activeElement === first) {\n event.preventDefault();\n focusLast(surfaceRef.value);\n }\n\n if (!event.shiftKey && activeElement === last) {\n event.preventDefault();\n focusFirst(surfaceRef.value);\n }\n};\n\n// The off-canvas drawer only exists in mobile mode; keep body-scroll lock and\n// focus handling in sync with both the open flag and the responsive mode.\nconst syncOverlayState = (open: boolean, wasOpen: boolean) => {\n if (open && isMobile.value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (wasOpen) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n};\n\nwatch(isSidebarOpen, (value, previousValue) => {\n syncOverlayState(value, Boolean(previousValue));\n});\n\n// Entering immersive removes the drawer from the DOM without changing\n// `sidebarOpen`, so the sidebarOpen watcher never fires and would leave the\n// body scroll-locked with focus stranded on an unmounted surface. Release and\n// re-arm here, mirroring the responsive-mode watcher below.\nwatch(isImmersive, (immersive) => {\n if (!isSidebarOpen.value || !isMobile.value) {\n return;\n }\n\n if (immersive) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n } else {\n lockBodyScroll();\n focusSurface();\n }\n});\n\nwatch(isMobile, (mobile) => {\n if (!isSidebarOpen.value) {\n return;\n }\n\n // Leaving mobile removes the drawer from the DOM, so release the lock and\n // restore focus; re-entering mobile while \"open\" re-arms the overlay.\n if (mobile) {\n lockBodyScroll();\n focusSurface();\n } else {\n unlockBodyScroll();\n }\n});\n\nwatch(\n () => props.breakpoint,\n () => {\n if (typeof window !== 'undefined') {\n setupMediaQuery();\n }\n },\n);\n\nonMounted(() => {\n setupMediaQuery();\n});\n\nonBeforeUnmount(() => {\n teardownMediaQuery();\n unlockBodyScroll();\n});\n\nprovide(treeSidebarInjectionKey, {\n collapsed: effectiveCollapsed,\n});\n\nconst rootClasses = computed(() => [\n 't-app-shell',\n `t-app-shell--${props.side}`,\n {\n 'is-mobile': isMobile.value,\n 'is-collapsed':\n !isMobile.value && props.collapsible && isCollapsed.value,\n 'is-sidebar-open': isMobile.value && isSidebarOpen.value,\n 'is-immersive': isImmersive.value,\n },\n attrs.class,\n]);\n\nconst rootStyle = computed(() => [\n {\n '--tree-app-shell-sidebar-width': props.sidebarWidth,\n '--tree-app-shell-collapsed-width': props.collapsedWidth,\n },\n attrs.style,\n]);\n\nconst rootAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst slotProps = computed<AppShellSlotProps>(() => ({\n mobile: isMobile.value,\n collapsed: effectiveCollapsed.value,\n sidebarOpen: isSidebarOpen.value,\n immersive: isImmersive.value,\n toggleSidebar,\n closeSidebar,\n toggleCollapsed,\n toggleImmersive,\n}));\n</script>\n\n<template>\n <component\n :is=\"as\"\n v-bind=\"rootAttrs\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-mobile=\"isMobile ? 'true' : 'false'\"\n >\n <header\n class=\"t-app-shell__header\"\n :class=\"{\n 'has-start': Boolean($slots['header-start']),\n 'has-end': Boolean($slots['header-end']),\n }\"\n >\n <button\n v-if=\"isMobile && showMenuButton\"\n type=\"button\"\n class=\"t-app-shell__menu-button\"\n :aria-label=\"menuLabel\"\n :aria-expanded=\"isSidebarOpen\"\n :aria-controls=\"sidebarId\"\n @click=\"toggleSidebar\"\n >\n <slot\n name=\"menu-icon\"\n :sidebar-open=\"isSidebarOpen\"\n >\n <MenuIcon\n v-bind=\"treeIconDefaults\"\n :size=\"24\"\n aria-hidden=\"true\"\n />\n </slot>\n </button>\n\n <div\n v-if=\"$slots['header-start']\"\n class=\"t-app-shell__header-start\"\n >\n <slot\n name=\"header-start\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__header-content\">\n <slot\n name=\"header\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div\n v-if=\"$slots['header-end']\"\n class=\"t-app-shell__header-end\"\n >\n <slot\n name=\"header-end\"\n v-bind=\"slotProps\"\n />\n </div>\n </header>\n\n <aside\n v-if=\"!isMobile\"\n :id=\"sidebarId\"\n class=\"t-app-shell__sidebar\"\n :aria-label=\"sidebarLabel\"\n >\n <div\n v-if=\"$slots['sidebar-header']\"\n class=\"t-app-shell__sidebar-header\"\n >\n <slot\n name=\"sidebar-header\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__sidebar-body\">\n <slot\n name=\"sidebar\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div\n v-if=\"$slots['sidebar-footer'] || showCollapseToggle\"\n class=\"t-app-shell__sidebar-footer\"\n >\n <slot\n name=\"sidebar-footer\"\n v-bind=\"slotProps\"\n />\n\n <button\n v-if=\"showCollapseToggle\"\n type=\"button\"\n class=\"t-app-shell__collapse-button\"\n :aria-label=\"isCollapsed ? expandLabel : collapseLabel\"\n :aria-expanded=\"!isCollapsed\"\n :aria-controls=\"sidebarId\"\n @click=\"toggleCollapsed\"\n >\n <slot\n name=\"collapse-icon\"\n :collapsed=\"effectiveCollapsed\"\n >\n <CollapseIcon\n v-bind=\"treeIconDefaults\"\n aria-hidden=\"true\"\n />\n </slot>\n </button>\n </div>\n </aside>\n\n <main class=\"t-app-shell__main\">\n <slot\n :mobile=\"isMobile\"\n :collapsed=\"effectiveCollapsed\"\n :immersive=\"isImmersive\"\n :toggle-immersive=\"toggleImmersive\"\n />\n </main>\n\n <transition name=\"t-app-shell-fade\">\n <div\n v-if=\"isMobile && isSidebarOpen && !isImmersive\"\n class=\"t-app-shell__overlay\"\n >\n <div\n class=\"t-app-shell__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <aside\n :id=\"sidebarId\"\n ref=\"surfaceRef\"\n class=\"t-app-shell__drawer\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-label=\"sidebarLabel\"\n tabindex=\"-1\"\n @keydown=\"onKeydown\"\n >\n <div class=\"t-app-shell__drawer-topbar\">\n <button\n type=\"button\"\n class=\"t-app-shell__drawer-close\"\n :aria-label=\"closeLabel\"\n @click=\"closeSidebar\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n <div class=\"t-app-shell__drawer-body\">\n <div\n v-if=\"$slots['sidebar-header']\"\n class=\"t-app-shell__sidebar-header\"\n >\n <slot\n name=\"sidebar-header\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div class=\"t-app-shell__sidebar-body\">\n <slot\n name=\"sidebar\"\n v-bind=\"slotProps\"\n />\n </div>\n\n <div\n v-if=\"$slots['sidebar-footer']\"\n class=\"t-app-shell__sidebar-footer\"\n >\n <slot\n name=\"sidebar-footer\"\n v-bind=\"slotProps\"\n />\n </div>\n </div>\n </aside>\n </div>\n </transition>\n </component>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TButton.cjs","names":[],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TButton.cjs","names":[],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs, watchEffect } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\n// Left as a runtime reference (see vue vite.config `define`) so the consumer's\n// bundler — not TreeUI's build — decides dev vs prod. `typeof` guards raw ESM\n// where `process` is absent; the check tree-shakes out of production bundles.\nconst isDevEnv = (): boolean =>\n typeof process !== 'undefined' && process.env != null && process.env.NODE_ENV !== 'production';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// An icon-only button has no visible text and an aria-hidden icon, so without a\n// name it is unlabelled for assistive tech. Warn in development only; production\n// stays silent (and the check is stripped by the consumer's bundler).\nif (isDevEnv()) {\n watchEffect(() => {\n if (\n props.iconOnly &&\n !props.label &&\n !attrs['aria-label'] &&\n !attrs['aria-labelledby']\n ) {\n console.warn(\n '[TButton] `iconOnly` needs an accessible name — pass the `label` prop (or `aria-label`).',\n );\n }\n });\n}\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"TButton.js","names":[],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TButton.js","names":[],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs, watchEffect } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\n// Left as a runtime reference (see vue vite.config `define`) so the consumer's\n// bundler — not TreeUI's build — decides dev vs prod. `typeof` guards raw ESM\n// where `process` is absent; the check tree-shakes out of production bundles.\nconst isDevEnv = (): boolean =>\n typeof process !== 'undefined' && process.env != null && process.env.NODE_ENV !== 'production';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// An icon-only button has no visible text and an aria-hidden icon, so without a\n// name it is unlabelled for assistive tech. Warn in development only; production\n// stays silent (and the check is stripped by the consumer's bundler).\nif (isDevEnv()) {\n watchEffect(() => {\n if (\n props.iconOnly &&\n !props.label &&\n !attrs['aria-label'] &&\n !attrs['aria-labelledby']\n ) {\n console.warn(\n '[TButton] `iconOnly` needs an accessible name — pass the `label` prop (or `aria-label`).',\n );\n }\n });\n}\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"TButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/TButton.vue"],"names":[],"mappings":"AAoJA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG1D,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC,CAAC;AA2FJ,iBAAS,cAAc;WAiFT,OAAO,IAA6B;;sBAXvB,GAAG;yBACA,GAAG;;;;EAehC;AAgBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;UAvMV,QAAQ,GAAG,QAAQ,GAAG,OAAO;cAnBzB,OAAO;UADX,KAAK;WAmBJ,MAAM;aApBJ,QAAQ,GAAG,OAAO;QADvB,MAAM;aAID,OAAO;kBAKF,MAAM;0BAKE,OAAO;cAKnB,OAAO;WAKV,OAAO;WAEP,OAAO,GAAG,QAAQ,GAAG,KAAK;6EA4MpC,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"TButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/TButton.vue"],"names":[],"mappings":"AA6KA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAS1D,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CACpC,CAAC;AA8GJ,iBAAS,cAAc;WAiFT,OAAO,IAA6B;;sBAXvB,GAAG;yBACA,GAAG;;;;EAehC;AAgBD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;UA1NV,QAAQ,GAAG,QAAQ,GAAG,OAAO;cAnBzB,OAAO;UADX,KAAK;WAmBJ,MAAM;aApBJ,QAAQ,GAAG,OAAO;QADvB,MAAM;aAID,OAAO;kBAKF,MAAM;0BAKE,OAAO;cAKnB,OAAO;WAKV,OAAO;WAEP,OAAO,GAAG,QAAQ,GAAG,KAAK;6EA+NpC,CAAC;wBACkB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAAnG,wBAAoG;AAapG,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1,2 +1,2 @@
1
- const e=require("./TSpinner.cjs");let t=require("vue"),n=require("@treeui/utils");var r={key:0,class:`t-button__spinner`},i={key:1,class:`t-button__icon`,"aria-hidden":`true`},a={key:2,class:`t-button__label`},o=(0,t.defineComponent)({__name:`TButton`,props:{as:{default:`button`},variant:{default:`solid`},size:{default:`md`},disabled:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},loadingLabel:{default:`Loading`},hideIconWhileLoading:{type:Boolean,default:!0},iconOnly:{type:Boolean,default:!1},label:{default:void 0},type:{default:`button`},block:{type:Boolean,default:!1},align:{default:`center`}},emits:[`click`],setup(o,{emit:s}){let c=o,l=s,u=(0,n.tv)({base:`t-button`,variants:{variant:{solid:`t-button--solid`,outline:`t-button--outline`,ghost:`t-button--ghost`,soft:`t-button--soft`,danger:`t-button--danger`,brand:`t-button--brand`},size:{sm:`t-button--sm`,md:`t-button--md`,lg:`t-button--lg`}}}),d=(0,t.computed)(()=>c.as===`button`),f=(0,t.computed)(()=>c.disabled||c.loading),p=(0,t.computed)(()=>c.loading&&c.hideIconWhileLoading),m=(0,t.computed)(()=>u({variant:c.variant,size:c.size,class:{"is-loading":c.loading,"is-disabled":f.value,"t-button--block":c.block,"t-button--icon":c.iconOnly,"t-button--align-start":c.align===`start`,"t-button--align-end":c.align===`end`}})),h=e=>{if(f.value){e.preventDefault(),e.stopPropagation();return}l(`click`,e)};return(n,s)=>((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(o.as),{type:d.value?o.type:void 0,class:(0,t.normalizeClass)(m.value),disabled:d.value?f.value:void 0,"aria-disabled":!d.value&&f.value?`true`:void 0,"aria-busy":o.loading||void 0,"aria-label":o.label,tabindex:!d.value&&f.value?-1:void 0,onClick:h},{default:(0,t.withCtx)(()=>[o.loading?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,r,[(0,t.createVNode)(e.default,{size:`sm`,label:o.loadingLabel},null,8,[`label`])])):(0,t.createCommentVNode)(``,!0),n.$slots.icon&&!p.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,[(0,t.renderSlot)(n.$slots,`icon`)])):(0,t.createCommentVNode)(``,!0),o.iconOnly?(0,t.createCommentVNode)(``,!0):((0,t.openBlock)(),(0,t.createElementBlock)(`span`,a,[(0,t.renderSlot)(n.$slots,`default`)]))]),_:3},8,[`type`,`class`,`disabled`,`aria-disabled`,`aria-busy`,`aria-label`,`tabindex`]))}});exports.default=o;
1
+ const e=require("./TSpinner.cjs");let t=require("vue"),n=require("@treeui/utils");var r={key:0,class:`t-button__spinner`},i={key:1,class:`t-button__icon`,"aria-hidden":`true`},a={key:2,class:`t-button__label`},o=(0,t.defineComponent)({__name:`TButton`,props:{as:{default:`button`},variant:{default:`solid`},size:{default:`md`},disabled:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},loadingLabel:{default:`Loading`},hideIconWhileLoading:{type:Boolean,default:!0},iconOnly:{type:Boolean,default:!1},label:{default:void 0},type:{default:`button`},block:{type:Boolean,default:!1},align:{default:`center`}},emits:[`click`],setup(o,{emit:s}){let c=()=>typeof process<`u`&&process.env!=null&&process.env.NODE_ENV!==`production`,l=o,u=s,d=(0,n.tv)({base:`t-button`,variants:{variant:{solid:`t-button--solid`,outline:`t-button--outline`,ghost:`t-button--ghost`,soft:`t-button--soft`,danger:`t-button--danger`,brand:`t-button--brand`},size:{sm:`t-button--sm`,md:`t-button--md`,lg:`t-button--lg`}}}),f=(0,t.useAttrs)(),p=(0,t.computed)(()=>l.as===`button`),m=(0,t.computed)(()=>l.disabled||l.loading);c()&&(0,t.watchEffect)(()=>{l.iconOnly&&!l.label&&!f[`aria-label`]&&!f[`aria-labelledby`]&&console.warn("[TButton] `iconOnly` needs an accessible name — pass the `label` prop (or `aria-label`).")});let h=(0,t.computed)(()=>l.loading&&l.hideIconWhileLoading),g=(0,t.computed)(()=>d({variant:l.variant,size:l.size,class:{"is-loading":l.loading,"is-disabled":m.value,"t-button--block":l.block,"t-button--icon":l.iconOnly,"t-button--align-start":l.align===`start`,"t-button--align-end":l.align===`end`}})),_=e=>{if(m.value){e.preventDefault(),e.stopPropagation();return}u(`click`,e)};return(n,s)=>((0,t.openBlock)(),(0,t.createBlock)((0,t.resolveDynamicComponent)(o.as),{type:p.value?o.type:void 0,class:(0,t.normalizeClass)(g.value),disabled:p.value?m.value:void 0,"aria-disabled":!p.value&&m.value?`true`:void 0,"aria-busy":o.loading||void 0,"aria-label":o.label,tabindex:!p.value&&m.value?-1:void 0,onClick:_},{default:(0,t.withCtx)(()=>[o.loading?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,r,[(0,t.createVNode)(e.default,{size:`sm`,label:o.loadingLabel},null,8,[`label`])])):(0,t.createCommentVNode)(``,!0),n.$slots.icon&&!h.value?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,[(0,t.renderSlot)(n.$slots,`icon`)])):(0,t.createCommentVNode)(``,!0),o.iconOnly?(0,t.createCommentVNode)(``,!0):((0,t.openBlock)(),(0,t.createElementBlock)(`span`,a,[(0,t.renderSlot)(n.$slots,`default`)]))]),_:3},8,[`type`,`class`,`disabled`,`aria-disabled`,`aria-busy`,`aria-label`,`tabindex`]))}});exports.default=o;
2
2
  //# sourceMappingURL=TButton.vue_vue_type_script_setup_true_lang.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TButton.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":"0oBAMA,IAAM,EAAQ,EA8CR,EAAO,EAIP,GAAA,EAAA,EAAA,GAAA,CAAiB,CACrB,KAAM,WACN,SAAU,CACR,QAAS,CACP,MAAO,kBACP,QAAS,oBACT,MAAO,kBACP,KAAM,iBACN,OAAQ,mBACR,MAAO,iBACT,EACA,KAAM,CACJ,GAAI,eACJ,GAAI,eACJ,GAAI,cACN,CACF,CACF,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAAgC,EAAM,KAAO,QAAQ,EACrD,GAAA,EAAA,EAAA,SAAA,KAA4B,EAAM,UAAY,EAAM,OAAO,EAI3D,GAAA,EAAA,EAAA,SAAA,KAA8B,EAAM,SAAW,EAAM,oBAAoB,EAEzE,GAAA,EAAA,EAAA,SAAA,KACJ,EAAY,CACV,QAAS,EAAM,QACf,KAAM,EAAM,KACZ,MAAO,CACL,aAAc,EAAM,QACpB,cAAe,EAAW,MAC1B,kBAAmB,EAAM,MACzB,iBAAkB,EAAM,SACxB,wBAAyB,EAAM,QAAU,QACzC,sBAAuB,EAAM,QAAU,KACzC,CACF,CAAC,CACH,EAEM,EAAW,GAAsB,CACrC,GAAI,EAAW,MAAO,CACpB,EAAM,eAAe,EACrB,EAAM,gBAAgB,EACtB,MACF,CAEA,EAAK,QAAS,CAAK,CACrB,kFAKS,EAAA,EAAE,EAAA,CACN,KAAM,EAAA,MAAiB,EAAA,KAAO,IAAA,GAC9B,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAO,EACd,SAAU,EAAA,MAAiB,EAAA,MAAa,IAAA,GACxC,gBAAa,CAAG,EAAA,OAAkB,EAAA,MAAU,OAAY,IAAA,GACxD,YAAW,EAAA,SAAW,IAAA,GACtB,aAAY,EAAA,MACZ,SAAQ,CAAG,EAAA,OAAkB,EAAA,MAAU,GAAQ,IAAA,GACxC,sCAUD,CAPC,EAAA,UAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAOD,OARP,EAQO,EAAA,EAAA,EAAA,YAAA,CADH,EAAA,QAAA,CAFA,KAAK,KACJ,MAAO,EAAA,mEAIJA,EAAAA,OAAO,MAAI,CAAK,EAAA,QAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAKjB,OANP,EAMO,EAAA,EAAA,EAAA,WAAA,CADe,EAAA,OAAA,MAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,EAGb,EAAA,UAGC,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,IAHD,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIF,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADG,EAAA,OAAA,SAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"TButton.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, useAttrs, watchEffect } from 'vue';\nimport { tv } from '@treeui/utils';\nimport type { TSize, TVariant } from '../types/contracts';\nimport TSpinner from './TSpinner.vue';\n\n// Left as a runtime reference (see vue vite.config `define`) so the consumer's\n// bundler — not TreeUI's build — decides dev vs prod. `typeof` guards raw ESM\n// where `process` is absent; the check tree-shakes out of production bundles.\nconst isDevEnv = (): boolean =>\n typeof process !== 'undefined' && process.env != null && process.env.NODE_ENV !== 'production';\n\nconst props = withDefaults(\n defineProps<{\n as?: string;\n variant?: TVariant | 'brand';\n size?: TSize;\n disabled?: boolean;\n loading?: boolean;\n /**\n * Accessible announcement while `loading`, forwarded to the spinner.\n * The default is English; pass the active locale's string to localize it.\n */\n loadingLabel?: string;\n /**\n * While `loading`, hide the `icon` slot so the spinner replaces the icon\n * instead of rendering beside it. Set to `false` to keep both visible.\n */\n hideIconWhileLoading?: boolean;\n /**\n * Square, icon-only button. The visible label is dropped, so an accessible\n * name is required — pass `label` (or `aria-label`).\n */\n iconOnly?: boolean;\n /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */\n label?: string;\n type?: 'button' | 'submit' | 'reset';\n /** Stretch to the full width of the container. */\n block?: boolean;\n /** Content alignment — only meaningful together with `block`. */\n align?: 'start' | 'center' | 'end';\n }>(),\n {\n as: 'button',\n variant: 'solid',\n size: 'md',\n disabled: false,\n loading: false,\n loadingLabel: 'Loading',\n hideIconWhileLoading: true,\n iconOnly: false,\n label: undefined,\n type: 'button',\n block: false,\n align: 'center',\n },\n);\n\nconst emit = defineEmits<{\n click: [event: MouseEvent];\n}>();\n\nconst buttonClass = tv({\n base: 't-button',\n variants: {\n variant: {\n solid: 't-button--solid',\n outline: 't-button--outline',\n ghost: 't-button--ghost',\n soft: 't-button--soft',\n danger: 't-button--danger',\n brand: 't-button--brand',\n },\n size: {\n sm: 't-button--sm',\n md: 't-button--md',\n lg: 't-button--lg',\n },\n },\n});\n\nconst attrs = useAttrs();\nconst isNativeButton = computed(() => props.as === 'button');\nconst isDisabled = computed(() => props.disabled || props.loading);\n\n// An icon-only button has no visible text and an aria-hidden icon, so without a\n// name it is unlabelled for assistive tech. Warn in development only; production\n// stays silent (and the check is stripped by the consumer's bundler).\nif (isDevEnv()) {\n watchEffect(() => {\n if (\n props.iconOnly &&\n !props.label &&\n !attrs['aria-label'] &&\n !attrs['aria-labelledby']\n ) {\n console.warn(\n '[TButton] `iconOnly` needs an accessible name — pass the `label` prop (or `aria-label`).',\n );\n }\n });\n}\n\n// The spinner takes the icon's leading position, so rendering both would show\n// two glyphs and widen the button mid-action.\nconst isIconHidden = computed(() => props.loading && props.hideIconWhileLoading);\n\nconst classes = computed(() =>\n buttonClass({\n variant: props.variant,\n size: props.size,\n class: {\n 'is-loading': props.loading,\n 'is-disabled': isDisabled.value,\n 't-button--block': props.block,\n 't-button--icon': props.iconOnly,\n 't-button--align-start': props.align === 'start',\n 't-button--align-end': props.align === 'end',\n },\n }),\n);\n\nconst onClick = (event: MouseEvent) => {\n if (isDisabled.value) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n emit('click', event);\n};\n</script>\n\n<template>\n <component\n :is=\"as\"\n :type=\"isNativeButton ? type : undefined\"\n :class=\"classes\"\n :disabled=\"isNativeButton ? isDisabled : undefined\"\n :aria-disabled=\"!isNativeButton && isDisabled ? 'true' : undefined\"\n :aria-busy=\"loading || undefined\"\n :aria-label=\"label\"\n :tabindex=\"!isNativeButton && isDisabled ? -1 : undefined\"\n @click=\"onClick\"\n >\n <span\n v-if=\"loading\"\n class=\"t-button__spinner\"\n >\n <TSpinner\n size=\"sm\"\n :label=\"loadingLabel\"\n />\n </span>\n <span\n v-if=\"$slots.icon && !isIconHidden\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span\n v-if=\"!iconOnly\"\n class=\"t-button__label\"\n >\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":"0oBASA,IAAM,MACJ,OAAO,QAAY,KAAe,QAAQ,KAAO,MAAA,QAAA,IAAA,WAAiC,aAE9E,EAAQ,EA8CR,EAAO,EAIP,GAAA,EAAA,EAAA,GAAA,CAAiB,CACrB,KAAM,WACN,SAAU,CACR,QAAS,CACP,MAAO,kBACP,QAAS,oBACT,MAAO,kBACP,KAAM,iBACN,OAAQ,mBACR,MAAO,iBACT,EACA,KAAM,CACJ,GAAI,eACJ,GAAI,eACJ,GAAI,cACN,CACF,CACF,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,CAAiB,EACjB,GAAA,EAAA,EAAA,SAAA,KAAgC,EAAM,KAAO,QAAQ,EACrD,GAAA,EAAA,EAAA,SAAA,KAA4B,EAAM,UAAY,EAAM,OAAO,EAK7D,EAAS,IACX,EAAA,EAAA,YAAA,KAAkB,CAEd,EAAM,UACN,CAAC,EAAM,OACP,CAAC,EAAM,eACP,CAAC,EAAM,oBAEP,QAAQ,KACN,0FACF,CAEJ,CAAC,EAKH,IAAM,GAAA,EAAA,EAAA,SAAA,KAA8B,EAAM,SAAW,EAAM,oBAAoB,EAEzE,GAAA,EAAA,EAAA,SAAA,KACJ,EAAY,CACV,QAAS,EAAM,QACf,KAAM,EAAM,KACZ,MAAO,CACL,aAAc,EAAM,QACpB,cAAe,EAAW,MAC1B,kBAAmB,EAAM,MACzB,iBAAkB,EAAM,SACxB,wBAAyB,EAAM,QAAU,QACzC,sBAAuB,EAAM,QAAU,KACzC,CACF,CAAC,CACH,EAEM,EAAW,GAAsB,CACrC,GAAI,EAAW,MAAO,CACpB,EAAM,eAAe,EACrB,EAAM,gBAAgB,EACtB,MACF,CAEA,EAAK,QAAS,CAAK,CACrB,kFAKS,EAAA,EAAE,EAAA,CACN,KAAM,EAAA,MAAiB,EAAA,KAAO,IAAA,GAC9B,OAAA,EAAA,EAAA,eAAA,CAAO,EAAA,KAAO,EACd,SAAU,EAAA,MAAiB,EAAA,MAAa,IAAA,GACxC,gBAAa,CAAG,EAAA,OAAkB,EAAA,MAAU,OAAY,IAAA,GACxD,YAAW,EAAA,SAAW,IAAA,GACtB,aAAY,EAAA,MACZ,SAAQ,CAAG,EAAA,OAAkB,EAAA,MAAU,GAAQ,IAAA,GACxC,sCAUD,CAPC,EAAA,UAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAOD,OARP,EAQO,EAAA,EAAA,EAAA,YAAA,CADH,EAAA,QAAA,CAFA,KAAK,KACJ,MAAO,EAAA,mEAIJA,EAAAA,OAAO,MAAI,CAAK,EAAA,QAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAKjB,OANP,EAMO,EAAA,EAAA,EAAA,WAAA,CADe,EAAA,OAAA,MAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,EAGb,EAAA,UAGC,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,IAHD,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAIF,OALP,EAKO,EAAA,EAAA,EAAA,WAAA,CADG,EAAA,OAAA,SAAA,CAAA,CAAA"}
@@ -1,18 +1,18 @@
1
1
  import e from "./TSpinner.js";
2
- import { computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createVNode as a, defineComponent as o, normalizeClass as s, openBlock as c, renderSlot as l, resolveDynamicComponent as u, withCtx as d } from "vue";
3
- import { tv as f } from "@treeui/utils";
2
+ import { computed as t, createBlock as n, createCommentVNode as r, createElementBlock as i, createVNode as a, defineComponent as o, normalizeClass as s, openBlock as c, renderSlot as l, resolveDynamicComponent as u, useAttrs as d, watchEffect as f, withCtx as p } from "vue";
3
+ import { tv as m } from "@treeui/utils";
4
4
  //#region src/components/TButton.vue?vue&type=script&setup=true&lang.ts
5
- var p = {
5
+ var h = {
6
6
  key: 0,
7
7
  class: "t-button__spinner"
8
- }, m = {
8
+ }, g = {
9
9
  key: 1,
10
10
  class: "t-button__icon",
11
11
  "aria-hidden": "true"
12
- }, h = {
12
+ }, _ = {
13
13
  key: 2,
14
14
  class: "t-button__label"
15
- }, g = /*@__PURE__*/ o({
15
+ }, v = /*@__PURE__*/ o({
16
16
  __name: "TButton",
17
17
  props: {
18
18
  as: { default: "button" },
@@ -44,8 +44,8 @@ var p = {
44
44
  align: { default: "center" }
45
45
  },
46
46
  emits: ["click"],
47
- setup(o, { emit: g }) {
48
- let _ = o, v = g, y = f({
47
+ setup(o, { emit: v }) {
48
+ let y = () => typeof process < "u" && process.env != null && process.env.NODE_ENV !== "production", b = o, x = v, S = m({
49
49
  base: "t-button",
50
50
  variants: {
51
51
  variant: {
@@ -62,41 +62,45 @@ var p = {
62
62
  lg: "t-button--lg"
63
63
  }
64
64
  }
65
- }), b = t(() => _.as === "button"), x = t(() => _.disabled || _.loading), S = t(() => _.loading && _.hideIconWhileLoading), C = t(() => y({
66
- variant: _.variant,
67
- size: _.size,
65
+ }), C = d(), w = t(() => b.as === "button"), T = t(() => b.disabled || b.loading);
66
+ y() && f(() => {
67
+ b.iconOnly && !b.label && !C["aria-label"] && !C["aria-labelledby"] && console.warn("[TButton] `iconOnly` needs an accessible name — pass the `label` prop (or `aria-label`).");
68
+ });
69
+ let E = t(() => b.loading && b.hideIconWhileLoading), D = t(() => S({
70
+ variant: b.variant,
71
+ size: b.size,
68
72
  class: {
69
- "is-loading": _.loading,
70
- "is-disabled": x.value,
71
- "t-button--block": _.block,
72
- "t-button--icon": _.iconOnly,
73
- "t-button--align-start": _.align === "start",
74
- "t-button--align-end": _.align === "end"
73
+ "is-loading": b.loading,
74
+ "is-disabled": T.value,
75
+ "t-button--block": b.block,
76
+ "t-button--icon": b.iconOnly,
77
+ "t-button--align-start": b.align === "start",
78
+ "t-button--align-end": b.align === "end"
75
79
  }
76
- })), w = (e) => {
77
- if (x.value) {
80
+ })), O = (e) => {
81
+ if (T.value) {
78
82
  e.preventDefault(), e.stopPropagation();
79
83
  return;
80
84
  }
81
- v("click", e);
85
+ x("click", e);
82
86
  };
83
- return (t, f) => (c(), n(u(o.as), {
84
- type: b.value ? o.type : void 0,
85
- class: s(C.value),
86
- disabled: b.value ? x.value : void 0,
87
- "aria-disabled": !b.value && x.value ? "true" : void 0,
87
+ return (t, d) => (c(), n(u(o.as), {
88
+ type: w.value ? o.type : void 0,
89
+ class: s(D.value),
90
+ disabled: w.value ? T.value : void 0,
91
+ "aria-disabled": !w.value && T.value ? "true" : void 0,
88
92
  "aria-busy": o.loading || void 0,
89
93
  "aria-label": o.label,
90
- tabindex: !b.value && x.value ? -1 : void 0,
91
- onClick: w
94
+ tabindex: !w.value && T.value ? -1 : void 0,
95
+ onClick: O
92
96
  }, {
93
- default: d(() => [
94
- o.loading ? (c(), i("span", p, [a(e, {
97
+ default: p(() => [
98
+ o.loading ? (c(), i("span", h, [a(e, {
95
99
  size: "sm",
96
100
  label: o.loadingLabel
97
101
  }, null, 8, ["label"])])) : r("", !0),
98
- t.$slots.icon && !S.value ? (c(), i("span", m, [l(t.$slots, "icon")])) : r("", !0),
99
- o.iconOnly ? r("", !0) : (c(), i("span", h, [l(t.$slots, "default")]))
102
+ t.$slots.icon && !E.value ? (c(), i("span", g, [l(t.$slots, "icon")])) : r("", !0),
103
+ o.iconOnly ? r("", !0) : (c(), i("span", _, [l(t.$slots, "default")]))
100
104
  ]),
101
105
  _: 3
102
106
  }, 8, [
@@ -111,6 +115,6 @@ var p = {
111
115
  }
112
116
  });
113
117
  //#endregion
114
- export { g as default };
118
+ export { v as default };
115
119
 
116
120
  //# sourceMappingURL=TButton.vue_vue_type_script_setup_true_lang.js.map