@sebgroup/green-core 2.19.0 → 2.20.0-rc.20251215154321804

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.
Files changed (64) hide show
  1. package/components/badge/badge.component.d.ts +0 -23
  2. package/components/badge/badge.component.js +18 -105
  3. package/components/badge/badge.styles.js +96 -2
  4. package/components/checkbox/checkbox.component.js +24 -22
  5. package/components/checkbox/checkbox.styles.js +0 -8
  6. package/components/dropdown/dropdown.component.js +4 -1
  7. package/components/index.d.ts +2 -0
  8. package/components/index.js +2 -0
  9. package/components/input/input.styles.js +10 -1
  10. package/components/pagination/index.d.ts +1 -0
  11. package/components/pagination/index.js +1 -0
  12. package/components/pagination/pagination.component.d.ts +82 -0
  13. package/components/pagination/pagination.component.js +441 -0
  14. package/components/pagination/pagination.d.ts +2 -0
  15. package/components/pagination/pagination.js +6 -0
  16. package/components/pagination/pagination.styles.d.ts +1 -0
  17. package/components/pagination/pagination.styles.js +19 -0
  18. package/components/table/index.d.ts +2 -0
  19. package/components/table/index.js +6 -0
  20. package/components/table/table.component.d.ts +140 -0
  21. package/components/table/table.component.js +1090 -0
  22. package/components/table/table.d.ts +2 -0
  23. package/components/table/table.imports.d.ts +6 -0
  24. package/components/table/table.imports.js +63 -0
  25. package/components/table/table.js +6 -0
  26. package/components/table/table.stories.data.d.ts +53 -0
  27. package/components/table/table.stories.data.js +401 -0
  28. package/components/table/table.styles.d.ts +1 -0
  29. package/components/table/table.styles.js +788 -0
  30. package/components/table/table.types.d.ts +155 -0
  31. package/components/table/table.types.js +24 -0
  32. package/custom-elements.json +12280 -10492
  33. package/gds-element.js +1 -1
  34. package/generated/locales/da.d.ts +32 -0
  35. package/generated/locales/da.js +32 -0
  36. package/generated/locales/de.d.ts +32 -0
  37. package/generated/locales/de.js +32 -0
  38. package/generated/locales/fi.d.ts +32 -0
  39. package/generated/locales/fi.js +32 -0
  40. package/generated/locales/fr.d.ts +32 -0
  41. package/generated/locales/fr.js +32 -0
  42. package/generated/locales/it.d.ts +32 -0
  43. package/generated/locales/it.js +32 -0
  44. package/generated/locales/nl.d.ts +32 -0
  45. package/generated/locales/nl.js +32 -0
  46. package/generated/locales/no.d.ts +32 -0
  47. package/generated/locales/no.js +33 -1
  48. package/generated/locales/sv.d.ts +32 -0
  49. package/generated/locales/sv.js +32 -0
  50. package/generated/react/index.d.ts +8 -6
  51. package/generated/react/index.js +8 -6
  52. package/generated/react/input/index.d.ts +1 -1
  53. package/generated/react/pagination/index.d.ts +395 -0
  54. package/generated/react/pagination/index.js +13 -0
  55. package/generated/react/table/index.d.ts +395 -0
  56. package/generated/react/table/index.js +13 -0
  57. package/package.json +8 -1
  58. package/primitives/field-base/field-base.component.d.ts +1 -0
  59. package/primitives/field-base/field-base.component.js +8 -0
  60. package/primitives/field-base/field-base.styles.js +9 -1
  61. package/pure.d.ts +2 -0
  62. package/pure.js +2 -0
  63. package/shared-styles/rbcb-toggle.style.js +41 -12
  64. package/utils/helpers/custom-element-scoping.js +1 -1
@@ -0,0 +1,1090 @@
1
+ import {
2
+ __decorateClass,
3
+ __privateAdd,
4
+ __privateGet,
5
+ __privateMethod,
6
+ __privateSet
7
+ } from "../../chunks/chunk.QU3DSPNU.js";
8
+ var _cache, _cacheDuration, _templateCache, _GdsTable_instances, Density_get, hasSelection_get, isAllSelected_get, isPartialSelection_get, getCacheKey_fn, isCacheValid_fn, loadData_fn, getSlotContent_fn, renderCell_fn, renderCellContent_fn, renderSortIcon_fn, hasHeaderContent_fn, renderHeaderControls_fn, renderColumnHeader_fn, renderActionsHeader_fn, renderSelectableHeader_fn, renderColumnHeaders_fn, renderTableHeader_fn, renderTableCell_fn, renderSelectableCell_fn, renderRowCells_fn, renderActionsCell_fn, renderTableRow_fn, renderCheckbox_fn, renderSkeletonCell_fn, renderSkeletonRow_fn, renderTableBody_fn, renderTable_fn, renderErrorState_fn, renderEmptyState_fn, renderFooter_fn, handleSearch_fn, handleSearchClear_fn, handleSort_fn, handlePageChange_fn, handlePageSizeChange_fn, handleColumnVisibility_fn, handleSelectAll_fn, handleRowSelect_fn, selectAllInternal_fn, clearSelectionInternal_fn, emitSelectionChange_fn, initializeScrollTracking_fn, updateVerticalScrollState_fn, updateHorizontalScrollState_fn;
9
+ import { localized, msg } from "@lit/localize";
10
+ import { property, state } from "lit/decorators.js";
11
+ import { classMap } from "lit/directives/class-map.js";
12
+ import { ifDefined } from "lit/directives/if-defined.js";
13
+ import { styleMap } from "lit/directives/style-map.js";
14
+ import { when } from "lit/directives/when.js";
15
+ import { GdsElement } from "../../gds-element.js";
16
+ import { watchMediaQuery } from "../../utils/decorators/index.js";
17
+ import { styleExpressionProperty } from "../../utils/decorators/style-expression-property.js";
18
+ import { watch } from "../../utils/decorators/watch.js";
19
+ import { forSpaceTokensAndCustomValues } from "../../utils/helpers/index.js";
20
+ import {
21
+ gdsCustomElement,
22
+ html
23
+ } from "../../utils/helpers/custom-element-scoping.js";
24
+ import * as Table from "./table.imports";
25
+ import * as Types from "./table.types";
26
+ import * as Types2 from "./table.types";
27
+ let GdsTable = class extends GdsElement {
28
+ constructor() {
29
+ super(...arguments);
30
+ __privateAdd(this, _GdsTable_instances);
31
+ __privateAdd(this, _cache, {});
32
+ __privateAdd(this, _cacheDuration, 5 * 60 * 1e3);
33
+ __privateAdd(this, _templateCache, /* @__PURE__ */ new Map());
34
+ this.options = [5, 10, 20, 50, 100];
35
+ this.page = 1;
36
+ this.rows = 10;
37
+ this.columns = [];
38
+ this.density = "comfortable";
39
+ this.selectable = false;
40
+ this.responsive = false;
41
+ this.plain = false;
42
+ this.searchable = false;
43
+ this.settings = false;
44
+ this.striped = false;
45
+ this.nocache = false;
46
+ this.variant = "secondary";
47
+ this._isMobile = false;
48
+ this._view = {
49
+ page: this.page,
50
+ rows: this.rows,
51
+ searchQuery: "",
52
+ visibleColumns: /* @__PURE__ */ new Set()
53
+ };
54
+ this._loaded = true;
55
+ this._loading = false;
56
+ this._rowsState = [];
57
+ this._total = 0;
58
+ this._selected = /* @__PURE__ */ new Set();
59
+ this._error = null;
60
+ }
61
+ _handleMobile(matches) {
62
+ this._isMobile = matches;
63
+ }
64
+ _onDataChange() {
65
+ __privateSet(this, _cache, {});
66
+ __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
67
+ }
68
+ _onColumnsChange() {
69
+ __privateSet(this, _cache, {});
70
+ this._view = {
71
+ ...this._view,
72
+ page: Number(this.page ?? 1),
73
+ rows: Number(this.rows ?? 10),
74
+ visibleColumns: new Set(
75
+ this.columns.filter((col) => col.visible !== false).map((col) => col.key)
76
+ )
77
+ };
78
+ }
79
+ connectedCallback() {
80
+ super.connectedCallback();
81
+ this.updateComplete.then(() => {
82
+ __privateMethod(this, _GdsTable_instances, initializeScrollTracking_fn).call(this);
83
+ });
84
+ }
85
+ render() {
86
+ const classes = {
87
+ table: true,
88
+ plain: this.plain,
89
+ striped: this.striped,
90
+ [this.density]: this.density
91
+ };
92
+ return html`
93
+ <div class="${classMap(classes)}">
94
+ ${[
95
+ __privateMethod(this, _GdsTable_instances, renderHeaderControls_fn).call(this),
96
+ when(
97
+ this._error,
98
+ () => __privateMethod(this, _GdsTable_instances, renderErrorState_fn).call(this),
99
+ () => when(
100
+ this._rowsState.length === 0 && !this._loading,
101
+ () => __privateMethod(this, _GdsTable_instances, renderEmptyState_fn).call(this),
102
+ () => __privateMethod(this, _GdsTable_instances, renderTable_fn).call(this)
103
+ )
104
+ ),
105
+ __privateMethod(this, _GdsTable_instances, renderFooter_fn).call(this)
106
+ ]}
107
+ </div>
108
+ `;
109
+ }
110
+ /**
111
+ * Public API
112
+ * Clear all selections
113
+ */
114
+ clearSelection() {
115
+ __privateMethod(this, _GdsTable_instances, clearSelectionInternal_fn).call(this);
116
+ __privateMethod(this, _GdsTable_instances, emitSelectionChange_fn).call(this);
117
+ }
118
+ /**
119
+ * Select all rows
120
+ */
121
+ selectAll() {
122
+ __privateMethod(this, _GdsTable_instances, selectAllInternal_fn).call(this);
123
+ __privateMethod(this, _GdsTable_instances, emitSelectionChange_fn).call(this);
124
+ }
125
+ /**
126
+ * Select specific rows by indices
127
+ */
128
+ setSelection(indices) {
129
+ const validIndices = indices.filter(
130
+ (i) => i >= 0 && i < this._rowsState.length
131
+ );
132
+ this._selected = new Set(validIndices);
133
+ __privateMethod(this, _GdsTable_instances, emitSelectionChange_fn).call(this);
134
+ this.requestUpdate();
135
+ }
136
+ /**
137
+ * Get selected row data
138
+ */
139
+ getSelection() {
140
+ const indices = Array.from(this._selected);
141
+ return {
142
+ indices,
143
+ data: indices.map((i) => this._rowsState[i])
144
+ };
145
+ }
146
+ };
147
+ _cache = new WeakMap();
148
+ _cacheDuration = new WeakMap();
149
+ _templateCache = new WeakMap();
150
+ _GdsTable_instances = new WeakSet();
151
+ Density_get = function() {
152
+ return Types.DENSITY_CONFIG[this.density];
153
+ };
154
+ hasSelection_get = function() {
155
+ return this._selected.size > 0;
156
+ };
157
+ isAllSelected_get = function() {
158
+ return this._rowsState.length > 0 && this._selected.size === this._rowsState.length;
159
+ };
160
+ isPartialSelection_get = function() {
161
+ return __privateGet(this, _GdsTable_instances, hasSelection_get) && !__privateGet(this, _GdsTable_instances, isAllSelected_get);
162
+ };
163
+ getCacheKey_fn = function() {
164
+ return JSON.stringify({
165
+ page: this._view.page,
166
+ rows: this._view.rows,
167
+ sortColumn: this._view.sortColumn,
168
+ sortDirection: this._view.sortDirection,
169
+ searchQuery: this._view.searchQuery
170
+ });
171
+ };
172
+ isCacheValid_fn = function(entry) {
173
+ return Date.now() - entry.timestamp < __privateGet(this, _cacheDuration);
174
+ };
175
+ loadData_fn = async function() {
176
+ if (!this.data) return;
177
+ if (!this.nocache) {
178
+ const cacheKey = __privateMethod(this, _GdsTable_instances, getCacheKey_fn).call(this);
179
+ const cachedData = __privateGet(this, _cache)[cacheKey];
180
+ if (cachedData && __privateMethod(this, _GdsTable_instances, isCacheValid_fn).call(this, cachedData)) {
181
+ this._rowsState = cachedData.rows;
182
+ this._total = cachedData.total;
183
+ this._loaded = false;
184
+ return;
185
+ }
186
+ }
187
+ this._loading = true;
188
+ this._error = null;
189
+ try {
190
+ const response = await this.data({
191
+ page: this._view.page,
192
+ rows: this._view.rows,
193
+ sortColumn: this._view.sortColumn,
194
+ sortDirection: this._view.sortDirection,
195
+ searchQuery: this._view.searchQuery
196
+ });
197
+ if (!this.nocache) {
198
+ const cacheKey = __privateMethod(this, _GdsTable_instances, getCacheKey_fn).call(this);
199
+ __privateGet(this, _cache)[cacheKey] = {
200
+ rows: response.rows,
201
+ total: response.total,
202
+ timestamp: Date.now()
203
+ };
204
+ }
205
+ this._rowsState = response.rows;
206
+ this._total = response.total;
207
+ this._selected.clear();
208
+ this._loaded = false;
209
+ this.dispatchEvent(
210
+ new CustomEvent("gds-table-data-loaded", {
211
+ detail: response,
212
+ bubbles: true
213
+ })
214
+ );
215
+ } catch (error) {
216
+ this._error = error;
217
+ this.dispatchEvent(
218
+ new CustomEvent("gds-table-data-error", {
219
+ detail: error,
220
+ bubbles: true
221
+ })
222
+ );
223
+ } finally {
224
+ this._loading = false;
225
+ }
226
+ };
227
+ /**
228
+ * Retrieves template content for the given slot name.
229
+ * Uses caching to prevent repeated DOM queries for better performance in large tables.
230
+ */
231
+ getSlotContent_fn = function(slot) {
232
+ if (!slot) return null;
233
+ if (!__privateGet(this, _templateCache).has(slot)) {
234
+ const template = this.querySelector(
235
+ `template[name="${slot}"]`
236
+ );
237
+ __privateGet(this, _templateCache).set(slot, template);
238
+ }
239
+ return __privateGet(this, _templateCache).get(slot)?.content.cloneNode(true);
240
+ };
241
+ renderCell_fn = function(config, row) {
242
+ if (!config) return null;
243
+ if (Array.isArray(config)) {
244
+ return config.map((c) => __privateMethod(this, _GdsTable_instances, renderCell_fn).call(this, c, row));
245
+ }
246
+ const resolve = (value) => typeof value === "function" ? value(row) : value;
247
+ switch (config.type) {
248
+ case "badge": {
249
+ const variant = resolve(config.variant) || "information";
250
+ const size = resolve(config.size) || __privateGet(this, _GdsTable_instances, Density_get).badge;
251
+ return html`
252
+ <gds-badge size="${size}" variant="${variant}">
253
+ ${resolve(config.value)}
254
+ </gds-badge>
255
+ `;
256
+ }
257
+ case "image": {
258
+ const src = resolve(config.src);
259
+ if (!src) return null;
260
+ const width = resolve(config.width) || "24px";
261
+ const height = resolve(config.height) || "24px";
262
+ const borderRadius = resolve(config["border-radius"]) || "max";
263
+ const objectFit = resolve(config["object-fit"]) || "cover";
264
+ const alt = resolve(config.alt) || "";
265
+ return html`
266
+ <gds-img
267
+ src="${src}"
268
+ alt="${alt}"
269
+ width="${width}"
270
+ height="${height}"
271
+ border-radius="${borderRadius}"
272
+ object-fit="${objectFit}"
273
+ object-position="center"
274
+ ></gds-img>
275
+ `;
276
+ }
277
+ case "icon": {
278
+ const template = resolve(config.template);
279
+ const size = resolve(config.size);
280
+ const color = resolve(config.color);
281
+ const clonedSlot = __privateMethod(this, _GdsTable_instances, getSlotContent_fn).call(this, template);
282
+ if (!clonedSlot) return null;
283
+ if (clonedSlot instanceof DocumentFragment) {
284
+ const iconElement = clonedSlot.firstElementChild;
285
+ if (iconElement) {
286
+ if (size) iconElement.setAttribute("size", size);
287
+ if (color) iconElement.setAttribute("color", color);
288
+ }
289
+ }
290
+ return clonedSlot;
291
+ }
292
+ case "button": {
293
+ const size = resolve(config.size) || __privateGet(this, _GdsTable_instances, Density_get).button;
294
+ const variant = resolve(config.variant);
295
+ const rank = resolve(config.rank);
296
+ const label = resolve(config.label);
297
+ const template = resolve(config.template);
298
+ const clonedSlot = __privateMethod(this, _GdsTable_instances, getSlotContent_fn).call(this, template);
299
+ const content = [label, clonedSlot];
300
+ return html`
301
+ <gds-button
302
+ size="${size}"
303
+ variant="${variant || "neutral"}"
304
+ rank="${rank || "secondary"}"
305
+ @click="${(e) => {
306
+ e.stopPropagation();
307
+ config.onClick(row);
308
+ }}"
309
+ >
310
+ ${content}
311
+ </gds-button>
312
+ `;
313
+ }
314
+ case "link": {
315
+ const href = resolve(config.href);
316
+ if (!href) return null;
317
+ const label = resolve(config.label);
318
+ const target = resolve(config.target);
319
+ const download = resolve(config.download);
320
+ const template = resolve(config.template);
321
+ const clonedSlot = __privateMethod(this, _GdsTable_instances, getSlotContent_fn).call(this, template);
322
+ const content = [label, clonedSlot];
323
+ return html`
324
+ <gds-link
325
+ href=${ifDefined(href)}
326
+ target=${ifDefined(target)}
327
+ .download=${download}
328
+ text-decoration="underline"
329
+ >
330
+ ${content}
331
+ </gds-link>
332
+ `;
333
+ }
334
+ case "context-menu": {
335
+ const items = config.items;
336
+ const size = __privateGet(this, _GdsTable_instances, Density_get).button;
337
+ return html`
338
+ <gds-context-menu>
339
+ <gds-button
340
+ slot="trigger"
341
+ size="${size}"
342
+ rank="tertiary"
343
+ label="${msg("Actions")}"
344
+ >
345
+ <gds-icon-dot-grid-one-horizontal></gds-icon-dot-grid-one-horizontal>
346
+ </gds-button>
347
+ ${items.map((item) => {
348
+ const label = resolve(item.label);
349
+ return html`
350
+ <gds-menu-item @click="${() => item.onClick(row)}">
351
+ ${label}
352
+ </gds-menu-item>
353
+ `;
354
+ })}
355
+ </gds-context-menu>
356
+ `;
357
+ }
358
+ case "formatted-number": {
359
+ const value = resolve(config.value);
360
+ const formatter = Table.FormatNumber[config.format || "decimalsAndThousands"];
361
+ return formatter(value, config.locale, config.currency, config.decimals);
362
+ }
363
+ case "formatted-account": {
364
+ const value = resolve(config.value);
365
+ const formatter = Table.FormatAccount[config.format || "seb-account"];
366
+ return formatter(value);
367
+ }
368
+ case "formatted-date": {
369
+ const value = resolve(config.value);
370
+ const formatter = Table.FormatDate[config.format || "dateLong"];
371
+ return formatter(value, config.locale);
372
+ }
373
+ default:
374
+ return null;
375
+ }
376
+ };
377
+ /**
378
+ * Renders the content of a table cell with support for custom transformations,
379
+ * cell types, and responsive mobile labels.
380
+ *
381
+ * Value resolution priority:
382
+ * 1. column.value - Direct transform function
383
+ * 2. cell.value - Cell type configuration (badge, button, etc.)
384
+ * 3. row[column.key] - Raw data value
385
+ */
386
+ renderCellContent_fn = function(row, column) {
387
+ const { cell } = column;
388
+ let value;
389
+ if (column.value) {
390
+ value = column.value(row);
391
+ } else if (cell?.value) {
392
+ value = __privateMethod(this, _GdsTable_instances, renderCell_fn).call(this, cell.value, row);
393
+ } else {
394
+ value = row[column.key];
395
+ }
396
+ const processedValue = column.justify ? html`<span>${value}</span>` : value;
397
+ const isResponsive = this._isMobile && this.responsive;
398
+ const mobileLabel = isResponsive ? html`
399
+ <span class="column-label" aria-hidden="true">
400
+ ${column.label}:
401
+ </span>
402
+ ` : null;
403
+ const ariaLabel = isResponsive ? `${column.label}: ` : "";
404
+ return html`
405
+ <div class="cell-content" aria-label="${ariaLabel}">
406
+ ${[
407
+ mobileLabel,
408
+ __privateMethod(this, _GdsTable_instances, renderCell_fn).call(this, cell?.lead, row),
409
+ processedValue,
410
+ __privateMethod(this, _GdsTable_instances, renderCell_fn).call(this, cell?.trail, row)
411
+ ]}
412
+ </div>
413
+ `;
414
+ };
415
+ renderSortIcon_fn = function(column) {
416
+ const isSorted = this._view.sortColumn === column.key;
417
+ const sortDirection = this._view.sortDirection;
418
+ if (isSorted) {
419
+ return sortDirection === "asc" ? html`<gds-icon-sort-up size="m"></gds-icon-sort-up>` : html`<gds-icon-sort-down size="m"></gds-icon-sort-down>`;
420
+ }
421
+ return html`<gds-icon-sort-up size="m"></gds-icon-sort-up>`;
422
+ };
423
+ hasHeaderContent_fn = function() {
424
+ return this.searchable || this.settings || this.querySelector('[slot="header-lead"]') || this.querySelector('[slot="header-trail"]');
425
+ };
426
+ renderHeaderControls_fn = function() {
427
+ if (this.plain || !__privateMethod(this, _GdsTable_instances, hasHeaderContent_fn).call(this)) return null;
428
+ return html`
429
+ <div class="header">
430
+ <div class="lead">
431
+ ${when(
432
+ this.searchable,
433
+ () => html`
434
+ <gds-input
435
+ type="text"
436
+ size="${__privateGet(this, _GdsTable_instances, Density_get).input}"
437
+ plain
438
+ clearable
439
+ label="${msg("Search table")}"
440
+ .value=${this._view.searchQuery}
441
+ @input=${__privateMethod(this, _GdsTable_instances, handleSearch_fn)}
442
+ @gds-input-cleared=${__privateMethod(this, _GdsTable_instances, handleSearchClear_fn)}
443
+ width="100%; l{240px}"
444
+ min-width="240px"
445
+ >
446
+ <gds-icon-magnifying-glass
447
+ slot="lead"
448
+ ></gds-icon-magnifying-glass>
449
+ </gds-input>
450
+ `
451
+ )}
452
+ <slot name="header-lead"></slot>
453
+ </div>
454
+ <div class="trail">
455
+ <slot name="header-trail"></slot>
456
+ ${when(
457
+ this.settings,
458
+ () => html`
459
+ <gds-dropdown
460
+ multiple
461
+ plain
462
+ size="${__privateGet(this, _GdsTable_instances, Density_get).dropdown}"
463
+ label="${msg("Select visible columns")}"
464
+ searchable
465
+ .value=${Array.from(this._view.visibleColumns)}
466
+ @change=${__privateMethod(this, _GdsTable_instances, handleColumnVisibility_fn)}
467
+ >
468
+ <span slot="trigger">${msg("Columns")}</span>
469
+ ${this.columns.map(
470
+ (column) => html`
471
+ <gds-option
472
+ value=${column.key}
473
+ ?selected=${this._view.visibleColumns.has(column.key)}
474
+ >
475
+ ${column.label}
476
+ </gds-option>
477
+ `
478
+ )}
479
+ </gds-dropdown>
480
+ `
481
+ )}
482
+ </div>
483
+ </div>
484
+ `;
485
+ };
486
+ renderColumnHeader_fn = function(column) {
487
+ const isSorted = this._view.sortColumn === column.key;
488
+ const sortDirection = this._view.sortDirection;
489
+ let ariaLabel = column.label;
490
+ if (column.sortable) {
491
+ if (isSorted) {
492
+ const direction = sortDirection === "asc" ? msg("ascending") : msg("descending");
493
+ ariaLabel = `${column.label}, ${msg("sorted")} ${direction}`;
494
+ } else {
495
+ ariaLabel = `${column.label}, ${msg("sortable")}`;
496
+ }
497
+ }
498
+ const classes = classMap({
499
+ sortable: !!column.sortable,
500
+ sorted: isSorted,
501
+ "sort-asc": isSorted && sortDirection === "asc",
502
+ "sort-desc": isSorted && sortDirection === "desc",
503
+ [`align-${column.align}`]: !!column.align,
504
+ [`justify-${column.justify}`]: !!column.justify
505
+ });
506
+ return html`
507
+ <th
508
+ class=${classes}
509
+ aria-sort="${isSorted ? sortDirection === "asc" ? "ascending" : "descending" : "none"}"
510
+ @click=${column.sortable ? () => __privateMethod(this, _GdsTable_instances, handleSort_fn).call(this, column.key) : null}
511
+ >
512
+ <div class="column-header">
513
+ <span class="column-label" aria-label="${ariaLabel}">
514
+ ${column.label}
515
+ </span>
516
+ ${when(
517
+ column.sortable,
518
+ () => html`
519
+ <span class="sort-icon">${__privateMethod(this, _GdsTable_instances, renderSortIcon_fn).call(this, column)}</span>
520
+ `
521
+ )}
522
+ </div>
523
+ </th>
524
+ `;
525
+ };
526
+ renderActionsHeader_fn = function() {
527
+ if (!this.actions || typeof this.actions === "function") return null;
528
+ const label = this.actions.label || msg("Actions");
529
+ const classes = classMap({
530
+ actions: true,
531
+ [`align-${this.actions.align}`]: !!this.actions.align,
532
+ [`justify-${this.actions.justify}`]: !!this.actions.justify
533
+ });
534
+ return html`
535
+ <th class="${classes}">
536
+ <div class="column-header">
537
+ <div class="column-label">${label}</div>
538
+ </div>
539
+ </th>
540
+ `;
541
+ };
542
+ renderSelectableHeader_fn = function() {
543
+ if (!this.selectable) return null;
544
+ return html`
545
+ <th class="checkbox-cell">
546
+ ${__privateMethod(this, _GdsTable_instances, renderCheckbox_fn).call(this, {
547
+ checked: __privateGet(this, _GdsTable_instances, isAllSelected_get),
548
+ indeterminate: __privateGet(this, _GdsTable_instances, isPartialSelection_get),
549
+ ariaLabel: msg("Select all rows"),
550
+ onToggle: () => __privateMethod(this, _GdsTable_instances, handleSelectAll_fn).call(this, {})
551
+ })}
552
+ </th>
553
+ `;
554
+ };
555
+ renderColumnHeaders_fn = function() {
556
+ return this.columns.filter((column) => this._view.visibleColumns.has(column.key)).map((column) => __privateMethod(this, _GdsTable_instances, renderColumnHeader_fn).call(this, column));
557
+ };
558
+ renderTableHeader_fn = function() {
559
+ return html`
560
+ <thead>
561
+ <tr>
562
+ ${[
563
+ __privateMethod(this, _GdsTable_instances, renderSelectableHeader_fn).call(this),
564
+ __privateMethod(this, _GdsTable_instances, renderColumnHeaders_fn).call(this),
565
+ __privateMethod(this, _GdsTable_instances, renderActionsHeader_fn).call(this)
566
+ ]}
567
+ </tr>
568
+ </thead>
569
+ `;
570
+ };
571
+ renderTableCell_fn = function(row, column) {
572
+ const classes = classMap({
573
+ [`align-${column.align}`]: !!column.align,
574
+ [`justify-${column.justify}`]: !!column.justify,
575
+ wrap: Boolean(column.width)
576
+ });
577
+ const style = styleMap({
578
+ "--cell-width": column.width
579
+ });
580
+ return html`
581
+ <td style=${style} class=${classes}>
582
+ ${__privateMethod(this, _GdsTable_instances, renderCellContent_fn).call(this, row, column)}
583
+ </td>
584
+ `;
585
+ };
586
+ renderSelectableCell_fn = function(index) {
587
+ if (!this.selectable) return null;
588
+ const selectRowLabel = `${msg("Select row")} ${index + 1}`;
589
+ return html`
590
+ <td class="checkbox-cell">
591
+ ${__privateMethod(this, _GdsTable_instances, renderCheckbox_fn).call(this, {
592
+ checked: this._selected.has(index),
593
+ indeterminate: false,
594
+ ariaLabel: selectRowLabel,
595
+ onToggle: () => __privateMethod(this, _GdsTable_instances, handleRowSelect_fn).call(this, index, {
596
+ detail: { checked: !this._selected.has(index) }
597
+ })
598
+ })}
599
+ </td>
600
+ `;
601
+ };
602
+ renderRowCells_fn = function(row) {
603
+ return this.columns.filter((column) => this._view.visibleColumns.has(column.key)).map((column) => __privateMethod(this, _GdsTable_instances, renderTableCell_fn).call(this, row, column));
604
+ };
605
+ renderActionsCell_fn = function(row, index) {
606
+ if (!this.actions) return null;
607
+ if (typeof this.actions === "function") {
608
+ return html`
609
+ <td class="actions-cell">
610
+ <div class="cell-content">${this.actions(row, index)}</div>
611
+ </td>
612
+ `;
613
+ }
614
+ const content = __privateMethod(this, _GdsTable_instances, renderCell_fn).call(this, this.actions.cell, row);
615
+ const classes = classMap({
616
+ "actions-cell": true,
617
+ [`align-${this.actions.align}`]: !!this.actions.align,
618
+ [`justify-${this.actions.justify}`]: !!this.actions.justify
619
+ });
620
+ return html`
621
+ <td class="${classes}">
622
+ <div class="cell-content">${content}</div>
623
+ </td>
624
+ `;
625
+ };
626
+ renderTableRow_fn = function(row, index) {
627
+ return html`
628
+ <tr
629
+ class=${classMap({
630
+ selected: this._selected.has(index),
631
+ loading: this._loading
632
+ })}
633
+ >
634
+ ${[
635
+ __privateMethod(this, _GdsTable_instances, renderSelectableCell_fn).call(this, index),
636
+ __privateMethod(this, _GdsTable_instances, renderRowCells_fn).call(this, row),
637
+ __privateMethod(this, _GdsTable_instances, renderActionsCell_fn).call(this, row, index)
638
+ ]}
639
+ </tr>
640
+ `;
641
+ };
642
+ renderCheckbox_fn = function({
643
+ checked,
644
+ indeterminate = false,
645
+ disabled = false,
646
+ ariaLabel,
647
+ onToggle
648
+ }) {
649
+ const toggle = (e) => {
650
+ e.stopPropagation();
651
+ if (disabled) return;
652
+ onToggle();
653
+ };
654
+ const onKey = (e) => {
655
+ if (e.key === " " || e.key === "Enter") {
656
+ e.preventDefault();
657
+ toggle(e);
658
+ }
659
+ };
660
+ return html`
661
+ <div
662
+ class="rbcb-wrapper"
663
+ role="checkbox"
664
+ aria-checked=${indeterminate ? "mixed" : checked ? "true" : "false"}
665
+ aria-label=${ariaLabel}
666
+ @click=${toggle}
667
+ @keydown=${onKey}
668
+ >
669
+ <input
670
+ type="checkbox"
671
+ class="visually-hidden-checkbox"
672
+ .checked=${checked}
673
+ .indeterminate=${indeterminate}
674
+ ?disabled=${disabled}
675
+ aria-hidden="true"
676
+ @change=${toggle}
677
+ />
678
+ ${Table.Checkbox({
679
+ checked,
680
+ indeterminate,
681
+ disabled,
682
+ invalid: false
683
+ })}
684
+ </div>
685
+ `;
686
+ };
687
+ renderSkeletonCell_fn = function(column) {
688
+ const isResponsive = this._isMobile && this.responsive;
689
+ const mobileLabel = isResponsive ? html`<span class="skeleton skeleton-text"></span>` : null;
690
+ return html`
691
+ <div class="cell-content">
692
+ ${mobileLabel}
693
+ <span class="skeleton skeleton-text"></span>
694
+ </div>
695
+ `;
696
+ };
697
+ renderSkeletonRow_fn = function(index) {
698
+ return html`
699
+ <tr class="skeleton-row">
700
+ ${when(
701
+ this.selectable,
702
+ () => html`
703
+ <td class="checkbox-cell">
704
+ <span class="skeleton skeleton-checkbox"></span>
705
+ </td>
706
+ `
707
+ )}
708
+ ${this.columns.filter((column) => this._view.visibleColumns.has(column.key)).map((column) => html`<td>${__privateMethod(this, _GdsTable_instances, renderSkeletonCell_fn).call(this, column)}</td>`)}
709
+ ${when(
710
+ this.actions,
711
+ () => html`
712
+ <td class="actions-cell">
713
+ <div class="cell-content">
714
+ <span class="skeleton skeleton-action"></span>
715
+ </div>
716
+ </td>
717
+ `
718
+ )}
719
+ </tr>
720
+ `;
721
+ };
722
+ renderTableBody_fn = function() {
723
+ if (this._loading && this._loaded) {
724
+ const skeletonRows = Array.from(
725
+ { length: this._view.rows },
726
+ (_, i) => __privateMethod(this, _GdsTable_instances, renderSkeletonRow_fn).call(this, i)
727
+ );
728
+ return html`<tbody aria-busy="true" aria-live="polite">
729
+ ${skeletonRows}
730
+ </tbody>`;
731
+ }
732
+ return html`
733
+ <tbody aria-live="polite">
734
+ ${this._rowsState.map((row, index) => __privateMethod(this, _GdsTable_instances, renderTableRow_fn).call(this, row, index))}
735
+ </tbody>
736
+ `;
737
+ };
738
+ renderTable_fn = function() {
739
+ const CLASSES = classMap({
740
+ responsive: this.responsive,
741
+ data: true,
742
+ [`variant-${this.variant}`]: true,
743
+ loading: this._loading,
744
+ loaded: !this._loading && !this._loaded
745
+ });
746
+ const caption = `${msg("Data table with")} ${this._total} ${msg("rows")}`;
747
+ return html`
748
+ <gds-card
749
+ variant="${this.variant}"
750
+ padding="0"
751
+ border-radius="m"
752
+ border-width="0; s{5xs}"
753
+ class="table-card"
754
+ >
755
+ <div class=${CLASSES} tabindex="0">
756
+ <table aria-label="${caption}">
757
+ <caption class="visually-hidden">
758
+ ${caption}
759
+ </caption>
760
+ ${__privateMethod(this, _GdsTable_instances, renderTableHeader_fn).call(this)} ${__privateMethod(this, _GdsTable_instances, renderTableBody_fn).call(this)}
761
+ </table>
762
+ </div>
763
+ </gds-card>
764
+ `;
765
+ };
766
+ renderErrorState_fn = function() {
767
+ return html`
768
+ <gds-card variant="secondary" border-radius="m">
769
+ <slot name="error">
770
+ <gds-text tag="p">${msg("Error loading data")}</gds-text>
771
+ <gds-button
772
+ size="small"
773
+ label="${msg("Retry loading data")}"
774
+ @click=${() => __privateMethod(this, _GdsTable_instances, loadData_fn).call(this)}
775
+ >
776
+ ${msg("Retry")}
777
+ </gds-button>
778
+ </slot>
779
+ </gds-card>
780
+ `;
781
+ };
782
+ renderEmptyState_fn = function() {
783
+ const hasSearch = this._view.searchQuery.length > 0;
784
+ if (hasSearch) {
785
+ return html`
786
+ <gds-card variant="secondary" border-radius="m">
787
+ <slot name="no-results">
788
+ <gds-flex flex-direction="column" align-items="flex-start" gap="s">
789
+ <gds-text tag="p" font="heading-s">
790
+ ${msg("No results found")}
791
+ </gds-text>
792
+ <gds-text tag="p" font="detail-book-s">
793
+ ${msg("No results for")} "${this._view.searchQuery}"
794
+ </gds-text>
795
+ <gds-button
796
+ size="small"
797
+ label="${msg("Clear search for")} ${this._view.searchQuery}"
798
+ @click=${__privateMethod(this, _GdsTable_instances, handleSearchClear_fn)}
799
+ >
800
+ ${msg("Clear search")}
801
+ </gds-button>
802
+ </gds-flex>
803
+ </slot>
804
+ </gds-card>
805
+ `;
806
+ }
807
+ return html`
808
+ <gds-card variant="secondary" border-radius="m">
809
+ <slot name="empty">
810
+ <gds-text tag="p" font="heading-s">
811
+ ${msg("No data available")}
812
+ </gds-text>
813
+ </slot>
814
+ </gds-card>
815
+ `;
816
+ };
817
+ renderFooter_fn = function() {
818
+ if (this.plain || this._total < 1) return null;
819
+ const start = (this._view.page - 1) * this._view.rows + 1;
820
+ const end = Math.min(this._view.page * this._view.rows, this._total);
821
+ const summaryString = `${start} - ${end} ${msg("of")} ${this._total}`;
822
+ return html`
823
+ <gds-pagination
824
+ .page=${this._view.page}
825
+ .rows=${this._view.rows}
826
+ .options=${this.options}
827
+ .total=${this._total}
828
+ .density=${this.density}
829
+ .label=${summaryString}
830
+ @gds-page-change=${__privateMethod(this, _GdsTable_instances, handlePageChange_fn)}
831
+ @gds-rows-change=${__privateMethod(this, _GdsTable_instances, handlePageSizeChange_fn)}
832
+ width="100%"
833
+ >
834
+ </gds-pagination>
835
+ `;
836
+ };
837
+ handleSearch_fn = async function(e) {
838
+ const input = e.target;
839
+ this._view = {
840
+ ...this._view,
841
+ searchQuery: input.value,
842
+ page: 1
843
+ };
844
+ await __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
845
+ };
846
+ handleSearchClear_fn = async function() {
847
+ this._view = {
848
+ ...this._view,
849
+ searchQuery: "",
850
+ page: 1
851
+ };
852
+ await __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
853
+ };
854
+ handleSort_fn = async function(columnKey) {
855
+ this._view = {
856
+ ...this._view,
857
+ sortColumn: columnKey,
858
+ sortDirection: this._view.sortColumn === columnKey && this._view.sortDirection === "asc" ? "desc" : "asc",
859
+ page: 1
860
+ };
861
+ await __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
862
+ };
863
+ handlePageChange_fn = async function(e) {
864
+ this._view = {
865
+ ...this._view,
866
+ page: e.detail.page
867
+ };
868
+ await __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
869
+ };
870
+ handlePageSizeChange_fn = async function(e) {
871
+ this._view = {
872
+ ...this._view,
873
+ rows: e.detail.rows,
874
+ page: 1
875
+ };
876
+ await __privateMethod(this, _GdsTable_instances, loadData_fn).call(this);
877
+ };
878
+ /**
879
+ * Handles column visibility dropdown changes
880
+ * Updates visible columns set and triggers re-render
881
+ */
882
+ handleColumnVisibility_fn = function(e) {
883
+ const selectedColumns = e.detail.value;
884
+ this._view = {
885
+ ...this._view,
886
+ visibleColumns: new Set(selectedColumns)
887
+ };
888
+ this.requestUpdate();
889
+ };
890
+ /**
891
+ * Handles select all checkbox change
892
+ * Toggles between all selected and none selected
893
+ */
894
+ handleSelectAll_fn = function(e) {
895
+ if (__privateGet(this, _GdsTable_instances, isAllSelected_get)) {
896
+ __privateMethod(this, _GdsTable_instances, clearSelectionInternal_fn).call(this);
897
+ } else {
898
+ __privateMethod(this, _GdsTable_instances, selectAllInternal_fn).call(this);
899
+ }
900
+ __privateMethod(this, _GdsTable_instances, emitSelectionChange_fn).call(this);
901
+ };
902
+ /**
903
+ * Handles individual row selection change
904
+ */
905
+ handleRowSelect_fn = function(index, e) {
906
+ const isChecked = e.detail.checked;
907
+ if (isChecked) {
908
+ this._selected.add(index);
909
+ } else {
910
+ this._selected.delete(index);
911
+ }
912
+ __privateMethod(this, _GdsTable_instances, emitSelectionChange_fn).call(this);
913
+ this.requestUpdate();
914
+ };
915
+ /**
916
+ * Internal method to select all rows
917
+ */
918
+ selectAllInternal_fn = function() {
919
+ this._selected = new Set(this._rowsState.map((_, i) => i));
920
+ this.requestUpdate();
921
+ };
922
+ /**
923
+ * Internal method to clear all selections
924
+ */
925
+ clearSelectionInternal_fn = function() {
926
+ this._selected.clear();
927
+ this.requestUpdate();
928
+ };
929
+ /**
930
+ * Emits selection change event with current selection details
931
+ */
932
+ emitSelectionChange_fn = function() {
933
+ this.dispatchEvent(
934
+ new CustomEvent("gds-table-selection", {
935
+ detail: {
936
+ selectedIndices: Array.from(this._selected),
937
+ selectedData: Array.from(this._selected).map(
938
+ (i) => this._rowsState[i]
939
+ ),
940
+ count: this._selected.size
941
+ },
942
+ bubbles: true
943
+ })
944
+ );
945
+ };
946
+ /**
947
+ * Initializes scroll tracking for the table data container.
948
+ * Sets up event listeners and performs initial scroll state check.
949
+ */
950
+ initializeScrollTracking_fn = function() {
951
+ const dataContainer = this.shadowRoot?.querySelector(".data");
952
+ if (!dataContainer) return;
953
+ const updateScrollState = () => {
954
+ __privateMethod(this, _GdsTable_instances, updateVerticalScrollState_fn).call(this, dataContainer);
955
+ __privateMethod(this, _GdsTable_instances, updateHorizontalScrollState_fn).call(this, dataContainer);
956
+ };
957
+ dataContainer.addEventListener("scroll", updateScrollState);
958
+ updateScrollState();
959
+ };
960
+ /**
961
+ * Updates CSS classes based on vertical scroll position.
962
+ * Adds 'scrolled' class when scrolled down from top.
963
+ */
964
+ updateVerticalScrollState_fn = function(container) {
965
+ const { scrollTop } = container;
966
+ if (scrollTop > 0) {
967
+ container.classList.add("scrolled");
968
+ } else {
969
+ container.classList.remove("scrolled");
970
+ }
971
+ };
972
+ /**
973
+ * Updates CSS classes based on horizontal scroll position.
974
+ * Manages 'scrolled-x-start', 'scrolled-x-middle', and 'scrolled-x-end' classes
975
+ * to indicate scroll position for styling purposes (e.g., shadows, sticky columns).
976
+ */
977
+ updateHorizontalScrollState_fn = function(container) {
978
+ const { scrollLeft, scrollWidth, clientWidth } = container;
979
+ const maxScrollLeft = scrollWidth - clientWidth;
980
+ if (scrollLeft <= 0) {
981
+ container.classList.add("scrolled-x-start");
982
+ container.classList.remove("scrolled-x-middle", "scrolled-x-end");
983
+ } else if (scrollLeft >= maxScrollLeft - 1) {
984
+ container.classList.add("scrolled-x-end");
985
+ container.classList.remove("scrolled-x-start", "scrolled-x-middle");
986
+ } else {
987
+ container.classList.add("scrolled-x-middle");
988
+ container.classList.remove("scrolled-x-start", "scrolled-x-end");
989
+ }
990
+ };
991
+ GdsTable.styles = Table.Styles;
992
+ __decorateClass([
993
+ property({ type: Array })
994
+ ], GdsTable.prototype, "options", 2);
995
+ __decorateClass([
996
+ property({ type: Number })
997
+ ], GdsTable.prototype, "page", 2);
998
+ __decorateClass([
999
+ property({ type: Number })
1000
+ ], GdsTable.prototype, "rows", 2);
1001
+ __decorateClass([
1002
+ property({ type: Array })
1003
+ ], GdsTable.prototype, "columns", 2);
1004
+ __decorateClass([
1005
+ property()
1006
+ ], GdsTable.prototype, "data", 2);
1007
+ __decorateClass([
1008
+ property({ reflect: false })
1009
+ ], GdsTable.prototype, "density", 2);
1010
+ __decorateClass([
1011
+ property({ type: Boolean, reflect: false })
1012
+ ], GdsTable.prototype, "selectable", 2);
1013
+ __decorateClass([
1014
+ property({ type: Boolean, reflect: false })
1015
+ ], GdsTable.prototype, "responsive", 2);
1016
+ __decorateClass([
1017
+ property({ type: Boolean, reflect: false })
1018
+ ], GdsTable.prototype, "plain", 2);
1019
+ __decorateClass([
1020
+ property({ type: Boolean, reflect: false })
1021
+ ], GdsTable.prototype, "searchable", 2);
1022
+ __decorateClass([
1023
+ property({ type: Boolean, reflect: false })
1024
+ ], GdsTable.prototype, "settings", 2);
1025
+ __decorateClass([
1026
+ property({ type: Boolean, reflect: false })
1027
+ ], GdsTable.prototype, "striped", 2);
1028
+ __decorateClass([
1029
+ property()
1030
+ ], GdsTable.prototype, "actions", 2);
1031
+ __decorateClass([
1032
+ property({ type: Boolean, reflect: false })
1033
+ ], GdsTable.prototype, "nocache", 2);
1034
+ __decorateClass([
1035
+ property()
1036
+ ], GdsTable.prototype, "dataLoadKey", 2);
1037
+ __decorateClass([
1038
+ styleExpressionProperty({
1039
+ ...forSpaceTokensAndCustomValues,
1040
+ property: "--_table-height",
1041
+ selector: ".data"
1042
+ })
1043
+ ], GdsTable.prototype, "height", 2);
1044
+ __decorateClass([
1045
+ property()
1046
+ ], GdsTable.prototype, "variant", 2);
1047
+ __decorateClass([
1048
+ state()
1049
+ ], GdsTable.prototype, "_isMobile", 2);
1050
+ __decorateClass([
1051
+ watchMediaQuery("(max-width: 768px)")
1052
+ ], GdsTable.prototype, "_handleMobile", 1);
1053
+ __decorateClass([
1054
+ state()
1055
+ ], GdsTable.prototype, "_view", 2);
1056
+ __decorateClass([
1057
+ state()
1058
+ ], GdsTable.prototype, "_loaded", 2);
1059
+ __decorateClass([
1060
+ state()
1061
+ ], GdsTable.prototype, "_loading", 2);
1062
+ __decorateClass([
1063
+ state()
1064
+ ], GdsTable.prototype, "_rowsState", 2);
1065
+ __decorateClass([
1066
+ state()
1067
+ ], GdsTable.prototype, "_total", 2);
1068
+ __decorateClass([
1069
+ state()
1070
+ ], GdsTable.prototype, "_selected", 2);
1071
+ __decorateClass([
1072
+ state()
1073
+ ], GdsTable.prototype, "_error", 2);
1074
+ __decorateClass([
1075
+ watch("dataLoadKey"),
1076
+ watch("data")
1077
+ ], GdsTable.prototype, "_onDataChange", 1);
1078
+ __decorateClass([
1079
+ watch("columns")
1080
+ ], GdsTable.prototype, "_onColumnsChange", 1);
1081
+ GdsTable = __decorateClass([
1082
+ localized(),
1083
+ gdsCustomElement("gds-table", {
1084
+ dependsOn: Table.Dependencies
1085
+ })
1086
+ ], GdsTable);
1087
+ export {
1088
+ GdsTable,
1089
+ Types2 as Types
1090
+ };