nuxt-ui-tools 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) 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.d.vue.ts +2 -2
  19. package/dist/runtime/form/components/root/Form.vue +5 -3
  20. package/dist/runtime/form/components/root/Form.vue.d.ts +2 -2
  21. package/dist/runtime/form/composables/use-field-control.d.ts +1 -1
  22. package/dist/runtime/form/composables/use-field-control.js +4 -0
  23. package/dist/runtime/form/composables/use-field-options.d.ts +1 -1
  24. package/dist/runtime/form/composables/use-field-options.js +75 -31
  25. package/dist/runtime/form/composables/use-form-field-chrome.d.ts +3 -0
  26. package/dist/runtime/form/composables/use-form-field-chrome.js +9 -0
  27. package/dist/runtime/form/composables/use-form-runtime.js +17 -5
  28. package/dist/runtime/form/fields/array-list/component.vue +4 -1
  29. package/dist/runtime/form/fields/auto-complete/component.vue +23 -16
  30. package/dist/runtime/form/fields/checkbox-card/component.vue +28 -29
  31. package/dist/runtime/form/fields/checkbox-group/component.vue +28 -29
  32. package/dist/runtime/form/fields/color-picker/component.vue +4 -2
  33. package/dist/runtime/form/fields/date-family/component.vue +9 -4
  34. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.d.vue.ts +13 -0
  35. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.vue +24 -0
  36. package/dist/runtime/form/fields/hierarchy/SelectionCheckbox.vue.d.ts +13 -0
  37. package/dist/runtime/form/fields/hierarchy/SelectionRadio.d.vue.ts +14 -0
  38. package/dist/runtime/form/fields/hierarchy/SelectionRadio.vue +27 -0
  39. package/dist/runtime/form/fields/hierarchy/SelectionRadio.vue.d.ts +14 -0
  40. package/dist/runtime/form/fields/hierarchy/component.vue +257 -142
  41. package/dist/runtime/form/fields/hierarchy/utils.d.ts +9 -0
  42. package/dist/runtime/form/fields/hierarchy/utils.js +32 -0
  43. package/dist/runtime/form/fields/input-group/component.vue +7 -30
  44. package/dist/runtime/form/fields/matrix/component.vue +9 -3
  45. package/dist/runtime/form/fields/phone-number/component.vue +7 -2
  46. package/dist/runtime/form/fields/rating/component.vue +25 -2
  47. package/dist/runtime/form/fields/select/component.vue +29 -21
  48. package/dist/runtime/form/fields/switch-group/component.vue +8 -3
  49. package/dist/runtime/form/fields/time/component.vue +7 -5
  50. package/dist/runtime/form/fields/upload/component.vue +5 -3
  51. package/dist/runtime/form/types/api.d.ts +9 -3
  52. package/dist/runtime/form/types/field-base.d.ts +3 -1
  53. package/dist/runtime/form/types/runtime.d.ts +2 -0
  54. package/dist/runtime/form/types/ui.d.ts +1 -0
  55. package/dist/runtime/form/utils/api.js +3 -0
  56. package/dist/runtime/form/utils/options.d.ts +11 -2
  57. package/dist/runtime/form/utils/options.js +57 -9
  58. package/dist/runtime/form/utils/state.js +10 -2
  59. package/dist/runtime/i18n/locales/en.js +38 -0
  60. package/dist/runtime/i18n/locales/fr.js +38 -0
  61. package/dist/runtime/i18n/types.d.ts +38 -0
  62. package/dist/runtime/i18n/use-locale.d.ts +2 -2
  63. package/dist/runtime/i18n/use-locale.js +3 -3
  64. package/dist/runtime/spreadsheet/components/layout/SpreadsheetImportFooter.d.vue.ts +2 -2
  65. package/dist/runtime/spreadsheet/components/layout/SpreadsheetImportFooter.vue.d.ts +2 -2
  66. package/dist/runtime/spreadsheet/components/steps/review/SpreadsheetReviewInspection.d.vue.ts +2 -2
  67. package/dist/runtime/spreadsheet/components/steps/review/SpreadsheetReviewInspection.vue.d.ts +2 -2
  68. package/dist/runtime/spreadsheet/composables/use-spreadsheet-internals.d.ts +15 -15
  69. package/dist/runtime/spreadsheet/composables/use-spreadsheet-resolutions.d.ts +2 -2
  70. package/dist/runtime/spreadsheet/schema/normalize.d.ts +1 -1
  71. package/dist/runtime/spreadsheet/utils/references/sources.d.ts +1 -1
  72. package/dist/runtime/table/components/DataList.d.vue.ts +2 -0
  73. package/dist/runtime/table/components/DataList.vue.d.ts +2 -0
  74. package/dist/runtime/table/components/actions/RowActions.d.vue.ts +4 -2
  75. package/dist/runtime/table/components/actions/RowActions.vue +2 -0
  76. package/dist/runtime/table/components/actions/RowActions.vue.d.ts +4 -2
  77. package/dist/runtime/table/components/data-list/DataListAddFilter.d.vue.ts +5 -3
  78. package/dist/runtime/table/components/data-list/DataListAddFilter.vue +6 -1
  79. package/dist/runtime/table/components/data-list/DataListAddFilter.vue.d.ts +5 -3
  80. package/dist/runtime/table/components/data-list/DataListContent.d.vue.ts +24 -17
  81. package/dist/runtime/table/components/data-list/DataListContent.vue +70 -17
  82. package/dist/runtime/table/components/data-list/DataListContent.vue.d.ts +24 -17
  83. package/dist/runtime/table/components/data-list/DataListDefault.d.vue.ts +2 -0
  84. package/dist/runtime/table/components/data-list/DataListDefault.vue.d.ts +2 -0
  85. package/dist/runtime/table/components/data-list/DataListFilterTags.d.vue.ts +2 -0
  86. package/dist/runtime/table/components/data-list/DataListFilterTags.vue.d.ts +2 -0
  87. package/dist/runtime/table/components/data-list/DataListInfiniteLoader.d.vue.ts +1 -1
  88. package/dist/runtime/table/components/data-list/DataListInfiniteLoader.vue.d.ts +1 -1
  89. package/dist/runtime/table/components/data-list/DataListLayoutSwitch.vue +17 -11
  90. package/dist/runtime/table/components/data-list/DataListPagination.d.vue.ts +1 -1
  91. package/dist/runtime/table/components/data-list/DataListPagination.vue.d.ts +1 -1
  92. package/dist/runtime/table/components/data-list/DataListRoot.vue +2 -46
  93. package/dist/runtime/table/components/data-list/DataListSortMenu.d.vue.ts +1 -1
  94. package/dist/runtime/table/components/data-list/DataListSortMenu.vue +6 -0
  95. package/dist/runtime/table/components/data-list/DataListSortMenu.vue.d.ts +1 -1
  96. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.d.vue.ts +5 -0
  97. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.vue +182 -59
  98. package/dist/runtime/table/components/filters/shared/DynamicFilterPicker.vue.d.ts +5 -0
  99. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.d.vue.ts +3 -1
  100. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.vue +29 -5
  101. package/dist/runtime/table/components/filters/shared/FilterMatchModeButton.vue.d.ts +3 -1
  102. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.d.vue.ts +17 -0
  103. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.vue +47 -0
  104. package/dist/runtime/table/components/filters/shared/FilterMatchModePanel.vue.d.ts +17 -0
  105. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.d.vue.ts +3 -1
  106. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.vue +12 -3
  107. package/dist/runtime/table/components/filters/shared/FilterOptionMultipleList.vue.d.ts +3 -1
  108. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.d.vue.ts +3 -0
  109. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.vue +11 -1
  110. package/dist/runtime/table/components/filters/shared/FilterOptionPickerContent.vue.d.ts +3 -0
  111. package/dist/runtime/table/components/filters/shared/FilterOptionRow.d.vue.ts +3 -0
  112. package/dist/runtime/table/components/filters/shared/FilterOptionRow.vue +48 -9
  113. package/dist/runtime/table/components/filters/shared/FilterOptionRow.vue.d.ts +3 -0
  114. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.d.vue.ts +3 -0
  115. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.vue +35 -9
  116. package/dist/runtime/table/components/filters/shared/FilterOptionSingleList.vue.d.ts +3 -0
  117. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.d.vue.ts +3 -0
  118. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.vue +77 -20
  119. package/dist/runtime/table/components/filters/shared/FilterOptionTreeContent.vue.d.ts +3 -0
  120. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.d.vue.ts +27 -0
  121. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.vue +36 -0
  122. package/dist/runtime/table/components/filters/shared/FilterPopoverShell.vue.d.ts +27 -0
  123. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.d.vue.ts +3 -0
  124. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.vue +40 -10
  125. package/dist/runtime/table/components/filters/shared/FilterSearchablePanel.vue.d.ts +3 -0
  126. package/dist/runtime/table/components/filters/shared/FilterStageTransition.d.vue.ts +23 -0
  127. package/dist/runtime/table/components/filters/shared/FilterStageTransition.vue +21 -0
  128. package/dist/runtime/table/components/filters/shared/FilterStageTransition.vue.d.ts +23 -0
  129. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.d.vue.ts +3 -2
  130. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.vue +26 -25
  131. package/dist/runtime/table/components/filters/shared/FilterTriggerTag.vue.d.ts +3 -2
  132. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.d.vue.ts +1 -1
  133. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.vue +75 -22
  134. package/dist/runtime/table/components/filters/tags/BooleanFilterTag.vue.d.ts +1 -1
  135. package/dist/runtime/table/components/filters/tags/DateFilterTag.d.vue.ts +3 -1
  136. package/dist/runtime/table/components/filters/tags/DateFilterTag.vue +254 -160
  137. package/dist/runtime/table/components/filters/tags/DateFilterTag.vue.d.ts +3 -1
  138. package/dist/runtime/table/components/filters/tags/FilterTagsBar.d.vue.ts +7 -6
  139. package/dist/runtime/table/components/filters/tags/FilterTagsBar.vue +12 -27
  140. package/dist/runtime/table/components/filters/tags/FilterTagsBar.vue.d.ts +7 -6
  141. package/dist/runtime/table/components/filters/tags/NumberFilterTag.d.vue.ts +3 -2
  142. package/dist/runtime/table/components/filters/tags/NumberFilterTag.vue +192 -106
  143. package/dist/runtime/table/components/filters/tags/NumberFilterTag.vue.d.ts +3 -2
  144. package/dist/runtime/table/components/filters/tags/OptionFilterTag.d.vue.ts +3 -2
  145. package/dist/runtime/table/components/filters/tags/OptionFilterTag.vue +110 -48
  146. package/dist/runtime/table/components/filters/tags/OptionFilterTag.vue.d.ts +3 -2
  147. package/dist/runtime/table/components/filters/tags/TextFilterTag.d.vue.ts +3 -2
  148. package/dist/runtime/table/components/filters/tags/TextFilterTag.vue +120 -57
  149. package/dist/runtime/table/components/filters/tags/TextFilterTag.vue.d.ts +3 -2
  150. package/dist/runtime/table/components/grid/GridRenderer.vue +1 -1
  151. package/dist/runtime/table/components/layout/TableFooter.d.vue.ts +1 -1
  152. package/dist/runtime/table/components/layout/TableFooter.vue +1 -0
  153. package/dist/runtime/table/components/layout/TableFooter.vue.d.ts +1 -1
  154. package/dist/runtime/table/components/table/TableCellEllipsis.d.ts +1 -1
  155. package/dist/runtime/table/components/table/TableRenderer.vue +24 -12
  156. package/dist/runtime/table/composables/use-filter-tag-session.d.ts +3 -4
  157. package/dist/runtime/table/composables/use-filter-tag-session.js +12 -32
  158. package/dist/runtime/table/composables/use-query-state.d.ts +5 -5
  159. package/dist/runtime/table/composables/use-query-state.js +7 -32
  160. package/dist/runtime/table/composables/use-table-api.js +2 -2
  161. package/dist/runtime/table/composables/use-table-columns.d.ts +4 -14
  162. package/dist/runtime/table/composables/use-table-filter-presentation.d.ts +0 -3
  163. package/dist/runtime/table/composables/use-table-filter-presentation.js +0 -9
  164. package/dist/runtime/table/composables/use-table-filters.js +18 -7
  165. package/dist/runtime/table/composables/use-table-internals.d.ts +24 -63
  166. package/dist/runtime/table/composables/use-table-pagination.d.ts +2 -2
  167. package/dist/runtime/table/composables/use-table-state.d.ts +2 -2
  168. package/dist/runtime/table/types/actions.d.ts +1 -1
  169. package/dist/runtime/table/types/data-list.d.ts +41 -8
  170. package/dist/runtime/table/types/filters.d.ts +4 -0
  171. package/dist/runtime/table/utils/actions.d.ts +1 -1
  172. package/dist/runtime/table/utils/columns/menu.d.ts +2 -11
  173. package/dist/runtime/table/utils/columns/render.d.ts +2 -9
  174. package/dist/runtime/table/utils/columns/render.js +39 -30
  175. package/dist/runtime/table/utils/columns/state.d.ts +1 -1
  176. package/dist/runtime/table/utils/data-list-ui.d.ts +3 -1
  177. package/dist/runtime/table/utils/data-list-ui.js +45 -0
  178. package/dist/runtime/table/utils/filters/editor-size.d.ts +11 -0
  179. package/dist/runtime/table/utils/filters/editor-size.js +45 -0
  180. package/dist/runtime/table/utils/filters/index.d.ts +1 -1
  181. package/dist/runtime/table/utils/filters/index.js +1 -1
  182. package/dist/runtime/table/utils/query-state.d.ts +18 -1
  183. package/dist/runtime/table/utils/query-state.js +109 -0
  184. package/package.json +4 -2
  185. package/dist/runtime/table/utils/filters/operators.d.ts +0 -4
  186. package/dist/runtime/table/utils/filters/operators.js +0 -6
@@ -2,22 +2,50 @@
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
3
  import UIcon from "@nuxt/ui/components/Icon.vue";
4
4
  import UPopover from "@nuxt/ui/components/Popover.vue";
5
- import { computed, ref } from "vue";
5
+ import { computed, nextTick, ref } from "vue";
6
6
  import { useUiToolsLocale } from "#ui-tools/i18n";
7
7
  import { useDataListUi } from "../../../composables/use-data-list-ui";
8
- import { mergeDataListUiClass, resolveFilterTriggerIcon } from "../../../utils";
8
+ import { useTableInternals } from "../../../composables/use-table-internals";
9
+ import {
10
+ mergeDataListUiClass,
11
+ resolveFilterEditorSizeClasses,
12
+ resolveFilterTriggerIcon
13
+ } from "../../../utils";
14
+ import { resolveFilterTagComponent } from "../tags/registry";
15
+ import FilterMatchModePanel from "./FilterMatchModePanel.vue";
9
16
  import FilterSearchablePanel from "./FilterSearchablePanel.vue";
17
+ import FilterStageTransition from "./FilterStageTransition.vue";
10
18
  const props = defineProps({
11
19
  definitions: { type: Array, required: true },
20
+ sessionDefinition: { type: null, required: false },
12
21
  getLabel: { type: Function, required: true },
13
22
  size: { type: String, required: false },
14
23
  ui: { type: Object, required: false }
15
24
  });
16
- const emit = defineEmits(["select"]);
25
+ const emit = defineEmits(["select", "release"]);
17
26
  const { t } = useUiToolsLocale();
27
+ const internals = useTableInternals();
18
28
  const dataListUi = useDataListUi();
19
29
  const isOpen = ref(false);
20
30
  const searchQuery = ref("");
31
+ const selectedKey = ref(null);
32
+ const pendingOperator = ref();
33
+ const stage = ref("picker");
34
+ const stageDirection = ref("forward");
35
+ const stageTransitioning = ref(false);
36
+ let releaseAfterCommit = false;
37
+ const size = computed(
38
+ () => props.size ?? dataListUi.ui.value.filterTags?.size ?? dataListUi.controlSize.value
39
+ );
40
+ const sizeClasses = computed(() => resolveFilterEditorSizeClasses(size.value));
41
+ const selectedDefinition = computed(() => {
42
+ if (selectedKey.value == null) return void 0;
43
+ if (props.sessionDefinition?.key === selectedKey.value) return props.sessionDefinition;
44
+ return props.definitions.find((definition) => definition.key === selectedKey.value);
45
+ });
46
+ const operatorItems = computed(
47
+ () => selectedKey.value == null ? [] : internals.filters.getFilterOperatorOptions({ key: selectedKey.value })
48
+ );
21
49
  const filteredDefinitions = computed(() => {
22
50
  const search = searchQuery.value.trim().toLowerCase();
23
51
  if (!search) return props.definitions;
@@ -25,19 +53,65 @@ const filteredDefinitions = computed(() => {
25
53
  (definition) => props.getLabel(definition).toLowerCase().includes(search)
26
54
  );
27
55
  });
28
- function handleSelect(key) {
56
+ async function handleSelect(key) {
57
+ selectedKey.value = key;
58
+ searchQuery.value = "";
59
+ const items = internals.filters.getFilterOperatorOptions({ key });
60
+ if (items.length > 1) {
61
+ pendingOperator.value = internals.filters.getFilterOperator({ key });
62
+ stageDirection.value = "forward";
63
+ stageTransitioning.value = true;
64
+ stage.value = "match-mode";
65
+ return;
66
+ }
67
+ const defaultOperator = items[0]?.value;
68
+ if (!defaultOperator) return;
69
+ await openEditor(defaultOperator);
70
+ }
71
+ async function openEditor(operator) {
72
+ const key = selectedKey.value;
73
+ if (!key) return;
74
+ pendingOperator.value = operator;
29
75
  emit("select", key);
76
+ await nextTick();
77
+ stageDirection.value = "forward";
78
+ stageTransitioning.value = true;
79
+ stage.value = "editor";
80
+ }
81
+ function handleFocusOutside(event) {
82
+ if (stageTransitioning.value) event.preventDefault();
83
+ }
84
+ function handleOpenChange(nextOpen) {
85
+ isOpen.value = nextOpen;
86
+ if (!nextOpen && !releaseAfterCommit) releaseSession();
87
+ }
88
+ function handleSessionClosed() {
30
89
  isOpen.value = false;
90
+ releaseAfterCommit = true;
91
+ queueMicrotask(() => {
92
+ releaseSession();
93
+ releaseAfterCommit = false;
94
+ });
95
+ }
96
+ function releaseSession() {
97
+ const key = selectedKey.value;
98
+ selectedKey.value = null;
99
+ pendingOperator.value = void 0;
31
100
  searchQuery.value = "";
101
+ stage.value = "picker";
102
+ stageDirection.value = "backward";
103
+ if (key) emit("release", key);
32
104
  }
33
105
  function open() {
34
106
  isOpen.value = true;
35
107
  }
36
108
  function close() {
37
109
  isOpen.value = false;
110
+ releaseSession();
38
111
  }
39
112
  function toggle() {
40
- isOpen.value = !isOpen.value;
113
+ if (isOpen.value) close();
114
+ else open();
41
115
  }
42
116
  </script>
43
117
 
@@ -45,89 +119,138 @@ function toggle() {
45
119
  <UPopover
46
120
  :open="isOpen"
47
121
  mode="click"
48
- :content="{ side: 'bottom', align: 'start', sideOffset: 8 }"
122
+ :content="{
123
+ side: 'bottom',
124
+ align: 'start',
125
+ sideOffset: 8,
126
+ onFocusOutside: handleFocusOutside
127
+ }"
49
128
  :ui="{
50
129
  content: mergeDataListUiClass(
51
- 'w-fit max-w-[calc(100vw-1rem)] overflow-hidden p-0 shadow-none',
130
+ 'w-fit max-w-[calc(100vw-1rem)] overflow-hidden p-0',
52
131
  void 0,
53
132
  ui?.popoverContent
54
133
  )
55
134
  }"
56
- @update:open="isOpen = $event"
135
+ @update:open="handleOpenChange"
57
136
  >
58
137
  <slot
138
+ v-if="$slots.trigger"
59
139
  name="trigger"
60
140
  :open="open"
61
141
  :close="close"
62
142
  :toggle="toggle"
63
143
  :open-state="isOpen"
64
- :trigger-props="{ type: 'button', 'aria-expanded': isOpen }"
65
- >
66
- <UButton
67
- color="neutral"
68
- variant="outline"
69
- :size="props.size ?? dataListUi.ui.value.filterTags?.size ?? dataListUi.controlSize.value"
70
- icon="i-lucide-plus"
71
- :label="t('table.controls.addFilter')"
72
- :ui="{
73
- base: mergeDataListUiClass('shrink-0 border-dashed', void 0, ui?.trigger)
144
+ :stage="stage"
145
+ :definition="selectedDefinition"
146
+ :trigger-props="{
147
+ type: 'button',
148
+ 'aria-expanded': isOpen
149
+ }"
150
+ />
151
+ <UButton
152
+ v-else
153
+ color="neutral"
154
+ variant="outline"
155
+ :size="size"
156
+ :icon="selectedDefinition ? resolveFilterTriggerIcon(selectedDefinition) : 'i-lucide-plus'"
157
+ :label="selectedDefinition ? getLabel(selectedDefinition) : t('table.controls.addFilter')"
158
+ :ui="{
159
+ base: mergeDataListUiClass(
160
+ `shrink-0 ${selectedDefinition ? '' : 'border-dashed'}`,
161
+ void 0,
162
+ ui?.trigger
163
+ )
74
164
  }"
75
- />
76
- </slot>
165
+ />
77
166
 
78
167
  <template #content>
79
- <div
80
- :class="
168
+ <FilterStageTransition
169
+ :stage-key="`${stage}:${selectedKey ?? ''}:${pendingOperator ?? ''}`"
170
+ :direction="stageDirection"
171
+ @settled="stageTransitioning = false"
172
+ >
173
+ <div
174
+ v-if="stage === 'picker'"
175
+ :class="mergeDataListUiClass(sizeClasses.editor, void 0, ui?.panel)"
176
+ >
177
+ <FilterSearchablePanel
178
+ v-model:search-query="searchQuery"
179
+ searchable
180
+ autofocus
181
+ :search-placeholder="t('table.controls.searchFilters')"
182
+ :show-empty="!filteredDefinitions.length"
183
+ :empty-label="t('table.controls.noMatchingFilters')"
184
+ max-height-class="max-h-72"
185
+ :size="size"
186
+ :ui="ui"
187
+ >
188
+ <button
189
+ v-for="definition in filteredDefinitions"
190
+ :key="definition.key"
191
+ type="button"
192
+ :class="
81
193
  mergeDataListUiClass(
82
- 'w-fit min-w-[18rem] max-w-[min(24rem,calc(100vw-1rem))]',
194
+ `flex min-w-0 items-center rounded-md text-left transition-colors hover:bg-elevated/70 ${sizeClasses.option}`,
83
195
  void 0,
84
- ui?.panel
196
+ ui?.option
85
197
  )
86
198
  "
87
- >
88
- <FilterSearchablePanel
89
- v-model:search-query="searchQuery"
90
- searchable
91
- autofocus
92
- :search-placeholder="t('table.controls.searchFilters')"
93
- :show-empty="!filteredDefinitions.length"
94
- :empty-label="t('table.controls.noMatchingFilters')"
95
- max-height-class="max-h-72"
96
- >
97
- <button
98
- v-for="definition in filteredDefinitions"
99
- :key="definition.key"
100
- type="button"
101
- :class="
199
+ @click="handleSelect(definition.key)"
200
+ >
201
+ <UIcon
202
+ :name="resolveFilterTriggerIcon(definition)"
203
+ :class="
102
204
  mergeDataListUiClass(
103
- 'flex min-w-0 items-center gap-3 rounded-md px-3 py-2 text-left transition-colors hover:bg-elevated/70',
205
+ `${sizeClasses.optionIcon} shrink-0 text-muted`,
104
206
  void 0,
105
- ui?.option
207
+ ui?.optionIcon
106
208
  )
107
209
  "
108
- @click="handleSelect(definition.key)"
109
- >
110
- <UIcon
111
- :name="resolveFilterTriggerIcon(definition)"
112
- :class="mergeDataListUiClass('size-4 shrink-0 text-muted', void 0, ui?.optionIcon)"
113
- />
114
- <span
115
- :class="
210
+ />
211
+ <span
212
+ :class="
116
213
  mergeDataListUiClass(
117
- 'min-w-0 flex-1 truncate text-sm text-default',
214
+ `min-w-0 flex-1 truncate text-default ${sizeClasses.optionLabel}`,
118
215
  void 0,
119
216
  ui?.optionLabel
120
217
  )
121
218
  "
122
- >
123
- {{ getLabel(definition) }}
124
- </span>
125
- <span :class="mergeDataListUiClass('text-muted', void 0, ui?.optionTrailingIcon)">
126
- <UIcon name="i-lucide-arrow-right" class="size-4" />
127
- </span>
128
- </button>
129
- </FilterSearchablePanel>
130
- </div>
219
+ >
220
+ {{ getLabel(definition) }}
221
+ </span>
222
+ <span :class="mergeDataListUiClass('text-muted', void 0, ui?.optionTrailingIcon)">
223
+ <UIcon name="i-lucide-arrow-right" class="size-4" />
224
+ </span>
225
+ </button>
226
+ </FilterSearchablePanel>
227
+ </div>
228
+
229
+ <div
230
+ v-else-if="stage === 'match-mode'"
231
+ :class="mergeDataListUiClass(sizeClasses.editor, void 0, ui?.panel)"
232
+ >
233
+ <FilterMatchModePanel
234
+ :items="operatorItems"
235
+ :selected="pendingOperator"
236
+ :size="size"
237
+ :ui="ui"
238
+ @select="openEditor"
239
+ />
240
+ </div>
241
+
242
+ <component
243
+ :is="resolveFilterTagComponent(sessionDefinition)"
244
+ v-else-if="stage === 'editor' && sessionDefinition"
245
+ :definition="sessionDefinition"
246
+ dynamic
247
+ session
248
+ embedded
249
+ :initial-operator="pendingOperator"
250
+ @dismiss="handleSessionClosed"
251
+ @session-closed="handleSessionClosed"
252
+ />
253
+ </FilterStageTransition>
131
254
  </template>
132
255
  </UPopover>
133
256
  </template>
@@ -1,6 +1,7 @@
1
1
  import type { DataListAddFilterUi, DataListControlSize, TableUiFilterDefinition } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  definitions: TableUiFilterDefinition[];
4
+ sessionDefinition?: TableUiFilterDefinition;
4
5
  getLabel: (definition: TableUiFilterDefinition) => string;
5
6
  size?: DataListControlSize;
6
7
  ui?: DataListAddFilterUi;
@@ -13,6 +14,8 @@ declare var __VLS_10: {
13
14
  close: typeof close;
14
15
  toggle: typeof toggle;
15
16
  openState: boolean;
17
+ stage: "editor" | "match-mode" | "picker";
18
+ definition: TableUiFilterDefinition | undefined;
16
19
  triggerProps: {
17
20
  type: string;
18
21
  'aria-expanded': boolean;
@@ -23,8 +26,10 @@ type __VLS_Slots = {} & {
23
26
  };
24
27
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
25
28
  select: (key: string) => any;
29
+ release: (key: string) => any;
26
30
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
27
31
  onSelect?: ((key: string) => any) | undefined;
32
+ onRelease?: ((key: string) => any) | undefined;
28
33
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
34
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
30
35
  declare const _default: typeof __VLS_export;
@@ -1,4 +1,4 @@
1
- import type { TableFilterOperator } from '../../../types/index.js';
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableFilterOperator } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  label: string;
4
4
  items?: Array<{
@@ -6,6 +6,8 @@ type __VLS_Props = {
6
6
  value: TableFilterOperator;
7
7
  }>;
8
8
  variant?: 'default' | 'compact';
9
+ size?: DataListControlSize;
10
+ ui?: DataListFilterEditorUi;
9
11
  };
10
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
13
  select: (value: TableFilterOperator) => any;
@@ -1,16 +1,30 @@
1
1
  <script setup>
2
2
  import UButton from "@nuxt/ui/components/Button.vue";
3
3
  import UDropdownMenu from "@nuxt/ui/components/DropdownMenu.vue";
4
- defineProps({
4
+ import { computed } from "vue";
5
+ import { useDataListUi } from "../../../composables/use-data-list-ui";
6
+ import { mergeDataListUiClass } from "../../../utils";
7
+ const props = defineProps({
5
8
  label: { type: String, required: true },
6
9
  items: { type: Array, required: false, default: () => [] },
7
- variant: { type: String, required: false, default: "default" }
10
+ variant: { type: String, required: false, default: "default" },
11
+ size: { type: String, required: false },
12
+ ui: { type: Object, required: false }
8
13
  });
14
+ const dataListUi = useDataListUi();
15
+ const inheritedPart = computed(
16
+ () => props.variant === "compact" ? dataListUi.ui.value.filterPanel : dataListUi.ui.value.filterTags
17
+ );
18
+ const resolvedSize = computed(
19
+ () => props.size ?? inheritedPart.value?.size ?? dataListUi.controlSize.value
20
+ );
21
+ const resolvedUi = computed(() => ({ ...inheritedPart.value?.ui, ...props.ui }));
9
22
  const emit = defineEmits(["select"]);
10
23
  </script>
11
24
 
12
25
  <template>
13
26
  <UDropdownMenu
27
+ :size="resolvedSize"
14
28
  :items="[
15
29
  items.map((item) => ({
16
30
  label: item.label,
@@ -18,15 +32,25 @@ const emit = defineEmits(["select"]);
18
32
  }))
19
33
  ]"
20
34
  :content="{ side: 'bottom', align: 'end', sideOffset: 6 }"
21
- :ui="{ content: 'w-fit p-1 shadow-none' }"
35
+ :ui="{
36
+ content: mergeDataListUiClass('w-fit p-1', void 0, resolvedUi.operatorContent),
37
+ item: resolvedUi.operatorItem,
38
+ itemLabel: resolvedUi.operatorLabel
39
+ }"
22
40
  >
23
41
  <UButton
24
42
  color="neutral"
25
43
  :variant="variant === 'compact' ? 'ghost' : 'outline'"
26
- :size="variant === 'compact' ? 'sm' : 'md'"
44
+ :size="resolvedSize"
27
45
  :label="label"
28
46
  trailing-icon="i-lucide-chevron-down"
29
- :class="variant === 'compact' ? 'px-2.5' : void 0"
47
+ :ui="{
48
+ base: mergeDataListUiClass(
49
+ variant === 'compact' ? 'px-2.5' : void 0,
50
+ void 0,
51
+ resolvedUi.operatorTrigger
52
+ )
53
+ }"
30
54
  @pointerdown.stop
31
55
  @click.stop
32
56
  />
@@ -1,4 +1,4 @@
1
- import type { TableFilterOperator } from '../../../types/index.js';
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableFilterOperator } from '../../../types/index.js';
2
2
  type __VLS_Props = {
3
3
  label: string;
4
4
  items?: Array<{
@@ -6,6 +6,8 @@ type __VLS_Props = {
6
6
  value: TableFilterOperator;
7
7
  }>;
8
8
  variant?: 'default' | 'compact';
9
+ size?: DataListControlSize;
10
+ ui?: DataListFilterEditorUi;
9
11
  };
10
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
13
  select: (value: TableFilterOperator) => any;
@@ -0,0 +1,17 @@
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableFilterOperator } from '../../../types/index.js';
2
+ type __VLS_Props = {
3
+ items: Array<{
4
+ label: string;
5
+ value: TableFilterOperator;
6
+ }>;
7
+ selected?: TableFilterOperator;
8
+ size?: DataListControlSize;
9
+ ui?: DataListFilterEditorUi;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ select: (value: TableFilterOperator) => any;
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onSelect?: ((value: TableFilterOperator) => any) | undefined;
15
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,47 @@
1
+ <script setup>
2
+ import UIcon from "@nuxt/ui/components/Icon.vue";
3
+ import { mergeDataListUiClass, resolveFilterEditorSizeClasses } from "../../../utils";
4
+ const props = defineProps({
5
+ items: { type: Array, required: true },
6
+ selected: { type: String, required: false },
7
+ size: { type: String, required: false },
8
+ ui: { type: Object, required: false }
9
+ });
10
+ const emit = defineEmits(["select"]);
11
+ const sizeClasses = resolveFilterEditorSizeClasses(props.size);
12
+ </script>
13
+
14
+ <template>
15
+ <div :class="mergeDataListUiClass(sizeClasses.scrollArea, void 0, ui?.list)">
16
+ <button
17
+ v-for="item in items"
18
+ :key="item.value"
19
+ type="button"
20
+ :class="
21
+ mergeDataListUiClass(
22
+ `flex w-full items-center rounded-md text-left transition-colors hover:bg-elevated/70 ${sizeClasses.option}`,
23
+ void 0,
24
+ ui?.operatorItem
25
+ )
26
+ "
27
+ @click="emit('select', item.value)"
28
+ >
29
+ <span
30
+ :class="
31
+ mergeDataListUiClass(
32
+ `min-w-0 flex-1 truncate text-default ${sizeClasses.optionLabel}`,
33
+ void 0,
34
+ ui?.operatorLabel
35
+ )
36
+ "
37
+ >
38
+ {{ item.label }}
39
+ </span>
40
+ <UIcon
41
+ v-if="item.value === selected"
42
+ name="i-lucide-check"
43
+ :class="`${sizeClasses.optionIcon} shrink-0 text-muted`"
44
+ />
45
+ </button>
46
+ </div>
47
+ </template>
@@ -0,0 +1,17 @@
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableFilterOperator } from '../../../types/index.js';
2
+ type __VLS_Props = {
3
+ items: Array<{
4
+ label: string;
5
+ value: TableFilterOperator;
6
+ }>;
7
+ selected?: TableFilterOperator;
8
+ size?: DataListControlSize;
9
+ ui?: DataListFilterEditorUi;
10
+ };
11
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
12
+ select: (value: TableFilterOperator) => any;
13
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
14
+ onSelect?: ((value: TableFilterOperator) => any) | undefined;
15
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -1,4 +1,4 @@
1
- import type { TableResolvedFilterOptionEntry } from '../../../types/index.js';
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableResolvedFilterOptionEntry } from '../../../types/index.js';
2
2
  interface FilterOptionMultipleListSection {
3
3
  key: string;
4
4
  entries: Array<TableResolvedFilterOptionEntry & {
@@ -13,6 +13,8 @@ type __VLS_Props = {
13
13
  countLoading: boolean;
14
14
  selectedIcon?: string;
15
15
  truncate?: boolean;
16
+ size?: DataListControlSize;
17
+ ui?: DataListFilterEditorUi;
16
18
  };
17
19
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
18
20
  select: (options: {
@@ -1,21 +1,28 @@
1
1
  <script setup>
2
+ import { computed } from "vue";
3
+ import { useDataListUi } from "../../../composables/use-data-list-ui";
4
+ import { mergeDataListUiClass } from "../../../utils";
2
5
  import FilterOptionRow from "./FilterOptionRow.vue";
3
6
  const props = defineProps({
4
7
  sections: { type: Array, required: true },
5
8
  showCounts: { type: Boolean, required: true },
6
9
  countLoading: { type: Boolean, required: true },
7
10
  selectedIcon: { type: String, required: false },
8
- truncate: { type: Boolean, required: false }
11
+ truncate: { type: Boolean, required: false },
12
+ size: { type: String, required: false },
13
+ ui: { type: Object, required: false }
9
14
  });
10
15
  const emit = defineEmits(["select"]);
16
+ const dataListUi = useDataListUi();
17
+ const ui = computed(() => props.ui ?? dataListUi.ui.value.filterTags?.ui);
11
18
  </script>
12
19
 
13
20
  <template>
14
- <div class="grid gap-0.5">
21
+ <div :class="mergeDataListUiClass('grid gap-0.5', void 0, ui?.list)">
15
22
  <template v-for="section in props.sections" :key="section.key">
16
23
  <div
17
24
  v-if="section.dividerBefore && section.entries.length"
18
- class="my-1 border-t border-default"
25
+ :class="mergeDataListUiClass('my-1 border-t border-default', void 0, ui?.listDivider)"
19
26
  />
20
27
 
21
28
  <button
@@ -33,6 +40,8 @@ const emit = defineEmits(["select"]);
33
40
  :leading-icon="entry.icon"
34
41
  :selected-icon="props.selectedIcon"
35
42
  :truncate="props.truncate"
43
+ :size="props.size"
44
+ :ui="props.ui"
36
45
  />
37
46
  </button>
38
47
  </template>
@@ -1,4 +1,4 @@
1
- import type { TableResolvedFilterOptionEntry } from '../../../types/index.js';
1
+ import type { DataListControlSize, DataListFilterEditorUi, TableResolvedFilterOptionEntry } from '../../../types/index.js';
2
2
  interface FilterOptionMultipleListSection {
3
3
  key: string;
4
4
  entries: Array<TableResolvedFilterOptionEntry & {
@@ -13,6 +13,8 @@ type __VLS_Props = {
13
13
  countLoading: boolean;
14
14
  selectedIcon?: string;
15
15
  truncate?: boolean;
16
+ size?: DataListControlSize;
17
+ ui?: DataListFilterEditorUi;
16
18
  };
17
19
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
18
20
  select: (options: {
@@ -1,4 +1,5 @@
1
1
  import type { useOptionFilterEditorState } from '../../../composables/use-option-filter-editor-state.js';
2
+ import type { DataListControlSize, DataListFilterEditorUi } from '../../../types/index.js';
2
3
  interface FilterOptionMultipleListSection {
3
4
  key: string;
4
5
  entries: Array<ReturnType<typeof useOptionFilterEditorState>['displayEntries']['value'][number]>;
@@ -7,6 +8,8 @@ interface FilterOptionMultipleListSection {
7
8
  type __VLS_Props = {
8
9
  state: ReturnType<typeof useOptionFilterEditorState>;
9
10
  sections?: FilterOptionMultipleListSection[];
11
+ size?: DataListControlSize;
12
+ ui?: DataListFilterEditorUi;
10
13
  };
11
14
  type __VLS_ModelProps = {
12
15
  'searchQuery'?: string;
@@ -6,7 +6,9 @@ import FilterOptionTreeContent from "./FilterOptionTreeContent.vue";
6
6
  import FilterSearchablePanel from "./FilterSearchablePanel.vue";
7
7
  const props = defineProps({
8
8
  state: { type: null, required: true },
9
- sections: { type: Array, required: false }
9
+ sections: { type: Array, required: false },
10
+ size: { type: String, required: false },
11
+ ui: { type: Object, required: false }
10
12
  });
11
13
  const searchQuery = defineModel("searchQuery", { type: String, ...{
12
14
  default: ""
@@ -39,6 +41,8 @@ function handleSelect(options) {
39
41
  !props.state.optionSource.isLoading.value && !props.state.displayEntries.value.length && !props.state.visibleTreeEntries.value.length
40
42
  "
41
43
  :empty-label="props.state.filterUi.value.labels.empty"
44
+ :size="props.size"
45
+ :ui="props.ui"
42
46
  >
43
47
  <template v-if="props.state.filterUi.value.presentation === 'tree'">
44
48
  <template v-if="props.state.optionSource.isLoading.value">
@@ -61,6 +65,8 @@ function handleSelect(options) {
61
65
  props.state.filterUi.value.row.showCounts && props.state.optionSource.isCountLoading.value
62
66
  "
63
67
  :selected-icon="props.state.filterUi.value.row.selectedIcon"
68
+ :size="props.size"
69
+ :ui="props.ui"
64
70
  @toggle-entry="emit('toggleTreeEntry', $event)"
65
71
  @toggle-expanded="emit('toggleExpanded', $event)"
66
72
  />
@@ -86,6 +92,8 @@ function handleSelect(options) {
86
92
  :count-loading="props.state.optionSource.isCountLoading.value"
87
93
  :selected-icon="props.state.filterUi.value.row.selectedIcon"
88
94
  :truncate="props.state.filterUi.value.row.truncate"
95
+ :size="props.size"
96
+ :ui="props.ui"
89
97
  @select="handleSelect($event)"
90
98
  />
91
99
  </template>
@@ -108,6 +116,8 @@ function handleSelect(options) {
108
116
  :count-loading="
109
117
  props.state.filterUi.value.row.showCounts && props.state.optionSource.isCountLoading.value
110
118
  "
119
+ :size="props.size"
120
+ :ui="props.ui"
111
121
  />
112
122
  </template>
113
123
  </FilterSearchablePanel>
@@ -1,4 +1,5 @@
1
1
  import type { useOptionFilterEditorState } from '../../../composables/use-option-filter-editor-state.js';
2
+ import type { DataListControlSize, DataListFilterEditorUi } from '../../../types/index.js';
2
3
  interface FilterOptionMultipleListSection {
3
4
  key: string;
4
5
  entries: Array<ReturnType<typeof useOptionFilterEditorState>['displayEntries']['value'][number]>;
@@ -7,6 +8,8 @@ interface FilterOptionMultipleListSection {
7
8
  type __VLS_Props = {
8
9
  state: ReturnType<typeof useOptionFilterEditorState>;
9
10
  sections?: FilterOptionMultipleListSection[];
11
+ size?: DataListControlSize;
12
+ ui?: DataListFilterEditorUi;
10
13
  };
11
14
  type __VLS_ModelProps = {
12
15
  'searchQuery'?: string;