@human-kit/svelte-components 1.0.0-alpha.18 → 1.0.0-alpha.19

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.
@@ -0,0 +1,76 @@
1
+ <script lang="ts">
2
+ import { Table } from '../index';
3
+ import type { TableColumnWidth } from '../root/context';
4
+
5
+ let currentColumnWidths = $state<Map<string, TableColumnWidth> | undefined>(undefined);
6
+ </script>
7
+
8
+ <div data-testid="narrow-min-width-container" style="width: 240px; overflow-x: auto;">
9
+ <Table.Root
10
+ aria-label="Narrow min width table"
11
+ bind:columnWidths={currentColumnWidths}
12
+ class="min-w-full border-collapse text-left"
13
+ >
14
+ <Table.Header>
15
+ <Table.Row>
16
+ <Table.Column id="request" isRowHeader textValue="Request" minWidth={75}>
17
+ <Table.ColumnHeaderCell data-testid="narrow-request-header-cell">
18
+ <div class="flex items-center justify-between gap-3">
19
+ <span>Request</span>
20
+ <Table.ColumnResizer
21
+ data-testid="narrow-request-resizer"
22
+ class="inline-flex w-3 cursor-col-resize justify-center"
23
+ />
24
+ </div>
25
+ </Table.ColumnHeaderCell>
26
+ </Table.Column>
27
+ <Table.Column id="requester" textValue="Requester" minWidth={140}>
28
+ <Table.ColumnHeaderCell data-testid="narrow-requester-header-cell">
29
+ <div class="flex items-center justify-between gap-3">
30
+ <span>Requester</span>
31
+ <Table.ColumnResizer class="inline-flex w-3 cursor-col-resize justify-center" />
32
+ </div>
33
+ </Table.ColumnHeaderCell>
34
+ </Table.Column>
35
+ <Table.Column id="area" textValue="Area">
36
+ <Table.ColumnHeaderCell data-testid="narrow-area-header-cell">
37
+ <div class="flex items-center justify-between gap-3">
38
+ <span>Area</span>
39
+ <Table.ColumnResizer class="inline-flex w-3 cursor-col-resize justify-center" />
40
+ </div>
41
+ </Table.ColumnHeaderCell>
42
+ </Table.Column>
43
+ <Table.Column id="status" textValue="Status">
44
+ <Table.ColumnHeaderCell data-testid="narrow-status-header-cell">
45
+ <div class="flex items-center justify-between gap-3">
46
+ <span>Status</span>
47
+ <Table.ColumnResizer class="inline-flex w-3 cursor-col-resize justify-center" />
48
+ </div>
49
+ </Table.ColumnHeaderCell>
50
+ </Table.Column>
51
+ <Table.Column id="total" textValue="Total">
52
+ <Table.ColumnHeaderCell data-testid="narrow-total-header-cell">
53
+ <div class="flex items-center justify-between gap-3">
54
+ <span>Total</span>
55
+ <Table.ColumnResizer class="inline-flex w-3 cursor-col-resize justify-center" />
56
+ </div>
57
+ </Table.ColumnHeaderCell>
58
+ </Table.Column>
59
+ </Table.Row>
60
+ </Table.Header>
61
+
62
+ <Table.Body>
63
+ <Table.Row id="pr-001">
64
+ <Table.Cell>PR-001</Table.Cell>
65
+ <Table.Cell>Ana Gomez</Table.Cell>
66
+ <Table.Cell>Ops</Table.Cell>
67
+ <Table.Cell>Pending</Table.Cell>
68
+ <Table.Cell>$1,520</Table.Cell>
69
+ </Table.Row>
70
+ </Table.Body>
71
+ </Table.Root>
72
+ </div>
73
+
74
+ <output data-testid="narrow-min-width-widths"
75
+ >{JSON.stringify(Object.fromEntries(currentColumnWidths ?? new Map()))}</output
76
+ >
@@ -0,0 +1,3 @@
1
+ declare const TableColumnResizerNarrowMinWidthTest: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type TableColumnResizerNarrowMinWidthTest = ReturnType<typeof TableColumnResizerNarrowMinWidthTest>;
3
+ export default TableColumnResizerNarrowMinWidthTest;
@@ -213,7 +213,16 @@ export function createTableContext(options = {}) {
213
213
  return hiddenColumnIds.has(columnId);
214
214
  }
215
215
  function getColumnMinWidth(columnId) {
216
- return getColumnRegistrationById(columnId)?.minWidth;
216
+ const registration = getColumnRegistrationById(columnId);
217
+ if (!registration)
218
+ return undefined;
219
+ if (registration.minWidth !== undefined)
220
+ return registration.minWidth;
221
+ if (!isColumnResizable(columnId) &&
222
+ !isRelativeColumnWidth(getEffectiveColumnWidthSpec(columnId))) {
223
+ return undefined;
224
+ }
225
+ return getColumnWidthBounds(columnId).minWidth;
217
226
  }
218
227
  function getColumnMaxWidth(columnId) {
219
228
  return getColumnRegistrationById(columnId)?.maxWidth;
@@ -483,6 +492,8 @@ export function createTableContext(options = {}) {
483
492
  let fixedPxTotal = 0;
484
493
  let percentTotal = 0;
485
494
  let totalFr = 0;
495
+ const resolvedVisibleWidths = getResolvedVisibleColumnWidths();
496
+ const tableWidth = getMeasuredTableWidth();
486
497
  for (const token of getVisibleOrderedColumnTokens()) {
487
498
  const column = columns.get(token);
488
499
  if (!column)
@@ -513,6 +524,25 @@ export function createTableContext(options = {}) {
513
524
  const availableWidthExpression = availableWidthTerms.length === 1
514
525
  ? availableWidthTerms[0]
515
526
  : `(${availableWidthTerms.join(' - ')})`;
527
+ if (tableWidth !== undefined) {
528
+ const targetRelativeTotal = Math.max(tableWidth - fixedPxTotal, 0);
529
+ let actualRelativeTotal = 0;
530
+ for (const token of getVisibleOrderedColumnTokens()) {
531
+ const column = columns.get(token);
532
+ if (!column)
533
+ continue;
534
+ const spec = parseColumnWidth(getEffectiveColumnWidthSpec(column.id));
535
+ if (!spec || spec.unit === 'px')
536
+ continue;
537
+ actualRelativeTotal += resolvedVisibleWidths.get(column.id) ?? 0;
538
+ }
539
+ if (Math.abs(actualRelativeTotal - targetRelativeTotal) > 1) {
540
+ const constrainedWidth = resolvedVisibleWidths.get(columnId);
541
+ if (constrainedWidth !== undefined) {
542
+ return `${constrainedWidth}px`;
543
+ }
544
+ }
545
+ }
516
546
  if (frShare === 1) {
517
547
  return `calc(${availableWidthExpression})`;
518
548
  }
@@ -1195,6 +1225,7 @@ export function createTableContext(options = {}) {
1195
1225
  cellOrder.push(cell.key);
1196
1226
  }
1197
1227
  notifyLayout();
1228
+ notifyWidth();
1198
1229
  }
1199
1230
  function unregisterCell(key) {
1200
1231
  cells.delete(key);
@@ -1207,6 +1238,7 @@ export function createTableContext(options = {}) {
1207
1238
  notifyFocus();
1208
1239
  }
1209
1240
  notifyLayout();
1241
+ notifyWidth();
1210
1242
  }
1211
1243
  function isCellFocused(key) {
1212
1244
  return focusedCellKey === key;
@@ -210,6 +210,20 @@
210
210
  return columns;
211
211
  });
212
212
 
213
+ const minimumTableWidth = $derived.by(() => {
214
+ if (!hasResizable && !ctx.hasRelativeVisibleColumnWidths()) return undefined;
215
+
216
+ let total = 0;
217
+ let hasMinimumWidth = false;
218
+ for (const column of layoutColumns) {
219
+ if (column.minWidth === undefined) continue;
220
+ total += column.minWidth;
221
+ hasMinimumWidth = true;
222
+ }
223
+
224
+ return hasMinimumWidth ? total : undefined;
225
+ });
226
+
213
227
  const explicitManagedTableWidth = $derived.by(() => {
214
228
  void $layoutVersion;
215
229
  if (ctx.hasRelativeVisibleColumnWidths()) return undefined;
@@ -303,6 +317,8 @@
303
317
  ctx.refreshMeasuredLayout();
304
318
  };
305
319
 
320
+ refreshMeasuredLayout();
321
+
306
322
  window.addEventListener('resize', refreshMeasuredLayout);
307
323
  window.visualViewport?.addEventListener('resize', refreshMeasuredLayout);
308
324
 
@@ -475,7 +491,11 @@
475
491
  style:width={resolvedTableWidth !== undefined
476
492
  ? `${resolvedTableWidth}px`
477
493
  : fallbackRelativeTableWidth}
478
- style:min-width={resolvedTableWidth !== undefined ? '0' : undefined}
494
+ style:min-width={minimumTableWidth !== undefined
495
+ ? `${minimumTableWidth}px`
496
+ : resolvedTableWidth !== undefined
497
+ ? '0'
498
+ : undefined}
479
499
  aria-label={ariaLabel}
480
500
  aria-labelledby={ariaLabelledby}
481
501
  aria-colcount={ariaColCount}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@human-kit/svelte-components",
3
- "version": "1.0.0-alpha.18",
3
+ "version": "1.0.0-alpha.19",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "svelte": "./dist/index.js",