@sebgroup/green-core 2.35.1 → 2.37.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.
Files changed (39) hide show
  1. package/components/button/button.trans.styles.scss.js +1 -1
  2. package/components/calendar/calendar.trans.styles.scss.js +1 -1
  3. package/components/context-menu/context-menu.trans.styles.scss.js +1 -1
  4. package/components/datepicker/datepicker.trans.styles.scss.js +1 -1
  5. package/components/dialog/dialog.component.d.ts +22 -2
  6. package/components/dialog/dialog.component.js +104 -23
  7. package/components/formatted-text/date/date-time-formatter.js +1 -3
  8. package/components/grouped-list/grouped-list.trans.styles.scss.js +1 -1
  9. package/components/pagination/pagination.component.js +11 -8
  10. package/components/popover/popover.trans.styles.scss.js +1 -1
  11. package/components/segmented-control/segment/segment.trans.styles.scss.js +1 -1
  12. package/components/segmented-control/segmented-control.trans.styles.css.js +1 -1
  13. package/components/table/table.component.d.ts +30 -1
  14. package/components/table/table.component.js +205 -203
  15. package/components/table/table.stories.data.d.ts +33 -47
  16. package/components/table/table.stories.data.js +308 -287
  17. package/components/table/table.styles.js +196 -11
  18. package/components/table/table.types.d.ts +24 -81
  19. package/components/table/table.types.js +40 -10
  20. package/components/theme/chlorophyll-tokens.scss.js +1 -1
  21. package/custom-elements.json +21506 -21247
  22. package/gds-element.js +1 -1
  23. package/generated/mcp/components.json +1 -1
  24. package/generated/mcp/dialog/api.md +8 -4
  25. package/generated/mcp/icons.json +1 -1
  26. package/generated/mcp/index.json +1 -1
  27. package/generated/mcp/table/api.md +4 -1
  28. package/generated/react/dialog/index.d.ts +2 -1
  29. package/generated/react/index.d.ts +1 -1
  30. package/generated/react/index.js +1 -1
  31. package/generated/react/table/index.d.ts +3 -1
  32. package/package.json +1 -1
  33. package/primitives/field-base/field-base.trans.styles.scss.js +1 -1
  34. package/primitives/listbox/listbox.trans.styles.scss.js +1 -1
  35. package/primitives/listbox/option.trans.styles.scss.js +1 -1
  36. package/primitives/menu/menu-heading.trans.styles.scss.js +1 -1
  37. package/utils/helpers/custom-element-scoping.js +1 -1
  38. package/utils/helpers/id.d.ts +0 -3
  39. package/utils/helpers/id.js +6 -1
@@ -1,67 +1,69 @@
1
1
  import "../../chunks/chunk.QU3DSPNU.js";
2
- const USERS = {
3
- FIRST_NAMES: [
4
- "Alexandra",
5
- "Benjamin",
6
- "Caroline",
7
- "David",
8
- "Elena",
9
- "Fredrik"
10
- ],
11
- LAST_NAMES: ["Andersson", "Bergstr\xF6m", "Carlsson", "Dahlstr\xF6m", "Eriksson"],
12
- ROLES: ["Admin", "User", "Editor"],
13
- STATUSES: ["Active", "Inactive"],
14
- DEPARTMENTS: ["Engineering", "Sales", "Marketing", "Support", "HR"],
15
- COUNT: 100
2
+ import { html } from "lit";
3
+ import { Slot } from "./table.types.js";
4
+ const USERS_URL = "https://api.seb.io/components/table/table.users.json";
5
+ const FEEDBACK_URL = "https://api.seb.io/components/table/table.feedback.json";
6
+ let usersCache = null;
7
+ let usersPromise = null;
8
+ let feedbackCache = null;
9
+ let feedbackPromise = null;
10
+ const defineSlots = (row) => ({
11
+ ...row,
12
+ name: Slot(row.name, ["avatar", "value"]),
13
+ // name: Slot(row.name, ['avatar', 'value'], row.email),
14
+ email: Slot(row.email, ["value", "copy-button"]),
15
+ status: Slot(row.status, ["status"]),
16
+ amount: Slot(row.amount, ["amount", "currency"]),
17
+ account: Slot(row.account, ["main"]),
18
+ login: Slot(row.lastLogin, ["main"]),
19
+ download: Slot(row.download ?? "#", ["main"])
20
+ });
21
+ let usersRawCache = null;
22
+ let usersRawPromise = null;
23
+ const loadUsersRaw = async () => {
24
+ if (usersRawCache) return usersRawCache;
25
+ if (usersRawPromise) return usersRawPromise;
26
+ usersRawPromise = fetch(USERS_URL).then((response) => response.json()).then((data) => {
27
+ usersRawCache = data;
28
+ return data;
29
+ });
30
+ return usersRawPromise;
16
31
  };
17
- const generateUserRecord = (index) => {
18
- const id = index + 1;
19
- const firstName = USERS.FIRST_NAMES[index % USERS.FIRST_NAMES.length];
20
- const lastName = USERS.LAST_NAMES[index % USERS.LAST_NAMES.length];
21
- return {
22
- id,
23
- name: `${firstName} ${lastName}`,
24
- email: `${firstName.toLowerCase()}@domain.tld`,
25
- role: USERS.ROLES[index % USERS.ROLES.length],
26
- status: USERS.STATUSES[index % USERS.STATUSES.length],
27
- department: USERS.DEPARTMENTS[index % USERS.DEPARTMENTS.length],
28
- amount: Math.floor(Math.random() * 5e5) + 1e4,
29
- account: `5440${String(index * 7919 % 1e7).padStart(7, "0")}`,
30
- lastLogin: new Date(
31
- Date.now() - Math.random() * 30 * 864e5
32
- ).toISOString(),
33
- avatarUrl: `https://api.dicebear.com/7.x/avataaars/svg?seed=${firstName}${lastName}`,
34
- download: `#`
35
- };
32
+ const loadUsers = async () => {
33
+ if (usersCache) return usersCache;
34
+ if (usersPromise) return usersPromise;
35
+ usersPromise = loadUsersRaw().then((data) => data.map(defineSlots)).then((data) => {
36
+ usersCache = data;
37
+ return data;
38
+ });
39
+ return usersPromise;
36
40
  };
37
- const generateUserDataset = () => Array.from({ length: USERS.COUNT }, (_, i) => generateUserRecord(i));
38
- const userDataProvider = async (request) => {
39
- await new Promise((resolve) => setTimeout(resolve, 1e3));
40
- const allData = generateUserDataset();
41
- let processedData = [...allData];
41
+ const createDataProvider = (loader) => async (request) => {
42
+ let data = await loader();
42
43
  if (request.searchQuery) {
43
44
  const query = request.searchQuery.toLowerCase();
44
- processedData = processedData.filter(
45
+ data = data.filter(
45
46
  (item) => Object.values(item).some(
46
- (value) => String(value).toLowerCase().includes(query)
47
+ (value) => value?.toString().toLowerCase().includes(query)
47
48
  )
48
49
  );
49
50
  }
50
- if (request.sortColumn) {
51
- processedData.sort((a, b) => {
52
- const aValue = String(a[request.sortColumn]);
53
- const bValue = String(b[request.sortColumn]);
54
- return request.sortDirection === "asc" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
51
+ if (request.sortColumn && data.length > 0) {
52
+ const key = request.sortColumn;
53
+ data = [...data].sort((a, b) => {
54
+ const aVal = a[key]?.toString() ?? "";
55
+ const bVal = b[key]?.toString() ?? "";
56
+ return request.sortDirection === "asc" ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
55
57
  });
56
58
  }
57
- const startIndex = (request.page - 1) * request.rows;
58
- const endIndex = startIndex + request.rows;
59
- const paginatedData = processedData.slice(startIndex, endIndex);
59
+ const start = (request.page - 1) * request.rows;
60
+ const end = start + request.rows;
60
61
  return {
61
- rows: paginatedData,
62
- total: processedData.length
62
+ rows: data.slice(start, end),
63
+ total: data.length
63
64
  };
64
65
  };
66
+ const userDataProvider = createDataProvider(loadUsers);
65
67
  const Users = {
66
68
  Columns: [
67
69
  {
@@ -72,223 +74,201 @@ const Users = {
72
74
  {
73
75
  key: "name",
74
76
  label: "Name",
75
- sortable: true,
76
- cell: {
77
- lead: {
78
- type: "image",
79
- src: (row) => row.avatarUrl,
80
- alt: (row) => row.name,
81
- width: "xl",
82
- height: "xl"
83
- }
84
- }
77
+ sortable: true
85
78
  },
86
79
  {
87
80
  key: "email",
88
81
  label: "Email",
89
82
  sortable: true,
90
- justify: "space-between",
91
- cell: {
92
- trail: {
93
- type: "button",
94
- rank: "tertiary",
95
- value: (row) => row.email,
96
- /* size: 'xs', */
97
- template: "email-copy"
98
- }
99
- }
83
+ justify: "space-between"
100
84
  },
101
85
  {
102
86
  key: "role",
103
87
  label: "Role",
104
88
  sortable: true,
105
- visible: false,
106
- value: (row) => `${row.role.toUpperCase()} (${row.department || "N/A"})`
89
+ visible: false
107
90
  },
108
91
  {
109
92
  key: "status",
110
93
  label: "Status",
111
- sortable: true,
112
- justify: "end",
113
- cell: {
114
- value: {
115
- type: "badge",
116
- value: (row) => row.status,
117
- variant: (row) => row.status === "Active" ? "positive" : "negative"
118
- }
119
- }
94
+ sortable: true
120
95
  },
121
96
  {
122
97
  key: "department",
123
98
  label: "Department",
124
- sortable: true,
125
- cell: {
126
- lead: {
127
- type: "icon",
128
- template: "department-icon"
129
- }
130
- }
99
+ sortable: true
131
100
  },
132
101
  {
133
102
  key: "amount",
134
103
  label: "Amount",
135
104
  sortable: true,
136
- justify: "end",
137
- cell: {
138
- value: {
139
- type: "formatted-number",
140
- value: (row) => row.amount
141
- },
142
- trail: {
143
- type: "badge",
144
- value: "SEK"
145
- }
146
- }
105
+ justify: "end"
147
106
  },
148
107
  {
149
108
  key: "account",
150
109
  label: "Account",
151
- sortable: true,
152
- cell: {
153
- value: {
154
- type: "formatted-account",
155
- value: (row) => row.account,
156
- format: "seb-account"
157
- }
158
- }
110
+ sortable: true
159
111
  },
160
112
  {
161
- key: "lastLogin",
113
+ key: "login",
162
114
  label: "Last Login",
163
- sortable: true,
164
- cell: {
165
- value: {
166
- type: "formatted-date",
167
- value: (row) => row.lastLogin,
168
- locale: "sv-SE",
169
- format: "dateLong"
170
- }
171
- }
115
+ sortable: true
172
116
  },
173
117
  {
174
118
  key: "download",
175
- label: "Download",
176
- cell: {
177
- value: {
178
- type: "link",
179
- href: (row) => row.download,
180
- download: true,
181
- template: "download-image",
182
- label: "Download file"
183
- }
184
- }
119
+ label: "Download"
185
120
  }
186
121
  ],
187
122
  Actions: {
188
123
  label: "Actions",
189
- justify: "end",
190
- cell: {
191
- type: "context-menu",
192
- items: [
193
- {
194
- label: (row) => row.status === "Active" ? "Deactivate" : "Activate"
195
- /* onClick: (row: UserData) => console.log('Toggle status', row), */
196
- },
197
- {
198
- label: "View Details"
199
- /* onClick: (row: UserData) => console.log('View user', row), */
200
- },
201
- {
202
- label: "Edit Profile"
203
- /* onClick: (row: UserData) => console.log('Edit user', row), */
204
- },
205
- {
206
- divider: true,
207
- label: "Delete User"
208
- /* onClick: (row: UserData) => {
209
- if (confirm(`Delete ${row.name}?`)) {
210
- console.log('Delete user', row)
211
- }
212
- }, */
213
- }
214
- ]
215
- }
124
+ justify: "end"
216
125
  },
217
- Data: userDataProvider
218
- };
219
- const FEEDBACK = {
220
- FIRST_NAMES: ["Sophie", "Marcus", "Isabella", "Johan", "Emma", "Lucas"],
221
- LAST_NAMES: ["Str\xF6m", "Nord", "Berg", "Gren", "Holm"],
222
- DEPARTMENTS: ["Engineering", "Sales", "Marketing", "Support", "HR"],
223
- STATUSES: ["Active", "Inactive"],
224
- FEEDBACK_TEXTS: [
225
- "Excellent user experience with intuitive interface and smooth navigation.",
226
- "Performance needs improvement when handling large datasets.",
227
- "Documentation is comprehensive but could benefit from more code examples.",
228
- "Outstanding accessibility features and WCAG compliance implementation.",
229
- "Mobile experience is good but some minor UI inconsistencies observed.",
230
- "Feature request: Please add real-time collaboration capabilities.",
231
- "Integration with third-party APIs works seamlessly.",
232
- "User support team is responsive and helpful.",
233
- "Suggest adding dark mode and customizable themes.",
234
- "Security audit results are impressive and thorough."
235
- ],
236
- NOTES: [
237
- "Customer upgraded to premium plan. All features activated.",
238
- "Q1 planning meeting scheduled for next week at 10 AM.",
239
- "Bug fix deployed in production. Monitor system for 24 hours.",
240
- "Account manager assigned: John Smith.",
241
- "Scheduled maintenance window: Saturday 2-4 AM.",
242
- "Training session completed successfully.",
243
- "Custom integration request in progress.",
244
- "Contract renewal due in 30 days.",
245
- "Performance optimization completed.",
246
- "Security certificates updated to latest version."
247
- ],
248
- COUNT: 50
249
- };
250
- const generateFeedbackRecord = (index) => {
251
- const id = index + 1;
252
- const firstName = FEEDBACK.FIRST_NAMES[index % FEEDBACK.FIRST_NAMES.length];
253
- const lastName = FEEDBACK.LAST_NAMES[index % FEEDBACK.LAST_NAMES.length];
254
- return {
255
- id,
256
- name: `${firstName} ${lastName}`,
257
- email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@company.com`,
258
- feedback: FEEDBACK.FEEDBACK_TEXTS[index % FEEDBACK.FEEDBACK_TEXTS.length],
259
- notes: FEEDBACK.NOTES[index % FEEDBACK.NOTES.length],
260
- status: index % 3 === 0 ? "Inactive" : "Active",
261
- department: FEEDBACK.DEPARTMENTS[index % FEEDBACK.DEPARTMENTS.length]
262
- };
263
- };
264
- const generateFeedbackDataset = () => Array.from({ length: FEEDBACK.COUNT }, (_, i) => generateFeedbackRecord(i));
265
- const feedbackDataProvider = async (request) => {
266
- await new Promise((resolve) => setTimeout(resolve, 800));
267
- const allData = generateFeedbackDataset();
268
- let processedData = [...allData];
269
- if (request.searchQuery) {
270
- const query = request.searchQuery.toLowerCase();
271
- processedData = processedData.filter(
272
- (item) => Object.values(item).some(
273
- (value) => String(value).toLowerCase().includes(query)
274
- )
126
+ Tfoot: {
127
+ label: "Totals",
128
+ sticky: true
129
+ },
130
+ Data: userDataProvider,
131
+ /**
132
+ * Generates slot content for the given rows (current page).
133
+ * Creates per-row slot elements using `columnKey:rowKey:slotId` convention.
134
+ *
135
+ * Used with Lit's `render()` to update table light DOM on each data load:
136
+ * ```ts
137
+ * @gds-table-data-loaded=${(e) => render(Users.SlotContent(e.detail.rows), table)}
138
+ * ```
139
+ */
140
+ SlotContent: (rows) => {
141
+ return html`
142
+ ${rows.map(
143
+ (row) => html`
144
+ <!-- name: avatar -->
145
+ <gds-img
146
+ src="${row.avatarUrl ?? "#"}"
147
+ alt="${String(row.name)}"
148
+ slot="name:${row.id}:avatar"
149
+ width="xl"
150
+ height="xl"
151
+ ></gds-img>
152
+
153
+ <!-- email: copy button -->
154
+ <gds-button
155
+ slot="email:${row.id}:copy-button"
156
+ rank="tertiary"
157
+ size="small"
158
+ >
159
+ <gds-icon-copy></gds-icon-copy>
160
+ </gds-button>
161
+
162
+ <!-- status: badge -->
163
+ <gds-badge
164
+ slot="status:${row.id}:status"
165
+ variant="${String(row.status) === "Active" ? "positive" : "negative"}"
166
+ size="small"
167
+ >
168
+ ${String(row.status)}
169
+ </gds-badge>
170
+
171
+ <!-- amount: formatted number -->
172
+ <gds-formatted-number
173
+ slot="amount:${row.id}:amount"
174
+ .value=${row.amount}
175
+ ></gds-formatted-number>
176
+
177
+ <!-- amount: currency -->
178
+ <gds-badge slot="amount:${row.id}:currency" size="small">
179
+ SEK
180
+ </gds-badge>
181
+
182
+ <!-- account: formatted account -->
183
+ <gds-formatted-account
184
+ slot="account:${row.id}:main"
185
+ account="${row.account}"
186
+ format="seb-account"
187
+ ></gds-formatted-account>
188
+
189
+ <!-- login: formatted date -->
190
+ <gds-formatted-date
191
+ slot="login:${row.id}:main"
192
+ .value="${String(row.login)}"
193
+ locale="sv-SE"
194
+ format="dateLong"
195
+ ></gds-formatted-date>
196
+
197
+ <!-- download: link with icon -->
198
+ <gds-link
199
+ slot="download:${row.id}:main"
200
+ href="${row.download ?? "#"}"
201
+ text-decoration="underline"
202
+ download
203
+ >
204
+ Download file
205
+ <gds-icon-cloud-download slot="trail"></gds-icon-cloud-download>
206
+ </gds-link>
207
+
208
+ <!-- actions: context menu -->
209
+ <gds-context-menu slot="actions:${row.id}:main">
210
+ <gds-button slot="trigger" rank="tertiary" size="small">
211
+ <gds-icon-dot-grid-one-horizontal></gds-icon-dot-grid-one-horizontal>
212
+ </gds-button>
213
+ <gds-menu-item>Edit ${String(row.name)}</gds-menu-item>
214
+ <gds-menu-item>Delete</gds-menu-item>
215
+ </gds-context-menu>
216
+ `
217
+ )}
218
+ `;
219
+ },
220
+ /**
221
+ * Generates tfoot slot content for the footer row.
222
+ * Receives all rows on the page and computes aggregations.
223
+ *
224
+ * Slot naming: `tfoot:{columnKey}`
225
+ */
226
+ TfootSlotContent: (rows) => {
227
+ const totalAmount = rows.reduce(
228
+ (sum, row) => sum + (Number(row.amount) || 0),
229
+ 0
275
230
  );
231
+ const activeCount = rows.filter(
232
+ (row) => String(row.status) === "Active"
233
+ ).length;
234
+ const activeRate = Math.round(activeCount / rows.length * 100);
235
+ const departments = new Set(rows.map((row) => row.department)).size;
236
+ return html`
237
+ <!-- tfoot: name row count -->
238
+ <span slot="tfoot:name">${rows.length} Users</span>
239
+
240
+ <!-- tfoot: status active rate -->
241
+ <gds-badge
242
+ slot="tfoot:status"
243
+ variant="${activeRate >= 70 ? "positive" : activeRate >= 40 ? "warning" : "negative"}"
244
+ size="small"
245
+ >
246
+ ${activeRate}% active
247
+ </gds-badge>
248
+
249
+ <!-- tfoot: department count -->
250
+ <gds-badge slot="tfoot:department" variant="information" size="small">
251
+ ${departments} depts
252
+ </gds-badge>
253
+
254
+ <!-- tfoot: amount sum -->
255
+ <gds-flex slot="tfoot:amount" gap="s" align-items="center">
256
+ <gds-formatted-number .value=${totalAmount}></gds-formatted-number>
257
+ <gds-badge size="small">SEK</gds-badge>
258
+ </gds-flex>
259
+ `;
276
260
  }
277
- if (request.sortColumn) {
278
- processedData.sort((a, b) => {
279
- const aValue = String(a[request.sortColumn]);
280
- const bValue = String(b[request.sortColumn]);
281
- return request.sortDirection === "asc" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
282
- });
283
- }
284
- const startIndex = (request.page - 1) * request.rows;
285
- const endIndex = startIndex + request.rows;
286
- const paginatedData = processedData.slice(startIndex, endIndex);
287
- return {
288
- rows: paginatedData,
289
- total: processedData.length
290
- };
291
261
  };
262
+ const loadFeedback = async () => {
263
+ if (feedbackCache) return feedbackCache;
264
+ if (feedbackPromise) return feedbackPromise;
265
+ feedbackPromise = fetch(FEEDBACK_URL).then((response) => response.json()).then((data) => {
266
+ feedbackCache = data;
267
+ return data;
268
+ });
269
+ return feedbackPromise;
270
+ };
271
+ const feedbackDataProvider = createDataProvider(loadFeedback);
292
272
  const Feedback = {
293
273
  Columns: [
294
274
  {
@@ -300,13 +280,14 @@ const Feedback = {
300
280
  {
301
281
  key: "feedback",
302
282
  label: "Feedback",
283
+ align: "start",
303
284
  width: "350px"
304
285
  },
305
286
  {
306
287
  key: "notes",
307
288
  label: "Notes",
308
289
  align: "start",
309
- width: "300px"
290
+ width: "460px"
310
291
  },
311
292
  {
312
293
  key: "department",
@@ -320,83 +301,123 @@ const Feedback = {
320
301
  sortable: true,
321
302
  align: "start",
322
303
  justify: "end",
323
- width: "100px",
324
- cell: {
325
- value: {
326
- type: "badge",
327
- value: (row) => row.status,
328
- variant: (row) => row.status === "Active" ? "positive" : "negative",
329
- size: "small"
330
- }
331
- }
304
+ width: "100px"
332
305
  }
333
306
  ],
307
+ Data: feedbackDataProvider
308
+ };
309
+ const actionsStaticRows = [
310
+ {
311
+ id: 1,
312
+ task: "Review contract",
313
+ assignee: "Anna Svensson",
314
+ priority: "High"
315
+ },
316
+ {
317
+ id: 2,
318
+ task: "Update pricing",
319
+ assignee: "Erik Lindgren",
320
+ priority: "Medium"
321
+ },
322
+ { id: 3, task: "Send invoice", assignee: "Maria Berg", priority: "Low" },
323
+ {
324
+ id: 4,
325
+ task: "Approve budget",
326
+ assignee: "Johan Nilsson",
327
+ priority: "High"
328
+ }
329
+ ];
330
+ const actionsDataProvider = async (request) => {
331
+ const start = (request.page - 1) * request.rows;
332
+ const page = actionsStaticRows.slice(start, start + request.rows);
333
+ return { rows: page, total: actionsStaticRows.length };
334
+ };
335
+ const Actions = {
336
+ Columns: [
337
+ { key: "task", label: "Task", align: "center" },
338
+ { key: "assignee", label: "Assignee", align: "center" },
339
+ { key: "priority", label: "Priority", align: "center", width: "100px" }
340
+ ],
334
341
  MultipleActions: {
335
342
  label: "Actions",
336
- align: "start",
343
+ align: "center",
337
344
  justify: "start",
338
- cell: [
339
- {
340
- type: "button",
341
- size: "xs",
342
- template: "actions-activate"
343
- },
344
- {
345
- type: "button",
346
- size: "xs",
347
- variant: "negative",
348
- template: "actions-delete"
349
- }
350
- ]
345
+ // width: '150px',
346
+ sticky: true
347
+ },
348
+ MultipleActionsSlotContent: (rows) => {
349
+ return html`
350
+ ${rows.map(
351
+ (row, i) => html`
352
+ <gds-button
353
+ slot="actions:${row.id ?? i + 1}:main"
354
+ rank="secondary"
355
+ size="small"
356
+ variant="positive"
357
+ >
358
+ <gds-icon-circle-check size="m"></gds-icon-circle-check>
359
+ </gds-button>
360
+ <gds-button
361
+ slot="actions:${row.id ?? i + 1}:main"
362
+ rank="secondary"
363
+ size="small"
364
+ variant="negative"
365
+ >
366
+ <gds-icon-cross-small size="m"></gds-icon-cross-small>
367
+ </gds-button>
368
+ `
369
+ )}
370
+ `;
351
371
  },
352
372
  ActionLink: {
353
373
  label: "Actions",
354
- align: "start",
374
+ align: "center",
355
375
  justify: "end",
356
- cell: [
357
- {
358
- type: "link",
359
- href: "#",
360
- label: "Link"
361
- }
362
- ]
376
+ // width: '150px',
377
+ sticky: true
363
378
  },
364
- ActionButton: {
365
- label: "Actions",
366
- align: "start",
367
- justify: "start",
368
- cell: [
369
- {
370
- type: "button",
371
- label: "Link"
372
- }
373
- ]
379
+ ActionLinkSlotContent: (rows) => {
380
+ return html`
381
+ ${rows.map(
382
+ (row, i) => html`
383
+ <gds-button
384
+ slot="actions:${row.id ?? i + 1}:main"
385
+ size="small"
386
+ rank="secondary"
387
+ >
388
+ View details
389
+ </gds-button>
390
+ `
391
+ )}
392
+ `;
374
393
  },
375
394
  ActionContextMenu: {
376
395
  label: "Actions",
377
- align: "start",
396
+ align: "center",
378
397
  justify: "end",
379
- cell: {
380
- type: "context-menu",
381
- items: [
382
- {
383
- label: "Activate"
384
- },
385
- {
386
- label: "View Details"
387
- },
388
- {
389
- label: "Edit Profile"
390
- },
391
- {
392
- label: "Delete User"
393
- }
394
- ]
395
- }
398
+ // width: '150px',
399
+ sticky: true
396
400
  },
397
- Data: feedbackDataProvider
401
+ ActionContextMenuSlotContent: (rows) => {
402
+ return html`
403
+ ${rows.map(
404
+ (row, i) => html`
405
+ <gds-context-menu slot="actions:${row.id ?? i + 1}:main">
406
+ <gds-button slot="trigger" rank="tertiary" size="small">
407
+ <gds-icon-dot-grid-one-horizontal></gds-icon-dot-grid-one-horizontal>
408
+ </gds-button>
409
+ <gds-menu-item>Edit</gds-menu-item>
410
+ <gds-menu-item>Archive</gds-menu-item>
411
+ <gds-menu-item>Delete</gds-menu-item>
412
+ </gds-context-menu>
413
+ `
414
+ )}
415
+ `;
416
+ },
417
+ Data: actionsDataProvider
398
418
  };
399
419
  export {
420
+ Actions,
400
421
  Feedback,
401
422
  Users
402
423
  };