@jielga/tmdatagrid 2.1.4 → 2.3.0
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 +78 -5
- package/dist/index.js +2194 -1992
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/docs/cell-selection.md +1 -1
- package/docs/column-layout.md +13 -8
- package/docs/columns.md +59 -3
- package/docs/components.md +1 -0
- package/docs/export.md +2 -2
- package/docs/filtering.md +108 -15
- package/docs/getting-started.md +40 -0
- package/docs/grouping.md +9 -6
- package/docs/loading-and-empty.md +29 -9
- package/docs/localization.md +130 -3
- package/docs/menu.md +1 -1
- package/docs/pagination.md +26 -7
- package/docs/persistence.md +101 -2
- package/docs/row-details.md +41 -4
- package/docs/row-interaction.md +2 -2
- package/docs/row-selection.md +6 -7
- package/docs/row-styling.md +17 -0
- package/docs/scrolling.md +1 -1
- package/docs/server-side.md +3 -1
- package/docs/testing.md +18 -0
- package/docs/use-tm-data-grid.md +75 -36
- package/package.json +1 -1
- package/skills/appearance/SKILL.md +6 -4
- package/skills/appearance/references/labels.md +126 -0
- package/skills/cell-selection/SKILL.md +2 -2
- package/skills/columns/SKILL.md +44 -43
- package/skills/columns/references/columns-api.md +16 -1
- package/skills/data/SKILL.md +77 -50
- package/skills/editing/SKILL.md +1 -1
- package/skills/filtering/SKILL.md +94 -60
- package/skills/filtering/references/custom-filters.md +118 -0
- package/skills/getting-started/SKILL.md +37 -2
- package/skills/grouping/SKILL.md +16 -9
- package/skills/migrating-to-2/SKILL.md +1 -1
- package/skills/options/SKILL.md +206 -55
- package/skills/rows/SKILL.md +70 -39
- package/skills/server-side/SKILL.md +1 -1
- package/skills/testing/SKILL.md +12 -1
- package/skills/testing-components/SKILL.md +1 -1
- package/skills/testing-editing/SKILL.md +1 -1
- package/src/components/TMDataGridFilterPills.module.css +9 -7
- package/src/components/TMDataGridTable.module.css +15 -6
- package/src/components/TMDataGridTable.tsx +253 -41
- package/src/components/sticky.module.css +27 -7
- package/src/core/autosize.ts +19 -7
- package/src/core/cellRange.ts +11 -2
- package/src/core/colSpan.ts +78 -0
- package/src/core/columnUtils.ts +7 -0
- package/src/core/filterControls.ts +8 -0
- package/src/core/filterOperators.ts +29 -1
- package/src/core/persistence.ts +322 -26
- package/src/index.ts +5 -0
- package/src/useTMDataGrid.tsx +133 -14
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
._root_wlqnb_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_wlqnb_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_wlqnb_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_wlqnb_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_wlqnb_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_wlqnb_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-header-font-size:var(--dg-font-size);--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-focused-cell:1;--dg-z-pinned-cell:2;--dg-z-pinned-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_a5do5_1{flex-direction:column;width:280px;display:flex}._columnsPanelSearch_a5do5_7{padding:var(--mantine-spacing-sm)}._columnsPanelList_a5do5_11{gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-sm);flex-direction:column;display:flex}._columnsPanelSearch_a5do5_7+* ._columnsPanelList_a5do5_11{padding-top:0}._columnsPanelFooter_a5do5_22{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_1qtpn_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._tableWrapper_1qtpn_2[data-dg-filter-sidebar]{flex-direction:row}._scrollContainer_1qtpn_17{flex:1;min-width:0;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_1qtpn_29{align-content:start;min-height:100%;display:grid}._tabGuard_1qtpn_44{outline:none;width:0;height:0;position:absolute;overflow:hidden}._headerRow_1qtpn_54{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._bodyRow_1qtpn_63{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_1qtpn_63[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_1qtpn_63[data-new=true]{--row-bg:var(--dg-row-new-bg,var(--mantine-color-body))}._bodyRow_1qtpn_63:hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_1qtpn_63[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_1qtpn_63[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_1qtpn_63[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_1qtpn_63[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_1qtpn_63[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_1qtpn_63:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_1qtpn_137{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);background-image:linear-gradient(var(--row-bg), var(--row-bg));font-size:var(--dg-font-size);align-items:center;display:flex}._bodyCell_1qtpn_137[data-control-column=true]{padding:0}._grid_1qtpn_29[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_1qtpn_137[data-selected=true]{--dg-range-tint:color-mix(in srgb, var(--mantine-primary-color-filled) 14%, var(--row-bg));background-image:linear-gradient(var(--dg-range-tint), var(--dg-range-tint));--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_1qtpn_137[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_1qtpn_137[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_1qtpn_137[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_1qtpn_137[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_1qtpn_137[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_1qtpn_135{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_1qtpn_137[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_1qtpn_244{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorField_1qtpn_254{flex:auto;align-items:center;min-width:0;display:flex}._cellEditorActions_1qtpn_262{flex:none;align-items:center;display:flex}._bodyCell_1qtpn_137[data-dirty],._bodyCell_1qtpn_137[data-invalid],._entryCell_1qtpn_275[data-invalid]{position:relative}._bodyCell_1qtpn_137[data-dirty]:after,._bodyCell_1qtpn_137[data-invalid]:after,._entryCell_1qtpn_275[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_1qtpn_137[data-invalid]:after,._entryCell_1qtpn_275[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_1qtpn_137[data-align=right]{justify-content:flex-end}._bodyCell_1qtpn_137[data-align=center]{justify-content:center}._bodyCell_1qtpn_137[data-align=left] ._cellContent_1qtpn_135{flex:auto}._detailsCell_1qtpn_317{border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);background-image:linear-gradient(var(--row-bg), var(--row-bg));padding:var(--dg-padding);-webkit-user-select:text;user-select:text;cursor:auto;grid-column:1/-1}._messageRow_1qtpn_23{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_1qtpn_63[data-deleted=true]{opacity:.55;text-decoration:line-through}._bodyRow_1qtpn_63[data-deleted=true] ._bodyCell_1qtpn_137:not([data-control-column=true]){pointer-events:none}._entryBlock_1qtpn_369{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_1qtpn_378{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_1qtpn_391{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_1qtpn_391>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_1qtpn_404{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_1qtpn_404>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_1qtpn_275{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_1qtpn_275[data-control-column=true]{justify-content:center;padding:0}._entryRow_1qtpn_378[data-committed=true] ._entryCell_1qtpn_275{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-image:linear-gradient(var(--dg-row-new-bg,transparent), var(--dg-row-new-bg,transparent))}._entryRow_1qtpn_378[data-committed=true] ._entryCell_1qtpn_275[data-control-column=true]{padding:0}._rowStateIndicator_1qtpn_453{width:22px;height:22px;color:var(--mantine-color-dimmed);flex:none;justify-content:center;align-items:center;display:inline-flex}._rowStateIndicator_1qtpn_453[data-error]{color:var(--mantine-color-error)}._entryCell_1qtpn_275[data-align=right]{justify-content:flex-end}._entryCell_1qtpn_275[data-align=center]{justify-content:center}._matchHighlight_1qtpn_479{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_1qtpn_500{grid-column:1/-1;grid-template-columns:subgrid;top:calc(100% - var(--dg-summary-height,0px));z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_1qtpn_510{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_1qtpn_510[data-control-column=true]{padding:0}._summaryCell_1qtpn_510[data-align=right]{justify-content:flex-end}._summaryCell_1qtpn_510[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_wm77f_4{gap:var(--mantine-spacing-xs);flex-direction:column;display:flex}._filterRow_wm77f_12{align-items:flex-end;gap:var(--mantine-spacing-xs);display:flex}._filterRow_wm77f_12[data-layout=stacked]{align-items:end;gap:6px var(--mantine-spacing-xs);padding:var(--mantine-spacing-xs);border:1px solid var(--mantine-color-default-border);border-radius:var(--mantine-radius-sm);grid-template-columns:1fr auto;display:grid}._filterRow_wm77f_12[data-layout=stacked] ._filterRemove_wm77f_32{grid-area:1/2}._filterRow_wm77f_12[data-layout=stacked] ._filterColumnSlot_wm77f_37{grid-area:1/1;min-width:0}._filterRow_wm77f_12[data-layout=stacked] ._filterOperatorSlot_wm77f_43,._filterRow_wm77f_12[data-layout=stacked] ._filterValueSlot_wm77f_44{grid-column:1/-1;min-width:0}._filterPanelFooter_wm77f_49{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_1jwnm_16:after,._stickyRight_1jwnm_17:after{content:"";pointer-events:none;width:8px;position:absolute;top:0;bottom:0}._stickyLeft_1jwnm_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_1jwnm_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_1jwnm_16:after,._stickyRight_1jwnm_17:after{--dg-sticky-edge-range:20px;opacity:0;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(inline)}._stickyLeft_1jwnm_16:after{animation-name:_stickyEdgeIn_1jwnm_1;animation-range:0 var(--dg-sticky-edge-range)}._stickyRight_1jwnm_17:after{animation-name:_stickyEdgeOut_1jwnm_1;animation-range:calc(100% - var(--dg-sticky-edge-range)) 100%}}@keyframes _stickyEdgeIn_1jwnm_1{0%{opacity:0}to{opacity:1}}@keyframes _stickyEdgeOut_1jwnm_1{0%{opacity:1}to{opacity:0}}._headerBoundary_1jwnm_120: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()){._headerBoundary_1jwnm_120:after{animation:linear both _dgHeaderShadow_1jwnm_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dgHeaderShadow_1jwnm_1{0%{opacity:0}to{opacity:1}}._surfaceHeader_10bcx_5{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);padding-bottom:var(--mantine-spacing-xs);display:flex}._filterPopup_10bcx_18{top:calc(var(--dg-header-stack-height,var(--dg-header-height)) + 2px);left:var(--mantine-spacing-md);z-index:var(--dg-z-filter-popup,20);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}._filterSidebar_10bcx_33{min-width:0;padding:var(--mantine-spacing-sm);background-color:var(--mantine-color-body);border-left:1px solid var(--mantine-color-default-border);flex-direction:column;flex:none;display:flex}._filterSidebar_10bcx_33[data-side=left]{border-left:none;border-right:1px solid var(--mantine-color-default-border);order:-1}._filterSidebarBody_10bcx_51{flex:1;min-height:0}._headerFilterRow_h1geg_9{grid-column:1/-1;grid-template-columns:subgrid;top:var(--dg-header-height);z-index:var(--dg-z-header,6);display:grid;position:sticky}._headerFilterCell_h1geg_18{min-width:0;padding:calc(var(--dg-padding) / 2);background-color:var(--mantine-color-body);border-bottom:1px solid var(--mantine-color-default-border);align-items:center;gap:2px;display:flex;overflow:hidden}._headerFilterCell_h1geg_18[data-control-column=true]{padding:0}._headerFilterValue_h1geg_39{flex:1;min-width:0}._headerFilterOperator_h1geg_44{flex:none}._operatorItemActive_h1geg_48{color:var(--mantine-primary-color-filled);font-weight:600}._headerCell_18ma1_1{padding:0 var(--dg-padding);min-width:0;min-height:var(--dg-header-height);font-weight:600;font-size:var(--dg-header-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_18ma1_1[data-align=right]{justify-content:flex-end}._headerCell_18ma1_1[data-align=center]{justify-content:center}._headerCell_18ma1_1[data-control-column=true]{padding:0}._headerCellFiltered_18ma1_35 ._headerTitle_18ma1_35{color:var(--mantine-primary-color-filled)}._headerTitle_18ma1_35{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}._headerCell_18ma1_1[data-align=right] ._headerTitle_18ma1_35{text-align:right}._headerCell_18ma1_1[data-align=center] ._headerTitle_18ma1_35{justify-content:center;display:flex}._headerActions_18ma1_58{flex-shrink:0;align-items:center;gap:0;margin-left:auto;display:flex}._headerCell_18ma1_1[data-align=right] ._headerActions_18ma1_58{order:-1;margin-left:0;margin-right:auto}._headerAction_18ma1_58{display:none}._headerCell_18ma1_1:hover ._headerAction_18ma1_58,._headerCell_18ma1_1:focus-within ._headerAction_18ma1_58,._headerAction_18ma1_58[data-pinned-visible=true]{display:flex}._headerCellSortable_18ma1_87{cursor:pointer}._sortAction_18ma1_93:not([data-sorted]){opacity:.55}._sortAction_18ma1_93:not([data-sorted]):hover{opacity:1}._sortIndex_18ma1_103{color:var(--mantine-color-dimmed);text-align:center;min-width:10px;font-size:10px;font-weight:600;line-height:1}._headerCellDragging_18ma1_115{opacity:.4}._headerCellDropBefore_18ma1_119:before,._headerCellDropAfter_18ma1_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_18ma1_119:before{left:0}._headerCellDropAfter_18ma1_120:before{right:0}._columnSeparator_18ma1_140{z-index:1;justify-content:center;width:10px;height:50%;display:flex;position:absolute;top:25%;right:0;transform:translate(50%)}._headerCell_18ma1_1:last-child ._columnSeparator_18ma1_140{justify-content:flex-end;transform:none}._columnSeparatorResizable_18ma1_162{cursor:col-resize;touch-action:none}._columnSeparator_18ma1_140:after{content:"";background-color:#0000;width:1px;height:100%;transition:background-color .12s,width .12s}._headerCell_18ma1_1:hover ._columnSeparator_18ma1_140:after,._headerCell_18ma1_1:focus-within ._columnSeparator_18ma1_140:after{background-color:var(--mantine-color-default-border)}._columnSeparatorResizable_18ma1_162:hover:after,._columnSeparatorActive_18ma1_185:after{background-color:var(--mantine-primary-color-filled);width:2px}._menuItemActive_18ma1_191{background-color:var(--mantine-color-default-hover);font-weight:600}._toolbar_gwk05_1{align-items:center;gap:var(--mantine-spacing-xs);padding:6px var(--mantine-spacing-xs);flex-shrink:0;min-height:42px;display:flex}._toolbar_gwk05_1[data-with-bottom-border]{border-bottom:1px solid var(--mantine-color-default-border)}._toolbarSpacer_gwk05_15{flex:1}._summaryCount_gwk05_19{white-space:nowrap}._title_199r2_1{font-weight:500}._list_199r2_5{border:1px solid var(--mantine-color-default-border);border-radius:var(--mantine-radius-default);flex-direction:column;display:flex;overflow:hidden}._listHeader_199r2_13{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-xs) var(--mantine-spacing-sm);background-color:var(--mantine-color-default-hover);border-bottom:1px solid var(--mantine-color-default-border);display:flex}._headerLabel_199r2_23{cursor:pointer;font-weight:500}._rows_199r2_28{padding:calc(var(--mantine-spacing-xs) / 2) 0;flex-direction:column;display:flex}._row_199r2_28{padding:0 var(--mantine-spacing-sm)}._row_199r2_28:hover{background-color:var(--mantine-color-default-hover)}._rowBody_199r2_45{align-items:center}._rowLabelWrapper_199r2_49{flex:1;min-width:0}._rowLabel_199r2_49{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding-block:calc(var(--mantine-spacing-xs) * .75);cursor:pointer;display:flex}._rowText_199r2_63{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._rowHint_199r2_69{font-size:var(--mantine-font-size-xs);color:var(--mantine-color-dimmed);flex:none}._empty_199r2_75{padding:var(--mantine-spacing-xs) var(--mantine-spacing-sm)}
|
|
1
|
+
._root_wlqnb_8[data-size=xs]{--dg-row-height:34px;--dg-header-height:32px;--dg-font-size:var(--mantine-font-size-xs);--dg-padding:6px}._root_wlqnb_8[data-size=sm]{--dg-row-height:42px;--dg-header-height:38px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:8px}._root_wlqnb_8[data-size=md]{--dg-row-height:52px;--dg-header-height:44px;--dg-font-size:var(--mantine-font-size-sm);--dg-padding:10px}._root_wlqnb_8[data-size=lg]{--dg-row-height:62px;--dg-header-height:52px;--dg-font-size:var(--mantine-font-size-md);--dg-padding:14px}._root_wlqnb_8[data-size=xl]{--dg-row-height:72px;--dg-header-height:60px;--dg-font-size:var(--mantine-font-size-lg);--dg-padding:18px}._root_wlqnb_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-header-font-size:var(--dg-font-size);--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-focused-cell:1;--dg-z-pinned-cell:2;--dg-z-pinned-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_a5do5_1{flex-direction:column;width:280px;display:flex}._columnsPanelSearch_a5do5_7{padding:var(--mantine-spacing-sm)}._columnsPanelList_a5do5_11{gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-sm);flex-direction:column;display:flex}._columnsPanelSearch_a5do5_7+* ._columnsPanelList_a5do5_11{padding-top:0}._columnsPanelFooter_a5do5_22{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_34o3j_2{flex-direction:column;flex:1;min-height:0;display:flex;position:relative}._tableWrapper_34o3j_2[data-dg-filter-sidebar]{flex-direction:row}._scrollContainer_34o3j_17{flex:1;min-width:0;min-height:0;position:relative;overflow:auto;container-type:inline-size}._grid_34o3j_29{align-content:start;min-height:100%;display:grid}._tabGuard_34o3j_44{outline:none;width:0;height:0;position:absolute;overflow:hidden}._headerRow_34o3j_54{grid-column:1/-1;grid-template-columns:subgrid;z-index:var(--dg-z-header,6);display:grid;position:sticky;top:0}._bodyRow_34o3j_63{--row-bg:var(--mantine-color-body);grid-column:1/-1;grid-template-columns:subgrid;align-items:stretch;display:grid}._bodyRow_34o3j_63[data-striped=true]{--row-bg:var(--dg-row-striped-bg)}._bodyRow_34o3j_63[data-new=true]{--row-bg:var(--dg-row-new-bg,var(--mantine-color-body))}._bodyRow_34o3j_63:where([data-highlight-on-hover=true]):hover{--row-bg:var(--mantine-color-default-hover)}._bodyRow_34o3j_63[data-grouped=true]{--row-bg:var(--dg-row-group-bg)}._bodyRow_34o3j_63[data-context-menu=true]{--row-bg:var(--mantine-color-default-hover)}._bodyRow_34o3j_63[data-selected-bg=true]{--row-bg:var(--dg-row-selected-bg)}._bodyRow_34o3j_63[data-highlighted=true]{--row-bg:var(--dg-row-highlight-bg)}._bodyRow_34o3j_63[data-selects-on-click=true]{-webkit-user-select:none;user-select:none}._bodyRow_34o3j_63:focus-visible{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._bodyCell_34o3j_143{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);background-image:linear-gradient(var(--row-bg), var(--row-bg));font-size:var(--dg-font-size);align-items:center;display:flex}._bodyCell_34o3j_143[data-control-column=true]{padding:0}._grid_34o3j_29[data-range-dragging]{-webkit-user-select:none;user-select:none}._bodyCell_34o3j_143[data-selected=true]{--dg-range-tint:color-mix(in srgb, var(--mantine-primary-color-filled) 14%, var(--row-bg));background-image:linear-gradient(var(--dg-range-tint), var(--dg-range-tint));--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_34o3j_143[data-edge-top=true]{--dg-edge-top:var(--mantine-primary-color-filled)}._bodyCell_34o3j_143[data-edge-bottom=true]{--dg-edge-bottom:var(--mantine-primary-color-filled)}._bodyCell_34o3j_143[data-edge-left=true]{--dg-edge-left:var(--mantine-primary-color-filled)}._bodyCell_34o3j_143[data-edge-right=true]{--dg-edge-right:var(--mantine-primary-color-filled)}._bodyCell_34o3j_143[data-focused=true]{outline:2px solid var(--mantine-primary-color-filled);outline-offset:-2px}._cellContent_34o3j_141{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}._bodyCell_34o3j_143[data-editing]{padding:0 calc(var(--dg-padding) / 2)}._cellEditor_34o3j_250{align-items:center;gap:2px;width:100%;min-width:0;display:flex}._cellEditorField_34o3j_260{flex:auto;align-items:center;min-width:0;display:flex}._cellEditorActions_34o3j_268{flex:none;align-items:center;display:flex}._bodyCell_34o3j_143[data-dirty],._bodyCell_34o3j_143[data-invalid],._entryCell_34o3j_281[data-invalid]{position:relative}._bodyCell_34o3j_143[data-dirty]:after,._bodyCell_34o3j_143[data-invalid]:after,._entryCell_34o3j_281[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_34o3j_143[data-invalid]:after,._entryCell_34o3j_281[data-invalid]:after{border-top-color:var(--mantine-color-error);border-right-color:var(--mantine-color-error)}._bodyCell_34o3j_143[data-align=right]{justify-content:flex-end}._bodyCell_34o3j_143[data-align=center]{justify-content:center}._bodyCell_34o3j_143[data-align=left] ._cellContent_34o3j_141{flex:auto}._detailsCell_34o3j_323{border-bottom:1px solid var(--mantine-color-default-border);background-color:var(--mantine-color-body);background-image:linear-gradient(var(--row-bg), var(--row-bg));-webkit-user-select:text;user-select:text;cursor:auto;grid-column:1/-1}._messageRow_34o3j_23{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_34o3j_63[data-deleted=true]{opacity:.55;text-decoration:line-through}._bodyRow_34o3j_63[data-deleted=true] ._bodyCell_34o3j_143:not([data-control-column=true]){pointer-events:none}._entryBlock_34o3j_377{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_34o3j_386{grid-column:1/-1;grid-template-columns:subgrid;display:grid}._pinnedTopBlock_34o3j_399{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_34o3j_399>:last-child>[role=cell]{border-bottom:2px solid var(--mantine-color-default-border)}._pinnedBottomBlock_34o3j_412{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_34o3j_412>:first-child>[role=cell]{border-top:2px solid var(--mantine-color-default-border)}._entryCell_34o3j_281{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_34o3j_281[data-control-column=true]{justify-content:center;padding:0}._entryRow_34o3j_386[data-committed=true] ._entryCell_34o3j_281{padding:0 var(--dg-padding);border-bottom:1px solid var(--mantine-color-default-border);background-image:linear-gradient(var(--dg-row-new-bg,transparent), var(--dg-row-new-bg,transparent))}._entryRow_34o3j_386[data-committed=true] ._entryCell_34o3j_281[data-control-column=true]{padding:0}._rowStateIndicator_34o3j_461{width:22px;height:22px;color:var(--mantine-color-dimmed);flex:none;justify-content:center;align-items:center;display:inline-flex}._rowStateIndicator_34o3j_461[data-error]{color:var(--mantine-color-error)}._entryCell_34o3j_281[data-align=right]{justify-content:flex-end}._entryCell_34o3j_281[data-align=center]{justify-content:center}._matchHighlight_34o3j_487{background-color:var(--dg-match-highlight-bg,var(--mantine-color-yellow-2));color:inherit;border-radius:2px}:where([data-mantine-color-scheme=dark]) ._matchHighlight_34o3j_487{background-color:var(--dg-match-highlight-bg,#fab00559)}._summaryRow_34o3j_509{grid-column:1/-1;grid-template-columns:subgrid;top:calc(100% - var(--dg-summary-height,0px));z-index:var(--dg-z-summary-row,4);display:grid;position:sticky;bottom:0}._summaryCell_34o3j_519{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_34o3j_519[data-control-column=true]{padding:0}._summaryCell_34o3j_519[data-align=right]{justify-content:flex-end}._summaryCell_34o3j_519[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_wm77f_4{gap:var(--mantine-spacing-xs);flex-direction:column;display:flex}._filterRow_wm77f_12{align-items:flex-end;gap:var(--mantine-spacing-xs);display:flex}._filterRow_wm77f_12[data-layout=stacked]{align-items:end;gap:6px var(--mantine-spacing-xs);padding:var(--mantine-spacing-xs);border:1px solid var(--mantine-color-default-border);border-radius:var(--mantine-radius-sm);grid-template-columns:1fr auto;display:grid}._filterRow_wm77f_12[data-layout=stacked] ._filterRemove_wm77f_32{grid-area:1/2}._filterRow_wm77f_12[data-layout=stacked] ._filterColumnSlot_wm77f_37{grid-area:1/1;min-width:0}._filterRow_wm77f_12[data-layout=stacked] ._filterOperatorSlot_wm77f_43,._filterRow_wm77f_12[data-layout=stacked] ._filterValueSlot_wm77f_44{grid-column:1/-1;min-width:0}._filterPanelFooter_wm77f_49{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);display:flex}._filterPills_c75fv_3{align-items:center;gap:var(--mantine-spacing-xs);flex-wrap:wrap;display:flex}._filterPills_c75fv_3 ._pill_c75fv_15{background-color:var(--mantine-color-gray-1);color:var(--mantine-color-black);border:1px solid var(--mantine-color-gray-3)}:where([data-mantine-color-scheme=dark]) ._filterPills_c75fv_3 ._pill_c75fv_15{background-color:var(--mantine-color-dark-5);color:var(--mantine-color-dark-0);border-color:var(--mantine-color-dark-3)}._pillLabel_c75fv_29{font:inherit;color:inherit;cursor:pointer}._pillLabel_c75fv_29: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_1opmk_18:after,._stickyRight_1opmk_19:after{content:"";pointer-events:none;width:8px;position:absolute;top:0;bottom:0}._stickyLeft_1opmk_18:after{background:linear-gradient(90deg,#00000012,#00000006 45%,#0000);left:100%}._stickyRight_1opmk_19:after{background:linear-gradient(270deg,#00000012,#00000006 45%,#0000);right:100%}:where([data-mantine-color-scheme=dark]) ._stickyLeft_1opmk_18:after{background:linear-gradient(90deg,#00000042,#00000017 45%,#0000)}:where([data-mantine-color-scheme=dark]) ._stickyRight_1opmk_19:after{background:linear-gradient(270deg,#00000042,#00000017 45%,#0000)}@supports (animation-timeline:scroll()){._stickyLeft_1opmk_18:after,._stickyRight_1opmk_19:after{--dg-sticky-edge-range:20px;opacity:0;animation-timing-function:linear;animation-fill-mode:both;animation-timeline:scroll(inline)}._stickyLeft_1opmk_18:after{animation-name:_stickyEdgeIn_1opmk_1;animation-range:0 var(--dg-sticky-edge-range)}._stickyRight_1opmk_19:after{animation-name:_stickyEdgeOut_1opmk_1;animation-range:calc(100% - var(--dg-sticky-edge-range)) 100%}}@keyframes _stickyEdgeIn_1opmk_1{0%{opacity:0}to{opacity:1}}@keyframes _stickyEdgeOut_1opmk_1{0%{opacity:1}to{opacity:0}}._headerBoundary_1opmk_140: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()){._headerBoundary_1opmk_140:after{animation:linear both _dgHeaderShadow_1opmk_1;animation-timeline:scroll();animation-range:0 24px}}@keyframes _dgHeaderShadow_1opmk_1{0%{opacity:0}to{opacity:1}}._surfaceHeader_10bcx_5{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-md);padding-bottom:var(--mantine-spacing-xs);display:flex}._filterPopup_10bcx_18{top:calc(var(--dg-header-stack-height,var(--dg-header-height)) + 2px);left:var(--mantine-spacing-md);z-index:var(--dg-z-filter-popup,20);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}._filterSidebar_10bcx_33{min-width:0;padding:var(--mantine-spacing-sm);background-color:var(--mantine-color-body);border-left:1px solid var(--mantine-color-default-border);flex-direction:column;flex:none;display:flex}._filterSidebar_10bcx_33[data-side=left]{border-left:none;border-right:1px solid var(--mantine-color-default-border);order:-1}._filterSidebarBody_10bcx_51{flex:1;min-height:0}._headerFilterRow_h1geg_9{grid-column:1/-1;grid-template-columns:subgrid;top:var(--dg-header-height);z-index:var(--dg-z-header,6);display:grid;position:sticky}._headerFilterCell_h1geg_18{min-width:0;padding:calc(var(--dg-padding) / 2);background-color:var(--mantine-color-body);border-bottom:1px solid var(--mantine-color-default-border);align-items:center;gap:2px;display:flex;overflow:hidden}._headerFilterCell_h1geg_18[data-control-column=true]{padding:0}._headerFilterValue_h1geg_39{flex:1;min-width:0}._headerFilterOperator_h1geg_44{flex:none}._operatorItemActive_h1geg_48{color:var(--mantine-primary-color-filled);font-weight:600}._headerCell_18ma1_1{padding:0 var(--dg-padding);min-width:0;min-height:var(--dg-header-height);font-weight:600;font-size:var(--dg-header-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_18ma1_1[data-align=right]{justify-content:flex-end}._headerCell_18ma1_1[data-align=center]{justify-content:center}._headerCell_18ma1_1[data-control-column=true]{padding:0}._headerCellFiltered_18ma1_35 ._headerTitle_18ma1_35{color:var(--mantine-primary-color-filled)}._headerTitle_18ma1_35{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}._headerCell_18ma1_1[data-align=right] ._headerTitle_18ma1_35{text-align:right}._headerCell_18ma1_1[data-align=center] ._headerTitle_18ma1_35{justify-content:center;display:flex}._headerActions_18ma1_58{flex-shrink:0;align-items:center;gap:0;margin-left:auto;display:flex}._headerCell_18ma1_1[data-align=right] ._headerActions_18ma1_58{order:-1;margin-left:0;margin-right:auto}._headerAction_18ma1_58{display:none}._headerCell_18ma1_1:hover ._headerAction_18ma1_58,._headerCell_18ma1_1:focus-within ._headerAction_18ma1_58,._headerAction_18ma1_58[data-pinned-visible=true]{display:flex}._headerCellSortable_18ma1_87{cursor:pointer}._sortAction_18ma1_93:not([data-sorted]){opacity:.55}._sortAction_18ma1_93:not([data-sorted]):hover{opacity:1}._sortIndex_18ma1_103{color:var(--mantine-color-dimmed);text-align:center;min-width:10px;font-size:10px;font-weight:600;line-height:1}._headerCellDragging_18ma1_115{opacity:.4}._headerCellDropBefore_18ma1_119:before,._headerCellDropAfter_18ma1_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_18ma1_119:before{left:0}._headerCellDropAfter_18ma1_120:before{right:0}._columnSeparator_18ma1_140{z-index:1;justify-content:center;width:10px;height:50%;display:flex;position:absolute;top:25%;right:0;transform:translate(50%)}._headerCell_18ma1_1:last-child ._columnSeparator_18ma1_140{justify-content:flex-end;transform:none}._columnSeparatorResizable_18ma1_162{cursor:col-resize;touch-action:none}._columnSeparator_18ma1_140:after{content:"";background-color:#0000;width:1px;height:100%;transition:background-color .12s,width .12s}._headerCell_18ma1_1:hover ._columnSeparator_18ma1_140:after,._headerCell_18ma1_1:focus-within ._columnSeparator_18ma1_140:after{background-color:var(--mantine-color-default-border)}._columnSeparatorResizable_18ma1_162:hover:after,._columnSeparatorActive_18ma1_185:after{background-color:var(--mantine-primary-color-filled);width:2px}._menuItemActive_18ma1_191{background-color:var(--mantine-color-default-hover);font-weight:600}._toolbar_gwk05_1{align-items:center;gap:var(--mantine-spacing-xs);padding:6px var(--mantine-spacing-xs);flex-shrink:0;min-height:42px;display:flex}._toolbar_gwk05_1[data-with-bottom-border]{border-bottom:1px solid var(--mantine-color-default-border)}._toolbarSpacer_gwk05_15{flex:1}._summaryCount_gwk05_19{white-space:nowrap}._title_199r2_1{font-weight:500}._list_199r2_5{border:1px solid var(--mantine-color-default-border);border-radius:var(--mantine-radius-default);flex-direction:column;display:flex;overflow:hidden}._listHeader_199r2_13{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding:var(--mantine-spacing-xs) var(--mantine-spacing-sm);background-color:var(--mantine-color-default-hover);border-bottom:1px solid var(--mantine-color-default-border);display:flex}._headerLabel_199r2_23{cursor:pointer;font-weight:500}._rows_199r2_28{padding:calc(var(--mantine-spacing-xs) / 2) 0;flex-direction:column;display:flex}._row_199r2_28{padding:0 var(--mantine-spacing-sm)}._row_199r2_28:hover{background-color:var(--mantine-color-default-hover)}._rowBody_199r2_45{align-items:center}._rowLabelWrapper_199r2_49{flex:1;min-width:0}._rowLabel_199r2_49{justify-content:space-between;align-items:center;gap:var(--mantine-spacing-sm);padding-block:calc(var(--mantine-spacing-xs) * .75);cursor:pointer;display:flex}._rowText_199r2_63{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._rowHint_199r2_69{font-size:var(--mantine-font-size-xs);color:var(--mantine-color-dimmed);flex:none}._empty_199r2_75{padding:var(--mantine-spacing-xs) var(--mantine-spacing-sm)}
|
|
2
2
|
/*$vite$:1*/
|
package/docs/cell-selection.md
CHANGED
|
@@ -180,7 +180,7 @@ Unlike the Export cells item, `resolveRangeBounds` does not fall back to the foc
|
|
|
180
180
|
| `cellSelection` | Option | `"none" \| "single" \| "range"` | `"none"` | Turns the cell cursor, and the rectangle, on. |
|
|
181
181
|
| `TMDataGridCellSelectionMode` | Type | – | – | The type of `cellSelection`. |
|
|
182
182
|
| `onFocusedCellChange` | Callback | `(cell \| null) => void` | – | Follows the cursor. |
|
|
183
|
-
| `exportOptions` | Option | `TMDataGridExportOptions` | `
|
|
183
|
+
| `exportOptions` | Option | `TMDataGridExportOptions` | `csvExcelFormat()`, `"export"`, headers on, `"visible"` columns | Format, file name and header row of the Export cells item. See [Export](/docs/export). |
|
|
184
184
|
| `ui.state.focusedCell` | UI state | `{ rowId, columnId } \| null` | `null` | The cursor. |
|
|
185
185
|
| `ui.state.cellRange` | UI state | `{ anchor, focus } \| null` | `null` | The rectangle's two corners. |
|
|
186
186
|
| `ui.actions.setFocusedCell` · `setCellRange` | UI actions | – | – | Move either from your own code. |
|
package/docs/column-layout.md
CHANGED
|
@@ -14,7 +14,11 @@ hint: Drag a header to reorder · pin or hide from a column menu · drag a divid
|
|
|
14
14
|
## Hiding
|
|
15
15
|
|
|
16
16
|
**Hide column** in any column menu, and the column chooser for the whole list at once: a search field, one checkbox per column, show/hide all, and **Reset layout**.
|
|
17
|
-
The chooser
|
|
17
|
+
The chooser comes in three forms:
|
|
18
|
+
|
|
19
|
+
- `TMDataGrid.Menu.Columns` in the [grid menu](/docs/menu).
|
|
20
|
+
- **Manage columns**, a submenu of every column menu with the same items.
|
|
21
|
+
- `TMDataGrid.ColumnsPanel`, plain controls for a host that is not a menu.
|
|
18
22
|
|
|
19
23
|
`enableHiding: false` removes all of it; on a column it removes that column's
|
|
20
24
|
menu item and leaves it out of the panel, which lists what can be hidden and
|
|
@@ -42,8 +46,8 @@ computed from an `fr` value. The grid writes the column's rendered width into
|
|
|
42
46
|
To start pinned, set `initialState.columnPinning`. The slice is TanStack's
|
|
43
47
|
full `ColumnPinningState`, so a partial does not compile - name both sides.
|
|
44
48
|
A column pinned at mount has no rendered width to store, so it takes its
|
|
45
|
-
`size
|
|
46
|
-
|
|
49
|
+
`size`, clamped between `minSize` and `maxSize`; with none of them set that is
|
|
50
|
+
TanStack's default of `150`. Give such a column an explicit `size`:
|
|
47
51
|
|
|
48
52
|
```tsx
|
|
49
53
|
columnHelper.accessor("registration", { header: "Registration", size: 220 });
|
|
@@ -114,10 +118,11 @@ Columns are fluid by default. Each track is `minmax(minSize, flex fr)`.
|
|
|
114
118
|
|
|
115
119
|
| Column option | Effect |
|
|
116
120
|
| --- | --- |
|
|
117
|
-
| `minSize` | Minimum width, and the column's contribution to the grid minimum width. Defaults to `80`. |
|
|
121
|
+
| `minSize` | Minimum width, and the column's contribution to the grid minimum width. Also the floor of a resize and of a pinned width. Defaults to `80`, through `defaultColumn.minSize`. |
|
|
122
|
+
| `maxSize` | Ceiling of a resize, an autosize and a pinned width. Does not cap a fluid track. No default. |
|
|
118
123
|
| `meta.flex` | Share of the remaining width. Defaults to `1`. |
|
|
119
124
|
| `minSize === maxSize` | Fixed width. The column is never fluid. |
|
|
120
|
-
| `size` |
|
|
125
|
+
| `size` | Width of a column pinned at mount, clamped by `minSize` and `maxSize`. Ignored on a fluid column; a resize or an interactive pin stores the rendered width instead. Defaults to `150`. |
|
|
121
126
|
|
|
122
127
|
Drag a divider to resize. A column switches to a fixed pixel width the moment
|
|
123
128
|
it is resized or pinned, and the width is stored in `columnSizing`. The drag
|
|
@@ -148,8 +153,8 @@ the column's cells.
|
|
|
148
153
|
|
|
149
154
|
## Reset the layout
|
|
150
155
|
|
|
151
|
-
`resetSettings()` from the hook clears visibility, order, pinning
|
|
152
|
-
one call. The columns panel offers it as **Reset layout**.
|
|
156
|
+
`resetSettings()` from the hook clears visibility, order, pinning, widths and
|
|
157
|
+
grouping in one call. The columns panel offers it as **Reset layout**.
|
|
153
158
|
|
|
154
159
|
```tsx
|
|
155
160
|
const { resetSettings } = useTMDataGrid({ data, columns });
|
|
@@ -169,7 +174,7 @@ const { resetSettings } = useTMDataGrid({ data, columns });
|
|
|
169
174
|
| `meta.flex` | Column meta | `number` | `1` | Share of the remaining width. |
|
|
170
175
|
| `meta.autoSize` | Column meta | `boolean` | `false` | Autosize once, on the render the column's first cells appear in. |
|
|
171
176
|
| `minSize` / `maxSize` / `size` | Column options | `number` | `80` / – / – | Width bounds, and the fixed width once one applies. |
|
|
172
|
-
| `resetSettings` | Hook return | `() => void` | – | Clears visibility, order, pinning and
|
|
177
|
+
| `resetSettings` | Hook return | `() => void` | – | Clears visibility, order, pinning, widths and grouping. |
|
|
173
178
|
| `moveColumn` | Export | `({ table, columnId, targetId, side }) => void` | – | Moves a column beside another. |
|
|
174
179
|
| `moveColumnByStep` | Export | `({ table, columnId, direction }) => void` | – | Moves it one place. |
|
|
175
180
|
| `MoveColumnArgs` · `ColumnStepArgs` | Types | – | – | What `moveColumn` takes, and what `moveColumnByStep` and `getStepTargetColumn` take. |
|
package/docs/columns.md
CHANGED
|
@@ -88,6 +88,7 @@ Its type is `TMDataGridColumnMeta`.
|
|
|
88
88
|
| `options` | `TMDataGridOptionsSource` | - | The choices of a `select` / `multiSelect` column. See [Options](#options). |
|
|
89
89
|
| `flex` | `number` | `1` | Share of the remaining width. |
|
|
90
90
|
| `align` | `"left" \| "right" \| "center"` | `"left"` | Alignment, applied to both header and cells. |
|
|
91
|
+
| `colSpan` | `number \| ({ row, table }) => number` | `1` | Columns the cell covers on a row, counting itself. See [Spanning columns](#spanning-columns). |
|
|
91
92
|
| `autoSize` | `boolean` | `false` | Fit the column to its content once, on the render its first cells appear in. |
|
|
92
93
|
| `enableOrdering` | `boolean` | `true` | `false` keeps the column where it is. |
|
|
93
94
|
| `filter` | `TMDataGridColumnFilterOptions` | - | How this column filters. See [meta.filter](#metafilter). |
|
|
@@ -99,6 +100,7 @@ Its type is `TMDataGridColumnMeta`.
|
|
|
99
100
|
| --- | --- | --- | --- |
|
|
100
101
|
| `defaultOperator` | `TMDataGridFilterOperator` | The type's default | The operator a fresh filter starts with. See [Filtering](/docs/filtering#operators). |
|
|
101
102
|
| `control` | `TMDataGridFilterControlComponent` | By type and operator | Replaces the filter panel's value control. See [Filtering](/docs/filtering#replacing-the-value-control). |
|
|
103
|
+
| `url` | `boolean` | `true` | Keeps the column's filter out of a `persist.urlKey` link when `false`. See [Deep links](/docs/persistence#deep-links). |
|
|
102
104
|
|
|
103
105
|
```tsx
|
|
104
106
|
meta: {
|
|
@@ -185,6 +187,57 @@ A select column that declares no options still filters: the panel falls back to
|
|
|
185
187
|
the faceted values. Mantine's dropdowns are not virtualized, so use the function
|
|
186
188
|
form for very large sets.
|
|
187
189
|
|
|
190
|
+
## Spanning columns
|
|
191
|
+
|
|
192
|
+
`meta.colSpan` makes a column's cell cover the columns to its right.
|
|
193
|
+
A cell spanning `n` is one cell `n` columns wide, with one background and one
|
|
194
|
+
border, and the `n - 1` cells it covers do not render on that row.
|
|
195
|
+
A function decides per row:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
columnHelper.accessor("name", {
|
|
199
|
+
header: "Name",
|
|
200
|
+
meta: {
|
|
201
|
+
colSpan: ({ row }) => (row.getIsExpanded() ? Infinity : 1),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```demo
|
|
207
|
+
file: columns/SpanningCells.tsx
|
|
208
|
+
hint: Open a row with its chevron - its name takes the rest of the row, and the panel opens below.
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
- The span is counted over the displayed columns. Hiding or moving a column
|
|
212
|
+
changes what a span covers, so `Infinity` - "to the last of my columns" - is
|
|
213
|
+
usually safer than a count.
|
|
214
|
+
- A span stops at the last of your columns. It never covers the checkbox,
|
|
215
|
+
tree, details or edit lane.
|
|
216
|
+
- A span stops at the edge of its pinned block.
|
|
217
|
+
- A column covered by a span ignores its own `colSpan` on that row.
|
|
218
|
+
- Group rows ignore `colSpan`, and so does a row open in
|
|
219
|
+
[row edit mode](/docs/editing), where every column holds an editor.
|
|
220
|
+
- Sorting, filtering, copy and export still see every column. Autosize leaves
|
|
221
|
+
a spanning cell out of its column's measurement, and a column whose every
|
|
222
|
+
mounted cell spans fits its header.
|
|
223
|
+
- Under [cell selection](/docs/cell-selection) the spanning cell is one cell:
|
|
224
|
+
the arrow keys step over it, and a move onto a column it covers lands on it.
|
|
225
|
+
It is addressed by its first column: a range holds it when it holds that
|
|
226
|
+
column, and a range over only the columns it covers leaves it out. Copy and
|
|
227
|
+
export take every column of the range either way. When the column the focus
|
|
228
|
+
is on becomes covered, the focus moves to the spanning cell.
|
|
229
|
+
- Under [cell editing](/docs/editing) a covered column has no cell to open,
|
|
230
|
+
and Tab from the spanning cell's editor moves past the columns it covers.
|
|
231
|
+
A row keeps its cells while an editor is open in a column a span would
|
|
232
|
+
cover, and the span lands when the edit ends.
|
|
233
|
+
|
|
234
|
+
A cell renderer that reads `row.getIsExpanded()`, as the demo's does, has to
|
|
235
|
+
subscribe to the store - see
|
|
236
|
+
[Opening a row from elsewhere](/docs/row-details#opening-a-row-from-elsewhere).
|
|
237
|
+
|
|
238
|
+
The cell carries `aria-colspan` and `data-col-span` with the number of columns
|
|
239
|
+
it covers.
|
|
240
|
+
|
|
188
241
|
## Header groups
|
|
189
242
|
|
|
190
243
|
`columnHelper.group` nests columns under a shared header. The group is a header
|
|
@@ -231,8 +284,9 @@ Sizing, pinning, ordering and visibility are covered on
|
|
|
231
284
|
## The generated columns
|
|
232
285
|
|
|
233
286
|
Five lanes the grid adds when a feature needs them. All are **system lanes**:
|
|
234
|
-
|
|
235
|
-
|
|
287
|
+
pinned, with no column menu, never exported and never listed in the columns
|
|
288
|
+
panel. Four of them are fixed width with no resize handle; the tree lane can be
|
|
289
|
+
resized, and it is shown only while a grouping is active.
|
|
236
290
|
|
|
237
291
|
| Id | Appears when | Where |
|
|
238
292
|
| --- | --- | --- |
|
|
@@ -259,7 +313,9 @@ column can be placed in front of it.
|
|
|
259
313
|
| `meta.options` | Column meta | array \| `"faceted"` \| `(args) => …` | – | The choices of an option column. |
|
|
260
314
|
| `TMDataGridOptionsArgs` | Type | – | – | What a `meta.options` function receives: `{ table, column, row? }`. `row` is absent when the filter panel asks. |
|
|
261
315
|
| `meta.align` | Column meta | `"left" \| "right" \| "center"` | `"left"` | Header and cell alignment. |
|
|
262
|
-
| `meta.
|
|
316
|
+
| `meta.colSpan` | Column meta | `number \| (args) => number` | `1` | Columns the cell covers on a row. See [Spanning columns](#spanning-columns). |
|
|
317
|
+
| `TMDataGridColSpanArgs` | Type | `{ row, table }` | – | What a `meta.colSpan` function receives. |
|
|
318
|
+
| `meta.filter` | Column meta | `TMDataGridColumnFilterOptions` | – | How the column filters: `operators`, `defaultOperator`, `control`, `url`. |
|
|
263
319
|
| `meta.edit` | Column meta | `TMDataGridColumnEditOptions` | – | How the column edits: `enabled`, `field`, `editor`, `validate`, `mapValue`. |
|
|
264
320
|
| `resolveColumnOptions` | Export | `({ table, column, row? }) => options` | – | Normalises all three `meta.options` forms. |
|
|
265
321
|
| `optionsToComboboxData` | Export | `(options) => ComboboxData` | – | Options as Mantine `Select` data. |
|
package/docs/components.md
CHANGED
|
@@ -88,6 +88,7 @@ Pass the row type so the handlers are typed:
|
|
|
88
88
|
| `rowClassName` | `string \| (row) => string` | – | Class for a body row. See [Row styling](/docs/row-styling). |
|
|
89
89
|
| `rowStyle` | `TMDataGridRowStyle \| (row) => TMDataGridRowStyle` | – | Inline style for a body row. Set `--row-bg` rather than `background`. See [Row styling](/docs/row-styling#set-the-row-background). |
|
|
90
90
|
| `striped` | `boolean` | `false` | If set, every second row takes `--dg-row-striped-bg`. See [Striping](/docs/row-styling#striping). |
|
|
91
|
+
| `highlightOnHover` | `boolean` | On for rows that answer a click or a right-click | Whether a body row takes the hover tint. See [Hover](/docs/row-styling#hover). |
|
|
91
92
|
| `onScrollToTop` · `onScrollToBottom` · `onScrollToLeft` · `onScrollToRight` | `() => void` | – | Called once on arriving at that edge, not on mount and not per scroll event. See [Edge callbacks](/docs/scrolling#edge-callbacks). |
|
|
92
93
|
| `onReachEnd` | `() => void` | – | Called as the scroll nears the last row, once per row count. Sorting and filtering must be server-side. See [Infinite scroll](/docs/server-side#infinite-scroll). |
|
|
93
94
|
| `reachEndThreshold` | `number` | `10` | Rows before the end at which `onReachEnd` fires. |
|
package/docs/export.md
CHANGED
|
@@ -80,7 +80,7 @@ const grid = useTMDataGrid({
|
|
|
80
80
|
| `includeHeaders` | `boolean` | `true` | Determines whether the column labels are written as the first row. |
|
|
81
81
|
| `columns` | `"visible" \| "all" \| Array<string>` | `"visible"` | Which columns are written. See [What is written](#what-is-written). |
|
|
82
82
|
|
|
83
|
-
The option is read field by field, so
|
|
83
|
+
The option is read field by field, so an inline object literal needs no `useMemo`.
|
|
84
84
|
Every export of the grid reads it: the menu items, the hook, and the export item of the cell-range menu.
|
|
85
85
|
|
|
86
86
|
## Formats
|
|
@@ -290,7 +290,7 @@ See [Testing](/docs/testing).
|
|
|
290
290
|
|
|
291
291
|
| Name | Kind | Type | Default | What it does |
|
|
292
292
|
| --- | --- | --- | --- | --- |
|
|
293
|
-
| `exportOptions` | Option | `TMDataGridExportOptions` | `
|
|
293
|
+
| `exportOptions` | Option | `TMDataGridExportOptions` | `csvExcelFormat()`, `"export"`, headers on, `"visible"` columns | Format, file name and header row for every export of the grid. |
|
|
294
294
|
| `meta.enableExport` | Column meta | `boolean` | `true` | `false` leaves the column out of every export and of Ctrl+C. |
|
|
295
295
|
| `meta.exportValue` | Column meta | `({ value, row, column }) => unknown` | – | The value written in place of `row.getValue`. |
|
|
296
296
|
| `TMDataGridExportValueGetter` | Type | – | – | The type of `meta.exportValue`. |
|
package/docs/filtering.md
CHANGED
|
@@ -32,8 +32,8 @@ array only under `isAnyOf` / `isNoneOf` (the set the cell is tested against) and
|
|
|
32
32
|
|
|
33
33
|
A filter with an empty value stays in state, so a panel row survives while the
|
|
34
34
|
user types. (A header filter control has no row to keep alive and drops its
|
|
35
|
-
entry instead - see [inHeader](#inheader).)
|
|
36
|
-
indicator
|
|
35
|
+
entry instead - see [inHeader](#inheader).) The built-in matcher lets every row through, and
|
|
36
|
+
the filter does not set the header's filter indicator and produces no pill. `isFilterActive(value)` tests for that
|
|
37
37
|
state, and `activeColumnFilters` applies it across the whole slice, handing
|
|
38
38
|
back the entries that narrow the grid with their values typed as
|
|
39
39
|
`TMDataGridFilterValue` rather than as `unknown`. Entries in any other value
|
|
@@ -98,6 +98,8 @@ columnHelper.accessor("customer", {
|
|
|
98
98
|
|
|
99
99
|
`getColumnOperators(column)` returns the resolved list, and `getColumnDefaultOperator(column)` the operator a fresh filter on it opens on.
|
|
100
100
|
|
|
101
|
+
`meta.filter.url` keeps a column's filter out of a `persist.urlKey` link. See [Deep links](/docs/persistence#deep-links).
|
|
102
|
+
|
|
101
103
|
## The filters option
|
|
102
104
|
|
|
103
105
|
`filters` on `useTMDataGrid` decides where the filter controls render.
|
|
@@ -117,7 +119,7 @@ useTMDataGrid({ data, columns, filters: { surface: "sidebar", inHeader: true } }
|
|
|
117
119
|
`surface` and `inHeader` are two separate choices, not one list: `inHeader` composes with all three surfaces.
|
|
118
120
|
`{ surface: "none", inHeader: true }` is header filters and nothing else; `{ inHeader: true }` keeps the popup as well, for the multi-column work a header row has no room for.
|
|
119
121
|
|
|
120
|
-
The option is read field by field, so
|
|
122
|
+
The option is read field by field, so an inline object literal needs no `useMemo` - unlike `labels` and `persist`, it does not have to be referentially stable.
|
|
121
123
|
|
|
122
124
|
### surface: "popup"
|
|
123
125
|
|
|
@@ -132,7 +134,7 @@ Closing only hides the popup; the filters stay.
|
|
|
132
134
|
The same panel beside the rows, inside the grid frame and under the toolbar.
|
|
133
135
|
It is a column of the frame rather than a layer over it: the rows give up the width instead of being covered, a click in the table does not dismiss it, and clearing the filters leaves it standing with its **Add filter** button.
|
|
134
136
|
Escape closes it.
|
|
135
|
-
It starts open (`defaultOpen` defaults to `true` here) and renders the panel with `layout="stacked"`, because
|
|
137
|
+
It starts open (`defaultOpen` defaults to `true` here) and renders the panel with `layout="stacked"`, because the default 280px cannot fit the column, operator and value fields side by side.
|
|
136
138
|
|
|
137
139
|
```demo
|
|
138
140
|
file: columns/FilterSidebar.tsx
|
|
@@ -182,7 +184,7 @@ No props.
|
|
|
182
184
|
|
|
183
185
|
The panel of filter rows - one column / operator / value triple per filter, over an "Add filter" / "Clear all" footer.
|
|
184
186
|
It is a plain block with no title, no close button and no open state: it renders wherever it is mounted, and the popup and sidebar surfaces are wrappers around it.
|
|
185
|
-
It must be inside `<TMDataGrid>`, since it reads the grid from context, and it only reads and writes the table's `columnFilters` state, so
|
|
187
|
+
It must be inside `<TMDataGrid>`, since it reads the grid from context, and it only reads and writes the table's `columnFilters` state, so the same panel works unchanged under `manualFiltering`.
|
|
186
188
|
|
|
187
189
|
Pair it with `surface: "none"` so it is the only panel on the page, and drive it off `ui.state.filterPanelOpen` if it belongs behind a control of your own - `defaultOpen` sets where that state starts.
|
|
188
190
|
|
|
@@ -302,8 +304,8 @@ const SalaryFilter: TMDataGridFilterControlComponent = ({ layout, ...rest }) =>
|
|
|
302
304
|
layout === "header" ? <NumberInput {...} /> : <RangeSlider {...} />;
|
|
303
305
|
```
|
|
304
306
|
|
|
305
|
-
A control that ignores `layout` still works
|
|
306
|
-
|
|
307
|
+
A control that ignores `layout` still works and looks the same in every
|
|
308
|
+
surface, including a header cell, where the room is smallest. Every built-in
|
|
307
309
|
control honours it.
|
|
308
310
|
|
|
309
311
|
```demo
|
|
@@ -311,24 +313,111 @@ file: columns/CustomFilterControl.tsx
|
|
|
311
313
|
hint: Open the filter panel - Status offers chips, every other column the built-in control.
|
|
312
314
|
```
|
|
313
315
|
|
|
316
|
+
## Writing filters from your own interface
|
|
317
|
+
|
|
318
|
+
The grid's controls write plain TanStack state, so a control of your own does
|
|
319
|
+
the same. Write an envelope with `column.setFilterValue` or
|
|
320
|
+
`table.setColumnFilters`; the matcher, the pills, the header indicator and
|
|
321
|
+
`activeColumnFilters` all read it:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
import { emptyValueForOperator, type TMDataGridFilterValue } from "@jielga/tmdatagrid";
|
|
325
|
+
|
|
326
|
+
const status = grid.table.getColumn("status")!;
|
|
327
|
+
|
|
328
|
+
// A set filter, as the panel would write it.
|
|
329
|
+
status.setFilterValue({
|
|
330
|
+
operator: "isAnyOf",
|
|
331
|
+
value: ["active", "paused"],
|
|
332
|
+
} satisfies TMDataGridFilterValue);
|
|
333
|
+
|
|
334
|
+
// An empty envelope stays in state and matches every row.
|
|
335
|
+
status.setFilterValue({ operator: "isAnyOf", value: emptyValueForOperator("isAnyOf") });
|
|
336
|
+
|
|
337
|
+
// `undefined` removes the entry.
|
|
338
|
+
status.setFilterValue(undefined);
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`getColumnOperators(column)` returns the operators a column offers and
|
|
342
|
+
`getColumnDefaultOperator(column)` the one a fresh filter opens on;
|
|
343
|
+
`emptyValueForOperator(operator)` returns the empty value of the right shape.
|
|
344
|
+
|
|
345
|
+
To keep the grid's panel and place it yourself, set `filters: { surface: "none" }`
|
|
346
|
+
and render [TMDataGrid.FilterPanel](#tmdatagridfilterpanel) where it belongs.
|
|
347
|
+
To keep filtering on and drop only the column menu's Filter item, pass
|
|
348
|
+
`renderColumnMenuItems` to `TMDataGrid.Table` and leave out the item keyed
|
|
349
|
+
`"filter"` (see [Column menu](/docs/column-menu)). To replace every filter
|
|
350
|
+
control, set `enableColumnFilters: false` and write the envelope yourself;
|
|
351
|
+
filters in state still apply.
|
|
352
|
+
|
|
314
353
|
## Custom matching
|
|
315
354
|
|
|
316
355
|
To give a column its own matching logic instead of its own control, set
|
|
317
|
-
`filterFn` on the column definition.
|
|
318
|
-
|
|
356
|
+
`filterFn` on the column definition. A column `filterFn` replaces the shared
|
|
357
|
+
matcher for that column, so its third argument is the stored
|
|
358
|
+
`{ operator, value }` envelope, not the unwrapped value. Type it as
|
|
359
|
+
`TMDataGridFilterFn<TData>` and delegate to `tmDataGridFilterFn` for the
|
|
360
|
+
operators it does not handle itself. A column `filterFn` is also called with
|
|
361
|
+
half-typed envelopes, which the built-in matcher treats as matching every row,
|
|
362
|
+
so return `true` for `!isFilterActive(filter)` first:
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
import {
|
|
366
|
+
isFilterActive,
|
|
367
|
+
tmDataGridFilterFn,
|
|
368
|
+
type TMDataGridFilterFn,
|
|
369
|
+
} from "@jielga/tmdatagrid";
|
|
370
|
+
|
|
371
|
+
// Reads "contains" as "has this tag", so "ops" matches the tag "ops" and not
|
|
372
|
+
// "devops"; every other operator keeps the built-in matching.
|
|
373
|
+
const matchesTags: TMDataGridFilterFn<Employee> = (row, columnId, filter) => {
|
|
374
|
+
if (!isFilterActive(filter)) return true;
|
|
375
|
+
if (filter.operator === "contains") {
|
|
376
|
+
const wanted = String(filter.value).toLowerCase();
|
|
377
|
+
return row.original.tags.some((tag) => tag.toLowerCase() === wanted);
|
|
378
|
+
}
|
|
379
|
+
return tmDataGridFilterFn(row, columnId, filter);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
columnHelper.accessor((row) => row.tags.join(", "), {
|
|
383
|
+
id: "tags",
|
|
384
|
+
header: "Tags",
|
|
385
|
+
filterFn: matchesTags,
|
|
386
|
+
meta: { type: "string" },
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
`filter.value` is a string under the scalar operators, a `ReadonlyArray<string>`
|
|
391
|
+
under `isAnyOf` / `isNoneOf` and a `[min, max]` pair under `between`;
|
|
392
|
+
`filterValueShape(operator)` tells which. `matchesFilter(cellValue, filter)`
|
|
393
|
+
applies the built-in matching to a value derived by the function itself.
|
|
394
|
+
|
|
395
|
+
The column's filter controls do not change: the operators still come from
|
|
396
|
+
`meta.type` and `meta.filter.operators`, and the panel, the pills and the header
|
|
397
|
+
indicator keep reading the envelope. A filter function named by string also
|
|
398
|
+
receives the envelope and does not unwrap it, so TanStack's built-ins such as
|
|
399
|
+
`"includesString"` do not work as a column `filterFn`. Write custom matching as
|
|
400
|
+
a function.
|
|
319
401
|
|
|
320
402
|
## Turning it off
|
|
321
403
|
|
|
322
|
-
`enableColumnFilters: false` removes the
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
404
|
+
`enableColumnFilters: false` removes the Filter item from the column menu, the
|
|
405
|
+
`FilterButton`, the header filter row and the panel's column list, and disables
|
|
406
|
+
the panel's "Add filter" button. It does not clear `columnFilters`: an entry already in
|
|
407
|
+
state, or one written with `setFilterValue`, still narrows the rows, still shows
|
|
408
|
+
as a pill and still sets the header indicator. Call `table.resetColumnFilters()`
|
|
409
|
+
when switching the interface off. Under `filters.surface: "sidebar"`, set
|
|
410
|
+
`surface: "none"` as well, as the sidebar does not follow the switch.
|
|
411
|
+
|
|
412
|
+
`enableColumnFilter: false` on a column removes that column's menu item, its
|
|
413
|
+
entry in the panel's column list and its header control - the header cell
|
|
414
|
+
stays, empty.
|
|
326
415
|
|
|
327
416
|
## Reference
|
|
328
417
|
|
|
329
418
|
| Name | Kind | Type | Default | What it does |
|
|
330
419
|
| --- | --- | --- | --- | --- |
|
|
331
|
-
| `enableColumnFilters` | Table option | `boolean` | `true` | `false` removes the
|
|
420
|
+
| `enableColumnFilters` | Table option | `boolean` | `true` | `false` removes the menu item, the button, the header row and the panel's column list, and disables the panel's "Add filter" button. Filters already in state still apply. |
|
|
332
421
|
| `filters.surface` | Table option | `"popup" \| "sidebar" \| "none"` | `"popup"` | Which surface the table renders. |
|
|
333
422
|
| `filters.sidebarSide` | Table option | `"left" \| "right"` | `"right"` | Which side the sidebar sits on. |
|
|
334
423
|
| `filters.sidebarWidth` | Table option | `string` | `"280px"` | Width of the sidebar. |
|
|
@@ -339,7 +428,11 @@ header control - the header cell stays, empty.
|
|
|
339
428
|
| `meta.filter.operators` | Column meta | `readonly TMDataGridFilterOperator[]` | The type's list | The operators this column offers, a subset of its type's. |
|
|
340
429
|
| `meta.filter.defaultOperator` | Column meta | `TMDataGridFilterOperator` | The type's default, else the first offered | The operator a fresh filter opens on. |
|
|
341
430
|
| `meta.filter.control` | Column meta | `TMDataGridFilterControlComponent` | By type and operator | Replaces the value control. |
|
|
342
|
-
| `
|
|
431
|
+
| `meta.filter.url` | Column meta | `boolean` | `true` | Keeps the column's filter out of a `persist.urlKey` link when `false`. See [Deep links](/docs/persistence#deep-links). |
|
|
432
|
+
| `filterFn` | Column option | `TMDataGridFilterFn<TData>` \| name | `"tmDataGrid"` | Custom matching for one column. Receives the `{ operator, value }` envelope. |
|
|
433
|
+
| `TMDataGridFilterFn<TData>` | Type | `(row, columnId, filter: TMDataGridFilterValue, addMeta?) => boolean` | – | The signature of a column's own `filterFn`. |
|
|
434
|
+
| `tmDataGridFilterFn` | Export | `(row, columnId, filterValue: unknown) => boolean`, assignable to `TMDataGridFilterFn<TData>` | – | The shared matcher, for a custom `filterFn` to delegate to. |
|
|
435
|
+
| `matchesFilter` | Export | `(cellValue, filter: TMDataGridFilterValue) => boolean` | – | The built-in matching applied to one value. |
|
|
343
436
|
| `TMDataGrid.FilterPanel` | Component | `layout: "row" \| "stacked"` | `"row"` | The panel of filter rows, as a plain block. |
|
|
344
437
|
| `TMDataGrid.FilterButton` | Component | – | – | Toolbar button toggling the surface, with an active count. Seeds a filter row only when the panel is empty. |
|
|
345
438
|
| `TMDataGrid.FilterPills` | Component | takes `api` | – | Active filters as removable pills, renderable anywhere. |
|
package/docs/getting-started.md
CHANGED
|
@@ -112,6 +112,46 @@ file: getting-started/ToolbarAndFooter.tsx
|
|
|
112
112
|
[Grid anatomy](/docs/anatomy) for what each part is, and
|
|
113
113
|
[Toolbar](/docs/toolbar) for adding your own buttons among them.
|
|
114
114
|
|
|
115
|
+
## Coming from TanStack Table
|
|
116
|
+
|
|
117
|
+
`useTMDataGrid` takes TanStack's `TableOptions`, so a page built on
|
|
118
|
+
`useReactTable` keeps its `data`, `columns`, `state` and `onXChange` callbacks.
|
|
119
|
+
Go through these differences:
|
|
120
|
+
|
|
121
|
+
- **`getRowId`** - return the entity id. The index default points at another
|
|
122
|
+
record after a sort or a refetch, which breaks selection, expansion and
|
|
123
|
+
editing. Required once `editing` is set.
|
|
124
|
+
- **Stable `data` and `columns`** - define `columns` outside the component and
|
|
125
|
+
keep `data` referentially stable; a fresh `[]` for the empty case belongs in
|
|
126
|
+
a module-scope constant. Under `editing`, a transient `[]` drops every open
|
|
127
|
+
draft.
|
|
128
|
+
- **Sizing** - columns are fluid, `minmax(minSize, flex fr)`. `size` applies
|
|
129
|
+
only to a column pinned at mount, `maxSize` only to resizing and autosizing,
|
|
130
|
+
and `minSize` defaults to `80`. See
|
|
131
|
+
[Visibility, pinning, ordering and size](/docs/column-layout#sizing).
|
|
132
|
+
- **Defaults the grid changes** - `aggregationFn` is cleared, so grouping does
|
|
133
|
+
not sum anything on its own; `groupedColumnMode` is `"remove"`;
|
|
134
|
+
`autoResetExpanded` and `autoResetPageIndex` are off; `globalFilterFn` is the
|
|
135
|
+
fuzzy matcher. The full list is on
|
|
136
|
+
[useTMDataGrid](/docs/use-tm-data-grid#options).
|
|
137
|
+
- **Filters are envelopes** - `columnFilters` holds `{ operator, value }`, and
|
|
138
|
+
a column's own `filterFn` receives that envelope. See
|
|
139
|
+
[Filtering](/docs/filtering#custom-matching).
|
|
140
|
+
- **Interface the page already owns** - `enableGlobalFilter: false`, or no
|
|
141
|
+
`TMDataGrid.Search`, for the search; `enableColumnFilters: false`, or
|
|
142
|
+
`filters: { surface: "none" }` to keep filtering without the grid's panel.
|
|
143
|
+
See [Filtering](/docs/filtering#turning-it-off).
|
|
144
|
+
- **Page reset** - `resetPageOnQueryChange` (default `true`) returns to the
|
|
145
|
+
first page when a filter, the search, the sorting or the grouping changes
|
|
146
|
+
through the table. A data source re-filtered outside table state does not
|
|
147
|
+
trigger it; call `table.setPageIndex(0)` yourself, or use `manualFiltering`.
|
|
148
|
+
See [Server-side data](/docs/server-side).
|
|
149
|
+
- **State reads** - there is no `table.getState()`; read slices with
|
|
150
|
+
`useSelector(table.store, ...)`. See
|
|
151
|
+
[useTMDataGrid](/docs/use-tm-data-grid#reading-state).
|
|
152
|
+
- **Tests** - the grid publishes `data-dg-part`, `data-row-id` and
|
|
153
|
+
`data-column-id`, and no `data-testid`. See [Testing](/docs/testing).
|
|
154
|
+
|
|
115
155
|
## Where to go next
|
|
116
156
|
|
|
117
157
|
- **[Defining columns](/docs/columns)** - accessors, `meta.type`, and what each
|
package/docs/grouping.md
CHANGED
|
@@ -100,8 +100,8 @@ records inside collapsed sub-groups. It shows a tick once all of them are
|
|
|
100
100
|
selected and a dash while only some are.
|
|
101
101
|
|
|
102
102
|
Only the records are written to `rowSelection`. A group row is never in it, so
|
|
103
|
-
`getSelectedRowModel()` and
|
|
104
|
-
arranged.
|
|
103
|
+
`getSelectedRowModel()` and `onRowSelectionChange` do not depend on how the tree
|
|
104
|
+
is arranged.
|
|
105
105
|
|
|
106
106
|
Under `enableMultiRowSelection: false` group rows carry no checkbox.
|
|
107
107
|
|
|
@@ -125,8 +125,11 @@ While a column is grouped the grid renders the whole tree and relies on
|
|
|
125
125
|
virtualization. `TMDataGrid.Footer` greys its pager out and replaces the range
|
|
126
126
|
with `Grouped · all N rows`. Ungroup and paging resumes where it left off.
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
There is no option to keep the built-in pager active while grouped, and
|
|
129
|
+
`manualGrouping` does not change that: the pager greys out whenever `grouping`
|
|
130
|
+
is non-empty. To page a grouped grid, group and page on the server with
|
|
131
|
+
`manualPagination` and `manualGrouping`, and render the pager through
|
|
132
|
+
`renderPagination`, ignoring `isPagingActive`.
|
|
130
133
|
|
|
131
134
|
`isPagingActive(table, features)` is exported, so a custom pager can grey itself
|
|
132
135
|
out the same way:
|
|
@@ -150,12 +153,12 @@ server-side can set `enableGrouping: true` alongside `manualGrouping: true`. See
|
|
|
150
153
|
|
|
151
154
|
| Name | Kind | Type | Default | What it does |
|
|
152
155
|
| --- | --- | --- | --- | --- |
|
|
153
|
-
| `enableGrouping` | Table option | `boolean` | `true` | Group by and Ungroup menu items. Also a column option. |
|
|
156
|
+
| `enableGrouping` | Table option | `boolean` | `true`; `false` under `manualPagination` | Group by and Ungroup menu items, and the tree lane. Also a column option. |
|
|
154
157
|
| `groupedColumnMode` | Table option | `"reorder" \| "remove" \| false` | `"remove"` | Whether a grouped column leaves the grid or moves to the front. |
|
|
155
158
|
| `manualGrouping` | Table option | `boolean` | `false` | The rows arrive grouped. Required to group a server-paged grid. |
|
|
156
159
|
| `initialState.grouping` | Table option | `string[]` | `[]` | Column ids to group on at mount. A settings slice, so it persists. |
|
|
157
160
|
| `aggregationFn` | Column option | `TMDataGridAggregationName \| fn` | – | How a column fills in its group cells. Unset leaves them blank. |
|
|
158
|
-
| `aggregatedCell` | Column option | `(ctx) => ReactNode` |
|
|
161
|
+
| `aggregatedCell` | Column option | `(ctx) => ReactNode` | `cell` over the aggregate when `aggregationFn` is set, else blank | Renders a group row's value differently from a data row's. |
|
|
159
162
|
| `GROUP_COLUMN_ID` | Export | `"__group__"` | – | Id of the generated tree column. |
|
|
160
163
|
| `formatGroupValue` | Export | `(value) => string` | – | How the tree lane renders a group's value. |
|
|
161
164
|
| `getGroupDataRows` | Export | `(row) => Row[]` | – | Every record under a group row, at any depth. |
|