@openmfp/webcomponents 0.6.1

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 (140) hide show
  1. package/.github/workflows/pipeline.yaml +41 -0
  2. package/.storybook/main.ts +34 -0
  3. package/.storybook/preview.ts +29 -0
  4. package/.storybook/tsconfig.json +11 -0
  5. package/AGENTS.md +153 -0
  6. package/CODEOWNERS +6 -0
  7. package/CONTRIBUTING.md +95 -0
  8. package/LICENSE +201 -0
  9. package/LICENSES/Apache-2.0.txt +73 -0
  10. package/README.md +91 -0
  11. package/REUSE.toml +9 -0
  12. package/angular.json +157 -0
  13. package/docs/dashboard.md +358 -0
  14. package/docs/declarative-form.md +178 -0
  15. package/docs/declarative-table-card.md +235 -0
  16. package/docs/declarative-table.md +315 -0
  17. package/eslint.config.js +41 -0
  18. package/package.json +73 -0
  19. package/projects/ngx/cards/favorites/favorites.component.html +12 -0
  20. package/projects/ngx/cards/favorites/favorites.component.scss +50 -0
  21. package/projects/ngx/cards/favorites/favorites.component.ts +19 -0
  22. package/projects/ngx/cards/public-api.ts +4 -0
  23. package/projects/ngx/cards/service-status/service-status-card.component.html +15 -0
  24. package/projects/ngx/cards/service-status/service-status-card.component.scss +87 -0
  25. package/projects/ngx/cards/service-status/service-status-card.component.ts +36 -0
  26. package/projects/ngx/cards/stories/visited-service-card.stories.ts +149 -0
  27. package/projects/ngx/cards/visited-service-card/visited-service-card.component.html +17 -0
  28. package/projects/ngx/cards/visited-service-card/visited-service-card.component.scss +34 -0
  29. package/projects/ngx/cards/visited-service-card/visited-service-card.component.ts +22 -0
  30. package/projects/ngx/cards/whats-new/whats-new.component.html +10 -0
  31. package/projects/ngx/cards/whats-new/whats-new.component.scss +25 -0
  32. package/projects/ngx/cards/whats-new/whats-new.component.ts +46 -0
  33. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html +28 -0
  34. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.scss +44 -0
  35. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.spec.ts +85 -0
  36. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.ts +58 -0
  37. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.html +29 -0
  38. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.scss +63 -0
  39. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.spec.ts +255 -0
  40. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.ts +75 -0
  41. package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts +76 -0
  42. package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.ts +109 -0
  43. package/projects/ngx/declarative-ui/dashboard/card/utils/index.ts +4 -0
  44. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.spec.ts +141 -0
  45. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.ts +44 -0
  46. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.spec.ts +142 -0
  47. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.ts +52 -0
  48. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.spec.ts +107 -0
  49. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.ts +22 -0
  50. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html +134 -0
  51. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.scss +88 -0
  52. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.spec.ts +354 -0
  53. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.ts +238 -0
  54. package/projects/ngx/declarative-ui/dashboard/dashboard/index.ts +1 -0
  55. package/projects/ngx/declarative-ui/dashboard/index.ts +5 -0
  56. package/projects/ngx/declarative-ui/dashboard/models/constants.ts +2 -0
  57. package/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts +50 -0
  58. package/projects/ngx/declarative-ui/dashboard/models/index.ts +1 -0
  59. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html +28 -0
  60. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.scss +85 -0
  61. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.spec.ts +104 -0
  62. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.ts +23 -0
  63. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html +62 -0
  64. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.scss +12 -0
  65. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.spec.ts +301 -0
  66. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.ts +166 -0
  67. package/projects/ngx/declarative-ui/form/declarative-form/index.ts +1 -0
  68. package/projects/ngx/declarative-ui/form/index.ts +2 -0
  69. package/projects/ngx/declarative-ui/form/models/form-field-definition.ts +15 -0
  70. package/projects/ngx/declarative-ui/form/models/index.ts +1 -0
  71. package/projects/ngx/declarative-ui/form/utils/set-property-by-path.ts +30 -0
  72. package/projects/ngx/declarative-ui/models/index.ts +2 -0
  73. package/projects/ngx/declarative-ui/models/resource.ts +5 -0
  74. package/projects/ngx/declarative-ui/models/ui-definition.ts +95 -0
  75. package/projects/ngx/declarative-ui/public-api.ts +4 -0
  76. package/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts +91 -0
  77. package/projects/ngx/declarative-ui/stories/background-lightblue.png +0 -0
  78. package/projects/ngx/declarative-ui/stories/dashboard.cards.ts +107 -0
  79. package/projects/ngx/declarative-ui/stories/dashboard.stories.ts +296 -0
  80. package/projects/ngx/declarative-ui/stories/declarative-form.stories.ts +149 -0
  81. package/projects/ngx/declarative-ui/stories/declarative-table-card.stories.ts +358 -0
  82. package/projects/ngx/declarative-ui/stories/declarative-table.stories.ts +363 -0
  83. package/projects/ngx/declarative-ui/stories/pods-table.config.ts +188 -0
  84. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.html +138 -0
  85. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.scss +21 -0
  86. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.spec.ts +345 -0
  87. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.ts +61 -0
  88. package/projects/ngx/declarative-ui/table/declarative-table/index.ts +1 -0
  89. package/projects/ngx/declarative-ui/table/index.ts +2 -0
  90. package/projects/ngx/declarative-ui/table/models/index.ts +14 -0
  91. package/projects/ngx/declarative-ui/table/models/table.model.ts +17 -0
  92. package/projects/ngx/declarative-ui/table/utils/cssRules.engine.spec.ts +146 -0
  93. package/projects/ngx/declarative-ui/table/utils/cssRules.engine.ts +69 -0
  94. package/projects/ngx/declarative-ui/table/utils/field-definition.utils.spec.ts +70 -0
  95. package/projects/ngx/declarative-ui/table/utils/field-definition.utils.ts +13 -0
  96. package/projects/ngx/declarative-ui/table/utils/proccess-fields.spec.ts +511 -0
  97. package/projects/ngx/declarative-ui/table/utils/proccess-fields.ts +71 -0
  98. package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.spec.ts +372 -0
  99. package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.ts +98 -0
  100. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-cell.constants.ts +5 -0
  101. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.html +1 -0
  102. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.scss +0 -0
  103. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.spec.ts +119 -0
  104. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.ts +35 -0
  105. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.html +7 -0
  106. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.scss +0 -0
  107. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.spec.ts +114 -0
  108. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.ts +19 -0
  109. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.html +7 -0
  110. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.scss +10 -0
  111. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.spec.ts +188 -0
  112. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.ts +16 -0
  113. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.html +59 -0
  114. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.scss +33 -0
  115. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.spec.ts +316 -0
  116. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.ts +115 -0
  117. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html +156 -0
  118. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.scss +123 -0
  119. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.spec.ts +786 -0
  120. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.ts +286 -0
  121. package/projects/ngx/declarative-ui/table-card/index.ts +2 -0
  122. package/projects/ngx/declarative-ui/table-card/models/configs.ts +46 -0
  123. package/projects/ngx/declarative-ui/tsconfig.lib.json +11 -0
  124. package/projects/ngx/declarative-ui/tsconfig.lib.prod.json +9 -0
  125. package/projects/ngx/declarative-ui/tsconfig.spec.json +9 -0
  126. package/projects/ngx/ng-package.json +8 -0
  127. package/projects/ngx/package.json +22 -0
  128. package/projects/ngx/public-api.ts +2 -0
  129. package/projects/ngx/tsconfig.lib.json +11 -0
  130. package/projects/ngx/tsconfig.lib.prod.json +9 -0
  131. package/projects/webcomponents/main.ts +92 -0
  132. package/projects/webcomponents/tsconfig.app.json +9 -0
  133. package/projects/webcomponents-dashboard/main.ts +15 -0
  134. package/projects/webcomponents-dashboard/tsconfig.app.json +9 -0
  135. package/renovate.json +6 -0
  136. package/scripts/bundle-wc.mjs +79 -0
  137. package/tsconfig.json +37 -0
  138. package/tsconfig.spec.json +8 -0
  139. package/tsconfig.storybook.json +16 -0
  140. package/vitest.config.ts +26 -0
@@ -0,0 +1,358 @@
1
+ import type { FormFieldChangeEvent, FormFieldDefinition } from '../form/models';
2
+ import type { GenericResource } from '../models/resource';
3
+ import { DeclarativeTableCard } from '../table-card/declarative-table-card.component';
4
+ import type {
5
+ DeleteResourceConfirmationConfig,
6
+ ResourceFormConfig,
7
+ TableCardConfig,
8
+ TableCardFormState,
9
+ TableConfig,
10
+ } from '../table-card/models/configs';
11
+ import type { TableFieldDefinition } from '../table/models';
12
+ import { Component, Input } from '@angular/core';
13
+ import type { Meta, StoryObj } from '@storybook/angular';
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Sample data
17
+ // ---------------------------------------------------------------------------
18
+
19
+ interface Pod extends GenericResource {
20
+ id: string;
21
+ metadata: { name: string; namespace: string; uid: string };
22
+ status: { phase: string; ready: boolean; restarts: number; message?: string };
23
+ spec: { nodeName: string; image: string };
24
+ }
25
+
26
+ const PODS: Pod[] = [
27
+ {
28
+ id: 'abc-001',
29
+ metadata: { name: 'api-server-7d9f', namespace: 'default', uid: 'abc-001' },
30
+ status: { phase: 'Running', ready: true, restarts: 0 },
31
+ spec: { nodeName: 'node-1', image: 'nginx:1.25' },
32
+ isAvailable: true,
33
+ },
34
+ {
35
+ id: 'abc-002',
36
+ metadata: { name: 'worker-5bc8', namespace: 'default', uid: 'abc-002' },
37
+ status: {
38
+ phase: 'Pending',
39
+ ready: false,
40
+ restarts: 3,
41
+ message: 'ImagePullBackOff',
42
+ },
43
+ spec: { nodeName: 'node-2', image: 'myapp:latest' },
44
+ isAvailable: false,
45
+ accessibleName: 'Pod unavailable: ImagePullBackOff',
46
+ },
47
+ {
48
+ id: 'abc-003',
49
+ metadata: {
50
+ name: 'cache-redis-0',
51
+ namespace: 'kube-system',
52
+ uid: 'abc-003',
53
+ },
54
+ status: { phase: 'Running', ready: true, restarts: 1 },
55
+ spec: { nodeName: 'node-1', image: 'redis:7' },
56
+ isAvailable: true,
57
+ },
58
+ {
59
+ id: 'abc-004',
60
+ metadata: {
61
+ name: 'db-postgres-0',
62
+ namespace: 'production',
63
+ uid: 'abc-004',
64
+ },
65
+ status: {
66
+ phase: 'Failed',
67
+ ready: false,
68
+ restarts: 5,
69
+ message: 'CrashLoopBackOff',
70
+ },
71
+ spec: { nodeName: 'node-3', image: 'postgres:16' },
72
+ isAvailable: false,
73
+ accessibleName: 'Pod unavailable: CrashLoopBackOff',
74
+ },
75
+ {
76
+ id: 'abc-005',
77
+ metadata: {
78
+ name: 'ingress-ctrl-xkp',
79
+ namespace: 'default',
80
+ uid: 'abc-005',
81
+ },
82
+ status: { phase: 'Running', ready: true, restarts: 0 },
83
+ spec: { nodeName: 'node-2', image: 'nginx-ingress:1.9' },
84
+ isAvailable: true,
85
+ },
86
+ ];
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // Shared definitions
90
+ // ---------------------------------------------------------------------------
91
+
92
+ const BASE_COLUMNS: TableFieldDefinition[] = [
93
+ { label: 'Name', property: 'metadata.name' },
94
+ { label: 'Namespace', property: 'metadata.namespace' },
95
+ { label: 'Phase', property: 'status.phase' },
96
+ { label: 'Node', property: 'spec.nodeName' },
97
+ ];
98
+
99
+ const POD_FORM_FIELDS: FormFieldDefinition[] = [
100
+ { name: 'metadata.name', label: 'Name', required: true },
101
+ {
102
+ name: 'metadata.namespace',
103
+ label: 'Namespace',
104
+ required: true,
105
+ values: ['default', 'kube-system', 'production'],
106
+ },
107
+ ];
108
+
109
+ const CREATE_FORM_STATE_FIELDS: FormFieldDefinition[] = [
110
+ {
111
+ name: 'metadata.name',
112
+ label: 'Name',
113
+ required: true,
114
+ validation: 'onChange',
115
+ },
116
+ {
117
+ name: 'metadata.namespace',
118
+ label: 'Namespace',
119
+ required: true,
120
+ validation: 'onBlur',
121
+ },
122
+ ];
123
+
124
+ const POD_EDIT_FORM_FIELDS: FormFieldDefinition[] = [
125
+ { name: 'metadata.name', label: 'Name', required: true, disabled: true },
126
+ {
127
+ name: 'metadata.namespace',
128
+ label: 'Namespace',
129
+ required: true,
130
+ values: ['default', 'kube-system', 'production'],
131
+ },
132
+ ];
133
+
134
+ const BASE_TABLE_CONFIG: TableConfig = {
135
+ fields: BASE_COLUMNS,
136
+ paginationLimit: 5,
137
+ hasMore: false,
138
+ };
139
+
140
+ const BASE_CONFIG: TableCardConfig = {
141
+ header: 'Pods',
142
+ resourcesSearchable: true,
143
+ tableConfig: BASE_TABLE_CONFIG,
144
+ };
145
+
146
+ // ---------------------------------------------------------------------------
147
+ // Wrapper component for stories that need host-owned state
148
+ // ---------------------------------------------------------------------------
149
+
150
+ @Component({
151
+ selector: 'mfp-declarative-table-card-create-story',
152
+ imports: [DeclarativeTableCard],
153
+ template: `
154
+ <mfp-declarative-table-card
155
+ #tableCard
156
+ [config]="config"
157
+ [createFormState]="createFormState"
158
+ [resources]="resources"
159
+ (createFieldChange)="onCreateFieldChange($event)"
160
+ (createSubmit)="onCreateSubmit($event, tableCard)"
161
+ />
162
+ `,
163
+ })
164
+ class DeclarativeTableCardCreateStory {
165
+ @Input() config!: TableCardConfig;
166
+ @Input() resources: GenericResource[] = [];
167
+ createFormState: TableCardFormState = {};
168
+
169
+ onCreateFieldChange(event: FormFieldChangeEvent): void {
170
+ const fieldErrors: Record<string, string | null> = {
171
+ ...this.createFormState.fieldErrors,
172
+ };
173
+
174
+ switch (event.fieldProperty) {
175
+ case 'metadata.name':
176
+ fieldErrors[event.fieldProperty] = event.value
177
+ ? null
178
+ : 'Name is required';
179
+ break;
180
+ case 'metadata.namespace':
181
+ fieldErrors[event.fieldProperty] = event.value
182
+ ? null
183
+ : 'Namespace is required';
184
+ break;
185
+ }
186
+
187
+ this.createFormState = { fieldErrors };
188
+ }
189
+
190
+ onCreateSubmit(
191
+ _value: Record<string, unknown>,
192
+ tableCard: DeclarativeTableCard<GenericResource>,
193
+ ): void {
194
+ setTimeout(() => {
195
+ alert(JSON.stringify(_value));
196
+ tableCard.closeCreateDialog();
197
+ }, 1000);
198
+ }
199
+ }
200
+
201
+ // ---------------------------------------------------------------------------
202
+ // Meta
203
+ // ---------------------------------------------------------------------------
204
+
205
+ const meta: Meta<DeclarativeTableCard<GenericResource>> = {
206
+ title: 'Declarative UI / DeclarativeTableCard',
207
+ component: DeclarativeTableCardCreateStory,
208
+ tags: ['autodocs'],
209
+ parameters: {
210
+ layout: 'fullscreen',
211
+ },
212
+ argTypes: {
213
+ config: { control: 'object' },
214
+ createFormState: { control: 'object' },
215
+ editFormState: { control: 'object' },
216
+ },
217
+ args: {
218
+ config: BASE_CONFIG,
219
+ editFormState: {} satisfies TableCardFormState,
220
+ resources: PODS,
221
+ },
222
+ };
223
+
224
+ export default meta;
225
+ type Story = StoryObj<DeclarativeTableCard<GenericResource>>;
226
+
227
+ // ---------------------------------------------------------------------------
228
+ // Stories
229
+ // ---------------------------------------------------------------------------
230
+
231
+ /** Minimal card: header, columns, and resources. No dialogs or action buttons. */
232
+ export const Basic: Story = {};
233
+
234
+ /** Header with an info icon that shows a tooltip on hover. */
235
+ export const WithHeaderTooltip: Story = {
236
+ args: {
237
+ config: {
238
+ ...BASE_CONFIG,
239
+ headerTooltip: 'This table lists all pods running in the cluster.',
240
+ },
241
+ },
242
+ };
243
+
244
+ /** Adds a Create button that opens a dialog with name + namespace fields. */
245
+ export const WithCreate: Story = {
246
+ args: {
247
+ config: {
248
+ ...BASE_CONFIG,
249
+ createResourceFormConfig: {
250
+ fields: POD_FORM_FIELDS,
251
+ title: 'Create Pod',
252
+ confirmLabel: 'Create',
253
+ cancelLabel: 'Cancel',
254
+ } satisfies ResourceFormConfig,
255
+ },
256
+ },
257
+ };
258
+
259
+ /** Create dialog with host-owned validation and submit state. */
260
+ export const WithCreateFormState: StoryObj<DeclarativeTableCardCreateStory> = {
261
+ render: (args) => ({
262
+ props: args,
263
+ component: DeclarativeTableCardCreateStory,
264
+ }),
265
+ args: {
266
+ config: {
267
+ ...BASE_CONFIG,
268
+ createResourceFormConfig: {
269
+ fields: CREATE_FORM_STATE_FIELDS,
270
+ title: 'Create Pod',
271
+ confirmLabel: 'Create',
272
+ cancelLabel: 'Cancel',
273
+ } satisfies ResourceFormConfig,
274
+ },
275
+ resources: PODS,
276
+ },
277
+ };
278
+
279
+ /** Adds Edit row-action button. Clicking it opens a pre-filled dialog. */
280
+ export const WithEdit: Story = {
281
+ args: {
282
+ config: {
283
+ ...BASE_CONFIG,
284
+ editResourceFormConfig: {
285
+ fields: POD_EDIT_FORM_FIELDS,
286
+ title: 'Edit Pod',
287
+ confirmLabel: 'Save',
288
+ cancelLabel: 'Cancel',
289
+ } satisfies ResourceFormConfig,
290
+ },
291
+ },
292
+ };
293
+
294
+ /** Adds Delete row-action button with a confirmation dialog. */
295
+ export const WithDelete: Story = {
296
+ args: {
297
+ config: {
298
+ ...BASE_CONFIG,
299
+ deleteResourceConfirmationConfig: {
300
+ title: 'Delete Pod?',
301
+ message:
302
+ 'This action cannot be undone. The pod will be permanently removed.',
303
+ confirmLabel: 'Delete',
304
+ cancelLabel: 'Cancel',
305
+ } satisfies DeleteResourceConfirmationConfig,
306
+ },
307
+ },
308
+ };
309
+
310
+ /** Full action suite: Create button, Edit row button, Delete row button. */
311
+ export const WithAllActions: Story = {
312
+ args: {
313
+ config: {
314
+ ...BASE_CONFIG,
315
+ createResourceFormConfig: {
316
+ fields: POD_FORM_FIELDS,
317
+ title: 'Create Pod',
318
+ confirmLabel: 'Create',
319
+ cancelLabel: 'Cancel',
320
+ } satisfies ResourceFormConfig,
321
+ editResourceFormConfig: {
322
+ fields: POD_EDIT_FORM_FIELDS,
323
+ title: 'Edit Pod',
324
+ confirmLabel: 'Save',
325
+ cancelLabel: 'Cancel',
326
+ } satisfies ResourceFormConfig,
327
+ deleteResourceConfirmationConfig: {
328
+ title: 'Delete Pod?',
329
+ message:
330
+ 'This action cannot be undone. The pod will be permanently removed.',
331
+ confirmLabel: 'Delete',
332
+ cancelLabel: 'Cancel',
333
+ } satisfies DeleteResourceConfirmationConfig,
334
+ },
335
+ },
336
+ };
337
+
338
+ /** Empty resources array triggers the illustrated empty-state message inside the table. */
339
+ export const EmptyState: Story = {
340
+ args: {
341
+ resources: [],
342
+ },
343
+ };
344
+
345
+ /** Shows pagination controls when hasMore is true. */
346
+ export const WithPagination: Story = {
347
+ args: {
348
+ config: {
349
+ ...BASE_CONFIG,
350
+ tableConfig: {
351
+ ...BASE_TABLE_CONFIG,
352
+ totalItemsCount: 42,
353
+ paginationLimit: 5,
354
+ hasMore: true,
355
+ },
356
+ },
357
+ },
358
+ };