@jielga/tmdatagrid 2.0.0-beta.1 → 2.0.0-beta.2
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 +60 -23
- package/dist/index.js +2020 -1704
- 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 +2 -2
- package/skills/data/SKILL.md +1 -1
- package/skills/editing/SKILL.md +68 -213
- package/skills/editing/references/common-mistakes.md +177 -0
- package/skills/editing/references/editing-api.md +39 -13
- package/skills/editing/references/editors-and-validation.md +5 -2
- package/skills/filtering/SKILL.md +1 -1
- package/skills/getting-started/SKILL.md +1 -1
- package/skills/grouping/SKILL.md +1 -1
- package/skills/options/SKILL.md +2 -2
- package/skills/rows/SKILL.md +1 -1
- package/skills/rows/references/rows-api.md +1 -1
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +3 -2
- package/src/tmdatagrid/components/TMDataGrid.module.css +7 -0
- package/src/tmdatagrid/components/TMDataGridCellEditor.tsx +20 -8
- package/src/tmdatagrid/components/TMDataGridEditActions.tsx +1 -1
- package/src/tmdatagrid/components/TMDataGridEditColumn.tsx +242 -86
- package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +176 -77
- package/src/tmdatagrid/components/TMDataGridTable.module.css +47 -3
- package/src/tmdatagrid/components/TMDataGridTable.tsx +44 -4
- package/src/tmdatagrid/components/icons.ts +1 -0
- package/src/tmdatagrid/core/capabilities.ts +10 -0
- package/src/tmdatagrid/core/draftCellContext.ts +68 -0
- package/src/tmdatagrid/core/editEngine.ts +106 -32
- package/src/tmdatagrid/core/labels.ts +13 -1
- package/src/tmdatagrid/core/labelsSv.ts +4 -0
- package/src/tmdatagrid/index.ts +1 -1
- package/src/tmdatagrid/useTMDataGrid.tsx +39 -20
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
._root_ed4g_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_ed4g_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_ed4g_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_ed4g_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_ed4g_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_ed4g_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-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}}._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}._tableWrapper_15qzd_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._scrollContainer_15qzd_10{flex:1;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_15qzd_21{display:grid}._headerRow_15qzd_27{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._headerRow_15qzd_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_15qzd_27[data-dg-header-last]:after{animation:linear both _dg-header-shadow_15qzd_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dg-header-shadow_15qzd_1{0%{opacity:0}to{opacity:1}}._bodyRow_15qzd_76{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_15qzd_76[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_15qzd_76:hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_15qzd_76[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_15qzd_76[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_15qzd_76[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_15qzd_76[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_15qzd_76[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_15qzd_76:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_15qzd_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_15qzd_143[data-control-column=true]{padding:0}._grid_15qzd_21[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_15qzd_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_15qzd_143[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_15qzd_143[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_15qzd_143[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_15qzd_143[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_15qzd_143[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_15qzd_141{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_15qzd_143[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_15qzd_243{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorActions_15qzd_252{flex:none;align-items:center;display:flex}._bodyCell_15qzd_143[data-dirty],._bodyCell_15qzd_143[data-invalid]{position:relative}._bodyCell_15qzd_143[data-dirty]:after,._bodyCell_15qzd_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_15qzd_143[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_15qzd_143[data-align=right]{justify-content:flex-end}._bodyCell_15qzd_143[data-align=center]{justify-content:center}._bodyCell_15qzd_143[data-align=left] ._cellContent_15qzd_141{flex:auto}._detailsCell_15qzd_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_15qzd_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_15qzd_76[data-deleted=true]{opacity:.55;pointer-events:none;text-decoration:line-through}._entryBlock_15qzd_347{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_15qzd_356{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_15qzd_369{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_15qzd_369>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_15qzd_382{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_15qzd_382>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_15qzd_395{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_15qzd_395[data-control-column=true]{justify-content:center;padding:0}._entryCell_15qzd_395[data-align=right]{justify-content:flex-end}._entryCell_15qzd_395[data-align=center]{justify-content:center}._matchHighlight_15qzd_422{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_15qzd_434{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_15qzd_443{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_15qzd_443[data-control-column=true]{padding:0}._summaryCell_15qzd_443[data-align=right]{justify-content:flex-end}._summaryCell_15qzd_443[data-align=center]{justify-content:center}._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_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}
|
|
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.2",
|
|
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.2'
|
|
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.2'
|
|
20
20
|
sources:
|
|
21
21
|
- 'Jielga/TMDataGrid:src/docs/columns.md'
|
|
22
22
|
- 'Jielga/TMDataGrid:src/docs/column-layout.md'
|
|
@@ -246,7 +246,7 @@ asks for it.
|
|
|
246
246
|
| Checkbox | `SELECT_COLUMN_ID` | Selection is on and the mode has checkboxes |
|
|
247
247
|
| Tree | `GROUP_COLUMN_ID` | A column is grouped |
|
|
248
248
|
| Details | `DETAILS_COLUMN_ID` | `renderDetails` is set |
|
|
249
|
-
| Edit | `EDIT_COLUMN_ID` | Row mode,
|
|
249
|
+
| Edit | `EDIT_COLUMN_ID` | Row mode, draft mode, or `editing.onRowDelete` |
|
|
250
250
|
|
|
251
251
|
They are structural: fixed width, no column menu, and they cannot be sorted,
|
|
252
252
|
filtered, resized, re-pinned or moved. The checkbox lane anchors the left pinned
|
package/skills/data/SKILL.md
CHANGED
package/skills/editing/SKILL.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: editing
|
|
3
3
|
description: >
|
|
4
4
|
Edit cells and rows in TMDataGrid. Covers the editing option with its four
|
|
5
|
-
mode policies (cell, cellConfirm, row,
|
|
6
|
-
editing.onCommit and editing.
|
|
5
|
+
mode policies (cell, cellConfirm, row, draft), the required getRowId,
|
|
6
|
+
editing.onCommit and editing.onCommitDrafts, why the grid never mutates data,
|
|
7
7
|
per-column gating with meta.edit.enabled and meta.edit.field, the six built-in
|
|
8
8
|
editors picked by meta.type, custom editors through meta.edit.editor,
|
|
9
9
|
per-keystroke value mapping with meta.edit.mapValue, field validation with
|
|
@@ -17,7 +17,7 @@ description: >
|
|
|
17
17
|
metadata:
|
|
18
18
|
type: core
|
|
19
19
|
library: '@jielga/tmdatagrid'
|
|
20
|
-
library_version: '2.0.0-beta.
|
|
20
|
+
library_version: '2.0.0-beta.2'
|
|
21
21
|
sources:
|
|
22
22
|
- 'Jielga/TMDataGrid:src/docs/editing.md'
|
|
23
23
|
- 'Jielga/TMDataGrid:src/docs/query-builder.md'
|
|
@@ -69,8 +69,8 @@ const grid = useTMDataGrid({
|
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
Two rules are compile errors, not options that silently do nothing: `editing`
|
|
72
|
-
requires `getRowId`, and `editing.
|
|
73
|
-
`editing.mode: "
|
|
72
|
+
requires `getRowId`, and `editing.onCommitDrafts` exists only under
|
|
73
|
+
`editing.mode: "draft"`. Draft _without_ `onCommitDrafts` is fine: `submitAll`
|
|
74
74
|
falls back to the per-row `editing.onCommit` loop.
|
|
75
75
|
|
|
76
76
|
## The four modes
|
|
@@ -83,16 +83,17 @@ as a commit, and which controls trigger it.
|
|
|
83
83
|
| `"cell"` | Enter, Tab, blur | Escape | none |
|
|
84
84
|
| `"cellConfirm"` | ✓ or Enter; blur keeps the draft | ✕ or Escape | ✓ / ✕ beside the input |
|
|
85
85
|
| `"row"` | Save in the edit lane, or Ctrl+Enter | Cancel, or Escape | generated edit lane |
|
|
86
|
-
| `"
|
|
86
|
+
| `"draft"` | `edit.submitAll()` | `edit.cancelAll()`, or per row in the lane | `TMDataGrid.EditActions` + the edit lane |
|
|
87
87
|
|
|
88
88
|
Which to pick: `"cell"` for saved-as-you-go spreadsheet feel; `"cellConfirm"`
|
|
89
89
|
when a stray click must not fire a request; `"row"` when the row is the unit of
|
|
90
|
-
the save or a rule spans two columns; `"
|
|
90
|
+
the save or a rule spans two columns; `"draft"` for many edits sent as one
|
|
91
91
|
transaction.
|
|
92
92
|
|
|
93
93
|
An editor opens on double-click, or with the cell cursor on the cell: Enter, F2,
|
|
94
94
|
or typing, where the first character replaces the value. Delete or Backspace
|
|
95
|
-
clears the value and commits without opening an editor
|
|
95
|
+
clears the value and commits without opening an editor; under `"draft"` the
|
|
96
|
+
cleared value is held with the other drafts instead. Editing implies cell
|
|
96
97
|
selection: `cellSelection` defaults to `"single"` while `editing` is set. The
|
|
97
98
|
grid places the caret in the cell that was opened, and `edit.addRow()` places it
|
|
98
99
|
in the new row's first editable cell, so a `meta.edit.editor` receives focus
|
|
@@ -103,13 +104,26 @@ the cell clicked, opens every editable cell of the row, and ✓ saves them as on
|
|
|
103
104
|
commit. Rows accumulate: opening a second row leaves the first open, and each
|
|
104
105
|
row's ✓ and ✕ act on that row alone.
|
|
105
106
|
|
|
106
|
-
Under `"
|
|
107
|
-
the draft,
|
|
108
|
-
|
|
109
|
-
`
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
107
|
+
Under `"draft"` nothing reaches a callback until `submitAll`. Enter and Tab hold
|
|
108
|
+
the draft, Tab moving on to the next editable cell, Escape drops that one draft,
|
|
109
|
+
and drafts accumulate across rows, surviving filters, sorts and scrolling.
|
|
110
|
+
`edit.commit(rowId)` validates and holds the draft too, so there is no per-row
|
|
111
|
+
escape hatch to the consumer. A held draft is displayed: the cell renders the
|
|
112
|
+
draft value through the column's own `cell` renderer, with the blue corner
|
|
113
|
+
marking it dirty and `data-dirty` on the row.
|
|
114
|
+
|
|
115
|
+
The edit lane is the change indicator and the per-row undo: an edited row shows
|
|
116
|
+
a pencil icon and Revert, which drops that row's draft; a new row a plus icon, a
|
|
117
|
+
pencil that reopens it, and ✕; a row marked for deletion a trash icon and
|
|
118
|
+
Restore. A row holding a dirty draft hides the trash - revert first, then
|
|
119
|
+
delete. A row blocked by validation turns its icon red with the message in the
|
|
120
|
+
tooltip.
|
|
121
|
+
|
|
122
|
+
`submitAll` then commits every pending change: through the per-row
|
|
123
|
+
`editing.onCommit` / `editing.onRowAdd` / `editing.onRowDelete` loop by default,
|
|
124
|
+
or through one `editing.onCommitDrafts({ rows, added, deleted })` call when that
|
|
125
|
+
is set. Rows failing validation stay open either way, and a rejected save keeps
|
|
126
|
+
every draft.
|
|
113
127
|
|
|
114
128
|
## What a commit receives
|
|
115
129
|
|
|
@@ -169,7 +183,7 @@ import { z } from "zod";
|
|
|
169
183
|
// Field level, on the column. A bare schema means { onChange: schema }.
|
|
170
184
|
meta: { edit: { validate: z.string().min(2, "At least two characters") } }
|
|
171
185
|
|
|
172
|
-
// Form level, inside `editing`. Cross-field rules, under "row" or "
|
|
186
|
+
// Form level, inside `editing`. Cross-field rules, under "row" or "draft".
|
|
173
187
|
rowValidators: {
|
|
174
188
|
onSubmit: z
|
|
175
189
|
.object({ salary: z.number().positive(), status: z.string() })
|
|
@@ -197,8 +211,17 @@ Detail for all three: [references/editors-and-validation.md](references/editors-
|
|
|
197
211
|
|
|
198
212
|
`edit.addRow()` opens an entry row in a sticky block under the header, seeded
|
|
199
213
|
from `editing.newRowDefaults`. Enter, or the lane's ✓, commits the add through
|
|
200
|
-
`editing.onRowAdd` under the immediate modes;
|
|
201
|
-
|
|
214
|
+
`editing.onRowAdd` under the immediate modes; under draft mode it enters the
|
|
215
|
+
row, which is validated, held with the other drafts, and reported in
|
|
216
|
+
`submitAll`'s `added`. Escape, or ✕, discards the entry.
|
|
217
|
+
|
|
218
|
+
Under `"draft"` an entered row renders as a value row with no inputs, marked
|
|
219
|
+
`data-new` and `data-confirmed` and tinted with `--dg-row-new-bg`. By default it
|
|
220
|
+
joins the scrolling flow above the body rows; `editing.newRowsSticky: true`
|
|
221
|
+
keeps entered rows pinned in the entry block until Save all. Double-click, or
|
|
222
|
+
the lane's pencil, reopens it; ✕ removes it. To limit how many entry rows are
|
|
223
|
+
open at once, gate the Add button on
|
|
224
|
+
`useSelector(grid.edit.store, (s) => s.newRows.some((n) => !n.confirmed))`.
|
|
202
225
|
|
|
203
226
|
```tsx
|
|
204
227
|
const grid = useTMDataGrid({
|
|
@@ -206,9 +229,9 @@ const grid = useTMDataGrid({
|
|
|
206
229
|
columns,
|
|
207
230
|
getRowId: (row) => String(row.id),
|
|
208
231
|
editing: {
|
|
209
|
-
mode: "
|
|
232
|
+
mode: "draft",
|
|
210
233
|
newRowDefaults: () => ({ id: 0, firstName: "", salary: 30_000 }),
|
|
211
|
-
|
|
234
|
+
onCommitDrafts: async ({ rows, added, deleted }) => {
|
|
212
235
|
await api.saveBatch({ rows, added, deleted });
|
|
213
236
|
},
|
|
214
237
|
},
|
|
@@ -223,21 +246,23 @@ const grid = useTMDataGrid({
|
|
|
223
246
|
|
|
224
247
|
`edit.deleteRow(rowId)` calls `editing.onRowDelete({ rowId, row })` immediately
|
|
225
248
|
under the immediate modes, so put any confirmation inside that callback. Under
|
|
226
|
-
|
|
227
|
-
(`data-deleted`), the lane
|
|
228
|
-
|
|
229
|
-
|
|
249
|
+
draft mode it toggles a mark instead: the row renders struck through and inert
|
|
250
|
+
(`data-deleted`), the lane shows Restore, and `submitAll` reports the ids in
|
|
251
|
+
`deleted`. You apply adds and deletes, the same as edits. The engine's `tempId`
|
|
252
|
+
(`__new__1`, …) does not need to become a real id.
|
|
230
253
|
|
|
231
254
|
## The built-in controls
|
|
232
255
|
|
|
233
256
|
The generated edit lane (`EDIT_COLUMN_ID`, pinned right) appears when
|
|
234
|
-
`editing.mode` is `"row"`, or `editing.onRowDelete` is set
|
|
235
|
-
|
|
236
|
-
|
|
257
|
+
`editing.mode` is `"row"` or `"draft"`, or when `editing.onRowDelete` is set.
|
|
258
|
+
Nothing else adds it, and `"cell"` mode renders no controls of its own. Under
|
|
259
|
+
`"row"` it holds Save and Cancel while a row is open; under `"draft"` it holds
|
|
260
|
+
the row-state marker with Revert and Restore, and Save and Cancel never appear.
|
|
261
|
+
Every control carries a tooltip from the labels.
|
|
237
262
|
|
|
238
263
|
`TMDataGrid.EditActions` is Save with the pending count plus Discard. It greys
|
|
239
264
|
out while nothing is pending, spins while a submit is in flight, renders nothing
|
|
240
|
-
while editing is off, and works under any mode, not only
|
|
265
|
+
while editing is off, and works under any mode, not only draft.
|
|
241
266
|
|
|
242
267
|
`renderActions` replaces the pair and hands over its pieces:
|
|
243
268
|
|
|
@@ -286,192 +311,20 @@ the form cannot see a draft.
|
|
|
286
311
|
|
|
287
312
|
## Common mistakes
|
|
288
313
|
|
|
289
|
-
|
|
314
|
+
Each one compiles and raises no warning. The reason and the fix for every entry
|
|
315
|
+
are in [references/common-mistakes.md](references/common-mistakes.md).
|
|
290
316
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
});
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
Correct: wire `editing.onCommit` to apply the change where the data lives, as
|
|
306
|
-
in [Setup](#setup).
|
|
307
|
-
|
|
308
|
-
Source: `src/docs/editing.md`, `src/tmdatagrid/core/editEngine.ts`.
|
|
309
|
-
|
|
310
|
-
### CRITICAL `getRowId` built from the row index
|
|
311
|
-
|
|
312
|
-
`getRowId` accepts any string, so an index-based id compiles. Drafts are keyed
|
|
313
|
-
by it, so after a sort or a filter the draft is applied to whichever record now
|
|
314
|
-
sits at that index.
|
|
315
|
-
|
|
316
|
-
Wrong:
|
|
317
|
-
|
|
318
|
-
```tsx
|
|
319
|
-
getRowId: (row, index) => String(index),
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
Correct:
|
|
323
|
-
|
|
324
|
-
```tsx
|
|
325
|
-
getRowId: (row) => String(row.id),
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
Source: `src/tmdatagrid/useTMDataGrid.tsx` (`TMDataGridEditingCallbacks`).
|
|
329
|
-
|
|
330
|
-
### HIGH A cell editor defined inside the component
|
|
331
|
-
|
|
332
|
-
`meta.edit.editor` is rendered as JSX, so its identity is its component type. An
|
|
333
|
-
inline arrow function is a new type on every render, which unmounts the open
|
|
334
|
-
editor and discards what was being typed.
|
|
335
|
-
|
|
336
|
-
Wrong:
|
|
337
|
-
|
|
338
|
-
```tsx
|
|
339
|
-
meta: { edit: { editor: ({ field }) => <Slider value={field.state.value} /> } },
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
Correct:
|
|
343
|
-
|
|
344
|
-
```tsx
|
|
345
|
-
// Module scope, referenced by name.
|
|
346
|
-
const SalaryEditor: TMDataGridEditorComponent = ({ field, commit }) => (
|
|
347
|
-
<Slider
|
|
348
|
-
value={Number(field.state.value ?? 0)}
|
|
349
|
-
onChange={(next) => field.handleChange(next)}
|
|
350
|
-
onChangeEnd={() => void commit()}
|
|
351
|
-
/>
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
meta: { edit: { editor: SalaryEditor } },
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
Source: `src/docs/editors.md`, `src/tmdatagrid/core/editEngine.ts`.
|
|
358
|
-
|
|
359
|
-
### HIGH A cross-field rule under `editing.mode: "cell"`
|
|
360
|
-
|
|
361
|
-
Under `"cell"` each cell commits on its own, so a rule spanning two columns
|
|
362
|
-
cannot be satisfied by either one: the first cell edited is rejected against the
|
|
363
|
-
other column's old value, and the row cannot be saved.
|
|
364
|
-
|
|
365
|
-
Wrong:
|
|
366
|
-
|
|
367
|
-
```tsx
|
|
368
|
-
useTMDataGrid({
|
|
369
|
-
editing: { mode: "cell", rowValidators: { onSubmit: endAfterStart } },
|
|
370
|
-
});
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
Correct:
|
|
374
|
-
|
|
375
|
-
```tsx
|
|
376
|
-
// "row" (or "batch") validates the whole row in one commit.
|
|
377
|
-
useTMDataGrid({
|
|
378
|
-
editing: { mode: "row", rowValidators: { onSubmit: endAfterStart } },
|
|
379
|
-
});
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
Source: `src/docs/editors.md` (Validation).
|
|
383
|
-
|
|
384
|
-
### HIGH An `accessorFn` column that never opens an editor
|
|
385
|
-
|
|
386
|
-
Editability follows the data path, not the column. A column built on an accessor
|
|
387
|
-
function has no `accessorKey`, so it maps to nothing and stays read-only while
|
|
388
|
-
every other column edits. No warning is raised.
|
|
389
|
-
|
|
390
|
-
Wrong:
|
|
391
|
-
|
|
392
|
-
```tsx
|
|
393
|
-
columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
|
|
394
|
-
id: "fullName",
|
|
395
|
-
header: "Full name",
|
|
396
|
-
});
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
Correct:
|
|
400
|
-
|
|
401
|
-
```tsx
|
|
402
|
-
columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
|
|
403
|
-
id: "fullName",
|
|
404
|
-
header: "Full name",
|
|
405
|
-
meta: { label: "Full name", edit: { field: "lastName" } },
|
|
406
|
-
});
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
Source: `src/docs/editing.md` (Which cells edit).
|
|
410
|
-
|
|
411
|
-
### HIGH Swallowing the error in `editing.onCommit`
|
|
412
|
-
|
|
413
|
-
The draft is dropped when `editing.onCommit` resolves. A `try/catch` that logs
|
|
414
|
-
the failure resolves it, so a save that failed on the server clears the editor
|
|
415
|
-
and the grid shows the old value as though nothing happened.
|
|
416
|
-
|
|
417
|
-
Wrong:
|
|
418
|
-
|
|
419
|
-
```tsx
|
|
420
|
-
onCommit: async ({ rowId, changes }) => {
|
|
421
|
-
try {
|
|
422
|
-
await api.patch(rowId, changes);
|
|
423
|
-
} catch (error) {
|
|
424
|
-
console.error(error);
|
|
425
|
-
}
|
|
426
|
-
},
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
Correct: no `catch` - let the rejection propagate, and the form stays open
|
|
430
|
-
with the error on the row.
|
|
431
|
-
|
|
432
|
-
Source: `src/tmdatagrid/useTMDataGrid.tsx` (`TMDataGridEditingCallbacks`).
|
|
433
|
-
|
|
434
|
-
### HIGH Submitting an outer form while the grid holds a draft
|
|
435
|
-
|
|
436
|
-
The outer form's array contains only committed rows. Under any mode a mid-edit
|
|
437
|
-
row is invisible to it, and under `"batch"` every edit is until `submitAll()`,
|
|
438
|
-
so a form submit saves stale rows and collection rules skip pending values.
|
|
439
|
-
|
|
440
|
-
Correct:
|
|
441
|
-
|
|
442
|
-
```tsx
|
|
443
|
-
const hasOpenDraft = useSelector(grid.edit.store, (s) => s.openRowIds.length > 0);
|
|
444
|
-
|
|
445
|
-
<Button type="submit" disabled={!canSubmit || hasOpenDraft}>Save</Button>
|
|
446
|
-
// or flush instead of blocking:
|
|
447
|
-
const flushed = await grid.edit.submitAll();
|
|
448
|
-
if (flushed) await form.handleSubmit();
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
Source: `src/docs/query-builder.md` (Which mode, Submitting).
|
|
452
|
-
|
|
453
|
-
### MEDIUM Reading a commit's result as the saved value
|
|
454
|
-
|
|
455
|
-
`edit.commit(rowId)` and `edit.submitAll()` resolve to a `boolean` saying
|
|
456
|
-
whether the form closed, and resolve `false` when validation or a rejected save
|
|
457
|
-
kept it open. Ignoring the result reports a save that did not happen.
|
|
458
|
-
|
|
459
|
-
```tsx
|
|
460
|
-
const saved = await grid.edit.submitAll();
|
|
461
|
-
notifications.show({ message: saved ? "Saved" : "Some rows need attention" });
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
Source: `src/tmdatagrid/core/editEngine.ts` (`TMDataGridEditApi`).
|
|
465
|
-
|
|
466
|
-
### MEDIUM Expecting `editing.onRowDelete` to fire under batch
|
|
467
|
-
|
|
468
|
-
Under the immediate modes `edit.deleteRow` calls `editing.onRowDelete` at once.
|
|
469
|
-
Under `"batch"` it only toggles a deletion mark, and the ids arrive later in
|
|
470
|
-
`submitAll`'s `deleted`, so a batch grid that deletes through
|
|
471
|
-
`editing.onRowDelete` alone never removes anything. Handle `deleted` in
|
|
472
|
-
`editing.onCommitBatch`.
|
|
473
|
-
|
|
474
|
-
Source: `src/docs/editing.md` (Adding and deleting rows).
|
|
317
|
+
| Severity | Mistake |
|
|
318
|
+
| --- | --- |
|
|
319
|
+
| CRITICAL | Expecting the grid to write into `data` - without `editing.onCommit` the cell reverts |
|
|
320
|
+
| CRITICAL | `getRowId` built from the row index - drafts follow the index, not the record |
|
|
321
|
+
| HIGH | A cell editor defined inside the component - a new type per render unmounts the editor |
|
|
322
|
+
| HIGH | A cross-field rule under `mode: "cell"` - `rowValidators` needs `"row"` or `"draft"` |
|
|
323
|
+
| HIGH | An `accessorFn` column with no `meta.edit.field` - it maps to nothing and stays read-only |
|
|
324
|
+
| HIGH | Swallowing the error in `editing.onCommit` - a resolved catch drops the draft |
|
|
325
|
+
| HIGH | Submitting an outer form while the grid holds a draft - it saves stale rows |
|
|
326
|
+
| MEDIUM | Reading a commit's result as the saved value - it is a `boolean` about the form |
|
|
327
|
+
| MEDIUM | Expecting `editing.onRowDelete` to fire under draft - the mark waits for `submitAll` |
|
|
475
328
|
|
|
476
329
|
## References
|
|
477
330
|
|
|
@@ -480,6 +333,8 @@ Source: `src/docs/editing.md` (Adding and deleting rows).
|
|
|
480
333
|
validators, server-side errors.
|
|
481
334
|
- [Editing API](references/editing-api.md) - every option, callback, column meta
|
|
482
335
|
field, export, CSS variable and data attribute belonging to editing.
|
|
336
|
+
- [Common mistakes](references/common-mistakes.md) - the failure modes above,
|
|
337
|
+
each with its wrong and correct form.
|
|
483
338
|
|
|
484
339
|
See also: the `columns` skill for `meta.type` and the shared `meta.options`
|
|
485
340
|
source, and the `testing` skill for driving editors from a test.
|