@atscript/vue-table 0.1.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/dist/as-action-form-dialog.cjs +221 -0
- package/dist/as-action-form-dialog.d.cts +6 -0
- package/dist/as-action-form-dialog.d.mts +7 -0
- package/dist/as-action-form-dialog.mjs +221 -0
- package/dist/as-action-menu-content-CXsdPn42.mjs +104 -0
- package/dist/as-action-menu-content-CyUfBrWH.cjs +109 -0
- package/dist/as-cell-array-CXeZzZqt.cjs +69 -0
- package/dist/as-cell-array-DOQKR6t5.mjs +64 -0
- package/dist/as-cell-array.cjs +3 -0
- package/dist/as-cell-array.d.cts +2 -0
- package/dist/as-cell-array.d.mts +2 -0
- package/dist/as-cell-array.mjs +3 -0
- package/dist/as-cell-array.vue-DZGM2VHh.d.mts +12 -0
- package/dist/as-cell-array.vue-pFs5GcCR.d.cts +12 -0
- package/dist/as-cell-date-CTrvxS1h.cjs +78 -0
- package/dist/as-cell-date-Cq49RHmL.mjs +73 -0
- package/dist/as-cell-date.cjs +3 -0
- package/dist/as-cell-date.d.cts +2 -0
- package/dist/as-cell-date.d.mts +2 -0
- package/dist/as-cell-date.mjs +3 -0
- package/dist/as-cell-date.vue-BBSps2B2.d.cts +12 -0
- package/dist/as-cell-date.vue-Zlt4mHWb.d.mts +12 -0
- package/dist/as-cell-json-BynWIs1d.mjs +37 -0
- package/dist/as-cell-json-DvHvQ6IL.cjs +42 -0
- package/dist/as-cell-json-popover-BWdNs1YU.cjs +70 -0
- package/dist/as-cell-json-popover-DUq25I0L.mjs +65 -0
- package/dist/as-cell-json.cjs +3 -0
- package/dist/as-cell-json.d.cts +2 -0
- package/dist/as-cell-json.d.mts +2 -0
- package/dist/as-cell-json.mjs +3 -0
- package/dist/as-cell-json.vue-C6wg4ARZ.d.cts +12 -0
- package/dist/as-cell-json.vue-CESWuCer.d.mts +12 -0
- package/dist/as-cell-number-0_WrSCzu.cjs +76 -0
- package/dist/as-cell-number-Bc1C97Vg.mjs +71 -0
- package/dist/as-cell-number.cjs +3 -0
- package/dist/as-cell-number.d.cts +2 -0
- package/dist/as-cell-number.d.mts +2 -0
- package/dist/as-cell-number.mjs +3 -0
- package/dist/as-cell-number.vue-1Oq7nVI3.d.mts +12 -0
- package/dist/as-cell-number.vue-CJ2K5zeM.d.cts +12 -0
- package/dist/as-cell-union-C1w3B38J.mjs +88 -0
- package/dist/as-cell-union-CFAI0utz.cjs +93 -0
- package/dist/as-cell-union.cjs +4 -0
- package/dist/as-cell-union.d.cts +2 -0
- package/dist/as-cell-union.d.mts +2 -0
- package/dist/as-cell-union.mjs +4 -0
- package/dist/as-cell-union.vue-CslPM_c2.d.cts +12 -0
- package/dist/as-cell-union.vue-NnDmQZOA.d.mts +12 -0
- package/dist/as-column-menu-CH9Htz0Q.cjs +220 -0
- package/dist/as-column-menu-DCfhorMP.mjs +215 -0
- package/dist/as-column-menu.cjs +2 -0
- package/dist/as-column-menu.d.cts +2 -0
- package/dist/as-column-menu.d.mts +2 -0
- package/dist/as-column-menu.mjs +2 -0
- package/dist/as-column-menu.vue-C9e6wJ3z.d.mts +47 -0
- package/dist/as-column-menu.vue-o0qFdzoL.d.cts +47 -0
- package/dist/as-config-dialog-d2k7_l0U.cjs +699 -0
- package/dist/as-config-dialog-vRklaKbi.mjs +688 -0
- package/dist/as-config-dialog.cjs +3 -0
- package/dist/as-config-dialog.d.cts +2 -0
- package/dist/as-config-dialog.d.mts +2 -0
- package/dist/as-config-dialog.mjs +3 -0
- package/dist/as-config-dialog.vue-C6Q62xF5.d.mts +7 -0
- package/dist/as-config-dialog.vue-DvvJi3xx.d.cts +7 -0
- package/dist/as-confirm-dialog-BLh3Ju4-.mjs +52 -0
- package/dist/as-confirm-dialog-BgpIEE2z.cjs +57 -0
- package/dist/as-confirm-dialog.cjs +3 -0
- package/dist/as-confirm-dialog.d.cts +2 -0
- package/dist/as-confirm-dialog.d.mts +2 -0
- package/dist/as-confirm-dialog.mjs +3 -0
- package/dist/as-confirm-dialog.vue-CXxLpzbu.d.cts +7 -0
- package/dist/as-confirm-dialog.vue-pas8jGhv.d.mts +7 -0
- package/dist/as-filter-dialog-C0HMpUPT.mjs +610 -0
- package/dist/as-filter-dialog-DcGvIV3h.cjs +621 -0
- package/dist/as-filter-dialog.cjs +15 -0
- package/dist/as-filter-dialog.d.cts +2 -0
- package/dist/as-filter-dialog.d.mts +2 -0
- package/dist/as-filter-dialog.mjs +15 -0
- package/dist/as-filter-dialog.vue-BV2J8PgZ.d.cts +7 -0
- package/dist/as-filter-dialog.vue-RDZjp4gJ.d.mts +7 -0
- package/dist/as-filter-field-B_tYzvvl.cjs +984 -0
- package/dist/as-filter-field-Bqvu2ASN.mjs +943 -0
- package/dist/as-filter-field.cjs +9 -0
- package/dist/as-filter-field.d.cts +2 -0
- package/dist/as-filter-field.d.mts +2 -0
- package/dist/as-filter-field.mjs +9 -0
- package/dist/as-filter-field.vue-ByQ8xIGq.d.cts +11 -0
- package/dist/as-filter-field.vue-QY8wi5S5.d.mts +11 -0
- package/dist/as-filter-input--nr72iwX.cjs +106 -0
- package/dist/as-filter-input-P1i0CW2-.mjs +101 -0
- package/dist/as-filter-input.cjs +2 -0
- package/dist/as-filter-input.d.cts +2 -0
- package/dist/as-filter-input.d.mts +2 -0
- package/dist/as-filter-input.mjs +2 -0
- package/dist/as-filter-input.vue-CBQ71eNg.d.mts +18 -0
- package/dist/as-filter-input.vue-CS4nOk_Q.d.cts +18 -0
- package/dist/as-filters-Bxa9ZEMm.mjs +44 -0
- package/dist/as-filters-xRT2qv56.cjs +49 -0
- package/dist/as-filters.cjs +10 -0
- package/dist/as-filters.d.cts +2 -0
- package/dist/as-filters.d.mts +2 -0
- package/dist/as-filters.mjs +10 -0
- package/dist/as-filters.vue-BsMgYUcX.d.mts +10 -0
- package/dist/as-filters.vue-fv-tRL2H.d.cts +10 -0
- package/dist/as-preset-dialog-BaTfwMnh.cjs +569 -0
- package/dist/as-preset-dialog-BdDRgwf_.mjs +564 -0
- package/dist/as-preset-dialog.cjs +4 -0
- package/dist/as-preset-dialog.d.cts +2 -0
- package/dist/as-preset-dialog.d.mts +2 -0
- package/dist/as-preset-dialog.mjs +4 -0
- package/dist/as-preset-dialog.vue-Bzv-ON9W.d.mts +7 -0
- package/dist/as-preset-dialog.vue-DP9fy00Y.d.cts +7 -0
- package/dist/as-preset-picker-BQbNEiy9.mjs +427 -0
- package/dist/as-preset-picker-Ce3crTQy.cjs +432 -0
- package/dist/as-preset-picker.cjs +4 -0
- package/dist/as-preset-picker.d.cts +2 -0
- package/dist/as-preset-picker.d.mts +2 -0
- package/dist/as-preset-picker.mjs +4 -0
- package/dist/as-preset-picker.vue-CTBk6leV.d.mts +7 -0
- package/dist/as-preset-picker.vue-DfXS3pGl.d.cts +7 -0
- package/dist/as-row-actions-B6Kob6gt.cjs +120 -0
- package/dist/as-row-actions-CeWBBGqh.mjs +115 -0
- package/dist/as-row-actions.cjs +4 -0
- package/dist/as-row-actions.d.cts +2 -0
- package/dist/as-row-actions.d.mts +2 -0
- package/dist/as-row-actions.mjs +4 -0
- package/dist/as-row-actions.vue-BPaQfGev.d.mts +11 -0
- package/dist/as-row-actions.vue-Bvcc2tUN.d.cts +11 -0
- package/dist/as-table-Cnw2fOqZ.mjs +204 -0
- package/dist/as-table-DlDFxdXI.cjs +209 -0
- package/dist/as-table-actions-BK1Thy2G.cjs +142 -0
- package/dist/as-table-actions-BpMiNFni.mjs +137 -0
- package/dist/as-table-actions.cjs +4 -0
- package/dist/as-table-actions.d.cts +2 -0
- package/dist/as-table-actions.d.mts +2 -0
- package/dist/as-table-actions.mjs +4 -0
- package/dist/as-table-actions.vue-B7Q-JA3z.d.cts +47 -0
- package/dist/as-table-actions.vue-Bs1Jl1ep.d.mts +47 -0
- package/dist/as-table-base-D0k4k7k_.mjs +646 -0
- package/dist/as-table-base-VIz-B_6_.cjs +651 -0
- package/dist/as-table-cell-value-B1CiJYFn.mjs +26 -0
- package/dist/as-table-cell-value-CuxRtFn9.cjs +31 -0
- package/dist/as-table-cell-value.cjs +3 -0
- package/dist/as-table-cell-value.d.cts +2 -0
- package/dist/as-table-cell-value.d.mts +2 -0
- package/dist/as-table-cell-value.mjs +3 -0
- package/dist/as-table-cell-value.vue-BgFDv2JQ.d.cts +12 -0
- package/dist/as-table-cell-value.vue-BuPCQ8YA.d.mts +12 -0
- package/dist/as-table-header-cell-C3zeZUZo.cjs +117 -0
- package/dist/as-table-header-cell-CBn_ioCe.mjs +112 -0
- package/dist/as-table-header-cell.cjs +3 -0
- package/dist/as-table-header-cell.d.cts +2 -0
- package/dist/as-table-header-cell.d.mts +2 -0
- package/dist/as-table-header-cell.mjs +3 -0
- package/dist/as-table-header-cell.vue-Bc_DSsGY.d.cts +31 -0
- package/dist/as-table-header-cell.vue-DNMOHfek.d.mts +31 -0
- package/dist/as-table-root-Br6WcGRo.cjs +263 -0
- package/dist/as-table-root-gG7pTIdD.mjs +258 -0
- package/dist/as-table-root.cjs +28 -0
- package/dist/as-table-root.d.cts +2 -0
- package/dist/as-table-root.d.mts +2 -0
- package/dist/as-table-root.mjs +28 -0
- package/dist/as-table-root.vue-5_OhVwse.d.mts +2258 -0
- package/dist/as-table-root.vue-CSqEtIll.d.cts +2258 -0
- package/dist/as-table-status-BjRGGuhC.mjs +683 -0
- package/dist/as-table-status-DWYoJIMC.cjs +724 -0
- package/dist/as-table.cjs +10 -0
- package/dist/as-table.d.cts +2 -0
- package/dist/as-table.d.mts +2 -0
- package/dist/as-table.mjs +10 -0
- package/dist/as-table.vue-BTYg-e3Z.d.mts +81 -0
- package/dist/as-table.vue-wdRARLIe.d.cts +81 -0
- package/dist/as-window-table-CKIfo3M_.mjs +709 -0
- package/dist/as-window-table-DE7_NyEP.cjs +714 -0
- package/dist/as-window-table.cjs +9 -0
- package/dist/as-window-table.d.cts +2 -0
- package/dist/as-window-table.d.mts +2 -0
- package/dist/as-window-table.mjs +9 -0
- package/dist/as-window-table.vue-Bf8xGC9M.d.mts +86 -0
- package/dist/as-window-table.vue-CA8qsrz4.d.cts +86 -0
- package/dist/format-cell-B2xMDYO9.mjs +27 -0
- package/dist/format-cell-D4mqaN0E.cjs +32 -0
- package/dist/get-cell-value-CZSVfDLg.cjs +19 -0
- package/dist/get-cell-value-DiH84HKL.mjs +14 -0
- package/dist/index.cjs +598 -0
- package/dist/index.d.cts +21 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +505 -0
- package/dist/preset-aspect-display-BYeiSgcc.mjs +43 -0
- package/dist/preset-aspect-display-y8aal_EF.cjs +72 -0
- package/dist/types-BvvXN72P.d.mts +531 -0
- package/dist/types-CNMmF6W2.d.cts +531 -0
- package/dist/use-cell-locale-1uQaFTLQ.mjs +23 -0
- package/dist/use-cell-locale-B480_QYK.cjs +34 -0
- package/dist/use-table-column-handlers-CGYAY2xH.cjs +65 -0
- package/dist/use-table-column-handlers-t6xi1yCE.mjs +54 -0
- package/dist/use-table-state-C4JbonEZ.mjs +1822 -0
- package/dist/use-table-state-MU-vuzui.cjs +1917 -0
- package/package.json +195 -0
- package/styles.d.ts +2 -0
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
const require_use_table_state = require("./use-table-state-MU-vuzui.cjs");
|
|
2
|
+
const require_as_table_status = require("./as-table-status-DWYoJIMC.cjs");
|
|
3
|
+
const require_as_table_base = require("./as-table-base-VIz-B_6_.cjs");
|
|
4
|
+
let _atscript_ui = require("@atscript/ui");
|
|
5
|
+
let vue = require("vue");
|
|
6
|
+
let _atscript_ui_table = require("@atscript/ui-table");
|
|
7
|
+
let _vueuse_core = require("@vueuse/core");
|
|
8
|
+
let reka_ui = require("reka-ui");
|
|
9
|
+
//#region src/composables/as-presets-app.ts
|
|
10
|
+
/**
|
|
11
|
+
* App-wide injection key for the presets system. The host app calls
|
|
12
|
+
* `app.provide(AS_PRESETS_APP, '<your-app>')` once at boot; every
|
|
13
|
+
* `<AsTableRoot>`, `usePresets`, and `useAppPrefs` call below it pulls the
|
|
14
|
+
* value via `inject(AS_PRESETS_APP)` unless an explicit `app` option
|
|
15
|
+
* overrides it.
|
|
16
|
+
*
|
|
17
|
+
* The string identifies the application namespace on the server side —
|
|
18
|
+
* one Moost backend can serve many apps; rows are scoped by `(app,
|
|
19
|
+
* tableKey)`.
|
|
20
|
+
*/
|
|
21
|
+
const AS_PRESETS_APP = Symbol("AS_PRESETS_APP");
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the app name with these precedence rules:
|
|
24
|
+
*
|
|
25
|
+
* 1. `explicit` argument (composable option) — wins.
|
|
26
|
+
* 2. `inject(AS_PRESETS_APP)` from the Vue tree.
|
|
27
|
+
* 3. Throws — composable can't run without an app namespace.
|
|
28
|
+
*
|
|
29
|
+
* Throws a clear error when neither is available so misconfiguration
|
|
30
|
+
* surfaces at setup time, not when the first network round-trip fails.
|
|
31
|
+
*/
|
|
32
|
+
function injectPresetsApp(explicit) {
|
|
33
|
+
if (explicit && explicit.length > 0) return explicit;
|
|
34
|
+
const fromProvide = (0, vue.inject)(AS_PRESETS_APP, void 0);
|
|
35
|
+
if (fromProvide && fromProvide.length > 0) return fromProvide;
|
|
36
|
+
throw new Error("[vue-table] AS_PRESETS_APP not provided. Call `app.provide(AS_PRESETS_APP, '<your-app>')` once at boot, or pass `app` to the composable.");
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/composables/use-local-draft.ts
|
|
40
|
+
const DEFAULT_DEBOUNCE_MS = 300;
|
|
41
|
+
/**
|
|
42
|
+
* localStorage overlay manager for table presets. One overlay per
|
|
43
|
+
* `(app, tableKey)`; switching presets clears it (caller's responsibility
|
|
44
|
+
* — this composable only tracks state, not which preset is active).
|
|
45
|
+
*/
|
|
46
|
+
function useLocalDraft(opts) {
|
|
47
|
+
const key = `as-table-draft:${opts.app}:${opts.tableKey}`;
|
|
48
|
+
const debounceMs = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
49
|
+
const storage = resolveStorage(opts.storage);
|
|
50
|
+
function isEnabled() {
|
|
51
|
+
if (typeof opts.enabled === "boolean") return opts.enabled;
|
|
52
|
+
if ((0, vue.isRef)(opts.enabled)) return Boolean(opts.enabled.value);
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
function readDraft() {
|
|
56
|
+
if (!storage) return null;
|
|
57
|
+
try {
|
|
58
|
+
const raw = storage.getItem(key);
|
|
59
|
+
if (!raw) return null;
|
|
60
|
+
const parsed = JSON.parse(raw);
|
|
61
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
62
|
+
return parsed;
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.warn("[vue-table] useLocalDraft: corrupted localStorage entry, ignoring", err);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function writeDraft(draft) {
|
|
69
|
+
if (!storage) return;
|
|
70
|
+
try {
|
|
71
|
+
storage.setItem(key, JSON.stringify(draft));
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.warn("[vue-table] useLocalDraft: localStorage write failed", err);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function clear() {
|
|
77
|
+
if (!storage) return;
|
|
78
|
+
try {
|
|
79
|
+
storage.removeItem(key);
|
|
80
|
+
} catch {}
|
|
81
|
+
}
|
|
82
|
+
function hydrate(applied) {
|
|
83
|
+
if (!isEnabled()) return applied;
|
|
84
|
+
const draft = readDraft();
|
|
85
|
+
if (!draft || (0, _atscript_ui_table.isEmptyDraft)(draft)) return applied;
|
|
86
|
+
const overlay = (0, _atscript_ui_table.deserializeDraft)(draft, opts.availableAspects);
|
|
87
|
+
return {
|
|
88
|
+
...applied,
|
|
89
|
+
...overlay
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function watchAndPersist(currentSnapshot, activePresetSnapshot) {
|
|
93
|
+
let lastDraftSerialized = "";
|
|
94
|
+
let lastPresetRef = null;
|
|
95
|
+
let lastPresetSerialized = "";
|
|
96
|
+
function flush(current, preset) {
|
|
97
|
+
if (!isEnabled()) return;
|
|
98
|
+
const draft = (0, _atscript_ui_table.serializeDraft)(current, opts.availableAspects);
|
|
99
|
+
if ((0, _atscript_ui_table.isEmptyDraft)(draft)) {
|
|
100
|
+
clear();
|
|
101
|
+
lastDraftSerialized = "";
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const draftSerialized = (0, _atscript_ui_table.stableStringify)(draft);
|
|
105
|
+
if (preset !== lastPresetRef) {
|
|
106
|
+
lastPresetRef = preset;
|
|
107
|
+
lastPresetSerialized = (0, _atscript_ui_table.stableStringify)((0, _atscript_ui_table.serializeDraft)(preset, opts.availableAspects));
|
|
108
|
+
}
|
|
109
|
+
if (draftSerialized === lastPresetSerialized) {
|
|
110
|
+
clear();
|
|
111
|
+
lastDraftSerialized = "";
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (draftSerialized === lastDraftSerialized) return;
|
|
115
|
+
lastDraftSerialized = draftSerialized;
|
|
116
|
+
writeDraft(draft);
|
|
117
|
+
}
|
|
118
|
+
const flushDebounced = (0, _atscript_ui_table.debounce)(((current, preset) => flush(current, preset)), debounceMs);
|
|
119
|
+
const stop = (0, vue.watch)(() => [currentSnapshot(), activePresetSnapshot()], ([current, preset]) => flushDebounced(current, preset), { flush: "post" });
|
|
120
|
+
return () => {
|
|
121
|
+
flushDebounced.cancel();
|
|
122
|
+
stop();
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
hydrate,
|
|
127
|
+
watchAndPersist,
|
|
128
|
+
clear,
|
|
129
|
+
readDraft
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function resolveStorage(provided) {
|
|
133
|
+
if (provided !== void 0) return provided;
|
|
134
|
+
try {
|
|
135
|
+
return globalThis.localStorage ?? null;
|
|
136
|
+
} catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/composables/use-presets.ts
|
|
142
|
+
/**
|
|
143
|
+
* Public dev-facing composable for table presets. Powers `<AsPresetPicker>`
|
|
144
|
+
* internally and is exported for devs who want to wire bespoke surfaces.
|
|
145
|
+
*
|
|
146
|
+
* Stateful: holds reactive `presets` / `userConf` / `capabilities` and
|
|
147
|
+
* supports optimistic mutators that re-list after each successful write.
|
|
148
|
+
*
|
|
149
|
+
* Active-preset selection (`activePresetId`) is **owned by the caller** —
|
|
150
|
+
* the composable provides the ref but doesn't auto-resolve it on mount;
|
|
151
|
+
* that's the table-state's responsibility (Slice 4) since it depends on
|
|
152
|
+
* `userConf.defaultPresetId` resolution + Standard fallback.
|
|
153
|
+
*/
|
|
154
|
+
function usePresets(opts) {
|
|
155
|
+
const app = injectPresetsApp(opts.app);
|
|
156
|
+
if (!opts.tableKey) throw new Error("[vue-table] usePresets: `tableKey` is required");
|
|
157
|
+
const client = new _atscript_ui_table.PresetsClient({
|
|
158
|
+
url: opts.url,
|
|
159
|
+
app,
|
|
160
|
+
tableKey: opts.tableKey,
|
|
161
|
+
clientFactory: opts.clientFactory
|
|
162
|
+
});
|
|
163
|
+
const systemPresetsResolved = (0, vue.computed)(() => (0, _atscript_ui_table.resolveSystemPresets)(opts.systemPresets));
|
|
164
|
+
const presets = (0, vue.shallowRef)([]);
|
|
165
|
+
const userConf = (0, vue.shallowRef)(null);
|
|
166
|
+
const capabilities = (0, vue.ref)(null);
|
|
167
|
+
const loading = (0, vue.ref)(false);
|
|
168
|
+
const error = (0, vue.ref)(null);
|
|
169
|
+
const denied = (0, vue.ref)(false);
|
|
170
|
+
const activePresetId = (0, vue.ref)(null);
|
|
171
|
+
const available = (0, vue.computed)(() => !denied.value);
|
|
172
|
+
const presetsById = (0, vue.computed)(() => {
|
|
173
|
+
const map = /* @__PURE__ */ new Map();
|
|
174
|
+
for (const row of presets.value) map.set(row.id, row);
|
|
175
|
+
return map;
|
|
176
|
+
});
|
|
177
|
+
const systemPresetsById = (0, vue.computed)(() => {
|
|
178
|
+
const map = /* @__PURE__ */ new Map();
|
|
179
|
+
for (const sp of systemPresetsResolved.value) map.set(sp.id, sp);
|
|
180
|
+
return map;
|
|
181
|
+
});
|
|
182
|
+
const activePreset = (0, vue.computed)(() => {
|
|
183
|
+
const id = activePresetId.value;
|
|
184
|
+
if (!id) return null;
|
|
185
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) {
|
|
186
|
+
const entry = systemPresetsById.value.get(id);
|
|
187
|
+
return entry ? {
|
|
188
|
+
kind: "system",
|
|
189
|
+
entry
|
|
190
|
+
} : null;
|
|
191
|
+
}
|
|
192
|
+
const entry = presetsById.value.get(id);
|
|
193
|
+
return entry ? {
|
|
194
|
+
kind: "stored",
|
|
195
|
+
entry
|
|
196
|
+
} : null;
|
|
197
|
+
});
|
|
198
|
+
const currentUser = (0, vue.computed)(() => {
|
|
199
|
+
const fromCaps = capabilities.value?.userId;
|
|
200
|
+
if (typeof fromCaps === "string" && fromCaps.length > 0) return fromCaps;
|
|
201
|
+
for (const row of presets.value) if (row.public !== true && typeof row.user === "string" && row.user.length > 0) return row.user;
|
|
202
|
+
return null;
|
|
203
|
+
});
|
|
204
|
+
function isOwned(id) {
|
|
205
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) return false;
|
|
206
|
+
const row = presetsById.value.get(id);
|
|
207
|
+
if (!row) return false;
|
|
208
|
+
if (row.public !== true) return true;
|
|
209
|
+
const me = currentUser.value;
|
|
210
|
+
return me !== null && row.user === me;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* @param opts.capabilities — set `false` for refresh-after-mutation calls
|
|
214
|
+
* (fav-toggle, save, rename, delete, public-toggle, set-default) where
|
|
215
|
+
* role-derived capabilities can't have changed. Default `true`, used
|
|
216
|
+
* only on the initial mount load.
|
|
217
|
+
*/
|
|
218
|
+
let batchDepth = 0;
|
|
219
|
+
let reloadPending = false;
|
|
220
|
+
async function maybeReloadAfterMutation() {
|
|
221
|
+
if (batchDepth > 0) {
|
|
222
|
+
reloadPending = true;
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
await reload({ capabilities: false });
|
|
226
|
+
}
|
|
227
|
+
async function batch(fn) {
|
|
228
|
+
batchDepth++;
|
|
229
|
+
try {
|
|
230
|
+
return await fn();
|
|
231
|
+
} finally {
|
|
232
|
+
batchDepth--;
|
|
233
|
+
if (batchDepth === 0 && reloadPending) {
|
|
234
|
+
reloadPending = false;
|
|
235
|
+
await reload({ capabilities: false });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function reload(opts = {}) {
|
|
240
|
+
loading.value = true;
|
|
241
|
+
error.value = null;
|
|
242
|
+
try {
|
|
243
|
+
const result = await client.list(opts);
|
|
244
|
+
if (result.denied) {
|
|
245
|
+
denied.value = true;
|
|
246
|
+
presets.value = [];
|
|
247
|
+
userConf.value = null;
|
|
248
|
+
capabilities.value = null;
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
denied.value = false;
|
|
252
|
+
presets.value = result.presets;
|
|
253
|
+
userConf.value = result.userConf;
|
|
254
|
+
if (result.capabilities !== void 0) capabilities.value = result.capabilities;
|
|
255
|
+
} catch (err) {
|
|
256
|
+
if ((0, _atscript_ui_table.isAuthError)(err)) {
|
|
257
|
+
denied.value = true;
|
|
258
|
+
presets.value = [];
|
|
259
|
+
userConf.value = null;
|
|
260
|
+
capabilities.value = null;
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
error.value = err;
|
|
264
|
+
console.warn("[vue-table] usePresets load failed:", err);
|
|
265
|
+
} finally {
|
|
266
|
+
loading.value = false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function savePreset(snapshot) {
|
|
270
|
+
const id = activePresetId.value;
|
|
271
|
+
if (!id) throw new Error("[vue-table] usePresets.savePreset: no active preset");
|
|
272
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) throw new Error("[vue-table] usePresets.savePreset: system presets cannot be overwritten");
|
|
273
|
+
const row = presetsById.value.get(id);
|
|
274
|
+
const label = row?.label ?? (row?.data)?.label ?? "";
|
|
275
|
+
if (!label) throw new Error("[vue-table] usePresets.savePreset: existing preset has no label");
|
|
276
|
+
await client.savePreset(id, label, snapshot);
|
|
277
|
+
await maybeReloadAfterMutation();
|
|
278
|
+
}
|
|
279
|
+
async function savePresetAs(label, snapshot, saveOpts = {}) {
|
|
280
|
+
const result = await client.savePresetAs(label, snapshot, saveOpts);
|
|
281
|
+
await maybeReloadAfterMutation();
|
|
282
|
+
activePresetId.value = result.id;
|
|
283
|
+
return result.id;
|
|
284
|
+
}
|
|
285
|
+
async function renamePreset(id, label) {
|
|
286
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) throw new Error("[vue-table] usePresets.renamePreset: system presets cannot be renamed");
|
|
287
|
+
await client.renamePreset(id, label);
|
|
288
|
+
await maybeReloadAfterMutation();
|
|
289
|
+
}
|
|
290
|
+
async function deletePreset(id) {
|
|
291
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) throw new Error("[vue-table] usePresets.deletePreset: system presets cannot be deleted");
|
|
292
|
+
await client.deletePreset(id);
|
|
293
|
+
if (activePresetId.value === id) activePresetId.value = _atscript_ui_table.STANDARD_PRESET_ID;
|
|
294
|
+
await maybeReloadAfterMutation();
|
|
295
|
+
}
|
|
296
|
+
async function togglePublic(id) {
|
|
297
|
+
if ((0, _atscript_ui_table.isSystemPresetId)(id)) throw new Error("[vue-table] usePresets.togglePublic: system presets are not public");
|
|
298
|
+
const row = presetsById.value.get(id);
|
|
299
|
+
if (!row) return;
|
|
300
|
+
await client.setPublic(id, row.public !== true);
|
|
301
|
+
await maybeReloadAfterMutation();
|
|
302
|
+
}
|
|
303
|
+
async function setDefault(id) {
|
|
304
|
+
const user = currentUser.value ?? void 0;
|
|
305
|
+
await client.upsertUserConf(userConf.value, { defaultPresetId: id ?? void 0 }, user);
|
|
306
|
+
await maybeReloadAfterMutation();
|
|
307
|
+
}
|
|
308
|
+
async function toggleFav(id) {
|
|
309
|
+
const current = (userConf.value?.data)?.favPresetIds;
|
|
310
|
+
const set = new Set(current ?? []);
|
|
311
|
+
if (set.has(id)) set.delete(id);
|
|
312
|
+
else set.add(id);
|
|
313
|
+
await setFavorites([...set]);
|
|
314
|
+
}
|
|
315
|
+
async function setFavorites(ids) {
|
|
316
|
+
const user = currentUser.value ?? void 0;
|
|
317
|
+
await client.upsertUserConf(userConf.value, { favPresetIds: ids }, user);
|
|
318
|
+
if (userConf.value) userConf.value = {
|
|
319
|
+
...userConf.value,
|
|
320
|
+
data: {
|
|
321
|
+
...userConf.value.data,
|
|
322
|
+
favPresetIds: ids
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
await maybeReloadAfterMutation();
|
|
326
|
+
}
|
|
327
|
+
if (opts.autoLoad !== false) reload();
|
|
328
|
+
return {
|
|
329
|
+
presets,
|
|
330
|
+
presetsById,
|
|
331
|
+
userConf,
|
|
332
|
+
capabilities,
|
|
333
|
+
systemPresets: systemPresetsResolved,
|
|
334
|
+
systemPresetsById,
|
|
335
|
+
available,
|
|
336
|
+
loading,
|
|
337
|
+
error,
|
|
338
|
+
currentUser,
|
|
339
|
+
activePresetId,
|
|
340
|
+
activePreset,
|
|
341
|
+
isOwned,
|
|
342
|
+
reload,
|
|
343
|
+
batch,
|
|
344
|
+
savePreset,
|
|
345
|
+
savePresetAs,
|
|
346
|
+
renamePreset,
|
|
347
|
+
deletePreset,
|
|
348
|
+
togglePublic,
|
|
349
|
+
setDefault,
|
|
350
|
+
toggleFav,
|
|
351
|
+
setFavorites
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
//#endregion
|
|
355
|
+
//#region src/composables/use-table.ts
|
|
356
|
+
/** Thin alias over `resetMetaCache` — retained so existing test code keeps working. */
|
|
357
|
+
function clearTableCache() {
|
|
358
|
+
(0, _atscript_ui.resetMetaCache)();
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Main entry composable for table setup.
|
|
362
|
+
*
|
|
363
|
+
* @param url — Table endpoint URL (e.g. "/db/tables/products")
|
|
364
|
+
*/
|
|
365
|
+
function useTable(url, opts) {
|
|
366
|
+
const entry = (0, _atscript_ui.getMetaEntry)(url, opts?.clientFactory);
|
|
367
|
+
if (!entry.tableDef) entry.tableDef = Promise.all([entry.meta, entry.type]).then(([meta, type]) => (0, _atscript_ui.createTableDef)(meta, type));
|
|
368
|
+
const { client } = entry;
|
|
369
|
+
const defPromise = entry.tableDef;
|
|
370
|
+
const preset = opts?.preset;
|
|
371
|
+
const presetsHandle = preset ? usePresets({
|
|
372
|
+
url: preset.url,
|
|
373
|
+
tableKey: preset.tableKey,
|
|
374
|
+
app: preset.app,
|
|
375
|
+
clientFactory: opts?.clientFactory,
|
|
376
|
+
systemPresets: preset.systemPresets
|
|
377
|
+
}) : null;
|
|
378
|
+
const draftHandle = preset ? useLocalDraft({
|
|
379
|
+
app: injectPresetsApp(preset.app),
|
|
380
|
+
tableKey: preset.tableKey,
|
|
381
|
+
enabled: preset.persistDrafts ?? false,
|
|
382
|
+
availableAspects: preset.aspects ?? require_use_table_state.DEFAULT_AVAILABLE_ASPECTS
|
|
383
|
+
}) : null;
|
|
384
|
+
const { state, internals } = require_use_table_state.createTableState({
|
|
385
|
+
client,
|
|
386
|
+
limit: opts?.limit,
|
|
387
|
+
selection: {
|
|
388
|
+
rowValueFn: opts?.rowValueFn,
|
|
389
|
+
selectedRows: opts?.selectedRows
|
|
390
|
+
},
|
|
391
|
+
model: {
|
|
392
|
+
filterFields: opts?.filterFields,
|
|
393
|
+
columnNames: opts?.columnNames,
|
|
394
|
+
columnWidths: opts?.columnWidths,
|
|
395
|
+
sorters: opts?.sorters
|
|
396
|
+
},
|
|
397
|
+
query: {
|
|
398
|
+
fn: opts?.queryFn,
|
|
399
|
+
forceFilters: opts?.forceFilters,
|
|
400
|
+
forceSorters: opts?.forceSorters,
|
|
401
|
+
blockQuery: opts?.blockQuery,
|
|
402
|
+
queryOnMount: opts?.queryOnMount,
|
|
403
|
+
urlQueryReady: opts?.urlQueryReady,
|
|
404
|
+
onUrlQueryChange: opts?.onUrlQueryChange,
|
|
405
|
+
urlQuerySync: opts?.urlQuerySync
|
|
406
|
+
},
|
|
407
|
+
window: {
|
|
408
|
+
blockSize: opts?.blockSize,
|
|
409
|
+
dragReleaseDebounceMs: opts?.dragReleaseDebounceMs
|
|
410
|
+
},
|
|
411
|
+
actions: {
|
|
412
|
+
refreshOnAction: opts?.refreshOnAction,
|
|
413
|
+
onResolved: opts?.onActionResolved
|
|
414
|
+
},
|
|
415
|
+
preset: {
|
|
416
|
+
presetsHandle,
|
|
417
|
+
draftHandle,
|
|
418
|
+
availableAspects: preset?.aspects,
|
|
419
|
+
persistDrafts: preset?.persistDrafts ?? false
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
require_as_table_status.useTableSelection(state, { mode: opts?.selectionPersistence ?? "trim" });
|
|
423
|
+
if (opts?.provideContext !== false) require_use_table_state.provideTableContext({
|
|
424
|
+
state,
|
|
425
|
+
client,
|
|
426
|
+
controls: opts?.controls ?? {},
|
|
427
|
+
types: opts?.types,
|
|
428
|
+
components: opts?.components,
|
|
429
|
+
formTypes: opts?.formTypes,
|
|
430
|
+
formComponents: opts?.formComponents
|
|
431
|
+
});
|
|
432
|
+
defPromise.then((def) => {
|
|
433
|
+
internals.init(def);
|
|
434
|
+
}).catch((err) => {
|
|
435
|
+
state.metadataError.value = err instanceof Error ? err : new Error(String(err));
|
|
436
|
+
}).finally(() => {
|
|
437
|
+
state.loadingMetadata.value = false;
|
|
438
|
+
});
|
|
439
|
+
return state;
|
|
440
|
+
}
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/composables/use-drag-scroll.ts
|
|
443
|
+
/**
|
|
444
|
+
* Pointer-drag horizontal scroll for a container. Listens for pointerdown on
|
|
445
|
+
* the container, then attaches pointermove / pointerup / pointercancel to
|
|
446
|
+
* `window` so drag stays smooth even when the pointer leaves the container
|
|
447
|
+
* (including dragging over an input or outside the viewport).
|
|
448
|
+
*/
|
|
449
|
+
function useDragScroll(el) {
|
|
450
|
+
let startX = 0;
|
|
451
|
+
let startScroll = 0;
|
|
452
|
+
let dragging = false;
|
|
453
|
+
let pointerId = null;
|
|
454
|
+
function onMove(e) {
|
|
455
|
+
if (pointerId !== e.pointerId || !el.value) return;
|
|
456
|
+
const dx = e.clientX - startX;
|
|
457
|
+
if (!dragging) {
|
|
458
|
+
if (Math.abs(dx) < 4) return;
|
|
459
|
+
dragging = true;
|
|
460
|
+
}
|
|
461
|
+
el.value.scrollLeft = startScroll - dx;
|
|
462
|
+
e.preventDefault();
|
|
463
|
+
}
|
|
464
|
+
function onUp(e) {
|
|
465
|
+
if (pointerId !== e.pointerId) return;
|
|
466
|
+
window.removeEventListener("pointermove", onMove);
|
|
467
|
+
window.removeEventListener("pointerup", onUp);
|
|
468
|
+
window.removeEventListener("pointercancel", onUp);
|
|
469
|
+
pointerId = null;
|
|
470
|
+
dragging = false;
|
|
471
|
+
}
|
|
472
|
+
function onDown(e) {
|
|
473
|
+
const target = e.target;
|
|
474
|
+
if (!el.value || !target) return;
|
|
475
|
+
if (target.closest("input, textarea, button, [role=button], a")) return;
|
|
476
|
+
if (e.button !== 0) return;
|
|
477
|
+
startX = e.clientX;
|
|
478
|
+
startScroll = el.value.scrollLeft;
|
|
479
|
+
pointerId = e.pointerId;
|
|
480
|
+
dragging = false;
|
|
481
|
+
window.addEventListener("pointermove", onMove);
|
|
482
|
+
window.addEventListener("pointerup", onUp);
|
|
483
|
+
window.addEventListener("pointercancel", onUp);
|
|
484
|
+
}
|
|
485
|
+
function onWheel(e) {
|
|
486
|
+
if (!el.value) return;
|
|
487
|
+
const dx = e.deltaX;
|
|
488
|
+
const dy = e.deltaY;
|
|
489
|
+
if (Math.abs(dy) > Math.abs(dx)) {
|
|
490
|
+
el.value.scrollLeft += dy;
|
|
491
|
+
e.preventDefault();
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const attach = (node) => {
|
|
495
|
+
node.addEventListener("pointerdown", onDown);
|
|
496
|
+
node.addEventListener("wheel", onWheel, { passive: false });
|
|
497
|
+
};
|
|
498
|
+
const detach = (node) => {
|
|
499
|
+
node.removeEventListener("pointerdown", onDown);
|
|
500
|
+
node.removeEventListener("wheel", onWheel);
|
|
501
|
+
};
|
|
502
|
+
(0, vue.watch)(el, (node, prev) => {
|
|
503
|
+
if (prev) detach(prev);
|
|
504
|
+
if (node) attach(node);
|
|
505
|
+
}, { immediate: true });
|
|
506
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
507
|
+
if (el.value) detach(el.value);
|
|
508
|
+
window.removeEventListener("pointermove", onMove);
|
|
509
|
+
window.removeEventListener("pointerup", onUp);
|
|
510
|
+
window.removeEventListener("pointercancel", onUp);
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/components/defaults/as-filter-field.vue?vue&type=script&setup=true&lang.ts
|
|
515
|
+
const _hoisted_1 = ["aria-disabled"];
|
|
516
|
+
const _hoisted_2 = ["for"];
|
|
517
|
+
const _hoisted_3 = { class: "as-filter-field-body" };
|
|
518
|
+
const _hoisted_4 = {
|
|
519
|
+
key: 0,
|
|
520
|
+
class: "as-filter-field-loading"
|
|
521
|
+
};
|
|
522
|
+
const _hoisted_5 = ["onClick"];
|
|
523
|
+
const _hoisted_6 = ["id"];
|
|
524
|
+
const _hoisted_7 = { class: "as-filter-field-dropdown-body" };
|
|
525
|
+
const _hoisted_8 = {
|
|
526
|
+
key: 0,
|
|
527
|
+
class: "as-table-query-overlay"
|
|
528
|
+
};
|
|
529
|
+
const _hoisted_9 = {
|
|
530
|
+
key: 0,
|
|
531
|
+
class: "as-vh-empty"
|
|
532
|
+
};
|
|
533
|
+
const _hoisted_10 = {
|
|
534
|
+
key: 0,
|
|
535
|
+
class: "as-vh-empty-body"
|
|
536
|
+
};
|
|
537
|
+
const _hoisted_11 = { class: "as-vh-empty-code" };
|
|
538
|
+
const _hoisted_12 = {
|
|
539
|
+
key: 1,
|
|
540
|
+
class: "as-vh-empty-body"
|
|
541
|
+
};
|
|
542
|
+
const _hoisted_13 = {
|
|
543
|
+
key: 0,
|
|
544
|
+
class: "as-filter-field-dropdown-footer"
|
|
545
|
+
};
|
|
546
|
+
const _hoisted_14 = { class: "as-filter-field-input" };
|
|
547
|
+
const _hoisted_15 = ["onClick"];
|
|
548
|
+
const _hoisted_16 = [
|
|
549
|
+
"id",
|
|
550
|
+
"value",
|
|
551
|
+
"onKeydown"
|
|
552
|
+
];
|
|
553
|
+
//#endregion
|
|
554
|
+
//#region src/components/defaults/as-filter-field.vue
|
|
555
|
+
var as_filter_field_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
556
|
+
__name: "as-filter-field",
|
|
557
|
+
props: { column: {
|
|
558
|
+
type: Object,
|
|
559
|
+
required: true
|
|
560
|
+
} },
|
|
561
|
+
setup(__props) {
|
|
562
|
+
const props = __props;
|
|
563
|
+
const { state } = require_use_table_state.useTableContext();
|
|
564
|
+
const chipsScrollEl = (0, vue.ref)(null);
|
|
565
|
+
useDragScroll(chipsScrollEl);
|
|
566
|
+
const info = props.column.valueHelpInfo;
|
|
567
|
+
const hasValueHelp = !!info;
|
|
568
|
+
const hasOptions = !!(props.column.options && props.column.options.length > 0);
|
|
569
|
+
const hasDropdown = hasValueHelp || hasOptions;
|
|
570
|
+
const filterType = (0, _atscript_ui_table.columnFilterType)(props.column.type);
|
|
571
|
+
let vhClient;
|
|
572
|
+
let innerState;
|
|
573
|
+
const resolved = (0, vue.shallowRef)(null);
|
|
574
|
+
if (hasValueHelp && info) {
|
|
575
|
+
vhClient = new _atscript_ui.ValueHelpClient((0, _atscript_ui.getMetaEntry)(info.url).client);
|
|
576
|
+
innerState = useTable(info.url, {
|
|
577
|
+
select: "none",
|
|
578
|
+
queryOnMount: false,
|
|
579
|
+
limit: 10,
|
|
580
|
+
provideContext: false
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
const dictColumns = (0, vue.computed)(() => {
|
|
584
|
+
if (!resolved.value || !innerState) return [];
|
|
585
|
+
const paths = (0, _atscript_ui.valueHelpDictPaths)(resolved.value);
|
|
586
|
+
return innerState.allColumns.value.filter((c) => paths.has(c.path));
|
|
587
|
+
});
|
|
588
|
+
async function ensureResolved() {
|
|
589
|
+
if (resolved.value) return resolved.value;
|
|
590
|
+
if (!info) return null;
|
|
591
|
+
try {
|
|
592
|
+
resolved.value = await (0, _atscript_ui.resolveValueHelp)(info.url);
|
|
593
|
+
return resolved.value;
|
|
594
|
+
} catch {
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function kickoffResolve() {
|
|
599
|
+
ensureResolved();
|
|
600
|
+
}
|
|
601
|
+
const enumRows = hasOptions ? (0, vue.computed)(() => (props.column.options ?? []).map((opt) => ({
|
|
602
|
+
__key: opt.key,
|
|
603
|
+
__label: opt.label
|
|
604
|
+
}))) : void 0;
|
|
605
|
+
const enumColumns = hasOptions ? [{
|
|
606
|
+
path: "__label",
|
|
607
|
+
label: "Value",
|
|
608
|
+
type: "text",
|
|
609
|
+
sortable: false,
|
|
610
|
+
filterable: false,
|
|
611
|
+
visible: true,
|
|
612
|
+
order: 0
|
|
613
|
+
}] : void 0;
|
|
614
|
+
const dropdownRows = (0, vue.computed)(() => {
|
|
615
|
+
if (innerState) return innerState.results.value;
|
|
616
|
+
if (enumRows) return enumRows.value;
|
|
617
|
+
return [];
|
|
618
|
+
});
|
|
619
|
+
const dropdownColumns = (0, vue.computed)(() => {
|
|
620
|
+
if (hasValueHelp) return dictColumns.value;
|
|
621
|
+
if (enumColumns) return enumColumns;
|
|
622
|
+
return [];
|
|
623
|
+
});
|
|
624
|
+
const dropdownQuerying = (0, vue.computed)(() => {
|
|
625
|
+
if (innerState) return innerState.querying.value;
|
|
626
|
+
return false;
|
|
627
|
+
});
|
|
628
|
+
const dropdownQueryError = (0, vue.computed)(() => {
|
|
629
|
+
if (innerState) return innerState.queryError.value;
|
|
630
|
+
return null;
|
|
631
|
+
});
|
|
632
|
+
const dropdownLoadingMetadata = (0, vue.computed)(() => {
|
|
633
|
+
if (innerState) return innerState.loadingMetadata.value;
|
|
634
|
+
return false;
|
|
635
|
+
});
|
|
636
|
+
const seeAllCount = (0, vue.computed)(() => {
|
|
637
|
+
if (innerState) return innerState.totalCount.value;
|
|
638
|
+
if (enumRows) return enumRows.value.length;
|
|
639
|
+
return 0;
|
|
640
|
+
});
|
|
641
|
+
function extractEqValues(conditions) {
|
|
642
|
+
if (!conditions) return [];
|
|
643
|
+
const values = [];
|
|
644
|
+
for (const c of conditions) if ((0, _atscript_ui_table.isSimpleEq)(c)) values.push(c.value[0]);
|
|
645
|
+
return values;
|
|
646
|
+
}
|
|
647
|
+
const selectedValues = (0, vue.ref)(hasDropdown ? extractEqValues(state.filters.value[props.column.path]) : []);
|
|
648
|
+
if (hasDropdown) {
|
|
649
|
+
(0, vue.watch)(selectedValues, (values) => {
|
|
650
|
+
if ((0, _atscript_ui_table.arraysEqual)(values, extractEqValues(state.filters.value[props.column.path]))) return;
|
|
651
|
+
const nonEq = (state.filters.value[props.column.path] ?? []).filter((c) => c.type !== "eq");
|
|
652
|
+
const merged = [...values.map((v) => ({
|
|
653
|
+
type: "eq",
|
|
654
|
+
value: [v]
|
|
655
|
+
})), ...nonEq];
|
|
656
|
+
if (merged.some(_atscript_ui_table.isFilled)) state.setFieldFilter(props.column.path, merged);
|
|
657
|
+
else state.removeFieldFilter(props.column.path);
|
|
658
|
+
});
|
|
659
|
+
(0, vue.watch)(() => state.filters.value[props.column.path], (conditions) => {
|
|
660
|
+
const newValues = extractEqValues(conditions);
|
|
661
|
+
if ((0, _atscript_ui_table.arraysEqual)(newValues, selectedValues.value)) return;
|
|
662
|
+
selectedValues.value = newValues;
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
const chips = (0, vue.computed)(() => {
|
|
666
|
+
return (state.filters.value[props.column.path] ?? []).filter(_atscript_ui_table.isFilled).map((cond, i) => ({
|
|
667
|
+
key: `${cond.type}:${i}:${String(cond.value[0] ?? "")}`,
|
|
668
|
+
label: (0, _atscript_ui_table.formatFilterCondition)(cond),
|
|
669
|
+
condition: cond
|
|
670
|
+
}));
|
|
671
|
+
});
|
|
672
|
+
function scrollChipsToEnd() {
|
|
673
|
+
(0, vue.nextTick)(() => {
|
|
674
|
+
const el = chipsScrollEl.value;
|
|
675
|
+
if (el) el.scrollLeft = el.scrollWidth;
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
(0, vue.watch)(() => chips.value.length, (len, prev) => {
|
|
679
|
+
if (len > prev) scrollChipsToEnd();
|
|
680
|
+
});
|
|
681
|
+
function rowValueFn(row) {
|
|
682
|
+
if (hasValueHelp && info) return row[info.targetField];
|
|
683
|
+
if (hasOptions) return row.__key;
|
|
684
|
+
}
|
|
685
|
+
const inputId = (0, vue.useId)();
|
|
686
|
+
const searchTerm = (0, vue.ref)("");
|
|
687
|
+
const dropdownOpen = (0, vue.ref)(false);
|
|
688
|
+
if (innerState) (0, vue.watch)(dropdownOpen, async (open) => {
|
|
689
|
+
if (!open) return;
|
|
690
|
+
const r = await ensureResolved();
|
|
691
|
+
await (0, _vueuse_core.until)(() => innerState.tableDef.value).toBeTruthy();
|
|
692
|
+
if (r) {
|
|
693
|
+
const dictPaths = (0, _atscript_ui.valueHelpDictPaths)(r);
|
|
694
|
+
const dictCols = innerState.allColumns.value.filter((c) => dictPaths.has(c.path));
|
|
695
|
+
if (dictCols.length > 0) innerState.columnNames.value = dictCols.map((c) => c.path);
|
|
696
|
+
}
|
|
697
|
+
innerState.query();
|
|
698
|
+
}, { once: true });
|
|
699
|
+
const debouncedSearch = hasValueHelp ? (0, _atscript_ui_table.debounce)(() => {
|
|
700
|
+
doSearch(searchTerm.value);
|
|
701
|
+
}, 500) : void 0;
|
|
702
|
+
(0, vue.onBeforeUnmount)(() => {
|
|
703
|
+
debouncedSearch?.cancel();
|
|
704
|
+
});
|
|
705
|
+
function onSearchInput(event) {
|
|
706
|
+
searchTerm.value = event.target.value;
|
|
707
|
+
if (hasValueHelp) debouncedSearch();
|
|
708
|
+
}
|
|
709
|
+
async function doSearch(text) {
|
|
710
|
+
if (!vhClient || !innerState) return;
|
|
711
|
+
const r = await ensureResolved();
|
|
712
|
+
if (!r) return;
|
|
713
|
+
innerState.querying.value = true;
|
|
714
|
+
try {
|
|
715
|
+
const result = await vhClient.search(r, {
|
|
716
|
+
text: text || void 0,
|
|
717
|
+
mode: "filter",
|
|
718
|
+
limit: 10
|
|
719
|
+
});
|
|
720
|
+
innerState.results.value = result.items;
|
|
721
|
+
innerState.queryError.value = null;
|
|
722
|
+
} catch (err) {
|
|
723
|
+
innerState.results.value = [];
|
|
724
|
+
innerState.queryError.value = err instanceof Error ? err : new Error(String(err));
|
|
725
|
+
} finally {
|
|
726
|
+
innerState.querying.value = false;
|
|
727
|
+
}
|
|
728
|
+
dropdownOpen.value = false;
|
|
729
|
+
await (0, vue.nextTick)();
|
|
730
|
+
await (0, vue.nextTick)();
|
|
731
|
+
await (0, vue.nextTick)();
|
|
732
|
+
dropdownOpen.value = true;
|
|
733
|
+
}
|
|
734
|
+
function filterFunction(val) {
|
|
735
|
+
if (!hasOptions || !searchTerm.value) return val;
|
|
736
|
+
const term = searchTerm.value.toLowerCase();
|
|
737
|
+
return val.filter((item) => {
|
|
738
|
+
if (typeof item === "object" && item !== null) {
|
|
739
|
+
const row = item;
|
|
740
|
+
return String(row.__key ?? "").toLowerCase().includes(term) || String(row.__label ?? "").toLowerCase().includes(term);
|
|
741
|
+
}
|
|
742
|
+
return String(item).toLowerCase().includes(term);
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
const noEnumMatches = (0, vue.computed)(() => {
|
|
746
|
+
if (!dropdownOpen.value || !enumRows) return false;
|
|
747
|
+
return filterFunction(enumRows.value).length === 0;
|
|
748
|
+
});
|
|
749
|
+
function removeChip(chip) {
|
|
750
|
+
const remaining = (state.filters.value[props.column.path] ?? []).filter((c) => c !== chip.condition);
|
|
751
|
+
if (remaining.some(_atscript_ui_table.isFilled)) state.setFieldFilter(props.column.path, remaining);
|
|
752
|
+
else state.removeFieldFilter(props.column.path);
|
|
753
|
+
}
|
|
754
|
+
function clearAll() {
|
|
755
|
+
state.removeFieldFilter(props.column.path);
|
|
756
|
+
}
|
|
757
|
+
function openFilterDialog() {
|
|
758
|
+
dropdownOpen.value = false;
|
|
759
|
+
state.openFilterDialog(props.column);
|
|
760
|
+
}
|
|
761
|
+
function onBackspace() {
|
|
762
|
+
if (searchTerm.value !== "" || chips.value.length === 0) return;
|
|
763
|
+
const filled = (state.filters.value[props.column.path] ?? []).filter(_atscript_ui_table.isFilled);
|
|
764
|
+
if (filled.length === 0) return;
|
|
765
|
+
const remaining = filled.slice(0, -1);
|
|
766
|
+
if (remaining.length > 0) state.setFieldFilter(props.column.path, remaining);
|
|
767
|
+
else state.removeFieldFilter(props.column.path);
|
|
768
|
+
}
|
|
769
|
+
function onAnchorClick() {
|
|
770
|
+
dropdownOpen.value = true;
|
|
771
|
+
kickoffResolve();
|
|
772
|
+
}
|
|
773
|
+
function onInputFocus() {
|
|
774
|
+
dropdownOpen.value = true;
|
|
775
|
+
kickoffResolve();
|
|
776
|
+
scrollChipsToEnd();
|
|
777
|
+
}
|
|
778
|
+
function onEnter() {
|
|
779
|
+
if (hasDropdown || !searchTerm.value.trim()) return;
|
|
780
|
+
const parsed = (0, _atscript_ui_table.parseFilterInput)(searchTerm.value, filterType, props.column.nullable);
|
|
781
|
+
if (!parsed) return;
|
|
782
|
+
const filled = (state.filters.value[props.column.path] ?? []).filter(_atscript_ui_table.isFilled);
|
|
783
|
+
state.setFieldFilter(props.column.path, [...filled, parsed]);
|
|
784
|
+
searchTerm.value = "";
|
|
785
|
+
}
|
|
786
|
+
function onF4(event) {
|
|
787
|
+
event.preventDefault();
|
|
788
|
+
openFilterDialog();
|
|
789
|
+
}
|
|
790
|
+
return (_ctx, _cache) => {
|
|
791
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
792
|
+
class: "as-filter-field",
|
|
793
|
+
"aria-disabled": dropdownLoadingMetadata.value ? true : void 0
|
|
794
|
+
}, [(0, vue.createElementVNode)("label", {
|
|
795
|
+
for: (0, vue.unref)(inputId),
|
|
796
|
+
class: "as-filter-field-label"
|
|
797
|
+
}, (0, vue.toDisplayString)(__props.column.label), 9, _hoisted_2), (0, vue.createElementVNode)("div", _hoisted_3, [
|
|
798
|
+
dropdownLoadingMetadata.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4, [..._cache[5] || (_cache[5] = [(0, vue.createElementVNode)("span", {
|
|
799
|
+
class: "as-filter-field-loading-icon",
|
|
800
|
+
"aria-hidden": "true"
|
|
801
|
+
}, null, -1)])])) : (0, vue.unref)(hasDropdown) ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(reka_ui.ComboboxRoot), {
|
|
802
|
+
key: 1,
|
|
803
|
+
modelValue: selectedValues.value,
|
|
804
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => selectedValues.value = $event),
|
|
805
|
+
open: dropdownOpen.value,
|
|
806
|
+
"onUpdate:open": _cache[2] || (_cache[2] = ($event) => dropdownOpen.value = $event),
|
|
807
|
+
multiple: true,
|
|
808
|
+
"reset-search-term-on-blur": false,
|
|
809
|
+
"as-child": ""
|
|
810
|
+
}, {
|
|
811
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(reka_ui.ComboboxAnchor), { "as-child": "" }, {
|
|
812
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", {
|
|
813
|
+
class: "as-filter-field-input",
|
|
814
|
+
onClick: onAnchorClick
|
|
815
|
+
}, [(0, vue.createElementVNode)("div", {
|
|
816
|
+
ref_key: "chipsScrollEl",
|
|
817
|
+
ref: chipsScrollEl,
|
|
818
|
+
class: "as-filter-field-chips"
|
|
819
|
+
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(chips.value, (chip) => {
|
|
820
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
821
|
+
key: chip.key,
|
|
822
|
+
class: "as-filter-field-chip"
|
|
823
|
+
}, [(0, vue.createTextVNode)((0, vue.toDisplayString)(chip.label) + " ", 1), (0, vue.createElementVNode)("span", {
|
|
824
|
+
class: "as-filter-field-chip-remove",
|
|
825
|
+
role: "button",
|
|
826
|
+
tabindex: "-1",
|
|
827
|
+
onClick: (0, vue.withModifiers)(($event) => removeChip(chip), ["stop", "prevent"])
|
|
828
|
+
}, [..._cache[6] || (_cache[6] = [(0, vue.createElementVNode)("span", {
|
|
829
|
+
class: "i-as-close",
|
|
830
|
+
"aria-hidden": "true"
|
|
831
|
+
}, null, -1)])], 8, _hoisted_5)]);
|
|
832
|
+
}), 128))], 512), (0, vue.createVNode)((0, vue.unref)(reka_ui.ComboboxInput), { "as-child": "" }, {
|
|
833
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("input", {
|
|
834
|
+
id: (0, vue.unref)(inputId),
|
|
835
|
+
class: "as-filter-field-search",
|
|
836
|
+
onInput: onSearchInput,
|
|
837
|
+
onKeydown: [(0, vue.withKeys)(onBackspace, ["backspace"]), (0, vue.withKeys)(onF4, ["f4"])],
|
|
838
|
+
onFocus: onInputFocus
|
|
839
|
+
}, null, 40, _hoisted_6)]),
|
|
840
|
+
_: 1
|
|
841
|
+
})])]),
|
|
842
|
+
_: 1
|
|
843
|
+
}), (0, vue.createVNode)((0, vue.unref)(reka_ui.ComboboxContent), {
|
|
844
|
+
class: "as-filter-field-dropdown",
|
|
845
|
+
"side-offset": 4,
|
|
846
|
+
align: "start",
|
|
847
|
+
position: "popper",
|
|
848
|
+
onOpenAutoFocus: _cache[0] || (_cache[0] = (0, vue.withModifiers)(() => {}, ["prevent"]))
|
|
849
|
+
}, {
|
|
850
|
+
default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(reka_ui.ComboboxViewport), null, {
|
|
851
|
+
default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", _hoisted_7, [(0, vue.createVNode)(require_as_table_base.as_table_base_default, {
|
|
852
|
+
"render-mode": "combobox",
|
|
853
|
+
"row-value-fn": rowValueFn,
|
|
854
|
+
columns: dropdownColumns.value,
|
|
855
|
+
rows: dropdownRows.value,
|
|
856
|
+
sorters: [],
|
|
857
|
+
querying: dropdownQuerying.value,
|
|
858
|
+
"query-error": dropdownQueryError.value,
|
|
859
|
+
"search-term": searchTerm.value,
|
|
860
|
+
"sticky-header": true,
|
|
861
|
+
"column-menu": {
|
|
862
|
+
sort: false,
|
|
863
|
+
filters: false,
|
|
864
|
+
hide: false
|
|
865
|
+
}
|
|
866
|
+
}, null, 8, [
|
|
867
|
+
"columns",
|
|
868
|
+
"rows",
|
|
869
|
+
"querying",
|
|
870
|
+
"query-error",
|
|
871
|
+
"search-term"
|
|
872
|
+
]), dropdownQuerying.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8, [..._cache[7] || (_cache[7] = [(0, vue.createElementVNode)("span", {
|
|
873
|
+
class: "as-table-query-overlay-icon",
|
|
874
|
+
"aria-hidden": "true"
|
|
875
|
+
}, null, -1)])])) : (0, vue.createCommentVNode)("v-if", true)]), noEnumMatches.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9, [
|
|
876
|
+
_cache[10] || (_cache[10] = (0, vue.createElementVNode)("span", {
|
|
877
|
+
class: "as-vh-empty-icon i-as-search",
|
|
878
|
+
"aria-hidden": "true"
|
|
879
|
+
}, null, -1)),
|
|
880
|
+
_cache[11] || (_cache[11] = (0, vue.createElementVNode)("p", { class: "as-vh-empty-title" }, "No matching values", -1)),
|
|
881
|
+
searchTerm.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_10, [
|
|
882
|
+
_cache[8] || (_cache[8] = (0, vue.createTextVNode)(" No entries match ", -1)),
|
|
883
|
+
(0, vue.createElementVNode)("span", _hoisted_11, "\"" + (0, vue.toDisplayString)(searchTerm.value) + "\"", 1),
|
|
884
|
+
_cache[9] || (_cache[9] = (0, vue.createTextVNode)(". Try a different search. ", -1))
|
|
885
|
+
])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("p", _hoisted_12, "No entries available"))
|
|
886
|
+
])) : (0, vue.createCommentVNode)("v-if", true)]),
|
|
887
|
+
_: 1
|
|
888
|
+
}), chips.value.length > 0 || seeAllCount.value > 10 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_13, [chips.value.length > 0 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
889
|
+
key: 0,
|
|
890
|
+
type: "button",
|
|
891
|
+
onClick: clearAll
|
|
892
|
+
}, "Reset")) : (0, vue.createCommentVNode)("v-if", true), seeAllCount.value > 10 ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("button", {
|
|
893
|
+
key: 1,
|
|
894
|
+
type: "button",
|
|
895
|
+
onClick: openFilterDialog
|
|
896
|
+
}, [(0, vue.createTextVNode)(" See All (" + (0, vue.toDisplayString)(seeAllCount.value) + ") ", 1), _cache[12] || (_cache[12] = (0, vue.createElementVNode)("span", { class: "as-kbd" }, "F4", -1))])) : (0, vue.createCommentVNode)("v-if", true)])) : (0, vue.createCommentVNode)("v-if", true)]),
|
|
897
|
+
_: 1
|
|
898
|
+
})]),
|
|
899
|
+
_: 1
|
|
900
|
+
}, 8, ["modelValue", "open"])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.createCommentVNode)(" Plain input (no dropdown) "), (0, vue.createElementVNode)("div", _hoisted_14, [(0, vue.createElementVNode)("div", {
|
|
901
|
+
ref_key: "chipsScrollEl",
|
|
902
|
+
ref: chipsScrollEl,
|
|
903
|
+
class: "as-filter-field-chips"
|
|
904
|
+
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(chips.value, (chip) => {
|
|
905
|
+
return (0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
|
|
906
|
+
key: chip.key,
|
|
907
|
+
class: "as-filter-field-chip"
|
|
908
|
+
}, [(0, vue.createTextVNode)((0, vue.toDisplayString)(chip.label) + " ", 1), (0, vue.createElementVNode)("span", {
|
|
909
|
+
class: "as-filter-field-chip-remove",
|
|
910
|
+
role: "button",
|
|
911
|
+
tabindex: "-1",
|
|
912
|
+
onClick: (0, vue.withModifiers)(($event) => removeChip(chip), ["stop", "prevent"])
|
|
913
|
+
}, " × ", 8, _hoisted_15)]);
|
|
914
|
+
}), 128))], 512), (0, vue.createElementVNode)("input", {
|
|
915
|
+
id: (0, vue.unref)(inputId),
|
|
916
|
+
class: "as-filter-field-search",
|
|
917
|
+
value: searchTerm.value,
|
|
918
|
+
onInput: _cache[3] || (_cache[3] = ($event) => searchTerm.value = $event.target.value),
|
|
919
|
+
onKeydown: [
|
|
920
|
+
(0, vue.withKeys)(onBackspace, ["backspace"]),
|
|
921
|
+
(0, vue.withKeys)((0, vue.withModifiers)(onEnter, ["prevent"]), ["enter"]),
|
|
922
|
+
(0, vue.withKeys)(onF4, ["f4"])
|
|
923
|
+
],
|
|
924
|
+
onFocus: _cache[4] || (_cache[4] = ($event) => scrollChipsToEnd())
|
|
925
|
+
}, null, 40, _hoisted_16)])], 2112)),
|
|
926
|
+
(0, vue.createCommentVNode)(" `tabindex=\"-1\"`: don't compete with the field's own input for tab\n order — Tab moves cleanly between filter fields, F4 on the input\n opens this dialog. Button stays click-target for mouse users. "),
|
|
927
|
+
(0, vue.createElementVNode)("button", {
|
|
928
|
+
type: "button",
|
|
929
|
+
class: "as-filter-field-f4",
|
|
930
|
+
tabindex: "-1",
|
|
931
|
+
"aria-label": "Open filter dialog (F4)",
|
|
932
|
+
title: "Open filter dialog (F4)",
|
|
933
|
+
onClick: openFilterDialog
|
|
934
|
+
}, [..._cache[13] || (_cache[13] = [(0, vue.createElementVNode)("span", {
|
|
935
|
+
class: "i-as-value-help",
|
|
936
|
+
"aria-hidden": "true"
|
|
937
|
+
}, null, -1)])])
|
|
938
|
+
])], 8, _hoisted_1);
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
});
|
|
942
|
+
//#endregion
|
|
943
|
+
Object.defineProperty(exports, "AS_PRESETS_APP", {
|
|
944
|
+
enumerable: true,
|
|
945
|
+
get: function() {
|
|
946
|
+
return AS_PRESETS_APP;
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
Object.defineProperty(exports, "as_filter_field_default", {
|
|
950
|
+
enumerable: true,
|
|
951
|
+
get: function() {
|
|
952
|
+
return as_filter_field_default;
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
Object.defineProperty(exports, "clearTableCache", {
|
|
956
|
+
enumerable: true,
|
|
957
|
+
get: function() {
|
|
958
|
+
return clearTableCache;
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
Object.defineProperty(exports, "injectPresetsApp", {
|
|
962
|
+
enumerable: true,
|
|
963
|
+
get: function() {
|
|
964
|
+
return injectPresetsApp;
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
Object.defineProperty(exports, "useLocalDraft", {
|
|
968
|
+
enumerable: true,
|
|
969
|
+
get: function() {
|
|
970
|
+
return useLocalDraft;
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
Object.defineProperty(exports, "usePresets", {
|
|
974
|
+
enumerable: true,
|
|
975
|
+
get: function() {
|
|
976
|
+
return usePresets;
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
Object.defineProperty(exports, "useTable", {
|
|
980
|
+
enumerable: true,
|
|
981
|
+
get: function() {
|
|
982
|
+
return useTable;
|
|
983
|
+
}
|
|
984
|
+
});
|