@jielga/tmdatagrid 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/index.d.ts +225 -225
- package/dist/index.js +58 -50
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -2
- package/skills/columns/SKILL.md +4 -4
- package/skills/features/SKILL.md +30 -30
- package/skills/getting-started/SKILL.md +16 -16
- package/skills/options/SKILL.md +8 -8
- package/skills/server-side/SKILL.md +7 -7
- package/skills/testing/SKILL.md +12 -12
- package/src/tmdatagrid/TMDataGridContext.ts +2 -2
- package/src/tmdatagrid/components/TMDataGrid.module.css +2 -2
- package/src/tmdatagrid/components/TMDataGrid.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridCellEditor.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridColumnsPanel.tsx +2 -2
- package/src/tmdatagrid/components/TMDataGridDetailsColumn.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridEditActions.tsx +2 -2
- package/src/tmdatagrid/components/TMDataGridEditColumn.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridEntryRows.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridFilterPanel.tsx +6 -6
- package/src/tmdatagrid/components/TMDataGridFilterPills.module.css +2 -2
- package/src/tmdatagrid/components/TMDataGridFilterPills.tsx +1 -1
- package/src/tmdatagrid/components/TMDataGridFooter.module.css +1 -1
- package/src/tmdatagrid/components/TMDataGridFooter.tsx +12 -6
- package/src/tmdatagrid/components/TMDataGridGroupColumn.module.css +1 -1
- package/src/tmdatagrid/components/TMDataGridGroupColumn.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridHeaderCell.module.css +8 -8
- package/src/tmdatagrid/components/TMDataGridHeaderCell.tsx +12 -12
- package/src/tmdatagrid/components/TMDataGridRowNumberColumn.tsx +4 -4
- package/src/tmdatagrid/components/TMDataGridSearch.tsx +5 -5
- package/src/tmdatagrid/components/TMDataGridSelectColumn.tsx +8 -8
- package/src/tmdatagrid/components/TMDataGridTable.module.css +18 -18
- package/src/tmdatagrid/components/TMDataGridTable.tsx +116 -116
- package/src/tmdatagrid/components/TMDataGridToolbar.tsx +5 -5
- package/src/tmdatagrid/components/editors/TMDataGridBooleanEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridDateEditor.tsx +2 -2
- package/src/tmdatagrid/components/editors/TMDataGridMultiSelectEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridNumberEditor.tsx +1 -1
- package/src/tmdatagrid/components/editors/TMDataGridSelectEditor.tsx +2 -2
- package/src/tmdatagrid/components/editors/editorShared.ts +3 -3
- package/src/tmdatagrid/components/filters/DgDateRangeFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/DgRangeSliderFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/DgTriStateFilter.tsx +1 -1
- package/src/tmdatagrid/components/filters/TMDataGridFilterValueInput.tsx +2 -2
- package/src/tmdatagrid/components/sticky.module.css +8 -8
- package/src/tmdatagrid/core/autosize.ts +4 -4
- package/src/tmdatagrid/core/capabilities.ts +17 -17
- package/src/tmdatagrid/core/cellExport.ts +13 -13
- package/src/tmdatagrid/core/cellNavigation.ts +6 -6
- package/src/tmdatagrid/core/cellRange.ts +4 -4
- package/src/tmdatagrid/core/columnOptions.ts +2 -2
- package/src/tmdatagrid/core/columnOrdering.ts +2 -2
- package/src/tmdatagrid/core/columnUtils.ts +3 -3
- package/src/tmdatagrid/core/editEngine.ts +49 -49
- package/src/tmdatagrid/core/expanding.ts +5 -5
- package/src/tmdatagrid/core/filterControls.ts +5 -5
- package/src/tmdatagrid/core/filterOperators.ts +14 -14
- package/src/tmdatagrid/core/labels.ts +8 -8
- package/src/tmdatagrid/core/matchHighlight.ts +4 -4
- package/src/tmdatagrid/core/persistence.ts +8 -8
- package/src/tmdatagrid/core/quickSearch.ts +8 -8
- package/src/tmdatagrid/core/rowPinning.ts +3 -3
- package/src/tmdatagrid/core/rowSelection.ts +12 -12
- package/src/tmdatagrid/core/sizes.ts +1 -1
- package/src/tmdatagrid/core/summary.ts +3 -3
- package/src/tmdatagrid/useTMDataGrid.tsx +79 -79
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
._root_nuit2_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_nuit2_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_nuit2_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_nuit2_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_nuit2_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_nuit2_8{--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(--mantine-radius-md);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_h06xv_4{width:100%;min-width:0;font-size:var(--dg-font-size);color:inherit;align-items:center;gap:6px;display:flex}._chevron_h06xv_14{color:var(--mantine-color-dimmed);flex:none;align-items:center;transition:transform .12s;display:flex}._chevron_h06xv_14[data-expanded=true]{transform:rotate(90deg)}@media (prefers-reduced-motion:reduce){._chevron_h06xv_14{transition:none}}._groupLabel_h06xv_34{white-space:nowrap;text-overflow:ellipsis;min-width:0;font-weight:600;overflow:hidden}._groupCount_h06xv_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_1yybb_3{align-items:center;gap:var(--mantine-spacing-xs);flex-wrap:wrap;display:flex}._filterPills_1yybb_3 ._pill_1yybb_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_1yybb_27{font:inherit;color:inherit;cursor:pointer}._pillLabel_1yybb_27:hover{text-decoration:underline}._footer_149ca_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_149ca_1[data-paging-suspended=true]{opacity:.55}._tableWrapper_18r3a_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._scrollContainer_18r3a_10{flex:1;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_18r3a_21{display:grid}._headerRow_18r3a_27{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._headerRow_18r3a_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_18r3a_27[data-dg-header-last]:after{animation:linear both _dg-header-shadow_18r3a_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dg-header-shadow_18r3a_1{0%{opacity:0}to{opacity:1}}._bodyRow_18r3a_76{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_18r3a_76[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_18r3a_76:hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_18r3a_76[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_18r3a_76[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_18r3a_76[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_18r3a_76[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_18r3a_76[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_18r3a_76:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_18r3a_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_18r3a_143[data-control-column=true]{padding:0}._grid_18r3a_21[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_18r3a_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_18r3a_143[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_18r3a_143[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_18r3a_143[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_18r3a_143[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_18r3a_143[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_18r3a_141{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_18r3a_143[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_18r3a_243{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorActions_18r3a_252{flex:none;align-items:center;display:flex}._bodyCell_18r3a_143[data-dirty],._bodyCell_18r3a_143[data-invalid]{position:relative}._bodyCell_18r3a_143[data-dirty]:after,._bodyCell_18r3a_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_18r3a_143[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_18r3a_143[data-align=right]{justify-content:flex-end}._bodyCell_18r3a_143[data-align=center]{justify-content:center}._bodyCell_18r3a_143[data-align=left] ._cellContent_18r3a_141{flex:auto}._detailsCell_18r3a_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_18r3a_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_18r3a_76[data-deleted=true]{opacity:.55;pointer-events:none;text-decoration:line-through}._entryBlock_18r3a_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_18r3a_356{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_18r3a_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_18r3a_369>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_18r3a_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_18r3a_382>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_18r3a_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_18r3a_395[data-control-column=true]{justify-content:center;padding:0}._entryCell_18r3a_395[data-align=right]{justify-content:flex-end}._entryCell_18r3a_395[data-align=center]{justify-content:center}._matchHighlight_18r3a_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_18r3a_434{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_18r3a_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_18r3a_443[data-control-column=true]{padding:0}._summaryCell_18r3a_443[data-align=right]{justify-content:flex-end}._summaryCell_18r3a_443[data-align=center]{justify-content:center}._stickyLeft_6z1iq_16:after,._stickyRight_6z1iq_17:after{content:"";pointer-events:none;width:8px;position:absolute;top:0;bottom:0}._stickyLeft_6z1iq_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_6z1iq_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_6z1iq_16:after,._stickyRight_6z1iq_17:after{--dg-sticky-edge-range:20px;opacity:0;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(inline)}._stickyLeft_6z1iq_16:after{animation-name:_stickyEdgeIn_6z1iq_1;animation-range:0 var(--dg-sticky-edge-range)}._stickyRight_6z1iq_17:after{animation-name:_stickyEdgeOut_6z1iq_1;animation-range:calc(100% - var(--dg-sticky-edge-range)) 100%}}@keyframes _stickyEdgeIn_6z1iq_1{0%{opacity:0}to{opacity:1}}@keyframes _stickyEdgeOut_6z1iq_1{0%{opacity:1}to{opacity:0}}._headerCell_ikfbg_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_ikfbg_1[data-align=right]{justify-content:flex-end}._headerCell_ikfbg_1[data-align=center]{justify-content:center}._headerCell_ikfbg_1[data-control-column=true]{padding:0}._headerCellFiltered_ikfbg_35 ._headerTitle_ikfbg_35{color:var(--mantine-primary-color-filled)}._headerTitle_ikfbg_35{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}._headerCell_ikfbg_1[data-align=right] ._headerTitle_ikfbg_35{text-align:right}._headerCell_ikfbg_1[data-align=center] ._headerTitle_ikfbg_35{justify-content:center;display:flex}._headerActions_ikfbg_58{flex-shrink:0;align-items:center;gap:0;margin-left:auto;display:flex}._headerCell_ikfbg_1[data-align=right] ._headerActions_ikfbg_58{order:-1;margin-left:0;margin-right:auto}._headerAction_ikfbg_58{display:none}._headerCell_ikfbg_1:hover ._headerAction_ikfbg_58,._headerCell_ikfbg_1:focus-within ._headerAction_ikfbg_58,._headerAction_ikfbg_58[data-pinned-visible=true]{display:flex}._headerCellSortable_ikfbg_87{cursor:pointer}._sortAction_ikfbg_93[data-sorted=false]{opacity:.55}._sortAction_ikfbg_93[data-sorted=false]:hover{opacity:1}._sortIndex_ikfbg_103{color:var(--mantine-color-dimmed);text-align:center;min-width:10px;font-size:10px;font-weight:600;line-height:1}._headerCellDragging_ikfbg_115{opacity:.4}._headerCellDropBefore_ikfbg_119:before,._headerCellDropAfter_ikfbg_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_ikfbg_119:before{left:0}._headerCellDropAfter_ikfbg_120:before{right:0}._columnSeparator_ikfbg_140{z-index:1;justify-content:center;width:10px;height:50%;display:flex;position:absolute;top:25%;right:0;transform:translate(50%)}._columnSeparatorResizable_ikfbg_152{cursor:col-resize;touch-action:none}._columnSeparator_ikfbg_140:after{content:"";background-color:#0000;width:1px;height:100%;transition:background-color .12s,width .12s}._headerCell_ikfbg_1:hover ._columnSeparator_ikfbg_140:after,._headerCell_ikfbg_1:focus-within ._columnSeparator_ikfbg_140:after{background-color:var(--mantine-color-default-border)}._columnSeparatorResizable_ikfbg_152:hover:after,._columnSeparatorActive_ikfbg_175:after{background-color:var(--mantine-primary-color-filled);width:2px}._menuItemActive_ikfbg_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_1e2oi_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_1e2oi_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_1e2oi_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_1e2oi_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_1e2oi_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_1e2oi_8{--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(--mantine-radius-md);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}
|
|
2
2
|
/*$vite$:1*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jielga/tmdatagrid",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A React data grid built on TanStack Table v9 and Mantine
|
|
3
|
+
"version": "1.0.1",
|
|
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",
|
|
7
7
|
"sideEffects": [
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"build": "tsc -b && vite build",
|
|
61
61
|
"build:lib": "vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json && rolldown -c rolldown.dts.config.mjs",
|
|
62
62
|
"lint": "oxlint",
|
|
63
|
+
"check:style": "node scripts/check-house-style.mjs",
|
|
63
64
|
"test": "vitest run",
|
|
64
65
|
"test:watch": "vitest",
|
|
65
66
|
"preview": "vite preview",
|
package/skills/columns/SKILL.md
CHANGED
|
@@ -11,14 +11,14 @@ description: >
|
|
|
11
11
|
metadata:
|
|
12
12
|
type: core
|
|
13
13
|
library: '@jielga/tmdatagrid'
|
|
14
|
-
library_version: '1.0.
|
|
14
|
+
library_version: '1.0.1'
|
|
15
15
|
sources:
|
|
16
16
|
- 'Jielga/TMDataGrid:src/docs/columns.md'
|
|
17
17
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/filterOperators.ts'
|
|
18
18
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/columnUtils.ts'
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
# TMDataGrid
|
|
21
|
+
# TMDataGrid - Columns
|
|
22
22
|
|
|
23
23
|
`createTMDataGridColumnHelper<TData>()` returns a TanStack column helper bound to
|
|
24
24
|
the grid feature set, which gives `meta` and `filterFn` their correct types.
|
|
@@ -160,7 +160,7 @@ When `header` is a component there is no string to fall back to, so the column
|
|
|
160
160
|
manager and column menus show the raw id (`"fullName"`) instead of a name.
|
|
161
161
|
|
|
162
162
|
```tsx
|
|
163
|
-
// Wrong
|
|
163
|
+
// Wrong - menus show "fullName".
|
|
164
164
|
columnHelper.accessor("fullName", { header: () => <Icon /> });
|
|
165
165
|
|
|
166
166
|
// Right.
|
|
@@ -185,7 +185,7 @@ const active = columnFilters.filter((filter) => isFilterActive(filter.value));
|
|
|
185
185
|
### Numeric operators on a column without meta.type
|
|
186
186
|
|
|
187
187
|
`getColumnType(column)` defaults to `"string"`, so a numeric column that omits
|
|
188
|
-
`meta: { type: "number" }` offers only the string operators
|
|
188
|
+
`meta: { type: "number" }` offers only the string operators - `greaterThan` and
|
|
189
189
|
the other comparisons never appear in the panel, and comparisons run as text.
|
|
190
190
|
|
|
191
191
|
### Setting size to control width
|
package/skills/features/SKILL.md
CHANGED
|
@@ -18,14 +18,14 @@ description: >
|
|
|
18
18
|
metadata:
|
|
19
19
|
type: core
|
|
20
20
|
library: '@jielga/tmdatagrid'
|
|
21
|
-
library_version: '1.0.
|
|
21
|
+
library_version: '1.0.1'
|
|
22
22
|
sources:
|
|
23
23
|
- 'Jielga/TMDataGrid:src/docs/features.md'
|
|
24
24
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/capabilities.ts'
|
|
25
25
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/columnOrdering.ts'
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
# TMDataGrid
|
|
28
|
+
# TMDataGrid - Features and capabilities
|
|
29
29
|
|
|
30
30
|
Almost every control is bound to the TanStack capability check for that feature,
|
|
31
31
|
so setting the standard table or column option removes the corresponding
|
|
@@ -51,7 +51,7 @@ like the options around it; pagination is the one switch that defaults to off.
|
|
|
51
51
|
| `enableColumnOrdering: false` | Table | Header dragging and the move menu items |
|
|
52
52
|
| `meta.enableOrdering: false` | Column | That column's header dragging and move menu items |
|
|
53
53
|
| `enableRowSelection: false` | Table | The checkbox column |
|
|
54
|
-
| `rowSelectionMode: "row"` | Table | The checkbox column
|
|
54
|
+
| `rowSelectionMode: "row"` | Table | The checkbox column - the row itself selects instead. See Row selection |
|
|
55
55
|
| `highlightSelectedRows: false` | Table | The highlight background on selected rows. Follows the selection mode by default |
|
|
56
56
|
| `enablePagination: true` | Table | Opt-in: adds paging and the `Footer` pager. Off by default |
|
|
57
57
|
|
|
@@ -73,10 +73,10 @@ const grid = useTMDataGrid({
|
|
|
73
73
|
## Row selection
|
|
74
74
|
|
|
75
75
|
On by default, in two modes. Both write to the same `rowSelection` state, so
|
|
76
|
-
everything downstream
|
|
77
|
-
|
|
76
|
+
everything downstream (the toolbar count, `getSelectedRowModel()`, persistence)
|
|
77
|
+
is unaffected by the choice.
|
|
78
78
|
|
|
79
|
-
**Checkbox**
|
|
79
|
+
**Checkbox** - the default. A checkbox column is added as the first column, with
|
|
80
80
|
a select-all box in its header. Clicking a row elsewhere does not select it, and
|
|
81
81
|
a selected row is not highlighted: the checkbox already says so.
|
|
82
82
|
|
|
@@ -84,8 +84,8 @@ a selected row is not highlighted: the checkbox already says so.
|
|
|
84
84
|
const grid = useTMDataGrid({ data, columns });
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
**Row**
|
|
88
|
-
highlight background
|
|
87
|
+
**Row** - no checkbox column. Clicking a row toggles it, and the row takes the
|
|
88
|
+
highlight background - the only feedback a click gives. Other rows keep their
|
|
89
89
|
state, so a click never clears the rest of the selection. Rows are focusable in
|
|
90
90
|
this mode and Space or Enter toggles the focused row.
|
|
91
91
|
|
|
@@ -94,11 +94,11 @@ const grid = useTMDataGrid({ data, columns, rowSelectionMode: "row" });
|
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
`enableRowSelection: false` removes both, and `rowSelectionMode` is then
|
|
97
|
-
ignored. `TMDataGrid.Table`'s `onRowClick` still fires in either mode
|
|
97
|
+
ignored. `TMDataGrid.Table`'s `onRowClick` still fires in either mode - under
|
|
98
98
|
`"row"` it runs in addition to the selection, not instead of it.
|
|
99
99
|
|
|
100
|
-
`highlightSelectedRows` follows the mode
|
|
101
|
-
`"checkbox"`
|
|
100
|
+
`highlightSelectedRows` follows the mode - on for `"row"`, off for
|
|
101
|
+
`"checkbox"` - and can be set to override either way. The colour is the
|
|
102
102
|
`--dg-row-selected-bg` CSS variable (default `--mantine-primary-color-light`);
|
|
103
103
|
change it on the grid element without touching the flag:
|
|
104
104
|
|
|
@@ -121,13 +121,13 @@ Off by default: the grid renders every filtered and sorted row and relies on
|
|
|
121
121
|
virtualization. Three modes:
|
|
122
122
|
|
|
123
123
|
```tsx
|
|
124
|
-
// No pagination (default)
|
|
124
|
+
// No pagination (default) - TMDataGrid.Footer renders nothing.
|
|
125
125
|
const grid = useTMDataGrid({ data, columns });
|
|
126
126
|
|
|
127
|
-
// Client pagination
|
|
127
|
+
// Client pagination - pages locally, Footer renders its pager.
|
|
128
128
|
const grid = useTMDataGrid({ data, columns, enablePagination: true });
|
|
129
129
|
|
|
130
|
-
// Manual pagination
|
|
130
|
+
// Manual pagination - manualPagination implies enablePagination.
|
|
131
131
|
const grid = useTMDataGrid({
|
|
132
132
|
data: page.rows,
|
|
133
133
|
columns,
|
|
@@ -215,8 +215,8 @@ grid into left, centre and right, then `columnOrder` sequences the centre while
|
|
|
215
215
|
`columnPinning.left` / `.right` sequence the pinned lanes. Unpin first to move a
|
|
216
216
|
column out of a pinned region.
|
|
217
217
|
|
|
218
|
-
Ordering writes `columnOrder` as the complete leaf order
|
|
219
|
-
columns included
|
|
218
|
+
Ordering writes `columnOrder` as the complete leaf order - hidden and pinned
|
|
219
|
+
columns included - so a column keeps its position when it is later shown or
|
|
220
220
|
unpinned; moving a pinned column also rewrites its `columnPinning` array. Both
|
|
221
221
|
slices are covered by `settingsKey`.
|
|
222
222
|
|
|
@@ -236,7 +236,7 @@ import {
|
|
|
236
236
|
moveColumn({ table, columnId: "salary", targetId: "age", side: "before" });
|
|
237
237
|
moveColumnByStep({ table, columnId: "salary", direction: 1 });
|
|
238
238
|
|
|
239
|
-
// null at the edge of a region
|
|
239
|
+
// null at the edge of a region - what the move menu items disable themselves on.
|
|
240
240
|
const next = getStepTargetColumn({ table, columnId: "salary", direction: 1 });
|
|
241
241
|
```
|
|
242
242
|
|
|
@@ -269,11 +269,11 @@ carry `data-focused` / `data-selected` / `data-edge-*`.
|
|
|
269
269
|
The body is one tab stop: controls inside body cells take `tabindex="-1"` while
|
|
270
270
|
cell selection is on, so Tab leaves the grid instead of walking one control per
|
|
271
271
|
mounted row. Enter/F2 steps in, Escape steps out, Space ticks the row from any
|
|
272
|
-
cell. Custom cell controls should do the same
|
|
272
|
+
cell. Custom cell controls should do the same -
|
|
273
273
|
`tabIndex={useCellControlTabIndex()}`. Header controls are untouched.
|
|
274
274
|
|
|
275
|
-
The generated lanes (checkbox, tree, details) are selectable and navigable
|
|
276
|
-
they take the tint and the outline
|
|
275
|
+
The generated lanes (checkbox, tree, details) are selectable and navigable -
|
|
276
|
+
they take the tint and the outline - but never exported; a block covering only
|
|
277
277
|
those disables Copy and Export.
|
|
278
278
|
|
|
279
279
|
Drag across cells to select a rectangle; Shift+click extends one. The state is
|
|
@@ -284,8 +284,8 @@ Move them with `ui.actions.setFocusedCell` / `setCellRange`, follow them with
|
|
|
284
284
|
|
|
285
285
|
Right-clicking inside the selection offers Copy, "Export as CSV for Excel" and
|
|
286
286
|
an Include headers toggle; a consumer's `rowContextMenu` items follow a divider.
|
|
287
|
-
The CSV is Nordic-Excel shaped
|
|
288
|
-
decimal comma
|
|
287
|
+
The CSV is Nordic-Excel shaped - `sep=;` line, UTF-8 BOM, CRLF, semicolons,
|
|
288
|
+
decimal comma - and `cellExport` on `TMDataGrid.Table` changes any of that.
|
|
289
289
|
Generated lanes (checkbox, tree, details) are never exported, and what is
|
|
290
290
|
written is the cell's value rather than what it renders.
|
|
291
291
|
|
|
@@ -295,7 +295,7 @@ Always enabled. Only rows within the viewport, plus a small overscan, are
|
|
|
295
295
|
mounted, so page size does not affect how much is rendered.
|
|
296
296
|
|
|
297
297
|
`overscan` on `useTMDataGrid` (default `6`) sets how many rows are kept mounted
|
|
298
|
-
on each side of the viewport
|
|
298
|
+
on each side of the viewport - the one configurable part.
|
|
299
299
|
|
|
300
300
|
Row height comes from `meta.rowHeight`, or from the `size` prop when unset. Rows
|
|
301
301
|
are fixed height; an accurate value keeps scrolling precise.
|
|
@@ -305,12 +305,12 @@ are fixed height; an accurate value keeps scrolling precise.
|
|
|
305
305
|
### Calling getCanX() in a custom component
|
|
306
306
|
|
|
307
307
|
```tsx
|
|
308
|
-
// Wrong
|
|
308
|
+
// Wrong - memoized under the React Compiler, so the button
|
|
309
309
|
// never reappears when enableColumnFilters flips back to true.
|
|
310
310
|
const { table } = useTMDataGridContext();
|
|
311
311
|
if (!table.getAllLeafColumns().some((c) => c.getCanFilter())) return null;
|
|
312
312
|
|
|
313
|
-
// Right
|
|
313
|
+
// Right - features is a value that changes.
|
|
314
314
|
const { table, features } = useTMDataGridContext();
|
|
315
315
|
const { canFilterAny } = getGridCapabilities(table, features);
|
|
316
316
|
if (!canFilterAny) return null;
|
|
@@ -325,28 +325,28 @@ overlap or leave gaps as you scroll. Set `meta.rowHeight` instead.
|
|
|
325
325
|
### Reordering a pinned column through columnOrder
|
|
326
326
|
|
|
327
327
|
```tsx
|
|
328
|
-
// Wrong
|
|
328
|
+
// Wrong - the left and right regions are sequenced by columnPinning,
|
|
329
329
|
// so this moves nothing on screen.
|
|
330
330
|
table.setColumnOrder(["__select__", "department", "id", …]);
|
|
331
331
|
|
|
332
|
-
// Right
|
|
332
|
+
// Right - moveColumn writes whichever slice the column's region uses.
|
|
333
333
|
moveColumn({ table, columnId: "department", targetId: "id", side: "before" });
|
|
334
334
|
```
|
|
335
335
|
|
|
336
336
|
### Rendering the Footer without enabling pagination
|
|
337
337
|
|
|
338
338
|
```tsx
|
|
339
|
-
// Wrong
|
|
339
|
+
// Wrong - pagination defaults to off, so the Footer renders nothing.
|
|
340
340
|
const grid = useTMDataGrid({ data, columns });
|
|
341
341
|
<TMDataGrid.Footer />
|
|
342
342
|
|
|
343
|
-
// Right
|
|
343
|
+
// Right - opt in (manualPagination: true also counts).
|
|
344
344
|
const grid = useTMDataGrid({ data, columns, enablePagination: true });
|
|
345
345
|
<TMDataGrid.Footer />
|
|
346
346
|
```
|
|
347
347
|
|
|
348
348
|
### Expecting a table-level flag to override a column
|
|
349
349
|
|
|
350
|
-
Table and column options compose
|
|
350
|
+
Table and column options compose - the table flag gates the feature, and the
|
|
351
351
|
column flag narrows it further. `enableSorting: true` on a column does not
|
|
352
352
|
re-enable sorting for a table that set `enableSorting: false`.
|
|
@@ -10,7 +10,7 @@ description: >
|
|
|
10
10
|
metadata:
|
|
11
11
|
type: core
|
|
12
12
|
library: '@jielga/tmdatagrid'
|
|
13
|
-
library_version: '1.0.
|
|
13
|
+
library_version: '1.0.1'
|
|
14
14
|
sources:
|
|
15
15
|
- 'Jielga/TMDataGrid:src/docs/getting-started.md'
|
|
16
16
|
- 'Jielga/TMDataGrid:src/docs/components.md'
|
|
@@ -18,12 +18,12 @@ sources:
|
|
|
18
18
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/sizes.ts'
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
# TMDataGrid
|
|
21
|
+
# TMDataGrid - Getting started
|
|
22
22
|
|
|
23
23
|
`useTMDataGrid` creates the table, `TMDataGrid` provides it through context, and
|
|
24
24
|
the parts rendered inside read what they need from that context. Only the parts
|
|
25
25
|
you render exist, and only the features you enable have state: pagination is
|
|
26
|
-
opt-in via `enablePagination`
|
|
26
|
+
opt-in via `enablePagination` - by default every row renders, virtualized.
|
|
27
27
|
|
|
28
28
|
## Install
|
|
29
29
|
|
|
@@ -107,7 +107,7 @@ Spread the hook result (`{...grid}`) rather than assigning `table`, `ui` and
|
|
|
107
107
|
| Pagination | Off by default: all rows render, virtualized. Opt in with `enablePagination: true`. |
|
|
108
108
|
| Sizing | `size="xs"` to `size="xl"` scales rows, type and controls. |
|
|
109
109
|
|
|
110
|
-
Each is bound to a capability check
|
|
110
|
+
Each is bound to a capability check - disabling the standard table or column
|
|
111
111
|
option also removes its interface. Column ordering (`enableColumnOrdering`) and
|
|
112
112
|
pagination (`enablePagination`) are the two switches the grid defines itself.
|
|
113
113
|
See the `features` skill.
|
|
@@ -125,7 +125,7 @@ takes a fixed pixel width once resized or pinned.
|
|
|
125
125
|
|
|
126
126
|
All read the grid from context and must be rendered inside `TMDataGrid`, except
|
|
127
127
|
`TMDataGrid.FilterPills`, which takes the grid as an `api` prop and can live
|
|
128
|
-
anywhere on the page. Order and presence are up to you
|
|
128
|
+
anywhere on the page. Order and presence are up to you - the root is a plain
|
|
129
129
|
flex column.
|
|
130
130
|
|
|
131
131
|
| Component | Props | Notes |
|
|
@@ -134,12 +134,12 @@ flex column.
|
|
|
134
134
|
| `TMDataGrid.Table` | `onRowClick(row)`, `rowContextMenu` render prop, `rowContextMenuProps` | Header, virtualized body, filter panel. `onRowClick` runs in addition to selection under `rowSelectionMode: "row"`. |
|
|
135
135
|
| `TMDataGrid.Footer` | `pageSizeOptions` (default `[10, 25, 50, 100]`), `pagination` render prop | Pagination controls. Renders nothing unless pagination is enabled. |
|
|
136
136
|
| `TMDataGrid.Toolbar` | `children` | Flex row above the grid. |
|
|
137
|
-
| `TMDataGrid.Spacer` |
|
|
137
|
+
| `TMDataGrid.Spacer` | - | Pushes later toolbar items right. |
|
|
138
138
|
| `TMDataGrid.SummaryCount` | `children` | Visible rows out of total. |
|
|
139
|
-
| `TMDataGrid.FilterButton` |
|
|
140
|
-
| `TMDataGrid.ColumnsButton` |
|
|
141
|
-
| `TMDataGrid.FilterPanel` |
|
|
142
|
-
| `TMDataGrid.ColumnsPanel` |
|
|
139
|
+
| `TMDataGrid.FilterButton` | - | Toggles filter panel. Renders nothing if no column is filterable. |
|
|
140
|
+
| `TMDataGrid.ColumnsButton` | - | Opens column manager. Renders nothing if no column is hideable. |
|
|
141
|
+
| `TMDataGrid.FilterPanel` | - | Rendered by `.Table`; exported for custom layouts. Header close button, Escape, click-away, "Add filter" and "Clear all". |
|
|
142
|
+
| `TMDataGrid.ColumnsPanel` | - | Rendered by `.ColumnsButton`; exported for custom layouts. |
|
|
143
143
|
| `TMDataGrid.FilterPills` | `api`, `size` (default `"sm"`), `showClearAll` (default `true`), `onPillClick(columnId)`, `className` | One pill per active filter, ✕ to clear it. Takes the api as a prop, so it can be rendered outside the grid. Also exported as `TMDataGridFilterPills`. |
|
|
144
144
|
|
|
145
145
|
Pass the row type so `onRowClick` stays typed:
|
|
@@ -149,8 +149,8 @@ Pass the row type so `onRowClick` stays typed:
|
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
`rowContextMenu` fills the dropdown of a Mantine `Menu` the grid opens at the
|
|
152
|
-
pointer on a right-click (or a long press). The grid owns the `Menu`
|
|
153
|
-
positioning, and closing on Escape, outside click, body scroll or an item pick
|
|
152
|
+
pointer on a right-click (or a long press). The grid owns the `Menu` - opening,
|
|
153
|
+
positioning, and closing on Escape, outside click, body scroll or an item pick -
|
|
154
154
|
so the render prop only says what goes in it:
|
|
155
155
|
|
|
156
156
|
```tsx
|
|
@@ -174,7 +174,7 @@ so the render prop only says what goes in it:
|
|
|
174
174
|
`cell` is the one that was right-clicked, `table` is there for actions that read
|
|
175
175
|
the selection, and `close` is for dropdown content that is not a `Menu.Item`
|
|
176
176
|
(those close themselves). Return `null` to leave a row without a menu. It is
|
|
177
|
-
called during render, and only for the open row, so it must stay pure
|
|
177
|
+
called during render, and only for the open row, so it must stay pure - put the
|
|
178
178
|
work in the item handlers. Right-clicking does not change the selection or the
|
|
179
179
|
highlight; the row carries `data-context-menu` while its menu is open. Pass
|
|
180
180
|
`rowContextMenuProps` for `width`, `shadow`, `position` and the rest.
|
|
@@ -241,7 +241,7 @@ A new array on every render rebuilds the table's column model. Define `columns`
|
|
|
241
241
|
at module scope; keep `data` stable with `useMemo`.
|
|
242
242
|
|
|
243
243
|
```tsx
|
|
244
|
-
// Wrong
|
|
244
|
+
// Wrong - rebuilds the column model every render.
|
|
245
245
|
export function Employees({ data }: { data: Employee[] }) {
|
|
246
246
|
const columns = columnHelper.columns([...]);
|
|
247
247
|
const grid = useTMDataGrid({ data, columns });
|
|
@@ -251,7 +251,7 @@ export function Employees({ data }: { data: Employee[] }) {
|
|
|
251
251
|
### Root with no bounded height
|
|
252
252
|
|
|
253
253
|
The root is `overflow: hidden`. Without `flex: 1; minHeight: 0` in a flex parent
|
|
254
|
-
or an explicit height, the table area collapses and no rows are visible
|
|
254
|
+
or an explicit height, the table area collapses and no rows are visible - there
|
|
255
255
|
is no error.
|
|
256
256
|
|
|
257
257
|
### Assigning the hook result field by field
|
|
@@ -261,7 +261,7 @@ and feature toggles stop being reactive. Spread instead: `<TMDataGrid {...grid}>
|
|
|
261
261
|
|
|
262
262
|
### Expecting Footer to enable pagination
|
|
263
263
|
|
|
264
|
-
Rendering `TMDataGrid.Footer` does not switch pagination on
|
|
264
|
+
Rendering `TMDataGrid.Footer` does not switch pagination on - the option does.
|
|
265
265
|
With pagination off (the default) the Footer renders nothing and every row is
|
|
266
266
|
rendered, virtualized. Set `enablePagination: true` (or `manualPagination:
|
|
267
267
|
true` for server paging) to page the data and show the pager.
|
package/skills/options/SKILL.md
CHANGED
|
@@ -13,14 +13,14 @@ description: >
|
|
|
13
13
|
metadata:
|
|
14
14
|
type: core
|
|
15
15
|
library: '@jielga/tmdatagrid'
|
|
16
|
-
library_version: '1.0.
|
|
16
|
+
library_version: '1.0.1'
|
|
17
17
|
sources:
|
|
18
18
|
- 'Jielga/TMDataGrid:src/docs/use-tm-data-grid.md'
|
|
19
19
|
- 'Jielga/TMDataGrid:src/tmdatagrid/useTMDataGrid.tsx'
|
|
20
20
|
- 'Jielga/TMDataGrid:src/tmdatagrid/core/persistence.ts'
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
# TMDataGrid
|
|
23
|
+
# TMDataGrid - useTMDataGrid
|
|
24
24
|
|
|
25
25
|
Creates the table instance and the state used by the grid interface.
|
|
26
26
|
|
|
@@ -69,7 +69,7 @@ rather than forwarded to TanStack.
|
|
|
69
69
|
|
|
70
70
|
| Slice | Default |
|
|
71
71
|
| --- | --- |
|
|
72
|
-
| `pagination` | `{ pageIndex: 0, pageSize: 25 }`
|
|
72
|
+
| `pagination` | `{ pageIndex: 0, pageSize: 25 }` - inert until pagination is enabled |
|
|
73
73
|
| `columnPinning.left` | The checkbox column, followed by any columns you provide |
|
|
74
74
|
| `globalFilterFn` | `"includesString"` |
|
|
75
75
|
|
|
@@ -136,7 +136,7 @@ names are typed per group, so only valid names are accepted.
|
|
|
136
136
|
Restoring happens once on mount through `initialState`. Writing is a subscription
|
|
137
137
|
to the table store, so state changed directly through the table API is persisted
|
|
138
138
|
too. Only selected slices are read back, and unrecognised keys are ignored. All
|
|
139
|
-
storage access is guarded
|
|
139
|
+
storage access is guarded - if storage is unavailable, disabled or full,
|
|
140
140
|
persistence is skipped rather than throwing.
|
|
141
141
|
|
|
142
142
|
## Return value
|
|
@@ -180,7 +180,7 @@ The last two move the cell cursor and the selected rectangle under
|
|
|
180
180
|
`cellSelection`; DOM focus follows `focusedCell` and scrolls its row into view.
|
|
181
181
|
|
|
182
182
|
`startColumnDrag` / `endColumnDrag` are called by the header cells while a column is being dragged, and
|
|
183
|
-
`ui.draggedColumnId` holds the column being moved
|
|
183
|
+
`ui.draggedColumnId` holds the column being moved - browsers keep `dataTransfer`
|
|
184
184
|
unreadable until the drop.
|
|
185
185
|
|
|
186
186
|
`openColumnFilter(grid, columnId)` combines the two steps the column menu uses:
|
|
@@ -190,11 +190,11 @@ add an empty filter row for the column if none exists, then open the panel.
|
|
|
190
190
|
|
|
191
191
|
### Reading store state during render
|
|
192
192
|
|
|
193
|
-
`grid.table.store.state` is a plain read
|
|
193
|
+
`grid.table.store.state` is a plain read - it does not subscribe the component,
|
|
194
194
|
so the value is correct on first render and then never updates.
|
|
195
195
|
|
|
196
196
|
```tsx
|
|
197
|
-
// Wrong
|
|
197
|
+
// Wrong - never re-renders when the selection changes.
|
|
198
198
|
const count = Object.keys(grid.table.store.state.rowSelection).length;
|
|
199
199
|
|
|
200
200
|
// Right.
|
|
@@ -219,5 +219,5 @@ Include a tenant or user identifier in the key.
|
|
|
219
219
|
### Unstable data reference
|
|
220
220
|
|
|
221
221
|
A new array identity on each render re-runs the row model. `data={rows ?? []}`
|
|
222
|
-
allocates a fresh `[]` every render when `rows` is undefined
|
|
222
|
+
allocates a fresh `[]` every render when `rows` is undefined - hoist the empty
|
|
223
223
|
array to a module-scope constant or `useMemo` the expression.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: server-side
|
|
3
3
|
description: >
|
|
4
|
-
Drive TMDataGrid from a server with TanStack manual modes
|
|
4
|
+
Drive TMDataGrid from a server with TanStack manual modes - manualPagination,
|
|
5
5
|
manualSorting, manualFiltering, rowCount, controlled state and onXChange
|
|
6
6
|
callbacks. Covers the loading and totalRowCount meta fields, forwarding the
|
|
7
7
|
plain-JSON columnFilters model to an API with isFilterActive, persistence
|
|
@@ -10,18 +10,18 @@ description: >
|
|
|
10
10
|
metadata:
|
|
11
11
|
type: core
|
|
12
12
|
library: '@jielga/tmdatagrid'
|
|
13
|
-
library_version: '1.0.
|
|
13
|
+
library_version: '1.0.1'
|
|
14
14
|
sources:
|
|
15
15
|
- 'Jielga/TMDataGrid:src/docs/server-side.md'
|
|
16
16
|
- 'Jielga/TMDataGrid:src/tmdatagrid/useTMDataGrid.tsx'
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
# TMDataGrid
|
|
19
|
+
# TMDataGrid - Server-side data
|
|
20
20
|
|
|
21
21
|
The grid reads rows through `getPaginatedRowModel()` and totals through
|
|
22
22
|
`getRowCount()` and `getPageCount()`, all of which respect TanStack's manual
|
|
23
23
|
modes. A server-driven grid therefore needs only the standard `manual*`
|
|
24
|
-
configuration
|
|
24
|
+
configuration - no grid-specific options. `manualPagination: true` also
|
|
25
25
|
switches the grid's pagination flag on, so `TMDataGrid.Footer` renders its
|
|
26
26
|
pager without `enablePagination`. Declare `pageCount: -1` when the total is
|
|
27
27
|
unknown; the next button then stays enabled.
|
|
@@ -85,7 +85,7 @@ Filter values are plain JSON, so `columnFilters` forwards without transformation
|
|
|
85
85
|
]
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
Translate at the API boundary, and skip entries whose value is still empty
|
|
88
|
+
Translate at the API boundary, and skip entries whose value is still empty -
|
|
89
89
|
those match all rows:
|
|
90
90
|
|
|
91
91
|
```ts
|
|
@@ -122,8 +122,8 @@ const selectedIds = useSelector(grid.table.store, (state) =>
|
|
|
122
122
|
|
|
123
123
|
### Omitting rowCount under manualPagination
|
|
124
124
|
|
|
125
|
-
Without `rowCount` the table derives the total from the rows it was handed
|
|
126
|
-
one page
|
|
125
|
+
Without `rowCount` the table derives the total from the rows it was handed -
|
|
126
|
+
one page - so `getPageCount()` returns 1. The footer shows "1–25 of 25" and the
|
|
127
127
|
next-page button is disabled, with no error. Pass the server total.
|
|
128
128
|
|
|
129
129
|
### Filters sent without isFilterActive
|
package/skills/testing/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: testing
|
|
3
3
|
description: >
|
|
4
|
-
Write tests against TMDataGrid from a consuming app
|
|
4
|
+
Write tests against TMDataGrid from a consuming app - Playwright or React
|
|
5
5
|
Testing Library. Covers the data-dg-part contract, data-row-id/data-column-id
|
|
6
6
|
coordinates, naming a grid with data-testid, the roles and ARIA the grid
|
|
7
7
|
publishes, the cell/gridcell role flip under cell selection, reaching rows
|
|
@@ -11,25 +11,25 @@ description: >
|
|
|
11
11
|
metadata:
|
|
12
12
|
type: core
|
|
13
13
|
library: '@jielga/tmdatagrid'
|
|
14
|
-
library_version: '1.0.
|
|
14
|
+
library_version: '1.0.1'
|
|
15
15
|
sources:
|
|
16
16
|
- 'Jielga/TMDataGrid:src/docs/testing.md'
|
|
17
17
|
- 'Jielga/TMDataGrid:src/tmdatagrid/components/TMDataGrid.tsx'
|
|
18
18
|
- 'Jielga/TMDataGrid:src/tmdatagrid/components/TMDataGridTable.tsx'
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
# TMDataGrid
|
|
21
|
+
# TMDataGrid - Testing
|
|
22
22
|
|
|
23
23
|
The grid names its own pieces so a suite can be written against structure
|
|
24
24
|
rather than against copy or class names. Three hooks carry it:
|
|
25
25
|
|
|
26
|
-
- **`data-dg-part`**
|
|
27
|
-
- **`data-row-id` / `data-column-id`**
|
|
28
|
-
- **roles and ARIA**
|
|
26
|
+
- **`data-dg-part`** - *what* an element is (`"row"`, `"filter-button"`)
|
|
27
|
+
- **`data-row-id` / `data-column-id`** - *which* one, using your own ids
|
|
28
|
+
- **roles and ARIA** - framework-neutral, and what a screen reader reads
|
|
29
29
|
|
|
30
30
|
Selectors compose: `[data-dg-part="save-row"][data-row-id="42"]`.
|
|
31
31
|
|
|
32
|
-
The grid mints no `data-testid` of its own
|
|
32
|
+
The grid mints no `data-testid` of its own - that attribute belongs to the app,
|
|
33
33
|
and Playwright's `testIdAttribute` is configurable. `@mantine/core` and
|
|
34
34
|
`@tanstack/*` ship none either.
|
|
35
35
|
|
|
@@ -56,7 +56,7 @@ accessible name belongs to the element carrying the `grid` role.
|
|
|
56
56
|
| Body cell | `cell`, or `gridcell` under cell selection | `data-row-id`, `data-column-id`, `data-editing`, `data-dirty`, `data-invalid`, `data-focused` |
|
|
57
57
|
| Header cell | `columnheader` | `data-column-id`, `aria-sort` |
|
|
58
58
|
|
|
59
|
-
Body cells carry no `data-dg-part`
|
|
59
|
+
Body cells carry no `data-dg-part` - the coordinate pair already names them.
|
|
60
60
|
|
|
61
61
|
## Parts
|
|
62
62
|
|
|
@@ -79,7 +79,7 @@ Body cells carry no `data-dg-part` — the coordinate pair already names them.
|
|
|
79
79
|
**Keyed by both**: `editor`.
|
|
80
80
|
|
|
81
81
|
Inside a `filter-row` the controls are `filter-column`, `filter-operator` and
|
|
82
|
-
`filter-value`
|
|
82
|
+
`filter-value` - or `filter-value-from` / `filter-value-to` for `between`.
|
|
83
83
|
|
|
84
84
|
A column declaring `meta.filterControl` or `meta.editor` renders your own
|
|
85
85
|
component in that slot, so `filter-value` and `editor-input` cover the built-ins
|
|
@@ -131,10 +131,10 @@ Only the rows in the viewport plus overscan are in the DOM. A row at index 500
|
|
|
131
131
|
has no element, and Playwright cannot scroll to what it cannot find.
|
|
132
132
|
|
|
133
133
|
**Count rows off the grid.** `data-dg-row-count` is the body rows the grid is
|
|
134
|
-
showing
|
|
134
|
+
showing - the current page under pagination, everything the filters left
|
|
135
135
|
otherwise. (`aria-rowcount` also counts the header and summary rows.)
|
|
136
136
|
|
|
137
|
-
**Reach a row by narrowing to it**
|
|
137
|
+
**Reach a row by narrowing to it** - filter or search. Faster, more stable, and
|
|
138
138
|
what a user would do. Where the row must be reached in place,
|
|
139
139
|
`grid.scrollToRow({ rowId, align })` moves the virtualizer and answers whether
|
|
140
140
|
the row was reachable; from Playwright that needs the app to expose the api.
|
|
@@ -164,7 +164,7 @@ layout, so the count depends on the stubbed element size. Assert
|
|
|
164
164
|
### getByRole("cell") on a grid with cell selection
|
|
165
165
|
|
|
166
166
|
`enableCellSelection` turns every `cell` into a `gridcell`, and the grid's
|
|
167
|
-
`table` into a `grid`
|
|
167
|
+
`table` into a `grid` - a widget with a keyboard cursor is not a table of
|
|
168
168
|
content. Tests written on the role break when the feature is switched on. Query
|
|
169
169
|
cells by `[data-row-id][data-column-id]`, which do not move.
|
|
170
170
|
|
|
@@ -5,7 +5,7 @@ import type { TMDataGridApi } from "./useTMDataGrid";
|
|
|
5
5
|
/**
|
|
6
6
|
* Row shape the chrome components work against. They only ever touch columns,
|
|
7
7
|
* rows and cells generically, so the concrete row type is erased at the context
|
|
8
|
-
* boundary
|
|
8
|
+
* boundary - the same trick Mantine uses for its compound components.
|
|
9
9
|
*/
|
|
10
10
|
export type TMDataGridRowData = Record<string, unknown>;
|
|
11
11
|
|
|
@@ -36,7 +36,7 @@ export function useTMDataGridContext(): TMDataGridContextValue {
|
|
|
36
36
|
*
|
|
37
37
|
* `-1` once cell selection is on, and this is what makes the promise of one tab
|
|
38
38
|
* stop true. Without it the browser walks Tab into the checkbox of every
|
|
39
|
-
* mounted row
|
|
39
|
+
* mounted row - a grid showing twenty rows would be twenty tab stops, and
|
|
40
40
|
* scrolling would change how many. Enter or F2 steps into the cell instead,
|
|
41
41
|
* which reaches a `-1` control perfectly well.
|
|
42
42
|
*
|