@jielga/tmdatagrid 2.0.0-beta.4 → 2.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +339 -152
- package/dist/index.js +2602 -2450
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/skills/appearance/SKILL.md +1 -1
- package/skills/cell-selection/SKILL.md +1 -1
- package/skills/columns/SKILL.md +44 -2
- package/skills/data/SKILL.md +14 -10
- package/skills/editing/SKILL.md +140 -68
- package/skills/editing/references/common-mistakes.md +98 -8
- package/skills/editing/references/editing-api.md +40 -30
- package/skills/editing/references/editors-and-validation.md +65 -14
- package/skills/filtering/SKILL.md +1 -1
- package/skills/getting-started/SKILL.md +3 -3
- package/skills/grouping/SKILL.md +5 -3
- package/skills/options/SKILL.md +2 -2
- package/skills/rows/SKILL.md +7 -3
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +1 -1
- package/src/tmdatagrid/components/TMDataGrid.tsx +2 -2
- package/src/tmdatagrid/components/TMDataGridCellEditor.tsx +33 -34
- package/src/tmdatagrid/components/TMDataGridDraftActions.tsx +296 -0
- package/src/tmdatagrid/components/TMDataGridEditColumn.tsx +40 -33
- package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +7 -7
- package/src/tmdatagrid/components/TMDataGridTable.tsx +27 -5
- package/src/tmdatagrid/components/TMDataGridToolbar.module.css +4 -0
- package/src/tmdatagrid/components/TMDataGridToolbar.tsx +8 -10
- package/src/tmdatagrid/components/editors/TMDataGridNumberEditor.tsx +34 -4
- package/src/tmdatagrid/components/editors/editorShared.ts +1 -29
- package/src/tmdatagrid/core/capabilities.ts +14 -6
- package/src/tmdatagrid/core/editEngine.ts +472 -96
- package/src/tmdatagrid/core/labels.ts +3 -3
- package/src/tmdatagrid/core/summary.ts +10 -2
- package/src/tmdatagrid/index.ts +9 -7
- package/src/tmdatagrid/useTMDataGrid.tsx +107 -47
- package/src/tmdatagrid/components/TMDataGridEditActions.tsx +0 -233
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
._root_1wvkg_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_1wvkg_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_1wvkg_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_1wvkg_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_1wvkg_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_1wvkg_8{--dg-radius:var(--mantine-radius-md);--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px;--dg-row-selected-bg:var(--mantine-primary-color-light);--dg-row-highlight-bg:var(--mantine-primary-color-light-hover);--dg-row-group-bg:var(--mantine-color-body);--dg-row-striped-bg:color-mix(in srgb, var(--mantine-color-text) 3.5%, var(--mantine-color-body));--dg-row-new-bg:color-mix(in srgb, var(--mantine-color-green-6) 8%, var(--mantine-color-body));--dg-z-pinned-cell:2;--dg-z-focused-cell:3;--dg-z-pinned-row:4;--dg-z-pinned-row-pinned-cell:5;--dg-z-summary-row:4;--dg-z-summary-pinned-cell:5;--dg-z-header:6;--dg-z-header-pinned-cell:7;text-align:left;border:1px solid var(--mantine-color-default-border);border-radius:var(--dg-radius);background-color:var(--mantine-color-body);flex-direction:column;min-height:0;display:flex;overflow:hidden}._columnsPanel_1492o_1{flex-direction:column;width:280px;display:flex}._columnsPanelSearch_1492o_7{padding:var(--mantine-spacing-sm)}._columnsPanelList_1492o_11{gap:var(--mantine-spacing-sm);padding:0 var(--mantine-spacing-sm) var(--mantine-spacing-sm);flex-direction:column;display:flex}._columnsPanelFooter_1492o_18{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-sm);border-top:1px solid var(--mantine-color-default-border);display:flex}._detailsToggle_n39tz_3{width:100%;height:100%;color:inherit;justify-content:center;align-items:center;display:flex}._detailsToggle_n39tz_3:hover ._chevron_n39tz_12{color:var(--mantine-color-text)}._chevron_n39tz_12{color:var(--mantine-color-dimmed);align-items:center;transition:transform .12s;display:flex}._chevron_n39tz_12[data-expanded=true]{transform:rotate(90deg)}@media (prefers-reduced-motion:reduce){._chevron_n39tz_12{transition:none}}._tableWrapper_uqiy9_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._scrollContainer_uqiy9_10{flex:1;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_uqiy9_21{display:grid}._headerRow_uqiy9_27{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._headerRow_uqiy9_27[data-dg-header-last]:after{content:"";pointer-events:none;background:linear-gradient(to bottom, var(--dg-header-shadow-color,#00000024), transparent);opacity:0;height:6px;position:absolute;inset:100% 0 auto}@supports (animation-timeline:scroll()){._headerRow_uqiy9_27[data-dg-header-last]:after{animation:linear both _dg-header-shadow_uqiy9_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dg-header-shadow_uqiy9_1{0%{opacity:0}to{opacity:1}}._bodyRow_uqiy9_76{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_uqiy9_76[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_uqiy9_76:hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_uqiy9_76[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_uqiy9_76[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_uqiy9_76[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_uqiy9_76[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_uqiy9_76[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_uqiy9_76:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_uqiy9_143{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--row-bg);font-size:var(--dg-font-size);align-items:center;display:flex}._bodyCell_uqiy9_143[data-control-column=true]{padding:0}._grid_uqiy9_21[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_uqiy9_143[data-selected=true]{background-color:color-mix(in srgb, var(--mantine-primary-color-filled) 14%, var(--row-bg));--dg-edge-top:transparent;--dg-edge-bottom:transparent;--dg-edge-left:transparent;--dg-edge-right:transparent;box-shadow:inset 0 1px 0 0 var(--dg-edge-top), inset 0 -1px 0 0 var(--dg-edge-bottom), inset 1px 0 0 0 var(--dg-edge-left), inset -1px 0 0 0 var(--dg-edge-right)}._bodyCell_uqiy9_143[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_uqiy9_141{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_uqiy9_143[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_uqiy9_243{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorActions_uqiy9_252{flex:none;align-items:center;display:flex}._bodyCell_uqiy9_143[data-dirty],._bodyCell_uqiy9_143[data-invalid]{position:relative}._bodyCell_uqiy9_143[data-dirty]:after,._bodyCell_uqiy9_143[data-invalid]:after{content:"";border:5px solid #0000;border-top-color:var(--mantine-primary-color-filled);border-right-color:var(--mantine-primary-color-filled);position:absolute;top:0;right:0}._bodyCell_uqiy9_143[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_uqiy9_143[data-align=right]{justify-content:flex-end}._bodyCell_uqiy9_143[data-align=center]{justify-content:center}._bodyCell_uqiy9_143[data-align=left] ._cellContent_uqiy9_141{flex:auto}._detailsCell_uqiy9_303{border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--row-bg);padding:var(--dg-padding);-webkit-user-select:text;user-select:text;cursor:auto;grid-column:1/-1}._messageRow_uqiy9_15{justify-content:center;justify-self:start;align-items:center;gap:var(--mantine-spacing-xs);width:100cqi;padding:var(--mantine-spacing-xl);flex-direction:column;grid-column:1/-1;display:flex;position:sticky;left:0}._bodyRow_uqiy9_76[data-deleted=true]{opacity:.55;text-decoration:line-through}._bodyRow_uqiy9_76[data-deleted=true] ._bodyCell_uqiy9_143:not([data-control-column=true]){pointer-events:none}._entryBlock_uqiy9_353{grid-column:1/-1;grid-template-columns:subgrid;top:var(--dg-header-height,0px);z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._entryRow_uqiy9_362,._entryFlowBlock_uqiy9_371{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_uqiy9_384{grid-column:1/-1;grid-template-columns:subgrid;top:calc(var(--dg-header-height,0px) + var(--dg-entry-height,0px));z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._pinnedTopBlock_uqiy9_384>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_uqiy9_397{grid-column:1/-1;grid-template-columns:subgrid;bottom:var(--dg-summary-height,0px);z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._pinnedBottomBlock_uqiy9_397>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_uqiy9_410{padding:0 calc(var(--dg-padding) / 2);border-bottom:2px solid var(--mantine-primary-color-filled);background-color:var(--mantine-color-body);font-size:var(--dg-font-size);align-items:center;display:flex}._entryCell_uqiy9_410[data-control-column=true]{justify-content:center;padding:0}._entryRow_uqiy9_362[data-confirmed=true] ._entryCell_uqiy9_410{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--dg-row-new-bg,var(--mantine-color-body))}._entryRow_uqiy9_362[data-confirmed=true] ._entryCell_uqiy9_410[data-control-column=true]{padding:0}._rowStateIndicator_uqiy9_440{width:22px;height:22px;color:var(--mantine-color-dimmed);flex:none;justify-content:center;align-items:center;display:inline-flex}._rowStateIndicator_uqiy9_440[data-error]{color:var(--mantine-color-error)}._entryCell_uqiy9_410[data-align=right]{justify-content:flex-end}._entryCell_uqiy9_410[data-align=center]{justify-content:center}._matchHighlight_uqiy9_466{background-color:var(--dg-match-highlight-bg,var(--lightningcss-light,var(--mantine-color-yellow-2))var(--lightningcss-dark,#fab00559));color:inherit;border-radius:2px}._summaryRow_uqiy9_478{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_uqiy9_487{padding:0 var(--dg-padding);border-top:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);font-size:var(--dg-font-size);align-items:center;font-weight:600;display:flex}._summaryCell_uqiy9_487[data-control-column=true]{padding:0}._summaryCell_uqiy9_487[data-align=right]{justify-content:flex-end}._summaryCell_uqiy9_487[data-align=center]{justify-content:center}._groupToggle_1954o_4{width:100%;min-width:0;font-size:var(--dg-font-size);color:inherit;align-items:center;gap:6px;display:flex}._chevron_1954o_14{color:var(--mantine-color-dimmed);flex:none;align-items:center;transition:transform .12s;display:flex}._chevron_1954o_14[data-expanded=true]{transform:rotate(90deg)}@media (prefers-reduced-motion:reduce){._chevron_1954o_14{transition:none}}._groupLabel_1954o_34{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}._groupCount_1954o_44{color:var(--mantine-color-dimmed);font-variant-numeric:tabular-nums;flex:none}._filterPanel_izakx_4{top:calc(var(--dg-header-height) + 2px);left:var(--mantine-spacing-md);z-index:5;padding:var(--mantine-spacing-sm);border-radius:var(--mantine-radius-md);border:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);box-shadow:var(--mantine-shadow-md);position:absolute}._filterRow_izakx_16{align-items:flex-end;gap:var(--mantine-spacing-xs);display:flex}._filterPanelHeader_izakx_22{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);padding-bottom:var(--mantine-spacing-xs);display:flex}._filterPanelFooter_izakx_30{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);display:flex}._filterPills_14wl0_3{align-items:center;gap:var(--mantine-spacing-xs);flex-wrap:wrap;display:flex}._filterPills_14wl0_3 ._pill_14wl0_15{background-color:var(--lightningcss-light,var(--mantine-color-gray-1))var(--lightningcss-dark,var(--mantine-color-dark-5));color:var(--lightningcss-light,var(--mantine-color-black))var(--lightningcss-dark,var(--mantine-color-dark-0));border:1px solid var(--lightningcss-light,var(--mantine-color-gray-3))var(--lightningcss-dark,var(--mantine-color-dark-3))}._pillLabel_14wl0_27{font:inherit;color:inherit;cursor:pointer}._pillLabel_14wl0_27:hover{text-decoration:underline}._footer_te0a3_1{justify-content:flex-end;align-items:center;gap:var(--mantine-spacing-lg);padding:4px var(--mantine-spacing-sm);border-top:1px solid var(--mantine-color-default-border);flex-shrink:0;min-height:48px;display:flex}._footer_te0a3_1[data-paging-suspended=true]{opacity:.55}._stickyLeft_1vw51_16:after,._stickyRight_1vw51_17:after{content:"";pointer-events:none;width:8px;position:absolute;top:0;bottom:0}._stickyLeft_1vw51_16:after{background:linear-gradient(90deg,var(--lightningcss-light,#00000012)var(--lightningcss-dark,#00000042),var(--lightningcss-light,#00000006)var(--lightningcss-dark,#00000017) 45%,#0000);left:100%}._stickyRight_1vw51_17:after{background:linear-gradient(270deg,var(--lightningcss-light,#00000012)var(--lightningcss-dark,#00000042),var(--lightningcss-light,#00000006)var(--lightningcss-dark,#00000017) 45%,#0000);right:100%}@supports (animation-timeline:scroll()){._stickyLeft_1vw51_16:after,._stickyRight_1vw51_17:after{--dg-sticky-edge-range:20px;opacity:0;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(inline)}._stickyLeft_1vw51_16:after{animation-name:_stickyEdgeIn_1vw51_1;animation-range:0 var(--dg-sticky-edge-range)}._stickyRight_1vw51_17:after{animation-name:_stickyEdgeOut_1vw51_1;animation-range:calc(100% - var(--dg-sticky-edge-range)) 100%}}@keyframes _stickyEdgeIn_1vw51_1{0%{opacity:0}to{opacity:1}}@keyframes _stickyEdgeOut_1vw51_1{0%{opacity:1}to{opacity:0}}._headerCell_188ed_1{padding:0 var(--dg-padding);min-width:0;min-height:var(--dg-header-height);font-weight:600;font-size:var(--dg-font-size);background-color:var(--mantine-color-body);border-bottom:1px solid var(--mantine-color-default-border);-webkit-user-select:none;user-select:none;align-items:center;gap:2px;display:flex;position:relative}._headerCell_188ed_1[data-align=right]{justify-content:flex-end}._headerCell_188ed_1[data-align=center]{justify-content:center}._headerCell_188ed_1[data-control-column=true]{padding:0}._headerCellFiltered_188ed_35 ._headerTitle_188ed_35{color:var(--mantine-primary-color-filled)}._headerTitle_188ed_35{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}._headerCell_188ed_1[data-align=right] ._headerTitle_188ed_35{text-align:right}._headerCell_188ed_1[data-align=center] ._headerTitle_188ed_35{justify-content:center;display:flex}._headerActions_188ed_58{flex-shrink:0;align-items:center;gap:0;margin-left:auto;display:flex}._headerCell_188ed_1[data-align=right] ._headerActions_188ed_58{order:-1;margin-left:0;margin-right:auto}._headerAction_188ed_58{display:none}._headerCell_188ed_1:hover ._headerAction_188ed_58,._headerCell_188ed_1:focus-within ._headerAction_188ed_58,._headerAction_188ed_58[data-pinned-visible=true]{display:flex}._headerCellSortable_188ed_87{cursor:pointer}._sortAction_188ed_93[data-sorted=false]{opacity:.55}._sortAction_188ed_93[data-sorted=false]:hover{opacity:1}._sortIndex_188ed_103{color:var(--mantine-color-dimmed);text-align:center;min-width:10px;font-size:10px;font-weight:600;line-height:1}._headerCellDragging_188ed_115{opacity:.4}._headerCellDropBefore_188ed_119:before,._headerCellDropAfter_188ed_120:before{content:"";background-color:var(--mantine-primary-color-filled);z-index:5;pointer-events:none;width:2px;position:absolute;top:0;bottom:0}._headerCellDropBefore_188ed_119:before{left:0}._headerCellDropAfter_188ed_120:before{right:0}._columnSeparator_188ed_140{z-index:1;justify-content:center;width:10px;height:50%;display:flex;position:absolute;top:25%;right:0;transform:translate(50%)}._columnSeparatorResizable_188ed_152{cursor:col-resize;touch-action:none}._columnSeparator_188ed_140:after{content:"";background-color:#0000;width:1px;height:100%;transition:background-color .12s,width .12s}._headerCell_188ed_1:hover ._columnSeparator_188ed_140:after,._headerCell_188ed_1:focus-within ._columnSeparator_188ed_140:after{background-color:var(--mantine-color-default-border)}._columnSeparatorResizable_188ed_152:hover:after,._columnSeparatorActive_188ed_175:after{background-color:var(--mantine-primary-color-filled);width:2px}._menuItemActive_188ed_181{background-color:var(--mantine-color-default-hover);font-weight:600}._toolbar_4my8t_1{align-items:center;gap:var(--mantine-spacing-xs);padding:6px var(--mantine-spacing-xs);flex-shrink:0;min-height:42px;display:flex}._toolbarSpacer_4my8t_10{flex:1}
|
|
1
|
+
._root_1wvkg_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_1wvkg_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_1wvkg_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_1wvkg_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_1wvkg_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_1wvkg_8{--dg-radius:var(--mantine-radius-md);--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px;--dg-row-selected-bg:var(--mantine-primary-color-light);--dg-row-highlight-bg:var(--mantine-primary-color-light-hover);--dg-row-group-bg:var(--mantine-color-body);--dg-row-striped-bg:color-mix(in srgb, var(--mantine-color-text) 3.5%, var(--mantine-color-body));--dg-row-new-bg:color-mix(in srgb, var(--mantine-color-green-6) 8%, var(--mantine-color-body));--dg-z-pinned-cell:2;--dg-z-focused-cell:3;--dg-z-pinned-row:4;--dg-z-pinned-row-pinned-cell:5;--dg-z-summary-row:4;--dg-z-summary-pinned-cell:5;--dg-z-header:6;--dg-z-header-pinned-cell:7;text-align:left;border:1px solid var(--mantine-color-default-border);border-radius:var(--dg-radius);background-color:var(--mantine-color-body);flex-direction:column;min-height:0;display:flex;overflow:hidden}._columnsPanel_1492o_1{flex-direction:column;width:280px;display:flex}._columnsPanelSearch_1492o_7{padding:var(--mantine-spacing-sm)}._columnsPanelList_1492o_11{gap:var(--mantine-spacing-sm);padding:0 var(--mantine-spacing-sm) var(--mantine-spacing-sm);flex-direction:column;display:flex}._columnsPanelFooter_1492o_18{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-sm);border-top:1px solid var(--mantine-color-default-border);display:flex}._detailsToggle_n39tz_3{width:100%;height:100%;color:inherit;justify-content:center;align-items:center;display:flex}._detailsToggle_n39tz_3:hover ._chevron_n39tz_12{color:var(--mantine-color-text)}._chevron_n39tz_12{color:var(--mantine-color-dimmed);align-items:center;transition:transform .12s;display:flex}._chevron_n39tz_12[data-expanded=true]{transform:rotate(90deg)}@media (prefers-reduced-motion:reduce){._chevron_n39tz_12{transition:none}}._tableWrapper_uqiy9_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._scrollContainer_uqiy9_10{flex:1;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_uqiy9_21{display:grid}._headerRow_uqiy9_27{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._headerRow_uqiy9_27[data-dg-header-last]:after{content:"";pointer-events:none;background:linear-gradient(to bottom, var(--dg-header-shadow-color,#00000024), transparent);opacity:0;height:6px;position:absolute;inset:100% 0 auto}@supports (animation-timeline:scroll()){._headerRow_uqiy9_27[data-dg-header-last]:after{animation:linear both _dg-header-shadow_uqiy9_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dg-header-shadow_uqiy9_1{0%{opacity:0}to{opacity:1}}._bodyRow_uqiy9_76{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_uqiy9_76[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_uqiy9_76:hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_uqiy9_76[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_uqiy9_76[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_uqiy9_76[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_uqiy9_76[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_uqiy9_76[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_uqiy9_76:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_uqiy9_143{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--row-bg);font-size:var(--dg-font-size);align-items:center;display:flex}._bodyCell_uqiy9_143[data-control-column=true]{padding:0}._grid_uqiy9_21[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_uqiy9_143[data-selected=true]{background-color:color-mix(in srgb, var(--mantine-primary-color-filled) 14%, var(--row-bg));--dg-edge-top:transparent;--dg-edge-bottom:transparent;--dg-edge-left:transparent;--dg-edge-right:transparent;box-shadow:inset 0 1px 0 0 var(--dg-edge-top), inset 0 -1px 0 0 var(--dg-edge-bottom), inset 1px 0 0 0 var(--dg-edge-left), inset -1px 0 0 0 var(--dg-edge-right)}._bodyCell_uqiy9_143[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_uqiy9_143[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_uqiy9_141{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_uqiy9_143[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_uqiy9_243{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorActions_uqiy9_252{flex:none;align-items:center;display:flex}._bodyCell_uqiy9_143[data-dirty],._bodyCell_uqiy9_143[data-invalid]{position:relative}._bodyCell_uqiy9_143[data-dirty]:after,._bodyCell_uqiy9_143[data-invalid]:after{content:"";border:5px solid #0000;border-top-color:var(--mantine-primary-color-filled);border-right-color:var(--mantine-primary-color-filled);position:absolute;top:0;right:0}._bodyCell_uqiy9_143[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_uqiy9_143[data-align=right]{justify-content:flex-end}._bodyCell_uqiy9_143[data-align=center]{justify-content:center}._bodyCell_uqiy9_143[data-align=left] ._cellContent_uqiy9_141{flex:auto}._detailsCell_uqiy9_303{border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--row-bg);padding:var(--dg-padding);-webkit-user-select:text;user-select:text;cursor:auto;grid-column:1/-1}._messageRow_uqiy9_15{justify-content:center;justify-self:start;align-items:center;gap:var(--mantine-spacing-xs);width:100cqi;padding:var(--mantine-spacing-xl);flex-direction:column;grid-column:1/-1;display:flex;position:sticky;left:0}._bodyRow_uqiy9_76[data-deleted=true]{opacity:.55;text-decoration:line-through}._bodyRow_uqiy9_76[data-deleted=true] ._bodyCell_uqiy9_143:not([data-control-column=true]){pointer-events:none}._entryBlock_uqiy9_353{grid-column:1/-1;grid-template-columns:subgrid;top:var(--dg-header-height,0px);z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._entryRow_uqiy9_362,._entryFlowBlock_uqiy9_371{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_uqiy9_384{grid-column:1/-1;grid-template-columns:subgrid;top:calc(var(--dg-header-height,0px) + var(--dg-entry-height,0px));z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._pinnedTopBlock_uqiy9_384>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_uqiy9_397{grid-column:1/-1;grid-template-columns:subgrid;bottom:var(--dg-summary-height,0px);z-index:var(--dg-z-pinned-row,4);display:grid;position:sticky}._pinnedBottomBlock_uqiy9_397>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_uqiy9_410{padding:0 calc(var(--dg-padding) / 2);border-bottom:2px solid var(--mantine-primary-color-filled);background-color:var(--mantine-color-body);font-size:var(--dg-font-size);align-items:center;display:flex}._entryCell_uqiy9_410[data-control-column=true]{justify-content:center;padding:0}._entryRow_uqiy9_362[data-confirmed=true] ._entryCell_uqiy9_410{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--dg-row-new-bg,var(--mantine-color-body))}._entryRow_uqiy9_362[data-confirmed=true] ._entryCell_uqiy9_410[data-control-column=true]{padding:0}._rowStateIndicator_uqiy9_440{width:22px;height:22px;color:var(--mantine-color-dimmed);flex:none;justify-content:center;align-items:center;display:inline-flex}._rowStateIndicator_uqiy9_440[data-error]{color:var(--mantine-color-error)}._entryCell_uqiy9_410[data-align=right]{justify-content:flex-end}._entryCell_uqiy9_410[data-align=center]{justify-content:center}._matchHighlight_uqiy9_466{background-color:var(--dg-match-highlight-bg,var(--lightningcss-light,var(--mantine-color-yellow-2))var(--lightningcss-dark,#fab00559));color:inherit;border-radius:2px}._summaryRow_uqiy9_478{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_uqiy9_487{padding:0 var(--dg-padding);border-top:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);font-size:var(--dg-font-size);align-items:center;font-weight:600;display:flex}._summaryCell_uqiy9_487[data-control-column=true]{padding:0}._summaryCell_uqiy9_487[data-align=right]{justify-content:flex-end}._summaryCell_uqiy9_487[data-align=center]{justify-content:center}._groupToggle_1954o_4{width:100%;min-width:0;font-size:var(--dg-font-size);color:inherit;align-items:center;gap:6px;display:flex}._chevron_1954o_14{color:var(--mantine-color-dimmed);flex:none;align-items:center;transition:transform .12s;display:flex}._chevron_1954o_14[data-expanded=true]{transform:rotate(90deg)}@media (prefers-reduced-motion:reduce){._chevron_1954o_14{transition:none}}._groupLabel_1954o_34{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}._groupCount_1954o_44{color:var(--mantine-color-dimmed);font-variant-numeric:tabular-nums;flex:none}._filterPanel_izakx_4{top:calc(var(--dg-header-height) + 2px);left:var(--mantine-spacing-md);z-index:5;padding:var(--mantine-spacing-sm);border-radius:var(--mantine-radius-md);border:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);box-shadow:var(--mantine-shadow-md);position:absolute}._filterRow_izakx_16{align-items:flex-end;gap:var(--mantine-spacing-xs);display:flex}._filterPanelHeader_izakx_22{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);padding-bottom:var(--mantine-spacing-xs);display:flex}._filterPanelFooter_izakx_30{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);display:flex}._filterPills_14wl0_3{align-items:center;gap:var(--mantine-spacing-xs);flex-wrap:wrap;display:flex}._filterPills_14wl0_3 ._pill_14wl0_15{background-color:var(--lightningcss-light,var(--mantine-color-gray-1))var(--lightningcss-dark,var(--mantine-color-dark-5));color:var(--lightningcss-light,var(--mantine-color-black))var(--lightningcss-dark,var(--mantine-color-dark-0));border:1px solid var(--lightningcss-light,var(--mantine-color-gray-3))var(--lightningcss-dark,var(--mantine-color-dark-3))}._pillLabel_14wl0_27{font:inherit;color:inherit;cursor:pointer}._pillLabel_14wl0_27:hover{text-decoration:underline}._footer_te0a3_1{justify-content:flex-end;align-items:center;gap:var(--mantine-spacing-lg);padding:4px var(--mantine-spacing-sm);border-top:1px solid var(--mantine-color-default-border);flex-shrink:0;min-height:48px;display:flex}._footer_te0a3_1[data-paging-suspended=true]{opacity:.55}._stickyLeft_1vw51_16:after,._stickyRight_1vw51_17:after{content:"";pointer-events:none;width:8px;position:absolute;top:0;bottom:0}._stickyLeft_1vw51_16:after{background:linear-gradient(90deg,var(--lightningcss-light,#00000012)var(--lightningcss-dark,#00000042),var(--lightningcss-light,#00000006)var(--lightningcss-dark,#00000017) 45%,#0000);left:100%}._stickyRight_1vw51_17:after{background:linear-gradient(270deg,var(--lightningcss-light,#00000012)var(--lightningcss-dark,#00000042),var(--lightningcss-light,#00000006)var(--lightningcss-dark,#00000017) 45%,#0000);right:100%}@supports (animation-timeline:scroll()){._stickyLeft_1vw51_16:after,._stickyRight_1vw51_17:after{--dg-sticky-edge-range:20px;opacity:0;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(inline)}._stickyLeft_1vw51_16:after{animation-name:_stickyEdgeIn_1vw51_1;animation-range:0 var(--dg-sticky-edge-range)}._stickyRight_1vw51_17:after{animation-name:_stickyEdgeOut_1vw51_1;animation-range:calc(100% - var(--dg-sticky-edge-range)) 100%}}@keyframes _stickyEdgeIn_1vw51_1{0%{opacity:0}to{opacity:1}}@keyframes _stickyEdgeOut_1vw51_1{0%{opacity:1}to{opacity:0}}._headerCell_188ed_1{padding:0 var(--dg-padding);min-width:0;min-height:var(--dg-header-height);font-weight:600;font-size:var(--dg-font-size);background-color:var(--mantine-color-body);border-bottom:1px solid var(--mantine-color-default-border);-webkit-user-select:none;user-select:none;align-items:center;gap:2px;display:flex;position:relative}._headerCell_188ed_1[data-align=right]{justify-content:flex-end}._headerCell_188ed_1[data-align=center]{justify-content:center}._headerCell_188ed_1[data-control-column=true]{padding:0}._headerCellFiltered_188ed_35 ._headerTitle_188ed_35{color:var(--mantine-primary-color-filled)}._headerTitle_188ed_35{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}._headerCell_188ed_1[data-align=right] ._headerTitle_188ed_35{text-align:right}._headerCell_188ed_1[data-align=center] ._headerTitle_188ed_35{justify-content:center;display:flex}._headerActions_188ed_58{flex-shrink:0;align-items:center;gap:0;margin-left:auto;display:flex}._headerCell_188ed_1[data-align=right] ._headerActions_188ed_58{order:-1;margin-left:0;margin-right:auto}._headerAction_188ed_58{display:none}._headerCell_188ed_1:hover ._headerAction_188ed_58,._headerCell_188ed_1:focus-within ._headerAction_188ed_58,._headerAction_188ed_58[data-pinned-visible=true]{display:flex}._headerCellSortable_188ed_87{cursor:pointer}._sortAction_188ed_93[data-sorted=false]{opacity:.55}._sortAction_188ed_93[data-sorted=false]:hover{opacity:1}._sortIndex_188ed_103{color:var(--mantine-color-dimmed);text-align:center;min-width:10px;font-size:10px;font-weight:600;line-height:1}._headerCellDragging_188ed_115{opacity:.4}._headerCellDropBefore_188ed_119:before,._headerCellDropAfter_188ed_120:before{content:"";background-color:var(--mantine-primary-color-filled);z-index:5;pointer-events:none;width:2px;position:absolute;top:0;bottom:0}._headerCellDropBefore_188ed_119:before{left:0}._headerCellDropAfter_188ed_120:before{right:0}._columnSeparator_188ed_140{z-index:1;justify-content:center;width:10px;height:50%;display:flex;position:absolute;top:25%;right:0;transform:translate(50%)}._columnSeparatorResizable_188ed_152{cursor:col-resize;touch-action:none}._columnSeparator_188ed_140:after{content:"";background-color:#0000;width:1px;height:100%;transition:background-color .12s,width .12s}._headerCell_188ed_1:hover ._columnSeparator_188ed_140:after,._headerCell_188ed_1:focus-within ._columnSeparator_188ed_140:after{background-color:var(--mantine-color-default-border)}._columnSeparatorResizable_188ed_152:hover:after,._columnSeparatorActive_188ed_175:after{background-color:var(--mantine-primary-color-filled);width:2px}._menuItemActive_188ed_181{background-color:var(--mantine-color-default-hover);font-weight:600}._toolbar_1459c_1{align-items:center;gap:var(--mantine-spacing-xs);padding:6px var(--mantine-spacing-xs);flex-shrink:0;min-height:42px;display:flex}._toolbarSpacer_1459c_10{flex:1}._summaryCount_1459c_14{white-space:nowrap}
|
|
2
2
|
/*$vite$:1*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jielga/tmdatagrid",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.7",
|
|
4
4
|
"description": "A React data grid built on TanStack Table v9 and Mantine - always virtualized, with resizable, reorderable, sortable, filterable, hideable and pinnable columns.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,7 +14,7 @@ description: >
|
|
|
14
14
|
metadata:
|
|
15
15
|
type: core
|
|
16
16
|
library: '@jielga/tmdatagrid'
|
|
17
|
-
library_version: '2.0.0-beta.
|
|
17
|
+
library_version: '2.0.0-beta.7'
|
|
18
18
|
sources:
|
|
19
19
|
- 'Jielga/TMDataGrid:src/docs/cell-selection.md'
|
|
20
20
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/cellNavigation.ts'
|
package/skills/columns/SKILL.md
CHANGED
|
@@ -16,7 +16,7 @@ description: >
|
|
|
16
16
|
metadata:
|
|
17
17
|
type: core
|
|
18
18
|
library: '@jielga/tmdatagrid'
|
|
19
|
-
library_version: '2.0.0-beta.
|
|
19
|
+
library_version: '2.0.0-beta.7'
|
|
20
20
|
sources:
|
|
21
21
|
- 'Jielga/TMDataGrid:src/docs/columns.md'
|
|
22
22
|
- 'Jielga/TMDataGrid:src/docs/column-layout.md'
|
|
@@ -55,6 +55,26 @@ const columns = columnHelper.columns([
|
|
|
55
55
|
Define columns at module scope. A new array on every render rebuilds the table's
|
|
56
56
|
column model.
|
|
57
57
|
|
|
58
|
+
A dotted `accessorKey` reads a nested field, and the column id it derives
|
|
59
|
+
replaces the dots: `accessorKey: "address.city"` makes column id
|
|
60
|
+
`address_city`, while the edit path stays `"address.city"`. Anything that
|
|
61
|
+
addresses the column by id - `initialState`, `editing.columns`, `moveColumn`,
|
|
62
|
+
a test selector - takes the underscore form.
|
|
63
|
+
|
|
64
|
+
`columnHelper.group` nests columns under a shared header; `columns` takes
|
|
65
|
+
another `columnHelper.columns` call, not a bare array:
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
columnHelper.group({
|
|
69
|
+
id: "person",
|
|
70
|
+
header: "Person",
|
|
71
|
+
columns: columnHelper.columns([
|
|
72
|
+
columnHelper.accessor("firstName", { header: "First" }),
|
|
73
|
+
columnHelper.accessor("lastName", { header: "Last" }),
|
|
74
|
+
]),
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
58
78
|
## meta
|
|
59
79
|
|
|
60
80
|
| Field | Type | Default | Description |
|
|
@@ -246,7 +266,7 @@ asks for it.
|
|
|
246
266
|
| Checkbox | `SELECT_COLUMN_ID` | Selection is on and the mode has checkboxes |
|
|
247
267
|
| Tree | `GROUP_COLUMN_ID` | A column is grouped |
|
|
248
268
|
| Details | `DETAILS_COLUMN_ID` | `renderDetails` is set |
|
|
249
|
-
| Edit | `EDIT_COLUMN_ID` | Row mode, draft
|
|
269
|
+
| Edit | `EDIT_COLUMN_ID` | Row mode, `editing.draft`, or `editing.onRowDelete` |
|
|
250
270
|
|
|
251
271
|
They are structural: fixed width, no column menu, and they cannot be sorted,
|
|
252
272
|
filtered, resized, re-pinned or moved. The checkbox lane anchors the left pinned
|
|
@@ -281,6 +301,28 @@ columnHelper.accessor("email", {
|
|
|
281
301
|
|
|
282
302
|
Source: `src/docs/column-layout.md` (Sizing).
|
|
283
303
|
|
|
304
|
+
### HIGH Addressing a dotted column by its accessor key
|
|
305
|
+
|
|
306
|
+
A dotted `accessorKey` produces a column id with underscores, so state and
|
|
307
|
+
calls keyed by column id silently match nothing when given the dotted form.
|
|
308
|
+
|
|
309
|
+
Wrong:
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
initialState: { columnVisibility: { "address.city": false } },
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Correct:
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
initialState: { columnVisibility: { address_city: false } },
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The edit path is the exception: `meta.edit.field` and validation issue paths
|
|
322
|
+
stay dotted, because they address the data, not the column.
|
|
323
|
+
|
|
324
|
+
Source: `src/docs/columns.md` (The column helper).
|
|
325
|
+
|
|
284
326
|
### CRITICAL A component header without `meta.label`
|
|
285
327
|
|
|
286
328
|
`getColumnLabel(column)` falls back to a *string* header, then to the column id.
|
package/skills/data/SKILL.md
CHANGED
|
@@ -6,16 +6,16 @@ description: >
|
|
|
6
6
|
enablePagination, manualPagination), the Footer's renderPagination slot over {
|
|
7
7
|
state, actions, Controls }, getTMDataGridPaginationApi, isPagingActive versus
|
|
8
8
|
canPaginate, always-on virtualization with overscan and meta.rowHeight,
|
|
9
|
-
scrollToRow
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
scrollToRow, the edge callbacks onScrollToBottom / onScrollToRight and why
|
|
10
|
+
onReachEnd is better for loading more, the header and pinned-lane depth
|
|
11
|
+
shadows, and the four empty states in precedence order with meta.loading,
|
|
12
|
+
renderEmptyState, hasActiveFilters, TMDataGrid.LoadingIndicator and
|
|
13
|
+
TMDataGrid.SummaryCount. Load when adding a pager, tuning scrolling, scrolling
|
|
14
|
+
to a row, or deciding what an empty grid should say.
|
|
15
15
|
metadata:
|
|
16
16
|
type: core
|
|
17
17
|
library: '@jielga/tmdatagrid'
|
|
18
|
-
library_version: '2.0.0-beta.
|
|
18
|
+
library_version: '2.0.0-beta.7'
|
|
19
19
|
sources:
|
|
20
20
|
- 'Jielga/TMDataGrid:src/docs/pagination.md'
|
|
21
21
|
- 'Jielga/TMDataGrid:src/docs/scrolling.md'
|
|
@@ -118,8 +118,13 @@ grid.scrollToRow({ rowId: "42", align: "center" });
|
|
|
118
118
|
|
|
119
119
|
`scrollToRow` exists because the target row may not be mounted, and
|
|
120
120
|
`element.scrollIntoView()` cannot find an element that is not rendered. `align`
|
|
121
|
-
is `"start"`, `"center"`, `"end"` or `"auto"`.
|
|
122
|
-
|
|
121
|
+
is `"start"`, `"center"`, `"end"` or `"auto"`. It answers whether the row could
|
|
122
|
+
be reached: `false` when it is filtered out, on another page or an id matching
|
|
123
|
+
no row, and a pinned row answers `true` without scrolling.
|
|
124
|
+
|
|
125
|
+
The hook reaches the virtualizer through `scrollerRef`, which
|
|
126
|
+
`TMDataGrid.Table` fills in. That is internal wiring, not an API - spread the
|
|
127
|
+
whole grid object onto `<TMDataGrid>` or nothing scrolls.
|
|
123
128
|
|
|
124
129
|
`TMDataGrid.Table` reports arrivals at each edge - `onScrollToTop`,
|
|
125
130
|
`onScrollToBottom`, `onScrollToLeft`, `onScrollToRight` - firing **once** on
|
|
@@ -286,7 +291,6 @@ Source: `src/docs/pagination.md` (Grouping suspends it).
|
|
|
286
291
|
| `overscan` | Option | `number` | `6` | Rows kept mounted beyond each edge of the viewport. |
|
|
287
292
|
| `meta.rowHeight` | Option | `number` | From `size` | Row height in pixels. The virtualizer needs a number. |
|
|
288
293
|
| `scrollToRow` | Hook return | `({ rowId, align? }) => boolean` | `align: "auto"` | Scrolls a row into view, mounted or not. |
|
|
289
|
-
| `scrollerRef` | Hook return | `RefObject<HTMLDivElement>` | – | The scroll container. |
|
|
290
294
|
| `onScrollToTop` · `onScrollToBottom` · `onScrollToLeft` · `onScrollToRight` | Table props | `() => void` | – | Fire once on arriving at that edge. |
|
|
291
295
|
| `TMDataGridScrollAlign` | Export | `"start" \| "center" \| "end" \| "auto"` | – | The `align` argument. |
|
|
292
296
|
| `meta.loading` | Option | `boolean` | `false` | A fetch is in flight. Takes precedence over every empty message. |
|
package/skills/editing/SKILL.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: editing
|
|
3
3
|
description: >
|
|
4
|
-
Edit cells and rows in TMDataGrid. Covers the editing option
|
|
5
|
-
mode
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
not open.
|
|
4
|
+
Edit cells and rows in TMDataGrid. Covers the editing option and its two axes
|
|
5
|
+
(mode: cell, cellConfirm, row; draft), the required getRowId, editing.onCommit
|
|
6
|
+
and editing.onSaveDrafts, why the grid never mutates data, gating with
|
|
7
|
+
editing.columns, meta.edit.enabled and meta.edit.field, the built-in editors
|
|
8
|
+
picked by meta.type, custom editors via meta.edit.editor, value mapping with
|
|
9
|
+
meta.edit.mapValue, validation at every level - meta.edit.validate,
|
|
10
|
+
cross-field editing.rowValidators, cross-row editing.tableValidators over the
|
|
11
|
+
draft-overlaid collection - adding and deleting rows (edit.addRow,
|
|
12
|
+
newRowDefaults, onRowAdd, onRowDelete), the edit lane, TMDataGrid.DraftActions
|
|
13
|
+
and renderActions, and the edit engine (begin, commit, commitAll, saveDrafts,
|
|
14
|
+
addRows, setCellValue, setRowValues, getForm, store). Load when making a grid
|
|
15
|
+
editable, choosing an edit mode, wiring a save, writing a cell editor,
|
|
16
|
+
validating an edit, writing cells from a toolbar action or bulk fill, or when
|
|
17
|
+
cells will not open.
|
|
18
18
|
metadata:
|
|
19
19
|
type: core
|
|
20
20
|
library: '@jielga/tmdatagrid'
|
|
21
|
-
library_version: '2.0.0-beta.
|
|
21
|
+
library_version: '2.0.0-beta.7'
|
|
22
22
|
sources:
|
|
23
23
|
- 'Jielga/TMDataGrid:src/docs/editing.md'
|
|
24
24
|
- 'Jielga/TMDataGrid:src/docs/query-builder.md'
|
|
@@ -71,30 +71,32 @@ const grid = useTMDataGrid({
|
|
|
71
71
|
|
|
72
72
|
Two rules are compile errors, not options that silently do nothing: `editing`
|
|
73
73
|
requires `getRowId`, and `editing.onSaveDrafts` exists only under
|
|
74
|
-
`editing.
|
|
75
|
-
falls back to the per-row `editing.onCommit` loop.
|
|
74
|
+
`editing.draft: true`. A draft store _without_ `onSaveDrafts` is fine:
|
|
75
|
+
`saveDrafts` falls back to the per-row `editing.onCommit` loop.
|
|
76
76
|
|
|
77
|
-
## The
|
|
77
|
+
## The two axes
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
`editing.mode` sets what counts as a commit; `editing.draft` sets where that commit goes.
|
|
80
|
+
They are independent, and every pair is legal.
|
|
81
81
|
|
|
82
82
|
| Mode | Commits on | Cancels on | Controls |
|
|
83
83
|
| --- | --- | --- | --- |
|
|
84
|
-
| `"cell"` | Enter, Tab,
|
|
85
|
-
| `"cellConfirm"` | ✓ or Enter;
|
|
86
|
-
| `"row"` | Save in the edit lane, or
|
|
87
|
-
| `"draft"` | Enter or the lane's ✓, into the draft store | `edit.cancelAll()`, or per row in the lane | `TMDataGrid.EditActions` + the edit lane |
|
|
84
|
+
| `"cell"` | Enter, Tab, leaving the cell | Escape | none |
|
|
85
|
+
| `"cellConfirm"` | ✓ or Enter; Tab and leaving keep the draft | ✕ or Escape | ✓ / ✕ beside the input |
|
|
86
|
+
| `"row"` | Save in the edit lane, or Enter | Cancel, or Escape | generated edit lane |
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
| `editing.draft` | Where a commit goes |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `false` (default) | Straight out: `onCommit`, `onRowAdd`, `onRowDelete` |
|
|
91
|
+
| `true` | Into the grid's draft store, until `edit.saveDrafts()` sends the lot |
|
|
92
|
+
|
|
93
|
+
Which to pick: `"cell"` for spreadsheet feel; `"cellConfirm"` when a stray click must not fire a request; `"row"` when the row is the unit of the save or a rule spans two columns.
|
|
94
|
+
Add `draft: true` for many edits sent as one transaction - `{ mode: "row", draft: true }` parks a whole row from the lane's ✓, `{ mode: "cell", draft: true }` parks a row as the caret leaves it.
|
|
93
95
|
|
|
94
96
|
An editor opens on double-click, or with the cell cursor on the cell: Enter, F2,
|
|
95
97
|
or typing, where the first character replaces the value. Delete or Backspace
|
|
96
|
-
clears the value and commits without opening an editor; under `
|
|
97
|
-
cleared value is held with the other drafts instead. Editing implies cell
|
|
98
|
+
clears the value and commits without opening an editor; under `draft: true`
|
|
99
|
+
the cleared value is held with the other drafts instead. Editing implies cell
|
|
98
100
|
selection: `cellSelection` defaults to `"single"` while `editing` is set. The
|
|
99
101
|
grid places the caret in the cell that was opened, and `edit.addRow()` places it
|
|
100
102
|
in the new row's first editable cell, so a `meta.edit.editor` receives focus
|
|
@@ -105,14 +107,11 @@ the cell clicked, opens every editable cell of the row, and ✓ saves them as on
|
|
|
105
107
|
commit. Rows accumulate: opening a second row leaves the first open, and each
|
|
106
108
|
row's ✓ and ✕ act on that row alone.
|
|
107
109
|
|
|
108
|
-
Under `
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
escape hatch to the consumer. A held draft is displayed: the cell renders the
|
|
114
|
-
draft value through the column's own `cell` renderer, with the blue corner
|
|
115
|
-
marking it dirty and `data-dirty` on the row.
|
|
110
|
+
Under `draft: true` nothing reaches a callback until `saveDrafts`.
|
|
111
|
+
The mode's own commit gesture parks the row instead of sending it, Escape drops that one draft, and parked rows accumulate, surviving filters, sorts and scrolling.
|
|
112
|
+
`edit.commit(rowId)` parks too, so there is no per-row escape hatch to the consumer.
|
|
113
|
+
A parked row is displayed: the cell renders the draft value through the column's own `cell` renderer, with the blue corner marking it dirty and `data-dirty` on the row.
|
|
114
|
+
An entry row is row-shaped in every mode - every editable cell open at once, the browser's Tab, and the lane's ✓ to enter it.
|
|
116
115
|
|
|
117
116
|
The edit lane is the change indicator and the per-row undo: an edited row shows
|
|
118
117
|
a pencil icon and Revert, which drops that row's draft; a new row a plus icon, a
|
|
@@ -158,6 +157,7 @@ records, so `accessorKey: "address.city"` edits `values.address.city`.
|
|
|
158
157
|
|
|
159
158
|
| Gate | Effect |
|
|
160
159
|
| --- | --- |
|
|
160
|
+
| `editing.columns: ["targetPct"]` | Only the named columns edit |
|
|
161
161
|
| `meta.edit.enabled: false` | The column never edits |
|
|
162
162
|
| `meta.edit.enabled: (row) => boolean` | Per row, per column |
|
|
163
163
|
| `meta.edit.field: "lastName"` | The path an `accessorFn` column writes to |
|
|
@@ -166,6 +166,11 @@ records, so `accessorKey: "address.city"` edits `values.address.city`.
|
|
|
166
166
|
Group rows and the generated lanes (checkbox, row number, details, edit) never
|
|
167
167
|
edit.
|
|
168
168
|
|
|
169
|
+
`editing.columns` lists the column ids that take edits; unset, the default, every column mapping to a data path is editable.
|
|
170
|
+
It gates before `meta.edit`, never past it: a column left out takes no edits whatever its own meta says, and a listed column still answers to its `meta.edit.enabled`.
|
|
171
|
+
The same list decides which cells an entry row opens.
|
|
172
|
+
`edit.isColumnEditable(column)` answers the column's half of the question with no row in hand, for a toolbar or a menu, and `edit.canEditCell(row, column)` asks both halves.
|
|
173
|
+
|
|
169
174
|
```tsx
|
|
170
175
|
// Computed column writing back to a real field, and per-row gating.
|
|
171
176
|
columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
|
|
@@ -184,7 +189,7 @@ columnHelper.accessor("salary", {
|
|
|
184
189
|
`meta.type` picks the editor - `"string"` (the default), `"number"`,
|
|
185
190
|
`"boolean"`, `"date"`, `"select"` and `"multiSelect"` - and `meta.options` feeds
|
|
186
191
|
the two select editors from the same declaration the filter panel reads. Each
|
|
187
|
-
one, with the export that wraps it, is in
|
|
192
|
+
one, with the value it writes into the draft and the export that wraps it, is in
|
|
188
193
|
[references/editors-and-validation.md](references/editors-and-validation.md#the-built-in-editors).
|
|
189
194
|
|
|
190
195
|
`meta.edit.editor` replaces one, `meta.edit.validate` guards the field, and
|
|
@@ -197,7 +202,7 @@ import { z } from "zod";
|
|
|
197
202
|
// Field level, on the column. A bare schema means { onChange: schema }.
|
|
198
203
|
meta: { edit: { validate: z.string().min(2, "At least two characters") } }
|
|
199
204
|
|
|
200
|
-
// Form level, inside `editing`. Cross-field rules, under "row"
|
|
205
|
+
// Form level, inside `editing`. Cross-field rules, under "row".
|
|
201
206
|
rowValidators: {
|
|
202
207
|
onSubmit: z
|
|
203
208
|
.object({ salary: z.number().positive(), status: z.string() })
|
|
@@ -210,6 +215,24 @@ rowValidators: {
|
|
|
210
215
|
Pathed issues land on the matching cells, pathless ones on the row, and cell
|
|
211
216
|
corners mark both: blue for a dirty draft, red for a validation error.
|
|
212
217
|
|
|
218
|
+
`editing.tableValidators` carries the rules that need the other rows - no
|
|
219
|
+
duplicate keys, no overlapping ranges, shares summing to a total. Its
|
|
220
|
+
`onSubmit` / `onSubmitAsync` receive `{ value, rowId, isNew, rows }`, where
|
|
221
|
+
`rows` is the collection as it would stand if the commit landed: every draft
|
|
222
|
+
overlaid, entry rows appended, deletion-marked rows removed. Same result
|
|
223
|
+
vocabulary as `rowValidators`; errors land on the committing row. The rules
|
|
224
|
+
re-run per parked row during `saveDrafts`, so a draft a later edit
|
|
225
|
+
invalidated blocks the save.
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
tableValidators: {
|
|
229
|
+
onSubmit: ({ value, rowId, rows }) =>
|
|
230
|
+
rows.some((r) => r.rowId !== rowId && r.value.code === value.code)
|
|
231
|
+
? { fields: { code: "Codes must be unique" } }
|
|
232
|
+
: undefined,
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
213
236
|
`meta.edit.mapValue` rewrites a value instead of rejecting it: uppercase a code,
|
|
214
237
|
strip spaces from an IBAN, clamp a number. It runs on every write an editor
|
|
215
238
|
makes, so a text input maps per keystroke, and what it returns is what the
|
|
@@ -227,12 +250,12 @@ Detail for all three: [references/editors-and-validation.md](references/editors-
|
|
|
227
250
|
from `editing.newRowDefaults`. `edit.addRow(values)` overrides that seed key by
|
|
228
251
|
key, so `addRow()` opens the `newRowDefaults` row and `addRow(values)` opens it
|
|
229
252
|
with those fields filled in - pass a whole row to duplicate it. Enter, or the
|
|
230
|
-
lane's ✓, commits the add through `editing.onRowAdd
|
|
231
|
-
|
|
253
|
+
lane's ✓, commits the add through `editing.onRowAdd`; under `draft: true` it
|
|
254
|
+
parks the row in the draft store, validated, and
|
|
232
255
|
`saveDrafts` reports it in `added`. Escape, or ✕, discards the entry. An entry
|
|
233
256
|
row never OK'd is not part of a save - it stays open.
|
|
234
257
|
|
|
235
|
-
Under `
|
|
258
|
+
Under `draft: true` an entered row renders as a value row with no inputs, marked
|
|
236
259
|
`data-new` and `data-committed` and tinted with `--dg-row-new-bg`. By default it
|
|
237
260
|
joins the scrolling flow above the body rows; `editing.newRowsSticky: true`
|
|
238
261
|
keeps committed rows pinned in the entry block until the save. Double-click, or
|
|
@@ -246,7 +269,8 @@ const grid = useTMDataGrid({
|
|
|
246
269
|
columns,
|
|
247
270
|
getRowId: (row) => String(row.id),
|
|
248
271
|
editing: {
|
|
249
|
-
mode: "
|
|
272
|
+
mode: "row",
|
|
273
|
+
draft: true,
|
|
250
274
|
newRowDefaults: () => ({ id: 0, firstName: "", salary: 30_000 }),
|
|
251
275
|
onSaveDrafts: async ({ updated, created, deleted }) => {
|
|
252
276
|
await api.saveBatch({ updated, created, deleted });
|
|
@@ -260,7 +284,7 @@ const grid = useTMDataGrid({
|
|
|
260
284
|
Add senior
|
|
261
285
|
</Button>
|
|
262
286
|
<TMDataGrid.Spacer />
|
|
263
|
-
<TMDataGrid.
|
|
287
|
+
<TMDataGrid.DraftActions />
|
|
264
288
|
</TMDataGrid.Toolbar>;
|
|
265
289
|
```
|
|
266
290
|
|
|
@@ -277,33 +301,44 @@ if (open.length > 0) notify(`${open.length} rows need attention`);
|
|
|
277
301
|
await grid.edit.saveDrafts();
|
|
278
302
|
```
|
|
279
303
|
|
|
280
|
-
`edit.deleteRow(rowId)` calls `editing.onRowDelete({ rowId, row })`
|
|
281
|
-
|
|
282
|
-
|
|
304
|
+
`edit.deleteRow(rowId)` calls `editing.onRowDelete({ rowId, row })`
|
|
305
|
+
immediately, so put any confirmation inside that callback. Under `draft: true`
|
|
306
|
+
it toggles a mark instead: the row renders struck through and inert
|
|
283
307
|
(`data-deleted`), the lane shows Restore, and `saveDrafts` reports the ids in
|
|
284
308
|
`deleted`. You apply adds and deletes, the same as edits. The engine's `tempId`
|
|
285
309
|
(`__new__1`, …) does not need to become a real id.
|
|
286
310
|
|
|
287
311
|
## The built-in controls
|
|
288
312
|
|
|
289
|
-
The generated edit lane (`EDIT_COLUMN_ID`, pinned right) appears when
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
the
|
|
313
|
+
The generated edit lane (`EDIT_COLUMN_ID`, pinned right) appears when `editing.mode` is `"row"`, when `editing.draft` is on, or when `editing.onRowDelete` is set.
|
|
314
|
+
Nothing else adds it.
|
|
315
|
+
It holds one thing per axis: the mode's own controls while a row is open - Save and Cancel under `"row"` - and, once a row is parked, the row-state marker with Revert or Restore.
|
|
316
|
+
A parked row never offers a save.
|
|
317
|
+
The trash shows when the deletion has somewhere to report to: `onRowDelete` is set, or under `draft: true`, `onSaveDrafts` is.
|
|
318
|
+
If validation blocks a row, its marker - or the open row's ✓ - turns red with the message in the tooltip, which is where a pathless `rowValidators` message shows.
|
|
294
319
|
Every control carries a tooltip from the labels.
|
|
295
320
|
|
|
296
|
-
`TMDataGrid.
|
|
297
|
-
|
|
321
|
+
`TMDataGrid.DraftActions` is Save with the draft-store count, Discard, and a
|
|
322
|
+
note counting the rows still open. Save greys out while the store is empty
|
|
323
|
+
however much is being typed, spins while a submit is in flight, renders nothing
|
|
298
324
|
while editing is off, and works under any mode, not only draft.
|
|
299
325
|
|
|
300
|
-
`renderActions` replaces the
|
|
326
|
+
`renderActions` replaces the set and hands over its pieces:
|
|
301
327
|
|
|
302
328
|
```tsx
|
|
303
|
-
<TMDataGrid.
|
|
304
|
-
renderActions={({ state, Controls }) => (
|
|
329
|
+
<TMDataGrid.DraftActions
|
|
330
|
+
renderActions={({ state, actions, Controls }) => (
|
|
305
331
|
<Group>
|
|
306
|
-
{state.
|
|
332
|
+
{state.draftCount > 0 && <Badge>{state.draftCount}</Badge>}
|
|
333
|
+
<Button
|
|
334
|
+
disabled={state.openCount === 0}
|
|
335
|
+
onClick={() => {
|
|
336
|
+
actions.scrollToFirstOpenRow("center");
|
|
337
|
+
}}
|
|
338
|
+
>
|
|
339
|
+
Go to open row
|
|
340
|
+
</Button>
|
|
341
|
+
<Controls.OpenRowsNote />
|
|
307
342
|
<Controls.Save />
|
|
308
343
|
<Controls.Discard />
|
|
309
344
|
</Group>
|
|
@@ -311,23 +346,55 @@ while editing is off, and works under any mode, not only draft.
|
|
|
311
346
|
/>
|
|
312
347
|
```
|
|
313
348
|
|
|
314
|
-
`state` is
|
|
349
|
+
`state` is
|
|
350
|
+
`{ draftCount, openCount, openRowIds, pendingCount, isSubmitting }` -
|
|
351
|
+
`pendingCount` deprecated, reading as `draftCount + openCount`. `actions` is
|
|
352
|
+
`{ save, commitAll, discard, scrollToRow, scrollToFirstOpenRow }`, and
|
|
353
|
+
`Controls` is `{ Save, Discard, OpenRowsNote }`.
|
|
354
|
+
|
|
355
|
+
The grid is always virtualized, so an open row far down the list has no element
|
|
356
|
+
to scroll to. `actions.scrollToFirstOpenRow(align?)` moves the virtualizer to
|
|
357
|
+
the topmost open row and answers whether it could be reached; `false` means
|
|
358
|
+
every open row is filtered out, on another page or collapsed in a group. An
|
|
359
|
+
open entry row answers `true` without scrolling - the entry block is sticky, so
|
|
360
|
+
it is on screen already.
|
|
361
|
+
|
|
362
|
+
The two orderings differ: `state.openRowIds` is the order the grid opened the
|
|
363
|
+
rows, `scrollToFirstOpenRow` is display order. `openRowIds[0]` need not be the
|
|
364
|
+
row it reaches.
|
|
315
365
|
|
|
316
366
|
## The engine: `edit`
|
|
317
367
|
|
|
318
368
|
`grid.edit` is public, and everything the built-in controls do goes through it:
|
|
319
369
|
`begin` and `commit`, `cancel` / `cancelAll`, `commitAll` / `saveDrafts`,
|
|
320
|
-
`addRow` / `addRows` /
|
|
370
|
+
`setCellValue` / `setRowValues` / `clearCell`, `addRow` / `addRows` /
|
|
321
371
|
`deleteRow`, `getForm`, and `store` for `useSelector` (an example is under
|
|
322
372
|
[Submitting an outer form](#high-submitting-an-outer-form-while-the-grid-holds-a-draft)).
|
|
323
|
-
|
|
324
|
-
`
|
|
373
|
+
`edit.store` publishes each open or parked row's drafted values as
|
|
374
|
+
`rows[rowId].values`, which is what a computed cell or a cross-row check reads
|
|
375
|
+
- `useTMDataGridContext()` reaches the engine from inside a cell renderer.
|
|
376
|
+
Every member with its signature, the gates, `isColumnEditable`, `deactivate`,
|
|
377
|
+
and the `edit.store` shape are in
|
|
325
378
|
[references/editing-api.md](references/editing-api.md#the-edit-engine).
|
|
326
379
|
|
|
327
380
|
`getForm` exposes the row's form: render it in a drawer and it shares values,
|
|
328
381
|
dirty state and errors with the inline cells, because it is the same
|
|
329
382
|
`FormApi`.
|
|
330
383
|
|
|
384
|
+
`edit.setCellValue(rowId, columnId, value)` writes one cell and commits its row with no editor open, which is what a toolbar action or a bulk fill wants.
|
|
385
|
+
The row need not be mounted, so a selected row inside a collapsed group takes the write like any other.
|
|
386
|
+
`edit.setRowValues(rowId, values)` does several cells of one row in a single commit, keyed by column id, all or nothing.
|
|
387
|
+
|
|
388
|
+
```tsx
|
|
389
|
+
for (const row of grid.table.getSelectedRowModel().rows) {
|
|
390
|
+
await grid.edit.setCellValue(row.id, "targetPct", equalWeight(row.original));
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Under `draft: true` each row parks in the draft store like any hand-made edit, with the same change markers and the same per-row revert, and the basket leaves through `saveDrafts`.
|
|
395
|
+
`value` is the stored value: no editor runs, so `meta.edit.mapValue` does not run either, while `meta.edit.validate` does.
|
|
396
|
+
Both resolve `false` when the cell takes no edit - no such row or column, `editing.columns` excludes it, `meta.edit.enabled` is off, or the row is not editable - and when validation refuses the value, which leaves the row open carrying its errors.
|
|
397
|
+
|
|
331
398
|
## Inside an outer form
|
|
332
399
|
|
|
333
400
|
A `@tanstack/react-form` form can hold the row array, with the grid as a
|
|
@@ -338,10 +405,12 @@ approval, map by row id (never index), and assign negative ids to new rows.
|
|
|
338
405
|
|
|
339
406
|
The validation split follows from what each side can see: **a rule decidable
|
|
340
407
|
from one row belongs to the grid (`meta.edit.validate`,
|
|
341
|
-
`editing.rowValidators`)
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
the form
|
|
408
|
+
`editing.rowValidators`), and a rule needing the other rows belongs to
|
|
409
|
+
`editing.tableValidators`, which is handed the collection with every draft
|
|
410
|
+
overlaid.** A collection rule may live in the outer form's field validator
|
|
411
|
+
instead, where the submit gate is the form's own; `edit.store` publishes each
|
|
412
|
+
row's drafted values as `rows[rowId].values` for a rule there that must count
|
|
413
|
+
pending values.
|
|
345
414
|
|
|
346
415
|
## Common mistakes
|
|
347
416
|
|
|
@@ -353,10 +422,13 @@ are in [references/common-mistakes.md](references/common-mistakes.md).
|
|
|
353
422
|
| CRITICAL | Expecting the grid to write into `data` - without `editing.onCommit` the cell reverts |
|
|
354
423
|
| CRITICAL | `getRowId` built from the row index - drafts follow the index, not the record |
|
|
355
424
|
| HIGH | A cell editor defined inside the component - a new type per render unmounts the editor |
|
|
356
|
-
| HIGH | A
|
|
425
|
+
| HIGH | A custom editor that binds no error text - a refused commit shows no message; bind `field.state.meta.errors` |
|
|
426
|
+
| HIGH | A cross-field rule under `mode: "cell"` - `rowValidators` needs `"row"` |
|
|
357
427
|
| HIGH | An `accessorFn` column with no `meta.edit.field` - it maps to nothing and stays read-only |
|
|
358
428
|
| HIGH | Swallowing the error in `editing.onCommit` - a resolved catch drops the draft |
|
|
359
429
|
| HIGH | Submitting an outer form while the grid holds a draft - it saves stale rows |
|
|
430
|
+
| HIGH | A bulk write built from `begin` + `getForm` + `commit` - `getForm` can be `undefined`; `edit.setCellValue` is the write |
|
|
431
|
+
| MEDIUM | A computed column frozen while a row is edited - `accessorFn` reads `data`; read the draft from `edit.store`'s `rows[rowId].values` |
|
|
360
432
|
| MEDIUM | Reading a commit's result as the saved value - it is a `boolean` about the form |
|
|
361
433
|
| MEDIUM | Expecting `editing.onRowDelete` to fire under draft - the mark waits for `saveDrafts` |
|
|
362
434
|
|