@arcanejs/react-toolkit 0.12.4 → 0.13.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.
package/README.md CHANGED
@@ -2,309 +2,389 @@
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/%40arcanejs%2Freact-toolkit)](https://www.npmjs.com/package/@arcanejs/react-toolkit)
4
4
 
5
- `@arcanejs/react-toolkit` Allows you to quickly create real-time control panels
6
- for your single-process Node.js apps,
7
- using a custom react renderer, and WebSockets.
5
+ React renderer for ArcaneJS server-side control panels.
8
6
 
9
- Control panels can be accessed by any number of
10
- browsers / devices / clients simultaneously,
11
- and changes caused by any client will be immediately propagated to all other
12
- clients.
13
-
14
- The UI has also been designed primarily with touch devices in mind,
15
- but also works well with a cursor and keyboard.
7
+ This package lets you build toolkit component trees using React state/hooks on the server, then synchronize them to connected browser clients in real time.
16
8
 
17
9
  <p align="center">
18
10
  <img src="https://raw.githubusercontent.com/ArcaneWizards/arcanejs/main/packages/react-toolkit/docs/architecture.svg" alt="Architecture Diagram">
19
11
  </p>
20
12
 
21
- ## What
13
+ ## Why Use `@arcanejs/react-toolkit`
22
14
 
23
- - Easily create controller UIs for Node.js processes
15
+ This package is useful when you want a control panel for a long-running Node.js process without building a full web app stack.
24
16
 
25
- - Uses server-side **React** for state management and UI composition
17
+ It gives you:
26
18
 
27
- - This is not SSR, you can use `useState()` hooks etc...
19
+ - server-side React state/hooks for control logic
20
+ - realtime multi-client sync over WebSockets
21
+ - a ready set of control-oriented UI components (switches, sliders, groups, tabs, timelines)
22
+ - an extension path for custom components when core components are not enough
28
23
 
29
- - Instantly updates all clients using WebSockets
24
+ Typical use cases:
30
25
 
31
- - Collection of 9+ components to build your UIs
26
+ - home/lab automation control surfaces
27
+ - AV/lighting/operations dashboards on a local network
28
+ - internal tooling for stateful services/scripts that need live operator controls
32
29
 
33
- ## Why
30
+ ## When It Fits (And When It Doesn't)
34
31
 
35
- Sometimes you're working on relatively simple local applications or scripts,
36
- and would like to have a way to interact with the state or configuration
37
- of these applications in real-time,
38
- for example:
32
+ Good fit:
39
33
 
40
- - Lighting control or AV systems
41
- - Home-Automation or Office building management and operation
34
+ - single-process Node.js apps with in-memory state
35
+ - trusted/internal networks where operators need live controls
36
+ - projects where React composition is preferred over manual tree mutation
42
37
 
43
- ### Why Not
38
+ Not a fit:
44
39
 
45
- This project is not designed to be a general-purpose application framework,
46
- in particular, it's not suitable for any project / application that:
40
+ - internet-exposed apps requiring built-in auth/authz
41
+ - horizontally scaled/multi-process architectures needing shared state coordination
42
+ - general-purpose public web apps that need standard React DOM/SSR patterns
47
43
 
48
- - Needs to scale beyond a single Node.js process
49
- - Is stateless _(It's explicitly designed to manage in-memory state)_
50
- - Will be exposed over the internet _(no authentication has been implemented)_
44
+ ## Install
51
45
 
52
- ## Usage
46
+ ```bash
47
+ npm install react@^19.2.0 @arcanejs/toolkit @arcanejs/react-toolkit
48
+ ```
53
49
 
54
- Install the following packages:
50
+ Version compatibility:
55
51
 
56
- ```
57
- npm install --save react@^18 @arcanejs/toolkit @arcanejs/react-toolkit
58
- ```
52
+ - `@arcanejs/react-toolkit` is tested against React 19 and `react-reconciler` 0.33.x.
59
53
 
60
- Note:
54
+ Optional helper dependencies:
61
55
 
62
- - We explicitly require `react` version 18
63
- - We don't need `react-dom` or any react native libraries,
64
- `@arcanejs/react-toolkit` is the react renderer.
56
+ - `zod` is required if you use `@arcanejs/react-toolkit/data`
65
57
 
66
- Then you can then create control panels using react to manage the
67
- server-side state like this:
58
+ ## Quick Start
68
59
 
69
- ```ts
60
+ ```tsx
70
61
  import { useState } from 'react';
71
62
  import { Toolkit } from '@arcanejs/toolkit';
72
- import { ToolkitRenderer, Group, Switch, SliderButton } from '@arcanejs/react-toolkit';
63
+ import {
64
+ ToolkitRenderer,
65
+ Group,
66
+ Switch,
67
+ SliderButton,
68
+ } from '@arcanejs/react-toolkit';
73
69
 
74
70
  const toolkit = new Toolkit();
71
+ toolkit.start({ mode: 'automatic', port: 3000 });
75
72
 
76
- // Expose the toolkit control panel on HTTP port 3000
77
- // Navigate to http://localhost:3000 to access the control panel
78
- // this will be printed in your console
79
- toolkit.start({
80
- mode: 'automatic',
81
- port: 3000,
82
- });
83
-
84
- const ControlPanel = () => {
85
- const [switchState, setSwitchState] = useState<'off' | 'on'>('off');
86
- const [sliderValue, setSliderValue] = useState(50);
73
+ function App() {
74
+ const [enabled, setEnabled] = useState<'on' | 'off'>('off');
75
+ const [level, setLevel] = useState(50);
87
76
 
88
77
  return (
89
- <Group direction='vertical'>
78
+ <Group direction="vertical" title="Controller">
90
79
  <Group>
91
- {`Switch State: ${switchState}`}
92
- <Switch
93
- value={switchState}
94
- onChange={setSwitchState}
95
- />
80
+ {`Enabled: ${enabled}`}
81
+ <Switch value={enabled} onChange={setEnabled} />
96
82
  </Group>
97
83
  <Group>
98
- {`Slider Value: ${sliderValue}`}
99
- <SliderButton
100
- value={sliderValue}
101
- onChange={setSliderValue}
102
- min={0}
103
- max={100}
104
- />
84
+ {`Level: ${level}`}
85
+ <SliderButton value={level} onChange={setLevel} min={0} max={100} />
105
86
  </Group>
106
87
  </Group>
107
88
  );
108
- };
89
+ }
109
90
 
110
- // Start rendering the control panel with @arcanejs/react-toolkit
111
- ToolkitRenderer.render(<ControlPanel />, toolkit);
91
+ ToolkitRenderer.render(<App />, toolkit);
112
92
  ```
113
93
 
114
- You would then be able to access the following control panel
115
- from [localhost:3000](http://localhost:3000):
94
+ ## Core Exports
116
95
 
117
- ![Control Panel Screenshot](https://raw.githubusercontent.com/ArcaneWizards/arcanejs/main/packages/react-toolkit/docs/example-controller.png)
96
+ ### From `@arcanejs/react-toolkit`
118
97
 
119
- Please note:
98
+ - `ToolkitRenderer`
99
+ - `render(element, toolkit, rootGroupProps?, config?)`
100
+ - `renderGroup(element, group, config?)`
101
+ - Core React components:
102
+ - `Button`, `Group`, `GroupHeader`, `Label`, `Rect`, `SliderButton`, `Switch`, `Tab`, `Tabs`, `TextInput`, `Timeline`
103
+ - Extension helpers:
104
+ - `prepareComponents(namespace, components)`
105
+ - `CoreComponents`
120
106
 
121
- - You can not use normal `react-dom` / HTML elements in these applications
122
- or components, only `@arcanejs` components are supported.
107
+ Core component props/events map directly to the corresponding classes in `@arcanejs/toolkit`.
123
108
 
124
- - You are welcome to abstract / componentize your application as you like,
125
- in the same manner that you would any `react-dom` or `react-native` project.
109
+ ## Core Component API
126
110
 
127
- _See the [counter example](https://github.com/ArcaneWizards/arcanejs/blob/main/examples/react/src/counter.tsx)._
111
+ These are the React components most users consume directly from `@arcanejs/react-toolkit`.
128
112
 
129
- - This react / component-tree / state is managed server-side,
130
- and does not accurately represent the HTML used on the frontend.
131
- Your `@arcanejs` tree is converted to a JSON representation,
132
- and then sent to clients / browsers over a WebSocket.
133
- There is then a separate `react-dom` application
134
- that is loaded in the browser,
135
- and then used to render the JSON representation of the `@arcanejs` tree.
136
-
137
- - It's possible to define your own custom components,
138
- however this functionality is not documented.
139
-
140
- You can see code examples of this functionality here in the
141
- [custom components example app](https://github.com/ArcaneWizards/arcanejs/tree/main/examples/custom-components).
113
+ ### `Button`
142
114
 
143
- ## Components
115
+ Props:
144
116
 
145
- For full example usage all of our components in applications that are
146
- ready-to-run, we recommend that you check-out the
147
- [examples directory](https://github.com/ArcaneWizards/arcanejs/tree/main/examples/react).
117
+ - `text?: string | null`
118
+ - `icon?: string | null` (Material Symbols Outlined icon name)
119
+ - `mode?: 'normal' | 'pressed'`
120
+ - `error?: string | null`
121
+ - `onClick?: (connection) => void | Promise<void>`
148
122
 
149
- ### `Button`
123
+ Notes:
150
124
 
151
- **Properties:**
125
+ - `onClick` uses request/response semantics and can be async.
126
+ - Throwing (or rejecting) in `onClick` surfaces an error state in the UI.
152
127
 
153
- - `text: string` (optional)
128
+ ```tsx
129
+ <Button
130
+ text="Run"
131
+ icon="play_arrow"
132
+ onClick={async () => {
133
+ await runTask();
134
+ }}
135
+ />
136
+ ```
154
137
 
155
- Text to display on the button
138
+ ### `Group`
156
139
 
157
- - `icon: string` (optional)
140
+ Props:
158
141
 
159
- In icon name from [Material Icons](https://fonts.google.com/icons) to include
160
- on the button.
142
+ - `direction?: 'horizontal' | 'vertical'`
143
+ - `wrap?: boolean`
144
+ - `border?: true`
145
+ - `title?: string | null`
146
+ - `labels?: Array<{ text: string }> | null`
147
+ - `editableTitle?: boolean`
148
+ - `defaultCollapsibleState?: 'open' | 'closed' | 'auto'`
149
+ - `onTitleChanged?: (title, connection) => void`
161
150
 
162
- - `error: string` (optional)
151
+ Use `Group` as the primary layout primitive and nest groups freely.
163
152
 
164
- When set, highlight the button in a way to indicate an error,
165
- and expose the given text as a tooltip upon user hover.
153
+ ```tsx
154
+ <Group
155
+ direction="vertical"
156
+ title="Fixture Settings"
157
+ border
158
+ editableTitle
159
+ onTitleChanged={(title) => setPanelTitle(title)}
160
+ >
161
+ <Label text="Master Intensity" />
162
+ <SliderButton value={master} min={0} max={100} onChange={setMaster} />
163
+ </Group>
164
+ ```
166
165
 
167
- - `mode: 'normal' | 'pressed'` (default: `'normal'`)
166
+ ### `GroupHeader`
168
167
 
169
- Should the button display as pressed or not.
168
+ `GroupHeader` lets you place controls in a group's header area.
170
169
 
171
- - `onClick: () => void | Promise<void>`
170
+ ```tsx
171
+ <Group title="Playlist">
172
+ <GroupHeader>
173
+ <Button text="Add" onClick={addItem} />
174
+ <Button text="Shuffle" onClick={shuffle} />
175
+ </GroupHeader>
176
+ <Label text="Current Queue" />
177
+ </Group>
178
+ ```
172
179
 
173
- Set an event listener for when the button is pressed.
180
+ ### `Label`
174
181
 
175
- The listener can throw an exception, or return a promise that rejects,
176
- to indicate an error and propagate an error message to the user,
177
- similar to setting the `error` property.
182
+ Props:
178
183
 
179
- e.g.:
184
+ - `text: string | null`
185
+ - `bold?: boolean`
180
186
 
181
187
  ```tsx
182
- const MyComponent = () => (
183
- <Button text="Stop" onClick={() => doAThing()} icon="close" />
184
- );
188
+ <Label text={`Connected: ${isConnected ? 'yes' : 'no'}`} bold />
185
189
  ```
186
190
 
187
- ### `Group`
191
+ ### `Rect`
192
+
193
+ Props:
188
194
 
189
- This component is the primary building block when it comes to creating layouts,
190
- you generally have many groups,
191
- and nest them to achieve the desired layout.
195
+ - `color?: string`
196
+ - `grow?: boolean`
192
197
 
193
- You can think of a group as similar to a `<div>` or `<section>` in HTML.
198
+ Useful for color/state swatches.
199
+
200
+ ```tsx
201
+ <Group>
202
+ <Label text="Current Color" />
203
+ <Rect color={`hsl(${hue}deg 100% 50%)`} grow />
204
+ </Group>
205
+ ```
194
206
 
195
- **Properties:**
207
+ ### `SliderButton`
196
208
 
197
- - `direction: 'horizontal' | 'vertical'` (default: `'horizontal'`)
209
+ Props:
198
210
 
199
- Whether to arrange the children of this group in a row or column.
211
+ - `value: number` (required)
212
+ - `min?: number` (default `0`)
213
+ - `max?: number` (default `255`)
214
+ - `step?: number` (default `5`)
215
+ - `defaultValue?: number` (for uncontrolled style workflows)
216
+ - `gradient?: Array<{ color: string; position: number }>`
217
+ - `grow?: boolean`
218
+ - `onChange?: (value, connection) => void | Promise<void>`
200
219
 
201
- - `wrap: boolean` (default: false)
220
+ ```tsx
221
+ <SliderButton
222
+ value={temperature}
223
+ min={2700}
224
+ max={6500}
225
+ step={100}
226
+ onChange={setTemperature}
227
+ />
228
+ ```
202
229
 
203
- If true, when the group runs out of vertical or horizontal space, child
204
- components will be wrapped, and start to be arranged on additional columns
205
- or rows.
230
+ ### `Switch`
206
231
 
207
- - `border: boolean` (default: false)
232
+ Props:
208
233
 
209
- If true, this group will have a border and a different color background
210
- to its parent.
234
+ - `value?: 'on' | 'off'`
235
+ - `defaultValue?: 'on' | 'off'`
236
+ - `onChange?: (state, connection) => void | Promise<void>`
211
237
 
212
- This allows you to add a distinctive border between components,
213
- without needing to set a header, add header components,
214
- or make it collapsible.
238
+ ```tsx
239
+ <Switch value={enabled} onChange={setEnabled} />
240
+ ```
215
241
 
216
- - `title: string` (optional)
242
+ ### `Tabs` and `Tab`
217
243
 
218
- If set, will display a title as a header at the top of the group.
244
+ `Tabs` only accepts `Tab` children. Each `Tab` should contain one child component subtree.
219
245
 
220
- - `editableTitle: boolean` (default: false)
246
+ ```tsx
247
+ <Tabs>
248
+ <Tab name="Input">
249
+ <Group>
250
+ <TextInput value={input} onChange={setInput} />
251
+ </Group>
252
+ </Tab>
253
+ <Tab name="Output">
254
+ <Group>
255
+ <Label text={output} />
256
+ </Group>
257
+ </Tab>
258
+ </Tabs>
259
+ ```
221
260
 
222
- If true,
223
- will allow the user to click on the title to change it,
224
- which will trigger a callback to the listener `onTitleChanged`.
261
+ ### `TextInput`
225
262
 
226
- - `defaultCollapsibleState: 'open' | 'closed' | 'auto'`
227
- (optional, default: `undefined`)
263
+ Props:
228
264
 
229
- If set,
230
- will allow the user to expand / collapse the given group,
231
- by default set to the given state.
265
+ - `value?: string | null`
266
+ - `onChange?: (value, connection) => void | Promise<void>`
232
267
 
233
- Whether a group is open or closed is independent on a per-client basis,
234
- and a fresh page reload will set the collapsible state to the default set here.
268
+ ```tsx
269
+ <TextInput value={name} onChange={setName} />
270
+ ```
235
271
 
236
- - `labels: { text: string }[] | null` (default: null)
272
+ ### `Timeline`
237
273
 
238
- Adds labels next to the title in the group header.
274
+ Props:
239
275
 
240
- **Special Child Components**
276
+ - `state?`:
277
+ - `{ state: 'playing'; totalTimeMillis; effectiveStartTime; speed }`
278
+ - `{ state: 'stopped'; totalTimeMillis; currentTimeMillis }`
279
+ - `title?: string | null`
280
+ - `subtitles?: string[] | null`
281
+ - `source?: { name: string } | null`
241
282
 
242
- - `GroupHeader`
283
+ ```tsx
284
+ <Timeline
285
+ title="Show Timeline"
286
+ subtitles={[`Cue ${cue}`, `BPM ${bpm}`]}
287
+ source={{ name: activeTrack }}
288
+ state={
289
+ playing
290
+ ? {
291
+ state: 'playing',
292
+ totalTimeMillis: duration,
293
+ effectiveStartTime: startedAt,
294
+ speed: 1,
295
+ }
296
+ : {
297
+ state: 'stopped',
298
+ totalTimeMillis: duration,
299
+ currentTimeMillis: pausedAt,
300
+ }
301
+ }
302
+ />
303
+ ```
243
304
 
244
- You can add components to the header of a group by wrapping them in a
245
- `<GroupHeader/>` component directly under the `<Group/>`.
305
+ ## Helper Modules
246
306
 
247
- You can add as many separate `GroupHeader` components as needed throughout
248
- a `<Group>` component's direct children,
249
- and all nested components will be placed in the header.
307
+ ### `@arcanejs/react-toolkit/connections`
250
308
 
251
- Currently `GroupHeader` only supports rendering the following children:
309
+ Connection-awareness for server-side React trees:
252
310
 
253
- - `Button`
311
+ - `ConnectionsContext`
312
+ - `ConnectionsContextProvider`
254
313
 
255
- TODO: example
314
+ Use this to render connection-specific UI or track per-connection state.
256
315
 
257
- ### `Label`
316
+ ### `@arcanejs/react-toolkit/data`
258
317
 
259
- TODO
318
+ JSON file persistence helpers backed by Zod validation:
260
319
 
261
- ### `Rect`
320
+ - `createDataFileDefinition`
321
+ - `useDataFileContext`
322
+ - `useDataFileData`
323
+ - `useDataFileUpdater`
324
+ - `useDataFile`
325
+ - `useDataFileCore`
262
326
 
263
- TODO
327
+ Supports:
264
328
 
265
- ### `SliderButton`
329
+ - lazy file creation with defaults
330
+ - schema validation on load
331
+ - throttled disk writes
332
+ - path switching behavior (`onPathChange: 'transfer' | 'defaultValue'`)
266
333
 
267
- TODO
334
+ ### `@arcanejs/react-toolkit/colors`
268
335
 
269
- ### `Switch`
336
+ - `HslColor` type
337
+ - `HslColorPicker` component
270
338
 
271
- TODO
339
+ ### `@arcanejs/react-toolkit/logging`
272
340
 
273
- ### `Tabs`
341
+ - `LoggerContext`
342
+ - `useLogger()`
274
343
 
275
- TODO
344
+ ## Custom Component Namespaces
276
345
 
277
- ### `TextInput`
346
+ Use `prepareComponents(...)` + `ToolkitRenderer` config to add custom namespaces:
278
347
 
279
- TODO
348
+ ```tsx
349
+ import {
350
+ prepareComponents,
351
+ CoreComponents,
352
+ ToolkitRenderer,
353
+ } from '@arcanejs/react-toolkit';
354
+
355
+ const Custom = prepareComponents('custom', {
356
+ MyComponent,
357
+ });
280
358
 
281
- ### `Timeline`
359
+ ToolkitRenderer.render(
360
+ <App />,
361
+ toolkit,
362
+ {},
363
+ {
364
+ componentNamespaces: [CoreComponents, Custom],
365
+ },
366
+ );
367
+ ```
282
368
 
283
- TODO
369
+ You must also implement matching protocol/backend/frontend layers. See:
284
370
 
285
- ## [Examples](https://github.com/ArcaneWizards/arcanejs/tree/main/examples/react)
371
+ - <https://github.com/ArcaneWizards/arcanejs/tree/main/examples/custom-components>
286
372
 
287
- For a comprehensive list of examples,
288
- please see the example directory in the arcane monorepo:
289
- <https://github.com/ArcaneWizards/arcanejs/tree/main/examples/react>
373
+ ## Important Constraints
290
374
 
291
- ### [Example Philips Hue App](https://github.com/arcanejs/hue-example)
375
+ - This is a custom renderer, not React DOM. Standard HTML elements are not supported.
376
+ - React state/hooks run on the server process.
377
+ - Toolkit root can only be set once.
378
+ - Architecture is single-process and intentionally stateful.
379
+ - No built-in authentication/authorization.
292
380
 
293
- Check out this example repository that uses `@arcanejs/react-toolkit`
294
- to create an app that can be used to control a Philips Hue Bridge
295
- on your local network.
381
+ ## Stability / Suitability
296
382
 
297
- ## Status / Suitability / Security Disclaimer
383
+ ArcaneJS uses `react-reconciler` APIs and is considered experimental. It is best suited for trusted-network/internal control applications.
298
384
 
299
- This project is **experimental**,
300
- and takes advantage of unstable `react` APIs exposed via `react-render`.
301
- It's not suitable for production or commercial projects yet,
302
- especially those that rely on regular updates of dependencies
303
- for security reasons,
304
- as usage of this project may make it difficult to keep `react` up-to-date
305
- (that being said, the license does not prohibit this,
306
- so feel free to at-your-own-risk).
385
+ ## Examples
307
386
 
308
- There are also no authentication mechanisms implemented yet,
309
- so be careful when exposing your control panels over the network,
310
- as this will allow anyone to interact with your processes.
387
+ - React examples: <https://github.com/ArcaneWizards/arcanejs/tree/main/examples/react>
388
+ - Main readme example: <https://github.com/ArcaneWizards/arcanejs/blob/main/examples/react/src/readme.tsx>
389
+ - Connections example: <https://github.com/ArcaneWizards/arcanejs/blob/main/examples/react/src/connections.tsx>
390
+ - Data file example: <https://github.com/ArcaneWizards/arcanejs/blob/main/examples/react/src/data-file.tsx>
@@ -4,12 +4,13 @@ var _chunkRT2VSMJLjs = require('./chunk-RT2VSMJL.js');
4
4
 
5
5
  // src/index.tsx
6
6
  var _reactreconciler = require('react-reconciler'); var _reactreconciler2 = _interopRequireDefault(_reactreconciler);
7
+ var _react = require('react'); var _react2 = _interopRequireDefault(_react);
7
8
  var _constants = require('react-reconciler/constants');
8
9
  var _toolkit = require('@arcanejs/toolkit'); var ld = _interopRequireWildcard(_toolkit);
9
10
  var _base = require('@arcanejs/toolkit/components/base');
10
11
 
11
12
  // src/registry.ts
12
- var _react = require('react'); var _react2 = _interopRequireDefault(_react);
13
+
13
14
  var prepareComponents = (namespace, defn) => {
14
15
  const entries = Object.entries(defn);
15
16
  const _creators = entries.reduce((acc, [key, cls]) => {
@@ -67,9 +68,48 @@ var CoreComponents = prepareComponents("core", {
67
68
  // src/index.tsx
68
69
  var _jsxruntime = require('react/jsx-runtime');
69
70
  var canSetProps = (instance) => instance instanceof _base.Base;
70
- var hostConfig = ({
71
- componentNamespaces
72
- }) => {
71
+ var getPropsToSet = (props) => {
72
+ const updates = {};
73
+ for (const [key, val] of Object.entries(props)) {
74
+ if (key !== "children") {
75
+ updates[key] = val;
76
+ }
77
+ }
78
+ return updates;
79
+ };
80
+ var setInstanceProps = (instance, props) => {
81
+ if (canSetProps(instance)) {
82
+ instance.setProps(props);
83
+ } else {
84
+ throw new Error(`Unexpected Instance: ${instance}`);
85
+ }
86
+ };
87
+ var scheduleMicrotaskCompat = typeof queueMicrotask === "function" ? queueMicrotask : (cb) => {
88
+ Promise.resolve().then(cb);
89
+ };
90
+ var reportRendererError = (error) => {
91
+ console.error(error);
92
+ };
93
+ var createContainerCompat = (reconciler, container) => {
94
+ const createContainer = reconciler.createContainer;
95
+ if (createContainer.length <= 4) {
96
+ return createContainer(container, 0, false, null);
97
+ }
98
+ return createContainer(
99
+ container,
100
+ 0,
101
+ null,
102
+ false,
103
+ null,
104
+ "",
105
+ reportRendererError,
106
+ reportRendererError,
107
+ reportRendererError,
108
+ null
109
+ );
110
+ };
111
+ var ROOT_HOST_CONTEXT = {};
112
+ var hostConfig = ({ componentNamespaces }) => {
73
113
  const processedNamespaces = {};
74
114
  for (const namespace of componentNamespaces) {
75
115
  if (processedNamespaces[namespace._namespace]) {
@@ -77,12 +117,17 @@ var hostConfig = ({
77
117
  }
78
118
  processedNamespaces[namespace._namespace] = namespace;
79
119
  }
80
- return {
120
+ const hostTransitionContext = _react2.default.createContext(null);
121
+ let currentUpdatePriority = _constants.DefaultEventPriority;
122
+ const config = {
81
123
  supportsMutation: true,
82
124
  supportsPersistence: false,
83
125
  noTimeout: -1,
84
126
  isPrimaryRenderer: true,
85
127
  supportsHydration: false,
128
+ supportsMicrotasks: true,
129
+ NotPendingTransition: null,
130
+ HostTransitionContext: hostTransitionContext,
86
131
  afterActiveInstanceBlur: () => null,
87
132
  appendChild: (parentInstance, child) => {
88
133
  if (parentInstance instanceof _base.BaseParent) {
@@ -104,14 +149,23 @@ var hostConfig = ({
104
149
  beforeActiveInstanceBlur: () => null,
105
150
  cancelTimeout: (id) => clearTimeout(id),
106
151
  clearContainer: (container) => container.removeAllChildren(),
107
- commitMount: () => {
152
+ commitMount: (_instance, _type, _props) => {
108
153
  throw new Error(`Unexpected call to commitMount()`);
109
154
  },
110
- commitUpdate(instance, updatePayload, _type, _prevProps, _nextProps, _internalHandle) {
111
- if (canSetProps(instance)) {
112
- instance.setProps(updatePayload);
113
- } else {
114
- throw new Error(`Unexpected Instance: ${instance}`);
155
+ commitUpdate(instance, ...args) {
156
+ if (typeof args[0] === "string") {
157
+ const nextProps2 = args[2];
158
+ setInstanceProps(instance, getPropsToSet(nextProps2));
159
+ return;
160
+ }
161
+ const updatePayload = args[0];
162
+ if (updatePayload) {
163
+ setInstanceProps(instance, updatePayload);
164
+ return;
165
+ }
166
+ const nextProps = args[3];
167
+ if (nextProps) {
168
+ setInstanceProps(instance, getPropsToSet(nextProps));
115
169
  }
116
170
  },
117
171
  commitTextUpdate: (textInstance, _oldText, newText) => textInstance.setText(newText),
@@ -137,6 +191,7 @@ var hostConfig = ({
137
191
  detachDeletedInstance: () => null,
138
192
  getChildHostContext: (parentHostContext) => parentHostContext,
139
193
  getCurrentEventPriority: () => _constants.DefaultEventPriority,
194
+ getCurrentUpdatePriority: () => currentUpdatePriority,
140
195
  getInstanceFromNode: () => {
141
196
  throw new Error("Not yet implemented.");
142
197
  },
@@ -144,7 +199,7 @@ var hostConfig = ({
144
199
  throw new Error("Not yet implemented.");
145
200
  },
146
201
  getPublicInstance: (instance) => instance,
147
- getRootHostContext: () => null,
202
+ getRootHostContext: () => ROOT_HOST_CONTEXT,
148
203
  insertBefore: (parentInstance, child, beforeChild) => {
149
204
  if (parentInstance instanceof _base.BaseParent) {
150
205
  parentInstance.insertBefore(child, beforeChild);
@@ -154,21 +209,17 @@ var hostConfig = ({
154
209
  },
155
210
  insertInContainerBefore: (container, child, beforeChild) => container.insertBefore(child, beforeChild),
156
211
  finalizeInitialChildren: () => false,
212
+ maySuspendCommit: () => false,
213
+ preloadInstance: () => false,
157
214
  prepareForCommit: () => null,
158
215
  preparePortalMount: () => null,
159
216
  prepareScopeUpdate: () => null,
160
217
  prepareUpdate: (_instance, _type, _oldProps, newProps, _rootContainer, _hostContext) => {
161
- const updates = {};
162
- for (const [key, val] of Object.entries(newProps)) {
163
- if (key !== "children") {
164
- updates[key] = val;
165
- }
166
- }
167
- if (Object.keys(updates).length) {
168
- return updates;
169
- } else {
170
- return null;
171
- }
218
+ const updates = getPropsToSet(newProps);
219
+ return Object.keys(updates).length ? updates : null;
220
+ },
221
+ requestPostPaintCallback: (callback) => {
222
+ setTimeout(() => callback(Date.now()), 0);
172
223
  },
173
224
  removeChild(parentInstance, child) {
174
225
  if (parentInstance instanceof _base.BaseParent) {
@@ -182,31 +233,36 @@ var hostConfig = ({
182
233
  resetTextContent: () => {
183
234
  throw new Error(`Unexpected call to resetTextContent()`);
184
235
  },
236
+ resetFormInstance: () => null,
237
+ resolveEventTimeStamp: () => Date.now(),
238
+ resolveEventType: () => null,
239
+ resolveUpdatePriority: () => currentUpdatePriority,
185
240
  scheduleTimeout: (fn, delay) => setTimeout(fn, delay),
186
- shouldSetTextContent: () => false,
187
- // Not-implemented
188
- hideInstance: () => {
189
- console.log("Not-implemented: hideInstance");
190
- },
191
- hideTextInstance: () => {
192
- console.log("Not-implemented: hideTextInstance");
241
+ scheduleMicrotask: scheduleMicrotaskCompat,
242
+ setCurrentUpdatePriority: (newPriority) => {
243
+ currentUpdatePriority = newPriority;
193
244
  },
194
- unhideInstance: () => {
195
- console.log("Not-implemented: unhideInstance");
196
- },
197
- unhideTextInstance: () => {
198
- console.log("Not-implemented: unhideTextInstance");
199
- }
245
+ shouldAttemptEagerTransition: () => false,
246
+ shouldSetTextContent: () => false,
247
+ startSuspendingCommit: () => null,
248
+ suspendInstance: () => null,
249
+ trackSchedulerEvent: () => null,
250
+ waitForCommitToBeReady: () => null,
251
+ hideInstance: () => null,
252
+ hideTextInstance: () => null,
253
+ unhideInstance: () => null,
254
+ unhideTextInstance: () => null
200
255
  };
256
+ return config;
201
257
  };
202
258
  var ToolkitRenderer = {
203
259
  renderGroup: (component, container, config = {
204
260
  componentNamespaces: [CoreComponents]
205
261
  }) => {
206
262
  const reconciler = _reactreconciler2.default.call(void 0, hostConfig(config));
207
- const root = reconciler.createContainer(container, 0, false, null);
263
+ const root = createContainerCompat(reconciler, container);
208
264
  const componentWithContexts = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkRT2VSMJLjs.LoggerContext.Provider, { value: container.log, children: component });
209
- reconciler.updateContainer(componentWithContexts, root, null);
265
+ reconciler.updateContainer(componentWithContexts, root, null, void 0);
210
266
  },
211
267
  render: (component, container, rootGroupProps, config = {
212
268
  componentNamespaces: [CoreComponents]
@@ -4,6 +4,7 @@ import {
4
4
 
5
5
  // src/index.tsx
6
6
  import Reconciler from "react-reconciler";
7
+ import React2 from "react";
7
8
  import { DefaultEventPriority } from "react-reconciler/constants";
8
9
  import * as ld from "@arcanejs/toolkit";
9
10
  import { Base, BaseParent } from "@arcanejs/toolkit/components/base";
@@ -67,9 +68,48 @@ var CoreComponents = prepareComponents("core", {
67
68
  // src/index.tsx
68
69
  import { jsx } from "react/jsx-runtime";
69
70
  var canSetProps = (instance) => instance instanceof Base;
70
- var hostConfig = ({
71
- componentNamespaces
72
- }) => {
71
+ var getPropsToSet = (props) => {
72
+ const updates = {};
73
+ for (const [key, val] of Object.entries(props)) {
74
+ if (key !== "children") {
75
+ updates[key] = val;
76
+ }
77
+ }
78
+ return updates;
79
+ };
80
+ var setInstanceProps = (instance, props) => {
81
+ if (canSetProps(instance)) {
82
+ instance.setProps(props);
83
+ } else {
84
+ throw new Error(`Unexpected Instance: ${instance}`);
85
+ }
86
+ };
87
+ var scheduleMicrotaskCompat = typeof queueMicrotask === "function" ? queueMicrotask : (cb) => {
88
+ Promise.resolve().then(cb);
89
+ };
90
+ var reportRendererError = (error) => {
91
+ console.error(error);
92
+ };
93
+ var createContainerCompat = (reconciler, container) => {
94
+ const createContainer = reconciler.createContainer;
95
+ if (createContainer.length <= 4) {
96
+ return createContainer(container, 0, false, null);
97
+ }
98
+ return createContainer(
99
+ container,
100
+ 0,
101
+ null,
102
+ false,
103
+ null,
104
+ "",
105
+ reportRendererError,
106
+ reportRendererError,
107
+ reportRendererError,
108
+ null
109
+ );
110
+ };
111
+ var ROOT_HOST_CONTEXT = {};
112
+ var hostConfig = ({ componentNamespaces }) => {
73
113
  const processedNamespaces = {};
74
114
  for (const namespace of componentNamespaces) {
75
115
  if (processedNamespaces[namespace._namespace]) {
@@ -77,12 +117,17 @@ var hostConfig = ({
77
117
  }
78
118
  processedNamespaces[namespace._namespace] = namespace;
79
119
  }
80
- return {
120
+ const hostTransitionContext = React2.createContext(null);
121
+ let currentUpdatePriority = DefaultEventPriority;
122
+ const config = {
81
123
  supportsMutation: true,
82
124
  supportsPersistence: false,
83
125
  noTimeout: -1,
84
126
  isPrimaryRenderer: true,
85
127
  supportsHydration: false,
128
+ supportsMicrotasks: true,
129
+ NotPendingTransition: null,
130
+ HostTransitionContext: hostTransitionContext,
86
131
  afterActiveInstanceBlur: () => null,
87
132
  appendChild: (parentInstance, child) => {
88
133
  if (parentInstance instanceof BaseParent) {
@@ -104,14 +149,23 @@ var hostConfig = ({
104
149
  beforeActiveInstanceBlur: () => null,
105
150
  cancelTimeout: (id) => clearTimeout(id),
106
151
  clearContainer: (container) => container.removeAllChildren(),
107
- commitMount: () => {
152
+ commitMount: (_instance, _type, _props) => {
108
153
  throw new Error(`Unexpected call to commitMount()`);
109
154
  },
110
- commitUpdate(instance, updatePayload, _type, _prevProps, _nextProps, _internalHandle) {
111
- if (canSetProps(instance)) {
112
- instance.setProps(updatePayload);
113
- } else {
114
- throw new Error(`Unexpected Instance: ${instance}`);
155
+ commitUpdate(instance, ...args) {
156
+ if (typeof args[0] === "string") {
157
+ const nextProps2 = args[2];
158
+ setInstanceProps(instance, getPropsToSet(nextProps2));
159
+ return;
160
+ }
161
+ const updatePayload = args[0];
162
+ if (updatePayload) {
163
+ setInstanceProps(instance, updatePayload);
164
+ return;
165
+ }
166
+ const nextProps = args[3];
167
+ if (nextProps) {
168
+ setInstanceProps(instance, getPropsToSet(nextProps));
115
169
  }
116
170
  },
117
171
  commitTextUpdate: (textInstance, _oldText, newText) => textInstance.setText(newText),
@@ -137,6 +191,7 @@ var hostConfig = ({
137
191
  detachDeletedInstance: () => null,
138
192
  getChildHostContext: (parentHostContext) => parentHostContext,
139
193
  getCurrentEventPriority: () => DefaultEventPriority,
194
+ getCurrentUpdatePriority: () => currentUpdatePriority,
140
195
  getInstanceFromNode: () => {
141
196
  throw new Error("Not yet implemented.");
142
197
  },
@@ -144,7 +199,7 @@ var hostConfig = ({
144
199
  throw new Error("Not yet implemented.");
145
200
  },
146
201
  getPublicInstance: (instance) => instance,
147
- getRootHostContext: () => null,
202
+ getRootHostContext: () => ROOT_HOST_CONTEXT,
148
203
  insertBefore: (parentInstance, child, beforeChild) => {
149
204
  if (parentInstance instanceof BaseParent) {
150
205
  parentInstance.insertBefore(child, beforeChild);
@@ -154,21 +209,17 @@ var hostConfig = ({
154
209
  },
155
210
  insertInContainerBefore: (container, child, beforeChild) => container.insertBefore(child, beforeChild),
156
211
  finalizeInitialChildren: () => false,
212
+ maySuspendCommit: () => false,
213
+ preloadInstance: () => false,
157
214
  prepareForCommit: () => null,
158
215
  preparePortalMount: () => null,
159
216
  prepareScopeUpdate: () => null,
160
217
  prepareUpdate: (_instance, _type, _oldProps, newProps, _rootContainer, _hostContext) => {
161
- const updates = {};
162
- for (const [key, val] of Object.entries(newProps)) {
163
- if (key !== "children") {
164
- updates[key] = val;
165
- }
166
- }
167
- if (Object.keys(updates).length) {
168
- return updates;
169
- } else {
170
- return null;
171
- }
218
+ const updates = getPropsToSet(newProps);
219
+ return Object.keys(updates).length ? updates : null;
220
+ },
221
+ requestPostPaintCallback: (callback) => {
222
+ setTimeout(() => callback(Date.now()), 0);
172
223
  },
173
224
  removeChild(parentInstance, child) {
174
225
  if (parentInstance instanceof BaseParent) {
@@ -182,31 +233,36 @@ var hostConfig = ({
182
233
  resetTextContent: () => {
183
234
  throw new Error(`Unexpected call to resetTextContent()`);
184
235
  },
236
+ resetFormInstance: () => null,
237
+ resolveEventTimeStamp: () => Date.now(),
238
+ resolveEventType: () => null,
239
+ resolveUpdatePriority: () => currentUpdatePriority,
185
240
  scheduleTimeout: (fn, delay) => setTimeout(fn, delay),
186
- shouldSetTextContent: () => false,
187
- // Not-implemented
188
- hideInstance: () => {
189
- console.log("Not-implemented: hideInstance");
190
- },
191
- hideTextInstance: () => {
192
- console.log("Not-implemented: hideTextInstance");
193
- },
194
- unhideInstance: () => {
195
- console.log("Not-implemented: unhideInstance");
241
+ scheduleMicrotask: scheduleMicrotaskCompat,
242
+ setCurrentUpdatePriority: (newPriority) => {
243
+ currentUpdatePriority = newPriority;
196
244
  },
197
- unhideTextInstance: () => {
198
- console.log("Not-implemented: unhideTextInstance");
199
- }
245
+ shouldAttemptEagerTransition: () => false,
246
+ shouldSetTextContent: () => false,
247
+ startSuspendingCommit: () => null,
248
+ suspendInstance: () => null,
249
+ trackSchedulerEvent: () => null,
250
+ waitForCommitToBeReady: () => null,
251
+ hideInstance: () => null,
252
+ hideTextInstance: () => null,
253
+ unhideInstance: () => null,
254
+ unhideTextInstance: () => null
200
255
  };
256
+ return config;
201
257
  };
202
258
  var ToolkitRenderer = {
203
259
  renderGroup: (component, container, config = {
204
260
  componentNamespaces: [CoreComponents]
205
261
  }) => {
206
262
  const reconciler = Reconciler(hostConfig(config));
207
- const root = reconciler.createContainer(container, 0, false, null);
263
+ const root = createContainerCompat(reconciler, container);
208
264
  const componentWithContexts = /* @__PURE__ */ jsx(LoggerContext.Provider, { value: container.log, children: component });
209
- reconciler.updateContainer(componentWithContexts, root, null);
265
+ reconciler.updateContainer(componentWithContexts, root, null, void 0);
210
266
  },
211
267
  render: (component, container, rootGroupProps, config = {
212
268
  componentNamespaces: [CoreComponents]
package/dist/colors.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkQ54JXYCVjs = require('./chunk-Q54JXYCV.js');
5
+ var _chunkEJVUDIQPjs = require('./chunk-EJVUDIQP.js');
6
6
  require('./chunk-RT2VSMJL.js');
7
7
 
8
8
  // src/colors.tsx
@@ -56,10 +56,10 @@ var HslColorPicker = ({
56
56
  },
57
57
  [onChange]
58
58
  );
59
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkQ54JXYCVjs.Group, { ...DEFAULT_GROUP_PROPS, ...groupProps, children: [
60
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkQ54JXYCVjs.Rect, { color: `hsl(${hue}deg ${saturation}% ${lightness}% / ${alpha})` }),
59
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkEJVUDIQPjs.Group, { ...DEFAULT_GROUP_PROPS, ...groupProps, children: [
60
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkEJVUDIQPjs.Rect, { color: `hsl(${hue}deg ${saturation}% ${lightness}% / ${alpha})` }),
61
61
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
62
- _chunkQ54JXYCVjs.SliderButton,
62
+ _chunkEJVUDIQPjs.SliderButton,
63
63
  {
64
64
  value: hue,
65
65
  onChange: setHue,
@@ -71,7 +71,7 @@ var HslColorPicker = ({
71
71
  }
72
72
  ),
73
73
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
74
- _chunkQ54JXYCVjs.SliderButton,
74
+ _chunkEJVUDIQPjs.SliderButton,
75
75
  {
76
76
  value: saturation,
77
77
  onChange: setSat,
@@ -87,7 +87,7 @@ var HslColorPicker = ({
87
87
  }
88
88
  ),
89
89
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
90
- _chunkQ54JXYCVjs.SliderButton,
90
+ _chunkEJVUDIQPjs.SliderButton,
91
91
  {
92
92
  value: lightness,
93
93
  onChange: setLightness,
@@ -103,7 +103,7 @@ var HslColorPicker = ({
103
103
  }
104
104
  ),
105
105
  showAlpha && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
106
- _chunkQ54JXYCVjs.SliderButton,
106
+ _chunkEJVUDIQPjs.SliderButton,
107
107
  {
108
108
  value: alpha,
109
109
  onChange: setAlpha,
package/dist/colors.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  Group,
3
3
  Rect,
4
4
  SliderButton
5
- } from "./chunk-CAHNLXTY.mjs";
5
+ } from "./chunk-TP2BI3OM.mjs";
6
6
  import "./chunk-TOGR56FN.mjs";
7
7
 
8
8
  // src/colors.tsx
package/dist/index.d.mts CHANGED
@@ -51,8 +51,8 @@ type ReactToolkitConfig = {
51
51
  componentNamespaces: Array<PreparedComponents<any>>;
52
52
  };
53
53
  declare const ToolkitRenderer: {
54
- renderGroup: (component: JSX.Element, container: ld.Group, config?: ReactToolkitConfig) => void;
55
- render: (component: JSX.Element, container: ld.Toolkit, rootGroupProps?: Props, config?: ReactToolkitConfig) => void;
54
+ renderGroup: (component: React__default.ReactElement, container: ld.Group, config?: ReactToolkitConfig) => void;
55
+ render: (component: React__default.ReactElement, container: ld.Toolkit, rootGroupProps?: Props, config?: ReactToolkitConfig) => void;
56
56
  };
57
57
 
58
58
  declare const Button: React__default.ForwardRefExoticComponent<Partial<Partial<_arcanejs_toolkit_components_button.InternalProps>> & React__default.RefAttributes<ld.Button>>;
package/dist/index.d.ts CHANGED
@@ -51,8 +51,8 @@ type ReactToolkitConfig = {
51
51
  componentNamespaces: Array<PreparedComponents<any>>;
52
52
  };
53
53
  declare const ToolkitRenderer: {
54
- renderGroup: (component: JSX.Element, container: ld.Group, config?: ReactToolkitConfig) => void;
55
- render: (component: JSX.Element, container: ld.Toolkit, rootGroupProps?: Props, config?: ReactToolkitConfig) => void;
54
+ renderGroup: (component: React__default.ReactElement, container: ld.Group, config?: ReactToolkitConfig) => void;
55
+ render: (component: React__default.ReactElement, container: ld.Toolkit, rootGroupProps?: Props, config?: ReactToolkitConfig) => void;
56
56
  };
57
57
 
58
58
  declare const Button: React__default.ForwardRefExoticComponent<Partial<Partial<_arcanejs_toolkit_components_button.InternalProps>> & React__default.RefAttributes<ld.Button>>;
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
 
15
15
 
16
- var _chunkQ54JXYCVjs = require('./chunk-Q54JXYCV.js');
16
+ var _chunkEJVUDIQPjs = require('./chunk-EJVUDIQP.js');
17
17
  require('./chunk-RT2VSMJL.js');
18
18
 
19
19
 
@@ -30,4 +30,4 @@ require('./chunk-RT2VSMJL.js');
30
30
 
31
31
 
32
32
 
33
- exports.Button = _chunkQ54JXYCVjs.Button; exports.CoreComponents = _chunkQ54JXYCVjs.CoreComponents; exports.Group = _chunkQ54JXYCVjs.Group; exports.GroupHeader = _chunkQ54JXYCVjs.GroupHeader; exports.Label = _chunkQ54JXYCVjs.Label; exports.Rect = _chunkQ54JXYCVjs.Rect; exports.SliderButton = _chunkQ54JXYCVjs.SliderButton; exports.Switch = _chunkQ54JXYCVjs.Switch; exports.Tab = _chunkQ54JXYCVjs.Tab; exports.Tabs = _chunkQ54JXYCVjs.Tabs; exports.TextInput = _chunkQ54JXYCVjs.TextInput; exports.Timeline = _chunkQ54JXYCVjs.Timeline; exports.ToolkitRenderer = _chunkQ54JXYCVjs.ToolkitRenderer; exports.prepareComponents = _chunkQ54JXYCVjs.prepareComponents;
33
+ exports.Button = _chunkEJVUDIQPjs.Button; exports.CoreComponents = _chunkEJVUDIQPjs.CoreComponents; exports.Group = _chunkEJVUDIQPjs.Group; exports.GroupHeader = _chunkEJVUDIQPjs.GroupHeader; exports.Label = _chunkEJVUDIQPjs.Label; exports.Rect = _chunkEJVUDIQPjs.Rect; exports.SliderButton = _chunkEJVUDIQPjs.SliderButton; exports.Switch = _chunkEJVUDIQPjs.Switch; exports.Tab = _chunkEJVUDIQPjs.Tab; exports.Tabs = _chunkEJVUDIQPjs.Tabs; exports.TextInput = _chunkEJVUDIQPjs.TextInput; exports.Timeline = _chunkEJVUDIQPjs.Timeline; exports.ToolkitRenderer = _chunkEJVUDIQPjs.ToolkitRenderer; exports.prepareComponents = _chunkEJVUDIQPjs.prepareComponents;
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  Timeline,
14
14
  ToolkitRenderer,
15
15
  prepareComponents
16
- } from "./chunk-CAHNLXTY.mjs";
16
+ } from "./chunk-TP2BI3OM.mjs";
17
17
  import "./chunk-TOGR56FN.mjs";
18
18
  export {
19
19
  Button,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcanejs/react-toolkit",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
4
4
  "private": false,
5
5
  "description": "Build web-accessible control interfaces for your long-running Node.js processes",
6
6
  "keywords": [
@@ -55,8 +55,8 @@
55
55
  "@types/eslint": "^8.56.5",
56
56
  "@types/lodash": "^4.17.10",
57
57
  "@types/node": "^20.11.24",
58
- "@types/react": "^18",
59
- "@types/react-reconciler": "^0.28.8",
58
+ "@types/react": "^19.2.2",
59
+ "@types/react-reconciler": "^0.32.2",
60
60
  "check-export-map": "^1.3.1",
61
61
  "eslint": "^8.57.0",
62
62
  "tsup": "^8.1.0",
@@ -66,11 +66,11 @@
66
66
  "@arcanejs/typescript-config": "^0.0.0"
67
67
  },
68
68
  "dependencies": {
69
- "lodash": "^4.17.21",
70
- "react": "^18",
71
- "react-reconciler": "0.28.0",
72
- "@arcanejs/protocol": "^0.7.0",
73
- "@arcanejs/toolkit": "^6.0.0"
69
+ "lodash": "^4.17.23",
70
+ "react": "^19.2.0",
71
+ "react-reconciler": "0.33.0",
72
+ "@arcanejs/protocol": "^0.8.0",
73
+ "@arcanejs/toolkit": "^7.0.0"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "zod": "^3.23.8"