@witchcraft/ui 0.3.13 → 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.
@@ -224,3 +224,8 @@
224
224
  @apply cursor-pointer hover:text-accent-500;
225
225
  }
226
226
 
227
+ @utility no-truncate {
228
+ text-overflow: unset;
229
+ overflow: visible;
230
+ white-space: normal;
231
+ }
@@ -1,29 +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
- component: LibTable,
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>
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: () => ({ args }),
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="overflow-x-scroll scrollbar-hidden">
22
- <lib-table
23
- v-bind="args"
24
- >
25
- </lib-table>
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>
26
52
  </div>
53
+ <lib-table
54
+ v-if="show"
55
+ v-bind="args"
56
+ >
57
+ ${(args as any).slots}
58
+ </lib-table>
27
59
  `
28
60
  }),
29
61
  args: {
@@ -33,8 +65,7 @@ export const Primary: Story = {
33
65
  { prop1: "Item2 Prop 1", prop2: "Item2 Prop 2", prop3: "Item2 Prop 3" },
34
66
  { prop1: "Item3 Prop 1", prop2: "Item3 Prop 2", prop3: "Item3 Prop 3" }
35
67
  ],
36
- colConfig: { prop1: { name: "Header 1" }, prop2: { name: "Header 2" } },
37
- itemKey: "prop1"
68
+ colConfig: { prop1: { name: "Header 1" }, prop2: { name: "Header 2" } }
38
69
  }
39
70
  }
40
71
 
@@ -45,6 +76,7 @@ export const NoCellBorders: Story = {
45
76
  cellBorder: false
46
77
  }
47
78
  }
79
+
48
80
  export const NoBorders: Story = {
49
81
  ...Primary,
50
82
  args: {
@@ -91,6 +123,41 @@ export const NoHeaderNoCellBorders: Story = {
91
123
  cellBorder: false
92
124
  }
93
125
  }
126
+
127
+ export const InitialSize: Story = {
128
+ ...Primary,
129
+ args: {
130
+ ...Primary.args,
131
+ colConfig: {
132
+ prop1: { name: "Initially Flex 1", resizable: true },
133
+ prop2: { name: "Initially Flex 2", resizable: true },
134
+ prop3: { name: "Initially Size of Header", resizable: true }
135
+ },
136
+ resizable: {
137
+ enabled: true
138
+ },
139
+ class: `
140
+ [&:not(.resizable-cols-setup)]:w-full
141
+ [&:not(.resizable-cols-setup)]:block
142
+ [&:not(.resizable-cols-setup)_thead]:block
143
+ [&:not(.resizable-cols-setup)_thead_tr]:w-full
144
+ [&:not(.resizable-cols-setup)_thead_tr]:flex
145
+ [&:not(.resizable-cols-setup)_thead_tr]:flex-nowrap
146
+ [&:not(.resizable-cols-setup)_thead_th:not(.override-initial)]:flex-1
147
+ `,
148
+ slots: `
149
+ <template #header-prop3="colProps">
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>
157
+ `
158
+ }
159
+ }
160
+
94
161
  export const FitWidthFalse: Story = {
95
162
  ...Primary,
96
163
  args: {
@@ -101,6 +168,103 @@ export const FitWidthFalse: Story = {
101
168
  }
102
169
  }
103
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
+
104
268
  export const ThreeColSomeColsNotResizable: Story = {
105
269
  render: args => ({
106
270
  components,