@pyreon/rocketstyle 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +117 -199
  2. package/package.json +9 -9
package/README.md CHANGED
@@ -1,36 +1,22 @@
1
1
  # @pyreon/rocketstyle
2
2
 
3
- Multi-dimensional styling system for Pyreon.
3
+ Multi-dimensional component styling states, sizes, variants, themes, light/dark, all cached.
4
4
 
5
- Organize component styles by dimensionsstates, sizes, variants — instead of flat props. Chain theme values, attach CSS via `@pyreon/styler`, and get full TypeScript inference. Built-in pseudo-state handling, light/dark mode, and provider/consumer patterns for parent-child state propagation.
5
+ `@pyreon/rocketstyle` is the styling layer Pyreon's UI system builds on. Organize styles by named DIMENSIONS `state` (`primary` / `danger` / `success`), `size` (`sm` / `md` / `lg`), `variant`, plus any custom dimension you declare — instead of flat boolean props. Each dimension is a chainable method (`.states({...})`, `.sizes({...})`); per-dimension values are themed via `.theme()` callbacks that receive `(theme, mode, css)`, with light/dark mode threaded through and pseudo-states (`hover` / `focus` / `pressed` / `active` / `disabled`) auto-detected. Built on `@pyreon/attrs` + `@pyreon/styler`. Per-definition WeakMap caches make per-mount cost near zero for same-definition components — verified 73% reduction in `styler.resolve` calls on real-app benchmarks.
6
6
 
7
- ## Features
8
-
9
- - **Dimension-based theming** — define style variations as named dimensions (states, sizes, variants)
10
- - **Immutable chaining** — `.attrs()`, `.theme()`, `.states()`, `.sizes()`, `.styles()` and more
11
- - **Boolean shorthand** — `Button({ primary: true, lg: true })` instead of `Button({ state: 'primary', size: 'lg' })`
12
- - **Pseudo-state detection** — hover, focus, pressed tracked via signals and context
13
- - **Light/dark mode** — theme callbacks receive a mode parameter
14
- - **Provider/Consumer** — propagate parent state to children through context
15
- - **Multi-tier WeakMap caching** — dimension maps, reserved keys, omit Sets, and theme results cached per component definition (shared across all instances). Per-mount allocations near zero for same-definition components
16
- - **TypeScript inference** — dimension values and prop types inferred through the chain
17
-
18
- ## Installation
7
+ ## Install
19
8
 
20
9
  ```bash
21
- bun add @pyreon/rocketstyle
10
+ bun add @pyreon/rocketstyle @pyreon/core @pyreon/reactivity @pyreon/ui-core @pyreon/styler
22
11
  ```
23
12
 
24
- ## Quick Start
13
+ ## Quick start
25
14
 
26
- ```ts
15
+ ```tsx
27
16
  import rocketstyle from '@pyreon/rocketstyle'
28
17
  import { Element } from '@pyreon/elements'
29
18
 
30
- const Button = rocketstyle()({
31
- name: 'Button',
32
- component: Element,
33
- })
19
+ const Button = rocketstyle()({ name: 'Button', component: Element })
34
20
  .attrs({ tag: 'button' })
35
21
  .theme({
36
22
  fontSize: 16,
@@ -39,238 +25,178 @@ const Button = rocketstyle()({
39
25
  borderRadius: 4,
40
26
  color: '#fff',
41
27
  backgroundColor: '#0d6efd',
42
- hover: {
43
- backgroundColor: '#0b5ed7',
44
- },
28
+ hover: { backgroundColor: '#0b5ed7' },
45
29
  })
46
30
  .states({
47
- primary: {
48
- backgroundColor: '#0d6efd',
49
- hover: { backgroundColor: '#0b5ed7' },
50
- },
51
- danger: {
52
- backgroundColor: '#dc3545',
53
- hover: { backgroundColor: '#bb2d3b' },
54
- },
55
- success: {
56
- backgroundColor: '#198754',
57
- hover: { backgroundColor: '#157347' },
58
- },
31
+ primary: { backgroundColor: '#0d6efd', hover: { backgroundColor: '#0b5ed7' } },
32
+ danger: { backgroundColor: '#dc3545', hover: { backgroundColor: '#bb2d3b' } },
33
+ success: { backgroundColor: '#198754', hover: { backgroundColor: '#157347' } },
59
34
  })
60
35
  .sizes({
61
36
  sm: { fontSize: 14, paddingX: 12, paddingY: 6 },
62
37
  md: { fontSize: 16, paddingX: 16, paddingY: 8 },
63
38
  lg: { fontSize: 18, paddingX: 20, paddingY: 10 },
64
39
  })
65
- ```
66
40
 
67
- ```ts
68
- // Named props
69
- Button({ state: 'danger', size: 'lg', label: 'Delete' })
70
-
71
- // Boolean shorthand (when useBooleans is enabled)
72
- Button({ danger: true, lg: true, label: 'Delete' })
41
+ <Button state="danger" size="lg">Delete</Button>
73
42
  ```
74
43
 
75
- ## Core Concepts
44
+ ## Core concepts
76
45
 
77
46
  ### Dimensions
78
47
 
79
- A dimension is a named axis of style variation. The factory ships with four defaults:
48
+ A dimension is a named axis of style variation. Defaults ship four:
80
49
 
81
- | Dimension | Prop name | Multi | Example |
82
- | ---------- | --------- | ----- | ------------------------------ |
83
- | `states` | `state` | no | `primary`, `danger`, `success` |
84
- | `sizes` | `size` | no | `sm`, `md`, `lg` |
85
- | `variants` | `variant` | no | `outlined`, `filled` |
86
- | `multiple` | — | yes | `rounded`, `shadow` |
50
+ | Dimension | Prop name | Multi? | Example |
51
+ | ---------- | --------- | ------ | ------------------------------ |
52
+ | `states` | `state` | no | `primary`, `danger`, `success` |
53
+ | `sizes` | `size` | no | `sm`, `md`, `lg` |
54
+ | `variants` | `variant` | no | `outlined`, `filled` |
55
+ | `multiple` | — | yes | `rounded`, `shadow` |
87
56
 
88
- Each dimension creates a chain method (`.states()`, `.sizes()`, etc.) and a corresponding prop on the component.
57
+ Each declared dimension creates a chain method AND a corresponding prop on the component. Multi-dimensions accept multiple active values at once.
89
58
 
90
- **Multi dimensions** allow multiple values at once: `Button({ rounded: true, shadow: true })`.
59
+ ### Default: `useBooleans: false` (string prop values)
91
60
 
92
- ### Theme Object
61
+ ```tsx
62
+ <Button state="primary" size="lg">Save</Button>
63
+ ```
93
64
 
94
- The `.theme()` method defines base CSS property values. Values are processed by `@pyreon/unistyle` — numbers convert to rem, shorthand properties expand automatically.
65
+ Boolean shorthand (`<Button primary lg>Save</Button>`) is opt-in via `rocketstyle({ useBooleans: true })`. **Important**: before April 2026 the type default was `true` but the runtime was `false` boolean props typechecked but were silently dropped at runtime. Fixed in `rocketstyle/init.ts`; new code should not rely on the historical behaviour.
95
66
 
96
- Pseudo-state keys nest directly in the theme object:
67
+ ### Theme + pseudo-states
97
68
 
98
69
  ```ts
99
70
  .theme({
100
71
  color: '#333',
101
72
  fontSize: 16,
102
- hover: { color: '#000' },
103
- focus: { outline: '2px solid blue' },
104
- active: { transform: 'scale(0.98)' },
73
+ hover: { color: '#000' },
74
+ focus: { outline: '2px solid blue' },
75
+ active: { transform: 'scale(0.98)' },
76
+ disabled: { opacity: 0.5 },
105
77
  })
106
78
  ```
107
79
 
108
- ### Styles Function
80
+ Pseudo-state keys nest directly. Bases (`@pyreon/elements`) generate `:hover` / `:focus-visible` / `:active` / `:disabled` CSS from the nested objects. `:hover` is unconditional — applied to EVERY component with hover theme; only `cursor: pointer` is gated on `onClick` / `href`.
109
81
 
110
- The `.styles()` method defines the CSS template that receives the computed theme:
82
+ ### Styles callback
111
83
 
112
84
  ```ts
113
85
  .styles((css) => css`
86
+ cursor: pointer;
87
+ border: none;
88
+ transition: all 0.2s;
89
+
114
90
  ${({ $rocketstyle, $rocketstate }) => {
115
- // $rocketstyle — computed theme values (base + active dimension values merged)
91
+ // $rocketstyle — computed theme (base + active dimension values merged)
116
92
  // $rocketstate — { hover, focus, pressed, active, disabled, pseudo }
117
- return css`...`
93
+ return /* css string */
118
94
  }}
119
95
  `)
120
96
  ```
121
97
 
98
+ `$rocketstyle` is identity-cached — same dimension-prop combo produces the same object identity, which lets the styler's `classCache` skip resolve work entirely on cache hits.
99
+
122
100
  ## API
123
101
 
124
- ### rocketstyle(options?)
102
+ ### `rocketstyle(options?)({ name, component })`
125
103
 
126
104
  Factory initializer. Returns a function that accepts component configuration.
127
105
 
128
106
  ```ts
129
107
  const factory = rocketstyle({
130
- dimensions: {
131
- /* custom dimensions */
132
- },
108
+ dimensions: { /* custom dimensions */ },
133
109
  useBooleans: true,
134
110
  })
135
111
 
136
- const Component = factory({
137
- name: 'ComponentName',
138
- component: BaseComponent,
139
- })
112
+ const Button = factory({ name: 'Button', component: Element })
140
113
  ```
141
114
 
142
- ### .attrs(props | callback, options?)
143
-
144
- Same API as `@pyreon/attrs`. Define default props with optional priority and filter.
115
+ ### `.attrs(props | callback, options?)`
145
116
 
146
- ```ts
147
- Button.attrs({ tag: 'button', role: 'button' })
148
- Button.attrs((props) => ({ 'aria-label': props.label }))
149
- ```
117
+ Same as `@pyreon/attrs` — accumulate defaults, supports callback / priority / filter.
150
118
 
151
- ### .theme(values | callback)
119
+ ### `.theme(values | callback)`
152
120
 
153
- Base theme values applied to every instance.
121
+ Base theme applied to every instance.
154
122
 
155
123
  ```ts
156
- // Object form
157
- Button.theme({
158
- fontSize: 16,
159
- color: '#fff',
160
- hover: { opacity: 0.9 },
161
- })
162
-
163
- // Callback form — receives the theme context and mode
164
- Button.theme((theme, mode, css) => ({
124
+ .theme({ fontSize: 16, color: '#fff', hover: { opacity: 0.9 } })
125
+ .theme((theme, mode, css) => ({
165
126
  fontSize: 16,
166
127
  color: mode === 'dark' ? '#fff' : '#333',
167
128
  }))
168
129
  ```
169
130
 
170
- ### .states() / .sizes() / .variants() / .multiple()
131
+ ### `.states()` / `.sizes()` / `.variants()` / `.multiple()`
171
132
 
172
- Define values for each dimension. Each key becomes a selectable option.
133
+ Define per-dimension values.
173
134
 
174
135
  ```ts
175
- Button.states({
176
- primary: { backgroundColor: '#0d6efd' },
177
- danger: { backgroundColor: '#dc3545' },
178
- })
179
-
180
- Button.sizes({
181
- sm: { fontSize: 14, paddingX: 8 },
182
- lg: { fontSize: 18, paddingX: 20 },
183
- })
136
+ .states({ primary: { backgroundColor: '#0d6efd' }, danger: { backgroundColor: '#dc3545' } })
137
+ .sizes({ sm: { fontSize: 14, paddingX: 8 }, lg: { fontSize: 18, paddingX: 20 } })
138
+ .multiple({ rounded: { borderRadius: 999 }, shadow: { boxShadow: '0 2px 8px rgba(0,0,0,0.15)' } })
184
139
 
185
- // Multi dimensionmultiple can be active at once
186
- Button.multiple({
187
- rounded: { borderRadius: 999 },
188
- shadow: { boxShadow: '0 2px 8px rgba(0,0,0,0.15)' },
189
- })
190
- ```
191
-
192
- Dimension methods also accept callbacks:
193
-
194
- ```ts
195
- Button.states((theme, mode, css) => ({
140
+ // Callback formreceives (theme, mode, css)
141
+ .states((theme) => ({
196
142
  primary: { backgroundColor: theme.colors?.primary ?? '#0d6efd' },
197
143
  }))
198
144
  ```
199
145
 
200
- ### .styles(callback)
146
+ ### `.styles(callback)`
201
147
 
202
- Define the CSS template using `@pyreon/styler`'s `css` tagged template.
148
+ CSS template using `@pyreon/styler`'s `css` tagged template.
203
149
 
204
- ```ts
205
- Button.styles(
206
- (css) => css`
207
- cursor: pointer;
208
- border: none;
209
- transition: all 0.2s;
210
-
211
- ${({ $rocketstyle }) => makeItResponsive({ theme: $rocketstyle, styles, css })}
212
- `,
213
- )
214
- ```
215
-
216
- ### .config(options)
217
-
218
- Reconfigure the component.
150
+ ### `.config(options)`
219
151
 
220
152
  ```ts
221
153
  Button.config({
222
- name: 'PrimaryButton', // change displayName
223
- component: NewBase, // swap base component
224
- provider: true, // make this component a context provider
225
- consumer: (ctx) => ..., // consume parent component context
226
- inversed: true, // invert theme mode
227
- DEBUG: true, // enable debug logging
154
+ name: 'PrimaryButton',
155
+ component: NewBase, // swap base — resets prop chains
156
+ provider: true, // make this a context provider for children
157
+ consumer: (ctx) => …, // consume parent component context
158
+ inversed: true, // invert theme mode for subtree
159
+ DEBUG: true,
228
160
  })
229
161
  ```
230
162
 
231
- ### .compose(hocs) / .statics(metadata)
232
-
233
- Same API as `@pyreon/attrs`:
234
-
235
- ```ts
236
- Button.compose({ withTracking: trackingHoc })
237
- Button.statics({ category: 'action' })
163
+ ### `.compose(hocs)` / `.statics(metadata)`
238
164
 
239
- Button.meta.category // => 'action'
240
- ```
165
+ Same API as `@pyreon/attrs`.
241
166
 
242
- ### isRocketComponent(value)
167
+ ### `isRocketComponent(value)` / `resolveTheme(value)`
243
168
 
244
- Runtime type guard.
169
+ Runtime guard and theme accessor for use inside styled-component interpolations:
245
170
 
246
171
  ```ts
247
- import { isRocketComponent } from '@pyreon/rocketstyle'
172
+ import { isRocketComponent, resolveTheme } from '@pyreon/rocketstyle'
173
+
174
+ isRocketComponent(Button) // true
248
175
 
249
- isRocketComponent(Button) // => true
176
+ styled(Component)`
177
+ color: ${(props) => resolveTheme(props.$rocketstyle).color};
178
+ `
250
179
  ```
251
180
 
252
- ## Custom Dimensions
181
+ `resolveTheme` handles both function-accessor (reactive) and plain-object `$rocketstyle` shapes.
253
182
 
254
- Define your own dimensions by passing them to the factory:
183
+ ## Custom dimensions
255
184
 
256
185
  ```ts
257
186
  const rocketButton = rocketstyle({
258
187
  dimensions: {
259
- intent: 'intent', // prop: intent="primary"
260
- size: 'size', // prop: size="lg"
261
- appearance: {
262
- propName: 'appearance',
263
- multi: true, // allows multiple values
264
- },
188
+ intent: 'intent', // prop: intent="primary"
189
+ size: 'size',
190
+ appearance: { propName: 'appearance', multi: true },
265
191
  },
266
192
  })
267
193
  ```
268
194
 
269
- This creates `.intent()`, `.size()`, and `.appearance()` chain methods.
195
+ Creates `.intent()`, `.size()`, `.appearance()` chain methods.
270
196
 
271
- ## Transform Dimensions
197
+ ### Transform dimensions
272
198
 
273
- Mark a dimension as `transform: true` to make its values receive the accumulated theme from all prior dimensions. This is ideal for modifiers like `outlined` that derive styles from the active state:
199
+ Mark `transform: true` to make a dimension receive the accumulated theme from all prior dimensions ideal for modifiers like `outlined` that derive from the active state.
274
200
 
275
201
  ```ts
276
202
  const rocketButton = rocketstyle({
@@ -282,51 +208,44 @@ const rocketButton = rocketstyle({
282
208
 
283
209
  const Button = rocketButton({ name: 'Button', component: Element })
284
210
  .theme({ backgroundColor: '#0d6efd', color: '#fff' })
285
- .states({
286
- danger: { backgroundColor: '#dc3545', color: '#fff' },
287
- })
211
+ .states({ danger: { backgroundColor: '#dc3545', color: '#fff' } })
288
212
  .modifiers({
289
213
  outlined: (theme) => ({
290
- color: theme.backgroundColor,
214
+ color: theme.backgroundColor, // receives merged theme from prior dimensions
291
215
  backgroundColor: 'transparent',
292
216
  }),
293
217
  })
294
218
 
295
- // outlined receives { backgroundColor: '#dc3545', color: '#fff' } from the danger state
296
- Button({ state: 'danger', modifier: 'outlined' })
219
+ <Button state="danger" modifier="outlined" /> // outlined sees danger's red, becomes red-on-transparent
297
220
  ```
298
221
 
299
- ## Provider / Consumer
300
-
301
- Propagate parent component state to children through Pyreon's context system.
222
+ ## Provider / Consumer — parent-child state propagation
302
223
 
303
224
  ```ts
304
225
  // Parent provides its state
305
226
  const ButtonGroup = Button.config({ provider: true })
306
227
 
307
228
  // Child consumes parent state
308
- const ButtonIcon = rocketstyle()({
309
- name: 'ButtonIcon',
310
- component: Element,
311
- })
229
+ const ButtonIcon = rocketstyle()({ name: 'ButtonIcon', component: Element })
312
230
  .config({
313
- consumer: (ctx) =>
314
- ctx(({ pseudo }) => ({
315
- state: pseudo.hover ? 'active' : 'default',
316
- })),
231
+ consumer: (ctx) => ctx(({ pseudo }) => ({
232
+ state: pseudo.hover ? 'active' : 'default',
233
+ })),
317
234
  })
318
235
  .states({
319
236
  default: { color: '#666' },
320
- active: { color: '#fff' },
237
+ active: { color: '#fff' },
321
238
  })
322
239
 
323
- // Icon reacts to parent's hover state
324
- ButtonGroup({ state: 'primary', children: [ButtonIcon({}), 'Label'] })
240
+ <ButtonGroup state="primary">
241
+ <ButtonIcon />
242
+ Label
243
+ </ButtonGroup>
325
244
  ```
326
245
 
327
- ## Light / Dark Mode
246
+ ## Light / dark mode
328
247
 
329
- Theme callbacks receive a `mode` parameter:
248
+ Theme + dimension callbacks receive `(theme, mode, css)`. `mode === 'light' | 'dark'`. Use `inversed: true` on `.config()` to flip the mode for a subtree.
330
249
 
331
250
  ```ts
332
251
  Button.theme((theme, mode) => ({
@@ -335,32 +254,31 @@ Button.theme((theme, mode) => ({
335
254
  }))
336
255
  ```
337
256
 
338
- Use `inversed: true` in `.config()` to flip the mode for a component subtree.
339
-
340
257
  ## Performance
341
258
 
342
- Rocketstyle uses a multi-tier caching architecture to minimize per-mount allocations:
259
+ Per-definition WeakMap caches keep per-mount cost flat as instance count grows:
260
+
261
+ - **`_dimensionsCache`** — `getDimensionsMap` result keyed on dimension-themes identity
262
+ - **`_reservedKeysCache`** — `Object.keys(reservedPropNames)` keyed on keywords identity
263
+ - **`_omitSetCache`** — pre-built `Set<string>` for `omit()` (avoids per-mount Set allocation)
264
+ - **`LocalThemeManager`** — WeakMap tiers for baseTheme, dimensionThemes, and per-mode resolved themes
265
+ - **`_rsMemo`** — dimension-prop memo keyed by `mode|dimensionPropTuple|pseudoState`, LRU-bounded at 32 entries per theme. Hit returns identity-stable `{ rocketstyle, rocketstate }` so the downstream styler `classCache` skips resolve entirely. Real-app E2 benchmark: 200 Buttons × 5 runs, baseline dropped from 8.80ms to 4.80ms (-45%); per-Button `styler.resolve` from 22 to 6 (-73%).
343
266
 
344
- - **Per-definition caches** (shared across all instances via `WeakMap`):
345
- - `_dimensionsCache` — `getDimensionsMap` result keyed on dimension-themes identity
346
- - `_reservedKeysCache` — `Object.keys(reservedPropNames)` keyed on keywords identity
347
- - `_omitSetCache` — pre-built `Set<string>` for `omit()` (avoids per-mount Set construction)
348
- - `ALL_PSEUDO_KEYS` / `STATIC_OMIT_KEYS` — merged key arrays computed once
349
- - **Theme cache** (`LocalThemeManager`): `WeakMap` tiers for baseTheme, dimensionThemes, and per-mode resolved themes
350
- - **getTheme in-place merge**: dimension slices merged directly onto `finalTheme` instead of allocating a new target per `merge()` call
351
- - **Frozen `EMPTY_PSEUDO`**: shared frozen `{}` for pseudo-state defaults instead of 6 allocations per call
352
- - **Dev guard**: uses `__DEV__` (`import.meta.env.DEV`) — tree-shaken to zero bytes in production
267
+ Real apps MUST mount one shared `<PyreonUI>` provider for the memo to span instances — each provider mount creates a fresh `enrichedTheme` via `computed()`, which produces a different WeakMap key.
353
268
 
354
269
  For a 150-component page with 8 dimensions each: ~1,350 Set allocations, ~300 array spreads, and ~150 map rebuilds eliminated vs naive implementation.
355
270
 
356
- ## Peer Dependencies
271
+ ## Gotchas
272
+
273
+ - **`.config({ component: NewBase })` resets `attrs` / `priorityAttrs` / `filterAttrs` / `compose` chains** — they were tailored to the previous component's prop shape. `theme` / `styles` / dimension chains are preserved. Re-chain shared attrs explicitly if you swap the base.
274
+ - **`useBooleans: false` is the default** (since April 2026 alignment fix). String props are the idiomatic surface.
275
+ - **Cache keys are downstream of normalization.** Under `useBooleans: true`, the memo correctly keys by the resolved dimension (not the raw boolean prop) — otherwise every boolean variant would collide on the first cached entry.
276
+ - **Dimension props don't accept function accessors directly.** `state={() => signal()}` is wrong — write `state={signal()}` and let the compiler emit reactive `_rp()` wrapping. Caught by the Reactivity Lens.
277
+ - **`provider: true` + `consumer:` on the same component** is a legal but rare shape. Most apps separate the two for clarity.
278
+
279
+ ## Documentation
357
280
 
358
- | Package | Version |
359
- | ------------------ | ------- |
360
- | @pyreon/core | \* |
361
- | @pyreon/reactivity | \* |
362
- | @pyreon/ui-core | \* |
363
- | @pyreon/styler | \* |
281
+ Full docs: [docs.pyreon.dev/docs/rocketstyle](https://docs.pyreon.dev/docs/rocketstyle) (or `docs/docs/rocketstyle.md` in this repo).
364
282
 
365
283
  ## License
366
284
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/rocketstyle",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Multi-dimensional style composition for Pyreon components",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,19 +42,19 @@
42
42
  "typecheck": "tsc --noEmit"
43
43
  },
44
44
  "devDependencies": {
45
- "@pyreon/test-utils": "^0.13.9",
46
- "@pyreon/typescript": "^0.22.0",
47
- "@pyreon/ui-core": "^0.22.0",
45
+ "@pyreon/test-utils": "^0.13.10",
46
+ "@pyreon/typescript": "^0.23.0",
47
+ "@pyreon/ui-core": "^0.23.0",
48
48
  "@vitest/browser-playwright": "^4.1.4",
49
- "@vitus-labs/tools-rolldown": "^2.3.0"
49
+ "@vitus-labs/tools-rolldown": "^2.4.0"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">= 22"
53
53
  },
54
54
  "dependencies": {
55
- "@pyreon/core": "^0.22.0",
56
- "@pyreon/reactivity": "^0.22.0",
57
- "@pyreon/styler": "^0.22.0",
58
- "@pyreon/ui-core": "^0.22.0"
55
+ "@pyreon/core": "^0.23.0",
56
+ "@pyreon/reactivity": "^0.23.0",
57
+ "@pyreon/styler": "^0.23.0",
58
+ "@pyreon/ui-core": "^0.23.0"
59
59
  }
60
60
  }