@treeui/vue 0.16.0 → 0.18.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 (143) hide show
  1. package/dist/components/TAccordion.cjs.map +1 -1
  2. package/dist/components/TAccordion.js.map +1 -1
  3. package/dist/components/TAccordion.vue_vue_type_script_setup_true_lang.cjs +1 -1
  4. package/dist/components/TAccordion.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  5. package/dist/components/TAccordion.vue_vue_type_script_setup_true_lang.js +3 -3
  6. package/dist/components/TAccordion.vue_vue_type_script_setup_true_lang.js.map +1 -1
  7. package/dist/components/TAccordionItem.cjs.map +1 -1
  8. package/dist/components/TAccordionItem.js.map +1 -1
  9. package/dist/components/TAccordionItem.vue_vue_type_script_setup_true_lang.cjs +1 -1
  10. package/dist/components/TAccordionItem.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  11. package/dist/components/TAccordionItem.vue_vue_type_script_setup_true_lang.js +1 -1
  12. package/dist/components/TAccordionItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/components/TAppShell.cjs.map +1 -1
  14. package/dist/components/TAppShell.js.map +1 -1
  15. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs +1 -1
  16. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  17. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js +1 -1
  18. package/dist/components/TAppShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/TDatePicker.cjs.map +1 -1
  20. package/dist/components/TDatePicker.js.map +1 -1
  21. package/dist/components/TDatePicker.vue_vue_type_script_setup_true_lang.cjs +1 -1
  22. package/dist/components/TDatePicker.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  23. package/dist/components/TDatePicker.vue_vue_type_script_setup_true_lang.js +1 -1
  24. package/dist/components/TDatePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/TDateTimePicker.cjs.map +1 -1
  26. package/dist/components/TDateTimePicker.js.map +1 -1
  27. package/dist/components/TDateTimePicker.vue_vue_type_script_setup_true_lang.cjs +1 -1
  28. package/dist/components/TDateTimePicker.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  29. package/dist/components/TDateTimePicker.vue_vue_type_script_setup_true_lang.js +1 -1
  30. package/dist/components/TDateTimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  31. package/dist/components/TDrawer.cjs.map +1 -1
  32. package/dist/components/TDrawer.js.map +1 -1
  33. package/dist/components/TDrawer.vue_vue_type_script_setup_true_lang.cjs +1 -1
  34. package/dist/components/TDrawer.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  35. package/dist/components/TDrawer.vue_vue_type_script_setup_true_lang.js +1 -1
  36. package/dist/components/TDrawer.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/TDropdown.cjs.map +1 -1
  38. package/dist/components/TDropdown.js.map +1 -1
  39. package/dist/components/TDropdown.vue.d.ts +4 -0
  40. package/dist/components/TDropdown.vue.d.ts.map +1 -1
  41. package/dist/components/TDropdown.vue_vue_type_script_setup_true_lang.cjs +1 -1
  42. package/dist/components/TDropdown.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  43. package/dist/components/TDropdown.vue_vue_type_script_setup_true_lang.js +22 -18
  44. package/dist/components/TDropdown.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/TFlag.cjs +2 -0
  46. package/dist/components/TFlag.cjs.map +1 -0
  47. package/dist/components/TFlag.js +7 -0
  48. package/dist/components/TFlag.js.map +1 -0
  49. package/dist/components/TFlag.vue.d.ts +20 -0
  50. package/dist/components/TFlag.vue.d.ts.map +1 -0
  51. package/dist/components/TFlag.vue_vue_type_script_setup_true_lang.cjs +2 -0
  52. package/dist/components/TFlag.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  53. package/dist/components/TFlag.vue_vue_type_script_setup_true_lang.js +58 -0
  54. package/dist/components/TFlag.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/TIcon.cjs.map +1 -1
  56. package/dist/components/TIcon.js.map +1 -1
  57. package/dist/components/TIcon.vue.d.ts +1 -1
  58. package/dist/components/TIcon.vue.d.ts.map +1 -1
  59. package/dist/components/TIcon.vue_vue_type_script_setup_true_lang.cjs +1 -1
  60. package/dist/components/TIcon.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  61. package/dist/components/TIcon.vue_vue_type_script_setup_true_lang.js +18 -17
  62. package/dist/components/TIcon.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/TLanguageSelect.cjs +2 -0
  64. package/dist/components/TLanguageSelect.cjs.map +1 -0
  65. package/dist/components/TLanguageSelect.js +7 -0
  66. package/dist/components/TLanguageSelect.js.map +1 -0
  67. package/dist/components/TLanguageSelect.vue.d.ts +103 -0
  68. package/dist/components/TLanguageSelect.vue.d.ts.map +1 -0
  69. package/dist/components/TLanguageSelect.vue_vue_type_script_setup_true_lang.cjs +2 -0
  70. package/dist/components/TLanguageSelect.vue_vue_type_script_setup_true_lang.cjs.map +1 -0
  71. package/dist/components/TLanguageSelect.vue_vue_type_script_setup_true_lang.js +299 -0
  72. package/dist/components/TLanguageSelect.vue_vue_type_script_setup_true_lang.js.map +1 -0
  73. package/dist/components/TModal.cjs.map +1 -1
  74. package/dist/components/TModal.js.map +1 -1
  75. package/dist/components/TModal.vue_vue_type_script_setup_true_lang.cjs +1 -1
  76. package/dist/components/TModal.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  77. package/dist/components/TModal.vue_vue_type_script_setup_true_lang.js +1 -1
  78. package/dist/components/TModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  79. package/dist/components/TMultiSelect.cjs.map +1 -1
  80. package/dist/components/TMultiSelect.js.map +1 -1
  81. package/dist/components/TMultiSelect.vue_vue_type_script_setup_true_lang.cjs +1 -1
  82. package/dist/components/TMultiSelect.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  83. package/dist/components/TMultiSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  84. package/dist/components/TMultiSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/components/TNavMenu.cjs.map +1 -1
  86. package/dist/components/TNavMenu.js.map +1 -1
  87. package/dist/components/TNavMenu.vue.d.ts +7 -2
  88. package/dist/components/TNavMenu.vue.d.ts.map +1 -1
  89. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs +1 -1
  90. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  91. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js +50 -49
  92. package/dist/components/TNavMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/TPopover.cjs.map +1 -1
  94. package/dist/components/TPopover.js.map +1 -1
  95. package/dist/components/TPopover.vue.d.ts +4 -2
  96. package/dist/components/TPopover.vue.d.ts.map +1 -1
  97. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.cjs +1 -1
  98. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  99. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.js +10 -5
  100. package/dist/components/TPopover.vue_vue_type_script_setup_true_lang.js.map +1 -1
  101. package/dist/components/TPricingCard.vue.d.ts +1 -1
  102. package/dist/components/TPricingCard.vue.d.ts.map +1 -1
  103. package/dist/components/TSidebar.cjs.map +1 -1
  104. package/dist/components/TSidebar.js.map +1 -1
  105. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs +1 -1
  106. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  107. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js +1 -1
  108. package/dist/components/TSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/TSteps.cjs.map +1 -1
  110. package/dist/components/TSteps.js.map +1 -1
  111. package/dist/components/TSteps.vue_vue_type_script_setup_true_lang.cjs +1 -1
  112. package/dist/components/TSteps.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  113. package/dist/components/TSteps.vue_vue_type_script_setup_true_lang.js +1 -1
  114. package/dist/components/TSteps.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/TToast.cjs.map +1 -1
  116. package/dist/components/TToast.js.map +1 -1
  117. package/dist/components/TToast.vue.d.ts.map +1 -1
  118. package/dist/components/TToast.vue_vue_type_script_setup_true_lang.cjs +1 -1
  119. package/dist/components/TToast.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  120. package/dist/components/TToast.vue_vue_type_script_setup_true_lang.js +6 -6
  121. package/dist/components/TToast.vue_vue_type_script_setup_true_lang.js.map +1 -1
  122. package/dist/components/TTreeViewItem.cjs.map +1 -1
  123. package/dist/components/TTreeViewItem.js.map +1 -1
  124. package/dist/components/TTreeViewItem.vue_vue_type_script_setup_true_lang.cjs +1 -1
  125. package/dist/components/TTreeViewItem.vue_vue_type_script_setup_true_lang.cjs.map +1 -1
  126. package/dist/components/TTreeViewItem.vue_vue_type_script_setup_true_lang.js +1 -1
  127. package/dist/components/TTreeViewItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  128. package/dist/components/accordion.cjs.map +1 -1
  129. package/dist/components/accordion.d.ts +4 -4
  130. package/dist/components/accordion.d.ts.map +1 -1
  131. package/dist/components/accordion.js.map +1 -1
  132. package/dist/components/index.d.ts +5 -1
  133. package/dist/components/index.d.ts.map +1 -1
  134. package/dist/components/index.js +77 -0
  135. package/dist/index.cjs +1 -1
  136. package/dist/index.js +81 -78
  137. package/dist/plugin.cjs +1 -1
  138. package/dist/plugin.cjs.map +1 -1
  139. package/dist/plugin.d.ts.map +1 -1
  140. package/dist/plugin.js +146 -142
  141. package/dist/plugin.js.map +1 -1
  142. package/dist/style.css +1 -1
  143. package/package.json +2 -2
@@ -0,0 +1,299 @@
1
+ import e from "./TSpinner.js";
2
+ import { useControllableOpen as t } from "../composables/useControllableOpen.js";
3
+ import n from "./TFlag.js";
4
+ import r from "./TIcon.js";
5
+ import { Fragment as i, Transition as a, computed as o, createBlock as s, createCommentVNode as c, createElementBlock as l, createElementVNode as u, createTextVNode as ee, createVNode as d, defineComponent as f, mergeProps as p, nextTick as m, normalizeClass as h, normalizeStyle as te, onBeforeUnmount as g, openBlock as _, ref as v, renderList as y, renderSlot as b, toDisplayString as x, toRef as ne, unref as S, useAttrs as C, watch as w, withCtx as T } from "vue";
6
+ import { createId as E, isActivationKey as D, isEscapeKey as O } from "@treeui/utils";
7
+ //#region src/components/TLanguageSelect.vue?vue&type=script&setup=true&lang.ts
8
+ var k = ["data-state"], re = [
9
+ "disabled",
10
+ "aria-controls",
11
+ "aria-expanded",
12
+ "aria-invalid",
13
+ "aria-busy"
14
+ ], ie = {
15
+ key: 0,
16
+ class: "t-language-select__slot t-language-select__slot--prefix"
17
+ }, ae = ["data-placeholder"], oe = {
18
+ key: 6,
19
+ class: "t-language-select__chevron",
20
+ viewBox: "0 0 16 16",
21
+ fill: "none",
22
+ stroke: "currentColor",
23
+ "stroke-width": "2",
24
+ "stroke-linecap": "round",
25
+ "stroke-linejoin": "round",
26
+ "aria-hidden": "true"
27
+ }, se = ["id", "aria-label"], ce = {
28
+ key: 0,
29
+ class: "t-language-select__empty",
30
+ role: "presentation"
31
+ }, le = [
32
+ "aria-selected",
33
+ "aria-disabled",
34
+ "tabindex",
35
+ "onClick",
36
+ "onKeydown"
37
+ ], ue = { class: "t-language-select__option-text" }, de = { class: "t-language-select__option-label" }, fe = {
38
+ key: 0,
39
+ class: "t-language-select__description"
40
+ }, pe = {
41
+ key: 0,
42
+ class: "t-language-select__check",
43
+ viewBox: "0 0 16 16",
44
+ fill: "none",
45
+ stroke: "currentColor",
46
+ "stroke-width": "2",
47
+ "stroke-linecap": "round",
48
+ "stroke-linejoin": "round",
49
+ "aria-hidden": "true"
50
+ }, A = /*@__PURE__*/ f({
51
+ inheritAttrs: !1,
52
+ __name: "TLanguageSelect",
53
+ props: {
54
+ modelValue: { default: "" },
55
+ options: { default: () => [] },
56
+ open: {
57
+ type: Boolean,
58
+ default: void 0
59
+ },
60
+ defaultOpen: {
61
+ type: Boolean,
62
+ default: !1
63
+ },
64
+ size: { default: "md" },
65
+ variant: { default: "field" },
66
+ iconOnly: {
67
+ type: Boolean,
68
+ default: !1
69
+ },
70
+ width: { default: "full" },
71
+ disabled: {
72
+ type: Boolean,
73
+ default: !1
74
+ },
75
+ loading: {
76
+ type: Boolean,
77
+ default: !1
78
+ },
79
+ invalid: {
80
+ type: Boolean,
81
+ default: !1
82
+ },
83
+ placeholder: { default: "" },
84
+ flagBaseUrl: { default: void 0 },
85
+ emptyText: { default: "No languages available." }
86
+ },
87
+ emits: [
88
+ "update:modelValue",
89
+ "update:open",
90
+ "open-change"
91
+ ],
92
+ setup(f, { emit: A }) {
93
+ let j = f, M = A, N = C(), P = E("t-language-select"), F = v(null), I = v(null), L = v(null), R = v(/* @__PURE__ */ new Map()), z = v(-1), B = v(!1), V = o(() => {
94
+ let { class: e, style: t, ...n } = N;
95
+ return n;
96
+ }), { value: H, setValue: U } = t(ne(j, "open"), j.defaultOpen, (e) => {
97
+ M("update:open", e), M("open-change", e);
98
+ }), W = o(() => j.variant === "switcher"), me = o(() => [
99
+ "t-language-select",
100
+ `t-language-select--${j.size}`,
101
+ `t-language-select--${j.variant}`,
102
+ !W.value && j.width !== "full" ? `t-field-width--${j.width}` : null,
103
+ {
104
+ "t-language-select--icon-only": W.value && j.iconOnly,
105
+ "t-language-select--drop-up": B.value,
106
+ "is-disabled": j.disabled,
107
+ "is-invalid": j.invalid,
108
+ "is-loading": j.loading,
109
+ "is-open": H.value
110
+ },
111
+ N.class
112
+ ]), he = (e) => {
113
+ let t = e.parentElement;
114
+ for (; t && t !== document.body;) {
115
+ let { overflowY: e } = window.getComputedStyle(t);
116
+ if (e === "auto" || e === "scroll" || e === "hidden") return t;
117
+ t = t.parentElement;
118
+ }
119
+ return null;
120
+ }, ge = () => {
121
+ let e = I.value, t = L.value;
122
+ if (!e || !t) {
123
+ B.value = !1;
124
+ return;
125
+ }
126
+ let n = e.getBoundingClientRect(), r = t.getBoundingClientRect(), i = he(e)?.getBoundingClientRect(), a = Math.min(i?.bottom ?? Infinity, window.innerHeight), o = Math.max(i?.top ?? 0, 0), s = a - n.bottom, c = n.top - o;
127
+ B.value = r.bottom > a && c > s;
128
+ }, _e = o(() => N.style), G = o(() => j.options.find((e) => e.value === j.modelValue)), ve = o(() => G.value?.label ?? ""), ye = o(() => !(W.value && j.iconOnly) || !G.value?.code), K = o(() => j.options.filter((e) => !e.disabled)), be = () => {
129
+ let e = j.options.findIndex((e) => e.value === j.modelValue);
130
+ z.value = e >= 0 ? e : 0, B.value = !1, m(() => {
131
+ ge(), Z(z.value);
132
+ });
133
+ }, q = () => {
134
+ j.disabled || U(!0);
135
+ }, J = (e = !1) => {
136
+ U(!1), z.value = -1, e && m(() => I.value?.focus());
137
+ }, Y = () => {
138
+ H.value ? J() : q();
139
+ }, X = (e) => {
140
+ e.disabled || (M("update:modelValue", e.value), J(!0));
141
+ }, Z = (e) => {
142
+ let t = j.options[e];
143
+ t && R.value.get(t.value)?.focus();
144
+ }, xe = (e, t) => {
145
+ e instanceof HTMLElement ? R.value.set(t, e) : R.value.delete(t);
146
+ }, Q = (e) => {
147
+ let t = z.value + e;
148
+ for (; t >= 0 && t < j.options.length;) {
149
+ if (!j.options[t].disabled) {
150
+ z.value = t, Z(t);
151
+ return;
152
+ }
153
+ t += e;
154
+ }
155
+ }, Se = (e) => {
156
+ if (!j.disabled) {
157
+ if (O(e) && H.value) {
158
+ e.preventDefault(), J();
159
+ return;
160
+ }
161
+ (D(e) || e.key === "ArrowDown" || e.key === "ArrowUp") && (e.preventDefault(), q());
162
+ }
163
+ }, Ce = (e, t, n) => {
164
+ if (O(e)) {
165
+ e.preventDefault(), J(!0);
166
+ return;
167
+ }
168
+ if (D(e)) {
169
+ e.preventDefault(), X(t);
170
+ return;
171
+ }
172
+ switch (e.key) {
173
+ case "ArrowDown":
174
+ e.preventDefault(), Q(1);
175
+ break;
176
+ case "ArrowUp":
177
+ e.preventDefault(), Q(-1);
178
+ break;
179
+ case "Home":
180
+ e.preventDefault(), z.value = K.value.length > 0 ? j.options.indexOf(K.value[0]) : 0, Z(z.value);
181
+ break;
182
+ case "End":
183
+ e.preventDefault(), z.value = K.value.length > 0 ? j.options.indexOf(K.value[K.value.length - 1]) : j.options.length - 1, Z(z.value);
184
+ break;
185
+ default: break;
186
+ }
187
+ }, $ = (e) => {
188
+ if (!H.value) return;
189
+ let t = e.target;
190
+ t instanceof Node && (F.value?.contains(t) || J());
191
+ }, we = o(() => j.modelValue !== "");
192
+ return w(H, (e) => {
193
+ e ? (document.addEventListener("pointerdown", $), be()) : document.removeEventListener("pointerdown", $);
194
+ }, { immediate: !0 }), w(() => j.options.length, (e) => {
195
+ H.value && z.value >= e && (z.value = e - 1);
196
+ }), g(() => {
197
+ document.removeEventListener("pointerdown", $);
198
+ }), (t, o) => (_(), l("div", {
199
+ ref_key: "rootRef",
200
+ ref: F,
201
+ class: h(me.value),
202
+ style: te(_e.value),
203
+ "data-state": S(H) ? "open" : "closed"
204
+ }, [u("button", p({
205
+ ref_key: "triggerRef",
206
+ ref: I
207
+ }, V.value, {
208
+ type: "button",
209
+ class: "t-language-select__trigger",
210
+ disabled: f.disabled,
211
+ "aria-controls": S(H) ? S(P) : void 0,
212
+ "aria-haspopup": "listbox",
213
+ "aria-expanded": S(H),
214
+ "aria-invalid": f.invalid || void 0,
215
+ "aria-busy": f.loading || void 0,
216
+ onClick: Y,
217
+ onKeydown: Se
218
+ }), [
219
+ t.$slots.prefix ? (_(), l("span", ie, [b(t.$slots, "prefix")])) : c("", !0),
220
+ W.value ? (_(), s(r, {
221
+ key: 1,
222
+ name: "languages",
223
+ class: "t-language-select__translate"
224
+ })) : G.value?.code ? (_(), s(n, {
225
+ key: 2,
226
+ code: G.value.code,
227
+ "base-url": f.flagBaseUrl,
228
+ size: f.size
229
+ }, null, 8, [
230
+ "code",
231
+ "base-url",
232
+ "size"
233
+ ])) : c("", !0),
234
+ ye.value ? (_(), l("span", {
235
+ key: 3,
236
+ class: "t-language-select__value",
237
+ "data-placeholder": !we.value || void 0
238
+ }, x(ve.value || f.placeholder), 9, ae)) : c("", !0),
239
+ W.value && G.value?.code ? (_(), s(n, {
240
+ key: 4,
241
+ code: G.value.code,
242
+ "base-url": f.flagBaseUrl,
243
+ size: f.size
244
+ }, null, 8, [
245
+ "code",
246
+ "base-url",
247
+ "size"
248
+ ])) : c("", !0),
249
+ f.loading ? (_(), s(e, {
250
+ key: 5,
251
+ size: "sm",
252
+ label: "Loading"
253
+ })) : (_(), l("svg", oe, [...o[0] ||= [u("polyline", { points: "4 6 8 10 12 6" }, null, -1)]]))
254
+ ], 16, re), d(a, { name: "t-fade" }, {
255
+ default: T(() => [S(H) && !f.disabled ? (_(), l("ul", {
256
+ key: 0,
257
+ id: S(P),
258
+ ref_key: "listboxRef",
259
+ ref: L,
260
+ role: "listbox",
261
+ class: "t-language-select__listbox",
262
+ "aria-label": typeof V.value["aria-label"] == "string" ? V.value["aria-label"] : void 0
263
+ }, [f.options.length === 0 ? (_(), l("li", ce, [b(t.$slots, "empty", {}, () => [ee(x(f.emptyText), 1)])])) : c("", !0), (_(!0), l(i, null, y(f.options, (e, r) => (_(), l("li", {
264
+ key: e.value,
265
+ ref_for: !0,
266
+ ref: (t) => xe(t, e.value),
267
+ role: "option",
268
+ class: h(["t-language-select__option", {
269
+ "is-selected": e.value === f.modelValue,
270
+ "is-disabled": e.disabled,
271
+ "is-focused": r === z.value
272
+ }]),
273
+ "aria-selected": e.value === f.modelValue,
274
+ "aria-disabled": e.disabled || void 0,
275
+ tabindex: e.disabled ? -1 : 0,
276
+ onClick: (t) => X(e),
277
+ onKeydown: (t) => Ce(t, e, r)
278
+ }, [b(t.$slots, "option", {
279
+ option: e,
280
+ selected: e.value === f.modelValue,
281
+ focused: r === z.value
282
+ }, () => [e.code ? (_(), s(n, {
283
+ key: 0,
284
+ code: e.code,
285
+ "base-url": f.flagBaseUrl,
286
+ size: f.size
287
+ }, null, 8, [
288
+ "code",
289
+ "base-url",
290
+ "size"
291
+ ])) : c("", !0), u("span", ue, [u("span", de, x(e.label), 1), e.description ? (_(), l("span", fe, x(e.description), 1)) : c("", !0)])]), e.value === f.modelValue ? (_(), l("svg", pe, [...o[1] ||= [u("polyline", { points: "3.5 8.5 6.5 11.5 12.5 4.5" }, null, -1)]])) : c("", !0)], 42, le))), 128))], 8, se)) : c("", !0)]),
292
+ _: 3
293
+ })], 14, k));
294
+ }
295
+ });
296
+ //#endregion
297
+ export { A as default };
298
+
299
+ //# sourceMappingURL=TLanguageSelect.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TLanguageSelect.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TLanguageSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { createId, isActivationKey, isEscapeKey } from '@treeui/utils';\nimport { computed, nextTick, onBeforeUnmount, ref, toRef, useAttrs, watch } from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TFieldWidth, TSize } from '../types/contracts';\nimport TFlag from './TFlag.vue';\nimport TIcon from './TIcon.vue';\nimport TSpinner from './TSpinner.vue';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\n/**\n * `field` is a form control: it reads as the value of a labelled question, so the\n * flag leads and the trigger fills its container.\n *\n * `switcher` is a page-level control, typically in a navbar, where nothing nearby\n * says what it changes. The translate icon states the purpose up front and the\n * current flag closes the row, so the whole thing reads as \"page language, now\n * set to this\" without an external label.\n */\nexport type TLanguageSelectVariant = 'field' | 'switcher';\n\nexport interface TLanguageOption {\n label: string;\n /** Opaque application key — typically a BCP-47 tag. Never parsed or validated. */\n value: string;\n /** ISO 3166-1 alpha-2 code for the flag. Omit to render the option without one. */\n code?: string;\n /** Secondary line, e.g. the language's endonym. */\n description?: string;\n disabled?: boolean;\n}\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string;\n options?: TLanguageOption[];\n open?: boolean;\n defaultOpen?: boolean;\n size?: TSize;\n variant?: TLanguageSelectVariant;\n /** Hide the language name, leaving icon + flag. `switcher` only. */\n iconOnly?: boolean;\n /** Inline-size cap. Fluid (`full`) by default. */\n width?: TFieldWidth;\n disabled?: boolean;\n loading?: boolean;\n invalid?: boolean;\n placeholder?: string;\n /** Forwarded to every nested TFlag. Set once here to self-host flag assets. */\n flagBaseUrl?: string;\n emptyText?: string;\n }>(),\n {\n modelValue: '',\n options: () => [],\n open: undefined,\n defaultOpen: false,\n size: 'md',\n variant: 'field',\n iconOnly: false,\n width: 'full',\n disabled: false,\n loading: false,\n invalid: false,\n placeholder: '',\n flagBaseUrl: undefined,\n emptyText: 'No languages available.',\n },\n);\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string];\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\ndefineSlots<{\n prefix?: () => unknown;\n option?: (props: { option: TLanguageOption; selected: boolean; focused: boolean }) => unknown;\n empty?: () => unknown;\n}>();\n\nconst attrs = useAttrs();\nconst listboxId = createId('t-language-select');\nconst rootRef = ref<HTMLElement | null>(null);\nconst triggerRef = ref<HTMLButtonElement | null>(null);\nconst listboxRef = ref<HTMLElement | null>(null);\nconst optionRefs = ref<Map<string, HTMLElement>>(new Map());\nconst focusedIndex = ref(-1);\nconst dropUp = ref(false);\n\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst isSwitcher = computed(() => props.variant === 'switcher');\n\nconst rootClasses = computed(() => [\n 't-language-select',\n `t-language-select--${props.size}`,\n `t-language-select--${props.variant}`,\n // A switcher sizes to its content, so the field width scale does not apply.\n !isSwitcher.value && props.width !== 'full' ? `t-field-width--${props.width}` : null,\n {\n 't-language-select--icon-only': isSwitcher.value && props.iconOnly,\n 't-language-select--drop-up': dropUp.value,\n 'is-disabled': props.disabled,\n 'is-invalid': props.invalid,\n 'is-loading': props.loading,\n 'is-open': isOpen.value,\n },\n attrs.class,\n]);\n\n// Nearest ancestor that can clip the listbox (scroll container or hidden overflow).\nconst findClippingAncestor = (element: HTMLElement): HTMLElement | null => {\n let parent = element.parentElement;\n while (parent && parent !== document.body) {\n const { overflowY } = window.getComputedStyle(parent);\n if (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'hidden') {\n return parent;\n }\n parent = parent.parentElement;\n }\n return null;\n};\n\n// Flip the listbox above the trigger when its rendered position overflows the\n// nearest clipping ancestor (e.g. a modal body) or the viewport, and there is\n// more room above the trigger than below it. Measuring the rendered rect keeps\n// the decision in sync with the CSS offset (--tree-space-2) automatically.\nconst updateDropDirection = () => {\n const trigger = triggerRef.value;\n const listbox = listboxRef.value;\n if (!trigger || !listbox) {\n dropUp.value = false;\n return;\n }\n const triggerRect = trigger.getBoundingClientRect();\n const listboxRect = listbox.getBoundingClientRect();\n const boundary = findClippingAncestor(trigger)?.getBoundingClientRect();\n const bottomLimit = Math.min(boundary?.bottom ?? Infinity, window.innerHeight);\n const topLimit = Math.max(boundary?.top ?? 0, 0);\n const spaceBelow = bottomLimit - triggerRect.bottom;\n const spaceAbove = triggerRect.top - topLimit;\n dropUp.value = listboxRect.bottom > bottomLimit && spaceAbove > spaceBelow;\n};\n\nconst rootStyle = computed(() => attrs.style);\n\nconst selectedOption = computed(() =>\n props.options.find((o) => o.value === props.modelValue),\n);\n\nconst selectedLabel = computed(() => selectedOption.value?.label ?? '');\n\n// iconOnly leans on the flag to carry the current value. With no flag to show it\n// would leave the trigger stating nothing at all, so the name comes back.\nconst showValue = computed(\n () => !(isSwitcher.value && props.iconOnly) || !selectedOption.value?.code,\n);\n\nconst enabledOptions = computed(() =>\n props.options.filter((o) => !o.disabled),\n);\n\n// Runs for every open, however it was triggered. The listbox can also be opened\n// through `open` / `defaultOpen` without going near openDropdown(), so this lives\n// on the isOpen watcher rather than inside the click handler.\nconst onOpened = () => {\n const selectedIdx = props.options.findIndex((o) => o.value === props.modelValue);\n focusedIndex.value = selectedIdx >= 0 ? selectedIdx : 0;\n // Render downward first so the measurement always starts from the default position.\n dropUp.value = false;\n nextTick(() => {\n updateDropDirection();\n focusOption(focusedIndex.value);\n });\n};\n\nconst openDropdown = () => {\n if (props.disabled) return;\n setValue(true);\n};\n\nconst closeDropdown = (restoreFocus = false) => {\n setValue(false);\n focusedIndex.value = -1;\n if (restoreFocus) {\n nextTick(() => triggerRef.value?.focus());\n }\n};\n\nconst toggleDropdown = () => {\n if (isOpen.value) {\n closeDropdown();\n } else {\n openDropdown();\n }\n};\n\nconst selectOption = (opt: TLanguageOption) => {\n if (opt.disabled) return;\n emit('update:modelValue', opt.value);\n closeDropdown(true);\n};\n\nconst focusOption = (index: number) => {\n const opt = props.options[index];\n if (!opt) return;\n const el = optionRefs.value.get(opt.value);\n el?.focus();\n};\n\nconst setOptionRef = (el: Element | null, value: string) => {\n if (el instanceof HTMLElement) {\n optionRefs.value.set(value, el);\n } else {\n optionRefs.value.delete(value);\n }\n};\n\nconst moveFocus = (direction: 1 | -1) => {\n let nextIndex = focusedIndex.value + direction;\n while (nextIndex >= 0 && nextIndex < props.options.length) {\n if (!props.options[nextIndex].disabled) {\n focusedIndex.value = nextIndex;\n focusOption(nextIndex);\n return;\n }\n nextIndex += direction;\n }\n};\n\nconst onTriggerKeydown = (event: KeyboardEvent) => {\n if (props.disabled) return;\n\n if (isEscapeKey(event) && isOpen.value) {\n event.preventDefault();\n closeDropdown();\n return;\n }\n\n if (isActivationKey(event) || event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n openDropdown();\n }\n};\n\nconst onOptionKeydown = (event: KeyboardEvent, opt: TLanguageOption, _index: number) => {\n if (isEscapeKey(event)) {\n event.preventDefault();\n closeDropdown(true);\n return;\n }\n\n if (isActivationKey(event)) {\n event.preventDefault();\n selectOption(opt);\n return;\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n moveFocus(1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n moveFocus(-1);\n break;\n case 'Home':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[0])\n : 0;\n focusOption(focusedIndex.value);\n break;\n case 'End':\n event.preventDefault();\n focusedIndex.value = enabledOptions.value.length > 0\n ? props.options.indexOf(enabledOptions.value[enabledOptions.value.length - 1])\n : props.options.length - 1;\n focusOption(focusedIndex.value);\n break;\n default:\n break;\n }\n};\n\nconst onDocumentPointerDown = (event: PointerEvent) => {\n if (!isOpen.value) return;\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (rootRef.value?.contains(target)) return;\n closeDropdown();\n};\n\nconst hasSelection = computed(() => props.modelValue !== '');\n\n// immediate, so a listbox that is already open on mount (`defaultOpen`, or a\n// controlled `open` that starts true) still dismisses on outside click and still\n// measures its drop direction.\nwatch(isOpen, (value) => {\n if (value) {\n document.addEventListener('pointerdown', onDocumentPointerDown);\n onOpened();\n } else {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n }\n}, { immediate: true });\n\n// Options can shrink underneath an open listbox. Leaving focusedIndex past the\n// end would strand moveFocus(), which only ever walks outward from it.\nwatch(\n () => props.options.length,\n (length) => {\n if (isOpen.value && focusedIndex.value >= length) {\n focusedIndex.value = length - 1;\n }\n },\n);\n\nonBeforeUnmount(() => {\n document.removeEventListener('pointerdown', onDocumentPointerDown);\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <button\n ref=\"triggerRef\"\n v-bind=\"triggerAttrs\"\n type=\"button\"\n class=\"t-language-select__trigger\"\n :disabled=\"disabled\"\n :aria-controls=\"isOpen ? listboxId : undefined\"\n aria-haspopup=\"listbox\"\n :aria-expanded=\"isOpen\"\n :aria-invalid=\"invalid || undefined\"\n :aria-busy=\"loading || undefined\"\n @click=\"toggleDropdown\"\n @keydown=\"onTriggerKeydown\"\n >\n <span\n v-if=\"$slots.prefix\"\n class=\"t-language-select__slot t-language-select__slot--prefix\"\n >\n <slot name=\"prefix\" />\n </span>\n <!--\n The switcher leads with the translate icon so the control announces what\n it changes; the field leads with the flag, since a form label already\n does that job.\n -->\n <!-- Sized in CSS from the icon token scale, not TIcon's pixel `size` prop. -->\n <TIcon\n v-if=\"isSwitcher\"\n name=\"languages\"\n class=\"t-language-select__translate\"\n />\n <TFlag\n v-else-if=\"selectedOption?.code\"\n :code=\"selectedOption.code\"\n :base-url=\"flagBaseUrl\"\n :size=\"size\"\n />\n <span\n v-if=\"showValue\"\n class=\"t-language-select__value\"\n :data-placeholder=\"!hasSelection ? true : undefined\"\n >\n {{ selectedLabel || placeholder }}\n </span>\n <TFlag\n v-if=\"isSwitcher && selectedOption?.code\"\n :code=\"selectedOption.code\"\n :base-url=\"flagBaseUrl\"\n :size=\"size\"\n />\n <TSpinner\n v-if=\"loading\"\n size=\"sm\"\n label=\"Loading\"\n />\n <svg\n v-else\n class=\"t-language-select__chevron\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"4 6 8 10 12 6\" />\n </svg>\n </button>\n <transition name=\"t-fade\">\n <ul\n v-if=\"isOpen && !disabled\"\n :id=\"listboxId\"\n ref=\"listboxRef\"\n role=\"listbox\"\n class=\"t-language-select__listbox\"\n :aria-label=\"typeof triggerAttrs['aria-label'] === 'string' ? triggerAttrs['aria-label'] : undefined\"\n >\n <li\n v-if=\"options.length === 0\"\n class=\"t-language-select__empty\"\n role=\"presentation\"\n >\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </li>\n <li\n v-for=\"(opt, index) in options\"\n :key=\"opt.value\"\n :ref=\"(el) => setOptionRef(el as Element | null, opt.value)\"\n role=\"option\"\n class=\"t-language-select__option\"\n :class=\"{\n 'is-selected': opt.value === modelValue,\n 'is-disabled': opt.disabled,\n 'is-focused': index === focusedIndex,\n }\"\n :aria-selected=\"opt.value === modelValue\"\n :aria-disabled=\"opt.disabled || undefined\"\n :tabindex=\"opt.disabled ? -1 : 0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt, index)\"\n >\n <slot\n name=\"option\"\n :option=\"opt\"\n :selected=\"opt.value === modelValue\"\n :focused=\"index === focusedIndex\"\n >\n <TFlag\n v-if=\"opt.code\"\n :code=\"opt.code\"\n :base-url=\"flagBaseUrl\"\n :size=\"size\"\n />\n <span class=\"t-language-select__option-text\">\n <span class=\"t-language-select__option-label\">{{ opt.label }}</span>\n <span\n v-if=\"opt.description\"\n class=\"t-language-select__description\"\n >\n {{ opt.description }}\n </span>\n </span>\n </slot>\n <svg\n v-if=\"opt.value === modelValue\"\n class=\"t-language-select__check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"3.5 8.5 6.5 11.5 12.5 4.5\" />\n </svg>\n </li>\n </ul>\n </transition>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TModal.cjs","names":[],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TModal.cjs","names":[],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"TModal.js","names":[],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"TModal.js","names":[],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- const e=require("../composables/useControllableOpen.cjs");let t=require("vue"),n=require("@treeui/utils"),r=require("@treeui/icons");var i=[`data-state`],a=[`aria-disabled`],o=[`data-state`],s={class:`t-modal__positioner`},c=[`id`,`aria-labelledby`,`aria-describedby`],l={key:0,class:`t-modal__topbar`},u={class:`t-modal__title`},d=[`aria-label`],f={class:`t-modal__body`},p={key:2,class:`t-modal__footer`},m=(0,t.defineComponent)({inheritAttrs:!1,__name:`TModal`,props:{open:{type:Boolean,default:void 0},defaultOpen:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},size:{default:`md`},title:{default:``},description:{default:``},closeOnEscape:{type:Boolean,default:!0},closeOnOverlay:{type:Boolean,default:!0},showCloseButton:{type:Boolean,default:!0},closeLabel:{default:`Close modal`},id:{default:void 0}},emits:[`update:open`,`open-change`],setup(m,{emit:h}){let g=(0,r.getTreeIcon)(`x`),_=m,v=h,y=(0,t.useAttrs)(),b=_.id??(0,n.createId)(`t-modal`),x=`${b}-title`,S=`${b}-description`,C=(0,t.ref)(null),w=(0,t.ref)(null),T=(0,t.ref)(null),E=(0,t.computed)(()=>!!(_.title||D.header)),D=(0,t.useSlots)(),O=(0,t.computed)(()=>[`t-modal`,y.class]),k=(0,t.computed)(()=>y.style),A=(0,t.computed)(()=>{let{class:e,style:t,...n}=y;return n}),j=(0,t.computed)(()=>[`t-modal__surface`,`t-modal__surface--${_.size}`]),{value:M,setValue:N}=e.useControllableOpen((0,t.toRef)(_,`open`),_.defaultOpen,e=>{v(`update:open`,e),v(`open-change`,e)}),P=(0,t.computed)(()=>E.value?x:void 0),F=(0,t.computed)(()=>_.description?S:void 0),I=0,L=``,R=()=>{typeof document>`u`||(I===0&&(L=document.body.style.overflow,document.body.style.overflow=`hidden`),I+=1)},z=()=>{typeof document>`u`||I===0||(--I,I===0&&(document.body.style.overflow=L))},B=()=>{(0,t.nextTick)(()=>{w.value&&((0,n.focusFirst)(w.value)||w.value.focus())})},V=()=>{_.disabled||(T.value=document.activeElement,N(!0))},H=()=>{N(!1)},U=e=>{if(_.disabled){e.preventDefault(),e.stopPropagation();return}e.defaultPrevented||V()},W=()=>{_.closeOnOverlay&&H()},G=e=>{e.stopPropagation()},K=e=>{if((0,n.isEscapeKey)(e)&&_.closeOnEscape){e.preventDefault(),H();return}if(e.key!==`Tab`||!w.value)return;let t=(0,n.getFocusableElements)(w.value);if(!t.length){e.preventDefault(),w.value.focus();return}let r=t[0],i=t[t.length-1],a=document.activeElement;e.shiftKey&&a===r&&(e.preventDefault(),(0,n.focusLast)(w.value)),!e.shiftKey&&a===i&&(e.preventDefault(),(0,n.focusFirst)(w.value))};return(0,t.watch)(M,(e,n)=>{if(e){R(),B();return}n&&(z(),(0,t.nextTick)(()=>{T.value?.focus()}))}),(0,t.onBeforeUnmount)(()=>{M.value&&z()}),(e,n)=>((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{ref_key:`rootRef`,ref:C,class:(0,t.normalizeClass)(O.value),style:(0,t.normalizeStyle)(k.value),"data-state":(0,t.unref)(M)?`open`:`closed`},[e.$slots.trigger?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0,class:`t-modal__trigger`},A.value,{"aria-disabled":m.disabled||void 0,onClick:U}),[(0,t.renderSlot)(e.$slots,`trigger`)],16,a)):(0,t.createCommentVNode)(``,!0),((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:`body`},[(0,t.createVNode)(t.Transition,{name:`t-modal-fade`},{default:(0,t.withCtx)(()=>[(0,t.unref)(M)?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,class:`t-modal__portal`,"data-state":(0,t.unref)(M)?`open`:`closed`},[(0,t.createElementVNode)(`div`,{class:`t-modal__backdrop`,"aria-hidden":`true`,onClick:W}),(0,t.createElementVNode)(`div`,s,[(0,t.createElementVNode)(`div`,{id:(0,t.unref)(b),ref_key:`surfaceRef`,ref:w,class:(0,t.normalizeClass)(j.value),role:`dialog`,"aria-modal":`true`,"aria-labelledby":P.value,"aria-describedby":F.value,tabindex:`-1`,onClick:G,onKeydown:K},[E.value||m.showCloseButton?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,l,[E.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,id:x,class:`t-modal__header`},[(0,t.renderSlot)(e.$slots,`header`,{},()=>[(0,t.createElementVNode)(`h2`,u,(0,t.toDisplayString)(m.title),1)])])):(0,t.createCommentVNode)(``,!0),m.showCloseButton?((0,t.openBlock)(),(0,t.createElementBlock)(`button`,{key:1,type:`button`,class:`t-modal__close`,"aria-label":m.closeLabel,onClick:H},[(0,t.createVNode)((0,t.unref)(g),(0,t.normalizeProps)((0,t.guardReactiveProps)((0,t.unref)(r.treeIconDefaults))),null,16)],8,d)):(0,t.createCommentVNode)(``,!0)])):(0,t.createCommentVNode)(``,!0),m.description?((0,t.openBlock)(),(0,t.createElementBlock)(`p`,{key:1,id:S,class:`t-modal__description`},(0,t.toDisplayString)(m.description),1)):(0,t.createCommentVNode)(``,!0),(0,t.createElementVNode)(`div`,f,[(0,t.renderSlot)(e.$slots,`content`,{},()=>[(0,t.renderSlot)(e.$slots,`default`)])]),e.$slots.footer?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,p,[(0,t.renderSlot)(e.$slots,`footer`)])):(0,t.createCommentVNode)(``,!0)],42,c)])],8,o)):(0,t.createCommentVNode)(``,!0)]),_:3})]))],14,i))}});exports.default=m;
1
+ const e=require("../composables/useControllableOpen.cjs");let t=require("vue"),n=require("@treeui/utils"),r=require("@treeui/icons");var i=[`data-state`],a=[`aria-disabled`],o=[`data-state`],s={class:`t-modal__positioner`},c=[`id`,`aria-labelledby`,`aria-describedby`],l={key:0,class:`t-modal__topbar`},u={class:`t-modal__title`},d=[`aria-label`],f={class:`t-modal__body`},p={key:2,class:`t-modal__footer`},m=(0,t.defineComponent)({inheritAttrs:!1,__name:`TModal`,props:{open:{type:Boolean,default:void 0},defaultOpen:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},size:{default:`md`},title:{default:``},description:{default:``},closeOnEscape:{type:Boolean,default:!0},closeOnOverlay:{type:Boolean,default:!0},showCloseButton:{type:Boolean,default:!0},closeLabel:{default:`Close modal`},id:{default:void 0}},emits:[`update:open`,`open-change`],setup(m,{emit:h}){let g=(0,t.computed)(()=>(0,r.getTreeIcon)(`x`)),_=m,v=h,y=(0,t.useAttrs)(),b=_.id??(0,n.createId)(`t-modal`),x=`${b}-title`,S=`${b}-description`,C=(0,t.ref)(null),w=(0,t.ref)(null),T=(0,t.ref)(null),E=(0,t.computed)(()=>!!(_.title||D.header)),D=(0,t.useSlots)(),O=(0,t.computed)(()=>[`t-modal`,y.class]),k=(0,t.computed)(()=>y.style),A=(0,t.computed)(()=>{let{class:e,style:t,...n}=y;return n}),j=(0,t.computed)(()=>[`t-modal__surface`,`t-modal__surface--${_.size}`]),{value:M,setValue:N}=e.useControllableOpen((0,t.toRef)(_,`open`),_.defaultOpen,e=>{v(`update:open`,e),v(`open-change`,e)}),P=(0,t.computed)(()=>E.value?x:void 0),F=(0,t.computed)(()=>_.description?S:void 0),I=0,L=``,R=()=>{typeof document>`u`||(I===0&&(L=document.body.style.overflow,document.body.style.overflow=`hidden`),I+=1)},z=()=>{typeof document>`u`||I===0||(--I,I===0&&(document.body.style.overflow=L))},B=()=>{(0,t.nextTick)(()=>{w.value&&((0,n.focusFirst)(w.value)||w.value.focus())})},V=()=>{_.disabled||(T.value=document.activeElement,N(!0))},H=()=>{N(!1)},U=e=>{if(_.disabled){e.preventDefault(),e.stopPropagation();return}e.defaultPrevented||V()},W=()=>{_.closeOnOverlay&&H()},G=e=>{e.stopPropagation()},K=e=>{if((0,n.isEscapeKey)(e)&&_.closeOnEscape){e.preventDefault(),H();return}if(e.key!==`Tab`||!w.value)return;let t=(0,n.getFocusableElements)(w.value);if(!t.length){e.preventDefault(),w.value.focus();return}let r=t[0],i=t[t.length-1],a=document.activeElement;e.shiftKey&&a===r&&(e.preventDefault(),(0,n.focusLast)(w.value)),!e.shiftKey&&a===i&&(e.preventDefault(),(0,n.focusFirst)(w.value))};return(0,t.watch)(M,(e,n)=>{if(e){R(),B();return}n&&(z(),(0,t.nextTick)(()=>{T.value?.focus()}))}),(0,t.onBeforeUnmount)(()=>{M.value&&z()}),(e,n)=>((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{ref_key:`rootRef`,ref:C,class:(0,t.normalizeClass)(O.value),style:(0,t.normalizeStyle)(k.value),"data-state":(0,t.unref)(M)?`open`:`closed`},[e.$slots.trigger?((0,t.openBlock)(),(0,t.createElementBlock)(`span`,(0,t.mergeProps)({key:0,class:`t-modal__trigger`},A.value,{"aria-disabled":m.disabled||void 0,onClick:U}),[(0,t.renderSlot)(e.$slots,`trigger`)],16,a)):(0,t.createCommentVNode)(``,!0),((0,t.openBlock)(),(0,t.createBlock)(t.Teleport,{to:`body`},[(0,t.createVNode)(t.Transition,{name:`t-modal-fade`},{default:(0,t.withCtx)(()=>[(0,t.unref)(M)?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,class:`t-modal__portal`,"data-state":(0,t.unref)(M)?`open`:`closed`},[(0,t.createElementVNode)(`div`,{class:`t-modal__backdrop`,"aria-hidden":`true`,onClick:W}),(0,t.createElementVNode)(`div`,s,[(0,t.createElementVNode)(`div`,{id:(0,t.unref)(b),ref_key:`surfaceRef`,ref:w,class:(0,t.normalizeClass)(j.value),role:`dialog`,"aria-modal":`true`,"aria-labelledby":P.value,"aria-describedby":F.value,tabindex:`-1`,onClick:G,onKeydown:K},[E.value||m.showCloseButton?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,l,[E.value?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,{key:0,id:x,class:`t-modal__header`},[(0,t.renderSlot)(e.$slots,`header`,{},()=>[(0,t.createElementVNode)(`h2`,u,(0,t.toDisplayString)(m.title),1)])])):(0,t.createCommentVNode)(``,!0),m.showCloseButton?((0,t.openBlock)(),(0,t.createElementBlock)(`button`,{key:1,type:`button`,class:`t-modal__close`,"aria-label":m.closeLabel,onClick:H},[(0,t.createVNode)((0,t.unref)(g),(0,t.normalizeProps)((0,t.guardReactiveProps)((0,t.unref)(r.treeIconDefaults))),null,16)],8,d)):(0,t.createCommentVNode)(``,!0)])):(0,t.createCommentVNode)(``,!0),m.description?((0,t.openBlock)(),(0,t.createElementBlock)(`p`,{key:1,id:S,class:`t-modal__description`},(0,t.toDisplayString)(m.description),1)):(0,t.createCommentVNode)(``,!0),(0,t.createElementVNode)(`div`,f,[(0,t.renderSlot)(e.$slots,`content`,{},()=>[(0,t.renderSlot)(e.$slots,`default`)])]),e.$slots.footer?((0,t.openBlock)(),(0,t.createElementBlock)(`div`,p,[(0,t.renderSlot)(e.$slots,`footer`)])):(0,t.createCommentVNode)(``,!0)],42,c)])],8,o)):(0,t.createCommentVNode)(``,!0)]),_:3})]))],14,i))}});exports.default=m;
2
2
  //# sourceMappingURL=TModal.vue_vue_type_script_setup_true_lang.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TModal.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TModal.vue_vue_type_script_setup_true_lang.cjs","names":["$slots"],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
@@ -49,7 +49,7 @@ var se = ["data-state"], ce = ["aria-disabled"], D = ["data-state"], O = { class
49
49
  },
50
50
  emits: ["update:open", "open-change"],
51
51
  setup(l, { emit: F }) {
52
- let I = ae("x"), L = l, R = F, z = S(), B = L.id ?? te("t-modal"), V = `${B}-title`, H = `${B}-description`, U = _(null), W = _(null), G = _(null), K = r(() => !!(L.title || le.header)), le = C(), ue = r(() => ["t-modal", z.class]), de = r(() => z.style), fe = r(() => {
52
+ let I = r(() => ae("x")), L = l, R = F, z = S(), B = L.id ?? te("t-modal"), V = `${B}-title`, H = `${B}-description`, U = _(null), W = _(null), G = _(null), K = r(() => !!(L.title || le.header)), le = C(), ue = r(() => ["t-modal", z.class]), de = r(() => z.style), fe = r(() => {
53
53
  let { class: e, style: t, ...n } = z;
54
54
  return n;
55
55
  }), pe = r(() => ["t-modal__surface", `t-modal__surface--${L.size}`]), { value: q, setValue: J } = e(b(L, "open"), L.defaultOpen, (e) => {
@@ -1 +1 @@
1
- {"version":3,"file":"TModal.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = getTreeIcon('x');\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TModal.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../src/components/TModal.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 ref,\n toRef,\n useAttrs,\n watch,\n} from 'vue';\nimport { useControllableOpen } from '../composables/useControllableOpen';\nimport type { TSize } from '../types/contracts';\n\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst CloseIcon = computed(() => getTreeIcon('x'));\n\nconst props = withDefaults(\n defineProps<{\n open?: boolean;\n defaultOpen?: boolean;\n disabled?: boolean;\n size?: TSize;\n title?: string;\n description?: string;\n closeOnEscape?: boolean;\n closeOnOverlay?: boolean;\n showCloseButton?: boolean;\n closeLabel?: string;\n id?: string;\n }>(),\n {\n open: undefined,\n defaultOpen: false,\n disabled: false,\n size: 'md',\n title: '',\n description: '',\n closeOnEscape: true,\n closeOnOverlay: true,\n showCloseButton: true,\n closeLabel: 'Close modal',\n id: undefined,\n },\n);\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean];\n 'open-change': [value: boolean];\n}>();\n\nconst attrs = useAttrs();\nconst modalId = props.id ?? createId('t-modal');\nconst titleId = `${modalId}-title`;\nconst descriptionId = `${modalId}-description`;\nconst rootRef = ref<HTMLElement | null>(null);\nconst surfaceRef = ref<HTMLElement | null>(null);\nconst previousFocusedElement = ref<HTMLElement | null>(null);\nconst hasHeaderContent = computed(() => Boolean(props.title || slots.header));\n\nconst slots = defineSlots<{\n default?: () => unknown;\n trigger?: () => unknown;\n header?: () => unknown;\n content?: () => unknown;\n footer?: () => unknown;\n}>();\n\nconst rootClasses = computed(() => ['t-modal', attrs.class]);\nconst rootStyle = computed(() => attrs.style);\nconst triggerAttrs = computed(() => {\n const { class: _class, style: _style, ...rest } = attrs;\n return rest;\n});\nconst surfaceClasses = computed(() => [\n 't-modal__surface',\n `t-modal__surface--${props.size}`,\n]);\n\nconst { value: isOpen, setValue } = useControllableOpen(\n toRef(props, 'open'),\n props.defaultOpen,\n (value) => {\n emit('update:open', value);\n emit('open-change', value);\n },\n);\n\nconst labelledBy = computed(() => (hasHeaderContent.value ? titleId : undefined));\nconst describedBy = computed(() => (props.description ? descriptionId : undefined));\n\nlet openOverlayCount = 0;\nlet previousBodyOverflow = '';\n\nconst lockBodyScroll = () => {\n if (typeof document === 'undefined') {\n return;\n }\n\n if (openOverlayCount === 0) {\n previousBodyOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n openOverlayCount += 1;\n};\n\nconst unlockBodyScroll = () => {\n if (typeof document === 'undefined' || openOverlayCount === 0) {\n return;\n }\n\n openOverlayCount -= 1;\n\n if (openOverlayCount === 0) {\n document.body.style.overflow = previousBodyOverflow;\n }\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 openModal = () => {\n if (props.disabled) {\n return;\n }\n\n previousFocusedElement.value = document.activeElement as HTMLElement | null;\n setValue(true);\n};\n\nconst closeModal = () => {\n setValue(false);\n};\n\nconst onTriggerClick = (event: MouseEvent) => {\n if (props.disabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n openModal();\n};\n\nconst onOverlayClick = () => {\n if (!props.closeOnOverlay) {\n return;\n }\n\n closeModal();\n};\n\nconst onSurfaceClick = (event: MouseEvent) => {\n event.stopPropagation();\n};\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (isEscapeKey(event) && props.closeOnEscape) {\n event.preventDefault();\n closeModal();\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\nwatch(isOpen, (value, previousValue) => {\n if (value) {\n lockBodyScroll();\n focusSurface();\n return;\n }\n\n if (previousValue) {\n unlockBodyScroll();\n nextTick(() => {\n previousFocusedElement.value?.focus();\n });\n }\n});\n\nonBeforeUnmount(() => {\n if (isOpen.value) {\n unlockBodyScroll();\n }\n});\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n :class=\"rootClasses\"\n :style=\"rootStyle\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <span\n v-if=\"$slots.trigger\"\n class=\"t-modal__trigger\"\n v-bind=\"triggerAttrs\"\n :aria-disabled=\"disabled || undefined\"\n @click=\"onTriggerClick\"\n >\n <slot name=\"trigger\" />\n </span>\n\n <Teleport to=\"body\">\n <transition name=\"t-modal-fade\">\n <div\n v-if=\"isOpen\"\n class=\"t-modal__portal\"\n :data-state=\"isOpen ? 'open' : 'closed'\"\n >\n <div\n class=\"t-modal__backdrop\"\n aria-hidden=\"true\"\n @click=\"onOverlayClick\"\n />\n <div class=\"t-modal__positioner\">\n <div\n :id=\"modalId\"\n ref=\"surfaceRef\"\n :class=\"surfaceClasses\"\n role=\"dialog\"\n aria-modal=\"true\"\n :aria-labelledby=\"labelledBy\"\n :aria-describedby=\"describedBy\"\n tabindex=\"-1\"\n @click=\"onSurfaceClick\"\n @keydown=\"onKeydown\"\n >\n <div\n v-if=\"hasHeaderContent || showCloseButton\"\n class=\"t-modal__topbar\"\n >\n <div\n v-if=\"hasHeaderContent\"\n :id=\"titleId\"\n class=\"t-modal__header\"\n >\n <slot name=\"header\">\n <h2 class=\"t-modal__title\">\n {{ title }}\n </h2>\n </slot>\n </div>\n <button\n v-if=\"showCloseButton\"\n type=\"button\"\n class=\"t-modal__close\"\n :aria-label=\"closeLabel\"\n @click=\"closeModal\"\n >\n <CloseIcon v-bind=\"treeIconDefaults\" />\n </button>\n </div>\n\n <p\n v-if=\"description\"\n :id=\"descriptionId\"\n class=\"t-modal__description\"\n >\n {{ description }}\n </p>\n\n <div class=\"t-modal__body\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div\n v-if=\"$slots.footer\"\n class=\"t-modal__footer\"\n >\n <slot name=\"footer\" />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n"],"mappings":"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"}