nuxt-ui-tools 0.1.0 → 0.1.1

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 (164) hide show
  1. package/dist/module.d.mts +4 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +30 -15
  4. package/dist/runtime/form/components/actions/FormActions.d.vue.ts +0 -2
  5. package/dist/runtime/form/components/actions/FormActions.vue +5 -8
  6. package/dist/runtime/form/components/actions/FormActions.vue.d.ts +0 -2
  7. package/dist/runtime/form/components/layout/DrawerLayout.vue +5 -1
  8. package/dist/runtime/form/components/layout/ModalLayout.vue +5 -1
  9. package/dist/runtime/form/components/renderer/FormCompositeControl.d.vue.ts +15 -0
  10. package/dist/runtime/form/components/renderer/FormCompositeControl.vue +13 -0
  11. package/dist/runtime/form/components/renderer/FormCompositeControl.vue.d.ts +15 -0
  12. package/dist/runtime/form/components/renderer/FormFieldRenderer.d.vue.ts +1 -0
  13. package/dist/runtime/form/components/renderer/FormFieldRenderer.vue +19 -3
  14. package/dist/runtime/form/components/renderer/FormFieldRenderer.vue.d.ts +1 -0
  15. package/dist/runtime/form/components/renderer/FormFieldShell.d.vue.ts +4 -4
  16. package/dist/runtime/form/components/renderer/FormFieldShell.vue +15 -1
  17. package/dist/runtime/form/components/renderer/FormFieldShell.vue.d.ts +4 -4
  18. package/dist/runtime/form/components/root/Form.vue +5 -3
  19. package/dist/runtime/form/composables/use-field-control.d.ts +1 -1
  20. package/dist/runtime/form/composables/use-field-control.js +4 -0
  21. package/dist/runtime/form/composables/use-field-options.d.ts +1 -1
  22. package/dist/runtime/form/composables/use-field-options.js +75 -31
  23. package/dist/runtime/form/composables/use-form-field-chrome.d.ts +3 -0
  24. package/dist/runtime/form/composables/use-form-field-chrome.js +9 -0
  25. package/dist/runtime/form/composables/use-form-runtime.js +17 -5
  26. package/dist/runtime/form/fields/array-list/component.vue +4 -1
  27. package/dist/runtime/form/fields/auto-complete/component.vue +23 -16
  28. package/dist/runtime/form/fields/checkbox-card/component.vue +28 -29
  29. package/dist/runtime/form/fields/checkbox-group/component.vue +28 -29
  30. package/dist/runtime/form/fields/color-picker/component.vue +4 -2
  31. package/dist/runtime/form/fields/date-family/component.vue +9 -4
  32. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.d.vue.ts +13 -0
  33. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.vue +24 -0
  34. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.vue.d.ts +13 -0
  35. package/dist/runtime/form/fields/hierarchy/SelectionRadio.d.vue.ts +14 -0
  36. package/dist/runtime/form/fields/hierarchy/SelectionRadio.vue +27 -0
  37. package/dist/runtime/form/fields/hierarchy/SelectionRadio.vue.d.ts +14 -0
  38. package/dist/runtime/form/fields/hierarchy/component.vue +257 -142
  39. package/dist/runtime/form/fields/hierarchy/utils.d.ts +9 -0
  40. package/dist/runtime/form/fields/hierarchy/utils.js +32 -0
  41. package/dist/runtime/form/fields/input-group/component.vue +7 -30
  42. package/dist/runtime/form/fields/matrix/component.vue +9 -3
  43. package/dist/runtime/form/fields/phone-number/component.vue +7 -2
  44. package/dist/runtime/form/fields/rating/component.vue +25 -2
  45. package/dist/runtime/form/fields/select/component.vue +29 -21
  46. package/dist/runtime/form/fields/switch-group/component.vue +8 -3
  47. package/dist/runtime/form/fields/time/component.vue +7 -5
  48. package/dist/runtime/form/fields/upload/component.vue +5 -3
  49. package/dist/runtime/form/types/api.d.ts +9 -3
  50. package/dist/runtime/form/types/field-base.d.ts +3 -1
  51. package/dist/runtime/form/types/runtime.d.ts +2 -0
  52. package/dist/runtime/form/types/ui.d.ts +1 -0
  53. package/dist/runtime/form/utils/api.js +3 -0
  54. package/dist/runtime/form/utils/options.d.ts +11 -2
  55. package/dist/runtime/form/utils/options.js +57 -9
  56. package/dist/runtime/form/utils/state.js +10 -2
  57. package/dist/runtime/i18n/locales/en.js +38 -0
  58. package/dist/runtime/i18n/locales/fr.js +38 -0
  59. package/dist/runtime/i18n/types.d.ts +38 -0
  60. package/dist/runtime/i18n/use-locale.d.ts +2 -2
  61. package/dist/runtime/i18n/use-locale.js +3 -3
  62. package/dist/runtime/table/components/DataList.d.vue.ts +2 -0
  63. package/dist/runtime/table/components/DataList.vue.d.ts +2 -0
  64. package/dist/runtime/table/components/actions/RowActions.d.vue.ts +4 -2
  65. package/dist/runtime/table/components/actions/RowActions.vue +2 -0
  66. package/dist/runtime/table/components/actions/RowActions.vue.d.ts +4 -2
  67. package/dist/runtime/table/components/data-list/DataListAddFilter.d.vue.ts +5 -3
  68. package/dist/runtime/table/components/data-list/DataListAddFilter.vue +6 -1
  69. package/dist/runtime/table/components/data-list/DataListAddFilter.vue.d.ts +5 -3
  70. package/dist/runtime/table/components/data-list/DataListContent.d.vue.ts +24 -17
  71. package/dist/runtime/table/components/data-list/DataListContent.vue +70 -17
  72. package/dist/runtime/table/components/data-list/DataListContent.vue.d.ts +24 -17
  73. package/dist/runtime/table/components/data-list/DataListDefault.d.vue.ts +2 -0
  74. package/dist/runtime/table/components/data-list/DataListDefault.vue.d.ts +2 -0
  75. package/dist/runtime/table/components/data-list/DataListFilterTags.d.vue.ts +2 -0
  76. package/dist/runtime/table/components/data-list/DataListFilterTags.vue.d.ts +2 -0
  77. package/dist/runtime/table/components/data-list/DataListLayoutSwitch.vue +17 -11
  78. package/dist/runtime/table/components/data-list/DataListRoot.vue +2 -46
  79. package/dist/runtime/table/components/data-list/DataListSortMenu.vue +6 -0
  80. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.d.vue.ts +5 -0
  81. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.vue +182 -59
  82. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.vue.d.ts +5 -0
  83. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.d.vue.ts +3 -1
  84. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.vue +29 -5
  85. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.vue.d.ts +3 -1
  86. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.d.vue.ts +17 -0
  87. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.vue +47 -0
  88. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.vue.d.ts +17 -0
  89. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.d.vue.ts +3 -1
  90. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.vue +12 -3
  91. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.vue.d.ts +3 -1
  92. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.d.vue.ts +3 -0
  93. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.vue +11 -1
  94. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.vue.d.ts +3 -0
  95. package/dist/runtime/table/components/filters/shared/FilterOptionRow.d.vue.ts +3 -0
  96. package/dist/runtime/table/components/filters/shared/FilterOptionRow.vue +48 -9
  97. package/dist/runtime/table/components/filters/shared/FilterOptionRow.vue.d.ts +3 -0
  98. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.d.vue.ts +3 -0
  99. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.vue +35 -9
  100. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.vue.d.ts +3 -0
  101. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.d.vue.ts +3 -0
  102. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.vue +77 -20
  103. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.vue.d.ts +3 -0
  104. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.d.vue.ts +27 -0
  105. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.vue +36 -0
  106. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.vue.d.ts +27 -0
  107. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.d.vue.ts +3 -0
  108. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.vue +40 -10
  109. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.vue.d.ts +3 -0
  110. package/dist/runtime/table/components/filters/shared/FilterStageTransition.d.vue.ts +23 -0
  111. package/dist/runtime/table/components/filters/shared/FilterStageTransition.vue +21 -0
  112. package/dist/runtime/table/components/filters/shared/FilterStageTransition.vue.d.ts +23 -0
  113. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.d.vue.ts +3 -2
  114. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.vue +26 -25
  115. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.vue.d.ts +3 -2
  116. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.d.vue.ts +1 -1
  117. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.vue +75 -22
  118. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.vue.d.ts +1 -1
  119. package/dist/runtime/table/components/filters/tags/DateFilterTag.d.vue.ts +3 -1
  120. package/dist/runtime/table/components/filters/tags/DateFilterTag.vue +254 -160
  121. package/dist/runtime/table/components/filters/tags/DateFilterTag.vue.d.ts +3 -1
  122. package/dist/runtime/table/components/filters/tags/FilterTagsBar.d.vue.ts +7 -6
  123. package/dist/runtime/table/components/filters/tags/FilterTagsBar.vue +12 -27
  124. package/dist/runtime/table/components/filters/tags/FilterTagsBar.vue.d.ts +7 -6
  125. package/dist/runtime/table/components/filters/tags/NumberFilterTag.d.vue.ts +3 -2
  126. package/dist/runtime/table/components/filters/tags/NumberFilterTag.vue +192 -106
  127. package/dist/runtime/table/components/filters/tags/NumberFilterTag.vue.d.ts +3 -2
  128. package/dist/runtime/table/components/filters/tags/OptionFilterTag.d.vue.ts +3 -2
  129. package/dist/runtime/table/components/filters/tags/OptionFilterTag.vue +110 -48
  130. package/dist/runtime/table/components/filters/tags/OptionFilterTag.vue.d.ts +3 -2
  131. package/dist/runtime/table/components/filters/tags/TextFilterTag.d.vue.ts +3 -2
  132. package/dist/runtime/table/components/filters/tags/TextFilterTag.vue +120 -57
  133. package/dist/runtime/table/components/filters/tags/TextFilterTag.vue.d.ts +3 -2
  134. package/dist/runtime/table/components/grid/GridRenderer.vue +1 -1
  135. package/dist/runtime/table/components/layout/TableFooter.vue +1 -0
  136. package/dist/runtime/table/components/table/TableRenderer.vue +18 -9
  137. package/dist/runtime/table/composables/use-filter-tag-session.d.ts +3 -4
  138. package/dist/runtime/table/composables/use-filter-tag-session.js +12 -32
  139. package/dist/runtime/table/composables/use-query-state.d.ts +3 -3
  140. package/dist/runtime/table/composables/use-query-state.js +7 -32
  141. package/dist/runtime/table/composables/use-table-api.js +2 -2
  142. package/dist/runtime/table/composables/use-table-columns.d.ts +1 -11
  143. package/dist/runtime/table/composables/use-table-filter-presentation.d.ts +0 -3
  144. package/dist/runtime/table/composables/use-table-filter-presentation.js +0 -9
  145. package/dist/runtime/table/composables/use-table-filters.js +18 -7
  146. package/dist/runtime/table/composables/use-table-internals.d.ts +3 -42
  147. package/dist/runtime/table/types/actions.d.ts +1 -1
  148. package/dist/runtime/table/types/data-list.d.ts +41 -8
  149. package/dist/runtime/table/types/filters.d.ts +4 -0
  150. package/dist/runtime/table/utils/actions.d.ts +1 -1
  151. package/dist/runtime/table/utils/columns/menu.d.ts +2 -11
  152. package/dist/runtime/table/utils/columns/render.d.ts +2 -9
  153. package/dist/runtime/table/utils/columns/render.js +4 -4
  154. package/dist/runtime/table/utils/data-list-ui.d.ts +3 -1
  155. package/dist/runtime/table/utils/data-list-ui.js +45 -0
  156. package/dist/runtime/table/utils/filters/editor-size.d.ts +11 -0
  157. package/dist/runtime/table/utils/filters/editor-size.js +45 -0
  158. package/dist/runtime/table/utils/filters/index.d.ts +1 -1
  159. package/dist/runtime/table/utils/filters/index.js +1 -1
  160. package/dist/runtime/table/utils/query-state.d.ts +18 -1
  161. package/dist/runtime/table/utils/query-state.js +109 -0
  162. package/package.json +4 -2
  163. package/dist/runtime/table/utils/filters/operators.d.ts +0 -4
  164. package/dist/runtime/table/utils/filters/operators.js +0 -6
@@ -1,28 +1,43 @@
1
1
  <script setup>
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
- import UPopover from "@nuxt/ui/components/Popover.vue";
4
- import { computed, ref, toRef } from "vue";
3
+ import { computed, ref } from "vue";
5
4
  import { useRangeSelect } from "../../../../shared";
5
+ import { useDataListUi } from "../../../composables/use-data-list-ui";
6
6
  import { useFilterTagSession } from "../../../composables/use-filter-tag-session";
7
7
  import { useOptionFilterEditorState } from "../../../composables/use-option-filter-editor-state";
8
8
  import { useTableInternals } from "../../../composables/use-table-internals";
9
- import { resolveFilterTriggerIcon } from "../../../utils";
9
+ import {
10
+ mergeDataListUiClass,
11
+ resolveFilterEditorSizeClasses,
12
+ resolveFilterTriggerIcon
13
+ } from "../../../utils";
14
+ import FilterMatchModePanel from "../shared/FilterMatchModePanel.vue";
10
15
  import FilterOptionPickerContent from "../shared/FilterOptionPickerContent.vue";
16
+ import FilterPopoverShell from "../shared/FilterPopoverShell.vue";
17
+ import FilterStageTransition from "../shared/FilterStageTransition.vue";
11
18
  import TableFilterTrigger from "../shared/FilterTriggerTag.vue";
12
19
  const props = defineProps({
13
20
  definition: { type: Object, required: true },
14
21
  dynamic: { type: Boolean, required: false },
15
22
  session: { type: Boolean, required: false },
16
- activationToken: { type: Number, required: false }
23
+ embedded: { type: Boolean, required: false },
24
+ initialOperator: { type: String, required: false }
17
25
  });
18
26
  const emit = defineEmits(["dismiss", "sessionClosed"]);
19
27
  const internals = useTableInternals();
28
+ const dataListUi = useDataListUi();
29
+ const dataListFilterUi = computed(() => dataListUi.ui.value.filterTags?.ui);
30
+ const size = computed(() => dataListUi.ui.value.filterTags?.size ?? dataListUi.controlSize.value);
31
+ const sizeClasses = computed(() => resolveFilterEditorSizeClasses(size.value));
20
32
  const searchQuery = ref("");
21
33
  const isSessionOpen = ref(false);
22
34
  const isContentReady = ref(false);
23
- const pendingOperator = ref();
35
+ const pendingOperator = ref(props.initialOperator);
24
36
  const localSelectedValues = ref([]);
25
37
  const pinnedValues = ref(/* @__PURE__ */ new Set());
38
+ const stage = ref("editor");
39
+ const stageDirection = ref("forward");
40
+ const stageTransitioning = ref(false);
26
41
  const operator = computed(() => {
27
42
  const next = pendingOperator.value ?? internals.filters.getFilterOperator({
28
43
  key: props.definition.key
@@ -43,11 +58,10 @@ const state = useOptionFilterEditorState({
43
58
  });
44
59
  const session = useFilterTagSession({
45
60
  isOpen: isSessionOpen,
46
- activationToken: toRef(props, "activationToken"),
47
61
  session: props.session,
48
62
  dynamic: props.dynamic,
63
+ embedded: props.embedded,
49
64
  hasCommittedState: () => internals.filters.getFilterState({ key: props.definition.key }) != null,
50
- onActivated: () => handleActivate(operator.value),
51
65
  onOpen: () => {
52
66
  isContentReady.value = false;
53
67
  initLocalState();
@@ -109,7 +123,9 @@ const restRangeSelect = useRangeSelect({
109
123
  onToggle: state.toggleValue
110
124
  });
111
125
  function initLocalState() {
112
- const committedRule = internals.filters.getFilterState({ key: props.definition.key });
126
+ const committedRule = internals.filters.getFilterState({
127
+ key: props.definition.key
128
+ });
113
129
  const values = Array.isArray(committedRule?.value) ? committedRule.value.filter(
114
130
  (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean"
115
131
  ) : committedRule?.value != null && (typeof committedRule.value === "string" || typeof committedRule.value === "number" || typeof committedRule.value === "boolean") ? [committedRule.value] : [];
@@ -119,19 +135,27 @@ function initLocalState() {
119
135
  }
120
136
  function handleActivate(op) {
121
137
  pendingOperator.value = op;
122
- session.openWithLock();
138
+ stage.value = "editor";
139
+ stageDirection.value = "backward";
140
+ session.open();
141
+ }
142
+ function handleRequestMatchMode() {
143
+ stageDirection.value = "forward";
144
+ stageTransitioning.value = true;
145
+ stage.value = "match-mode";
146
+ session.open();
123
147
  }
124
148
  function handleOperatorChange(op) {
125
- if (state.filterUi.value.clearOnOperatorChange)
126
- internals.filters.clearFilter({ key: props.definition.key });
127
149
  localSelectedValues.value = [];
128
150
  pinnedValues.value = /* @__PURE__ */ new Set();
129
151
  state.resetExpandedIds();
130
152
  searchQuery.value = "";
131
153
  pinnedRangeSelect.reset();
132
154
  restRangeSelect.reset();
133
- if (state.filterUi.value.reopenOnOperatorChange) handleActivate(op);
134
- else pendingOperator.value = op;
155
+ pendingOperator.value = op;
156
+ stageDirection.value = "forward";
157
+ stageTransitioning.value = true;
158
+ stage.value = "editor";
135
159
  }
136
160
  function setSelectedValues(values) {
137
161
  localSelectedValues.value = values;
@@ -183,11 +207,14 @@ function handleContentMounted() {
183
207
  </script>
184
208
 
185
209
  <template>
186
- <UPopover
210
+ <FilterPopoverShell
187
211
  :open="session.isOpen.value"
188
- :content="{ side: 'bottom', align: 'start', sideOffset: 8 }"
189
- :ui="{ content: 'w-fit overflow-hidden p-0 shadow-none' }"
190
- @update:open="session.handleOpenChange"
212
+ :embedded="embedded"
213
+ :transitioning="stageTransitioning"
214
+ :content-class="
215
+ mergeDataListUiClass('w-fit overflow-hidden p-0', void 0, dataListFilterUi?.popoverContent)
216
+ "
217
+ @update-open="session.handleOpenChange"
191
218
  >
192
219
  <slot
193
220
  name="trigger"
@@ -203,52 +230,87 @@ function handleContentMounted() {
203
230
  <TableFilterTrigger
204
231
  :label="internals.filters.getFilterLabelText({ label: definition.label })"
205
232
  :leading-icon="resolveFilterTriggerIcon(definition)"
233
+ :operator="operator"
206
234
  :operator-label="operatorLabel"
207
235
  :operator-items="operatorItems"
208
236
  :preview-tags="preview.tags"
209
237
  :preview-summary="preview.summary"
210
238
  :active="preview.active"
211
- @select-operator="handleOperatorChange"
212
239
  @activate="handleActivate"
240
+ @request-match-mode="handleRequestMatchMode"
213
241
  @clear="clearFilter"
214
242
  />
215
243
  </slot>
216
244
 
217
245
  <template #content>
218
- <div class="w-fit max-w-[calc(100vw-1rem)] bg-default" @vue:mounted="handleContentMounted">
219
- <FilterOptionPickerContent
220
- v-model:search-query="searchQuery"
221
- :flat-radio-value="state.flatRadioValue.value"
222
- :tree-radio-value="state.treeRadioValue.value"
223
- :state="state"
224
- :sections="listSections"
225
- @update:flat-radio-value="state.flatRadioValue.value = $event"
226
- @update:tree-radio-value="state.treeRadioValue.value = $event"
227
- @select-entry="handleSelectEntry"
228
- @toggle-tree-entry="handleToggleTreeEntry"
229
- @toggle-expanded="state.toggleExpanded"
246
+ <FilterStageTransition
247
+ :stage-key="stage"
248
+ :direction="stageDirection"
249
+ @settled="stageTransitioning = false"
250
+ >
251
+ <FilterMatchModePanel
252
+ v-if="stage === 'match-mode'"
253
+ :items="operatorItems"
254
+ :selected="operator"
255
+ :size="size"
256
+ :ui="dataListFilterUi"
257
+ @select="handleOperatorChange"
230
258
  />
231
-
232
259
  <div
233
- v-if="state.filterUi.value.commitMode === 'manual'"
234
- class="flex items-center justify-between border-t border-default p-2"
260
+ v-else
261
+ :class="
262
+ mergeDataListUiClass(
263
+ `${sizeClasses.editor} max-w-[calc(100vw-1rem)] bg-default`,
264
+ void 0,
265
+ dataListFilterUi?.editor
266
+ )
267
+ "
268
+ @vue:mounted="handleContentMounted"
235
269
  >
236
- <UButton
237
- color="neutral"
238
- variant="ghost"
239
- size="sm"
240
- :label="state.filterUi.value.actions.clear"
241
- @click="clearFilter"
242
- />
243
- <UButton
244
- color="neutral"
245
- variant="subtle"
246
- size="sm"
247
- :label="state.filterUi.value.actions.apply"
248
- @click="applyFilter"
270
+ <FilterOptionPickerContent
271
+ v-model:search-query="searchQuery"
272
+ :flat-radio-value="state.flatRadioValue.value"
273
+ :tree-radio-value="state.treeRadioValue.value"
274
+ :state="state"
275
+ :sections="listSections"
276
+ :size="size"
277
+ :ui="dataListFilterUi"
278
+ @update:flat-radio-value="state.flatRadioValue.value = $event"
279
+ @update:tree-radio-value="state.treeRadioValue.value = $event"
280
+ @select-entry="handleSelectEntry"
281
+ @toggle-tree-entry="handleToggleTreeEntry"
282
+ @toggle-expanded="state.toggleExpanded"
249
283
  />
284
+
285
+ <div
286
+ v-if="state.filterUi.value.commitMode === 'manual'"
287
+ :class="
288
+ mergeDataListUiClass(
289
+ `flex items-center justify-between border-t border-default ${sizeClasses.footer}`,
290
+ void 0,
291
+ dataListFilterUi?.footer
292
+ )
293
+ "
294
+ >
295
+ <UButton
296
+ color="neutral"
297
+ variant="ghost"
298
+ :size="size"
299
+ :label="state.filterUi.value.actions.clear"
300
+ :ui="{ base: dataListFilterUi?.clear }"
301
+ @click="clearFilter"
302
+ />
303
+ <UButton
304
+ color="neutral"
305
+ variant="subtle"
306
+ :size="size"
307
+ :label="state.filterUi.value.actions.apply"
308
+ :ui="{ base: dataListFilterUi?.apply }"
309
+ @click="applyFilter"
310
+ />
311
+ </div>
250
312
  </div>
251
- </div>
313
+ </FilterStageTransition>
252
314
  </template>
253
- </UPopover>
315
+ </FilterPopoverShell>
254
316
  </template>
@@ -1,9 +1,10 @@
1
- import type { TableOptionFilterDefinition } from '../../../types/index.js';
1
+ import type { TableFilterOperator, TableOptionFilterDefinition } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  definition: TableOptionFilterDefinition;
4
4
  dynamic?: boolean;
5
5
  session?: boolean;
6
- activationToken?: number;
6
+ embedded?: boolean;
7
+ initialOperator?: TableFilterOperator;
7
8
  };
8
9
  declare var __VLS_10: {
9
10
  preview: import("../../../utils/index.js").FilterPreviewResult;
@@ -1,9 +1,10 @@
1
- import type { TableTextFilterDefinition } from '../../../types/index.js';
1
+ import type { TableFilterOperator, TableTextFilterDefinition } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  definition: TableTextFilterDefinition;
4
4
  dynamic?: boolean;
5
5
  session?: boolean;
6
- activationToken?: number;
6
+ embedded?: boolean;
7
+ initialOperator?: TableFilterOperator;
7
8
  };
8
9
  declare var __VLS_10: {
9
10
  preview: import("../../../utils/index.js").FilterPreviewResult;
@@ -1,22 +1,32 @@
1
1
  <script setup>
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
3
  import UInput from "@nuxt/ui/components/Input.vue";
4
- import UPopover from "@nuxt/ui/components/Popover.vue";
5
- import { computed, ref, toRef } from "vue";
4
+ import { computed, ref } from "vue";
5
+ import { useDataListUi } from "../../../composables/use-data-list-ui";
6
6
  import { useFilterTagSession } from "../../../composables/use-filter-tag-session";
7
7
  import { useTableInternals } from "../../../composables/use-table-internals";
8
- import { resolveFilterTriggerIcon, resolveTextFilterUi } from "../../../utils";
8
+ import { mergeDataListUiClass, resolveFilterTriggerIcon, resolveTextFilterUi } from "../../../utils";
9
+ import FilterMatchModePanel from "../shared/FilterMatchModePanel.vue";
10
+ import FilterPopoverShell from "../shared/FilterPopoverShell.vue";
11
+ import FilterStageTransition from "../shared/FilterStageTransition.vue";
9
12
  import TableFilterTrigger from "../shared/FilterTriggerTag.vue";
10
13
  const props = defineProps({
11
14
  definition: { type: Object, required: true },
12
15
  dynamic: { type: Boolean, required: false },
13
16
  session: { type: Boolean, required: false },
14
- activationToken: { type: Number, required: false }
17
+ embedded: { type: Boolean, required: false },
18
+ initialOperator: { type: String, required: false }
15
19
  });
16
20
  const emit = defineEmits(["dismiss", "sessionClosed"]);
17
21
  const internals = useTableInternals();
18
- const pendingOperator = ref();
22
+ const dataListUi = useDataListUi();
23
+ const dataListFilterUi = computed(() => dataListUi.ui.value.filterTags?.ui);
24
+ const size = computed(() => dataListUi.ui.value.filterTags?.size ?? dataListUi.controlSize.value);
25
+ const pendingOperator = ref(props.initialOperator);
19
26
  const localValue = ref("");
27
+ const stage = ref("editor");
28
+ const stageDirection = ref("forward");
29
+ const stageTransitioning = ref(false);
20
30
  const preview = computed(
21
31
  () => internals.filters.getFilterPreview({
22
32
  key: props.definition.key
@@ -40,15 +50,16 @@ const operatorItems = computed(
40
50
  );
41
51
  const filterUi = computed(() => resolveTextFilterUi(props.definition, operator.value));
42
52
  function initLocalState() {
43
- const value = internals.filters.getFilterState({ key: props.definition.key })?.value;
53
+ const value = internals.filters.getFilterState({
54
+ key: props.definition.key
55
+ })?.value;
44
56
  localValue.value = value == null ? "" : String(value);
45
57
  }
46
58
  const session = useFilterTagSession({
47
- activationToken: toRef(props, "activationToken"),
48
59
  session: props.session,
49
60
  dynamic: props.dynamic,
61
+ embedded: props.embedded,
50
62
  hasCommittedState: () => internals.filters.getFilterState({ key: props.definition.key }) != null,
51
- onActivated: () => handleActivate(operator.value),
52
63
  onOpen: initLocalState,
53
64
  onClose: () => {
54
65
  pendingOperator.value = void 0;
@@ -58,7 +69,15 @@ const session = useFilterTagSession({
58
69
  });
59
70
  function handleActivate(op) {
60
71
  pendingOperator.value = op;
61
- session.openWithLock();
72
+ stage.value = "editor";
73
+ stageDirection.value = "backward";
74
+ session.open();
75
+ }
76
+ function handleRequestMatchMode() {
77
+ stageDirection.value = "forward";
78
+ stageTransitioning.value = true;
79
+ stage.value = "match-mode";
80
+ session.open();
62
81
  }
63
82
  function applyFilter() {
64
83
  const op = pendingOperator.value;
@@ -75,12 +94,11 @@ function clearFilter() {
75
94
  session.close();
76
95
  }
77
96
  function handleOperatorChange(op) {
78
- if (filterUi.value.clearOnOperatorChange) {
79
- internals.filters.clearFilter({ key: props.definition.key });
80
- }
81
97
  localValue.value = "";
82
- if (filterUi.value.reopenOnOperatorChange) handleActivate(op);
83
- else pendingOperator.value = op;
98
+ pendingOperator.value = op;
99
+ stageDirection.value = "forward";
100
+ stageTransitioning.value = true;
101
+ stage.value = "editor";
84
102
  }
85
103
  function handleValueUpdate(value) {
86
104
  localValue.value = value == null ? "" : String(value);
@@ -95,13 +113,14 @@ function handleValueUpdate(value) {
95
113
  </script>
96
114
 
97
115
  <template>
98
- <UPopover
116
+ <FilterPopoverShell
99
117
  :open="session.isOpen.value"
100
- :content="{ side: 'bottom', align: 'start', sideOffset: 8 }"
101
- :ui="{
102
- content: 'w-fit overflow-hidden p-0 shadow-none'
103
- }"
104
- @update:open="session.handleOpenChange"
118
+ :embedded="embedded"
119
+ :transitioning="stageTransitioning"
120
+ :content-class="
121
+ mergeDataListUiClass('w-fit overflow-hidden p-0', void 0, dataListFilterUi?.popoverContent)
122
+ "
123
+ @update-open="session.handleOpenChange"
105
124
  >
106
125
  <slot
107
126
  name="trigger"
@@ -117,55 +136,99 @@ function handleValueUpdate(value) {
117
136
  <TableFilterTrigger
118
137
  :label="internals.filters.getFilterLabelText({ label: definition.label })"
119
138
  :leading-icon="resolveFilterTriggerIcon(definition)"
139
+ :operator="operator"
120
140
  :operator-label="operatorLabel"
121
141
  :operator-items="operatorItems"
122
142
  :preview-summary="preview.summary"
123
143
  :active="preview.active"
124
- @select-operator="handleOperatorChange"
125
144
  @activate="handleActivate"
145
+ @request-match-mode="handleRequestMatchMode"
126
146
  @clear="clearFilter"
127
147
  />
128
148
  </slot>
129
149
 
130
150
  <template #content>
131
- <div class="w-fit max-w-[calc(100vw-1rem)] bg-default">
132
- <div class="border-b border-default p-2">
133
- <UInput
134
- :model-value="localValue"
135
- :type="filterUi.inputType"
136
- :icon="filterUi.leadingIcon"
137
- :placeholder="filterUi.placeholder"
138
- :autocomplete="filterUi.autocomplete"
139
- :autofocus="filterUi.input.autofocus"
140
- :highlight="filterUi.input.highlight"
141
- :fixed="filterUi.input.fixed"
142
- class="w-[min(13rem,calc(100vw-3rem))] max-w-full"
143
- :ui="{ base: 'rounded-md' }"
144
- @update:model-value="handleValueUpdate"
145
- @keydown.enter.prevent="applyFilter"
146
- />
147
- </div>
148
-
151
+ <FilterStageTransition
152
+ :stage-key="stage"
153
+ :direction="stageDirection"
154
+ @settled="stageTransitioning = false"
155
+ >
156
+ <FilterMatchModePanel
157
+ v-if="stage === 'match-mode'"
158
+ :items="operatorItems"
159
+ :selected="operator"
160
+ :size="size"
161
+ :ui="dataListFilterUi"
162
+ @select="handleOperatorChange"
163
+ />
149
164
  <div
150
- v-if="filterUi.commitMode === 'manual'"
151
- class="flex items-center justify-between border-t border-default p-2"
165
+ v-else
166
+ :class="
167
+ mergeDataListUiClass(
168
+ 'w-fit max-w-[calc(100vw-1rem)] bg-default',
169
+ void 0,
170
+ dataListFilterUi?.editor
171
+ )
172
+ "
152
173
  >
153
- <UButton
154
- color="neutral"
155
- variant="ghost"
156
- size="sm"
157
- :label="filterUi.actions.clear"
158
- @click="clearFilter"
159
- />
160
- <UButton
161
- color="neutral"
162
- variant="subtle"
163
- size="sm"
164
- :label="filterUi.actions.apply"
165
- @click="applyFilter"
166
- />
174
+ <div
175
+ :class="
176
+ mergeDataListUiClass(
177
+ 'border-b border-default p-2',
178
+ void 0,
179
+ dataListFilterUi?.inputs
180
+ )
181
+ "
182
+ >
183
+ <UInput
184
+ :model-value="localValue"
185
+ :type="filterUi.inputType"
186
+ :icon="filterUi.leadingIcon"
187
+ :placeholder="filterUi.placeholder"
188
+ :autocomplete="filterUi.autocomplete"
189
+ :autofocus="filterUi.input.autofocus"
190
+ :highlight="filterUi.input.highlight"
191
+ :fixed="filterUi.input.fixed"
192
+ :size="size"
193
+ class="w-[min(13rem,calc(100vw-3rem))] max-w-full"
194
+ :ui="{
195
+ root: dataListFilterUi?.search,
196
+ base: dataListFilterUi?.searchInput
197
+ }"
198
+ @update:model-value="handleValueUpdate"
199
+ @keydown.enter.prevent="applyFilter"
200
+ />
201
+ </div>
202
+
203
+ <div
204
+ v-if="filterUi.commitMode === 'manual'"
205
+ :class="
206
+ mergeDataListUiClass(
207
+ 'flex items-center justify-between border-t border-default p-2',
208
+ void 0,
209
+ dataListFilterUi?.footer
210
+ )
211
+ "
212
+ >
213
+ <UButton
214
+ color="neutral"
215
+ variant="ghost"
216
+ :size="size"
217
+ :label="filterUi.actions.clear"
218
+ :ui="{ base: dataListFilterUi?.clear }"
219
+ @click="clearFilter"
220
+ />
221
+ <UButton
222
+ color="neutral"
223
+ variant="subtle"
224
+ :size="size"
225
+ :label="filterUi.actions.apply"
226
+ :ui="{ base: dataListFilterUi?.apply }"
227
+ @click="applyFilter"
228
+ />
229
+ </div>
167
230
  </div>
168
- </div>
231
+ </FilterStageTransition>
169
232
  </template>
170
- </UPopover>
233
+ </FilterPopoverShell>
171
234
  </template>
@@ -1,9 +1,10 @@
1
- import type { TableTextFilterDefinition } from '../../../types/index.js';
1
+ import type { TableFilterOperator, TableTextFilterDefinition } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  definition: TableTextFilterDefinition;
4
4
  dynamic?: boolean;
5
5
  session?: boolean;
6
- activationToken?: number;
6
+ embedded?: boolean;
7
+ initialOperator?: TableFilterOperator;
7
8
  };
8
9
  declare var __VLS_10: {
9
10
  preview: import("../../../utils/index.js").FilterPreviewResult;
@@ -162,7 +162,7 @@ function unwrapElement(value) {
162
162
  </div>
163
163
  </div>
164
164
 
165
- <div v-else :class="mergeDataListUiClass('px-0 py-1', void 0, ui?.flow)">
165
+ <div v-else :class="mergeDataListUiClass(void 0, void 0, ui?.flowRoot)">
166
166
  <div
167
167
  v-if="showInitialLoading"
168
168
  :class="mergeDataListUiClass('grid gap-4', void 0, ui?.loading)"
@@ -80,6 +80,7 @@ function formatCount(value) {
80
80
  <span>{{ t("table.footer.rowsPerPage") }}</span>
81
81
 
82
82
  <UDropdownMenu
83
+ :size="controlSize"
83
84
  :items="pageSizeItems"
84
85
  :content="{ align: 'end', side: 'top', sideOffset: 10 }"
85
86
  >
@@ -42,7 +42,7 @@ watch(tableEmpty, (isEmpty) => {
42
42
 
43
43
  <template>
44
44
  <div
45
- :class="mergeDataListUiClass('relative overflow-hidden', void 0, ui?.root)"
45
+ :class="mergeDataListUiClass('relative overflow-hidden', void 0, ui?.wrapper)"
46
46
  :style="height ? { height } : void 0"
47
47
  >
48
48
  <UTable
@@ -79,18 +79,31 @@ watch(tableEmpty, (isEmpty) => {
79
79
  loading-animation="carousel"
80
80
  :class="height ? 'h-full' : void 0"
81
81
  :ui="{
82
- root: ui?.base,
82
+ root: ui?.root,
83
+ base: ui?.base,
83
84
  caption: ui?.caption,
84
85
  thead: mergeDataListUiClass(
85
86
  'group/table-head after:inset-x-0 after:bottom-0 after:w-full after:z-[2] after:pointer-events-none',
86
87
  void 0,
87
88
  ui?.thead
88
89
  ),
89
- tbody: ui?.tbody,
90
+ tbody: mergeDataListUiClass(
91
+ 'border-b border-default [&>tr]:hover:bg-elevated/50',
92
+ void 0,
93
+ ui?.tbody
94
+ ),
90
95
  tfoot: ui?.tfoot,
91
- tr: mergeDataListUiClass('transition-colors', void 0, ui?.tr),
96
+ tr: mergeDataListUiClass(
97
+ 'border-b border-default transition-colors last:border-b',
98
+ void 0,
99
+ ui?.tr
100
+ ),
92
101
  th: ui?.th,
93
- td: ui?.td,
102
+ td: mergeDataListUiClass(
103
+ '[&[data-pinned=left]]:bg-inherit [&[data-pinned=right]]:bg-inherit',
104
+ void 0,
105
+ ui?.td
106
+ ),
94
107
  separator: ui?.separator,
95
108
  empty: ui?.empty,
96
109
  loading: ui?.loading
@@ -142,7 +155,3 @@ watch(tableEmpty, (isEmpty) => {
142
155
  </div>
143
156
  </div>
144
157
  </template>
145
-
146
- <style scoped>
147
- :deep([data-slot=root]){scrollbar-color:color-mix(in oklab,var(--ui-border) 82%,transparent) transparent;scrollbar-width:thin}:deep([data-slot=root]:hover){scrollbar-color:color-mix(in oklab,var(--ui-border-accented) 92%,transparent) transparent}:deep([data-slot=root]::-webkit-scrollbar){height:10px;width:10px}:deep([data-slot=root]::-webkit-scrollbar-track){background:transparent}:deep([data-slot=root]::-webkit-scrollbar-thumb){background:color-mix(in oklab,var(--ui-border) 86%,transparent);background-clip:padding-box;border:2px solid transparent;border-radius:999px}:deep([data-slot=root]:hover::-webkit-scrollbar-thumb){background:color-mix(in oklab,var(--ui-border-accented) 80%,transparent);background-clip:padding-box}:deep([data-slot=root]::-webkit-scrollbar-thumb:hover){background:color-mix(in oklab,var(--ui-border-accented) 95%,transparent);background-clip:padding-box}:deep([data-slot=root]::-webkit-scrollbar-corner){background:transparent}:deep(th[data-pinned]){backdrop-filter:blur(6px) saturate(120%);background-color:color-mix(in oklab,var(--ui-bg) 94%,transparent)!important;background-image:none!important}:deep(td[data-pinned]){backdrop-filter:none;background-color:color-mix(in oklab,var(--ui-bg) 96%,transparent)!important;background-image:none!important}:deep(tbody tr[data-selected=true] td){background-color:color-mix(in oklab,var(--ui-bg-elevated) 88%,transparent)!important;color:var(--ui-text)!important}:deep(tbody tr:hover td){background-color:color-mix(in oklab,var(--ui-bg-elevated) 18%,transparent)!important}:deep(tr[data-selected=true] td[data-pinned]){backdrop-filter:none;background-color:color-mix(in oklab,var(--ui-bg-elevated) 96%,transparent)!important;color:var(--ui-text)!important}:deep(tbody tr:hover td[data-pinned]){backdrop-filter:none;background-color:color-mix(in oklab,var(--ui-bg-elevated) 68%,transparent)!important}:deep(td[data-pinned=left]),:deep(th[data-pinned=left]){box-shadow:12px 0 18px -18px color-mix(in oklab,var(--ui-border-accented) 80%,transparent)}:deep(td[data-pinned=right]),:deep(th[data-pinned=right]){box-shadow:-12px 0 18px -18px color-mix(in oklab,var(--ui-border-accented) 80%,transparent)}:deep(thead th){border-bottom-color:var(--ui-border)!important}:deep(thead tr[data-slot=separator]){background-color:var(--ui-border)!important;border-color:var(--ui-border)!important}:deep(tbody td){border-bottom-color:color-mix(in oklab,var(--ui-border) 34%,transparent)!important}
148
- </style>
@@ -1,11 +1,10 @@
1
1
  import { type Ref } from 'vue';
2
2
  export interface UseFilterTagSessionParams {
3
3
  isOpen?: Ref<boolean>;
4
- activationToken?: Ref<number | undefined>;
5
4
  session?: boolean;
6
5
  dynamic?: boolean;
6
+ embedded?: boolean;
7
7
  hasCommittedState: () => boolean;
8
- onActivated: () => void;
9
8
  onOpen: () => void;
10
9
  onClose: () => void;
11
10
  onSessionClosed: () => void;
@@ -13,7 +12,7 @@ export interface UseFilterTagSessionParams {
13
12
  }
14
13
  export declare function useFilterTagSession(options: UseFilterTagSessionParams): {
15
14
  isOpen: Ref<boolean, boolean>;
16
- openWithLock: () => void;
17
- handleOpenChange: (open: boolean) => void;
15
+ open: () => void;
16
+ handleOpenChange: (nextOpen: boolean) => void;
18
17
  close: () => void;
19
18
  };