@sidekick-coder/zenith-kit 0.3.12 → 0.4.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.
@@ -1,8 +1,11 @@
1
1
  @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
+ @import "./theme.css";
3
4
 
4
5
  @custom-variant dark (&:is(.dark *));
5
6
 
7
+ @layer base {
8
+
6
9
  :root {
7
10
  --background: oklch(1 0 0);
8
11
  --foreground: oklch(0.141 0.005 285.823);
@@ -74,68 +77,6 @@
74
77
  --sidebar-ring: oklch(0.442 0.017 285.786);
75
78
  }
76
79
 
77
- @theme inline {
78
- --color-background: var(--background);
79
- --color-foreground: var(--foreground);
80
- --color-card: var(--card);
81
- --color-card-foreground: var(--card-foreground);
82
- --color-popover: var(--popover);
83
- --color-popover-foreground: var(--popover-foreground);
84
- --color-primary: var(--primary);
85
- --color-primary-foreground: var(--primary-foreground);
86
- --color-secondary: var(--secondary);
87
- --color-secondary-foreground: var(--secondary-foreground);
88
- --color-muted: var(--muted);
89
- --color-muted-foreground: var(--muted-foreground);
90
- --color-accent: var(--accent);
91
- --color-accent-foreground: var(--accent-foreground);
92
- --color-destructive: var(--destructive);
93
- --color-destructive-foreground: var(--destructive-foreground);
94
- --color-border: var(--border);
95
- --color-input: var(--input);
96
- --color-ring: var(--ring);
97
- --color-chart-1: var(--chart-1);
98
- --color-chart-2: var(--chart-2);
99
- --color-chart-3: var(--chart-3);
100
- --color-chart-4: var(--chart-4);
101
- --color-chart-5: var(--chart-5);
102
- --radius-sm: calc(var(--radius) - 4px);
103
- --radius-md: calc(var(--radius) - 2px);
104
- --radius-lg: var(--radius);
105
- --radius-xl: calc(var(--radius) + 4px);
106
- --color-sidebar: var(--sidebar);
107
- --color-sidebar-foreground: var(--sidebar-foreground);
108
- --color-sidebar-primary: var(--sidebar-primary);
109
- --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
110
- --color-sidebar-accent: var(--sidebar-accent);
111
- --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
112
- --color-sidebar-border: var(--sidebar-border);
113
- --color-sidebar-ring: var(--sidebar-ring);
114
- --animate-accordion-down: accordion-down 0.2s ease-out;
115
- --animate-accordion-up: accordion-up 0.2s ease-out;
116
-
117
- @keyframes accordion-down {
118
- from {
119
- height: 0;
120
- }
121
-
122
- to {
123
- height: var(--reka-accordion-content-height);
124
- }
125
- }
126
-
127
- @keyframes accordion-up {
128
- from {
129
- height: var(--reka-accordion-content-height);
130
- }
131
-
132
- to {
133
- height: 0;
134
- }
135
- }
136
- }
137
-
138
-
139
80
  * {
140
81
  @apply border-border outline-ring/50;
141
82
  }
@@ -154,3 +95,31 @@ iconify-icon {
154
95
  width: 1em;
155
96
  height: 1em;
156
97
  }
98
+
99
+ /* scrollbars */
100
+ /* .zenith-scrollbar { */
101
+ /* scrollbar-width: thin; */
102
+ /* scrollbar-color: var(--foreground) var(--background); */
103
+ /* scrollbar-gutter: stable both-edges; */
104
+ /* } */
105
+
106
+ .zenith-scrollbar::-webkit-scrollbar {
107
+ width: 8px;
108
+ height: 8px;
109
+ }
110
+
111
+ .zenith-scrollbar::-webkit-scrollbar-track {
112
+ background: var(--background);
113
+ }
114
+
115
+ .zenith-scrollbar::-webkit-scrollbar-thumb {
116
+ background-color: var(--foreground);
117
+ border-radius: 4px;
118
+ border: 2px solid var(--background);
119
+ }
120
+
121
+ .zenith-scrollbar::-webkit-scrollbar-corner {
122
+ background: var(--background);
123
+ }
124
+
125
+ }
@@ -0,0 +1,56 @@
1
+ @theme inline {
2
+ --color-background: var(--background);
3
+ --color-foreground: var(--foreground);
4
+ --color-card: var(--card);
5
+ --color-card-foreground: var(--card-foreground);
6
+ --color-popover: var(--popover);
7
+ --color-popover-foreground: var(--popover-foreground);
8
+ --color-primary: var(--primary);
9
+ --color-primary-foreground: var(--primary-foreground);
10
+ --color-secondary: var(--secondary);
11
+ --color-secondary-foreground: var(--secondary-foreground);
12
+ --color-muted: var(--muted);
13
+ --color-muted-foreground: var(--muted-foreground);
14
+ --color-accent: var(--accent);
15
+ --color-accent-foreground: var(--accent-foreground);
16
+ --color-destructive: var(--destructive);
17
+ --color-destructive-foreground: var(--destructive-foreground);
18
+ --color-border: var(--border);
19
+ --color-input: var(--input);
20
+ --color-ring: var(--ring);
21
+ --color-chart-1: var(--chart-1);
22
+ --color-chart-2: var(--chart-2);
23
+ --color-chart-3: var(--chart-3);
24
+ --color-chart-4: var(--chart-4);
25
+ --color-chart-5: var(--chart-5);
26
+ --radius-sm: calc(var(--radius) - 4px);
27
+ --radius-md: calc(var(--radius) - 2px);
28
+ --radius-lg: var(--radius);
29
+ --radius-xl: calc(var(--radius) + 4px);
30
+ --color-sidebar: var(--sidebar);
31
+ --color-sidebar-foreground: var(--sidebar-foreground);
32
+ --color-sidebar-primary: var(--sidebar-primary);
33
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
34
+ --color-sidebar-accent: var(--sidebar-accent);
35
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
36
+ --color-sidebar-border: var(--sidebar-border);
37
+ --color-sidebar-ring: var(--sidebar-ring);
38
+ --animate-accordion-down: accordion-down 0.2s ease-out;
39
+ --animate-accordion-up: accordion-up 0.2s ease-out;
40
+ @keyframes accordion-down {
41
+ from {
42
+ height: 0;
43
+ }
44
+ to {
45
+ height: var(--reka-accordion-content-height);
46
+ }
47
+ }
48
+ @keyframes accordion-up {
49
+ from {
50
+ height: var(--reka-accordion-content-height);
51
+ }
52
+ to {
53
+ height: 0;
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,475 @@
1
+ // @ts-check
2
+ import { createFilter } from '@rollup/pluginutils'
3
+ import MagicString from 'magic-string'
4
+ import * as acorn from 'acorn'
5
+ import postcss from 'postcss'
6
+ import selectorParser from 'postcss-selector-parser'
7
+
8
+ /**
9
+ * @typedef {Object} Options
10
+ * @property {string} prefix - Prefix prepended to every Tailwind class found (Tailwind v4 variant-style prefix, e.g. `tw` -> `tw:flex`, `tw:hover:flex`)
11
+ * @property {string | string[]} [include] - Files to include (default: `**\/*.{vue,html,js,jsx,ts,tsx}`)
12
+ * @property {string | string[]} [exclude] - Files to exclude (default: `node_modules/**`)
13
+ * @property {string[]} [excludeVars] - CSS custom property (variable) names to leave untouched, e.g. `--reka-*`. Supports `*` wildcards. By default every custom property is prefixed.
14
+ * @property {{ ignore?: string[] }} [classes] - `classes.ignore` lists literal class names (e.g. `.dark`) that must never receive the prefix, even when found as a standalone class. Compound/variant classes that merely contain the name (e.g. `dark:bg-input`) are still prefixed as usual.
15
+ */
16
+
17
+ /**
18
+ * Matches `class`, `className`, `:class` and `v-bind:class` attributes and
19
+ * captures the quote character used and the raw attribute value.
20
+ */
21
+ const CLASS_ATTR_REGEX = /(?:^|\s)(?:class|className|:class|v-bind:class)\s*=\s*(?<quote>["'])(?<value>.*?)\k<quote>/gs
22
+
23
+ /**
24
+ * Matches `style`, `:style` and `v-bind:style` attributes and captures the
25
+ * quote character used and the raw attribute value.
26
+ */
27
+ const STYLE_ATTR_REGEX = /(?:^|\s)(?:style|:style|v-bind:style)\s*=\s*(?<quote>["'])(?<value>.*?)\k<quote>/gs
28
+
29
+ /**
30
+ * Matches a CSS custom property name, e.g. `--sidebar-width`.
31
+ */
32
+ const CSS_VAR_NAME_REGEX = /--[a-zA-Z0-9_-]+/g
33
+
34
+ /**
35
+ * Binary operators that compare a value for equality; string literals used
36
+ * as an operand of these must never be treated as class names, since they
37
+ * are being compared against a variable (e.g. `side === 'left'`), not
38
+ * rendered as a class.
39
+ */
40
+ const EQUALITY_OPERATORS = new Set(['===', '!==', '==', '!='])
41
+
42
+ /**
43
+ * Builds a matcher for CSS variable names that should be left untouched,
44
+ * supporting simple `*` wildcards (e.g. `--reka-*`).
45
+ *
46
+ * @param {string[] | undefined} patterns
47
+ */
48
+ function createVarExcludeMatcher(patterns) {
49
+ if (!patterns || patterns.length === 0) {
50
+ return () => false
51
+ }
52
+
53
+ const regexes = patterns.map(pattern => {
54
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*')
55
+
56
+ return new RegExp(`^${escaped}$`)
57
+ })
58
+
59
+ return (/** @type {string} */ name) => regexes.some(regex => regex.test(name))
60
+ }
61
+
62
+ /**
63
+ * Builds the set of literal class names that must never receive the
64
+ * prefix (e.g. `.dark`), normalized to strip the leading `.` so it can be
65
+ * compared directly against a class token/selector class value.
66
+ *
67
+ * @param {string[] | undefined} patterns
68
+ */
69
+ function createIgnoredClassSet(patterns) {
70
+ return new Set((patterns || []).map(pattern => pattern.replace(/^\./, '')))
71
+ }
72
+
73
+
74
+ /**
75
+ * Renames a single CSS custom property name (e.g. `--sidebar-width` ->
76
+ * `--zkit-sidebar-width`), leaving it untouched if it's already prefixed or
77
+ * matches the exclude matcher.
78
+ *
79
+ * @param {string} name
80
+ * @param {string} prefix
81
+ * @param {(name: string) => boolean} isExcluded
82
+ */
83
+ function renameCssVarName(name, prefix, isExcluded) {
84
+ if (!name.startsWith('--') || name.startsWith(`--${prefix}-`) || isExcluded(name)) {
85
+ return name
86
+ }
87
+
88
+ return `--${prefix}-${name.slice(2)}`
89
+ }
90
+
91
+ /**
92
+ * Renames every CSS custom property reference found inside a chunk of text
93
+ * (e.g. `var(--sidebar-width)`, or the `--sidebar-width` inside Tailwind's
94
+ * `w-(--sidebar-width)` shorthand), leaving anything that isn't a `--name`
95
+ * token untouched.
96
+ *
97
+ * @param {string} text
98
+ * @param {string} prefix
99
+ * @param {(name: string) => boolean} isExcluded
100
+ */
101
+ function renameCssVarRefs(text, prefix, isExcluded) {
102
+ return text.replace(CSS_VAR_NAME_REGEX, match => renameCssVarName(match, prefix, isExcluded))
103
+ }
104
+
105
+ /**
106
+ * @param {string} className
107
+ * @param {string} prefix
108
+ * @param {(name: string) => boolean} isExcluded
109
+ * @param {Set<string>} ignoredClasses
110
+ */
111
+ function prefixClassName(className, prefix, isExcluded, ignoredClasses) {
112
+ if (!className) return className
113
+
114
+ // a class that is exactly one of the ignored literal names (e.g. `dark`)
115
+ // must be left completely untouched: no prefix, no embedded var rename
116
+ if (ignoredClasses.has(className)) {
117
+ return className
118
+ }
119
+
120
+ // rename any CSS variable reference embedded in the class itself, e.g.
121
+ // `w-(--sidebar-width)` or `[calc(var(--sidebar-width)*-1)]`, so it stays
122
+ // in sync with the renamed custom properties in the generated CSS
123
+ const withRenamedVars = className.includes('--')
124
+ ? renameCssVarRefs(className, prefix, isExcluded)
125
+ : className
126
+
127
+ if (withRenamedVars.startsWith(`${prefix}:`)) {
128
+ return withRenamedVars
129
+ }
130
+
131
+ return `${prefix}:${withRenamedVars}`
132
+ }
133
+
134
+ /**
135
+ * @param {string} value
136
+ * @param {string} prefix
137
+ * @param {(name: string) => boolean} isExcluded
138
+ * @param {Set<string>} ignoredClasses
139
+ */
140
+ function prefixClassList(value, prefix, isExcluded, ignoredClasses) {
141
+ return value
142
+ .split(/(\s+)/) // split keeping whitespace so original formatting is preserved
143
+ .map(token => (token.trim() ? prefixClassName(token, prefix, isExcluded, ignoredClasses) : token))
144
+ .join('')
145
+ }
146
+
147
+ /**
148
+ * @param {any} node
149
+ * @param {any} parent
150
+ */
151
+ function isComparisonOperand(node, parent) {
152
+ return !!parent
153
+ && parent.type === 'BinaryExpression'
154
+ && EQUALITY_OPERATORS.has(parent.operator)
155
+ && (parent.left === node || parent.right === node)
156
+ }
157
+
158
+ /**
159
+ * Prefixes only the string literals that are actually rendered as class
160
+ * names inside a dynamic `:class`/`v-bind:class` JS expression, leaving
161
+ * string literals used as comparison operands untouched
162
+ * (e.g. `side === 'left' ? 'left-0' : 'right-0'` only prefixes `'left-0'`
163
+ * and `'right-0'`, never the `'left'` being compared against `side`).
164
+ *
165
+ * Falls back to returning the original value untouched if the expression
166
+ * cannot be parsed as JavaScript.
167
+ *
168
+ * @param {string} value
169
+ * @param {string} prefix
170
+ * @param {(name: string) => boolean} isExcluded
171
+ * @param {Set<string>} ignoredClasses
172
+ */
173
+ function prefixDynamicClassValue(value, prefix, isExcluded, ignoredClasses) {
174
+ const wrapped = `(${value})`
175
+
176
+ let ast
177
+
178
+ try {
179
+ ast = acorn.parseExpressionAt(wrapped, 0, { ecmaVersion: 'latest' })
180
+ } catch {
181
+ return value
182
+ }
183
+
184
+ const s = new MagicString(wrapped)
185
+ let hasChanges = false
186
+
187
+ /**
188
+ * @param {any} node
189
+ * @param {any} parent
190
+ */
191
+ function walk(node, parent) {
192
+ if (!node || typeof node !== 'object' || typeof node.type !== 'string') return
193
+
194
+ const isStringLiteral = node.type === 'Literal' && typeof node.value === 'string'
195
+
196
+ if (isStringLiteral && !isComparisonOperand(node, parent)) {
197
+ const quote = node.raw?.[0] === "'" ? "'" : '"'
198
+ const newValue = prefixClassList(node.value, prefix, isExcluded, ignoredClasses)
199
+
200
+ if (newValue !== node.value) {
201
+ s.overwrite(node.start, node.end, `${quote}${newValue}${quote}`)
202
+ hasChanges = true
203
+ }
204
+ }
205
+
206
+ // don't descend into a string literal node, there is nothing left to walk
207
+ if (isStringLiteral) return
208
+
209
+ for (const key in node) {
210
+ if (key === 'start' || key === 'end' || key === 'type') continue
211
+ const child = node[key]
212
+
213
+ if (Array.isArray(child)) {
214
+ child.forEach(item => walk(item, node))
215
+ } else {
216
+ walk(child, node)
217
+ }
218
+ }
219
+ }
220
+
221
+ walk(ast, null)
222
+
223
+ if (!hasChanges) return value
224
+
225
+ return s.toString().slice(1, -1)
226
+ }
227
+
228
+ /**
229
+ * Rewrites every class selector in the given CSS so it targets the prefixed
230
+ * classes emitted by `prefixClassList`, e.g. `.flex` -> `.zkit\:flex` and
231
+ * `.hover\:flex:hover` -> `.zkit\:hover\:flex:hover`.
232
+ *
233
+ * This is required because Tailwind's own class scanner reads the original
234
+ * (unprefixed) source files directly from disk, so it always generates
235
+ * unprefixed utility CSS regardless of what this plugin does to the JS/Vue
236
+ * output. Prefixing the generated CSS selectors keeps them in sync with the
237
+ * classes emitted at runtime.
238
+ *
239
+ * Every CSS custom property (variable) declaration and usage is also
240
+ * prefixed (e.g. `--sidebar-width` -> `--zkit-sidebar-width`), unless it
241
+ * matches `excludeVars`, so the library's variables never collide with a
242
+ * consuming app's own variables of the same name.
243
+ *
244
+ * Classes matching `ignoredClasses` exactly (e.g. `dark`) are left
245
+ * completely untouched, even standalone in a selector such as
246
+ * `:is(.dark *)`; compound/variant classes that merely contain the name
247
+ * (e.g. `dark:bg-input`) are still prefixed as usual.
248
+ *
249
+ * @param {string} css
250
+ * @param {string} prefix
251
+ * @param {(name: string) => boolean} isExcluded
252
+ * @param {Set<string>} ignoredClasses
253
+ */
254
+ function prefixCss(css, prefix, isExcluded, ignoredClasses) {
255
+ const root = postcss.parse(css)
256
+
257
+ const transform = selectorParser(selectors => {
258
+ selectors.walkClasses(classNode => {
259
+ if (classNode.value.startsWith(`${prefix}:`)) return
260
+ if (ignoredClasses.has(classNode.value)) return
261
+
262
+ classNode.value = `${prefix}:${classNode.value}`
263
+ })
264
+ })
265
+
266
+ root.walkRules(rule => {
267
+ rule.selector = transform.processSync(rule.selector)
268
+ })
269
+
270
+ // rename every remaining `--name` token anywhere in the stylesheet:
271
+ // declaration props/values, `@property --name { ... }` at-rules and any
272
+ // custom property reference embedded in a selector (e.g. the
273
+ // `--sidebar-width` inside `.zkit\:w-\(--sidebar-width\)`)
274
+ return renameCssVarRefs(root.toString(), prefix, isExcluded)
275
+ }
276
+
277
+ /**
278
+ * Renames CSS custom properties referenced inside a `:style`/`v-bind:style`
279
+ * dynamic binding, so they stay in sync with the renamed variables in the
280
+ * generated CSS: object keys that declare a custom property (e.g.
281
+ * `{ '--sidebar-width': width }`) and any `var(--name)` reference inside a
282
+ * string value (e.g. `{ '--normal-bg': 'var(--popover)' }`).
283
+ *
284
+ * Falls back to returning the original value unchanged if it cannot be
285
+ * parsed as JavaScript.
286
+ *
287
+ * @param {string} value
288
+ * @param {string} prefix
289
+ * @param {(name: string) => boolean} isExcluded
290
+ */
291
+ function prefixDynamicStyleValue(value, prefix, isExcluded) {
292
+ const wrapped = `(${value})`
293
+
294
+ let ast
295
+
296
+ try {
297
+ ast = acorn.parseExpressionAt(wrapped, 0, { ecmaVersion: 'latest' })
298
+ } catch {
299
+ return value
300
+ }
301
+
302
+ const s = new MagicString(wrapped)
303
+ let hasChanges = false
304
+
305
+ /**
306
+ * @param {any} node
307
+ * @param {any} parent
308
+ */
309
+ function walk(node, parent) {
310
+ if (!node || typeof node !== 'object' || typeof node.type !== 'string') return
311
+
312
+ const isStringLiteral = node.type === 'Literal' && typeof node.value === 'string'
313
+
314
+ if (isStringLiteral && node.value.includes('--')) {
315
+ const quote = node.raw?.[0] === "'" ? "'" : '"'
316
+
317
+ // object keys declaring a custom property (`'--sidebar-width': ...`)
318
+ // are renamed wholesale; any other string is only scanned for
319
+ // `var(--name)`-style references
320
+ const isObjectKey = parent?.type === 'Property' && parent.key === node && !parent.computed
321
+
322
+ const newValue = isObjectKey && node.value.startsWith('--')
323
+ ? renameCssVarName(node.value, prefix, isExcluded)
324
+ : renameCssVarRefs(node.value, prefix, isExcluded)
325
+
326
+ if (newValue !== node.value) {
327
+ s.overwrite(node.start, node.end, `${quote}${newValue}${quote}`)
328
+ hasChanges = true
329
+ }
330
+ }
331
+
332
+ if (isStringLiteral) return
333
+
334
+ for (const key in node) {
335
+ if (key === 'start' || key === 'end' || key === 'type') continue
336
+ const child = node[key]
337
+
338
+ if (Array.isArray(child)) {
339
+ child.forEach(item => walk(item, node))
340
+ } else {
341
+ walk(child, node)
342
+ }
343
+ }
344
+ }
345
+
346
+ walk(ast, null)
347
+
348
+ if (!hasChanges) return value
349
+
350
+ return s.toString().slice(1, -1)
351
+ }
352
+
353
+ /**
354
+ * Vite plugin that scans included files for Tailwind CSS classes (`class`,
355
+ * `className`, `:class`, `v-bind:class`) and prepends a fixed prefix to each
356
+ * class found, following Tailwind v4's variant-style prefix syntax
357
+ * (e.g. `flex` -> `tw:flex`, `hover:flex` -> `tw:hover:flex`).
358
+ *
359
+ * @param {Options} options
360
+ * @returns {import('vite').Plugin[]}
361
+ */
362
+ export default function(options) {
363
+ const prefix = options?.prefix
364
+
365
+ if (!prefix) {
366
+ throw new Error('[tailwindAutoPrefix] "prefix" option is required')
367
+ }
368
+
369
+ const include = options?.include || '**/*.{vue,html,js,jsx,ts,tsx}'
370
+ const exclude = options?.exclude || 'node_modules/**'
371
+
372
+ const filter = createFilter(include, exclude)
373
+ const isExcludedVar = createVarExcludeMatcher(options?.excludeVars)
374
+ const ignoredClasses = createIgnoredClassSet(options?.classes?.ignore)
375
+
376
+ const sourcePlugin = {
377
+ name: 'tailwind-auto-prefix',
378
+ enforce: /** @type {const} */ ('pre'),
379
+
380
+ /**
381
+ * @param {string} code
382
+ * @param {string} id
383
+ */
384
+ transform(code, id) {
385
+ if (!filter(id)) {
386
+ return null
387
+ }
388
+
389
+ const s = new MagicString(code)
390
+ let hasChanges = false
391
+
392
+ CLASS_ATTR_REGEX.lastIndex = 0
393
+
394
+ let match
395
+
396
+ while ((match = CLASS_ATTR_REGEX.exec(code))) {
397
+ const fullMatch = match[0]
398
+ const { quote, value } = /** @type {{ quote: string, value: string }} */ (match.groups)
399
+
400
+ const quotedValue = `${quote}${value}${quote}`
401
+ const relativeIndex = fullMatch.lastIndexOf(quotedValue)
402
+ const valueStart = match.index + relativeIndex + 1
403
+ const valueEnd = valueStart + value.length
404
+
405
+ const isDynamicBinding = /^\s*(?::class|v-bind:class)\s*=/.test(fullMatch)
406
+
407
+ let newValue
408
+
409
+ if (isDynamicBinding) {
410
+ newValue = prefixDynamicClassValue(value, prefix, isExcludedVar, ignoredClasses)
411
+ } else {
412
+ newValue = prefixClassList(value, prefix, isExcludedVar, ignoredClasses)
413
+ }
414
+
415
+ if (newValue !== value) {
416
+ s.overwrite(valueStart, valueEnd, newValue)
417
+ hasChanges = true
418
+ }
419
+ }
420
+
421
+ STYLE_ATTR_REGEX.lastIndex = 0
422
+
423
+ while ((match = STYLE_ATTR_REGEX.exec(code))) {
424
+ const fullMatch = match[0]
425
+ const { quote, value } = /** @type {{ quote: string, value: string }} */ (match.groups)
426
+
427
+ const quotedValue = `${quote}${value}${quote}`
428
+ const relativeIndex = fullMatch.lastIndexOf(quotedValue)
429
+ const valueStart = match.index + relativeIndex + 1
430
+ const valueEnd = valueStart + value.length
431
+
432
+ const isDynamicBinding = /^\s*(?::style|v-bind:style)\s*=/.test(fullMatch)
433
+
434
+ const newValue = isDynamicBinding
435
+ ? prefixDynamicStyleValue(value, prefix, isExcludedVar)
436
+ : renameCssVarRefs(value, prefix, isExcludedVar)
437
+
438
+ if (newValue !== value) {
439
+ s.overwrite(valueStart, valueEnd, newValue)
440
+ hasChanges = true
441
+ }
442
+ }
443
+
444
+ if (!hasChanges) return null
445
+
446
+ return {
447
+ code: s.toString(),
448
+ map: s.generateMap({ hires: true }),
449
+ }
450
+ },
451
+ }
452
+
453
+ const cssPlugin = {
454
+ name: 'tailwind-auto-prefix:css',
455
+ enforce: /** @type {const} */ ('post'),
456
+
457
+ /**
458
+ * @param {*} _options
459
+ * @param {Record<string, import('vite').Rollup.OutputAsset | import('vite').Rollup.OutputChunk>} bundle
460
+ */
461
+ generateBundle(_options, bundle) {
462
+ for (const fileName of Object.keys(bundle)) {
463
+ const chunk = bundle[fileName]
464
+
465
+ if (chunk.type !== 'asset' || !fileName.endsWith('.css') || typeof chunk.source !== 'string') {
466
+ continue
467
+ }
468
+
469
+ chunk.source = prefixCss(chunk.source, prefix, isExcludedVar, ignoredClasses)
470
+ }
471
+ },
472
+ }
473
+
474
+ return [sourcePlugin, cssPlugin]
475
+ }