@leaflink/stash 52.0.3 → 53.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -49
- package/dist/Accordion.js +16 -16
- package/dist/Accordion.js.map +1 -1
- package/dist/AccordionGroup.js +7 -7
- package/dist/AccordionGroup.js.map +1 -1
- package/dist/ActionsDropdown.js +16 -16
- package/dist/ActionsDropdown.js.map +1 -1
- package/dist/AddressSelect.js.map +1 -1
- package/dist/AddressSelect.vue.d.ts +1 -1
- package/dist/Alert.js +34 -34
- package/dist/Alert.js.map +1 -1
- package/dist/AppNavigationItem.js +31 -31
- package/dist/AppNavigationItem.js.map +1 -1
- package/dist/AppSidebar.js +19 -19
- package/dist/AppSidebar.js.map +1 -1
- package/dist/AppTopbar.js +32 -32
- package/dist/AppTopbar.js.map +1 -1
- package/dist/Avatar.js +18 -18
- package/dist/Avatar.js.map +1 -1
- package/dist/Backdrop.js +5 -5
- package/dist/Backdrop.js.map +1 -1
- package/dist/Badge.js +38 -38
- package/dist/Badge.js.map +1 -1
- package/dist/Box.js +1 -1
- package/dist/{Box.vue_vue_type_script_setup_true_lang-rFnvwLVY.js → Box.vue_vue_type_script_setup_true_lang-dFFZN40_.js} +6 -6
- package/dist/{Box.vue_vue_type_script_setup_true_lang-rFnvwLVY.js.map → Box.vue_vue_type_script_setup_true_lang-dFFZN40_.js.map} +1 -1
- package/dist/Button.js +21 -21
- package/dist/Button.js.map +1 -1
- package/dist/ButtonGroup.js +26 -26
- package/dist/ButtonGroup.js.map +1 -1
- package/dist/Card.js +14 -14
- package/dist/Card.js.map +1 -1
- package/dist/CardContent.js +1 -1
- package/dist/CardContent.js.map +1 -1
- package/dist/CardFooter.js +1 -1
- package/dist/CardFooter.js.map +1 -1
- package/dist/CardHeader.js +4 -4
- package/dist/CardHeader.js.map +1 -1
- package/dist/CardMedia.js +20 -20
- package/dist/CardMedia.js.map +1 -1
- package/dist/Carousel.js +60 -60
- package/dist/Carousel.js.map +1 -1
- package/dist/Checkbox.js +30 -30
- package/dist/Checkbox.js.map +1 -1
- package/dist/Checkbox.vue.d.ts +0 -3
- package/dist/Chip.js +33 -33
- package/dist/Chip.js.map +1 -1
- package/dist/ConfirmationCodeInput.js +72 -72
- package/dist/ConfirmationCodeInput.js.map +1 -1
- package/dist/ContextSwitcher.js +27 -27
- package/dist/ContextSwitcher.js.map +1 -1
- package/dist/Copy.js +47 -48
- package/dist/Copy.js.map +1 -1
- package/dist/CurrencyInput.js +1 -1
- package/dist/CurrencyInput.js.map +1 -1
- package/dist/CurrencyInput.vue.d.ts +5 -5
- package/dist/DataView.js +23 -23
- package/dist/DataView.js.map +1 -1
- package/dist/DataViewFilters.js +26 -26
- package/dist/DataViewFilters.js.map +1 -1
- package/dist/DataViewSortButton.js +22 -22
- package/dist/DataViewSortButton.js.map +1 -1
- package/dist/DataViewToolbar.js +52 -52
- package/dist/DataViewToolbar.js.map +1 -1
- package/dist/DatePicker.js +10 -10
- package/dist/DatePicker.js.map +1 -1
- package/dist/DescriptionList.js +2 -2
- package/dist/DescriptionList.js.map +1 -1
- package/dist/DescriptionListDetail.js +2 -2
- package/dist/DescriptionListDetail.js.map +1 -1
- package/dist/DescriptionListGroup.js +9 -9
- package/dist/DescriptionListGroup.js.map +1 -1
- package/dist/DescriptionListTerm.js +8 -8
- package/dist/DescriptionListTerm.js.map +1 -1
- package/dist/Dialog.js +47 -47
- package/dist/Dialog.js.map +1 -1
- package/dist/Divider.js +6 -6
- package/dist/Divider.js.map +1 -1
- package/dist/Dropdown.js +20 -20
- package/dist/Dropdown.js.map +1 -1
- package/dist/EmptyState.js +26 -26
- package/dist/EmptyState.js.map +1 -1
- package/dist/Field.js +1 -1
- package/dist/{Field.vue_vue_type_script_setup_true_lang-DI6z3AE9.js → Field.vue_vue_type_script_setup_true_lang-dAGKfjf5.js} +17 -17
- package/dist/Field.vue_vue_type_script_setup_true_lang-dAGKfjf5.js.map +1 -0
- package/dist/FileUpload.js +47 -49
- package/dist/FileUpload.js.map +1 -1
- package/dist/FilterChip.js +20 -20
- package/dist/FilterChip.js.map +1 -1
- package/dist/FilterDrawerItem.js +13 -13
- package/dist/FilterDrawerItem.js.map +1 -1
- package/dist/FilterDropdown.js +27 -27
- package/dist/FilterDropdown.js.map +1 -1
- package/dist/FilterSelect.js +33 -33
- package/dist/FilterSelect.js.map +1 -1
- package/dist/Filters.js +29 -29
- package/dist/Filters.js.map +1 -1
- package/dist/Filters.vue.d.ts +2 -8
- package/dist/HttpError.js +29 -29
- package/dist/HttpError.js.map +1 -1
- package/dist/HttpError.vue.d.ts +0 -3
- package/dist/Icon.js +12 -12
- package/dist/Icon.js.map +1 -1
- package/dist/IconLabel.js +19 -19
- package/dist/IconLabel.js.map +1 -1
- package/dist/IconLabel.vue.d.ts +1 -1
- package/dist/Illustration.js +2 -2
- package/dist/{Illustration.vue_vue_type_script_setup_true_lang-BrqEF8xe.js → Illustration.vue_vue_type_script_setup_true_lang-C1bPkWZZ.js} +4 -4
- package/dist/{Illustration.vue_vue_type_script_setup_true_lang-BrqEF8xe.js.map → Illustration.vue_vue_type_script_setup_true_lang-C1bPkWZZ.js.map} +1 -1
- package/dist/Image.js +2 -2
- package/dist/Image.vue.d.ts +0 -3
- package/dist/{Image.vue_vue_type_script_setup_true_lang-D5u4av0_.js → Image.vue_vue_type_script_setup_true_lang-CAj0FH9h.js} +11 -11
- package/dist/Image.vue_vue_type_script_setup_true_lang-CAj0FH9h.js.map +1 -0
- package/dist/InlineEdit.js +8 -8
- package/dist/InlineEdit.js.map +1 -1
- package/dist/Input.js +29 -29
- package/dist/Input.js.map +1 -1
- package/dist/InputOptions.js +87 -84
- package/dist/InputOptions.js.map +1 -1
- package/dist/InputOptions.vue.d.ts +2 -2
- package/dist/IntegrationIcon.js +11 -11
- package/dist/IntegrationIcon.js.map +1 -1
- package/dist/Label.js +1 -1
- package/dist/{Label.vue_vue_type_script_setup_true_lang-CNquF3AP.js → Label.vue_vue_type_script_setup_true_lang-xwY3X-iV.js} +16 -16
- package/dist/{Label.vue_vue_type_script_setup_true_lang-CNquF3AP.js.map → Label.vue_vue_type_script_setup_true_lang-xwY3X-iV.js.map} +1 -1
- package/dist/ListItem.js +14 -14
- package/dist/ListItem.js.map +1 -1
- package/dist/ListItem.vue.d.ts +0 -6
- package/dist/ListItemCell.js +9 -9
- package/dist/ListItemCell.js.map +1 -1
- package/dist/ListView.js +138 -141
- package/dist/ListView.js.map +1 -1
- package/dist/ListView.vue.d.ts +2 -26
- package/dist/Loading.js +8 -8
- package/dist/Loading.js.map +1 -1
- package/dist/Logo.js +1 -1
- package/dist/{Logo.vue_vue_type_script_setup_true_lang-Dz8c98sc.js → Logo.vue_vue_type_script_setup_true_lang-DghNC_k6.js} +3 -3
- package/dist/{Logo.vue_vue_type_script_setup_true_lang-Dz8c98sc.js.map → Logo.vue_vue_type_script_setup_true_lang-DghNC_k6.js.map} +1 -1
- package/dist/Menu.js +5 -5
- package/dist/Menu.js.map +1 -1
- package/dist/MenuItem.js +12 -12
- package/dist/MenuItem.js.map +1 -1
- package/dist/Metric.js +24 -24
- package/dist/Metric.js.map +1 -1
- package/dist/Modal.js +60 -60
- package/dist/Modal.js.map +1 -1
- package/dist/Modals.js +1 -1
- package/dist/Modals.js.map +1 -1
- package/dist/Module.js +6 -6
- package/dist/Module.js.map +1 -1
- package/dist/ModuleContent.js +16 -16
- package/dist/ModuleContent.js.map +1 -1
- package/dist/ModuleFooter.js +13 -13
- package/dist/ModuleFooter.js.map +1 -1
- package/dist/ModuleHeader.js +29 -29
- package/dist/ModuleHeader.js.map +1 -1
- package/dist/MoreActions.js +81 -84
- package/dist/MoreActions.js.map +1 -1
- package/dist/ObfuscateText.js +4 -4
- package/dist/ObfuscateText.js.map +1 -1
- package/dist/PageContent.js +13 -13
- package/dist/PageContent.js.map +1 -1
- package/dist/PageHeader.js +28 -28
- package/dist/PageHeader.js.map +1 -1
- package/dist/PageNavigation.js +1 -1
- package/dist/Paginate.js +45 -45
- package/dist/Paginate.js.map +1 -1
- package/dist/QuickAction.js +18 -18
- package/dist/QuickAction.js.map +1 -1
- package/dist/Radio.js +17 -17
- package/dist/Radio.js.map +1 -1
- package/dist/RadioGroup.js +121 -121
- package/dist/RadioGroup.js.map +1 -1
- package/dist/RadioNew.js +80 -80
- package/dist/RadioNew.js.map +1 -1
- package/dist/RadioNew.vue.d.ts +0 -3
- package/dist/RangeInput.js +2 -2
- package/dist/RangeInput.js.map +1 -1
- package/dist/SearchBar.js +9 -9
- package/dist/SearchBar.js.map +1 -1
- package/dist/SectionHeader.js +14 -14
- package/dist/SectionHeader.js.map +1 -1
- package/dist/Select.js +369 -366
- package/dist/Select.js.map +1 -1
- package/dist/SelectStatus.js +26 -26
- package/dist/SelectStatus.js.map +1 -1
- package/dist/Skeleton.js +20 -20
- package/dist/Skeleton.js.map +1 -1
- package/dist/Step.js +37 -40
- package/dist/Step.js.map +1 -1
- package/dist/Stepper.js +17 -17
- package/dist/Stepper.js.map +1 -1
- package/dist/Switch.js +57 -57
- package/dist/Switch.js.map +1 -1
- package/dist/Tab.js +17 -19
- package/dist/Tab.js.map +1 -1
- package/dist/TabPanel.js +1 -1
- package/dist/TabPanel.js.map +1 -1
- package/dist/Table.js +22 -22
- package/dist/Table.js.map +1 -1
- package/dist/TableCell.js +32 -32
- package/dist/TableCell.js.map +1 -1
- package/dist/TableHeaderCell.js +35 -35
- package/dist/TableHeaderCell.js.map +1 -1
- package/dist/TableHeaderRow.js +10 -10
- package/dist/TableHeaderRow.js.map +1 -1
- package/dist/TableRow.js +51 -51
- package/dist/TableRow.js.map +1 -1
- package/dist/Tabs.js +2 -2
- package/dist/{Tabs.vue_vue_type_script_setup_true_lang-B3Irnlcd.js → Tabs.vue_vue_type_script_setup_true_lang-BVTCcK6M.js} +33 -33
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-BVTCcK6M.js.map +1 -0
- package/dist/TextEditor.js +8 -8
- package/dist/TextEditor.js.map +1 -1
- package/dist/Textarea.js +15 -15
- package/dist/Textarea.js.map +1 -1
- package/dist/Thumbnail.js +41 -41
- package/dist/Thumbnail.js.map +1 -1
- package/dist/ThumbnailEmpty.js +3 -3
- package/dist/ThumbnailEmpty.js.map +1 -1
- package/dist/ThumbnailGroup.js +22 -22
- package/dist/ThumbnailGroup.js.map +1 -1
- package/dist/Timeline.js +3 -3
- package/dist/Timeline.js.map +1 -1
- package/dist/TimelineItem.js +22 -22
- package/dist/TimelineItem.js.map +1 -1
- package/dist/Toast.js +29 -29
- package/dist/Toast.js.map +1 -1
- package/dist/Toast.vue.d.ts +3 -0
- package/dist/Toasts.js +11 -11
- package/dist/Toasts.js.map +1 -1
- package/dist/Tooltip.js +2 -81
- package/dist/Tooltip.js.map +1 -1
- package/dist/Tooltip.vue.d.ts +1 -1
- package/dist/Tooltip.vue_vue_type_script_setup_true_lang-mzBLSXy3.js +84 -0
- package/dist/Tooltip.vue_vue_type_script_setup_true_lang-mzBLSXy3.js.map +1 -0
- package/dist/components.css +2 -2
- package/dist/constants.d.ts +9 -9
- package/dist/constants.js +17 -17
- package/dist/constants.js.map +1 -1
- package/dist/directives/tooltip.js +2 -2
- package/dist/directives/tooltip.js.map +1 -1
- package/dist/{index-C14LhAwV.js → index-DBV9Uz0C.js} +3 -3
- package/dist/{index-C14LhAwV.js.map → index-DBV9Uz0C.js.map} +1 -1
- package/dist/tailwind-base.js.d.ts +12 -0
- package/dist/tailwind-base.js.map +1 -1
- package/dist/useSortable.js +1 -1
- package/dist/utils/helpers.js +15 -15
- package/dist/utils/helpers.js.map +1 -1
- package/package.json +15 -15
- package/styles/backwards-compat.css +373 -2851
- package/styles/main.css +8 -0
- package/styles/sofia-font.css +23 -27
- package/styles/theme.css +1033 -0
- package/dist/Field.vue_vue_type_script_setup_true_lang-DI6z3AE9.js.map +0 -1
- package/dist/Image.vue_vue_type_script_setup_true_lang-D5u4av0_.js.map +0 -1
- package/dist/Tabs.vue_vue_type_script_setup_true_lang-B3Irnlcd.js.map +0 -1
- package/dist/tailwind-base.d.ts +0 -333
- package/styles/base.css +0 -902
- package/tailwind-base.ts +0 -455
package/dist/DataView.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { defineComponent as R, useCssModule as U, ref as l, inject as J, computed as n, watch as
|
|
1
|
+
import { defineComponent as R, useCssModule as U, ref as l, inject as J, computed as n, watch as z, provide as W, createElementBlock as G, openBlock as V, renderSlot as Z, createBlock as q, createCommentVNode as H, normalizeClass as K, unref as Q } from "vue";
|
|
2
2
|
import X from "lodash-es/cloneDeep";
|
|
3
3
|
import { M as I } from "./Module.keys-CEsrW2f0.js";
|
|
4
4
|
import Y from "./Paginate.js";
|
|
5
|
-
import { a as
|
|
5
|
+
import { a as O, D as w } from "./DataView.keys-aSOnA4AD.js";
|
|
6
6
|
import { _ as tt } from "./_plugin-vue_export-helper-CHgC5LLL.js";
|
|
7
|
-
function
|
|
7
|
+
function y(a) {
|
|
8
8
|
const o = a[0] === "-" ? "desc" : "asc";
|
|
9
9
|
return { id: o === "asc" ? a : a.slice(1), order: o };
|
|
10
10
|
}
|
|
@@ -42,7 +42,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
42
42
|
currentSort: { default: void 0 },
|
|
43
43
|
data: { default: () => [] },
|
|
44
44
|
density: { default: "comfortable" },
|
|
45
|
-
pageSize: { default:
|
|
45
|
+
pageSize: { default: O },
|
|
46
46
|
disablePagination: { type: Boolean, default: !1 },
|
|
47
47
|
hideBottomPagination: { type: Boolean, default: !1 },
|
|
48
48
|
totalDataCount: { default: 0 },
|
|
@@ -58,7 +58,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
58
58
|
return t.variant;
|
|
59
59
|
if (((e = _.variant) == null ? void 0 : e.value) === "table")
|
|
60
60
|
return "table";
|
|
61
|
-
}),
|
|
61
|
+
}), x = n(() => _.variant !== void 0), u = l(1), E = n(() => !t.disablePagination && t.totalDataCount > 0), N = n(() => t.totalDataCount === 1 / 0 && !t.hasNextPage), p = n(() => Math.ceil(t.totalDataCount / t.pageSize)), i = function(e, { shouldEmit: r } = {}) {
|
|
62
62
|
var c, h;
|
|
63
63
|
u.value = e, r && (S(), d("update:currentPage", e, t.pageSize)), Number((c = P.value) == null ? void 0 : c.getBoundingClientRect().top) < 0 && ((h = P.value) == null || h.scrollIntoView({ behavior: "smooth", block: "start" }));
|
|
64
64
|
}, C = function({ shouldEmit: e } = {}) {
|
|
@@ -68,7 +68,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
68
68
|
const r = Math.min(u.value + 1, p.value);
|
|
69
69
|
i(r, { shouldEmit: e });
|
|
70
70
|
};
|
|
71
|
-
|
|
71
|
+
z(
|
|
72
72
|
() => t.currentPage,
|
|
73
73
|
() => {
|
|
74
74
|
i(t.currentPage);
|
|
@@ -76,14 +76,14 @@ const ot = /* @__PURE__ */ R({
|
|
|
76
76
|
{ immediate: !0 }
|
|
77
77
|
);
|
|
78
78
|
const s = l(void 0), B = n(
|
|
79
|
-
() => s.value ?
|
|
79
|
+
() => s.value ? y(s.value).id : void 0
|
|
80
80
|
), M = n(
|
|
81
|
-
() => s.value ?
|
|
81
|
+
() => s.value ? y(s.value).order : void 0
|
|
82
82
|
), v = function(e, { sortOrder: r, shouldEmit: c } = {}) {
|
|
83
|
-
const { id: h, order: F } =
|
|
83
|
+
const { id: h, order: F } = y(s.value || ""), k = at({ newId: e, newOrder: r, oldId: h, oldOrder: F });
|
|
84
84
|
s.value = k, i(1), c && (S(), d("update:currentSort", k));
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
z(
|
|
87
87
|
() => t.currentSort,
|
|
88
88
|
() => {
|
|
89
89
|
v(t.currentSort);
|
|
@@ -93,7 +93,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
93
93
|
const g = l(""), T = l(!1), j = l(!1), m = function(e, { shouldEmit: r } = {}) {
|
|
94
94
|
g.value = e || "", i(1), r && (S(), d("update:currentSearch", e));
|
|
95
95
|
};
|
|
96
|
-
|
|
96
|
+
z(
|
|
97
97
|
() => t.currentSearch,
|
|
98
98
|
() => {
|
|
99
99
|
m(t.currentSearch);
|
|
@@ -113,12 +113,12 @@ const ot = /* @__PURE__ */ R({
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
return W(
|
|
116
|
-
|
|
116
|
+
w.key,
|
|
117
117
|
Object.freeze({
|
|
118
118
|
// Pagination
|
|
119
119
|
currentPage: n(() => u.value),
|
|
120
|
-
isPaginationEnabled:
|
|
121
|
-
isPaginateNextDisabled:
|
|
120
|
+
isPaginationEnabled: E,
|
|
121
|
+
isPaginateNextDisabled: N,
|
|
122
122
|
pageCount: p,
|
|
123
123
|
pageSize: n(() => t.pageSize),
|
|
124
124
|
totalDataCount: n(() => t.totalDataCount),
|
|
@@ -138,7 +138,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
138
138
|
isEmpty: n(() => t.data.length === 0),
|
|
139
139
|
isSelectable: j,
|
|
140
140
|
isLoading: n(() => t.isLoading),
|
|
141
|
-
isWithinModule:
|
|
141
|
+
isWithinModule: x,
|
|
142
142
|
variant: L
|
|
143
143
|
})
|
|
144
144
|
), o({
|
|
@@ -156,7 +156,7 @@ const ot = /* @__PURE__ */ R({
|
|
|
156
156
|
}), (e, r) => (V(), G("div", {
|
|
157
157
|
ref_key: "rootRef",
|
|
158
158
|
ref: P,
|
|
159
|
-
class: "stash-data-view
|
|
159
|
+
class: "stash-data-view relative",
|
|
160
160
|
"data-test": "stash-data-view"
|
|
161
161
|
}, [
|
|
162
162
|
Z(e.$slots, "default", {
|
|
@@ -172,11 +172,11 @@ const ot = /* @__PURE__ */ R({
|
|
|
172
172
|
updateCurrentSort: v,
|
|
173
173
|
updateCurrentSearch: m
|
|
174
174
|
}),
|
|
175
|
-
|
|
175
|
+
E.value && !x.value && p.value > 1 && !t.hideBottomPagination ? (V(), q(Y, {
|
|
176
176
|
key: 0,
|
|
177
|
-
class: K(["
|
|
177
|
+
class: K(["mt-6", Q($).paginate]),
|
|
178
178
|
"current-page": u.value,
|
|
179
|
-
"is-next-disabled": e.isLoading ||
|
|
179
|
+
"is-next-disabled": e.isLoading || N.value,
|
|
180
180
|
"list-length": t.totalDataCount,
|
|
181
181
|
"page-size": t.pageSize,
|
|
182
182
|
variant: t.totalDataCount === 1 / 0 ? "stats" : "standard",
|
|
@@ -184,17 +184,17 @@ const ot = /* @__PURE__ */ R({
|
|
|
184
184
|
}, null, 8, ["class", "current-page", "is-next-disabled", "list-length", "page-size", "variant"])) : H("", !0)
|
|
185
185
|
], 512));
|
|
186
186
|
}
|
|
187
|
-
}), rt = "
|
|
187
|
+
}), rt = "_paginate_1xzdj_3", it = {
|
|
188
188
|
paginate: rt
|
|
189
189
|
}, ut = {
|
|
190
190
|
$style: it
|
|
191
191
|
}, vt = /* @__PURE__ */ tt(ot, [["__cssModules", ut]]);
|
|
192
192
|
export {
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
w as DATA_VIEW_INJECTION,
|
|
194
|
+
O as DEFAULT_PAGE_SIZE,
|
|
195
195
|
nt as DataViewVariant,
|
|
196
196
|
vt as default,
|
|
197
|
-
|
|
197
|
+
y as deserializeSortValue,
|
|
198
198
|
at as getNextSort,
|
|
199
199
|
et as serializeSortValue
|
|
200
200
|
};
|
package/dist/DataView.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataView.js","sources":["../src/components/DataView/DataView.utils.ts","../src/components/DataView/DataView.types.ts","../src/components/DataView/DataView.vue"],"sourcesContent":["import { SortId, SortOrder, SortValue, SortValueDeserialized } from './DataView.types';\n\n/**\n * Receives a SortValue (ex: `'-product_name'`) and returns an object with a `id` and an `order`.\n */\nexport function deserializeSortValue(sort: SortValue): SortValueDeserialized {\n const order = sort[0] === '-' ? 'desc' : 'asc';\n const id = order === 'asc' ? sort : sort.slice(1);\n\n return { id, order };\n}\n\n/**\n * Receives an object with a `id` and an `order` and returns a SortValue (ex: `'-product_name'`).\n */\nexport function serializeSortValue({ id, order }: SortValueDeserialized): SortValue {\n return `${order === 'desc' ? '-' : ''}${id}`;\n}\n\ninterface GetNextSortArgs {\n newId: SortId | undefined;\n newOrder?: SortOrder;\n oldId?: SortId;\n oldOrder?: SortOrder;\n}\n\n/**\n * Given new and old sorting data, it returns the next sorting value using the following sorting cycle:\n *\n * \"unsorted --> ascending --> descending --> unsorted\"\n */\nexport function getNextSort({ newId, newOrder, oldId, oldOrder }: GetNextSortArgs): SortValue | undefined {\n if (!newId) {\n return undefined;\n }\n\n if (newId !== oldId) {\n // if sorting by a new field, sort ascending\n return serializeSortValue({ id: newId, order: newOrder || 'asc' });\n }\n\n /**\n * `newOrder` and `oldOrder` can each have 3 different values: undefined, 'asc', or 'desc'.\n * Therefore, there are 9 possible combinations (3 times 3). See below:\n */\n\n // #region newOrder: undefined\n if (!newOrder && !oldOrder) {\n return newId; // ascending\n }\n\n if (!newOrder && oldOrder === 'desc') {\n return undefined; // unsorted\n }\n\n if (!newOrder && oldOrder === 'asc') {\n return `-${newId}`; // descending\n }\n // #endregion\n\n // #region newOrder: asc\n if (newOrder === 'asc' && !oldOrder) {\n return newId;\n }\n\n if (newOrder === 'asc' && oldOrder === 'asc') {\n return undefined;\n }\n\n if (newOrder === 'asc' && oldOrder === 'desc') {\n return newId;\n }\n // #endregion\n\n // #region newOrder: desc\n if (newOrder === 'desc' && !oldOrder) {\n return `-${newId}`;\n }\n\n if (newOrder === 'desc' && oldOrder === 'desc') {\n return undefined;\n }\n\n if (newOrder === 'desc' && oldOrder === 'asc') {\n return `-${newId}`;\n }\n // #endregion\n}\n","import { ComputedRef, Ref } from 'vue';\n\nimport { SpacingDensities } from '../../../types/misc';\n\nexport enum DataViewVariant {\n Table = 'table',\n}\n\nexport type DataViewVariants = `${DataViewVariant}`;\n\n/**\n * A unique id for a sorting strategy. If the order is descending, it must begin with \"-\" (a hyphen/dash).\n *\n * Ex: `'product_name'` if ascending or `'-product_name'` if descending\n */\nexport type SortValue = string;\n\n/**\n * The SortValue with its leading hyphen/dash removed\n */\nexport type SortId = string;\n\n/**\n * Determined by whether or not there is a leading hyphen/dash in the SortValue\n */\nexport type SortOrder = 'asc' | 'desc';\n\n/**\n * A deserialized instance of a `SortValue`.\n */\nexport type SortValueDeserialized = {\n id: SortId;\n order: SortOrder;\n};\n\n/** Updates the DataView internal state with the given sortId */\nexport type UpdateCurrentSort = (\n sortId: SortId | undefined,\n options?: {\n sortOrder?: SortOrder;\n /** If true, emits the `update:currentSort` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the given page */\nexport type SetPage = (\n page: number,\n options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the previous page */\nexport type GoPrevPage = (options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n}) => void;\n\n/** Updates the DataView internal state with the next page */\nexport type GoNextPage = (options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n}) => void;\n\n/** Updates the DataView internal state with the given searchTerm */\nexport type UpdateCurrentSearch = (\n searchTerm?: string,\n options?: {\n /** If true, emits the `update:currentSearch` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the given filter values */\nexport type UpdateCurrentFilters<FilterValues = object> = (\n newFilters: FilterValues,\n options?: {\n /** If true, emits the `update:currentSearch` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\nexport interface UpdateEvent<FilterValues = object> {\n page?: number;\n pageSize?: number;\n ordering?: string;\n search?: string;\n filters?: FilterValues;\n}\n\nexport interface DataViewInjection {\n currentPage: ComputedRef<number>;\n\n /** Optional override for the next button disabled state */\n isPaginateNextDisabled: ComputedRef<boolean>;\n\n isPaginationEnabled: ComputedRef<boolean>;\n\n pageCount: ComputedRef<number>;\n\n pageSize: ComputedRef<number>;\n\n totalDataCount: ComputedRef<number>;\n\n /** Updates the DataView internal state with the given page */\n setPage: SetPage;\n\n /** Updates the DataView internal state with the previous page */\n goPrevPage: GoPrevPage;\n\n /** Updates the DataView internal state with the next page */\n goNextPage: GoNextPage;\n\n currentSortId: ComputedRef<SortId | undefined>;\n\n currentSortOrder: ComputedRef<SortOrder | undefined>;\n\n /** Updates the DataView internal state with the given sortId */\n updateCurrentSort: UpdateCurrentSort;\n\n currentSearch: ComputedRef<string>;\n\n /** Updates the DataView internal state with the given searchTerm */\n updateCurrentSearch: UpdateCurrentSearch;\n\n /**\n * The DataView's padding; the default value is \"comfortable\". On small screens, the density will always be \"compact\".\n */\n density: ComputedRef<SpacingDensities | undefined>;\n\n /**\n * Defines if a DataView has a Toolbar rendered. This prop is updated when DataViewToolbar exists and is mounted.\n */\n hasToolbar?: Ref<boolean>;\n\n /**\n * Enables certain loading indicators to be displayed within the DataView.\n */\n isLoading?: ComputedRef<boolean>;\n\n /**\n * Enables certain empty states to be displayed within the DataView.\n */\n isEmpty?: ComputedRef<boolean>;\n\n /**\n * Allows Table to control whether or not a DataViewToolbar should show a checkmark\n */\n isSelectable?: Ref<boolean>;\n\n /**\n * Whether or not the DataView is rendered within a Module; the value is inferred based on being\n * able to inject details from Module.\n *\n * Note: This is sent to DataView child components so they only need to worry about interfacing\n * with the DataViewInjection API.\n */\n isWithinModule: ComputedRef<boolean>;\n\n /**\n * The DataView's variant; the default value is undefined.\n */\n variant: ComputedRef<DataViewVariants | undefined>;\n}\n","<script lang=\"ts\">\n export * from './DataView.constants';\n export * from './DataView.keys';\n export * from './DataView.types';\n export * from './DataView.utils';\n</script>\n\n<script setup lang=\"ts\">\n import cloneDeep from 'lodash-es/cloneDeep';\n import { computed, inject, provide, ref, useCssModule, watch } from 'vue';\n\n import { SpacingDensities } from '../../../types/misc';\n import { MODULE_INJECTION } from '../Module/Module.keys';\n import Paginate from '../Paginate/Paginate.vue';\n import { DEFAULT_PAGE_SIZE } from './DataView.constants';\n import { DATA_VIEW_INJECTION } from './DataView.keys';\n import {\n DataViewVariants,\n GoNextPage,\n GoPrevPage,\n SetPage,\n SortId,\n SortOrder,\n SortValue,\n UpdateCurrentFilters,\n UpdateCurrentSearch,\n UpdateCurrentSort,\n UpdateEvent,\n } from './DataView.types';\n import { deserializeSortValue, getNextSort } from './DataView.utils';\n\n export interface DataViewProps {\n /**\n * Can be used to provide the initial page.\n * Also, it can be used to control the active page with `v-model:current-page=\"myPage\"`.\n */\n currentPage?: number;\n\n /**\n * Can be used to set the initial search term.\n * Also, it can be used to control the active search term with `v-model:current-search=\"mySearchTerm\"`.\n */\n currentSearch?: string;\n\n /**\n * Can be used to provide the initial sort order.\n * Also, it can be used to control the active sort order with `v-model:current-sort=\"mySortOrder\"`.\n */\n currentSort?: SortValue;\n\n /**\n * A list of records. If pagination is enabled, `data` must be only the current page of records.\n */\n data?: object[];\n\n /**\n * Controls the DataView's padding; the default value is \"comfortable\". On small screens, \"compact\" density is applied regardless of this prop's value.\n */\n density?: SpacingDensities;\n\n /**\n * The number of records to display per page.\n */\n pageSize?: number;\n\n /**\n * Opt-out of displaying pagination. Hides the pagination buttons and page stats.\n */\n disablePagination?: boolean;\n\n /**\n * Hides the bottom pagination without disabling the pagination from the toolbar\n */\n hideBottomPagination?: boolean;\n\n /**\n * The total number of records available.\n * Used to auto-enable pagination when results exist.\n * Use `Infinity` for activating 'n of many' pagination\n * DataView does not paginate data for you; instead, `props.data` should always show\n * the current page of results.\n */\n totalDataCount?: number;\n\n /**\n * Whether there is a next page of data or not as informed by the server.\n * This only applies when`totalDataCount=\"Infinity\"` to determine if the \"Next\" pagination button should be disabled.\n */\n hasNextPage?: boolean;\n\n /**\n * DataView variant. The default value is `undefined`. Will default to `table` when used within\n * a `<Module variant=\"table\">`.\n */\n variant?: DataViewVariants;\n\n isLoading?: boolean;\n }\n\n const props = withDefaults(defineProps<DataViewProps>(), {\n currentPage: 1,\n currentSearch: undefined,\n currentSort: undefined,\n data: () => [],\n density: 'comfortable',\n pageSize: DEFAULT_PAGE_SIZE,\n disablePagination: false,\n totalDataCount: 0,\n hasNextPage: undefined,\n hideBottomPagination: false,\n variant: undefined,\n });\n\n const emit = defineEmits<{\n (e: 'update', state: UpdateEvent): void;\n (e: 'update:currentFilters', newFilters: object): void;\n (e: 'update:currentPage', page: number, pageSize: number): void;\n (e: 'update:currentSearch', searchTerm?: string): void;\n (e: 'update:currentSort', payload?: SortValue): void;\n }>();\n\n const classes = useCssModule();\n const rootRef = ref<HTMLElement | null>(null);\n const moduleInjection = inject(MODULE_INJECTION.key, MODULE_INJECTION.defaults);\n const computedVariant = computed<DataViewVariants | undefined>(() => {\n if (props.variant) {\n return props.variant;\n }\n\n if (moduleInjection.variant?.value === 'table') {\n return 'table';\n }\n\n return undefined;\n });\n const isWithinModule = computed(() => moduleInjection.variant !== undefined);\n\n // #region pagination\n const internalPage = ref(1);\n const isPaginationEnabled = computed(() => !props.disablePagination && props.totalDataCount > 0);\n const isPaginateNextDisabled = computed(() => props.totalDataCount === Infinity && !props.hasNextPage);\n const pageCount = computed(() => Math.ceil(props.totalDataCount / props.pageSize));\n\n const setPage: SetPage = function (page: number, { shouldEmit } = {}) {\n internalPage.value = page;\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentPage', page, props.pageSize);\n }\n\n if (Number(rootRef.value?.getBoundingClientRect().top) < 0) {\n rootRef.value?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n };\n\n const goPrevPage: GoPrevPage = function ({ shouldEmit } = {}) {\n const page = Math.max(internalPage.value - 1, 1);\n\n setPage(page, { shouldEmit });\n };\n\n /** Updates the DataView internal state with the previous page */\n const goNextPage: GoNextPage = function ({ shouldEmit } = {}) {\n const page = Math.min(internalPage.value + 1, pageCount.value);\n\n setPage(page, { shouldEmit });\n };\n\n watch(\n () => props.currentPage,\n () => {\n setPage(props.currentPage);\n },\n { immediate: true },\n );\n // #endregion pagination\n\n // #region sorting\n const internalSort = ref<SortValue | undefined>(undefined);\n\n const internalSortId = computed<SortId | undefined>(() =>\n internalSort.value ? deserializeSortValue(internalSort.value).id : undefined,\n );\n const internalSortOrder = computed<SortOrder | undefined>(() =>\n internalSort.value ? deserializeSortValue(internalSort.value).order : undefined,\n );\n\n const updateCurrentSort: UpdateCurrentSort = function (sortId, { sortOrder, shouldEmit } = {}) {\n const { id: oldId, order: oldOrder } = deserializeSortValue(internalSort.value || '');\n const nextSort = getNextSort({ newId: sortId, newOrder: sortOrder, oldId, oldOrder });\n\n internalSort.value = nextSort;\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentSort', nextSort);\n }\n };\n\n watch(\n () => props.currentSort,\n () => {\n updateCurrentSort(props.currentSort);\n },\n { immediate: true },\n );\n // #endregion sorting\n\n // #region search\n const internalSearch = ref('');\n\n const hasToolbar = ref(false);\n const isSelectable = ref(false);\n\n const updateCurrentSearch: UpdateCurrentSearch = function (searchTerm, { shouldEmit } = {}) {\n internalSearch.value = searchTerm || '';\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentSearch', searchTerm);\n }\n };\n\n watch(\n () => props.currentSearch,\n () => {\n updateCurrentSearch(props.currentSearch);\n },\n { immediate: true },\n );\n // #endregion search\n\n // #region filters\n const internalFilters = ref<object>({});\n\n const updateCurrentFilters: UpdateCurrentFilters = function (newFilters: object, { shouldEmit } = {}) {\n internalFilters.value = newFilters;\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentFilters', newFilters);\n }\n };\n // #endregion filters\n\n function emitUpdate() {\n emit('update', {\n page: internalPage.value,\n pageSize: props.pageSize,\n ordering: internalSort.value,\n search: internalSearch.value,\n filters: cloneDeep(internalFilters.value),\n });\n }\n\n provide(\n DATA_VIEW_INJECTION.key,\n Object.freeze({\n // Pagination\n currentPage: computed(() => internalPage.value),\n isPaginationEnabled,\n isPaginateNextDisabled,\n pageCount,\n pageSize: computed(() => props.pageSize),\n totalDataCount: computed(() => props.totalDataCount),\n setPage,\n goPrevPage,\n goNextPage,\n\n // Sorting\n currentSortId: internalSortId,\n currentSortOrder: internalSortOrder,\n updateCurrentSort,\n\n // Search\n currentSearch: computed(() => internalSearch.value),\n updateCurrentSearch,\n\n // Miscellaneous\n density: computed(() => props.density),\n hasToolbar,\n isEmpty: computed(() => props.data.length === 0),\n isSelectable,\n isLoading: computed(() => props.isLoading),\n isWithinModule,\n variant: computedVariant,\n }),\n );\n\n defineExpose({\n page: computed(() => internalPage.value),\n pageSize: computed(() => props.pageSize),\n setPage,\n goPrevPage,\n goNextPage,\n ordering: computed(() => internalSort.value),\n updateCurrentSort,\n search: computed(() => internalSearch.value),\n updateCurrentSearch,\n filters: computed(() => internalFilters.value),\n updateCurrentFilters,\n });\n</script>\n\n<template>\n <div ref=\"rootRef\" class=\"stash-data-view tw-relative\" data-test=\"stash-data-view\">\n <!-- @slot default -->\n <slot\n :current-page=\"internalPage\"\n :current-sort-id=\"internalSortId\"\n :current-sort-order=\"internalSortOrder\"\n :data=\"data\"\n :go-prev-page=\"goPrevPage\"\n :go-next-page=\"goNextPage\"\n :page-count=\"pageCount\"\n :set-page=\"setPage\"\n :total-data-count=\"props.totalDataCount\"\n :update-current-sort=\"updateCurrentSort\"\n :update-current-search=\"updateCurrentSearch\"\n ></slot>\n\n <Paginate\n v-if=\"isPaginationEnabled && !isWithinModule && pageCount > 1 && !props.hideBottomPagination\"\n class=\"tw-mt-6\"\n :class=\"classes.paginate\"\n :current-page=\"internalPage\"\n :is-next-disabled=\"isLoading || isPaginateNextDisabled\"\n :list-length=\"props.totalDataCount\"\n :page-size=\"props.pageSize\"\n :variant=\"props.totalDataCount === Infinity ? 'stats' : 'standard'\"\n @set-page=\"(page: number) => setPage(page, { shouldEmit: true })\"\n />\n </div>\n</template>\n\n<style module>\n .paginate ul {\n margin: 0;\n }\n</style>\n"],"names":["deserializeSortValue","sort","order","serializeSortValue","id","getNextSort","newId","newOrder","oldId","oldOrder","DataViewVariant","props","__props","emit","__emit","classes","useCssModule","rootRef","ref","moduleInjection","inject","MODULE_INJECTION","computedVariant","computed","_a","isWithinModule","internalPage","isPaginationEnabled","isPaginateNextDisabled","pageCount","setPage","page","shouldEmit","emitUpdate","_b","goPrevPage","goNextPage","watch","internalSort","internalSortId","internalSortOrder","updateCurrentSort","sortId","sortOrder","nextSort","internalSearch","hasToolbar","isSelectable","updateCurrentSearch","searchTerm","internalFilters","updateCurrentFilters","newFilters","cloneDeep","provide","DATA_VIEW_INJECTION","__expose"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataView.js","sources":["../src/components/DataView/DataView.utils.ts","../src/components/DataView/DataView.types.ts","../src/components/DataView/DataView.vue"],"sourcesContent":["import { SortId, SortOrder, SortValue, SortValueDeserialized } from './DataView.types';\n\n/**\n * Receives a SortValue (ex: `'-product_name'`) and returns an object with a `id` and an `order`.\n */\nexport function deserializeSortValue(sort: SortValue): SortValueDeserialized {\n const order = sort[0] === '-' ? 'desc' : 'asc';\n const id = order === 'asc' ? sort : sort.slice(1);\n\n return { id, order };\n}\n\n/**\n * Receives an object with a `id` and an `order` and returns a SortValue (ex: `'-product_name'`).\n */\nexport function serializeSortValue({ id, order }: SortValueDeserialized): SortValue {\n return `${order === 'desc' ? '-' : ''}${id}`;\n}\n\ninterface GetNextSortArgs {\n newId: SortId | undefined;\n newOrder?: SortOrder;\n oldId?: SortId;\n oldOrder?: SortOrder;\n}\n\n/**\n * Given new and old sorting data, it returns the next sorting value using the following sorting cycle:\n *\n * \"unsorted --> ascending --> descending --> unsorted\"\n */\nexport function getNextSort({ newId, newOrder, oldId, oldOrder }: GetNextSortArgs): SortValue | undefined {\n if (!newId) {\n return undefined;\n }\n\n if (newId !== oldId) {\n // if sorting by a new field, sort ascending\n return serializeSortValue({ id: newId, order: newOrder || 'asc' });\n }\n\n /**\n * `newOrder` and `oldOrder` can each have 3 different values: undefined, 'asc', or 'desc'.\n * Therefore, there are 9 possible combinations (3 times 3). See below:\n */\n\n // #region newOrder: undefined\n if (!newOrder && !oldOrder) {\n return newId; // ascending\n }\n\n if (!newOrder && oldOrder === 'desc') {\n return undefined; // unsorted\n }\n\n if (!newOrder && oldOrder === 'asc') {\n return `-${newId}`; // descending\n }\n // #endregion\n\n // #region newOrder: asc\n if (newOrder === 'asc' && !oldOrder) {\n return newId;\n }\n\n if (newOrder === 'asc' && oldOrder === 'asc') {\n return undefined;\n }\n\n if (newOrder === 'asc' && oldOrder === 'desc') {\n return newId;\n }\n // #endregion\n\n // #region newOrder: desc\n if (newOrder === 'desc' && !oldOrder) {\n return `-${newId}`;\n }\n\n if (newOrder === 'desc' && oldOrder === 'desc') {\n return undefined;\n }\n\n if (newOrder === 'desc' && oldOrder === 'asc') {\n return `-${newId}`;\n }\n // #endregion\n}\n","import { ComputedRef, Ref } from 'vue';\n\nimport { SpacingDensities } from '../../../types/misc';\n\nexport enum DataViewVariant {\n Table = 'table',\n}\n\nexport type DataViewVariants = `${DataViewVariant}`;\n\n/**\n * A unique id for a sorting strategy. If the order is descending, it must begin with \"-\" (a hyphen/dash).\n *\n * Ex: `'product_name'` if ascending or `'-product_name'` if descending\n */\nexport type SortValue = string;\n\n/**\n * The SortValue with its leading hyphen/dash removed\n */\nexport type SortId = string;\n\n/**\n * Determined by whether or not there is a leading hyphen/dash in the SortValue\n */\nexport type SortOrder = 'asc' | 'desc';\n\n/**\n * A deserialized instance of a `SortValue`.\n */\nexport type SortValueDeserialized = {\n id: SortId;\n order: SortOrder;\n};\n\n/** Updates the DataView internal state with the given sortId */\nexport type UpdateCurrentSort = (\n sortId: SortId | undefined,\n options?: {\n sortOrder?: SortOrder;\n /** If true, emits the `update:currentSort` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the given page */\nexport type SetPage = (\n page: number,\n options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the previous page */\nexport type GoPrevPage = (options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n}) => void;\n\n/** Updates the DataView internal state with the next page */\nexport type GoNextPage = (options?: {\n /** If true, emits the `update:currentPage` and `update` events from DataView */\n shouldEmit?: boolean;\n}) => void;\n\n/** Updates the DataView internal state with the given searchTerm */\nexport type UpdateCurrentSearch = (\n searchTerm?: string,\n options?: {\n /** If true, emits the `update:currentSearch` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\n/** Updates the DataView internal state with the given filter values */\nexport type UpdateCurrentFilters<FilterValues = object> = (\n newFilters: FilterValues,\n options?: {\n /** If true, emits the `update:currentSearch` and `update` events from DataView */\n shouldEmit?: boolean;\n },\n) => void;\n\nexport interface UpdateEvent<FilterValues = object> {\n page?: number;\n pageSize?: number;\n ordering?: string;\n search?: string;\n filters?: FilterValues;\n}\n\nexport interface DataViewInjection {\n currentPage: ComputedRef<number>;\n\n /** Optional override for the next button disabled state */\n isPaginateNextDisabled: ComputedRef<boolean>;\n\n isPaginationEnabled: ComputedRef<boolean>;\n\n pageCount: ComputedRef<number>;\n\n pageSize: ComputedRef<number>;\n\n totalDataCount: ComputedRef<number>;\n\n /** Updates the DataView internal state with the given page */\n setPage: SetPage;\n\n /** Updates the DataView internal state with the previous page */\n goPrevPage: GoPrevPage;\n\n /** Updates the DataView internal state with the next page */\n goNextPage: GoNextPage;\n\n currentSortId: ComputedRef<SortId | undefined>;\n\n currentSortOrder: ComputedRef<SortOrder | undefined>;\n\n /** Updates the DataView internal state with the given sortId */\n updateCurrentSort: UpdateCurrentSort;\n\n currentSearch: ComputedRef<string>;\n\n /** Updates the DataView internal state with the given searchTerm */\n updateCurrentSearch: UpdateCurrentSearch;\n\n /**\n * The DataView's padding; the default value is \"comfortable\". On small screens, the density will always be \"compact\".\n */\n density: ComputedRef<SpacingDensities | undefined>;\n\n /**\n * Defines if a DataView has a Toolbar rendered. This prop is updated when DataViewToolbar exists and is mounted.\n */\n hasToolbar?: Ref<boolean>;\n\n /**\n * Enables certain loading indicators to be displayed within the DataView.\n */\n isLoading?: ComputedRef<boolean>;\n\n /**\n * Enables certain empty states to be displayed within the DataView.\n */\n isEmpty?: ComputedRef<boolean>;\n\n /**\n * Allows Table to control whether or not a DataViewToolbar should show a checkmark\n */\n isSelectable?: Ref<boolean>;\n\n /**\n * Whether or not the DataView is rendered within a Module; the value is inferred based on being\n * able to inject details from Module.\n *\n * Note: This is sent to DataView child components so they only need to worry about interfacing\n * with the DataViewInjection API.\n */\n isWithinModule: ComputedRef<boolean>;\n\n /**\n * The DataView's variant; the default value is undefined.\n */\n variant: ComputedRef<DataViewVariants | undefined>;\n}\n","<script lang=\"ts\">\n export * from './DataView.constants';\n export * from './DataView.keys';\n export * from './DataView.types';\n export * from './DataView.utils';\n</script>\n\n<script setup lang=\"ts\">\n import cloneDeep from 'lodash-es/cloneDeep';\n import { computed, inject, provide, ref, useCssModule, watch } from 'vue';\n\n import { SpacingDensities } from '../../../types/misc';\n import { MODULE_INJECTION } from '../Module/Module.keys';\n import Paginate from '../Paginate/Paginate.vue';\n import { DEFAULT_PAGE_SIZE } from './DataView.constants';\n import { DATA_VIEW_INJECTION } from './DataView.keys';\n import {\n DataViewVariants,\n GoNextPage,\n GoPrevPage,\n SetPage,\n SortId,\n SortOrder,\n SortValue,\n UpdateCurrentFilters,\n UpdateCurrentSearch,\n UpdateCurrentSort,\n UpdateEvent,\n } from './DataView.types';\n import { deserializeSortValue, getNextSort } from './DataView.utils';\n\n export interface DataViewProps {\n /**\n * Can be used to provide the initial page.\n * Also, it can be used to control the active page with `v-model:current-page=\"myPage\"`.\n */\n currentPage?: number;\n\n /**\n * Can be used to set the initial search term.\n * Also, it can be used to control the active search term with `v-model:current-search=\"mySearchTerm\"`.\n */\n currentSearch?: string;\n\n /**\n * Can be used to provide the initial sort order.\n * Also, it can be used to control the active sort order with `v-model:current-sort=\"mySortOrder\"`.\n */\n currentSort?: SortValue;\n\n /**\n * A list of records. If pagination is enabled, `data` must be only the current page of records.\n */\n data?: object[];\n\n /**\n * Controls the DataView's padding; the default value is \"comfortable\". On small screens, \"compact\" density is applied regardless of this prop's value.\n */\n density?: SpacingDensities;\n\n /**\n * The number of records to display per page.\n */\n pageSize?: number;\n\n /**\n * Opt-out of displaying pagination. Hides the pagination buttons and page stats.\n */\n disablePagination?: boolean;\n\n /**\n * Hides the bottom pagination without disabling the pagination from the toolbar\n */\n hideBottomPagination?: boolean;\n\n /**\n * The total number of records available.\n * Used to auto-enable pagination when results exist.\n * Use `Infinity` for activating 'n of many' pagination\n * DataView does not paginate data for you; instead, `props.data` should always show\n * the current page of results.\n */\n totalDataCount?: number;\n\n /**\n * Whether there is a next page of data or not as informed by the server.\n * This only applies when`totalDataCount=\"Infinity\"` to determine if the \"Next\" pagination button should be disabled.\n */\n hasNextPage?: boolean;\n\n /**\n * DataView variant. The default value is `undefined`. Will default to `table` when used within\n * a `<Module variant=\"table\">`.\n */\n variant?: DataViewVariants;\n\n isLoading?: boolean;\n }\n\n const props = withDefaults(defineProps<DataViewProps>(), {\n currentPage: 1,\n currentSearch: undefined,\n currentSort: undefined,\n data: () => [],\n density: 'comfortable',\n pageSize: DEFAULT_PAGE_SIZE,\n disablePagination: false,\n totalDataCount: 0,\n hasNextPage: undefined,\n hideBottomPagination: false,\n variant: undefined,\n });\n\n const emit = defineEmits<{\n (e: 'update', state: UpdateEvent): void;\n (e: 'update:currentFilters', newFilters: object): void;\n (e: 'update:currentPage', page: number, pageSize: number): void;\n (e: 'update:currentSearch', searchTerm?: string): void;\n (e: 'update:currentSort', payload?: SortValue): void;\n }>();\n\n const classes = useCssModule();\n const rootRef = ref<HTMLElement | null>(null);\n const moduleInjection = inject(MODULE_INJECTION.key, MODULE_INJECTION.defaults);\n const computedVariant = computed<DataViewVariants | undefined>(() => {\n if (props.variant) {\n return props.variant;\n }\n\n if (moduleInjection.variant?.value === 'table') {\n return 'table';\n }\n\n return undefined;\n });\n const isWithinModule = computed(() => moduleInjection.variant !== undefined);\n\n // #region pagination\n const internalPage = ref(1);\n const isPaginationEnabled = computed(() => !props.disablePagination && props.totalDataCount > 0);\n const isPaginateNextDisabled = computed(() => props.totalDataCount === Infinity && !props.hasNextPage);\n const pageCount = computed(() => Math.ceil(props.totalDataCount / props.pageSize));\n\n const setPage: SetPage = function (page: number, { shouldEmit } = {}) {\n internalPage.value = page;\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentPage', page, props.pageSize);\n }\n\n if (Number(rootRef.value?.getBoundingClientRect().top) < 0) {\n rootRef.value?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n };\n\n const goPrevPage: GoPrevPage = function ({ shouldEmit } = {}) {\n const page = Math.max(internalPage.value - 1, 1);\n\n setPage(page, { shouldEmit });\n };\n\n /** Updates the DataView internal state with the previous page */\n const goNextPage: GoNextPage = function ({ shouldEmit } = {}) {\n const page = Math.min(internalPage.value + 1, pageCount.value);\n\n setPage(page, { shouldEmit });\n };\n\n watch(\n () => props.currentPage,\n () => {\n setPage(props.currentPage);\n },\n { immediate: true },\n );\n // #endregion pagination\n\n // #region sorting\n const internalSort = ref<SortValue | undefined>(undefined);\n\n const internalSortId = computed<SortId | undefined>(() =>\n internalSort.value ? deserializeSortValue(internalSort.value).id : undefined,\n );\n const internalSortOrder = computed<SortOrder | undefined>(() =>\n internalSort.value ? deserializeSortValue(internalSort.value).order : undefined,\n );\n\n const updateCurrentSort: UpdateCurrentSort = function (sortId, { sortOrder, shouldEmit } = {}) {\n const { id: oldId, order: oldOrder } = deserializeSortValue(internalSort.value || '');\n const nextSort = getNextSort({ newId: sortId, newOrder: sortOrder, oldId, oldOrder });\n\n internalSort.value = nextSort;\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentSort', nextSort);\n }\n };\n\n watch(\n () => props.currentSort,\n () => {\n updateCurrentSort(props.currentSort);\n },\n { immediate: true },\n );\n // #endregion sorting\n\n // #region search\n const internalSearch = ref('');\n\n const hasToolbar = ref(false);\n const isSelectable = ref(false);\n\n const updateCurrentSearch: UpdateCurrentSearch = function (searchTerm, { shouldEmit } = {}) {\n internalSearch.value = searchTerm || '';\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentSearch', searchTerm);\n }\n };\n\n watch(\n () => props.currentSearch,\n () => {\n updateCurrentSearch(props.currentSearch);\n },\n { immediate: true },\n );\n // #endregion search\n\n // #region filters\n const internalFilters = ref<object>({});\n\n const updateCurrentFilters: UpdateCurrentFilters = function (newFilters: object, { shouldEmit } = {}) {\n internalFilters.value = newFilters;\n setPage(1);\n\n if (shouldEmit) {\n emitUpdate();\n emit('update:currentFilters', newFilters);\n }\n };\n // #endregion filters\n\n function emitUpdate() {\n emit('update', {\n page: internalPage.value,\n pageSize: props.pageSize,\n ordering: internalSort.value,\n search: internalSearch.value,\n filters: cloneDeep(internalFilters.value),\n });\n }\n\n provide(\n DATA_VIEW_INJECTION.key,\n Object.freeze({\n // Pagination\n currentPage: computed(() => internalPage.value),\n isPaginationEnabled,\n isPaginateNextDisabled,\n pageCount,\n pageSize: computed(() => props.pageSize),\n totalDataCount: computed(() => props.totalDataCount),\n setPage,\n goPrevPage,\n goNextPage,\n\n // Sorting\n currentSortId: internalSortId,\n currentSortOrder: internalSortOrder,\n updateCurrentSort,\n\n // Search\n currentSearch: computed(() => internalSearch.value),\n updateCurrentSearch,\n\n // Miscellaneous\n density: computed(() => props.density),\n hasToolbar,\n isEmpty: computed(() => props.data.length === 0),\n isSelectable,\n isLoading: computed(() => props.isLoading),\n isWithinModule,\n variant: computedVariant,\n }),\n );\n\n defineExpose({\n page: computed(() => internalPage.value),\n pageSize: computed(() => props.pageSize),\n setPage,\n goPrevPage,\n goNextPage,\n ordering: computed(() => internalSort.value),\n updateCurrentSort,\n search: computed(() => internalSearch.value),\n updateCurrentSearch,\n filters: computed(() => internalFilters.value),\n updateCurrentFilters,\n });\n</script>\n\n<template>\n <div ref=\"rootRef\" class=\"stash-data-view relative\" data-test=\"stash-data-view\">\n <!-- @slot default -->\n <slot\n :current-page=\"internalPage\"\n :current-sort-id=\"internalSortId\"\n :current-sort-order=\"internalSortOrder\"\n :data=\"data\"\n :go-prev-page=\"goPrevPage\"\n :go-next-page=\"goNextPage\"\n :page-count=\"pageCount\"\n :set-page=\"setPage\"\n :total-data-count=\"props.totalDataCount\"\n :update-current-sort=\"updateCurrentSort\"\n :update-current-search=\"updateCurrentSearch\"\n ></slot>\n\n <Paginate\n v-if=\"isPaginationEnabled && !isWithinModule && pageCount > 1 && !props.hideBottomPagination\"\n class=\"mt-6\"\n :class=\"classes.paginate\"\n :current-page=\"internalPage\"\n :is-next-disabled=\"isLoading || isPaginateNextDisabled\"\n :list-length=\"props.totalDataCount\"\n :page-size=\"props.pageSize\"\n :variant=\"props.totalDataCount === Infinity ? 'stats' : 'standard'\"\n @set-page=\"(page: number) => setPage(page, { shouldEmit: true })\"\n />\n </div>\n</template>\n\n<style module>\n @layer utilities {\n .paginate ul {\n margin: 0;\n }\n }\n</style>\n"],"names":["deserializeSortValue","sort","order","serializeSortValue","id","getNextSort","newId","newOrder","oldId","oldOrder","DataViewVariant","props","__props","emit","__emit","classes","useCssModule","rootRef","ref","moduleInjection","inject","MODULE_INJECTION","computedVariant","computed","_a","isWithinModule","internalPage","isPaginationEnabled","isPaginateNextDisabled","pageCount","setPage","page","shouldEmit","emitUpdate","_b","goPrevPage","goNextPage","watch","internalSort","internalSortId","internalSortOrder","updateCurrentSort","sortId","sortOrder","nextSort","internalSearch","hasToolbar","isSelectable","updateCurrentSearch","searchTerm","internalFilters","updateCurrentFilters","newFilters","cloneDeep","provide","DATA_VIEW_INJECTION","__expose"],"mappings":"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"}
|
package/dist/DataViewFilters.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { ref as B, computed as C, defineComponent as j, useSlots as O, inject as z, provide as J, watch as Q, createBlock as
|
|
1
|
+
import { ref as B, computed as C, defineComponent as j, useSlots as O, inject as z, provide as J, watch as Q, createBlock as m, openBlock as f, normalizeClass as U, unref as t, withCtx as u, createCommentVNode as p, createElementBlock as Z, mergeProps as $, createElementVNode as A, renderSlot as G, createVNode as I, createTextVNode as k, toDisplayString as w } from "vue";
|
|
2
2
|
import q from "./useMediaQuery.js";
|
|
3
3
|
import { SCREEN_SIZES as H } from "./constants.js";
|
|
4
4
|
import { t as d } from "./locale.js";
|
|
5
|
-
import { _ as K } from "./Box.vue_vue_type_script_setup_true_lang-
|
|
5
|
+
import { _ as K } from "./Box.vue_vue_type_script_setup_true_lang-dFFZN40_.js";
|
|
6
6
|
import _ from "./Button.js";
|
|
7
7
|
import L from "lodash-es/cloneDeep";
|
|
8
8
|
import P from "./Icon.js";
|
|
9
9
|
import { D as R } from "./DataView.keys-aSOnA4AD.js";
|
|
10
10
|
import X from "./FilterChip.js";
|
|
11
|
-
import { _ as Y } from "./Label.vue_vue_type_script_setup_true_lang-
|
|
11
|
+
import { _ as Y } from "./Label.vue_vue_type_script_setup_true_lang-xwY3X-iV.js";
|
|
12
12
|
import ee from "./Modal.js";
|
|
13
13
|
import te from "./SearchBar.js";
|
|
14
14
|
import { D as le } from "./DataViewFilters.keys-BLu07FiP.js";
|
|
@@ -69,8 +69,8 @@ function Ae({
|
|
|
69
69
|
}
|
|
70
70
|
const se = {
|
|
71
71
|
key: 1,
|
|
72
|
-
class: "
|
|
73
|
-
}, re = { class: "
|
|
72
|
+
class: "col-span-12 row-start-2 md:col-start-7 md:row-start-1 lg:col-span-8 lg:col-start-5"
|
|
73
|
+
}, re = { class: "hidden md:block" }, ie = { class: "flex gap-4" }, oe = { class: "inline-flex items-center gap-3" }, ne = { class: "flex justify-end gap-gutter" }, he = /* @__PURE__ */ j({
|
|
74
74
|
__name: "DataViewFilters",
|
|
75
75
|
props: {
|
|
76
76
|
filtersLabelText: { default: d("ll.filterBy") },
|
|
@@ -124,16 +124,16 @@ const se = {
|
|
|
124
124
|
}
|
|
125
125
|
return Q(r, () => {
|
|
126
126
|
r.value && o("open-drawer");
|
|
127
|
-
}), (s, v) => (f(),
|
|
128
|
-
class: U(["stash-data-view-filters
|
|
127
|
+
}), (s, v) => (f(), m(K, {
|
|
128
|
+
class: U(["stash-data-view-filters grid grid-cols-12 gap-6 p-3", { "lg:p-6": t(E) === "comfortable", "mb-3": !t(S) }]),
|
|
129
129
|
radius: t(S) ? "none" : "rounded",
|
|
130
130
|
"data-test": "stash-data-view-filters",
|
|
131
131
|
"disable-padding": ""
|
|
132
132
|
}, {
|
|
133
133
|
default: u(() => [
|
|
134
|
-
e.showSearch ? (f(),
|
|
134
|
+
e.showSearch ? (f(), m(te, $({
|
|
135
135
|
key: 0,
|
|
136
|
-
class: "
|
|
136
|
+
class: "col-span-12 md:col-span-6 lg:col-span-4",
|
|
137
137
|
"data-test": "stash-data-view-filters|search-bar",
|
|
138
138
|
"is-loading": t(g),
|
|
139
139
|
label: t(d)("ll.search"),
|
|
@@ -146,7 +146,7 @@ const se = {
|
|
|
146
146
|
G(s.$slots, "filters-label", {}, () => [
|
|
147
147
|
I(Y, null, {
|
|
148
148
|
default: u(() => [
|
|
149
|
-
k(
|
|
149
|
+
k(w(e.filtersLabelText), 1)
|
|
150
150
|
]),
|
|
151
151
|
_: 1
|
|
152
152
|
})
|
|
@@ -155,7 +155,7 @@ const se = {
|
|
|
155
155
|
A("div", ie, [
|
|
156
156
|
I(X, {
|
|
157
157
|
secondary: "",
|
|
158
|
-
class: "!
|
|
158
|
+
class: "!md:inline-flex !flex w-full justify-center gap-4 md:w-auto",
|
|
159
159
|
"data-test": "stash-data-view-filters|drawer-toggle-button",
|
|
160
160
|
"filter-count": c.value,
|
|
161
161
|
onClick: v[1] || (v[1] = (F) => r.value = !0)
|
|
@@ -164,27 +164,27 @@ const se = {
|
|
|
164
164
|
A("span", oe, [
|
|
165
165
|
I(P, {
|
|
166
166
|
name: "filter-line",
|
|
167
|
-
class: "
|
|
167
|
+
class: "text-ice-700"
|
|
168
168
|
}),
|
|
169
|
-
A("span", null,
|
|
169
|
+
A("span", null, w(t(d)("ll.filters")), 1)
|
|
170
170
|
])
|
|
171
171
|
]),
|
|
172
172
|
_: 1
|
|
173
173
|
}, 8, ["filter-count"]),
|
|
174
174
|
t(h) ? G(s.$slots, "default", { key: 0 }) : p("", !0),
|
|
175
|
-
c.value > 0 && t(h) ? (f(),
|
|
175
|
+
c.value > 0 && t(h) ? (f(), m(_, {
|
|
176
176
|
key: 1,
|
|
177
177
|
inline: "",
|
|
178
178
|
onClick: x
|
|
179
179
|
}, {
|
|
180
180
|
default: u(() => [
|
|
181
|
-
k(
|
|
181
|
+
k(w(t(d)("ll.resetAll")), 1)
|
|
182
182
|
]),
|
|
183
183
|
_: 1
|
|
184
184
|
})) : p("", !0)
|
|
185
185
|
])
|
|
186
186
|
])) : p("", !0),
|
|
187
|
-
y.drawer ? (f(),
|
|
187
|
+
y.drawer ? (f(), m(ee, $({
|
|
188
188
|
key: 2,
|
|
189
189
|
"data-test": "stash-data-view-filters|drawer",
|
|
190
190
|
"disable-body-padding": "",
|
|
@@ -194,10 +194,10 @@ const se = {
|
|
|
194
194
|
title: t(d)("ll.allFilters")
|
|
195
195
|
}, e.drawerProps, { onDismiss: T }), {
|
|
196
196
|
headerAction: u(() => [
|
|
197
|
-
b.value ? (f(),
|
|
197
|
+
b.value ? (f(), m(_, {
|
|
198
198
|
key: 0,
|
|
199
199
|
icon: "",
|
|
200
|
-
class: "
|
|
200
|
+
class: "text-ice-100",
|
|
201
201
|
"data-test": "stash-data-view-filters|drawer-previous-button",
|
|
202
202
|
"aria-label": t(d)("ll.previous"),
|
|
203
203
|
title: t(d)("ll.previous"),
|
|
@@ -211,45 +211,45 @@ const se = {
|
|
|
211
211
|
]),
|
|
212
212
|
footer: u(() => [
|
|
213
213
|
A("div", ne, [
|
|
214
|
-
c.value === 0 ? (f(),
|
|
214
|
+
c.value === 0 ? (f(), m(_, {
|
|
215
215
|
key: 0,
|
|
216
216
|
secondary: "",
|
|
217
217
|
onClick: T
|
|
218
218
|
}, {
|
|
219
219
|
default: u(() => [
|
|
220
|
-
k(
|
|
220
|
+
k(w(t(d)("ll.cancel")), 1)
|
|
221
221
|
]),
|
|
222
222
|
_: 1
|
|
223
223
|
})) : p("", !0),
|
|
224
|
-
(V.value || e.drawerStyle === "cascade") && c.value > 0 ? (f(),
|
|
224
|
+
(V.value || e.drawerStyle === "cascade") && c.value > 0 ? (f(), m(_, {
|
|
225
225
|
key: 1,
|
|
226
226
|
secondary: "",
|
|
227
227
|
disabled: t(g),
|
|
228
228
|
onClick: x
|
|
229
229
|
}, {
|
|
230
230
|
default: u(() => [
|
|
231
|
-
k(
|
|
231
|
+
k(w(t(d)("ll.resetAll")), 1)
|
|
232
232
|
]),
|
|
233
233
|
_: 1
|
|
234
234
|
}, 8, ["disabled"])) : p("", !0),
|
|
235
|
-
b.value && n.value > 0 ? (f(),
|
|
235
|
+
b.value && n.value > 0 ? (f(), m(_, {
|
|
236
236
|
key: 2,
|
|
237
237
|
secondary: "",
|
|
238
238
|
disabled: t(g),
|
|
239
239
|
onClick: M
|
|
240
240
|
}, {
|
|
241
241
|
default: u(() => [
|
|
242
|
-
k(
|
|
242
|
+
k(w(t(d)("ll.reset")), 1)
|
|
243
243
|
]),
|
|
244
244
|
_: 1
|
|
245
245
|
}, 8, ["disabled"])) : p("", !0),
|
|
246
|
-
b.value || e.drawerStyle === "cascade" ? (f(),
|
|
246
|
+
b.value || e.drawerStyle === "cascade" ? (f(), m(_, {
|
|
247
247
|
key: 3,
|
|
248
248
|
disabled: t(g),
|
|
249
249
|
onClick: D
|
|
250
250
|
}, {
|
|
251
251
|
default: u(() => [
|
|
252
|
-
k(
|
|
252
|
+
k(w(t(d)("ll.apply")), 1)
|
|
253
253
|
]),
|
|
254
254
|
_: 1
|
|
255
255
|
}, 8, ["disabled"])) : p("", !0)
|
|
@@ -1 +1 @@
|
|
|
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?: () => unknown;\n drawer?: () => unknown;\n 'filters-label'?: () => unknown;\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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"}
|
|
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?: () => unknown;\n drawer?: () => unknown;\n 'filters-label'?: () => unknown;\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 grid grid-cols-12 gap-6 p-3\"\n :class=\"{ 'lg:p-6': density === 'comfortable', '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=\"col-span-12 md:col-span-6 lg: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=\"col-span-12 row-start-2 md:col-start-7 md:row-start-1 lg:col-span-8 lg:col-start-5\"\n >\n <div class=\"hidden md:block\">\n <slot name=\"filters-label\">\n <Label>{{ props.filtersLabelText }}</Label>\n </slot>\n </div>\n <div class=\"flex gap-4\">\n <FilterChip\n secondary\n class=\"!md:inline-flex !flex w-full justify-center gap-4 md:w-auto\"\n data-test=\"stash-data-view-filters|drawer-toggle-button\"\n :filter-count=\"totalActiveFiltersCount\"\n @click=\"isDrawerOpen = true\"\n >\n <span class=\"inline-flex items-center gap-3\">\n <Icon name=\"filter-line\" class=\"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=\"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=\"flex justify-end 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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"}
|