vueless 1.3.9-beta.8 → 1.4.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.
- package/composables/useUI.ts +187 -155
- package/composables/useVirtualScroll.ts +100 -0
- package/package.json +2 -2
- package/types.ts +11 -0
- package/ui.button-link/ULink.vue +18 -2
- package/ui.data-table/UTable.vue +597 -198
- package/ui.data-table/UTableRow.vue +372 -168
- package/ui.data-table/config.ts +33 -5
- package/ui.data-table/storybook/stories.ts +163 -0
- package/ui.data-table/tests/UTable.test.ts +456 -20
- package/ui.data-table/tests/UTableRow.test.ts +35 -104
- package/ui.data-table/types.ts +57 -0
- package/ui.data-table/utilTable.ts +16 -10
- package/ui.form-checkbox/UCheckbox.vue +3 -7
- package/ui.text-notify/config.ts +1 -1
- package/ui.text-number/UNumber.vue +36 -2
- package/ui.text-number/config.ts +1 -0
- package/ui.text-number/storybook/stories.ts +11 -0
- package/ui.text-number/tests/UNumber.test.ts +90 -0
- package/ui.text-number/types.ts +5 -0
- package/utils/node/mergeConfigs.d.ts +2 -2
- package/utils/node/mergeConfigs.js +240 -121
- package/utils/node/vuelessConfig.d.ts +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ref } from "vue";
|
|
2
|
+
|
|
1
3
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
2
4
|
|
|
3
5
|
import {
|
|
@@ -18,6 +20,8 @@ import UBadge from "../../ui.text-badge/UBadge.vue";
|
|
|
18
20
|
import URow from "../../ui.container-row/URow.vue";
|
|
19
21
|
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
20
22
|
import ULoader from "../../ui.loader/ULoader.vue";
|
|
23
|
+
import UInputSearch from "../../ui.form-input-search/UInputSearch.vue";
|
|
24
|
+
import UText from "../../ui.text-block/UText.vue";
|
|
21
25
|
|
|
22
26
|
import tooltip from "../../v.tooltip/vTooltip";
|
|
23
27
|
import type { Row, Props, ColumnObject } from "../types";
|
|
@@ -971,3 +975,162 @@ FooterSlot.args = {
|
|
|
971
975
|
</template>
|
|
972
976
|
`,
|
|
973
977
|
};
|
|
978
|
+
|
|
979
|
+
function generateNestedRows(count: number): Row[] {
|
|
980
|
+
return Array.from({ length: count }, (_, i) => {
|
|
981
|
+
const hasChildren = i % 10 === 0;
|
|
982
|
+
const row: Row = {
|
|
983
|
+
id: `row-${i}`,
|
|
984
|
+
orderId: `ORD-${String(i).padStart(5, "0")}`,
|
|
985
|
+
customerName: ["Alice Johnson", "Michael Smith", "Emma Brown", "James Wilson"][i % 4],
|
|
986
|
+
status: ["Pending", "Shipped", "Delivered", "Cancelled"][i % 4],
|
|
987
|
+
totalPrice: `$${(Math.random() * 500).toFixed(2)}`,
|
|
988
|
+
};
|
|
989
|
+
|
|
990
|
+
if (hasChildren) {
|
|
991
|
+
row.row = Array.from({ length: 3 }, (_, j) => ({
|
|
992
|
+
id: `row-${i}-child-${j}`,
|
|
993
|
+
orderId: `SUB-${String(i).padStart(5, "0")}-${j + 1}`,
|
|
994
|
+
customerName: "",
|
|
995
|
+
status: ["Processing", "Packed", "Ready"][j % 3],
|
|
996
|
+
totalPrice: `$${(Math.random() * 100).toFixed(2)}`,
|
|
997
|
+
}));
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
return row;
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
export const VirtualScroll: StoryFn<UTableArgs> = (args: UTableArgs) => ({
|
|
1005
|
+
components: { UTable, UBadge },
|
|
1006
|
+
setup() {
|
|
1007
|
+
const rows = generateNestedRows(100000);
|
|
1008
|
+
|
|
1009
|
+
return { args, rows };
|
|
1010
|
+
},
|
|
1011
|
+
template: `
|
|
1012
|
+
<UTable
|
|
1013
|
+
:columns="[
|
|
1014
|
+
{ key: 'orderId', label: 'Order ID', thClass: 'w-1/5' },
|
|
1015
|
+
{ key: 'customerName', label: 'Customer Name' },
|
|
1016
|
+
{ key: 'status', label: 'Status' },
|
|
1017
|
+
{ key: 'totalPrice', label: 'Total Price' },
|
|
1018
|
+
]"
|
|
1019
|
+
:rows="rows"
|
|
1020
|
+
compact
|
|
1021
|
+
virtual-scroll
|
|
1022
|
+
:row-height="46"
|
|
1023
|
+
:buffer-size="10"
|
|
1024
|
+
>
|
|
1025
|
+
<template #cell-status="{ value }">
|
|
1026
|
+
<UBadge
|
|
1027
|
+
:label="value"
|
|
1028
|
+
variant="soft"
|
|
1029
|
+
:color="
|
|
1030
|
+
value === 'Delivered' ? 'success' :
|
|
1031
|
+
value === 'Cancelled' ? 'error' :
|
|
1032
|
+
value === 'Pending' ? 'notice' :
|
|
1033
|
+
value === 'Shipped' || value === 'Processing' ? 'info' :
|
|
1034
|
+
value === 'Packed' || value === 'Ready' ? 'primary' : ''
|
|
1035
|
+
"
|
|
1036
|
+
/>
|
|
1037
|
+
</template>
|
|
1038
|
+
</UTable>
|
|
1039
|
+
`,
|
|
1040
|
+
});
|
|
1041
|
+
VirtualScroll.parameters = {
|
|
1042
|
+
docs: {
|
|
1043
|
+
description: {
|
|
1044
|
+
story:
|
|
1045
|
+
"Virtual scrolling enables rendering of large datasets (100,000+ rows) with optimal performance. " +
|
|
1046
|
+
"Only visible rows are rendered in the DOM, with collapsible nested rows fully supported. " +
|
|
1047
|
+
"Use `virtualScroll` prop to enable, and configure `rowHeight`, `scrollHeight`, and `bufferSize` as needed.",
|
|
1048
|
+
},
|
|
1049
|
+
},
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
export const VirtualSearch: StoryFn<UTableArgs> = (args: UTableArgs) => ({
|
|
1053
|
+
components: { UTable, UInputSearch, UButton, URow, UText },
|
|
1054
|
+
setup() {
|
|
1055
|
+
const rows = generateNestedRows(100000);
|
|
1056
|
+
const search = ref("");
|
|
1057
|
+
const searchMatch = ref(-1);
|
|
1058
|
+
const totalMatches = ref(0);
|
|
1059
|
+
|
|
1060
|
+
function onPrev() {
|
|
1061
|
+
if (totalMatches.value === 0) return;
|
|
1062
|
+
|
|
1063
|
+
searchMatch.value = searchMatch.value <= 0 ? totalMatches.value - 1 : searchMatch.value - 1;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
function onNext() {
|
|
1067
|
+
if (totalMatches.value === 0) return;
|
|
1068
|
+
|
|
1069
|
+
searchMatch.value = searchMatch.value >= totalMatches.value - 1 ? 0 : searchMatch.value + 1;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
return { args, rows, search, searchMatch, totalMatches, onPrev, onNext };
|
|
1073
|
+
},
|
|
1074
|
+
template: `
|
|
1075
|
+
<URow align="stretch" gap="xs" class="mb-4">
|
|
1076
|
+
<UInputSearch
|
|
1077
|
+
v-model="search"
|
|
1078
|
+
placeholder="Search in table..."
|
|
1079
|
+
size="md"
|
|
1080
|
+
@clear="searchMatch = -1"
|
|
1081
|
+
>
|
|
1082
|
+
<template #right>
|
|
1083
|
+
<UText :label="searchMatch + 1 + ' / ' + totalMatches" :wrap="false" class="ml-1" />
|
|
1084
|
+
</template>
|
|
1085
|
+
</UInputSearch>
|
|
1086
|
+
|
|
1087
|
+
<UButton
|
|
1088
|
+
square
|
|
1089
|
+
size="sm"
|
|
1090
|
+
title="Prev"
|
|
1091
|
+
variant="soft"
|
|
1092
|
+
icon="keyboard_arrow_up"
|
|
1093
|
+
:disabled="totalMatches === 0"
|
|
1094
|
+
@click="onPrev"
|
|
1095
|
+
/>
|
|
1096
|
+
|
|
1097
|
+
<UButton
|
|
1098
|
+
square
|
|
1099
|
+
size="sm"
|
|
1100
|
+
title="Next"
|
|
1101
|
+
variant="soft"
|
|
1102
|
+
icon="keyboard_arrow_down"
|
|
1103
|
+
:disabled="totalMatches === 0"
|
|
1104
|
+
@click="onNext"
|
|
1105
|
+
/>
|
|
1106
|
+
</URow>
|
|
1107
|
+
|
|
1108
|
+
<UTable
|
|
1109
|
+
:columns="[
|
|
1110
|
+
{ key: 'orderId', label: 'Order ID', thClass: 'w-1/5' },
|
|
1111
|
+
{ key: 'customerName', label: 'Customer Name' },
|
|
1112
|
+
{ key: 'status', label: 'Status' },
|
|
1113
|
+
{ key: 'totalPrice', label: 'Total Price' },
|
|
1114
|
+
]"
|
|
1115
|
+
:rows="rows"
|
|
1116
|
+
compact
|
|
1117
|
+
virtual-scroll
|
|
1118
|
+
:row-height="45"
|
|
1119
|
+
:buffer-size="10"
|
|
1120
|
+
:search="search"
|
|
1121
|
+
:search-match="searchMatch"
|
|
1122
|
+
@search="totalMatches = $event"
|
|
1123
|
+
/>
|
|
1124
|
+
`,
|
|
1125
|
+
});
|
|
1126
|
+
VirtualSearch.parameters = {
|
|
1127
|
+
docs: {
|
|
1128
|
+
description: {
|
|
1129
|
+
story:
|
|
1130
|
+
"Search functionality with virtual scrolling. " +
|
|
1131
|
+
"Use `search` prop to pass a search string and `searchMatch` prop to highlight a specific match. " +
|
|
1132
|
+
"The `@search` event emits the total number of matches found. " +
|
|
1133
|
+
"Use Prev/Next buttons to navigate between matches.",
|
|
1134
|
+
},
|
|
1135
|
+
},
|
|
1136
|
+
};
|