@ulu/frontend-vue 0.2.0-beta.12 → 0.2.0-beta.14
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.
- package/dist/components/collapsible/UluTabGroup.vue.d.ts +2 -0
- package/dist/components/collapsible/UluTabGroup.vue.d.ts.map +1 -1
- package/dist/components/collapsible/UluTabGroup.vue.js +23 -14
- package/dist/components/systems/facets/useFacets.d.ts +3 -0
- package/dist/components/systems/facets/useFacets.d.ts.map +1 -1
- package/dist/components/systems/facets/useFacets.js +124 -112
- package/lib/components/collapsible/UluTabGroup.vue +21 -6
- package/lib/components/systems/facets/useFacets.js +33 -17
- package/package.json +1 -1
|
@@ -5,9 +5,11 @@ type __VLS_WithTemplateSlots<T, S> = T & (new () => {
|
|
|
5
5
|
});
|
|
6
6
|
declare const __VLS_component: import('vue').DefineComponent<{}, {
|
|
7
7
|
vertical: boolean;
|
|
8
|
+
modifiers?: string | unknown[] | undefined;
|
|
8
9
|
defaultIndex?: number | undefined;
|
|
9
10
|
$props: {
|
|
10
11
|
readonly vertical?: boolean | undefined;
|
|
12
|
+
readonly modifiers?: string | unknown[] | undefined;
|
|
11
13
|
readonly defaultIndex?: number | undefined;
|
|
12
14
|
};
|
|
13
15
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UluTabGroup.vue.d.ts","sourceRoot":"","sources":["../../../lib/components/collapsible/UluTabGroup.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UluTabGroup.vue.d.ts","sourceRoot":"","sources":["../../../lib/components/collapsible/UluTabGroup.vue"],"names":[],"mappings":"AAoBA;wBAmJqB,uBAAuB,CAAC,OAAO,eAAe,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;;6BAEtE,CAAC,EAAE,CAAC;;;AAVjC;;;;;;;;;2OAOG"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createBlock as
|
|
2
|
-
import { TabGroup as
|
|
3
|
-
|
|
1
|
+
import { createBlock as l, openBlock as i, unref as t, withCtx as n, createElementVNode as d, mergeProps as c, renderSlot as u, normalizeProps as f, guardReactiveProps as m } from "vue";
|
|
2
|
+
import { TabGroup as p } from "@headlessui/vue";
|
|
3
|
+
import { useModifiers as v } from "../../composables/useModifiers.js";
|
|
4
|
+
const h = /* @__PURE__ */ Object.assign({
|
|
4
5
|
inheritAttrs: !1
|
|
5
6
|
}, {
|
|
6
7
|
__name: "UluTabGroup",
|
|
@@ -12,26 +13,34 @@ const b = /* @__PURE__ */ Object.assign({
|
|
|
12
13
|
/**
|
|
13
14
|
* Whether or not to use vertical layout
|
|
14
15
|
*/
|
|
15
|
-
vertical: Boolean
|
|
16
|
+
vertical: Boolean,
|
|
17
|
+
/**
|
|
18
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
19
|
+
*/
|
|
20
|
+
modifiers: [String, Array]
|
|
16
21
|
},
|
|
17
22
|
setup(e) {
|
|
18
|
-
|
|
23
|
+
const a = e, { resolvedModifiers: s } = v({ props: a, baseClass: "tabs" });
|
|
24
|
+
return (r, b) => (i(), l(t(p), {
|
|
19
25
|
defaultIndex: e.defaultIndex,
|
|
20
26
|
vertical: e.vertical
|
|
21
27
|
}, {
|
|
22
|
-
default: n((
|
|
23
|
-
|
|
24
|
-
class:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
default: n((o) => [
|
|
29
|
+
d("div", c(r.$attrs, {
|
|
30
|
+
class: ["tabs", [
|
|
31
|
+
t(s),
|
|
32
|
+
{
|
|
33
|
+
"tabs--vertical": e.vertical
|
|
34
|
+
}
|
|
35
|
+
]]
|
|
36
|
+
}), [
|
|
37
|
+
u(r.$slots, "default", f(m(o)))
|
|
38
|
+
], 16)
|
|
30
39
|
]),
|
|
31
40
|
_: 3
|
|
32
41
|
}, 8, ["defaultIndex", "vertical"]));
|
|
33
42
|
}
|
|
34
43
|
});
|
|
35
44
|
export {
|
|
36
|
-
|
|
45
|
+
h as default
|
|
37
46
|
};
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* @param {Object} [options.urlSync] - Optional configuration to sync state with URL.
|
|
15
15
|
* @param {import('vue-router').Router} [options.urlSync.router] - The Vue Router instance.
|
|
16
16
|
* @param {import('vue-router').RouteLocationNormalizedLoaded} [options.urlSync.route] - The current route instance.
|
|
17
|
+
* @param {Function} [options.isPinned] - A function that receives an item and returns true if it should be pinned to the top of the results.
|
|
17
18
|
*/
|
|
18
19
|
export function useFacets(allItems: import('vue').Ref<Array<Object>>, options?: {
|
|
19
20
|
initialFacets?: any[] | undefined;
|
|
@@ -29,6 +30,7 @@ export function useFacets(allItems: import('vue').Ref<Array<Object>>, options?:
|
|
|
29
30
|
router?: import('vue-router').Router | undefined;
|
|
30
31
|
route?: import('vue-router').RouteLocationNormalizedLoadedGeneric | undefined;
|
|
31
32
|
} | undefined;
|
|
33
|
+
isPinned?: Function | undefined;
|
|
32
34
|
}): {
|
|
33
35
|
facets: import('vue').Ref<never[], never[]>;
|
|
34
36
|
searchValue: import('vue').Ref<string, string>;
|
|
@@ -51,6 +53,7 @@ export function useFacets(allItems: import('vue').Ref<Array<Object>>, options?:
|
|
|
51
53
|
} | undefined;
|
|
52
54
|
}>;
|
|
53
55
|
displayItems: import('vue').ComputedRef<any>;
|
|
56
|
+
pinnedItems: import('vue').ComputedRef<any[] | never[]>;
|
|
54
57
|
selectedFacets: import('vue').ComputedRef<any[]>;
|
|
55
58
|
clearFilters: () => void;
|
|
56
59
|
handleFacetChange: ({ groupUid, facetUid, selected }: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFacets.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/facets/useFacets.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useFacets.d.ts","sourceRoot":"","sources":["../../../../lib/components/systems/facets/useFacets.js"],"names":[],"mappings":"AAiHA;;;;;;;;;;;;;;;;;GAiBG;AACH,oCAhBW,OAAO,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,YAExC;IAAwB,aAAa;IACb,WAAW;IACV,kBAAkB;IAClB,eAAe;IACd,cAAc;IACf,cAAc;IACd,aAAa;IACX,YAAY;IACd,SAAS;IACT,OAAO;;;;IAGL,QAAQ;CACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+WA"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { ref as T, computed as
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import { ref as T, computed as E, watch as $, watchPostEffect as X } from "vue";
|
|
2
|
+
import Y from "fuse.js";
|
|
3
|
+
const Z = (u) => typeof u == "function";
|
|
4
|
+
function ee(u) {
|
|
4
5
|
const h = /* @__PURE__ */ new Set();
|
|
5
6
|
for (const d of u)
|
|
6
|
-
for (const
|
|
7
|
-
h.add(
|
|
7
|
+
for (const a of d)
|
|
8
|
+
h.add(a);
|
|
8
9
|
return h;
|
|
9
10
|
}
|
|
10
11
|
function k(u) {
|
|
11
12
|
if (!u || u.length === 0) return /* @__PURE__ */ new Set();
|
|
12
|
-
const h = u.sort((
|
|
13
|
-
for (let
|
|
13
|
+
const h = u.sort((a, S) => a.size - S.size), d = new Set(h[0]);
|
|
14
|
+
for (let a = 1; a < h.length; a++) {
|
|
14
15
|
for (const S of d)
|
|
15
|
-
h[
|
|
16
|
+
h[a].has(S) || d.delete(S);
|
|
16
17
|
if (d.size === 0) break;
|
|
17
18
|
}
|
|
18
19
|
return d;
|
|
@@ -20,207 +21,218 @@ function k(u) {
|
|
|
20
21
|
function O(u, h, d) {
|
|
21
22
|
if (!u || u.length === 0)
|
|
22
23
|
return d;
|
|
23
|
-
const
|
|
24
|
-
const z = S.children.map((
|
|
25
|
-
const v = `${S.uid}:${
|
|
24
|
+
const a = u.map((S) => {
|
|
25
|
+
const z = S.children.map((V) => {
|
|
26
|
+
const v = `${S.uid}:${V.uid}`;
|
|
26
27
|
return h.get(v) || /* @__PURE__ */ new Set();
|
|
27
28
|
});
|
|
28
|
-
return S.match === "all" ? k(z) :
|
|
29
|
+
return S.match === "all" ? k(z) : ee(z);
|
|
29
30
|
});
|
|
30
|
-
return k(
|
|
31
|
+
return k(a);
|
|
31
32
|
}
|
|
32
|
-
function
|
|
33
|
+
function te(u, h) {
|
|
33
34
|
return !h || !Array.isArray(h) ? [] : h.map((d) => {
|
|
34
|
-
const
|
|
35
|
+
const a = /* @__PURE__ */ new Set(), S = d.getValue || ((v) => v[d.uid]);
|
|
35
36
|
u.forEach((v) => {
|
|
36
|
-
const
|
|
37
|
-
Array.isArray(
|
|
37
|
+
const F = S(v);
|
|
38
|
+
Array.isArray(F) ? F.forEach((A) => A && a.add(A)) : F && a.add(F);
|
|
38
39
|
});
|
|
39
|
-
const z = d.getLabel || ((v) => v),
|
|
40
|
+
const z = d.getLabel || ((v) => v), V = [...a].map((v) => ({
|
|
40
41
|
uid: v,
|
|
41
42
|
label: z(v),
|
|
42
43
|
selected: !1
|
|
43
44
|
}));
|
|
44
|
-
return
|
|
45
|
+
return V.sort((v, F) => String(v.label).localeCompare(String(F.label))), {
|
|
45
46
|
...d,
|
|
46
|
-
children:
|
|
47
|
+
children: V
|
|
47
48
|
};
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
|
-
function
|
|
51
|
+
function re(u, h = {}) {
|
|
51
52
|
const {
|
|
52
53
|
initialFacets: d,
|
|
53
|
-
facetFields:
|
|
54
|
+
facetFields: a,
|
|
54
55
|
initialSearchValue: S = "",
|
|
55
56
|
initialSortType: z = "az",
|
|
56
|
-
noDefaultSorts:
|
|
57
|
+
noDefaultSorts: V = !1,
|
|
57
58
|
extraSortTypes: v = {},
|
|
58
|
-
searchOptions:
|
|
59
|
-
getSortValue:
|
|
59
|
+
searchOptions: F = {},
|
|
60
|
+
getSortValue: A = (e) => e.title || e.label || "",
|
|
60
61
|
countMode: q = "none",
|
|
61
62
|
// 'none', 'simple', 'intuitive'
|
|
62
|
-
urlSync: U
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
urlSync: U,
|
|
64
|
+
isPinned: B
|
|
65
|
+
} = h, _ = (e) => e.sort((t, r) => {
|
|
66
|
+
const n = A(t), s = A(r);
|
|
65
67
|
return n && s ? String(n).localeCompare(String(s)) : n ? -1 : s ? 1 : 0;
|
|
66
|
-
}),
|
|
67
|
-
az: { text: "A-Z", sort:
|
|
68
|
-
za: { text: "Z-A", sort: (e) =>
|
|
68
|
+
}), j = {
|
|
69
|
+
az: { text: "A-Z", sort: _ },
|
|
70
|
+
za: { text: "Z-A", sort: (e) => _(e).reverse() }
|
|
69
71
|
};
|
|
70
|
-
function
|
|
72
|
+
function D(e) {
|
|
71
73
|
return (e || []).map((t) => ({
|
|
72
74
|
...t,
|
|
73
75
|
open: t.open || !1,
|
|
74
|
-
children: t.children.map((
|
|
75
|
-
...
|
|
76
|
-
selected:
|
|
76
|
+
children: t.children.map((r) => ({
|
|
77
|
+
...r,
|
|
78
|
+
selected: r.selected || !1
|
|
77
79
|
})),
|
|
78
80
|
selectedCount: 0
|
|
79
81
|
}));
|
|
80
82
|
}
|
|
81
|
-
const f = T([]), x = T(S),
|
|
82
|
-
...
|
|
83
|
+
const f = T([]), x = T(S), I = T(z), G = E(() => !a || !u.value?.length ? null : te(u.value, a)), J = E(() => ({
|
|
84
|
+
...V ? {} : j,
|
|
83
85
|
...v
|
|
84
|
-
})), M =
|
|
86
|
+
})), M = E(() => {
|
|
85
87
|
const e = /* @__PURE__ */ new Map(), t = y.value;
|
|
86
|
-
if (!t || !
|
|
87
|
-
const
|
|
88
|
+
if (!t || !a) return e;
|
|
89
|
+
const r = new Map(a.map((n) => {
|
|
88
90
|
const s = n.getValue || ((o) => o[n.uid]);
|
|
89
91
|
return [n.uid, s];
|
|
90
92
|
}));
|
|
91
93
|
for (let n = 0; n < t.length; n++) {
|
|
92
94
|
const s = t[n];
|
|
93
|
-
for (const o of
|
|
94
|
-
const
|
|
95
|
-
for (const m of
|
|
95
|
+
for (const o of a) {
|
|
96
|
+
const l = r.get(o.uid)(s), c = Array.isArray(l) ? l : l ? [l] : [];
|
|
97
|
+
for (const m of c) {
|
|
96
98
|
const p = `${o.uid}:${m}`;
|
|
97
99
|
e.has(p) || e.set(p, /* @__PURE__ */ new Set()), e.get(p).add(n);
|
|
98
100
|
}
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
return e;
|
|
102
|
-
}),
|
|
104
|
+
}), R = E(() => ({
|
|
103
105
|
shouldSort: !0,
|
|
104
106
|
keys: ["title", "label", "description", "author"],
|
|
105
|
-
...
|
|
106
|
-
})), y =
|
|
107
|
+
...F
|
|
108
|
+
})), y = E(() => x.value?.length ? new Y(u.value, R.value).search(x.value).map((t) => t.item) : u.value), b = E(() => {
|
|
107
109
|
const e = [];
|
|
108
110
|
return f.value.forEach((t) => {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
+
const r = t.children.filter((n) => n.selected);
|
|
112
|
+
r.length > 0 && e.push({ ...t, children: r });
|
|
111
113
|
}), e;
|
|
112
|
-
}),
|
|
113
|
-
if (!
|
|
114
|
+
}), L = E(() => {
|
|
115
|
+
if (!b.value.length)
|
|
114
116
|
return y.value;
|
|
115
117
|
const e = M.value;
|
|
116
|
-
if (e.size === 0 && y.value.length > 0 &&
|
|
118
|
+
if (e.size === 0 && y.value.length > 0 && a?.length > 0)
|
|
117
119
|
return [];
|
|
118
|
-
const t = new Set(y.value.map((s, o) => o)),
|
|
119
|
-
for (const s of
|
|
120
|
+
const t = new Set(y.value.map((s, o) => o)), r = O(b.value, e, t), n = [];
|
|
121
|
+
for (const s of r)
|
|
120
122
|
n.push(y.value[s]);
|
|
121
123
|
return n;
|
|
122
|
-
}),
|
|
123
|
-
const e =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
}), N = E(() => {
|
|
125
|
+
const e = J.value[I.value]?.sort;
|
|
126
|
+
let t = Z(e) ? e([...L.value]) : [...L.value];
|
|
127
|
+
if (Z(B)) {
|
|
128
|
+
const r = [], n = [];
|
|
129
|
+
return t.forEach((s) => B(s) ? r.push(s) : n.push(s)), { pinned: r, unpinned: n, all: [...r, ...n] };
|
|
130
|
+
}
|
|
131
|
+
return { pinned: [], unpinned: t, all: t };
|
|
132
|
+
}), W = E(() => N.value.all), H = E(() => N.value.pinned);
|
|
133
|
+
function K() {
|
|
127
134
|
f.value.forEach((e) => {
|
|
128
135
|
e.children && e.children.forEach((t) => t.selected = !1), e.selectedCount = 0;
|
|
129
136
|
});
|
|
130
137
|
}
|
|
131
|
-
function
|
|
138
|
+
function P({ groupUid: e, facetUid: t, selected: r }) {
|
|
132
139
|
const n = f.value.find((s) => s.uid === e);
|
|
133
140
|
if (n) {
|
|
134
|
-
!n.multiple &&
|
|
141
|
+
!n.multiple && r && n.children.forEach((o) => {
|
|
135
142
|
o.uid !== t && (o.selected = !1);
|
|
136
143
|
});
|
|
137
144
|
const s = n.children.find((o) => o.uid === t);
|
|
138
|
-
s && (s.selected =
|
|
145
|
+
s && (s.selected = r), n.selectedCount = n.children.filter((o) => o.selected).length;
|
|
139
146
|
}
|
|
140
147
|
}
|
|
141
|
-
if ($(
|
|
142
|
-
const t =
|
|
143
|
-
t.forEach((
|
|
144
|
-
|
|
148
|
+
if ($(G, (e) => {
|
|
149
|
+
const t = D(d || e);
|
|
150
|
+
t.forEach((r) => {
|
|
151
|
+
r.selectedCount = r.children.filter((n) => n.selected).length;
|
|
145
152
|
}), f.value = t;
|
|
146
|
-
}, { immediate: !0 }), $([
|
|
147
|
-
if (!(q === "none" || !f.value.length) && !(e ===
|
|
153
|
+
}, { immediate: !0 }), $([b, y], ([e, t], [r, n]) => {
|
|
154
|
+
if (!(q === "none" || !f.value.length) && !(e === r && t === n)) {
|
|
148
155
|
if (q === "simple") {
|
|
149
156
|
const s = M.value;
|
|
150
|
-
if (s.size === 0 && y.value.length > 0 &&
|
|
157
|
+
if (s.size === 0 && y.value.length > 0 && a?.length > 0)
|
|
151
158
|
return;
|
|
152
|
-
const o = new Set(y.value.map((
|
|
153
|
-
f.value.forEach((
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
const p = `${
|
|
159
|
+
const o = new Set(y.value.map((i, l) => l));
|
|
160
|
+
f.value.forEach((i) => {
|
|
161
|
+
const l = e.filter((m) => m.uid !== i.uid), c = O(l, s, o);
|
|
162
|
+
i.children.forEach((m) => {
|
|
163
|
+
const p = `${i.uid}:${m.uid}`, g = s.get(p) || /* @__PURE__ */ new Set(), w = k([c, g]);
|
|
157
164
|
m.count = w.size;
|
|
158
165
|
});
|
|
159
166
|
});
|
|
160
167
|
} else if (q === "intuitive") {
|
|
161
168
|
const s = M.value;
|
|
162
|
-
if (s.size === 0 && y.value.length > 0 &&
|
|
169
|
+
if (s.size === 0 && y.value.length > 0 && a?.length > 0)
|
|
163
170
|
return;
|
|
164
|
-
const o = new Set(y.value.map((
|
|
165
|
-
f.value.forEach((
|
|
166
|
-
|
|
167
|
-
const m = `${
|
|
168
|
-
if (
|
|
169
|
-
if (
|
|
170
|
-
const g = k([
|
|
171
|
-
|
|
171
|
+
const o = new Set(y.value.map((l, c) => c)), i = O(e, s, o);
|
|
172
|
+
f.value.forEach((l) => {
|
|
173
|
+
l.children.forEach((c) => {
|
|
174
|
+
const m = `${l.uid}:${c.uid}`, p = s.get(m) || /* @__PURE__ */ new Set();
|
|
175
|
+
if (c.selected)
|
|
176
|
+
if (l.multiple) {
|
|
177
|
+
const g = k([i, p]);
|
|
178
|
+
c.count = g.size;
|
|
172
179
|
} else
|
|
173
|
-
|
|
180
|
+
c.count = i.size;
|
|
174
181
|
else {
|
|
175
182
|
const g = [];
|
|
176
183
|
for (const C of e)
|
|
177
184
|
g.push({ ...C, children: [...C.children] });
|
|
178
|
-
let w = g.find((C) => C.uid ===
|
|
179
|
-
w || (w = { ...
|
|
180
|
-
const
|
|
181
|
-
|
|
185
|
+
let w = g.find((C) => C.uid === l.uid);
|
|
186
|
+
w || (w = { ...l, children: [] }, g.push(w)), l.multiple ? w.children.push(c) : w.children = [c];
|
|
187
|
+
const Q = O(g, s, o);
|
|
188
|
+
c.count = Q.size;
|
|
182
189
|
}
|
|
183
190
|
});
|
|
184
191
|
});
|
|
185
192
|
}
|
|
186
193
|
}
|
|
187
194
|
}, { deep: !0, immediate: !0 }), U?.router && U?.route) {
|
|
188
|
-
const { router: e, route: t } = U,
|
|
189
|
-
if (!
|
|
190
|
-
const
|
|
191
|
-
delete
|
|
192
|
-
|
|
193
|
-
}), JSON.stringify(
|
|
195
|
+
const { router: e, route: t } = U, r = () => f.value && f.value.length > 0, n = () => {
|
|
196
|
+
if (!r()) return;
|
|
197
|
+
const i = { ...t.query };
|
|
198
|
+
delete i.sort, delete i.search, f.value.forEach((l) => delete i[l.uid]), I.value && I.value !== z && (i.sort = I.value), x.value && (i.search = x.value), b.value.forEach((l) => {
|
|
199
|
+
l.children.length > 0 && (i[l.uid] = l.children.map((c) => c.uid).join(","));
|
|
200
|
+
}), JSON.stringify(i) !== JSON.stringify(t.query) && e.push({ query: i });
|
|
194
201
|
}, s = () => {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
f.value.forEach((
|
|
199
|
-
const m =
|
|
200
|
-
|
|
201
|
-
}), f.value.forEach((
|
|
202
|
-
const m =
|
|
203
|
-
|
|
202
|
+
const i = t.query;
|
|
203
|
+
i.sort && (I.value = i.sort), i.search && (x.value = i.search);
|
|
204
|
+
const l = /* @__PURE__ */ new Map();
|
|
205
|
+
f.value.forEach((c) => {
|
|
206
|
+
const m = i[c.uid] ? i[c.uid].split(",") : [];
|
|
207
|
+
l.set(c.uid, new Set(m));
|
|
208
|
+
}), f.value.forEach((c) => {
|
|
209
|
+
const m = l.get(c.uid) || /* @__PURE__ */ new Set();
|
|
210
|
+
c.children.forEach((p) => {
|
|
204
211
|
const g = p.selected, w = m.has(p.uid);
|
|
205
|
-
g !== w &&
|
|
212
|
+
g !== w && P({ groupUid: c.uid, facetUid: p.uid, selected: w });
|
|
206
213
|
});
|
|
207
214
|
});
|
|
208
|
-
}, o =
|
|
215
|
+
}, o = X(() => {
|
|
209
216
|
f.value && f.value.length > 0 && (s(), o());
|
|
210
217
|
});
|
|
211
|
-
$(
|
|
218
|
+
$(
|
|
219
|
+
[I, x, b],
|
|
220
|
+
n,
|
|
221
|
+
{ deep: !0 }
|
|
222
|
+
), $(() => t.query, s);
|
|
212
223
|
}
|
|
213
224
|
return {
|
|
214
225
|
facets: f,
|
|
215
226
|
searchValue: x,
|
|
216
|
-
selectedSort:
|
|
217
|
-
sortTypes:
|
|
218
|
-
displayItems:
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
227
|
+
selectedSort: I,
|
|
228
|
+
sortTypes: J,
|
|
229
|
+
displayItems: W,
|
|
230
|
+
pinnedItems: H,
|
|
231
|
+
selectedFacets: b,
|
|
232
|
+
clearFilters: K,
|
|
233
|
+
handleFacetChange: P
|
|
222
234
|
};
|
|
223
235
|
}
|
|
224
236
|
export {
|
|
225
|
-
|
|
237
|
+
re as useFacets
|
|
226
238
|
};
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TabGroup
|
|
2
|
+
<TabGroup
|
|
3
|
+
v-slot="slotProps"
|
|
4
|
+
:defaultIndex="defaultIndex"
|
|
5
|
+
:vertical="vertical"
|
|
6
|
+
>
|
|
3
7
|
<div
|
|
8
|
+
v-bind="$attrs"
|
|
4
9
|
class="tabs"
|
|
5
|
-
:class="
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
:class="[
|
|
11
|
+
resolvedModifiers,
|
|
12
|
+
{
|
|
13
|
+
'tabs--vertical' : vertical
|
|
14
|
+
}
|
|
15
|
+
]"
|
|
8
16
|
>
|
|
9
17
|
<slot v-bind="slotProps"/>
|
|
10
18
|
</div>
|
|
@@ -13,12 +21,13 @@
|
|
|
13
21
|
|
|
14
22
|
<script setup>
|
|
15
23
|
import { TabGroup } from "@headlessui/vue";
|
|
24
|
+
import { useModifiers } from "../../composables/useModifiers.js";
|
|
16
25
|
|
|
17
26
|
defineOptions({
|
|
18
27
|
inheritAttrs: false
|
|
19
28
|
});
|
|
20
29
|
|
|
21
|
-
defineProps({
|
|
30
|
+
const props = defineProps({
|
|
22
31
|
/**
|
|
23
32
|
* Active tab index by default
|
|
24
33
|
*/
|
|
@@ -26,6 +35,12 @@
|
|
|
26
35
|
/**
|
|
27
36
|
* Whether or not to use vertical layout
|
|
28
37
|
*/
|
|
29
|
-
vertical: Boolean
|
|
38
|
+
vertical: Boolean,
|
|
39
|
+
/**
|
|
40
|
+
* Class modifiers (ie. 'transparent', 'secondary', etc)
|
|
41
|
+
*/
|
|
42
|
+
modifiers: [String, Array]
|
|
30
43
|
});
|
|
44
|
+
|
|
45
|
+
const { resolvedModifiers } = useModifiers({ props, baseClass: "tabs" });
|
|
31
46
|
</script>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ref, computed, watch,
|
|
2
|
-
import Fuse from
|
|
1
|
+
import { ref, computed, watch, watchPostEffect } from "vue";
|
|
2
|
+
import Fuse from "fuse.js";
|
|
3
|
+
|
|
4
|
+
const isFunction = v => typeof v === "function";
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Helper function to create a union of multiple Sets.
|
|
@@ -58,7 +60,7 @@ function getFilteredSetFromIndex(selected, index, allItemsSet) {
|
|
|
58
60
|
});
|
|
59
61
|
|
|
60
62
|
// For 'all' (AND), intersect the sets within the group.
|
|
61
|
-
if (group.match ===
|
|
63
|
+
if (group.match === "all") {
|
|
62
64
|
return intersectSets(childSets);
|
|
63
65
|
}
|
|
64
66
|
// For 'some' (OR), union the sets within the group.
|
|
@@ -125,19 +127,21 @@ function generateInitialFacets(allItems, facetFields) {
|
|
|
125
127
|
* @param {Object} [options.urlSync] - Optional configuration to sync state with URL.
|
|
126
128
|
* @param {import('vue-router').Router} [options.urlSync.router] - The Vue Router instance.
|
|
127
129
|
* @param {import('vue-router').RouteLocationNormalizedLoaded} [options.urlSync.route] - The current route instance.
|
|
130
|
+
* @param {Function} [options.isPinned] - A function that receives an item and returns true if it should be pinned to the top of the results.
|
|
128
131
|
*/
|
|
129
132
|
export function useFacets(allItems, options = {}) {
|
|
130
133
|
const {
|
|
131
134
|
initialFacets,
|
|
132
135
|
facetFields,
|
|
133
|
-
initialSearchValue =
|
|
134
|
-
initialSortType =
|
|
136
|
+
initialSearchValue = "",
|
|
137
|
+
initialSortType = "az",
|
|
135
138
|
noDefaultSorts = false,
|
|
136
139
|
extraSortTypes = {},
|
|
137
140
|
searchOptions: initialSearchOptions = {},
|
|
138
141
|
getSortValue = item => (item.title || item.label || ""),
|
|
139
|
-
countMode =
|
|
140
|
-
urlSync: urlSyncOptions
|
|
142
|
+
countMode = "none", // 'none', 'simple', 'intuitive'
|
|
143
|
+
urlSync: urlSyncOptions,
|
|
144
|
+
isPinned
|
|
141
145
|
} = options;
|
|
142
146
|
|
|
143
147
|
const sortAlpha = items => {
|
|
@@ -261,14 +265,22 @@ export function useFacets(allItems, options = {}) {
|
|
|
261
265
|
return result;
|
|
262
266
|
});
|
|
263
267
|
|
|
264
|
-
const
|
|
268
|
+
const displayItemsGrouped = computed(() => {
|
|
265
269
|
const sortFn = sortTypes.value[selectedSort.value]?.sort;
|
|
266
|
-
|
|
267
|
-
|
|
270
|
+
let sorted = isFunction(sortFn) ? sortFn([...filteredItems.value]) : [...filteredItems.value];
|
|
271
|
+
|
|
272
|
+
if (isFunction(isPinned)) {
|
|
273
|
+
const pinned = [];
|
|
274
|
+
const unpinned = [];
|
|
275
|
+
sorted.forEach(item => isPinned(item) ? pinned.push(item) : unpinned.push(item));
|
|
276
|
+
return { pinned, unpinned, all: [...pinned, ...unpinned] };
|
|
268
277
|
}
|
|
269
|
-
return
|
|
278
|
+
return { pinned: [], unpinned: sorted, all: sorted };
|
|
270
279
|
});
|
|
271
280
|
|
|
281
|
+
const displayItems = computed(() => displayItemsGrouped.value.all);
|
|
282
|
+
const pinnedItems = computed(() => displayItemsGrouped.value.pinned);
|
|
283
|
+
|
|
272
284
|
// --- Methods ---
|
|
273
285
|
function clearFilters() {
|
|
274
286
|
facets.value.forEach(group => {
|
|
@@ -309,12 +321,12 @@ export function useFacets(allItems, options = {}) {
|
|
|
309
321
|
}, { immediate: true });
|
|
310
322
|
|
|
311
323
|
watch([selectedFacets, searchedItems], ([currentSelected, currentSearchedItems], [prevSelected, prevSearchedItems]) => {
|
|
312
|
-
if (countMode ===
|
|
324
|
+
if (countMode === "none" || !facets.value.length) return;
|
|
313
325
|
|
|
314
326
|
// A simple optimization to prevent re-calculating counts if the actual data hasn't changed.
|
|
315
327
|
if (currentSelected === prevSelected && currentSearchedItems === prevSearchedItems) return;
|
|
316
328
|
|
|
317
|
-
if (countMode ===
|
|
329
|
+
if (countMode === "simple") {
|
|
318
330
|
const index = facetIndex.value;
|
|
319
331
|
if (index.size === 0 && searchedItems.value.length > 0 && facetFields?.length > 0) {
|
|
320
332
|
return; // Index not ready
|
|
@@ -337,7 +349,7 @@ export function useFacets(allItems, options = {}) {
|
|
|
337
349
|
child.count = intersection.size;
|
|
338
350
|
});
|
|
339
351
|
});
|
|
340
|
-
} else if (countMode ===
|
|
352
|
+
} else if (countMode === "intuitive") {
|
|
341
353
|
const index = facetIndex.value;
|
|
342
354
|
if (index.size === 0 && searchedItems.value.length > 0 && facetFields?.length > 0) {
|
|
343
355
|
// Index might not be ready yet.
|
|
@@ -348,7 +360,7 @@ export function useFacets(allItems, options = {}) {
|
|
|
348
360
|
|
|
349
361
|
facets.value.forEach(group => {
|
|
350
362
|
group.children.forEach(child => {
|
|
351
|
-
const key = `${group.uid}:${child.uid}`;
|
|
363
|
+
const key = `${ group.uid }:${ child.uid }`;
|
|
352
364
|
const childSet = index.get(key) || new Set();
|
|
353
365
|
|
|
354
366
|
if (child.selected) {
|
|
@@ -438,7 +450,7 @@ export function useFacets(allItems, options = {}) {
|
|
|
438
450
|
|
|
439
451
|
const selectionsFromUrl = new Map();
|
|
440
452
|
facets.value.forEach(group => {
|
|
441
|
-
const selectedUids = query[group.uid] ? query[group.uid].split(
|
|
453
|
+
const selectedUids = query[group.uid] ? query[group.uid].split(",") : [];
|
|
442
454
|
selectionsFromUrl.set(group.uid, new Set(selectedUids));
|
|
443
455
|
});
|
|
444
456
|
|
|
@@ -463,7 +475,10 @@ export function useFacets(allItems, options = {}) {
|
|
|
463
475
|
});
|
|
464
476
|
|
|
465
477
|
// Sync state changes TO the URL
|
|
466
|
-
watch(
|
|
478
|
+
watch(
|
|
479
|
+
[selectedSort, searchValue, selectedFacets], updateUrlFromState,
|
|
480
|
+
{ deep: true }
|
|
481
|
+
);
|
|
467
482
|
|
|
468
483
|
// Sync URL changes TO the state
|
|
469
484
|
watch(() => route.query, updateStateFromUrl);
|
|
@@ -475,6 +490,7 @@ export function useFacets(allItems, options = {}) {
|
|
|
475
490
|
selectedSort,
|
|
476
491
|
sortTypes,
|
|
477
492
|
displayItems,
|
|
493
|
+
pinnedItems,
|
|
478
494
|
selectedFacets,
|
|
479
495
|
clearFilters,
|
|
480
496
|
handleFacetChange
|