@treeui/vue 0.18.0 → 0.19.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 (43) 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 +24 -2
  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 +96 -121
  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 +21 -0
  12. package/dist/components/TButton.vue.d.ts.map +1 -1
  13. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs +1 -1
  14. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  15. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js +47 -31
  16. package/dist/components/TButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/TLanguageSelect.vue.d.ts +1 -1
  18. package/dist/components/TLanguageSelect.vue.d.ts.map +1 -1
  19. package/dist/components/TTable.cjs.map +1 -1
  20. package/dist/components/TTable.js.map +1 -1
  21. package/dist/components/TTable.vue.d.ts +8 -2
  22. package/dist/components/TTable.vue.d.ts.map +1 -1
  23. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.cjs +1 -1
  24. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  25. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.js +71 -80
  26. package/dist/components/TTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  27. package/dist/components/TTag.cjs.map +1 -1
  28. package/dist/components/TTag.js.map +1 -1
  29. package/dist/components/TTag.vue.d.ts.map +1 -1
  30. package/dist/components/TTag.vue_vue_type_script_setup_true_lang.cjs +1 -1
  31. package/dist/components/TTag.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  32. package/dist/components/TTag.vue_vue_type_script_setup_true_lang.js +22 -29
  33. package/dist/components/TTag.vue_vue_type_script_setup_true_lang.js.map +1 -1
  34. package/dist/components/TText.cjs.map +1 -1
  35. package/dist/components/TText.js.map +1 -1
  36. package/dist/components/TText.vue.d.ts +7 -0
  37. package/dist/components/TText.vue.d.ts.map +1 -1
  38. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs +1 -1
  39. package/dist/components/TText.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  40. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js +8 -1
  41. package/dist/components/TText.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/style.css +1 -1
  43. package/package.json +3 -3
@@ -1,20 +1,20 @@
1
1
  import { useControllableOpen as e } from "../composables/useControllableOpen.js";
2
2
  import { treeSidebarInjectionKey as t } from "./sidebar.js";
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 ee, nextTick as d, normalizeClass as f, 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 oe, focusFirst as x, focusLast as se, getFocusableElements as ce, isEscapeKey as le } from "@treeui/utils";
5
- import { getTreeIcon as ue, treeIconDefaults as de } from "@treeui/icons";
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";
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
- var S = [
7
+ var le = [
8
8
  "aria-label",
9
9
  "aria-expanded",
10
10
  "aria-controls"
11
- ], C = {
11
+ ], ue = {
12
12
  key: 1,
13
13
  class: "t-app-shell__header-start"
14
- }, fe = { class: "t-app-shell__header-content" }, pe = ["id", "aria-label"], me = {
14
+ }, de = { class: "t-app-shell__header-content" }, fe = ["id", "aria-label"], pe = {
15
15
  key: 0,
16
16
  class: "t-app-shell__sidebar-header"
17
- }, he = { class: "t-app-shell__sidebar-body" }, w = {
17
+ }, me = { class: "t-app-shell__sidebar-body" }, he = {
18
18
  key: 1,
19
19
  class: "t-app-shell__sidebar-footer"
20
20
  }, ge = [
@@ -27,10 +27,10 @@ var S = [
27
27
  }, ye = ["id", "aria-label"], be = { class: "t-app-shell__drawer-topbar" }, xe = ["aria-label"], Se = { class: "t-app-shell__drawer-body" }, Ce = {
28
28
  key: 0,
29
29
  class: "t-app-shell__sidebar-header"
30
- }, we = { class: "t-app-shell__sidebar-body" }, T = {
30
+ }, we = { class: "t-app-shell__sidebar-body" }, Te = {
31
31
  key: 1,
32
32
  class: "t-app-shell__sidebar-footer"
33
- }, E = /*@__PURE__*/ l({
33
+ }, T = /*@__PURE__*/ l({
34
34
  inheritAttrs: !1,
35
35
  __name: "TAppShell",
36
36
  props: {
@@ -63,6 +63,14 @@ var S = [
63
63
  type: Boolean,
64
64
  default: !1
65
65
  },
66
+ immersive: {
67
+ type: Boolean,
68
+ default: void 0
69
+ },
70
+ defaultImmersive: {
71
+ type: Boolean,
72
+ default: !1
73
+ },
66
74
  closeOnEscape: {
67
75
  type: Boolean,
68
76
  default: !0
@@ -89,188 +97,155 @@ var S = [
89
97
  "update:collapsed",
90
98
  "collapse-change",
91
99
  "update:sidebarOpen",
92
- "sidebar-open-change"
100
+ "sidebar-open-change",
101
+ "update:immersive",
102
+ "immersive-change"
93
103
  ],
94
- setup(l, { emit: E }) {
95
- let D = r(() => ue("x")), O = l, k = E, A = ae(), j = oe("t-app-shell-sidebar"), { value: M, setValue: Te } = e(_(O, "collapsed"), O.defaultCollapsed, (e) => {
96
- k("update:collapsed", e), k("collapse-change", e);
97
- }), { value: N, setValue: P } = e(_(O, "sidebarOpen"), O.defaultSidebarOpen, (e) => {
98
- k("update:sidebarOpen", e), k("sidebar-open-change", e);
99
- }), F = h(!1), I = null, L = (e) => {
104
+ 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) => {
106
+ D("update:collapsed", e), D("collapse-change", e);
107
+ }), { value: j, setValue: M } = e(_(E, "sidebarOpen"), E.defaultSidebarOpen, (e) => {
108
+ D("update:sidebarOpen", e), D("sidebar-open-change", e);
109
+ }), { value: N, setValue: ke } = e(_(E, "immersive"), E.defaultImmersive, (e) => {
110
+ D("update:immersive", e), D("immersive-change", e);
111
+ }), P = () => {
112
+ ke(!N.value);
113
+ }, F = h(!1), I = null, L = (e) => {
100
114
  F.value = e.matches;
101
115
  }, R = () => {
102
- typeof window > "u" || typeof window.matchMedia != "function" || (z(), I = window.matchMedia(`(max-width: ${O.breakpoint})`), F.value = I.matches, I.addEventListener?.("change", L));
116
+ typeof window > "u" || typeof window.matchMedia != "function" || (z(), I = window.matchMedia(`(max-width: ${E.breakpoint})`), F.value = I.matches, I.addEventListener?.("change", L));
103
117
  }, z = () => {
104
118
  I?.removeEventListener?.("change", L), I = null;
105
- }, B = r(() => O.mobile ?? F.value), V = r(() => !B.value && O.collapsible && O.showCollapseButton), H = r(() => !B.value && M.value), U = h(null), W = h(null), G = "", K = !1, q = () => {
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 = () => {
106
120
  typeof document > "u" || K || (G = document.body.style.overflow, document.body.style.overflow = "hidden", K = !0);
107
121
  }, J = () => {
108
122
  typeof document > "u" || !K || (document.body.style.overflow = G, K = !1);
109
123
  }, Y = () => {
110
- d(() => {
111
- U.value && (x(U.value) || U.value.focus());
124
+ f(() => {
125
+ U.value && (S(U.value) || U.value.focus());
112
126
  });
113
- }, Ee = () => {
114
- W.value = typeof document > "u" ? null : document.activeElement, P(!0);
127
+ }, je = () => {
128
+ W.value = typeof document > "u" ? null : document.activeElement, M(!0);
115
129
  }, X = () => {
116
- P(!1);
130
+ M(!1);
117
131
  }, Z = () => {
118
- N.value ? X() : Ee();
132
+ j.value ? X() : je();
119
133
  }, Q = () => {
120
- O.collapsible && Te(!M.value);
121
- }, De = () => {
122
- O.closeOnOverlay && X();
123
- }, Oe = (e) => {
124
- if (le(e) && O.closeOnEscape) {
134
+ E.collapsible && Oe(!A.value);
135
+ }, Me = () => {
136
+ E.closeOnOverlay && X();
137
+ }, Ne = (e) => {
138
+ if (ce(e) && E.closeOnEscape) {
125
139
  e.preventDefault(), X();
126
140
  return;
127
141
  }
128
142
  if (e.key !== "Tab" || !U.value) return;
129
- let t = ce(U.value);
143
+ let t = se(U.value);
130
144
  if (!t.length) {
131
145
  e.preventDefault(), U.value.focus();
132
146
  return;
133
147
  }
134
148
  let n = t[0], r = t[t.length - 1], i = document.activeElement;
135
- e.shiftKey && i === n && (e.preventDefault(), se(U.value)), !e.shiftKey && i === r && (e.preventDefault(), x(U.value));
136
- }, ke = (e, t) => {
149
+ e.shiftKey && i === n && (e.preventDefault(), oe(U.value)), !e.shiftKey && i === r && (e.preventDefault(), S(U.value));
150
+ }, Pe = (e, t) => {
137
151
  if (e && B.value) {
138
152
  q(), Y();
139
153
  return;
140
154
  }
141
- t && (J(), d(() => {
155
+ t && (J(), f(() => {
142
156
  W.value?.focus();
143
157
  }));
144
158
  };
145
- y(N, (e, t) => {
146
- ke(e, !!t);
159
+ y(j, (e, t) => {
160
+ Pe(e, !!t);
147
161
  }), y(B, (e) => {
148
- N.value && (e ? (q(), Y()) : J());
149
- }), y(() => O.breakpoint, () => {
162
+ j.value && (e ? (q(), Y()) : J());
163
+ }), y(() => E.breakpoint, () => {
150
164
  typeof window < "u" && R();
151
165
  }), ne(() => {
152
166
  R();
153
167
  }), te(() => {
154
168
  z(), J();
155
169
  }), re(t, { collapsed: H });
156
- let Ae = r(() => [
170
+ let Fe = r(() => [
157
171
  "t-app-shell",
158
- `t-app-shell--${O.side}`,
172
+ `t-app-shell--${E.side}`,
159
173
  {
160
174
  "is-mobile": B.value,
161
- "is-collapsed": !B.value && O.collapsible && M.value,
162
- "is-sidebar-open": B.value && N.value
175
+ "is-collapsed": !B.value && E.collapsible && A.value,
176
+ "is-sidebar-open": B.value && j.value,
177
+ "is-immersive": N.value
163
178
  },
164
- A.class
165
- ]), je = r(() => [{
166
- "--tree-app-shell-sidebar-width": O.sidebarWidth,
167
- "--tree-app-shell-collapsed-width": O.collapsedWidth
168
- }, A.style]), Me = r(() => {
169
- let { class: e, style: t, ...n } = A;
179
+ O.class
180
+ ]), Ie = r(() => [{
181
+ "--tree-app-shell-sidebar-width": E.sidebarWidth,
182
+ "--tree-app-shell-collapsed-width": E.collapsedWidth
183
+ }, O.style]), Le = r(() => {
184
+ let { class: e, style: t, ...n } = O;
170
185
  return n;
171
186
  }), $ = r(() => ({
172
187
  mobile: B.value,
173
188
  collapsed: H.value,
174
- sidebarOpen: N.value,
189
+ sidebarOpen: j.value,
190
+ immersive: N.value,
175
191
  toggleSidebar: Z,
176
192
  closeSidebar: X,
177
- toggleCollapsed: Q
193
+ toggleCollapsed: Q,
194
+ toggleImmersive: P
178
195
  }));
179
- return (e, t) => (m(), i(ie(l.as), ee(Me.value, {
180
- class: Ae.value,
181
- style: je.value,
196
+ return (e, t) => (m(), i(ie(l.as), d(Le.value, {
197
+ class: Fe.value,
198
+ style: Ie.value,
182
199
  "data-mobile": B.value ? "true" : "false"
183
200
  }), {
184
201
  default: b(() => [
185
- s("header", { class: f(["t-app-shell__header", { "has-start": !!e.$slots["header-start"] }]) }, [
202
+ s("header", { class: ee(["t-app-shell__header", { "has-start": !!e.$slots["header-start"] }]) }, [
186
203
  B.value && l.showMenuButton ? (m(), o("button", {
187
204
  key: 0,
188
205
  type: "button",
189
206
  class: "t-app-shell__menu-button",
190
207
  "aria-label": l.menuLabel,
191
- "aria-expanded": v(N),
192
- "aria-controls": v(j),
208
+ "aria-expanded": v(j),
209
+ "aria-controls": v(k),
193
210
  onClick: Z
194
- }, [g(e.$slots, "menu-icon", { sidebarOpen: v(N) }, () => [t[0] ||= s("svg", {
195
- xmlns: "http://www.w3.org/2000/svg",
196
- width: "24",
197
- height: "24",
198
- viewBox: "0 0 24 24",
199
- fill: "none",
200
- stroke: "currentColor",
201
- "stroke-width": "2",
202
- "stroke-linecap": "round",
203
- "stroke-linejoin": "round",
211
+ }, [g(e.$slots, "menu-icon", { sidebarOpen: v(j) }, () => [c(v(De), d(v(w), {
212
+ size: 24,
204
213
  "aria-hidden": "true"
205
- }, [
206
- s("line", {
207
- x1: "4",
208
- x2: "20",
209
- y1: "6",
210
- y2: "6"
211
- }),
212
- s("line", {
213
- x1: "4",
214
- x2: "20",
215
- y1: "12",
216
- y2: "12"
217
- }),
218
- s("line", {
219
- x1: "4",
220
- x2: "20",
221
- y1: "18",
222
- y2: "18"
223
- })
224
- ], -1)])], 8, S)) : a("", !0),
225
- e.$slots["header-start"] ? (m(), o("div", C, [g(e.$slots, "header-start", p(u($.value)))])) : a("", !0),
226
- s("div", fe, [g(e.$slots, "header", p(u($.value)))])
214
+ }), null, 16)])], 8, le)) : a("", !0),
215
+ 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)))])
227
217
  ], 2),
228
218
  B.value ? a("", !0) : (m(), o("aside", {
229
219
  key: 0,
230
- id: v(j),
220
+ id: v(k),
231
221
  class: "t-app-shell__sidebar",
232
222
  "aria-label": l.sidebarLabel
233
223
  }, [
234
- e.$slots["sidebar-header"] ? (m(), o("div", me, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
235
- s("div", he, [g(e.$slots, "sidebar", p(u($.value)))]),
236
- e.$slots["sidebar-footer"] || V.value ? (m(), o("div", w, [g(e.$slots, "sidebar-footer", p(u($.value))), V.value ? (m(), o("button", {
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", {
237
227
  key: 0,
238
228
  type: "button",
239
229
  class: "t-app-shell__collapse-button",
240
- "aria-label": v(M) ? l.expandLabel : l.collapseLabel,
241
- "aria-expanded": !v(M),
242
- "aria-controls": v(j),
230
+ "aria-label": v(A) ? l.expandLabel : l.collapseLabel,
231
+ "aria-expanded": !v(A),
232
+ "aria-controls": v(k),
243
233
  onClick: Q
244
- }, [g(e.$slots, "collapse-icon", { collapsed: H.value }, () => [t[1] ||= s("svg", {
245
- xmlns: "http://www.w3.org/2000/svg",
246
- width: "20",
247
- height: "20",
248
- viewBox: "0 0 24 24",
249
- fill: "none",
250
- stroke: "currentColor",
251
- "stroke-width": "2",
252
- "stroke-linecap": "round",
253
- "stroke-linejoin": "round",
254
- "aria-hidden": "true"
255
- }, [s("rect", {
256
- x: "3",
257
- y: "3",
258
- width: "18",
259
- height: "18",
260
- rx: "2"
261
- }), s("path", { d: "M9 3v18" })], -1)])], 8, ge)) : a("", !0)])) : a("", !0)
262
- ], 8, pe)),
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)),
263
236
  s("main", _e, [g(e.$slots, "default", {
264
237
  mobile: B.value,
265
- collapsed: H.value
238
+ collapsed: H.value,
239
+ immersive: v(N),
240
+ toggleImmersive: P
266
241
  })]),
267
242
  c(n, { name: "t-app-shell-fade" }, {
268
- default: b(() => [B.value && v(N) ? (m(), o("div", ve, [s("div", {
243
+ default: b(() => [B.value && v(j) && !v(N) ? (m(), o("div", ve, [s("div", {
269
244
  class: "t-app-shell__backdrop",
270
245
  "aria-hidden": "true",
271
- onClick: De
246
+ onClick: Me
272
247
  }), s("aside", {
273
- id: v(j),
248
+ id: v(k),
274
249
  ref_key: "surfaceRef",
275
250
  ref: U,
276
251
  class: "t-app-shell__drawer",
@@ -278,16 +253,16 @@ var S = [
278
253
  "aria-modal": "true",
279
254
  "aria-label": l.sidebarLabel,
280
255
  tabindex: "-1",
281
- onKeydown: Oe
256
+ onKeydown: Ne
282
257
  }, [s("div", be, [s("button", {
283
258
  type: "button",
284
259
  class: "t-app-shell__drawer-close",
285
260
  "aria-label": l.closeLabel,
286
261
  onClick: X
287
- }, [c(v(D), p(u(v(de))), null, 16)], 8, xe)]), s("div", Se, [
262
+ }, [c(v(Ee), p(u(v(w))), null, 16)], 8, xe)]), s("div", Se, [
288
263
  e.$slots["sidebar-header"] ? (m(), o("div", Ce, [g(e.$slots, "sidebar-header", p(u($.value)))])) : a("", !0),
289
264
  s("div", we, [g(e.$slots, "sidebar", p(u($.value)))]),
290
- e.$slots["sidebar-footer"] ? (m(), o("div", T, [g(e.$slots, "sidebar-footer", p(u($.value)))])) : a("", !0)
265
+ e.$slots["sidebar-footer"] ? (m(), o("div", Te, [g(e.$slots, "sidebar-footer", p(u($.value)))])) : a("", !0)
291
266
  ])], 40, ye)])) : a("", !0)]),
292
267
  _: 3
293
268
  })
@@ -301,6 +276,6 @@ var S = [
301
276
  }
302
277
  });
303
278
  //#endregion
304
- export { E as default };
279
+ export { T as default };
305
280
 
306
281
  //# sourceMappingURL=TAppShell.vue_vue_type_script_setup_true_lang.js.map
@@ -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'));\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 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 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}>();\n\nexport interface AppShellSlotProps {\n mobile: boolean;\n collapsed: boolean;\n sidebarOpen: boolean;\n toggleSidebar: () => void;\n closeSidebar: () => void;\n toggleCollapsed: () => 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 default?: (props: Pick<AppShellSlotProps, 'mobile' | 'collapsed'>) => 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\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\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 },\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 toggleSidebar,\n closeSidebar,\n toggleCollapsed,\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 <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line\n x1=\"4\"\n x2=\"20\"\n y1=\"6\"\n y2=\"6\"\n />\n <line\n x1=\"4\"\n x2=\"20\"\n y1=\"12\"\n y2=\"12\"\n />\n <line\n x1=\"4\"\n x2=\"20\"\n y1=\"18\"\n y2=\"18\"\n />\n </svg>\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 <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <rect\n x=\"3\"\n y=\"3\"\n width=\"18\"\n height=\"18\"\n rx=\"2\"\n />\n <path d=\"M9 3v18\" />\n </svg>\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 />\n </main>\n\n <transition name=\"t-app-shell-fade\">\n <div\n v-if=\"isMobile && isSidebarOpen\"\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,IAAY,QAAe,GAAY,GAAG,CAAC,GAE3C,IAAQ,GAgDR,IAAO,GA8BP,IAAQ,GAAS,GACjB,IAAY,GAAS,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,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,GAEM,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;GACrD;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;GACA;GACA;EACF,EAAE;yBAIA,EAuNY,GAtNL,EAAA,EAAE,GADT,GAEU,GAqNE,OArNO;GAChB,OAAO,GAAA;GACP,OAAO,GAAA;GACP,eAAa,EAAA,QAAQ,SAAA;;oBAqEb;IAnET,EAmES,UAAA,EAlEP,OAAK,EAAA,CAAC,uBAAqB,EAAA,aACJ,EAAQA,EAAAA,OAAM,gBAAA,CAAA,CAAA,EAAA,GAAA;KAG7B,EAAA,SAAY,EAAA,kBAAA,EAAA,GADpB,EA6CS,UAAA;;MA3CP,MAAK;MACL,OAAM;MACL,cAAY,EAAA;MACZ,iBAAe,EAAA,CAAA;MACf,iBAAe,EAAA,CAAA;MACf,SAAO;SAER,EAmCO,EAAA,QAAA,aAAA,EAjCJ,aAAc,EAAA,CAAA,EAAa,SAiCvB,CAAA,AAAA,EAAA,OA/BL,EA8BM,OAAA;MA7BJ,OAAM;MACN,OAAM;MACN,QAAO;MACP,SAAQ;MACR,MAAK;MACL,QAAO;MACP,gBAAa;MACb,kBAAe;MACf,mBAAgB;MAChB,eAAY;;MAEZ,EAKE,QAAA;OAJA,IAAG;OACH,IAAG;OACH,IAAG;OACH,IAAG;;MAEL,EAKE,QAAA;OAJA,IAAG;OACH,IAAG;OACH,IAAG;OACH,IAAG;;MAEL,EAKE,QAAA;OAJA,IAAG;OACH,IAAG;OACH,IAAG;OACH,IAAG;;;KAOHA,EAAAA,OAAM,mBAAA,EAAA,GADd,EAQM,OARN,GAQM,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,EAqEQ,SAAA;;KAnEL,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,EA6CM,OA7CN,GA6CM,CAzCJ,EAGE,EAAA,QAAA,kBAAA,EAAA,EADQ,EAAA,KAAS,CAAA,CAAA,GAIX,EAAA,SAAA,EAAA,GADR,EAmCS,UAAA;;MAjCP,MAAK;MACL,OAAM;MACL,cAAY,EAAA,CAAA,IAAc,EAAA,cAAc,EAAA;MACxC,iBAAa,CAAG,EAAA,CAAA;MAChB,iBAAe,EAAA,CAAA;MACf,SAAO;SAER,EAyBO,EAAA,QAAA,iBAAA,EAvBJ,WAAW,EAAA,MAAkB,SAuBzB,CAAA,AAAA,EAAA,OArBL,EAoBM,OAAA;MAnBJ,OAAM;MACN,OAAM;MACN,QAAO;MACP,SAAQ;MACR,MAAK;MACL,QAAO;MACP,gBAAa;MACb,kBAAe;MACf,mBAAgB;MAChB,eAAY;SAEZ,EAME,QAAA;MALA,GAAE;MACF,GAAE;MACF,OAAM;MACN,QAAO;MACP,IAAG;SAEL,EAAoB,QAAA,EAAd,GAAE,UAAS,CAAA,CAAA,GAAA,EAAA,CAAA,CAAA,CAAA,GAAA,GAAA,EAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;IAO3B,EAKO,QALP,IAKO,CAJL,EAGE,EAAA,QAAA,WAAA;KAFC,QAAQ,EAAA;KACR,WAAW,EAAA;;IAIhB,EA4Da,GAAA,EA5DD,MAAK,mBAAkB,GAAA;uBAEzB,EAAA,SAAY,EAAA,CAAA,KAAA,EAAA,GADpB,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,CAAA,GAAA,EAAA,EAApB,EAAA,EAAA,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,GAQM,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 /** 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":"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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 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 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);\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--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 :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=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-button__label\">\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 } 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 +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 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 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);\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--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 :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=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-button__label\">\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 } 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":""}
@@ -5,6 +5,23 @@ type __VLS_Props = {
5
5
  size?: TSize;
6
6
  disabled?: boolean;
7
7
  loading?: boolean;
8
+ /**
9
+ * Accessible announcement while `loading`, forwarded to the spinner.
10
+ * The default is English; pass the active locale's string to localize it.
11
+ */
12
+ loadingLabel?: string;
13
+ /**
14
+ * While `loading`, hide the `icon` slot so the spinner replaces the icon
15
+ * instead of rendering beside it. Set to `false` to keep both visible.
16
+ */
17
+ hideIconWhileLoading?: boolean;
18
+ /**
19
+ * Square, icon-only button. The visible label is dropped, so an accessible
20
+ * name is required — pass `label` (or `aria-label`).
21
+ */
22
+ iconOnly?: boolean;
23
+ /** Accessible name, rendered as `aria-label`. Required when `iconOnly`. */
24
+ label?: string;
8
25
  type?: 'button' | 'submit' | 'reset';
9
26
  /** Stretch to the full width of the container. */
10
27
  block?: boolean;
@@ -29,9 +46,13 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}
29
46
  type: "button" | "submit" | "reset";
30
47
  disabled: boolean;
31
48
  size: TSize;
49
+ label: string;
32
50
  variant: TVariant | "brand";
33
51
  as: string;
34
52
  loading: boolean;
53
+ loadingLabel: string;
54
+ hideIconWhileLoading: boolean;
55
+ iconOnly: boolean;
35
56
  block: boolean;
36
57
  align: "start" | "center" | "end";
37
58
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"TButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/TButton.vue"],"names":[],"mappings":"AAqHA,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,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;AA6EJ,iBAAS,cAAc;WA6ET,OAAO,IAA6B;;sBAXvB,GAAG;yBACA,GAAG;;;;EAehC;AAeD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAC9D,QAAA,MAAM,eAAe;;;;;UApLV,QAAQ,GAAG,QAAQ,GAAG,OAAO;cAFzB,OAAO;UADX,KAAK;aADF,QAAQ,GAAG,OAAO;QADvB,MAAM;aAID,OAAO;WAGT,OAAO;WAEP,OAAO,GAAG,QAAQ,GAAG,KAAK;6EAyLpC,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":"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,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={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},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)(()=>u({variant:c.variant,size:c.size,class:{"is-loading":c.loading,"is-disabled":f.value,"t-button--block":c.block,"t-button--align-start":c.align===`start`,"t-button--align-end":c.align===`end`}})),m=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)(p.value),disabled:d.value?f.value:void 0,"aria-disabled":!d.value&&f.value?`true`:void 0,"aria-busy":o.loading||void 0,tabindex:!d.value&&f.value?-1:void 0,onClick:m},{default:(0,t.withCtx)(()=>[o.loading?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,r,[(0,t.createVNode)(e.default,{size:`sm`,label:`Loading`})])):(0,t.createCommentVNode)(``,!0),n.$slots.icon?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,i,[(0,t.renderSlot)(n.$slots,`icon`)])):(0,t.createCommentVNode)(``,!0),(0,t.createElementVNode)(`span`,a,[(0,t.renderSlot)(n.$slots,`default`)])]),_:3},8,[`type`,`class`,`disabled`,`aria-disabled`,`aria-busy`,`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=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;
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 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 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);\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--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 :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=\"Loading\"\n />\n </span>\n <span\n v-if=\"$slots.icon\"\n class=\"t-button__icon\"\n aria-hidden=\"true\"\n >\n <slot name=\"icon\" />\n </span>\n <span class=\"t-button__label\">\n <slot />\n </span>\n </component>\n</template>\n"],"mappings":"0fAMA,IAAM,EAAQ,EAyBR,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,EAC3D,GAAA,EAAA,EAAA,SAAA,KACJ,EAAY,CACV,QAAS,EAAM,QACf,KAAM,EAAM,KACZ,MAAO,CACL,aAAc,EAAM,QACpB,cAAe,EAAW,MAC1B,kBAAmB,EAAM,MACzB,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,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,KACL,MAAM,+CAIFA,EAAAA,OAAO,OAAA,EAAA,EAAA,UAAA,CAAA,GAAA,EAAA,EAAA,mBAAA,CAKR,OANP,EAMO,EAAA,EAAA,EAAA,WAAA,CADe,EAAA,OAAA,MAAA,CAAA,CAAA,IAAA,EAAA,EAAA,mBAAA,CAAA,GAAA,EAAA,2BAIf,OAFP,EAEO,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 } 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"}