@drivenets/design-system 0.18.1 → 0.20.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/CHANGELOG.md +48 -0
- package/dist/index.cjs +17038 -10114
- package/dist/index.d.cts +1355 -444
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1354 -443
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17073 -10172
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +41 -41
- package/src/components/ds-bot-button/ds-bot-button.figma.ts +38 -0
- package/src/components/ds-bot-button/ds-bot-button.module.scss +41 -0
- package/src/components/ds-bot-button/ds-bot-button.tsx +48 -0
- package/src/components/ds-bot-button/ds-bot-button.types.ts +33 -0
- package/src/components/ds-bot-button/index.ts +2 -0
- package/src/components/ds-bot-button/net-gen-logo.tsx +46 -0
- package/src/components/ds-bulk-actions/components/action-button.tsx +42 -0
- package/src/components/ds-bulk-actions/components/menu-entries.tsx +76 -0
- package/src/components/ds-bulk-actions/components/overflow.tsx +75 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.figma.ts +28 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.module.scss +199 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.tsx +220 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.types.ts +170 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.unit.test.ts +195 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.utils.ts +91 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.utils.unit.test.ts +134 -0
- package/src/components/ds-bulk-actions/hooks/compute-bulk-actions-overflow.ts +85 -0
- package/src/components/ds-bulk-actions/hooks/use-bulk-actions-overflow.ts +153 -0
- package/src/components/ds-bulk-actions/index.ts +18 -0
- package/src/components/ds-button-v3/ds-button-v3.module.scss +2 -2
- package/src/components/ds-catalog-layout/ds-catalog-layout.figma.ts +1 -1
- package/src/components/ds-checkbox/ds-checkbox.figma.ts +3 -0
- package/src/components/ds-checkbox/ds-checkbox.module.scss +102 -20
- package/src/components/ds-checkbox/ds-checkbox.tsx +30 -2
- package/src/components/ds-checkbox/ds-checkbox.types.ts +10 -0
- package/src/components/ds-code-input/collapsed-code-field/collapsed-code-field.module.scss +169 -0
- package/src/components/ds-code-input/collapsed-code-field/collapsed-code-field.tsx +92 -0
- package/src/components/ds-code-input/collapsed-code-field/index.ts +1 -0
- package/src/components/ds-code-input/ds-code-input-panel/ds-code-input-panel.module.scss +110 -0
- package/src/components/ds-code-input/ds-code-input-panel/ds-code-input-panel.tsx +61 -0
- package/src/components/ds-code-input/ds-code-input-panel/index.ts +1 -0
- package/src/components/ds-code-input/ds-code-input.module.scss +25 -0
- package/src/components/ds-code-input/ds-code-input.tsx +401 -0
- package/src/components/ds-code-input/ds-code-input.types.ts +166 -0
- package/src/components/ds-code-input/ds-code-input.utils.ts +94 -0
- package/src/components/ds-code-input/ds-code-input.utils.unit.test.ts +166 -0
- package/src/components/ds-code-input/index.ts +2 -0
- package/src/components/ds-code-input/use-collapsed-viewport.ts +289 -0
- package/src/components/ds-code-input/use-editor-host.ts +87 -0
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +2 -0
- package/src/components/ds-empty-state/ds-empty-state.module.scss +16 -0
- package/src/components/ds-empty-state/ds-empty-state.tsx +45 -0
- package/src/components/ds-empty-state/ds-empty-state.types.ts +38 -0
- package/src/components/ds-empty-state/index.ts +3 -0
- package/src/components/ds-file-upload/ds-file-upload.tsx +4 -1
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/ds-filters-bar-builder.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/ds-filters-bar-builder.types.ts +41 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-clear-all.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/ds-filters-bar-conditions.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/ds-filters-bar-conditions.types.ts +30 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-pinned.ts +31 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/ds-filters-bar-query.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/ds-filters-bar-query.types.ts +22 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-saved-filters.ts +19 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-search.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-summary.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-toolbar.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-view-switch.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-view.ts +11 -0
- package/src/components/ds-filters-bar/components/index.ts +11 -0
- package/src/components/ds-filters-bar/ds-filters-bar.context.ts +69 -0
- package/src/components/ds-filters-bar/ds-filters-bar.tsx +120 -0
- package/src/components/ds-filters-bar/ds-filters-bar.types.ts +440 -0
- package/src/components/ds-filters-bar/ds-filters-bar.unit.test.ts +216 -0
- package/src/components/ds-filters-bar/ds-filters-bar.utils.ts +141 -0
- package/src/components/ds-filters-bar/index.ts +1 -0
- package/src/components/ds-form-control/ds-form-control.module.scss +18 -0
- package/src/components/ds-form-control/ds-form-control.tsx +61 -19
- package/src/components/ds-form-control/ds-form-control.types.ts +2 -1
- package/src/components/ds-icon/custom-icons/index.ts +2 -0
- package/src/components/ds-icon/custom-icons/special-adv-filters.tsx +28 -0
- package/src/components/ds-illustration/ds-illustration.figma.ts +34 -0
- package/src/components/ds-illustration/ds-illustration.module.scss +6 -0
- package/src/components/ds-illustration/ds-illustration.tsx +29 -0
- package/src/components/ds-illustration/ds-illustration.types.ts +45 -0
- package/src/components/ds-illustration/illustrations/configuration.tsx +51 -0
- package/src/components/ds-illustration/illustrations/device.tsx +133 -0
- package/src/components/ds-illustration/illustrations/done.tsx +107 -0
- package/src/components/{ds-catalog-layout/catalog-layout-empty-illustration.tsx → ds-illustration/illustrations/empty-inbox.tsx} +10 -14
- package/src/components/ds-illustration/illustrations/error.tsx +86 -0
- package/src/components/ds-illustration/illustrations/go-filter.tsx +51 -0
- package/src/components/ds-illustration/illustrations/illustration-clouds.tsx +10 -0
- package/src/components/ds-illustration/illustrations/index.ts +39 -0
- package/src/components/ds-illustration/illustrations/no-connection.tsx +54 -0
- package/src/components/ds-illustration/illustrations/no-credit-card.tsx +48 -0
- package/src/components/ds-illustration/illustrations/no-device.tsx +61 -0
- package/src/components/ds-illustration/illustrations/no-documents.tsx +52 -0
- package/src/components/ds-illustration/illustrations/no-gps.tsx +57 -0
- package/src/components/ds-illustration/illustrations/no-images.tsx +82 -0
- package/src/components/ds-illustration/illustrations/no-items-cart.tsx +86 -0
- package/src/components/ds-illustration/illustrations/no-messages.tsx +51 -0
- package/src/components/ds-illustration/illustrations/no-search-result.tsx +76 -0
- package/src/components/ds-illustration/illustrations/no-tasks.tsx +61 -0
- package/src/components/ds-illustration/illustrations/site.tsx +80 -0
- package/src/components/ds-illustration/index.ts +3 -0
- package/src/components/ds-main-menu/components/expanded-item/expanded-item.tsx +108 -0
- package/src/components/ds-main-menu/components/expanded-item/expanded-item.types.ts +8 -0
- package/src/components/ds-main-menu/components/expanded-item/index.ts +1 -0
- package/src/components/ds-main-menu/components/menu-graphic/index.ts +1 -0
- package/src/components/ds-main-menu/components/menu-graphic/menu-graphic.tsx +16 -0
- package/src/components/ds-main-menu/components/menu-graphic/menu-graphic.types.ts +7 -0
- package/src/components/ds-main-menu/components/tile-link/index.ts +1 -0
- package/src/components/ds-main-menu/components/tile-link/tile-link.tsx +85 -0
- package/src/components/ds-main-menu/components/tile-link/tile-link.types.ts +8 -0
- package/src/components/ds-main-menu/components/utility-link/index.ts +1 -0
- package/src/components/ds-main-menu/components/utility-link/utility-link.tsx +37 -0
- package/src/components/ds-main-menu/components/utility-link/utility-link.types.ts +7 -0
- package/src/components/ds-main-menu/ds-main-menu.figma.ts +17 -0
- package/src/components/ds-main-menu/ds-main-menu.module.scss +349 -0
- package/src/components/ds-main-menu/ds-main-menu.tsx +102 -0
- package/src/components/ds-main-menu/ds-main-menu.types.ts +86 -0
- package/src/components/ds-main-menu/ds-main-menu.utils.ts +40 -0
- package/src/components/ds-main-menu/index.ts +9 -0
- package/src/components/ds-modal/figma/ds-modal-footer.figma.ts +1 -1
- package/src/components/ds-pin-toggle/ds-pin-toggle.figma.ts +27 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.module.scss +41 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.tsx +43 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.types.ts +29 -0
- package/src/components/ds-pin-toggle/index.ts +2 -0
- package/src/components/ds-popover/components/popover-trigger/index.ts +1 -0
- package/src/components/ds-popover/components/popover-trigger/popover-trigger.tsx +15 -0
- package/src/components/ds-popover/ds-popover.context.ts +18 -0
- package/src/components/ds-popover/ds-popover.hover-intent.ts +65 -0
- package/src/components/ds-popover/ds-popover.tsx +164 -41
- package/src/components/ds-popover/ds-popover.types.ts +65 -0
- package/src/components/ds-popover/ds-popover.utils.ts +60 -0
- package/src/components/ds-popover/ds-popover.utils.unit.test.ts +25 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-delete-confirm.tsx +53 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-name-entry.tsx +64 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-name-modal.tsx +50 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/ds-saved-filters-row.module.scss +68 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/ds-saved-filters-row.tsx +83 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/index.ts +1 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-save.tsx +164 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/ds-saved-filters-trigger.module.scss +21 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/ds-saved-filters-trigger.tsx +237 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/index.ts +1 -0
- package/src/components/ds-saved-filters/components/index.ts +2 -0
- package/src/components/ds-saved-filters/ds-saved-filters.ts +6 -0
- package/src/components/ds-saved-filters/ds-saved-filters.types.ts +106 -0
- package/src/components/ds-saved-filters/ds-saved-filters.utils.ts +35 -0
- package/src/components/ds-saved-filters/hooks/index.ts +1 -0
- package/src/components/ds-saved-filters/hooks/use-picker-outside-dismiss.ts +42 -0
- package/src/components/ds-saved-filters/index.ts +2 -0
- package/src/components/ds-segment-group/ds-segment-group.module.scss +65 -37
- package/src/components/ds-segment-group/ds-segment-group.tsx +17 -5
- package/src/components/ds-segment-group/ds-segment-group.types.ts +20 -5
- package/src/components/ds-segment-group/figma/ds-segment-group-v2-item.figma.ts +109 -0
- package/src/components/ds-segment-group/figma/ds-segment-group-v2.figma.ts +31 -0
- package/src/components/ds-site-node/ds-site-node.tsx +2 -2
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.module.scss +12 -2
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +2 -3
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.module.scss +1 -6
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.tsx +6 -3
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +18 -7
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +27 -21
- package/src/components/ds-table/components/ds-table-header-label.module.scss +12 -0
- package/src/components/ds-table/components/ds-table-header-label.tsx +28 -0
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +0 -1
- package/src/components/ds-table/context/ds-table-context.tsx +8 -0
- package/src/components/ds-table/ds-table.module.scss +26 -16
- package/src/components/ds-table/ds-table.tsx +46 -14
- package/src/components/ds-table/ds-table.types.ts +33 -3
- package/src/components/ds-table/hooks/use-column-resize.ts +114 -11
- package/src/components/ds-table/hooks/use-scrollbar-spacer.ts +108 -0
- package/src/components/ds-table/hooks/use-scrollbar-spacer.unit.test.ts +26 -0
- package/src/components/ds-table/styles/_variables.scss +0 -2
- package/src/components/ds-table/utils/column-size.ts +274 -1
- package/src/components/ds-table/utils/column-size.unit.test.ts +157 -0
- package/src/components/ds-table/utils/constants.ts +13 -5
- package/src/components/ds-table/utils/table-columns.tsx +27 -13
- package/src/components/ds-table/utils/table-columns.unit.test.ts +44 -0
- package/src/components/ds-tag/ds-tag.figma.ts +23 -3
- package/src/components/ds-tag/ds-tag.module.scss +71 -7
- package/src/components/ds-tag/ds-tag.tsx +115 -14
- package/src/components/ds-tag/ds-tag.types.ts +70 -3
- package/src/components/ds-tag/ds-tag.unit.test.ts +23 -4
- package/src/components/ds-tag/index.ts +2 -2
- package/src/components/ds-text-input/ds-input-field-v02.figma.ts +2 -0
- package/src/components/ds-toggle/ds-toggle.module.scss +18 -0
- package/src/components/ds-toggle/ds-toggle.tsx +15 -9
- package/src/components/ds-toggle/ds-toggle.types.ts +6 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.module.scss +69 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.tsx +55 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.types.ts +43 -0
- package/src/components/ds-toggle-filter-data/index.ts +1 -0
- package/src/components/ds-tooltip/ds-tooltip.module.scss +8 -0
- package/src/components/ds-tooltip/ds-tooltip.tsx +7 -3
- package/src/components/ds-tooltip/ds-tooltip.types.ts +17 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.figma.ts +35 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.module.scss +150 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.tsx +161 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.types.ts +117 -0
- package/src/components/ds-top-bar-navigation/index.ts +2 -0
- package/src/components/ds-tree/ds-tree.tsx +10 -10
- package/src/components/ds-tree/ds-tree.types.ts +40 -7
- package/src/index.ts +8 -0
- package/src/utils/use-is-horizontally-overflowing.ts +35 -0
- package/src/components/ds-site-node/hooks/use-is-overflowing.ts +0 -31
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss +0 -112
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.tsx +0 -67
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.types.ts +0 -41
- package/src/components/ds-table/components/ds-table-bulk-actions/index.ts +0 -2
|
@@ -188,25 +188,257 @@ export const measureLeafHeaderWidths = (
|
|
|
188
188
|
return widths;
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
const CONTAINER_SIZE_SNAP_PX = 1;
|
|
192
|
+
|
|
193
|
+
const absorbSizingDrift = (sizing: ColumnSizingState, ids: string[], drift: number): void => {
|
|
194
|
+
for (const id of [...ids].reverse()) {
|
|
195
|
+
if (drift === 0) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const current = sizing[id];
|
|
200
|
+
if (current === undefined) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const nextSize = Math.max(RESIZE_MIN_COLUMN_WIDTH, current - drift);
|
|
205
|
+
drift -= current - nextSize;
|
|
206
|
+
sizing[id] = nextSize;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const toIdSet = (ids: ReadonlySet<string> | readonly string[]): ReadonlySet<string> =>
|
|
211
|
+
ids instanceof Set ? ids : new Set(ids);
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Grows `ids` so their combined increase equals `extra`. Shares follow each
|
|
215
|
+
* id's current width; leftover rounding is absorbed on the last id.
|
|
216
|
+
*/
|
|
217
|
+
const distributeExtraSpace = (
|
|
218
|
+
sizing: ColumnSizingState,
|
|
219
|
+
ids: string[],
|
|
220
|
+
extra: number,
|
|
221
|
+
maxById?: ReadonlyMap<string, number>,
|
|
222
|
+
): void => {
|
|
223
|
+
if (ids.length === 0 || extra <= 0) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let remaining = extra;
|
|
228
|
+
let open = ids.filter((id) => (sizing[id] ?? 0) < (maxById?.get(id) ?? DEFAULT_MAX_COLUMN_SIZE));
|
|
229
|
+
|
|
230
|
+
while (remaining > 0 && open.length > 0) {
|
|
231
|
+
let weightSum = 0;
|
|
232
|
+
|
|
233
|
+
for (const id of open) {
|
|
234
|
+
weightSum += sizing[id] ?? 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let assigned = 0;
|
|
238
|
+
const stillOpen: string[] = [];
|
|
239
|
+
|
|
240
|
+
for (const id of open) {
|
|
241
|
+
const current = sizing[id] ?? 0;
|
|
242
|
+
const max = maxById?.get(id) ?? DEFAULT_MAX_COLUMN_SIZE;
|
|
243
|
+
const room = max - current;
|
|
244
|
+
const rawShare = weightSum <= 0 ? remaining / open.length : remaining * (current / weightSum);
|
|
245
|
+
const share = Math.min(room, Math.round(rawShare));
|
|
246
|
+
sizing[id] = current + share;
|
|
247
|
+
assigned += share;
|
|
248
|
+
|
|
249
|
+
if (current + share < max) {
|
|
250
|
+
stillOpen.push(id);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let leftover = remaining - assigned;
|
|
255
|
+
|
|
256
|
+
for (const id of stillOpen) {
|
|
257
|
+
if (leftover <= 0) {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const max = maxById?.get(id) ?? DEFAULT_MAX_COLUMN_SIZE;
|
|
262
|
+
const add = Math.min(leftover, max - (sizing[id] ?? 0));
|
|
263
|
+
sizing[id] = (sizing[id] ?? 0) + add;
|
|
264
|
+
leftover -= add;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (assigned === 0 && leftover === remaining) {
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
remaining = leftover;
|
|
272
|
+
open = stillOpen.filter((id) => (sizing[id] ?? 0) < (maxById?.get(id) ?? DEFAULT_MAX_COLUMN_SIZE));
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
191
276
|
/**
|
|
192
277
|
* Sizing entries for leaves that are not yet in `existing`. Does not overwrite
|
|
193
|
-
* user-resized (or previously snapshotted) ids.
|
|
278
|
+
* user-resized (or previously snapshotted) ids. Rounds each measurement, then
|
|
279
|
+
* shifts leftover pixels onto the last missing leaf so the visible total
|
|
280
|
+
* matches the measured width (or the container, when they differ by 1px).
|
|
281
|
+
* When the measured total is short of the container, leftover space is shared
|
|
282
|
+
* across missing fill leaves in `fillableIds`.
|
|
194
283
|
*/
|
|
195
284
|
export const collectMissingLeafSizing = (
|
|
196
285
|
measured: Record<string, number>,
|
|
197
286
|
existing: ColumnSizingState,
|
|
287
|
+
containerWidth?: number,
|
|
288
|
+
fillableIds?: ReadonlySet<string> | readonly string[],
|
|
198
289
|
): ColumnSizingState => {
|
|
199
290
|
const next: ColumnSizingState = {};
|
|
291
|
+
const missingIds: string[] = [];
|
|
200
292
|
|
|
201
293
|
for (const [id, width] of Object.entries(measured)) {
|
|
202
294
|
if (existing[id] === undefined) {
|
|
203
295
|
next[id] = Math.round(width);
|
|
296
|
+
missingIds.push(id);
|
|
204
297
|
}
|
|
205
298
|
}
|
|
206
299
|
|
|
300
|
+
if (missingIds.length === 0) {
|
|
301
|
+
return next;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
let roundedMissingSum = 0;
|
|
305
|
+
let unroundedMissingSum = 0;
|
|
306
|
+
|
|
307
|
+
for (const id of missingIds) {
|
|
308
|
+
roundedMissingSum += next[id] ?? 0;
|
|
309
|
+
unroundedMissingSum += measured[id] ?? 0;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
absorbSizingDrift(next, missingIds, roundedMissingSum - Math.round(unroundedMissingSum));
|
|
313
|
+
|
|
314
|
+
if (containerWidth === undefined || !Number.isFinite(containerWidth) || containerWidth <= 0) {
|
|
315
|
+
return next;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let projected = 0;
|
|
319
|
+
|
|
320
|
+
for (const id of Object.keys(measured)) {
|
|
321
|
+
projected += existing[id] ?? next[id] ?? 0;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const delta = projected - containerWidth;
|
|
325
|
+
|
|
326
|
+
if (Math.abs(delta) <= CONTAINER_SIZE_SNAP_PX) {
|
|
327
|
+
absorbSizingDrift(next, missingIds, delta);
|
|
328
|
+
return next;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (delta < 0 && fillableIds) {
|
|
332
|
+
const fillable = toIdSet(fillableIds);
|
|
333
|
+
distributeExtraSpace(
|
|
334
|
+
next,
|
|
335
|
+
missingIds.filter((id) => fillable.has(id)),
|
|
336
|
+
-delta,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
207
340
|
return next;
|
|
208
341
|
};
|
|
209
342
|
|
|
343
|
+
const maxSizeOf = (id: string, boundsById: Map<string, ColumnSizeBoundsSource['columnDef']>): number =>
|
|
344
|
+
boundsById.get(id)?.maxSize ?? DEFAULT_MAX_COLUMN_SIZE;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* After clamp, grow fill leaves that still have room so the projected
|
|
348
|
+
* measured total matches the container. A leaf that hit `maxSize` must not
|
|
349
|
+
* leave a gap — leftover pixels go to siblings.
|
|
350
|
+
*/
|
|
351
|
+
export const growFillLeavesToContainer = (
|
|
352
|
+
sizing: ColumnSizingState,
|
|
353
|
+
existing: ColumnSizingState,
|
|
354
|
+
measuredIds: readonly string[],
|
|
355
|
+
containerWidth: number,
|
|
356
|
+
fillableIds: ReadonlySet<string> | readonly string[],
|
|
357
|
+
bounds: ReadonlyArray<ColumnSizeBoundsSource>,
|
|
358
|
+
): ColumnSizingState => {
|
|
359
|
+
if (!Number.isFinite(containerWidth) || containerWidth <= 0 || measuredIds.length === 0) {
|
|
360
|
+
return sizing;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
let projected = 0;
|
|
364
|
+
|
|
365
|
+
for (const id of measuredIds) {
|
|
366
|
+
projected += existing[id] ?? sizing[id] ?? 0;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const extra = containerWidth - projected;
|
|
370
|
+
if (extra <= 0) {
|
|
371
|
+
return sizing;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const fillable = toIdSet(fillableIds);
|
|
375
|
+
const growable = Object.keys(sizing).filter((id) => fillable.has(id));
|
|
376
|
+
if (growable.length === 0) {
|
|
377
|
+
return sizing;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const next = { ...sizing };
|
|
381
|
+
const boundsById = new Map(bounds.map((column) => [column.id, column.columnDef]));
|
|
382
|
+
distributeExtraSpace(next, growable, extra, new Map(growable.map((id) => [id, maxSizeOf(id, boundsById)])));
|
|
383
|
+
|
|
384
|
+
return next;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const minSizeOf = (id: string, boundsById: Map<string, ColumnSizeBoundsSource['columnDef']>): number =>
|
|
388
|
+
boundsById.get(id)?.minSize ?? RESIZE_MIN_COLUMN_WIDTH;
|
|
389
|
+
|
|
390
|
+
const shrinkColumnTrack = (
|
|
391
|
+
sizing: ColumnSizingState,
|
|
392
|
+
ids: readonly string[],
|
|
393
|
+
amount: number,
|
|
394
|
+
bounds: ReadonlyArray<ColumnSizeBoundsSource>,
|
|
395
|
+
): void => {
|
|
396
|
+
const boundsById = new Map(bounds.map((column) => [column.id, column.columnDef]));
|
|
397
|
+
let remaining = amount;
|
|
398
|
+
|
|
399
|
+
for (const id of [...ids].reverse()) {
|
|
400
|
+
if (remaining <= 0) {
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const current = sizing[id];
|
|
405
|
+
if (current === undefined) {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const nextSize = Math.max(minSizeOf(id, boundsById), current - remaining);
|
|
410
|
+
remaining -= current - nextSize;
|
|
411
|
+
sizing[id] = nextSize;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Grows or shrinks `ids` so the column track changes by `delta` (positive =
|
|
417
|
+
* grow). Used when the **Scrollbar spacer** toggles after seed; does not
|
|
418
|
+
* invent ids missing from `sizing`.
|
|
419
|
+
*/
|
|
420
|
+
export const shiftColumnTrack = (
|
|
421
|
+
sizing: ColumnSizingState,
|
|
422
|
+
ids: readonly string[],
|
|
423
|
+
delta: number,
|
|
424
|
+
bounds: ReadonlyArray<ColumnSizeBoundsSource>,
|
|
425
|
+
): ColumnSizingState => {
|
|
426
|
+
if (!Number.isFinite(delta) || delta === 0 || ids.length === 0) {
|
|
427
|
+
return sizing;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const next = { ...sizing };
|
|
431
|
+
|
|
432
|
+
if (delta > 0) {
|
|
433
|
+
const boundsById = new Map(bounds.map((column) => [column.id, column.columnDef]));
|
|
434
|
+
distributeExtraSpace(next, [...ids], delta, new Map(ids.map((id) => [id, maxSizeOf(id, boundsById)])));
|
|
435
|
+
} else {
|
|
436
|
+
shrinkColumnTrack(next, ids, -delta, bounds);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return clampColumnSizing(next, bounds);
|
|
440
|
+
};
|
|
441
|
+
|
|
210
442
|
/**
|
|
211
443
|
* Copy of `columnSizing` without injected utility leaves. Use at the public
|
|
212
444
|
* `onColumnSizingChange` boundary so consumers persist only their own columns.
|
|
@@ -222,3 +454,44 @@ export const omitBuiltinColumnSizing = (columnSizing: ColumnSizingState): Column
|
|
|
222
454
|
|
|
223
455
|
return next;
|
|
224
456
|
};
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Authored utility-column width, or `fallback` when the value is omitted,
|
|
460
|
+
* non-finite, or not positive.
|
|
461
|
+
*/
|
|
462
|
+
export const resolveUtilityColumnWidth = (width: number | undefined, fallback: number): number => {
|
|
463
|
+
if (width === undefined || !Number.isFinite(width) || width <= 0) {
|
|
464
|
+
return fallback;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return width;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Drops any utility ids from `columnSizing`, then applies `utilityColumnSizing`
|
|
472
|
+
* so those leaves always take the authored width.
|
|
473
|
+
*/
|
|
474
|
+
export const withUtilityColumnSizing = (
|
|
475
|
+
columnSizing: ColumnSizingState,
|
|
476
|
+
utilityColumnSizing: ColumnSizingState,
|
|
477
|
+
): ColumnSizingState => ({
|
|
478
|
+
...omitBuiltinColumnSizing(columnSizing),
|
|
479
|
+
...utilityColumnSizing,
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Authored sizes for injected utility leaves, keyed by column id.
|
|
484
|
+
*/
|
|
485
|
+
export const getUtilityColumnSizing = (
|
|
486
|
+
columns: ReadonlyArray<{ id?: string; size?: number }>,
|
|
487
|
+
): ColumnSizingState => {
|
|
488
|
+
const next: ColumnSizingState = {};
|
|
489
|
+
|
|
490
|
+
for (const column of columns) {
|
|
491
|
+
if (column.id !== undefined && BUILTIN_COLUMN_IDS.has(column.id) && column.size !== undefined) {
|
|
492
|
+
next[column.id] = column.size;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return next;
|
|
497
|
+
};
|
|
@@ -13,8 +13,13 @@ import {
|
|
|
13
13
|
getResizableColumnStyle,
|
|
14
14
|
getResizableHeaderStyle,
|
|
15
15
|
getResizeOriginSize,
|
|
16
|
+
getUtilityColumnSizing,
|
|
17
|
+
growFillLeavesToContainer,
|
|
16
18
|
isExplicitColumnWidth,
|
|
17
19
|
omitBuiltinColumnSizing,
|
|
20
|
+
resolveUtilityColumnWidth,
|
|
21
|
+
shiftColumnTrack,
|
|
22
|
+
withUtilityColumnSizing,
|
|
18
23
|
} from './column-size';
|
|
19
24
|
import {
|
|
20
25
|
EXPANDER_COLUMN_ID,
|
|
@@ -179,6 +184,115 @@ describe('collectMissingLeafSizing', () => {
|
|
|
179
184
|
it('returns an empty map when every measured id already has a sizing entry', () => {
|
|
180
185
|
expect(collectMissingLeafSizing({ a: 100 }, { a: 90 })).toEqual({});
|
|
181
186
|
});
|
|
187
|
+
|
|
188
|
+
it('reconciles independent rounding so seeded widths match the measured total', () => {
|
|
189
|
+
const next = collectMissingLeafSizing({ a: 500.6, b: 500.6 }, {});
|
|
190
|
+
|
|
191
|
+
expect(next).toEqual({ a: 501, b: 500 });
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('absorbs rounding drift into missing ids and leaves existing widths unchanged', () => {
|
|
195
|
+
expect(collectMissingLeafSizing({ a: 500.6, b: 500.6 }, { b: 501 }, 1001)).toEqual({ a: 500 });
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('does not snap seeded widths to the container when measured columns overflow it', () => {
|
|
199
|
+
expect(collectMissingLeafSizing({ a: 1000, b: 1000 }, {}, 1116)).toEqual({ a: 1000, b: 1000 });
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('snaps a 1px measured overflow to the container width', () => {
|
|
203
|
+
const next = collectMissingLeafSizing({ a: 558.5, b: 558.5 }, {}, 1116);
|
|
204
|
+
const total = Object.values(next).reduce((sum, width) => sum + width, 0);
|
|
205
|
+
|
|
206
|
+
expect(total).toBe(1116);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('distributes container underflow across fill leaves by their measured share', () => {
|
|
210
|
+
const next = collectMissingLeafSizing({ a: 200, b: 200 }, {}, 1200, ['a', 'b']);
|
|
211
|
+
|
|
212
|
+
expect(next).toEqual({ a: 600, b: 600 });
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('grows only fill leaves when the container is wider than the measured total', () => {
|
|
216
|
+
const next = collectMissingLeafSizing({ a: 200, b: 200, c: 200 }, {}, 1200, ['b', 'c']);
|
|
217
|
+
|
|
218
|
+
expect(next).toEqual({ a: 200, b: 500, c: 500 });
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('growFillLeavesToContainer', () => {
|
|
223
|
+
it('moves leftover space onto uncapped fill leaves after a sibling hits maxSize', () => {
|
|
224
|
+
const next = growFillLeavesToContainer(
|
|
225
|
+
{ a: 280, b: 360, c: 360 },
|
|
226
|
+
{},
|
|
227
|
+
['a', 'b', 'c'],
|
|
228
|
+
1200,
|
|
229
|
+
['a', 'b', 'c'],
|
|
230
|
+
[
|
|
231
|
+
{ id: 'a', columnDef: { maxSize: 280 } },
|
|
232
|
+
{ id: 'b', columnDef: {} },
|
|
233
|
+
{ id: 'c', columnDef: {} },
|
|
234
|
+
],
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
expect(next.a).toBe(280);
|
|
238
|
+
expect(next.b).toBeGreaterThan(360);
|
|
239
|
+
expect(next.c).toBeGreaterThan(360);
|
|
240
|
+
expect((next.a ?? 0) + (next.b ?? 0) + (next.c ?? 0)).toBe(1200);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('does not grow an explicit leaf when filling leftover space', () => {
|
|
244
|
+
const next = growFillLeavesToContainer(
|
|
245
|
+
{ a: 280, b: 360, c: 360 },
|
|
246
|
+
{},
|
|
247
|
+
['a', 'b', 'c'],
|
|
248
|
+
1200,
|
|
249
|
+
['b', 'c'],
|
|
250
|
+
[
|
|
251
|
+
{ id: 'a', columnDef: { maxSize: 280 } },
|
|
252
|
+
{ id: 'b', columnDef: {} },
|
|
253
|
+
{ id: 'c', columnDef: {} },
|
|
254
|
+
],
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
expect(next).toEqual({ a: 280, b: 460, c: 460 });
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe('shiftColumnTrack', () => {
|
|
262
|
+
const bounds = [
|
|
263
|
+
{ id: 'a', columnDef: {} },
|
|
264
|
+
{ id: 'b', columnDef: {} },
|
|
265
|
+
];
|
|
266
|
+
|
|
267
|
+
it('returns the same map when delta is 0', () => {
|
|
268
|
+
const sizing = { a: 200, b: 200 };
|
|
269
|
+
|
|
270
|
+
expect(shiftColumnTrack(sizing, ['a', 'b'], 0, bounds)).toBe(sizing);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it('shrinks from the last leaf when the spacer appears', () => {
|
|
274
|
+
const next = shiftColumnTrack({ a: 500, b: 500 }, ['a', 'b'], -10, bounds);
|
|
275
|
+
|
|
276
|
+
expect(next.a).toBe(500);
|
|
277
|
+
expect(next.b).toBe(490);
|
|
278
|
+
expect((next.a ?? 0) + (next.b ?? 0)).toBe(990);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it('grows leaves when the spacer disappears', () => {
|
|
282
|
+
const next = shiftColumnTrack({ a: 500, b: 490 }, ['a', 'b'], 10, bounds);
|
|
283
|
+
|
|
284
|
+
expect((next.a ?? 0) + (next.b ?? 0)).toBe(1000);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('does not shrink a leaf below minSize', () => {
|
|
288
|
+
const next = shiftColumnTrack({ a: 200, b: 52 }, ['a', 'b'], -10, [
|
|
289
|
+
{ id: 'a', columnDef: {} },
|
|
290
|
+
{ id: 'b', columnDef: { minSize: 52 } },
|
|
291
|
+
]);
|
|
292
|
+
|
|
293
|
+
expect(next.b).toBe(52);
|
|
294
|
+
expect(next.a).toBe(190);
|
|
295
|
+
});
|
|
182
296
|
});
|
|
183
297
|
|
|
184
298
|
describe('omitBuiltinColumnSizing', () => {
|
|
@@ -211,3 +325,46 @@ describe('omitBuiltinColumnSizing', () => {
|
|
|
211
325
|
expect(next).not.toBe(sizing);
|
|
212
326
|
});
|
|
213
327
|
});
|
|
328
|
+
|
|
329
|
+
describe('resolveUtilityColumnWidth', () => {
|
|
330
|
+
it('returns the fallback when the width is omitted, non-finite, or not positive', () => {
|
|
331
|
+
expect(resolveUtilityColumnWidth(undefined, 36)).toBe(36);
|
|
332
|
+
expect(resolveUtilityColumnWidth(0, 36)).toBe(36);
|
|
333
|
+
expect(resolveUtilityColumnWidth(-8, 36)).toBe(36);
|
|
334
|
+
expect(resolveUtilityColumnWidth(Number.NaN, 36)).toBe(36);
|
|
335
|
+
expect(resolveUtilityColumnWidth(Number.POSITIVE_INFINITY, 36)).toBe(36);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('returns a positive finite width as-is', () => {
|
|
339
|
+
expect(resolveUtilityColumnWidth(48, 36)).toBe(48);
|
|
340
|
+
expect(resolveUtilityColumnWidth(1, 36)).toBe(1);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
describe('withUtilityColumnSizing', () => {
|
|
345
|
+
it('strips inbound utility ids and overlays the authored widths', () => {
|
|
346
|
+
expect(
|
|
347
|
+
withUtilityColumnSizing(
|
|
348
|
+
{ [SELECT_COLUMN_ID]: 80, firstName: 200 },
|
|
349
|
+
{ [SELECT_COLUMN_ID]: 48, [EXPANDER_COLUMN_ID]: 40 },
|
|
350
|
+
),
|
|
351
|
+
).toEqual({ firstName: 200, [SELECT_COLUMN_ID]: 48, [EXPANDER_COLUMN_ID]: 40 });
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
describe('getUtilityColumnSizing', () => {
|
|
356
|
+
it('collects size entries for injected utility leaves only', () => {
|
|
357
|
+
expect(
|
|
358
|
+
getUtilityColumnSizing([
|
|
359
|
+
{ id: REORDER_COLUMN_ID, size: 80 },
|
|
360
|
+
{ id: EXPANDER_COLUMN_ID, size: 40 },
|
|
361
|
+
{ id: SELECT_COLUMN_ID, size: 48 },
|
|
362
|
+
{ id: 'firstName', size: 200 },
|
|
363
|
+
]),
|
|
364
|
+
).toEqual({
|
|
365
|
+
[REORDER_COLUMN_ID]: 80,
|
|
366
|
+
[EXPANDER_COLUMN_ID]: 40,
|
|
367
|
+
[SELECT_COLUMN_ID]: 48,
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
});
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Default text for empty table state
|
|
3
|
-
*/
|
|
4
|
-
export const EMPTY_TABLE_STATE_TEXT = 'No results.';
|
|
5
|
-
|
|
6
1
|
/**
|
|
7
2
|
* Column id used for the synthetic expander column injected when `expandable` is set.
|
|
8
3
|
*/
|
|
@@ -55,6 +50,19 @@ export const SKELETON_ROW_COUNT = 5;
|
|
|
55
50
|
*/
|
|
56
51
|
export const RESIZE_MIN_COLUMN_WIDTH = 52;
|
|
57
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Pixel width of the full-height resize overlay divider. Must match
|
|
55
|
+
* `$resize-divider-width` in `styles/_variables.scss`.
|
|
56
|
+
*/
|
|
57
|
+
export const RESIZE_DIVIDER_WIDTH = 2;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Rest width of the header **Scrollbar spacer** when the body overflows
|
|
61
|
+
* vertically. Must match `$scrollbar-default-size` in `styles/_scrollbars.scss`.
|
|
62
|
+
* Hover (12px) is intentionally not tracked.
|
|
63
|
+
*/
|
|
64
|
+
export const SCROLLBAR_SPACER_WIDTH = 10;
|
|
65
|
+
|
|
58
66
|
/**
|
|
59
67
|
* Width change (in px) applied per Arrow key press when a resize handle is
|
|
60
68
|
* focused.
|
|
@@ -3,6 +3,7 @@ import { DsSkeletonText } from '../../ds-skeleton';
|
|
|
3
3
|
import { DsTableHeaderSelectableCell } from '../components/ds-table-header-selectable-cell';
|
|
4
4
|
import { DsTableRowExpandableCell } from '../components/ds-table-row-expandable-cell';
|
|
5
5
|
import { DsTableRowSelectableCell } from '../components/ds-table-row-selectable-cell';
|
|
6
|
+
import { resolveUtilityColumnWidth } from './column-size';
|
|
6
7
|
import {
|
|
7
8
|
EXPANDER_COLUMN_ID,
|
|
8
9
|
EXPANDER_COLUMN_WIDTH,
|
|
@@ -19,6 +20,9 @@ export type GetAugmentedColumnsOptions = {
|
|
|
19
20
|
reorderable: boolean;
|
|
20
21
|
virtualized: boolean;
|
|
21
22
|
showSelectAllCheckbox: boolean;
|
|
23
|
+
selectableColumnWidth?: number;
|
|
24
|
+
expandableColumnWidth?: number;
|
|
25
|
+
reorderableColumnWidth?: number;
|
|
22
26
|
};
|
|
23
27
|
|
|
24
28
|
const EXPLICIT_SIZE_META = { hasExplicitSize: true } as const;
|
|
@@ -41,6 +45,13 @@ const stampExplicitSize = <TData, TValue>(columns: ColumnDef<TData, TValue>[]):
|
|
|
41
45
|
return { ...column, meta: { ...column.meta, ...EXPLICIT_SIZE_META } };
|
|
42
46
|
});
|
|
43
47
|
|
|
48
|
+
/** Pin min/max so the table-wide resize `minSize` cannot stretch this column. */
|
|
49
|
+
const pinUtilityColumnSize = (width: number) => ({
|
|
50
|
+
size: width,
|
|
51
|
+
minSize: width,
|
|
52
|
+
maxSize: width,
|
|
53
|
+
});
|
|
54
|
+
|
|
44
55
|
/**
|
|
45
56
|
* Prepends the builtin select / expander / reorder columns when those features
|
|
46
57
|
* are on. Reorder is omitted for virtualized tables. Unshift order yields
|
|
@@ -48,19 +59,24 @@ const stampExplicitSize = <TData, TValue>(columns: ColumnDef<TData, TValue>[]):
|
|
|
48
59
|
*/
|
|
49
60
|
export const getAugmentedColumns = <TData, TValue>(
|
|
50
61
|
columns: ColumnDef<TData, TValue>[],
|
|
51
|
-
{
|
|
62
|
+
{
|
|
63
|
+
selectable,
|
|
64
|
+
expandable,
|
|
65
|
+
reorderable,
|
|
66
|
+
virtualized,
|
|
67
|
+
showSelectAllCheckbox,
|
|
68
|
+
selectableColumnWidth,
|
|
69
|
+
expandableColumnWidth,
|
|
70
|
+
reorderableColumnWidth,
|
|
71
|
+
}: GetAugmentedColumnsOptions,
|
|
52
72
|
): ColumnDef<TData, TValue>[] => {
|
|
53
73
|
const augmentedColumns: ColumnDef<TData, TValue>[] = stampExplicitSize(columns);
|
|
54
74
|
|
|
55
75
|
if (selectable) {
|
|
76
|
+
const width = resolveUtilityColumnWidth(selectableColumnWidth, SELECT_COLUMN_WIDTH);
|
|
56
77
|
augmentedColumns.unshift({
|
|
57
78
|
id: SELECT_COLUMN_ID,
|
|
58
|
-
|
|
59
|
-
// Pin min/max to the fixed width: `enableResizing: false` blocks the
|
|
60
|
-
// handle but not the table-wide resize `minSize`, which would otherwise
|
|
61
|
-
// stretch this column.
|
|
62
|
-
minSize: SELECT_COLUMN_WIDTH,
|
|
63
|
-
maxSize: SELECT_COLUMN_WIDTH,
|
|
79
|
+
...pinUtilityColumnSize(width),
|
|
64
80
|
enableSorting: false,
|
|
65
81
|
enableResizing: false,
|
|
66
82
|
meta: EXPLICIT_SIZE_META,
|
|
@@ -70,11 +86,10 @@ export const getAugmentedColumns = <TData, TValue>(
|
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
if (expandable) {
|
|
89
|
+
const width = resolveUtilityColumnWidth(expandableColumnWidth, EXPANDER_COLUMN_WIDTH);
|
|
73
90
|
augmentedColumns.unshift({
|
|
74
91
|
id: EXPANDER_COLUMN_ID,
|
|
75
|
-
|
|
76
|
-
minSize: EXPANDER_COLUMN_WIDTH,
|
|
77
|
-
maxSize: EXPANDER_COLUMN_WIDTH,
|
|
92
|
+
...pinUtilityColumnSize(width),
|
|
78
93
|
enableSorting: false,
|
|
79
94
|
enableResizing: false,
|
|
80
95
|
meta: EXPLICIT_SIZE_META,
|
|
@@ -84,13 +99,12 @@ export const getAugmentedColumns = <TData, TValue>(
|
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
if (reorderable && !virtualized) {
|
|
102
|
+
const width = resolveUtilityColumnWidth(reorderableColumnWidth, REORDER_COLUMN_WIDTH);
|
|
87
103
|
// Cell is rendered inline by DsTableRow when it encounters REORDER_COLUMN_ID,
|
|
88
104
|
// since the drag handle needs row-level useSortable state.
|
|
89
105
|
augmentedColumns.unshift({
|
|
90
106
|
id: REORDER_COLUMN_ID,
|
|
91
|
-
|
|
92
|
-
minSize: REORDER_COLUMN_WIDTH,
|
|
93
|
-
maxSize: REORDER_COLUMN_WIDTH,
|
|
107
|
+
...pinUtilityColumnSize(width),
|
|
94
108
|
enableSorting: false,
|
|
95
109
|
enableResizing: false,
|
|
96
110
|
meta: EXPLICIT_SIZE_META,
|
|
@@ -100,6 +100,50 @@ describe('getAugmentedColumns', () => {
|
|
|
100
100
|
}
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
+
it('pins custom utility column widths and ignores them when the feature is off', () => {
|
|
104
|
+
const columns = getAugmentedColumns([nameColumn], {
|
|
105
|
+
...noFeatures,
|
|
106
|
+
selectable: true,
|
|
107
|
+
expandable: true,
|
|
108
|
+
reorderable: true,
|
|
109
|
+
selectableColumnWidth: 48,
|
|
110
|
+
expandableColumnWidth: 40,
|
|
111
|
+
reorderableColumnWidth: 80,
|
|
112
|
+
});
|
|
113
|
+
const boundsById = new Map(columns.map((column) => [column.id, column]));
|
|
114
|
+
|
|
115
|
+
expect(boundsById.get(SELECT_COLUMN_ID)?.size).toBe(48);
|
|
116
|
+
expect(boundsById.get(SELECT_COLUMN_ID)?.minSize).toBe(48);
|
|
117
|
+
expect(boundsById.get(SELECT_COLUMN_ID)?.maxSize).toBe(48);
|
|
118
|
+
expect(boundsById.get(EXPANDER_COLUMN_ID)?.size).toBe(40);
|
|
119
|
+
expect(boundsById.get(EXPANDER_COLUMN_ID)?.minSize).toBe(40);
|
|
120
|
+
expect(boundsById.get(EXPANDER_COLUMN_ID)?.maxSize).toBe(40);
|
|
121
|
+
expect(boundsById.get(REORDER_COLUMN_ID)?.size).toBe(80);
|
|
122
|
+
expect(boundsById.get(REORDER_COLUMN_ID)?.minSize).toBe(80);
|
|
123
|
+
expect(boundsById.get(REORDER_COLUMN_ID)?.maxSize).toBe(80);
|
|
124
|
+
|
|
125
|
+
expect(
|
|
126
|
+
columnIds(getAugmentedColumns([nameColumn], { ...noFeatures, selectableColumnWidth: 48 })),
|
|
127
|
+
).toEqual(['name']);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('falls back to the default width when the custom width is invalid', () => {
|
|
131
|
+
const columns = getAugmentedColumns([nameColumn], {
|
|
132
|
+
...noFeatures,
|
|
133
|
+
selectable: true,
|
|
134
|
+
expandable: true,
|
|
135
|
+
reorderable: true,
|
|
136
|
+
selectableColumnWidth: 0,
|
|
137
|
+
expandableColumnWidth: Number.NaN,
|
|
138
|
+
reorderableColumnWidth: -10,
|
|
139
|
+
});
|
|
140
|
+
const boundsById = new Map(columns.map((column) => [column.id, column]));
|
|
141
|
+
|
|
142
|
+
expect(boundsById.get(SELECT_COLUMN_ID)?.size).toBe(SELECT_COLUMN_WIDTH);
|
|
143
|
+
expect(boundsById.get(EXPANDER_COLUMN_ID)?.size).toBe(EXPANDER_COLUMN_WIDTH);
|
|
144
|
+
expect(boundsById.get(REORDER_COLUMN_ID)?.size).toBe(REORDER_COLUMN_WIDTH);
|
|
145
|
+
});
|
|
146
|
+
|
|
103
147
|
it('stamps hasExplicitSize on authored leaves and builtins, not on unsized leaves', () => {
|
|
104
148
|
const columns = getAugmentedColumns(
|
|
105
149
|
[
|