@atscript/vue-table 0.1.152 → 0.1.153

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{as-filter-dialog-Cd16xRfM.cjs → as-filter-dialog-BB9M5PhT.cjs} +3 -3
  2. package/dist/{as-filter-dialog-8xvnKXTd.mjs → as-filter-dialog-DA7vdmUO.mjs} +3 -3
  3. package/dist/as-filter-dialog.cjs +1 -1
  4. package/dist/as-filter-dialog.mjs +1 -1
  5. package/dist/{as-filter-field-BPPMOZ9M.cjs → as-filter-field-BFCTuRAa.cjs} +1 -1
  6. package/dist/{as-filter-field-DEBQQy_6.mjs → as-filter-field-BxZwGNoI.mjs} +1 -1
  7. package/dist/as-filter-field.cjs +1 -1
  8. package/dist/as-filter-field.mjs +1 -1
  9. package/dist/{as-filters-C22XxgEx.cjs → as-filters-9kFdHR4q.cjs} +1 -1
  10. package/dist/{as-filters-CT1ks7gu.mjs → as-filters-Cu8Hulrv.mjs} +1 -1
  11. package/dist/as-filters.cjs +1 -1
  12. package/dist/as-filters.mjs +1 -1
  13. package/dist/as-table-actions.d.cts +1 -1
  14. package/dist/as-table-actions.d.mts +1 -1
  15. package/dist/{as-table-actions.vue-BMC3nQ5z.d.mts → as-table-actions.vue-DNNYGVQW.d.mts} +1 -1
  16. package/dist/{as-table-actions.vue-D8KKwLdM.d.cts → as-table-actions.vue-Dzi8wX-e.d.cts} +1 -1
  17. package/dist/{as-table-root-BeyqcJUq.mjs → as-table-root-_eZRGvAC.mjs} +7 -1
  18. package/dist/{as-table-root-BQ5PA2SL.cjs → as-table-root-c2ep1IOv.cjs} +7 -1
  19. package/dist/as-table-root.cjs +1 -1
  20. package/dist/as-table-root.d.cts +1 -1
  21. package/dist/as-table-root.d.mts +1 -1
  22. package/dist/as-table-root.mjs +1 -1
  23. package/dist/{as-table-root.vue-Mvmfeg6Y.d.cts → as-table-root.vue-CwQtwsIY.d.cts} +39 -11
  24. package/dist/{as-table-root.vue-mhHmNm2I.d.mts → as-table-root.vue-D1M2B9A_.d.mts} +39 -11
  25. package/dist/as-table.d.cts +1 -1
  26. package/dist/as-table.d.mts +1 -1
  27. package/dist/as-window-table.d.cts +1 -1
  28. package/dist/as-window-table.d.mts +1 -1
  29. package/dist/index.cjs +5 -5
  30. package/dist/index.d.cts +2 -2
  31. package/dist/index.d.mts +2 -2
  32. package/dist/index.mjs +5 -5
  33. package/dist/{use-table-CTCYFwrE.mjs → use-table-D86LSCnG.mjs} +103 -27
  34. package/dist/{use-table-B3CvWW_y.cjs → use-table-nZElzw2r.cjs} +100 -24
  35. package/package.json +11 -11
@@ -1,14 +1,14 @@
1
1
  const require_use_table_state = require("./use-table-state-zE3BpeA7.cjs");
2
- const require_use_table = require("./use-table-B3CvWW_y.cjs");
2
+ const require_use_table = require("./use-table-nZElzw2r.cjs");
3
3
  const require_use_table_nav_bridge = require("./use-table-nav-bridge-C43u266u.cjs");
4
4
  const require_use_table_component = require("./use-table-component-Daap95CE.cjs");
5
5
  const require_as_config_dialog = require("./as-config-dialog-XSkaW1X0.cjs");
6
6
  const require_use_seed_on_open = require("./use-seed-on-open-Dg9I89fU.cjs");
7
7
  const require_use_condition_format = require("./use-condition-format-Dyb5CVYw.cjs");
8
- const require_as_filter_field = require("./as-filter-field-BPPMOZ9M.cjs");
8
+ const require_as_filter_field = require("./as-filter-field-BFCTuRAa.cjs");
9
9
  const require_as_filter_input = require("./as-filter-input-DZkhoSWO.cjs");
10
10
  const require_as_window_table = require("./as-window-table-BvUfaBj8.cjs");
11
- const require_as_filters = require("./as-filters-C22XxgEx.cjs");
11
+ const require_as_filters = require("./as-filters-9kFdHR4q.cjs");
12
12
  let _atscript_ui = require("@atscript/ui");
13
13
  let vue = require("vue");
14
14
  let _atscript_ui_table = require("@atscript/ui-table");
@@ -1,14 +1,14 @@
1
1
  import { a as useTableContext, o as useTableContextOptional, r as provideTableContext, t as createStaticTableState } from "./use-table-state-DzvCmxEx.mjs";
2
- import { r as useTable } from "./use-table-CTCYFwrE.mjs";
2
+ import { r as useTable } from "./use-table-D86LSCnG.mjs";
3
3
  import { t as useTableNavBridge } from "./use-table-nav-bridge-Ch61msQs.mjs";
4
4
  import { t as useTableComponent } from "./use-table-component-B9QRSvoR.mjs";
5
5
  import { n as useDialogTabKeyboard, t as as_config_dialog_default } from "./as-config-dialog-DW4WfYEi.mjs";
6
6
  import { t as useSeedOnOpen } from "./use-seed-on-open-DO3A1kIb.mjs";
7
7
  import { t as useConditionFormat } from "./use-condition-format-ka5_XiSn.mjs";
8
- import { a as valueColumn, i as hasValuePicker, n as createDistinctPager, r as declineIfRejected } from "./as-filter-field-DEBQQy_6.mjs";
8
+ import { a as valueColumn, i as hasValuePicker, n as createDistinctPager, r as declineIfRejected } from "./as-filter-field-BxZwGNoI.mjs";
9
9
  import { t as as_filter_input_default } from "./as-filter-input-DeI85XVZ.mjs";
10
10
  import { t as as_window_table_default } from "./as-window-table-Cf523h8Q.mjs";
11
- import { t as as_filters_default } from "./as-filters-CT1ks7gu.mjs";
11
+ import { t as as_filters_default } from "./as-filters-Cu8Hulrv.mjs";
12
12
  import { resolveValueHelp, valueHelpDictPaths } from "@atscript/ui";
13
13
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeModels, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderList, resolveDynamicComponent, shallowRef, toDisplayString, unref, useModel, watch, withCtx } from "vue";
14
14
  import { columnDefaultCondition, columnFilter, conditionLabel, filledFilterCount, isColumnFilterable, isFilled, isSimpleEq, isTemporalKind, sameColumnSet, temporalShortcuts } from "@atscript/ui-table";
@@ -1,2 +1,2 @@
1
- const require_as_filter_dialog = require("./as-filter-dialog-Cd16xRfM.cjs");
1
+ const require_as_filter_dialog = require("./as-filter-dialog-BB9M5PhT.cjs");
2
2
  module.exports = require_as_filter_dialog.as_filter_dialog_default;
@@ -1,2 +1,2 @@
1
- import { t as as_filter_dialog_default } from "./as-filter-dialog-8xvnKXTd.mjs";
1
+ import { t as as_filter_dialog_default } from "./as-filter-dialog-DA7vdmUO.mjs";
2
2
  export { as_filter_dialog_default as default };
@@ -1,5 +1,5 @@
1
1
  const require_use_table_state = require("./use-table-state-zE3BpeA7.cjs");
2
- const require_use_table = require("./use-table-B3CvWW_y.cjs");
2
+ const require_use_table = require("./use-table-nZElzw2r.cjs");
3
3
  const require_use_condition_format = require("./use-condition-format-Dyb5CVYw.cjs");
4
4
  const require_as_table_base = require("./as-table-base-D_Hmin8J.cjs");
5
5
  let _atscript_ui = require("@atscript/ui");
@@ -1,5 +1,5 @@
1
1
  import { a as useTableContext } from "./use-table-state-DzvCmxEx.mjs";
2
- import { r as useTable } from "./use-table-CTCYFwrE.mjs";
2
+ import { r as useTable } from "./use-table-D86LSCnG.mjs";
3
3
  import { t as useConditionFormat } from "./use-condition-format-ka5_XiSn.mjs";
4
4
  import { t as as_table_base_default } from "./as-table-base-C1B_VVk-.mjs";
5
5
  import { NUMERIC_VALUE_KINDS, ValueHelpClient, fetchDistinctValues, getMetaEntry, isPickerDeclined, optionValue, resolveValueHelp, valueHelpDictPaths } from "@atscript/ui";
@@ -1,2 +1,2 @@
1
- const require_as_filter_field = require("./as-filter-field-BPPMOZ9M.cjs");
1
+ const require_as_filter_field = require("./as-filter-field-BFCTuRAa.cjs");
2
2
  module.exports = require_as_filter_field.as_filter_field_default;
@@ -1,2 +1,2 @@
1
- import { t as as_filter_field_default } from "./as-filter-field-DEBQQy_6.mjs";
1
+ import { t as as_filter_field_default } from "./as-filter-field-BxZwGNoI.mjs";
2
2
  export { as_filter_field_default as default };
@@ -1,6 +1,6 @@
1
1
  const require_use_table_state = require("./use-table-state-zE3BpeA7.cjs");
2
2
  const require_use_table_component = require("./use-table-component-Daap95CE.cjs");
3
- const require_as_filter_field = require("./as-filter-field-BPPMOZ9M.cjs");
3
+ const require_as_filter_field = require("./as-filter-field-BFCTuRAa.cjs");
4
4
  const require_as_residual_filter = require("./as-residual-filter-BGz7pSdL.cjs");
5
5
  let vue = require("vue");
6
6
  let _atscript_ui_table = require("@atscript/ui-table");
@@ -1,6 +1,6 @@
1
1
  import { a as useTableContext } from "./use-table-state-DzvCmxEx.mjs";
2
2
  import { t as useTableComponent } from "./use-table-component-B9QRSvoR.mjs";
3
- import { t as as_filter_field_default } from "./as-filter-field-DEBQQy_6.mjs";
3
+ import { t as as_filter_field_default } from "./as-filter-field-BxZwGNoI.mjs";
4
4
  import { t as as_residual_filter_default } from "./as-residual-filter-BoeOL9AJ.mjs";
5
5
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, mergeModels, mergeProps, openBlock, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useModel, watch, withCtx } from "vue";
6
6
  import { filterExprKey } from "@atscript/ui-table";
@@ -1,2 +1,2 @@
1
- const require_as_filters = require("./as-filters-C22XxgEx.cjs");
1
+ const require_as_filters = require("./as-filters-9kFdHR4q.cjs");
2
2
  module.exports = require_as_filters.as_filters_default;
@@ -1,2 +1,2 @@
1
- import { t as as_filters_default } from "./as-filters-CT1ks7gu.mjs";
1
+ import { t as as_filters_default } from "./as-filters-Cu8Hulrv.mjs";
2
2
  export { as_filters_default as default };
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./as-table-actions.vue-D8KKwLdM.cjs";
1
+ import { t as _default } from "./as-table-actions.vue-Dzi8wX-e.cjs";
2
2
  export = _default;
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./as-table-actions.vue-BMC3nQ5z.mjs";
1
+ import { t as _default } from "./as-table-actions.vue-DNNYGVQW.mjs";
2
2
  export { _default as default };
@@ -23,7 +23,7 @@ declare var __VLS_1: {
23
23
  defaultAction: TVueTableActionInfo | undefined;
24
24
  otherActions: TVueTableActionInfo[];
25
25
  trailingRowActions: TVueTableActionInfo[];
26
- level: "rows" | "row" | "table";
26
+ level: "table" | "rows" | "row";
27
27
  ids: Record<string, unknown>[];
28
28
  target: PromptTarget | undefined;
29
29
  count: number;
@@ -23,7 +23,7 @@ declare var __VLS_1: {
23
23
  defaultAction: TVueTableActionInfo | undefined;
24
24
  otherActions: TVueTableActionInfo[];
25
25
  trailingRowActions: TVueTableActionInfo[];
26
- level: "rows" | "row" | "table";
26
+ level: "table" | "rows" | "row";
27
27
  ids: Record<string, unknown>[];
28
28
  target: PromptTarget | undefined;
29
29
  count: number;
@@ -1,5 +1,5 @@
1
1
  import { c as warnUnsupportedFilter, i as useRegisterMainActionListener, s as warnFieldsDropped, t as createStaticTableState } from "./use-table-state-DzvCmxEx.mjs";
2
- import { n as finalizeTableState, r as useTable } from "./use-table-CTCYFwrE.mjs";
2
+ import { n as finalizeTableState, r as useTable } from "./use-table-D86LSCnG.mjs";
3
3
  import { n as useCellLocale, t as provideCellLocale } from "./use-cell-locale-Bye0ANIP.mjs";
4
4
  import { t as useTableNavBridge } from "./use-table-nav-bridge-Ch61msQs.mjs";
5
5
  import { t as useHasEmitListener } from "./use-has-emit-listener-CsF2w9iT.mjs";
@@ -44,6 +44,10 @@ var as_table_root_default = /* @__PURE__ */ defineComponent({
44
44
  type: Function,
45
45
  required: false
46
46
  },
47
+ metaKey: {
48
+ type: String,
49
+ required: false
50
+ },
47
51
  controls: {
48
52
  type: Object,
49
53
  required: false
@@ -302,6 +306,7 @@ var as_table_root_default = /* @__PURE__ */ defineComponent({
302
306
  blockSize: props.blockSize,
303
307
  dragReleaseDebounceMs: props.dragReleaseDebounceMs,
304
308
  clientFactory: props.clientFactory,
309
+ metaKey: props.metaKey,
305
310
  controls: props.controls,
306
311
  types: props.types,
307
312
  components: props.components,
@@ -339,6 +344,7 @@ var as_table_root_default = /* @__PURE__ */ defineComponent({
339
344
  "displayColumns",
340
345
  "limit",
341
346
  "clientFactory",
347
+ "metaKey",
342
348
  ...localMode ? ["columns"] : []
343
349
  ];
344
350
  const sameValue = (a, b) => {
@@ -1,5 +1,5 @@
1
1
  const require_use_table_state = require("./use-table-state-zE3BpeA7.cjs");
2
- const require_use_table = require("./use-table-B3CvWW_y.cjs");
2
+ const require_use_table = require("./use-table-nZElzw2r.cjs");
3
3
  const require_use_cell_locale = require("./use-cell-locale-Dy5Rf1yp.cjs");
4
4
  const require_use_table_nav_bridge = require("./use-table-nav-bridge-C43u266u.cjs");
5
5
  const require_use_has_emit_listener = require("./use-has-emit-listener-gD1aWp6N.cjs");
@@ -44,6 +44,10 @@ var as_table_root_default = /* @__PURE__ */ (0, vue.defineComponent)({
44
44
  type: Function,
45
45
  required: false
46
46
  },
47
+ metaKey: {
48
+ type: String,
49
+ required: false
50
+ },
47
51
  controls: {
48
52
  type: Object,
49
53
  required: false
@@ -302,6 +306,7 @@ var as_table_root_default = /* @__PURE__ */ (0, vue.defineComponent)({
302
306
  blockSize: props.blockSize,
303
307
  dragReleaseDebounceMs: props.dragReleaseDebounceMs,
304
308
  clientFactory: props.clientFactory,
309
+ metaKey: props.metaKey,
305
310
  controls: props.controls,
306
311
  types: props.types,
307
312
  components: props.components,
@@ -339,6 +344,7 @@ var as_table_root_default = /* @__PURE__ */ (0, vue.defineComponent)({
339
344
  "displayColumns",
340
345
  "limit",
341
346
  "clientFactory",
347
+ "metaKey",
342
348
  ...localMode ? ["columns"] : []
343
349
  ];
344
350
  const sameValue = (a, b) => {
@@ -1,2 +1,2 @@
1
- const require_as_table_root = require("./as-table-root-BQ5PA2SL.cjs");
1
+ const require_as_table_root = require("./as-table-root-c2ep1IOv.cjs");
2
2
  module.exports = require_as_table_root.as_table_root_default;
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./as-table-root.vue-Mvmfeg6Y.cjs";
1
+ import { t as _default } from "./as-table-root.vue-CwQtwsIY.cjs";
2
2
  export = _default;
@@ -1,2 +1,2 @@
1
- import { t as _default } from "./as-table-root.vue-mhHmNm2I.mjs";
1
+ import { t as _default } from "./as-table-root.vue-D1M2B9A_.mjs";
2
2
  export { _default as default };
@@ -1,2 +1,2 @@
1
- import { t as as_table_root_default } from "./as-table-root-BeyqcJUq.mjs";
1
+ import { t as as_table_root_default } from "./as-table-root-_eZRGvAC.mjs";
2
2
  export { as_table_root_default as default };
@@ -124,6 +124,11 @@ interface UsePresetsReturn {
124
124
  systemPresetsById: ComputedRef<Map<string, SystemPreset>>;
125
125
  /** False on 401/403 from initial load — UI hides itself. */
126
126
  available: ComputedRef<boolean>;
127
+ /**
128
+ * True while the preset rows load. Capabilities load beside it and never
129
+ * hold it (they arrive in `capabilities`); a load served from the session
130
+ * cache never sets it.
131
+ */
127
132
  loading: Ref<boolean>;
128
133
  /**
129
134
  * Load failure from `reload()`, or null. Mutator failures are NOT recorded
@@ -188,6 +193,14 @@ interface UsePresetsReturn {
188
193
  * Stateful: holds reactive `presets` / `userConf` / `capabilities` and
189
194
  * supports optimistic mutators that re-list after each successful write.
190
195
  *
196
+ * Once the app binds the viewer with `setMetaCacheIdentity()`, loads go
197
+ * through the browser session cache of `@atscript/ui-table`: a re-mount
198
+ * applies the cached rows synchronously (no request inside the max age,
199
+ * a background revalidation after it), capabilities load once per session,
200
+ * and a write here updates every other mounted consumer of the same
201
+ * `(url, app, tableKey)` — in this tab directly, in other tabs through a
202
+ * `BroadcastChannel`.
203
+ *
191
204
  * Active-preset selection (`activePresetId`) is **owned by the caller** —
192
205
  * the composable provides the ref but doesn't auto-resolve it on mount;
193
206
  * that's the table-state's responsibility (Slice 4) since it depends on
@@ -589,6 +602,14 @@ interface UseTableOptions {
589
602
  dragReleaseDebounceMs?: number;
590
603
  /** Factory to create a client from a URL. Only honored on the first `useTable`/`resolveValueHelp` call per URL — subsequent callers reuse the cached client. */
591
604
  clientFactory?: ClientFactory;
605
+ /**
606
+ * Store key for `/meta` revalidation (default: the URL). Pass the route
607
+ * template of a parametric mount (e.g. `"/api/db/ticket-issue/:key"`) so
608
+ * every key shares one stored `/meta`: a new key costs a `304`, not the
609
+ * full body. Only honored on the first call per URL, like `clientFactory`.
610
+ * Since 0.1.153.
611
+ */
612
+ metaKey?: string;
592
613
  /** Skin-slot overrides for table chrome (header cells, filter dialog, column menu, etc.). */
593
614
  controls?: TAsTableControls;
594
615
  /** Cell-type → component dispatch map. Use {@link createDefaultCellTypes} to seed defaults. */
@@ -1121,20 +1142,20 @@ type __VLS_Slots$2 = {} & { [K in NonNullable<typeof __VLS_28>]?: (props: typeof
1121
1142
  'query-loading'?: (props: typeof __VLS_31) => any;
1122
1143
  };
1123
1144
  declare const __VLS_base$2: vue.DefineComponent<__VLS_Props$2, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1124
- "main-action": (row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1145
+ "main-action": (row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1125
1146
  "row-click": (row: Record<string, unknown>, event: MouseEvent) => any;
1126
1147
  "row-dblclick": (row: Record<string, unknown>, event: MouseEvent) => any;
1127
1148
  }, string, vue.PublicProps, Readonly<__VLS_Props$2> & Readonly<{
1128
- "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1149
+ "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1129
1150
  "onRow-click"?: ((row: Record<string, unknown>, event: MouseEvent) => any) | undefined;
1130
1151
  "onRow-dblclick"?: ((row: Record<string, unknown>, event: MouseEvent) => any) | undefined;
1131
1152
  }>, {
1153
+ select: SelectionMode;
1132
1154
  stickyHeader: boolean;
1133
1155
  virtualOverscan: number;
1134
1156
  reorderable: boolean;
1135
1157
  resizable: boolean;
1136
1158
  columnMinWidth: number;
1137
- select: SelectionMode;
1138
1159
  selectOn: SelectOn;
1139
1160
  rowDelete: boolean | RowDeleteOpt;
1140
1161
  rowActionsColumn: RowActionsColumnPlacement | false;
@@ -1256,20 +1277,20 @@ type __VLS_Slots$1 = {} & { [K in NonNullable<typeof __VLS_24>]?: (props: typeof
1256
1277
  'query-loading'?: (props: typeof __VLS_27) => any;
1257
1278
  };
1258
1279
  declare const __VLS_base$1: vue.DefineComponent<__VLS_Props$1, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1259
- "main-action": (row: Row, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1280
+ "main-action": (row: Row, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1260
1281
  "row-click": (row: Row, event: MouseEvent) => any;
1261
1282
  "row-dblclick": (row: Row, event: MouseEvent) => any;
1262
1283
  error: (error: Error, kind: QueryErrorKind) => any;
1263
1284
  }, string, vue.PublicProps, Readonly<__VLS_Props$1> & Readonly<{
1264
- "onMain-action"?: ((row: Row, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1285
+ "onMain-action"?: ((row: Row, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1265
1286
  "onRow-click"?: ((row: Row, event: MouseEvent) => any) | undefined;
1266
1287
  "onRow-dblclick"?: ((row: Row, event: MouseEvent) => any) | undefined;
1267
1288
  onError?: ((error: Error, kind: QueryErrorKind) => any) | undefined;
1268
1289
  }>, {
1290
+ select: SelectionMode;
1269
1291
  reorderable: boolean;
1270
1292
  resizable: boolean;
1271
1293
  columnMinWidth: number;
1272
- select: SelectionMode;
1273
1294
  selectOn: SelectOn;
1274
1295
  rowDelete: boolean | RowDeleteOpt;
1275
1296
  rowActionsColumn: RowActionsColumnPlacement | false;
@@ -1382,7 +1403,14 @@ type __VLS_Props = {
1382
1403
  * a row's `$actions` gated away never appears. Since 0.1.134.
1383
1404
  */
1384
1405
  rowActions?: RowActionsConfig; /** Factory to create a client from a URL. Falls back to the app-wide default set via `setDefaultClientFactory` (or the built-in `new Client(url)` factory if unset). */
1385
- clientFactory?: ClientFactory; /** Skin-slot overrides for table chrome — header cells, filter dialog, column menu, etc. Use {@link createDefaultControls} to seed defaults. */
1406
+ clientFactory?: ClientFactory;
1407
+ /**
1408
+ * Store key for `/meta` revalidation (default: the URL). Pass the route
1409
+ * template of a parametric mount (e.g. `"/api/db/ticket-issue/:key"`) so
1410
+ * a table opened for a new key revalidates the `/meta` already loaded for
1411
+ * another key (a `304`) instead of downloading it. Since 0.1.153.
1412
+ */
1413
+ metaKey?: string; /** Skin-slot overrides for table chrome — header cells, filter dialog, column menu, etc. Use {@link createDefaultControls} to seed defaults. */
1386
1414
  controls?: TAsTableControls; /** Cell-type → component dispatch map. Use {@link createDefaultCellTypes} to seed defaults. */
1387
1415
  types?: TAsCellTypeComponents; /** Named cell-component overrides — looked up by `@ui.table.component "name"`. */
1388
1416
  components?: Record<string, Component>;
@@ -1554,12 +1582,13 @@ declare const __VLS_base: vue.DefineComponent<__VLS_PublicProps, {
1554
1582
  "update:querySelection": (value: QuerySelection | null) => any;
1555
1583
  "update:urlQuery": (value: string | undefined) => any;
1556
1584
  } & {
1585
+ action: (action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: MouseEvent | KeyboardEvent | undefined) => any;
1557
1586
  "unsupported-filter": (issue: UnsupportedFilter) => any;
1558
1587
  "selection-reset": (event: SelectionResetEvent) => any;
1559
1588
  "fields-dropped": (report: DroppedFieldsReport) => any;
1560
- "main-action": (row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1561
- action: (action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: KeyboardEvent | MouseEvent | undefined) => any;
1589
+ "main-action": (row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1562
1590
  }, string, vue.PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
1591
+ onAction?: ((action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: MouseEvent | KeyboardEvent | undefined) => any) | undefined;
1563
1592
  "onUnsupported-filter"?: ((issue: UnsupportedFilter) => any) | undefined;
1564
1593
  "onSelection-reset"?: ((event: SelectionResetEvent) => any) | undefined;
1565
1594
  "onFields-dropped"?: ((report: DroppedFieldsReport) => any) | undefined;
@@ -1571,8 +1600,7 @@ declare const __VLS_base: vue.DefineComponent<__VLS_PublicProps, {
1571
1600
  "onUpdate:selectedRows"?: ((value: unknown[]) => any) | undefined;
1572
1601
  "onUpdate:querySelection"?: ((value: QuerySelection | null) => any) | undefined;
1573
1602
  "onUpdate:urlQuery"?: ((value: string | undefined) => any) | undefined;
1574
- "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1575
- onAction?: ((action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: KeyboardEvent | MouseEvent | undefined) => any) | undefined;
1603
+ "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1576
1604
  }>, {
1577
1605
  localSort: boolean;
1578
1606
  queryOnMount: boolean;
@@ -124,6 +124,11 @@ interface UsePresetsReturn {
124
124
  systemPresetsById: ComputedRef<Map<string, SystemPreset>>;
125
125
  /** False on 401/403 from initial load — UI hides itself. */
126
126
  available: ComputedRef<boolean>;
127
+ /**
128
+ * True while the preset rows load. Capabilities load beside it and never
129
+ * hold it (they arrive in `capabilities`); a load served from the session
130
+ * cache never sets it.
131
+ */
127
132
  loading: Ref<boolean>;
128
133
  /**
129
134
  * Load failure from `reload()`, or null. Mutator failures are NOT recorded
@@ -188,6 +193,14 @@ interface UsePresetsReturn {
188
193
  * Stateful: holds reactive `presets` / `userConf` / `capabilities` and
189
194
  * supports optimistic mutators that re-list after each successful write.
190
195
  *
196
+ * Once the app binds the viewer with `setMetaCacheIdentity()`, loads go
197
+ * through the browser session cache of `@atscript/ui-table`: a re-mount
198
+ * applies the cached rows synchronously (no request inside the max age,
199
+ * a background revalidation after it), capabilities load once per session,
200
+ * and a write here updates every other mounted consumer of the same
201
+ * `(url, app, tableKey)` — in this tab directly, in other tabs through a
202
+ * `BroadcastChannel`.
203
+ *
191
204
  * Active-preset selection (`activePresetId`) is **owned by the caller** —
192
205
  * the composable provides the ref but doesn't auto-resolve it on mount;
193
206
  * that's the table-state's responsibility (Slice 4) since it depends on
@@ -589,6 +602,14 @@ interface UseTableOptions {
589
602
  dragReleaseDebounceMs?: number;
590
603
  /** Factory to create a client from a URL. Only honored on the first `useTable`/`resolveValueHelp` call per URL — subsequent callers reuse the cached client. */
591
604
  clientFactory?: ClientFactory;
605
+ /**
606
+ * Store key for `/meta` revalidation (default: the URL). Pass the route
607
+ * template of a parametric mount (e.g. `"/api/db/ticket-issue/:key"`) so
608
+ * every key shares one stored `/meta`: a new key costs a `304`, not the
609
+ * full body. Only honored on the first call per URL, like `clientFactory`.
610
+ * Since 0.1.153.
611
+ */
612
+ metaKey?: string;
592
613
  /** Skin-slot overrides for table chrome (header cells, filter dialog, column menu, etc.). */
593
614
  controls?: TAsTableControls;
594
615
  /** Cell-type → component dispatch map. Use {@link createDefaultCellTypes} to seed defaults. */
@@ -1121,20 +1142,20 @@ type __VLS_Slots$2 = {} & { [K in NonNullable<typeof __VLS_28>]?: (props: typeof
1121
1142
  'query-loading'?: (props: typeof __VLS_31) => any;
1122
1143
  };
1123
1144
  declare const __VLS_base$2: vue.DefineComponent<__VLS_Props$2, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1124
- "main-action": (row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1145
+ "main-action": (row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1125
1146
  "row-click": (row: Record<string, unknown>, event: MouseEvent) => any;
1126
1147
  "row-dblclick": (row: Record<string, unknown>, event: MouseEvent) => any;
1127
1148
  }, string, vue.PublicProps, Readonly<__VLS_Props$2> & Readonly<{
1128
- "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1149
+ "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1129
1150
  "onRow-click"?: ((row: Record<string, unknown>, event: MouseEvent) => any) | undefined;
1130
1151
  "onRow-dblclick"?: ((row: Record<string, unknown>, event: MouseEvent) => any) | undefined;
1131
1152
  }>, {
1153
+ select: SelectionMode;
1132
1154
  stickyHeader: boolean;
1133
1155
  virtualOverscan: number;
1134
1156
  reorderable: boolean;
1135
1157
  resizable: boolean;
1136
1158
  columnMinWidth: number;
1137
- select: SelectionMode;
1138
1159
  selectOn: SelectOn;
1139
1160
  rowDelete: boolean | RowDeleteOpt;
1140
1161
  rowActionsColumn: RowActionsColumnPlacement | false;
@@ -1256,20 +1277,20 @@ type __VLS_Slots$1 = {} & { [K in NonNullable<typeof __VLS_24>]?: (props: typeof
1256
1277
  'query-loading'?: (props: typeof __VLS_27) => any;
1257
1278
  };
1258
1279
  declare const __VLS_base$1: vue.DefineComponent<__VLS_Props$1, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {} & {
1259
- "main-action": (row: Row, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1280
+ "main-action": (row: Row, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1260
1281
  "row-click": (row: Row, event: MouseEvent) => any;
1261
1282
  "row-dblclick": (row: Row, event: MouseEvent) => any;
1262
1283
  error: (error: Error, kind: QueryErrorKind) => any;
1263
1284
  }, string, vue.PublicProps, Readonly<__VLS_Props$1> & Readonly<{
1264
- "onMain-action"?: ((row: Row, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1285
+ "onMain-action"?: ((row: Row, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1265
1286
  "onRow-click"?: ((row: Row, event: MouseEvent) => any) | undefined;
1266
1287
  "onRow-dblclick"?: ((row: Row, event: MouseEvent) => any) | undefined;
1267
1288
  onError?: ((error: Error, kind: QueryErrorKind) => any) | undefined;
1268
1289
  }>, {
1290
+ select: SelectionMode;
1269
1291
  reorderable: boolean;
1270
1292
  resizable: boolean;
1271
1293
  columnMinWidth: number;
1272
- select: SelectionMode;
1273
1294
  selectOn: SelectOn;
1274
1295
  rowDelete: boolean | RowDeleteOpt;
1275
1296
  rowActionsColumn: RowActionsColumnPlacement | false;
@@ -1382,7 +1403,14 @@ type __VLS_Props = {
1382
1403
  * a row's `$actions` gated away never appears. Since 0.1.134.
1383
1404
  */
1384
1405
  rowActions?: RowActionsConfig; /** Factory to create a client from a URL. Falls back to the app-wide default set via `setDefaultClientFactory` (or the built-in `new Client(url)` factory if unset). */
1385
- clientFactory?: ClientFactory; /** Skin-slot overrides for table chrome — header cells, filter dialog, column menu, etc. Use {@link createDefaultControls} to seed defaults. */
1406
+ clientFactory?: ClientFactory;
1407
+ /**
1408
+ * Store key for `/meta` revalidation (default: the URL). Pass the route
1409
+ * template of a parametric mount (e.g. `"/api/db/ticket-issue/:key"`) so
1410
+ * a table opened for a new key revalidates the `/meta` already loaded for
1411
+ * another key (a `304`) instead of downloading it. Since 0.1.153.
1412
+ */
1413
+ metaKey?: string; /** Skin-slot overrides for table chrome — header cells, filter dialog, column menu, etc. Use {@link createDefaultControls} to seed defaults. */
1386
1414
  controls?: TAsTableControls; /** Cell-type → component dispatch map. Use {@link createDefaultCellTypes} to seed defaults. */
1387
1415
  types?: TAsCellTypeComponents; /** Named cell-component overrides — looked up by `@ui.table.component "name"`. */
1388
1416
  components?: Record<string, Component>;
@@ -1554,12 +1582,13 @@ declare const __VLS_base: vue.DefineComponent<__VLS_PublicProps, {
1554
1582
  "update:querySelection": (value: QuerySelection | null) => any;
1555
1583
  "update:urlQuery": (value: string | undefined) => any;
1556
1584
  } & {
1585
+ action: (action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: MouseEvent | KeyboardEvent | undefined) => any;
1557
1586
  "unsupported-filter": (issue: UnsupportedFilter) => any;
1558
1587
  "selection-reset": (event: SelectionResetEvent) => any;
1559
1588
  "fields-dropped": (report: DroppedFieldsReport) => any;
1560
- "main-action": (row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any;
1561
- action: (action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: KeyboardEvent | MouseEvent | undefined) => any;
1589
+ "main-action": (row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any;
1562
1590
  }, string, vue.PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
1591
+ onAction?: ((action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: MouseEvent | KeyboardEvent | undefined) => any) | undefined;
1563
1592
  "onUnsupported-filter"?: ((issue: UnsupportedFilter) => any) | undefined;
1564
1593
  "onSelection-reset"?: ((event: SelectionResetEvent) => any) | undefined;
1565
1594
  "onFields-dropped"?: ((report: DroppedFieldsReport) => any) | undefined;
@@ -1571,8 +1600,7 @@ declare const __VLS_base: vue.DefineComponent<__VLS_PublicProps, {
1571
1600
  "onUpdate:selectedRows"?: ((value: unknown[]) => any) | undefined;
1572
1601
  "onUpdate:querySelection"?: ((value: QuerySelection | null) => any) | undefined;
1573
1602
  "onUpdate:urlQuery"?: ((value: string | undefined) => any) | undefined;
1574
- "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: KeyboardEvent | MouseEvent) => any) | undefined;
1575
- onAction?: ((action: TVueTableActionInfo, ids: unknown[], result: ActionResult, event?: KeyboardEvent | MouseEvent | undefined) => any) | undefined;
1603
+ "onMain-action"?: ((row: Record<string, unknown>, absIndex: number, event: MouseEvent | KeyboardEvent) => any) | undefined;
1576
1604
  }>, {
1577
1605
  localSort: boolean;
1578
1606
  queryOnMount: boolean;
@@ -1,2 +1,2 @@
1
- import { L as _default } from "./as-table-root.vue-Mvmfeg6Y.cjs";
1
+ import { L as _default } from "./as-table-root.vue-CwQtwsIY.cjs";
2
2
  export = _default;
@@ -1,2 +1,2 @@
1
- import { L as _default } from "./as-table-root.vue-mhHmNm2I.mjs";
1
+ import { L as _default } from "./as-table-root.vue-D1M2B9A_.mjs";
2
2
  export { _default as default };
@@ -1,2 +1,2 @@
1
- import { I as _default } from "./as-table-root.vue-Mvmfeg6Y.cjs";
1
+ import { I as _default } from "./as-table-root.vue-CwQtwsIY.cjs";
2
2
  export = _default;
@@ -1,2 +1,2 @@
1
- import { I as _default } from "./as-table-root.vue-mhHmNm2I.mjs";
1
+ import { I as _default } from "./as-table-root.vue-D1M2B9A_.mjs";
2
2
  export { _default as default };
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_use_table_state = require("./use-table-state-zE3BpeA7.cjs");
3
3
  const require_get_cell_value = require("./get-cell-value-CJT4fk4y.cjs");
4
4
  const require_use_table_selection = require("./use-table-selection-Cs7-gjHg.cjs");
5
- const require_use_table = require("./use-table-B3CvWW_y.cjs");
5
+ const require_use_table = require("./use-table-nZElzw2r.cjs");
6
6
  const require_use_cell_locale = require("./use-cell-locale-Dy5Rf1yp.cjs");
7
7
  const require_use_table_nav_bridge = require("./use-table-nav-bridge-C43u266u.cjs");
8
8
  const require_use_table_component = require("./use-table-component-Daap95CE.cjs");
@@ -15,17 +15,17 @@ const require_as_cell_union = require("./as-cell-union-DpCEHLzN.cjs");
15
15
  const require_as_column_menu = require("./as-column-menu-ChB7hzmr.cjs");
16
16
  const require_as_config_dialog = require("./as-config-dialog-XSkaW1X0.cjs");
17
17
  const require_as_confirm_dialog = require("./as-confirm-dialog-pcKkl-Qo.cjs");
18
- const require_as_filter_field = require("./as-filter-field-BPPMOZ9M.cjs");
18
+ const require_as_filter_field = require("./as-filter-field-BFCTuRAa.cjs");
19
19
  const require_as_filter_input = require("./as-filter-input-DZkhoSWO.cjs");
20
- const require_as_filter_dialog = require("./as-filter-dialog-Cd16xRfM.cjs");
20
+ const require_as_filter_dialog = require("./as-filter-dialog-BB9M5PhT.cjs");
21
21
  const require_as_table_header_cell = require("./as-table-header-cell-Ch0J_Axe.cjs");
22
22
  const require_as_window_table = require("./as-window-table-BvUfaBj8.cjs");
23
23
  const require_as_table_cell_value = require("./as-table-cell-value-CGBk-KWx.cjs");
24
24
  const require_as_residual_filter = require("./as-residual-filter-BGz7pSdL.cjs");
25
- const require_as_filters = require("./as-filters-C22XxgEx.cjs");
25
+ const require_as_filters = require("./as-filters-9kFdHR4q.cjs");
26
26
  const require_as_preset_dialog = require("./as-preset-dialog-CFvmrXGP.cjs");
27
27
  const require_as_row_actions = require("./as-row-actions-S_IVb5c2.cjs");
28
- const require_as_table_root = require("./as-table-root-BQ5PA2SL.cjs");
28
+ const require_as_table_root = require("./as-table-root-c2ep1IOv.cjs");
29
29
  const require_as_table = require("./as-table-BIKHGH4x.cjs");
30
30
  const require_as_table_actions = require("./as-table-actions-CgMktjjD.cjs");
31
31
  const require_as_preset_picker = require("./as-preset-picker-DjV1c6Kh.cjs");
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { t as _default$11 } from "./as-filters.vue-vH1FHn9L.cjs";
2
2
  import { t as _default$13 } from "./as-preset-picker.vue-DfXS3pGl.cjs";
3
3
  import { A as RowSelectableHook, B as TableSelection, C as ResolvedRowActions, D as RowClassHook, E as RowAttrsHook, F as TAsCellTypeComponents, I as TAsTableControls, L as TVueTableActionInfo, M as SelectAllState, N as SelectOn, O as RowDeleteOpt, P as SelectionResetEvent, R as TableActionsState, S as ReactiveTableState, T as RowActionsConfig, V as resolveRowActions, _ as MainActionRequest, a as identifierFieldsOf, b as QueryErrorKind, c as ActionResult, d as ConfigTab, g as LocalRowAction, h as InvokeOpts, i as extractIdentifier, j as RowSelectableVerdict, k as RowHookContext, l as ApplyUrlQueryOptions, n as QUERY_TARGET_UNSUPPORTED_REASON, o as queryTargetGate, p as DroppedFieldsReport, r as actionIdentifiers, s as ActionQueryTarget, u as ColumnMenuConfig, v as NavKeyOptions, x as QuerySelection, z as TableNavBridge } from "./intent-scope-CGch9yhy.cjs";
4
- import { t as _default$16 } from "./as-table-actions.vue-D8KKwLdM.cjs";
5
- import { $ as ExportProgress, A as getColumnWidth, B as UseAppPrefsReturn, C as getDefaultClientFactory, Ct as UsePresetsOptions, D as setDefaultClientFactory, Dt as UseLocalDraftOptions, E as resolveSystemPresets, Et as StorageLike, F as createDefaultControls, G as TableUrlQueryRouter, H as AS_PRESETS_APP, I as _default$20, J as useTableActions, K as UseTableUrlQueryOptions, L as _default$15, M as provideCellLocale, N as useCellLocale, O as formatCellValue, Ot as UseLocalDraftReturn, P as createDefaultCellTypes, Q as ExportCellFormatter, R as useTableComponent, S as UserConfData, St as ActivePresetView, T as resetDefaultClientFactory, Tt as usePresets, U as injectPresetsApp, V as useAppPrefs, W as TableUrlQueryRoute, X as useTableFilter, Y as useTableSearch, Z as useTableNavBridge, _ as SYSTEM_PRESET_PREFIX, _t as createStaticTableState, a as CsvOptions, at as UseTableOptions, b as SystemPresetInput, bt as useTableContext, c as ExportScalar, ct as SelectionPersistence, d as PresetCapabilities, dt as CreateStaticTableStateOptions, et as ExportResult, f as PresetData, ft as CreateTableStateOptions, g as STANDARD_PRESET_ID, gt as TableStateInternals, h as QueryOptions, ht as TableModelRefs, i as ClientFactory, it as useTableExport, j as CellLocale, k as getCellValue, kt as useLocalDraft, l as PRESET_ASPECTS, lt as useTableSelection, m as PresetSnapshotWire, mt as TableContext, n as AppConfData, nt as UseTableExportReturn, o as DisplayColumnDef, ot as clearTableCache, p as PresetSnapshot, pt as QueryFn, q as useTableUrlQuery, r as AsPresetEntryRow, rt as downloadExport, s as ExportAbortError, st as useTable, t as _default$19, tt as ExportRowsOptions, u as PresetAspect, ut as BuildQueryOptions, v as SelectionQuery, vt as createTableState, w as isSystemPresetId, wt as UsePresetsReturn, x as UrlQuerySync, xt as useTableContextOptional, y as SystemPreset, yt as provideTableContext, z as UseAppPrefsOptions } from "./as-table-root.vue-Mvmfeg6Y.cjs";
4
+ import { t as _default$16 } from "./as-table-actions.vue-Dzi8wX-e.cjs";
5
+ import { $ as ExportProgress, A as getColumnWidth, B as UseAppPrefsReturn, C as getDefaultClientFactory, Ct as UsePresetsOptions, D as setDefaultClientFactory, Dt as UseLocalDraftOptions, E as resolveSystemPresets, Et as StorageLike, F as createDefaultControls, G as TableUrlQueryRouter, H as AS_PRESETS_APP, I as _default$20, J as useTableActions, K as UseTableUrlQueryOptions, L as _default$15, M as provideCellLocale, N as useCellLocale, O as formatCellValue, Ot as UseLocalDraftReturn, P as createDefaultCellTypes, Q as ExportCellFormatter, R as useTableComponent, S as UserConfData, St as ActivePresetView, T as resetDefaultClientFactory, Tt as usePresets, U as injectPresetsApp, V as useAppPrefs, W as TableUrlQueryRoute, X as useTableFilter, Y as useTableSearch, Z as useTableNavBridge, _ as SYSTEM_PRESET_PREFIX, _t as createStaticTableState, a as CsvOptions, at as UseTableOptions, b as SystemPresetInput, bt as useTableContext, c as ExportScalar, ct as SelectionPersistence, d as PresetCapabilities, dt as CreateStaticTableStateOptions, et as ExportResult, f as PresetData, ft as CreateTableStateOptions, g as STANDARD_PRESET_ID, gt as TableStateInternals, h as QueryOptions, ht as TableModelRefs, i as ClientFactory, it as useTableExport, j as CellLocale, k as getCellValue, kt as useLocalDraft, l as PRESET_ASPECTS, lt as useTableSelection, m as PresetSnapshotWire, mt as TableContext, n as AppConfData, nt as UseTableExportReturn, o as DisplayColumnDef, ot as clearTableCache, p as PresetSnapshot, pt as QueryFn, q as useTableUrlQuery, r as AsPresetEntryRow, rt as downloadExport, s as ExportAbortError, st as useTable, t as _default$19, tt as ExportRowsOptions, u as PresetAspect, ut as BuildQueryOptions, v as SelectionQuery, vt as createTableState, w as isSystemPresetId, wt as UsePresetsReturn, x as UrlQuerySync, xt as useTableContextOptional, y as SystemPreset, yt as provideTableContext, z as UseAppPrefsOptions } from "./as-table-root.vue-CwQtwsIY.cjs";
6
6
  import { t as _default } from "./as-cell-array.vue-C4BTM8YW.cjs";
7
7
  import { t as _default$1 } from "./as-cell-date.vue-DwTSTjsj.cjs";
8
8
  import { t as _default$2 } from "./as-cell-json.vue-pwE9uJdv.cjs";
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { t as _default$11 } from "./as-filters.vue-Bu4wK0iD.mjs";
2
2
  import { t as _default$13 } from "./as-preset-picker.vue-DAUZOlOD.mjs";
3
3
  import { A as RowSelectableHook, B as TableSelection, C as ResolvedRowActions, D as RowClassHook, E as RowAttrsHook, F as TAsCellTypeComponents, I as TAsTableControls, L as TVueTableActionInfo, M as SelectAllState, N as SelectOn, O as RowDeleteOpt, P as SelectionResetEvent, R as TableActionsState, S as ReactiveTableState, T as RowActionsConfig, V as resolveRowActions, _ as MainActionRequest, a as identifierFieldsOf, b as QueryErrorKind, c as ActionResult, d as ConfigTab, g as LocalRowAction, h as InvokeOpts, i as extractIdentifier, j as RowSelectableVerdict, k as RowHookContext, l as ApplyUrlQueryOptions, n as QUERY_TARGET_UNSUPPORTED_REASON, o as queryTargetGate, p as DroppedFieldsReport, r as actionIdentifiers, s as ActionQueryTarget, u as ColumnMenuConfig, v as NavKeyOptions, x as QuerySelection, z as TableNavBridge } from "./intent-scope-CvD4YOvf.mjs";
4
- import { t as _default$16 } from "./as-table-actions.vue-BMC3nQ5z.mjs";
5
- import { $ as ExportProgress, A as getColumnWidth, B as UseAppPrefsReturn, C as getDefaultClientFactory, Ct as UsePresetsOptions, D as setDefaultClientFactory, Dt as UseLocalDraftOptions, E as resolveSystemPresets, Et as StorageLike, F as createDefaultControls, G as TableUrlQueryRouter, H as AS_PRESETS_APP, I as _default$20, J as useTableActions, K as UseTableUrlQueryOptions, L as _default$15, M as provideCellLocale, N as useCellLocale, O as formatCellValue, Ot as UseLocalDraftReturn, P as createDefaultCellTypes, Q as ExportCellFormatter, R as useTableComponent, S as UserConfData, St as ActivePresetView, T as resetDefaultClientFactory, Tt as usePresets, U as injectPresetsApp, V as useAppPrefs, W as TableUrlQueryRoute, X as useTableFilter, Y as useTableSearch, Z as useTableNavBridge, _ as SYSTEM_PRESET_PREFIX, _t as createStaticTableState, a as CsvOptions, at as UseTableOptions, b as SystemPresetInput, bt as useTableContext, c as ExportScalar, ct as SelectionPersistence, d as PresetCapabilities, dt as CreateStaticTableStateOptions, et as ExportResult, f as PresetData, ft as CreateTableStateOptions, g as STANDARD_PRESET_ID, gt as TableStateInternals, h as QueryOptions, ht as TableModelRefs, i as ClientFactory, it as useTableExport, j as CellLocale, k as getCellValue, kt as useLocalDraft, l as PRESET_ASPECTS, lt as useTableSelection, m as PresetSnapshotWire, mt as TableContext, n as AppConfData, nt as UseTableExportReturn, o as DisplayColumnDef, ot as clearTableCache, p as PresetSnapshot, pt as QueryFn, q as useTableUrlQuery, r as AsPresetEntryRow, rt as downloadExport, s as ExportAbortError, st as useTable, t as _default$19, tt as ExportRowsOptions, u as PresetAspect, ut as BuildQueryOptions, v as SelectionQuery, vt as createTableState, w as isSystemPresetId, wt as UsePresetsReturn, x as UrlQuerySync, xt as useTableContextOptional, y as SystemPreset, yt as provideTableContext, z as UseAppPrefsOptions } from "./as-table-root.vue-mhHmNm2I.mjs";
4
+ import { t as _default$16 } from "./as-table-actions.vue-DNNYGVQW.mjs";
5
+ import { $ as ExportProgress, A as getColumnWidth, B as UseAppPrefsReturn, C as getDefaultClientFactory, Ct as UsePresetsOptions, D as setDefaultClientFactory, Dt as UseLocalDraftOptions, E as resolveSystemPresets, Et as StorageLike, F as createDefaultControls, G as TableUrlQueryRouter, H as AS_PRESETS_APP, I as _default$20, J as useTableActions, K as UseTableUrlQueryOptions, L as _default$15, M as provideCellLocale, N as useCellLocale, O as formatCellValue, Ot as UseLocalDraftReturn, P as createDefaultCellTypes, Q as ExportCellFormatter, R as useTableComponent, S as UserConfData, St as ActivePresetView, T as resetDefaultClientFactory, Tt as usePresets, U as injectPresetsApp, V as useAppPrefs, W as TableUrlQueryRoute, X as useTableFilter, Y as useTableSearch, Z as useTableNavBridge, _ as SYSTEM_PRESET_PREFIX, _t as createStaticTableState, a as CsvOptions, at as UseTableOptions, b as SystemPresetInput, bt as useTableContext, c as ExportScalar, ct as SelectionPersistence, d as PresetCapabilities, dt as CreateStaticTableStateOptions, et as ExportResult, f as PresetData, ft as CreateTableStateOptions, g as STANDARD_PRESET_ID, gt as TableStateInternals, h as QueryOptions, ht as TableModelRefs, i as ClientFactory, it as useTableExport, j as CellLocale, k as getCellValue, kt as useLocalDraft, l as PRESET_ASPECTS, lt as useTableSelection, m as PresetSnapshotWire, mt as TableContext, n as AppConfData, nt as UseTableExportReturn, o as DisplayColumnDef, ot as clearTableCache, p as PresetSnapshot, pt as QueryFn, q as useTableUrlQuery, r as AsPresetEntryRow, rt as downloadExport, s as ExportAbortError, st as useTable, t as _default$19, tt as ExportRowsOptions, u as PresetAspect, ut as BuildQueryOptions, v as SelectionQuery, vt as createTableState, w as isSystemPresetId, wt as UsePresetsReturn, x as UrlQuerySync, xt as useTableContextOptional, y as SystemPreset, yt as provideTableContext, z as UseAppPrefsOptions } from "./as-table-root.vue-D1M2B9A_.mjs";
6
6
  import { t as _default } from "./as-cell-array.vue-D4vS7C_D.mjs";
7
7
  import { t as _default$1 } from "./as-cell-date.vue-Dyq2-vg9.mjs";
8
8
  import { t as _default$2 } from "./as-cell-json.vue-C0_LDvQw.mjs";
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { I as queryTargetGate, O as extractIdentifier, V as ROW_ACTIONS_TYPE, a as useTableContext, b as QUERY_TARGET_UNSUPPORTED_REASON, k as identifierFieldsOf, n as createTableState, o as useTableContextOptional, r as provideTableContext, t as createStaticTableState, v as resolveRowActions, x as actionIdentifiers } from "./use-table-state-DzvCmxEx.mjs";
2
2
  import { t as getCellValue } from "./get-cell-value-Cb3X8nUn.mjs";
3
3
  import { n as useTableSelection } from "./use-table-selection-CdaOPo1d.mjs";
4
- import { a as useLocalDraft, i as usePresets, o as AS_PRESETS_APP, r as useTable, s as injectPresetsApp, t as clearTableCache } from "./use-table-CTCYFwrE.mjs";
4
+ import { a as useLocalDraft, i as usePresets, o as AS_PRESETS_APP, r as useTable, s as injectPresetsApp, t as clearTableCache } from "./use-table-D86LSCnG.mjs";
5
5
  import { n as useCellLocale, t as provideCellLocale } from "./use-cell-locale-Bye0ANIP.mjs";
6
6
  import { t as useTableNavBridge } from "./use-table-nav-bridge-Ch61msQs.mjs";
7
7
  import { t as useTableComponent } from "./use-table-component-B9QRSvoR.mjs";
@@ -14,17 +14,17 @@ import { t as as_cell_union_default } from "./as-cell-union-C9Bbnkrg.mjs";
14
14
  import { t as as_column_menu_default } from "./as-column-menu-CBtUfYEE.mjs";
15
15
  import { t as as_config_dialog_default } from "./as-config-dialog-DW4WfYEi.mjs";
16
16
  import { t as as_confirm_dialog_default } from "./as-confirm-dialog-rWRl5z4R.mjs";
17
- import { t as as_filter_field_default } from "./as-filter-field-DEBQQy_6.mjs";
17
+ import { t as as_filter_field_default } from "./as-filter-field-BxZwGNoI.mjs";
18
18
  import { t as as_filter_input_default } from "./as-filter-input-DeI85XVZ.mjs";
19
- import { t as as_filter_dialog_default } from "./as-filter-dialog-8xvnKXTd.mjs";
19
+ import { t as as_filter_dialog_default } from "./as-filter-dialog-DA7vdmUO.mjs";
20
20
  import { t as as_table_header_cell_default } from "./as-table-header-cell-Bg5wAPHv.mjs";
21
21
  import { t as as_window_table_default } from "./as-window-table-Cf523h8Q.mjs";
22
22
  import { t as as_table_cell_value_default } from "./as-table-cell-value-BYJd-QRA.mjs";
23
23
  import { t as as_residual_filter_default } from "./as-residual-filter-BoeOL9AJ.mjs";
24
- import { t as as_filters_default } from "./as-filters-CT1ks7gu.mjs";
24
+ import { t as as_filters_default } from "./as-filters-Cu8Hulrv.mjs";
25
25
  import { t as as_preset_dialog_default } from "./as-preset-dialog-BXL8yt8O.mjs";
26
26
  import { t as as_row_actions_default } from "./as-row-actions-QN_UFuah.mjs";
27
- import { t as as_table_root_default } from "./as-table-root-BeyqcJUq.mjs";
27
+ import { t as as_table_root_default } from "./as-table-root-_eZRGvAC.mjs";
28
28
  import { t as as_table_default } from "./as-table-DEjvo36o.mjs";
29
29
  import { t as as_table_actions_default } from "./as-table-actions-m-QLy2Ys.mjs";
30
30
  import { t as as_preset_picker_default } from "./as-preset-picker-IVVvFw6r.mjs";
@@ -1,9 +1,9 @@
1
1
  import { l as DEFAULT_AVAILABLE_ASPECTS, n as createTableState, r as provideTableContext } from "./use-table-state-DzvCmxEx.mjs";
2
2
  import { n as useTableSelection } from "./use-table-selection-CdaOPo1d.mjs";
3
3
  import { n as useCellLocale } from "./use-cell-locale-Bye0ANIP.mjs";
4
- import { createTableDef, getMetaEntry, resetMetaCache } from "@atscript/ui";
5
- import { computed, getCurrentInstance, inject, isRef, ref, shallowRef, toValue, watch } from "vue";
6
- import { PresetsClient, STANDARD_PRESET_ID, debounce, deserializeDraft, isEmptyDraft, isSystemPresetId, isUnavailableError, resolveSystemPresets, serializeDraft, stableStringify } from "@atscript/ui-table";
4
+ import { getMetaEntry, getMetaTableDef, resetMetaCache } from "@atscript/ui";
5
+ import { computed, getCurrentInstance, getCurrentScope, inject, isRef, onScopeDispose, ref, shallowRef, toValue, watch } from "vue";
6
+ import { PresetsClient, STANDARD_PRESET_ID, cachedPresetCapabilities, cachedPresetRows, debounce, deserializeDraft, isEmptyDraft, isPresetsCacheActive, isSystemPresetId, isUnavailableError, loadPresetCapabilities, loadPresetRows, presetsCacheKey, publishPresetsWrite, resolveSystemPresets, serializeDraft, sharedPresetsClient, stableStringify, subscribePresetsCache } from "@atscript/ui-table";
7
7
  //#region src/composables/as-presets-app.ts
8
8
  /**
9
9
  * App-wide injection key for the presets system. The host app calls
@@ -174,6 +174,14 @@ function resolveStorage(provided) {
174
174
  * Stateful: holds reactive `presets` / `userConf` / `capabilities` and
175
175
  * supports optimistic mutators that re-list after each successful write.
176
176
  *
177
+ * Once the app binds the viewer with `setMetaCacheIdentity()`, loads go
178
+ * through the browser session cache of `@atscript/ui-table`: a re-mount
179
+ * applies the cached rows synchronously (no request inside the max age,
180
+ * a background revalidation after it), capabilities load once per session,
181
+ * and a write here updates every other mounted consumer of the same
182
+ * `(url, app, tableKey)` — in this tab directly, in other tabs through a
183
+ * `BroadcastChannel`.
184
+ *
177
185
  * Active-preset selection (`activePresetId`) is **owned by the caller** —
178
186
  * the composable provides the ref but doesn't auto-resolve it on mount;
179
187
  * that's the table-state's responsibility (Slice 4) since it depends on
@@ -182,10 +190,13 @@ function resolveStorage(provided) {
182
190
  function usePresets(opts) {
183
191
  const app = injectPresetsApp(opts.app);
184
192
  if (!opts.tableKey) throw new Error("[vue-table] usePresets: `tableKey` is required");
193
+ const cached = isPresetsCacheActive();
194
+ const cacheKey = presetsCacheKey(opts.url, app, opts.tableKey);
185
195
  const client = new PresetsClient({
186
196
  url: opts.url,
187
197
  app,
188
198
  tableKey: opts.tableKey,
199
+ client: cached ? sharedPresetsClient(opts.url, opts.clientFactory) : void 0,
189
200
  clientFactory: opts.clientFactory
190
201
  });
191
202
  const systemPresetsResolved = computed(() => resolveSystemPresets(opts.systemPresets));
@@ -237,11 +248,68 @@ function usePresets(opts) {
237
248
  const me = currentUser.value;
238
249
  return me !== null && row.user === me;
239
250
  }
251
+ function applyRows(rows) {
252
+ denied.value = false;
253
+ presets.value = rows.presets;
254
+ userConf.value = rows.userConf;
255
+ }
256
+ function applyDenied() {
257
+ denied.value = true;
258
+ presets.value = [];
259
+ userConf.value = null;
260
+ capabilities.value = null;
261
+ }
262
+ function applyResult(result) {
263
+ if (result.denied) applyDenied();
264
+ else applyRows(result);
265
+ }
266
+ const listener = {
267
+ onRows: applyRows,
268
+ onCapabilities: (caps) => {
269
+ if (!denied.value) capabilities.value = caps;
270
+ },
271
+ refresh: (full) => {
272
+ revalidate();
273
+ if (full) loadCapabilities();
274
+ }
275
+ };
276
+ if (cached && getCurrentScope()) onScopeDispose(subscribePresetsCache(cacheKey, listener));
277
+ function fetchRows(force) {
278
+ const fetch = () => client.list({ capabilities: false });
279
+ return cached ? loadPresetRows(cacheKey, fetch, {
280
+ force,
281
+ origin: listener
282
+ }) : fetch();
283
+ }
284
+ /**
285
+ * Capabilities load beside the rows and never block the first query —
286
+ * only the rows (default preset) and the table definition do. They only
287
+ * gate save / publish / limit UI.
288
+ */
289
+ async function loadCapabilities() {
290
+ const hit = cached ? cachedPresetCapabilities(cacheKey) : void 0;
291
+ if (hit) {
292
+ if (!denied.value) capabilities.value = hit;
293
+ return;
294
+ }
295
+ const fetch = () => client.loadCapabilities();
296
+ try {
297
+ const caps = await (cached ? loadPresetCapabilities(cacheKey, fetch, listener) : fetch());
298
+ if (!denied.value) capabilities.value = caps;
299
+ } catch {
300
+ capabilities.value = null;
301
+ }
302
+ }
303
+ /** Background row refresh: no `loading`, failures keep what is shown. */
304
+ async function revalidate() {
305
+ try {
306
+ applyResult(await fetchRows(true));
307
+ } catch {}
308
+ }
240
309
  /**
241
310
  * @param opts.capabilities — set `false` for refresh-after-mutation calls
242
311
  * (fav-toggle, save, rename, delete, public-toggle, set-default) where
243
- * role-derived capabilities can't have changed. Default `true`, used
244
- * only on the initial mount load.
312
+ * role-derived capabilities can't have changed. Default `true`.
245
313
  */
246
314
  let batchDepth = 0;
247
315
  let reloadPending = false;
@@ -250,7 +318,12 @@ function usePresets(opts) {
250
318
  reloadPending = true;
251
319
  return;
252
320
  }
321
+ await reloadAfterWrite();
322
+ }
323
+ /** The trailing reload of a write: refreshes the shared entry (other mounted tables follow) and tells other tabs. */
324
+ async function reloadAfterWrite() {
253
325
  await reload({ capabilities: false });
326
+ if (cached) publishPresetsWrite(cacheKey);
254
327
  }
255
328
  async function batch(fn) {
256
329
  batchDepth++;
@@ -260,32 +333,23 @@ function usePresets(opts) {
260
333
  batchDepth--;
261
334
  if (batchDepth === 0 && reloadPending) {
262
335
  reloadPending = false;
263
- await reload({ capabilities: false });
336
+ await reloadAfterWrite();
264
337
  }
265
338
  }
266
339
  }
267
- async function reload(opts = {}) {
340
+ async function reload(reloadOpts = {}) {
341
+ if (reloadOpts.capabilities !== false) loadCapabilities();
342
+ await load(true);
343
+ }
344
+ /** Foreground row load: drives `loading` and `error`. */
345
+ async function load(force) {
268
346
  loading.value = true;
269
347
  error.value = null;
270
348
  try {
271
- const result = await client.list(opts);
272
- if (result.denied) {
273
- denied.value = true;
274
- presets.value = [];
275
- userConf.value = null;
276
- capabilities.value = null;
277
- return;
278
- }
279
- denied.value = false;
280
- presets.value = result.presets;
281
- userConf.value = result.userConf;
282
- if (result.capabilities !== void 0) capabilities.value = result.capabilities;
349
+ applyResult(await fetchRows(force));
283
350
  } catch (err) {
284
351
  if (isUnavailableError(err)) {
285
- denied.value = true;
286
- presets.value = [];
287
- userConf.value = null;
288
- capabilities.value = null;
352
+ applyDenied();
289
353
  return;
290
354
  }
291
355
  error.value = err;
@@ -294,6 +358,19 @@ function usePresets(opts) {
294
358
  loading.value = false;
295
359
  }
296
360
  }
361
+ /**
362
+ * Initial load. From the session cache when it holds this scope: rows are
363
+ * applied synchronously (the default preset resolves with no network
364
+ * wait) and revalidated in the background once past the max age — a
365
+ * revalidation updates the list but never re-applies the default.
366
+ */
367
+ async function initialLoad() {
368
+ const hit = cached ? cachedPresetRows(cacheKey) : void 0;
369
+ if (hit) applyRows(hit.rows);
370
+ loadCapabilities();
371
+ if (!hit) await load(false);
372
+ else if (!hit.fresh) await revalidate();
373
+ }
297
374
  async function savePreset(snapshot) {
298
375
  const id = activePresetId.value;
299
376
  if (!id) throw new Error("[vue-table] usePresets.savePreset: no active preset");
@@ -352,7 +429,7 @@ function usePresets(opts) {
352
429
  };
353
430
  await maybeReloadAfterMutation();
354
431
  }
355
- if (opts.autoLoad !== false) reload();
432
+ if (opts.autoLoad !== false) initialLoad();
356
433
  return {
357
434
  presets,
358
435
  presetsById,
@@ -409,10 +486,9 @@ function finalizeTableState(state, client, opts) {
409
486
  * @param url — Table endpoint URL (e.g. "/db/tables/products")
410
487
  */
411
488
  function useTable(url, opts) {
412
- const entry = getMetaEntry(url, opts?.clientFactory);
413
- if (!entry.tableDef) entry.tableDef = Promise.all([entry.meta, entry.type]).then(([meta, type]) => createTableDef(meta, type));
489
+ const entry = getMetaEntry(url, opts?.clientFactory, { metaKey: opts?.metaKey });
414
490
  const { client } = entry;
415
- const defPromise = entry.tableDef;
491
+ const defPromise = getMetaTableDef(entry);
416
492
  const cellLocale = getCurrentInstance() ? useCellLocale() : void 0;
417
493
  const preset = opts?.preset;
418
494
  const presetsHandle = preset ? usePresets({
@@ -174,6 +174,14 @@ function resolveStorage(provided) {
174
174
  * Stateful: holds reactive `presets` / `userConf` / `capabilities` and
175
175
  * supports optimistic mutators that re-list after each successful write.
176
176
  *
177
+ * Once the app binds the viewer with `setMetaCacheIdentity()`, loads go
178
+ * through the browser session cache of `@atscript/ui-table`: a re-mount
179
+ * applies the cached rows synchronously (no request inside the max age,
180
+ * a background revalidation after it), capabilities load once per session,
181
+ * and a write here updates every other mounted consumer of the same
182
+ * `(url, app, tableKey)` — in this tab directly, in other tabs through a
183
+ * `BroadcastChannel`.
184
+ *
177
185
  * Active-preset selection (`activePresetId`) is **owned by the caller** —
178
186
  * the composable provides the ref but doesn't auto-resolve it on mount;
179
187
  * that's the table-state's responsibility (Slice 4) since it depends on
@@ -182,10 +190,13 @@ function resolveStorage(provided) {
182
190
  function usePresets(opts) {
183
191
  const app = injectPresetsApp(opts.app);
184
192
  if (!opts.tableKey) throw new Error("[vue-table] usePresets: `tableKey` is required");
193
+ const cached = (0, _atscript_ui_table.isPresetsCacheActive)();
194
+ const cacheKey = (0, _atscript_ui_table.presetsCacheKey)(opts.url, app, opts.tableKey);
185
195
  const client = new _atscript_ui_table.PresetsClient({
186
196
  url: opts.url,
187
197
  app,
188
198
  tableKey: opts.tableKey,
199
+ client: cached ? (0, _atscript_ui_table.sharedPresetsClient)(opts.url, opts.clientFactory) : void 0,
189
200
  clientFactory: opts.clientFactory
190
201
  });
191
202
  const systemPresetsResolved = (0, vue.computed)(() => (0, _atscript_ui_table.resolveSystemPresets)(opts.systemPresets));
@@ -237,11 +248,68 @@ function usePresets(opts) {
237
248
  const me = currentUser.value;
238
249
  return me !== null && row.user === me;
239
250
  }
251
+ function applyRows(rows) {
252
+ denied.value = false;
253
+ presets.value = rows.presets;
254
+ userConf.value = rows.userConf;
255
+ }
256
+ function applyDenied() {
257
+ denied.value = true;
258
+ presets.value = [];
259
+ userConf.value = null;
260
+ capabilities.value = null;
261
+ }
262
+ function applyResult(result) {
263
+ if (result.denied) applyDenied();
264
+ else applyRows(result);
265
+ }
266
+ const listener = {
267
+ onRows: applyRows,
268
+ onCapabilities: (caps) => {
269
+ if (!denied.value) capabilities.value = caps;
270
+ },
271
+ refresh: (full) => {
272
+ revalidate();
273
+ if (full) loadCapabilities();
274
+ }
275
+ };
276
+ if (cached && (0, vue.getCurrentScope)()) (0, vue.onScopeDispose)((0, _atscript_ui_table.subscribePresetsCache)(cacheKey, listener));
277
+ function fetchRows(force) {
278
+ const fetch = () => client.list({ capabilities: false });
279
+ return cached ? (0, _atscript_ui_table.loadPresetRows)(cacheKey, fetch, {
280
+ force,
281
+ origin: listener
282
+ }) : fetch();
283
+ }
284
+ /**
285
+ * Capabilities load beside the rows and never block the first query —
286
+ * only the rows (default preset) and the table definition do. They only
287
+ * gate save / publish / limit UI.
288
+ */
289
+ async function loadCapabilities() {
290
+ const hit = cached ? (0, _atscript_ui_table.cachedPresetCapabilities)(cacheKey) : void 0;
291
+ if (hit) {
292
+ if (!denied.value) capabilities.value = hit;
293
+ return;
294
+ }
295
+ const fetch = () => client.loadCapabilities();
296
+ try {
297
+ const caps = await (cached ? (0, _atscript_ui_table.loadPresetCapabilities)(cacheKey, fetch, listener) : fetch());
298
+ if (!denied.value) capabilities.value = caps;
299
+ } catch {
300
+ capabilities.value = null;
301
+ }
302
+ }
303
+ /** Background row refresh: no `loading`, failures keep what is shown. */
304
+ async function revalidate() {
305
+ try {
306
+ applyResult(await fetchRows(true));
307
+ } catch {}
308
+ }
240
309
  /**
241
310
  * @param opts.capabilities — set `false` for refresh-after-mutation calls
242
311
  * (fav-toggle, save, rename, delete, public-toggle, set-default) where
243
- * role-derived capabilities can't have changed. Default `true`, used
244
- * only on the initial mount load.
312
+ * role-derived capabilities can't have changed. Default `true`.
245
313
  */
246
314
  let batchDepth = 0;
247
315
  let reloadPending = false;
@@ -250,7 +318,12 @@ function usePresets(opts) {
250
318
  reloadPending = true;
251
319
  return;
252
320
  }
321
+ await reloadAfterWrite();
322
+ }
323
+ /** The trailing reload of a write: refreshes the shared entry (other mounted tables follow) and tells other tabs. */
324
+ async function reloadAfterWrite() {
253
325
  await reload({ capabilities: false });
326
+ if (cached) (0, _atscript_ui_table.publishPresetsWrite)(cacheKey);
254
327
  }
255
328
  async function batch(fn) {
256
329
  batchDepth++;
@@ -260,32 +333,23 @@ function usePresets(opts) {
260
333
  batchDepth--;
261
334
  if (batchDepth === 0 && reloadPending) {
262
335
  reloadPending = false;
263
- await reload({ capabilities: false });
336
+ await reloadAfterWrite();
264
337
  }
265
338
  }
266
339
  }
267
- async function reload(opts = {}) {
340
+ async function reload(reloadOpts = {}) {
341
+ if (reloadOpts.capabilities !== false) loadCapabilities();
342
+ await load(true);
343
+ }
344
+ /** Foreground row load: drives `loading` and `error`. */
345
+ async function load(force) {
268
346
  loading.value = true;
269
347
  error.value = null;
270
348
  try {
271
- const result = await client.list(opts);
272
- if (result.denied) {
273
- denied.value = true;
274
- presets.value = [];
275
- userConf.value = null;
276
- capabilities.value = null;
277
- return;
278
- }
279
- denied.value = false;
280
- presets.value = result.presets;
281
- userConf.value = result.userConf;
282
- if (result.capabilities !== void 0) capabilities.value = result.capabilities;
349
+ applyResult(await fetchRows(force));
283
350
  } catch (err) {
284
351
  if ((0, _atscript_ui_table.isUnavailableError)(err)) {
285
- denied.value = true;
286
- presets.value = [];
287
- userConf.value = null;
288
- capabilities.value = null;
352
+ applyDenied();
289
353
  return;
290
354
  }
291
355
  error.value = err;
@@ -294,6 +358,19 @@ function usePresets(opts) {
294
358
  loading.value = false;
295
359
  }
296
360
  }
361
+ /**
362
+ * Initial load. From the session cache when it holds this scope: rows are
363
+ * applied synchronously (the default preset resolves with no network
364
+ * wait) and revalidated in the background once past the max age — a
365
+ * revalidation updates the list but never re-applies the default.
366
+ */
367
+ async function initialLoad() {
368
+ const hit = cached ? (0, _atscript_ui_table.cachedPresetRows)(cacheKey) : void 0;
369
+ if (hit) applyRows(hit.rows);
370
+ loadCapabilities();
371
+ if (!hit) await load(false);
372
+ else if (!hit.fresh) await revalidate();
373
+ }
297
374
  async function savePreset(snapshot) {
298
375
  const id = activePresetId.value;
299
376
  if (!id) throw new Error("[vue-table] usePresets.savePreset: no active preset");
@@ -352,7 +429,7 @@ function usePresets(opts) {
352
429
  };
353
430
  await maybeReloadAfterMutation();
354
431
  }
355
- if (opts.autoLoad !== false) reload();
432
+ if (opts.autoLoad !== false) initialLoad();
356
433
  return {
357
434
  presets,
358
435
  presetsById,
@@ -409,10 +486,9 @@ function finalizeTableState(state, client, opts) {
409
486
  * @param url — Table endpoint URL (e.g. "/db/tables/products")
410
487
  */
411
488
  function useTable(url, opts) {
412
- const entry = (0, _atscript_ui.getMetaEntry)(url, opts?.clientFactory);
413
- if (!entry.tableDef) entry.tableDef = Promise.all([entry.meta, entry.type]).then(([meta, type]) => (0, _atscript_ui.createTableDef)(meta, type));
489
+ const entry = (0, _atscript_ui.getMetaEntry)(url, opts?.clientFactory, { metaKey: opts?.metaKey });
414
490
  const { client } = entry;
415
- const defPromise = entry.tableDef;
491
+ const defPromise = (0, _atscript_ui.getMetaTableDef)(entry);
416
492
  const cellLocale = (0, vue.getCurrentInstance)() ? require_use_cell_locale.useCellLocale() : void 0;
417
493
  const preset = opts?.preset;
418
494
  const presetsHandle = preset ? usePresets({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/vue-table",
3
- "version": "0.1.152",
3
+ "version": "0.1.153",
4
4
  "description": "Type-driven table components for Atscript with Vue 3",
5
5
  "keywords": [
6
6
  "atscript",
@@ -167,17 +167,17 @@
167
167
  "access": "public"
168
168
  },
169
169
  "dependencies": {
170
- "@atscript/ui": "^0.1.152",
171
- "@atscript/vue-form": "^0.1.152",
172
- "@atscript/ui-table": "^0.1.152"
170
+ "@atscript/ui": "^0.1.153",
171
+ "@atscript/ui-table": "^0.1.153",
172
+ "@atscript/vue-form": "^0.1.153"
173
173
  },
174
174
  "devDependencies": {
175
- "@atscript/core": "^0.1.102",
176
- "@atscript/db-client": "^0.1.151",
177
- "@atscript/typescript": "^0.1.102",
175
+ "@atscript/core": "^0.1.103",
176
+ "@atscript/db-client": "^0.1.153",
177
+ "@atscript/typescript": "^0.1.103",
178
178
  "@tanstack/vue-virtual": "^3.13.26",
179
- "@uniqu/core": "^0.1.14",
180
- "@uniqu/url": "^0.1.14",
179
+ "@uniqu/core": "^0.1.15",
180
+ "@uniqu/url": "^0.1.15",
181
181
  "@vitejs/plugin-vue": "^6",
182
182
  "@vue/test-utils": "^2",
183
183
  "@vueuse/core": "^14.3.0",
@@ -190,9 +190,9 @@
190
190
  "vunor": "^0.3.2"
191
191
  },
192
192
  "peerDependencies": {
193
- "@atscript/db-client": "^0.1.151",
193
+ "@atscript/db-client": "^0.1.153",
194
194
  "@tanstack/vue-virtual": "^3.13.26",
195
- "@uniqu/url": "^0.1.14",
195
+ "@uniqu/url": "^0.1.15",
196
196
  "@vueuse/core": "^14.3.0",
197
197
  "reka-ui": "^2.9.8",
198
198
  "vue": "^3"