@atscript/vue-table 0.1.133 → 0.1.134

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 (153) hide show
  1. package/dist/as-action-form-dialog.cjs +1 -1
  2. package/dist/as-action-form-dialog.mjs +1 -1
  3. package/dist/{as-action-menu-content-DiS37BYK.cjs → as-action-menu-content-C_D_Fepo.cjs} +1 -1
  4. package/dist/{as-action-menu-content-4D7CJNgr.mjs → as-action-menu-content-rim8hAO9.mjs} +1 -1
  5. package/dist/{as-cell-array-2qmJ1lT2.mjs → as-cell-array-BWHkJX3I.mjs} +2 -2
  6. package/dist/{as-cell-array-iPeUnk2G.cjs → as-cell-array-D-8Pqlgo.cjs} +2 -2
  7. package/dist/as-cell-array.cjs +1 -1
  8. package/dist/as-cell-array.mjs +1 -1
  9. package/dist/{as-cell-date-DyixWKuS.cjs → as-cell-date-DviMJEqs.cjs} +2 -2
  10. package/dist/{as-cell-date-BwFgi6O0.mjs → as-cell-date-mGlnDeLP.mjs} +2 -2
  11. package/dist/as-cell-date.cjs +1 -1
  12. package/dist/as-cell-date.mjs +1 -1
  13. package/dist/{as-cell-json--95Xq6yq.mjs → as-cell-json-2I081xnO.mjs} +2 -2
  14. package/dist/{as-cell-json-Bvv2P7YV.cjs → as-cell-json-CaVB6e7V.cjs} +2 -2
  15. package/dist/as-cell-json.cjs +1 -1
  16. package/dist/as-cell-json.mjs +1 -1
  17. package/dist/{as-cell-number-DuPMOesI.cjs → as-cell-number-BnYbxOiG.cjs} +2 -2
  18. package/dist/{as-cell-number-DKRaS9pM.mjs → as-cell-number-CP2AZI9g.mjs} +2 -2
  19. package/dist/as-cell-number.cjs +1 -1
  20. package/dist/as-cell-number.mjs +1 -1
  21. package/dist/{as-cell-union-DJNsEKTi.cjs → as-cell-union-BjMP91PS.cjs} +3 -3
  22. package/dist/{as-cell-union-C9FukGqF.mjs → as-cell-union-NHpDCXty.mjs} +3 -3
  23. package/dist/as-cell-union.cjs +1 -1
  24. package/dist/as-cell-union.mjs +1 -1
  25. package/dist/as-column-menu.cjs +1 -1
  26. package/dist/as-column-menu.d.cts +1 -1
  27. package/dist/as-column-menu.d.mts +1 -1
  28. package/dist/as-column-menu.mjs +1 -1
  29. package/dist/{as-column-menu.vue-Cuelpv3p.d.mts → as-column-menu.vue-De7SRhj6.d.cts} +2 -2
  30. package/dist/{as-column-menu.vue-CZ8XqHl0.d.cts → as-column-menu.vue-Dg0H1dOd.d.mts} +2 -2
  31. package/dist/{as-config-dialog-BKsm8OHR.mjs → as-config-dialog-BUBHiVlf.mjs} +28 -15
  32. package/dist/{as-config-dialog-Bt8oP8qg.cjs → as-config-dialog-DvBptYMS.cjs} +28 -15
  33. package/dist/as-config-dialog.cjs +1 -1
  34. package/dist/as-config-dialog.mjs +1 -1
  35. package/dist/{as-confirm-dialog-Cw7KErhz.cjs → as-confirm-dialog-ByMfIG0A.cjs} +1 -1
  36. package/dist/{as-confirm-dialog-BV01t7dn.mjs → as-confirm-dialog-G4ZoL_Xo.mjs} +1 -1
  37. package/dist/as-confirm-dialog.cjs +1 -1
  38. package/dist/as-confirm-dialog.mjs +1 -1
  39. package/dist/{as-filter-dialog-Ckrl79kU.mjs → as-filter-dialog-BJWH8cvc.mjs} +9 -9
  40. package/dist/{as-filter-dialog-Bxii-mYH.cjs → as-filter-dialog-C2oyT0yt.cjs} +9 -9
  41. package/dist/as-filter-dialog.cjs +1 -1
  42. package/dist/as-filter-dialog.mjs +1 -1
  43. package/dist/{as-filter-field-C-IFnj8K.mjs → as-filter-field-B2skq4K0.mjs} +3 -3
  44. package/dist/{as-filter-field-xBr6TtKo.cjs → as-filter-field-DxGfasQj.cjs} +3 -3
  45. package/dist/as-filter-field.cjs +1 -1
  46. package/dist/as-filter-field.mjs +1 -1
  47. package/dist/as-filter-input.cjs +1 -1
  48. package/dist/as-filter-input.mjs +1 -1
  49. package/dist/{as-filters-DuCk8nkk.cjs → as-filters-Bhte22La.cjs} +3 -3
  50. package/dist/{as-filters-DJEQj7_p.mjs → as-filters-DogNVlqr.mjs} +3 -3
  51. package/dist/as-filters.cjs +1 -1
  52. package/dist/as-filters.mjs +1 -1
  53. package/dist/{as-preset-dialog-CCIacZ2C.mjs → as-preset-dialog-BwHV6Y77.mjs} +3 -3
  54. package/dist/{as-preset-dialog-jZeyXJeJ.cjs → as-preset-dialog-D2a6nxEX.cjs} +3 -3
  55. package/dist/as-preset-dialog.cjs +1 -1
  56. package/dist/as-preset-dialog.mjs +1 -1
  57. package/dist/{as-preset-picker-DGSqQl9A.mjs → as-preset-picker-B0JnyAPA.mjs} +2 -2
  58. package/dist/{as-preset-picker-4xXU1KQz.cjs → as-preset-picker-DbkmapBx.cjs} +2 -2
  59. package/dist/as-preset-picker.cjs +1 -1
  60. package/dist/as-preset-picker.mjs +1 -1
  61. package/dist/{as-row-actions-pukI1JT7.mjs → as-row-actions-BkIsJVBm.mjs} +24 -11
  62. package/dist/{as-row-actions-B_OHWIAt.cjs → as-row-actions-CRg8LHGk.cjs} +24 -11
  63. package/dist/as-row-actions.cjs +1 -1
  64. package/dist/as-row-actions.d.cts +1 -1
  65. package/dist/as-row-actions.d.mts +1 -1
  66. package/dist/as-row-actions.mjs +1 -1
  67. package/dist/{as-row-actions.vue-DUSDuoR2.d.mts → as-row-actions.vue-VpJsBAJ4.d.mts} +8 -0
  68. package/dist/{as-row-actions.vue-Bvcc2tUN.d.cts → as-row-actions.vue-dn_DKcMm.d.cts} +8 -0
  69. package/dist/{as-table-D5_bQ0p5.mjs → as-table-BEvsX87E.mjs} +6 -6
  70. package/dist/{as-table-actions-DKYK_mTO.mjs → as-table-actions-B5upF1bQ.mjs} +14 -9
  71. package/dist/{as-table-actions-qb0gQz2D.cjs → as-table-actions-B6sKd4sl.cjs} +14 -9
  72. package/dist/as-table-actions.cjs +1 -1
  73. package/dist/as-table-actions.d.cts +1 -1
  74. package/dist/as-table-actions.d.mts +1 -1
  75. package/dist/as-table-actions.mjs +1 -1
  76. package/dist/{as-table-actions.vue-CckRRsL6.d.cts → as-table-actions.vue-CoxhpIlJ.d.mts} +2 -2
  77. package/dist/{as-table-actions.vue-DsqauvXR.d.mts → as-table-actions.vue-Kic8m28V.d.cts} +2 -2
  78. package/dist/{as-table-base-B0arhJI8.mjs → as-table-base-BxKBdIdS.mjs} +3 -3
  79. package/dist/{as-table-base-Dfw012G5.cjs → as-table-base-DLuhKz69.cjs} +3 -3
  80. package/dist/{as-table-cell-value-D1JkTQt0.cjs → as-table-cell-value-BAi5yadc.cjs} +2 -2
  81. package/dist/{as-table-cell-value-CPcFxSOj.mjs → as-table-cell-value-BVcfhhCb.mjs} +2 -2
  82. package/dist/as-table-cell-value.cjs +1 -1
  83. package/dist/as-table-cell-value.mjs +1 -1
  84. package/dist/{as-table-header-cell-Bb4ddLmQ.cjs → as-table-header-cell-Bv6q5iKA.cjs} +2 -2
  85. package/dist/{as-table-header-cell-q-c_QklI.mjs → as-table-header-cell-Xd3cvnII.mjs} +2 -2
  86. package/dist/as-table-header-cell.cjs +1 -1
  87. package/dist/as-table-header-cell.d.cts +1 -1
  88. package/dist/as-table-header-cell.d.mts +1 -1
  89. package/dist/as-table-header-cell.mjs +1 -1
  90. package/dist/{as-table-header-cell.vue-BjVOEFqz.d.mts → as-table-header-cell.vue-AS6u4e6v.d.cts} +2 -2
  91. package/dist/{as-table-header-cell.vue-qS1Xfc-U.d.cts → as-table-header-cell.vue-zKOmlzhT.d.mts} +2 -2
  92. package/dist/{as-table-root-Bpsrp0Vz.mjs → as-table-root-C1A6JkwL.mjs} +111 -9
  93. package/dist/{as-table-root-CUDO9ybm.cjs → as-table-root-DlYjnZax.cjs} +111 -9
  94. package/dist/as-table-root.cjs +1 -1
  95. package/dist/as-table-root.d.cts +1 -1
  96. package/dist/as-table-root.d.mts +1 -1
  97. package/dist/as-table-root.mjs +1 -1
  98. package/dist/{as-table-root.vue-szvjZsCn.d.cts → as-table-root.vue-CWk9YgpG.d.mts} +205 -32
  99. package/dist/{as-table-root.vue-BPU92_Ns.d.mts → as-table-root.vue-D94eypcL.d.cts} +206 -33
  100. package/dist/{as-table-status-BgDexT2x.cjs → as-table-status-B2HPerJT.cjs} +5 -5
  101. package/dist/{as-table-status-B9jlzPPV.mjs → as-table-status-QzlBdSiR.mjs} +5 -5
  102. package/dist/{as-table-BejpMVid.cjs → as-table-vJbZyZVx.cjs} +6 -6
  103. package/dist/as-table.cjs +1 -1
  104. package/dist/as-table.d.cts +1 -1
  105. package/dist/as-table.d.mts +1 -1
  106. package/dist/as-table.mjs +1 -1
  107. package/dist/{as-table.vue-4WhMA8AM.d.mts → as-table.vue-BB1vaNL6.d.cts} +4 -4
  108. package/dist/{as-table.vue-_urybtQj.d.cts → as-table.vue-BUDFTCpo.d.mts} +4 -4
  109. package/dist/{as-window-table-S1XWpDHQ.mjs → as-window-table-BH0tDDnr.mjs} +11 -7
  110. package/dist/{as-window-table-CXq6UuUx.cjs → as-window-table-Bl_q72WL.cjs} +11 -7
  111. package/dist/as-window-table.cjs +1 -1
  112. package/dist/as-window-table.d.cts +1 -1
  113. package/dist/as-window-table.d.mts +1 -1
  114. package/dist/as-window-table.mjs +1 -1
  115. package/dist/{as-window-table.vue-h1bdyMv7.d.cts → as-window-table.vue-Be2IA0Eb.d.cts} +3 -3
  116. package/dist/{as-window-table.vue-CWsJvOkL.d.mts → as-window-table.vue-CLqFM2ff.d.mts} +3 -3
  117. package/dist/index.cjs +193 -29
  118. package/dist/index.d.cts +9 -9
  119. package/dist/index.d.mts +9 -9
  120. package/dist/index.mjs +186 -31
  121. package/dist/{types-BZ0HssRY.d.cts → types--ex8BJIO.d.cts} +138 -2
  122. package/dist/{types-CXz-4dPz.d.mts → types-CBGaTR2Z.d.mts} +138 -2
  123. package/dist/{use-table-Bk-jSxOM.mjs → use-table-BFhbfWgY.mjs} +23 -13
  124. package/dist/{use-table-component-KuzZxAP8.mjs → use-table-component-CRmLHdqi.mjs} +1 -1
  125. package/dist/{use-table-component-DlLganVc.cjs → use-table-component-DS5NJPzs.cjs} +1 -1
  126. package/dist/{use-table-nav-bridge-CVUmTjDr.cjs → use-table-nav-bridge-DS14D_rG.cjs} +1 -1
  127. package/dist/{use-table-nav-bridge-B9SSEajW.mjs → use-table-nav-bridge-DzJN5v9a.mjs} +1 -1
  128. package/dist/{use-table-CdFFqaEx.cjs → use-table-nvuZdgUd.cjs} +28 -12
  129. package/dist/{use-table-state-DLJbW753.mjs → use-table-state-mBXx11aH.mjs} +208 -52
  130. package/dist/{use-table-state-D6dHOFrA.cjs → use-table-state-mhm-YWnu.cjs} +212 -56
  131. package/package.json +4 -4
  132. /package/dist/{as-cell-json-popover-Dkdv5Y9E.mjs → as-cell-json-popover-CH5bAcLE.mjs} +0 -0
  133. /package/dist/{as-cell-json-popover-BM2QLgfk.cjs → as-cell-json-popover-vty5vMjW.cjs} +0 -0
  134. /package/dist/{as-column-menu-kTIQfLTi.mjs → as-column-menu-BMTS3DO2.mjs} +0 -0
  135. /package/dist/{as-column-menu-fZVbJ9lU.cjs → as-column-menu-D_8NxujZ.cjs} +0 -0
  136. /package/dist/{as-filter-input-BM23TNeh.mjs → as-filter-input-C8KmOus8.mjs} +0 -0
  137. /package/dist/{as-filter-input-DJu2k9gO.cjs → as-filter-input-DUqpkTkg.cjs} +0 -0
  138. /package/dist/{error-message-CglODWl4.cjs → error-message-CfKpn_5w.cjs} +0 -0
  139. /package/dist/{error-message-hPSAu8Ug.mjs → error-message-gNEXnnbb.mjs} +0 -0
  140. /package/dist/{format-cell-D1Ziv96Q.mjs → format-cell-Bx7wNc4X.mjs} +0 -0
  141. /package/dist/{format-cell-vCNTh4WZ.cjs → format-cell-DaxV6WIJ.cjs} +0 -0
  142. /package/dist/{get-cell-value-4rHKP-TG.cjs → get-cell-value-CJT4fk4y.cjs} +0 -0
  143. /package/dist/{get-cell-value-C8LLc_Rr.mjs → get-cell-value-Cb3X8nUn.mjs} +0 -0
  144. /package/dist/{use-cell-locale-MQXoONh5.mjs → use-cell-locale-CxQOQsns.mjs} +0 -0
  145. /package/dist/{use-cell-locale-BGBRQB7s.cjs → use-cell-locale-caG2Fzpc.cjs} +0 -0
  146. /package/dist/{use-has-emit-listener-hhOH8CBI.cjs → use-has-emit-listener-BaGFZDyM.cjs} +0 -0
  147. /package/dist/{use-has-emit-listener-BTMDIv2e.mjs → use-has-emit-listener-DrBbsLHQ.mjs} +0 -0
  148. /package/dist/{use-seed-on-open-Dg9I89fU.cjs → use-seed-on-open-9TSm1Vbv.cjs} +0 -0
  149. /package/dist/{use-seed-on-open-DO3A1kIb.mjs → use-seed-on-open-DSh4XFyp.mjs} +0 -0
  150. /package/dist/{use-table-column-handlers-ehreEzcx.cjs → use-table-column-handlers-BMrP0WY2.cjs} +0 -0
  151. /package/dist/{use-table-column-handlers-CpiiIniD.mjs → use-table-column-handlers-Bx3JERqs.mjs} +0 -0
  152. /package/dist/{use-table-selection-Cmiu1h4S.cjs → use-table-selection-DtCV3rhu.cjs} +0 -0
  153. /package/dist/{use-table-selection-C84z4OZy.mjs → use-table-selection-ULbKT2xW.mjs} +0 -0
@@ -1,6 +1,7 @@
1
+ import { t as getCellValue } from "./get-cell-value-Cb3X8nUn.mjs";
1
2
  import { navigateHrefFor } from "@atscript/ui";
2
3
  import { computed, inject, nextTick, onBeforeUnmount, onScopeDispose, provide, ref, shallowRef, toValue, watch } from "vue";
3
- import { STANDARD_PRESET_ID, blockStartFor, buildTableQuery, debounce, derivePresetAspects, fromWireSnapshot, isDirtyAgainst, isFilled, isSystemPresetId, pageAlignedBlocksFor, planFetch, reconcileColumnWidthDefaults, resolveAspectGate, resolveSystemPresets, rowsToPks, sameColumnSet, sortersEqual, stateToUrlQueryString, togglePk, urlQueryStringToState, walkBackwardAbsorb, walkForwardAbsorb } from "@atscript/ui-table";
4
+ import { STANDARD_PRESET_ID, blockStartFor, buildTableQuery, cellAsString, debounce, derivePresetAspects, fromWireSnapshot, isDirtyAgainst, isFilled, isSystemPresetId, mergeDisplayColumns, mergeSorters, pageAlignedBlocksFor, planFetch, reconcileColumnWidthDefaults, resolveAspectGate, resolveSystemPresets, rowsToPks, sameColumnSet, sortRowsLocally, sortersEqual, stateToUrlQueryString, togglePk, urlQueryStringToState, walkBackwardAbsorb, walkForwardAbsorb } from "@atscript/ui-table";
4
5
  import { formatIdentifier } from "@atscript/db-client";
5
6
  //#region src/types.ts
6
7
  /** UI-side sentinel for the synthesised row-delete processor. */
@@ -43,18 +44,25 @@ function rowActionGate(row) {
43
44
  return names ? gateFor(new Set(names)) : null;
44
45
  }
45
46
  /**
46
- * Filter a `{default, others, rows}` triple through an availability `gate`.
47
- * When `gate` is `null`, returns the input `buckets` reference unchanged so
48
- * source-array references stay stable downstream (no spurious recomputes in
49
- * consumers that compare array identity). Shared by the single-row
50
- * (`applyRowGate`) and bulk (`applyRowsGate`) paths.
47
+ * Walk a `{default, others, rows}` triple once: keep the actions `gate`
48
+ * admits, then run each survivor through `map`. Both are optional — with
49
+ * neither, the input `buckets` reference comes back unchanged so source-array
50
+ * references stay stable downstream (no spurious recomputes in consumers that
51
+ * compare array identity). Shared by the single-row (`applyRowGate`), bulk
52
+ * (`applyRowsGate`) and per-screen-policy paths.
51
53
  */
52
- function applyGate(buckets, gate) {
53
- if (!gate) return buckets;
54
+ function applyGate(buckets, gate, map) {
55
+ if (!gate && !map) return buckets;
56
+ const keep = gate ?? (() => true);
57
+ const walk = (list) => {
58
+ const kept = gate ? list.filter(keep) : list;
59
+ return map ? kept.map(map) : kept;
60
+ };
61
+ const def = buckets.default;
54
62
  return {
55
- default: buckets.default && gate(buckets.default) ? buckets.default : void 0,
56
- others: buckets.others.filter(gate),
57
- rows: buckets.rows.filter(gate)
63
+ default: def && keep(def) ? map ? map(def) : def : void 0,
64
+ others: walk(buckets.others),
65
+ rows: walk(buckets.rows)
58
66
  };
59
67
  }
60
68
  /**
@@ -281,12 +289,16 @@ async function triggerAction(state, action, ctx, event) {
281
289
  if (input === null) return;
282
290
  state.actions.invoke(action, pk, {
283
291
  event,
284
- input
292
+ input,
293
+ row: ctx.row
285
294
  });
286
295
  return;
287
296
  }
288
297
  if (!await confirmAction(state, action, ctx)) return;
289
- state.actions.invoke(action, pk, { event });
298
+ state.actions.invoke(action, pk, {
299
+ event,
300
+ row: ctx.row
301
+ });
290
302
  }
291
303
  /**
292
304
  * Pick the `pk` argument to forward to `state.actions.invoke` based on the
@@ -308,6 +320,75 @@ function idsForAction(level, pk) {
308
320
  return pk === void 0 ? [] : [pk];
309
321
  }
310
322
  //#endregion
323
+ //#region src/composables/state/row-actions-config.ts
324
+ /** The app definition behind a client-only action, or `undefined` for a server action. */
325
+ function localActionOf(action) {
326
+ return action.$local;
327
+ }
328
+ /** Wrap an app-owned action in the descriptor shape the row-actions cell renders. */
329
+ function toLocalActionInfo(local) {
330
+ return {
331
+ name: local.name,
332
+ label: local.label,
333
+ level: "row",
334
+ processor: "custom",
335
+ value: "",
336
+ icon: local.icon,
337
+ intent: local.intent,
338
+ promptText: local.promptText,
339
+ $local: local
340
+ };
341
+ }
342
+ /**
343
+ * Render-time href for a row action, whichever kind it is: a client-only
344
+ * action builds its own from the row — still mapped through
345
+ * `state.resolveHref`, so router base paths apply exactly as they do for a
346
+ * server `navigate` action — and a server action goes through
347
+ * {@link actionHref}.
348
+ */
349
+ function rowActionHref(state, action, id, row) {
350
+ const local = localActionOf(action);
351
+ if (local) return local.href && row !== void 0 ? state.resolveHref(local.href(row)) : void 0;
352
+ return actionHref(state, action, id);
353
+ }
354
+ const EMPTY = Object.freeze([]);
355
+ /** The identity policy — used when no `RowActionsConfig` is wired. */
356
+ const PASS_THROUGH = {
357
+ apply: (buckets) => buckets,
358
+ extra: () => EMPTY
359
+ };
360
+ /** Compile a per-screen {@link RowActionsConfig} into a {@link RowActionsPolicy}. */
361
+ function compileRowActionsConfig(config) {
362
+ if (!config) return PASS_THROUGH;
363
+ const include = config.include ? new Set(config.include) : null;
364
+ const exclude = config.exclude ? new Set(config.exclude) : null;
365
+ const overrides = config.overrides;
366
+ const gate = (a) => (!include || include.has(a.name)) && !exclude?.has(a.name);
367
+ const decorate = overrides ? (action) => {
368
+ const patch = overrides[action.name];
369
+ if (!patch) return action;
370
+ const next = { ...action };
371
+ for (const key of [
372
+ "label",
373
+ "icon",
374
+ "intent",
375
+ "promptText"
376
+ ]) {
377
+ const value = patch[key];
378
+ if (value !== void 0) next[key] = value;
379
+ }
380
+ return next;
381
+ } : void 0;
382
+ const locals = (config.extra ?? []).filter((local) => !exclude?.has(local.name));
383
+ return {
384
+ apply: (buckets) => applyGate(buckets, gate, decorate),
385
+ extra: (row) => {
386
+ if (locals.length === 0) return EMPTY;
387
+ return (row === void 0 ? locals : locals.filter((l) => l.enabled?.(row) !== false)).map(toLocalActionInfo);
388
+ }
389
+ };
390
+ }
391
+ //#endregion
311
392
  //#region src/composables/state/create-actions.ts
312
393
  const REMOVE_NAME = REMOVE_PROCESSOR;
313
394
  const REMOVE_DEFAULTS = {
@@ -340,13 +421,16 @@ function createActions(opts) {
340
421
  let result;
341
422
  try {
342
423
  switch (action.processor) {
343
- case "custom":
424
+ case "custom": {
425
+ const local = localActionOf(action);
426
+ if (local?.onInvoke) await local.onInvoke(callOpts?.row ?? {}, Array.isArray(pk) ? pk[0] : pk);
344
427
  result = {
345
428
  ok: true,
346
429
  kind: "custom",
347
430
  dispatched: true
348
431
  };
349
432
  break;
433
+ }
350
434
  case "navigate":
351
435
  await opts.client.action(action.name, pk);
352
436
  result = {
@@ -1440,17 +1524,21 @@ const DEFAULT_BLOCK_SIZE = 100;
1440
1524
  const DEFAULT_DRAG_RELEASE_DEBOUNCE_MS = 300;
1441
1525
  const DEFAULT_ITEMS_PER_PAGE = 25;
1442
1526
  let _tblUid = 0;
1527
+ /** Shared empty sorter list — keeps `splitSorters` identity-stable. */
1528
+ const EMPTY_SORTERS = Object.freeze([]);
1443
1529
  /**
1444
- * Coerce a primitive cell value to a string for the static-mode query
1445
- * function's substring search and locale-aware sort. Objects fall back to
1446
- * `""` so `'[object Object]'` never leaks into the search index. Module
1447
- * scope so it's not recreated on every fetch.
1530
+ * Build the value reader used for in-memory sorting: a display column's
1531
+ * `sortValue(row)` wins for its own key, everything else reads the row by
1532
+ * path. Returns `getCellValue` itself when no display column defines one.
1448
1533
  */
1449
- function cellAsString(v) {
1450
- if (v == null) return "";
1451
- if (typeof v === "string") return v;
1452
- if (typeof v === "number" || typeof v === "boolean") return v.toString();
1453
- return "";
1534
+ function createSortValueReader(display) {
1535
+ const map = /* @__PURE__ */ new Map();
1536
+ for (const d of display ?? []) if (d.sortValue) map.set(d.key, d.sortValue);
1537
+ if (map.size === 0) return getCellValue;
1538
+ return (row, field) => {
1539
+ const fn = map.get(field);
1540
+ return fn ? fn(row) : getCellValue(row, field);
1541
+ };
1454
1542
  }
1455
1543
  /**
1456
1544
  * Promise-based dialog slot. A second `request()` while one is open
@@ -1526,6 +1614,13 @@ function createTableState(opts) {
1526
1614
  });
1527
1615
  const rowDelete = ref(false);
1528
1616
  const includeActions = ref(false);
1617
+ const rowActions = ref(void 0);
1618
+ /**
1619
+ * The per-screen row-action policy, compiled once per config change instead
1620
+ * of once per row per render — and read by every surface that renders row
1621
+ * actions, so the cell and the selection toolbar can't drift apart.
1622
+ */
1623
+ const rowActionsPolicy = computed(() => compileRowActionsConfig(rowActions.value));
1529
1624
  const filters = shallowRef({});
1530
1625
  const results = shallowRef([]);
1531
1626
  const resultsStart = ref(0);
@@ -1612,23 +1707,65 @@ function createTableState(opts) {
1612
1707
  let generation = 0;
1613
1708
  let queryDetected = false;
1614
1709
  let skipPaginationWatch = 0;
1615
- function buildCurrentQuery() {
1710
+ /**
1711
+ * Paths of client-owned columns — they have no server field behind them, so
1712
+ * they are stripped from `$select` and from `$sort`. Recomputed only when
1713
+ * the column set changes.
1714
+ */
1715
+ const localColumnPaths = computed(() => {
1716
+ const out = /* @__PURE__ */ new Set();
1717
+ for (const c of allColumns.value) if (c.local) out.add(c.path);
1718
+ return out;
1719
+ });
1720
+ /**
1721
+ * The active sorters split by who applies them: `server` goes into `$sort`,
1722
+ * `local` targets a client-owned column and is applied in memory. One pass,
1723
+ * one dependency — the two halves are complements.
1724
+ */
1725
+ const splitSorters = computed(() => {
1726
+ const paths = localColumnPaths.value;
1727
+ if (paths.size === 0) return {
1728
+ local: EMPTY_SORTERS,
1729
+ server: sorters.value
1730
+ };
1731
+ const local = [];
1732
+ const server = [];
1733
+ for (const s of sorters.value) (paths.has(s.field) ? local : server).push(s);
1734
+ return {
1735
+ local,
1736
+ server
1737
+ };
1738
+ });
1739
+ /** `true` while the query deliberately drops user sorters to keep search relevance. */
1740
+ function sortersIgnored() {
1741
+ return ignoreSortersWhenSearched.value && !!searchTerm.value;
1742
+ }
1743
+ /** Reads the value a sorter orders by — a display column's `sortValue` wins. */
1744
+ const sortValueOf = createSortValueReader(opts.displayColumns);
1745
+ function applyLocalSort(rows) {
1746
+ if (queryOpts?.preSorted) return rows;
1747
+ if (splitSorters.value.local.length === 0 || sortersIgnored()) return rows;
1748
+ return sortRowsLocally(rows, queryOpts?.forceSorters?.length ? mergeSorters(queryOpts.forceSorters, sorters.value) : sorters.value, sortValueOf);
1749
+ }
1750
+ function buildCurrentQuery(buildOpts) {
1616
1751
  const available = tableDef.value?.fetchableFields ?? new Set(allColumns.value.map((c) => c.path));
1617
1752
  const extra = /* @__PURE__ */ new Set();
1618
1753
  for (const c of columns.value) for (const p of c.selectWith ?? []) if (available.has(p)) extra.add(p);
1619
1754
  if (queryOpts?.alwaysSelected) {
1620
1755
  for (const p of queryOpts.alwaysSelected) if (available.has(p)) extra.add(p);
1621
1756
  }
1757
+ const localPaths = localColumnPaths.value;
1758
+ const requested = buildOpts?.columnPaths ?? columnNames.value;
1622
1759
  return buildTableQuery({
1623
- visibleColumnPaths: columnNames.value,
1760
+ visibleColumnPaths: localPaths.size ? requested.filter((p) => !localPaths.has(p)) : requested,
1624
1761
  extraSelect: extra.size ? [...extra] : void 0,
1625
- sorters: sorters.value,
1762
+ sorters: splitSorters.value.server,
1626
1763
  forceSorters: queryOpts?.forceSorters,
1627
1764
  filters: filters.value,
1628
1765
  forceFilters: queryOpts?.forceFilters,
1629
1766
  search: searchTerm.value || void 0,
1630
- ignoreSorters: ignoreSortersWhenSearched.value && !!searchTerm.value,
1631
- includeActions: includeActions.value
1767
+ ignoreSorters: sortersIgnored(),
1768
+ includeActions: buildOpts?.includeActions ?? includeActions.value
1632
1769
  });
1633
1770
  }
1634
1771
  function dispatchPages(query, page, size) {
@@ -1840,6 +1977,7 @@ function createTableState(opts) {
1840
1977
  selectableCount,
1841
1978
  selectAll,
1842
1979
  rowDelete,
1980
+ rowActions,
1843
1981
  includeActions,
1844
1982
  activeIndex,
1845
1983
  navMode,
@@ -1870,6 +2008,11 @@ function createTableState(opts) {
1870
2008
  queryNext,
1871
2009
  loadRange,
1872
2010
  invalidate,
2011
+ buildQuery: buildCurrentQuery,
2012
+ fetchPage: dispatchPages,
2013
+ localColumnPaths,
2014
+ applyLocalSort,
2015
+ rowActionsPolicy,
1873
2016
  dataAt,
1874
2017
  loadingAt,
1875
2018
  errorAt,
@@ -2028,6 +2171,11 @@ function createTableState(opts) {
2028
2171
  if (sortersEqual(prev, next)) return;
2029
2172
  if (searchTerm.value) setIgnoreSortersInternal(false);
2030
2173
  if (!queryDetected) return;
2174
+ const paths = localColumnPaths.value;
2175
+ if (paths.size > 0) {
2176
+ const keep = (s) => !paths.has(s.field);
2177
+ if (sortersEqual(prev.filter(keep), next.filter(keep))) return;
2178
+ }
2031
2179
  requestRefresh();
2032
2180
  }, { immediate: false });
2033
2181
  watch(() => searchTerm.value, (next, prev) => {
@@ -2098,10 +2246,11 @@ function createTableState(opts) {
2098
2246
  state,
2099
2247
  internals: {
2100
2248
  init(def) {
2101
- allColumns.value = def.columns;
2102
- const reconciled = reconcileColumnWidthDefaults(def.columns, columnWidths.value);
2249
+ const merged = mergeDisplayColumns(def.columns, opts.displayColumns ?? []);
2250
+ allColumns.value = merged;
2251
+ const reconciled = reconcileColumnWidthDefaults(merged, columnWidths.value);
2103
2252
  if (reconciled !== columnWidths.value) columnWidths.value = reconciled;
2104
- if (columnNames.value.length === 0) columnNames.value = def.columns.map((c) => c.path);
2253
+ if (columnNames.value.length === 0) columnNames.value = merged.map((c) => c.path);
2105
2254
  tableDef.value = def;
2106
2255
  },
2107
2256
  resetPagination
@@ -2115,6 +2264,7 @@ function createTableState(opts) {
2115
2264
  */
2116
2265
  function createStaticTableState(opts) {
2117
2266
  let _state = null;
2267
+ let fetcher = null;
2118
2268
  const queryFn = (q, page, size) => {
2119
2269
  if (!_state) return Promise.resolve({
2120
2270
  data: [],
@@ -2123,13 +2273,21 @@ function createStaticTableState(opts) {
2123
2273
  itemsPerPage: size,
2124
2274
  pages: 1
2125
2275
  });
2126
- return buildStaticQueryFn(opts, _state)(q, page, size);
2276
+ fetcher ??= buildStaticQueryFn(opts, _state);
2277
+ return fetcher(q, page, size);
2127
2278
  };
2128
2279
  const result = createTableState({
2129
2280
  client: {},
2130
2281
  selection: opts.selection,
2131
2282
  limit: opts.limit,
2132
- query: { fn: queryFn }
2283
+ displayColumns: opts.displayColumns,
2284
+ model: opts.model,
2285
+ actions: opts.actions,
2286
+ query: {
2287
+ fn: queryFn,
2288
+ queryOnMount: opts.queryOnMount,
2289
+ preSorted: true
2290
+ }
2133
2291
  });
2134
2292
  _state = result.state;
2135
2293
  result.state.loadingMetadata.value = false;
@@ -2161,26 +2319,24 @@ function createStaticTableState(opts) {
2161
2319
  }
2162
2320
  function buildStaticQueryFn(opts, state) {
2163
2321
  const searchPaths = opts.searchPaths ?? [];
2322
+ const sortValueOf = createSortValueReader(opts.displayColumns);
2323
+ let sortedFrom = null;
2324
+ let sortedBy = null;
2325
+ let sorted = [];
2326
+ function sortedRows(all) {
2327
+ const by = state.sorters.value;
2328
+ if (all !== sortedFrom || by !== sortedBy) {
2329
+ sorted = sortRowsLocally(all, by, sortValueOf);
2330
+ sortedFrom = all;
2331
+ sortedBy = by;
2332
+ }
2333
+ return sorted;
2334
+ }
2164
2335
  return (_query, page, size) => {
2165
- let filtered = opts.rows;
2336
+ const all = toValue(opts.rows);
2337
+ let filtered = opts.localSort === false ? all : sortedRows(all);
2166
2338
  const term = state.searchTerm.value.trim().toLowerCase();
2167
- if (term && searchPaths.length > 0) filtered = filtered.filter((row) => searchPaths.some((p) => cellAsString(row[p]).toLowerCase().includes(term)));
2168
- const active = state.sorters.value;
2169
- if (active.length > 0) filtered = filtered.toSorted((a, b) => {
2170
- for (const s of active) {
2171
- const dir = s.direction === "desc" ? -1 : 1;
2172
- const av = a[s.field];
2173
- const bv = b[s.field];
2174
- if (typeof av === "number" && typeof bv === "number") {
2175
- if (av < bv) return -dir;
2176
- if (av > bv) return dir;
2177
- } else {
2178
- const cmp = cellAsString(av).localeCompare(cellAsString(bv));
2179
- if (cmp !== 0) return cmp * dir;
2180
- }
2181
- }
2182
- return 0;
2183
- });
2339
+ if (term && searchPaths.length > 0) filtered = filtered.filter((row) => searchPaths.some((p) => cellAsString(getCellValue(row, p)).toLowerCase().includes(term)));
2184
2340
  const start = (page - 1) * size;
2185
2341
  return Promise.resolve({
2186
2342
  data: filtered.slice(start, start + size),
@@ -2234,4 +2390,4 @@ function useRegisterMainActionListener(state, listener, enabled) {
2234
2390
  });
2235
2391
  }
2236
2392
  //#endregion
2237
- export { isModClick as C, ROW_ACTIONS_TYPE as D, ROW_ACTIONS_PATH as E, intentToScope as S, triggerAction as T, ariaLabelFor as _, useTableContext as a, extractIdentifier as b, ASPECT_ICONS as c, readPresetLabel as d, INTERACTIVE_SELECTOR as f, applyRowsGate as g, applyRowGate as h, useRegisterMainActionListener as i, ASPECT_LABELS as l, actionHref as m, createTableState as n, useTableContextOptional as o, onSelectControlKeydown as p, provideTableContext as r, DEFAULT_AVAILABLE_ASPECTS as s, createStaticTableState as t, ownerNameOf as u, collectIdentifiers as v, isPlainLeftClick as w, intentClass as x, createNavigateGestures as y };
2393
+ export { isModClick as C, ROW_ACTIONS_TYPE as D, ROW_ACTIONS_PATH as E, intentToScope as S, triggerAction as T, ariaLabelFor as _, useTableContext as a, extractIdentifier as b, ASPECT_ICONS as c, readPresetLabel as d, INTERACTIVE_SELECTOR as f, applyRowsGate as g, applyRowGate as h, useRegisterMainActionListener as i, ASPECT_LABELS as l, rowActionHref as m, createTableState as n, useTableContextOptional as o, onSelectControlKeydown as p, provideTableContext as r, DEFAULT_AVAILABLE_ASPECTS as s, createStaticTableState as t, ownerNameOf as u, collectIdentifiers as v, isPlainLeftClick as w, intentClass as x, createNavigateGestures as y };