@htlkg/components 0.0.2 → 0.0.4

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 (60) hide show
  1. package/README.md +52 -0
  2. package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js +367 -0
  3. package/dist/AdminWrapper.vue_vue_type_script_setup_true_lang-B32IylcT.js.map +1 -0
  4. package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js +263 -0
  5. package/dist/Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js.map +1 -0
  6. package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js +580 -0
  7. package/dist/DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js.map +1 -0
  8. package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js +187 -0
  9. package/dist/ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js.map +1 -0
  10. package/dist/_plugin-vue_export-helper-1tPrXgE0.js +11 -0
  11. package/dist/_plugin-vue_export-helper-1tPrXgE0.js.map +1 -0
  12. package/dist/components.css +15 -0
  13. package/dist/composables/index.js +32 -573
  14. package/dist/composables/index.js.map +1 -1
  15. package/dist/data/index.js +18 -0
  16. package/dist/data/index.js.map +1 -0
  17. package/dist/domain/index.js +8 -0
  18. package/dist/domain/index.js.map +1 -0
  19. package/dist/filterHelpers-DgRyoYSa.js +1386 -0
  20. package/dist/filterHelpers-DgRyoYSa.js.map +1 -0
  21. package/dist/forms/index.js +6 -0
  22. package/dist/forms/index.js.map +1 -0
  23. package/dist/index-DGO_pNgG.js +79 -0
  24. package/dist/index-DGO_pNgG.js.map +1 -0
  25. package/dist/index-QK97OdqQ.js +25 -0
  26. package/dist/index-QK97OdqQ.js.map +1 -0
  27. package/dist/index.js +67 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/navigation/index.js +8 -0
  30. package/dist/navigation/index.js.map +1 -0
  31. package/dist/overlays/index.js +8 -0
  32. package/dist/overlays/index.js.map +1 -0
  33. package/dist/stores/index.js +14 -0
  34. package/dist/stores/index.js.map +1 -0
  35. package/dist/useAdminPage-GhgXp0x8.js +1070 -0
  36. package/dist/useAdminPage-GhgXp0x8.js.map +1 -0
  37. package/dist/useTable-DutR1gkg.js +293 -0
  38. package/dist/useTable-DutR1gkg.js.map +1 -0
  39. package/package.json +43 -14
  40. package/src/composables/composables.md +109 -0
  41. package/src/composables/index.ts +69 -0
  42. package/src/composables/useAdminPage.ts +462 -0
  43. package/src/composables/useConfirmation.ts +358 -0
  44. package/src/composables/usePageContext.ts +171 -0
  45. package/src/composables/useStats.ts +361 -0
  46. package/src/composables/useTable.ts +26 -5
  47. package/src/composables/useWizard.ts +448 -0
  48. package/src/data/DataTable.vue +553 -0
  49. package/src/data/Table/Table.vue +295 -0
  50. package/src/data/columnHelpers.ts +503 -0
  51. package/src/data/data.md +106 -0
  52. package/src/data/filterHelpers.ts +358 -0
  53. package/src/data/index.ts +31 -0
  54. package/src/domain/domain.md +102 -0
  55. package/src/forms/JsonSchemaForm.vue +4 -1
  56. package/src/forms/forms.md +89 -0
  57. package/src/index.ts +4 -3
  58. package/src/navigation/navigation.md +80 -0
  59. package/src/overlays/overlays.md +86 -0
  60. package/src/stores/stores.md +82 -0
@@ -0,0 +1,1386 @@
1
+ import { defineComponent, ref, computed, createBlock, openBlock, unref, createElementBlock, toDisplayString, Fragment, renderList, renderSlot, createTextVNode, toRef, watch } from "vue";
2
+ import { uiTable, uiSelectMultiple, uiSelect, uiChart } from "@hotelinking/ui";
3
+ import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.js";
4
+ import { u as useTable } from "./useTable-DutR1gkg.js";
5
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
6
+ __name: "Table",
7
+ props: {
8
+ items: {},
9
+ header: {},
10
+ loading: { type: Boolean, default: false },
11
+ currentPage: { default: 1 },
12
+ totalPages: { default: 1 },
13
+ totalItems: { default: 0 },
14
+ pageSize: { default: 10 },
15
+ orderedBy: { default: "" },
16
+ orderDirection: { default: "asc" },
17
+ actions: {},
18
+ selectAllItemsModal: {},
19
+ resetSelected: { type: Boolean, default: false },
20
+ smartFilterCategories: {},
21
+ filterLiterals: { default: () => ({
22
+ filters: "Smart Filters",
23
+ contains: "contains",
24
+ is: "is",
25
+ and: "and",
26
+ or: "or",
27
+ deleteAll: "Delete All",
28
+ filter: "Filter"
29
+ }) },
30
+ filters: {},
31
+ tableActionsDropdown: {},
32
+ tableActionButtons: {},
33
+ noResults: {},
34
+ hiddenColumns: {}
35
+ },
36
+ emits: ["update:currentPage", "update:pageSize", "update:selected", "update:orderedBy", "update:orderDirection", "update:resetSelected", "table-action", "table-action-selected", "table-action-button-clicked", "smart-filters-sent", "smart-filters-cleared", "smart-filter-deleted", "custom-emit", "modal-action", "select-all-items", "deselect-all-items", "no-results-action", "no-results-option-selected", "columns-visibility-changed", "order-by", "change-page", "change-page-size"],
37
+ setup(__props, { expose: __expose, emit: __emit }) {
38
+ const props = __props;
39
+ const emit = __emit;
40
+ const internalHiddenColumns = ref(props.hiddenColumns || []);
41
+ const selectedItemIds = ref(/* @__PURE__ */ new Set());
42
+ const pageSizeOptions = computed(() => [
43
+ { name: "10", value: "10", active: props.pageSize === 10 },
44
+ { name: "25", value: "25", active: props.pageSize === 25 },
45
+ { name: "50", value: "50", active: props.pageSize === 50 },
46
+ { name: "100", value: "100", active: props.pageSize === 100 }
47
+ ]);
48
+ function handleOrderBy(event) {
49
+ emit("update:orderedBy", event.value);
50
+ emit("update:orderDirection", event.orderDirection);
51
+ emit("order-by", event);
52
+ }
53
+ function handleChangePage(page) {
54
+ emit("update:currentPage", page);
55
+ emit("change-page", page);
56
+ }
57
+ function handleChangePageSize(size) {
58
+ const numSize = typeof size === "string" ? Number(size) : size;
59
+ emit("update:pageSize", numSize);
60
+ emit("change-page-size", size);
61
+ emit("update:currentPage", 1);
62
+ }
63
+ function handleTableAction(data) {
64
+ selectedItemIds.value = new Set(data.items);
65
+ updateSelectedItems();
66
+ emit("table-action", data);
67
+ }
68
+ function handleTableActionSelected(item) {
69
+ emit("table-action-selected", item);
70
+ }
71
+ function handleTableActionButtonClicked(data) {
72
+ emit("table-action-button-clicked", data);
73
+ }
74
+ function handleSmartFiltersSent(filters2) {
75
+ emit("smart-filters-sent", filters2);
76
+ }
77
+ function handleSmartFiltersCleared() {
78
+ emit("smart-filters-cleared");
79
+ }
80
+ function handleSmartFilterDeleted(index) {
81
+ emit("smart-filter-deleted", index);
82
+ }
83
+ function handleCustomEmit(data) {
84
+ emit("custom-emit", data);
85
+ }
86
+ function handleColumnsVisibilityChanged(event) {
87
+ if (event.hidden) {
88
+ if (!internalHiddenColumns.value.includes(event.index)) {
89
+ internalHiddenColumns.value.push(event.index);
90
+ }
91
+ } else {
92
+ const index = internalHiddenColumns.value.indexOf(event.index);
93
+ if (index > -1) {
94
+ internalHiddenColumns.value.splice(index, 1);
95
+ }
96
+ }
97
+ emit("columns-visibility-changed", event);
98
+ }
99
+ function handleModalAction(data) {
100
+ emit("modal-action", data);
101
+ }
102
+ function handleSelectAllItems() {
103
+ selectedItemIds.value = new Set(props.items.map((item) => item.id));
104
+ updateSelectedItems();
105
+ emit("select-all-items");
106
+ }
107
+ function handleDeselectAllItems() {
108
+ selectedItemIds.value.clear();
109
+ updateSelectedItems();
110
+ emit("deselect-all-items");
111
+ }
112
+ function handleNoResultsAction(action) {
113
+ emit("no-results-action", action);
114
+ }
115
+ function handleNoResultsOptionSelected(item) {
116
+ emit("no-results-option-selected", item);
117
+ }
118
+ function handleSelectedItemsDeleted() {
119
+ emit("update:resetSelected", false);
120
+ }
121
+ function updateSelectedItems() {
122
+ const selected = props.items.filter((item) => item.id && selectedItemIds.value.has(item.id));
123
+ emit("update:selected", selected);
124
+ }
125
+ __expose({
126
+ clearSelection: () => {
127
+ emit("update:resetSelected", true);
128
+ selectedItemIds.value.clear();
129
+ updateSelectedItems();
130
+ },
131
+ getHiddenColumns: () => internalHiddenColumns.value,
132
+ getSelectedItems: () => Array.from(selectedItemIds.value),
133
+ getSelectedItemsData: () => props.items.filter((item) => item.id && selectedItemIds.value.has(item.id))
134
+ });
135
+ return (_ctx, _cache) => {
136
+ return openBlock(), createBlock(unref(uiTable), {
137
+ loading: __props.loading,
138
+ header: __props.header,
139
+ items: __props.items,
140
+ "ordered-by": __props.orderedBy,
141
+ "order-direction": __props.orderDirection,
142
+ actions: __props.actions,
143
+ "hidden-columns": internalHiddenColumns.value,
144
+ "reset-selected": __props.resetSelected,
145
+ "select-all-items-modal": __props.selectAllItemsModal,
146
+ "smart-filter-categories": __props.smartFilterCategories,
147
+ "filter-literals": __props.filterLiterals,
148
+ filters: __props.filters,
149
+ "table-actions-dropdown": __props.tableActionsDropdown,
150
+ "table-action-buttons": __props.tableActionButtons,
151
+ "pagination-current": __props.currentPage,
152
+ "pagination-total": __props.totalPages,
153
+ "pagination-total-items": __props.totalItems,
154
+ "page-size-options": pageSizeOptions.value,
155
+ "current-page-size": __props.pageSize,
156
+ "no-results": __props.noResults,
157
+ onOrderBy: handleOrderBy,
158
+ onTableAction: handleTableAction,
159
+ onTableActionSelected: handleTableActionSelected,
160
+ onTableActionButtonClicked: handleTableActionButtonClicked,
161
+ onSmartFiltersSent: handleSmartFiltersSent,
162
+ onSmartFiltersCleared: handleSmartFiltersCleared,
163
+ onSmartFilterDeleted: handleSmartFilterDeleted,
164
+ onChangePage: handleChangePage,
165
+ onChangePageSize: handleChangePageSize,
166
+ onCustomEmit: handleCustomEmit,
167
+ onColumnsVisibilityChanged: handleColumnsVisibilityChanged,
168
+ onSelectedItemsDeleted: handleSelectedItemsDeleted,
169
+ onModalAction: handleModalAction,
170
+ onSelectAllItems: handleSelectAllItems,
171
+ onDeselectAllItems: handleDeselectAllItems,
172
+ onNoResultsAction: handleNoResultsAction,
173
+ onNoResultsOptionSelected: handleNoResultsOptionSelected
174
+ }, null, 8, ["loading", "header", "items", "ordered-by", "order-direction", "actions", "hidden-columns", "reset-selected", "select-all-items-modal", "smart-filter-categories", "filter-literals", "filters", "table-actions-dropdown", "table-action-buttons", "pagination-current", "pagination-total", "pagination-total-items", "page-size-options", "current-page-size", "no-results"]);
175
+ };
176
+ }
177
+ });
178
+ const Table = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-80c477af"]]);
179
+ const _hoisted_1 = { class: "w-full" };
180
+ const _hoisted_2 = {
181
+ key: 0,
182
+ class: "p-8 text-center text-gray-600"
183
+ };
184
+ const _hoisted_3 = {
185
+ key: 1,
186
+ class: "p-8 text-center text-gray-600"
187
+ };
188
+ const _hoisted_4 = {
189
+ key: 2,
190
+ class: "flex flex-col gap-2"
191
+ };
192
+ const _hoisted_5 = ["onClick"];
193
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
194
+ __name: "DataList",
195
+ props: {
196
+ items: {},
197
+ loading: { type: Boolean, default: false },
198
+ emptyMessage: { default: "No items to display" }
199
+ },
200
+ emits: ["item-click"],
201
+ setup(__props, { expose: __expose, emit: __emit }) {
202
+ const props = __props;
203
+ const emit = __emit;
204
+ __expose({
205
+ getItems: () => props.items
206
+ });
207
+ return (_ctx, _cache) => {
208
+ return openBlock(), createElementBlock("div", _hoisted_1, [
209
+ __props.loading ? (openBlock(), createElementBlock("div", _hoisted_2, " Loading... ")) : __props.items.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(__props.emptyMessage), 1)) : (openBlock(), createElementBlock("div", _hoisted_4, [
210
+ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item, index) => {
211
+ return openBlock(), createElementBlock("div", {
212
+ key: index,
213
+ class: "p-4 border border-gray-200 rounded-md cursor-pointer hover:bg-gray-50 transition-colors",
214
+ onClick: ($event) => emit("item-click", item)
215
+ }, [
216
+ renderSlot(_ctx.$slots, "default", {
217
+ item,
218
+ index
219
+ }, () => [
220
+ createTextVNode(toDisplayString(JSON.stringify(item)), 1)
221
+ ])
222
+ ], 8, _hoisted_5);
223
+ }), 128))
224
+ ]))
225
+ ]);
226
+ };
227
+ }
228
+ });
229
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
230
+ __name: "SearchableSelect",
231
+ props: {
232
+ options: {},
233
+ modelValue: { default: null },
234
+ labelKey: { default: "label" },
235
+ valueKey: { default: "id" },
236
+ placeholder: { default: "Select an option" },
237
+ label: { default: "" },
238
+ error: { default: "" },
239
+ color: { default: "gray" },
240
+ loading: { type: Boolean, default: false },
241
+ disabled: { type: Boolean, default: false },
242
+ requiredText: { default: "" },
243
+ multiple: { type: Boolean, default: false }
244
+ },
245
+ emits: ["update:modelValue", "change"],
246
+ setup(__props, { expose: __expose, emit: __emit }) {
247
+ const props = __props;
248
+ const emit = __emit;
249
+ const transformedItems = computed(() => {
250
+ return props.options.map((option) => ({
251
+ id: String(option[props.valueKey]),
252
+ name: String(option[props.labelKey]),
253
+ label: option.label ? String(option.label) : void 0
254
+ }));
255
+ });
256
+ const selectedItem = computed(() => {
257
+ if (props.multiple || !props.modelValue) {
258
+ return { id: "", name: "", label: void 0 };
259
+ }
260
+ const value = props.modelValue;
261
+ return {
262
+ id: String(value[props.valueKey]),
263
+ name: String(value[props.labelKey]),
264
+ label: value.label ? String(value.label) : void 0
265
+ };
266
+ });
267
+ const selectedItems = computed(() => {
268
+ if (!props.multiple || !props.modelValue) return [];
269
+ const values = Array.isArray(props.modelValue) ? props.modelValue : [props.modelValue];
270
+ return values.map((value) => ({
271
+ id: String(value[props.valueKey]),
272
+ name: String(value[props.labelKey]),
273
+ label: value.label ? String(value.label) : void 0
274
+ }));
275
+ });
276
+ function handleSelectChange(selected) {
277
+ if (props.multiple) {
278
+ const originalValues = selected.map((item) => {
279
+ return props.options.find((opt) => String(opt[props.valueKey]) === item.id);
280
+ }).filter(Boolean);
281
+ emit("update:modelValue", originalValues);
282
+ emit("change", originalValues);
283
+ } else {
284
+ const originalValue = props.options.find((opt) => String(opt[props.valueKey]) === selected.id);
285
+ emit("update:modelValue", originalValue || null);
286
+ emit("change", originalValue || null);
287
+ }
288
+ }
289
+ __expose({
290
+ getSelected: () => props.modelValue
291
+ });
292
+ return (_ctx, _cache) => {
293
+ return __props.multiple ? (openBlock(), createBlock(unref(uiSelectMultiple), {
294
+ key: 0,
295
+ items: transformedItems.value,
296
+ label: __props.label,
297
+ placeholder: __props.placeholder,
298
+ error: __props.error,
299
+ color: __props.color,
300
+ select: selectedItems.value,
301
+ loading: __props.loading,
302
+ disabled: __props.disabled,
303
+ "required-text": __props.requiredText,
304
+ onSelectChanged: handleSelectChange
305
+ }, null, 8, ["items", "label", "placeholder", "error", "color", "select", "loading", "disabled", "required-text"])) : (openBlock(), createBlock(unref(uiSelect), {
306
+ key: 1,
307
+ items: transformedItems.value,
308
+ label: __props.label,
309
+ placeholder: __props.placeholder,
310
+ error: __props.error,
311
+ color: __props.color,
312
+ select: selectedItem.value,
313
+ loading: __props.loading,
314
+ disabled: __props.disabled,
315
+ "required-text": __props.requiredText,
316
+ onSelectChanged: handleSelectChange
317
+ }, null, 8, ["items", "label", "placeholder", "error", "color", "select", "loading", "disabled", "required-text"]));
318
+ };
319
+ }
320
+ });
321
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
322
+ __name: "Chart",
323
+ props: {
324
+ id: {},
325
+ title: {},
326
+ series: {},
327
+ type: { default: "line" },
328
+ options: {},
329
+ loading: { type: Boolean, default: false },
330
+ empty: { type: Boolean, default: false },
331
+ range: {},
332
+ horizontal: { type: Boolean, default: false },
333
+ stacked: { type: Boolean, default: false },
334
+ height: {},
335
+ labels: {},
336
+ dates: {},
337
+ isNps: { type: Boolean, default: false },
338
+ npsLiterals: {},
339
+ annotations: {}
340
+ },
341
+ emits: ["range-selected", "chart-updated", "data-point-selection", "maximize"],
342
+ setup(__props, { expose: __expose, emit: __emit }) {
343
+ const props = __props;
344
+ const emit = __emit;
345
+ function handleRangeSelected(data) {
346
+ emit("range-selected", data);
347
+ }
348
+ function handleChartUpdated() {
349
+ emit("chart-updated");
350
+ }
351
+ function handleDataPointSelection(data) {
352
+ emit("data-point-selection", data);
353
+ }
354
+ function handleMaximizeChart(chartId) {
355
+ emit("maximize", chartId);
356
+ }
357
+ function refresh() {
358
+ emit("chart-updated");
359
+ }
360
+ function getChartId() {
361
+ return props.id;
362
+ }
363
+ __expose({
364
+ refresh,
365
+ getChartId
366
+ });
367
+ return (_ctx, _cache) => {
368
+ return openBlock(), createBlock(unref(uiChart), {
369
+ id: __props.id,
370
+ title: __props.title,
371
+ type: __props.type,
372
+ series: __props.series,
373
+ options: __props.options,
374
+ loading: __props.loading,
375
+ empty: __props.empty,
376
+ range: __props.range,
377
+ horizontal: __props.horizontal,
378
+ stacked: __props.stacked,
379
+ height: __props.height,
380
+ labels: __props.labels,
381
+ dates: __props.dates,
382
+ isNps: __props.isNps,
383
+ npsLiterals: __props.npsLiterals,
384
+ annotations: __props.annotations,
385
+ onSelectedRange: handleRangeSelected,
386
+ onChartUpdated: handleChartUpdated,
387
+ onDataPointSelection: handleDataPointSelection,
388
+ onMaximizeChart: handleMaximizeChart
389
+ }, null, 8, ["id", "title", "type", "series", "options", "loading", "empty", "range", "horizontal", "stacked", "height", "labels", "dates", "isNps", "npsLiterals", "annotations"]);
390
+ };
391
+ }
392
+ });
393
+ const _sfc_main = /* @__PURE__ */ defineComponent({
394
+ __name: "DataTable",
395
+ props: {
396
+ items: {},
397
+ columns: {},
398
+ filters: {},
399
+ initialFilters: {},
400
+ loading: { type: Boolean, default: false },
401
+ pageSize: { default: 10 },
402
+ currentPage: { default: 1 },
403
+ totalPages: { default: 1 },
404
+ totalItems: { default: 0 },
405
+ idKey: { default: "id" },
406
+ actions: {},
407
+ selectable: { type: Boolean, default: false },
408
+ bulkActions: {},
409
+ noResults: {},
410
+ defaultSortKey: {},
411
+ defaultSortOrder: { default: "asc" },
412
+ syncUrl: { type: Boolean, default: false }
413
+ },
414
+ emits: ["action", "bulkAction", "selection", "rowClick", "customEmit", "pageChange", "sortChange", "filterChange"],
415
+ setup(__props, { emit: __emit }) {
416
+ const props = __props;
417
+ const emit = __emit;
418
+ function updateUrl(params) {
419
+ if (typeof window === "undefined") return;
420
+ const url = new URL(window.location.href);
421
+ Object.entries(params).forEach(([key, value]) => {
422
+ if (value !== void 0 && value !== "") {
423
+ url.searchParams.set(key, value);
424
+ } else {
425
+ url.searchParams.delete(key);
426
+ }
427
+ });
428
+ window.location.href = url.toString();
429
+ }
430
+ function handlePageChange(page) {
431
+ if (props.syncUrl) {
432
+ emit("pageChange", page);
433
+ updateUrl({ page: String(page) });
434
+ } else {
435
+ table.handlePageChange(page);
436
+ }
437
+ }
438
+ function handlePageSizeChange(size) {
439
+ if (props.syncUrl) {
440
+ updateUrl({ pageSize: String(size), page: "1" });
441
+ } else {
442
+ table.handlePageSizeChange(size);
443
+ }
444
+ }
445
+ function handleOrderBy(event) {
446
+ if (props.syncUrl) {
447
+ emit("sortChange", event.value, event.orderDirection);
448
+ updateUrl({ sortKey: event.value, sortOrder: event.orderDirection, page: "1" });
449
+ } else {
450
+ table.handleOrderBy(event);
451
+ }
452
+ }
453
+ function extractFilterValue(value) {
454
+ if (value === void 0 || value === null || value === "") {
455
+ return void 0;
456
+ }
457
+ if (typeof value === "object" && value !== null && "id" in value) {
458
+ return String(value.id);
459
+ }
460
+ return String(value);
461
+ }
462
+ function handleFiltersApplied(filters2) {
463
+ if (props.syncUrl) {
464
+ const filterParams = { page: "1" };
465
+ if (filters2 && typeof filters2 === "object" && "filters" in filters2 && Array.isArray(filters2.filters)) {
466
+ filters2.filters.forEach((f) => {
467
+ const extractedValue = extractFilterValue(f.value);
468
+ if (extractedValue !== void 0) {
469
+ filterParams[f.name] = extractedValue;
470
+ }
471
+ });
472
+ } else if (Array.isArray(filters2)) {
473
+ filters2.forEach((f) => {
474
+ const key = f.category || f.name;
475
+ const extractedValue = extractFilterValue(f.value);
476
+ if (key && extractedValue !== void 0) {
477
+ filterParams[key] = extractedValue;
478
+ }
479
+ });
480
+ } else if (filters2 && typeof filters2 === "object") {
481
+ Object.entries(filters2).forEach(([key, value]) => {
482
+ if (key === "logicOperator" || key === "filters") return;
483
+ const extractedValue = extractFilterValue(value);
484
+ if (extractedValue !== void 0) {
485
+ filterParams[key] = extractedValue;
486
+ }
487
+ });
488
+ }
489
+ emit("filterChange", filterParams);
490
+ updateUrl(filterParams);
491
+ } else {
492
+ table.handleSmartFiltersApplied(filters2);
493
+ }
494
+ }
495
+ function handleFiltersCleared() {
496
+ if (props.syncUrl) {
497
+ if (typeof window === "undefined") return;
498
+ const url = new URL(window.location.href);
499
+ const keysToRemove = [];
500
+ url.searchParams.forEach((_, key) => {
501
+ if (!["page", "pageSize", "sortKey", "sortOrder"].includes(key)) {
502
+ keysToRemove.push(key);
503
+ }
504
+ });
505
+ keysToRemove.forEach((key) => url.searchParams.delete(key));
506
+ url.searchParams.set("page", "1");
507
+ window.location.href = url.toString();
508
+ } else {
509
+ table.handleSmartFiltersCleared();
510
+ }
511
+ }
512
+ function handleFilterDeleted(index) {
513
+ if (props.syncUrl) {
514
+ handleFiltersCleared();
515
+ } else {
516
+ table.handleSmartFilterDeleted(index);
517
+ }
518
+ }
519
+ const table = useTable({
520
+ items: toRef(() => props.items),
521
+ pageSize: props.pageSize,
522
+ sortKey: props.defaultSortKey ?? "",
523
+ sortOrder: props.defaultSortOrder,
524
+ idKey: props.idKey
525
+ });
526
+ const tableHeader = computed(
527
+ () => props.columns.map((col) => ({
528
+ name: col.key,
529
+ label: col.label,
530
+ sortable: col.sortable !== false,
531
+ width: col.width
532
+ }))
533
+ );
534
+ const tableItems = computed(() => {
535
+ const itemsToRender = props.syncUrl ? props.items : table.paginatedItems.value;
536
+ return itemsToRender.map((item, itemIndex) => ({
537
+ id: item[props.idKey],
538
+ row: props.columns.map((col) => {
539
+ if (col.render) {
540
+ return col.render(item, itemIndex);
541
+ }
542
+ const value = item[col.key];
543
+ return formatCellValue(value, col.type);
544
+ }),
545
+ // Store original item for action handlers
546
+ _originalData: item
547
+ }));
548
+ });
549
+ const filterCategories = computed(
550
+ () => {
551
+ var _a;
552
+ return ((_a = props.filters) == null ? void 0 : _a.map((f) => ({
553
+ id: f.key,
554
+ name: f.label,
555
+ componentType: mapFilterType(f.type),
556
+ defaultProps: buildFilterProps(f)
557
+ }))) ?? [];
558
+ }
559
+ );
560
+ const initialTableFilters = computed(() => {
561
+ if (!props.initialFilters || !props.filters) return void 0;
562
+ const filterEntries = Object.entries(props.initialFilters).filter(
563
+ ([, value]) => value !== void 0 && value !== null && value !== ""
564
+ );
565
+ if (filterEntries.length === 0) return void 0;
566
+ return {
567
+ logicOperator: "and",
568
+ filters: filterEntries.map(([key, value]) => {
569
+ var _a;
570
+ const filterDef = (_a = props.filters) == null ? void 0 : _a.find((f) => f.key === key);
571
+ return {
572
+ name: key,
573
+ label: (filterDef == null ? void 0 : filterDef.label) ?? key,
574
+ type: filterDef ? mapFilterType(filterDef.type) : "uiInput",
575
+ value: String(value)
576
+ };
577
+ })
578
+ };
579
+ });
580
+ const rowActions = computed(() => {
581
+ if (!props.actions || props.actions.length === 0) return void 0;
582
+ return props.actions.map((action) => {
583
+ if (typeof action === "string") {
584
+ return { name: action, id: action };
585
+ }
586
+ return { name: action.label, id: action.id };
587
+ });
588
+ });
589
+ const bulkActionButtons = computed(() => {
590
+ if (!props.bulkActions || !props.selectable) return void 0;
591
+ return props.bulkActions.map((action) => ({
592
+ text: action.label,
593
+ id: action.id,
594
+ color: action.variant === "danger" ? "red" : action.variant === "warning" ? "yellow" : "blue",
595
+ icon: action.icon
596
+ }));
597
+ });
598
+ const selectAllModal = computed(() => {
599
+ if (!props.selectable) return void 0;
600
+ return {
601
+ title: "Select All Items",
602
+ message: `Select all ${table.totalItems.value} items?`,
603
+ cancelText: "Select page only",
604
+ confirmText: "Select all"
605
+ };
606
+ });
607
+ function formatCellValue(value, type) {
608
+ if (value === null || value === void 0) return "";
609
+ switch (type) {
610
+ case "date":
611
+ if (value instanceof Date) {
612
+ return value.toLocaleDateString();
613
+ }
614
+ if (typeof value === "string") {
615
+ return new Date(value).toLocaleDateString();
616
+ }
617
+ return value;
618
+ case "number":
619
+ return typeof value === "number" ? value.toLocaleString() : value;
620
+ case "badge":
621
+ return { content: value, type: "badge" };
622
+ case "tag":
623
+ return { content: value, type: "tag" };
624
+ default:
625
+ return value;
626
+ }
627
+ }
628
+ function mapFilterType(type) {
629
+ switch (type) {
630
+ case "select":
631
+ return "uiSelect";
632
+ default:
633
+ return "uiInput";
634
+ }
635
+ }
636
+ function buildFilterProps(filter) {
637
+ const defaultProps = {};
638
+ if (filter.placeholder) {
639
+ defaultProps.placeholder = filter.placeholder;
640
+ }
641
+ if (filter.type === "select" && filter.options) {
642
+ defaultProps.items = filter.options.map((opt, index) => ({
643
+ id: String(index),
644
+ name: String(opt.value),
645
+ // This is what gets used as filter value
646
+ label: opt.label
647
+ // This is what gets displayed
648
+ }));
649
+ }
650
+ if (filter.type === "number") {
651
+ defaultProps.type = "number";
652
+ }
653
+ return defaultProps;
654
+ }
655
+ function handleTableAction(data) {
656
+ const itemId = data.items[0];
657
+ const tableItem = tableItems.value.find((ti) => ti.id === itemId);
658
+ if (tableItem && tableItem._originalData) {
659
+ emit("action", data.action, tableItem._originalData);
660
+ }
661
+ }
662
+ function handleBulkActionClick(data) {
663
+ emit("bulkAction", data.id, table.selectedItems.value);
664
+ }
665
+ function handleCustomEmit(data) {
666
+ emit("customEmit", data);
667
+ }
668
+ watch(
669
+ () => table.selectedItems.value,
670
+ (items) => {
671
+ emit("selection", items);
672
+ },
673
+ { deep: true }
674
+ );
675
+ return (_ctx, _cache) => {
676
+ return openBlock(), createBlock(Table, {
677
+ header: tableHeader.value,
678
+ items: tableItems.value,
679
+ loading: __props.loading,
680
+ "current-page": __props.syncUrl ? __props.currentPage : unref(table).currentPage.value,
681
+ "total-pages": __props.syncUrl ? __props.totalPages : unref(table).totalPages.value,
682
+ "total-items": __props.syncUrl ? __props.totalItems : unref(table).totalItems.value,
683
+ "page-size": __props.syncUrl ? __props.pageSize : unref(table).pageSize.value,
684
+ "ordered-by": __props.defaultSortKey ?? unref(table).sortKey.value,
685
+ "order-direction": __props.defaultSortOrder ?? unref(table).sortOrder.value,
686
+ "smart-filter-categories": filterCategories.value,
687
+ filters: initialTableFilters.value,
688
+ "hidden-columns": unref(table).hiddenColumns.value,
689
+ "reset-selected": unref(table).resetSelected.value,
690
+ actions: rowActions.value,
691
+ "select-all-items-modal": selectAllModal.value,
692
+ "table-action-buttons": bulkActionButtons.value,
693
+ "no-results": __props.noResults,
694
+ onChangePage: handlePageChange,
695
+ onChangePageSize: handlePageSizeChange,
696
+ onOrderBy: handleOrderBy,
697
+ onSmartFiltersSent: handleFiltersApplied,
698
+ onSmartFiltersCleared: handleFiltersCleared,
699
+ onSmartFilterDeleted: handleFilterDeleted,
700
+ onColumnsVisibilityChanged: unref(table).handleColumnsVisibilityChanged,
701
+ onModalAction: unref(table).handleModalAction,
702
+ onTableAction: handleTableAction,
703
+ onTableActionButtonClicked: handleBulkActionClick,
704
+ onCustomEmit: handleCustomEmit
705
+ }, null, 8, ["header", "items", "loading", "current-page", "total-pages", "total-items", "page-size", "ordered-by", "order-direction", "smart-filter-categories", "filters", "hidden-columns", "reset-selected", "actions", "select-all-items-modal", "table-action-buttons", "no-results", "onColumnsVisibilityChanged", "onModalAction"]);
706
+ };
707
+ }
708
+ });
709
+ const columns = {
710
+ /**
711
+ * Simple text column
712
+ *
713
+ * @example
714
+ * columns.text('name', 'Name')
715
+ */
716
+ text: (key, label, options) => ({
717
+ key,
718
+ label,
719
+ type: "text",
720
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
721
+ width: options == null ? void 0 : options.width
722
+ }),
723
+ /**
724
+ * Number column with locale formatting
725
+ *
726
+ * @example
727
+ * columns.number('amount', 'Amount')
728
+ * columns.number('price', 'Price', { prefix: '$', decimals: 2 })
729
+ */
730
+ number: (key, label, options) => ({
731
+ key,
732
+ label,
733
+ type: "number",
734
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
735
+ render: (item) => {
736
+ const value = item[key];
737
+ if (value === null || value === void 0) return "";
738
+ const formatted = (options == null ? void 0 : options.decimals) !== void 0 ? Number(value).toLocaleString(void 0, {
739
+ minimumFractionDigits: options.decimals,
740
+ maximumFractionDigits: options.decimals
741
+ }) : Number(value).toLocaleString();
742
+ return `${(options == null ? void 0 : options.prefix) ?? ""}${formatted}${(options == null ? void 0 : options.suffix) ?? ""}`;
743
+ }
744
+ }),
745
+ /**
746
+ * Date column with formatting
747
+ *
748
+ * @example
749
+ * columns.date('createdAt', 'Created')
750
+ * columns.date('updatedAt', 'Updated', { format: 'long' })
751
+ */
752
+ date: (key, label, options) => ({
753
+ key,
754
+ label,
755
+ type: "date",
756
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
757
+ render: (item) => {
758
+ const value = item[key];
759
+ if (!value) return "";
760
+ const date = value instanceof Date ? value : new Date(value);
761
+ if (Number.isNaN(date.getTime())) return "";
762
+ const formatOptions = {
763
+ short: { dateStyle: "short" },
764
+ medium: { dateStyle: "medium" },
765
+ long: { dateStyle: "long" },
766
+ full: { dateStyle: "full" }
767
+ }[(options == null ? void 0 : options.format) ?? "medium"];
768
+ return date.toLocaleDateString(options == null ? void 0 : options.locale, formatOptions);
769
+ }
770
+ }),
771
+ /**
772
+ * DateTime column with formatting
773
+ *
774
+ * @example
775
+ * columns.dateTime('createdAt', 'Created At')
776
+ */
777
+ dateTime: (key, label, options) => ({
778
+ key,
779
+ label,
780
+ type: "date",
781
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
782
+ render: (item) => {
783
+ const value = item[key];
784
+ if (!value) return "";
785
+ const date = value instanceof Date ? value : new Date(value);
786
+ if (Number.isNaN(date.getTime())) return "";
787
+ return date.toLocaleString(options == null ? void 0 : options.locale, {
788
+ dateStyle: "medium",
789
+ timeStyle: "short"
790
+ });
791
+ }
792
+ }),
793
+ /**
794
+ * Tag column with optional color function
795
+ *
796
+ * @example
797
+ * columns.tag('status', 'Status')
798
+ * columns.tag('status', 'Status', (item) => item.active ? 'green' : 'red')
799
+ */
800
+ tag: (key, label, colorFn, options) => ({
801
+ key,
802
+ label,
803
+ type: "tag",
804
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
805
+ render: (item) => {
806
+ const value = item[key];
807
+ return {
808
+ content: value,
809
+ color: (colorFn == null ? void 0 : colorFn(item)) ?? "gray",
810
+ type: "tag"
811
+ };
812
+ }
813
+ }),
814
+ /**
815
+ * Badge column (numeric badge style)
816
+ *
817
+ * @example
818
+ * columns.badge('count', 'Count')
819
+ * columns.badge('brandCount', 'Brands')
820
+ */
821
+ badge: (key, label, options) => ({
822
+ key,
823
+ label,
824
+ type: "badge",
825
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
826
+ render: (item) => ({
827
+ content: item[key],
828
+ type: "badge"
829
+ })
830
+ }),
831
+ /**
832
+ * Boolean column rendered as tag
833
+ *
834
+ * @example
835
+ * columns.boolean('active', 'Active')
836
+ * columns.boolean('verified', 'Verified', { trueLabel: 'Yes', falseLabel: 'No' })
837
+ */
838
+ boolean: (key, label, options) => ({
839
+ key,
840
+ label,
841
+ type: "tag",
842
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
843
+ render: (item) => {
844
+ const value = Boolean(item[key]);
845
+ return {
846
+ content: value ? (options == null ? void 0 : options.trueLabel) ?? "Yes" : (options == null ? void 0 : options.falseLabel) ?? "No",
847
+ color: value ? (options == null ? void 0 : options.trueColor) ?? "green" : (options == null ? void 0 : options.falseColor) ?? "red",
848
+ type: "tag"
849
+ };
850
+ }
851
+ }),
852
+ /**
853
+ * Email column (renders as link)
854
+ *
855
+ * @example
856
+ * columns.email('email', 'Email')
857
+ */
858
+ email: (key, label, options) => ({
859
+ key,
860
+ label,
861
+ type: "text",
862
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
863
+ render: (item) => ({
864
+ content: item[key],
865
+ type: "link",
866
+ href: `mailto:${item[key]}`
867
+ })
868
+ }),
869
+ /**
870
+ * Actions column (row actions)
871
+ *
872
+ * @example
873
+ * columns.actions(['view', 'edit', 'delete'])
874
+ */
875
+ actions: (actions) => ({
876
+ key: "_actions",
877
+ label: "",
878
+ sortable: false,
879
+ render: () => actions
880
+ }),
881
+ /**
882
+ * Custom render column
883
+ *
884
+ * @example
885
+ * columns.custom('fullName', 'Name', (item) => `${item.firstName} ${item.lastName}`)
886
+ */
887
+ custom: (key, label, render, options) => ({
888
+ key,
889
+ label,
890
+ sortable: (options == null ? void 0 : options.sortable) ?? false,
891
+ width: options == null ? void 0 : options.width,
892
+ render
893
+ }),
894
+ /**
895
+ * Truncated text column
896
+ *
897
+ * @example
898
+ * columns.truncate('description', 'Description', 50)
899
+ */
900
+ truncate: (key, label, maxLength, options) => ({
901
+ key,
902
+ label,
903
+ type: "text",
904
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
905
+ render: (item) => {
906
+ const value = String(item[key] ?? "");
907
+ if (value.length <= maxLength) return value;
908
+ return `${value.substring(0, maxLength)}...`;
909
+ }
910
+ }),
911
+ /**
912
+ * Image column
913
+ *
914
+ * @example
915
+ * columns.image('avatar', 'Avatar', { size: 32 })
916
+ */
917
+ image: (key, label, options) => ({
918
+ key,
919
+ label,
920
+ sortable: false,
921
+ render: (item) => ({
922
+ content: item[key] || (options == null ? void 0 : options.fallback),
923
+ type: "image",
924
+ size: (options == null ? void 0 : options.size) ?? 32
925
+ })
926
+ }),
927
+ /**
928
+ * Progress column
929
+ *
930
+ * @example
931
+ * columns.progress('completion', 'Progress')
932
+ */
933
+ progress: (key, label, options) => ({
934
+ key,
935
+ label,
936
+ type: "number",
937
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
938
+ render: (item) => ({
939
+ content: item[key],
940
+ type: "progress",
941
+ max: (options == null ? void 0 : options.max) ?? 100
942
+ })
943
+ }),
944
+ /**
945
+ * Clickable link column that emits an action
946
+ *
947
+ * @example
948
+ * // Simple link with action
949
+ * columns.link('name', 'Campaign Name', (item) => ({
950
+ * action: 'view',
951
+ * data: { id: item.id }
952
+ * }))
953
+ *
954
+ * // Link with custom emit handler in parent
955
+ * columns.link('title', 'Title', (item) => ({
956
+ * action: 'openDetails',
957
+ * data: item
958
+ * }))
959
+ */
960
+ link: (key, label, emitConfig, options) => ({
961
+ key,
962
+ label,
963
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
964
+ width: options == null ? void 0 : options.width,
965
+ render: (item) => ({
966
+ content: item[key],
967
+ type: "link",
968
+ emits: emitConfig(item)
969
+ })
970
+ }),
971
+ /**
972
+ * Link to external URL
973
+ *
974
+ * @example
975
+ * columns.externalLink('website', 'Website')
976
+ * columns.externalLink('url', 'URL', { newTab: true })
977
+ */
978
+ externalLink: (key, label, options) => ({
979
+ key,
980
+ label,
981
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
982
+ render: (item) => {
983
+ const url = item[key];
984
+ const display = (options == null ? void 0 : options.displayKey) ? item[options.displayKey] : url;
985
+ return {
986
+ content: display,
987
+ type: "link",
988
+ href: url,
989
+ target: (options == null ? void 0 : options.newTab) ? "_blank" : void 0
990
+ };
991
+ }
992
+ }),
993
+ /**
994
+ * Relative time column (e.g., "2 hours ago")
995
+ *
996
+ * @example
997
+ * columns.relativeTime('updatedAt', 'Last Updated')
998
+ */
999
+ relativeTime: (key, label, options) => ({
1000
+ key,
1001
+ label,
1002
+ type: "date",
1003
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
1004
+ render: (item) => {
1005
+ const value = item[key];
1006
+ if (!value) return "";
1007
+ const date = value instanceof Date ? value : new Date(value);
1008
+ if (Number.isNaN(date.getTime())) return "";
1009
+ const now = /* @__PURE__ */ new Date();
1010
+ const diffMs = now.getTime() - date.getTime();
1011
+ const diffSecs = Math.floor(diffMs / 1e3);
1012
+ const diffMins = Math.floor(diffSecs / 60);
1013
+ const diffHours = Math.floor(diffMins / 60);
1014
+ const diffDays = Math.floor(diffHours / 24);
1015
+ if (diffSecs < 60) return "Just now";
1016
+ if (diffMins < 60) return `${diffMins}m ago`;
1017
+ if (diffHours < 24) return `${diffHours}h ago`;
1018
+ if (diffDays < 7) return `${diffDays}d ago`;
1019
+ return date.toLocaleDateString(options == null ? void 0 : options.locale);
1020
+ }
1021
+ }),
1022
+ /**
1023
+ * User/Avatar column with name and optional subtitle
1024
+ *
1025
+ * @example
1026
+ * columns.user('assignee', 'Assigned To', { avatarKey: 'avatar', subtitleKey: 'email' })
1027
+ */
1028
+ user: (key, label, options) => ({
1029
+ key,
1030
+ label,
1031
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
1032
+ render: (item) => ({
1033
+ content: item[key],
1034
+ type: "guest",
1035
+ avatar: (options == null ? void 0 : options.avatarKey) ? item[options.avatarKey] : void 0,
1036
+ subtitle: (options == null ? void 0 : options.subtitleKey) ? item[options.subtitleKey] : void 0
1037
+ })
1038
+ }),
1039
+ /**
1040
+ * Currency column with formatting
1041
+ *
1042
+ * @example
1043
+ * columns.currency('amount', 'Total', { currency: 'EUR' })
1044
+ * columns.currency('price', 'Price', { currency: 'USD', locale: 'en-US' })
1045
+ */
1046
+ currency: (key, label, options) => ({
1047
+ key,
1048
+ label,
1049
+ type: "number",
1050
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
1051
+ render: (item) => {
1052
+ const value = item[key];
1053
+ if (value === null || value === void 0) return "";
1054
+ return new Intl.NumberFormat((options == null ? void 0 : options.locale) ?? "en-US", {
1055
+ style: "currency",
1056
+ currency: (options == null ? void 0 : options.currency) ?? "EUR"
1057
+ }).format(Number(value));
1058
+ }
1059
+ }),
1060
+ /**
1061
+ * Percentage column
1062
+ *
1063
+ * @example
1064
+ * columns.percentage('openRate', 'Open Rate')
1065
+ * columns.percentage('completion', 'Progress', { decimals: 0 })
1066
+ */
1067
+ percentage: (key, label, options) => ({
1068
+ key,
1069
+ label,
1070
+ type: "number",
1071
+ sortable: (options == null ? void 0 : options.sortable) ?? true,
1072
+ render: (item) => {
1073
+ const value = item[key];
1074
+ if (value === null || value === void 0) return "";
1075
+ const numValue = (options == null ? void 0 : options.multiply) ? Number(value) * 100 : Number(value);
1076
+ return `${numValue.toFixed((options == null ? void 0 : options.decimals) ?? 1)}%`;
1077
+ }
1078
+ })
1079
+ };
1080
+ const statusColors = {
1081
+ active: "green",
1082
+ inactive: "gray",
1083
+ pending: "yellow",
1084
+ approved: "green",
1085
+ rejected: "red",
1086
+ draft: "gray",
1087
+ published: "green",
1088
+ archived: "gray",
1089
+ error: "red",
1090
+ success: "green",
1091
+ warning: "yellow",
1092
+ info: "blue"
1093
+ };
1094
+ function getStatusColor(status) {
1095
+ return statusColors[status == null ? void 0 : status.toLowerCase()] ?? "gray";
1096
+ }
1097
+ function createStatusColorFn(key) {
1098
+ return (item) => getStatusColor(String(item[key]));
1099
+ }
1100
+ const statusOptions = [
1101
+ { label: "Active", value: "active" },
1102
+ { label: "Inactive", value: "inactive" },
1103
+ { label: "Pending", value: "pending" },
1104
+ { label: "Archived", value: "archived" }
1105
+ ];
1106
+ const booleanOptions = [
1107
+ { label: "Yes", value: "true" },
1108
+ { label: "No", value: "false" }
1109
+ ];
1110
+ const filters = {
1111
+ /**
1112
+ * Text search filter
1113
+ *
1114
+ * @example
1115
+ * filters.text('name', 'Name')
1116
+ * filters.text('email', 'Email', 'Search by email address...')
1117
+ */
1118
+ text: (key, label, placeholder) => ({
1119
+ key,
1120
+ label,
1121
+ type: "text",
1122
+ placeholder: placeholder ?? `Search by ${label.toLowerCase()}...`
1123
+ }),
1124
+ /**
1125
+ * Select dropdown filter
1126
+ *
1127
+ * @example
1128
+ * filters.select('role', 'Role', [
1129
+ * { label: 'Admin', value: 'admin' },
1130
+ * { label: 'User', value: 'user' },
1131
+ * ])
1132
+ */
1133
+ select: (key, label, options) => ({
1134
+ key,
1135
+ label,
1136
+ type: "select",
1137
+ options
1138
+ }),
1139
+ /**
1140
+ * Status filter with common status options
1141
+ *
1142
+ * @example
1143
+ * filters.status()
1144
+ * filters.status('state', 'State')
1145
+ * filters.status('status', 'Status', [
1146
+ * { label: 'Active', value: 'active' },
1147
+ * { label: 'Draft', value: 'draft' },
1148
+ * ])
1149
+ */
1150
+ status: (key = "status", label = "Status", options) => ({
1151
+ key,
1152
+ label,
1153
+ type: "select",
1154
+ options: options ?? statusOptions
1155
+ }),
1156
+ /**
1157
+ * Boolean (Yes/No) filter
1158
+ *
1159
+ * @example
1160
+ * filters.boolean('verified', 'Verified')
1161
+ * filters.boolean('active', 'Active', 'Enabled', 'Disabled')
1162
+ */
1163
+ boolean: (key, label, trueLabel = "Yes", falseLabel = "No") => ({
1164
+ key,
1165
+ label,
1166
+ type: "select",
1167
+ options: [
1168
+ { label: trueLabel, value: "true" },
1169
+ { label: falseLabel, value: "false" }
1170
+ ]
1171
+ }),
1172
+ /**
1173
+ * Number filter
1174
+ *
1175
+ * @example
1176
+ * filters.number('age', 'Age')
1177
+ * filters.number('amount', 'Amount', 'Enter amount...')
1178
+ */
1179
+ number: (key, label, placeholder) => ({
1180
+ key,
1181
+ label,
1182
+ type: "number",
1183
+ placeholder: placeholder ?? `Enter ${label.toLowerCase()}...`
1184
+ }),
1185
+ /**
1186
+ * Date filter
1187
+ *
1188
+ * @example
1189
+ * filters.date('createdAt', 'Created Date')
1190
+ */
1191
+ date: (key, label) => ({
1192
+ key,
1193
+ label,
1194
+ type: "date"
1195
+ }),
1196
+ /**
1197
+ * Date range filter
1198
+ *
1199
+ * @example
1200
+ * filters.dateRange('createdAt', 'Created')
1201
+ */
1202
+ dateRange: (key, label) => ({
1203
+ key,
1204
+ label,
1205
+ type: "dateRange"
1206
+ }),
1207
+ /**
1208
+ * Role filter with common role options
1209
+ *
1210
+ * @example
1211
+ * filters.role()
1212
+ * filters.role('userRole', 'User Role')
1213
+ */
1214
+ role: (key = "role", label = "Role", options) => ({
1215
+ key,
1216
+ label,
1217
+ type: "select",
1218
+ options: options ?? [
1219
+ { label: "Admin", value: "admin" },
1220
+ { label: "Manager", value: "manager" },
1221
+ { label: "User", value: "user" },
1222
+ { label: "Guest", value: "guest" }
1223
+ ]
1224
+ }),
1225
+ /**
1226
+ * Type filter (generic entity type)
1227
+ *
1228
+ * @example
1229
+ * filters.type('campaignType', 'Type', [
1230
+ * { label: 'Email', value: 'email' },
1231
+ * { label: 'SMS', value: 'sms' },
1232
+ * ])
1233
+ */
1234
+ type: (key, label, options) => ({
1235
+ key,
1236
+ label,
1237
+ type: "select",
1238
+ options
1239
+ }),
1240
+ /**
1241
+ * Priority filter
1242
+ *
1243
+ * @example
1244
+ * filters.priority()
1245
+ * filters.priority('urgency', 'Urgency')
1246
+ */
1247
+ priority: (key = "priority", label = "Priority") => ({
1248
+ key,
1249
+ label,
1250
+ type: "select",
1251
+ options: [
1252
+ { label: "Low", value: "low" },
1253
+ { label: "Medium", value: "medium" },
1254
+ { label: "High", value: "high" },
1255
+ { label: "Critical", value: "critical" }
1256
+ ]
1257
+ }),
1258
+ /**
1259
+ * Category filter from dynamic options
1260
+ *
1261
+ * @example
1262
+ * // From array of objects
1263
+ * filters.fromData('categoryId', 'Category', categories, 'name', 'id')
1264
+ */
1265
+ fromData: (key, label, data, labelKey, valueKey) => ({
1266
+ key,
1267
+ label,
1268
+ type: "select",
1269
+ options: data.map((item) => ({
1270
+ label: String(item[labelKey]),
1271
+ value: item[valueKey]
1272
+ }))
1273
+ }),
1274
+ /**
1275
+ * Enum filter from TypeScript enum
1276
+ *
1277
+ * @example
1278
+ * enum Status { Active = 'active', Inactive = 'inactive' }
1279
+ * filters.fromEnum('status', 'Status', Status)
1280
+ */
1281
+ fromEnum: (key, label, enumObj) => ({
1282
+ key,
1283
+ label,
1284
+ type: "select",
1285
+ options: Object.entries(enumObj).filter(([k]) => Number.isNaN(Number(k))).map(([enumKey, enumValue]) => ({
1286
+ label: enumKey.replace(/([A-Z])/g, " $1").trim(),
1287
+ // Convert camelCase to Title Case
1288
+ value: enumValue
1289
+ }))
1290
+ })
1291
+ };
1292
+ function createFilterGroup(config) {
1293
+ const result = [];
1294
+ if (config.search) {
1295
+ config.search.forEach((field) => {
1296
+ result.push(filters.text(field, field.charAt(0).toUpperCase() + field.slice(1)));
1297
+ });
1298
+ }
1299
+ if (config.status) {
1300
+ if (typeof config.status === "boolean") {
1301
+ result.push(filters.status());
1302
+ } else {
1303
+ result.push(filters.status(config.status.key, config.status.label, config.status.options));
1304
+ }
1305
+ }
1306
+ if (config.dateRange) {
1307
+ result.push(filters.dateRange(config.dateRange, "Date Range"));
1308
+ }
1309
+ if (config.custom) {
1310
+ result.push(...config.custom);
1311
+ }
1312
+ return result;
1313
+ }
1314
+ const filterPresets = {
1315
+ /**
1316
+ * Filters for user/account tables
1317
+ */
1318
+ users: () => [
1319
+ filters.text("name", "Name"),
1320
+ filters.text("email", "Email"),
1321
+ filters.role(),
1322
+ filters.status()
1323
+ ],
1324
+ /**
1325
+ * Filters for campaign tables
1326
+ */
1327
+ campaigns: () => [
1328
+ filters.text("name", "Campaign Name"),
1329
+ filters.status("status", "Status", [
1330
+ { label: "Active", value: "active" },
1331
+ { label: "Draft", value: "draft" },
1332
+ { label: "Completed", value: "completed" },
1333
+ { label: "Archived", value: "archived" },
1334
+ { label: "Failed", value: "failed" }
1335
+ ]),
1336
+ filters.dateRange("createdAt", "Created Date")
1337
+ ],
1338
+ /**
1339
+ * Filters for contact tables
1340
+ */
1341
+ contacts: () => [
1342
+ filters.text("name", "Name"),
1343
+ filters.text("email", "Email"),
1344
+ filters.text("phone", "Phone"),
1345
+ filters.status()
1346
+ ],
1347
+ /**
1348
+ * Filters for booking/reservation tables
1349
+ */
1350
+ bookings: () => [
1351
+ filters.text("guestName", "Guest Name"),
1352
+ filters.text("confirmationNumber", "Confirmation #"),
1353
+ filters.status("status", "Status", [
1354
+ { label: "Confirmed", value: "confirmed" },
1355
+ { label: "Pending", value: "pending" },
1356
+ { label: "Cancelled", value: "cancelled" },
1357
+ { label: "Completed", value: "completed" }
1358
+ ]),
1359
+ filters.dateRange("checkIn", "Check-in Date")
1360
+ ],
1361
+ /**
1362
+ * Filters for audit/log tables
1363
+ */
1364
+ auditLogs: () => [
1365
+ filters.text("action", "Action"),
1366
+ filters.text("user", "User"),
1367
+ filters.dateRange("timestamp", "Date")
1368
+ ]
1369
+ };
1370
+ export {
1371
+ Table as T,
1372
+ _sfc_main$3 as _,
1373
+ _sfc_main$2 as a,
1374
+ _sfc_main$1 as b,
1375
+ _sfc_main as c,
1376
+ columns as d,
1377
+ createStatusColorFn as e,
1378
+ filters as f,
1379
+ getStatusColor as g,
1380
+ filterPresets as h,
1381
+ createFilterGroup as i,
1382
+ statusOptions as j,
1383
+ booleanOptions as k,
1384
+ statusColors as s
1385
+ };
1386
+ //# sourceMappingURL=filterHelpers-DgRyoYSa.js.map