@leaflink/stash 49.3.0 → 49.3.2

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,19 +1,19 @@
1
- import { ref as x, computed as S, defineComponent as W, useSlots as j, inject as M, provide as O, watch as J, openBlock as f, createBlock as v, normalizeClass as z, unref as r, withCtx as u, mergeProps as P, createCommentVNode as p, createElementBlock as Q, createElementVNode as _, renderSlot as V, createVNode as I, createTextVNode as k, toDisplayString as g } from "vue";
2
- import U from "./useMediaQuery.js";
3
- import { SCREEN_SIZES as Z } from "./constants.js";
1
+ import { ref as B, computed as C, defineComponent as j, useSlots as O, inject as z, provide as J, watch as Q, openBlock as p, createBlock as m, normalizeClass as U, unref as t, withCtx as u, mergeProps as $, createCommentVNode as f, createElementBlock as Z, createElementVNode as A, renderSlot as G, createVNode as I, createTextVNode as k, toDisplayString as w } from "vue";
2
+ import q from "./useMediaQuery.js";
3
+ import { SCREEN_SIZES as H } from "./constants.js";
4
4
  import { t as d } from "./locale.js";
5
- import { _ as q } from "./Box.vue_vue_type_script_setup_true_lang-69e5176b.js";
6
- import C from "./Button.js";
7
- import T from "lodash-es/cloneDeep";
8
- import $ from "./Icon.js";
5
+ import { _ as K } from "./Box.vue_vue_type_script_setup_true_lang-69e5176b.js";
6
+ import _ from "./Button.js";
7
+ import L from "lodash-es/cloneDeep";
8
+ import P from "./Icon.js";
9
9
  import "./Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js";
10
- import { D as G } from "./DataView.vue_used_vue_type_style_index_0_lang.module-5c180dba.js";
11
- import H from "./FilterChip.js";
12
- import { _ as K } from "./Label.vue_vue_type_script_setup_true_lang-4b02087f.js";
13
- import X from "./Modal.js";
14
- import Y from "./SearchBar.js";
15
- import { D as ee } from "./DataViewFilters.keys-c80ffabe.js";
16
- import { i as L } from "./isDefined-2ce6cde4.js";
10
+ import { D as R } from "./DataView.vue_used_vue_type_style_index_0_lang.module-5c180dba.js";
11
+ import X from "./FilterChip.js";
12
+ import { _ as Y } from "./Label.vue_vue_type_script_setup_true_lang-4b02087f.js";
13
+ import ee from "./Modal.js";
14
+ import te from "./SearchBar.js";
15
+ import { D as le } from "./DataViewFilters.keys-c80ffabe.js";
16
+ import { i as W } from "./isDefined-2ce6cde4.js";
17
17
  import "lodash-es/get";
18
18
  import "./Button.vue_used_vue_type_style_index_0_lang.module-4dabc2a9.js";
19
19
  import "./_plugin-vue_export-helper-dad06003.js";
@@ -27,249 +27,262 @@ import "./Input.js";
27
27
  import "lodash-es/isNil";
28
28
  import "./utils/i18n.js";
29
29
  import "./Field.vue_vue_type_script_setup_true_lang-e1e4ff03.js";
30
- function Te({
31
- schema: s,
32
- dataViewRef: D
30
+ var re = /* @__PURE__ */ ((l) => (l.Cascade = "cascade", l.Nested = "nested", l))(re || {});
31
+ function Pe({
32
+ schema: l,
33
+ dataViewRef: N
33
34
  }) {
34
- const e = x({}), o = x({});
35
- for (const t in s)
36
- e.value[t] = s[t].defaultValue, o.value[t] = s[t].defaultValue;
37
- const m = D;
35
+ const e = B({}), o = B({});
36
+ for (const r in l)
37
+ e.value[r] = l[r].defaultValue, o.value[r] = l[r].defaultValue;
38
+ const y = N;
38
39
  function h() {
39
- e.value = T(o.value), m.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
40
+ e.value = L(o.value), y.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
40
41
  }
41
- function B() {
42
- for (const t in s)
43
- e.value[t] = s[t].defaultValue, o.value[t] = s[t].defaultValue;
44
- m.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
42
+ function V() {
43
+ for (const r in l)
44
+ e.value[r] = l[r].defaultValue, o.value[r] = l[r].defaultValue;
45
+ y.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
45
46
  }
46
- function y(t) {
47
- for (const i in s)
48
- s[i].group === t && (e.value[i] = s[i].defaultValue, o.value[i] = s[i].defaultValue);
49
- m.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
47
+ function b(r) {
48
+ for (const i in l)
49
+ l[i].group === r && (e.value[i] = l[i].defaultValue, o.value[i] = l[i].defaultValue);
50
+ y.value.updateCurrentFilters(e.value, { shouldEmit: !0 });
50
51
  }
51
- function A() {
52
- o.value = T(e.value);
52
+ function E() {
53
+ o.value = L(e.value);
53
54
  }
54
- const E = S(() => {
55
+ const g = C(() => {
55
56
  var i;
56
- const t = {};
57
- for (const a in s) {
58
- const n = s[a], w = e.value[a];
59
- (((i = n.isActive) == null ? void 0 : i.call(n, w)) || L(w)) && n.group && (t[n.group] = (t[n.group] ?? 0) + 1);
57
+ const r = {};
58
+ for (const c in l) {
59
+ const n = l[c], s = e.value[c];
60
+ (((i = n.isActive) == null ? void 0 : i.call(n, s)) || W(s)) && n.group && (r[n.group] = (r[n.group] ?? 0) + 1);
60
61
  }
61
- return t;
62
- }), N = S(() => {
62
+ return r;
63
+ }), S = C(() => {
63
64
  var i;
64
- let t = 0;
65
- for (const a in s) {
66
- const n = s[a], w = e.value[a];
67
- (((i = n.isActive) == null ? void 0 : i.call(n, w)) || L(w)) && (t += 1);
65
+ let r = 0;
66
+ for (const c in l) {
67
+ const n = l[c], s = e.value[c];
68
+ (((i = n.isActive) == null ? void 0 : i.call(n, s)) || W(s)) && (r += 1);
68
69
  }
69
- return t;
70
+ return r;
70
71
  });
71
72
  return {
72
73
  applyFilters: h,
73
- resetAllFilters: B,
74
+ resetAllFilters: V,
74
75
  // @ts-expect-error "could be instantiated with a different subtype": TODO: figure out how to resolve the types
75
- resetFilterGroup: y,
76
- undoWorkingFilters: A,
77
- activeFiltersCounts: E,
78
- totalActiveFiltersCount: N,
76
+ resetFilterGroup: b,
77
+ undoWorkingFilters: E,
78
+ activeFiltersCounts: g,
79
+ totalActiveFiltersCount: S,
79
80
  appliedFilters: e,
80
81
  workingFilters: o
81
82
  };
82
83
  }
83
- const te = {
84
+ const ae = {
84
85
  key: 1,
85
86
  class: "tw-col-span-12 tw-row-start-2 md:tw-col-start-7 md:tw-row-start-1 lg:tw-col-span-8 lg:tw-col-start-5"
86
- }, le = { class: "tw-hidden md:tw-block" }, re = { class: "tw-flex tw-gap-4" }, se = { class: "tw-inline-flex tw-items-center tw-gap-3" }, ae = { class: "tw-flex tw-flex-col-reverse tw-gap-gutter lg:tw-flex-row lg:tw-justify-end" }, $e = /* @__PURE__ */ W({
87
+ }, se = { class: "tw-hidden md:tw-block" }, ie = { class: "tw-flex tw-gap-4" }, oe = { class: "tw-inline-flex tw-items-center tw-gap-3" }, ne = { class: "tw-flex tw-justify-end tw-gap-gutter" }, Re = /* @__PURE__ */ j({
87
88
  __name: "DataViewFilters",
88
89
  props: {
89
90
  filtersLabelText: { default: d("ll.filterBy") },
90
91
  searchBarProps: { default: void 0 },
91
92
  showSearch: { type: Boolean, default: !0 },
92
- drawerStyle: { default: "nested" },
93
+ drawerStyle: { default: "cascade" },
93
94
  drawerProps: { default: void 0 },
94
95
  showDrawerPreviousButton: { type: Boolean, default: !1 },
95
96
  useFiltersInstance: { default: void 0 },
96
97
  onApply: { type: Function, default: void 0 },
97
- activeGroup: { default: "" }
98
+ activeGroup: { default: void 0 }
98
99
  },
99
100
  emits: ["open-drawer", "dismiss", "previous", "reset-group", "reset-all"],
100
- setup(s, { emit: D }) {
101
- const e = s, o = D, m = j(), h = U(`(min-width: ${Z.lg})`), {
102
- density: B,
103
- isLoading: y,
104
- isWithinModule: A,
105
- currentSearch: E,
106
- updateCurrentSearch: N
107
- } = M(G.key, G.defaults);
108
- O(ee.key, {
101
+ setup(l, { emit: N }) {
102
+ const e = l, o = N, y = O(), h = q(`(min-width: ${H.lg})`), V = C(() => e.drawerStyle === "nested" && !e.activeGroup), b = C(() => e.drawerStyle === "nested" && e.activeGroup), {
103
+ density: E,
104
+ isLoading: g,
105
+ isWithinModule: S,
106
+ currentSearch: r,
107
+ updateCurrentSearch: i
108
+ } = z(R.key, R.defaults);
109
+ J(le.key, {
109
110
  useFiltersInstance: e.useFiltersInstance,
110
111
  drawerStyle: e.drawerStyle
111
112
  });
112
- const t = S(() => {
113
- var l;
114
- return ((l = e.useFiltersInstance) == null ? void 0 : l.totalActiveFiltersCount.value) ?? 0;
115
- }), i = S(
113
+ const c = C(() => {
114
+ var a;
115
+ return ((a = e.useFiltersInstance) == null ? void 0 : a.totalActiveFiltersCount.value) ?? 0;
116
+ }), n = C(
116
117
  () => {
117
- var l;
118
- return ((l = e.useFiltersInstance) == null ? void 0 : l.activeFiltersCounts.value[e.activeGroup]) ?? 0;
118
+ var a;
119
+ return Number(e.activeGroup && ((a = e.useFiltersInstance) == null ? void 0 : a.activeFiltersCounts.value[e.activeGroup])) || 0;
119
120
  }
120
- ), a = x(!1);
121
- async function n() {
122
- var c, F;
123
- const { preventDismiss: l } = await ((c = e.onApply) == null ? void 0 : c.call(e)) || ((F = e.useFiltersInstance) == null ? void 0 : F.applyFilters()) || {};
124
- l || (a.value = !1);
121
+ ), s = B(!1);
122
+ async function D() {
123
+ var v, F;
124
+ const { preventDismiss: a } = await ((v = e.onApply) == null ? void 0 : v.call(e)) || ((F = e.useFiltersInstance) == null ? void 0 : F.applyFilters()) || {};
125
+ a || (s.value = !1);
125
126
  }
126
- function w() {
127
- var l;
128
- (l = e.useFiltersInstance) == null || l.resetFilterGroup(e.activeGroup), o("reset-group"), a.value = !1;
127
+ function M() {
128
+ var a;
129
+ e.activeGroup && ((a = e.useFiltersInstance) == null || a.resetFilterGroup(e.activeGroup), o("reset-group"), s.value = !1);
129
130
  }
130
- function b() {
131
- var l;
132
- (l = e.useFiltersInstance) == null || l.resetAllFilters(), o("reset-all"), a.value = !1;
131
+ function x() {
132
+ var a;
133
+ (a = e.useFiltersInstance) == null || a.resetAllFilters(), o("reset-all"), s.value = !1;
133
134
  }
134
- function R() {
135
- var l;
136
- (l = e.useFiltersInstance) == null || l.undoWorkingFilters(), a.value = !1, o("dismiss");
135
+ function T() {
136
+ var a;
137
+ (a = e.useFiltersInstance) == null || a.undoWorkingFilters(), s.value = !1, o("dismiss");
137
138
  }
138
- return J(a, () => {
139
- a.value && o("open-drawer");
140
- }), (l, c) => (f(), v(q, {
141
- class: z(["stash-data-view-filters tw-grid tw-grid-cols-12 tw-gap-6 tw-p-3", { "lg:tw-p-6": r(B) === "comfortable", "tw-mb-3": !r(A) }]),
142
- radius: r(A) ? "none" : "rounded",
139
+ return Q(s, () => {
140
+ s.value && o("open-drawer");
141
+ }), (a, v) => (p(), m(K, {
142
+ class: U(["stash-data-view-filters tw-grid tw-grid-cols-12 tw-gap-6 tw-p-3", { "lg:tw-p-6": t(E) === "comfortable", "tw-mb-3": !t(S) }]),
143
+ radius: t(S) ? "none" : "rounded",
143
144
  "data-test": "stash-data-view-filters",
144
145
  "disable-padding": ""
145
146
  }, {
146
147
  default: u(() => [
147
- e.showSearch ? (f(), v(Y, P({
148
+ e.showSearch ? (p(), m(te, $({
148
149
  key: 0,
149
150
  class: "tw-col-span-12 md:tw-col-span-6 lg:tw-col-span-4",
150
151
  "data-test": "stash-data-view-filters|search-bar",
151
- "is-loading": r(y),
152
- label: r(d)("ll.search"),
153
- "model-value": r(E)
152
+ "is-loading": t(g),
153
+ label: t(d)("ll.search"),
154
+ "model-value": t(r)
154
155
  }, e.searchBarProps, {
155
- onSearch: c[0] || (c[0] = (F) => r(N)(F, { shouldEmit: !0 }))
156
- }), null, 16, ["is-loading", "label", "model-value"])) : p("", !0),
157
- m.default ? (f(), Q("div", te, [
158
- _("div", le, [
159
- V(l.$slots, "filters-label", {}, () => [
160
- I(K, null, {
156
+ onSearch: v[0] || (v[0] = (F) => t(i)(F, { shouldEmit: !0 }))
157
+ }), null, 16, ["is-loading", "label", "model-value"])) : f("", !0),
158
+ y.default ? (p(), Z("div", ae, [
159
+ A("div", se, [
160
+ G(a.$slots, "filters-label", {}, () => [
161
+ I(Y, null, {
161
162
  default: u(() => [
162
- k(g(e.filtersLabelText), 1)
163
+ k(w(e.filtersLabelText), 1)
163
164
  ]),
164
165
  _: 1
165
166
  })
166
167
  ])
167
168
  ]),
168
- _("div", re, [
169
- I(H, {
169
+ A("div", ie, [
170
+ I(X, {
170
171
  secondary: "",
171
172
  class: "!tw-flex tw-w-full tw-justify-center tw-gap-4 md:!tw-inline-flex md:tw-w-auto",
172
173
  "data-test": "stash-data-view-filters|drawer-toggle-button",
173
- "filter-count": t.value,
174
- onClick: c[1] || (c[1] = (F) => a.value = !0)
174
+ "filter-count": c.value,
175
+ onClick: v[1] || (v[1] = (F) => s.value = !0)
175
176
  }, {
176
177
  default: u(() => [
177
- _("span", se, [
178
- I($, {
178
+ A("span", oe, [
179
+ I(P, {
179
180
  name: "filter-line",
180
181
  class: "tw-text-ice-700"
181
182
  }),
182
- _("span", null, g(r(d)("ll.filters")), 1)
183
+ A("span", null, w(t(d)("ll.filters")), 1)
183
184
  ])
184
185
  ]),
185
186
  _: 1
186
187
  }, 8, ["filter-count"]),
187
- r(h) ? V(l.$slots, "default", { key: 0 }) : p("", !0),
188
- t.value > 0 && r(h) ? (f(), v(C, {
188
+ t(h) ? G(a.$slots, "default", { key: 0 }) : f("", !0),
189
+ c.value > 0 && t(h) ? (p(), m(_, {
189
190
  key: 1,
190
191
  inline: "",
191
- onClick: b
192
+ onClick: x
192
193
  }, {
193
194
  default: u(() => [
194
- k(g(r(d)("ll.resetAll")), 1)
195
+ k(w(t(d)("ll.resetAll")), 1)
195
196
  ]),
196
197
  _: 1
197
- })) : p("", !0)
198
+ })) : f("", !0)
198
199
  ])
199
- ])) : p("", !0),
200
- m.drawer ? (f(), v(X, P({
200
+ ])) : f("", !0),
201
+ y.drawer ? (p(), m(ee, $({
201
202
  key: 2,
202
203
  "data-test": "stash-data-view-filters|drawer",
203
204
  "disable-body-padding": "",
204
205
  position: "right",
205
- "is-open": a.value,
206
- title: r(d)("ll.allFilters")
207
- }, e.drawerProps, { onDismiss: R }), {
206
+ size: "narrow",
207
+ "is-open": s.value,
208
+ title: t(d)("ll.allFilters")
209
+ }, e.drawerProps, { onDismiss: T }), {
208
210
  headerAction: u(() => [
209
- e.showDrawerPreviousButton ? (f(), v(C, {
211
+ b.value ? (p(), m(_, {
210
212
  key: 0,
211
213
  icon: "",
212
214
  class: "tw-text-ice-100",
213
215
  "data-test": "stash-data-view-filters|drawer-previous-button",
214
- "aria-label": r(d)("ll.previous"),
215
- title: r(d)("ll.previous"),
216
- onClick: c[2] || (c[2] = (F) => o("previous"))
216
+ "aria-label": t(d)("ll.previous"),
217
+ title: t(d)("ll.previous"),
218
+ onClick: v[2] || (v[2] = (F) => o("previous"))
217
219
  }, {
218
220
  default: u(() => [
219
- I($, { name: "chevron-left" })
221
+ I(P, { name: "chevron-left" })
220
222
  ]),
221
223
  _: 1
222
- }, 8, ["aria-label", "title"])) : p("", !0)
224
+ }, 8, ["aria-label", "title"])) : f("", !0)
223
225
  ]),
224
226
  footer: u(() => [
225
- _("div", ae, [
226
- !e.showDrawerPreviousButton && t.value > 0 ? (f(), v(C, {
227
+ A("div", ne, [
228
+ c.value === 0 ? (p(), m(_, {
227
229
  key: 0,
228
230
  secondary: "",
229
- disabled: r(y),
230
- onClick: b
231
+ onClick: T
231
232
  }, {
232
233
  default: u(() => [
233
- k(g(r(d)("ll.resetAll")), 1)
234
+ k(w(t(d)("ll.cancel")), 1)
234
235
  ]),
235
236
  _: 1
236
- }, 8, ["disabled"])) : p("", !0),
237
- (e.showDrawerPreviousButton || e.drawerStyle === "cascade") && i.value > 0 ? (f(), v(C, {
237
+ })) : f("", !0),
238
+ (V.value || e.drawerStyle === "cascade") && c.value > 0 ? (p(), m(_, {
238
239
  key: 1,
239
240
  secondary: "",
240
- disabled: r(y),
241
- onClick: w
241
+ disabled: t(g),
242
+ onClick: x
242
243
  }, {
243
244
  default: u(() => [
244
- k(g(r(d)("ll.reset")), 1)
245
+ k(w(t(d)("ll.resetAll")), 1)
245
246
  ]),
246
247
  _: 1
247
- }, 8, ["disabled"])) : p("", !0),
248
- e.showDrawerPreviousButton || e.drawerStyle === "cascade" ? (f(), v(C, {
248
+ }, 8, ["disabled"])) : f("", !0),
249
+ b.value && n.value > 0 ? (p(), m(_, {
249
250
  key: 2,
250
- disabled: r(y),
251
- onClick: n
251
+ secondary: "",
252
+ disabled: t(g),
253
+ onClick: M
254
+ }, {
255
+ default: u(() => [
256
+ k(w(t(d)("ll.reset")), 1)
257
+ ]),
258
+ _: 1
259
+ }, 8, ["disabled"])) : f("", !0),
260
+ b.value || e.drawerStyle === "cascade" ? (p(), m(_, {
261
+ key: 3,
262
+ disabled: t(g),
263
+ onClick: D
252
264
  }, {
253
265
  default: u(() => [
254
- k(g(r(d)("ll.apply")), 1)
266
+ k(w(t(d)("ll.apply")), 1)
255
267
  ]),
256
268
  _: 1
257
- }, 8, ["disabled"])) : p("", !0)
269
+ }, 8, ["disabled"])) : f("", !0)
258
270
  ])
259
271
  ]),
260
272
  default: u(() => [
261
- V(l.$slots, "drawer")
273
+ G(a.$slots, "drawer")
262
274
  ]),
263
275
  _: 3
264
- }, 16, ["is-open", "title"])) : p("", !0)
276
+ }, 16, ["is-open", "title"])) : f("", !0)
265
277
  ]),
266
278
  _: 3
267
279
  }, 8, ["class", "radius"]));
268
280
  }
269
281
  });
270
282
  export {
271
- ee as DATA_VIEW_FILTERS_UTILS_INJECTION,
272
- $e as default,
273
- Te as useFilters
283
+ le as DATA_VIEW_FILTERS_UTILS_INJECTION,
284
+ re as DrawerStyle,
285
+ Re as default,
286
+ Pe as useFilters
274
287
  };
275
288
  //# sourceMappingURL=DataViewFilters.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataViewFilters.js","sources":["../src/components/DataViewFilters/useFilters.ts","../src/components/DataViewFilters/DataViewFilters.vue"],"sourcesContent":["import cloneDeep from 'lodash-es/cloneDeep';\nimport { computed, ComputedRef, Ref, ref } from 'vue';\n\nimport isDefined from '../../composables/useValidation/utils/isDefined';\nimport DataView from '../DataView/DataView.vue';\n\ntype DataViewInstance = InstanceType<typeof DataView>;\n\n/**\n * Contains metadata and configuration for the filters.\n * @see https://www.typescriptlang.org/docs/handbook/2/mapped-types.html\n */\nexport type UseFiltersSchema<Values extends object, Groups extends string> = {\n [Property in keyof Values]: {\n defaultValue?: Values[Property];\n group?: Groups;\n isActive?: (value: Values[Property]) => boolean;\n };\n};\n\nexport interface UseFiltersArgs<Values extends object, Groups extends string> {\n schema: UseFiltersSchema<Values, Groups>;\n /** A ref for an instance of DataView */\n dataViewRef: Ref<unknown>; // Note: using `Ref<InstanceType<typeof DataView>>` here causes type errors when providing a value for this argument\n}\n\nexport interface UseFiltersReturnType<Values = object, Groups extends string = string> {\n applyFilters: () => void;\n resetAllFilters: () => void;\n resetFilterGroup: (group: string) => void; // Note: group is intentionally not typed as `Groups` since there is no way to pass in a Groups type to UseFiltersReturnType within DataViewFilters.vue\n undoWorkingFilters: () => void;\n activeFiltersCounts: ComputedRef<Record<Groups, number>>;\n totalActiveFiltersCount: ComputedRef<number>;\n appliedFilters: Ref<Values>;\n workingFilters: Ref<Values>;\n}\n\n/**\n * Provides utility functions for working with `DataViewFilters`.\n */\nexport function useFilters<Values extends object, Groups extends string>({\n schema,\n dataViewRef,\n}: UseFiltersArgs<Values, Groups>): UseFiltersReturnType<Values, Groups> {\n const appliedFilters = ref({}) as Ref<Values>;\n const workingFilters = ref({}) as Ref<Values>;\n\n for (const filterName in schema) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n\n const dvRef = dataViewRef as Ref<DataViewInstance>;\n\n /**\n * For when an \"Apply\" button is clicked. It does the following:\n * 1) applies the working filter state\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function applyFilters() {\n appliedFilters.value = cloneDeep(workingFilters.value);\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * For when a \"Reset all\" button is clicked. It does the following:\n * 1) applies the defaultValue filter values to all filters\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function resetAllFilters() {\n for (const filterName in schema) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * For when a \"Reset\" button is clicked. It does the following:\n * 1) applies the defaultValue filter values to the given filter group\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function resetFilterGroup(group: Groups) {\n for (const filterName in schema) {\n if (schema[filterName].group === group) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n }\n\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * Resets the `workingFilters` to match the `appliedFilters`. This can be used when the FilterDrawer or a FilterDropdown is dismissed without clicking \"Reset\" or \"Apply\".\n */\n function undoWorkingFilters() {\n workingFilters.value = cloneDeep(appliedFilters.value);\n }\n\n const activeFiltersCounts = computed(() => {\n const counts = {} as Record<Groups, number>;\n\n for (const filterName in schema) {\n const config = schema[filterName];\n const value = appliedFilters.value[filterName];\n const isActive = config.isActive?.(value) || isDefined(value);\n\n if (isActive && config.group) {\n counts[config.group] = (counts[config.group] ?? 0) + 1;\n }\n }\n\n return counts;\n });\n\n const totalActiveFiltersCount = computed(() => {\n let count = 0;\n\n for (const filterName in schema) {\n const config = schema[filterName];\n const value = appliedFilters.value[filterName];\n const isActive = config.isActive?.(value) || isDefined(value);\n\n if (isActive) {\n count += 1;\n }\n }\n\n return count;\n });\n\n return {\n applyFilters,\n resetAllFilters,\n // @ts-expect-error \"could be instantiated with a different subtype\": TODO: figure out how to resolve the types\n resetFilterGroup,\n undoWorkingFilters,\n activeFiltersCounts,\n totalActiveFiltersCount,\n appliedFilters,\n workingFilters,\n };\n}\n\nexport default useFilters;\n","<script lang=\"ts\">\n export * from './DataViewFilters.keys';\n export * from './DataViewFilters.types';\n export * from './useFilters';\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, provide, ref, watch } from 'vue';\n\n import useMediaQuery from '../../composables/useMediaQuery/useMediaQuery';\n import { SCREEN_SIZES } from '../../constants';\n import { t } from '../../locale';\n import Box from '../Box/Box.vue';\n import Button from '../Button/Button.vue';\n import { DATA_VIEW_INJECTION } from '../DataView/DataView.vue';\n import FilterChip from '../FilterChip/FilterChip.vue';\n import Icon from '../Icon/Icon.vue';\n import Label from '../Label/Label.vue';\n import Modal, { type ModalProps } from '../Modal/Modal.vue';\n import SearchBar, { SearchBarProps } from '../SearchBar/SearchBar.vue';\n import { DATA_VIEW_FILTERS_UTILS_INJECTION } from './DataViewFilters.keys';\n import type { DrawerStyle, OnApplyFilters } from './DataViewFilters.types';\n import type { UseFiltersReturnType } from './useFilters';\n\n export interface DataViewFiltersProps {\n filtersLabelText?: string;\n /**\n * Props to pass to the `SearchBar` component.\n */\n searchBarProps?: SearchBarProps;\n showSearch?: boolean;\n /** 'cascade' displays all fields within every filter group; 'nested' displays only the group names and requires clicking a group to view its fields */\n drawerStyle?: DrawerStyle;\n drawerProps?: ModalProps;\n showDrawerPreviousButton?: boolean;\n /**\n * Required when using filters. This prop should contain the return value of the `useFilters()` composable.\n */\n useFiltersInstance?: UseFiltersReturnType;\n onApply?: OnApplyFilters;\n /** The name of the active filter group. The active filter group is determined by which instance of FilterDropdown or FilterDrawerItem is open. */\n activeGroup?: string;\n }\n\n export interface DataViewFiltersSlots {\n default?: void;\n drawer?: void;\n 'filters-label'?: void;\n }\n\n const props = withDefaults(defineProps<DataViewFiltersProps>(), {\n filtersLabelText: t('ll.filterBy'),\n isLoading: false,\n drawerStyle: 'nested',\n drawerProps: undefined,\n searchBarProps: undefined,\n showDrawerPreviousButton: false,\n showSearch: true,\n useFiltersInstance: undefined,\n onApply: undefined,\n activeGroup: '',\n });\n\n const emit = defineEmits<{\n /** When the drawer is opened */\n (e: 'open-drawer'): void;\n /** When the drawer is dismissed */\n (e: 'dismiss'): void;\n /** When the \"Previous\" button in the header is clicked */\n (e: 'previous'): void;\n /** When the \"Reset\" button is clicked while viewing a filter group */\n (e: 'reset-group'): void;\n /** When one of the \"Reset All\" buttons is clicked */\n (e: 'reset-all'): void;\n }>();\n\n const slots = defineSlots<DataViewFiltersSlots>();\n\n const isDesktop = useMediaQuery(`(min-width: ${SCREEN_SIZES.lg})`);\n\n const {\n density,\n isLoading: isDataViewLoading,\n isWithinModule,\n currentSearch,\n updateCurrentSearch,\n } = inject(DATA_VIEW_INJECTION.key, DATA_VIEW_INJECTION.defaults);\n\n provide(DATA_VIEW_FILTERS_UTILS_INJECTION.key, {\n useFiltersInstance: props.useFiltersInstance,\n drawerStyle: props.drawerStyle,\n });\n\n const totalActiveFiltersCount = computed(() => props.useFiltersInstance?.totalActiveFiltersCount.value ?? 0);\n const activeGroupActiveFiltersCount = computed(\n () => props.useFiltersInstance?.activeFiltersCounts.value[props.activeGroup] ?? 0,\n );\n const isDrawerOpen = ref(false);\n\n async function handleApplyClick() {\n const { preventDismiss } = (await props.onApply?.()) || props.useFiltersInstance?.applyFilters() || {};\n\n if (!preventDismiss) {\n isDrawerOpen.value = false;\n }\n }\n\n function handleResetGroupClick() {\n props.useFiltersInstance?.resetFilterGroup(props.activeGroup);\n emit('reset-group');\n isDrawerOpen.value = false;\n }\n\n function handleResetAllClick() {\n props.useFiltersInstance?.resetAllFilters();\n emit('reset-all');\n isDrawerOpen.value = false;\n }\n\n function onDismiss() {\n props.useFiltersInstance?.undoWorkingFilters();\n isDrawerOpen.value = false;\n emit('dismiss');\n }\n\n watch(isDrawerOpen, () => {\n if (isDrawerOpen.value) {\n emit('open-drawer');\n }\n });\n</script>\n\n<template>\n <Box\n class=\"stash-data-view-filters tw-grid tw-grid-cols-12 tw-gap-6 tw-p-3\"\n :class=\"{ 'lg:tw-p-6': density === 'comfortable', 'tw-mb-3': !isWithinModule }\"\n :radius=\"isWithinModule ? 'none' : 'rounded'\"\n data-test=\"stash-data-view-filters\"\n disable-padding\n >\n <SearchBar\n v-if=\"props.showSearch\"\n class=\"tw-col-span-12 md:tw-col-span-6 lg:tw-col-span-4\"\n data-test=\"stash-data-view-filters|search-bar\"\n :is-loading=\"isDataViewLoading\"\n :label=\"t('ll.search')\"\n :model-value=\"currentSearch\"\n v-bind=\"props.searchBarProps\"\n @search=\"(searchTerm) => updateCurrentSearch(searchTerm, { shouldEmit: true })\"\n />\n <div\n v-if=\"slots.default\"\n class=\"tw-col-span-12 tw-row-start-2 md:tw-col-start-7 md:tw-row-start-1 lg:tw-col-span-8 lg:tw-col-start-5\"\n >\n <div class=\"tw-hidden md:tw-block\">\n <slot name=\"filters-label\">\n <Label>{{ props.filtersLabelText }}</Label>\n </slot>\n </div>\n <div class=\"tw-flex tw-gap-4\">\n <FilterChip\n secondary\n class=\"!tw-flex tw-w-full tw-justify-center tw-gap-4 md:!tw-inline-flex md:tw-w-auto\"\n data-test=\"stash-data-view-filters|drawer-toggle-button\"\n :filter-count=\"totalActiveFiltersCount\"\n @click=\"isDrawerOpen = true\"\n >\n <span class=\"tw-inline-flex tw-items-center tw-gap-3\">\n <Icon name=\"filter-line\" class=\"tw-text-ice-700\" />\n <span>{{ t('ll.filters') }}</span>\n </span>\n </FilterChip>\n <slot v-if=\"isDesktop\"></slot>\n <Button v-if=\"totalActiveFiltersCount > 0 && isDesktop\" inline @click=\"handleResetAllClick\">\n {{ t('ll.resetAll') }}\n </Button>\n </div>\n </div>\n <Modal\n v-if=\"slots.drawer\"\n data-test=\"stash-data-view-filters|drawer\"\n disable-body-padding\n position=\"right\"\n :is-open=\"isDrawerOpen\"\n :title=\"t('ll.allFilters')\"\n v-bind=\"props.drawerProps\"\n @dismiss=\"onDismiss\"\n >\n <template #headerAction>\n <Button\n v-if=\"props.showDrawerPreviousButton\"\n icon\n class=\"tw-text-ice-100\"\n data-test=\"stash-data-view-filters|drawer-previous-button\"\n :aria-label=\"t('ll.previous')\"\n :title=\"t('ll.previous')\"\n @click=\"emit('previous')\"\n >\n <Icon name=\"chevron-left\" />\n </Button>\n </template>\n\n <slot name=\"drawer\"></slot>\n\n <template #footer>\n <div class=\"tw-flex tw-flex-col-reverse tw-gap-gutter lg:tw-flex-row lg:tw-justify-end\">\n <Button\n v-if=\"!props.showDrawerPreviousButton && totalActiveFiltersCount > 0\"\n secondary\n :disabled=\"isDataViewLoading\"\n @click=\"handleResetAllClick\"\n >\n {{ t('ll.resetAll') }}\n </Button>\n <Button\n v-if=\"\n (props.showDrawerPreviousButton || props.drawerStyle === 'cascade') && activeGroupActiveFiltersCount > 0\n \"\n secondary\n :disabled=\"isDataViewLoading\"\n @click=\"handleResetGroupClick\"\n >\n {{ t('ll.reset') }}\n </Button>\n <Button\n v-if=\"props.showDrawerPreviousButton || props.drawerStyle === 'cascade'\"\n :disabled=\"isDataViewLoading\"\n @click=\"handleApplyClick\"\n >\n {{ t('ll.apply') }}\n </Button>\n </div>\n </template>\n </Modal>\n </Box>\n</template>\n"],"names":["useFilters","schema","dataViewRef","appliedFilters","ref","workingFilters","filterName","dvRef","applyFilters","cloneDeep","resetAllFilters","resetFilterGroup","group","undoWorkingFilters","activeFiltersCounts","computed","counts","config","value","_a","isDefined","totalActiveFiltersCount","count","props","__props","emit","__emit","slots","_useSlots","isDesktop","useMediaQuery","SCREEN_SIZES","density","isDataViewLoading","isWithinModule","currentSearch","updateCurrentSearch","inject","DATA_VIEW_INJECTION","provide","DATA_VIEW_FILTERS_UTILS_INJECTION","activeGroupActiveFiltersCount","isDrawerOpen","handleApplyClick","preventDismiss","_b","handleResetGroupClick","handleResetAllClick","onDismiss","watch"],"mappings":"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"}
1
+ {"version":3,"file":"DataViewFilters.js","sources":["../src/components/DataViewFilters/DataViewFilters.types.ts","../src/components/DataViewFilters/useFilters.ts","../src/components/DataViewFilters/DataViewFilters.vue"],"sourcesContent":["import { UseFiltersReturnType } from './useFilters';\n\n/**\n * A function that is called when the user clicks one of the \"Apply\" buttons in DataViewFilters.\n *\n * A return value of `{ preventDismiss: true }` can be used to prevent the DataViewFilters drawer or a FilterDropdown from closing, such as when some filters have invalid values.\n */\nexport type OnApplyFilters = () => Promise<{ preventDismiss?: boolean } | void> | { preventDismiss?: boolean } | void;\n\nexport enum DrawerStyle {\n /** Displays all groups and their fields without the need for navigating submenus. */\n Cascade = 'cascade',\n /** Displays only group names or fields; navigation between the group names and a submenu of fields is required. */\n Nested = 'nested',\n}\n\nexport type DrawerStyles = `${DrawerStyle}`;\n\nexport interface DataViewFiltersUtilsInjection {\n useFiltersInstance?: UseFiltersReturnType;\n drawerStyle?: DrawerStyles;\n}\n","import cloneDeep from 'lodash-es/cloneDeep';\nimport { computed, ComputedRef, Ref, ref } from 'vue';\n\nimport isDefined from '../../composables/useValidation/utils/isDefined';\nimport DataView from '../DataView/DataView.vue';\n\ntype DataViewInstance = InstanceType<typeof DataView>;\n\n/**\n * Contains metadata and configuration for the filters.\n * @see https://www.typescriptlang.org/docs/handbook/2/mapped-types.html\n */\nexport type UseFiltersSchema<Values extends object, Groups extends string> = {\n [Property in keyof Values]: {\n defaultValue?: Values[Property];\n group?: Groups;\n isActive?: (value: Values[Property]) => boolean;\n };\n};\n\nexport interface UseFiltersArgs<Values extends object, Groups extends string> {\n schema: UseFiltersSchema<Values, Groups>;\n /** A ref for an instance of DataView */\n dataViewRef: Ref<unknown>; // Note: using `Ref<InstanceType<typeof DataView>>` here causes type errors when providing a value for this argument\n}\n\nexport interface UseFiltersReturnType<Values = object, Groups extends string = string> {\n applyFilters: () => void;\n resetAllFilters: () => void;\n resetFilterGroup: (group: string) => void; // Note: group is intentionally not typed as `Groups` since there is no way to pass in a Groups type to UseFiltersReturnType within DataViewFilters.vue\n undoWorkingFilters: () => void;\n activeFiltersCounts: ComputedRef<Record<Groups, number>>;\n totalActiveFiltersCount: ComputedRef<number>;\n appliedFilters: Ref<Values>;\n workingFilters: Ref<Values>;\n}\n\n/**\n * Provides utility functions for working with `DataViewFilters`.\n */\nexport function useFilters<Values extends object, Groups extends string>({\n schema,\n dataViewRef,\n}: UseFiltersArgs<Values, Groups>): UseFiltersReturnType<Values, Groups> {\n const appliedFilters = ref({}) as Ref<Values>;\n const workingFilters = ref({}) as Ref<Values>;\n\n for (const filterName in schema) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n\n const dvRef = dataViewRef as Ref<DataViewInstance>;\n\n /**\n * For when an \"Apply\" button is clicked. It does the following:\n * 1) applies the working filter state\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function applyFilters() {\n appliedFilters.value = cloneDeep(workingFilters.value);\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * For when a \"Reset all\" button is clicked. It does the following:\n * 1) applies the defaultValue filter values to all filters\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function resetAllFilters() {\n for (const filterName in schema) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * For when a \"Reset\" button is clicked. It does the following:\n * 1) applies the defaultValue filter values to the given filter group\n * 2) sets the current page to 1\n * 3) emits the \"update\" event from DataView\n */\n function resetFilterGroup(group: Groups) {\n for (const filterName in schema) {\n if (schema[filterName].group === group) {\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n appliedFilters.value[filterName] = schema[filterName].defaultValue;\n // @ts-expect-error \"could be instantiated with an arbitrary type\"; TODO: figure out how to resolve the types\n workingFilters.value[filterName] = schema[filterName].defaultValue;\n }\n }\n\n dvRef.value.updateCurrentFilters(appliedFilters.value, { shouldEmit: true });\n }\n\n /**\n * Resets the `workingFilters` to match the `appliedFilters`. This can be used when the FilterDrawer or a FilterDropdown is dismissed without clicking \"Reset\" or \"Apply\".\n */\n function undoWorkingFilters() {\n workingFilters.value = cloneDeep(appliedFilters.value);\n }\n\n const activeFiltersCounts = computed(() => {\n const counts = {} as Record<Groups, number>;\n\n for (const filterName in schema) {\n const config = schema[filterName];\n const value = appliedFilters.value[filterName];\n const isActive = config.isActive?.(value) || isDefined(value);\n\n if (isActive && config.group) {\n counts[config.group] = (counts[config.group] ?? 0) + 1;\n }\n }\n\n return counts;\n });\n\n const totalActiveFiltersCount = computed(() => {\n let count = 0;\n\n for (const filterName in schema) {\n const config = schema[filterName];\n const value = appliedFilters.value[filterName];\n const isActive = config.isActive?.(value) || isDefined(value);\n\n if (isActive) {\n count += 1;\n }\n }\n\n return count;\n });\n\n return {\n applyFilters,\n resetAllFilters,\n // @ts-expect-error \"could be instantiated with a different subtype\": TODO: figure out how to resolve the types\n resetFilterGroup,\n undoWorkingFilters,\n activeFiltersCounts,\n totalActiveFiltersCount,\n appliedFilters,\n workingFilters,\n };\n}\n\nexport default useFilters;\n","<script lang=\"ts\">\n export * from './DataViewFilters.keys';\n export * from './DataViewFilters.types';\n export * from './useFilters';\n</script>\n\n<script setup lang=\"ts\">\n import { computed, inject, provide, ref, watch } from 'vue';\n\n import useMediaQuery from '../../composables/useMediaQuery/useMediaQuery';\n import { SCREEN_SIZES } from '../../constants';\n import { t } from '../../locale';\n import Box from '../Box/Box.vue';\n import Button from '../Button/Button.vue';\n import { DATA_VIEW_INJECTION } from '../DataView/DataView.vue';\n import FilterChip from '../FilterChip/FilterChip.vue';\n import Icon from '../Icon/Icon.vue';\n import Label from '../Label/Label.vue';\n import Modal, { type ModalProps } from '../Modal/Modal.vue';\n import SearchBar, { SearchBarProps } from '../SearchBar/SearchBar.vue';\n import { DATA_VIEW_FILTERS_UTILS_INJECTION } from './DataViewFilters.keys';\n import type { DrawerStyles, OnApplyFilters } from './DataViewFilters.types';\n import type { UseFiltersReturnType } from './useFilters';\n\n export interface DataViewFiltersProps {\n filtersLabelText?: string;\n /**\n * Props to pass to the `SearchBar` component.\n */\n searchBarProps?: SearchBarProps;\n showSearch?: boolean;\n /** 'cascade' displays all fields within every filter group; 'nested' displays only the group names and requires clicking a group to view its fields. */\n drawerStyle?: DrawerStyles;\n drawerProps?: ModalProps;\n /**\n * @deprecated The `activeGroup` prop is a sufficient replacement for this prop. A falsy `activeGroup` will hide the button and a truthy `activeGroup` will show it (when the `drawerStyle` is 'nested').\n *\n * **Note:** This prop has no effect when using a \"cascade\" `drawerStyle`.\n */\n showDrawerPreviousButton?: boolean;\n /**\n * Required when using filters. This prop should contain the return value of the `useFilters()` composable.\n */\n useFiltersInstance?: UseFiltersReturnType;\n onApply?: OnApplyFilters;\n /**\n * The name of the active filter group. The active filter group is determined by which instance of FilterDropdown or FilterDrawerItem is open.\n *\n * **Note:** This prop is required when using a \"nested\" `drawerStyle`, but has no effect when using a \"cascade\" `drawerStyle`.\n */\n activeGroup?: string;\n }\n\n export interface DataViewFiltersSlots {\n default?: void;\n drawer?: void;\n 'filters-label'?: void;\n }\n\n const props = withDefaults(defineProps<DataViewFiltersProps>(), {\n filtersLabelText: t('ll.filterBy'),\n isLoading: false,\n drawerStyle: 'cascade',\n drawerProps: undefined,\n searchBarProps: undefined,\n showDrawerPreviousButton: false,\n showSearch: true,\n useFiltersInstance: undefined,\n onApply: undefined,\n activeGroup: undefined,\n });\n\n const emit = defineEmits<{\n /** When the drawer is opened */\n (e: 'open-drawer'): void;\n /** When the drawer is dismissed */\n (e: 'dismiss'): void;\n /** When the \"Previous\" button in the header is clicked */\n (e: 'previous'): void;\n /** When the \"Reset\" button is clicked while viewing a filter group */\n (e: 'reset-group'): void;\n /** When one of the \"Reset All\" buttons is clicked */\n (e: 'reset-all'): void;\n }>();\n\n const slots = defineSlots<DataViewFiltersSlots>();\n\n const isDesktop = useMediaQuery(`(min-width: ${SCREEN_SIZES.lg})`);\n const isViewingGroupsMenu = computed(() => props.drawerStyle === 'nested' && !props.activeGroup);\n const isViewingSingleGroup = computed(() => props.drawerStyle === 'nested' && props.activeGroup);\n\n const {\n density,\n isLoading: isDataViewLoading,\n isWithinModule,\n currentSearch,\n updateCurrentSearch,\n } = inject(DATA_VIEW_INJECTION.key, DATA_VIEW_INJECTION.defaults);\n\n provide(DATA_VIEW_FILTERS_UTILS_INJECTION.key, {\n useFiltersInstance: props.useFiltersInstance,\n drawerStyle: props.drawerStyle,\n });\n\n const totalActiveFiltersCount = computed(() => props.useFiltersInstance?.totalActiveFiltersCount.value ?? 0);\n /** The number of active filters in the currently active group. This is only used when the drawerStyle is 'nested'. */\n const activeGroupActiveFiltersCount = computed(\n () => Number(props.activeGroup && props.useFiltersInstance?.activeFiltersCounts.value[props.activeGroup]) || 0,\n );\n const isDrawerOpen = ref(false);\n\n async function handleApplyClick() {\n const { preventDismiss } = (await props.onApply?.()) || props.useFiltersInstance?.applyFilters() || {};\n\n if (!preventDismiss) {\n isDrawerOpen.value = false;\n }\n }\n\n function handleResetGroupClick() {\n if (!props.activeGroup) {\n return;\n }\n\n props.useFiltersInstance?.resetFilterGroup(props.activeGroup);\n emit('reset-group');\n isDrawerOpen.value = false;\n }\n\n function handleResetAllClick() {\n props.useFiltersInstance?.resetAllFilters();\n emit('reset-all');\n isDrawerOpen.value = false;\n }\n\n function onDismiss() {\n props.useFiltersInstance?.undoWorkingFilters();\n isDrawerOpen.value = false;\n emit('dismiss');\n }\n\n watch(isDrawerOpen, () => {\n if (isDrawerOpen.value) {\n emit('open-drawer');\n }\n });\n</script>\n\n<template>\n <Box\n class=\"stash-data-view-filters tw-grid tw-grid-cols-12 tw-gap-6 tw-p-3\"\n :class=\"{ 'lg:tw-p-6': density === 'comfortable', 'tw-mb-3': !isWithinModule }\"\n :radius=\"isWithinModule ? 'none' : 'rounded'\"\n data-test=\"stash-data-view-filters\"\n disable-padding\n >\n <SearchBar\n v-if=\"props.showSearch\"\n class=\"tw-col-span-12 md:tw-col-span-6 lg:tw-col-span-4\"\n data-test=\"stash-data-view-filters|search-bar\"\n :is-loading=\"isDataViewLoading\"\n :label=\"t('ll.search')\"\n :model-value=\"currentSearch\"\n v-bind=\"props.searchBarProps\"\n @search=\"(searchTerm) => updateCurrentSearch(searchTerm, { shouldEmit: true })\"\n />\n <div\n v-if=\"slots.default\"\n class=\"tw-col-span-12 tw-row-start-2 md:tw-col-start-7 md:tw-row-start-1 lg:tw-col-span-8 lg:tw-col-start-5\"\n >\n <div class=\"tw-hidden md:tw-block\">\n <slot name=\"filters-label\">\n <Label>{{ props.filtersLabelText }}</Label>\n </slot>\n </div>\n <div class=\"tw-flex tw-gap-4\">\n <FilterChip\n secondary\n class=\"!tw-flex tw-w-full tw-justify-center tw-gap-4 md:!tw-inline-flex md:tw-w-auto\"\n data-test=\"stash-data-view-filters|drawer-toggle-button\"\n :filter-count=\"totalActiveFiltersCount\"\n @click=\"isDrawerOpen = true\"\n >\n <span class=\"tw-inline-flex tw-items-center tw-gap-3\">\n <Icon name=\"filter-line\" class=\"tw-text-ice-700\" />\n <span>{{ t('ll.filters') }}</span>\n </span>\n </FilterChip>\n <slot v-if=\"isDesktop\"></slot>\n <Button v-if=\"totalActiveFiltersCount > 0 && isDesktop\" inline @click=\"handleResetAllClick\">\n {{ t('ll.resetAll') }}\n </Button>\n </div>\n </div>\n <Modal\n v-if=\"slots.drawer\"\n data-test=\"stash-data-view-filters|drawer\"\n disable-body-padding\n position=\"right\"\n size=\"narrow\"\n :is-open=\"isDrawerOpen\"\n :title=\"t('ll.allFilters')\"\n v-bind=\"props.drawerProps\"\n @dismiss=\"onDismiss\"\n >\n <template #headerAction>\n <Button\n v-if=\"isViewingSingleGroup\"\n icon\n class=\"tw-text-ice-100\"\n data-test=\"stash-data-view-filters|drawer-previous-button\"\n :aria-label=\"t('ll.previous')\"\n :title=\"t('ll.previous')\"\n @click=\"emit('previous')\"\n >\n <Icon name=\"chevron-left\" />\n </Button>\n </template>\n\n <slot name=\"drawer\"></slot>\n\n <template #footer>\n <div class=\"tw-flex tw-justify-end tw-gap-gutter\">\n <Button v-if=\"totalActiveFiltersCount === 0\" secondary @click=\"onDismiss\">\n {{ t('ll.cancel') }}\n </Button>\n <Button\n v-if=\"(isViewingGroupsMenu || props.drawerStyle === 'cascade') && totalActiveFiltersCount > 0\"\n secondary\n :disabled=\"isDataViewLoading\"\n @click=\"handleResetAllClick\"\n >\n {{ t('ll.resetAll') }}\n </Button>\n <Button\n v-if=\"isViewingSingleGroup && activeGroupActiveFiltersCount > 0\"\n secondary\n :disabled=\"isDataViewLoading\"\n @click=\"handleResetGroupClick\"\n >\n {{ t('ll.reset') }}\n </Button>\n <Button\n v-if=\"isViewingSingleGroup || props.drawerStyle === 'cascade'\"\n :disabled=\"isDataViewLoading\"\n @click=\"handleApplyClick\"\n >\n {{ t('ll.apply') }}\n </Button>\n </div>\n </template>\n </Modal>\n </Box>\n</template>\n"],"names":["DrawerStyle","useFilters","schema","dataViewRef","appliedFilters","ref","workingFilters","filterName","dvRef","applyFilters","cloneDeep","resetAllFilters","resetFilterGroup","group","undoWorkingFilters","activeFiltersCounts","computed","counts","config","value","_a","isDefined","totalActiveFiltersCount","count","props","__props","emit","__emit","slots","_useSlots","isDesktop","useMediaQuery","SCREEN_SIZES","isViewingGroupsMenu","isViewingSingleGroup","density","isDataViewLoading","isWithinModule","currentSearch","updateCurrentSearch","inject","DATA_VIEW_INJECTION","provide","DATA_VIEW_FILTERS_UTILS_INJECTION","activeGroupActiveFiltersCount","isDrawerOpen","handleApplyClick","preventDismiss","_b","handleResetGroupClick","handleResetAllClick","onDismiss","watch"],"mappings":"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"}
@@ -44,16 +44,25 @@ export declare interface DataViewFiltersProps {
44
44
  */
45
45
  searchBarProps?: SearchBarProps;
46
46
  showSearch?: boolean;
47
- /** 'cascade' displays all fields within every filter group; 'nested' displays only the group names and requires clicking a group to view its fields */
48
- drawerStyle?: DrawerStyle;
47
+ /** 'cascade' displays all fields within every filter group; 'nested' displays only the group names and requires clicking a group to view its fields. */
48
+ drawerStyle?: DrawerStyles;
49
49
  drawerProps?: ModalProps;
50
+ /**
51
+ * @deprecated The `activeGroup` prop is a sufficient replacement for this prop. A falsy `activeGroup` will hide the button and a truthy `activeGroup` will show it (when the `drawerStyle` is 'nested').
52
+ *
53
+ * **Note:** This prop has no effect when using a "cascade" `drawerStyle`.
54
+ */
50
55
  showDrawerPreviousButton?: boolean;
51
56
  /**
52
57
  * Required when using filters. This prop should contain the return value of the `useFilters()` composable.
53
58
  */
54
59
  useFiltersInstance?: UseFiltersReturnType;
55
60
  onApply?: OnApplyFilters;
56
- /** The name of the active filter group. The active filter group is determined by which instance of FilterDropdown or FilterDrawerItem is open. */
61
+ /**
62
+ * The name of the active filter group. The active filter group is determined by which instance of FilterDropdown or FilterDrawerItem is open.
63
+ *
64
+ * **Note:** This prop is required when using a "nested" `drawerStyle`, but has no effect when using a "cascade" `drawerStyle`.
65
+ */
57
66
  activeGroup?: string;
58
67
  }
59
68
 
@@ -65,7 +74,7 @@ export declare interface DataViewFiltersSlots {
65
74
 
66
75
  export declare interface DataViewFiltersUtilsInjection {
67
76
  useFiltersInstance?: UseFiltersReturnType;
68
- drawerStyle?: DrawerStyle;
77
+ drawerStyle?: DrawerStyles;
69
78
  }
70
79
 
71
80
  declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<DataViewFiltersProps>, {
@@ -78,7 +87,7 @@ declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes
78
87
  showSearch: boolean;
79
88
  useFiltersInstance: undefined;
80
89
  onApply: undefined;
81
- activeGroup: string;
90
+ activeGroup: undefined;
82
91
  }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
83
92
  "open-drawer": () => void;
84
93
  dismiss: () => void;
@@ -95,7 +104,7 @@ declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes
95
104
  showSearch: boolean;
96
105
  useFiltersInstance: undefined;
97
106
  onApply: undefined;
98
- activeGroup: string;
107
+ activeGroup: undefined;
99
108
  }>>> & Readonly<{
100
109
  onDismiss?: (() => any) | undefined;
101
110
  "onOpen-drawer"?: (() => any) | undefined;
@@ -106,7 +115,7 @@ declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes
106
115
  filtersLabelText: string;
107
116
  searchBarProps: SearchBarProps;
108
117
  showSearch: boolean;
109
- drawerStyle: DrawerStyle;
118
+ drawerStyle: "cascade" | "nested";
110
119
  drawerProps: ModalProps;
111
120
  showDrawerPreviousButton: boolean;
112
121
  useFiltersInstance: UseFiltersReturnType<object, string>;
@@ -115,7 +124,14 @@ declare const _default: __VLS_WithTemplateSlots<DefineComponent<ExtractPropTypes
115
124
  }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>, Readonly<DataViewFiltersSlots> & DataViewFiltersSlots>;
116
125
  export default _default;
117
126
 
118
- export declare type DrawerStyle = 'cascade' | 'nested';
127
+ export declare enum DrawerStyle {
128
+ /** Displays all groups and their fields without the need for navigating submenus. */
129
+ Cascade = "cascade",
130
+ /** Displays only group names or fields; navigation between the group names and a submenu of fields is required. */
131
+ Nested = "nested"
132
+ }
133
+
134
+ export declare type DrawerStyles = `${DrawerStyle}`;
119
135
 
120
136
  declare interface Injection<T> {
121
137
  key: InjectionKey<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leaflink/stash",
3
- "version": "49.3.0",
3
+ "version": "49.3.2",
4
4
  "description": "LeafLink's design system.",
5
5
  "homepage": "https://stash.leaflink.com",
6
6
  "main": "./dist/index.ts",