frutjam 2.0.1 → 2.0.2

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.
Files changed (62) hide show
  1. package/dist/base.css +2 -2
  2. package/dist/components/accordion.css +2 -2
  3. package/dist/components/alert.css +2 -2
  4. package/dist/components/avatar.css +2 -2
  5. package/dist/components/badge.css +2 -2
  6. package/dist/components/breadcrumb.css +2 -2
  7. package/dist/components/button.css +2 -2
  8. package/dist/components/card.css +2 -2
  9. package/dist/components/carousel.css +2 -2
  10. package/dist/components/chat.css +2 -2
  11. package/dist/components/checkbox.css +2 -2
  12. package/dist/components/collapsible.css +2 -2
  13. package/dist/components/combobox.css +2 -2
  14. package/dist/components/countdown.css +2 -2
  15. package/dist/components/diff.css +2 -2
  16. package/dist/components/divider.css +2 -2
  17. package/dist/components/drawer.css +2 -2
  18. package/dist/components/footer.css +2 -2
  19. package/dist/components/header.css +2 -2
  20. package/dist/components/hero.css +2 -2
  21. package/dist/components/indicator.css +2 -2
  22. package/dist/components/input.css +2 -2
  23. package/dist/components/join.css +2 -2
  24. package/dist/components/kbd.css +2 -2
  25. package/dist/components/link.css +2 -2
  26. package/dist/components/loading.css +2 -2
  27. package/dist/components/mask.css +2 -2
  28. package/dist/components/menu.css +2 -2
  29. package/dist/components/modal.css +2 -2
  30. package/dist/components/navbar.css +2 -2
  31. package/dist/components/popover.css +2 -2
  32. package/dist/components/progress.css +2 -2
  33. package/dist/components/radial-progress.css +2 -2
  34. package/dist/components/radio.css +2 -2
  35. package/dist/components/range.css +2 -2
  36. package/dist/components/rating.css +2 -2
  37. package/dist/components/select.css +2 -2
  38. package/dist/components/sidebar.css +2 -2
  39. package/dist/components/skeleton.css +2 -2
  40. package/dist/components/stat.css +2 -2
  41. package/dist/components/status.css +2 -2
  42. package/dist/components/steps.css +2 -2
  43. package/dist/components/surface.css +2 -2
  44. package/dist/components/swap.css +2 -2
  45. package/dist/components/table.css +2 -2
  46. package/dist/components/tabs.css +2 -2
  47. package/dist/components/tag.css +2 -2
  48. package/dist/components/textarea.css +2 -2
  49. package/dist/components/timeline.css +2 -2
  50. package/dist/components/toast.css +2 -2
  51. package/dist/components/toggle.css +2 -2
  52. package/dist/components/tooltip.css +2 -2
  53. package/dist/frutjam.min.css +3 -3
  54. package/dist/plugin.js +52 -5
  55. package/dist/themes/darkberry.css +1 -1
  56. package/dist/themes/snowberry.css +1 -1
  57. package/dist/utilities/headings.css +2 -2
  58. package/dist/utilities/para.css +2 -2
  59. package/dist/utilities/typography.css +1 -1
  60. package/dist/utilities/wrapper.css +2 -2
  61. package/index.js +43 -0
  62. package/package.json +4 -4
package/dist/plugin.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | MIT License | https://frutjam.com */
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | MIT License | https://frutjam.com */
2
2
 
3
3
  // Tailwind v4 plugin.withOptions implementation
4
4
  const plugin = {
@@ -67,12 +67,59 @@ function sortUtils(obj) {
67
67
  )
68
68
  }
69
69
 
70
- // Recursively remap :root keys to a custom selector
70
+ // Split a comma-separated selector list by top-level commas (ignores commas inside parentheses)
71
+ function splitTopLevelCommas(str) {
72
+ const parts = []
73
+ let depth = 0, start = 0
74
+ for (let i = 0; i < str.length; i++) {
75
+ if (str[i] === '(') depth++
76
+ else if (str[i] === ')') depth--
77
+ else if (str[i] === ',' && depth === 0) {
78
+ parts.push(str.slice(start, i))
79
+ start = i + 1
80
+ }
81
+ }
82
+ parts.push(str.slice(start))
83
+ return parts
84
+ }
85
+
86
+ // Scope one part of a comma-separated selector list to rootSelector.
87
+ // Returns an array of replacement selectors.
88
+ // [data-theme] selectors become compound with rootSelector so theme variables
89
+ // only apply when data-theme is set directly on the root element — no ancestor
90
+ // inheritance, which would break the isolation guarantee of the root option.
91
+ function scopeThemePart(part, rootSelector) {
92
+ const t = part.trimStart()
93
+ const lead = part.slice(0, part.length - t.length)
94
+ if (t.startsWith(rootSelector)) return [part]
95
+ if (t.startsWith(':is([data-theme')) {
96
+ const values = []
97
+ const re = /\[data-theme=["']([^"']+)["']\]/g
98
+ let m
99
+ while ((m = re.exec(t)) !== null) values.push(m[1])
100
+ return values.map(function(v) { return lead + rootSelector + '[data-theme="' + v + '"]' })
101
+ }
102
+ if (/^\[data-theme=/.test(t)) {
103
+ const m = t.match(/^\[data-theme=["']([^"']+)["']\]/)
104
+ if (m) return [lead + rootSelector + '[data-theme="' + m[1] + '"]']
105
+ }
106
+ if (t.startsWith('[data-theme]')) {
107
+ return [lead + rootSelector + '[data-theme]']
108
+ }
109
+ return [part]
110
+ }
111
+
112
+ // Recursively remap :root and scope [data-theme] selectors to a custom root selector
71
113
  function remapRoot(obj, rootSelector) {
72
114
  if (!rootSelector || rootSelector === ":root") return obj
73
115
  return Object.fromEntries(
74
116
  Object.entries(obj).map(([k, v]) => {
75
- const newKey = k.replace(/:root\b/g, rootSelector)
117
+ let newKey = k.replace(/:root\b/g, rootSelector)
118
+ if (!newKey.startsWith('@')) {
119
+ newKey = splitTopLevelCommas(newKey).flatMap(function(part) {
120
+ return scopeThemePart(part, rootSelector)
121
+ }).join(',')
122
+ }
76
123
  const newVal = (v && typeof v === "object") ? remapRoot(v, rootSelector) : v
77
124
  return [newKey, newVal]
78
125
  })
@@ -103,7 +150,7 @@ export default plugin.withOptions(
103
150
  if (logs) {
104
151
  const d = "\x1b[2m", r = "\x1b[0m"
105
152
  const badge = "\x1b[46m\x1b[30m frutjam \x1b[0m"
106
- console.log("\n" + badge + " " + d + "v2.0.1" + r + "\n")
153
+ console.log("\n" + badge + " " + d + "v2.0.2" + r + "\n")
107
154
  }
108
155
 
109
156
  // Base
@@ -112,7 +159,7 @@ export default plugin.withOptions(
112
159
  // Themes
113
160
  const activeThemes = Array.isArray(themes) ? themes : [themes]
114
161
  for (const [name, styles] of Object.entries(THEMES)) {
115
- if (activeThemes.includes(name)) addBase(styles)
162
+ if (activeThemes.includes(name)) addBase(remapRoot(styles, root))
116
163
  }
117
164
 
118
165
  // Components — class selectors via addUtilities (enables lg:/hover:/etc. variants),
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
2
  @layer theme{:is([data-theme=darkberry],[data-theme=dark]){--scheme-color:dark;--border-radius:0.25rem;--color-base:oklch(10.889% 0.00301 17.398);--color-on-base:oklch(98% 0.01 270);--color-neutral:oklch(85% 0 0);--color-on-neutral:oklch(20% 0 0);--color-primary:oklch(66.385% 0.18368 285.592);--color-on-primary:oklch(10% 0.01 270);--color-secondary:oklch(65% 0.18 220);--color-on-secondary:oklch(10% 0.01 220);--color-accent:oklch(75% 0.18 50);--color-on-accent:oklch(10% 0.01 50);--color-info:oklch(91.67% .077 205.04);--color-on-info:oklch(10% 0.01 250);--color-success:oklch(65% 0.18 140);--color-on-success:oklch(10% 0.01 140);--color-warning:oklch(75% 0.20 85);--color-on-warning:oklch(10% 0.01 85);--color-error:oklch(60% 0.22 30);--color-on-error:oklch(10% 0.01 30)}}
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
2
  @layer theme{:is([data-theme=snowberry],[data-theme=light]),:root:not([data-theme]){--scheme-color:light;--border-radius:0.25rem;--color-base:oklch(1 0 0);--color-on-base:oklch(0.22 0 0);--color-neutral:oklch(0.15 0 0);--color-on-neutral:oklch(1 0 0);--color-primary:oklch(51.1% 0.262 276.966);--color-on-primary:oklch(96.2% 0.018 272.314);--color-secondary:oklch(0.591 0.293 322.896);--color-on-secondary:oklch(1 0 0);--color-accent:oklch(0.541 0.281 293.009);--color-on-accent:oklch(1 0 0);--color-info:oklch(0.685 0.169 237.323);--color-on-info:oklch(0.15 0 0);--color-success:oklch(0.792 0.209 151.711);--color-on-success:oklch(0.15 0 0);--color-warning:oklch(0.852 0.199 91.936);--color-on-warning:oklch(0.15 0 0);--color-error:oklch(0.577 0.245 27.325);--color-on-error:oklch(1 0 0)}}
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
- /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */.heading-2xl{--heading-size:1rem;--heading-size:1.5rem}.heading-2xl,.heading-3xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-3xl{--heading-size:1rem;--heading-size:1.875rem}.heading-4xl{--heading-size:1rem;--heading-size:2.25rem}.heading-4xl,.heading-5xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-5xl{--heading-size:1rem;--heading-size:3rem}.heading-6xl{--heading-size:1rem;--heading-size:3.75rem}.heading-6xl,.heading-7xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-7xl{--heading-size:1rem;--heading-size:4.5rem}.heading-8xl{--heading-size:1rem;--heading-size:6rem}.heading-8xl,.heading-9xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-9xl{--heading-size:1rem;--heading-size:8rem}.heading-lg{--heading-size:1rem;--heading-size:1.125rem}.heading-lg,.heading-md{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-md{--heading-size:1rem}.heading-sm{--heading-size:1rem;--heading-size:0.875rem}.heading-sm,.heading-xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-xl{--heading-size:1rem;--heading-size:1.25rem}.heading-xs{--heading-size:1rem;--heading-size:0.75rem}.heading,.heading-xs{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading{--heading-size:1rem}
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */.heading-2xl{--heading-size:1rem;--heading-size:1.5rem}.heading-2xl,.heading-3xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-3xl{--heading-size:1rem;--heading-size:1.875rem}.heading-4xl{--heading-size:1rem;--heading-size:2.25rem}.heading-4xl,.heading-5xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-5xl{--heading-size:1rem;--heading-size:3rem}.heading-6xl{--heading-size:1rem;--heading-size:3.75rem}.heading-6xl,.heading-7xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-7xl{--heading-size:1rem;--heading-size:4.5rem}.heading-8xl{--heading-size:1rem;--heading-size:6rem}.heading-8xl,.heading-9xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-9xl{--heading-size:1rem;--heading-size:8rem}.heading-lg{--heading-size:1rem;--heading-size:1.125rem}.heading-lg,.heading-md{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-md{--heading-size:1rem}.heading-sm{--heading-size:1rem;--heading-size:0.875rem}.heading-sm,.heading-xl{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading-xl{--heading-size:1rem;--heading-size:1.25rem}.heading-xs{--heading-size:1rem;--heading-size:0.75rem}.heading,.heading-xs{color:var(--color-on-base);font-weight:700;text-wrap-style:balance;font-size:var(--heading-size);line-height:1.15}.heading{--heading-size:1rem}
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
- /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */.para-2xl{font-size:var(--text-base);font-size:var(--text-2xl)}.para-2xl,.para-3xl{text-wrap-style:pretty;line-height:1.6}.para-3xl{font-size:var(--text-base);font-size:var(--text-3xl)}.para-4xl{font-size:var(--text-base);font-size:var(--text-4xl)}.para-4xl,.para-5xl{text-wrap-style:pretty;line-height:1.6}.para-5xl{font-size:var(--text-base);font-size:var(--text-5xl)}.para-6xl{font-size:var(--text-base);font-size:var(--text-6xl)}.para-6xl,.para-7xl{text-wrap-style:pretty;line-height:1.6}.para-7xl{font-size:var(--text-base);font-size:var(--text-7xl)}.para-8xl{font-size:var(--text-base);font-size:var(--text-8xl)}.para-8xl,.para-9xl{text-wrap-style:pretty;line-height:1.6}.para-9xl{font-size:var(--text-base);font-size:var(--text-9xl)}.para-lg{font-size:var(--text-base);font-size:var(--text-lg)}.para-lg,.para-md{text-wrap-style:pretty;line-height:1.6}.para-md{font-size:var(--text-base)}.para-sm{font-size:var(--text-base);font-size:var(--text-sm)}.para-sm,.para-xl{text-wrap-style:pretty;line-height:1.6}.para-xl{font-size:var(--text-base);font-size:var(--text-xl)}.para-xs{font-size:var(--text-base);font-size:var(--text-xs)}.para,.para-xs{text-wrap-style:pretty;line-height:1.6}.para{font-size:var(--text-base)}
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */.para-2xl{font-size:var(--text-base);font-size:var(--text-2xl)}.para-2xl,.para-3xl{text-wrap-style:pretty;line-height:1.6}.para-3xl{font-size:var(--text-base);font-size:var(--text-3xl)}.para-4xl{font-size:var(--text-base);font-size:var(--text-4xl)}.para-4xl,.para-5xl{text-wrap-style:pretty;line-height:1.6}.para-5xl{font-size:var(--text-base);font-size:var(--text-5xl)}.para-6xl{font-size:var(--text-base);font-size:var(--text-6xl)}.para-6xl,.para-7xl{text-wrap-style:pretty;line-height:1.6}.para-7xl{font-size:var(--text-base);font-size:var(--text-7xl)}.para-8xl{font-size:var(--text-base);font-size:var(--text-8xl)}.para-8xl,.para-9xl{text-wrap-style:pretty;line-height:1.6}.para-9xl{font-size:var(--text-base);font-size:var(--text-9xl)}.para-lg{font-size:var(--text-base);font-size:var(--text-lg)}.para-lg,.para-md{text-wrap-style:pretty;line-height:1.6}.para-md{font-size:var(--text-base)}.para-sm{font-size:var(--text-base);font-size:var(--text-sm)}.para-sm,.para-xl{text-wrap-style:pretty;line-height:1.6}.para-xl{font-size:var(--text-base);font-size:var(--text-xl)}.para-xs{font-size:var(--text-base);font-size:var(--text-xs)}.para,.para-xs{text-wrap-style:pretty;line-height:1.6}.para{font-size:var(--text-base)}
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
2
  .prose-frutjam{--tw-prose-body:var(--color-body);--tw-prose-headings:var(--color-on-base);--tw-prose-lead:var(--color-on-neutral);--tw-prose-bold:var(--color-on-base);--tw-prose-links:var(--color-primary);--tw-prose-counters:var(--color-neutral);--tw-prose-bullets:var(--color-neutral);--tw-prose-hr:var(--color-base-soft);--tw-prose-quotes:var(--color-on-base);--tw-prose-quote-borders:var(--color-primary);--tw-prose-code:var(--color-on-base);--tw-prose-pre-code:var(--color-on-base);--tw-prose-pre-bg:var(--color-base-soft);--tw-prose-th-borders:var(--color-base-soft);--tw-prose-td-borders:var(--color-base-soft);--tw-prose-captions:var(--color-on-neutral);--tw-prose-kbd:var(--color-body);--tw-prose-invert-body:var(--color-on-neutral);--tw-prose-invert-headings:var(--color-on-base);--tw-prose-invert-links:var(--color-primary)}
@@ -1,2 +1,2 @@
1
- /*! frutjam v2.0.1 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
- /*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */.wrapper-full{width:100%;max-width:100%;box-sizing:border-box;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-2xl{box-sizing:border-box;max-width:1536px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-lg{box-sizing:border-box;max-width:1024px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-md{box-sizing:border-box;max-width:768px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-sm{box-sizing:border-box;max-width:640px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-xl{box-sizing:border-box;max-width:1280px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-xs{box-sizing:border-box;max-width:320px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper{box-sizing:border-box;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}
1
+ /*! frutjam v2.0.2 (c) 2026 Nezanuha | Released under the MIT License | https://frutjam.com */
2
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */.wrapper-full{width:100%;max-width:100%;box-sizing:border-box;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-2xl{box-sizing:border-box;max-width:1536px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-lg{box-sizing:border-box;max-width:1024px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-md{box-sizing:border-box;max-width:768px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-sm{box-sizing:border-box;max-width:640px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-xl{box-sizing:border-box;max-width:1280px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper-xs{box-sizing:border-box;max-width:320px;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}.wrapper{box-sizing:border-box;margin-inline:auto;padding-inline:1rem;@media (width >= 40rem){padding-inline:2rem}@media (width >= 64rem){padding-inline:4rem}}
package/index.js CHANGED
@@ -133,6 +133,41 @@ const BASE_CORE = [
133
133
 
134
134
  // ── Build ────────────────────────────────────────────────────────────────────
135
135
 
136
+ // Scope one selector part (already split from a comma list) to rootSelector.
137
+ // Returns an array of replacement selectors.
138
+ // [data-theme] selectors become compound with rootSelector so theme variables
139
+ // only apply when data-theme is set directly on the root element — no ancestor
140
+ // inheritance, which would break the isolation guarantee of the root option.
141
+ function scopeThemeSelector(sel, rootSelector) {
142
+ const t = sel.trimStart()
143
+ const lead = sel.slice(0, sel.length - t.length)
144
+
145
+ // Already remapped from :root (e.g. rootSelector:not([data-theme])) — keep as-is
146
+ if (t.startsWith(rootSelector)) return [sel]
147
+
148
+ // :is([data-theme="x"], [data-theme="y"]) — flatten into individual compound selectors
149
+ if (t.startsWith(":is([data-theme")) {
150
+ const values = []
151
+ const re = /\[data-theme=["']([^"']+)["']\]/g
152
+ let m
153
+ while ((m = re.exec(t)) !== null) values.push(m[1])
154
+ return values.map(v => `${lead}${rootSelector}[data-theme="${v}"]`)
155
+ }
156
+
157
+ // [data-theme="x"] — compound with rootSelector
158
+ if (/^\[data-theme=/.test(t)) {
159
+ const m = t.match(/^\[data-theme=["']([^"']+)["']\]/)
160
+ if (m) return [`${lead}${rootSelector}[data-theme="${m[1]}"]`]
161
+ }
162
+
163
+ // [data-theme] without value (base tokens) — compound with rootSelector
164
+ if (t.startsWith("[data-theme]")) {
165
+ return [`${lead}${rootSelector}[data-theme]`]
166
+ }
167
+
168
+ return [sel]
169
+ }
170
+
136
171
  function buildCSS(prefix, themes, reset, rootSelector, include, exclude) {
137
172
  // Resolve which components+utilities to include
138
173
  let keys = Object.keys(REGISTRY)
@@ -169,6 +204,14 @@ function buildCSS(prefix, themes, reset, rootSelector, include, exclude) {
169
204
  const customThemes = buildCustomThemes(themes)
170
205
  if (customThemes) css += "\n\n" + customThemes
171
206
 
207
+ if (rootSelector !== ":root") {
208
+ const ast = postcss.parse(css)
209
+ ast.walkRules(rule => {
210
+ rule.selectors = rule.selectors.flatMap(sel => scopeThemeSelector(sel, rootSelector))
211
+ })
212
+ css = ast.toString()
213
+ }
214
+
172
215
  return { css, utilMap }
173
216
  }
174
217
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frutjam",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "A utility-first CSS UI Library for Tailwind CSS",
5
5
  "type": "module",
6
6
  "exports": {
@@ -90,12 +90,12 @@
90
90
  }
91
91
  },
92
92
  "devDependencies": {
93
- "@tailwindcss/postcss": "^4.2.4",
93
+ "@tailwindcss/postcss": "^4.3.0",
94
94
  "autoprefixer": "^10.5.0",
95
- "cssnano": "^8.0.0",
95
+ "cssnano": "^8.0.1",
96
96
  "postcss": "^8.5.14",
97
97
  "postcss-js": "^5.1.0",
98
98
  "rimraf": "^6.1.3",
99
- "tailwindcss": "^4.2.4"
99
+ "tailwindcss": "^4.3.0"
100
100
  }
101
101
  }