vueless 0.0.809 → 0.0.810

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.809",
3
+ "version": "0.0.810",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -475,6 +475,7 @@ const {
475
475
  headerCheckboxAttrs,
476
476
  headerCounterAttrs,
477
477
  bodyEmptyStateAttrs,
478
+ bodyEmptyStateCellAttrs,
478
479
  bodyDateDividerAttrs,
479
480
  bodySelectedDateDividerAttrs,
480
481
  bodyCellDateDividerAttrs,
@@ -544,13 +545,6 @@ const {
544
545
  <template v-else>
545
546
  {{ column.label }}
546
547
  </template>
547
-
548
- <!--
549
- @slot Use it to add something after the needed header cell.
550
- @binding {object} column
551
- @binding {number} index
552
- -->
553
- <slot :name="`header-${column.key}-after`" :column="column" :index="index" />
554
548
  </div>
555
549
 
556
550
  <ULoaderProgress :loading="loading" v-bind="stickyHeaderLoaderAttrs" />
@@ -626,14 +620,13 @@ const {
626
620
  <thead v-bind="headerAttrs" :style="tableRowWidthStyle">
627
621
  <tr v-if="hasSlotContent($slots['before-header'])" v-bind="headerRowAttrs">
628
622
  <!--
629
- @slot Use it to add something before header row.
630
- @binding {number} cols-count
631
- -->
632
- <slot name="before-header" :cols-count="colsCount" />
623
+ @slot Use it to add something before header row.
624
+ @binding {number} cols-count
625
+ @binding {string} classes
626
+ -->
627
+ <slot name="before-header" :cols-count="colsCount" :classes="headerRowAttrs.class" />
633
628
  </tr>
634
629
 
635
- <tr v-if="hasSlotContent($slots['before-header'])" v-bind="headerRowAttrs"></tr>
636
-
637
630
  <tr ref="header-row" v-bind="headerRowAttrs">
638
631
  <th v-if="selectable" v-bind="headerCellCheckboxAttrs">
639
632
  <UCheckbox
@@ -672,13 +665,6 @@ const {
672
665
  <template v-else>
673
666
  {{ column.label }}
674
667
  </template>
675
-
676
- <!--
677
- @slot Use it to add something after the needed header cell.
678
- @binding {object} column
679
- @binding {number} index
680
- -->
681
- <slot :name="`header-${column.key}-after`" :column="column" :index="index" />
682
668
  </th>
683
669
  </tr>
684
670
 
@@ -792,15 +778,23 @@ const {
792
778
  v-if="rowIndex === lastRow && hasSlotContent($slots['after-last-row'])"
793
779
  v-bind="bodyRowAfterAttrs"
794
780
  >
795
- <!-- @slot Use it to add something after last row. -->
796
- <slot name="after-last-row" :cols-count="colsCount" />
781
+ <!--
782
+ @slot Use it to add something after last row.
783
+ @binding {number} cols-count
784
+ @classes {string} classes
785
+ -->
786
+ <slot
787
+ name="after-last-row"
788
+ :cols-count="colsCount"
789
+ :classes="bodyCellBaseAttrs.class"
790
+ />
797
791
  </tr>
798
792
  </template>
799
793
  </tbody>
800
794
 
801
795
  <tbody v-else>
802
796
  <tr>
803
- <td :colspan="colsCount">
797
+ <td :colspan="colsCount" v-bind="bodyEmptyStateCellAttrs">
804
798
  <!-- @slot Use it to add custom empty state. -->
805
799
  <slot name="empty-state">
806
800
  <UEmpty
@@ -30,6 +30,7 @@ export default /*tw*/ {
30
30
  table: "min-w-full border-none text-sm w-full table-auto",
31
31
  header: "border-b border-gray-200",
32
32
  headerRow: "",
33
+ headerRowBefore: "{>headerCellBase} py-1",
33
34
  headerCellBase: {
34
35
  base: "p-4 text-sm font-normal text-gray-500 text-left text-nowrap",
35
36
  variants: {
@@ -84,6 +85,7 @@ export default /*tw*/ {
84
85
  label: "bg-gray-100 transition",
85
86
  },
86
87
  bodyEmptyState: "{UEmpty} my-8",
88
+ bodyEmptyStateCell: "",
87
89
  footer: {
88
90
  base: "group/footer border-t border-solid border-gray-200",
89
91
  variants: {
@@ -13,6 +13,8 @@ import ULink from "../../ui.button-link/ULink.vue";
13
13
  import UMoney from "../../ui.text-money/UMoney.vue";
14
14
  import UBadge from "../../ui.text-badge/UBadge.vue";
15
15
  import URow from "../../ui.container-row/URow.vue";
16
+ import UIcon from "../../ui.image-icon/UIcon.vue";
17
+ import ULoader from "../../ui.loader/ULoader.vue";
16
18
 
17
19
  import type { Row, UTableProps } from "../types.ts";
18
20
 
@@ -49,10 +51,10 @@ export default {
49
51
  },
50
52
  args: {
51
53
  columns: [
52
- { key: "key_1", label: "title 1", thClass: "w-2/5" },
53
- { key: "key_2", label: "title 2" },
54
- { key: "key_3", label: "title 3" },
55
- { key: "key_4", label: "title 4" },
54
+ { key: "orderId", label: "Order Id", thClass: "w-2/5" },
55
+ { key: "customerName", label: "Customer Name" },
56
+ { key: "status", label: "Status" },
57
+ { key: "totalPrice", label: "Total Price" },
56
58
  ],
57
59
  row: getRow,
58
60
  numberOfRows: 5,
@@ -70,10 +72,10 @@ function getDateDividerRow(rowAmount: number) {
70
72
  .map((_, index) => {
71
73
  let rowDate = new Date().toString();
72
74
 
73
- if (index > Math.round(rowAmount / 2)) {
75
+ if (index > 1) {
74
76
  const date = new Date();
75
77
 
76
- date.setFullYear(date.getFullYear() + 1);
78
+ date.setFullYear(date.getFullYear());
77
79
 
78
80
  rowDate = date.toDateString();
79
81
  }
@@ -82,112 +84,109 @@ function getDateDividerRow(rowAmount: number) {
82
84
  id: getRandomId(),
83
85
  isChecked: false,
84
86
  rowDate,
85
- key_1: "Info",
86
- key_2: "Statistics",
87
- key_3: "Reports",
88
- key_4: "Discounts",
87
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
88
+ customerName: ["Alice Johnson", "Michael Smith", "Emma Brown", "James Wilson"][
89
+ Math.floor(Math.random() * 4)
90
+ ],
91
+ status: ["Pending", "Shipped", "Delivered", "Cancelled"][Math.floor(Math.random() * 4)],
92
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
89
93
  };
90
94
  });
91
95
  }
92
96
 
97
+ function getRow() {
98
+ return {
99
+ id: getRandomId(),
100
+ isChecked: false,
101
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
102
+ customerName: ["Alice Johnson", "Michael Smith", "Emma Brown", "James Wilson"][
103
+ Math.floor(Math.random() * 4)
104
+ ],
105
+ status: ["Pending", "Shipped", "Delivered", "Cancelled"][Math.floor(Math.random() * 4)],
106
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
107
+ };
108
+ }
109
+
93
110
  function getNestedRow() {
94
111
  return {
95
112
  id: getRandomId(),
96
113
  isChecked: false,
97
- key_1: "Click to expand",
98
- key_2: "Some data",
99
- key_3: "Numbers",
100
- key_4: "Statistics",
114
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
115
+ customerName: ["Alice Johnson", "Michael Smith", "Emma Brown", "James Wilson"][
116
+ Math.floor(Math.random() * 4)
117
+ ],
118
+ status: ["Processing", "Shipped", "Delivered", "Cancelled"][Math.floor(Math.random() * 4)],
119
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
101
120
  row: [
102
121
  {
103
122
  id: getRandomId(),
104
123
  isChecked: false,
105
124
  isShown: false,
106
- key_1: "Nesting",
107
- key_2: "Nesting",
108
- key_3: "Nesting",
109
- key_4: "Nesting",
125
+ orderId: "Suborder-1",
126
+ customerName: "",
127
+ status: "",
128
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
110
129
  row: {
111
130
  id: getRandomId(),
112
131
  isChecked: false,
113
132
  isShown: false,
114
- key_1: "Second level nesting",
115
- key_2: "Second level nesting",
116
- key_3: "Second level nesting",
117
- key_4: "Second level nesting",
133
+ orderId: "Extra Services",
134
+ customerName: "",
135
+ status: "",
136
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
118
137
  },
119
138
  },
120
139
  {
121
140
  id: getRandomId(),
122
141
  isChecked: false,
123
142
  isShown: false,
124
- key_1: "Nesting",
125
- key_2: "Nesting",
126
- key_3: "Nesting",
127
- key_4: "Nesting",
143
+ orderId: "Suborder-2",
144
+ customerName: "",
145
+ status: "",
146
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
128
147
  row: {
129
148
  id: getRandomId(),
130
149
  isChecked: false,
131
150
  isShown: false,
132
- key_1: "Second level nesting",
133
- key_2: "Second level nesting",
134
- key_3: "Second level nesting",
135
- key_4: "Second level nesting",
136
- row: {
137
- id: getRandomId(),
138
- isChecked: false,
139
- isShown: false,
140
- key_1: "Third level nesting",
141
- key_2: "Third level nesting",
142
- key_3: "Third level nesting",
143
- key_4: "Third level nesting",
144
- },
151
+ orderId: "Extra Services",
152
+ customerName: "",
153
+ status: "",
154
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
145
155
  },
146
156
  },
147
157
  ],
148
158
  };
149
159
  }
150
160
 
151
- function getRow() {
152
- return {
153
- id: getRandomId(),
154
- isChecked: false,
155
- key_1: "Info",
156
- key_2: "Statistics",
157
- key_3: "Reports",
158
- key_4: "Discounts",
159
- };
160
- }
161
-
162
161
  function getNestedContentRow(index: number) {
163
- if (index === 0) {
162
+ if (index === 1) {
164
163
  return {
165
164
  id: getRandomId(),
166
165
  isChecked: false,
167
- key_1: "Row with nested content",
168
- key_2: "Basic data",
169
- key_3: "More info",
166
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
167
+ customerName: "John Doe",
168
+ status: "Processing",
170
169
  nestedData: {
171
170
  isChecked: false,
172
171
  isShown: false,
173
172
  rows: [
174
173
  {
175
174
  id: getRandomId(),
176
- key_1: "Detail 1A",
177
- key_2: "Info 1B",
178
- key_3: "Data 1C",
175
+ category: "Gadgets",
176
+ itemName: "Ergonomic Mouse",
177
+ quantity: 2,
179
178
  },
180
179
  {
181
180
  id: getRandomId(),
182
- key_1: "Detail 2A",
183
- key_2: "Info 2B",
184
- key_3: "Data 2C",
181
+ category: "Gadgets",
182
+ itemName: "Wireless Keyboard",
183
+ quantity: 1,
185
184
  },
186
185
  {
187
186
  id: getRandomId(),
188
- key_1: "Detail 3A",
189
- key_2: "Info 3B",
190
- key_3: "Data 3C",
187
+ category: "Electronics",
188
+ itemName: "USB-C Hub",
189
+ quantity: 3,
191
190
  },
192
191
  ],
193
192
  },
@@ -196,15 +195,18 @@ function getNestedContentRow(index: number) {
196
195
  return {
197
196
  id: getRandomId(),
198
197
  isChecked: false,
199
- key_1: `Regular row ${index}`,
200
- key_2: "Standard info",
201
- key_3: "Basic data",
198
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
199
+ customerName: ["Alice Johnson", "Michael Smith", "Emma Brown", "James Wilson"][
200
+ Math.floor(Math.random() * 4)
201
+ ],
202
+ status: ["Processing", "Shipped", "Delivered", "Cancelled"][Math.floor(Math.random() * 4)],
203
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
202
204
  };
203
205
  }
204
206
  }
205
207
 
206
208
  const DefaultTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
207
- components: { UTable, UButton, ULink, UMoney, UBadge, URow },
209
+ components: { UTable, UButton, ULink, UMoney, UBadge, URow, UIcon, ULoader },
208
210
  setup() {
209
211
  const slots = getSlotNames(UTable.__name);
210
212
 
@@ -235,82 +237,117 @@ const DefaultTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
235
237
  },
236
238
  });
237
239
 
238
- const EmptyTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
239
- components: { UTable },
240
+ export const Default = DefaultTemplate.bind({});
241
+ Default.args = {};
242
+
243
+ const LoadingTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
244
+ components: { UTable, UButton },
240
245
  setup() {
241
246
  const slots = getSlotNames(UTable.__name);
242
247
 
243
248
  return { args, slots };
244
249
  },
245
250
  template: `
246
- <UTable v-bind="args" :rows="[]" />
251
+ <UButton
252
+ label="Toggle loading"
253
+ @click="args.loading = !args.loading"
254
+ class="mb-4"
255
+ />
256
+
257
+ <UTable
258
+ v-bind="args"
259
+ :rows="args.rows"
260
+ >
261
+ ${args.slotTemplate || getSlotsFragment("")}
262
+ </UTable>
247
263
  `,
248
264
  });
249
265
 
250
- export const Default = DefaultTemplate.bind({});
251
- Default.args = {};
252
-
253
- export const Nesting = DefaultTemplate.bind({});
254
- Nesting.args = { row: getNestedRow, selectable: true };
266
+ export const Loading = LoadingTemplate.bind({});
267
+ Loading.args = {};
268
+ Loading.parameters = {
269
+ docs: {
270
+ description: {
271
+ story: "Set table loader state.",
272
+ },
273
+ },
274
+ };
255
275
 
256
- export const NestedContent = DefaultTemplate.bind({});
257
- NestedContent.args = {
258
- columns: [
259
- { key: "key_1", label: "Title 1" },
260
- { key: "key_2", label: "Title 2" },
261
- { key: "key_3", label: "Title 3" },
276
+ export const EmptyCellLabel = DefaultTemplate.bind({});
277
+ EmptyCellLabel.args = {
278
+ emptyCellLabel: "NO DATA FOUND",
279
+ rows: [
280
+ {
281
+ id: getRandomId(),
282
+ isChecked: false,
283
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
284
+ customerName: "",
285
+ status: "",
286
+ totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
287
+ },
262
288
  ],
263
- row: getNestedContentRow,
264
- slotTemplate: `
265
- <template #nested-content="{ row }">
266
- <div class="p-4 bg-gray-100">
267
- <UTable
268
- :columns="[
269
- { key: 'key_1', label: 'Detail' },
270
- { key: 'key_2', label: 'Info' },
271
- { key: 'key_3', label: 'Data' },
272
- ]"
273
- :rows="row.nestedData.rows"
274
- compact
275
- />
276
- </div>
277
- </template>
278
- `,
289
+ };
290
+ EmptyCellLabel.parameters = {
291
+ docs: {
292
+ description: {
293
+ story: "Label to display for empty cell values.",
294
+ },
295
+ },
296
+ };
297
+
298
+ export const Nesting = DefaultTemplate.bind({});
299
+ Nesting.args = { row: getNestedRow };
300
+ Nesting.parameters = {
301
+ docs: {
302
+ description: {
303
+ story:
304
+ "If you need to have nested row(s) in the table, you can use the `row` key inside a row object.",
305
+ },
306
+ },
279
307
  };
280
308
 
281
- export const RowAndCellClasses = DefaultTemplate.bind({});
282
- RowAndCellClasses.args = {
309
+ export const CellClasses = DefaultTemplate.bind({});
310
+ CellClasses.args = {
283
311
  rows: [
284
312
  {
285
313
  id: getRandomId(),
286
314
  isChecked: false,
287
- key_1: "Info",
288
- key_2: "Statistics",
289
- key_3: { value: "Reports", class: "bg-red-200" },
290
- key_4: "Discounts",
315
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
316
+ customerName: "John Doe",
317
+ status: { value: "Cancelled", class: "bg-red-200" },
318
+ totalPrice: "$18.92",
291
319
  },
292
320
  {
293
321
  id: getRandomId(),
294
322
  isChecked: false,
295
323
  class: "bg-green-100",
296
- key_1: "Data",
297
- key_2: "Meetings",
298
- key_3: "Calendar",
299
- key_4: "Departments",
324
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
325
+ customerName: "Bob Smith",
326
+ status: "Delivered",
327
+ totalPrice: "$173.11",
300
328
  },
301
329
  {
302
330
  id: getRandomId(),
303
331
  isChecked: false,
304
- key_1: "Events",
305
- key_2: "Sales",
306
- key_3: "Renovation",
307
- key_4: "Calendar",
332
+ orderId: `ORD-${Math.floor(Math.random() * 10000)}`,
333
+ customerName: "Helen Williams",
334
+ status: { value: "Delivered", contentClasses: "line-through" },
335
+ totalPrice: "$314.26",
308
336
  },
309
337
  ],
310
338
  };
339
+ CellClasses.parameters = {
340
+ docs: {
341
+ description: {
342
+ story:
343
+ // eslint-disable-next-line vue/max-len
344
+ "To apply classes to a table content, you may use different approaches: <br/> 1. Pass a string with classes to the `class` key in a row object (classes are applied to the whole row). <br/> 2. Pass a string with classes to the `class` key in a cell object (classes are applied to the table cell, while the value is passed via a `value` key). <br/> 3. Pass a string with classes to the `contentClasses` key in a cell object (classes are applied to the cell content, while the value is passed via a `value` key).",
345
+ },
346
+ },
347
+ };
311
348
 
312
- export const Empty = EmptyTemplate.bind({});
313
- Empty.args = {};
349
+ export const Empty = DefaultTemplate.bind({});
350
+ Empty.args = { rows: [] };
314
351
 
315
352
  export const Selectable = DefaultTemplate.bind({});
316
353
  Selectable.args = { selectable: true };
@@ -327,10 +364,9 @@ StickyFooter.args = {
327
364
  stickyFooter: true,
328
365
  slotTemplate: `
329
366
  <template #footer>
330
- <td>
331
- <p>
332
- 🤘🤘🤘
333
- Lorem ipsum dolor sit amet.
367
+ <td colspan="4">
368
+ <p class="font-semibold text-gray-700">
369
+ 📊 Summary: 50 transactions processed | Total Revenue: <strong>$12,345.67</strong>
334
370
  </p>
335
371
  </td>
336
372
  </template>
@@ -339,45 +375,49 @@ StickyFooter.args = {
339
375
 
340
376
  export const Compact = DefaultTemplate.bind({});
341
377
  Compact.args = { compact: true };
378
+ Compact.parameters = {
379
+ docs: {
380
+ description: {
381
+ story: "`compact` prop makes the table compact (fewer spacings).",
382
+ },
383
+ },
384
+ };
342
385
 
343
386
  export const DateDivider = DefaultTemplate.bind({});
344
- DateDivider.args = { dateDivider: true, rows: getDateDividerRow(10) };
387
+ DateDivider.args = { dateDivider: true, rows: getDateDividerRow(4) };
388
+ DateDivider.parameters = {
389
+ docs: {
390
+ description: {
391
+ story: "Show date divider line between dates.",
392
+ },
393
+ },
394
+ };
345
395
 
346
396
  export const DateDividerCustomLabel = DefaultTemplate.bind({});
347
-
348
- const dateDividerCustomLabelRows = getDateDividerRow(10);
349
-
350
397
  DateDividerCustomLabel.args = {
351
- rows: dateDividerCustomLabelRows,
398
+ rows: getDateDividerRow(4),
352
399
  dateDivider: [
353
400
  {
354
- date: dateDividerCustomLabelRows.at(6)!.rowDate,
401
+ date: getDateDividerRow(4).at(2)!.rowDate,
355
402
  label: "Custom label for specific date",
356
403
  config: { label: "!text-orange-400", divider: "!border-orange-300" },
357
404
  },
358
405
  ],
359
406
  };
360
-
361
- export const SlotDefault = DefaultTemplate.bind({});
362
- SlotDefault.args = {
363
- slotTemplate: `
364
- <template #cell-key_3="{value}">
365
- 🤘🤘🤘
366
- </template>
367
- `,
407
+ DateDividerCustomLabel.parameters = {
408
+ docs: {
409
+ description: {
410
+ story:
411
+ "You can customize date divider by passing necessary data in `date`, `label` and `config` object keys.",
412
+ },
413
+ },
368
414
  };
369
415
 
370
- export const SlotExpand = DefaultTemplate.bind({});
371
- SlotExpand.args = {
372
- row: getNestedRow,
416
+ export const SlotHeaderKey = DefaultTemplate.bind({});
417
+ SlotHeaderKey.args = {
373
418
  slotTemplate: `
374
- <template #expand="{ row, isExpanded }">
375
- <div v-if="isExpanded">
376
- 🔼
377
- </div>
378
- <div v-if="!isExpanded">
379
- 🔽
380
- </div>
419
+ <template #header-status="{ column }">
420
+ <UBadge :label="column?.label" />
381
421
  </template>
382
422
  `,
383
423
  };
@@ -409,122 +449,129 @@ SlotHeaderActions.args = {
409
449
  `,
410
450
  };
411
451
 
452
+ export const SlotBeforeHeader = DefaultTemplate.bind({});
453
+ SlotBeforeHeader.args = {
454
+ slotTemplate: `
455
+ <template #before-header="{ colsCount, classes }">
456
+ <td :colspan="colsCount" :class="classes">
457
+ <p class="p-2">
458
+ 📅 Latest data updated on {{ new Date().toLocaleDateString() }}.
459
+ Please verify all entries for accuracy before proceeding.
460
+ </p>
461
+ </td>
462
+ </template>
463
+ `,
464
+ };
465
+
412
466
  export const SlotBeforeFirstRow = DefaultTemplate.bind({});
413
467
  SlotBeforeFirstRow.args = {
414
468
  slotTemplate: `
415
469
  <template #before-first-row>
416
- <p>
417
- 🤘🤘🤘
418
- Lorem ipsum dolor sit amet, consectetur adipiscing elit,
419
- sed do eiusmod tempor incididunt ut labore et dolore magna
420
- aliqua.
470
+ <p class="py-2">
471
+ 📌 Showing the latest data as of {{ new Date().toLocaleDateString() }}.
472
+ Please ensure all entries are up to date.
421
473
  </p>
422
474
  </template>
423
475
  `,
424
476
  };
425
477
 
426
- export const SlotAfterLastRow = DefaultTemplate.bind({});
427
- SlotAfterLastRow.args = {
478
+ export const CellSlots = DefaultTemplate.bind({});
479
+ CellSlots.args = {
428
480
  slotTemplate: `
429
- <template #after-last-row>
430
- <p>
431
- 🤘🤘🤘
432
- Lorem ipsum dolor sit amet, consectetur adipiscing elit,
433
- sed do eiusmod tempor incididunt ut labore et dolore magna
434
- aliqua.
435
- </p>
481
+ <template #cell-orderId="{ value }">
482
+ <ULink :label="value" color="green" />
483
+ </template>
484
+
485
+ <template #cell-customerName="{ value }">
486
+ <UBadge :label="value" />
487
+ </template>
488
+
489
+ <template #cell-totalPrice="{ value }">
490
+ <UMoney :value="value.slice(1)" symbol="€" symbolAlign="left" />
436
491
  </template>
437
492
  `,
438
493
  };
439
494
 
440
- export const SlotFooter = DefaultTemplate.bind({});
441
- SlotFooter.args = {
495
+ export const SlotExpand = DefaultTemplate.bind({});
496
+ SlotExpand.args = {
497
+ row: getNestedRow,
442
498
  slotTemplate: `
443
- <template #footer>
444
- <td>
445
- <p>
446
- Lorem ipsum dolor sit amet, consectetur adipiscing elit,
447
- sed do eiusmod tempor incididunt ut labore et dolore magna
448
- aliqua. Ut enim ad minim veniam, quis nostrud exercitation
449
- ullamco laboris nisi ut aliquip ex ea commodo consequat.
450
- </p>
451
- </td>
499
+ <template #expand="{ row, expanded }">
500
+ <UBadge v-if="expanded" label="Collapse" class="cursor-pointer" />
501
+ <UBadge v-if="!expanded" label="Expand" class="cursor-pointer" />
452
502
  </template>
453
503
  `,
454
504
  };
455
505
 
456
- export const CellSlots = DefaultTemplate.bind({});
457
- CellSlots.args = {
506
+ export const SlotNestedContent = DefaultTemplate.bind({});
507
+ SlotNestedContent.args = {
458
508
  columns: [
459
- { key: "link", label: "link" },
460
- { key: "money", label: "money", thClass: "text-right" },
461
- { key: "email", label: "email" },
462
- { key: "tags", label: "tags" },
509
+ { key: "orderId", label: "Order Id" },
510
+ { key: "customerName", label: "Customer Name" },
511
+ { key: "status", label: "Status" },
463
512
  ],
464
- row: {
465
- id: getRandomId(),
466
- link: "some link",
467
- money: {
468
- sum: 10,
469
- currencySymbol: "$",
470
- },
471
- email: "some@email.ua",
472
- tags: {
473
- tags: { label: "some tag" },
474
- variant: "orange",
513
+ row: getNestedContentRow,
514
+ slotTemplate: `
515
+ <template #nested-content="{ row }">
516
+ <div class="p-4 bg-gray-100">
517
+ <UTable
518
+ :columns="[
519
+ { key: 'category', label: 'Category' },
520
+ { key: 'itemName', label: 'Product' },
521
+ { key: 'quantity', label: 'Quantity' },
522
+ ]"
523
+ :rows="row.nestedData.rows"
524
+ compact
525
+ />
526
+ </div>
527
+ </template>
528
+ `,
529
+ };
530
+ SlotNestedContent.parameters = {
531
+ docs: {
532
+ description: {
533
+ story:
534
+ // eslint-disable-next-line vue/max-len
535
+ "You can also pass nested content inside the row (to render a nested table, for example). Use the `nestedData` key inside a row object.",
475
536
  },
476
- row: [
477
- {
478
- id: getRandomId(),
479
- isShown: true,
480
- link: "some link",
481
- money: {
482
- sum: 10,
483
- currencySymbol: "$",
484
- },
485
- email: "some@email.ua",
486
- tags: {
487
- tags: { label: "some tag" },
488
- variant: "orange",
489
- },
490
- },
491
- {
492
- id: getRandomId(),
493
- isShown: true,
494
- link: "some link",
495
- money: {
496
- sum: 10,
497
- currencySymbol: "$",
498
- },
499
- email: "some@email.ua",
500
- tags: {
501
- tags: { label: "some tag" },
502
- variant: "orange",
503
- },
504
- },
505
- ],
506
537
  },
538
+ };
507
539
 
540
+ export const SlotAfterLastRow = DefaultTemplate.bind({});
541
+ SlotAfterLastRow.args = {
508
542
  slotTemplate: `
509
- <template #cell-link="{ value }">
510
- <ULink :url="value" :label="value" />
511
- </template>
512
-
513
- <template #cell-money="{ value }">
514
- <UMoney :sum="value.sum" :symbol="value.currencySymbol" />
543
+ <template #after-last-row="{ colsCount, classes }">
544
+ <td :colspan="colsCount" :class="classes">
545
+ <p>
546
+ ✅ End of results. If you need more data, try adjusting your filters or loading more entries.
547
+ </p>
548
+ </td>
515
549
  </template>
550
+ `,
551
+ };
516
552
 
517
- <template #cell-email="{ value }">
518
- <ULink :label="value" :url="value" type="email" />
553
+ export const SlotEmptyState = DefaultTemplate.bind({});
554
+ SlotEmptyState.args = {
555
+ rows: [],
556
+ config: {
557
+ i18n: { noData: "Fetching data..." },
558
+ bodyEmptyStateCell: "py-10",
559
+ },
560
+ slotTemplate: `
561
+ <template #empty-state>
562
+ <ULoader loading size="lg" :config="{ loader: 'mx-auto mb-4' }" />
563
+ <p class="text-center">Fetching latest data, please wait...</p>
519
564
  </template>
565
+ `,
566
+ };
520
567
 
521
- <template #cell-tags="{ value }">
522
- <UBadge
523
- v-for="item in value.tags"
524
- :key="item"
525
- :label="item"
526
- :color="value.variant"
527
- />
568
+ export const SlotFooter = DefaultTemplate.bind({});
569
+ SlotFooter.args = {
570
+ slotTemplate: `
571
+ <template #footer>
572
+ <td colspan="100%" class="px-2">
573
+ 🔍 For more detailed insights, please visit our data analysis page or reach out to support for assistance.
574
+ </td>
528
575
  </template>
529
576
  `,
530
577
  };