@affino/datagrid-vue-app 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -780,6 +780,7 @@ Object form:
780
780
  ## Custom Cell Renderers
781
781
 
782
782
  Columns can provide a `cellRenderer` callback that returns Vue content for the display layer.
783
+ If a custom cell also needs keyboard-accessible interaction without breaking the grid-owned focus model, declare `cellInteraction` on the column and use `context.interactive` inside the renderer.
783
784
 
784
785
  ```vue
785
786
  <script setup lang="ts">
@@ -791,11 +792,12 @@ interface Row {
791
792
  employee: string
792
793
  status: string
793
794
  approval: string
795
+ approved: boolean
794
796
  }
795
797
 
796
798
  const rows: Row[] = [
797
- { id: "w1", employee: "Maya Patel", status: "Submitted", approval: "Waiting" },
798
- { id: "w2", employee: "Liam Chen", status: "Approved", approval: "Approved" },
799
+ { id: "w1", employee: "Maya Patel", status: "Submitted", approval: "Waiting", approved: false },
800
+ { id: "w2", employee: "Liam Chen", status: "Approved", approval: "Approved", approved: true },
799
801
  ]
800
802
 
801
803
  const columns: DataGridAppColumnInput<Row>[] = [
@@ -803,6 +805,16 @@ const columns: DataGridAppColumnInput<Row>[] = [
803
805
  {
804
806
  key: "status",
805
807
  label: "Status",
808
+ cellInteraction: {
809
+ click: true,
810
+ keyboard: ["enter", "space"],
811
+ role: "button",
812
+ label: ({ row }) => row?.approved ? "Reopen approval" : "Approve row",
813
+ pressed: ({ row }) => row?.approved === true,
814
+ onInvoke: ({ rowId, row }) => {
815
+ console.log("toggle approval", rowId, row?.status)
816
+ },
817
+ },
806
818
  cellRenderer: ({ displayValue, row }) => h("span", {
807
819
  class: [
808
820
  "status-pill",
@@ -810,7 +822,20 @@ const columns: DataGridAppColumnInput<Row>[] = [
810
822
  ],
811
823
  }, displayValue),
812
824
  },
813
- { key: "approval", label: "Approval" },
825
+ {
826
+ key: "approval",
827
+ label: "Approval",
828
+ cellRenderer: ({ displayValue, interactive }) => h("button", {
829
+ type: "button",
830
+ class: "approval-action",
831
+ disabled: interactive?.enabled === false,
832
+ "aria-pressed": interactive?.ariaPressed,
833
+ onClick: event => {
834
+ event.stopPropagation()
835
+ interactive?.activate("click")
836
+ },
837
+ }, displayValue),
838
+ },
814
839
  ]
815
840
  </script>
816
841
 
@@ -827,14 +852,38 @@ const columns: DataGridAppColumnInput<Row>[] = [
827
852
  - `column` and `columnIndex`
828
853
  - `value`: raw string value used by the stage
829
854
  - `displayValue`: formatted display string after presentation rules
855
+ - `interactive`: resolved cell interaction contract when the column declares `cellInteraction`; otherwise `null`
856
+
857
+ `interactive` exposes:
858
+
859
+ - `enabled`: `false` only when the interaction is currently disabled
860
+ - `click`: whether click invocation is enabled for the cell wrapper
861
+ - `keyboard`: enabled keyboard triggers (`enter`, `space`)
862
+ - `role`, `ariaLabel`, `ariaPressed`, `ariaChecked`, `ariaDisabled`
863
+ - `activate(trigger?)`: invoke the same column-level interaction path used by grid keyboard and wrapper click handling
830
864
 
831
865
  Guidelines:
832
866
 
833
- - treat `cellRenderer` as display-only; editing, selection, fill, clipboard, and menus still belong to the grid shell
867
+ - keep interaction intent on the column via `cellInteraction`; use `interactive.activate(...)` from the renderer instead of ad-hoc row-local handlers
868
+ - the grid shell still owns focus, selection, fill, clipboard, menus, and editing; `cellInteraction` only adds semantic invoke behavior inside that model
834
869
  - prefer pure render output from row data over local mutable renderer state
835
870
  - keep identifiers, derived values, and formula-result columns read-only where appropriate
836
871
  - if a renderer caches local UI state, listen for targeted app-layer cell refresh and re-sync on refresh
837
872
 
873
+ ### System checkbox interactions
874
+
875
+ The built-in row-selection checkbox column uses the same `cellInteraction` contract internally.
876
+ That means row checkboxes and the header select-all control now follow the same semantic path as authored interactive cells: click and keyboard invoke flow through one runtime contract, while the stage exposes the matching checkbox ARIA state.
877
+
878
+ Practical implications:
879
+
880
+ - `row-selection` is the reference example of a package-owned `cellInteraction` column
881
+ - row checkboxes expose checkbox semantics without introducing nested focus targets inside the grid cell
882
+ - the header checkbox stays aligned with the current visible body rows, including filtered slices
883
+ - custom boolean/action columns should prefer this pattern instead of bespoke click handlers attached inside renderers
884
+
885
+ For a live example, open the sandbox route `/vue/row-selection-grid` and switch between the visible row filters before using the header checkbox.
886
+
838
887
  ## Theme
839
888
 
840
889
  Preset string:
@@ -184,6 +184,14 @@ declare const _default: import("vue").DefineComponent<{
184
184
  type: PropType<number | undefined>;
185
185
  default: undefined;
186
186
  };
187
+ fillHandle: {
188
+ type: BooleanConstructor;
189
+ default: boolean;
190
+ };
191
+ rangeMove: {
192
+ type: BooleanConstructor;
193
+ default: boolean;
194
+ };
187
195
  rowHover: {
188
196
  type: BooleanConstructor;
189
197
  default: boolean;
@@ -373,6 +381,14 @@ declare const _default: import("vue").DefineComponent<{
373
381
  type: PropType<number | undefined>;
374
382
  default: undefined;
375
383
  };
384
+ fillHandle: {
385
+ type: BooleanConstructor;
386
+ default: boolean;
387
+ };
388
+ rangeMove: {
389
+ type: BooleanConstructor;
390
+ default: boolean;
391
+ };
376
392
  rowHover: {
377
393
  type: BooleanConstructor;
378
394
  default: boolean;
@@ -436,6 +452,8 @@ declare const _default: import("vue").DefineComponent<{
436
452
  advancedFilter: DataGridAdvancedFilterProp | undefined;
437
453
  minRows: number | undefined;
438
454
  maxRows: number | undefined;
455
+ fillHandle: boolean;
456
+ rangeMove: boolean;
439
457
  viewMode: DataGridAppViewMode | undefined;
440
458
  pageSize: number | undefined;
441
459
  currentPage: number | undefined;
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as yn, computed as u, ref as y, watch as de, nextTick as Mt, onMounted as wn, onBeforeUnmount as pn, openBlock as De, createElementBlock as We, createElementVNode as V, normalizeStyle as ne, createVNode as bn, mergeProps as Sn, unref as Mn, createCommentVNode as Tn } from "vue";
2
- import { o as Pn, q as Dn, _ as Wn } from "./DataGridTableStage.vue_vue_type_script_setup_true_lang-Bb5ixAcf.js";
2
+ import { o as Pn, q as Dn, _ as Wn } from "./DataGridTableStage.vue_vue_type_script_setup_true_lang-l1nn1PNS.js";
3
3
  import { resolveDataGridGanttAnalysis as _n, buildDataGridGanttVisibleBars as kn, buildDataGridGanttDependencyPaths as Rn, resolveDataGridGanttRangeFrame as Xe, buildDataGridTimelineRenderModels as Tt, resolveDataGridTimelineDateToPixel as Pt, resolveDataGridTimelineScrollLeftForDate as En, applyDataGridGanttDragDelta as In, hitTestDataGridGanttBar as Dt, clampDataGridTimelineScrollLeft as xn, buildDataGridGanttRowEditPatch as Cn } from "@affino/datagrid-gantt";
4
4
  const be = 0.5, Ln = 1.25;
5
5
  function Hn(s) {
@@ -1,5 +1,5 @@
1
1
  import { defineComponent as e, h as r } from "vue";
2
- import { _ as a } from "./DataGridGanttStage.vue_vue_type_script_setup_true_lang-DiaL9sUh.js";
2
+ import { _ as a } from "./DataGridGanttStage.vue_vue_type_script_setup_true_lang-BYUAjngz.js";
3
3
  import { normalizeDataGridGanttOptions as n } from "@affino/datagrid-gantt";
4
4
  const m = e({
5
5
  name: "DataGridGanttStageEntry",