@atscript/vue-table 0.1.133 → 0.1.135

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-D8VzLK9e.cjs} +1 -1
  4. package/dist/{as-action-menu-content-4D7CJNgr.mjs → as-action-menu-content-qATZy3cu.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-BaIGUOhP.d.mts} +1 -1
  30. package/dist/{as-column-menu.vue-CZ8XqHl0.d.cts → as-column-menu.vue-CDlI4-Cz.d.cts} +1 -1
  31. package/dist/{as-config-dialog-BKsm8OHR.mjs → as-config-dialog-BMQxSqzl.mjs} +31 -15
  32. package/dist/{as-config-dialog-Bt8oP8qg.cjs → as-config-dialog-CP362FP3.cjs} +31 -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-D41XaN_P.cjs} +1 -1
  36. package/dist/{as-confirm-dialog-BV01t7dn.mjs → as-confirm-dialog-Dp_njNXz.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-Bxii-mYH.cjs → as-filter-dialog-BCUqpKPd.cjs} +9 -9
  40. package/dist/{as-filter-dialog-Ckrl79kU.mjs → as-filter-dialog-kAXGDwsk.mjs} +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-xBr6TtKo.cjs → as-filter-field-D3jSbSwB.cjs} +3 -3
  44. package/dist/{as-filter-field-C-IFnj8K.mjs → as-filter-field-WnV2axh8.mjs} +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-DJEQj7_p.mjs → as-filters-Bc44srvA.mjs} +3 -3
  50. package/dist/{as-filters-DuCk8nkk.cjs → as-filters-Dp93OWRS.cjs} +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-Bx4nRuyk.mjs} +3 -3
  54. package/dist/{as-preset-dialog-jZeyXJeJ.cjs → as-preset-dialog-pusPD935.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-BRQdflJz.mjs} +54 -50
  58. package/dist/{as-preset-picker-4xXU1KQz.cjs → as-preset-picker-nAx3MYl7.cjs} +54 -50
  59. package/dist/as-preset-picker.cjs +1 -1
  60. package/dist/as-preset-picker.mjs +1 -1
  61. package/dist/{as-row-actions-B_OHWIAt.cjs → as-row-actions-PD-sFmDs.cjs} +24 -11
  62. package/dist/{as-row-actions-pukI1JT7.mjs → as-row-actions-gxmuZkYI.mjs} +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-AXXt5kQS.d.mts} +8 -0
  68. package/dist/{as-row-actions.vue-Bvcc2tUN.d.cts → as-row-actions.vue-D0MXQoeg.d.cts} +8 -0
  69. package/dist/{as-table-D5_bQ0p5.mjs → as-table-BIV1W3O9.mjs} +6 -6
  70. package/dist/{as-table-actions-DKYK_mTO.mjs → as-table-actions-DQ5Nn8Jc.mjs} +14 -9
  71. package/dist/{as-table-actions-qb0gQz2D.cjs → as-table-actions-D_PUqMYy.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-iKw4tsJh.d.cts} +2 -2
  77. package/dist/{as-table-actions.vue-DsqauvXR.d.mts → as-table-actions.vue-kndyFTyi.d.mts} +2 -2
  78. package/dist/{as-table-base-Dfw012G5.cjs → as-table-base-M6_12pPq.cjs} +3 -3
  79. package/dist/{as-table-base-B0arhJI8.mjs → as-table-base-kHOKCI7T.mjs} +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-q-c_QklI.mjs → as-table-header-cell-CZyy4q1s.mjs} +2 -2
  85. package/dist/{as-table-header-cell-Bb4ddLmQ.cjs → as-table-header-cell-Ct_GPLVu.cjs} +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-BNsOEsof.d.mts} +1 -1
  91. package/dist/{as-table-header-cell.vue-qS1Xfc-U.d.cts → as-table-header-cell.vue-DqjorECQ.d.cts} +1 -1
  92. package/dist/{as-table-root-Bpsrp0Vz.mjs → as-table-root-DGYw0kPC.mjs} +111 -9
  93. package/dist/{as-table-root-CUDO9ybm.cjs → as-table-root-EyN1JHuS.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-D0XFmTEL.d.mts} +201 -28
  99. package/dist/{as-table-root.vue-BPU92_Ns.d.mts → as-table-root.vue-Do0j4ibu.d.cts} +202 -29
  100. package/dist/{as-table-status-B9jlzPPV.mjs → as-table-status-CYzRbU71.mjs} +5 -5
  101. package/dist/{as-table-status-BgDexT2x.cjs → as-table-status-DMFZuZfJ.cjs} +5 -5
  102. package/dist/{as-table-BejpMVid.cjs → as-table-ucLFACn0.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-Dl0nGtMF.d.mts} +5 -5
  108. package/dist/{as-table.vue-_urybtQj.d.cts → as-table.vue-QQ1aXpJC.d.cts} +5 -5
  109. package/dist/{as-window-table-S1XWpDHQ.mjs → as-window-table-B9Y4Xgwm.mjs} +11 -7
  110. package/dist/{as-window-table-CXq6UuUx.cjs → as-window-table-Bxq7cYW5.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-CdfbFgGs.d.mts} +4 -4
  116. package/dist/{as-window-table.vue-CWsJvOkL.d.mts → as-window-table.vue-avZGJlCe.d.cts} +4 -4
  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-CyAmAg10.d.cts} +147 -2
  122. package/dist/{types-CXz-4dPz.d.mts → types-yS6-QFfT.d.mts} +147 -2
  123. package/dist/{use-table-Bk-jSxOM.mjs → use-table-BVptAnaS.mjs} +23 -13
  124. package/dist/{use-table-CdFFqaEx.cjs → use-table-Bm2a0g9D.cjs} +28 -12
  125. package/dist/{use-table-component-DlLganVc.cjs → use-table-component-Bpy5mg_P.cjs} +1 -1
  126. package/dist/{use-table-component-KuzZxAP8.mjs → use-table-component-DYzKgCC4.mjs} +1 -1
  127. package/dist/{use-table-nav-bridge-B9SSEajW.mjs → use-table-nav-bridge-LCL6vq9F.mjs} +1 -1
  128. package/dist/{use-table-nav-bridge-CVUmTjDr.cjs → use-table-nav-bridge-qyvyRm6S.cjs} +1 -1
  129. package/dist/{use-table-state-DLJbW753.mjs → use-table-state-CwfgWmuk.mjs} +222 -52
  130. package/dist/{use-table-state-D6dHOFrA.cjs → use-table-state-jljSQQ8m.cjs} +226 -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,8 +1,54 @@
1
1
  import { Component, ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
2
- import { ClientError, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
2
+ import { ClientError, PageResult, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
3
+ import { Uniquery } from "@uniqu/core";
3
4
  import { ColumnDef, PaginationControl, SortControl, TableDef } from "@atscript/ui";
4
5
  import { AsPresetEntryRow, AspectMask, ColumnWidthsMap, ConfigTab, FieldFilters, PresetAspect, PresetCapabilities, PresetSnapshot, SelectionMode, SystemPreset, SystemPresetInput, TableStateMethods } from "@atscript/ui-table";
5
6
 
7
+ //#region src/composables/state/intent-scope.d.ts
8
+ interface ActionBuckets {
9
+ default: TVueTableActionInfo | undefined;
10
+ others: TVueTableActionInfo[];
11
+ rows: TVueTableActionInfo[];
12
+ }
13
+ /**
14
+ * Build the identifier object to forward to `client.action` / `client.remove`.
15
+ *
16
+ * Per `@atscript/db-client` invariant #11, identifier bodies are object-only
17
+ * — never bare scalars, even for single-field PK tables. This helper accepts:
18
+ * - a row-shaped object (default `rowValueFn`) → picks `preferredId` fields;
19
+ * - a scalar value when `preferredId` has exactly one field (consumers that
20
+ * override `rowValueFn` to return the PK scalar) → wraps it.
21
+ *
22
+ * Returns `undefined` when no `preferredId` is declared, the source is
23
+ * `null`/`undefined`, or a scalar can't be paired with a single-field
24
+ * identifier.
25
+ */
26
+ declare function extractIdentifier(source: unknown, preferredId: readonly string[]): Record<string, unknown> | undefined;
27
+ //#endregion
28
+ //#region src/composables/state/row-actions-config.d.ts
29
+ /**
30
+ * A {@link RowActionsConfig} compiled into the two passes a surface runs per
31
+ * row. Built once per config change (not once per row per render), so the
32
+ * `include` / `exclude` sets and the override lookups exist once.
33
+ */
34
+ interface RowActionsPolicy {
35
+ /**
36
+ * Narrow + relabel already backend-gated buckets. Callers run
37
+ * `applyRowGate` FIRST — that order is the whole safety story: `include`
38
+ * can only narrow what the server allowed for the row, and `overrides`
39
+ * (presentation only) cannot resurrect an action the server gated away.
40
+ * Returns the input reference when the policy touches nothing.
41
+ */
42
+ apply: (buckets: ActionBuckets) => ActionBuckets;
43
+ /**
44
+ * The app-owned actions for `row`. `include` lists SERVER action names —
45
+ * being listed in `extra` IS an app action's opt-in — so only `exclude` and
46
+ * the action's own `enabled(row)` apply here. Pass no row to skip the
47
+ * per-row gate (a surface with no row in hand).
48
+ */
49
+ extra: (row?: Record<string, unknown>) => TVueTableActionInfo[];
50
+ }
51
+ //#endregion
6
52
  //#region src/types.d.ts
7
53
  /** UI-side sentinel for the synthesised row-delete processor. */
8
54
  declare const REMOVE_PROCESSOR = "__remove";
@@ -28,6 +74,52 @@ interface InvokeOpts {
28
74
  * actions without a form.
29
75
  */
30
76
  input?: unknown;
77
+ /**
78
+ * The row the action was triggered from. Only consumed by client-only row
79
+ * actions (`RowActionsConfig.extra`), whose `onInvoke(row, pk)` receives it.
80
+ * Since 0.1.134.
81
+ */
82
+ row?: Record<string, unknown>;
83
+ }
84
+ /**
85
+ * A row action the APP owns — it has no server counterpart, so the backend
86
+ * never gates it. Either `href` (rendered as a real anchor, mapped through
87
+ * `state.resolveHref`) or `onInvoke` (runs locally, then settles as an
88
+ * `@action` emit with `kind: 'custom'`). Since 0.1.134.
89
+ */
90
+ interface LocalRowAction {
91
+ /** Unique among the row actions; also the `@action` emit's `action.name`. */
92
+ name: string;
93
+ label: string;
94
+ icon?: string;
95
+ intent?: TDbActionInfo["intent"];
96
+ /** Confirmation copy — same `$1` / `$N` substitution as a server action. */
97
+ promptText?: string | [string, string];
98
+ /** Link target for the row. Rendered as an anchor, mapped through `state.resolveHref`. */
99
+ href?: (row: Record<string, unknown>) => string;
100
+ /** Local handler. Awaited; a rejection settles the action as an error result. */
101
+ onInvoke?: (row: Record<string, unknown>, pk?: Record<string, unknown>) => void | Promise<void>;
102
+ /** Per-row gate. Returning `false` hides the action for that row. */
103
+ enabled?: (row: Record<string, unknown>) => boolean;
104
+ }
105
+ /**
106
+ * Per-screen presentation policy for the row-actions cell. Narrows and
107
+ * relabels what the server declared, and appends app-owned actions.
108
+ *
109
+ * Backend eligibility stays authoritative: `include` / `exclude` can only
110
+ * narrow the set a row's `$actions` already allows, and `overrides` only
111
+ * change how an action looks — neither can surface an action the server
112
+ * gated away. Since 0.1.134.
113
+ */
114
+ interface RowActionsConfig {
115
+ /** Allowlist of server action names. Omitted = every eligible action. */
116
+ include?: string[];
117
+ /** Denylist of server action names, applied after `include`. */
118
+ exclude?: string[];
119
+ /** Presentation overrides keyed by server action name. */
120
+ overrides?: Record<string, Partial<Pick<TVueTableActionInfo, "label" | "icon" | "intent" | "promptText">>>;
121
+ /** App-owned actions appended after the server ones. */
122
+ extra?: LocalRowAction[];
31
123
  }
32
124
  /** Discriminated result returned by `state.actions.invoke`. Never throws. */
33
125
  type ActionResult = {
@@ -406,6 +498,13 @@ interface ReactiveTableState extends TableStateMethods {
406
498
  * remounting.
407
499
  */
408
500
  rowDelete: Ref<boolean | RowDeleteOpt>;
501
+ /**
502
+ * Per-screen row-action policy — writable ref owned by `<AsTableRoot>`,
503
+ * like {@link rowDelete}. `<AsRowActions>` reads it from the context, so a
504
+ * standalone `<AsRowActions>` inside the table honours it too (an explicit
505
+ * `:actions` prop on that component wins). Since 0.1.134.
506
+ */
507
+ rowActions: Ref<RowActionsConfig | undefined>;
409
508
  /**
410
509
  * `?$actions=true` opt-in — writable ref owned by the renderer.
411
510
  * `<AsTable>` / `<AsWindowTable>` flip this on whenever their
@@ -557,6 +656,52 @@ interface ReactiveTableState extends TableStateMethods {
557
656
  * watchers refetch in reaction to the writes.
558
657
  */
559
658
  applyUrlQuery: (urlString: string) => void;
659
+ /**
660
+ * Build the Uniquery the table's own fetch would send right now — same
661
+ * filters, sorters, search, force-filters and `$select` projection. Used by
662
+ * `useTableExport` so an export never drifts from what is on screen.
663
+ * Since 0.1.134.
664
+ */
665
+ buildQuery: (opts?: {
666
+ columnPaths?: string[];
667
+ includeActions?: boolean;
668
+ }) => Uniquery;
669
+ /**
670
+ * Run one page through the table's configured query function (or its
671
+ * client). The single fetch path — a custom `queryFn` is honoured here too.
672
+ * Since 0.1.134.
673
+ */
674
+ fetchPage: (query: Uniquery, page: number, size: number) => Promise<PageResult<Record<string, unknown>>>;
675
+ /**
676
+ * Paths of the client-owned (`local`) columns — the ones no server field
677
+ * backs, so they never enter `$select`, `$sort` or filters. Since 0.1.134.
678
+ */
679
+ localColumnPaths: ComputedRef<Set<string>>;
680
+ /**
681
+ * Re-order already-loaded rows so a sorter on a client-owned column takes
682
+ * effect: the page is sorted by the FULL sorter list, which leaves the
683
+ * server's own ordering intact and slots the local sorter in at its real
684
+ * priority. Page-local by definition — it can only order what is loaded —
685
+ * and a no-op (returns the input reference) without a local sorter, in
686
+ * window mode, or when the rows arrive pre-sorted. Since 0.1.134.
687
+ */
688
+ applyLocalSort: <T extends Record<string, unknown>>(rows: T[]) => T[];
689
+ /**
690
+ * Whether a sorter on a client-owned column currently does anything — the
691
+ * single rule behind every sort affordance, so the header and the config
692
+ * dialog cannot offer different sets. `false` only in window mode behind a
693
+ * server fetcher, where rows are cached by absolute index and dropped as
694
+ * the viewport moves; an in-memory provider orders the whole dataset before
695
+ * it slices, so the sort holds there. Since 0.1.135.
696
+ */
697
+ localSortAvailable: ComputedRef<boolean>;
698
+ /**
699
+ * The row-action policy from {@link rowActions}, compiled once per config
700
+ * change. Every surface that renders row actions reads it — the row-actions
701
+ * cell and the selection toolbar — so they cannot show different sets.
702
+ * Since 0.1.134.
703
+ */
704
+ rowActionsPolicy: ComputedRef<RowActionsPolicy>;
560
705
  /**
561
706
  * Preset feature surface. Always present; inert (`available=false`,
562
707
  * mutators throw) when `useTable({ preset })` was not configured.
@@ -672,4 +817,4 @@ interface PresetSurface {
672
817
  lastError: Ref<Error | null>;
673
818
  }
674
819
  //#endregion
675
- export { TableNavBridge as S, RowSelectableVerdict as _, EnterAction as a, TVueTableActionInfo as b, NavKeyOptions as c, ReactiveTableState as d, RowAttrsHook as f, RowSelectableHook as g, RowHookContext as h, ConfirmOptions as i, PresetConfig as l, RowDeleteOpt as m, ColumnMenuConfig as n, InvokeOpts as o, RowClassHook as p, ConfigTab as r, MainActionRequest as s, ActionResult as t, QueryErrorKind as u, TAsCellTypeComponents as v, TableActionsState as x, TAsTableControls as y };
820
+ export { TableActionsState as C, TVueTableActionInfo as S, extractIdentifier as T, RowHookContext as _, EnterAction as a, TAsCellTypeComponents as b, MainActionRequest as c, QueryErrorKind as d, ReactiveTableState as f, RowDeleteOpt as g, RowClassHook as h, ConfirmOptions as i, NavKeyOptions as l, RowAttrsHook as m, ColumnMenuConfig as n, InvokeOpts as o, RowActionsConfig as p, ConfigTab as r, LocalRowAction as s, ActionResult as t, PresetConfig as u, RowSelectableHook as v, TableNavBridge as w, TAsTableControls as x, RowSelectableVerdict as y };
@@ -1,8 +1,54 @@
1
1
  import { ColumnDef, PaginationControl, SortControl, TableDef } from "@atscript/ui";
2
2
  import { Component, ComputedRef, MaybeRefOrGetter, Ref, ShallowRef } from "vue";
3
3
  import { AsPresetEntryRow, AspectMask, ColumnWidthsMap, ConfigTab, FieldFilters, PresetAspect, PresetCapabilities, PresetSnapshot, SelectionMode, SystemPreset, SystemPresetInput, TableStateMethods } from "@atscript/ui-table";
4
- import { ClientError, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
4
+ import { ClientError, PageResult, TDbActionInfo, TDbActionProcessor, TDbDeleteResult } from "@atscript/db-client";
5
+ import { Uniquery } from "@uniqu/core";
5
6
 
7
+ //#region src/composables/state/intent-scope.d.ts
8
+ interface ActionBuckets {
9
+ default: TVueTableActionInfo | undefined;
10
+ others: TVueTableActionInfo[];
11
+ rows: TVueTableActionInfo[];
12
+ }
13
+ /**
14
+ * Build the identifier object to forward to `client.action` / `client.remove`.
15
+ *
16
+ * Per `@atscript/db-client` invariant #11, identifier bodies are object-only
17
+ * — never bare scalars, even for single-field PK tables. This helper accepts:
18
+ * - a row-shaped object (default `rowValueFn`) → picks `preferredId` fields;
19
+ * - a scalar value when `preferredId` has exactly one field (consumers that
20
+ * override `rowValueFn` to return the PK scalar) → wraps it.
21
+ *
22
+ * Returns `undefined` when no `preferredId` is declared, the source is
23
+ * `null`/`undefined`, or a scalar can't be paired with a single-field
24
+ * identifier.
25
+ */
26
+ declare function extractIdentifier(source: unknown, preferredId: readonly string[]): Record<string, unknown> | undefined;
27
+ //#endregion
28
+ //#region src/composables/state/row-actions-config.d.ts
29
+ /**
30
+ * A {@link RowActionsConfig} compiled into the two passes a surface runs per
31
+ * row. Built once per config change (not once per row per render), so the
32
+ * `include` / `exclude` sets and the override lookups exist once.
33
+ */
34
+ interface RowActionsPolicy {
35
+ /**
36
+ * Narrow + relabel already backend-gated buckets. Callers run
37
+ * `applyRowGate` FIRST — that order is the whole safety story: `include`
38
+ * can only narrow what the server allowed for the row, and `overrides`
39
+ * (presentation only) cannot resurrect an action the server gated away.
40
+ * Returns the input reference when the policy touches nothing.
41
+ */
42
+ apply: (buckets: ActionBuckets) => ActionBuckets;
43
+ /**
44
+ * The app-owned actions for `row`. `include` lists SERVER action names —
45
+ * being listed in `extra` IS an app action's opt-in — so only `exclude` and
46
+ * the action's own `enabled(row)` apply here. Pass no row to skip the
47
+ * per-row gate (a surface with no row in hand).
48
+ */
49
+ extra: (row?: Record<string, unknown>) => TVueTableActionInfo[];
50
+ }
51
+ //#endregion
6
52
  //#region src/types.d.ts
7
53
  /** UI-side sentinel for the synthesised row-delete processor. */
8
54
  declare const REMOVE_PROCESSOR = "__remove";
@@ -28,6 +74,52 @@ interface InvokeOpts {
28
74
  * actions without a form.
29
75
  */
30
76
  input?: unknown;
77
+ /**
78
+ * The row the action was triggered from. Only consumed by client-only row
79
+ * actions (`RowActionsConfig.extra`), whose `onInvoke(row, pk)` receives it.
80
+ * Since 0.1.134.
81
+ */
82
+ row?: Record<string, unknown>;
83
+ }
84
+ /**
85
+ * A row action the APP owns — it has no server counterpart, so the backend
86
+ * never gates it. Either `href` (rendered as a real anchor, mapped through
87
+ * `state.resolveHref`) or `onInvoke` (runs locally, then settles as an
88
+ * `@action` emit with `kind: 'custom'`). Since 0.1.134.
89
+ */
90
+ interface LocalRowAction {
91
+ /** Unique among the row actions; also the `@action` emit's `action.name`. */
92
+ name: string;
93
+ label: string;
94
+ icon?: string;
95
+ intent?: TDbActionInfo["intent"];
96
+ /** Confirmation copy — same `$1` / `$N` substitution as a server action. */
97
+ promptText?: string | [string, string];
98
+ /** Link target for the row. Rendered as an anchor, mapped through `state.resolveHref`. */
99
+ href?: (row: Record<string, unknown>) => string;
100
+ /** Local handler. Awaited; a rejection settles the action as an error result. */
101
+ onInvoke?: (row: Record<string, unknown>, pk?: Record<string, unknown>) => void | Promise<void>;
102
+ /** Per-row gate. Returning `false` hides the action for that row. */
103
+ enabled?: (row: Record<string, unknown>) => boolean;
104
+ }
105
+ /**
106
+ * Per-screen presentation policy for the row-actions cell. Narrows and
107
+ * relabels what the server declared, and appends app-owned actions.
108
+ *
109
+ * Backend eligibility stays authoritative: `include` / `exclude` can only
110
+ * narrow the set a row's `$actions` already allows, and `overrides` only
111
+ * change how an action looks — neither can surface an action the server
112
+ * gated away. Since 0.1.134.
113
+ */
114
+ interface RowActionsConfig {
115
+ /** Allowlist of server action names. Omitted = every eligible action. */
116
+ include?: string[];
117
+ /** Denylist of server action names, applied after `include`. */
118
+ exclude?: string[];
119
+ /** Presentation overrides keyed by server action name. */
120
+ overrides?: Record<string, Partial<Pick<TVueTableActionInfo, "label" | "icon" | "intent" | "promptText">>>;
121
+ /** App-owned actions appended after the server ones. */
122
+ extra?: LocalRowAction[];
31
123
  }
32
124
  /** Discriminated result returned by `state.actions.invoke`. Never throws. */
33
125
  type ActionResult = {
@@ -406,6 +498,13 @@ interface ReactiveTableState extends TableStateMethods {
406
498
  * remounting.
407
499
  */
408
500
  rowDelete: Ref<boolean | RowDeleteOpt>;
501
+ /**
502
+ * Per-screen row-action policy — writable ref owned by `<AsTableRoot>`,
503
+ * like {@link rowDelete}. `<AsRowActions>` reads it from the context, so a
504
+ * standalone `<AsRowActions>` inside the table honours it too (an explicit
505
+ * `:actions` prop on that component wins). Since 0.1.134.
506
+ */
507
+ rowActions: Ref<RowActionsConfig | undefined>;
409
508
  /**
410
509
  * `?$actions=true` opt-in — writable ref owned by the renderer.
411
510
  * `<AsTable>` / `<AsWindowTable>` flip this on whenever their
@@ -557,6 +656,52 @@ interface ReactiveTableState extends TableStateMethods {
557
656
  * watchers refetch in reaction to the writes.
558
657
  */
559
658
  applyUrlQuery: (urlString: string) => void;
659
+ /**
660
+ * Build the Uniquery the table's own fetch would send right now — same
661
+ * filters, sorters, search, force-filters and `$select` projection. Used by
662
+ * `useTableExport` so an export never drifts from what is on screen.
663
+ * Since 0.1.134.
664
+ */
665
+ buildQuery: (opts?: {
666
+ columnPaths?: string[];
667
+ includeActions?: boolean;
668
+ }) => Uniquery;
669
+ /**
670
+ * Run one page through the table's configured query function (or its
671
+ * client). The single fetch path — a custom `queryFn` is honoured here too.
672
+ * Since 0.1.134.
673
+ */
674
+ fetchPage: (query: Uniquery, page: number, size: number) => Promise<PageResult<Record<string, unknown>>>;
675
+ /**
676
+ * Paths of the client-owned (`local`) columns — the ones no server field
677
+ * backs, so they never enter `$select`, `$sort` or filters. Since 0.1.134.
678
+ */
679
+ localColumnPaths: ComputedRef<Set<string>>;
680
+ /**
681
+ * Re-order already-loaded rows so a sorter on a client-owned column takes
682
+ * effect: the page is sorted by the FULL sorter list, which leaves the
683
+ * server's own ordering intact and slots the local sorter in at its real
684
+ * priority. Page-local by definition — it can only order what is loaded —
685
+ * and a no-op (returns the input reference) without a local sorter, in
686
+ * window mode, or when the rows arrive pre-sorted. Since 0.1.134.
687
+ */
688
+ applyLocalSort: <T extends Record<string, unknown>>(rows: T[]) => T[];
689
+ /**
690
+ * Whether a sorter on a client-owned column currently does anything — the
691
+ * single rule behind every sort affordance, so the header and the config
692
+ * dialog cannot offer different sets. `false` only in window mode behind a
693
+ * server fetcher, where rows are cached by absolute index and dropped as
694
+ * the viewport moves; an in-memory provider orders the whole dataset before
695
+ * it slices, so the sort holds there. Since 0.1.135.
696
+ */
697
+ localSortAvailable: ComputedRef<boolean>;
698
+ /**
699
+ * The row-action policy from {@link rowActions}, compiled once per config
700
+ * change. Every surface that renders row actions reads it — the row-actions
701
+ * cell and the selection toolbar — so they cannot show different sets.
702
+ * Since 0.1.134.
703
+ */
704
+ rowActionsPolicy: ComputedRef<RowActionsPolicy>;
560
705
  /**
561
706
  * Preset feature surface. Always present; inert (`available=false`,
562
707
  * mutators throw) when `useTable({ preset })` was not configured.
@@ -672,4 +817,4 @@ interface PresetSurface {
672
817
  lastError: Ref<Error | null>;
673
818
  }
674
819
  //#endregion
675
- export { TableNavBridge as S, RowSelectableVerdict as _, EnterAction as a, TVueTableActionInfo as b, NavKeyOptions as c, ReactiveTableState as d, RowAttrsHook as f, RowSelectableHook as g, RowHookContext as h, ConfirmOptions as i, PresetConfig as l, RowDeleteOpt as m, ColumnMenuConfig as n, InvokeOpts as o, RowClassHook as p, ConfigTab as r, MainActionRequest as s, ActionResult as t, QueryErrorKind as u, TAsCellTypeComponents as v, TableActionsState as x, TAsTableControls as y };
820
+ export { TableActionsState as C, TVueTableActionInfo as S, extractIdentifier as T, RowHookContext as _, EnterAction as a, TAsCellTypeComponents as b, MainActionRequest as c, QueryErrorKind as d, ReactiveTableState as f, RowDeleteOpt as g, RowClassHook as h, ConfirmOptions as i, NavKeyOptions as l, RowAttrsHook as m, ColumnMenuConfig as n, InvokeOpts as o, RowActionsConfig as p, ConfigTab as r, LocalRowAction as s, ActionResult as t, PresetConfig as u, RowSelectableHook as v, TableNavBridge as w, TAsTableControls as x, RowSelectableVerdict as y };
@@ -1,5 +1,5 @@
1
- import { n as createTableState, r as provideTableContext, s as DEFAULT_AVAILABLE_ASPECTS } from "./use-table-state-DLJbW753.mjs";
2
- import { n as useTableSelection } from "./use-table-selection-C84z4OZy.mjs";
1
+ import { n as createTableState, r as provideTableContext, s as DEFAULT_AVAILABLE_ASPECTS } from "./use-table-state-CwfgWmuk.mjs";
2
+ import { n as useTableSelection } from "./use-table-selection-ULbKT2xW.mjs";
3
3
  import { createTableDef, getMetaEntry, resetMetaCache } from "@atscript/ui";
4
4
  import { computed, inject, isRef, ref, shallowRef, toValue, watch } from "vue";
5
5
  import { PresetsClient, STANDARD_PRESET_ID, debounce, deserializeDraft, isEmptyDraft, isSystemPresetId, isUnavailableError, resolveSystemPresets, serializeDraft, stableStringify } from "@atscript/ui-table";
@@ -368,6 +368,24 @@ function clearTableCache() {
368
368
  resetMetaCache();
369
369
  }
370
370
  /**
371
+ * The tail every table setup shares: wire selection persistence, then publish
372
+ * the context to the subtree. Split out so the local (`:rows`) path in
373
+ * `<AsTableRoot>` and `useTable` cannot drift on which keys get provided.
374
+ */
375
+ function finalizeTableState(state, client, opts) {
376
+ useTableSelection(state, { mode: opts?.selectionPersistence ?? "trim" });
377
+ if (opts?.provideContext === false) return;
378
+ provideTableContext({
379
+ state,
380
+ client,
381
+ controls: opts?.controls ?? {},
382
+ types: opts?.types,
383
+ components: opts?.components,
384
+ formTypes: opts?.formTypes,
385
+ formComponents: opts?.formComponents
386
+ });
387
+ }
388
+ /**
371
389
  * Main entry composable for table setup.
372
390
  *
373
391
  * @param url — Table endpoint URL (e.g. "/db/tables/products")
@@ -427,6 +445,7 @@ function useTable(url, opts) {
427
445
  resolveHref: opts?.resolveHref,
428
446
  onResolved: opts?.onActionResolved
429
447
  },
448
+ displayColumns: opts?.displayColumns,
430
449
  preset: {
431
450
  presetsHandle,
432
451
  draftHandle,
@@ -435,16 +454,7 @@ function useTable(url, opts) {
435
454
  persistDrafts: preset?.persistDrafts ?? false
436
455
  }
437
456
  });
438
- useTableSelection(state, { mode: opts?.selectionPersistence ?? "trim" });
439
- if (opts?.provideContext !== false) provideTableContext({
440
- state,
441
- client,
442
- controls: opts?.controls ?? {},
443
- types: opts?.types,
444
- components: opts?.components,
445
- formTypes: opts?.formTypes,
446
- formComponents: opts?.formComponents
447
- });
457
+ finalizeTableState(state, client, opts);
448
458
  defPromise.then((def) => {
449
459
  internals.init(def);
450
460
  }).catch((err) => {
@@ -455,4 +465,4 @@ function useTable(url, opts) {
455
465
  return state;
456
466
  }
457
467
  //#endregion
458
- export { AS_PRESETS_APP as a, useLocalDraft as i, useTable as n, injectPresetsApp as o, usePresets as r, clearTableCache as t };
468
+ export { useLocalDraft as a, usePresets as i, finalizeTableState as n, AS_PRESETS_APP as o, useTable as r, injectPresetsApp as s, clearTableCache as t };
@@ -1,5 +1,5 @@
1
- const require_use_table_state = require("./use-table-state-D6dHOFrA.cjs");
2
- const require_use_table_selection = require("./use-table-selection-Cmiu1h4S.cjs");
1
+ const require_use_table_state = require("./use-table-state-jljSQQ8m.cjs");
2
+ const require_use_table_selection = require("./use-table-selection-DtCV3rhu.cjs");
3
3
  let _atscript_ui = require("@atscript/ui");
4
4
  let vue = require("vue");
5
5
  let _atscript_ui_table = require("@atscript/ui-table");
@@ -368,6 +368,24 @@ function clearTableCache() {
368
368
  (0, _atscript_ui.resetMetaCache)();
369
369
  }
370
370
  /**
371
+ * The tail every table setup shares: wire selection persistence, then publish
372
+ * the context to the subtree. Split out so the local (`:rows`) path in
373
+ * `<AsTableRoot>` and `useTable` cannot drift on which keys get provided.
374
+ */
375
+ function finalizeTableState(state, client, opts) {
376
+ require_use_table_selection.useTableSelection(state, { mode: opts?.selectionPersistence ?? "trim" });
377
+ if (opts?.provideContext === false) return;
378
+ require_use_table_state.provideTableContext({
379
+ state,
380
+ client,
381
+ controls: opts?.controls ?? {},
382
+ types: opts?.types,
383
+ components: opts?.components,
384
+ formTypes: opts?.formTypes,
385
+ formComponents: opts?.formComponents
386
+ });
387
+ }
388
+ /**
371
389
  * Main entry composable for table setup.
372
390
  *
373
391
  * @param url — Table endpoint URL (e.g. "/db/tables/products")
@@ -427,6 +445,7 @@ function useTable(url, opts) {
427
445
  resolveHref: opts?.resolveHref,
428
446
  onResolved: opts?.onActionResolved
429
447
  },
448
+ displayColumns: opts?.displayColumns,
430
449
  preset: {
431
450
  presetsHandle,
432
451
  draftHandle,
@@ -435,16 +454,7 @@ function useTable(url, opts) {
435
454
  persistDrafts: preset?.persistDrafts ?? false
436
455
  }
437
456
  });
438
- require_use_table_selection.useTableSelection(state, { mode: opts?.selectionPersistence ?? "trim" });
439
- if (opts?.provideContext !== false) require_use_table_state.provideTableContext({
440
- state,
441
- client,
442
- controls: opts?.controls ?? {},
443
- types: opts?.types,
444
- components: opts?.components,
445
- formTypes: opts?.formTypes,
446
- formComponents: opts?.formComponents
447
- });
457
+ finalizeTableState(state, client, opts);
448
458
  defPromise.then((def) => {
449
459
  internals.init(def);
450
460
  }).catch((err) => {
@@ -467,6 +477,12 @@ Object.defineProperty(exports, "clearTableCache", {
467
477
  return clearTableCache;
468
478
  }
469
479
  });
480
+ Object.defineProperty(exports, "finalizeTableState", {
481
+ enumerable: true,
482
+ get: function() {
483
+ return finalizeTableState;
484
+ }
485
+ });
470
486
  Object.defineProperty(exports, "injectPresetsApp", {
471
487
  enumerable: true,
472
488
  get: function() {
@@ -1,4 +1,4 @@
1
- const require_use_table_state = require("./use-table-state-D6dHOFrA.cjs");
1
+ const require_use_table_state = require("./use-table-state-jljSQQ8m.cjs");
2
2
  //#region src/composables/use-table-component.ts
3
3
  /**
4
4
  * Resolve a single skin-slot component from the injected `controls` map,
@@ -1,4 +1,4 @@
1
- import { o as useTableContextOptional } from "./use-table-state-DLJbW753.mjs";
1
+ import { o as useTableContextOptional } from "./use-table-state-CwfgWmuk.mjs";
2
2
  //#region src/composables/use-table-component.ts
3
3
  /**
4
4
  * Resolve a single skin-slot component from the injected `controls` map,
@@ -1,4 +1,4 @@
1
- import { o as useTableContextOptional } from "./use-table-state-DLJbW753.mjs";
1
+ import { o as useTableContextOptional } from "./use-table-state-CwfgWmuk.mjs";
2
2
  //#region src/composables/use-table-nav-bridge.ts
3
3
  function isPassthroughKey(event) {
4
4
  const key = event.key;
@@ -1,4 +1,4 @@
1
- const require_use_table_state = require("./use-table-state-D6dHOFrA.cjs");
1
+ const require_use_table_state = require("./use-table-state-jljSQQ8m.cjs");
2
2
  //#region src/composables/use-table-nav-bridge.ts
3
3
  function isPassthroughKey(event) {
4
4
  const key = event.key;