@ac-design/design-system 2.9.1 → 2.10.1

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.
@@ -0,0 +1,437 @@
1
+ import e from "./AcSpinner.js";
2
+ import { fixedFrame as t } from "./fixedFrame.js";
3
+ import { Fragment as n, Teleport as r, Transition as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, mergeModels as p, mergeProps as ee, nextTick as m, normalizeClass as h, normalizeStyle as te, onBeforeUnmount as ne, openBlock as g, ref as _, renderList as re, renderSlot as v, resolveDynamicComponent as ie, toDisplayString as y, unref as b, useAttrs as ae, useId as oe, useModel as se, useSlots as ce, watch as x, withCtx as le, withModifiers as ue } from "vue";
4
+ import { Check as de, ChevronDown as fe, ChevronUp as pe } from "@lucide/vue";
5
+ //#region src/lib/components/AcCombobox.vue?vue&type=script&setup=true&lang.ts
6
+ var me = {
7
+ key: 1,
8
+ class: "text-muted"
9
+ }, he = {
10
+ key: 2,
11
+ class: "text-danger",
12
+ "aria-hidden": "true"
13
+ }, ge = [
14
+ "value",
15
+ "aria-expanded",
16
+ "aria-activedescendant",
17
+ "aria-label",
18
+ "aria-describedby",
19
+ "aria-invalid",
20
+ "aria-required",
21
+ "aria-busy",
22
+ "placeholder",
23
+ "disabled",
24
+ "readonly",
25
+ "required"
26
+ ], _e = [
27
+ "aria-label",
28
+ "aria-expanded",
29
+ "disabled"
30
+ ], ve = [
31
+ "aria-labelledby",
32
+ "aria-label",
33
+ "aria-busy"
34
+ ], ye = [
35
+ "id",
36
+ "aria-selected",
37
+ "aria-disabled",
38
+ "onMouseenter",
39
+ "onClick"
40
+ ], be = { class: "min-w-0 flex-1" }, xe = {
41
+ key: 0,
42
+ class: "block truncate text-xs font-normal text-muted"
43
+ }, Se = {
44
+ key: 0,
45
+ role: "presentation",
46
+ class: "px-4 py-3 text-center text-base text-muted"
47
+ }, S = 320, Ce = "focus-within:shadow-[0_0_0_2px_color-mix(in_srgb,var(--color-danger)_20%,transparent)]", C = /*@__PURE__*/ f({
48
+ inheritAttrs: !1,
49
+ __name: "AcCombobox",
50
+ props: /*@__PURE__*/ p({
51
+ options: { default: () => [] },
52
+ label: { default: "" },
53
+ labelClass: {
54
+ type: [
55
+ Boolean,
56
+ null,
57
+ String,
58
+ Object,
59
+ Array
60
+ ],
61
+ default: void 0
62
+ },
63
+ placeholder: { default: void 0 },
64
+ hint: { default: "" },
65
+ size: { default: "normal" },
66
+ disabled: {
67
+ type: Boolean,
68
+ default: !1
69
+ },
70
+ readonly: {
71
+ type: Boolean,
72
+ default: !1
73
+ },
74
+ required: {
75
+ type: Boolean,
76
+ default: !1
77
+ },
78
+ requiredMark: {
79
+ type: Boolean,
80
+ default: !1
81
+ },
82
+ errorMsg: { default: "" },
83
+ invalid: {
84
+ type: Boolean,
85
+ default: !1
86
+ },
87
+ allowCustom: {
88
+ type: Boolean,
89
+ default: !0
90
+ },
91
+ filter: {
92
+ type: [Function, Boolean],
93
+ default: void 0
94
+ },
95
+ loading: {
96
+ type: Boolean,
97
+ default: !1
98
+ },
99
+ loadingText: { default: "Loading…" },
100
+ emptyText: { default: "" },
101
+ openOnFocus: {
102
+ type: Boolean,
103
+ default: !0
104
+ },
105
+ placement: { default: "bottom" },
106
+ inputClass: {
107
+ type: [
108
+ Boolean,
109
+ null,
110
+ String,
111
+ Object,
112
+ Array
113
+ ],
114
+ default: void 0
115
+ }
116
+ }, {
117
+ modelValue: { default: "" },
118
+ modelModifiers: {}
119
+ }),
120
+ emits: /*@__PURE__*/ p([
121
+ "select",
122
+ "search",
123
+ "focus",
124
+ "blur"
125
+ ], ["update:modelValue"]),
126
+ setup(f, { expose: p, emit: C }) {
127
+ let w = f, T = se(f, "modelValue"), E = C, D = ce(), O = {
128
+ small: {
129
+ box: "h-9",
130
+ start: "pl-4",
131
+ end: "pr-1"
132
+ },
133
+ normal: {
134
+ box: "h-10.5",
135
+ start: "pl-5",
136
+ end: "pr-2"
137
+ }
138
+ }, k = oe(), A = ae(), j = `${k}-input`, M = `${k}-list`, N = `${k}-label`, we = `${k}-hint`, Te = `${k}-msg`, Ee = _(null), P = _(null), F = _(null), I = _(!1), L = _(""), R = _(-1), z = _(!1), B = _(!1), V = _({
139
+ left: 0,
140
+ minWidth: 0,
141
+ maxWidth: S,
142
+ maxHeight: 288
143
+ }), De = a(() => ({
144
+ class: A.class,
145
+ style: A.style
146
+ })), Oe = a(() => {
147
+ let { class: e, style: t, ...n } = A;
148
+ return n;
149
+ }), H = a(() => w.options.map((e) => typeof e == "string" ? {
150
+ value: e,
151
+ label: e
152
+ } : {
153
+ ...e,
154
+ label: e.label ?? e.value
155
+ })), U = a(() => {
156
+ let e = L.value.trim();
157
+ if (w.filter === !1 || !z.value || !e) return H.value;
158
+ let t = w.filter ?? Fe;
159
+ return H.value.filter((n) => t(n, e));
160
+ }), W = a(() => w.size in O ? w.size : "normal"), ke = a(() => !!w.errorMsg || w.invalid), Ae = a(() => !!(w.label || w.readonly || D["label-icon"] || D["label-extra"])), je = a(() => w.label ? void 0 : A["aria-label"] ?? w.placeholder), Me = a(() => [
161
+ A["aria-describedby"],
162
+ w.hint && we,
163
+ w.errorMsg && Te
164
+ ].filter(Boolean).join(" ") || void 0), Ne = a(() => ke.value ? ["border-danger/50 bg-background focus-within:border-danger", Ce] : [
165
+ w.readonly ? "bg-surface-muted" : "bg-background",
166
+ "border-border focus-within:focus-ring",
167
+ !w.disabled && !w.readonly && "hover:border-accent-active"
168
+ ]), Pe = a(() => {
169
+ if (w.emptyText) return w.emptyText;
170
+ let e = L.value.trim();
171
+ return z.value && e ? `No matches for “${e}”` : "No suggestions";
172
+ });
173
+ function Fe(e, t) {
174
+ let n = t.toLowerCase();
175
+ return (e.label ?? e.value).toLowerCase().includes(n) || e.value.toLowerCase().includes(n);
176
+ }
177
+ function G(e) {
178
+ return w.allowCustom ? e : H.value.find((t) => t.value === e)?.label ?? e;
179
+ }
180
+ function K(e) {
181
+ return `${k}-opt-${e}`;
182
+ }
183
+ function q(e) {
184
+ return e.value === T.value;
185
+ }
186
+ function J(e = 0, t = 1) {
187
+ for (let n = e; n >= 0 && n < U.value.length; n += t) if (!U.value[n].disabled) return n;
188
+ return -1;
189
+ }
190
+ function Y() {
191
+ let e = Ee.value;
192
+ if (!e) return;
193
+ let n = e.getBoundingClientRect(), r = t(), i = r.bottom - n.bottom - 4 - 8, a = n.top - r.top - 4 - 8, [o, s] = w.placement === "top" ? [a, i] : [i, a], c = o < 180 && s > o, l = w.placement === "top" ? !c : c, u = Math.max(n.width, Math.min(S, r.width - 16)), d = Math.min(Math.max(F.value?.offsetWidth ?? n.width, n.width), u), f = n.left - r.left, p = {
194
+ left: f + d > r.width - 8 ? Math.max(8, n.right - r.left - d) : f,
195
+ minWidth: n.width,
196
+ maxWidth: u
197
+ };
198
+ V.value = l ? {
199
+ ...p,
200
+ bottom: r.bottom - n.top + 4,
201
+ maxHeight: Math.min(288, a)
202
+ } : {
203
+ ...p,
204
+ top: n.bottom + 4 - r.top,
205
+ maxHeight: Math.min(288, i)
206
+ };
207
+ }
208
+ function Ie() {
209
+ m(() => F.value?.querySelector(`#${CSS.escape(K(R.value))}`)?.scrollIntoView({ block: "nearest" }));
210
+ }
211
+ function X(e = "none") {
212
+ if (w.disabled || w.readonly || I.value) return;
213
+ z.value = !1, I.value = !0;
214
+ let t = U.value.findIndex(q);
215
+ e === "none" ? R.value = -1 : t >= 0 && !U.value[t].disabled ? R.value = t : R.value = e === "first" ? J() : J(U.value.length - 1, -1), Ie();
216
+ }
217
+ function Z() {
218
+ I.value = !1;
219
+ }
220
+ function Le() {
221
+ if (I.value) return Z();
222
+ X(), P.value?.focus();
223
+ }
224
+ function Re(e) {
225
+ let t = U.value.length;
226
+ if (!t) return;
227
+ let n = R.value < 0 ? e > 0 ? -1 : t : R.value;
228
+ for (let r = 0; r < t && (n = (n + e + t) % t, U.value[n].disabled); r++);
229
+ R.value = n, Ie();
230
+ }
231
+ function ze(e) {
232
+ e.disabled || (T.value = e.value, L.value = G(e.value), B.value = !1, E("select", e), Z());
233
+ }
234
+ function Be() {
235
+ if (w.allowCustom || !B.value) return;
236
+ let e = L.value.trim().toLowerCase();
237
+ if (!e) T.value = "";
238
+ else {
239
+ let t = H.value.find((t) => !t.disabled && (t.label.toLowerCase() === e || t.value.toLowerCase() === e));
240
+ t && t.value !== T.value && (T.value = t.value, E("select", t));
241
+ }
242
+ L.value = G(T.value), B.value = !1;
243
+ }
244
+ function Ve() {
245
+ L.value = "", T.value = "", B.value = !1, E("search", "");
246
+ }
247
+ function He(e) {
248
+ let t = e.target.value;
249
+ L.value = t, w.allowCustom ? T.value = t : B.value = !0, X(), z.value = !0, R.value = w.allowCustom ? -1 : J(), E("search", t);
250
+ }
251
+ function Ue(e) {
252
+ E("focus", e), w.openOnFocus && X();
253
+ }
254
+ function We(e) {
255
+ Z(), Be(), E("blur", e);
256
+ }
257
+ function Ge() {
258
+ w.openOnFocus && X();
259
+ }
260
+ function Ke(e) {
261
+ if (!(w.disabled || w.readonly || e.isComposing)) switch (e.key) {
262
+ case "ArrowDown":
263
+ e.preventDefault(), e.altKey ? X() : I.value ? Re(1) : X("first");
264
+ break;
265
+ case "ArrowUp":
266
+ e.preventDefault(), e.altKey ? Z() : I.value ? Re(-1) : X("last");
267
+ break;
268
+ case "Enter": {
269
+ if (!I.value) return;
270
+ let t = U.value[R.value];
271
+ t ? (e.preventDefault(), ze(t)) : (Z(), Be());
272
+ break;
273
+ }
274
+ case "Escape":
275
+ I.value ? (e.preventDefault(), Z()) : L.value && (e.preventDefault(), Ve());
276
+ break;
277
+ case "Home":
278
+ case "End":
279
+ case "ArrowLeft":
280
+ case "ArrowRight": R.value = -1;
281
+ }
282
+ }
283
+ function Q(e) {
284
+ e?.target instanceof Node && F.value?.contains(e.target) || Y();
285
+ }
286
+ function $() {
287
+ window.removeEventListener("scroll", Q, !0), window.removeEventListener("resize", Q);
288
+ }
289
+ return x(() => T.value, (e) => {
290
+ L.value = G(e ?? ""), B.value = !1;
291
+ }, { immediate: !0 }), x(H, () => {
292
+ B.value || (L.value = G(T.value ?? ""));
293
+ }), x(U, (e) => {
294
+ !w.allowCustom && z.value ? R.value = J() : R.value >= e.length && (R.value = -1), I.value && m(Y);
295
+ }), x(I, async (e) => {
296
+ if (!e) {
297
+ R.value = -1, $();
298
+ return;
299
+ }
300
+ Y(), window.addEventListener("scroll", Q, !0), window.addEventListener("resize", Q), await m(), Y();
301
+ }), ne($), p({ focus: () => P.value?.focus() }), (t, a) => (g(), c("div", ee(De.value, {
302
+ class: ["[:where(&)]:w-full", f.disabled && "opacity-50"],
303
+ "data-ac-ds": "",
304
+ "data-testid": "ac-combobox"
305
+ }), [
306
+ Ae.value ? (g(), c("div", {
307
+ key: 0,
308
+ class: h(["mb-2 flex items-center gap-1 text-base font-medium text-heading", f.labelClass])
309
+ }, [
310
+ v(t.$slots, "label-icon"),
311
+ f.label ? (g(), c("label", {
312
+ key: 0,
313
+ id: N,
314
+ for: j
315
+ }, y(f.label), 1)) : s("", !0),
316
+ f.readonly ? (g(), c("span", me, "(read only)")) : s("", !0),
317
+ v(t.$slots, "label-extra"),
318
+ f.required || f.requiredMark ? (g(), c("span", he, "*")) : s("", !0)
319
+ ], 2)) : s("", !0),
320
+ f.hint ? (g(), c("p", {
321
+ key: 1,
322
+ id: we,
323
+ class: "mb-2 text-base text-muted"
324
+ }, y(f.hint), 1)) : s("", !0),
325
+ l("div", {
326
+ ref_key: "field",
327
+ ref: Ee,
328
+ class: h(["relative flex w-full items-center rounded-10 border transition-[border-color,box-shadow,background-color] duration-200", [O[W.value].box, Ne.value]])
329
+ }, [l("input", ee({
330
+ id: j,
331
+ ref_key: "input",
332
+ ref: P
333
+ }, Oe.value, {
334
+ value: L.value,
335
+ type: "text",
336
+ role: "combobox",
337
+ autocomplete: "off",
338
+ "aria-autocomplete": "list",
339
+ "aria-expanded": I.value,
340
+ "aria-controls": M,
341
+ "aria-activedescendant": I.value && R.value >= 0 ? K(R.value) : void 0,
342
+ "aria-label": je.value,
343
+ "aria-describedby": Me.value,
344
+ "aria-invalid": ke.value || void 0,
345
+ "aria-required": f.required || f.requiredMark || void 0,
346
+ "aria-busy": f.loading || void 0,
347
+ placeholder: f.placeholder,
348
+ disabled: f.disabled,
349
+ readonly: f.readonly,
350
+ required: f.required,
351
+ class: ["block h-full w-full min-w-0 flex-1 rounded-10 bg-transparent pr-2 text-base font-normal text-heading outline-none placeholder:text-muted/80 disabled:cursor-not-allowed", [O[W.value].start, f.inputClass]],
352
+ onInput: He,
353
+ onKeydown: Ke,
354
+ onFocus: Ue,
355
+ onBlur: We,
356
+ onClick: Ge
357
+ }), null, 16, ge), l("span", { class: h(["flex h-full shrink-0 items-center gap-1 text-muted", O[W.value].end]) }, [f.loading ? (g(), o(e, {
358
+ key: 0,
359
+ class: "text-primary",
360
+ label: ""
361
+ })) : s("", !0), f.readonly ? s("", !0) : (g(), c("button", {
362
+ key: 1,
363
+ type: "button",
364
+ tabindex: "-1",
365
+ class: "inline-flex size-7 cursor-pointer items-center justify-center rounded-8 transition-colors hover:bg-accent-hover hover:text-primary disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-muted",
366
+ "aria-label": I.value ? "Hide suggestions" : "Show suggestions",
367
+ "aria-controls": M,
368
+ "aria-expanded": I.value,
369
+ disabled: f.disabled,
370
+ "data-testid": "ac-combobox-toggle",
371
+ onMousedown: a[0] ||= ue(() => {}, ["prevent"]),
372
+ onClick: Le
373
+ }, [(g(), o(ie(I.value ? b(pe) : b(fe)), {
374
+ class: "size-4",
375
+ "aria-hidden": "true"
376
+ }))], 40, _e))], 2)], 2),
377
+ f.errorMsg ? (g(), c("p", {
378
+ key: 2,
379
+ id: Te,
380
+ class: "mt-1 text-base text-danger-strong",
381
+ role: "alert"
382
+ }, y(f.errorMsg), 1)) : s("", !0),
383
+ v(t.$slots, "message"),
384
+ (g(), o(r, { to: "body" }, [d(i, {
385
+ "enter-active-class": "transition-opacity duration-100 ease-out motion-reduce:transition-none",
386
+ "enter-from-class": "opacity-0",
387
+ "leave-active-class": "transition-opacity duration-75 ease-in motion-reduce:transition-none",
388
+ "leave-to-class": "opacity-0"
389
+ }, {
390
+ default: le(() => [I.value ? (g(), c("div", {
391
+ key: 0,
392
+ ref_key: "panel",
393
+ ref: F,
394
+ class: "fixed z-[90] flex w-max flex-col overflow-hidden rounded-10 border border-border bg-background shadow-lg",
395
+ style: te({
396
+ top: V.value.top === void 0 ? void 0 : `${V.value.top}px`,
397
+ bottom: V.value.bottom === void 0 ? void 0 : `${V.value.bottom}px`,
398
+ left: `${V.value.left}px`,
399
+ minWidth: `${V.value.minWidth}px`,
400
+ maxWidth: `${V.value.maxWidth}px`,
401
+ maxHeight: `${V.value.maxHeight}px`
402
+ }),
403
+ "data-ac-ds": "",
404
+ "data-testid": "ac-combobox-panel",
405
+ onMousedown: a[1] ||= ue(() => {}, ["prevent"])
406
+ }, [l("ul", {
407
+ id: M,
408
+ role: "listbox",
409
+ "aria-labelledby": f.label ? N : void 0,
410
+ "aria-label": f.label ? void 0 : je.value,
411
+ "aria-busy": f.loading || void 0,
412
+ class: "ac-scrollbar max-h-60 min-h-0 flex-1 p-1"
413
+ }, [(g(!0), c(n, null, re(U.value, (e, n) => (g(), c("li", {
414
+ id: K(n),
415
+ key: e.value,
416
+ role: "option",
417
+ "aria-selected": q(e),
418
+ "aria-disabled": e.disabled || void 0,
419
+ class: h(["flex cursor-pointer items-start gap-2.5 rounded-6 px-4 py-2 text-base text-heading transition-colors", [e.disabled && "cursor-not-allowed opacity-50", n === R.value ? "bg-accent-hover" : q(e) && "bg-accent"]]),
420
+ onMouseenter: (t) => !e.disabled && (R.value = n),
421
+ onClick: (t) => ze(e)
422
+ }, [l("span", be, [v(t.$slots, "option", {
423
+ option: e,
424
+ selected: q(e),
425
+ active: n === R.value
426
+ }, () => [l("span", { class: h(["block truncate", q(e) && "font-medium text-primary-strong"]) }, y(e.label), 3), e.description ? (g(), c("span", xe, y(e.description), 1)) : s("", !0)])]), !t.$slots.option && q(e) ? (g(), o(b(de), {
427
+ key: 0,
428
+ class: "mt-0.5 size-4 shrink-0 text-primary",
429
+ "aria-hidden": "true"
430
+ })) : s("", !0)], 42, ye))), 128)), U.value.length ? s("", !0) : (g(), c("li", Se, [f.loading ? (g(), c(n, { key: 0 }, [u(y(f.loadingText), 1)], 64)) : v(t.$slots, "empty", { query: L.value.trim() }, () => [u(y(Pe.value), 1)], void 0, 1)]))], 8, ve)], 36)) : s("", !0)]),
431
+ _: 3
432
+ })]))
433
+ ], 16));
434
+ }
435
+ });
436
+ //#endregion
437
+ export { C as default };
@@ -0,0 +1,5 @@
1
+ import e from "./AcPopover.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/lib/components/AcPopover.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
@@ -0,0 +1,71 @@
1
+ export interface Props {
2
+ /** Text of the default trigger button, e.g. "Filters". Without a `title` it is also the panel's accessible name. */
3
+ label?: string;
4
+ /** Heading at the top of the panel. It names the dialog for screen readers. */
5
+ title?: string;
6
+ /** Shows this number in a badge on the default trigger and turns it primary, e.g. the count of active filters. Hidden at 0. */
7
+ count?: number;
8
+ /** Which edge of the trigger the panel lines up with. Use `end` for a trigger at the right of a toolbar. */
9
+ align?: "start" | "end";
10
+ /** Preferred side. The panel flips when there isn't room. */
11
+ placement?: "bottom" | "top";
12
+ /** Panel width: `sm` 240px, `md` 288px, `lg` 384px, or a number of px. It never grows wider than the viewport minus 16px. */
13
+ width?: "sm" | "md" | "lg" | number;
14
+ /** Disables the default trigger and stops the panel opening. */
15
+ disabled?: boolean;
16
+ }
17
+ type __VLS_Props = Props;
18
+ type __VLS_Slots = {
19
+ /** Custom trigger, usually an `AcButton`. Bind `@click="toggle"`; the popover adds the ARIA attributes. */
20
+ trigger?: (props: {
21
+ open: boolean;
22
+ toggle: () => void;
23
+ }) => unknown;
24
+ /** A 16px icon before the default trigger's label, e.g. `Filter`. */
25
+ icon?: () => unknown;
26
+ /** The panel's content: form controls, text or links. It scrolls when the panel is taller than the room left. */
27
+ default?: () => unknown;
28
+ /** Right-aligned buttons under a divider, e.g. Apply. */
29
+ footer?: () => unknown;
30
+ /** Left side of the footer, e.g. a Reset link. */
31
+ "footer-left"?: () => unknown;
32
+ };
33
+ declare function show(): void;
34
+ declare function toggle(): void;
35
+ type __VLS_ModelProps = {
36
+ /** Whether the panel is open. Bind with `v-model:open` to open or close it from code, e.g. after Apply. */
37
+ "open"?: boolean;
38
+ };
39
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
40
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
41
+ /** Opens the panel and moves focus into it. */
42
+ open: typeof show;
43
+ /** Closes the panel; focus returns to the trigger if it was inside. */
44
+ close: () => void;
45
+ /** Opens or closes the panel. */
46
+ toggle: typeof toggle;
47
+ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
48
+ open: () => any;
49
+ "update:open": (value: boolean) => any;
50
+ close: () => any;
51
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
52
+ onOpen?: (() => any) | undefined;
53
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
54
+ onClose?: (() => any) | undefined;
55
+ }>, {
56
+ label: string;
57
+ title: string;
58
+ disabled: boolean;
59
+ width: "sm" | "md" | "lg" | number;
60
+ placement: "bottom" | "top";
61
+ align: "start" | "end";
62
+ count: number;
63
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
64
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
65
+ declare const _default: typeof __VLS_export;
66
+ export default _default;
67
+ type __VLS_WithSlots<T, S> = T & {
68
+ new (): {
69
+ $slots: S;
70
+ };
71
+ };