@pyreon/styler 0.11.6 → 0.11.8

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.
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, h, provide, useContext } from "@pyreon/core";
2
- import { effect } from "@pyreon/reactivity";
2
+ import { effect, runUntracked } from "@pyreon/reactivity";
3
3
 
4
4
  //#region src/resolve.ts
5
5
  /**
@@ -799,13 +799,15 @@ const createStyledComponent = (tag, strings, values, options) => {
799
799
  const DynamicStyled = (rawProps) => {
800
800
  const theme = useTheme();
801
801
  const $rs = rawProps.$rocketstyle;
802
+ const $rsState = rawProps.$rocketstate;
802
803
  const isReactiveRS = typeof $rs === "function";
804
+ const isReactiveState = typeof $rsState === "function";
803
805
  const resolvedRS = isReactiveRS ? $rs() : $rs;
806
+ const resolvedState = isReactiveState ? $rsState() : $rsState;
804
807
  const cssText = normalizeCSS(resolve(strings, values, {
805
- ...isReactiveRS ? {
806
- ...rawProps,
807
- $rocketstyle: resolvedRS
808
- } : rawProps,
808
+ ...rawProps,
809
+ ...isReactiveRS ? { $rocketstyle: resolvedRS } : {},
810
+ ...isReactiveState ? { $rocketstate: resolvedState } : {},
809
811
  theme
810
812
  }));
811
813
  const initialClassName = cssText.length > 0 ? sheet.insert(cssText, boost) : "";
@@ -827,17 +829,21 @@ const createStyledComponent = (tag, strings, values, options) => {
827
829
  }, initialClassName, isDOM, customFilter);
828
830
  if (isReactiveRS) effect(() => {
829
831
  const newRS = $rs();
830
- const newCss = normalizeCSS(resolve(strings, values, {
831
- ...rawProps,
832
- $rocketstyle: newRS,
833
- theme
834
- }));
835
- const newClass = newCss.length > 0 ? sheet.insert(newCss, boost) : "";
836
- if (el && newClass !== currentClassName) {
837
- if (currentClassName) el.classList.remove(currentClassName);
838
- if (newClass) el.classList.add(newClass);
839
- currentClassName = newClass;
840
- }
832
+ const newState = isReactiveState ? $rsState() : $rsState;
833
+ runUntracked(() => {
834
+ const newCss = normalizeCSS(resolve(strings, values, {
835
+ ...rawProps,
836
+ $rocketstyle: newRS,
837
+ $rocketstate: newState,
838
+ theme
839
+ }));
840
+ const newClass = newCss.length > 0 ? sheet.insert(newCss, boost) : "";
841
+ if (el && newClass !== currentClassName) {
842
+ if (currentClassName) el.classList.remove(currentClassName);
843
+ if (newClass) el.classList.add(newClass);
844
+ currentClassName = newClass;
845
+ }
846
+ });
841
847
  });
842
848
  return h(finalTag, finalProps, ...Array.isArray(rawProps.children) ? rawProps.children : rawProps.children != null ? [rawProps.children] : []);
843
849
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/styler",
3
- "version": "0.11.6",
3
+ "version": "0.11.8",
4
4
  "description": "Lightweight CSS-in-JS engine for Pyreon",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,12 +41,12 @@
41
41
  "typecheck": "tsc --noEmit"
42
42
  },
43
43
  "devDependencies": {
44
- "@pyreon/typescript": "^0.11.6",
44
+ "@pyreon/typescript": "^0.11.8",
45
45
  "@vitus-labs/tools-rolldown": "^1.15.3"
46
46
  },
47
47
  "peerDependencies": {
48
- "@pyreon/core": "^0.11.6",
49
- "@pyreon/reactivity": "^0.11.6"
48
+ "@pyreon/core": "^0.11.8",
49
+ "@pyreon/reactivity": "^0.11.8"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">= 22"
package/src/styled.tsx CHANGED
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import type { ComponentFn, VNode } from '@pyreon/core'
19
19
  import { h } from '@pyreon/core'
20
- import { effect } from '@pyreon/reactivity'
20
+ import { effect, runUntracked } from '@pyreon/reactivity'
21
21
  import { buildProps } from './forward'
22
22
  import { type Interpolation, normalizeCSS, resolve } from './resolve'
23
23
  import { isDynamic } from './shared'
@@ -132,11 +132,22 @@ const createStyledComponent = (
132
132
  const DynamicStyled: ComponentFn = (rawProps: Record<string, any>): VNode | null => {
133
133
  const theme = useTheme()
134
134
  const $rs = rawProps.$rocketstyle
135
+ const $rsState = rawProps.$rocketstate
135
136
  const isReactiveRS = typeof $rs === 'function'
137
+ const isReactiveState = typeof $rsState === 'function'
136
138
 
137
- // Resolve initial $rocketstyle value
139
+ // Resolve initial accessor values — both $rocketstyle and $rocketstate
140
+ // must be plain objects when passed to resolve(), because .styles()
141
+ // interpolation functions destructure them directly:
142
+ // const { hover, pressed } = $rocketstate.pseudo
143
+ // const { hover: hoverStyles } = $rocketstyle
138
144
  const resolvedRS = isReactiveRS ? $rs() : $rs
139
- const initialProps = isReactiveRS ? { ...rawProps, $rocketstyle: resolvedRS } : rawProps
145
+ const resolvedState = isReactiveState ? $rsState() : $rsState
146
+ const initialProps = {
147
+ ...rawProps,
148
+ ...(isReactiveRS ? { $rocketstyle: resolvedRS } : {}),
149
+ ...(isReactiveState ? { $rocketstate: resolvedState } : {}),
150
+ }
140
151
  const cssText = normalizeCSS(resolve(strings, values, { ...initialProps, theme }))
141
152
  const initialClassName = cssText.length > 0 ? sheet.insert(cssText, boost) : ''
142
153
 
@@ -163,19 +174,36 @@ const createStyledComponent = (
163
174
  customFilter,
164
175
  )
165
176
 
166
- // Set up reactive class swap when $rocketstyle is a function accessor
177
+ // Set up reactive class swap when $rocketstyle is a function accessor.
178
+ // CRITICAL: only $rs() is tracked. resolve() and DOM mutations run
179
+ // inside runUntracked() to prevent subscribing to signals read by
180
+ // interpolation functions (theme properties, context getters, etc.).
181
+ // Without this, every styled component's effect subscribes to every
182
+ // signal touched during CSS resolution — causing an exponential
183
+ // cascade across 50+ components on any signal change.
167
184
  if (isReactiveRS) {
168
185
  effect(() => {
169
- const newRS = $rs() // reactive read tracks mode dependency
170
- const newResolvedProps = { ...rawProps, $rocketstyle: newRS }
171
- const newCss = normalizeCSS(resolve(strings, values, { ...newResolvedProps, theme }))
172
- const newClass = newCss.length > 0 ? sheet.insert(newCss, boost) : ''
173
-
174
- if (el && newClass !== currentClassName) {
175
- if (currentClassName) el.classList.remove(currentClassName)
176
- if (newClass) el.classList.add(newClass)
177
- currentClassName = newClass
178
- }
186
+ const newRS = $rs() // TRACKED: subscribes to mode + dimension signals
187
+ const newState = isReactiveState ? $rsState() : $rsState // TRACKED
188
+
189
+ runUntracked(() => {
190
+ // UNTRACKED: resolve + DOM mutation — no additional subscriptions
191
+ const newResolvedProps = {
192
+ ...rawProps,
193
+ $rocketstyle: newRS,
194
+ $rocketstate: newState,
195
+ }
196
+ const newCss = normalizeCSS(
197
+ resolve(strings, values, { ...newResolvedProps, theme }),
198
+ )
199
+ const newClass = newCss.length > 0 ? sheet.insert(newCss, boost) : ''
200
+
201
+ if (el && newClass !== currentClassName) {
202
+ if (currentClassName) el.classList.remove(currentClassName)
203
+ if (newClass) el.classList.add(newClass)
204
+ currentClassName = newClass
205
+ }
206
+ })
179
207
  })
180
208
  }
181
209