qstd 0.1.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.
@@ -0,0 +1,475 @@
1
+ 'use strict';
2
+
3
+ // src/preset/index.ts
4
+ var preset = {
5
+ name: "qstd-preset",
6
+ globalCss: {
7
+ ":root": { colorScheme: "light dark" },
8
+ html: {
9
+ fontSize: 16,
10
+ lineHeight: 1.5,
11
+ fontFamily: "geologica, sans-serif"
12
+ }
13
+ },
14
+ theme: {
15
+ semanticTokens: {
16
+ colors: {
17
+ "text-primary": {
18
+ value: {
19
+ base: "{colors.neutral.900}",
20
+ _dark: "{colors.neutral.100}"
21
+ }
22
+ },
23
+ "text-secondary": {
24
+ value: {
25
+ base: "{colors.neutral.400}",
26
+ _dark: "{colors.neutral.400}"
27
+ }
28
+ },
29
+ "text-inverted": {
30
+ value: {
31
+ base: "{colors.neutral.100}",
32
+ _dark: "{colors.neutral.900}"
33
+ }
34
+ },
35
+ "text-alert": {
36
+ value: { base: "{colors.red.600}", _dark: "{colors.red.400}" }
37
+ },
38
+ "input-border-color": {
39
+ value: {
40
+ base: "{colors.neutral.300}",
41
+ _dark: "{colors.neutral.600}"
42
+ }
43
+ },
44
+ "input-border-color-error": {
45
+ value: { base: "{colors.red.400}", _dark: "{colors.red.400}" }
46
+ },
47
+ "input-outline-color-error": {
48
+ value: { base: "{colors.red.500}", _dark: "{colors.red.500}" }
49
+ },
50
+ "input-label-color": {
51
+ value: {
52
+ base: "{colors.neutral.400}",
53
+ _dark: "{colors.neutral.400}"
54
+ }
55
+ },
56
+ "input-label-color-lifted": {
57
+ value: { base: "{colors.blue.500}", _dark: "{colors.blue.500}" }
58
+ },
59
+ "input-label-bg": {
60
+ value: {
61
+ base: "{colors.neutral.100}",
62
+ _dark: "{colors.neutral.800}"
63
+ }
64
+ }
65
+ }
66
+ },
67
+ extend: {
68
+ breakpoints: { xs: "600px" },
69
+ keyframes: {
70
+ spin: {
71
+ from: { transform: "rotate(0deg)" },
72
+ to: { transform: "rotate(360deg)" }
73
+ },
74
+ sheen: {
75
+ from: { backgroundPositionX: "200%" },
76
+ to: { backgroundPositionX: "-200%" }
77
+ },
78
+ pulse: {
79
+ "0%": { transform: "scale(1, 1)" },
80
+ "50%": { opacity: 0.3 },
81
+ "100%": { transform: "scale(1.3)", opacity: 0 }
82
+ }
83
+ }
84
+ }
85
+ },
86
+ conditions: {
87
+ extend: {
88
+ dark: "[data-theme=dark] &",
89
+ activeMouse: "&:active:not(:focus-visible):not(:disabled)",
90
+ activeKeyboard: "&:active:focus-visible:not(:disabled)",
91
+ active: "&:active:not(:disabled), &:active:not(:focus-visible):not(:disabled), &:active:focus-visible:not(:disabled)",
92
+ hover: "&:hover:not(:disabled)",
93
+ checkbox: "& [data-checkbox]",
94
+ radioLabel: "& [data-radio-label]",
95
+ radioDisabled: "& :is(:disabled, [disabled], [data-disabled], [aria-disabled=true])",
96
+ radioSelected: "& :is([aria-selected=true], [data-selected])",
97
+ radioCircleOuter: "& [data-radio-outer]",
98
+ radioCircleInner: "& [data-radio-inner]",
99
+ radioFocusRing: "& [data-radio-focusring]",
100
+ backdrop: "[data-backdrop]:has(> &)",
101
+ path: "& path",
102
+ svg: "& svg"
103
+ }
104
+ },
105
+ utilities: {
106
+ rounded: {
107
+ values: { type: "boolean | number" },
108
+ transform(value) {
109
+ return { borderRadius: typeof value === "boolean" ? 9999 : value };
110
+ }
111
+ },
112
+ extend: {
113
+ grid: {
114
+ values: { type: "boolean" },
115
+ transform() {
116
+ return { display: "grid" };
117
+ }
118
+ },
119
+ flex: {
120
+ values: { type: "boolean" },
121
+ transform(value) {
122
+ return {
123
+ display: "flex",
124
+ ...typeof value === "string" && { flexWrap: value }
125
+ };
126
+ }
127
+ },
128
+ center: {
129
+ values: { type: "boolean" },
130
+ transform() {
131
+ return { placeContent: "center", placeItems: "center" };
132
+ }
133
+ },
134
+ relative: {
135
+ values: { type: "boolean" },
136
+ transform() {
137
+ return { position: "relative" };
138
+ }
139
+ },
140
+ absolute: {
141
+ values: { type: "boolean" },
142
+ transform() {
143
+ return { position: "absolute" };
144
+ }
145
+ },
146
+ fixed: {
147
+ values: { type: "boolean" },
148
+ transform() {
149
+ return { position: "fixed" };
150
+ }
151
+ },
152
+ sticky: {
153
+ values: { type: "boolean" },
154
+ transform() {
155
+ return { position: "sticky" };
156
+ }
157
+ },
158
+ // use br for numbers
159
+ borderRadius: {
160
+ className: "rounded",
161
+ shorthand: "br",
162
+ values: { type: "boolean | number" },
163
+ transform(value) {
164
+ return { borderRadius: typeof value === "boolean" ? 9999 : value };
165
+ }
166
+ },
167
+ size: {
168
+ values: { type: "number" },
169
+ transform(value) {
170
+ return { width: value, height: value };
171
+ }
172
+ },
173
+ pointer: {
174
+ values: { type: "boolean" },
175
+ transform() {
176
+ return { cursor: "pointer" };
177
+ }
178
+ },
179
+ strokeColor: {
180
+ values: "colors",
181
+ transform(value) {
182
+ return { "&, & path": { stroke: value } };
183
+ }
184
+ },
185
+ strokeWidth: {
186
+ values: { type: "number" },
187
+ transform(value) {
188
+ return { "&, & path": { strokeWidth: value } };
189
+ }
190
+ },
191
+ debug: {
192
+ values: { type: "boolean" },
193
+ transform(value) {
194
+ if (value === true) return { border: "1px solid red" };
195
+ if (typeof value === "string") {
196
+ const parts = value.trim().split(/\s+/);
197
+ let borderWidth = "1px", borderStyle = "solid", borderColor = "red";
198
+ parts.forEach((part) => {
199
+ if (/^\d+(\.\d+)?(px|em|rem|%|pt|pc|in|cm|mm|ex|ch|vw|vh|vmin|vmax)$/.test(
200
+ part
201
+ ))
202
+ borderWidth = part;
203
+ else if (/^(none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset)$/.test(
204
+ part
205
+ ))
206
+ borderStyle = part;
207
+ else borderColor = part;
208
+ });
209
+ const isKeyword = /^(currentColor|transparent|inherit|initial|unset|revert)$/i.test(
210
+ borderColor
211
+ );
212
+ const isHex = /^#/.test(borderColor);
213
+ const isFunc = /^(rgb|rgba|hsl|hsla|lab|lch|oklab|oklch|color)\(/i.test(
214
+ borderColor
215
+ );
216
+ const isVarRef = /^var\(/.test(borderColor);
217
+ const looksLikeScaleToken = /^[a-zA-Z][\w-]*\.\d{2,3}$/.test(
218
+ borderColor
219
+ );
220
+ const looksLikeSemanticToken = /^[a-zA-Z][\w-]*-[\w-]+$/.test(
221
+ borderColor
222
+ );
223
+ const shouldWrap = !isKeyword && !isHex && !isFunc && !isVarRef && (looksLikeScaleToken || looksLikeSemanticToken);
224
+ const normalizedBorderColor = shouldWrap ? `var(--colors-${borderColor.replace(/\./g, "-")})` : borderColor;
225
+ return {
226
+ borderWidth,
227
+ borderStyle,
228
+ borderColor: normalizedBorderColor
229
+ };
230
+ }
231
+ return { border: "1px solid red" };
232
+ }
233
+ },
234
+ cols: {
235
+ transform(value) {
236
+ if (typeof value !== "string") return {};
237
+ const [templatePart, gapPart] = value.split("/").map((s) => s.trim());
238
+ const templateWords = templatePart.split(/\s+/);
239
+ let alignContent = "", gridTemplate = "", columnGap = "";
240
+ const alignmentValues = ["start", "center", "end"];
241
+ if (alignmentValues.includes(templateWords[0])) {
242
+ alignContent = templateWords[0];
243
+ if (templateWords.length > 1)
244
+ gridTemplate = templateWords.slice(1).join(" ");
245
+ } else gridTemplate = templateWords.join(" ");
246
+ if (gridTemplate) {
247
+ gridTemplate = gridTemplate.split(/\s+/).map((part) => {
248
+ if (/^\d+$/.test(part)) return `${part}fr`;
249
+ if (part === "m" || part === "mx") return "max-content";
250
+ return part;
251
+ }).join(" ");
252
+ }
253
+ if (gapPart) {
254
+ const gapValue = gapPart.trim();
255
+ columnGap = /^\d+$/.test(gapValue) ? `${gapValue}px` : gapValue;
256
+ }
257
+ const result = {};
258
+ if (alignContent) {
259
+ result.alignContent = alignContent;
260
+ result.alignItems = alignContent;
261
+ }
262
+ if (gridTemplate) result.gridTemplateColumns = gridTemplate;
263
+ if (columnGap) result.columnGap = columnGap;
264
+ return result;
265
+ }
266
+ },
267
+ rows: {
268
+ transform(value) {
269
+ if (typeof value !== "string") return {};
270
+ const [templatePart, gapPart] = value.split("/").map((s) => s.trim());
271
+ const templateWords = templatePart.split(/\s+/);
272
+ let justifyContent = "", gridTemplate = "", rowGap = "";
273
+ const justifyValues = ["start", "end", "between", "center"];
274
+ const justifyValue = justifyValues.includes(templateWords[0]) ? templateWords[0] : "";
275
+ if (justifyValue) {
276
+ justifyContent = justifyValue === "between" ? "space-between" : justifyValue;
277
+ if (templateWords.length > 1)
278
+ gridTemplate = templateWords.slice(1).join(" ");
279
+ } else gridTemplate = templateWords.join(" ");
280
+ if (gridTemplate) {
281
+ gridTemplate = gridTemplate.split(/\s+/).map((part) => {
282
+ if (/^\d+$/.test(part)) return `${part}fr`;
283
+ if (part === "m" || part === "mx") return "max-content";
284
+ return part;
285
+ }).join(" ");
286
+ }
287
+ if (gapPart) {
288
+ const gapValue = gapPart.trim();
289
+ rowGap = /^\d+$/.test(gapValue) ? `${gapValue}px` : gapValue;
290
+ }
291
+ const result = {};
292
+ if (justifyContent) {
293
+ result.justifyContent = justifyContent;
294
+ result.justifyItems = justifyContent;
295
+ }
296
+ if (gridTemplate) result.gridTemplateRows = gridTemplate;
297
+ if (rowGap) result.rowGap = rowGap;
298
+ return result;
299
+ }
300
+ },
301
+ gridAutoColumns: {
302
+ shorthand: "autoCols",
303
+ values: { type: "boolean" },
304
+ transform(value) {
305
+ return {
306
+ gridAutoFlow: "column",
307
+ gridAutoColumns: value === true ? "max-content" : value
308
+ };
309
+ }
310
+ },
311
+ placeI: {
312
+ values: { type: "boolean" },
313
+ transform(value) {
314
+ return { placeItems: value === true ? "center" : value };
315
+ }
316
+ },
317
+ placeC: {
318
+ values: { type: "boolean" },
319
+ transform(value) {
320
+ return { placeContent: value === true ? "center" : value };
321
+ }
322
+ },
323
+ placeS: {
324
+ values: { type: "boolean" },
325
+ transform(value) {
326
+ return { placeSelf: value === true ? "center" : value };
327
+ }
328
+ },
329
+ alignI: {
330
+ values: { type: "boolean" },
331
+ transform(value) {
332
+ return { alignItems: value === true ? "center" : value };
333
+ }
334
+ },
335
+ alignC: {
336
+ property: "alignContent",
337
+ values: { type: "boolean" },
338
+ transform(value) {
339
+ return { alignContent: value === true ? "center" : value };
340
+ }
341
+ },
342
+ alignS: {
343
+ values: { type: "boolean" },
344
+ transform(value) {
345
+ return { alignSelf: value === true ? "center" : value };
346
+ }
347
+ },
348
+ justifyI: {
349
+ values: { type: "boolean" },
350
+ transform(value) {
351
+ return { justifyItems: value === true ? "center" : value };
352
+ }
353
+ },
354
+ justifyC: {
355
+ values: { type: "boolean" },
356
+ transform(value) {
357
+ return { justifyContent: value === true ? "center" : value };
358
+ }
359
+ },
360
+ justifyS: {
361
+ values: { type: "boolean" },
362
+ transform(value) {
363
+ return { justifySelf: value === true ? "center" : value };
364
+ }
365
+ },
366
+ colN: {
367
+ values: { type: "number" },
368
+ transform(value) {
369
+ return { gridColumn: value };
370
+ }
371
+ },
372
+ spaceBetween: {
373
+ values: { type: "true" },
374
+ transform() {
375
+ return { justifyContent: "space-between" };
376
+ }
377
+ },
378
+ rowN: {
379
+ values: { type: "number" },
380
+ transform(value) {
381
+ return { gridRow: value };
382
+ }
383
+ },
384
+ columnGap: {
385
+ shorthand: "colG",
386
+ values: { type: "number" },
387
+ transform(value) {
388
+ return { columnGap: value };
389
+ }
390
+ },
391
+ gridColumnStart: {
392
+ shorthand: "colStart",
393
+ values: { type: "number" },
394
+ transform(value) {
395
+ return { gridColumnStart: value };
396
+ }
397
+ },
398
+ gridColumnEnd: {
399
+ shorthand: "colEnd",
400
+ values: { type: "number" },
401
+ transform(value) {
402
+ return { gridColumnEnd: value };
403
+ }
404
+ },
405
+ gridRowStart: {
406
+ shorthand: "rowStart",
407
+ values: { type: "number" },
408
+ transform(value) {
409
+ return { gridRowStart: value };
410
+ }
411
+ },
412
+ gridRowEnd: {
413
+ shorthand: "rowEnd",
414
+ values: { type: "number" },
415
+ transform(value) {
416
+ return { gridRowEnd: value };
417
+ }
418
+ },
419
+ rowGap: {
420
+ shorthand: "rowG",
421
+ values: { type: "number" },
422
+ transform(value) {
423
+ return { rowGap: value };
424
+ }
425
+ },
426
+ position: {
427
+ shorthand: "pos",
428
+ transform(value) {
429
+ return { position: value };
430
+ }
431
+ },
432
+ height: {
433
+ shorthand: "h",
434
+ values: { type: "boolean" },
435
+ transform(value) {
436
+ return { height: value === true ? "100%" : value };
437
+ }
438
+ },
439
+ width: {
440
+ shorthand: "w",
441
+ values: { type: "boolean" },
442
+ transform(value) {
443
+ return { width: value === true ? "100%" : value };
444
+ }
445
+ },
446
+ mr: {
447
+ transform(value) {
448
+ return { marginRight: value };
449
+ }
450
+ },
451
+ border: {
452
+ values: { type: "boolean" },
453
+ transform(value) {
454
+ return { border: value === true ? "1px solid red" : value };
455
+ }
456
+ },
457
+ ar: {
458
+ values: { type: "boolean" },
459
+ transform(value) {
460
+ return { aspectRatio: value === true ? 1 : value };
461
+ }
462
+ },
463
+ aspectRatio: {
464
+ shorthand: "ar",
465
+ values: { type: "boolean" },
466
+ transform(value) {
467
+ return { aspectRatio: value === true ? 1 : value };
468
+ }
469
+ }
470
+ }
471
+ }
472
+ };
473
+ var preset_default = preset;
474
+
475
+ module.exports = preset_default;
@@ -0,0 +1,39 @@
1
+ import { Preset } from '@pandacss/dev';
2
+
3
+ /**
4
+ * QSTD PRESET - Single Source of Truth for Styles
5
+ *
6
+ * This preset is exported to consumers and also used by qstd's own panda.config.ts.
7
+ * It contains all style definitions that should be shared with consumers:
8
+ * - globalCss: Root styles and html defaults
9
+ * - theme: Semantic tokens, breakpoints, keyframes
10
+ * - conditions: Custom selectors (dark mode, hover, focus, etc.)
11
+ * - utilities: All custom utilities (flex, grid, rounded, etc.)
12
+ *
13
+ * USAGE IN CONSUMER PROJECTS:
14
+ * ```typescript
15
+ * // panda.config.ts
16
+ * import qstdPreset from "qstd/preset";
17
+ * export default defineConfig({
18
+ * presets: ["@pandacss/dev/presets", qstdPreset],
19
+ * include: ["./src/**\/*.{ts,tsx}"]
20
+ * });
21
+ * ```
22
+ *
23
+ * USAGE IN QSTD ITSELF:
24
+ * The qstd panda.config.ts imports this same preset to avoid duplicating
25
+ * style definitions. This ensures consistency between development and
26
+ * what consumers receive.
27
+ *
28
+ * IMPORTANT: This preset should be used WITH Panda's base preset:
29
+ * presets: ["@pandacss/dev/presets", qstdPreset]
30
+ *
31
+ * If you only use [qstdPreset], you'll lose Panda's default colors and tokens!
32
+ *
33
+ * DEPENDENCIES:
34
+ * - Requires @pandacss/dev/presets for base colors (neutral, red, blue, etc.)
35
+ * - Order matters: base preset must come first to provide foundational tokens
36
+ */
37
+ declare const preset: Preset;
38
+
39
+ export { preset as default };
@@ -0,0 +1,39 @@
1
+ import { Preset } from '@pandacss/dev';
2
+
3
+ /**
4
+ * QSTD PRESET - Single Source of Truth for Styles
5
+ *
6
+ * This preset is exported to consumers and also used by qstd's own panda.config.ts.
7
+ * It contains all style definitions that should be shared with consumers:
8
+ * - globalCss: Root styles and html defaults
9
+ * - theme: Semantic tokens, breakpoints, keyframes
10
+ * - conditions: Custom selectors (dark mode, hover, focus, etc.)
11
+ * - utilities: All custom utilities (flex, grid, rounded, etc.)
12
+ *
13
+ * USAGE IN CONSUMER PROJECTS:
14
+ * ```typescript
15
+ * // panda.config.ts
16
+ * import qstdPreset from "qstd/preset";
17
+ * export default defineConfig({
18
+ * presets: ["@pandacss/dev/presets", qstdPreset],
19
+ * include: ["./src/**\/*.{ts,tsx}"]
20
+ * });
21
+ * ```
22
+ *
23
+ * USAGE IN QSTD ITSELF:
24
+ * The qstd panda.config.ts imports this same preset to avoid duplicating
25
+ * style definitions. This ensures consistency between development and
26
+ * what consumers receive.
27
+ *
28
+ * IMPORTANT: This preset should be used WITH Panda's base preset:
29
+ * presets: ["@pandacss/dev/presets", qstdPreset]
30
+ *
31
+ * If you only use [qstdPreset], you'll lose Panda's default colors and tokens!
32
+ *
33
+ * DEPENDENCIES:
34
+ * - Requires @pandacss/dev/presets for base colors (neutral, red, blue, etc.)
35
+ * - Order matters: base preset must come first to provide foundational tokens
36
+ */
37
+ declare const preset: Preset;
38
+
39
+ export { preset as default };