shopify-accelerate-app 1.0.62 → 1.1.1

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,12 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "mcp__claude_ai_Context7__resolve-library-id",
5
+ "WebSearch",
6
+ "WebFetch(domain:kitemetric.com)",
7
+ "WebFetch(domain:www.jetbrains.com)",
8
+ "WebFetch(domain:github.com)",
9
+ "Bash(cd:*)"
10
+ ]
11
+ }
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify-accelerate-app",
3
- "version": "1.0.62",
3
+ "version": "1.1.1",
4
4
  "description": "Shopify App development with full Typescript Support",
5
5
  "author": "Felix Tellmann",
6
6
  "license": "MIT",
@@ -34,9 +34,7 @@
34
34
  "dependencies": {
35
35
  "@swc/core": "^1.9.3",
36
36
  "@swc/helpers": "^0.5.15",
37
- "@tailwindcss/aspect-ratio": "^0.4.2",
38
- "@tailwindcss/container-queries": "^0.1.1",
39
- "autoprefixer": "^10.4.20",
37
+ "@tailwindcss/cli": "^4.0.0",
40
38
  "chalk": "4.1.2",
41
39
  "commander": "^12.1.0",
42
40
  "dotenv-mono": "^1.3.14",
@@ -50,18 +48,16 @@
50
48
  "json2toml": "^6.1.1",
51
49
  "node-watch": "^0.7.4",
52
50
  "postcss": "^8.4.49",
53
- "postcss-import": "^16.1.0",
54
51
  "preact": "^10.25.0",
55
52
  "prompts": "^2.4.2",
56
53
  "regenerator-runtime": "^0.14.1",
57
54
  "shopify-typed-node-api": "^2.1.1",
58
- "tailwindcss": "0.0.0-insiders.6069a81",
59
- "tailwindcss-container-queries-with-max-width": "^0.1.5",
55
+ "tailwindcss": "^4.0.0",
60
56
  "toml": "^3.0.0",
61
57
  "ts-node": "^10.9.2",
62
58
  "tsconfig-paths": "^4.2.0",
63
59
  "zustand": "^5.0.1",
64
- "tailwindcss-animate": "^1.0.7"
60
+ "tw-animate-css": "^1.0.0"
65
61
  },
66
62
  "devDependencies": {
67
63
  "@types/inquirer": "^9.0.7",
@@ -28,6 +28,9 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
28
28
  }
29
29
  const classNameString = special ? stringContent.split(" ") : stringContent.replace(/\s+/gi, " ").split(" ");
30
30
 
31
+ // v4 prefix uses colon separator (tw:flex) instead of dash (tw-flex)
32
+ const prefix_sep = `${prefix}:`;
33
+
31
34
  const prefixedClassNames = classNameString.map((className) => {
32
35
  if (!className.trim()) return className;
33
36
 
@@ -44,17 +47,17 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
44
47
  }
45
48
  if (
46
49
  final &&
47
- (str.startsWith(`${prefix}-`) || str.startsWith(`!${prefix}-`)) &&
50
+ (str.startsWith(prefix_sep) || str.startsWith(`!${prefix_sep}`)) &&
48
51
  !cssOutput?.includes(str.replace(/([@()%,/.[\]])/gi, "\\$1"))
49
52
  ) {
50
53
  notCSSClasses.set(str, str.replace(/([@()%,/.[\]])/gi, "\\$1"));
51
- return str.replace(`${prefix}-`, "").replace(`!${prefix}-`, "");
54
+ return str.replace(prefix_sep, "").replace(`!${prefix_sep}`, "");
52
55
  }
53
- if (index === arr.length - 1 && !str.startsWith(`${prefix}-`) && !str.startsWith(`!${prefix}-`)) {
56
+ if (index === arr.length - 1 && !str.startsWith(prefix_sep) && !str.startsWith(`!${prefix_sep}`)) {
54
57
  if (/^!/gi.test(str)) {
55
- return `!${prefix}-${str.replace(/^!/gi, "")}`;
58
+ return `!${prefix_sep}${str.replace(/^!/gi, "")}`;
56
59
  }
57
- return `${prefix}-${str}`;
60
+ return `${prefix_sep}${str}`;
58
61
  }
59
62
  return str;
60
63
  })
@@ -62,21 +65,21 @@ export const transformClassNameStrings = (stringContent, final = false, cssOutpu
62
65
  }
63
66
  if (
64
67
  final &&
65
- (className.startsWith(`${prefix}-`) || className.startsWith(`!${prefix}-`)) &&
68
+ (className.startsWith(prefix_sep) || className.startsWith(`!${prefix_sep}`)) &&
66
69
  !cssOutput?.includes(`${className.replace(/([@()%,/.[\]])/gi, "\\$1")} `) &&
67
70
  !cssOutput?.includes(`${className.replace(/([@()%,/.[\]])/gi, "\\$1")}:`)
68
71
  ) {
69
72
  notCSSClasses.set(className, className.replace(/([@()%,/.[\]])/gi, "\\$1"));
70
- return className.replace(`${prefix}-`, "").replace(`!${prefix}-`, "");
73
+ return className.replace(prefix_sep, "").replace(`!${prefix_sep}`, "");
71
74
  }
72
75
 
73
- if (className.startsWith(`${prefix}-`) || className.startsWith(`!${prefix}-`)) {
76
+ if (className.startsWith(prefix_sep) || className.startsWith(`!${prefix_sep}`)) {
74
77
  return className;
75
78
  } else {
76
79
  if (/^!/gi.test(className)) {
77
- return `!${prefix}-${className.replace(/^!/gi, "")}`;
80
+ return `!${prefix_sep}${className.replace(/^!/gi, "")}`;
78
81
  }
79
- return `${prefix}-${className}`;
82
+ return `${prefix_sep}${className}`;
80
83
  }
81
84
  });
82
85
 
@@ -0,0 +1,25 @@
1
+ const plugin = require("tailwindcss/plugin");
2
+
3
+ module.exports = plugin(({ matchUtilities, theme }) => {
4
+ matchUtilities(
5
+ {
6
+ "auto-col-flow": (value) => {
7
+ if (value?.includes("/")) {
8
+ const [cols, gap] = value.split("/");
9
+ const calculatedGap = /^(\d|\.)*$/gi.test(gap?.trim()) ? `${+gap * 4}px` : gap;
10
+
11
+ return {
12
+ gridAutoFlow: "column",
13
+ gridAutoColumns: `calc((100% - (${calculatedGap} * (${cols} - 1))) / ${cols})`,
14
+ columnGap: calculatedGap,
15
+ };
16
+ }
17
+ return {
18
+ gridAutoFlow: "column",
19
+ gridAutoColumns: value,
20
+ };
21
+ },
22
+ },
23
+ { values: theme("width") }
24
+ );
25
+ });
@@ -0,0 +1,330 @@
1
+ /* ============================================================
2
+ Tailwind CSS v4 — Base Configuration
3
+ This file is used as a template. At runtime, tailwind-watch.ts
4
+ generates the final input CSS by prepending prefix/important
5
+ options and appending the user's _tailwind.css via @import.
6
+ ============================================================ */
7
+
8
+ /* The @import "tailwindcss" line is generated dynamically in tailwind-watch.ts
9
+ to support conditional prefix() and important() options. */
10
+
11
+ /* --- Animations (replaces tailwindcss-animate) --- */
12
+ @import "tw-animate-css";
13
+
14
+ /* --- Theme Overrides --- */
15
+ @theme {
16
+ /* ---- Spacing (4px base) ---- */
17
+ --spacing: 4px;
18
+ --spacing-px: 1px;
19
+ --spacing-0: 0;
20
+ --spacing-0_5: 2px;
21
+ --spacing-1: 4px;
22
+ --spacing-1_5: 6px;
23
+ --spacing-2: 8px;
24
+ --spacing-2_5: 10px;
25
+ --spacing-3: 12px;
26
+ --spacing-3_5: 14px;
27
+ --spacing-4: 16px;
28
+ --spacing-5: 20px;
29
+ --spacing-6: 24px;
30
+ --spacing-7: 28px;
31
+ --spacing-8: 32px;
32
+ --spacing-9: 36px;
33
+ --spacing-10: 40px;
34
+ --spacing-11: 44px;
35
+ --spacing-12: 48px;
36
+ --spacing-14: 56px;
37
+ --spacing-16: 64px;
38
+ --spacing-20: 80px;
39
+ --spacing-24: 96px;
40
+ --spacing-28: 112px;
41
+ --spacing-32: 128px;
42
+ --spacing-36: 144px;
43
+ --spacing-40: 160px;
44
+ --spacing-44: 176px;
45
+ --spacing-48: 192px;
46
+ --spacing-52: 208px;
47
+ --spacing-56: 224px;
48
+ --spacing-60: 240px;
49
+ --spacing-64: 256px;
50
+ --spacing-72: 288px;
51
+ --spacing-80: 320px;
52
+ --spacing-96: 384px;
53
+
54
+ /* ---- Border Radius ---- */
55
+ --radius-none: 0px;
56
+ --radius-xs: 2px;
57
+ --radius-sm: 2px;
58
+ --radius-DEFAULT: 4px;
59
+ --radius-md: 6px;
60
+ --radius-lg: 8px;
61
+ --radius-xl: 12px;
62
+ --radius-2xl: 16px;
63
+ --radius-3xl: 24px;
64
+ --radius-full: 9999px;
65
+
66
+ /* ---- Font Size ---- */
67
+ --font-size-8: 9px;
68
+ --font-size-8--line-height: 1.55;
69
+ --font-size-9: 9px;
70
+ --font-size-9--line-height: 1.5;
71
+ --font-size-10: 10px;
72
+ --font-size-10--line-height: 1.5;
73
+ --font-size-11: 11px;
74
+ --font-size-11--line-height: 1.5;
75
+ --font-size-12: 12px;
76
+ --font-size-12--line-height: 1.5;
77
+ --font-size-13: 13px;
78
+ --font-size-13--line-height: 1.5;
79
+ --font-size-14: 14px;
80
+ --font-size-14--line-height: 1.5;
81
+ --font-size-15: 15px;
82
+ --font-size-15--line-height: 1.5;
83
+ --font-size-16: 16px;
84
+ --font-size-16--line-height: 1.5;
85
+ --font-size-17: 17px;
86
+ --font-size-17--line-height: 1.5;
87
+ --font-size-18: 18px;
88
+ --font-size-18--line-height: 1.45;
89
+ --font-size-19: 19px;
90
+ --font-size-19--line-height: 1.45;
91
+ --font-size-20: 20px;
92
+ --font-size-20--line-height: 1.45;
93
+ --font-size-21: 21px;
94
+ --font-size-21--line-height: 1.45;
95
+ --font-size-22: 22px;
96
+ --font-size-22--line-height: 1.4;
97
+ --font-size-23: 23px;
98
+ --font-size-23--line-height: 1.4;
99
+ --font-size-24: 24px;
100
+ --font-size-24--line-height: 1.4;
101
+ --font-size-xs: 12px;
102
+ --font-size-xs--line-height: 16px;
103
+ --font-size-sm: 14px;
104
+ --font-size-sm--line-height: 20px;
105
+ --font-size-base: 16px;
106
+ --font-size-base--line-height: 24px;
107
+ --font-size-lg: 18px;
108
+ --font-size-lg--line-height: 28px;
109
+ --font-size-xl: 20px;
110
+ --font-size-xl--line-height: 28px;
111
+ --font-size-2xl: 24px;
112
+ --font-size-2xl--line-height: 32px;
113
+ --font-size-3xl: 30px;
114
+ --font-size-3xl--line-height: 36px;
115
+ --font-size-4xl: 36px;
116
+ --font-size-4xl--line-height: 36px;
117
+ --font-size-5xl: 48px;
118
+ --font-size-5xl--line-height: 1;
119
+ --font-size-6xl: 60px;
120
+ --font-size-6xl--line-height: 1;
121
+ --font-size-7xl: 72px;
122
+ --font-size-7xl--line-height: 1;
123
+ --font-size-8xl: 96px;
124
+ --font-size-8xl--line-height: 1;
125
+ --font-size-9xl: 144px;
126
+ --font-size-9xl--line-height: 1;
127
+
128
+ /* ---- Line Height ---- */
129
+ --line-height-none: 1;
130
+ --line-height-tight: 1.25;
131
+ --line-height-snug: 1.375;
132
+ --line-height-normal: 1.5;
133
+ --line-height-relaxed: 1.625;
134
+ --line-height-loose: 2;
135
+ --line-height-3: 12px;
136
+ --line-height-4: 16px;
137
+ --line-height-5: 20px;
138
+ --line-height-6: 24px;
139
+ --line-height-7: 28px;
140
+ --line-height-8: 32px;
141
+ --line-height-9: 36px;
142
+ --line-height-10: 40px;
143
+
144
+ /* ---- Columns ---- */
145
+ --columns-auto: auto;
146
+ --columns-1: 1;
147
+ --columns-2: 2;
148
+ --columns-3: 3;
149
+ --columns-4: 4;
150
+ --columns-5: 5;
151
+ --columns-6: 6;
152
+ --columns-7: 7;
153
+ --columns-8: 8;
154
+ --columns-9: 9;
155
+ --columns-10: 10;
156
+ --columns-11: 11;
157
+ --columns-12: 12;
158
+ --columns-3xs: 256px;
159
+ --columns-2xs: 288px;
160
+ --columns-xs: 320px;
161
+ --columns-sm: 384px;
162
+ --columns-md: 448px;
163
+ --columns-lg: 512px;
164
+ --columns-xl: 576px;
165
+ --columns-2xl: 672px;
166
+ --columns-3xl: 768px;
167
+ --columns-4xl: 896px;
168
+ --columns-5xl: 1024px;
169
+ --columns-6xl: 1152px;
170
+ --columns-7xl: 1280px;
171
+ --columns-8xl: 1440px;
172
+
173
+ /* ---- Max Width ---- */
174
+ --max-width-none: none;
175
+ --max-width-0: 0px;
176
+ --max-width-xs: 320px;
177
+ --max-width-sm: 384px;
178
+ --max-width-md: 448px;
179
+ --max-width-lg: 512px;
180
+ --max-width-xl: 576px;
181
+ --max-width-2xl: 672px;
182
+ --max-width-3xl: 768px;
183
+ --max-width-4xl: 896px;
184
+ --max-width-5xl: 1024px;
185
+ --max-width-6xl: 1152px;
186
+ --max-width-7xl: 1280px;
187
+ --max-width-8xl: 90rem;
188
+ --max-width-full: 100%;
189
+ --max-width-min: min-content;
190
+ --max-width-max: max-content;
191
+ --max-width-fit: fit-content;
192
+ --max-width-prose: 65ch;
193
+
194
+ /* ---- Screens ---- */
195
+ --breakpoint-xxs: 373px;
196
+ --breakpoint-xs: 427px;
197
+
198
+ /* ---- Containers ---- */
199
+ --container-xxs: 373px;
200
+ --container-xs: 427px;
201
+
202
+ /* ---- Box Shadow (custom) ---- */
203
+ --shadow-invert-sm: 0 -1px 2px 0 rgb(0 0 0 / 0.05);
204
+ --shadow-invert: 0 -3px 5px 1px rgb(0 0 0 / 0.03), 0 -2px 4px 2px rgb(0 0 0 / 0.03);
205
+ --shadow-invert-md: 0 -4px 6px 1px rgb(0 0 0 / 0.07), 0 -2px 4px 2px rgb(0 0 0 / 0.07);
206
+ --shadow-invert-lg: 0 -10px 15px 3px rgb(0 0 0 / 0.1), 0 -4px 6px 4px rgb(0 0 0 / 0.1);
207
+ --shadow-invert-xl: 0 -20px 25px 5px rgb(0 0 0 / 0.1), 0 -8px 10px 6px rgb(0 0 0 / 0.1);
208
+ --shadow-invert-2xl: 0 -25px 50px 12px rgb(0 0 0 / 0.25);
209
+
210
+ /* ---- Keyframes ---- */
211
+ --animate-slide: slide 30s linear infinite;
212
+ --animate-marquee1: marquee1 30s linear infinite;
213
+ --animate-marquee2: marquee2 30s linear infinite;
214
+ --animate-circle: circle 8.1s linear;
215
+ --animate-dot: dot 8.1s linear;
216
+ --animate-typewriter: typewriter 0.5s linear infinite;
217
+ --animate-pulse-bg: pulse-bg 1s cubic-bezier(0.4, 0, 0.6, 1) infinite;
218
+
219
+ /* ---- Colors ---- */
220
+ /* v4 uses CSS color-mix for opacity — define base colors as rgb() */
221
+ --color-theme-trigger-bg: rgb(var(--lx-color-trigger-bg));
222
+ --color-theme-trigger-text: rgb(var(--lx-color-trigger-text));
223
+ --color-theme-bg: rgb(var(--lx-color-bg));
224
+ --color-theme-text: rgb(var(--lx-color-text));
225
+ --color-theme-button-bg: rgb(var(--lx-color-button-bg));
226
+ --color-theme-button-text: rgb(var(--lx-color-button-text));
227
+ }
228
+
229
+ @keyframes slide {
230
+ 0%, 100% { transform: translate3d(0, 0, 0); }
231
+ 100% { transform: translate3d(-50%, 0, 0); }
232
+ }
233
+
234
+ @keyframes marquee1 {
235
+ 0%, 100% { transform: translate3d(0, 0, 0); }
236
+ 100% { transform: translate3d(-100%, 0, 0); }
237
+ }
238
+
239
+ @keyframes marquee2 {
240
+ 0%, 100% { transform: translate3d(100%, 0, 0); }
241
+ 100% { transform: translate3d(0, 0, 0); }
242
+ }
243
+
244
+ @keyframes circle {
245
+ 0% { stroke-dashoffset: 90; }
246
+ 100% { stroke-dashoffset: 0; }
247
+ }
248
+
249
+ @keyframes dot {
250
+ 0%, 95% { fill: transparent; stroke: currentColor; stroke-opacity: 0.1; }
251
+ 100% { fill: currentColor; stroke: transparent; stroke-opacity: 0; }
252
+ }
253
+
254
+ @keyframes typewriter {
255
+ 0%, 100% { opacity: 1; }
256
+ 50% { opacity: 0; }
257
+ }
258
+
259
+ @keyframes pulse-bg {
260
+ 50% { --tw-bg-opacity: 0.5; }
261
+ }
262
+
263
+ /* --- Custom Variants (replaces addVariant calls) --- */
264
+ @custom-variant svg (& svg);
265
+ @custom-variant hfa (&:hover, &:focus, &:active);
266
+ @custom-variant hfw (&:hover, &:focus-visible, &:focus-within);
267
+ @custom-variant hfwa (&:hover, &:focus-visible, &:focus-within, &:active);
268
+ @custom-variant hfwaa (&:hover, &:focus-visible, &:focus-within, &:active, &.active);
269
+ @custom-variant hfva (&:hover, &:focus, &:focus-visible, &:active);
270
+ @custom-variant ha (&:hover, &:active);
271
+ @custom-variant hf (&:hover, &:focus-visible);
272
+ @custom-variant fa (&:focus, &:active);
273
+ @custom-variant f (&:focus);
274
+ @custom-variant fw (&:focus-within);
275
+ @custom-variant fv (&:focus-visible);
276
+ @custom-variant h (&:hover);
277
+ @custom-variant d (.dark &);
278
+ @custom-variant ac (&.active);
279
+ @custom-variant b (&::before);
280
+ @custom-variant a (&::after);
281
+ @custom-variant not-prose (:not(.prose &)&);
282
+ @custom-variant hfaa (&:hover, &:focus, &:active, &.active);
283
+ @custom-variant hfvaa (&:hover, &:focus, &:focus-visible, &:active, &.active);
284
+ @custom-variant group-hfa (.group:hover &, .group:focus &, .group:active &);
285
+ @custom-variant group-hf (.group:hover &, .group:focus &);
286
+ @custom-variant group-ac (.group.active &);
287
+ @custom-variant group-hfva (.group:hover &, .group:focus-visible &, .group:active &);
288
+ @custom-variant group-hfwa (.group:hover &, .group:focus-visible &, .group:focus-within &, .group:active &);
289
+ @custom-variant group-hfw (.group:hover &, .group:focus-visible &, .group:focus-within &);
290
+ @custom-variant peer-hfwa (.peer:hover ~ &, .peer:focus-visible ~ &, .peer:focus-within ~ &, .peer:active ~ &);
291
+ @custom-variant peer-fw (.peer:focus-within ~ &);
292
+
293
+ /* --- Dark mode as class-based --- */
294
+ @custom-variant dark (&:where(.dark *));
295
+
296
+ /* --- Custom Utilities (replaces addUtilities calls) --- */
297
+ @utility shape-geometric-precision {
298
+ shape-rendering: geometricPrecision;
299
+ }
300
+
301
+ @utility open-quote {
302
+ content: open-quote;
303
+ }
304
+
305
+ @utility close-quote {
306
+ content: close-quote;
307
+ }
308
+
309
+ @utility leading-0 {
310
+ line-height: 0;
311
+ }
312
+
313
+ @utility animation-pause {
314
+ animation-play-state: paused;
315
+ }
316
+
317
+ @utility animation-play {
318
+ animation-play-state: running;
319
+ }
320
+
321
+ /* --- Dynamic Utilities --- */
322
+
323
+ /* top-spacing: top = var(--spacing-top-bar-spacing) + spacing value */
324
+ @utility top-spacing-* {
325
+ top: calc(var(--spacing-top-bar) + --value(--spacing-*));
326
+ top: calc(var(--spacing-top-bar) + --value([length]));
327
+ }
328
+
329
+ /* auto-col-flow loaded via JS plugin for complex logic */
330
+ @plugin "./plugins/auto-col-flow.js";
@@ -1,4 +1,3 @@
1
- // import { require } from "../../require";
2
1
  import child_process from "child_process";
3
2
  import fs from "fs";
4
3
  import path from "path";
@@ -7,36 +6,142 @@ import { writeCompareFile } from "../utils/fs";
7
6
 
8
7
  const watch = require("node-watch");
9
8
 
9
+ /**
10
+ * Generates the Tailwind v4 input CSS dynamically.
11
+ * Combines the base config with conditional prefix/important options
12
+ * and the user's _tailwind.css file.
13
+ */
14
+ const generateInputCSS = (base_css_path: string, user_css_path: string): string => {
15
+ const prefix = process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX;
16
+ const important = process.env.SHOPIFY_ACCELERATE_TAILWIND_IMPORTANT;
17
+
18
+ // Build the @import "tailwindcss" line with options
19
+ // In v4, preflight is disabled by importing individual layers without preflight.css
20
+ const tailwind_import_options: string[] = [];
21
+ if (prefix) {
22
+ tailwind_import_options.push(`prefix(${prefix})`);
23
+ }
24
+
25
+ let tailwind_import: string;
26
+ if (important || tailwind_import_options.length > 0) {
27
+ // When disabling preflight or using prefix/important, import layers individually
28
+ const theme_options = prefix ? ` prefix(${prefix})` : "";
29
+ const utilities_options_parts: string[] = [];
30
+ if (prefix) utilities_options_parts.push(`prefix(${prefix})`);
31
+ if (important) utilities_options_parts.push(`important(${important})`);
32
+ const utilities_options = utilities_options_parts.length > 0 ? ` ${utilities_options_parts.join(" ")}` : "";
33
+
34
+ tailwind_import = [
35
+ `@layer theme, base, components;`,
36
+ `@import "tailwindcss/theme.css" layer(theme)${theme_options};`,
37
+ `/* Preflight intentionally omitted */`,
38
+ `/* Utilities are NOT in a @layer so they keep normal cascade priority (like v3) and can override other libraries */`,
39
+ `@import "tailwindcss/utilities.css"${utilities_options};`,
40
+ ].join("\n");
41
+ } else {
42
+ // No prefix or important — still skip preflight
43
+ tailwind_import = [
44
+ `@layer theme, base, components;`,
45
+ `@import "tailwindcss/theme.css" layer(theme);`,
46
+ `/* Preflight intentionally omitted */`,
47
+ `/* Utilities are NOT in a @layer so they keep normal cascade priority (like v3) and can override other libraries */`,
48
+ `@import "tailwindcss/utilities.css";`,
49
+ ].join("\n");
50
+ }
51
+
52
+ // Source paths for content detection
53
+ const extension_path = process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH ?? "";
54
+ const source_directive = extension_path
55
+ ? `@source "${extension_path}/**/*.{html,liquid,js,json}";`
56
+ : "";
57
+
58
+ // Safelist equivalent via @source inline()
59
+ const safelist_prefix = prefix ? `${prefix}:` : "";
60
+ const safelist = `@source inline("${safelist_prefix}inset-0 ${safelist_prefix}pointer-events-none [&>*]:${safelist_prefix}pointer-events-auto");`;
61
+
62
+ // Read the base CSS config (theme, variants, utilities, plugins)
63
+ // Resolve bare package imports to absolute paths so they work from the generated file's location
64
+ const tw_animate_path = path.join(package_root, "node_modules/tw-animate-css/dist/tw-animate.css").replace(/\\/g, "/");
65
+ const base_css = fs.readFileSync(base_css_path, { encoding: "utf-8" }).replace(
66
+ '@import "tw-animate-css"',
67
+ `@import "${tw_animate_path}"`
68
+ );
69
+
70
+ // Read the user's _tailwind.css
71
+ const user_css = fs.readFileSync(user_css_path, { encoding: "utf-8" });
72
+
73
+ return [
74
+ `/* Auto-generated Tailwind v4 input — do not edit */`,
75
+ tailwind_import,
76
+ ``,
77
+ base_css,
78
+ ``,
79
+ source_directive,
80
+ safelist,
81
+ ``,
82
+ `/* User styles */`,
83
+ user_css,
84
+ ].join("\n");
85
+ };
86
+
87
+ /**
88
+ * Generates a `tailwind.config.css` at the consuming project root so that
89
+ * IntelliJ / WebStorm's Tailwind Language Server can discover all custom
90
+ * theme tokens, variants, and utilities for autocomplete.
91
+ *
92
+ * The file is NOT used by the build — it exists solely for IDE support.
93
+ * Uses `writeCompareFile` to avoid unnecessary file-change events.
94
+ */
95
+ const generateIDEConfig = (base_css_import_path: string): void => {
96
+ const ide_config_path = path.join(process.cwd(), "tailwind.config.css");
97
+
98
+ const content = [
99
+ `/* Auto-generated by shopify-accelerate-app for IDE autocomplete.`,
100
+ ` This file is NOT used by the build — it exists solely so IntelliJ/WebStorm`,
101
+ ` can provide Tailwind CSS class autocomplete with all custom theme values,`,
102
+ ` variants, and utilities.`,
103
+ ``,
104
+ ` Do not edit — it will be regenerated on next \`dev\` start. */`,
105
+ `@import "tailwindcss";`,
106
+ `@import "${base_css_import_path}";`,
107
+ ].join("\n");
108
+
109
+ writeCompareFile(ide_config_path, content);
110
+ };
111
+
10
112
  export const runTailwindCSSWatcher = () => {
11
113
  const { package_root } = config;
12
114
 
13
- const hasConfig = fs.existsSync(path.join(root_dir, "tailwind.config.js"));
14
- const hasPostCss = fs.existsSync(path.join(root_dir, "postcss.config.js"));
15
- const inputFile = fs.existsSync(path.join(root_dir, `assets`, `_tailwind.css`));
16
- const resetInputFile = fs.existsSync(path.join(root_dir, `assets`, `_reset.css`));
115
+ const user_css_path = path.join(root_dir, "assets", "_tailwind.css");
116
+ const input_exists = fs.existsSync(user_css_path);
17
117
 
18
- if (!inputFile) {
118
+ if (!input_exists) {
19
119
  console.log("Tailwind Input file not found");
20
120
  return;
21
121
  }
22
122
 
23
- const filePath = path.join(config.extension_path, `assets`, `tailwind_pre_sort.css`);
123
+ const base_css_path = path.join(package_root, "src/tailwind/tailwind-base.css");
124
+
125
+ // Generate IDE config for Tailwind autocomplete in IntelliJ/WebStorm
126
+ generateIDEConfig("shopify-accelerate-app/src/tailwind/tailwind-base.css");
127
+ const generated_input_path = path.join(config.extension_path, "assets", "_tailwind_generated.css");
128
+ const pre_sort_path = path.join(config.extension_path, "assets", "tailwind_pre_sort.css");
129
+
130
+ // Generate the combined input CSS
131
+ const input_css = generateInputCSS(base_css_path, user_css_path);
132
+ fs.writeFileSync(generated_input_path, input_css);
24
133
 
25
134
  /*= =============== Tailwind Watcher ================ */
26
- console.log(path.join(root_dir, `assets`, `_tailwind.css`));
27
- console.log(path.join(package_root, `src/tailwind/tailwind.config.js`));
135
+ console.log(`Tailwind v4 input: ${generated_input_path}`);
136
+ console.log(`Tailwind v4 output: ${pre_sort_path}`);
28
137
  child_process.spawn(
29
138
  "npx",
30
139
  [
31
- "tailwindcss",
32
- "--config",
33
- /*hasConfig ? "tailwind.config.js" :*/ path.join(package_root, `src/tailwind/tailwind.config.js`),
34
- "--postcss",
35
- /*hasPostCss ? "postcss.config.js" : */ path.join(package_root, `src/tailwind/postcss.config.js`),
140
+ "@tailwindcss/cli",
36
141
  "-i",
37
- path.join(root_dir, `assets`, `_tailwind.css`),
142
+ generated_input_path,
38
143
  "-o",
39
- filePath,
144
+ pre_sort_path,
40
145
  "--watch",
41
146
  ],
42
147
  {
@@ -45,11 +150,22 @@ export const runTailwindCSSWatcher = () => {
45
150
  }
46
151
  );
47
152
 
153
+ // Regenerate input CSS when user's _tailwind.css changes
154
+ watch(path.join(root_dir, "assets"), { recursive: false }, (evt: string, name: string) => {
155
+ if (!name.match(/_tailwind\.css$/)) return;
156
+ try {
157
+ const updated_css = generateInputCSS(base_css_path, user_css_path);
158
+ fs.writeFileSync(generated_input_path, updated_css);
159
+ } catch (err) {
160
+ console.log(err);
161
+ }
162
+ });
163
+
48
164
  /*= =============== Tailwind Plugin Order ================ */
49
- watch(path.join(config.extension_path, "assets"), { recursive: false }, async (evt, name) => {
165
+ watch(path.join(config.extension_path, "assets"), { recursive: false }, async (evt: string, name: string) => {
50
166
  try {
51
- if (!name.match(/tailwind_pre_sort.css$/) || !fs.existsSync(filePath)) return;
52
- const file = fs.readFileSync(filePath, { encoding: "utf-8" });
167
+ if (!name.match(/tailwind_pre_sort.css$/) || !fs.existsSync(pre_sort_path)) return;
168
+ const file = fs.readFileSync(pre_sort_path, { encoding: "utf-8" });
53
169
 
54
170
  const top = file
55
171
  .split(/\n}/gi)
@@ -61,27 +177,27 @@ export const runTailwindCSSWatcher = () => {
61
177
  .join("\n}")}\n`;
62
178
  const content = top + bottom;
63
179
 
64
- const classesInOrder = [];
65
- const omitCompoundClasses = [":not", ":where", ">", "*", ","];
180
+ const classes_in_order: string[] = [];
181
+ const omit_compound_classes = [":not", ":where", ">", "*", ","];
66
182
 
67
183
  content.split("\n").forEach((line) => {
68
184
  if (!line.startsWith(".")) {
69
185
  return;
70
186
  }
71
187
 
72
- let writeOut = true;
188
+ let write_out = true;
73
189
 
74
- omitCompoundClasses.forEach((classToOmit) => {
75
- if (line.includes(classToOmit)) {
76
- writeOut = false;
190
+ omit_compound_classes.forEach((class_to_omit) => {
191
+ if (line.includes(class_to_omit)) {
192
+ write_out = false;
77
193
  return;
78
194
  }
79
195
  });
80
196
 
81
- if (writeOut) {
82
- const finalClassName = line.replace(/\./g, "").replace(/{/g, "").replace(/}/g, "").replace(/\\/g, "").trim();
83
- if (finalClassName !== "") {
84
- classesInOrder.push(`${finalClassName}`);
197
+ if (write_out) {
198
+ const final_class_name = line.replace(/\./g, "").replace(/{/g, "").replace(/}/g, "").replace(/\\/g, "").trim();
199
+ if (final_class_name !== "") {
200
+ classes_in_order.push(`${final_class_name}`);
85
201
  }
86
202
  }
87
203
  });
@@ -92,13 +208,14 @@ export const runTailwindCSSWatcher = () => {
92
208
  writeCompareFile(path.join(config.theme_output_path, `assets/listify-dev-tailwind.css`), content);
93
209
  }
94
210
 
211
+ // v4 prefix uses colon separator (tw:flex) instead of dash (tw-flex)
95
212
  writeCompareFile(
96
213
  path.join(process.cwd(), ".tailwindorder"),
97
- classesInOrder
214
+ classes_in_order
98
215
  .join("\n")
99
216
  .replace(
100
217
  new RegExp(
101
- `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}`,
218
+ `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}:` : ""}`,
102
219
  "gi"
103
220
  ),
104
221
  ""
@@ -1,8 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- "postcss-import": {},
4
- "tailwindcss/nesting": {},
5
- tailwindcss: {},
6
- autoprefixer: {},
7
- },
8
- };
@@ -1,462 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- // eslint-disable-next-line node/no-unpublished-require
3
- // import { require } from "../../require";
4
- const { defaultExtractor: createDefaultExtractor } = require("tailwindcss/lib/lib/defaultExtractor");
5
-
6
- const { default: resolveConfig } = require("tailwindcss/lib/util/resolveConfig");
7
- const plugin = require("tailwindcss/plugin");
8
- import { dotenvLoad } from "dotenv-mono";
9
- const dotenv = dotenvLoad(); // Dotenv instance
10
-
11
- /*const defaultExtractor = createDefaultExtractor({
12
- tailwindConfig: resolveConfig([
13
- {
14
- content: [
15
- `${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.{html,liquid,js,json}`,
16
- `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
17
- `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
18
- ],
19
- },
20
- ]),
21
- });
22
-
23
- const extractor = (content) => {
24
- return defaultExtractor(content).map((cls) => {
25
- console.log({ class: cls });
26
- return `tw-${cls}`;
27
- });
28
- };*/
29
-
30
- module.exports = {
31
- content: {
32
- files: [
33
- `${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/**/*.{html,liquid,js,json}`,
34
- `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**!/!*.css`,
35
- `!${process.env.SHOPIFY_ACCELERATE_EXTENSION_PATH}/!**/!*.css`,
36
- ],
37
- extract: {
38
- // ts: extractor,
39
- // tsx: extractor,
40
- // html: extractor,
41
- // liquid: (content) => {
42
- // console.log({ content });
43
- // return content;
44
- // },
45
- // js: extractor,
46
- // json: extractor,
47
- },
48
- },
49
- safelist: [
50
- `!${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}fixed`,
51
- `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}inset-0`,
52
- `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""}pointer-events-none`,
53
- `${
54
- process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : ""
55
- }[&>*]:pointer-events-auto`,
56
- ],
57
- darkMode: "class", // or 'media' or 'class'
58
- // mode: process.env.NODE_ENV ? "jit" : undefined,
59
- // important: true,
60
- important: process.env.SHOPIFY_ACCELERATE_TAILWIND_IMPORTANT,
61
- prefix: process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX ? `${process.env.SHOPIFY_ACCELERATE_TAILWIND_PREFIX}-` : undefined,
62
- corePlugins: {
63
- preflight: false,
64
- },
65
- mode: "jit",
66
- theme: {
67
- borderRadius: {
68
- none: "0px",
69
- sm: "2px",
70
- DEFAULT: "4px",
71
- md: "6px",
72
- lg: "8px",
73
- xl: "12px",
74
- "2xl": "16px",
75
- "3xl": "24px",
76
- full: "9999px",
77
- },
78
- columns: {
79
- auto: "auto",
80
- 1: "1",
81
- 2: "2",
82
- 3: "3",
83
- 4: "4",
84
- 5: "5",
85
- 6: "6",
86
- 7: "7",
87
- 8: "8",
88
- 9: "9",
89
- 10: "10",
90
- 11: "11",
91
- 12: "12",
92
- "3xs": "256px",
93
- "2xs": "288px",
94
- xs: "320px",
95
- sm: "384px",
96
- md: "448px",
97
- lg: "512px",
98
- xl: "576px",
99
- "2xl": "672px",
100
- "3xl": "768px",
101
- "4xl": "896px",
102
- "5xl": "1024px",
103
- "6xl": "1152px",
104
- "7xl": "1280px",
105
- "8xl": "1440px",
106
- },
107
- fontSize: {
108
- 8: ["9px", "1.55"],
109
- 9: ["9px", "1.5"],
110
- 10: ["10px", "1.5"],
111
- 11: ["11px", "1.5"],
112
- 12: ["12px", "1.5"],
113
- 13: ["13px", "1.5"],
114
- 14: ["14px", "1.5"],
115
- 15: ["15px", "1.5"],
116
- 16: ["16px", "1.5"],
117
- 17: ["17px", "1.5"],
118
- 18: ["18px", "1.45"],
119
- 19: ["19px", "1.45"],
120
- 20: ["20px", "1.45"],
121
- 21: ["21px", "1.45"],
122
- 22: ["22px", "1.4"],
123
- 23: ["23px", "1.4"],
124
- 24: ["24px", "1.4"],
125
- xs: ["12px", { lineHeight: "16px" }],
126
- sm: ["14px", { lineHeight: "20px" }],
127
- base: ["16px", { lineHeight: "24px" }],
128
- lg: ["18px", { lineHeight: "28px" }],
129
- xl: ["20px", { lineHeight: "28px" }],
130
- "2xl": ["24px", { lineHeight: "32px" }],
131
- "3xl": ["30px", { lineHeight: "36px" }],
132
- "4xl": ["36px", { lineHeight: "36px" }],
133
- "5xl": ["48px", { lineHeight: "1" }],
134
- "6xl": ["60px", { lineHeight: "1" }],
135
- "7xl": ["72px", { lineHeight: "1" }],
136
- "8xl": ["96px", { lineHeight: "1" }],
137
- "9xl": ["144px", { lineHeight: "1" }],
138
- },
139
- lineHeight: {
140
- none: "1",
141
- tight: "1.25",
142
- snug: "1.375",
143
- normal: "1.5",
144
- relaxed: "1.625",
145
- loose: "2",
146
- 3: "12px",
147
- 4: "16px",
148
- 5: "20px",
149
- 6: "24px",
150
- 7: "28px",
151
- 8: "32px",
152
- 9: "36px",
153
- 10: "40px",
154
- },
155
- maxWidth: ({ theme, breakpoints }) => ({
156
- none: "none",
157
- 0: "0px",
158
- xs: "320px",
159
- sm: "384px",
160
- md: "448px",
161
- lg: "512px",
162
- xl: "576px",
163
- "2xl": "672px",
164
- "3xl": "768px",
165
- "4xl": "896px",
166
- "5xl": "1024px",
167
- "6xl": "1152px",
168
- "7xl": "1280px",
169
- full: "100%",
170
- min: "min-content",
171
- max: "max-content",
172
- fit: "fit-content",
173
- prose: "65ch",
174
- ...breakpoints(theme("screens")),
175
- }),
176
- spacing: {
177
- px: "1px",
178
- 0: "0",
179
- 0.5: "2px",
180
- 1: "4px",
181
- 1.5: "6px",
182
- 2: "8px",
183
- 2.5: "10px",
184
- 3: "12px",
185
- 3.5: "14px",
186
- 4: "16px",
187
- 5: "20px",
188
- 6: "24px",
189
- 7: "28px",
190
- 8: "32px",
191
- 9: "36px",
192
- 10: "40px",
193
- 11: "44px",
194
- 12: "48px",
195
- 14: "56px",
196
- 16: "64px",
197
- 20: "80px",
198
- 24: "96px",
199
- 28: "112px",
200
- 32: "128px",
201
- 36: "144px",
202
- 40: "160px",
203
- 44: "176px",
204
- 48: "192px",
205
- 52: "208px",
206
- 56: "224px",
207
- 60: "240px",
208
- 64: "256px",
209
- 72: "288px",
210
- 80: "320px",
211
- 96: "384px",
212
- },
213
- extend: {
214
- screens: {
215
- xxs: "373px" /* tiny phone*/,
216
- xs: "427px" /*smaller than iphone pro max*/,
217
- },
218
- containers: {
219
- xxs: "373px" /* tiny phone*/,
220
- xs: "427px" /*smaller than iphone pro max*/,
221
- sm: "640px",
222
- md: "768px",
223
- lg: "1024px",
224
- xl: "1280px",
225
- "2xl": "1536px",
226
- "max-xxs": "-373px" /* tiny phone*/,
227
- "max-xs": "-427px" /*smaller than iphone pro max*/,
228
- "max-sm": "-640px",
229
- "max-md": "-768px",
230
- "max-lg": "-1024px",
231
- "max-xl": "-1280px",
232
- "max-2xl": "-1536px",
233
- },
234
- fontSize: {
235
- 8: ["9px", "1.55"],
236
- 9: ["9px", "1.5"],
237
- 10: ["10px", "1.5"],
238
- 11: ["11px", "1.5"],
239
- 12: ["12px", "1.5"],
240
- 13: ["13px", "1.5"],
241
- 14: ["14px", "1.5"],
242
- 15: ["15px", "1.5"],
243
- 16: ["16px", "1.5"],
244
- 17: ["17px", "1.5"],
245
- 18: ["18px", "1.45"],
246
- 19: ["19px", "1.45"],
247
- 20: ["20px", "1.45"],
248
- 21: ["21px", "1.45"],
249
- 22: ["22px", "1.4"],
250
- 23: ["23px", "1.4"],
251
- 24: ["24px", "1.4"],
252
- },
253
- maxWidth: {
254
- "8xl": "90rem",
255
- },
256
- boxShadow: {
257
- "invert-sm": "0 -1px 2px 0 rgb(0 0 0 / 0.05)",
258
- invert: "0 -3px 5px 1px rgb(0 0 0 / 0.03), 0 -2px 4px 2px rgb(0 0 0 / 0.03)",
259
- "invert-md": "0 -4px 6px 1px rgb(0 0 0 / 0.07), 0 -2px 4px 2px rgb(0 0 0 / 0.07)",
260
- "invert-lg": "0 -10px 15px 3px rgb(0 0 0 / 0.1), 0 -4px 6px 4px rgb(0 0 0 / 0.1)",
261
- "invert-xl": "0 -20px 25px 5px rgb(0 0 0 / 0.1), 0 -8px 10px 6px rgb(0 0 0 / 0.1)",
262
- "invert-2xl": "0 -25px 50px 12px rgb(0 0 0 / 0.25)",
263
- },
264
- keyframes: {
265
- slide: {
266
- "0%, 100%": { transform: "translate3d(0,0,0)" },
267
- "100%": { transform: "translate3d(-50%,0,0)" },
268
- },
269
- marquee1: {
270
- "0%, 100%": { transform: "translate3d(0,0,0)" },
271
- "100%": { transform: "translate3d(-100%,0,0)" },
272
- },
273
- marquee2: {
274
- "0%, 100%": { transform: "translate3d(100%,0,0)" },
275
- "100%": { transform: "translate3d(0,0,0)" },
276
- },
277
- circle: {
278
- "0%": { strokeDashoffset: "90" },
279
- "100%": { strokeDashoffset: "0" },
280
- },
281
- dot: {
282
- "0%,95%": { fill: "transparent", stroke: "currentColor", strokeOpacity: "0.1" },
283
- "100%": { fill: "currentColor", stroke: "transparent", strokeOpacity: "0" },
284
- },
285
- typewriter: {
286
- "0%, 100%": { opacity: "1" },
287
- "50%": { opacity: "0" },
288
- },
289
- "pulse-bg": {
290
- "50%": { "--tw-bg-opacity": "0.5" },
291
- },
292
- },
293
- animation: {
294
- slide: "slide 30s linear infinite",
295
- marquee1: "marquee1 30s linear infinite",
296
- marquee2: "marquee2 30s linear infinite",
297
- circle: "circle 8.1s linear",
298
- dot: "dot 8.1s linear",
299
- typewriter: "typewriter 0.5s linear infinite",
300
- "pulse-bg": "pulse-bg 1s cubic-bezier(0.4, 0, 0.6, 1) infinite",
301
- },
302
- colors: {
303
- theme: {
304
- "trigger-bg": "rgb(var(--lx-color-trigger-bg) / <alpha-value>)",
305
- "trigger-text": "rgb(var(--lx-color-trigger-text) / <alpha-value>)",
306
- bg: "rgb(var(--lx-color-bg) / <alpha-value>)",
307
- text: "rgb(var(--lx-color-text) / <alpha-value>)",
308
- "button-bg": "rgb(var(--lx-color-button-bg) / <alpha-value>)",
309
- "button-text": "rgb(var(--lx-color-button-text) / <alpha-value>)",
310
- },
311
- },
312
- },
313
- variants: {
314
- extend: {},
315
- },
316
- },
317
- plugins: [
318
- require("autoprefixer"),
319
- require("@tailwindcss/aspect-ratio"),
320
- require("tailwindcss-container-queries-with-max-width"),
321
- require("tailwindcss-animate"),
322
- // require("@tailwindcss/forms"),
323
- plugin(({ addVariant, addUtilities, matchUtilities, theme }) => {
324
- addVariant("svg", ["& svg"]);
325
- addVariant("hfa", ["&:hover", "&:focus", "&:active"]);
326
- addVariant("hfw", ["&:hover", "&:focus-visible", "&:focus-within"]);
327
- addVariant("hfwa", ["&:hover", "&:focus-visible", "&:focus-within", "&:active"]);
328
- addVariant("hfwaa", ["&:hover", "&:focus-visible", "&:focus-within", "&:active", "&.active"]);
329
- addVariant("hfva", ["&:hover", "&:focus", "&:focus-visible", "&:active"]);
330
- addVariant("ha", ["&:hover", "&:active"]);
331
- addVariant("hf", ["&:hover", "&:focus-visible"]);
332
- addVariant("fa", ["&:focus", "&:active"]);
333
- addVariant("f", ["&:focus"]);
334
- addVariant("fw", ["&:focus-within"]);
335
- addVariant("fv", ["&:focus-visible"]);
336
- addVariant("h", ["&:hover"]);
337
- addVariant("d", [".dark &"]);
338
- addVariant("ac", ["&.active"]);
339
- addVariant("b", ["&::before"]);
340
- addVariant("a", ["&::after"]);
341
- addVariant("not-prose", [":not(.prose &)&"]);
342
- addVariant("hfaa", ["&:hover", "&:focus", "&:active", "&.active"]);
343
- addVariant("hfvaa", ["&:hover", "&:focus", "&:focus-visible", "&:active", "&.active"]);
344
- addVariant("group-hfa", [".group:hover &", ".group:focus &", ".group:active &"]);
345
- addVariant("group-hf", [".group:hover &", ".group:focus &"]);
346
- addVariant("group-ac", [".group.active &"]);
347
-
348
- addVariant("group-hfva", [".group:hover &", ".group:focus-visible &", ".group:active &"]);
349
- addVariant("group-hfwa", [".group:hover &", ".group:focus-visible &", ".group:focus-within &", ".group:active &"]);
350
- addVariant("group-hfw", [".group:hover &", ".group:focus-visible &", ".group:focus-within &"]);
351
- addVariant("peer-hfwa", [".peer:hover ~ &", ".peer:focus-visible ~ &", ".peer:focus-within ~ &", ".peer:active ~ &"]);
352
- addVariant("peer-fw", [".peer:focus-within ~ &"]);
353
- matchUtilities(
354
- {
355
- "top-spacing": (value) => ({
356
- top: `calc(${theme("spacing.top-bar-spacing")} + ${value})`,
357
- }),
358
- },
359
- { values: theme("spacing") }
360
- );
361
- matchUtilities(
362
- {
363
- "auto-col-flow": (value) => {
364
- if (value?.includes("/")) {
365
- const [cols, gap] = value.split("/");
366
- const calculatedGap = /^(\d|\.)*$/gi.test(gap?.trim()) ? `${+gap * 4}px` : gap;
367
-
368
- return {
369
- gridAutoFlow: `column`,
370
- gridAutoColumns: ` calc((100% - (${calculatedGap} * (${cols} - 1))) / ${cols})`,
371
- columnGap: `${calculatedGap}`,
372
- };
373
- }
374
- return {
375
- gridAutoFlow: `column`,
376
- gridAutoColumns: `${value}`,
377
- };
378
- },
379
- },
380
- { values: theme("width") }
381
- );
382
- /*matchUtilities(
383
- {
384
- "border-w": (value) => ({
385
- borderWidth: `${value}`,
386
- }),
387
- },
388
- { values: theme("spacing") }
389
- );
390
- matchUtilities(
391
- {
392
- "border-x-w": (value) => ({
393
- borderLeftWidth: `${value}`,
394
- borderRightWidth: `${value}`,
395
- }),
396
- },
397
- { values: theme("spacing") }
398
- );
399
- matchUtilities(
400
- {
401
- "border-l-w": (value) => ({
402
- borderLeftWidth: `${value}`,
403
- }),
404
- },
405
- { values: theme("spacing") }
406
- );
407
- matchUtilities(
408
- {
409
- "border-r-w": (value) => ({
410
- borderRightWidth: `${value}`,
411
- }),
412
- },
413
- { values: theme("spacing") }
414
- );
415
- matchUtilities(
416
- {
417
- "border-y-w": (value) => ({
418
- borderTopWidth: `${value}`,
419
- borderBottomWidth: `${value}`,
420
- }),
421
- },
422
- { values: theme("spacing") }
423
- );
424
- matchUtilities(
425
- {
426
- "border-t-w": (value) => ({
427
- borderTopWidth: `${value}`,
428
- }),
429
- },
430
- { values: theme("spacing") }
431
- );
432
- matchUtilities(
433
- {
434
- "border-b-w": (value) => ({
435
- borderBottomWidth: `${value}`,
436
- }),
437
- },
438
- { values: theme("spacing") }
439
- );*/
440
- addUtilities({
441
- ".shape-geometric-precision": {
442
- "shape-rendering": "geometricPrecision",
443
- },
444
- ".open-quote": {
445
- content: "open-quote",
446
- },
447
- ".close-quote": {
448
- content: "close-quote",
449
- },
450
- ".leading-0": {
451
- "line-height": "0",
452
- },
453
- ".animation-pause": {
454
- "animation-play-state": "paused",
455
- },
456
- ".animation-play": {
457
- "animation-play-state": "running",
458
- },
459
- });
460
- }),
461
- ],
462
- };