srcdev-nuxt-components 9.4.6 → 9.4.7
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/.claude/commands/migrate-component.md +34 -3
- package/.claude/component-ledger/audit.json +1 -1
- package/.claude/component-ledger/build.mjs +27 -0
- package/.claude/component-ledger/output.html +8 -3
- package/.claude/component-ledger/template.html +7 -2
- package/.claude/skills/components/column-flow-grid.md +93 -0
- package/.claude/skills/components/entry-animation.md +88 -0
- package/.claude/skills/components/input-copy.md +2 -0
- package/.claude/skills/components/input-text-core.md +186 -0
- package/.claude/skills/components/masonry-grid.md +153 -0
- package/.claude/skills/components/pop-over.md +100 -0
- package/.claude/skills/index.md +6 -1
- package/.vscode/srcdev-component-column-flow-grid.code-snippets +39 -0
- package/.vscode/srcdev-component-entry-animation.code-snippets +29 -0
- package/.vscode/srcdev-component-input-text.code-snippets +107 -0
- package/.vscode/srcdev-component-masonry-grid.code-snippets +51 -0
- package/.vscode/srcdev-component-pop-over.code-snippets +44 -0
- package/app/components/01.atoms/animations/entry/EntryAnimation.vue +7 -1
- package/app/components/01.atoms/animations/entry/stories/EntryAnimation.stories.ts +47 -0
- package/app/components/01.atoms/animations/entry/tests/EntryAnimation.spec.ts +57 -0
- package/app/components/01.atoms/canvas-switcher/stories/CanvasSwitcher.stories.ts +9 -10
- package/app/components/01.atoms/content-wrappers/docs-pages/stories/ContentDocs.stories.ts +12 -13
- package/app/components/01.atoms/grids/column-flow-grid/CONSUMER-STYLING.md +33 -0
- package/app/components/01.atoms/grids/column-flow-grid/ColumnFlowGrid.vue +55 -0
- package/app/components/01.atoms/grids/column-flow-grid/stories/ColumnFlowGrid.stories.ts +178 -0
- package/app/components/01.atoms/grids/column-flow-grid/tests/ColumnFlowGrid.spec.ts +75 -0
- package/app/components/01.atoms/grids/masonry-grid/CONSUMER-STYLING.md +35 -0
- package/app/components/01.atoms/grids/masonry-grid/MasonryGrid.vue +178 -0
- package/app/components/01.atoms/grids/masonry-grid/stories/MasonryGrid.stories.ts +199 -0
- package/app/components/01.atoms/grids/masonry-grid/tests/MasonryGrid.spec.ts +158 -0
- package/app/components/01.atoms/pop-over/CONSUMER-STYLING.md +54 -0
- package/app/components/01.atoms/pop-over/PopOver.vue +201 -0
- package/app/components/01.atoms/pop-over/stories/PopOver.stories.ts +141 -0
- package/app/components/01.atoms/pop-over/tests/PopOver.spec.ts +195 -0
- package/app/components/01.atoms/pop-over/tests/__snapshots__/PopOver.spec.ts.snap +11 -0
- package/app/components/02.molecules/action-menu/stories/ActionMenu.stories.ts +8 -2
- package/app/components/02.molecules/input-copy/InputCopy.vue +14 -0
- package/app/components/02.molecules/input-copy/stories/InputCopy.stories.ts +15 -0
- package/app/components/02.molecules/input-copy/tests/InputCopy.spec.ts +41 -0
- package/app/components/05.forms/input-select/InputSelectCore.vue +1 -1
- package/app/components/05.forms/input-text/InputTextCore.vue +6 -0
- package/app/components/05.forms/input-text/stories/InputPasswordWithLabel.stories.ts +49 -20
- package/app/components/05.forms/input-text/stories/InputTextAsNumberWithLabel.stories.ts +41 -22
- package/app/components/05.forms/input-text/stories/InputTextCore.stories.ts +48 -22
- package/app/components/05.forms/input-text/stories/InputTextWithLabel.stories.ts +43 -17
- package/app/components/05.forms/input-text/tests/InputPasswordWithLabel.spec.ts +56 -0
- package/app/components/05.forms/input-text/tests/InputTextAsNumberWithLabel.spec.ts +61 -0
- package/app/components/05.forms/input-text/tests/InputTextCore.spec.ts +60 -0
- package/app/components/05.forms/input-text/tests/InputTextWithLabel.spec.ts +46 -0
- package/app/components/05.forms/input-text/variants/InputPasswordWithLabel.vue +7 -1
- package/app/components/05.forms/input-text/variants/InputTextAsNumberWithLabel.vue +8 -2
- package/app/components/05.forms/input-text/variants/InputTextWithLabel.vue +6 -0
- package/app/components/05.forms/input-textarea/stories/InputTextareaCore.stories.ts +20 -20
- package/app/components/05.forms/input-textarea/stories/InputTextareaWithLabel.stories.ts +32 -26
- package/app/types/forms/types.forms.d.ts +1 -1
- package/package.json +1 -1
- package/app/components/masonry-grid/MasonryGrid.vue +0 -68
- package/app/components/masonry-grid-ordered/MasonryGridOrdered.vue +0 -163
- package/app/components/masonry-grid-ordered/MasonryGridOrderedGridExperiment.vue +0 -259
- package/app/components/masonry-grid-ordered/stories/MasonryGridOrdered.stories.ts +0 -354
- package/app/components/masonry-grid-sorted/MasonryGridSorted.vue +0 -120
- package/app/components/pop-over/PopOver.vue +0 -90
- package/app/layouts/default.vue +0 -308
- package/app/layouts/site-navigation-demo.vue +0 -188
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryFn } from "@nuxtjs/storybook";
|
|
2
|
-
import StorybookComponent from "../MasonryGridOrdered.vue";
|
|
3
|
-
import type { IQuote } from "~/types/types.quotes";
|
|
4
|
-
|
|
5
|
-
// Custom interface for story args
|
|
6
|
-
interface MasonryGridOrderedStoryArgs {
|
|
7
|
-
gridData: IQuote[];
|
|
8
|
-
gap: number;
|
|
9
|
-
minTileWidth: number;
|
|
10
|
-
fixedWidth: boolean;
|
|
11
|
-
styleClassPassthrough: string[];
|
|
12
|
-
// Display options for stories
|
|
13
|
-
showBorders: boolean;
|
|
14
|
-
showNumbers: boolean;
|
|
15
|
-
itemVariant: "simple" | "card" | "detailed";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Sample data for stories
|
|
19
|
-
const sampleQuotes: IQuote[] = [
|
|
20
|
-
{
|
|
21
|
-
id: 1,
|
|
22
|
-
quote: "The only way to do great work is to love what you do.",
|
|
23
|
-
author: "Steve Jobs",
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
id: 2,
|
|
27
|
-
quote: "Life is what happens to you while you're busy making other plans.",
|
|
28
|
-
author: "John Lennon",
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: 3,
|
|
32
|
-
quote: "The future belongs to those who believe in the beauty of their dreams.",
|
|
33
|
-
author: "Eleanor Roosevelt",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: 4,
|
|
37
|
-
quote: "It is during our darkest moments that we must focus to see the light.",
|
|
38
|
-
author: "Aristotle",
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
id: 5,
|
|
42
|
-
quote: "The way to get started is to quit talking and begin doing.",
|
|
43
|
-
author: "Walt Disney",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: 6,
|
|
47
|
-
quote: "Don't let yesterday take up too much of today.",
|
|
48
|
-
author: "Will Rogers",
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: 7,
|
|
52
|
-
quote: "You learn more from failure than from success. Don't let it stop you. Failure builds character.",
|
|
53
|
-
author: "Unknown",
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
id: 8,
|
|
57
|
-
quote: "It's not whether you get knocked down, it's whether you get up.",
|
|
58
|
-
author: "Vince Lombardi",
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
id: 9,
|
|
62
|
-
quote:
|
|
63
|
-
"If you are working on something that you really care about, you don't have to be pushed. The vision pulls you.",
|
|
64
|
-
author: "Steve Jobs",
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
id: 10,
|
|
68
|
-
quote: "People who are crazy enough to think they can change the world, are the ones who do.",
|
|
69
|
-
author: "Rob Siltanen",
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
id: 11,
|
|
73
|
-
quote: "We don't make mistakes, just happy little accidents.",
|
|
74
|
-
author: "Bob Ross",
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: 12,
|
|
78
|
-
quote: "In the middle of every difficulty lies opportunity.",
|
|
79
|
-
author: "Albert Einstein",
|
|
80
|
-
},
|
|
81
|
-
];
|
|
82
|
-
|
|
83
|
-
export default {
|
|
84
|
-
title: "Components/UI/MasonryGridOrdered",
|
|
85
|
-
component: StorybookComponent,
|
|
86
|
-
argTypes: {
|
|
87
|
-
// Layout Configuration
|
|
88
|
-
gap: {
|
|
89
|
-
control: { type: "range", min: 0, max: 50, step: 2 },
|
|
90
|
-
description: "Gap between grid items in pixels",
|
|
91
|
-
table: {
|
|
92
|
-
category: "Layout",
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
minTileWidth: {
|
|
96
|
-
control: { type: "range", min: 200, max: 500, step: 10 },
|
|
97
|
-
description: "Minimum width for each grid tile",
|
|
98
|
-
table: {
|
|
99
|
-
category: "Layout",
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
fixedWidth: {
|
|
103
|
-
control: { type: "boolean" },
|
|
104
|
-
description: "Whether to use fixed width for tiles",
|
|
105
|
-
table: {
|
|
106
|
-
category: "Layout",
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
styleClassPassthrough: {
|
|
110
|
-
control: { type: "object" },
|
|
111
|
-
description: "Additional CSS classes to pass through",
|
|
112
|
-
table: {
|
|
113
|
-
category: "Layout",
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
// Data Configuration
|
|
117
|
-
gridData: {
|
|
118
|
-
control: { type: "object" },
|
|
119
|
-
description: "Array of quote objects to display in the grid",
|
|
120
|
-
table: {
|
|
121
|
-
category: "Data",
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
// Display Options (for stories only)
|
|
125
|
-
showBorders: {
|
|
126
|
-
control: { type: "boolean" },
|
|
127
|
-
description: "Show borders around grid items",
|
|
128
|
-
table: {
|
|
129
|
-
category: "Display Options",
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
showNumbers: {
|
|
133
|
-
control: { type: "boolean" },
|
|
134
|
-
description: "Show index numbers on grid items",
|
|
135
|
-
table: {
|
|
136
|
-
category: "Display Options",
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
itemVariant: {
|
|
140
|
-
control: { type: "select" },
|
|
141
|
-
options: ["simple", "card", "detailed"],
|
|
142
|
-
description: "Style variant for grid items",
|
|
143
|
-
table: {
|
|
144
|
-
category: "Display Options",
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
args: {
|
|
149
|
-
gridData: sampleQuotes.slice(0, 8),
|
|
150
|
-
gap: 12,
|
|
151
|
-
minTileWidth: 300,
|
|
152
|
-
fixedWidth: true,
|
|
153
|
-
styleClassPassthrough: ["mi-auto"],
|
|
154
|
-
showBorders: true,
|
|
155
|
-
showNumbers: true,
|
|
156
|
-
itemVariant: "card",
|
|
157
|
-
},
|
|
158
|
-
} as Meta<MasonryGridOrderedStoryArgs>;
|
|
159
|
-
|
|
160
|
-
const Template: StoryFn<MasonryGridOrderedStoryArgs> = (args) => ({
|
|
161
|
-
components: {
|
|
162
|
-
StorybookComponent,
|
|
163
|
-
},
|
|
164
|
-
setup() {
|
|
165
|
-
const getItemClasses = (variant: string, showBorders: boolean) => {
|
|
166
|
-
const baseClasses = ["p-10"];
|
|
167
|
-
|
|
168
|
-
if (showBorders) {
|
|
169
|
-
baseClasses.push("border", "border-1", "border-grey-dark");
|
|
170
|
-
|
|
171
|
-
if (variant === "card") {
|
|
172
|
-
baseClasses.push("border-r-4");
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (variant === "detailed") {
|
|
177
|
-
baseClasses.push("bg-gray-1", "rounded-4");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return baseClasses.join(" ");
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
return { args, getItemClasses };
|
|
184
|
-
},
|
|
185
|
-
template: `
|
|
186
|
-
<div style="padding: 20px; max-width: 1200px; margin: 0 auto;">
|
|
187
|
-
<div style="margin-bottom: 20px;">
|
|
188
|
-
<h3 style="margin-bottom: 10px;">MasonryGridOrdered Component</h3>
|
|
189
|
-
<p style="color: #666; margin-bottom: 20px;">
|
|
190
|
-
Displaying {{ args.gridData.length }} items with {{ args.gap }}px gap and {{ args.minTileWidth }}px minimum width
|
|
191
|
-
</p>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
<StorybookComponent
|
|
195
|
-
:gridData="args.gridData"
|
|
196
|
-
:gap="args.gap"
|
|
197
|
-
:min-tile-width="args.minTileWidth"
|
|
198
|
-
:fixed-width="args.fixedWidth"
|
|
199
|
-
:styleClassPassthrough="args.styleClassPassthrough"
|
|
200
|
-
>
|
|
201
|
-
<template v-for="(item, index) in args.gridData" v-slot:[item.id]>
|
|
202
|
-
<div :class="getItemClasses(args.itemVariant, args.showBorders)">
|
|
203
|
-
<p v-if="args.showNumbers" class="text-normal wght-700" style="margin-bottom: 8px;">
|
|
204
|
-
{{ index + 1 }}: {{ item.author }}
|
|
205
|
-
</p>
|
|
206
|
-
<p v-else class="text-normal wght-700" style="margin-bottom: 8px;">
|
|
207
|
-
{{ item.author }}
|
|
208
|
-
</p>
|
|
209
|
-
<p class="text-normal">{{ item.quote }}</p>
|
|
210
|
-
</div>
|
|
211
|
-
</template>
|
|
212
|
-
</StorybookComponent>
|
|
213
|
-
</div>
|
|
214
|
-
`,
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
export const Default = Template.bind({});
|
|
218
|
-
|
|
219
|
-
export const SmallGap = Template.bind({});
|
|
220
|
-
SmallGap.args = {
|
|
221
|
-
gap: 4,
|
|
222
|
-
minTileWidth: 250,
|
|
223
|
-
fixedWidth: false,
|
|
224
|
-
itemVariant: "simple",
|
|
225
|
-
showBorders: false,
|
|
226
|
-
showNumbers: false,
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
export const LargeGap = Template.bind({});
|
|
230
|
-
LargeGap.args = {
|
|
231
|
-
gap: 24,
|
|
232
|
-
minTileWidth: 320,
|
|
233
|
-
fixedWidth: true,
|
|
234
|
-
itemVariant: "card",
|
|
235
|
-
showBorders: true,
|
|
236
|
-
showNumbers: true,
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
export const WideItems = Template.bind({});
|
|
240
|
-
WideItems.args = {
|
|
241
|
-
gap: 16,
|
|
242
|
-
minTileWidth: 400,
|
|
243
|
-
fixedWidth: false,
|
|
244
|
-
itemVariant: "detailed",
|
|
245
|
-
showBorders: true,
|
|
246
|
-
showNumbers: false,
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
export const NarrowItems = Template.bind({});
|
|
250
|
-
NarrowItems.args = {
|
|
251
|
-
gap: 8,
|
|
252
|
-
minTileWidth: 200,
|
|
253
|
-
fixedWidth: true,
|
|
254
|
-
itemVariant: "simple",
|
|
255
|
-
showBorders: true,
|
|
256
|
-
showNumbers: true,
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
export const ManyItems = Template.bind({});
|
|
260
|
-
ManyItems.args = {
|
|
261
|
-
gridData: sampleQuotes, // All 12 items
|
|
262
|
-
gap: 12,
|
|
263
|
-
minTileWidth: 280,
|
|
264
|
-
fixedWidth: true,
|
|
265
|
-
itemVariant: "card",
|
|
266
|
-
showBorders: true,
|
|
267
|
-
showNumbers: true,
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
export const FewItems = Template.bind({});
|
|
271
|
-
FewItems.args = {
|
|
272
|
-
gridData: sampleQuotes.slice(0, 4),
|
|
273
|
-
gap: 20,
|
|
274
|
-
minTileWidth: 350,
|
|
275
|
-
fixedWidth: false,
|
|
276
|
-
itemVariant: "detailed",
|
|
277
|
-
showBorders: true,
|
|
278
|
-
showNumbers: false,
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
export const MinimalStyle = Template.bind({});
|
|
282
|
-
MinimalStyle.args = {
|
|
283
|
-
gap: 16,
|
|
284
|
-
minTileWidth: 300,
|
|
285
|
-
fixedWidth: false,
|
|
286
|
-
styleClassPassthrough: [],
|
|
287
|
-
itemVariant: "simple",
|
|
288
|
-
showBorders: false,
|
|
289
|
-
showNumbers: false,
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
export const CustomStyles = Template.bind({});
|
|
293
|
-
CustomStyles.args = {
|
|
294
|
-
gap: 12,
|
|
295
|
-
minTileWidth: 320,
|
|
296
|
-
fixedWidth: true,
|
|
297
|
-
styleClassPassthrough: ["mi-auto", "mb-20"],
|
|
298
|
-
itemVariant: "detailed",
|
|
299
|
-
showBorders: true,
|
|
300
|
-
showNumbers: true,
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
// Example with different content structure
|
|
304
|
-
const Template2: StoryFn<MasonryGridOrderedStoryArgs> = (args) => ({
|
|
305
|
-
components: {
|
|
306
|
-
StorybookComponent,
|
|
307
|
-
},
|
|
308
|
-
setup() {
|
|
309
|
-
return { args };
|
|
310
|
-
},
|
|
311
|
-
template: `
|
|
312
|
-
<div style="padding: 20px; max-width: 1200px; margin: 0 auto;">
|
|
313
|
-
<div style="margin-bottom: 20px;">
|
|
314
|
-
<h3 style="margin-bottom: 10px;">Custom Content Example</h3>
|
|
315
|
-
<p style="color: #666; margin-bottom: 20px;">
|
|
316
|
-
Showing how different content can be displayed in the masonry grid
|
|
317
|
-
</p>
|
|
318
|
-
</div>
|
|
319
|
-
|
|
320
|
-
<StorybookComponent
|
|
321
|
-
:gridData="args.gridData"
|
|
322
|
-
:gap="args.gap"
|
|
323
|
-
:min-tile-width="args.minTileWidth"
|
|
324
|
-
:fixed-width="args.fixedWidth"
|
|
325
|
-
:styleClassPassthrough="args.styleClassPassthrough"
|
|
326
|
-
>
|
|
327
|
-
<template v-for="(item, index) in args.gridData" v-slot:[item.id]>
|
|
328
|
-
<div class="p-16 bg-gray-1 rounded-8 border border-1 border-gray-6">
|
|
329
|
-
<div style="display: flex; align-items: center; margin-bottom: 12px;">
|
|
330
|
-
<div
|
|
331
|
-
style="width: 32px; height: 32px; border-radius: 50%; background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; margin-right: 12px; font-size: 14px;"
|
|
332
|
-
>
|
|
333
|
-
{{ index + 1 }}
|
|
334
|
-
</div>
|
|
335
|
-
<h4 class="text-normal wght-700" style="margin: 0;">{{ item.author }}</h4>
|
|
336
|
-
</div>
|
|
337
|
-
<blockquote class="text-normal" style="font-style: italic; border-left: 3px solid #667eea; padding-left: 12px; margin: 0;">
|
|
338
|
-
"{{ item.quote }}"
|
|
339
|
-
</blockquote>
|
|
340
|
-
</div>
|
|
341
|
-
</template>
|
|
342
|
-
</StorybookComponent>
|
|
343
|
-
</div>
|
|
344
|
-
`,
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
export const RichContent = Template2.bind({});
|
|
348
|
-
RichContent.args = {
|
|
349
|
-
gridData: sampleQuotes.slice(0, 6),
|
|
350
|
-
gap: 16,
|
|
351
|
-
minTileWidth: 320,
|
|
352
|
-
fixedWidth: false,
|
|
353
|
-
styleClassPassthrough: ["mi-auto"],
|
|
354
|
-
};
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="masonry-grid-wrapper"
|
|
4
|
-
:class="[elementClasses]"
|
|
5
|
-
:style="`--_masonry-grid-gap: ${gap}${unit}; --_item-min-width: ${itemMinWidth}px`"
|
|
6
|
-
ref="gridWrapper"
|
|
7
|
-
>
|
|
8
|
-
<template v-for="item in rearrangedItems" :key="item.id">
|
|
9
|
-
<div class="masonry-grid-item">
|
|
10
|
-
<slot :name="item.id"></slot>
|
|
11
|
-
</div>
|
|
12
|
-
</template>
|
|
13
|
-
</div>
|
|
14
|
-
</template>
|
|
15
|
-
|
|
16
|
-
<script setup lang="ts">
|
|
17
|
-
const props = defineProps({
|
|
18
|
-
gridData: {
|
|
19
|
-
type: Array as PropType<any[]>,
|
|
20
|
-
default: () => [],
|
|
21
|
-
},
|
|
22
|
-
itemMinWidth: {
|
|
23
|
-
type: Number,
|
|
24
|
-
default: 300,
|
|
25
|
-
},
|
|
26
|
-
gap: {
|
|
27
|
-
type: Number,
|
|
28
|
-
default: 1.2,
|
|
29
|
-
},
|
|
30
|
-
unit: {
|
|
31
|
-
type: String,
|
|
32
|
-
default: "rem",
|
|
33
|
-
},
|
|
34
|
-
styleClassPassthrough: {
|
|
35
|
-
type: [String, Array] as PropType<string | string[]>,
|
|
36
|
-
default: () => [],
|
|
37
|
-
},
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
41
|
-
|
|
42
|
-
const gridData = toRef(() => props.gridData)
|
|
43
|
-
|
|
44
|
-
const gridWrapper = ref<HTMLDivElement>()
|
|
45
|
-
|
|
46
|
-
const getColumnCountWithinGridWrapper = () => {
|
|
47
|
-
return gridWrapper.value ? Math.floor(gridWrapper.value.clientWidth / props.itemMinWidth) : 0
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// const columns = ref(4);
|
|
51
|
-
const columns = computed(() => {
|
|
52
|
-
return gridWrapper.value ? Math.floor(gridWrapper.value.clientWidth / props.itemMinWidth) : 0
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const rearrangeArray = (items: any[], columns: number): any[] => {
|
|
56
|
-
const rows = Math.ceil(items.length / columns)
|
|
57
|
-
const rearrangedArray = []
|
|
58
|
-
|
|
59
|
-
for (let col = 0; col < columns; col++) {
|
|
60
|
-
for (let row = 0; row < rows; row++) {
|
|
61
|
-
const index = row * columns + col
|
|
62
|
-
if (index < items.length) {
|
|
63
|
-
rearrangedArray.push(items[index])
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return rearrangedArray
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const rearrangedItems = computed(() => rearrangeArray(props.gridData, columns.value))
|
|
72
|
-
// const rearrangedItems = computed(() => {
|
|
73
|
-
// const rows = Math.ceil(props.gridData.length / columns.value);
|
|
74
|
-
// const rearrangedArray = [];
|
|
75
|
-
|
|
76
|
-
// for (let col = 0; col < columns.value; col++) {
|
|
77
|
-
// for (let row = 0; row < rows; row++) {
|
|
78
|
-
// const index = row * columns.value + col;
|
|
79
|
-
// if (index < props.gridData.length) {
|
|
80
|
-
// rearrangedArray.push(props.gridData[index]);
|
|
81
|
-
// }
|
|
82
|
-
// }
|
|
83
|
-
// }
|
|
84
|
-
|
|
85
|
-
// return rearrangedArray;
|
|
86
|
-
// });
|
|
87
|
-
|
|
88
|
-
watch(
|
|
89
|
-
() => props.styleClassPassthrough,
|
|
90
|
-
() => {
|
|
91
|
-
resetElementClasses(props.styleClassPassthrough)
|
|
92
|
-
}
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
// onMounted(() => {
|
|
96
|
-
// console.log(getColumnCountWithinGridWrapper());
|
|
97
|
-
// });
|
|
98
|
-
|
|
99
|
-
// useResizeObserver(gridWrapper, () => {
|
|
100
|
-
// console.log(getColumnCountWithinGridWrapper());
|
|
101
|
-
// });
|
|
102
|
-
</script>
|
|
103
|
-
|
|
104
|
-
<style lang="css">
|
|
105
|
-
@layer components {
|
|
106
|
-
.masonry-grid-wrapper {
|
|
107
|
-
--_border-color: light-dark(hsl(0, 29%, 3%), hsl(0, 0%, 92%));
|
|
108
|
-
|
|
109
|
-
columns: var(--_item-min-width);
|
|
110
|
-
gap: var(--_masonry-grid-gap);
|
|
111
|
-
|
|
112
|
-
.masonry-grid-item {
|
|
113
|
-
break-inside: avoid;
|
|
114
|
-
outline: 0.1rem solid var(--_border-color);
|
|
115
|
-
padding: 1.2rem;
|
|
116
|
-
margin-block-end: var(--_masonry-grid-gap);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
</style>
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<ClientOnly>
|
|
3
|
-
<button :popovertarget popovertargetaction="toggle" class="popover-trigger" :class="[elementClasses]">
|
|
4
|
-
<slot name="trigger"></slot>
|
|
5
|
-
</button>
|
|
6
|
-
|
|
7
|
-
<div class="dialog" popover role="tooltip" :id="popovertarget" :class="[elementClasses]">
|
|
8
|
-
<button :popovertarget popovertargetaction="hide">x</button>
|
|
9
|
-
<slot name="popoverCotent"></slot>
|
|
10
|
-
</div>
|
|
11
|
-
</ClientOnly>
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<script setup lang="ts">
|
|
15
|
-
const props = defineProps({
|
|
16
|
-
popovertarget: {
|
|
17
|
-
type: String,
|
|
18
|
-
required: true,
|
|
19
|
-
},
|
|
20
|
-
styleClassPassthrough: {
|
|
21
|
-
type: [String, Array] as PropType<string | string[]>,
|
|
22
|
-
default: () => [],
|
|
23
|
-
},
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
const anchorName = `--anchor-${useId()}`
|
|
27
|
-
|
|
28
|
-
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<style scoped lang="css">
|
|
32
|
-
@layer components {
|
|
33
|
-
@layer popover-setup {
|
|
34
|
-
/* @position-try --right {
|
|
35
|
-
inset: auto;
|
|
36
|
-
top: anchor(top);
|
|
37
|
-
left: calc(anchor(right) + 10px);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@position-try --left {
|
|
41
|
-
inset: auto;
|
|
42
|
-
top: anchor(top);
|
|
43
|
-
right: calc(anchor(left) + 10px);
|
|
44
|
-
} */
|
|
45
|
-
|
|
46
|
-
.popover-trigger {
|
|
47
|
-
anchor-name: v-bind(anchorName);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.dialog {
|
|
51
|
-
display: none;
|
|
52
|
-
position: absolute;
|
|
53
|
-
position-anchor: v-bind(anchorName);
|
|
54
|
-
margin: 0;
|
|
55
|
-
inset: auto;
|
|
56
|
-
top: calc(anchor(top) + 0px);
|
|
57
|
-
left: calc(anchor(right) + 10px);
|
|
58
|
-
opacity: 0;
|
|
59
|
-
transition: opacity 200ms, display 200ms, overlay 200ms;
|
|
60
|
-
transition-behavior: allow-discrete;
|
|
61
|
-
|
|
62
|
-
position-try-fallbacks: flip-inline;
|
|
63
|
-
|
|
64
|
-
&:popover-open {
|
|
65
|
-
display: block;
|
|
66
|
-
opacity: 1;
|
|
67
|
-
|
|
68
|
-
@starting-style {
|
|
69
|
-
display: block;
|
|
70
|
-
opacity: 0;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@position-try --top-left {
|
|
76
|
-
top: anchor(top);
|
|
77
|
-
right: calc(anchor(left + 10px));
|
|
78
|
-
left: unset;
|
|
79
|
-
/* width: revert; */
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@position-try --bottom-right {
|
|
83
|
-
top: anchor(bottom);
|
|
84
|
-
/* right: calc(anchor(left + 10px)); */
|
|
85
|
-
/* left: unset; */
|
|
86
|
-
/* width: revert; */
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
</style>
|