@leaflink/stash 44.0.0-beta.1 → 44.0.0-beta.11

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.
Files changed (228) hide show
  1. package/README.md +107 -39
  2. package/dist/ActionsDropdown.js +25 -25
  3. package/dist/ActionsDropdown.js.map +1 -1
  4. package/dist/AddressSelect.js +12 -11
  5. package/dist/AddressSelect.js.map +1 -1
  6. package/dist/Alert.js +9 -9
  7. package/dist/Alert.js.map +1 -1
  8. package/dist/AppNavigationItem.js +22 -22
  9. package/dist/AppNavigationItem.js.map +1 -1
  10. package/dist/AppSidebar.js +11 -11
  11. package/dist/AppSidebar.js.map +1 -1
  12. package/dist/AppTopbar.js +12 -12
  13. package/dist/Avatar.js +12 -12
  14. package/dist/Avatar.js.map +1 -1
  15. package/dist/Backdrop.js +1 -1
  16. package/dist/Backdrop.js.map +1 -1
  17. package/dist/Badge.js +12 -12
  18. package/dist/Badge.js.map +1 -1
  19. package/dist/Badge.vue.d.ts +1 -1
  20. package/dist/Button.js +1 -1
  21. package/dist/Button.js.map +1 -1
  22. package/dist/Button.vue_used_vue_type_style_index_0_lang.module-63d31dc0.js +17 -0
  23. package/dist/Button.vue_used_vue_type_style_index_0_lang.module-63d31dc0.js.map +1 -0
  24. package/dist/ButtonGroup.js +28 -28
  25. package/dist/ButtonGroup.js.map +1 -1
  26. package/dist/Card.js +3 -3
  27. package/dist/Card.js.map +1 -1
  28. package/dist/CardHeader.js +3 -3
  29. package/dist/CardMedia.js +1 -1
  30. package/dist/CardMedia.js.map +1 -1
  31. package/dist/Carousel.js +260 -248
  32. package/dist/Carousel.js.map +1 -1
  33. package/dist/Checkbox.js +58 -46
  34. package/dist/Checkbox.js.map +1 -1
  35. package/dist/Checkbox.vue.d.ts +2 -0
  36. package/dist/Checkbox.vue_used_vue_type_style_index_0_lang.module-fa8d9c06.js +9 -0
  37. package/dist/Checkbox.vue_used_vue_type_style_index_0_lang.module-fa8d9c06.js.map +1 -0
  38. package/dist/ChevronToggle.js +1 -1
  39. package/dist/Chip.js +1 -1
  40. package/dist/Chip.js.map +1 -1
  41. package/dist/ConfirmationCodeInput.js +21 -21
  42. package/dist/ConfirmationCodeInput.js.map +1 -1
  43. package/dist/ContextSwitcher.js +6 -5
  44. package/dist/ContextSwitcher.js.map +1 -1
  45. package/dist/Copy.js +1 -1
  46. package/dist/CurrencyInput.js +2 -2
  47. package/dist/DataView.js +1 -1
  48. package/dist/DataViewFilters.js +7 -7
  49. package/dist/DataViewFilters.js.map +1 -1
  50. package/dist/DataViewSortButton.js +47 -38
  51. package/dist/DataViewSortButton.js.map +1 -1
  52. package/dist/DataViewToolbar.js +4 -4
  53. package/dist/DataViewToolbar.js.map +1 -1
  54. package/dist/DatePicker.js +12 -15
  55. package/dist/DatePicker.js.map +1 -1
  56. package/dist/DescriptionListTerm.js +8 -8
  57. package/dist/DescriptionListTerm.js.map +1 -1
  58. package/dist/Dialog.js +46 -46
  59. package/dist/Dialog.js.map +1 -1
  60. package/dist/Divider.js +9 -9
  61. package/dist/Divider.js.map +1 -1
  62. package/dist/Dropdown.js +17 -17
  63. package/dist/Dropdown.js.map +1 -1
  64. package/dist/EmptyState.js +1 -1
  65. package/dist/EmptyState.js.map +1 -1
  66. package/dist/Expand.js +1 -1
  67. package/dist/{Expand.vue_vue_type_script_setup_true_lang-5fe03d51.js → Expand.vue_vue_type_script_setup_true_lang-1751f4a6.js} +14 -15
  68. package/dist/Expand.vue_vue_type_script_setup_true_lang-1751f4a6.js.map +1 -0
  69. package/dist/Field.js +2 -2
  70. package/dist/Field.vue.d.ts +1 -1
  71. package/dist/{Field.vue_vue_type_script_setup_true_lang-475832fe.js → Field.vue_vue_type_script_setup_true_lang-42ba3c5a.js} +5 -5
  72. package/dist/Field.vue_vue_type_script_setup_true_lang-42ba3c5a.js.map +1 -0
  73. package/dist/FileUpload.js +49 -47
  74. package/dist/FileUpload.js.map +1 -1
  75. package/dist/FilterChip.js +20 -20
  76. package/dist/FilterChip.js.map +1 -1
  77. package/dist/FilterDrawerItem.js +4 -4
  78. package/dist/FilterDrawerItem.js.map +1 -1
  79. package/dist/FilterDropdown.js +19 -19
  80. package/dist/FilterDropdown.js.map +1 -1
  81. package/dist/FilterSelect.js +27 -27
  82. package/dist/FilterSelect.js.map +1 -1
  83. package/dist/Filters.js +51 -50
  84. package/dist/Filters.js.map +1 -1
  85. package/dist/HttpError.js +28 -28
  86. package/dist/HttpError.js.map +1 -1
  87. package/dist/IconLabel.js +17 -17
  88. package/dist/IconLabel.js.map +1 -1
  89. package/dist/IconLabel.vue.d.ts +1 -1
  90. package/dist/Illustration.js +10 -60
  91. package/dist/Illustration.js.map +1 -1
  92. package/dist/Illustration.vue_vue_type_script_setup_true_lang-d6a94e17.js +56 -0
  93. package/dist/Illustration.vue_vue_type_script_setup_true_lang-d6a94e17.js.map +1 -0
  94. package/dist/Image.js +67 -72
  95. package/dist/Image.js.map +1 -1
  96. package/dist/InlineEdit.js +3 -3
  97. package/dist/InlineEdit.js.map +1 -1
  98. package/dist/Input.js +43 -43
  99. package/dist/Input.js.map +1 -1
  100. package/dist/InputOptions.js +34 -33
  101. package/dist/InputOptions.js.map +1 -1
  102. package/dist/Label.js +1 -1
  103. package/dist/Label.vue.d.ts +13 -2
  104. package/dist/Label.vue_vue_type_script_setup_true_lang-4b02087f.js +38 -0
  105. package/dist/Label.vue_vue_type_script_setup_true_lang-4b02087f.js.map +1 -0
  106. package/dist/ListItem.js +16 -15
  107. package/dist/ListItem.js.map +1 -1
  108. package/dist/ListItemCell.js +9 -9
  109. package/dist/ListItemCell.js.map +1 -1
  110. package/dist/ListView.js +144 -140
  111. package/dist/ListView.js.map +1 -1
  112. package/dist/Loading.js +17 -10
  113. package/dist/Loading.js.map +1 -1
  114. package/dist/Loading.vue_used_vue_type_style_index_0_lang.module-ef5a3bc6.js +8 -0
  115. package/dist/Loading.vue_used_vue_type_style_index_0_lang.module-ef5a3bc6.js.map +1 -0
  116. package/dist/Menu.js +1 -1
  117. package/dist/Menu.js.map +1 -1
  118. package/dist/MenuItem.js +20 -14
  119. package/dist/MenuItem.js.map +1 -1
  120. package/dist/Metric.js +4 -4
  121. package/dist/Metric.js.map +1 -1
  122. package/dist/Modal.js +21 -21
  123. package/dist/Modal.js.map +1 -1
  124. package/dist/Modals.js +13 -13
  125. package/dist/Modals.js.map +1 -1
  126. package/dist/Module.js +2 -2
  127. package/dist/Module.js.map +1 -1
  128. package/dist/ModuleContent.js +2 -2
  129. package/dist/ModuleContent.js.map +1 -1
  130. package/dist/ModuleFooter.js +11 -11
  131. package/dist/ModuleFooter.js.map +1 -1
  132. package/dist/ModuleHeader.js +6 -6
  133. package/dist/ModuleHeader.js.map +1 -1
  134. package/dist/ObfuscateText.js +30 -32
  135. package/dist/ObfuscateText.js.map +1 -1
  136. package/dist/ObfuscateText.vue.d.ts +1 -1
  137. package/dist/PageContent.js +9 -9
  138. package/dist/PageContent.js.map +1 -1
  139. package/dist/PageHeader.js +24 -24
  140. package/dist/PageHeader.js.map +1 -1
  141. package/dist/PageNavigation.js +3 -3
  142. package/dist/PageNavigation.js.map +1 -1
  143. package/dist/Paginate.js +1 -1
  144. package/dist/Paginate.js.map +1 -1
  145. package/dist/Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js +11 -0
  146. package/dist/Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js.map +1 -0
  147. package/dist/QuickAction.js +20 -17
  148. package/dist/QuickAction.js.map +1 -1
  149. package/dist/Radio.js +30 -15
  150. package/dist/Radio.js.map +1 -1
  151. package/dist/RadioGroup.js +177 -148
  152. package/dist/RadioGroup.js.map +1 -1
  153. package/dist/RadioNew.js +118 -91
  154. package/dist/RadioNew.js.map +1 -1
  155. package/dist/SearchBar.js +27 -27
  156. package/dist/SearchBar.js.map +1 -1
  157. package/dist/Select.js +189 -188
  158. package/dist/Select.js.map +1 -1
  159. package/dist/SelectStatus.js +22 -21
  160. package/dist/SelectStatus.js.map +1 -1
  161. package/dist/Step.js +37 -37
  162. package/dist/Step.js.map +1 -1
  163. package/dist/Switch.js +44 -36
  164. package/dist/Switch.js.map +1 -1
  165. package/dist/Tab.js +3 -2
  166. package/dist/Tab.js.map +1 -1
  167. package/dist/{Tab.vue_vue_type_script_setup_true_lang-b810bee8.js → Tab.vue_vue_type_script_setup_true_lang-69d1b046.js} +23 -22
  168. package/dist/Tab.vue_vue_type_script_setup_true_lang-69d1b046.js.map +1 -0
  169. package/dist/Table.js +23 -22
  170. package/dist/Table.js.map +1 -1
  171. package/dist/Table.keys-cf93df19.js +27 -0
  172. package/dist/{Table.keys-1ebe4ecb.js.map → Table.keys-cf93df19.js.map} +1 -1
  173. package/dist/TableCell.js +24 -23
  174. package/dist/TableCell.js.map +1 -1
  175. package/dist/TableHeaderCell.js +37 -36
  176. package/dist/TableHeaderCell.js.map +1 -1
  177. package/dist/TableHeaderRow.js +13 -12
  178. package/dist/TableHeaderRow.js.map +1 -1
  179. package/dist/TableRow.js +36 -34
  180. package/dist/TableRow.js.map +1 -1
  181. package/dist/Tabs.js +2 -2
  182. package/dist/{Tabs.vue_used_vue_type_style_index_0_lang.module-4f247ed7.js → Tabs.vue_used_vue_type_style_index_0_lang.module-2a131332.js} +26 -26
  183. package/dist/Tabs.vue_used_vue_type_style_index_0_lang.module-2a131332.js.map +1 -0
  184. package/dist/Textarea.js +61 -53
  185. package/dist/Textarea.js.map +1 -1
  186. package/dist/Toast.js +23 -23
  187. package/dist/Toast.js.map +1 -1
  188. package/dist/components.css +1 -1
  189. package/dist/constants.d.ts +33 -26
  190. package/dist/constants.js +56 -41
  191. package/dist/constants.js.map +1 -1
  192. package/dist/index.js +21 -20
  193. package/dist/index.js.map +1 -1
  194. package/dist/storage.js +3 -2
  195. package/dist/storage.js.map +1 -1
  196. package/dist/tailwind-base.d.ts +16 -16
  197. package/dist/tailwind-base.js +16 -6
  198. package/dist/tailwind-base.js.map +1 -1
  199. package/dist/useGoogleMaps.js.map +1 -1
  200. package/dist/utils/helpers.js +37 -37
  201. package/dist/utils/helpers.js.map +1 -1
  202. package/dist/utils/storage.js +30 -29
  203. package/dist/utils/storage.js.map +1 -1
  204. package/package.json +2 -2
  205. package/styles/_core.scss +1 -1
  206. package/styles/backwards-compat.css +61 -105
  207. package/styles/base.css +271 -113
  208. package/tailwind-base.ts +6 -1
  209. package/dist/Button.vue_used_vue_type_style_index_0_lang.module-b77978d6.js +0 -17
  210. package/dist/Button.vue_used_vue_type_style_index_0_lang.module-b77978d6.js.map +0 -1
  211. package/dist/Checkbox.vue_vue_type_style_index_0_scoped_0d7e7fd0_lang-4ed993c7.js +0 -2
  212. package/dist/Checkbox.vue_vue_type_style_index_0_scoped_0d7e7fd0_lang-4ed993c7.js.map +0 -1
  213. package/dist/Expand.vue_vue_type_script_setup_true_lang-5fe03d51.js.map +0 -1
  214. package/dist/Field.vue_vue_type_script_setup_true_lang-475832fe.js.map +0 -1
  215. package/dist/Label.vue_vue_type_script_setup_true_lang-1d29d98a.js +0 -37
  216. package/dist/Label.vue_vue_type_script_setup_true_lang-1d29d98a.js.map +0 -1
  217. package/dist/Loading.vue_vue_type_style_index_0_scoped_bb8d5f15_lang-4ed993c7.js +0 -2
  218. package/dist/Loading.vue_vue_type_style_index_0_scoped_bb8d5f15_lang-4ed993c7.js.map +0 -1
  219. package/dist/Paginate.vue_used_vue_type_style_index_0_lang.module-bfccf992.js +0 -11
  220. package/dist/Paginate.vue_used_vue_type_style_index_0_lang.module-bfccf992.js.map +0 -1
  221. package/dist/Tab.vue_vue_type_script_setup_true_lang-b810bee8.js.map +0 -1
  222. package/dist/Table.keys-1ebe4ecb.js +0 -27
  223. package/dist/Tabs.vue_used_vue_type_style_index_0_lang.module-4f247ed7.js.map +0 -1
  224. package/styles/_base.scss +0 -493
  225. package/styles/elements/_links.scss +0 -32
  226. package/styles/elements/_lists.scss +0 -31
  227. package/styles/elements/_misc.scss +0 -16
  228. package/styles/main.scss +0 -38
@@ -1,6 +1,6 @@
1
1
  import { defineComponent as k, useCssModule as C, ref as m, watch as y, openBlock as c, createElementBlock as i, createElementVNode as E, Fragment as I, renderList as N, withDirectives as T, normalizeClass as p, unref as f, vModelText as D, toDisplayString as v, createCommentVNode as _ } from "vue";
2
2
  import { _ as S } from "./_plugin-vue_export-helper-dad06003.js";
3
- const B = { class: "tw-flex tw-gap-6 tw-mb-3" }, M = ["onUpdate:modelValue", "onPaste", "onKeyup", "onClick"], K = /* @__PURE__ */ k({
3
+ const z = { class: "tw-mb-3 tw-flex tw-gap-6" }, q = ["onUpdate:modelValue", "onPaste", "onKeyup", "onClick"], B = /* @__PURE__ */ k({
4
4
  __name: "ConfirmationCodeInput",
5
5
  props: {
6
6
  digitCount: { default: 6 },
@@ -10,10 +10,10 @@ const B = { class: "tw-flex tw-gap-6 tw-mb-3" }, M = ["onUpdate:modelValue", "on
10
10
  emits: ["update:model-value"],
11
11
  setup(x, { emit: d }) {
12
12
  const a = x, l = C(), s = m([]), n = m();
13
- function w(e) {
13
+ function g(e) {
14
14
  e.data && e.target.nextElementSibling ? e.target.nextElementSibling.focus() : e.data == null && e.target.previousElementSibling && e.target.previousElementSibling.focus();
15
15
  }
16
- function g(e, o) {
16
+ function h(e, o) {
17
17
  if (e.preventDefault(), s.value[o]) {
18
18
  n.value[o].focus();
19
19
  return;
@@ -23,7 +23,7 @@ const B = { class: "tw-flex tw-gap-6 tw-mb-3" }, M = ["onUpdate:modelValue", "on
23
23
  u && (t = r + 1);
24
24
  }), n.value[t].focus();
25
25
  }
26
- function h(e, o) {
26
+ function w(e, o) {
27
27
  if (e.key !== "Backspace" && !new RegExp("^([0-9])$").test(e.key)) {
28
28
  e.preventDefault();
29
29
  return;
@@ -74,9 +74,9 @@ const B = { class: "tw-flex tw-gap-6 tw-mb-3" }, M = ["onUpdate:modelValue", "on
74
74
  ref: "otpCont",
75
75
  class: "stash-confirmation-code-input tw-inline-block",
76
76
  "data-test": "stash-confirmation-code-input",
77
- onInput: w
77
+ onInput: g
78
78
  }, [
79
- E("div", B, [
79
+ E("div", z, [
80
80
  (c(!0), i(I, null, N(a.digitCount, (t, u) => T((c(), i("input", {
81
81
  key: t,
82
82
  ref_for: !0,
@@ -86,40 +86,40 @@ const B = { class: "tw-flex tw-gap-6 tw-mb-3" }, M = ["onUpdate:modelValue", "on
86
86
  "data-test": "stash-confirmation-code-input__otp",
87
87
  type: "text",
88
88
  maxlength: "1",
89
- class: p(["tw-p-2 tw-border focus:tw-border-blue-500 tw-text-center tw-text-ice-900 tw-font-medium tw-text-base", [
89
+ class: p(["tw-border tw-p-2 tw-text-center tw-text-base tw-font-medium tw-text-ice-900 focus:tw-border-blue-500", [
90
90
  f(l).otpCodeInput,
91
91
  { [f(l)["has-error"]]: !!a.errorText },
92
92
  { [f(l)["has-success"]]: !!a.successText }
93
93
  ]]),
94
94
  inputmode: "numeric",
95
95
  onPaste: (r) => t === 1 && b(r),
96
- onKeyup: (r) => h(r, u),
97
- onClick: (r) => g(r, u)
98
- }, null, 42, M)), [
96
+ onKeyup: (r) => w(r, u),
97
+ onClick: (r) => h(r, u)
98
+ }, null, 42, q)), [
99
99
  [D, s.value[t - 1]]
100
100
  ])), 128))
101
101
  ]),
102
102
  a.errorText ? (c(), i("small", {
103
103
  key: 0,
104
- class: p(["tw-block tw-text-red-500 tw-text-center", f(l).error]),
104
+ class: p(["tw-block tw-text-center tw-text-red-500", f(l).error]),
105
105
  "data-test": "field-error"
106
106
  }, v(a.errorText), 3)) : _("", !0),
107
107
  a.successText ? (c(), i("small", {
108
108
  key: 1,
109
- class: p(["tw-block tw-text-green-500 tw-text-center", f(l).error]),
109
+ class: p(["tw-block tw-text-center tw-text-green-500", f(l).error]),
110
110
  "data-test": "field-error"
111
111
  }, v(a.successText), 3)) : _("", !0)
112
112
  ], 544));
113
113
  }
114
- }), P = "_otpCodeInput_1wm2s_2", U = "_error_1wm2s_21", $ = {
115
- otpCodeInput: P,
116
- "has-error": "_has-error_1wm2s_9",
117
- "has-success": "_has-success_1wm2s_13",
118
- error: U
119
- }, j = {
120
- $style: $
121
- }, V = /* @__PURE__ */ S(K, [["__cssModules", j]]);
114
+ }), M = "_otpCodeInput_1qtz8_2", K = "_error_1qtz8_21", P = {
115
+ otpCodeInput: M,
116
+ "has-error": "_has-error_1qtz8_9",
117
+ "has-success": "_has-success_1qtz8_13",
118
+ error: K
119
+ }, U = {
120
+ $style: P
121
+ }, F = /* @__PURE__ */ S(B, [["__cssModules", U]]);
122
122
  export {
123
- V as default
123
+ F as default
124
124
  };
125
125
  //# sourceMappingURL=ConfirmationCodeInput.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConfirmationCodeInput.js","sources":["../src/components/ConfirmationCodeInput/ConfirmationCodeInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { Ref, ref, useCssModule, watch } from 'vue';\n\n const classes = useCssModule();\n\n export interface VerificationCodeInputProps {\n digitCount?: number;\n /**\n * Error text to display.\n */\n errorText?: string;\n /**\n * Success text to display.\n */\n successText?: string;\n }\n\n const props = withDefaults(defineProps<VerificationCodeInputProps>(), {\n digitCount: 6,\n errorText: undefined,\n successText: undefined,\n });\n\n const emit =\n defineEmits<{\n (e: 'update:model-value', value: number | null): void;\n }>();\n\n const data: Ref<Array<string>> = ref([]);\n const inputEl = ref();\n\n function handleOtpInput(e) {\n if (e.data && e.target.nextElementSibling) {\n e.target.nextElementSibling.focus();\n } else if (e.data == null && e.target.previousElementSibling) {\n e.target.previousElementSibling.focus();\n }\n }\n\n function handleFocus(event, elementIndex: number) {\n event.preventDefault();\n\n if (data.value[elementIndex]) {\n inputEl.value[elementIndex].focus();\n\n return;\n }\n\n let focusedIndex = 0;\n\n data.value.forEach((value, index) => {\n if (value) {\n focusedIndex = index + 1;\n }\n });\n\n inputEl.value[focusedIndex].focus();\n }\n\n function handleKeyUp(e: KeyboardEvent, index: number) {\n if (e.key !== 'Backspace' && !new RegExp('^([0-9])$').test(e.key)) {\n e.preventDefault();\n return;\n }\n\n let focusedIndex = 0;\n\n if (index !== 0) {\n focusedIndex = index - 1;\n } else {\n focusedIndex = 0;\n }\n\n if (e.key === 'Backspace') {\n if (index + 1 === data.value.length - 1 && data.value[index]) {\n inputEl.value[index + 1].focus();\n return;\n }\n\n if (data.value[index]) {\n return;\n }\n\n data.value[focusedIndex] = '';\n inputEl.value[focusedIndex].focus();\n\n return;\n }\n\n if (!new RegExp('^([0-9])$').test(e.key) && !data.value[index]) {\n data.value[focusedIndex] = '';\n inputEl.value[focusedIndex].focus();\n return;\n }\n }\n\n function handlePaste(e: ClipboardEvent) {\n const pasteData = e.clipboardData?.getData('text');\n\n if (isNaN(Number(pasteData))) {\n inputEl.value[0].focus();\n return;\n }\n\n let nextEl = inputEl.value[0].nextElementSibling;\n if (pasteData) {\n for (let i = 1; i < pasteData.length; i++) {\n if (nextEl) {\n data.value[i] = pasteData[i];\n nextEl = nextEl.nextElementSibling;\n }\n }\n }\n }\n\n watch(\n () => data,\n (newVal) => {\n if (newVal.value.join('') === '') {\n emit('update:model-value', null);\n } else {\n if (isNaN(Number(newVal.value[0]))) {\n data.value[0] = '';\n return;\n }\n emit('update:model-value', Number(newVal.value.join('')));\n }\n },\n { deep: true },\n );\n</script>\n\n<template>\n <form\n ref=\"otpCont\"\n class=\"stash-confirmation-code-input tw-inline-block\"\n data-test=\"stash-confirmation-code-input\"\n @input=\"handleOtpInput\"\n >\n <div class=\"tw-flex tw-gap-6 tw-mb-3\">\n <template v-for=\"(field, index) in props.digitCount\" :key=\"field\">\n <input\n ref=\"inputEl\"\n v-model=\"data[field - 1]\"\n data-test=\"stash-confirmation-code-input__otp\"\n type=\"text\"\n maxlength=\"1\"\n class=\"tw-p-2 tw-border focus:tw-border-blue-500 tw-text-center tw-text-ice-900 tw-font-medium tw-text-base\"\n :class=\"[\n classes.otpCodeInput,\n { [classes['has-error']]: !!props.errorText },\n { [classes['has-success']]: !!props.successText },\n ]\"\n inputmode=\"numeric\"\n @paste=\"field === 1 && handlePaste($event)\"\n @keyup=\"handleKeyUp($event, index)\"\n @click=\"(evt) => handleFocus(evt, index)\"\n />\n </template>\n </div>\n <small\n v-if=\"props.errorText\"\n class=\"tw-block tw-text-red-500 tw-text-center\"\n :class=\"classes.error\"\n data-test=\"field-error\"\n >\n {{ props.errorText }}\n </small>\n <small\n v-if=\"props.successText\"\n class=\"tw-block tw-text-green-500 tw-text-center\"\n :class=\"classes.error\"\n data-test=\"field-error\"\n >\n {{ props.successText }}\n </small>\n </form>\n</template>\n\n<style module>\n .otpCodeInput {\n border-radius: 4px;\n caret-color: transparent;\n height: 36px;\n width: 36px;\n }\n\n .otpCodeInput.has-error:not(:focus) {\n border-color: theme('colors.red.500');\n }\n\n .otpCodeInput.has-success:not(:focus) {\n border-color: theme('colors.green.500');\n }\n\n .otpCodeInput:focus {\n outline: none;\n }\n\n .error {\n margin-top: 4px;\n white-space: pre-line;\n }\n</style>\n"],"names":["classes","useCssModule","data","ref","inputEl","handleOtpInput","handleFocus","event","elementIndex","focusedIndex","value","index","handleKeyUp","handlePaste","pasteData","_a","nextEl","i","watch","newVal","emit"],"mappings":";;;;;;;;;;;iBAGQA,IAAUC,KAyBVC,IAA2BC,EAAI,CAAA,CAAE,GACjCC,IAAUD;AAEhB,aAASE,EAAe,GAAG;AACzB,MAAI,EAAE,QAAQ,EAAE,OAAO,qBACnB,EAAA,OAAO,mBAAmB,UACnB,EAAE,QAAQ,QAAQ,EAAE,OAAO,0BAClC,EAAA,OAAO,uBAAuB;IAEpC;AAES,aAAAC,EAAYC,GAAOC,GAAsB;AAG5C,UAFJD,EAAM,eAAe,GAEjBL,EAAK,MAAMM,CAAY,GAAG;AACpB,QAAAJ,EAAA,MAAMI,CAAY,EAAE,MAAM;AAElC;AAAA,MACF;AAEA,UAAIC,IAAe;AAEnB,MAAAP,EAAK,MAAM,QAAQ,CAACQ,GAAOC,MAAU;AACnC,QAAID,MACFD,IAAeE,IAAQ;AAAA,MACzB,CACD,GAEOP,EAAA,MAAMK,CAAY,EAAE,MAAM;AAAA,IACpC;AAES,aAAAG,EAAY,GAAkBD,GAAe;AAChD,UAAA,EAAE,QAAQ,eAAe,CAAC,IAAI,OAAO,WAAW,EAAE,KAAK,EAAE,GAAG,GAAG;AACjE,UAAE,eAAe;AACjB;AAAA,MACF;AAEA,UAAIF,IAAe;AAQf,UANAE,MAAU,IACZF,IAAeE,IAAQ,IAERF,IAAA,GAGb,EAAE,QAAQ,aAAa;AACrB,YAAAE,IAAQ,MAAMT,EAAK,MAAM,SAAS,KAAKA,EAAK,MAAMS,CAAK,GAAG;AAC5D,UAAAP,EAAQ,MAAMO,IAAQ,CAAC,EAAE,MAAM;AAC/B;AAAA,QACF;AAEI,YAAAT,EAAK,MAAMS,CAAK;AAClB;AAGG,QAAAT,EAAA,MAAMO,CAAY,IAAI,IACnBL,EAAA,MAAMK,CAAY,EAAE,MAAM;AAElC;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,OAAO,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,CAACP,EAAK,MAAMS,CAAK,GAAG;AACzD,QAAAT,EAAA,MAAMO,CAAY,IAAI,IACnBL,EAAA,MAAMK,CAAY,EAAE,MAAM;AAClC;AAAA,MACF;AAAA,IACF;AAEA,aAASI,EAAY,GAAmB;;AACtC,YAAMC,KAAYC,IAAA,EAAE,kBAAF,gBAAAA,EAAiB,QAAQ;AAE3C,UAAI,MAAM,OAAOD,CAAS,CAAC,GAAG;AACpB,QAAAV,EAAA,MAAM,CAAC,EAAE,MAAM;AACvB;AAAA,MACF;AAEA,UAAIY,IAASZ,EAAQ,MAAM,CAAC,EAAE;AAC9B,UAAIU;AACF,iBAASG,IAAI,GAAGA,IAAIH,EAAU,QAAQG;AACpC,UAAID,MACFd,EAAK,MAAMe,CAAC,IAAIH,EAAUG,CAAC,GAC3BD,IAASA,EAAO;AAAA,IAIxB;AAEA,WAAAE;AAAA,MACE,MAAMhB;AAAA,MACN,CAACiB,MAAW;AACV,YAAIA,EAAO,MAAM,KAAK,EAAE,MAAM;AAC5B,UAAAC,EAAK,sBAAsB,IAAI;AAAA,aAC1B;AACL,cAAI,MAAM,OAAOD,EAAO,MAAM,CAAC,CAAC,CAAC,GAAG;AAC7B,YAAAjB,EAAA,MAAM,CAAC,IAAI;AAChB;AAAA,UACF;AACA,UAAAkB,EAAK,sBAAsB,OAAOD,EAAO,MAAM,KAAK,EAAE,CAAC,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,MACA,EAAE,MAAM,GAAK;AAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ConfirmationCodeInput.js","sources":["../src/components/ConfirmationCodeInput/ConfirmationCodeInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { Ref, ref, useCssModule, watch } from 'vue';\n\n const classes = useCssModule();\n\n export interface VerificationCodeInputProps {\n digitCount?: number;\n /**\n * Error text to display.\n */\n errorText?: string;\n /**\n * Success text to display.\n */\n successText?: string;\n }\n\n const props = withDefaults(defineProps<VerificationCodeInputProps>(), {\n digitCount: 6,\n errorText: undefined,\n successText: undefined,\n });\n\n const emit =\n defineEmits<{\n (e: 'update:model-value', value: number | null): void;\n }>();\n\n const data: Ref<Array<string>> = ref([]);\n const inputEl = ref();\n\n function handleOtpInput(e) {\n if (e.data && e.target.nextElementSibling) {\n e.target.nextElementSibling.focus();\n } else if (e.data == null && e.target.previousElementSibling) {\n e.target.previousElementSibling.focus();\n }\n }\n\n function handleFocus(event, elementIndex: number) {\n event.preventDefault();\n\n if (data.value[elementIndex]) {\n inputEl.value[elementIndex].focus();\n\n return;\n }\n\n let focusedIndex = 0;\n\n data.value.forEach((value, index) => {\n if (value) {\n focusedIndex = index + 1;\n }\n });\n\n inputEl.value[focusedIndex].focus();\n }\n\n function handleKeyUp(e: KeyboardEvent, index: number) {\n if (e.key !== 'Backspace' && !new RegExp('^([0-9])$').test(e.key)) {\n e.preventDefault();\n return;\n }\n\n let focusedIndex = 0;\n\n if (index !== 0) {\n focusedIndex = index - 1;\n } else {\n focusedIndex = 0;\n }\n\n if (e.key === 'Backspace') {\n if (index + 1 === data.value.length - 1 && data.value[index]) {\n inputEl.value[index + 1].focus();\n return;\n }\n\n if (data.value[index]) {\n return;\n }\n\n data.value[focusedIndex] = '';\n inputEl.value[focusedIndex].focus();\n\n return;\n }\n\n if (!new RegExp('^([0-9])$').test(e.key) && !data.value[index]) {\n data.value[focusedIndex] = '';\n inputEl.value[focusedIndex].focus();\n return;\n }\n }\n\n function handlePaste(e: ClipboardEvent) {\n const pasteData = e.clipboardData?.getData('text');\n\n if (isNaN(Number(pasteData))) {\n inputEl.value[0].focus();\n return;\n }\n\n let nextEl = inputEl.value[0].nextElementSibling;\n if (pasteData) {\n for (let i = 1; i < pasteData.length; i++) {\n if (nextEl) {\n data.value[i] = pasteData[i];\n nextEl = nextEl.nextElementSibling;\n }\n }\n }\n }\n\n watch(\n () => data,\n (newVal) => {\n if (newVal.value.join('') === '') {\n emit('update:model-value', null);\n } else {\n if (isNaN(Number(newVal.value[0]))) {\n data.value[0] = '';\n return;\n }\n emit('update:model-value', Number(newVal.value.join('')));\n }\n },\n { deep: true },\n );\n</script>\n\n<template>\n <form\n ref=\"otpCont\"\n class=\"stash-confirmation-code-input tw-inline-block\"\n data-test=\"stash-confirmation-code-input\"\n @input=\"handleOtpInput\"\n >\n <div class=\"tw-mb-3 tw-flex tw-gap-6\">\n <template v-for=\"(field, index) in props.digitCount\" :key=\"field\">\n <input\n ref=\"inputEl\"\n v-model=\"data[field - 1]\"\n data-test=\"stash-confirmation-code-input__otp\"\n type=\"text\"\n maxlength=\"1\"\n class=\"tw-border tw-p-2 tw-text-center tw-text-base tw-font-medium tw-text-ice-900 focus:tw-border-blue-500\"\n :class=\"[\n classes.otpCodeInput,\n { [classes['has-error']]: !!props.errorText },\n { [classes['has-success']]: !!props.successText },\n ]\"\n inputmode=\"numeric\"\n @paste=\"field === 1 && handlePaste($event)\"\n @keyup=\"handleKeyUp($event, index)\"\n @click=\"(evt) => handleFocus(evt, index)\"\n />\n </template>\n </div>\n <small\n v-if=\"props.errorText\"\n class=\"tw-block tw-text-center tw-text-red-500\"\n :class=\"classes.error\"\n data-test=\"field-error\"\n >\n {{ props.errorText }}\n </small>\n <small\n v-if=\"props.successText\"\n class=\"tw-block tw-text-center tw-text-green-500\"\n :class=\"classes.error\"\n data-test=\"field-error\"\n >\n {{ props.successText }}\n </small>\n </form>\n</template>\n\n<style module>\n .otpCodeInput {\n border-radius: 4px;\n caret-color: transparent;\n height: 36px;\n width: 36px;\n }\n\n .otpCodeInput.has-error:not(:focus) {\n border-color: var(--color-red-500);\n }\n\n .otpCodeInput.has-success:not(:focus) {\n border-color: var(--color-green-500);\n }\n\n .otpCodeInput:focus {\n outline: none;\n }\n\n .error {\n margin-top: 4px;\n white-space: pre-line;\n }\n</style>\n"],"names":["classes","useCssModule","data","ref","inputEl","handleOtpInput","handleFocus","event","elementIndex","focusedIndex","value","index","handleKeyUp","handlePaste","pasteData","_a","nextEl","i","watch","newVal","emit"],"mappings":";;;;;;;;;;;iBAGQA,IAAUC,KAyBVC,IAA2BC,EAAI,CAAA,CAAE,GACjCC,IAAUD;AAEhB,aAASE,EAAe,GAAG;AACzB,MAAI,EAAE,QAAQ,EAAE,OAAO,qBACnB,EAAA,OAAO,mBAAmB,UACnB,EAAE,QAAQ,QAAQ,EAAE,OAAO,0BAClC,EAAA,OAAO,uBAAuB;IAEpC;AAES,aAAAC,EAAYC,GAAOC,GAAsB;AAG5C,UAFJD,EAAM,eAAe,GAEjBL,EAAK,MAAMM,CAAY,GAAG;AACpB,QAAAJ,EAAA,MAAMI,CAAY,EAAE,MAAM;AAElC;AAAA,MACF;AAEA,UAAIC,IAAe;AAEnB,MAAAP,EAAK,MAAM,QAAQ,CAACQ,GAAOC,MAAU;AACnC,QAAID,MACFD,IAAeE,IAAQ;AAAA,MACzB,CACD,GAEOP,EAAA,MAAMK,CAAY,EAAE,MAAM;AAAA,IACpC;AAES,aAAAG,EAAY,GAAkBD,GAAe;AAChD,UAAA,EAAE,QAAQ,eAAe,CAAC,IAAI,OAAO,WAAW,EAAE,KAAK,EAAE,GAAG,GAAG;AACjE,UAAE,eAAe;AACjB;AAAA,MACF;AAEA,UAAIF,IAAe;AAQf,UANAE,MAAU,IACZF,IAAeE,IAAQ,IAERF,IAAA,GAGb,EAAE,QAAQ,aAAa;AACrB,YAAAE,IAAQ,MAAMT,EAAK,MAAM,SAAS,KAAKA,EAAK,MAAMS,CAAK,GAAG;AAC5D,UAAAP,EAAQ,MAAMO,IAAQ,CAAC,EAAE,MAAM;AAC/B;AAAA,QACF;AAEI,YAAAT,EAAK,MAAMS,CAAK;AAClB;AAGG,QAAAT,EAAA,MAAMO,CAAY,IAAI,IACnBL,EAAA,MAAMK,CAAY,EAAE,MAAM;AAElC;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,OAAO,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,CAACP,EAAK,MAAMS,CAAK,GAAG;AACzD,QAAAT,EAAA,MAAMO,CAAY,IAAI,IACnBL,EAAA,MAAMK,CAAY,EAAE,MAAM;AAClC;AAAA,MACF;AAAA,IACF;AAEA,aAASI,EAAY,GAAmB;;AACtC,YAAMC,KAAYC,IAAA,EAAE,kBAAF,gBAAAA,EAAiB,QAAQ;AAE3C,UAAI,MAAM,OAAOD,CAAS,CAAC,GAAG;AACpB,QAAAV,EAAA,MAAM,CAAC,EAAE,MAAM;AACvB;AAAA,MACF;AAEA,UAAIY,IAASZ,EAAQ,MAAM,CAAC,EAAE;AAC9B,UAAIU;AACF,iBAASG,IAAI,GAAGA,IAAIH,EAAU,QAAQG;AACpC,UAAID,MACFd,EAAK,MAAMe,CAAC,IAAIH,EAAUG,CAAC,GAC3BD,IAASA,EAAO;AAAA,IAIxB;AAEA,WAAAE;AAAA,MACE,MAAMhB;AAAA,MACN,CAACiB,MAAW;AACV,YAAIA,EAAO,MAAM,KAAK,EAAE,MAAM;AAC5B,UAAAC,EAAK,sBAAsB,IAAI;AAAA,aAC1B;AACL,cAAI,MAAM,OAAOD,EAAO,MAAM,CAAC,CAAC,CAAC,GAAG;AAC7B,YAAAjB,EAAA,MAAM,CAAC,IAAI;AAChB;AAAA,UACF;AACA,UAAAkB,EAAK,sBAAsB,OAAOD,EAAO,MAAM,KAAK,EAAE,CAAC,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,MACA,EAAE,MAAM,GAAK;AAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,15 +1,16 @@
1
1
  import { defineComponent as k, computed as _, resolveComponent as C, openBlock as s, createElementBlock as l, Fragment as u, renderList as g, normalizeClass as d, toDisplayString as f, createBlock as x, withCtx as E, createTextVNode as S } from "vue";
2
2
  import { APPS as a } from "./constants.js";
3
3
  import { setPersistentItem as b, getPersistentItem as T, removePersistentItem as v } from "./utils/storage.js";
4
+ import "@leaflink/snitch";
4
5
  import "./utils/helpers.js";
5
6
  import "lodash-es/camelCase";
6
7
  import "lodash-es/get";
7
8
  import "lodash-es/isFinite";
8
9
  import "lodash-es/isPlainObject";
9
10
  const R = {
10
- class: "stash-context-switcher tw-bg-purple-700 tw-flex tw-text-center tw-p-1.5 tw-mx-auto tw-w-64 tw-rounded-full tw-border tw-border-white/10",
11
+ class: "stash-context-switcher tw-mx-auto tw-flex tw-w-64 tw-rounded-full tw-border tw-border-white/10 tw-bg-purple-700 tw-p-1.5 tw-text-center",
11
12
  "data-test": "stash-context-switcher"
12
- }, N = ["href", "onClick"], h = "-last-session", K = /* @__PURE__ */ k({
13
+ }, N = ["href", "onClick"], h = "-last-session", O = /* @__PURE__ */ k({
13
14
  name: "ll-context-switcher",
14
15
  __name: "ContextSwitcher",
15
16
  props: {
@@ -56,12 +57,12 @@ const R = {
56
57
  }, [
57
58
  t.hasBaseRoute ? (s(), l("a", {
58
59
  key: 0,
59
- class: d(["!tw-capitalize !tw-no-underline tw-w-1/2 tw-leading-none tw-font-semibold tw-py-2.5 tw-rounded-full tw-cursor-pointer", e.activeApp === t.app ? "tw-text-white tw-bg-royal-500" : "tw-text-ice-500"]),
60
+ class: d(["tw-w-1/2 tw-cursor-pointer tw-rounded-full tw-py-2.5 tw-font-semibold !tw-capitalize tw-leading-none !tw-no-underline", e.activeApp === t.app ? "tw-text-white tw-bg-royal-500" : "tw-text-ice-500"]),
60
61
  href: `/${t.name}`,
61
62
  onClick: (c) => m(c, t.app)
62
63
  }, f(t.app), 11, N)) : (s(), x(r, {
63
64
  key: 1,
64
- class: d(["!tw-capitalize !tw-no-underline tw-w-1/2 tw-leading-none tw-font-semibold tw-py-2.5 tw-rounded-full tw-cursor-pointer", e.activeApp === t.app ? "tw-text-white tw-bg-royal-500" : "tw-text-ice-500"]),
65
+ class: d(["tw-w-1/2 tw-cursor-pointer tw-rounded-full tw-py-2.5 tw-font-semibold !tw-capitalize tw-leading-none !tw-no-underline", e.activeApp === t.app ? "tw-text-white tw-bg-royal-500" : "tw-text-ice-500"]),
65
66
  to: { name: t.name, query: o.routeQuery },
66
67
  "data-test-route": JSON.stringify({ name: t.name, query: o.routeQuery }),
67
68
  onClick: (c) => m(c, t.app)
@@ -77,6 +78,6 @@ const R = {
77
78
  }
78
79
  });
79
80
  export {
80
- K as default
81
+ O as default
81
82
  };
82
83
  //# sourceMappingURL=ContextSwitcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextSwitcher.js","sources":["../src/components/ContextSwitcher/ContextSwitcher.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue';\n import type { LocationQuery } from 'vue-router';\n\n import { APPS } from '../../constants';\n import { getPersistentItem, removePersistentItem, setPersistentItem } from '../../utils/storage';\n\n defineOptions({\n name: 'll-context-switcher',\n });\n\n type AppValues = typeof APPS[keyof typeof APPS];\n\n export interface ContextSwitcherProps {\n /**\n * The current app that is active. Choices are 'marketplace' | 'payments'.\n */\n activeApp: AppValues;\n\n /**\n * Portal access to both marketplace and payments.\n */\n portalAccess?: {\n commercePortal: boolean;\n paymentsPortal: boolean;\n };\n\n /**\n * Url to replace the other app if current user does not have portal access.\n */\n limitedAccessUrl: string;\n\n routeQuery?: LocationQuery;\n }\n\n const props = withDefaults(defineProps<ContextSwitcherProps>(), {\n portalAccess: () => ({\n commercePortal: false,\n paymentsPortal: false,\n }),\n routeQuery: () => ({}),\n });\n\n const emit =\n defineEmits<{\n /**\n * Fires on click of the context switcher.\n * @deprecated Use `switch` instead.\n */\n (e: 'click', urlInfo: { from: string; to: string }): void;\n /**\n * Fires on click of the context switcher.\n */\n (e: 'switch', evt: MouseEvent, urlInfo: { from: string; to: string }): void;\n }>();\n\n interface ContextItem {\n app: AppValues;\n name: string;\n hasBaseRoute: boolean;\n }\n\n const CONTEXT_SWITCHER_STORAGE_KEY = '-last-session';\n\n const routes = computed<ContextItem[]>(() => {\n return [\n {\n app: APPS.MARKETPLACE,\n name: props.portalAccess.commercePortal ? 'dashboard' : props.limitedAccessUrl,\n hasBaseRoute: props.portalAccess.commercePortal,\n },\n {\n app: APPS.PAYMENTS,\n name: props.portalAccess.paymentsPortal ? 'payments' : props.limitedAccessUrl,\n hasBaseRoute: false,\n },\n ];\n });\n\n /**\n * Saves the current url in local storage before leaving the current app, if user has access to both apps\n * If a previous session url exists, redirect users there instead then remove the local storage item afterward.\n *\n * @param event - Event from user click.\n * @param app - App name of the clicked link, is a key of `APPS`.\n */\n function handleClick(event: MouseEvent, app: AppValues) {\n if (app === props.activeApp) {\n return;\n }\n\n const currentLocation = window.location.href;\n let destination = (event.target as HTMLAnchorElement).href;\n\n if (props.portalAccess.paymentsPortal && props.portalAccess.commercePortal) {\n const appRoute = app === APPS.PAYMENTS ? APPS.MARKETPLACE : APPS.PAYMENTS;\n const currentSessionName = `${appRoute}${CONTEXT_SWITCHER_STORAGE_KEY}`;\n const prevSessionName = `${app}${CONTEXT_SWITCHER_STORAGE_KEY}`;\n\n // save the current url in local storage\n setPersistentItem(currentSessionName, currentLocation, { global: true });\n\n // get the other app's url from local storage\n const prevSessionUrl = getPersistentItem(prevSessionName, { global: true });\n\n // if it exists, redirect users to such location and remove the item from local storage\n if (prevSessionUrl) {\n event.preventDefault();\n destination = prevSessionUrl;\n window.location.href = prevSessionUrl;\n removePersistentItem(prevSessionName, { global: true });\n }\n }\n\n emit('click', { from: currentLocation, to: destination });\n emit('switch', event, { from: currentLocation, to: destination });\n }\n</script>\n\n<template>\n <div\n class=\"\n stash-context-switcher\n tw-bg-purple-700 tw-flex tw-text-center tw-p-1.5 tw-mx-auto tw-w-64 tw-rounded-full tw-border tw-border-white/10\n \"\n data-test=\"stash-context-switcher\"\n >\n <template v-for=\"route in routes\" :key=\"route.app\">\n <!-- render anchor tag to override base route in Payments -->\n <a\n v-if=\"route.hasBaseRoute\"\n class=\"\n !tw-capitalize !tw-no-underline\n tw-w-1/2 tw-leading-none tw-font-semibold tw-py-2.5 tw-rounded-full tw-cursor-pointer\n \"\n :class=\"props.activeApp === route.app ? 'tw-text-white tw-bg-royal-500' : 'tw-text-ice-500'\"\n :href=\"`/${route.name}`\"\n @click=\"(evt) => handleClick(evt, route.app)\"\n >\n {{ route.app }}\n </a>\n\n <router-link\n v-else\n class=\"\n !tw-capitalize !tw-no-underline\n tw-w-1/2 tw-leading-none tw-font-semibold tw-py-2.5 tw-rounded-full tw-cursor-pointer\n \"\n :class=\"props.activeApp === route.app ? 'tw-text-white tw-bg-royal-500' : 'tw-text-ice-500'\"\n :to=\"{ name: route.name, query: routeQuery }\"\n :data-test-route=\"JSON.stringify({ name: route.name, query: routeQuery })\"\n @click=\"(evt) => handleClick(evt, route.app)\"\n >\n {{ route.app }}\n </router-link>\n </template>\n </div>\n</template>\n"],"names":["CONTEXT_SWITCHER_STORAGE_KEY","routes","computed","APPS","props","handleClick","event","app","currentLocation","destination","currentSessionName","prevSessionName","setPersistentItem","prevSessionUrl","getPersistentItem","removePersistentItem","emit"],"mappings":";;;;;;;;;;;4BA8DQA,IAA+B;;;;;;;;;;;;;;iBAE/BC,IAASC,EAAwB,MAC9B;AAAA,MACL;AAAA,QACE,KAAKC,EAAK;AAAA,QACV,MAAMC,EAAM,aAAa,iBAAiB,cAAcA,EAAM;AAAA,QAC9D,cAAcA,EAAM,aAAa;AAAA,MACnC;AAAA,MACA;AAAA,QACE,KAAKD,EAAK;AAAA,QACV,MAAMC,EAAM,aAAa,iBAAiB,aAAaA,EAAM;AAAA,QAC7D,cAAc;AAAA,MAChB;AAAA,IAAA,CAEH;AASQ,aAAAC,EAAYC,GAAmBC,GAAgB;AAClD,UAAAA,MAAQH,EAAM;AAChB;AAGI,YAAAI,IAAkB,OAAO,SAAS;AACpC,UAAAC,IAAeH,EAAM,OAA6B;AAEtD,UAAIF,EAAM,aAAa,kBAAkBA,EAAM,aAAa,gBAAgB;AAE1E,cAAMM,IAAqB,GADVH,MAAQJ,EAAK,WAAWA,EAAK,cAAcA,EAAK,QAC3B,GAAGH,CAA4B,IAC/DW,IAAkB,GAAGJ,CAAG,GAAGP,CAA4B;AAG7D,QAAAY,EAAkBF,GAAoBF,GAAiB,EAAE,QAAQ,GAAM,CAAA;AAGvE,cAAMK,IAAiBC,EAAkBH,GAAiB,EAAE,QAAQ,IAAM;AAG1E,QAAIE,MACFP,EAAM,eAAe,GACPG,IAAAI,GACd,OAAO,SAAS,OAAOA,GACvBE,EAAqBJ,GAAiB,EAAE,QAAQ,GAAM,CAAA;AAAA,MAE1D;AAEA,MAAAK,EAAK,SAAS,EAAE,MAAMR,GAAiB,IAAIC,GAAa,GACxDO,EAAK,UAAUV,GAAO,EAAE,MAAME,GAAiB,IAAIC,GAAa;AAAA,IAClE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ContextSwitcher.js","sources":["../src/components/ContextSwitcher/ContextSwitcher.vue"],"sourcesContent":["<script setup lang=\"ts\">\n import { computed } from 'vue';\n import type { LocationQuery } from 'vue-router';\n\n import { APPS } from '../../constants';\n import { getPersistentItem, removePersistentItem, setPersistentItem } from '../../utils/storage';\n\n defineOptions({\n name: 'll-context-switcher',\n });\n\n type AppValues = typeof APPS[keyof typeof APPS];\n\n export interface ContextSwitcherProps {\n /**\n * The current app that is active. Choices are 'marketplace' | 'payments'.\n */\n activeApp: AppValues;\n\n /**\n * Portal access to both marketplace and payments.\n */\n portalAccess?: {\n commercePortal: boolean;\n paymentsPortal: boolean;\n };\n\n /**\n * Url to replace the other app if current user does not have portal access.\n */\n limitedAccessUrl: string;\n\n routeQuery?: LocationQuery;\n }\n\n const props = withDefaults(defineProps<ContextSwitcherProps>(), {\n portalAccess: () => ({\n commercePortal: false,\n paymentsPortal: false,\n }),\n routeQuery: () => ({}),\n });\n\n const emit =\n defineEmits<{\n /**\n * Fires on click of the context switcher.\n * @deprecated Use `switch` instead.\n */\n (e: 'click', urlInfo: { from: string; to: string }): void;\n /**\n * Fires on click of the context switcher.\n */\n (e: 'switch', evt: MouseEvent, urlInfo: { from: string; to: string }): void;\n }>();\n\n interface ContextItem {\n app: AppValues;\n name: string;\n hasBaseRoute: boolean;\n }\n\n const CONTEXT_SWITCHER_STORAGE_KEY = '-last-session';\n\n const routes = computed<ContextItem[]>(() => {\n return [\n {\n app: APPS.MARKETPLACE,\n name: props.portalAccess.commercePortal ? 'dashboard' : props.limitedAccessUrl,\n hasBaseRoute: props.portalAccess.commercePortal,\n },\n {\n app: APPS.PAYMENTS,\n name: props.portalAccess.paymentsPortal ? 'payments' : props.limitedAccessUrl,\n hasBaseRoute: false,\n },\n ];\n });\n\n /**\n * Saves the current url in local storage before leaving the current app, if user has access to both apps\n * If a previous session url exists, redirect users there instead then remove the local storage item afterward.\n *\n * @param event - Event from user click.\n * @param app - App name of the clicked link, is a key of `APPS`.\n */\n function handleClick(event: MouseEvent, app: AppValues) {\n if (app === props.activeApp) {\n return;\n }\n\n const currentLocation = window.location.href;\n let destination = (event.target as HTMLAnchorElement).href;\n\n if (props.portalAccess.paymentsPortal && props.portalAccess.commercePortal) {\n const appRoute = app === APPS.PAYMENTS ? APPS.MARKETPLACE : APPS.PAYMENTS;\n const currentSessionName = `${appRoute}${CONTEXT_SWITCHER_STORAGE_KEY}`;\n const prevSessionName = `${app}${CONTEXT_SWITCHER_STORAGE_KEY}`;\n\n // save the current url in local storage\n setPersistentItem(currentSessionName, currentLocation, { global: true });\n\n // get the other app's url from local storage\n const prevSessionUrl = getPersistentItem(prevSessionName, { global: true });\n\n // if it exists, redirect users to such location and remove the item from local storage\n if (prevSessionUrl) {\n event.preventDefault();\n destination = prevSessionUrl;\n window.location.href = prevSessionUrl;\n removePersistentItem(prevSessionName, { global: true });\n }\n }\n\n emit('click', { from: currentLocation, to: destination });\n emit('switch', event, { from: currentLocation, to: destination });\n }\n</script>\n\n<template>\n <div\n class=\"\n stash-context-switcher\n tw-mx-auto tw-flex tw-w-64 tw-rounded-full tw-border tw-border-white/10 tw-bg-purple-700 tw-p-1.5 tw-text-center\n \"\n data-test=\"stash-context-switcher\"\n >\n <template v-for=\"route in routes\" :key=\"route.app\">\n <!-- render anchor tag to override base route in Payments -->\n <a\n v-if=\"route.hasBaseRoute\"\n class=\"\n tw-w-1/2 tw-cursor-pointer tw-rounded-full tw-py-2.5 tw-font-semibold\n !tw-capitalize\n tw-leading-none\n !tw-no-underline\n \"\n :class=\"props.activeApp === route.app ? 'tw-text-white tw-bg-royal-500' : 'tw-text-ice-500'\"\n :href=\"`/${route.name}`\"\n @click=\"(evt) => handleClick(evt, route.app)\"\n >\n {{ route.app }}\n </a>\n\n <router-link\n v-else\n class=\"\n tw-w-1/2 tw-cursor-pointer tw-rounded-full tw-py-2.5 tw-font-semibold\n !tw-capitalize\n tw-leading-none\n !tw-no-underline\n \"\n :class=\"props.activeApp === route.app ? 'tw-text-white tw-bg-royal-500' : 'tw-text-ice-500'\"\n :to=\"{ name: route.name, query: routeQuery }\"\n :data-test-route=\"JSON.stringify({ name: route.name, query: routeQuery })\"\n @click=\"(evt) => handleClick(evt, route.app)\"\n >\n {{ route.app }}\n </router-link>\n </template>\n </div>\n</template>\n"],"names":["CONTEXT_SWITCHER_STORAGE_KEY","routes","computed","APPS","props","handleClick","event","app","currentLocation","destination","currentSessionName","prevSessionName","setPersistentItem","prevSessionUrl","getPersistentItem","removePersistentItem","emit"],"mappings":";;;;;;;;;;;;4BA8DQA,IAA+B;;;;;;;;;;;;;;iBAE/BC,IAASC,EAAwB,MAC9B;AAAA,MACL;AAAA,QACE,KAAKC,EAAK;AAAA,QACV,MAAMC,EAAM,aAAa,iBAAiB,cAAcA,EAAM;AAAA,QAC9D,cAAcA,EAAM,aAAa;AAAA,MACnC;AAAA,MACA;AAAA,QACE,KAAKD,EAAK;AAAA,QACV,MAAMC,EAAM,aAAa,iBAAiB,aAAaA,EAAM;AAAA,QAC7D,cAAc;AAAA,MAChB;AAAA,IAAA,CAEH;AASQ,aAAAC,EAAYC,GAAmBC,GAAgB;AAClD,UAAAA,MAAQH,EAAM;AAChB;AAGI,YAAAI,IAAkB,OAAO,SAAS;AACpC,UAAAC,IAAeH,EAAM,OAA6B;AAEtD,UAAIF,EAAM,aAAa,kBAAkBA,EAAM,aAAa,gBAAgB;AAE1E,cAAMM,IAAqB,GADVH,MAAQJ,EAAK,WAAWA,EAAK,cAAcA,EAAK,QAC3B,GAAGH,CAA4B,IAC/DW,IAAkB,GAAGJ,CAAG,GAAGP,CAA4B;AAG7D,QAAAY,EAAkBF,GAAoBF,GAAiB,EAAE,QAAQ,GAAM,CAAA;AAGvE,cAAMK,IAAiBC,EAAkBH,GAAiB,EAAE,QAAQ,IAAM;AAG1E,QAAIE,MACFP,EAAM,eAAe,GACPG,IAAAI,GACd,OAAO,SAAS,OAAOA,GACvBE,EAAqBJ,GAAiB,EAAE,QAAQ,GAAM,CAAA;AAAA,MAE1D;AAEA,MAAAK,EAAK,SAAS,EAAE,MAAMR,GAAiB,IAAIC,GAAa,GACxDO,EAAK,UAAUV,GAAO,EAAE,MAAME,GAAiB,IAAIC,GAAa;AAAA,IAClE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/Copy.js CHANGED
@@ -12,7 +12,7 @@ import "lodash-es/camelCase";
12
12
  import "lodash-es/get";
13
13
  import "lodash-es/isFinite";
14
14
  import "lodash-es/isPlainObject";
15
- import "./Button.vue_used_vue_type_style_index_0_lang.module-b77978d6.js";
15
+ import "./Button.vue_used_vue_type_style_index_0_lang.module-63d31dc0.js";
16
16
  import "lodash-es/uniqueId";
17
17
  import "./index-79ce320f.js";
18
18
  import "./Icon.vue_used_vue_type_style_index_0_lang.module-eb359559.js";
@@ -6,9 +6,9 @@ import "./utils/i18n.js";
6
6
  import "./constants.js";
7
7
  import "./locale.js";
8
8
  import "lodash-es/get";
9
- import "./Field.vue_vue_type_script_setup_true_lang-475832fe.js";
9
+ import "./Field.vue_vue_type_script_setup_true_lang-42ba3c5a.js";
10
10
  import "lodash-es/uniqueId";
11
- import "./Label.vue_vue_type_script_setup_true_lang-1d29d98a.js";
11
+ import "./Label.vue_vue_type_script_setup_true_lang-4b02087f.js";
12
12
  import "./Icon.js";
13
13
  import "./index-79ce320f.js";
14
14
  import "./Icon.vue_used_vue_type_style_index_0_lang.module-eb359559.js";
package/dist/DataView.js CHANGED
@@ -8,7 +8,7 @@ import "./Icon.js";
8
8
  import "lodash-es/uniqueId";
9
9
  import "./index-79ce320f.js";
10
10
  import "./Icon.vue_used_vue_type_style_index_0_lang.module-eb359559.js";
11
- import "./Paginate.vue_used_vue_type_style_index_0_lang.module-bfccf992.js";
11
+ import "./Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js";
12
12
  function _(e) {
13
13
  const n = e[0] === "-" ? "desc" : "asc";
14
14
  return { id: n === "asc" ? e : e.slice(1), order: n };
@@ -6,16 +6,16 @@ import { _ as Z } from "./Box.vue_vue_type_script_setup_true_lang-69e5176b.js";
6
6
  import A from "./Button.js";
7
7
  import T from "lodash-es/cloneDeep";
8
8
  import $ from "./Icon.js";
9
- import "./Paginate.vue_used_vue_type_style_index_0_lang.module-bfccf992.js";
9
+ import "./Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js";
10
10
  import { D as G } from "./DataView.vue_used_vue_type_style_index_0_lang.module-d878ca9a.js";
11
11
  import q from "./FilterChip.js";
12
- import { _ as H } from "./Label.vue_vue_type_script_setup_true_lang-1d29d98a.js";
12
+ import { _ as H } from "./Label.vue_vue_type_script_setup_true_lang-4b02087f.js";
13
13
  import K from "./Modal.js";
14
14
  import X from "./SearchBar.js";
15
15
  import { D as Y } from "./DataViewFilters.keys-c80ffabe.js";
16
16
  import { i as L } from "./isDefined-2ce6cde4.js";
17
17
  import "lodash-es/get";
18
- import "./Button.vue_used_vue_type_style_index_0_lang.module-b77978d6.js";
18
+ import "./Button.vue_used_vue_type_style_index_0_lang.module-63d31dc0.js";
19
19
  import "./_plugin-vue_export-helper-dad06003.js";
20
20
  import "lodash-es/uniqueId";
21
21
  import "./index-79ce320f.js";
@@ -26,7 +26,7 @@ import "./Backdrop.js";
26
26
  import "./Input.js";
27
27
  import "lodash-es/isNil";
28
28
  import "./utils/i18n.js";
29
- import "./Field.vue_vue_type_script_setup_true_lang-475832fe.js";
29
+ import "./Field.vue_vue_type_script_setup_true_lang-42ba3c5a.js";
30
30
  function Pe({
31
31
  schema: a,
32
32
  dataViewRef: w
@@ -82,8 +82,8 @@ function Pe({
82
82
  }
83
83
  const ee = {
84
84
  key: 1,
85
- class: "tw-col-span-12 tw-row-start-2 md:tw-row-start-1 md:tw-col-start-7 lg:tw-col-start-5 lg:tw-col-span-8"
86
- }, te = { class: "tw-hidden md:tw-block" }, le = { class: "tw-flex tw-gap-4" }, re = { class: "tw-inline-flex tw-items-center tw-gap-3" }, se = { class: "tw-flex tw-flex-col-reverse lg:tw-flex-row lg:tw-justify-end tw-gap-gutter" }, Te = /* @__PURE__ */ R({
85
+ 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
+ }, te = { class: "tw-hidden md:tw-block" }, le = { class: "tw-flex tw-gap-4" }, re = { class: "tw-inline-flex tw-items-center tw-gap-3" }, se = { class: "tw-flex tw-flex-col-reverse tw-gap-gutter lg:tw-flex-row lg:tw-justify-end" }, Te = /* @__PURE__ */ R({
87
87
  __name: "DataViewFilters",
88
88
  props: {
89
89
  filtersLabelText: { default: n("ll.filterBy") },
@@ -135,7 +135,7 @@ const ee = {
135
135
  return O(r, () => {
136
136
  r.value && w("open-drawer");
137
137
  }), (s, d) => (c(), v(Z, {
138
- class: J(["stash-data-view-filters tw-grid tw-grid-cols-12 tw-p-3 tw-gap-6", { "lg:tw-p-6": t(D) === "comfortable", "tw-mb-3": !t(b) }]),
138
+ class: J(["stash-data-view-filters tw-grid tw-grid-cols-12 tw-gap-6 tw-p-3", { "lg:tw-p-6": t(D) === "comfortable", "tw-mb-3": !t(b) }]),
139
139
  radius: t(b) ? "none" : "rounded",
140
140
  "data-test": "stash-data-view-filters",
141
141
  "disable-padding": ""
@@ -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 =\n 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, { useFiltersInstance: props.useFiltersInstance, drawerStyle: props.drawerStyle});\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-p-3 tw-gap-6\"\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-row-start-1 md:tw-col-start-7 lg:tw-col-start-5 lg:tw-col-span-8\"\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 lg:tw-flex-row lg:tw-justify-end tw-gap-gutter\">\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","slots","_useSlots","isDesktop","useMediaQuery","SCREEN_SIZES","density","isDataViewLoading","isWithinModule","currentSearch","updateCurrentSearch","inject","DATA_VIEW_INJECTION","provide","DATA_VIEW_FILTERS_UTILS_INJECTION","props","activeGroupActiveFiltersCount","isDrawerOpen","handleApplyClick","preventDismiss","_b","handleResetGroupClick","emit","handleResetAllClick","onDismiss","watch"],"mappings":"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"}
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 =\n 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, { useFiltersInstance: props.useFiltersInstance, drawerStyle: props.drawerStyle});\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","slots","_useSlots","isDesktop","useMediaQuery","SCREEN_SIZES","density","isDataViewLoading","isWithinModule","currentSearch","updateCurrentSearch","inject","DATA_VIEW_INJECTION","provide","DATA_VIEW_FILTERS_UTILS_INJECTION","props","activeGroupActiveFiltersCount","isDrawerOpen","handleApplyClick","preventDismiss","_b","handleResetGroupClick","emit","handleResetAllClick","onDismiss","watch"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCO,SAASA,GAAyD;AAAA,EACvE,QAAAC;AAAA,EACA,aAAAC;AACF,GAAyE;AACjE,QAAAC,IAAiBC,EAAI,CAAA,CAAE,GACvBC,IAAiBD,EAAI,CAAA,CAAE;AAE7B,aAAWE,KAAcL;AAEvB,IAAAE,EAAe,MAAMG,CAAU,IAAIL,EAAOK,CAAU,EAAE,cAEtDD,EAAe,MAAMC,CAAU,IAAIL,EAAOK,CAAU,EAAE;AAGxD,QAAMC,IAAQL;AAQd,WAASM,IAAe;AACP,IAAAL,EAAA,QAAQM,EAAUJ,EAAe,KAAK,GACrDE,EAAM,MAAM,qBAAqBJ,EAAe,OAAO,EAAE,YAAY,IAAM;AAAA,EAC7E;AAQA,WAASO,IAAkB;AACzB,eAAWJ,KAAcL;AAEvB,MAAAE,EAAe,MAAMG,CAAU,IAAIL,EAAOK,CAAU,EAAE,cAEtDD,EAAe,MAAMC,CAAU,IAAIL,EAAOK,CAAU,EAAE;AAGxD,IAAAC,EAAM,MAAM,qBAAqBJ,EAAe,OAAO,EAAE,YAAY,IAAM;AAAA,EAC7E;AAQA,WAASQ,EAAiBC,GAAe;AACvC,eAAWN,KAAcL;AACvB,MAAIA,EAAOK,CAAU,EAAE,UAAUM,MAE/BT,EAAe,MAAMG,CAAU,IAAIL,EAAOK,CAAU,EAAE,cAEtDD,EAAe,MAAMC,CAAU,IAAIL,EAAOK,CAAU,EAAE;AAI1D,IAAAC,EAAM,MAAM,qBAAqBJ,EAAe,OAAO,EAAE,YAAY,IAAM;AAAA,EAC7E;AAKA,WAASU,IAAqB;AACb,IAAAR,EAAA,QAAQI,EAAUN,EAAe,KAAK;AAAA,EACvD;AAEM,QAAAW,IAAsBC,EAAS,MAAM;;AACzC,UAAMC,IAAS,CAAA;AAEf,eAAWV,KAAcL,GAAQ;AACzB,YAAAgB,IAAShB,EAAOK,CAAU,GAC1BY,IAAQf,EAAe,MAAMG,CAAU;AAGzC,SAFaa,IAAAF,EAAO,aAAP,gBAAAE,EAAA,KAAAF,GAAkBC,OAAUE,EAAUF,CAAK,MAE5CD,EAAO,UACrBD,EAAOC,EAAO,KAAK,KAAKD,EAAOC,EAAO,KAAK,KAAK,KAAK;AAAA,IAEzD;AAEO,WAAAD;AAAA,EAAA,CACR,GAEKK,IAA0BN,EAAS,MAAM;;AAC7C,QAAIO,IAAQ;AAEZ,eAAWhB,KAAcL,GAAQ;AACzB,YAAAgB,IAAShB,EAAOK,CAAU,GAC1BY,IAAQf,EAAe,MAAMG,CAAU;AAG7C,SAFiBa,IAAAF,EAAO,aAAP,gBAAAE,EAAA,KAAAF,GAAkBC,OAAUE,EAAUF,CAAK,OAGjDI,KAAA;AAAA,IAEb;AAEO,WAAAA;AAAA,EAAA,CACR;AAEM,SAAA;AAAA,IACL,cAAAd;AAAA,IACA,iBAAAE;AAAA;AAAA,IAEA,kBAAAC;AAAA,IACA,oBAAAE;AAAA,IACA,qBAAAC;AAAA,IACA,yBAAAO;AAAA,IACA,gBAAAlB;AAAA,IACA,gBAAAE;AAAA,EAAA;AAEJ;;;;;;;;;;;;;;;;;;;iBC5EQkB,IAAQC,KAERC,IAAYC,EAAc,eAAeC,EAAa,EAAE,GAAG,GAE3D;AAAA,MACJ,SAAAC;AAAA,MACA,WAAWC;AAAA,MACX,gBAAAC;AAAA,MACA,eAAAC;AAAA,MACA,qBAAAC;AAAA,IACE,IAAAC,EAAOC,EAAoB,KAAKA,EAAoB,QAAQ;AAExD,IAAAC,EAAAC,EAAkC,KAAK,EAAE,oBAAoBC,EAAM,oBAAoB,aAAaA,EAAM,YAAA,CAAY;AAE9H,UAAMhB,IAA0BN,EAAS;;AAAM,eAAAI,IAAAkB,EAAM,uBAAN,gBAAAlB,EAA0B,wBAAwB,UAAS;AAAA,KAAC,GACrGmB,IAAgCvB;AAAA,MACpC,MAAM;;AAAA,iBAAAI,IAAAkB,EAAM,uBAAN,gBAAAlB,EAA0B,oBAAoB,MAAMkB,EAAM,iBAAgB;AAAA;AAAA,IAAA,GAE5EE,IAAenC,EAAI,EAAK;AAE9B,mBAAeoC,IAAmB;;AAC1B,YAAA,EAAE,gBAAAC,MAAoB,QAAMtB,IAAAkB,EAAM,YAAN,gBAAAlB,EAAA,KAAAkB,SAAsBK,IAAAL,EAAM,uBAAN,gBAAAK,EAA0B,mBAAkB;AAEpG,MAAKD,MACHF,EAAa,QAAQ;AAAA,IAEzB;AAEA,aAASI,IAAwB;;AACzB,OAAAxB,IAAAkB,EAAA,uBAAA,QAAAlB,EAAoB,iBAAiBkB,EAAM,cACjDO,EAAK,aAAa,GAClBL,EAAa,QAAQ;AAAA,IACvB;AAEA,aAASM,IAAsB;;AAC7B,OAAA1B,IAAAkB,EAAM,uBAAN,QAAAlB,EAA0B,mBAC1ByB,EAAK,WAAW,GAChBL,EAAa,QAAQ;AAAA,IACvB;AAEA,aAASO,IAAY;;AACnB,OAAA3B,IAAAkB,EAAM,uBAAN,QAAAlB,EAA0B,sBAC1BoB,EAAa,QAAQ,IACrBK,EAAK,SAAS;AAAA,IAChB;AAEA,WAAAG,EAAMR,GAAc,MAAM;AACxB,MAAIA,EAAa,SACfK,EAAK,aAAa;AAAA,IACpB,CACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,15 +1,15 @@
1
- import { defineComponent as g, inject as y, openBlock as r, createBlock as n, withCtx as o, createVNode as i, createTextVNode as d, toDisplayString as l, unref as e, createElementVNode as c, createElementBlock as f, Fragment as w, renderList as D, normalizeClass as k, createCommentVNode as m } from "vue";
2
- import { t as S } from "./locale.js";
1
+ import { defineComponent as y, useCssModule as D, inject as S, openBlock as r, createBlock as d, withCtx as o, createVNode as i, createTextVNode as n, toDisplayString as l, unref as t, createElementVNode as c, createElementBlock as f, Fragment as k, renderList as V, normalizeClass as b, createCommentVNode as m } from "vue";
2
+ import { t as B } from "./locale.js";
3
3
  import u from "./Button.js";
4
4
  import "lodash-es/cloneDeep";
5
5
  import h from "./Icon.js";
6
- import "./Paginate.vue_used_vue_type_style_index_0_lang.module-bfccf992.js";
7
- import { D as b } from "./DataView.vue_used_vue_type_style_index_0_lang.module-d878ca9a.js";
8
- import V from "./Dropdown.js";
9
- import v from "./IconLabel.js";
10
- import { _ as B } from "./_plugin-vue_export-helper-dad06003.js";
6
+ import "./Paginate.vue_used_vue_type_style_index_0_lang.module-18343da7.js";
7
+ import { D as C } from "./DataView.vue_used_vue_type_style_index_0_lang.module-d878ca9a.js";
8
+ import E from "./Dropdown.js";
9
+ import I from "./IconLabel.js";
10
+ import { _ as N } from "./_plugin-vue_export-helper-dad06003.js";
11
11
  import "lodash-es/get";
12
- import "./Button.vue_used_vue_type_style_index_0_lang.module-b77978d6.js";
12
+ import "./Button.vue_used_vue_type_style_index_0_lang.module-63d31dc0.js";
13
13
  import "lodash-es/uniqueId";
14
14
  import "./index-79ce320f.js";
15
15
  import "./Icon.vue_used_vue_type_style_index_0_lang.module-eb359559.js";
@@ -20,40 +20,40 @@ import "./utils/helpers.js";
20
20
  import "lodash-es/camelCase";
21
21
  import "lodash-es/isFinite";
22
22
  import "lodash-es/isPlainObject";
23
- const I = {
23
+ const v = {
24
24
  class: "dropdown__list",
25
25
  "data-test": "stash-data-view-sort-button|sort-menu"
26
- }, E = ["onClick"], N = ["onClick"], A = /* @__PURE__ */ g({
26
+ }, A = ["onClick"], M = ["onClick"], T = /* @__PURE__ */ y({
27
27
  __name: "DataViewSortButton",
28
28
  props: {
29
29
  sortOptions: { default: () => [] }
30
30
  },
31
- setup(C) {
32
- const _ = C, { currentSortId: a, currentSortOrder: s, updateCurrentSort: p } = y(
33
- b.key,
34
- b.defaults
31
+ setup(x) {
32
+ const _ = x, p = D(), { currentSortId: s, currentSortOrder: a, updateCurrentSort: w } = S(
33
+ C.key,
34
+ C.defaults
35
35
  );
36
- return (T, L) => _.sortOptions.length ? (r(), n(V, {
36
+ return (q, F) => _.sortOptions.length ? (r(), d(E, {
37
37
  key: 0,
38
38
  align: "left",
39
39
  class: "stash-data-view-sort-button",
40
40
  "data-test": "stash-data-view-sort-button"
41
41
  }, {
42
- toggle: o(({ isActive: t, toggle: x }) => [
42
+ toggle: o(({ isActive: e, toggle: g }) => [
43
43
  i(u, {
44
44
  "icon-label": "",
45
- "aria-expanded": t.toString(),
45
+ "aria-expanded": e.toString(),
46
46
  class: "tw-text-blue-500",
47
47
  "data-test": "stash-data-view-sort-button|sort-menu-button",
48
- onClick: x
48
+ onClick: g
49
49
  }, {
50
50
  default: o(() => [
51
- i(v, {
51
+ i(I, {
52
52
  icon: "sort",
53
53
  stacked: ""
54
54
  }, {
55
55
  default: o(() => [
56
- d(l(e(S)("ll.sort")), 1)
56
+ n(l(t(B)("ll.sort")), 1)
57
57
  ]),
58
58
  _: 1
59
59
  })
@@ -62,57 +62,66 @@ const I = {
62
62
  }, 1032, ["aria-expanded", "onClick"])
63
63
  ]),
64
64
  default: o(() => [
65
- c("ul", I, [
66
- (r(!0), f(w, null, D(_.sortOptions, (t) => (r(), f(w, {
67
- key: t.id
65
+ c("ul", v, [
66
+ (r(!0), f(k, null, V(_.sortOptions, (e) => (r(), f(k, {
67
+ key: e.id
68
68
  }, [
69
69
  c("li", {
70
- class: k(["dropdown__item rounded", { "is-selected": t.id === e(a) && e(s) === "asc" }]),
71
- onClick: () => e(p)(t.id, { sortOrder: "asc", shouldEmit: !0 })
70
+ class: b(["dropdown__item tw-rounded", [
71
+ t(p).dropdown__item,
72
+ { "tw-bg-blue-100 tw-text-ice-700": e.id === t(s) && t(a) === "asc" }
73
+ ]]),
74
+ onClick: () => t(w)(e.id, { sortOrder: "asc", shouldEmit: !0 })
72
75
  }, [
73
76
  i(u, {
74
77
  inline: "",
75
78
  class: "tw-h-9"
76
79
  }, {
77
80
  default: o(() => [
78
- d(l(t.labelAsc) + " ", 1),
79
- t.id === e(a) && e(s) === "asc" ? (r(), n(h, {
81
+ n(l(e.labelAsc) + " ", 1),
82
+ e.id === t(s) && t(a) === "asc" ? (r(), d(h, {
80
83
  key: 0,
81
84
  name: "check",
82
- class: "tw-text-blue-500 tw-ml-auto"
85
+ class: "tw-ml-auto tw-text-blue-500"
83
86
  })) : m("", !0)
84
87
  ]),
85
88
  _: 2
86
89
  }, 1024)
87
- ], 10, E),
90
+ ], 10, A),
88
91
  c("li", {
89
- class: k(["dropdown__item rounded", { "is-selected": t.id === e(a) && e(s) === "desc" }]),
90
- onClick: () => e(p)(t.id, { sortOrder: "desc", shouldEmit: !0 })
92
+ class: b(["dropdown__item tw-rounded", [
93
+ t(p).dropdown__item,
94
+ { "tw-bg-blue-100 tw-text-ice-700": e.id === t(s) && t(a) === "desc" }
95
+ ]]),
96
+ onClick: () => t(w)(e.id, { sortOrder: "desc", shouldEmit: !0 })
91
97
  }, [
92
98
  i(u, {
93
99
  inline: "",
94
100
  class: "tw-h-9"
95
101
  }, {
96
102
  default: o(() => [
97
- d(l(t.labelDesc) + " ", 1),
98
- t.id === e(a) && e(s) === "desc" ? (r(), n(h, {
103
+ n(l(e.labelDesc) + " ", 1),
104
+ e.id === t(s) && t(a) === "desc" ? (r(), d(h, {
99
105
  key: 0,
100
106
  name: "check",
101
- class: "tw-text-blue-500 tw-ml-auto"
107
+ class: "tw-ml-auto tw-text-blue-500"
102
108
  })) : m("", !0)
103
109
  ]),
104
110
  _: 2
105
111
  }, 1024)
106
- ], 10, N)
112
+ ], 10, M)
107
113
  ], 64))), 128))
108
114
  ])
109
115
  ]),
110
116
  _: 1
111
117
  })) : m("", !0);
112
118
  }
113
- });
114
- const rt = /* @__PURE__ */ B(A, [["__scopeId", "data-v-e33a9680"]]);
119
+ }), z = "_dropdown__item_ozq17_2", L = {
120
+ dropdown__item: z
121
+ }, j = {
122
+ $style: L
123
+ }, nt = /* @__PURE__ */ N(T, [["__cssModules", j]]);
115
124
  export {
116
- rt as default
125
+ nt as default
117
126
  };
118
127
  //# sourceMappingURL=DataViewSortButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataViewSortButton.js","sources":["../src/components/DataViewSortButton/DataViewSortButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { inject } from 'vue';\n\n import { t } from '../../locale';\n import Button from '../Button/Button.vue';\n import { DATA_VIEW_INJECTION } from '../DataView/DataView.vue';\n import Dropdown from '../Dropdown/Dropdown.vue';\n import Icon from '../Icon/Icon.vue';\n import IconLabel from '../IconLabel/IconLabel.vue';\n import { SortOption } from './DataViewSortButton.types';\n\n export interface DataViewToolbarProps {\n /**\n * An array of sort options to display in the dropdown.\n */\n sortOptions?: SortOption[];\n }\n\n const props = withDefaults(defineProps<DataViewToolbarProps>(), {\n sortOptions: () => [],\n });\n\n const { currentSortId, currentSortOrder, updateCurrentSort } = inject(\n DATA_VIEW_INJECTION.key,\n DATA_VIEW_INJECTION.defaults,\n );\n</script>\n\n<template>\n <Dropdown\n v-if=\"props.sortOptions.length\"\n align=\"left\"\n class=\"stash-data-view-sort-button\"\n data-test=\"stash-data-view-sort-button\"\n >\n <template #toggle=\"{ isActive, toggle }\">\n <Button\n icon-label\n :aria-expanded=\"isActive.toString()\"\n class=\"tw-text-blue-500\"\n data-test=\"stash-data-view-sort-button|sort-menu-button\"\n @click=\"toggle\"\n >\n <IconLabel icon=\"sort\" stacked>\n {{ t('ll.sort') }}\n </IconLabel>\n </Button>\n </template>\n <ul class=\"dropdown__list\" data-test=\"stash-data-view-sort-button|sort-menu\">\n <template v-for=\"sortOption in props.sortOptions\" :key=\"sortOption.id\">\n <li\n class=\"dropdown__item rounded\"\n :class=\"{ 'is-selected': sortOption.id === currentSortId && currentSortOrder === 'asc' }\"\n @click=\"() => updateCurrentSort(sortOption.id, { sortOrder: 'asc', shouldEmit: true })\"\n >\n <Button inline class=\"tw-h-9\">\n {{ sortOption.labelAsc }}\n <Icon\n v-if=\"sortOption.id === currentSortId && currentSortOrder === 'asc'\"\n name=\"check\"\n class=\"tw-text-blue-500 tw-ml-auto\"\n />\n </Button>\n </li>\n <li\n class=\"dropdown__item rounded\"\n :class=\"{ 'is-selected': sortOption.id === currentSortId && currentSortOrder === 'desc' }\"\n @click=\"() => updateCurrentSort(sortOption.id, { sortOrder: 'desc', shouldEmit: true })\"\n >\n <Button inline class=\"tw-h-9\">\n {{ sortOption.labelDesc }}\n <Icon\n v-if=\"sortOption.id === currentSortId && currentSortOrder === 'desc'\"\n name=\"check\"\n class=\"tw-text-blue-500 tw-ml-auto\"\n />\n </Button>\n </li>\n </template>\n </ul>\n </Dropdown>\n</template>\n\n<style scoped>\n .dropdown__item > button {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n</style>\n"],"names":["currentSortId","currentSortOrder","updateCurrentSort","inject","DATA_VIEW_INJECTION"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsBQ,EAAE,eAAAA,GAAe,kBAAAC,GAAkB,mBAAAC,EAAsB,IAAAC;AAAA,MAC7DC,EAAoB;AAAA,MACpBA,EAAoB;AAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"DataViewSortButton.js","sources":["../src/components/DataViewSortButton/DataViewSortButton.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n import { inject, useCssModule } from 'vue';\n\n import { t } from '../../locale';\n import Button from '../Button/Button.vue';\n import { DATA_VIEW_INJECTION } from '../DataView/DataView.vue';\n import Dropdown from '../Dropdown/Dropdown.vue';\n import Icon from '../Icon/Icon.vue';\n import IconLabel from '../IconLabel/IconLabel.vue';\n import { SortOption } from './DataViewSortButton.types';\n\n export interface DataViewToolbarProps {\n /**\n * An array of sort options to display in the dropdown.\n */\n sortOptions?: SortOption[];\n }\n\n const props = withDefaults(defineProps<DataViewToolbarProps>(), {\n sortOptions: () => [],\n });\n const classes = useCssModule();\n\n const { currentSortId, currentSortOrder, updateCurrentSort } = inject(\n DATA_VIEW_INJECTION.key,\n DATA_VIEW_INJECTION.defaults,\n );\n</script>\n\n<template>\n <Dropdown\n v-if=\"props.sortOptions.length\"\n align=\"left\"\n class=\"stash-data-view-sort-button\"\n data-test=\"stash-data-view-sort-button\"\n >\n <template #toggle=\"{ isActive, toggle }\">\n <Button\n icon-label\n :aria-expanded=\"isActive.toString()\"\n class=\"tw-text-blue-500\"\n data-test=\"stash-data-view-sort-button|sort-menu-button\"\n @click=\"toggle\"\n >\n <IconLabel icon=\"sort\" stacked>\n {{ t('ll.sort') }}\n </IconLabel>\n </Button>\n </template>\n <ul class=\"dropdown__list\" data-test=\"stash-data-view-sort-button|sort-menu\">\n <template v-for=\"sortOption in props.sortOptions\" :key=\"sortOption.id\">\n <li\n class=\"dropdown__item tw-rounded\"\n :class=\"[\n classes.dropdown__item,\n { 'tw-bg-blue-100 tw-text-ice-700': sortOption.id === currentSortId && currentSortOrder === 'asc' },\n ]\"\n @click=\"() => updateCurrentSort(sortOption.id, { sortOrder: 'asc', shouldEmit: true })\"\n >\n <Button inline class=\"tw-h-9\">\n {{ sortOption.labelAsc }}\n <Icon\n v-if=\"sortOption.id === currentSortId && currentSortOrder === 'asc'\"\n name=\"check\"\n class=\"tw-ml-auto tw-text-blue-500\"\n />\n </Button>\n </li>\n <li\n class=\"dropdown__item tw-rounded\"\n :class=\"[\n classes.dropdown__item,\n { 'tw-bg-blue-100 tw-text-ice-700': sortOption.id === currentSortId && currentSortOrder === 'desc' },\n ]\"\n @click=\"() => updateCurrentSort(sortOption.id, { sortOrder: 'desc', shouldEmit: true })\"\n >\n <Button inline class=\"tw-h-9\">\n {{ sortOption.labelDesc }}\n <Icon\n v-if=\"sortOption.id === currentSortId && currentSortOrder === 'desc'\"\n name=\"check\"\n class=\"tw-ml-auto tw-text-blue-500\"\n />\n </Button>\n </li>\n </template>\n </ul>\n </Dropdown>\n</template>\n\n<style module>\n .dropdown__item > button {\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n</style>\n"],"names":["classes","useCssModule","currentSortId","currentSortOrder","updateCurrentSort","inject","DATA_VIEW_INJECTION"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqBQA,IAAUC,KAEV,EAAE,eAAAC,GAAe,kBAAAC,GAAkB,mBAAAC,EAAsB,IAAAC;AAAA,MAC7DC,EAAoB;AAAA,MACpBA,EAAoB;AAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}