vlite3 0.7.7 → 0.7.9

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.
@@ -1,13 +1,14 @@
1
- import { defineComponent as P, ref as g, computed as r, watch as U, openBlock as s, createBlock as m, unref as y, withCtx as v, createVNode as x, createElementVNode as d, normalizeClass as M, createElementBlock as h, toDisplayString as w, Fragment as I, renderList as q, withModifiers as T, createCommentVNode as V, createTextVNode as G } from "vue";
2
- import S from "../Icon.vue.js";
3
- import J from "../Dropdown/Dropdown.vue.js";
4
- import K from "../Dropdown/DropdownMenu.vue.js";
5
- import { $t as k } from "../../utils/i18n.js";
1
+ import { defineComponent as F, ref as x, computed as r, watch as $, openBlock as s, createBlock as f, unref as v, withCtx as p, createVNode as V, createElementVNode as d, normalizeClass as M, createElementBlock as h, toDisplayString as w, Fragment as I, renderList as P, withModifiers as T, createCommentVNode as S, createTextVNode as R } from "vue";
2
+ import k from "../Icon.vue.js";
3
+ import U from "../Dropdown/Dropdown.vue.js";
4
+ import q from "../Dropdown/DropdownMenu.vue.js";
5
+ import { $t as O } from "../../utils/i18n.js";
6
6
  import z from "../Badge.vue.js";
7
- const Q = { class: "flex flex-wrap gap-1.5 items-center flex-1 min-w-0 py-0.5" }, R = {
7
+ import { useMultiSelectHydration as G } from "./composables/useMultiSelectHydration.js";
8
+ const J = { class: "flex flex-wrap gap-1.5 items-center flex-1 min-w-0 py-0.5" }, K = {
8
9
  key: 0,
9
10
  class: "text-muted-foreground pl-1"
10
- }, W = { class: "truncate" }, X = ["onClick"], Y = { class: "flex items-center gap-2 pl-2 shrink-0 text-muted-foreground" }, ne = /* @__PURE__ */ P({
11
+ }, Q = { class: "truncate" }, W = ["onClick"], X = { class: "flex items-center gap-2 pl-2 shrink-0 text-muted-foreground" }, oe = /* @__PURE__ */ F({
11
12
  __name: "MultiSelect",
12
13
  props: {
13
14
  modelValue: { default: () => [] },
@@ -27,139 +28,136 @@ const Q = { class: "flex flex-wrap gap-1.5 items-center flex-1 min-w-0 py-0.5" }
27
28
  layout: { default: "default" }
28
29
  },
29
30
  emits: ["update:modelValue", "change", "load-more", "search"],
30
- setup(o, { emit: E }) {
31
- const a = o, i = E, c = g(!1), N = r(() => {
32
- if (a.placeholderI18n) return k(a.placeholderI18n);
33
- if (a.placeholder) return a.placeholder;
34
- const e = k("vlite.multiSelect.placeholder");
31
+ setup(n, { emit: L }) {
32
+ const l = n, i = L, c = x(!1), N = r(() => {
33
+ if (l.placeholderI18n) return O(l.placeholderI18n);
34
+ if (l.placeholder) return l.placeholder;
35
+ const e = O("vlite.multiSelect.placeholder");
35
36
  return e !== "vlite.multiSelect.placeholder" ? e : "Select items...";
36
- }), p = r(() => a.options ? a.options.map((e) => typeof e == "string" || typeof e == "number" ? { label: String(e), value: String(e) } : e) : []), u = g(/* @__PURE__ */ new Map()), b = g(!1), j = async (e) => {
37
- if (!a.fetchSelected || !e?.length) return;
38
- const t = e.filter((l) => {
39
- const n = u.value.has(l), C = p.value.some(($) => ($.value ?? $.label) === l);
40
- return !n && !C;
41
- });
42
- if (t.length) {
43
- b.value = !0;
44
- try {
45
- (await a.fetchSelected(t)).forEach((n) => {
46
- u.value.set(n.value ?? n.label, n);
47
- });
48
- } catch (l) {
49
- console.error("[MultiSelect] Hydration failed:", l);
50
- } finally {
51
- b.value = !1;
52
- }
53
- }
54
- };
55
- U(
56
- () => a.modelValue,
37
+ }), b = r(() => l.options ? l.options.map((e) => typeof e == "string" || typeof e == "number" ? { label: String(e), value: String(e) } : e) : []), B = x(!1), g = x(!1);
38
+ $(
39
+ b,
57
40
  (e) => {
58
- j(e || []);
41
+ !B.value && e.length > 0 && (B.value = !0, setTimeout(() => {
42
+ g.value = !0, u.hydrateSelected(l.modelValue || []);
43
+ }, 10));
59
44
  },
60
- { immediate: !0, deep: !0 }
45
+ { immediate: !0 }
61
46
  );
62
- const O = r(() => {
63
- const e = [...p.value], t = new Set(e.map((l) => l.value ?? l.label));
64
- return u.value.forEach((l, n) => {
65
- t.has(n) || (e.unshift(l), t.add(n));
47
+ const y = r(() => {
48
+ const e = [...b.value], t = new Set(e.map((a) => a.value ?? a.label));
49
+ return u.selectedBuffer.value.forEach((a, o) => {
50
+ t.has(o) || (e.unshift(a), t.add(o));
66
51
  }), e;
67
- }), f = r(() => O.value.filter((e) => {
52
+ }), u = G({
53
+ fetchSelected: l.fetchSelected,
54
+ getValues: () => l.modelValue || [],
55
+ getOptions: () => y.value,
56
+ isInitialLoadDone: () => g.value
57
+ });
58
+ $(
59
+ () => l.modelValue,
60
+ (e) => {
61
+ g.value && u.hydrateSelected(e || []);
62
+ },
63
+ { deep: !0 }
64
+ );
65
+ const m = r(() => y.value.filter((e) => {
68
66
  const t = e.value ?? e.label;
69
- return a.modelValue.includes(t);
70
- })), H = r(() => f.value.slice(0, a.maxVisible)), B = r(() => f.value.length - a.maxVisible), L = (e) => {
67
+ return l.modelValue.includes(t);
68
+ })), E = r(() => m.value.slice(0, l.maxVisible)), C = r(() => m.value.length - l.maxVisible), j = (e) => {
71
69
  const t = e.value ?? e.label;
72
- u.value.has(t) || u.value.set(t, e);
73
- const l = [...a.modelValue], n = l.indexOf(t);
74
- n === -1 ? l.push(t) : l.splice(n, 1), i("update:modelValue", l), i("change", l);
75
- }, A = (e) => {
76
- const t = a.modelValue.filter((l) => l !== e);
70
+ u.selectedBuffer.value.has(t) || u.selectedBuffer.value.set(t, e);
71
+ const a = [...l.modelValue], o = a.indexOf(t);
72
+ o === -1 ? a.push(t) : a.splice(o, 1), i("update:modelValue", a), i("change", a);
73
+ }, D = (e) => {
74
+ const t = l.modelValue.filter((a) => a !== e);
77
75
  i("update:modelValue", t), i("change", t);
78
- }, D = () => {
76
+ }, H = () => {
79
77
  i("update:modelValue", []), i("change", []);
80
- }, F = r(() => [
78
+ }, A = r(() => [
81
79
  "flex items-center justify-between w-full px-3 py-1.5 rounded-md border text-sm transition-colors cursor-pointer",
82
- a.disabled ? "opacity-50 cursor-not-allowed bg-muted" : a.variant === "floating" ? "bg-transparent text-foreground" : "bg-background hover:bg-gray-50/70",
83
- a.variant === "outline" || a.variant === "floating" ? "border-input" : "border-transparent bg-muted",
80
+ l.disabled ? "opacity-50 cursor-not-allowed bg-muted" : l.variant === "floating" ? "bg-transparent text-foreground" : "bg-background hover:bg-gray-50/70",
81
+ l.variant === "outline" || l.variant === "floating" ? "border-input" : "border-transparent bg-muted",
84
82
  c.value ? "border-primary/20" : ""
85
83
  ].join(" "));
86
- return r(() => a.size === "sm" ? "xs" : "sm"), (e, t) => (s(), m(y(J), {
84
+ return r(() => l.size === "sm" ? "xs" : "sm"), (e, t) => (s(), f(v(U), {
87
85
  isOpen: c.value,
88
- "onUpdate:isOpen": t[3] || (t[3] = (l) => c.value = l),
86
+ "onUpdate:isOpen": t[3] || (t[3] = (a) => c.value = a),
89
87
  "close-on-select": !1,
90
88
  selectable: !0,
91
- disabled: o.disabled
89
+ disabled: n.disabled
92
90
  }, {
93
- trigger: v(({ isOpen: l }) => [
91
+ trigger: p(({ isOpen: a }) => [
94
92
  d("div", {
95
- class: M(F.value)
93
+ class: M(A.value)
96
94
  }, [
97
- d("div", Q, [
98
- f.value.length === 0 ? (s(), h("span", R, w(N.value), 1)) : (s(), h(I, { key: 1 }, [
99
- (s(!0), h(I, null, q(H.value, (n) => (s(), m(z, {
100
- key: n.value,
95
+ d("div", J, [
96
+ m.value.length === 0 ? (s(), h("span", K, w(N.value), 1)) : (s(), h(I, { key: 1 }, [
97
+ (s(!0), h(I, null, P(E.value, (o) => (s(), f(z, {
98
+ key: o.value,
101
99
  variant: "secondary",
102
100
  class: "gap-1 pr-1 truncate max-w-[150px]"
103
101
  }, {
104
- default: v(() => [
105
- d("span", W, w(n.labelI18n ? y(k)(n.labelI18n) : n.label), 1),
106
- o.disabled ? V("", !0) : (s(), h("button", {
102
+ default: p(() => [
103
+ d("span", Q, w(o.labelI18n ? v(O)(o.labelI18n) : o.label), 1),
104
+ n.disabled ? S("", !0) : (s(), h("button", {
107
105
  key: 0,
108
106
  type: "button",
109
- onClick: T((C) => A(n.value), ["stop"]),
107
+ onClick: T((Y) => D(o.value), ["stop"]),
110
108
  class: "hover:bg-destructive/10 hover:text-destructive rounded-full p-0.5 transition-colors"
111
109
  }, [
112
- x(S, {
110
+ V(k, {
113
111
  icon: "lucide:x",
114
112
  class: "w-3 h-3"
115
113
  })
116
- ], 8, X))
114
+ ], 8, W))
117
115
  ]),
118
116
  _: 2
119
117
  }, 1024))), 128)),
120
- B.value > 0 ? (s(), m(z, {
118
+ C.value > 0 ? (s(), f(z, {
121
119
  key: 0,
122
120
  variant: "secondary",
123
121
  class: "font-normal text-muted-foreground"
124
122
  }, {
125
- default: v(() => [
126
- G(" +" + w(B.value), 1)
123
+ default: p(() => [
124
+ R(" +" + w(C.value), 1)
127
125
  ]),
128
126
  _: 1
129
- })) : V("", !0)
127
+ })) : S("", !0)
130
128
  ], 64))
131
129
  ]),
132
- d("div", Y, [
133
- f.value.length > 0 && !o.disabled ? (s(), m(S, {
130
+ d("div", X, [
131
+ m.value.length > 0 && !n.disabled ? (s(), f(k, {
134
132
  key: 0,
135
133
  icon: "lucide:x",
136
134
  class: "w-4 h-4 hover:text-foreground transition-colors",
137
- onClick: T(D, ["stop"])
138
- })) : V("", !0),
135
+ onClick: T(H, ["stop"])
136
+ })) : S("", !0),
139
137
  t[4] || (t[4] = d("div", { class: "w-px h-4 bg-border mx-0.5" }, null, -1)),
140
- x(S, {
138
+ V(k, {
141
139
  icon: "lucide:chevron-down",
142
- class: M(["w-4 h-4 transition-transform duration-200", { "rotate-180": l }])
140
+ class: M(["w-4 h-4 transition-transform duration-200", { "rotate-180": a }])
143
141
  }, null, 8, ["class"])
144
142
  ])
145
143
  ], 2)
146
144
  ]),
147
- default: v(() => [
148
- x(y(K), {
149
- options: p.value,
150
- cachedOptions: O.value,
151
- selected: o.modelValue,
145
+ default: p(() => [
146
+ V(v(q), {
147
+ options: b.value,
148
+ cachedOptions: y.value,
149
+ selected: n.modelValue,
152
150
  class: "min-w-[300px]",
153
- loading: o.loading || b.value,
154
- hasMore: o.hasMore,
155
- searchable: o.searchable,
156
- remote: o.remote,
157
- debounceTime: o.debounceTime,
158
- layout: o.layout,
159
- onSelect: L,
160
- onClose: t[0] || (t[0] = (l) => c.value = !1),
161
- onLoadMore: t[1] || (t[1] = (l) => e.$emit("load-more")),
162
- onSearch: t[2] || (t[2] = (l) => e.$emit("search", l))
151
+ loading: n.loading || v(u).isHydrating.value,
152
+ hasMore: n.hasMore,
153
+ searchable: n.searchable,
154
+ remote: n.remote,
155
+ debounceTime: n.debounceTime,
156
+ layout: n.layout,
157
+ onSelect: j,
158
+ onClose: t[0] || (t[0] = (a) => c.value = !1),
159
+ onLoadMore: t[1] || (t[1] = (a) => e.$emit("load-more")),
160
+ onSearch: t[2] || (t[2] = (a) => e.$emit("search", a))
163
161
  }, null, 8, ["options", "cachedOptions", "selected", "loading", "hasMore", "searchable", "remote", "debounceTime", "layout"])
164
162
  ]),
165
163
  _: 1
@@ -167,5 +165,5 @@ const Q = { class: "flex flex-wrap gap-1.5 items-center flex-1 min-w-0 py-0.5" }
167
165
  }
168
166
  });
169
167
  export {
170
- ne as default
168
+ oe as default
171
169
  };
@@ -0,0 +1,97 @@
1
+ import { IDropdownOption } from '../../../types';
2
+ interface UseMultiSelectHydrationOptions {
3
+ getValues: () => any[];
4
+ getOptions: () => IDropdownOption[];
5
+ fetchSelected?: (ids: any[]) => Promise<IDropdownOption[]>;
6
+ isInitialLoadDone: () => boolean;
7
+ }
8
+ /**
9
+ * Handles hydration of selected values that are not present in the current options list.
10
+ * Waits until initial options load is complete before checking for missing IDs.
11
+ */
12
+ export declare function useMultiSelectHydration(opts: UseMultiSelectHydrationOptions): {
13
+ selectedBuffer: import('vue').Ref<Map<any, {
14
+ label: string;
15
+ labelI18n?: string;
16
+ value?: any;
17
+ subtitle?: string;
18
+ subtitleI18n?: string;
19
+ description?: string;
20
+ descriptionI18n?: string;
21
+ icon?: string;
22
+ emoji?: string;
23
+ disabled?: {
24
+ valueOf: () => boolean;
25
+ };
26
+ iconClass?: string;
27
+ iconStyle?: any;
28
+ length?: number;
29
+ values?: any;
30
+ data?: any;
31
+ class?: string;
32
+ triggerClass?: string;
33
+ children?: /*elided*/ any[];
34
+ key?: string;
35
+ position?: any;
36
+ offset?: [number, number];
37
+ showChevron?: boolean;
38
+ confirmation?: boolean | {
39
+ title?: string;
40
+ description?: string;
41
+ confirmText?: string;
42
+ cancelText?: string;
43
+ variant?: "danger" | "primary" | "warning" | "success" | "info";
44
+ };
45
+ onSelect?: (payload: {
46
+ value: any;
47
+ option: IDropdownOption;
48
+ data: IDropdownOption[];
49
+ values?: any;
50
+ }) => void;
51
+ _originalOption?: /*elided*/ any;
52
+ _path?: /*elided*/ any[];
53
+ }> & Omit<Map<any, IDropdownOption>, keyof Map<any, any>>, Map<any, IDropdownOption> | (Map<any, {
54
+ label: string;
55
+ labelI18n?: string;
56
+ value?: any;
57
+ subtitle?: string;
58
+ subtitleI18n?: string;
59
+ description?: string;
60
+ descriptionI18n?: string;
61
+ icon?: string;
62
+ emoji?: string;
63
+ disabled?: {
64
+ valueOf: () => boolean;
65
+ };
66
+ iconClass?: string;
67
+ iconStyle?: any;
68
+ length?: number;
69
+ values?: any;
70
+ data?: any;
71
+ class?: string;
72
+ triggerClass?: string;
73
+ children?: /*elided*/ any[];
74
+ key?: string;
75
+ position?: any;
76
+ offset?: [number, number];
77
+ showChevron?: boolean;
78
+ confirmation?: boolean | {
79
+ title?: string;
80
+ description?: string;
81
+ confirmText?: string;
82
+ cancelText?: string;
83
+ variant?: "danger" | "primary" | "warning" | "success" | "info";
84
+ };
85
+ onSelect?: (payload: {
86
+ value: any;
87
+ option: IDropdownOption;
88
+ data: IDropdownOption[];
89
+ values?: any;
90
+ }) => void;
91
+ _originalOption?: /*elided*/ any;
92
+ _path?: /*elided*/ any[];
93
+ }> & Omit<Map<any, IDropdownOption>, keyof Map<any, any>>)>;
94
+ isHydrating: import('vue').Ref<boolean, boolean>;
95
+ hydrateSelected: (values: any[]) => Promise<void>;
96
+ };
97
+ export {};
@@ -0,0 +1,30 @@
1
+ import { ref as s } from "vue";
2
+ function h(n) {
3
+ const r = s(/* @__PURE__ */ new Map()), l = s(!1);
4
+ return {
5
+ selectedBuffer: r,
6
+ isHydrating: l,
7
+ hydrateSelected: async (c) => {
8
+ if (!n.fetchSelected || !c?.length || !n.isInitialLoadDone()) return;
9
+ const f = n.getOptions(), a = c.filter((e) => {
10
+ const t = r.value.has(e), o = f.some((i) => (i.value ?? i.label) === e);
11
+ return !t && !o;
12
+ });
13
+ if (a.length) {
14
+ l.value = !0;
15
+ try {
16
+ (await n.fetchSelected(a)).forEach((t) => {
17
+ r.value.set(t.value ?? t.label, t);
18
+ });
19
+ } catch (e) {
20
+ console.error("[MultiSelect] Hydration failed:", e);
21
+ } finally {
22
+ l.value = !1;
23
+ }
24
+ }
25
+ }
26
+ };
27
+ }
28
+ export {
29
+ h as useMultiSelectHydration
30
+ };
@@ -1 +1,2 @@
1
1
  export { default as MultiSelect } from './MultiSelect.vue';
2
+ export * from './composables/useMultiSelectHydration';
@@ -11,7 +11,7 @@ import "v-datepicker-lite";
11
11
  import "v-datepicker-lite/style.css";
12
12
  import "@jaames/iro";
13
13
  import "@vueuse/core";
14
- /* empty css */
14
+ /* empty css */
15
15
  import "iconify-icon-picker";
16
16
  import "iconify-icon-picker/style.css";
17
17
  /* empty css */