@witchcraft/ui 0.3.14 → 0.3.15
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/dist/module.json +1 -1
- package/dist/runtime/assets/utils.css +1 -1
- package/dist/runtime/components/LibTable/LibTable.d.vue.ts +62 -5
- package/dist/runtime/components/LibTable/LibTable.vue +302 -100
- package/dist/runtime/components/LibTable/LibTable.vue.d.ts +62 -5
- package/dist/runtime/directives/vResizableCols.js +8 -5
- package/dist/runtime/types/index.d.ts +7 -3
- package/dist/runtime/utils/twMerge.d.ts +1 -0
- package/dist/runtime/utils/twMerge.js +2 -1
- package/package.json +3 -1
- package/src/runtime/assets/utils.css +5 -0
- package/src/runtime/components/LibTable/LibTable.stories.ts +148 -17
- package/src/runtime/components/LibTable/LibTable.vue +378 -108
- package/src/runtime/directives/vResizableCols.ts +9 -5
- package/src/runtime/types/index.ts +7 -3
- package/src/runtime/utils/twMerge.ts +2 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type VirtualizerOptions } from "@tanstack/vue-virtual";
|
|
1
2
|
import { type TableHTMLAttributes } from "vue";
|
|
2
3
|
import type { ResizableOptions, TableColConfig } from "../../types/index.js";
|
|
3
4
|
import type { TailwindClassProp } from "../shared/props.js";
|
|
@@ -5,7 +6,6 @@ type T = any;
|
|
|
5
6
|
type RealProps = {
|
|
6
7
|
resizable?: Partial<ResizableOptions>;
|
|
7
8
|
values?: T[];
|
|
8
|
-
itemKey?: keyof T | ((item: T) => string);
|
|
9
9
|
/** Let's the table know the shape of the data since values might be empty. */
|
|
10
10
|
cols?: (keyof T)[];
|
|
11
11
|
rounded?: boolean;
|
|
@@ -13,6 +13,56 @@ type RealProps = {
|
|
|
13
13
|
cellBorder?: boolean;
|
|
14
14
|
header?: boolean;
|
|
15
15
|
colConfig?: TableColConfig<T>;
|
|
16
|
+
/**
|
|
17
|
+
* See tanstack/vue-virtual {@link https://tanstack.com/virtual/latest/docs/api/virtualizer}
|
|
18
|
+
*
|
|
19
|
+
* The defaults are:
|
|
20
|
+
*
|
|
21
|
+
* - enabled: false
|
|
22
|
+
* - method: "fixed"
|
|
23
|
+
* - overscan: (50 if fixed, 10 if dynamic)
|
|
24
|
+
* - estimateSize: () => { return 33 }
|
|
25
|
+
*
|
|
26
|
+
* This also has an additional option, `method`, which can be set to `fixed` or `dynamic` (experimental).
|
|
27
|
+
*
|
|
28
|
+
* Notes:
|
|
29
|
+
*
|
|
30
|
+
* - Because of how virtualization works, initial layout (before .resizable-cols-setup class is applied) will only have access to the headers and not the rows. This can cause cols to look very small, especially if using resizable.fitWidth false.
|
|
31
|
+
*
|
|
32
|
+
* ### Fixed
|
|
33
|
+
*
|
|
34
|
+
* `fixed` is the default and will set the height of ALL items to the height of the first item onMounted (tanstack does not do this and if your estimateSize if off, the scrolling is weird).
|
|
35
|
+
*
|
|
36
|
+
* Since the table now truncates rows by default, they will always be the same height unless you change the inner styling. In fixed mode, `forceRecalculateFixedVirtualizer` is exposed if you need to force re-calculation.
|
|
37
|
+
*
|
|
38
|
+
* If using slots, be sure to at least pass the `class` slot prop to the td element. `style` with width is also supplied but is not required if you're displaying the table as a table.
|
|
39
|
+
*
|
|
40
|
+
* ### Dynamic (experimental)
|
|
41
|
+
*
|
|
42
|
+
* In `dynamic` mode we use tanstack's measureElement method. This is more expensive, but it will work with any heights.
|
|
43
|
+
*
|
|
44
|
+
* Dynamic mode also requires the table displays itself using grid and flex post setup as otherwise dynamic mode doesn't work.
|
|
45
|
+
*
|
|
46
|
+
* You don't need to do anything unless using slots. If using slots, pass the given `ref` slot prop to ref (internally this is tanstack's measureElement) and the class and style slot props at the very least:
|
|
47
|
+
* ```vue
|
|
48
|
+
* <template #[`${colName}`]="slotProps">
|
|
49
|
+
* <td
|
|
50
|
+
* :ref="slotProps.ref"
|
|
51
|
+
* :class="slotProps.class"
|
|
52
|
+
* :style="slotProps.style"
|
|
53
|
+
* >
|
|
54
|
+
* {{ slotProps.value }}
|
|
55
|
+
* </td>
|
|
56
|
+
* </template>
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
virtualizerOptions?: Partial<VirtualizerOptions<any, any>> & {
|
|
60
|
+
method?: "fixed" | "dynamic";
|
|
61
|
+
};
|
|
62
|
+
/** Whether to enable sticky header styles. This requires `border:false`. This moves the border to the wrapper and styles a straight border between the scroll bar and the rounded border. */
|
|
63
|
+
stickyHeader?: boolean;
|
|
64
|
+
/** Which key to use for the rows (only if not using virtualization). */
|
|
65
|
+
itemKey?: keyof T | ((item: T) => string);
|
|
16
66
|
};
|
|
17
67
|
interface Props extends
|
|
18
68
|
/** @vue-ignore */
|
|
@@ -20,18 +70,25 @@ Partial<Omit<TableHTMLAttributes, "class" | "readonly" | "disabled"> & TailwindC
|
|
|
20
70
|
}
|
|
21
71
|
declare const _default: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
22
72
|
props: __VLS_PrettifyLocal<Pick<Partial<{}> & Omit<{} & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, never>, never> & Props & {}> & import("vue").PublicProps;
|
|
23
|
-
expose(exposed: import("vue").ShallowUnwrapRef<{
|
|
73
|
+
expose(exposed: import("vue").ShallowUnwrapRef<{
|
|
74
|
+
forceRecalculateFixedVirtualizer: () => void;
|
|
75
|
+
}>): void;
|
|
24
76
|
attrs: any;
|
|
25
77
|
slots: {
|
|
26
78
|
[x: string]: ((props: {
|
|
27
79
|
colKey: any;
|
|
28
80
|
config: any;
|
|
29
|
-
style:
|
|
30
|
-
|
|
81
|
+
style: {
|
|
82
|
+
width: any;
|
|
83
|
+
};
|
|
84
|
+
class: any;
|
|
31
85
|
}) => any) | undefined;
|
|
32
86
|
} & {
|
|
33
87
|
[x: string]: ((props: {
|
|
34
|
-
class:
|
|
88
|
+
class: any;
|
|
89
|
+
style: {
|
|
90
|
+
width: any;
|
|
91
|
+
};
|
|
35
92
|
item: any;
|
|
36
93
|
value: any;
|
|
37
94
|
}) => any) | undefined;
|
|
@@ -25,8 +25,8 @@ export const vResizableCols = {
|
|
|
25
25
|
},
|
|
26
26
|
updated(el, { value: opts = {} }) {
|
|
27
27
|
const options = override({ ...defaultOpts }, opts);
|
|
28
|
-
const info = el && getElInfo(el);
|
|
29
|
-
const hasGrips = el && elMap.get(el)
|
|
28
|
+
const info = el && options.enabled && getElInfo(el);
|
|
29
|
+
const hasGrips = el && options.enabled && elMap.get(el)?.grips;
|
|
30
30
|
const colsNotEqual = info && info.colCount !== options.colCount;
|
|
31
31
|
if (hasGrips && !options.enabled || colsNotEqual) {
|
|
32
32
|
teardownColumns(el);
|
|
@@ -88,7 +88,7 @@ function createPointerDownHandler(el) {
|
|
|
88
88
|
e.preventDefault();
|
|
89
89
|
document.addEventListener("pointerup", $el.pointerUpHandler);
|
|
90
90
|
const { col, colNext } = getCols(el);
|
|
91
|
-
if (col === null || colNext === null) {
|
|
91
|
+
if (col === null || colNext === null && $el.fitWidth) {
|
|
92
92
|
el.classList.add("resizable-cols-error");
|
|
93
93
|
} else {
|
|
94
94
|
document.addEventListener("pointermove", $el.pointerMoveHandler);
|
|
@@ -181,7 +181,7 @@ function getElInfo(el) {
|
|
|
181
181
|
function getColEls(el) {
|
|
182
182
|
const $el = elMap.get(el);
|
|
183
183
|
if (!$el) unreachable("El went missing.");
|
|
184
|
-
return [...el.querySelectorAll(`:scope ${$el.selector ? $el.selector : "tr > td"}`)];
|
|
184
|
+
return [...el.querySelectorAll(`:scope ${$el.selector ? $el.selector : "tr > th, tr > td"}`)];
|
|
185
185
|
}
|
|
186
186
|
function setupColumns(el, opts) {
|
|
187
187
|
const gripWidth = getTestGripSize(el);
|
|
@@ -196,7 +196,8 @@ function setupColumns(el, opts) {
|
|
|
196
196
|
margin: opts.margin === "dynamic" ? gripWidth : opts.margin,
|
|
197
197
|
colCount: opts.colCount,
|
|
198
198
|
widths: opts.widths,
|
|
199
|
-
selector: opts.selector
|
|
199
|
+
selector: opts.selector,
|
|
200
|
+
onTeardown: opts.onTeardown
|
|
200
201
|
};
|
|
201
202
|
elMap.set(el, $el);
|
|
202
203
|
const els = getColEls(el);
|
|
@@ -213,6 +214,7 @@ function setupColumns(el, opts) {
|
|
|
213
214
|
}
|
|
214
215
|
positionGrips(el);
|
|
215
216
|
el.classList.add("resizable-cols-setup");
|
|
217
|
+
opts.onSetup?.(el);
|
|
216
218
|
}
|
|
217
219
|
function positionGrips(el) {
|
|
218
220
|
let xPos = 0;
|
|
@@ -257,4 +259,5 @@ function teardownColumns(el) {
|
|
|
257
259
|
elMap.delete(el);
|
|
258
260
|
el.classList.remove("resizable-cols-setup");
|
|
259
261
|
removeGrips(el);
|
|
262
|
+
$el.onTeardown?.(el);
|
|
260
263
|
}
|
|
@@ -2,9 +2,7 @@ import type { ErrorW } from "@alanscodelog/utils";
|
|
|
2
2
|
import type { Ref } from "vue";
|
|
3
3
|
export type ResizableOptions = {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* ### true
|
|
5
|
+
* ### true (default)
|
|
8
6
|
* The directive will shrink/expand the columns when the table is resized and will use percentage widths on the table cells. This disables resizing of the last column (from the right handle).
|
|
9
7
|
*
|
|
10
8
|
* Additionally because of the way `table-layout:fixed` works, a min-width cannot be set on the elements via css, so instead, if the table shrinks past `opts.margin * col #`, `min-width` is set on the table until it's resized larger.
|
|
@@ -16,6 +14,8 @@ export type ResizableOptions = {
|
|
|
16
14
|
* The table can be resized past it's normal width and uses pixel widths on the table cells. You might want to set `overscroll-x: scroll` on a parent wrapping element.
|
|
17
15
|
*
|
|
18
16
|
* This will set the table width to `min-content`, else it doesn't work. Note that it does this after the initial reading/setting of sizes so you can, for example, layout the table with `width: 100%`.
|
|
17
|
+
*
|
|
18
|
+
* @default true
|
|
19
19
|
*/
|
|
20
20
|
fitWidth: boolean;
|
|
21
21
|
/**
|
|
@@ -42,6 +42,10 @@ export type ResizableOptions = {
|
|
|
42
42
|
widths: Ref<string[]>;
|
|
43
43
|
/** The selector to use for the cells. "tr > td" by default. */
|
|
44
44
|
selector: string;
|
|
45
|
+
/** Is called just after the `resizable-cols-setup` class is added. Can be useful for controlling the styling of wrappers or doing additional things post-setup. The default table element uses it to set the class on the wrapper also. */
|
|
46
|
+
onSetup?: (el: Element) => void;
|
|
47
|
+
/** Is called on teardown (after the `resizable-cols-setup` class is removed). */
|
|
48
|
+
onTeardown?: (el: Element) => void;
|
|
45
49
|
};
|
|
46
50
|
export type TableColConfig<T = {}> = Record<keyof T, {
|
|
47
51
|
name?: string;
|
|
@@ -2,7 +2,8 @@ import { extendTailwindMerge } from "tailwind-merge";
|
|
|
2
2
|
const _twMergeExtend = {
|
|
3
3
|
extend: {
|
|
4
4
|
classGroups: {
|
|
5
|
-
"focus-outline": [{ "focus-outline": ["", "no-offset", "none"] }]
|
|
5
|
+
"focus-outline": [{ "focus-outline": ["", "no-offset", "none"] }],
|
|
6
|
+
"no-truncate": ["truncate", "no-truncate"]
|
|
6
7
|
}
|
|
7
8
|
}
|
|
8
9
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@witchcraft/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.15",
|
|
4
4
|
"description": "Vue component library.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/runtime/main.lib.js",
|
|
@@ -89,6 +89,7 @@
|
|
|
89
89
|
"@chromatic-com/storybook": "^3.2.7",
|
|
90
90
|
"@commitlint/cli": "^19.8.1",
|
|
91
91
|
"@internationalized/date": "^3.9.0",
|
|
92
|
+
"@faker-js/faker": "^10.0.0",
|
|
92
93
|
"@nuxt/eslint-config": "^1.9.0",
|
|
93
94
|
"@nuxt/module-builder": "^1.0.2",
|
|
94
95
|
"@nuxtjs/i18n": "^9.5.6",
|
|
@@ -106,6 +107,7 @@
|
|
|
106
107
|
"@storybook/test-runner": "^0.22.1",
|
|
107
108
|
"@storybook/vue3": "^8.6.14",
|
|
108
109
|
"@storybook/vue3-vite": "^8.6.14",
|
|
110
|
+
"@tanstack/vue-virtual": "^3.13.0",
|
|
109
111
|
"@tailwindcss/cli": "^4.1.12",
|
|
110
112
|
"@tailwindcss/postcss": "^4.1.12",
|
|
111
113
|
"@types/node": "^24.3.0",
|
|
@@ -1,30 +1,61 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import { faker } from "@faker-js/faker"
|
|
2
3
|
import type { Meta, StoryObj } from "@storybook/vue3"
|
|
4
|
+
import { reactive, ref } from "vue"
|
|
3
5
|
|
|
4
6
|
import LibTable from "./LibTable.vue"
|
|
5
7
|
|
|
6
8
|
// todo
|
|
7
9
|
import * as components from "../index.js"
|
|
8
10
|
|
|
11
|
+
// faker is slow, we can just choose from a few hundred pre-generated sentences
|
|
12
|
+
const fakerSentences = Array.from({ length: 100 }).fill(0).map(_ => faker.lorem.sentence(faker.number.int({ min: 1, max: 50 })))
|
|
13
|
+
|
|
9
14
|
const meta: Meta<typeof LibTable> = {
|
|
10
15
|
component: LibTable as any,
|
|
11
16
|
title: "Components/Table"
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
export default meta
|
|
15
|
-
type Story = StoryObj<typeof LibTable> & { args: {
|
|
20
|
+
type Story = StoryObj<typeof LibTable> & { args: {
|
|
21
|
+
slots?: string
|
|
22
|
+
wrapperClass?: string
|
|
23
|
+
} }
|
|
16
24
|
export const Primary: Story = {
|
|
17
25
|
render: args => ({
|
|
18
26
|
components,
|
|
19
|
-
setup: () =>
|
|
27
|
+
setup: () => {
|
|
28
|
+
const show = ref(true)
|
|
29
|
+
// careful, storybook passes refs as is causing issues
|
|
30
|
+
//
|
|
31
|
+
const argsReactive = reactive({
|
|
32
|
+
...args,
|
|
33
|
+
resizable: {
|
|
34
|
+
enabled: true,
|
|
35
|
+
...args.resizable
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
args: argsReactive,
|
|
41
|
+
show
|
|
42
|
+
}
|
|
43
|
+
},
|
|
20
44
|
template: `
|
|
21
|
-
<div class="
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</
|
|
45
|
+
<div class="p-2 flex flex-col gap-2 border rounded-md mb-10">
|
|
46
|
+
Controls:
|
|
47
|
+
<div class="flex gap-2 w-full">
|
|
48
|
+
<LibButton class="flex-1" @click="args.resizable.enabled = !args.resizable.enabled">Toggle Resizable (currently {{args.resizable.enabled}})</LibButton>
|
|
49
|
+
</div>
|
|
50
|
+
<LibButton @click="args.stickyHeader = !args.stickyHeader">Toggle Sticky Header (currently {{args.stickyHeader}})</LibButton>
|
|
51
|
+
<LibButton @click="show = !show">Toggle Table</LibButton>
|
|
27
52
|
</div>
|
|
53
|
+
<lib-table
|
|
54
|
+
v-if="show"
|
|
55
|
+
v-bind="args"
|
|
56
|
+
>
|
|
57
|
+
${(args as any).slots}
|
|
58
|
+
</lib-table>
|
|
28
59
|
`
|
|
29
60
|
}),
|
|
30
61
|
args: {
|
|
@@ -34,8 +65,7 @@ export const Primary: Story = {
|
|
|
34
65
|
{ prop1: "Item2 Prop 1", prop2: "Item2 Prop 2", prop3: "Item2 Prop 3" },
|
|
35
66
|
{ prop1: "Item3 Prop 1", prop2: "Item3 Prop 2", prop3: "Item3 Prop 3" }
|
|
36
67
|
],
|
|
37
|
-
colConfig: { prop1: { name: "Header 1" }, prop2: { name: "Header 2" } }
|
|
38
|
-
itemKey: "prop1"
|
|
68
|
+
colConfig: { prop1: { name: "Header 1" }, prop2: { name: "Header 2" } }
|
|
39
69
|
}
|
|
40
70
|
}
|
|
41
71
|
|
|
@@ -46,6 +76,7 @@ export const NoCellBorders: Story = {
|
|
|
46
76
|
cellBorder: false
|
|
47
77
|
}
|
|
48
78
|
}
|
|
79
|
+
|
|
49
80
|
export const NoBorders: Story = {
|
|
50
81
|
...Primary,
|
|
51
82
|
args: {
|
|
@@ -106,24 +137,27 @@ export const InitialSize: Story = {
|
|
|
106
137
|
enabled: true
|
|
107
138
|
},
|
|
108
139
|
class: `
|
|
140
|
+
[&:not(.resizable-cols-setup)]:w-full
|
|
109
141
|
[&:not(.resizable-cols-setup)]:block
|
|
110
142
|
[&:not(.resizable-cols-setup)_thead]:block
|
|
111
143
|
[&:not(.resizable-cols-setup)_thead_tr]:w-full
|
|
112
144
|
[&:not(.resizable-cols-setup)_thead_tr]:flex
|
|
113
145
|
[&:not(.resizable-cols-setup)_thead_tr]:flex-nowrap
|
|
114
|
-
[&:not(.resizable-cols-setup)
|
|
146
|
+
[&:not(.resizable-cols-setup)_thead_th:not(.override-initial)]:flex-1
|
|
115
147
|
`,
|
|
116
148
|
slots: `
|
|
117
149
|
<template #header-prop3="colProps">
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
150
|
+
<th
|
|
151
|
+
:class="\`\${colProps.class} [table:not(.resizable-cols-setup)_&]:w-[min-content] whitespace-nowrap override-initial\`"
|
|
152
|
+
:style="colProps.style"
|
|
153
|
+
>
|
|
154
|
+
{{ colProps.config.name }}
|
|
155
|
+
</th>
|
|
156
|
+
</template>
|
|
124
157
|
`
|
|
125
158
|
}
|
|
126
159
|
}
|
|
160
|
+
|
|
127
161
|
export const FitWidthFalse: Story = {
|
|
128
162
|
...Primary,
|
|
129
163
|
args: {
|
|
@@ -134,6 +168,103 @@ export const FitWidthFalse: Story = {
|
|
|
134
168
|
}
|
|
135
169
|
}
|
|
136
170
|
|
|
171
|
+
|
|
172
|
+
export const StickyHeader: Story = {
|
|
173
|
+
...Primary,
|
|
174
|
+
args: {
|
|
175
|
+
...Primary.args,
|
|
176
|
+
resizable: {
|
|
177
|
+
enabled: true
|
|
178
|
+
},
|
|
179
|
+
stickyHeader: true,
|
|
180
|
+
// moving the border to the wrapper is to hide the little bits of border sticking out
|
|
181
|
+
// added back the right straight border otherwise the scrollbar looks ass
|
|
182
|
+
// this is ever so slightly visible if there is no scrollbar
|
|
183
|
+
wrapperClass: `
|
|
184
|
+
max-h-[50dvh]
|
|
185
|
+
`,
|
|
186
|
+
values: Array.from({ length: 200 }).fill(0).map((_, i) => ({
|
|
187
|
+
prop1: `Item${i + 1} Prop 1`,
|
|
188
|
+
prop2: `Item${i + 1} Prop 2`,
|
|
189
|
+
prop3: `Item${i + 1} Prop 3`
|
|
190
|
+
}))
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
export const VirtualizedFixedHeight: Story = {
|
|
196
|
+
...Primary,
|
|
197
|
+
args: {
|
|
198
|
+
...Primary.args,
|
|
199
|
+
resizable: {
|
|
200
|
+
enabled: true
|
|
201
|
+
},
|
|
202
|
+
virtualizerOptions: {
|
|
203
|
+
enabled: true
|
|
204
|
+
},
|
|
205
|
+
stickyHeader: true,
|
|
206
|
+
wrapperClass: `
|
|
207
|
+
max-h-[50dvh]
|
|
208
|
+
`,
|
|
209
|
+
values: Array.from({ length: 10000 }).fill(0).map((_, i) => ({
|
|
210
|
+
prop1: `Item${i + 1} Prop 1`,
|
|
211
|
+
prop2: `Item${i + 1} Prop 2`,
|
|
212
|
+
prop3: `Item${i + 1} Prop 3`
|
|
213
|
+
}))
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
// this is not the smoothest ever, but then the tan stack example isn't either
|
|
219
|
+
// i think the issue is when the scrollbar gets to it's min height
|
|
220
|
+
export const VirtualizedDynamicHeightExperimental: Story = {
|
|
221
|
+
...VirtualizedFixedHeight,
|
|
222
|
+
args: {
|
|
223
|
+
...VirtualizedFixedHeight.args,
|
|
224
|
+
virtualizerOptions: {
|
|
225
|
+
enabled: true,
|
|
226
|
+
method: "dynamic",
|
|
227
|
+
overscan: 5 // overscan is more expensive in dynamic mode
|
|
228
|
+
},
|
|
229
|
+
class: `
|
|
230
|
+
[&_td]:no-truncate!
|
|
231
|
+
[&_th]:no-truncate!
|
|
232
|
+
`,
|
|
233
|
+
values: Array.from({ length: 10000 }).fill(0).map((_, i) => ({
|
|
234
|
+
prop1: `Item${i + 1} Prop 1: ${faker.helpers.arrayElement(fakerSentences)}`,
|
|
235
|
+
prop2: `Item${i + 1} Prop 2: ${faker.helpers.arrayElement(fakerSentences)}`,
|
|
236
|
+
prop3: `Item${i + 1} Prop 3: ${faker.helpers.arrayElement(fakerSentences)}`
|
|
237
|
+
}))
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
export const VirtualizedFitWidthFalse: Story = {
|
|
243
|
+
...VirtualizedFixedHeight,
|
|
244
|
+
args: {
|
|
245
|
+
...VirtualizedFixedHeight.args,
|
|
246
|
+
resizable: {
|
|
247
|
+
fitWidth: false
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
class: `
|
|
251
|
+
[&_th]:no-truncate!
|
|
252
|
+
[&_th]:whitespace-nowrap!
|
|
253
|
+
[&:not(.resizable-cols-setup)]:w-max
|
|
254
|
+
[&:not(.resizable-cols-setup)_th]:w-max
|
|
255
|
+
`,
|
|
256
|
+
wrapperClass: `
|
|
257
|
+
max-h-[50dvh]
|
|
258
|
+
`,
|
|
259
|
+
values: Array.from({ length: 10000 }).fill(0).map((_, i) => ({
|
|
260
|
+
prop1: `Item${i + 1} Prop 1`,
|
|
261
|
+
prop2: `Item${i + 1} Prop 2`,
|
|
262
|
+
prop3: `Item${i + 1} Prop 3`
|
|
263
|
+
}))
|
|
264
|
+
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
137
268
|
export const ThreeColSomeColsNotResizable: Story = {
|
|
138
269
|
render: args => ({
|
|
139
270
|
components,
|