vueless 0.0.497 → 0.0.499

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.
@@ -1,13 +1,23 @@
1
+ import type { Meta, StoryFn } from "@storybook/vue3";
1
2
  import { getArgTypes, getSlotNames, getSlotsFragment } from "../../utils/storybook.ts";
2
3
  import { getRandomId } from "../../utils/ui.ts";
3
4
 
4
- import UTable from "../../ui.data-table/UTable.vue";
5
+ import UTable from "../UTable.vue";
5
6
  import UButton from "../../ui.button/UButton.vue";
6
7
  import ULink from "../../ui.button-link/ULink.vue";
7
8
  import UMoney from "../../ui.text-money/UMoney.vue";
8
9
  import UBadge from "../../ui.text-badge/UBadge.vue";
9
10
  import URow from "../../ui.container-row/URow.vue";
10
11
 
12
+ import type { Row, UTableProps } from "../types.ts";
13
+
14
+ interface UTableArgs extends UTableProps {
15
+ slotTemplate?: string;
16
+ enum: "size";
17
+ numberOfRows: number;
18
+ row: Row | typeof getRow | typeof getNestedRow | typeof getNestedContentRow;
19
+ }
20
+
11
21
  const SHORT_STORY_PARAMETERS = {
12
22
  docs: {
13
23
  story: {
@@ -45,7 +55,7 @@ export default {
45
55
  row: getRow,
46
56
  numberOfRows: 5,
47
57
  },
48
- };
58
+ } as Meta;
49
59
 
50
60
  function getDateDividerRow() {
51
61
  return {
@@ -128,7 +138,51 @@ function getRow() {
128
138
  };
129
139
  }
130
140
 
131
- const DefaultTemplate = (args) => ({
141
+ function getNestedContentRow(index: number) {
142
+ if (index === 0) {
143
+ return {
144
+ id: getRandomId(),
145
+ isChecked: false,
146
+ key_1: "Row with nested content",
147
+ key_2: "Basic data",
148
+ key_3: "More info",
149
+ nestedData: {
150
+ isChecked: false,
151
+ isHidden: true,
152
+ rows: [
153
+ {
154
+ id: getRandomId(),
155
+ key_1: "Detail 1A",
156
+ key_2: "Info 1B",
157
+ key_3: "Data 1C",
158
+ },
159
+ {
160
+ id: getRandomId(),
161
+ key_1: "Detail 2A",
162
+ key_2: "Info 2B",
163
+ key_3: "Data 2C",
164
+ },
165
+ {
166
+ id: getRandomId(),
167
+ key_1: "Detail 3A",
168
+ key_2: "Info 3B",
169
+ key_3: "Data 3C",
170
+ },
171
+ ],
172
+ },
173
+ };
174
+ } else {
175
+ return {
176
+ id: getRandomId(),
177
+ isChecked: false,
178
+ key_1: `Regular row ${index}`,
179
+ key_2: "Standard info",
180
+ key_3: "Basic data",
181
+ };
182
+ }
183
+ }
184
+
185
+ const DefaultTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
132
186
  components: { UTable, UButton, ULink, UMoney, UBadge, URow },
133
187
  setup() {
134
188
  const slots = getSlotNames(UTable.__name);
@@ -140,12 +194,12 @@ const DefaultTemplate = (args) => ({
140
194
  v-bind="args"
141
195
  :rows="args.rows || itemsData"
142
196
  >
143
- ${args.slotTemplate || getSlotsFragment()}
197
+ ${args.slotTemplate || getSlotsFragment("")}
144
198
  </UTable>
145
199
  `,
146
200
  computed: {
147
201
  itemsData() {
148
- let rows = [];
202
+ const rows = [];
149
203
 
150
204
  if (typeof args.row === "function") {
151
205
  for (let i = 0; i < args.numberOfRows; i++) {
@@ -160,7 +214,7 @@ const DefaultTemplate = (args) => ({
160
214
  },
161
215
  });
162
216
 
163
- const EmptyTemplate = (args) => ({
217
+ const EmptyTemplate: StoryFn<UTableArgs> = (args: UTableArgs) => ({
164
218
  components: { UTable },
165
219
  setup() {
166
220
  const slots = getSlotNames(UTable.__name);
@@ -185,49 +239,7 @@ NestedContent.args = {
185
239
  { key: "key_2", label: "Title 2" },
186
240
  { key: "key_3", label: "Title 3" },
187
241
  ],
188
- row: (index) => {
189
- if (index === 0) {
190
- return {
191
- id: getRandomId(),
192
- isChecked: false,
193
- key_1: "Row with nested content",
194
- key_2: "Basic data",
195
- key_3: "More info",
196
- nestedData: {
197
- isChecked: false,
198
- isHidden: true,
199
- rows: [
200
- {
201
- id: getRandomId(),
202
- key_1: "Detail 1A",
203
- key_2: "Info 1B",
204
- key_3: "Data 1C",
205
- },
206
- {
207
- id: getRandomId(),
208
- key_1: "Detail 2A",
209
- key_2: "Info 2B",
210
- key_3: "Data 2C",
211
- },
212
- {
213
- id: getRandomId(),
214
- key_1: "Detail 3A",
215
- key_2: "Info 3B",
216
- key_3: "Data 3C",
217
- },
218
- ],
219
- },
220
- };
221
- } else {
222
- return {
223
- id: getRandomId(),
224
- isChecked: false,
225
- key_1: `Regular row ${index}`,
226
- key_2: "Standard info",
227
- key_3: "Basic data",
228
- };
229
- }
230
- },
242
+ row: getNestedContentRow,
231
243
  slotTemplate: `
232
244
  <template #nested-content="{ row }">
233
245
  <div class="p-4 bg-gray-100">
@@ -313,7 +325,7 @@ DateDivider.args = { dateDivider: true, row: getDateDividerRow };
313
325
  export const DateDividerCustomLabel = DefaultTemplate.bind({});
314
326
  DateDividerCustomLabel.args = {
315
327
  rows: Array(10)
316
- .fill()
328
+ .fill({})
317
329
  .map(() => getDateDividerRow()),
318
330
  dateDivider: [{ date: new Date().toString(), label: "Custom label for specific date" }],
319
331
  };
@@ -407,6 +419,7 @@ CellSlots.args = {
407
419
  { key: "tags", label: "tags" },
408
420
  ],
409
421
  row: {
422
+ id: getRandomId(),
410
423
  link: "some link",
411
424
  money: {
412
425
  sum: 10,
@@ -419,6 +432,7 @@ CellSlots.args = {
419
432
  },
420
433
  row: [
421
434
  {
435
+ id: getRandomId(),
422
436
  isHidden: false,
423
437
  link: "some link",
424
438
  money: {
@@ -432,6 +446,7 @@ CellSlots.args = {
432
446
  },
433
447
  },
434
448
  {
449
+ id: getRandomId(),
435
450
  isHidden: false,
436
451
  link: "some link",
437
452
  money: {
@@ -0,0 +1,142 @@
1
+ import defaultConfig from "./config.ts";
2
+
3
+ import type { UnknownObject } from "../types.ts";
4
+ import type { Ref } from "vue";
5
+
6
+ type RowKeys =
7
+ | number
8
+ | string
9
+ | boolean
10
+ | undefined
11
+ | Date
12
+ | Row
13
+ | Row[]
14
+ | string
15
+ | ((row: Row) => string);
16
+
17
+ export interface CellObject {
18
+ contentClasses?: string | ((value: unknown | string, row: Row) => string);
19
+ class?: string | ((value: unknown | string, row: Row) => string);
20
+ [key: string]: unknown | string;
21
+ }
22
+
23
+ export type RowId = string | number;
24
+ export type Cell = CellObject | string;
25
+
26
+ export interface RowData {
27
+ [key: string]: Cell;
28
+ }
29
+
30
+ export interface DateDivider {
31
+ date: Date | string;
32
+ label?: string;
33
+ }
34
+
35
+ export interface Row {
36
+ id: RowId;
37
+ isChecked?: boolean;
38
+ isHidden?: boolean;
39
+ rowDate?: string | Date;
40
+ row?: Row | Row[];
41
+ nestedData?: Row;
42
+ class?: string | ((row: Row) => string);
43
+ [key: string]: Cell | RowKeys;
44
+ }
45
+
46
+ export interface ColumnObject {
47
+ key: string;
48
+ label?: string;
49
+ isHidden?: string;
50
+ class?: string | ((value: unknown | string, row: Row) => string);
51
+ tdClass?: string;
52
+ thClass?: string;
53
+ }
54
+
55
+ export type Column = ColumnObject | string;
56
+ export type Config = Partial<typeof defaultConfig>;
57
+
58
+ export interface RowScopedProps {
59
+ value: unknown | string | number;
60
+ row: Row;
61
+ }
62
+
63
+ export interface UTableProps {
64
+ /**
65
+ * Table columns (headers).
66
+ */
67
+ columns: Column[];
68
+
69
+ /**
70
+ * Table rows data.
71
+ */
72
+ rows: Row[];
73
+
74
+ /**
75
+ * Label to display for empty cell values.
76
+ */
77
+ emptyCellLabel?: string;
78
+
79
+ /**
80
+ * Show date divider line between dates.
81
+ */
82
+ dateDivider?: boolean | DateDivider[];
83
+
84
+ /**
85
+ * Allow rows selecting.
86
+ */
87
+ selectable?: boolean;
88
+
89
+ /**
90
+ * Makes the table compact (fewer spacings).
91
+ */
92
+ compact?: boolean;
93
+
94
+ /**
95
+ * Set header sticky.
96
+ */
97
+ stickyHeader?: boolean;
98
+
99
+ /**
100
+ * Set footer sticky.
101
+ */
102
+ stickyFooter?: boolean;
103
+
104
+ /**
105
+ * Set table loader state.
106
+ */
107
+ loading?: boolean;
108
+
109
+ /**
110
+ * Component config object.
111
+ */
112
+ config?: Config;
113
+
114
+ /**
115
+ * Data-test attribute for automated testing.
116
+ */
117
+ dataTest?: string;
118
+ }
119
+
120
+ export interface UTableRowAttrs {
121
+ bodyCellContentAttrs: Ref<UnknownObject>;
122
+ bodyCellCheckboxAttrs: Ref<UnknownObject>;
123
+ bodyCheckboxAttrs: Ref<UnknownObject>;
124
+ bodyCellNestedAttrs: Ref<UnknownObject>;
125
+ bodyCellNestedExpandIconAttrs: Ref<UnknownObject>;
126
+ bodyCellNestedCollapseIconAttrs: Ref<UnknownObject>;
127
+ bodyCellBaseAttrs: Ref<UnknownObject>;
128
+ bodyCellNestedExpandIconWrapperAttrs: Ref<UnknownObject>;
129
+ bodyRowCheckedAttrs: Ref<UnknownObject>;
130
+ bodyRowAttrs: Ref<UnknownObject>;
131
+ }
132
+
133
+ export interface UTableRowProps {
134
+ row: Row;
135
+ columns: ColumnObject[];
136
+ emptyCellLabel?: string;
137
+ selectable: boolean;
138
+ nestedLevel: number;
139
+ dataTest: string;
140
+ attrs: UTableRowAttrs;
141
+ config: Config;
142
+ }
@@ -1,12 +1,23 @@
1
1
  import { computed } from "vue";
2
2
  import useUI from "../composables/useUI.ts";
3
3
 
4
- import defaultConfig from "./config.js";
4
+ import defaultConfig from "./config.ts";
5
+
6
+ import type { Row, UTableProps, Config } from "./types.ts";
7
+ import type { UseAttrs } from "../types.ts";
8
+ import type { Ref } from "vue";
9
+
10
+ export type UTableState = {
11
+ tableRows: Ref<Row[]>;
12
+ isShownActionsHeader: Ref<boolean>;
13
+ isHeaderSticky: Ref<boolean>;
14
+ isFooterSticky: Ref<boolean>;
15
+ };
5
16
 
6
17
  export default function useAttrs(
7
- props,
8
- { tableRows, isShownActionsHeader, isHeaderSticky, isFooterSticky },
9
- ) {
18
+ props: UTableProps,
19
+ { tableRows, isShownActionsHeader, isHeaderSticky, isFooterSticky }: UTableState,
20
+ ): UseAttrs<Config> {
10
21
  const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI(
11
22
  defaultConfig,
12
23
  () => props.config,
@@ -27,15 +38,23 @@ export default function useAttrs(
27
38
 
28
39
  const keysAttrs = getKeysAttrs({}, extendingKeys, {
29
40
  stickyHeader: {
30
- extend: computed(() => [
31
- isShownActionsHeader.value && extendingKeysClasses.stickyHeaderActions.value,
32
- isShownActionsHeader.value &&
33
- isHeaderSticky.value &&
34
- extendingKeysClasses.stickyHeaderActions.value,
35
- !isShownActionsHeader.value &&
36
- isHeaderSticky.value &&
37
- extendingKeysClasses.stickyHeaderRow.value,
38
- ]),
41
+ extend: computed(() => {
42
+ const classes = [];
43
+
44
+ if (isShownActionsHeader.value) {
45
+ classes.push(extendingKeysClasses.stickyHeaderActions.value);
46
+ }
47
+
48
+ if (isShownActionsHeader.value && isHeaderSticky.value) {
49
+ classes.push(extendingKeysClasses.stickyHeaderActions.value);
50
+ }
51
+
52
+ if (!isShownActionsHeader.value && isHeaderSticky.value) {
53
+ classes.push(extendingKeysClasses.stickyHeaderRow.value);
54
+ }
55
+
56
+ return classes;
57
+ }),
39
58
  },
40
59
  stickyHeaderCell: {
41
60
  base: computed(() => [extendingKeysClasses.headerCellBase.value]),
@@ -73,7 +92,6 @@ export default function useAttrs(
73
92
 
74
93
  return {
75
94
  config,
76
- keysAttrs,
77
95
  ...keysAttrs,
78
96
  hasSlotContent,
79
97
  };
@@ -1,21 +1,23 @@
1
1
  import { getRandomId } from "../utils/ui.ts";
2
2
 
3
- export function normalizeColumns(columns) {
4
- return columns.map((column) => (typeof column === "string" ? { label: column } : column));
3
+ import type { Column, ColumnObject, Row, RowData, RowId } from "./types.ts";
4
+
5
+ export function normalizeColumns(columns: Column[]): ColumnObject[] {
6
+ return columns.map((column) =>
7
+ typeof column === "string" ? { label: column, key: column } : column,
8
+ );
5
9
  }
6
10
 
7
- export function getFilteredRow(row, columns) {
11
+ export function mapRowColumns(row: Row, columns: ColumnObject[]): RowData {
8
12
  const filteredRow = Object.entries(row).filter((item) => {
9
- const isShownColumn = columns.some((column) => column.key === item[0] && !column.isHidden);
10
-
11
- if (isShownColumn) return item;
13
+ return columns.some((column) => column.key === item[0] && !column.isHidden);
12
14
  });
13
15
 
14
- return Object.fromEntries(filteredRow);
16
+ return Object.fromEntries(filteredRow) as RowData;
15
17
  }
16
18
 
17
- export function syncRowCheck(row, selectedRows) {
18
- row.isChecked = selectedRows.includes(row.id);
19
+ export function syncRowCheck(row: Row, selectedRows: RowId[]) {
20
+ row.isChecked = selectedRows.map((rowId) => String(rowId)).includes(String(row.id));
19
21
 
20
22
  if (row.row && !Array.isArray(row.row)) {
21
23
  row.row = syncRowCheck(row.row, selectedRows);
@@ -24,7 +26,7 @@ export function syncRowCheck(row, selectedRows) {
24
26
  return row;
25
27
  }
26
28
 
27
- export function addRowId(row) {
29
+ export function addRowId(row: Row) {
28
30
  const hasRowId = typeof row.id !== "undefined" && row.id !== null && row.id !== "";
29
31
 
30
32
  row.id = hasRowId ? row.id : getRandomId();
@@ -40,11 +42,11 @@ export function addRowId(row) {
40
42
  return row;
41
43
  }
42
44
 
43
- export function toggleRowVisibility(row, targetRowId) {
45
+ export function toggleRowVisibility(row: Row, targetRowId: string | number) {
44
46
  if (row.id === targetRowId) {
45
- if (Object.hasOwn(row, "isHidden")) {
47
+ if (row.hasOwnProperty("isHidden")) {
46
48
  row.isHidden = !row.isHidden;
47
- } else if (row.nestedData && Object.hasOwn(row.nestedData, "isHidden")) {
49
+ } else if (row.nestedData && row.nestedData.hasOwnProperty("isHidden")) {
48
50
  row.nestedData.isHidden = !row.nestedData.isHidden;
49
51
  }
50
52
 
@@ -64,18 +66,22 @@ export function toggleRowVisibility(row, targetRowId) {
64
66
  }
65
67
  }
66
68
 
67
- export function switchRowCheck(row, isChecked) {
69
+ export function switchRowCheck(row: Row, isChecked: boolean) {
68
70
  row.isChecked = isChecked;
69
71
 
70
- if (row.row) {
72
+ if (row.row && !Array.isArray(row.row)) {
71
73
  switchRowCheck(row.row, isChecked);
72
74
  }
75
+
76
+ if (row.row && Array.isArray(row.row)) {
77
+ row.row.map((currentRow) => switchRowCheck(currentRow, isChecked));
78
+ }
73
79
  }
74
80
 
75
- export function getFlatRows(tableRows) {
76
- const rows = [];
81
+ export function getFlatRows(tableRows: Row[]) {
82
+ const rows: Row[] = [];
77
83
 
78
- function addRow(row) {
84
+ function addRow(row: Row) {
79
85
  rows.push(row);
80
86
 
81
87
  if (row.row && !Array.isArray(row.row)) {
@@ -40,11 +40,11 @@ import defaultConfig from "./config.ts";
40
40
 
41
41
  import type { UCalendarProps, DateValue, RangeDate, Locale } from "./types.ts";
42
42
  import type { ComputedRef, Ref } from "vue";
43
+ import type { DateLocale } from "./utilFormatting.ts";
43
44
 
44
45
  import DayView from "./UCalendarDayView.vue";
45
46
  import MonthView from "./UCalendarMonthView.vue";
46
47
  import YearView from "./UCalendarYearView.vue";
47
- import type { DateLocale } from "./utilFormatting.ts";
48
48
 
49
49
  type DefaultLocale = typeof defaultConfig.i18n;
50
50
 
@@ -131,10 +131,11 @@ export function createMergeConfigs(cx) {
131
131
  console.error("CompoundVariants should be an array.");
132
132
  }
133
133
 
134
- const globalConfigUniqueItems = cloneDeep(globalConfig.compoundVariants || []);
135
- const propsConfigUniqueItems = cloneDeep(propsConfig.compoundVariants || []);
134
+ const defaultCompoundVariants = expandCompoundVariants(defaultConfig.compoundVariants);
135
+ const globalCompoundVariants = expandCompoundVariants(globalConfig.compoundVariants);
136
+ const propsCompoundVariants = expandCompoundVariants(propsConfig.compoundVariants);
136
137
 
137
- const config = defaultConfig.compoundVariants?.map((defaultConfigItem) => {
138
+ const config = defaultCompoundVariants?.map((defaultConfigItem) => {
138
139
  /**
139
140
  * Compare two objects by keys for match.
140
141
  */
@@ -151,25 +152,27 @@ export function createMergeConfigs(cx) {
151
152
  }
152
153
 
153
154
  /**
154
- * Find the same compound variant item in custom config if exist.
155
+ * Find the same compound variant item in custom config if existed.
155
156
  */
156
157
  function findItem(config = []) {
157
- const globalConfigUniqueItemIndex = globalConfigUniqueItems.findIndex(isSameItem);
158
- const propsConfigUniqueItemIndex = propsConfigUniqueItems.findIndex(isSameItem);
158
+ config = cloneDeep(config);
159
+
160
+ const globalConfigUniqueItemIndex = globalCompoundVariants.findIndex(isSameItem);
161
+ const propsConfigUniqueItemIndex = propsCompoundVariants.findIndex(isSameItem);
159
162
 
160
163
  if (~globalConfigUniqueItemIndex) {
161
- globalConfigUniqueItems.splice(globalConfigUniqueItemIndex, 1);
164
+ globalCompoundVariants.splice(globalConfigUniqueItemIndex, 1);
162
165
  }
163
166
 
164
167
  if (~propsConfigUniqueItemIndex) {
165
- propsConfigUniqueItems.splice(propsConfigUniqueItemIndex, 1);
168
+ propsCompoundVariants.splice(propsConfigUniqueItemIndex, 1);
166
169
  }
167
170
 
168
171
  return config.find(isSameItem);
169
172
  }
170
173
 
171
- const globalConfigItem = findItem(globalConfig.compoundVariants);
172
- const propsConfigItem = findItem(propsConfig.compoundVariants);
174
+ const globalConfigItem = findItem(globalCompoundVariants);
175
+ const propsConfigItem = findItem(propsCompoundVariants);
173
176
 
174
177
  return globalConfigItem || propsConfigItem
175
178
  ? {
@@ -181,7 +184,35 @@ export function createMergeConfigs(cx) {
181
184
  : defaultConfigItem;
182
185
  });
183
186
 
184
- return [...(config || []), ...globalConfigUniqueItems, ...propsConfigUniqueItems];
187
+ return [...(config || []), ...globalCompoundVariants, ...propsCompoundVariants];
188
+ }
189
+
190
+ /**
191
+ * Convert compound variants with arrays in values into compound variants with primitives.
192
+ */
193
+ function expandCompoundVariants(compoundVariants) {
194
+ compoundVariants = cloneDeep(compoundVariants || []);
195
+
196
+ function expand(compoundVariant) {
197
+ const keysWithArray = Object.keys(compoundVariant).filter((key) =>
198
+ Array.isArray(compoundVariant[key]),
199
+ );
200
+
201
+ if (!keysWithArray.length) {
202
+ return [compoundVariant];
203
+ }
204
+
205
+ const [firstKey] = keysWithArray;
206
+ const expandedArray = compoundVariant[firstKey].map((value) => ({
207
+ ...compoundVariant,
208
+ [firstKey]: value,
209
+ }));
210
+
211
+ // Recursively expand the remaining array keys
212
+ return expandedArray.flatMap((expandedCompoundVariant) => expand(expandedCompoundVariant));
213
+ }
214
+
215
+ return compoundVariants.flatMap(expand);
185
216
  }
186
217
 
187
218
  return mergeConfigs;