srcdev-nuxt-components 9.1.41 → 9.1.43

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.
@@ -0,0 +1,311 @@
1
+ <template>
2
+ <div>
3
+ <NuxtLayout name="default">
4
+ <template #layout-content>
5
+
6
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-32']">
7
+ <h1 class="page-heading-1">AutoGrid</h1>
8
+ <p class="page-body-normal">
9
+ Responsive auto-fit CSS grid wrapper. Columns auto-fit to a minimum width; when
10
+ <code>is-responsive</code> is enabled, the minimum shifts at container breakpoints via
11
+ <code>@container</code> queries.
12
+ </p>
13
+ </LayoutRow>
14
+
15
+ <div v-if="isDev" class="qa-panel">
16
+ <details class="qa-panel__details">
17
+ <summary class="qa-panel__summary">
18
+ <span class="qa-panel__title">QA — AutoGrid</span>
19
+ <code class="qa-panel__status">
20
+ tag:{{ qaTag }} · responsive:{{ qaIsResponsive ? "on" : "off" }} · small:{{ qaMinColSizeSmall }} · default:{{ qaMinColSizeDefault }} · large:{{ qaMinColSizeLarge }} · gap:{{ qaGap }}
21
+ </code>
22
+ </summary>
23
+ <div class="qa-panel__body">
24
+
25
+ <div class="qa-panel__group">
26
+ <span class="qa-panel__label">tag</span>
27
+ <div class="qa-panel__chips">
28
+ <button
29
+ v-for="opt in tagOptions"
30
+ :key="opt"
31
+ class="qa-panel__chip"
32
+ :class="{ 'is-active': qaTag === opt }"
33
+ @click="qaTag = opt"
34
+ >{{ opt }}</button>
35
+ </div>
36
+ </div>
37
+
38
+ <div class="qa-panel__group">
39
+ <span class="qa-panel__label">is-responsive</span>
40
+ <div class="qa-panel__chips">
41
+ <button
42
+ v-for="opt in [true, false]"
43
+ :key="String(opt)"
44
+ class="qa-panel__chip"
45
+ :class="{ 'is-active': qaIsResponsive === opt }"
46
+ @click="qaIsResponsive = opt"
47
+ >{{ opt ? "on" : "off" }}</button>
48
+ </div>
49
+ </div>
50
+
51
+ <div class="qa-panel__group">
52
+ <span class="qa-panel__label">min-col-size-small</span>
53
+ <div class="qa-panel__chips">
54
+ <button
55
+ v-for="preset in sizePresets"
56
+ :key="preset"
57
+ class="qa-panel__chip"
58
+ :class="{ 'is-active': qaMinColSizeSmall === preset }"
59
+ @click="qaMinColSizeSmall = preset"
60
+ >{{ preset }}</button>
61
+ </div>
62
+ <input v-model="qaMinColSizeSmall" placeholder="e.g. 200px" class="qa-panel__input" />
63
+ </div>
64
+
65
+ <div class="qa-panel__group">
66
+ <span class="qa-panel__label">min-col-size-default</span>
67
+ <div class="qa-panel__chips">
68
+ <button
69
+ v-for="preset in sizePresets"
70
+ :key="preset"
71
+ class="qa-panel__chip"
72
+ :class="{ 'is-active': qaMinColSizeDefault === preset }"
73
+ @click="qaMinColSizeDefault = preset"
74
+ >{{ preset }}</button>
75
+ </div>
76
+ <input v-model="qaMinColSizeDefault" placeholder="e.g. 300px" class="qa-panel__input" />
77
+ </div>
78
+
79
+ <div class="qa-panel__group">
80
+ <span class="qa-panel__label">min-col-size-large</span>
81
+ <div class="qa-panel__chips">
82
+ <button
83
+ v-for="preset in sizePresets"
84
+ :key="preset"
85
+ class="qa-panel__chip"
86
+ :class="{ 'is-active': qaMinColSizeLarge === preset }"
87
+ @click="qaMinColSizeLarge = preset"
88
+ >{{ preset }}</button>
89
+ </div>
90
+ <input v-model="qaMinColSizeLarge" placeholder="e.g. 350px" class="qa-panel__input" />
91
+ </div>
92
+
93
+ <div class="qa-panel__group">
94
+ <span class="qa-panel__label">gap</span>
95
+ <div class="qa-panel__chips">
96
+ <button
97
+ v-for="preset in gapPresets"
98
+ :key="preset"
99
+ class="qa-panel__chip"
100
+ :class="{ 'is-active': qaGap === preset }"
101
+ @click="qaGap = preset"
102
+ >{{ preset }}</button>
103
+ </div>
104
+ <input v-model="qaGap" placeholder="e.g. 2rem" class="qa-panel__input" />
105
+ </div>
106
+
107
+ </div>
108
+ </details>
109
+ </div>
110
+
111
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-32']">
112
+ <div class="auto-grid-demo-container">
113
+ <AutoGrid
114
+ :tag="qaTag"
115
+ :is-responsive="qaIsResponsive"
116
+ :min-col-size-small="qaMinColSizeSmall"
117
+ :min-col-size-default="qaMinColSizeDefault"
118
+ :min-col-size-large="qaMinColSizeLarge"
119
+ :style="qaStyle"
120
+ >
121
+ <template v-for="card in statCards" #[card.id] :key="card.id">
122
+ <div class="stat-card">
123
+ <span class="stat-card__label">{{ card.label }}</span>
124
+ <span class="stat-card__value">{{ card.value }}</span>
125
+ </div>
126
+ </template>
127
+ </AutoGrid>
128
+ </div>
129
+ </LayoutRow>
130
+
131
+ </template>
132
+ </NuxtLayout>
133
+ </div>
134
+ </template>
135
+
136
+ <script setup lang="ts">
137
+ definePageMeta({ layout: false });
138
+
139
+ useHead({
140
+ title: "AutoGrid",
141
+ meta: [{ name: "description", content: "AutoGrid component demo" }],
142
+ bodyAttrs: { class: "auto-grid-page" },
143
+ });
144
+
145
+ const isDev = import.meta.dev;
146
+
147
+ const tagOptions = ["div", "section", "article", "main"] as const;
148
+ const qaTag = ref<"div" | "section" | "article" | "main">("div");
149
+ const qaIsResponsive = ref(false);
150
+ const qaMinColSizeSmall = ref("250px");
151
+ const qaMinColSizeDefault = ref("300px");
152
+ const qaMinColSizeLarge = ref("350px");
153
+ const qaGap = ref("1rem");
154
+
155
+ const sizePresets = ["150px", "200px", "250px", "300px", "350px", "400px"];
156
+ const gapPresets = ["0.5rem", "1rem", "1.6rem", "2.4rem", "3.2rem"];
157
+
158
+ const qaStyle = computed(() => ({
159
+ "--auto-grid-min-col-size-small": qaMinColSizeSmall.value,
160
+ "--auto-grid-min-col-size-default": qaMinColSizeDefault.value,
161
+ "--auto-grid-min-col-size-large": qaMinColSizeLarge.value,
162
+ "--auto-grid-gap": qaGap.value,
163
+ }));
164
+
165
+ const statCards = [
166
+ { id: "item-1", label: "Revenue", value: "£24,500" },
167
+ { id: "item-2", label: "Clients", value: "142" },
168
+ { id: "item-3", label: "Bookings", value: "38" },
169
+ { id: "item-4", label: "Avg. Rating", value: "4.9" },
170
+ { id: "item-5", label: "New Users", value: "76" },
171
+ { id: "item-6", label: "Retention", value: "91%" },
172
+ ];
173
+ </script>
174
+
175
+ <style lang="css">
176
+ .auto-grid-page {
177
+ code {
178
+ font-family: monospace;
179
+ font-size: 0.9em;
180
+ background: var(--slate-02);
181
+ padding: 0.1em 0.4em;
182
+ border-radius: 0.3rem;
183
+ }
184
+
185
+ .auto-grid-demo-container {
186
+ container-type: inline-size;
187
+ }
188
+
189
+ .stat-card {
190
+ display: flex;
191
+ flex-direction: column;
192
+ gap: 0.8rem;
193
+ padding: 2.4rem;
194
+ background: white;
195
+ border-radius: 0.8rem;
196
+ box-shadow: 0 2px 8px oklch(0% 0 0 / 0.08);
197
+ }
198
+
199
+ .stat-card__label {
200
+ font-size: 1.2rem;
201
+ font-weight: 600;
202
+ text-transform: uppercase;
203
+ letter-spacing: 0.05em;
204
+ color: var(--slate-08, #6b7280);
205
+ }
206
+
207
+ .stat-card__value {
208
+ font-size: 2.4rem;
209
+ font-weight: 700;
210
+ color: var(--slate-12, #111827);
211
+ }
212
+
213
+ /* ── QA Panel ──────────────────────────────────────────────────── */
214
+
215
+ .qa-panel {
216
+ background: oklch(15% 0 0);
217
+ color: white;
218
+ font-size: 1.3rem;
219
+ }
220
+
221
+ .qa-panel__details {
222
+ padding: 1rem 2rem;
223
+ }
224
+
225
+ .qa-panel__summary {
226
+ cursor: pointer;
227
+ display: flex;
228
+ align-items: center;
229
+ gap: 1.6rem;
230
+ list-style: none;
231
+ user-select: none;
232
+
233
+ &::-webkit-details-marker { display: none; }
234
+ }
235
+
236
+ .qa-panel__title {
237
+ font-weight: 600;
238
+ font-size: 1.1rem;
239
+ text-transform: uppercase;
240
+ letter-spacing: 0.08em;
241
+ }
242
+
243
+ .qa-panel__status {
244
+ font-family: monospace;
245
+ font-size: 1.2rem;
246
+ background: oklch(0% 0 0 / 0.3);
247
+ padding: 0.2rem 0.8rem;
248
+ border-radius: 0.4rem;
249
+ user-select: text;
250
+ cursor: text;
251
+ }
252
+
253
+ .qa-panel__body {
254
+ display: flex;
255
+ flex-wrap: wrap;
256
+ gap: 2.4rem;
257
+ padding-block: 1.2rem 0.4rem;
258
+ }
259
+
260
+ .qa-panel__group {
261
+ display: flex;
262
+ flex-direction: column;
263
+ gap: 0.6rem;
264
+ }
265
+
266
+ .qa-panel__label {
267
+ font-size: 1.1rem;
268
+ text-transform: uppercase;
269
+ letter-spacing: 0.08em;
270
+ opacity: 0.55;
271
+ }
272
+
273
+ .qa-panel__chips {
274
+ display: flex;
275
+ flex-wrap: wrap;
276
+ gap: 0.4rem;
277
+ }
278
+
279
+ .qa-panel__chip {
280
+ font-family: monospace;
281
+ font-size: 1.2rem;
282
+ color: white;
283
+ background: oklch(0% 0 0 / 0.25);
284
+ border: 1px solid oklch(100% 0 0 / 0.18);
285
+ padding: 0.3rem 1rem;
286
+ border-radius: 0.4rem;
287
+ cursor: pointer;
288
+ transition: background 0.15s;
289
+
290
+ &:hover { background: oklch(0% 0 0 / 0.4); }
291
+
292
+ &.is-active {
293
+ background: oklch(55% 0.18 240);
294
+ border-color: oklch(55% 0.18 240);
295
+ }
296
+ }
297
+
298
+ .qa-panel__input {
299
+ font-family: monospace;
300
+ font-size: 1.2rem;
301
+ color: white;
302
+ background: oklch(0% 0 0 / 0.25);
303
+ border: 1px solid oklch(100% 0 0 / 0.18);
304
+ padding: 0.3rem 1rem;
305
+ border-radius: 0.4rem;
306
+ width: 18rem;
307
+
308
+ &::placeholder { opacity: 0.45; }
309
+ }
310
+ }
311
+ </style>
@@ -7,6 +7,11 @@
7
7
  <NuxtLink class="page-body-normal" to="/grid-stack">GridStack</NuxtLink>
8
8
  </LayoutRow>
9
9
 
10
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
11
+ <h2 class="page-heading-2">AutoGrid</h2>
12
+ <NuxtLink class="page-body-normal" to="/auto-grid">AutoGrid</NuxtLink>
13
+ </LayoutRow>
14
+
10
15
  <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
11
16
  <h1 class="page-heading-1">Nuxt3 Components Layer</h1>
12
17
  <p>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.1.41",
4
+ "version": "9.1.43",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",
@@ -1,39 +0,0 @@
1
- <template>
2
- <component :is="tag" class="data-grid" :class="[elementClasses]" :aria-labelledby="ariaLabelledby">
3
- <slot v-for="(_, name) in $slots" :key="name" :name="name"></slot>
4
- </component>
5
- </template>
6
-
7
- <script setup lang="ts">
8
- interface Props {
9
- tag?: "div" | "section" | "article" | "main";
10
- styleClassPassthrough?: string | string[];
11
- }
12
-
13
- const props = withDefaults(defineProps<Props>(), {
14
- tag: "div",
15
- styleClassPassthrough: () => [],
16
- });
17
-
18
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
19
- const { ariaLabelledby } = useAriaLabelledById(props.tag);
20
-
21
- watch(
22
- () => props.styleClassPassthrough,
23
- () => resetElementClasses(props.styleClassPassthrough),
24
- );
25
- </script>
26
-
27
- <style lang="css">
28
- @layer components {
29
- .data-grid {
30
- /* CSS Tockens for @container grid-template-columns */
31
- --data-grid-columns: repeat(auto-fit, minmax(250px, 1fr));
32
- --data-grid-gap: 1rem;
33
-
34
- display: grid;
35
- grid-template-columns: var(--data-grid-columns);
36
- gap: var(--data-grid-gap);
37
- }
38
- }
39
- </style>