@atscript/vue-table 0.1.132 → 0.1.133
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/dist/as-action-form-dialog.cjs +42 -30
- package/dist/as-action-form-dialog.mjs +42 -30
- package/dist/{as-action-menu-content-4UfcabUe.mjs → as-action-menu-content-4D7CJNgr.mjs} +1 -1
- package/dist/{as-action-menu-content-C5qx9MPE.cjs → as-action-menu-content-DiS37BYK.cjs} +1 -1
- package/dist/as-column-menu.d.cts +1 -1
- package/dist/as-column-menu.d.mts +1 -1
- package/dist/{as-column-menu.vue-DL5N9mKR.d.mts → as-column-menu.vue-CZ8XqHl0.d.cts} +2 -2
- package/dist/{as-column-menu.vue-u_DNy3f-.d.cts → as-column-menu.vue-Cuelpv3p.d.mts} +2 -2
- package/dist/{as-config-dialog-BehfqIGd.mjs → as-config-dialog-BKsm8OHR.mjs} +30 -22
- package/dist/{as-config-dialog-BOYWPYYH.cjs → as-config-dialog-Bt8oP8qg.cjs} +29 -21
- package/dist/as-config-dialog.cjs +1 -1
- package/dist/as-config-dialog.mjs +1 -1
- package/dist/{as-confirm-dialog-bpN4A-KN.mjs → as-confirm-dialog-BV01t7dn.mjs} +12 -9
- package/dist/{as-confirm-dialog-UwhDHysk.cjs → as-confirm-dialog-Cw7KErhz.cjs} +12 -9
- package/dist/as-confirm-dialog.cjs +1 -1
- package/dist/as-confirm-dialog.mjs +1 -1
- package/dist/{as-filter-dialog-Dh2Ylthb.cjs → as-filter-dialog-Bxii-mYH.cjs} +31 -23
- package/dist/{as-filter-dialog-D1qzq-8b.mjs → as-filter-dialog-Ckrl79kU.mjs} +32 -24
- package/dist/as-filter-dialog.cjs +1 -1
- package/dist/as-filter-dialog.mjs +1 -1
- package/dist/{as-filter-field-DirBmnbb.mjs → as-filter-field-C-IFnj8K.mjs} +4 -4
- package/dist/{as-filter-field-DRsDJdpx.cjs → as-filter-field-xBr6TtKo.cjs} +4 -4
- package/dist/as-filter-field.cjs +1 -1
- package/dist/as-filter-field.mjs +1 -1
- package/dist/as-filters-DJEQj7_p.mjs +125 -0
- package/dist/as-filters-DuCk8nkk.cjs +130 -0
- package/dist/as-filters.cjs +1 -1
- package/dist/as-filters.d.cts +1 -1
- package/dist/as-filters.d.mts +1 -1
- package/dist/as-filters.mjs +1 -1
- package/dist/as-filters.vue-BG_ysCkC.d.mts +65 -0
- package/dist/as-filters.vue-DcxDnWAU.d.cts +65 -0
- package/dist/{as-preset-dialog-CDqCAR7N.mjs → as-preset-dialog-CCIacZ2C.mjs} +70 -20
- package/dist/{as-preset-dialog-DpM06jqR.cjs → as-preset-dialog-jZeyXJeJ.cjs} +74 -24
- package/dist/as-preset-dialog.cjs +1 -1
- package/dist/as-preset-dialog.mjs +1 -1
- package/dist/{as-preset-picker-jUS_YDX8.cjs → as-preset-picker-4xXU1KQz.cjs} +45 -21
- package/dist/{as-preset-picker-CISaxEZ0.mjs → as-preset-picker-DGSqQl9A.mjs} +39 -15
- package/dist/as-preset-picker.cjs +1 -1
- package/dist/as-preset-picker.mjs +1 -1
- package/dist/{as-row-actions-Bm6Bzyno.cjs → as-row-actions-B_OHWIAt.cjs} +2 -2
- package/dist/{as-row-actions-xqJeAdQl.mjs → as-row-actions-pukI1JT7.mjs} +2 -2
- package/dist/as-row-actions.cjs +1 -1
- package/dist/as-row-actions.mjs +1 -1
- package/dist/{as-table-BWUPzjRn.cjs → as-table-BejpMVid.cjs} +22 -4
- package/dist/{as-table-CDSG2yED.mjs → as-table-D5_bQ0p5.mjs} +22 -4
- package/dist/{as-table-actions-DMxeaczm.mjs → as-table-actions-DKYK_mTO.mjs} +57 -11
- package/dist/{as-table-actions-gV4lqqxc.cjs → as-table-actions-qb0gQz2D.cjs} +56 -10
- package/dist/as-table-actions.cjs +1 -1
- package/dist/as-table-actions.d.cts +1 -1
- package/dist/as-table-actions.d.mts +1 -1
- package/dist/as-table-actions.mjs +1 -1
- package/dist/{as-table-actions.vue-B-cgiCXP.d.cts → as-table-actions.vue-CckRRsL6.d.cts} +2 -2
- package/dist/{as-table-actions.vue-ClMa0OD1.d.mts → as-table-actions.vue-DsqauvXR.d.mts} +2 -2
- package/dist/{as-table-base-BaTE3VSN.mjs → as-table-base-B0arhJI8.mjs} +141 -46
- package/dist/{as-table-base-RG2TEIgV.cjs → as-table-base-Dfw012G5.cjs} +141 -46
- package/dist/{as-table-header-cell-CIqlO6Lw.cjs → as-table-header-cell-Bb4ddLmQ.cjs} +1 -1
- package/dist/{as-table-header-cell-Bdhl5Lox.mjs → as-table-header-cell-q-c_QklI.mjs} +1 -1
- package/dist/as-table-header-cell.cjs +1 -1
- package/dist/as-table-header-cell.d.cts +1 -1
- package/dist/as-table-header-cell.d.mts +1 -1
- package/dist/as-table-header-cell.mjs +1 -1
- package/dist/{as-table-header-cell.vue-BCszzxtU.d.mts → as-table-header-cell.vue-BjVOEFqz.d.mts} +1 -1
- package/dist/{as-table-header-cell.vue-BzTzfGRo.d.cts → as-table-header-cell.vue-qS1Xfc-U.d.cts} +1 -1
- package/dist/{as-table-root-BLReUbRH.mjs → as-table-root-Bpsrp0Vz.mjs} +5 -5
- package/dist/{as-table-root-DLJ_3Jf4.cjs → as-table-root-CUDO9ybm.cjs} +5 -5
- package/dist/as-table-root.cjs +1 -1
- package/dist/as-table-root.d.cts +1 -1
- package/dist/as-table-root.d.mts +1 -1
- package/dist/as-table-root.mjs +1 -1
- package/dist/{as-table-root.vue-QMT93qPk.d.mts → as-table-root.vue-BPU92_Ns.d.mts} +55 -12
- package/dist/{as-table-root.vue-D0T3n-Vm.d.cts → as-table-root.vue-szvjZsCn.d.cts} +55 -12
- package/dist/{as-table-status-DGTZlpyq.mjs → as-table-status-B9jlzPPV.mjs} +53 -37
- package/dist/{as-table-status-Du4WLF4k.cjs → as-table-status-BgDexT2x.cjs} +53 -37
- package/dist/as-table.cjs +1 -1
- package/dist/as-table.d.cts +1 -1
- package/dist/as-table.d.mts +1 -1
- package/dist/as-table.mjs +1 -1
- package/dist/{as-table.vue-Ds7MEp37.d.cts → as-table.vue-4WhMA8AM.d.mts} +27 -3
- package/dist/{as-table.vue-Ce5606ZO.d.mts → as-table.vue-_urybtQj.d.cts} +27 -3
- package/dist/{as-window-table-jD_y9yet.cjs → as-window-table-CXq6UuUx.cjs} +98 -19
- package/dist/{as-window-table-DWujiUQy.mjs → as-window-table-S1XWpDHQ.mjs} +98 -19
- package/dist/as-window-table.cjs +1 -1
- package/dist/as-window-table.d.cts +1 -1
- package/dist/as-window-table.d.mts +1 -1
- package/dist/as-window-table.mjs +1 -1
- package/dist/{as-window-table.vue-DfZF1Mux.d.mts → as-window-table.vue-CWsJvOkL.d.mts} +25 -2
- package/dist/{as-window-table.vue-Bhf9BK8E.d.cts → as-window-table.vue-h1bdyMv7.d.cts} +25 -2
- package/dist/error-message-CglODWl4.cjs +18 -0
- package/dist/error-message-hPSAu8Ug.mjs +13 -0
- package/dist/index.cjs +61 -29
- package/dist/index.d.cts +9 -9
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +62 -30
- package/dist/{types-CTMxE_zA.d.cts → types-BZ0HssRY.d.cts} +126 -4
- package/dist/{types-ByU4O0Yf.d.mts → types-CXz-4dPz.d.mts} +126 -4
- package/dist/{use-table-CyFcVtUN.mjs → use-table-Bk-jSxOM.mjs} +26 -11
- package/dist/{use-table-nvBq1dZ4.cjs → use-table-CdFFqaEx.cjs} +24 -9
- package/dist/{use-table-component-DO_kvKSf.cjs → use-table-component-DlLganVc.cjs} +1 -1
- package/dist/{use-table-component-K6xj1obF.mjs → use-table-component-KuzZxAP8.mjs} +1 -1
- package/dist/{use-table-nav-bridge-DeGeaQX-.mjs → use-table-nav-bridge-B9SSEajW.mjs} +1 -1
- package/dist/{use-table-nav-bridge-uOQUDooh.cjs → use-table-nav-bridge-CVUmTjDr.cjs} +1 -1
- package/dist/{use-table-state-Oi2ds4_a.cjs → use-table-state-D6dHOFrA.cjs} +329 -53
- package/dist/{use-table-state-BxX3SpeW.mjs → use-table-state-DLJbW753.mjs} +295 -55
- package/package.json +9 -9
- package/dist/as-filters-DCZTHjf5.cjs +0 -51
- package/dist/as-filters-beIud9sF.mjs +0 -46
- package/dist/as-filters.vue-DmECMd1v.d.mts +0 -10
- package/dist/as-filters.vue-fv-tRL2H.d.cts +0 -10
- package/dist/preset-aspect-display-IICxAlVo.mjs +0 -43
- package/dist/preset-aspect-display-TWwf6j1B.cjs +0 -72
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as useTableContext,
|
|
1
|
+
import { D as ROW_ACTIONS_TYPE, a as useTableContext, b as extractIdentifier, n as createTableState, o as useTableContextOptional, t as createStaticTableState } from "./use-table-state-DLJbW753.mjs";
|
|
2
2
|
import { n as useTableSelection } from "./use-table-selection-C84z4OZy.mjs";
|
|
3
|
-
import { a as AS_PRESETS_APP, i as useLocalDraft, n as useTable, o as injectPresetsApp, r as usePresets, t as clearTableCache } from "./use-table-
|
|
4
|
-
import { t as useTableNavBridge } from "./use-table-nav-bridge-
|
|
5
|
-
import { t as useTableComponent } from "./use-table-component-
|
|
3
|
+
import { a as AS_PRESETS_APP, i as useLocalDraft, n as useTable, o as injectPresetsApp, r as usePresets, t as clearTableCache } from "./use-table-Bk-jSxOM.mjs";
|
|
4
|
+
import { t as useTableNavBridge } from "./use-table-nav-bridge-B9SSEajW.mjs";
|
|
5
|
+
import { t as useTableComponent } from "./use-table-component-KuzZxAP8.mjs";
|
|
6
6
|
import { t as getCellValue } from "./get-cell-value-C8LLc_Rr.mjs";
|
|
7
7
|
import { t as as_cell_array_default } from "./as-cell-array-2qmJ1lT2.mjs";
|
|
8
8
|
import { t as as_cell_date_default } from "./as-cell-date-BwFgi6O0.mjs";
|
|
@@ -12,24 +12,24 @@ import { t as as_cell_number_default } from "./as-cell-number-DKRaS9pM.mjs";
|
|
|
12
12
|
import { t as formatCellValue } from "./format-cell-D1Ziv96Q.mjs";
|
|
13
13
|
import { t as as_cell_union_default } from "./as-cell-union-C9FukGqF.mjs";
|
|
14
14
|
import { t as as_column_menu_default } from "./as-column-menu-kTIQfLTi.mjs";
|
|
15
|
-
import { t as as_config_dialog_default } from "./as-config-dialog-
|
|
16
|
-
import { t as as_confirm_dialog_default } from "./as-confirm-dialog-
|
|
15
|
+
import { t as as_config_dialog_default } from "./as-config-dialog-BKsm8OHR.mjs";
|
|
16
|
+
import { t as as_confirm_dialog_default } from "./as-confirm-dialog-BV01t7dn.mjs";
|
|
17
17
|
import { t as as_filter_input_default } from "./as-filter-input-BM23TNeh.mjs";
|
|
18
|
-
import { t as as_filter_dialog_default } from "./as-filter-dialog-
|
|
19
|
-
import { t as as_table_header_cell_default } from "./as-table-header-cell-
|
|
20
|
-
import { t as as_window_table_default } from "./as-window-table-
|
|
21
|
-
import { t as as_filter_field_default } from "./as-filter-field-
|
|
22
|
-
import { t as as_filters_default } from "./as-filters-
|
|
23
|
-
import { t as as_preset_dialog_default } from "./as-preset-dialog-
|
|
24
|
-
import { t as as_row_actions_default } from "./as-row-actions-
|
|
18
|
+
import { t as as_filter_dialog_default } from "./as-filter-dialog-Ckrl79kU.mjs";
|
|
19
|
+
import { t as as_table_header_cell_default } from "./as-table-header-cell-q-c_QklI.mjs";
|
|
20
|
+
import { t as as_window_table_default } from "./as-window-table-S1XWpDHQ.mjs";
|
|
21
|
+
import { t as as_filter_field_default } from "./as-filter-field-C-IFnj8K.mjs";
|
|
22
|
+
import { t as as_filters_default } from "./as-filters-DJEQj7_p.mjs";
|
|
23
|
+
import { t as as_preset_dialog_default } from "./as-preset-dialog-CCIacZ2C.mjs";
|
|
24
|
+
import { t as as_row_actions_default } from "./as-row-actions-pukI1JT7.mjs";
|
|
25
25
|
import { t as as_table_cell_value_default } from "./as-table-cell-value-CPcFxSOj.mjs";
|
|
26
|
-
import { t as as_table_root_default } from "./as-table-root-
|
|
27
|
-
import { t as as_table_default } from "./as-table-
|
|
28
|
-
import { t as as_table_actions_default } from "./as-table-actions-
|
|
29
|
-
import { t as as_preset_picker_default } from "./as-preset-picker-
|
|
26
|
+
import { t as as_table_root_default } from "./as-table-root-Bpsrp0Vz.mjs";
|
|
27
|
+
import { t as as_table_default } from "./as-table-D5_bQ0p5.mjs";
|
|
28
|
+
import { t as as_table_actions_default } from "./as-table-actions-DKYK_mTO.mjs";
|
|
29
|
+
import { t as as_preset_picker_default } from "./as-preset-picker-DGSqQl9A.mjs";
|
|
30
30
|
import { getDefaultClientFactory, resetDefaultClientFactory, setDefaultClientFactory } from "@atscript/ui";
|
|
31
31
|
import { computed, effectScope, ref, shallowRef } from "vue";
|
|
32
|
-
import { AppPrefsClient, PRESET_ASPECTS, STANDARD_PRESET_ID, SYSTEM_PRESET_PREFIX, columnFilterType, conditionsForType, defaultCondition,
|
|
32
|
+
import { AppPrefsClient, PRESET_ASPECTS, STANDARD_PRESET_ID, SYSTEM_PRESET_PREFIX, columnFilterType, conditionsForType, defaultCondition, isFilled, isSystemPresetId, isUnavailableError, resolveSystemPresets, urlQueryConsumesKey } from "@atscript/ui-table";
|
|
33
33
|
import { StorageSerializers, useEventBus, useStorage } from "@vueuse/core";
|
|
34
34
|
//#region src/composables/use-table-filter.ts
|
|
35
35
|
/**
|
|
@@ -187,11 +187,19 @@ function findCleanEq(segment) {
|
|
|
187
187
|
* dependency on `vue-router` is added to `@atscript/vue-table`. Consumers
|
|
188
188
|
* pass in their already-resolved `useRoute()` and `useRouter()` instances.
|
|
189
189
|
*
|
|
190
|
-
* Scope:
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* write
|
|
194
|
-
*
|
|
190
|
+
* Scope: the bridge owns **only what the table reads back** (since 0.1.133).
|
|
191
|
+
* A key is the table's iff `urlQueryStringToState` would consume it — see
|
|
192
|
+
* `urlQueryConsumesKey` — or the bridge has written it before. Read and
|
|
193
|
+
* write therefore agree in both directions: a key the parser ignores (a host
|
|
194
|
+
* flag, an unrecognised `$control`) is never removed, and a key the parser
|
|
195
|
+
* reads is the bridge's to remove. Every write merges into the current
|
|
196
|
+
* `route.query`, in place.
|
|
197
|
+
*
|
|
198
|
+
* Without a `prefix` the bridge cannot tell a plain `field=value` filter from
|
|
199
|
+
* a page-owned flag of the same shape, so a plain key that was already in the
|
|
200
|
+
* URL when the bridge mounted counts as foreign until the bridge writes it
|
|
201
|
+
* itself. Pass `prefix` when a route carries a host key that could collide
|
|
202
|
+
* with a column path, or when it carries two tables.
|
|
195
203
|
*
|
|
196
204
|
* @example
|
|
197
205
|
* ```vue
|
|
@@ -199,6 +207,9 @@ function findCleanEq(segment) {
|
|
|
199
207
|
* import { useRoute, useRouter } from 'vue-router';
|
|
200
208
|
* import { useTableUrlQuery } from '@atscript/vue-table';
|
|
201
209
|
* const urlQuery = useTableUrlQuery(useRoute(), useRouter());
|
|
210
|
+
* // Two tables on one route:
|
|
211
|
+
* // const left = useTableUrlQuery(useRoute(), useRouter(), { prefix: 'a' });
|
|
212
|
+
* // const right = useTableUrlQuery(useRoute(), useRouter(), { prefix: 'b' });
|
|
202
213
|
* <\/script>
|
|
203
214
|
* <template>
|
|
204
215
|
* <AsTableRoot v-model:url-query="urlQuery" url="/db/products" .../>
|
|
@@ -207,25 +218,46 @@ function findCleanEq(segment) {
|
|
|
207
218
|
*/
|
|
208
219
|
function useTableUrlQuery(route, router, opts = {}) {
|
|
209
220
|
const navigate = (opts.mode ?? "replace") === "push" ? router.push.bind(router) : router.replace.bind(router);
|
|
221
|
+
const prefix = opts.prefix ? `${opts.prefix}.` : "";
|
|
222
|
+
const written = /* @__PURE__ */ new Set();
|
|
223
|
+
function isOwn(key) {
|
|
224
|
+
if (prefix) return key.startsWith(prefix);
|
|
225
|
+
return written.has(key) || urlQueryConsumesKey(key);
|
|
226
|
+
}
|
|
210
227
|
return computed({
|
|
211
228
|
get: () => {
|
|
212
229
|
const q = route.query;
|
|
213
230
|
const parts = [];
|
|
214
231
|
for (const key in q) {
|
|
232
|
+
if (prefix && !key.startsWith(prefix)) continue;
|
|
233
|
+
const own = prefix ? key.slice(prefix.length) : key;
|
|
215
234
|
const v = q[key];
|
|
216
|
-
if (Array.isArray(v)) for (const item of v) parts.push(item == null ?
|
|
217
|
-
else if (v == null) parts.push(
|
|
218
|
-
else parts.push(`${
|
|
235
|
+
if (Array.isArray(v)) for (const item of v) parts.push(item == null ? own : `${own}=${item}`);
|
|
236
|
+
else if (v == null) parts.push(own);
|
|
237
|
+
else parts.push(`${own}=${v}`);
|
|
219
238
|
}
|
|
220
239
|
return parts.join("&");
|
|
221
240
|
},
|
|
222
241
|
set: (urlString) => {
|
|
223
|
-
const
|
|
242
|
+
const serialized = /* @__PURE__ */ new Map();
|
|
224
243
|
for (const segment of splitSegments(urlString)) {
|
|
225
244
|
const eqIdx = findCleanEq(segment);
|
|
226
|
-
|
|
227
|
-
|
|
245
|
+
const key = eqIdx > 0 ? `${prefix}${segment.slice(0, eqIdx)}` : `${prefix}${segment}`;
|
|
246
|
+
serialized.set(key, eqIdx > 0 ? segment.slice(eqIdx + 1) : null);
|
|
247
|
+
written.add(key);
|
|
248
|
+
}
|
|
249
|
+
const query = {};
|
|
250
|
+
for (const key in route.query) {
|
|
251
|
+
if (!isOwn(key)) {
|
|
252
|
+
query[key] = route.query[key];
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
if (serialized.has(key)) {
|
|
256
|
+
query[key] = serialized.get(key);
|
|
257
|
+
serialized.delete(key);
|
|
258
|
+
}
|
|
228
259
|
}
|
|
260
|
+
for (const [key, value] of serialized) query[key] = value;
|
|
229
261
|
navigate({ query });
|
|
230
262
|
}
|
|
231
263
|
});
|
|
@@ -316,7 +348,7 @@ function createInstance(app, opts) {
|
|
|
316
348
|
cache.value = { ...result.prefs };
|
|
317
349
|
existing.value = result.row;
|
|
318
350
|
} catch (err) {
|
|
319
|
-
if (
|
|
351
|
+
if (isUnavailableError(err)) {
|
|
320
352
|
denied.value = true;
|
|
321
353
|
clearCache();
|
|
322
354
|
existing.value = null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, ComputedRef, Ref, ShallowRef } from "vue";
|
|
1
|
+
import { Component, ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
2
2
|
import { ClientError, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
|
|
3
3
|
import { ColumnDef, PaginationControl, SortControl, TableDef } from "@atscript/ui";
|
|
4
4
|
import { AsPresetEntryRow, AspectMask, ColumnWidthsMap, ConfigTab, FieldFilters, PresetAspect, PresetCapabilities, PresetSnapshot, SelectionMode, SystemPreset, SystemPresetInput, TableStateMethods } from "@atscript/ui-table";
|
|
@@ -190,14 +190,62 @@ interface PresetConfig {
|
|
|
190
190
|
* Add `'itemsPerPage'` for paginated tables; drop any aspect this app doesn't use.
|
|
191
191
|
*/
|
|
192
192
|
aspects?: PresetAspect[];
|
|
193
|
+
/**
|
|
194
|
+
* Aspects a SYSTEM preset owns. Intersected with `aspects`; defaults to all
|
|
195
|
+
* of them. Narrow it to e.g. `['filterOps']` when system presets are
|
|
196
|
+
* filter-only views that must not reset the user's columns, displayed
|
|
197
|
+
* filters, sorters or page size. Since 0.1.133.
|
|
198
|
+
*/
|
|
199
|
+
systemAspects?: PresetAspect[];
|
|
193
200
|
/**
|
|
194
201
|
* Opt-in localStorage overlay for the user's in-flight tweaks (default
|
|
195
202
|
* `false`). Persists `columns` / `filters` / `sorters` / opt-in
|
|
196
203
|
* `itemsPerPage`; `filterOps` / `searchTerm` / pagination are NOT persisted.
|
|
197
204
|
*/
|
|
198
205
|
persistDrafts?: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Identity the draft is stored under — pass the signed-in user's id
|
|
208
|
+
* whenever `persistDrafts` is on, so a shared browser never restores the
|
|
209
|
+
* previous user's draft. Omitted keeps the pre-0.1.133 unscoped key.
|
|
210
|
+
* Since 0.1.133.
|
|
211
|
+
*/
|
|
212
|
+
draftScope?: MaybeRefOrGetter<string | undefined>;
|
|
199
213
|
}
|
|
200
214
|
type QueryErrorKind = "initial" | "query" | "queryNext" | "loadRange";
|
|
215
|
+
/**
|
|
216
|
+
* Context handed to the per-row hooks of `<AsTable>` (`rowSelectable`,
|
|
217
|
+
* `rowClass`, `rowAttrs`). Since 0.1.133.
|
|
218
|
+
*/
|
|
219
|
+
interface RowHookContext {
|
|
220
|
+
/** Position of the row in the rows the renderer is currently rendering. */
|
|
221
|
+
index: number;
|
|
222
|
+
/**
|
|
223
|
+
* Whether the row's pk is in `state.selectedRows` right now. A getter —
|
|
224
|
+
* reading it subscribes that hook call to the selection, so predicates
|
|
225
|
+
* that ignore it are not re-run when the selection changes.
|
|
226
|
+
*/
|
|
227
|
+
readonly selected: boolean;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Per-row selectability predicate. Return `false` — or a string, which is
|
|
231
|
+
* surfaced as the disabled reason on the selection control — to make the row
|
|
232
|
+
* not selectable; `true` (or omitting the prop) keeps it selectable.
|
|
233
|
+
* Since 0.1.133.
|
|
234
|
+
*/
|
|
235
|
+
type RowSelectableHook = (row: Record<string, unknown>, ctx: RowHookContext) => boolean | string | undefined | void;
|
|
236
|
+
/** Extra classes for the row element. Since 0.1.133. */
|
|
237
|
+
type RowClassHook = (row: Record<string, unknown>, ctx: RowHookContext) => string | string[] | Record<string, boolean> | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* Extra attributes for the row element. The framework's own `id`, `role`,
|
|
240
|
+
* `aria-*`, `data-*`, `class` and `style` always win. Since 0.1.133.
|
|
241
|
+
*/
|
|
242
|
+
type RowAttrsHook = (row: Record<string, unknown>, ctx: RowHookContext) => Record<string, unknown> | undefined;
|
|
243
|
+
/** Normalised {@link RowSelectableHook} verdict. */
|
|
244
|
+
interface RowSelectableVerdict {
|
|
245
|
+
ok: boolean;
|
|
246
|
+
/** Disabled reason, when the predicate returned a string. */
|
|
247
|
+
reason?: string;
|
|
248
|
+
}
|
|
201
249
|
/** Controls which sections appear in the column header dropdown menu. */
|
|
202
250
|
interface ColumnMenuConfig {
|
|
203
251
|
sort?: boolean;
|
|
@@ -373,6 +421,31 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
373
421
|
* naturally without consulting mode.
|
|
374
422
|
*/
|
|
375
423
|
isPkSelected: (pk: unknown) => boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Per-row selectability predicate — writable ref owned by the renderer,
|
|
426
|
+
* like {@link rowDelete}. `<AsTable>` / `<AsWindowTable>` push their
|
|
427
|
+
* `:row-selectable` prop into it, and every selection path in the model
|
|
428
|
+
* gates on it. Since 0.1.133.
|
|
429
|
+
*/
|
|
430
|
+
rowSelectable: Ref<RowSelectableHook | undefined>;
|
|
431
|
+
/**
|
|
432
|
+
* Normalised `rowSelectable` verdict for one row. `index` is the row's
|
|
433
|
+
* position in what the renderer renders (absolute in window mode).
|
|
434
|
+
* Since 0.1.133.
|
|
435
|
+
*/
|
|
436
|
+
isRowSelectable: (row: Record<string, unknown>, index: number) => RowSelectableVerdict;
|
|
437
|
+
/** The subset of `rows` the `rowSelectable` predicate lets through. Since 0.1.133. */
|
|
438
|
+
selectableRows: (rows: readonly Record<string, unknown>[]) => Record<string, unknown>[];
|
|
439
|
+
/** How many of `rows` the `rowSelectable` predicate lets through. Since 0.1.133. */
|
|
440
|
+
selectableCount: (rows: readonly Record<string, unknown>[]) => number;
|
|
441
|
+
/**
|
|
442
|
+
* Select every eligible row in `rows`. An ineligible row that is already
|
|
443
|
+
* selected stays selected. `indexOf` maps a position in `rows` to the
|
|
444
|
+
* index the `rowSelectable` predicate sees — windowed callers pass it
|
|
445
|
+
* because their rows come from a cache keyed by absolute index.
|
|
446
|
+
* Since 0.1.133.
|
|
447
|
+
*/
|
|
448
|
+
selectAll: (rows: readonly Record<string, unknown>[], indexOf?: (position: number) => number) => void;
|
|
376
449
|
/** Column currently open in the filter dialog (null when closed). */
|
|
377
450
|
filterDialogColumn: Ref<ColumnDef | null>;
|
|
378
451
|
/** Absolute index of the keyboard-active row. -1 = nothing active. */
|
|
@@ -398,7 +471,10 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
398
471
|
setActive: (absIndex: number) => void;
|
|
399
472
|
/** Reset the active-row index to `-1`. */
|
|
400
473
|
clearActive: () => void;
|
|
401
|
-
/**
|
|
474
|
+
/**
|
|
475
|
+
* Toggle selection of the active row's PK in `selectedRows`. No-op in
|
|
476
|
+
* `select="none"` and on a row the `rowSelectable` predicate rejects.
|
|
477
|
+
*/
|
|
402
478
|
toggleActiveSelection: (mode: SelectionMode) => void;
|
|
403
479
|
/** Ask the rendering component to emit `main-action` for the active row. */
|
|
404
480
|
requestMainAction: (event: KeyboardEvent | MouseEvent) => void;
|
|
@@ -415,6 +491,12 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
415
491
|
* consumers should not mutate directly.
|
|
416
492
|
*/
|
|
417
493
|
confirmRequest: Ref<ConfirmRequest | null>;
|
|
494
|
+
/**
|
|
495
|
+
* The prompt request the dialog SURFACE renders: the last non-null
|
|
496
|
+
* `confirmRequest`, retained after it is answered so the copy survives the
|
|
497
|
+
* exit animation. Internal — used by the dialog. @since 0.1.133
|
|
498
|
+
*/
|
|
499
|
+
confirmDisplay: Ref<ConfirmRequest | null>;
|
|
418
500
|
/**
|
|
419
501
|
* Open the in-app confirm dialog with `message` as the body. Resolves
|
|
420
502
|
* `true` on accept, `false` on cancel/dismiss. Public — consumers can
|
|
@@ -431,12 +513,24 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
431
513
|
acceptPrompt: () => void;
|
|
432
514
|
/** Resolve the active prompt with `false`. Internal — used by the dialog. */
|
|
433
515
|
dismissPrompt: () => void;
|
|
516
|
+
/**
|
|
517
|
+
* Clear `confirmDisplay` once the dialog surface has left (bound to the
|
|
518
|
+
* content's `after-leave`). A no-op while a prompt is pending. Internal.
|
|
519
|
+
* @since 0.1.133
|
|
520
|
+
*/
|
|
521
|
+
releaseConfirm: () => void;
|
|
434
522
|
/**
|
|
435
523
|
* Currently pending action-form request — `null` when no form is open.
|
|
436
524
|
* Writes are owned by `requestActionInput()` / `acceptActionForm()` /
|
|
437
525
|
* `dismissActionForm()`; consumers should not mutate directly.
|
|
438
526
|
*/
|
|
439
527
|
actionFormRequest: Ref<ActionFormRequest | null>;
|
|
528
|
+
/**
|
|
529
|
+
* The form request the dialog SURFACE renders: the last non-null
|
|
530
|
+
* `actionFormRequest`, retained after it is answered so the title, id chips
|
|
531
|
+
* and form survive the exit animation. Internal. @since 0.1.133
|
|
532
|
+
*/
|
|
533
|
+
actionFormDisplay: Ref<ActionFormRequest | null>;
|
|
440
534
|
/**
|
|
441
535
|
* Open the action-form dialog. Resolves with the submitted form payload
|
|
442
536
|
* on accept, or `null` on cancel/dismiss.
|
|
@@ -449,6 +543,12 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
449
543
|
acceptActionForm: (input: unknown) => void;
|
|
450
544
|
/** Resolve the active form request with `null`. Internal — used by the dialog. */
|
|
451
545
|
dismissActionForm: () => void;
|
|
546
|
+
/**
|
|
547
|
+
* Clear `actionFormDisplay` (and the loaded schema/draft) once the dialog
|
|
548
|
+
* surface has left. A no-op while a request is pending. Internal.
|
|
549
|
+
* @since 0.1.133
|
|
550
|
+
*/
|
|
551
|
+
releaseActionForm: () => void;
|
|
452
552
|
/**
|
|
453
553
|
* Hydrate state from a URL query string produced by `stateToUrlQueryString`.
|
|
454
554
|
* Replaces filters / sorters / search / pagination with values decoded from
|
|
@@ -487,9 +587,22 @@ interface PresetSurface {
|
|
|
487
587
|
* `['columns', 'filters', 'filterOps', 'sorters']`.
|
|
488
588
|
*/
|
|
489
589
|
availableAspects: PresetAspect[];
|
|
590
|
+
/**
|
|
591
|
+
* Aspects a SYSTEM preset owns — subset of `availableAspects`, equal to it
|
|
592
|
+
* unless `preset.systemAspects` narrowed it. Drives apply/reset, the dirty
|
|
593
|
+
* baseline, the picker/dialog badges and the Save-As defaults for system
|
|
594
|
+
* presets. Since 0.1.133.
|
|
595
|
+
*/
|
|
596
|
+
systemAspects: PresetAspect[];
|
|
597
|
+
/**
|
|
598
|
+
* Aspects the preset `id` owns — the ones applying it writes. System →
|
|
599
|
+
* `systemAspects`, stored → what its snapshot claims, `null` (or an id
|
|
600
|
+
* with no row) → `availableAspects`. Since 0.1.133.
|
|
601
|
+
*/
|
|
602
|
+
ownedAspects: (id: string | null) => PresetAspect[];
|
|
490
603
|
/**
|
|
491
604
|
* False when `preset` config is absent OR the initial load returned
|
|
492
|
-
* 401/403 OR any other error. The picker / dialog should hide their UI.
|
|
605
|
+
* 401/403/404 OR any other error. The picker / dialog should hide their UI.
|
|
493
606
|
*/
|
|
494
607
|
available: ComputedRef<boolean>;
|
|
495
608
|
/** Currently active preset id (system `'sys:*'` or stored). null = no active. */
|
|
@@ -548,6 +661,15 @@ interface PresetSurface {
|
|
|
548
661
|
* feature is off.
|
|
549
662
|
*/
|
|
550
663
|
batch: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
664
|
+
/**
|
|
665
|
+
* Error thrown by the most recent mutator, or null — the SINGLE channel
|
|
666
|
+
* for preset write failures. Cleared when an OUTERMOST mutator starts, so
|
|
667
|
+
* a `batch()` counts as one user action: a failure early in a batch is not
|
|
668
|
+
* wiped by a later write inside it, and the batch's last failure wins.
|
|
669
|
+
* Mutators rethrow as well, so a caller can handle a single call; this ref
|
|
670
|
+
* is for UI that only needs to render the failure. Since 0.1.133.
|
|
671
|
+
*/
|
|
672
|
+
lastError: Ref<Error | null>;
|
|
551
673
|
}
|
|
552
674
|
//#endregion
|
|
553
|
-
export { TableNavBridge as _, EnterAction as a, NavKeyOptions as c, ReactiveTableState as d,
|
|
675
|
+
export { TableNavBridge as S, RowSelectableVerdict as _, EnterAction as a, TVueTableActionInfo as b, NavKeyOptions as c, ReactiveTableState as d, RowAttrsHook as f, RowSelectableHook as g, RowHookContext as h, ConfirmOptions as i, PresetConfig as l, RowDeleteOpt as m, ColumnMenuConfig as n, InvokeOpts as o, RowClassHook as p, ConfigTab as r, MainActionRequest as s, ActionResult as t, QueryErrorKind as u, TAsCellTypeComponents as v, TableActionsState as x, TAsTableControls as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ColumnDef, PaginationControl, SortControl, TableDef } from "@atscript/ui";
|
|
2
|
-
import { Component, ComputedRef, Ref, ShallowRef } from "vue";
|
|
2
|
+
import { Component, ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
|
|
3
3
|
import { AsPresetEntryRow, AspectMask, ColumnWidthsMap, ConfigTab, FieldFilters, PresetAspect, PresetCapabilities, PresetSnapshot, SelectionMode, SystemPreset, SystemPresetInput, TableStateMethods } from "@atscript/ui-table";
|
|
4
4
|
import { ClientError, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
|
|
5
5
|
|
|
@@ -190,14 +190,62 @@ interface PresetConfig {
|
|
|
190
190
|
* Add `'itemsPerPage'` for paginated tables; drop any aspect this app doesn't use.
|
|
191
191
|
*/
|
|
192
192
|
aspects?: PresetAspect[];
|
|
193
|
+
/**
|
|
194
|
+
* Aspects a SYSTEM preset owns. Intersected with `aspects`; defaults to all
|
|
195
|
+
* of them. Narrow it to e.g. `['filterOps']` when system presets are
|
|
196
|
+
* filter-only views that must not reset the user's columns, displayed
|
|
197
|
+
* filters, sorters or page size. Since 0.1.133.
|
|
198
|
+
*/
|
|
199
|
+
systemAspects?: PresetAspect[];
|
|
193
200
|
/**
|
|
194
201
|
* Opt-in localStorage overlay for the user's in-flight tweaks (default
|
|
195
202
|
* `false`). Persists `columns` / `filters` / `sorters` / opt-in
|
|
196
203
|
* `itemsPerPage`; `filterOps` / `searchTerm` / pagination are NOT persisted.
|
|
197
204
|
*/
|
|
198
205
|
persistDrafts?: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Identity the draft is stored under — pass the signed-in user's id
|
|
208
|
+
* whenever `persistDrafts` is on, so a shared browser never restores the
|
|
209
|
+
* previous user's draft. Omitted keeps the pre-0.1.133 unscoped key.
|
|
210
|
+
* Since 0.1.133.
|
|
211
|
+
*/
|
|
212
|
+
draftScope?: MaybeRefOrGetter<string | undefined>;
|
|
199
213
|
}
|
|
200
214
|
type QueryErrorKind = "initial" | "query" | "queryNext" | "loadRange";
|
|
215
|
+
/**
|
|
216
|
+
* Context handed to the per-row hooks of `<AsTable>` (`rowSelectable`,
|
|
217
|
+
* `rowClass`, `rowAttrs`). Since 0.1.133.
|
|
218
|
+
*/
|
|
219
|
+
interface RowHookContext {
|
|
220
|
+
/** Position of the row in the rows the renderer is currently rendering. */
|
|
221
|
+
index: number;
|
|
222
|
+
/**
|
|
223
|
+
* Whether the row's pk is in `state.selectedRows` right now. A getter —
|
|
224
|
+
* reading it subscribes that hook call to the selection, so predicates
|
|
225
|
+
* that ignore it are not re-run when the selection changes.
|
|
226
|
+
*/
|
|
227
|
+
readonly selected: boolean;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Per-row selectability predicate. Return `false` — or a string, which is
|
|
231
|
+
* surfaced as the disabled reason on the selection control — to make the row
|
|
232
|
+
* not selectable; `true` (or omitting the prop) keeps it selectable.
|
|
233
|
+
* Since 0.1.133.
|
|
234
|
+
*/
|
|
235
|
+
type RowSelectableHook = (row: Record<string, unknown>, ctx: RowHookContext) => boolean | string | undefined | void;
|
|
236
|
+
/** Extra classes for the row element. Since 0.1.133. */
|
|
237
|
+
type RowClassHook = (row: Record<string, unknown>, ctx: RowHookContext) => string | string[] | Record<string, boolean> | undefined;
|
|
238
|
+
/**
|
|
239
|
+
* Extra attributes for the row element. The framework's own `id`, `role`,
|
|
240
|
+
* `aria-*`, `data-*`, `class` and `style` always win. Since 0.1.133.
|
|
241
|
+
*/
|
|
242
|
+
type RowAttrsHook = (row: Record<string, unknown>, ctx: RowHookContext) => Record<string, unknown> | undefined;
|
|
243
|
+
/** Normalised {@link RowSelectableHook} verdict. */
|
|
244
|
+
interface RowSelectableVerdict {
|
|
245
|
+
ok: boolean;
|
|
246
|
+
/** Disabled reason, when the predicate returned a string. */
|
|
247
|
+
reason?: string;
|
|
248
|
+
}
|
|
201
249
|
/** Controls which sections appear in the column header dropdown menu. */
|
|
202
250
|
interface ColumnMenuConfig {
|
|
203
251
|
sort?: boolean;
|
|
@@ -373,6 +421,31 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
373
421
|
* naturally without consulting mode.
|
|
374
422
|
*/
|
|
375
423
|
isPkSelected: (pk: unknown) => boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Per-row selectability predicate — writable ref owned by the renderer,
|
|
426
|
+
* like {@link rowDelete}. `<AsTable>` / `<AsWindowTable>` push their
|
|
427
|
+
* `:row-selectable` prop into it, and every selection path in the model
|
|
428
|
+
* gates on it. Since 0.1.133.
|
|
429
|
+
*/
|
|
430
|
+
rowSelectable: Ref<RowSelectableHook | undefined>;
|
|
431
|
+
/**
|
|
432
|
+
* Normalised `rowSelectable` verdict for one row. `index` is the row's
|
|
433
|
+
* position in what the renderer renders (absolute in window mode).
|
|
434
|
+
* Since 0.1.133.
|
|
435
|
+
*/
|
|
436
|
+
isRowSelectable: (row: Record<string, unknown>, index: number) => RowSelectableVerdict;
|
|
437
|
+
/** The subset of `rows` the `rowSelectable` predicate lets through. Since 0.1.133. */
|
|
438
|
+
selectableRows: (rows: readonly Record<string, unknown>[]) => Record<string, unknown>[];
|
|
439
|
+
/** How many of `rows` the `rowSelectable` predicate lets through. Since 0.1.133. */
|
|
440
|
+
selectableCount: (rows: readonly Record<string, unknown>[]) => number;
|
|
441
|
+
/**
|
|
442
|
+
* Select every eligible row in `rows`. An ineligible row that is already
|
|
443
|
+
* selected stays selected. `indexOf` maps a position in `rows` to the
|
|
444
|
+
* index the `rowSelectable` predicate sees — windowed callers pass it
|
|
445
|
+
* because their rows come from a cache keyed by absolute index.
|
|
446
|
+
* Since 0.1.133.
|
|
447
|
+
*/
|
|
448
|
+
selectAll: (rows: readonly Record<string, unknown>[], indexOf?: (position: number) => number) => void;
|
|
376
449
|
/** Column currently open in the filter dialog (null when closed). */
|
|
377
450
|
filterDialogColumn: Ref<ColumnDef | null>;
|
|
378
451
|
/** Absolute index of the keyboard-active row. -1 = nothing active. */
|
|
@@ -398,7 +471,10 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
398
471
|
setActive: (absIndex: number) => void;
|
|
399
472
|
/** Reset the active-row index to `-1`. */
|
|
400
473
|
clearActive: () => void;
|
|
401
|
-
/**
|
|
474
|
+
/**
|
|
475
|
+
* Toggle selection of the active row's PK in `selectedRows`. No-op in
|
|
476
|
+
* `select="none"` and on a row the `rowSelectable` predicate rejects.
|
|
477
|
+
*/
|
|
402
478
|
toggleActiveSelection: (mode: SelectionMode) => void;
|
|
403
479
|
/** Ask the rendering component to emit `main-action` for the active row. */
|
|
404
480
|
requestMainAction: (event: KeyboardEvent | MouseEvent) => void;
|
|
@@ -415,6 +491,12 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
415
491
|
* consumers should not mutate directly.
|
|
416
492
|
*/
|
|
417
493
|
confirmRequest: Ref<ConfirmRequest | null>;
|
|
494
|
+
/**
|
|
495
|
+
* The prompt request the dialog SURFACE renders: the last non-null
|
|
496
|
+
* `confirmRequest`, retained after it is answered so the copy survives the
|
|
497
|
+
* exit animation. Internal — used by the dialog. @since 0.1.133
|
|
498
|
+
*/
|
|
499
|
+
confirmDisplay: Ref<ConfirmRequest | null>;
|
|
418
500
|
/**
|
|
419
501
|
* Open the in-app confirm dialog with `message` as the body. Resolves
|
|
420
502
|
* `true` on accept, `false` on cancel/dismiss. Public — consumers can
|
|
@@ -431,12 +513,24 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
431
513
|
acceptPrompt: () => void;
|
|
432
514
|
/** Resolve the active prompt with `false`. Internal — used by the dialog. */
|
|
433
515
|
dismissPrompt: () => void;
|
|
516
|
+
/**
|
|
517
|
+
* Clear `confirmDisplay` once the dialog surface has left (bound to the
|
|
518
|
+
* content's `after-leave`). A no-op while a prompt is pending. Internal.
|
|
519
|
+
* @since 0.1.133
|
|
520
|
+
*/
|
|
521
|
+
releaseConfirm: () => void;
|
|
434
522
|
/**
|
|
435
523
|
* Currently pending action-form request — `null` when no form is open.
|
|
436
524
|
* Writes are owned by `requestActionInput()` / `acceptActionForm()` /
|
|
437
525
|
* `dismissActionForm()`; consumers should not mutate directly.
|
|
438
526
|
*/
|
|
439
527
|
actionFormRequest: Ref<ActionFormRequest | null>;
|
|
528
|
+
/**
|
|
529
|
+
* The form request the dialog SURFACE renders: the last non-null
|
|
530
|
+
* `actionFormRequest`, retained after it is answered so the title, id chips
|
|
531
|
+
* and form survive the exit animation. Internal. @since 0.1.133
|
|
532
|
+
*/
|
|
533
|
+
actionFormDisplay: Ref<ActionFormRequest | null>;
|
|
440
534
|
/**
|
|
441
535
|
* Open the action-form dialog. Resolves with the submitted form payload
|
|
442
536
|
* on accept, or `null` on cancel/dismiss.
|
|
@@ -449,6 +543,12 @@ interface ReactiveTableState extends TableStateMethods {
|
|
|
449
543
|
acceptActionForm: (input: unknown) => void;
|
|
450
544
|
/** Resolve the active form request with `null`. Internal — used by the dialog. */
|
|
451
545
|
dismissActionForm: () => void;
|
|
546
|
+
/**
|
|
547
|
+
* Clear `actionFormDisplay` (and the loaded schema/draft) once the dialog
|
|
548
|
+
* surface has left. A no-op while a request is pending. Internal.
|
|
549
|
+
* @since 0.1.133
|
|
550
|
+
*/
|
|
551
|
+
releaseActionForm: () => void;
|
|
452
552
|
/**
|
|
453
553
|
* Hydrate state from a URL query string produced by `stateToUrlQueryString`.
|
|
454
554
|
* Replaces filters / sorters / search / pagination with values decoded from
|
|
@@ -487,9 +587,22 @@ interface PresetSurface {
|
|
|
487
587
|
* `['columns', 'filters', 'filterOps', 'sorters']`.
|
|
488
588
|
*/
|
|
489
589
|
availableAspects: PresetAspect[];
|
|
590
|
+
/**
|
|
591
|
+
* Aspects a SYSTEM preset owns — subset of `availableAspects`, equal to it
|
|
592
|
+
* unless `preset.systemAspects` narrowed it. Drives apply/reset, the dirty
|
|
593
|
+
* baseline, the picker/dialog badges and the Save-As defaults for system
|
|
594
|
+
* presets. Since 0.1.133.
|
|
595
|
+
*/
|
|
596
|
+
systemAspects: PresetAspect[];
|
|
597
|
+
/**
|
|
598
|
+
* Aspects the preset `id` owns — the ones applying it writes. System →
|
|
599
|
+
* `systemAspects`, stored → what its snapshot claims, `null` (or an id
|
|
600
|
+
* with no row) → `availableAspects`. Since 0.1.133.
|
|
601
|
+
*/
|
|
602
|
+
ownedAspects: (id: string | null) => PresetAspect[];
|
|
490
603
|
/**
|
|
491
604
|
* False when `preset` config is absent OR the initial load returned
|
|
492
|
-
* 401/403 OR any other error. The picker / dialog should hide their UI.
|
|
605
|
+
* 401/403/404 OR any other error. The picker / dialog should hide their UI.
|
|
493
606
|
*/
|
|
494
607
|
available: ComputedRef<boolean>;
|
|
495
608
|
/** Currently active preset id (system `'sys:*'` or stored). null = no active. */
|
|
@@ -548,6 +661,15 @@ interface PresetSurface {
|
|
|
548
661
|
* feature is off.
|
|
549
662
|
*/
|
|
550
663
|
batch: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
664
|
+
/**
|
|
665
|
+
* Error thrown by the most recent mutator, or null — the SINGLE channel
|
|
666
|
+
* for preset write failures. Cleared when an OUTERMOST mutator starts, so
|
|
667
|
+
* a `batch()` counts as one user action: a failure early in a batch is not
|
|
668
|
+
* wiped by a later write inside it, and the batch's last failure wins.
|
|
669
|
+
* Mutators rethrow as well, so a caller can handle a single call; this ref
|
|
670
|
+
* is for UI that only needs to render the failure. Since 0.1.133.
|
|
671
|
+
*/
|
|
672
|
+
lastError: Ref<Error | null>;
|
|
551
673
|
}
|
|
552
674
|
//#endregion
|
|
553
|
-
export { TableNavBridge as _, EnterAction as a, NavKeyOptions as c, ReactiveTableState as d,
|
|
675
|
+
export { TableNavBridge as S, RowSelectableVerdict as _, EnterAction as a, TVueTableActionInfo as b, NavKeyOptions as c, ReactiveTableState as d, RowAttrsHook as f, RowSelectableHook as g, RowHookContext as h, ConfirmOptions as i, PresetConfig as l, RowDeleteOpt as m, ColumnMenuConfig as n, InvokeOpts as o, RowClassHook as p, ConfigTab as r, MainActionRequest as s, ActionResult as t, QueryErrorKind as u, TAsCellTypeComponents as v, TableActionsState as x, TAsTableControls as y };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as createTableState, r as provideTableContext, s as DEFAULT_AVAILABLE_ASPECTS } from "./use-table-state-
|
|
1
|
+
import { n as createTableState, r as provideTableContext, s as DEFAULT_AVAILABLE_ASPECTS } from "./use-table-state-DLJbW753.mjs";
|
|
2
2
|
import { n as useTableSelection } from "./use-table-selection-C84z4OZy.mjs";
|
|
3
3
|
import { createTableDef, getMetaEntry, resetMetaCache } from "@atscript/ui";
|
|
4
|
-
import { computed, inject, isRef, ref, shallowRef, watch } from "vue";
|
|
5
|
-
import { PresetsClient, STANDARD_PRESET_ID, debounce, deserializeDraft,
|
|
4
|
+
import { computed, inject, isRef, ref, shallowRef, toValue, watch } from "vue";
|
|
5
|
+
import { PresetsClient, STANDARD_PRESET_ID, debounce, deserializeDraft, isEmptyDraft, isSystemPresetId, isUnavailableError, resolveSystemPresets, serializeDraft, stableStringify } from "@atscript/ui-table";
|
|
6
6
|
//#region src/composables/as-presets-app.ts
|
|
7
7
|
/**
|
|
8
8
|
* App-wide injection key for the presets system. The host app calls
|
|
@@ -37,11 +37,16 @@ function injectPresetsApp(explicit) {
|
|
|
37
37
|
const DEFAULT_DEBOUNCE_MS = 300;
|
|
38
38
|
/**
|
|
39
39
|
* localStorage overlay manager for table presets. One overlay per
|
|
40
|
-
* `(app, tableKey)`; switching presets clears it (caller's
|
|
41
|
-
* — this composable only tracks state, not which preset is
|
|
40
|
+
* `(app, scope, tableKey)`; switching presets clears it (caller's
|
|
41
|
+
* responsibility — this composable only tracks state, not which preset is
|
|
42
|
+
* active).
|
|
42
43
|
*/
|
|
43
44
|
function useLocalDraft(opts) {
|
|
44
|
-
|
|
45
|
+
/** Resolved per call — `scope` is reactive. */
|
|
46
|
+
function storageKey() {
|
|
47
|
+
const scope = toValue(opts.scope);
|
|
48
|
+
return scope ? `as-table-draft:${opts.app}:${scope}:${opts.tableKey}` : `as-table-draft:${opts.app}:${opts.tableKey}`;
|
|
49
|
+
}
|
|
45
50
|
const debounceMs = opts.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
46
51
|
const storage = resolveStorage(opts.storage);
|
|
47
52
|
function isEnabled() {
|
|
@@ -52,7 +57,7 @@ function useLocalDraft(opts) {
|
|
|
52
57
|
function readDraft() {
|
|
53
58
|
if (!storage) return null;
|
|
54
59
|
try {
|
|
55
|
-
const raw = storage.getItem(
|
|
60
|
+
const raw = storage.getItem(storageKey());
|
|
56
61
|
if (!raw) return null;
|
|
57
62
|
const parsed = JSON.parse(raw);
|
|
58
63
|
if (!parsed || typeof parsed !== "object") return null;
|
|
@@ -65,7 +70,7 @@ function useLocalDraft(opts) {
|
|
|
65
70
|
function writeDraft(draft) {
|
|
66
71
|
if (!storage) return;
|
|
67
72
|
try {
|
|
68
|
-
storage.setItem(
|
|
73
|
+
storage.setItem(storageKey(), JSON.stringify(draft));
|
|
69
74
|
} catch (err) {
|
|
70
75
|
console.warn("[vue-table] useLocalDraft: localStorage write failed", err);
|
|
71
76
|
}
|
|
@@ -73,7 +78,7 @@ function useLocalDraft(opts) {
|
|
|
73
78
|
function clear() {
|
|
74
79
|
if (!storage) return;
|
|
75
80
|
try {
|
|
76
|
-
storage.removeItem(
|
|
81
|
+
storage.removeItem(storageKey());
|
|
77
82
|
} catch {}
|
|
78
83
|
}
|
|
79
84
|
function hydrate(applied) {
|
|
@@ -114,9 +119,17 @@ function useLocalDraft(opts) {
|
|
|
114
119
|
}
|
|
115
120
|
const flushDebounced = debounce(((current, preset) => flush(current, preset)), debounceMs);
|
|
116
121
|
const stop = watch(() => [currentSnapshot(), activePresetSnapshot()], ([current, preset]) => flushDebounced(current, preset), { flush: "post" });
|
|
122
|
+
const stopScope = watch(() => toValue(opts.scope), () => {
|
|
123
|
+
flushDebounced.cancel();
|
|
124
|
+
lastPresetRef = null;
|
|
125
|
+
lastPresetSerialized = "";
|
|
126
|
+
const existing = readDraft();
|
|
127
|
+
lastDraftSerialized = existing && !isEmptyDraft(existing) ? stableStringify(existing) : "";
|
|
128
|
+
}, { flush: "post" });
|
|
117
129
|
return () => {
|
|
118
130
|
flushDebounced.cancel();
|
|
119
131
|
stop();
|
|
132
|
+
stopScope();
|
|
120
133
|
};
|
|
121
134
|
}
|
|
122
135
|
return {
|
|
@@ -250,7 +263,7 @@ function usePresets(opts) {
|
|
|
250
263
|
userConf.value = result.userConf;
|
|
251
264
|
if (result.capabilities !== void 0) capabilities.value = result.capabilities;
|
|
252
265
|
} catch (err) {
|
|
253
|
-
if (
|
|
266
|
+
if (isUnavailableError(err)) {
|
|
254
267
|
denied.value = true;
|
|
255
268
|
presets.value = [];
|
|
256
269
|
userConf.value = null;
|
|
@@ -376,7 +389,8 @@ function useTable(url, opts) {
|
|
|
376
389
|
app: injectPresetsApp(preset.app),
|
|
377
390
|
tableKey: preset.tableKey,
|
|
378
391
|
enabled: preset.persistDrafts ?? false,
|
|
379
|
-
availableAspects: preset.aspects ?? DEFAULT_AVAILABLE_ASPECTS
|
|
392
|
+
availableAspects: preset.aspects ?? DEFAULT_AVAILABLE_ASPECTS,
|
|
393
|
+
scope: preset.draftScope
|
|
380
394
|
}) : null;
|
|
381
395
|
const { state, internals } = createTableState({
|
|
382
396
|
client,
|
|
@@ -417,6 +431,7 @@ function useTable(url, opts) {
|
|
|
417
431
|
presetsHandle,
|
|
418
432
|
draftHandle,
|
|
419
433
|
availableAspects: preset?.aspects,
|
|
434
|
+
systemAspects: preset?.systemAspects,
|
|
420
435
|
persistDrafts: preset?.persistDrafts ?? false
|
|
421
436
|
}
|
|
422
437
|
});
|