@sladg/apex-state 3.1.0 → 3.2.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 +2 -0
- package/dist/apply-changes-Btg-SNmO.d.ts +1552 -0
- package/dist/index.d.ts +5 -1549
- package/dist/index.js.map +1 -1
- package/dist/testing/index.d.ts +113 -0
- package/dist/testing/index.js +1384 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1,1384 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/testing/index.ts
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { act } from "@testing-library/react";
|
|
10
|
+
import { proxy as proxy2, snapshot as snapshot4, useSnapshot as useSnapshot2 } from "valtio";
|
|
11
|
+
|
|
12
|
+
// src/utils/is.ts
|
|
13
|
+
var isNil = (value) => value == null;
|
|
14
|
+
var isUndefined = (value) => value === void 0;
|
|
15
|
+
var isNull = (value) => value === null;
|
|
16
|
+
var isObject = (value) => {
|
|
17
|
+
if (value == null || typeof value !== "object" || Array.isArray(value))
|
|
18
|
+
return false;
|
|
19
|
+
const proto = Object.getPrototypeOf(value);
|
|
20
|
+
return proto === Object.prototype || proto === null;
|
|
21
|
+
};
|
|
22
|
+
var isArray = (value) => Array.isArray(value);
|
|
23
|
+
var isString = (value) => typeof value === "string";
|
|
24
|
+
var isNumber = (value) => typeof value === "number";
|
|
25
|
+
var isBoolean = (value) => typeof value === "boolean";
|
|
26
|
+
var isFunction = (value) => typeof value === "function";
|
|
27
|
+
var isSymbol = (value) => typeof value === "symbol";
|
|
28
|
+
var isDate = (value) => value instanceof Date;
|
|
29
|
+
var isRegExp = (value) => value instanceof RegExp;
|
|
30
|
+
var isPrimitive = (value) => {
|
|
31
|
+
const type = typeof value;
|
|
32
|
+
return type === "string" || type === "number" || type === "boolean" || type === "symbol" || type === "bigint" || value == null;
|
|
33
|
+
};
|
|
34
|
+
var isEmptyObject = (value) => {
|
|
35
|
+
for (const key in value) {
|
|
36
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
};
|
|
42
|
+
var isEmpty = (value) => {
|
|
43
|
+
if (isNil(value)) return true;
|
|
44
|
+
if (isNumber(value) || isBoolean(value)) return false;
|
|
45
|
+
if (isString(value)) return value.length === 0;
|
|
46
|
+
if (isArray(value)) return value.length === 0;
|
|
47
|
+
if (isObject(value)) return isEmptyObject(value);
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
var isEqualArray = (a, b) => {
|
|
51
|
+
if (a.length !== b.length) return false;
|
|
52
|
+
for (let i = 0; i < a.length; i++) {
|
|
53
|
+
if (!iEqual(a[i], b[i])) return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
};
|
|
57
|
+
var isEqualObject = (a, b) => {
|
|
58
|
+
const keysA = Object.keys(a);
|
|
59
|
+
const keysB = Object.keys(b);
|
|
60
|
+
if (keysA.length !== keysB.length) return false;
|
|
61
|
+
for (const key of keysA) {
|
|
62
|
+
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
|
|
63
|
+
if (!iEqual(a[key], b[key])) return false;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
};
|
|
67
|
+
var iEqual = (a, b) => {
|
|
68
|
+
if (a === b) return true;
|
|
69
|
+
if (isArray(a) && isArray(b)) {
|
|
70
|
+
return isEqualArray(a, b);
|
|
71
|
+
}
|
|
72
|
+
if (isDate(a) && isDate(b)) {
|
|
73
|
+
return a.getTime() === b.getTime();
|
|
74
|
+
}
|
|
75
|
+
if (isRegExp(a) && isRegExp(b)) {
|
|
76
|
+
return a.toString() === b.toString();
|
|
77
|
+
}
|
|
78
|
+
if (isObject(a) && isObject(b)) {
|
|
79
|
+
return isEqualObject(a, b);
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
};
|
|
83
|
+
var isNotNil = (value) => value != null;
|
|
84
|
+
var isNotUndefined = (value) => value !== void 0;
|
|
85
|
+
var isNotNull = (value) => value !== null;
|
|
86
|
+
var isNotObject = (value) => !isObject(value);
|
|
87
|
+
var isNotArray = (value) => !Array.isArray(value);
|
|
88
|
+
var isNotString = (value) => typeof value !== "string";
|
|
89
|
+
var isNotNumber = (value) => typeof value !== "number";
|
|
90
|
+
var isNotBoolean = (value) => typeof value !== "boolean";
|
|
91
|
+
var isNotFunction = (value) => typeof value !== "function";
|
|
92
|
+
var isNotSymbol = (value) => typeof value !== "symbol";
|
|
93
|
+
var isNotDate = (value) => !(value instanceof Date);
|
|
94
|
+
var isNotRegExp = (value) => !(value instanceof RegExp);
|
|
95
|
+
var isNotPrimitive = (value) => {
|
|
96
|
+
const type = typeof value;
|
|
97
|
+
return !(type === "string" || type === "number" || type === "boolean" || type === "symbol" || type === "bigint" || value == null);
|
|
98
|
+
};
|
|
99
|
+
var isNotEmpty = (value) => !isEmpty(value);
|
|
100
|
+
var isNotEqual = (a, b) => !iEqual(a, b);
|
|
101
|
+
var is = {
|
|
102
|
+
nil: isNil,
|
|
103
|
+
undefined: isUndefined,
|
|
104
|
+
null: isNull,
|
|
105
|
+
object: isObject,
|
|
106
|
+
array: isArray,
|
|
107
|
+
string: isString,
|
|
108
|
+
number: isNumber,
|
|
109
|
+
boolean: isBoolean,
|
|
110
|
+
function: isFunction,
|
|
111
|
+
symbol: isSymbol,
|
|
112
|
+
date: isDate,
|
|
113
|
+
regexp: isRegExp,
|
|
114
|
+
primitive: isPrimitive,
|
|
115
|
+
empty: isEmpty,
|
|
116
|
+
equal: iEqual,
|
|
117
|
+
not: {
|
|
118
|
+
nil: isNotNil,
|
|
119
|
+
undefined: isNotUndefined,
|
|
120
|
+
null: isNotNull,
|
|
121
|
+
object: isNotObject,
|
|
122
|
+
array: isNotArray,
|
|
123
|
+
string: isNotString,
|
|
124
|
+
number: isNotNumber,
|
|
125
|
+
boolean: isNotBoolean,
|
|
126
|
+
function: isNotFunction,
|
|
127
|
+
symbol: isNotSymbol,
|
|
128
|
+
date: isNotDate,
|
|
129
|
+
regexp: isNotRegExp,
|
|
130
|
+
primitive: isNotPrimitive,
|
|
131
|
+
empty: isNotEmpty,
|
|
132
|
+
equal: isNotEqual
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// src/utils/dot.ts
|
|
137
|
+
var pathCache = /* @__PURE__ */ new Map();
|
|
138
|
+
var MAX_CACHE_SIZE = 1e3;
|
|
139
|
+
var getPathParts = (path) => {
|
|
140
|
+
if (typeof path !== "string") {
|
|
141
|
+
throw new TypeError(
|
|
142
|
+
`[apex-state] Path must be a string, received ${typeof path}: ${JSON.stringify(path)}. Paths must be dot-notation strings like "user.email" or "items.0.name".`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
let parts = pathCache.get(path);
|
|
146
|
+
if (!parts) {
|
|
147
|
+
parts = path.split(".");
|
|
148
|
+
if (pathCache.size >= MAX_CACHE_SIZE) {
|
|
149
|
+
pathCache.clear();
|
|
150
|
+
}
|
|
151
|
+
pathCache.set(path, parts);
|
|
152
|
+
}
|
|
153
|
+
return parts;
|
|
154
|
+
};
|
|
155
|
+
var get = (obj, path) => {
|
|
156
|
+
const parts = getPathParts(path);
|
|
157
|
+
let current = obj;
|
|
158
|
+
for (const part of parts) {
|
|
159
|
+
if (is.not.object(current)) {
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
current = Reflect.get(current, part);
|
|
163
|
+
}
|
|
164
|
+
return current;
|
|
165
|
+
};
|
|
166
|
+
var get__unsafe = (obj, path) => {
|
|
167
|
+
const parts = getPathParts(path);
|
|
168
|
+
let current = obj;
|
|
169
|
+
for (const part of parts) {
|
|
170
|
+
if (is.not.object(current)) {
|
|
171
|
+
return void 0;
|
|
172
|
+
}
|
|
173
|
+
current = Reflect.get(current, part);
|
|
174
|
+
}
|
|
175
|
+
return current;
|
|
176
|
+
};
|
|
177
|
+
var set = (obj, path, value) => {
|
|
178
|
+
const keys = getPathParts(path);
|
|
179
|
+
const last = keys.length - 1;
|
|
180
|
+
let current = obj;
|
|
181
|
+
for (let i = 0; i < last; i++) {
|
|
182
|
+
let next = Reflect.get(current, keys[i]);
|
|
183
|
+
if (!is.object(next)) {
|
|
184
|
+
next = {};
|
|
185
|
+
Reflect.set(current, keys[i], next);
|
|
186
|
+
}
|
|
187
|
+
current = next;
|
|
188
|
+
}
|
|
189
|
+
Reflect.set(current, keys[last], value);
|
|
190
|
+
};
|
|
191
|
+
var set__unsafe = (obj, path, value) => {
|
|
192
|
+
const keys = getPathParts(path);
|
|
193
|
+
const last = keys.length - 1;
|
|
194
|
+
let current = obj;
|
|
195
|
+
for (let i = 0; i < last; i++) {
|
|
196
|
+
let next = Reflect.get(current, keys[i]);
|
|
197
|
+
if (!is.object(next)) {
|
|
198
|
+
next = {};
|
|
199
|
+
Reflect.set(current, keys[i], next);
|
|
200
|
+
}
|
|
201
|
+
current = next;
|
|
202
|
+
}
|
|
203
|
+
Reflect.set(current, keys[last], value);
|
|
204
|
+
};
|
|
205
|
+
var has = (obj, path) => {
|
|
206
|
+
const parts = getPathParts(path);
|
|
207
|
+
let current = obj;
|
|
208
|
+
for (const part of parts) {
|
|
209
|
+
if (is.not.object(current)) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
current = Reflect.get(current, part);
|
|
213
|
+
}
|
|
214
|
+
return is.not.undefined(current);
|
|
215
|
+
};
|
|
216
|
+
var same = (obj, ...paths) => {
|
|
217
|
+
if (paths.length === 0) return true;
|
|
218
|
+
if (paths.length === 1) return true;
|
|
219
|
+
const firstValue = get__unsafe(obj, paths[0]);
|
|
220
|
+
for (let i = 1; i < paths.length; i++) {
|
|
221
|
+
if (!is.equal(get__unsafe(obj, paths[i]), firstValue)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
};
|
|
227
|
+
var dot = {
|
|
228
|
+
get,
|
|
229
|
+
get__unsafe,
|
|
230
|
+
set,
|
|
231
|
+
set__unsafe,
|
|
232
|
+
has,
|
|
233
|
+
same
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// src/store/create-store.ts
|
|
237
|
+
import { useCallback, useLayoutEffect } from "react";
|
|
238
|
+
import { snapshot as snapshot3, useSnapshot } from "valtio";
|
|
239
|
+
|
|
240
|
+
// src/concerns/registration.ts
|
|
241
|
+
import { effect } from "valtio-reactive";
|
|
242
|
+
|
|
243
|
+
// src/utils/bool-logic.ts
|
|
244
|
+
var evaluateNumericComparison = (logic, state) => {
|
|
245
|
+
if ("GT" in logic) {
|
|
246
|
+
const [path, threshold] = logic.GT;
|
|
247
|
+
const value = dot.get__unsafe(state, path);
|
|
248
|
+
return is.number(value) && value > threshold;
|
|
249
|
+
}
|
|
250
|
+
if ("LT" in logic) {
|
|
251
|
+
const [path, threshold] = logic.LT;
|
|
252
|
+
const value = dot.get__unsafe(state, path);
|
|
253
|
+
return is.number(value) && value < threshold;
|
|
254
|
+
}
|
|
255
|
+
if ("GTE" in logic) {
|
|
256
|
+
const [path, threshold] = logic.GTE;
|
|
257
|
+
const value = dot.get__unsafe(state, path);
|
|
258
|
+
return is.number(value) && value >= threshold;
|
|
259
|
+
}
|
|
260
|
+
if ("LTE" in logic) {
|
|
261
|
+
const [path, threshold] = logic.LTE;
|
|
262
|
+
const value = dot.get__unsafe(state, path);
|
|
263
|
+
return is.number(value) && value <= threshold;
|
|
264
|
+
}
|
|
265
|
+
return void 0;
|
|
266
|
+
};
|
|
267
|
+
var evaluateBoolLogic = (logic, state) => {
|
|
268
|
+
if ("IS_EQUAL" in logic) {
|
|
269
|
+
const [path, expected] = logic.IS_EQUAL;
|
|
270
|
+
return dot.get__unsafe(state, path) === expected;
|
|
271
|
+
}
|
|
272
|
+
if ("EXISTS" in logic) {
|
|
273
|
+
return is.not.nil(dot.get__unsafe(state, logic.EXISTS));
|
|
274
|
+
}
|
|
275
|
+
if ("IS_EMPTY" in logic) {
|
|
276
|
+
return is.empty(dot.get__unsafe(state, logic.IS_EMPTY));
|
|
277
|
+
}
|
|
278
|
+
if ("AND" in logic) {
|
|
279
|
+
return logic.AND.every((subLogic) => evaluateBoolLogic(subLogic, state));
|
|
280
|
+
}
|
|
281
|
+
if ("OR" in logic) {
|
|
282
|
+
return logic.OR.some((subLogic) => evaluateBoolLogic(subLogic, state));
|
|
283
|
+
}
|
|
284
|
+
if ("NOT" in logic) {
|
|
285
|
+
return !evaluateBoolLogic(logic.NOT, state);
|
|
286
|
+
}
|
|
287
|
+
const numericResult = evaluateNumericComparison(logic, state);
|
|
288
|
+
if (is.not.undefined(numericResult)) {
|
|
289
|
+
return numericResult;
|
|
290
|
+
}
|
|
291
|
+
if ("IN" in logic) {
|
|
292
|
+
const [path, allowed] = logic.IN;
|
|
293
|
+
return allowed.includes(dot.get__unsafe(state, path));
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// src/concerns/prebuilts/index.ts
|
|
299
|
+
var prebuilts_exports = {};
|
|
300
|
+
__export(prebuilts_exports, {
|
|
301
|
+
disabledWhen: () => disabledWhen,
|
|
302
|
+
dynamicLabel: () => dynamicLabel,
|
|
303
|
+
dynamicPlaceholder: () => dynamicPlaceholder,
|
|
304
|
+
dynamicTooltip: () => dynamicTooltip,
|
|
305
|
+
prebuilts: () => prebuilts,
|
|
306
|
+
prebuiltsNamespace: () => prebuiltsNamespace,
|
|
307
|
+
readonlyWhen: () => readonlyWhen,
|
|
308
|
+
validationState: () => validationState,
|
|
309
|
+
visibleWhen: () => visibleWhen
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// src/concerns/prebuilts/disabled-when.ts
|
|
313
|
+
var disabledWhen = {
|
|
314
|
+
name: "disabledWhen",
|
|
315
|
+
description: "Boolean logic for disabled state",
|
|
316
|
+
evaluate: (props) => {
|
|
317
|
+
return evaluateBoolLogic(props.boolLogic, props.state);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// src/utils/interpolation.ts
|
|
322
|
+
var extractPlaceholders = (template) => {
|
|
323
|
+
const regex = /\{\{([^}]+)\}\}/g;
|
|
324
|
+
const matches = [];
|
|
325
|
+
let match;
|
|
326
|
+
while ((match = regex.exec(template)) !== null) {
|
|
327
|
+
if (match[1]) {
|
|
328
|
+
matches.push(match[1]);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return matches;
|
|
332
|
+
};
|
|
333
|
+
var interpolateTemplate = (template, state) => {
|
|
334
|
+
return template.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
|
|
335
|
+
const value = dot.get__unsafe(state, path);
|
|
336
|
+
if (is.string(value)) return value;
|
|
337
|
+
if (is.number(value)) return String(value);
|
|
338
|
+
if (is.boolean(value)) return String(value);
|
|
339
|
+
return match;
|
|
340
|
+
});
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// src/concerns/prebuilts/dynamic-label.ts
|
|
344
|
+
var dynamicLabel = {
|
|
345
|
+
name: "dynamicLabel",
|
|
346
|
+
description: "Template string interpolation for labels",
|
|
347
|
+
evaluate: (props) => {
|
|
348
|
+
return interpolateTemplate(props.template, props.state);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
// src/concerns/prebuilts/dynamic-placeholder.ts
|
|
353
|
+
var dynamicPlaceholder = {
|
|
354
|
+
name: "dynamicPlaceholder",
|
|
355
|
+
description: "Template string interpolation for placeholders",
|
|
356
|
+
evaluate: (props) => {
|
|
357
|
+
return interpolateTemplate(props.template, props.state);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// src/concerns/prebuilts/dynamic-tooltip.ts
|
|
362
|
+
var dynamicTooltip = {
|
|
363
|
+
name: "dynamicTooltip",
|
|
364
|
+
description: "Template string interpolation for tooltips",
|
|
365
|
+
evaluate: (props) => {
|
|
366
|
+
return interpolateTemplate(props.template, props.state);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// src/concerns/prebuilts/readonly-when.ts
|
|
371
|
+
var readonlyWhen = {
|
|
372
|
+
name: "readonlyWhen",
|
|
373
|
+
description: "Boolean logic for readonly state",
|
|
374
|
+
evaluate: (props) => {
|
|
375
|
+
return evaluateBoolLogic(props.boolLogic, props.state);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
// src/concerns/prebuilts/validation-state.ts
|
|
380
|
+
var validationState = {
|
|
381
|
+
name: "validationState",
|
|
382
|
+
description: "Schema validation with isError flag and detailed errors",
|
|
383
|
+
evaluate: (props) => {
|
|
384
|
+
const valueToValidate = "scope" in props && props.scope ? dot.get__unsafe(props.state, props.scope) : props.value;
|
|
385
|
+
const result = props.schema.safeParse(valueToValidate);
|
|
386
|
+
if (result.success) {
|
|
387
|
+
return {
|
|
388
|
+
isError: false,
|
|
389
|
+
errors: []
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
const errors = result.error.errors.map((err) => ({
|
|
393
|
+
field: err.path.length > 0 ? err.path.join(".") : ".",
|
|
394
|
+
message: err.message
|
|
395
|
+
}));
|
|
396
|
+
return {
|
|
397
|
+
isError: true,
|
|
398
|
+
errors
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// src/concerns/prebuilts/visible-when.ts
|
|
404
|
+
var visibleWhen = {
|
|
405
|
+
name: "visibleWhen",
|
|
406
|
+
description: "Boolean logic for visibility",
|
|
407
|
+
evaluate: (props) => {
|
|
408
|
+
return evaluateBoolLogic(props.boolLogic, props.state);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// src/concerns/prebuilts/index.ts
|
|
413
|
+
var prebuilts = [
|
|
414
|
+
validationState,
|
|
415
|
+
disabledWhen,
|
|
416
|
+
readonlyWhen,
|
|
417
|
+
visibleWhen,
|
|
418
|
+
dynamicTooltip,
|
|
419
|
+
dynamicLabel,
|
|
420
|
+
dynamicPlaceholder
|
|
421
|
+
];
|
|
422
|
+
var prebuiltsNamespace = {
|
|
423
|
+
validationState,
|
|
424
|
+
disabledWhen,
|
|
425
|
+
readonlyWhen,
|
|
426
|
+
visibleWhen,
|
|
427
|
+
dynamicTooltip,
|
|
428
|
+
dynamicLabel,
|
|
429
|
+
dynamicPlaceholder
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// src/concerns/registry.ts
|
|
433
|
+
var findConcern = (name, concerns = prebuilts) => {
|
|
434
|
+
return concerns.find((c) => c.name === name);
|
|
435
|
+
};
|
|
436
|
+
var defaultConcerns = prebuilts;
|
|
437
|
+
|
|
438
|
+
// src/concerns/registration.wasm-impl.ts
|
|
439
|
+
import { effect as effect2 } from "valtio-reactive";
|
|
440
|
+
|
|
441
|
+
// src/core/context.ts
|
|
442
|
+
import { createContext, useContext } from "react";
|
|
443
|
+
var StoreContext = createContext(null);
|
|
444
|
+
StoreContext.displayName = "StoreContext";
|
|
445
|
+
|
|
446
|
+
// src/pipeline/process-changes.ts
|
|
447
|
+
import { snapshot } from "valtio";
|
|
448
|
+
|
|
449
|
+
// src/pipeline/apply-batch.ts
|
|
450
|
+
var applyBatch = (changes, state) => {
|
|
451
|
+
for (const [path, value] of changes) {
|
|
452
|
+
const pathStr = path;
|
|
453
|
+
const current = dot.get__unsafe(state, pathStr);
|
|
454
|
+
if (current !== value) {
|
|
455
|
+
dot.set__unsafe(state, pathStr, value);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
// src/pipeline/queue.ts
|
|
461
|
+
var queueChange = (props) => {
|
|
462
|
+
props.queue.push([props.path, props.value, props.meta]);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
// src/pipeline/processors/aggregation-writes.ts
|
|
466
|
+
var distributeToSources = (aggregation, targetPath, changePath, value, meta, queue) => {
|
|
467
|
+
const isExactMatch = changePath === targetPath;
|
|
468
|
+
for (const sourcePath of aggregation.sourcePaths) {
|
|
469
|
+
const finalPath = isExactMatch ? sourcePath : `${sourcePath}.${changePath.substring(targetPath.length + 1)}`;
|
|
470
|
+
queueChange({
|
|
471
|
+
queue,
|
|
472
|
+
path: finalPath,
|
|
473
|
+
value,
|
|
474
|
+
meta: { ...meta, isAggregationChange: true }
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
var processAggregationWrites = (changes, store) => {
|
|
479
|
+
const { aggregations } = store._internal.registrations;
|
|
480
|
+
const { queue } = store._internal.processing;
|
|
481
|
+
for (let i = changes.length - 1; i >= 0; i--) {
|
|
482
|
+
const [path, value, meta] = changes[i];
|
|
483
|
+
for (const [targetPath, items] of aggregations) {
|
|
484
|
+
const isExactMatch = path === targetPath;
|
|
485
|
+
const isChildPath = path.startsWith(targetPath + ".");
|
|
486
|
+
if (isExactMatch || isChildPath) {
|
|
487
|
+
for (const aggregation of items) {
|
|
488
|
+
distributeToSources(aggregation, targetPath, path, value, meta, queue);
|
|
489
|
+
}
|
|
490
|
+
changes.splice(i, 1);
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// src/core/path-groups.ts
|
|
498
|
+
var makeEdgeKey = (path1, path2) => path1 < path2 ? `${path1}--${path2}` : `${path2}--${path1}`;
|
|
499
|
+
var bfsCollect = (adjacency, startPath) => {
|
|
500
|
+
const visited = /* @__PURE__ */ new Set([startPath]);
|
|
501
|
+
const queue = [startPath];
|
|
502
|
+
while (queue.length > 0) {
|
|
503
|
+
const current = queue.shift();
|
|
504
|
+
const neighbors = adjacency.get(current);
|
|
505
|
+
if (!neighbors) continue;
|
|
506
|
+
for (const neighbor of neighbors) {
|
|
507
|
+
if (!visited.has(neighbor)) {
|
|
508
|
+
visited.add(neighbor);
|
|
509
|
+
queue.push(neighbor);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return visited;
|
|
514
|
+
};
|
|
515
|
+
var removeIsolatedPath = (groups, path) => {
|
|
516
|
+
const groupId = groups.pathToGroup.get(path);
|
|
517
|
+
if (groupId !== void 0) {
|
|
518
|
+
groups.groupToPaths.get(groupId)?.delete(path);
|
|
519
|
+
if (groups.groupToPaths.get(groupId)?.size === 0) {
|
|
520
|
+
groups.groupToPaths.delete(groupId);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
groups.pathToGroup.delete(path);
|
|
524
|
+
groups.adjacency.delete(path);
|
|
525
|
+
};
|
|
526
|
+
var handleComponentSplit = (groups, path1, path2) => {
|
|
527
|
+
const reachableFromPath1 = bfsCollect(groups.adjacency, path1);
|
|
528
|
+
if (reachableFromPath1.has(path2)) return;
|
|
529
|
+
const newGroupId = groups.nextGroupId++;
|
|
530
|
+
const oldGroupId = groups.pathToGroup.get(path2);
|
|
531
|
+
const newComponent = bfsCollect(groups.adjacency, path2);
|
|
532
|
+
for (const path of newComponent) {
|
|
533
|
+
groups.pathToGroup.set(path, newGroupId);
|
|
534
|
+
groups.groupToPaths.get(oldGroupId)?.delete(path);
|
|
535
|
+
}
|
|
536
|
+
groups.groupToPaths.set(newGroupId, newComponent);
|
|
537
|
+
if (groups.groupToPaths.get(oldGroupId)?.size === 0) {
|
|
538
|
+
groups.groupToPaths.delete(oldGroupId);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
var addEdge = (groups, path1, path2) => {
|
|
542
|
+
const edgeKey = makeEdgeKey(path1, path2);
|
|
543
|
+
if (groups.edges.has(edgeKey)) return;
|
|
544
|
+
groups.edges.add(edgeKey);
|
|
545
|
+
if (!groups.adjacency.has(path1)) groups.adjacency.set(path1, /* @__PURE__ */ new Set());
|
|
546
|
+
if (!groups.adjacency.has(path2)) groups.adjacency.set(path2, /* @__PURE__ */ new Set());
|
|
547
|
+
groups.adjacency.get(path1).add(path2);
|
|
548
|
+
groups.adjacency.get(path2).add(path1);
|
|
549
|
+
const g1 = groups.pathToGroup.get(path1);
|
|
550
|
+
const g2 = groups.pathToGroup.get(path2);
|
|
551
|
+
if (g1 === void 0 && g2 === void 0) {
|
|
552
|
+
const id = groups.nextGroupId++;
|
|
553
|
+
groups.pathToGroup.set(path1, id);
|
|
554
|
+
groups.pathToGroup.set(path2, id);
|
|
555
|
+
groups.groupToPaths.set(id, /* @__PURE__ */ new Set([path1, path2]));
|
|
556
|
+
} else if (g1 !== void 0 && g2 === void 0) {
|
|
557
|
+
groups.pathToGroup.set(path2, g1);
|
|
558
|
+
groups.groupToPaths.get(g1).add(path2);
|
|
559
|
+
} else if (g1 === void 0 && g2 !== void 0) {
|
|
560
|
+
groups.pathToGroup.set(path1, g2);
|
|
561
|
+
groups.groupToPaths.get(g2).add(path1);
|
|
562
|
+
} else if (g1 !== g2) {
|
|
563
|
+
const set1 = groups.groupToPaths.get(g1);
|
|
564
|
+
const set2 = groups.groupToPaths.get(g2);
|
|
565
|
+
const [smallerId, smallerSet, largerId, largerSet] = set1.size < set2.size ? [g1, set1, g2, set2] : [g2, set2, g1, set1];
|
|
566
|
+
for (const path of smallerSet) {
|
|
567
|
+
groups.pathToGroup.set(path, largerId);
|
|
568
|
+
largerSet.add(path);
|
|
569
|
+
}
|
|
570
|
+
groups.groupToPaths.delete(smallerId);
|
|
571
|
+
} else {
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
var removeEdge = (groups, path1, path2) => {
|
|
575
|
+
const edgeKey = makeEdgeKey(path1, path2);
|
|
576
|
+
if (!groups.edges.has(edgeKey)) return;
|
|
577
|
+
groups.edges.delete(edgeKey);
|
|
578
|
+
groups.adjacency.get(path1)?.delete(path2);
|
|
579
|
+
groups.adjacency.get(path2)?.delete(path1);
|
|
580
|
+
const adj1 = groups.adjacency.get(path1);
|
|
581
|
+
const adj2 = groups.adjacency.get(path2);
|
|
582
|
+
const path1Isolated = !adj1 || adj1.size === 0;
|
|
583
|
+
const path2Isolated = !adj2 || adj2.size === 0;
|
|
584
|
+
if (path1Isolated) removeIsolatedPath(groups, path1);
|
|
585
|
+
if (path2Isolated) removeIsolatedPath(groups, path2);
|
|
586
|
+
if (!path1Isolated && !path2Isolated) {
|
|
587
|
+
handleComponentSplit(groups, path1, path2);
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
var getAllGroups = (groups) => [...groups.groupToPaths.values()].map((set2) => [...set2]);
|
|
591
|
+
var getGroupPaths = (groups, path) => {
|
|
592
|
+
const groupId = groups.pathToGroup.get(path);
|
|
593
|
+
if (groupId === void 0) return [];
|
|
594
|
+
return [...groups.groupToPaths.get(groupId)];
|
|
595
|
+
};
|
|
596
|
+
var hasPath = (groups, path) => groups.pathToGroup.has(path);
|
|
597
|
+
var hasEdge = (groups, path1, path2) => groups.edges.has(makeEdgeKey(path1, path2));
|
|
598
|
+
var getPathDegree = (groups, path) => groups.adjacency.get(path)?.size ?? 0;
|
|
599
|
+
|
|
600
|
+
// src/pipeline/normalize-changes.ts
|
|
601
|
+
var normalizeChange = (props) => {
|
|
602
|
+
const { changePath, changeValue, changeMeta, registeredPath, matchMode } = props;
|
|
603
|
+
if (matchMode === "all" && changePath === registeredPath) {
|
|
604
|
+
return { relativePath: null, value: changeValue, meta: changeMeta };
|
|
605
|
+
}
|
|
606
|
+
if (matchMode === "all" && registeredPath.startsWith(changePath + ".")) {
|
|
607
|
+
if (is.not.object(changeValue)) {
|
|
608
|
+
return null;
|
|
609
|
+
}
|
|
610
|
+
const nestedPath = registeredPath.slice(changePath.length + 1);
|
|
611
|
+
const extractedValue = dot.get__unsafe(changeValue, nestedPath);
|
|
612
|
+
if (extractedValue === void 0) {
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
return { relativePath: null, value: extractedValue, meta: changeMeta };
|
|
616
|
+
}
|
|
617
|
+
if (changePath.startsWith(registeredPath + ".")) {
|
|
618
|
+
const relativePath = changePath.slice(registeredPath.length + 1);
|
|
619
|
+
return { relativePath, value: changeValue, meta: changeMeta };
|
|
620
|
+
}
|
|
621
|
+
return null;
|
|
622
|
+
};
|
|
623
|
+
var normalizeChangesForGroups = (props) => {
|
|
624
|
+
const result = [];
|
|
625
|
+
const matchMode = props.matchMode ?? "all";
|
|
626
|
+
for (const change of props.changes) {
|
|
627
|
+
const [changePath, changeValue, changeMeta] = change;
|
|
628
|
+
for (const group of props.pathGroups) {
|
|
629
|
+
let match = null;
|
|
630
|
+
for (const registeredPath of group) {
|
|
631
|
+
const normalized = normalizeChange({
|
|
632
|
+
changePath,
|
|
633
|
+
changeValue,
|
|
634
|
+
changeMeta,
|
|
635
|
+
registeredPath,
|
|
636
|
+
matchMode
|
|
637
|
+
});
|
|
638
|
+
if (normalized) {
|
|
639
|
+
match = { path: registeredPath, normalized };
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (match) {
|
|
644
|
+
result.push({
|
|
645
|
+
matchedPath: match.path,
|
|
646
|
+
relativePath: match.normalized.relativePath,
|
|
647
|
+
value: match.normalized.value,
|
|
648
|
+
meta: match.normalized.meta,
|
|
649
|
+
connectedPaths: group
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return result;
|
|
655
|
+
};
|
|
656
|
+
|
|
657
|
+
// src/pipeline/processors/flip-paths.ts
|
|
658
|
+
var processFlipPaths = (changes, store) => {
|
|
659
|
+
const { flip } = store._internal.graphs;
|
|
660
|
+
const { queue } = store._internal.processing;
|
|
661
|
+
const pathGroups = getAllGroups(flip);
|
|
662
|
+
if (pathGroups.length === 0) return;
|
|
663
|
+
const normalizedChanges = normalizeChangesForGroups({
|
|
664
|
+
changes,
|
|
665
|
+
pathGroups,
|
|
666
|
+
matchMode: "all"
|
|
667
|
+
});
|
|
668
|
+
for (const match of normalizedChanges) {
|
|
669
|
+
if (typeof match.value !== "boolean") continue;
|
|
670
|
+
const meta = { isFlipPathChange: true, ...match.meta };
|
|
671
|
+
for (const neighborPath of match.connectedPaths) {
|
|
672
|
+
if (neighborPath === match.matchedPath) continue;
|
|
673
|
+
const targetPath = match.relativePath ? `${neighborPath}.${match.relativePath}` : neighborPath;
|
|
674
|
+
queueChange({ queue, path: targetPath, value: !match.value, meta });
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
// src/utils/path-utils.ts
|
|
680
|
+
var getPathDepth = (path) => {
|
|
681
|
+
if (!path) return 0;
|
|
682
|
+
return path.split(".").length;
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// src/pipeline/processors/listeners.ts
|
|
686
|
+
var processListener = (props) => {
|
|
687
|
+
if (props.relevantChanges.length === 0) return;
|
|
688
|
+
const scope = props.registration.scope ?? "";
|
|
689
|
+
const scopedState = scope === "" ? props.currentState : dot.get__unsafe(props.currentState, scope);
|
|
690
|
+
const result = props.registration.fn(props.relevantChanges, scopedState);
|
|
691
|
+
if (!result || result.length === 0) return;
|
|
692
|
+
for (const [path, value, changeMeta] of result) {
|
|
693
|
+
const meta = { isListenerChange: true, ...changeMeta };
|
|
694
|
+
queueChange({ queue: props.queue, path, value, meta });
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
var filterAndRelativize = (changes, listenerPath) => {
|
|
698
|
+
const result = [];
|
|
699
|
+
if (listenerPath === "") {
|
|
700
|
+
for (const change of changes) {
|
|
701
|
+
if (!change[0].includes(".")) {
|
|
702
|
+
result.push(change);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return result;
|
|
706
|
+
}
|
|
707
|
+
const prefix = listenerPath + ".";
|
|
708
|
+
for (const change of changes) {
|
|
709
|
+
if (change[0] === listenerPath) {
|
|
710
|
+
result.push([change[0], change[1], change[2]]);
|
|
711
|
+
} else if (change[0].startsWith(prefix)) {
|
|
712
|
+
result.push([change[0].slice(prefix.length), change[1], change[2]]);
|
|
713
|
+
} else {
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
return result;
|
|
717
|
+
};
|
|
718
|
+
var processListeners = (changes, store, currentState) => {
|
|
719
|
+
const { listeners, sortedListenerPaths } = store._internal.graphs;
|
|
720
|
+
const { queue } = store._internal.processing;
|
|
721
|
+
const effectiveChanges = [];
|
|
722
|
+
for (const change of changes) {
|
|
723
|
+
const current = dot.get__unsafe(currentState, change[0]);
|
|
724
|
+
if (current !== change[1]) {
|
|
725
|
+
effectiveChanges.push(change);
|
|
726
|
+
} else {
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (effectiveChanges.length === 0) return;
|
|
730
|
+
const sortedChanges = effectiveChanges.sort(
|
|
731
|
+
(a, b) => getPathDepth(b[0]) - getPathDepth(a[0])
|
|
732
|
+
);
|
|
733
|
+
for (const listenerPath of sortedListenerPaths) {
|
|
734
|
+
const pathListeners = listeners.get(listenerPath);
|
|
735
|
+
const relevantChanges = filterAndRelativize(sortedChanges, listenerPath);
|
|
736
|
+
for (const registration of pathListeners) {
|
|
737
|
+
processListener({
|
|
738
|
+
// Safe: ListenerRegistration and ListenerRegistrationInternal have same runtime shape
|
|
739
|
+
// The function signature difference (ArrayOfChanges vs AnyChange[]) is a compile-time distinction only
|
|
740
|
+
registration,
|
|
741
|
+
relevantChanges,
|
|
742
|
+
currentState,
|
|
743
|
+
queue
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
|
|
749
|
+
// src/pipeline/processors/sync-paths.ts
|
|
750
|
+
var processSyncPaths = (changes, store) => {
|
|
751
|
+
const { sync } = store._internal.graphs;
|
|
752
|
+
const { queue } = store._internal.processing;
|
|
753
|
+
const pathGroups = getAllGroups(sync);
|
|
754
|
+
if (pathGroups.length === 0) return;
|
|
755
|
+
const normalizedChanges = normalizeChangesForGroups({
|
|
756
|
+
changes,
|
|
757
|
+
pathGroups,
|
|
758
|
+
matchMode: "all"
|
|
759
|
+
});
|
|
760
|
+
for (const match of normalizedChanges) {
|
|
761
|
+
const meta = { isSyncPathChange: true, ...match.meta };
|
|
762
|
+
for (const neighborPath of match.connectedPaths) {
|
|
763
|
+
if (neighborPath === match.matchedPath) continue;
|
|
764
|
+
const targetPath = match.relativePath ? `${neighborPath}.${match.relativePath}` : neighborPath;
|
|
765
|
+
queueChange({ queue, path: targetPath, value: match.value, meta });
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// src/pipeline/process-changes.ts
|
|
771
|
+
var processChangesJS = (store, initialChanges) => {
|
|
772
|
+
const { processing } = store._internal;
|
|
773
|
+
const filtered = [];
|
|
774
|
+
for (const change of initialChanges) {
|
|
775
|
+
const current = dot.get__unsafe(store.state, change[0]);
|
|
776
|
+
if (current !== change[1]) {
|
|
777
|
+
filtered.push(change);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
if (filtered.length === 0) return;
|
|
781
|
+
processing.queue = [...filtered];
|
|
782
|
+
const currentState = snapshot(store.state);
|
|
783
|
+
processAggregationWrites(processing.queue, store);
|
|
784
|
+
processSyncPaths(processing.queue, store);
|
|
785
|
+
processFlipPaths(processing.queue, store);
|
|
786
|
+
const preListenerQueue = [];
|
|
787
|
+
for (const change of processing.queue) {
|
|
788
|
+
const current = dot.get__unsafe(store.state, change[0]);
|
|
789
|
+
if (current !== change[1]) {
|
|
790
|
+
preListenerQueue.push(change);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
if (preListenerQueue.length === 0) {
|
|
794
|
+
processing.queue = [];
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
processing.queue = preListenerQueue;
|
|
798
|
+
processListeners(processing.queue, store, currentState);
|
|
799
|
+
if (store._debug) {
|
|
800
|
+
const trackEntry = {
|
|
801
|
+
input: initialChanges.map(([p, v, m]) => [p, v, m]),
|
|
802
|
+
applied: processing.queue.map(([path, value]) => ({
|
|
803
|
+
path,
|
|
804
|
+
value
|
|
805
|
+
})),
|
|
806
|
+
appliedConcerns: [],
|
|
807
|
+
timestamp: Date.now()
|
|
808
|
+
};
|
|
809
|
+
store._debug.calls.push(trackEntry);
|
|
810
|
+
}
|
|
811
|
+
applyBatch(processing.queue, store.state);
|
|
812
|
+
};
|
|
813
|
+
var processChangesLegacy = processChangesJS;
|
|
814
|
+
var processChanges = processChangesLegacy;
|
|
815
|
+
|
|
816
|
+
// src/pipeline/process-changes.wasm-impl.ts
|
|
817
|
+
import { snapshot as snapshot2 } from "valtio";
|
|
818
|
+
var CONCERNS_PREFIX = "_concerns.";
|
|
819
|
+
var CONCERNS_PREFIX_LEN = CONCERNS_PREFIX.length;
|
|
820
|
+
|
|
821
|
+
// src/sideEffects/prebuilts/aggregation.ts
|
|
822
|
+
import { effect as effect3 } from "valtio-reactive";
|
|
823
|
+
var registerAggregations = (store, id, aggregationPairs) => {
|
|
824
|
+
const { aggregations } = store._internal.registrations;
|
|
825
|
+
const disposeCallbacks = [];
|
|
826
|
+
const targets = /* @__PURE__ */ new Set();
|
|
827
|
+
const sources = /* @__PURE__ */ new Set();
|
|
828
|
+
for (const [target, source] of aggregationPairs) {
|
|
829
|
+
targets.add(target);
|
|
830
|
+
sources.add(source);
|
|
831
|
+
}
|
|
832
|
+
for (const target of targets) {
|
|
833
|
+
if (sources.has(target)) {
|
|
834
|
+
throw new Error(
|
|
835
|
+
`[apex-state] Circular aggregation: "${target}" cannot be both target and source`
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
const byTarget = /* @__PURE__ */ new Map();
|
|
840
|
+
for (const [target, source] of aggregationPairs) {
|
|
841
|
+
const existing = byTarget.get(target) ?? [];
|
|
842
|
+
existing.push(source);
|
|
843
|
+
byTarget.set(target, existing);
|
|
844
|
+
}
|
|
845
|
+
const createdAggregations = [];
|
|
846
|
+
for (const [targetPath, sourcePaths] of byTarget) {
|
|
847
|
+
const aggregation = {
|
|
848
|
+
targetPath,
|
|
849
|
+
sourcePaths,
|
|
850
|
+
id: `${id}:${targetPath}`
|
|
851
|
+
// Optional: for debugging
|
|
852
|
+
};
|
|
853
|
+
const existing = aggregations.get(targetPath) ?? [];
|
|
854
|
+
existing.push(aggregation);
|
|
855
|
+
aggregations.set(targetPath, existing);
|
|
856
|
+
createdAggregations.push(aggregation);
|
|
857
|
+
const dispose = effect3(() => {
|
|
858
|
+
if (sourcePaths.length === 0) {
|
|
859
|
+
dot.set__unsafe(store.state, targetPath, null);
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
const allEqual = dot.same(store.state, ...sourcePaths);
|
|
863
|
+
const result = allEqual ? dot.get__unsafe(store.state, sourcePaths[0]) : void 0;
|
|
864
|
+
dot.set__unsafe(store.state, targetPath, result);
|
|
865
|
+
});
|
|
866
|
+
disposeCallbacks.push(dispose);
|
|
867
|
+
}
|
|
868
|
+
return () => {
|
|
869
|
+
disposeCallbacks.forEach((dispose) => dispose());
|
|
870
|
+
for (const aggregation of createdAggregations) {
|
|
871
|
+
const items = aggregations.get(aggregation.targetPath) ?? [];
|
|
872
|
+
const filtered = items.filter((item) => item !== aggregation);
|
|
873
|
+
if (filtered.length === 0) {
|
|
874
|
+
aggregations.delete(aggregation.targetPath);
|
|
875
|
+
} else {
|
|
876
|
+
aggregations.set(aggregation.targetPath, filtered);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
// src/sideEffects/prebuilts/flip.ts
|
|
883
|
+
var registerFlipPair = (store, path1, path2) => {
|
|
884
|
+
const { flip } = store._internal.graphs;
|
|
885
|
+
addEdge(flip, path1, path2);
|
|
886
|
+
return () => {
|
|
887
|
+
if (hasEdge(flip, path1, path2)) {
|
|
888
|
+
removeEdge(flip, path1, path2);
|
|
889
|
+
}
|
|
890
|
+
if (hasPath(flip, path1) && getPathDegree(flip, path1) === 0) {
|
|
891
|
+
removeEdge(flip, path1, path1);
|
|
892
|
+
}
|
|
893
|
+
if (hasPath(flip, path2) && getPathDegree(flip, path2) === 0) {
|
|
894
|
+
removeEdge(flip, path2, path2);
|
|
895
|
+
}
|
|
896
|
+
};
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
// src/sideEffects/prebuilts/listeners.ts
|
|
900
|
+
var nextSubscriberId = 0;
|
|
901
|
+
var updateSortedListenerPaths = (graphs) => {
|
|
902
|
+
graphs.sortedListenerPaths = Array.from(graphs.listeners.keys()).sort(
|
|
903
|
+
(a, b) => getPathDepth(b) - getPathDepth(a)
|
|
904
|
+
);
|
|
905
|
+
};
|
|
906
|
+
var validateScopeAndPath = (path, scope) => {
|
|
907
|
+
if (path === null || scope === null) return;
|
|
908
|
+
if (path === scope) return;
|
|
909
|
+
if (!path.startsWith(scope + ".")) {
|
|
910
|
+
throw new Error(
|
|
911
|
+
`Invalid listener: scope '${scope}' must be a parent/ancestor of path '${path}', or one must be null`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
};
|
|
915
|
+
var registerListenerLegacy = (store, registration) => {
|
|
916
|
+
const { graphs } = store._internal;
|
|
917
|
+
const { listeners, listenerHandlers } = graphs;
|
|
918
|
+
validateScopeAndPath(registration.path, registration.scope);
|
|
919
|
+
const subscriberId = nextSubscriberId++;
|
|
920
|
+
const mapKey = registration.path ?? "";
|
|
921
|
+
const existing = listeners.get(mapKey) ?? [];
|
|
922
|
+
const originalFn = registration.fn;
|
|
923
|
+
registration.fn = (changes, state) => store._internal.timing.run("listeners", () => originalFn(changes, state), {
|
|
924
|
+
path: mapKey,
|
|
925
|
+
name: "listener"
|
|
926
|
+
});
|
|
927
|
+
listeners.set(mapKey, [...existing, registration]);
|
|
928
|
+
listenerHandlers.set(subscriberId, {
|
|
929
|
+
scope: registration.scope,
|
|
930
|
+
fn: registration.fn
|
|
931
|
+
});
|
|
932
|
+
updateSortedListenerPaths(graphs);
|
|
933
|
+
return () => {
|
|
934
|
+
const list = listeners.get(mapKey);
|
|
935
|
+
if (list) {
|
|
936
|
+
const filtered = list.filter((l) => l !== registration);
|
|
937
|
+
if (filtered.length > 0) {
|
|
938
|
+
listeners.set(mapKey, filtered);
|
|
939
|
+
} else {
|
|
940
|
+
listeners.delete(mapKey);
|
|
941
|
+
}
|
|
942
|
+
updateSortedListenerPaths(graphs);
|
|
943
|
+
}
|
|
944
|
+
listenerHandlers.delete(subscriberId);
|
|
945
|
+
};
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
// src/sideEffects/prebuilts/sync.ts
|
|
949
|
+
var collectGroupSyncChanges = (store, component) => {
|
|
950
|
+
const valueCounts = /* @__PURE__ */ new Map();
|
|
951
|
+
for (const path of component) {
|
|
952
|
+
const value = dot.get__unsafe(store.state, path);
|
|
953
|
+
if (is.not.nil(value)) {
|
|
954
|
+
const count = valueCounts.get(value) ?? 0;
|
|
955
|
+
valueCounts.set(value, count + 1);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
let mostCommonValue = void 0;
|
|
959
|
+
let maxCount = 0;
|
|
960
|
+
for (const [value, count] of valueCounts) {
|
|
961
|
+
if (count > maxCount) {
|
|
962
|
+
maxCount = count;
|
|
963
|
+
mostCommonValue = value;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
const changes = [];
|
|
967
|
+
if (is.not.undefined(mostCommonValue)) {
|
|
968
|
+
for (const path of component) {
|
|
969
|
+
const currentValue = dot.get__unsafe(store.state, path);
|
|
970
|
+
if (currentValue !== mostCommonValue) {
|
|
971
|
+
changes.push([
|
|
972
|
+
path,
|
|
973
|
+
mostCommonValue,
|
|
974
|
+
{ isSyncPathChange: true }
|
|
975
|
+
]);
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return changes;
|
|
980
|
+
};
|
|
981
|
+
var makeSyncEdgeCleanup = (sync, path1, path2) => () => {
|
|
982
|
+
if (hasEdge(sync, path1, path2)) {
|
|
983
|
+
removeEdge(sync, path1, path2);
|
|
984
|
+
}
|
|
985
|
+
if (hasPath(sync, path1) && getPathDegree(sync, path1) === 0) {
|
|
986
|
+
removeEdge(sync, path1, path1);
|
|
987
|
+
}
|
|
988
|
+
if (hasPath(sync, path2) && getPathDegree(sync, path2) === 0) {
|
|
989
|
+
removeEdge(sync, path2, path2);
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
var registerSyncPairsBatch = (store, pairs) => {
|
|
993
|
+
const { sync } = store._internal.graphs;
|
|
994
|
+
const edgeCleanups = [];
|
|
995
|
+
for (const [path1, path2] of pairs) {
|
|
996
|
+
addEdge(sync, path1, path2);
|
|
997
|
+
edgeCleanups.push(makeSyncEdgeCleanup(sync, path1, path2));
|
|
998
|
+
}
|
|
999
|
+
const processedGroups = /* @__PURE__ */ new Set();
|
|
1000
|
+
const allChanges = [];
|
|
1001
|
+
for (const [path1] of pairs) {
|
|
1002
|
+
const groupId = sync.pathToGroup.get(path1);
|
|
1003
|
+
if (groupId === void 0 || processedGroups.has(groupId)) continue;
|
|
1004
|
+
processedGroups.add(groupId);
|
|
1005
|
+
const component = getGroupPaths(sync, path1);
|
|
1006
|
+
const changes = collectGroupSyncChanges(store, component);
|
|
1007
|
+
allChanges.push(...changes);
|
|
1008
|
+
}
|
|
1009
|
+
if (allChanges.length > 0) {
|
|
1010
|
+
processChanges(store, allChanges);
|
|
1011
|
+
}
|
|
1012
|
+
return () => edgeCleanups.forEach((fn) => fn());
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
// src/sideEffects/registration.ts
|
|
1016
|
+
var registerSideEffectsImpl = (store, id, effects) => {
|
|
1017
|
+
const cleanups = [];
|
|
1018
|
+
if (effects.syncPaths) {
|
|
1019
|
+
const cleanup = registerSyncPairsBatch(store, effects.syncPaths);
|
|
1020
|
+
cleanups.push(cleanup);
|
|
1021
|
+
}
|
|
1022
|
+
if (effects.flipPaths) {
|
|
1023
|
+
for (const [path1, path2] of effects.flipPaths) {
|
|
1024
|
+
const cleanup = registerFlipPair(store, path1, path2);
|
|
1025
|
+
cleanups.push(cleanup);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
if (effects.aggregations) {
|
|
1029
|
+
const cleanup = registerAggregations(store, id, effects.aggregations);
|
|
1030
|
+
cleanups.push(cleanup);
|
|
1031
|
+
}
|
|
1032
|
+
if (effects.listeners) {
|
|
1033
|
+
for (const listener of effects.listeners) {
|
|
1034
|
+
const cleanup = registerListenerLegacy(store, listener);
|
|
1035
|
+
cleanups.push(cleanup);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
const combinedCleanup = () => cleanups.forEach((fn) => fn());
|
|
1039
|
+
store._internal.registrations.sideEffectCleanups.set(id, combinedCleanup);
|
|
1040
|
+
return () => {
|
|
1041
|
+
combinedCleanup();
|
|
1042
|
+
store._internal.registrations.sideEffectCleanups.delete(id);
|
|
1043
|
+
};
|
|
1044
|
+
};
|
|
1045
|
+
var registerSideEffects = (store, id, effects) => store._internal.timing.run(
|
|
1046
|
+
"registration",
|
|
1047
|
+
() => registerSideEffectsImpl(store, id, effects),
|
|
1048
|
+
{ path: id, name: "sideEffects" }
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
// src/utils/json.ts
|
|
1052
|
+
var createFastJson = (placeholders = []) => {
|
|
1053
|
+
const encodeMap = /* @__PURE__ */ new Map();
|
|
1054
|
+
const decodeMap = /* @__PURE__ */ new Map();
|
|
1055
|
+
for (const p of placeholders) {
|
|
1056
|
+
encodeMap.set(p.value, p.encoded);
|
|
1057
|
+
decodeMap.set(p.encoded, p.value);
|
|
1058
|
+
}
|
|
1059
|
+
const stringify = (value) => {
|
|
1060
|
+
if (encodeMap.has(value)) return encodeMap.get(value);
|
|
1061
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
1062
|
+
return String(value);
|
|
1063
|
+
if (value === null) return "null";
|
|
1064
|
+
return JSON.stringify(value);
|
|
1065
|
+
};
|
|
1066
|
+
const parse = (json) => {
|
|
1067
|
+
if (decodeMap.has(json)) return decodeMap.get(json);
|
|
1068
|
+
const c = json.charCodeAt(0);
|
|
1069
|
+
if (c >= 48 && c <= 57 || c === 45) return Number(json);
|
|
1070
|
+
if (json === "true") return true;
|
|
1071
|
+
if (json === "false") return false;
|
|
1072
|
+
if (json === "null") return null;
|
|
1073
|
+
return JSON.parse(json);
|
|
1074
|
+
};
|
|
1075
|
+
return { stringify, parse };
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
// src/wasm/bridge.ts
|
|
1079
|
+
var UNDEFINED_SENTINEL_JSON = '"__APEX_UNDEFINED__"';
|
|
1080
|
+
var { stringify: fastStringify, parse: fastParse } = createFastJson([
|
|
1081
|
+
{ value: void 0, encoded: UNDEFINED_SENTINEL_JSON }
|
|
1082
|
+
]);
|
|
1083
|
+
|
|
1084
|
+
// src/store/provider.tsx
|
|
1085
|
+
import { useEffect, useMemo, useState } from "react";
|
|
1086
|
+
import { proxy, ref } from "valtio";
|
|
1087
|
+
|
|
1088
|
+
// src/utils/derive-values.ts
|
|
1089
|
+
import { computed } from "valtio-reactive";
|
|
1090
|
+
|
|
1091
|
+
// src/store/provider.tsx
|
|
1092
|
+
import { jsx } from "react/jsx-runtime";
|
|
1093
|
+
|
|
1094
|
+
// src/hooks/use-buffered-field.ts
|
|
1095
|
+
import { useCallback as useCallback2, useState as useState2 } from "react";
|
|
1096
|
+
var useBufferedField = (field) => {
|
|
1097
|
+
const { value: storedValue, setValue: setStoredValue } = field;
|
|
1098
|
+
const [localValue, setLocalValue] = useState2(null);
|
|
1099
|
+
const isEditing = localValue !== null;
|
|
1100
|
+
const isDirty = isEditing && localValue !== storedValue;
|
|
1101
|
+
const setValue = useCallback2((newValue) => {
|
|
1102
|
+
setLocalValue(newValue);
|
|
1103
|
+
}, []);
|
|
1104
|
+
const commit = useCallback2(() => {
|
|
1105
|
+
if (localValue !== null) {
|
|
1106
|
+
setStoredValue(localValue);
|
|
1107
|
+
}
|
|
1108
|
+
setLocalValue(null);
|
|
1109
|
+
}, [localValue, setStoredValue]);
|
|
1110
|
+
const cancel = useCallback2(() => {
|
|
1111
|
+
setLocalValue(null);
|
|
1112
|
+
}, []);
|
|
1113
|
+
const value = isEditing ? localValue : storedValue;
|
|
1114
|
+
return { value, setValue, commit, cancel, isDirty };
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
// src/hooks/use-keyboard-select.ts
|
|
1118
|
+
import { useCallback as useCallback3, useRef } from "react";
|
|
1119
|
+
var useKeyboardSelect = (field, config) => {
|
|
1120
|
+
const { setValue } = field;
|
|
1121
|
+
const { options, debounceMs = 500, matchFromStart = true } = config;
|
|
1122
|
+
const searchRef = useRef("");
|
|
1123
|
+
const timeoutRef = useRef(null);
|
|
1124
|
+
const onKeyDown = useCallback3(
|
|
1125
|
+
(e) => {
|
|
1126
|
+
if (e.key.length !== 1) return;
|
|
1127
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
1128
|
+
const char = e.key.toLowerCase();
|
|
1129
|
+
if (timeoutRef.current) {
|
|
1130
|
+
clearTimeout(timeoutRef.current);
|
|
1131
|
+
}
|
|
1132
|
+
searchRef.current += char;
|
|
1133
|
+
const search = searchRef.current;
|
|
1134
|
+
const match = options.find((opt) => {
|
|
1135
|
+
const label = opt.label.toLowerCase();
|
|
1136
|
+
return matchFromStart ? label.startsWith(search) : label.includes(search);
|
|
1137
|
+
});
|
|
1138
|
+
if (match) {
|
|
1139
|
+
setValue(match.value);
|
|
1140
|
+
}
|
|
1141
|
+
timeoutRef.current = setTimeout(() => {
|
|
1142
|
+
searchRef.current = "";
|
|
1143
|
+
}, debounceMs);
|
|
1144
|
+
},
|
|
1145
|
+
[options, setValue, debounceMs, matchFromStart]
|
|
1146
|
+
);
|
|
1147
|
+
return { ...field, onKeyDown };
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// src/hooks/use-throttled-field.ts
|
|
1151
|
+
import { useCallback as useCallback4, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
1152
|
+
var useThrottledField = (field, config) => {
|
|
1153
|
+
const { setValue: originalSetValue, ...rest } = field;
|
|
1154
|
+
const { ms } = config;
|
|
1155
|
+
const throttleRef = useRef2({
|
|
1156
|
+
timeoutId: null,
|
|
1157
|
+
lastFlushTime: 0,
|
|
1158
|
+
pendingValue: void 0,
|
|
1159
|
+
pendingArgs: void 0,
|
|
1160
|
+
hasPending: false
|
|
1161
|
+
});
|
|
1162
|
+
const setValue = useCallback4(
|
|
1163
|
+
(newValue, ...args) => {
|
|
1164
|
+
const now = Date.now();
|
|
1165
|
+
const ref2 = throttleRef.current;
|
|
1166
|
+
const timeSinceLastFlush = now - ref2.lastFlushTime;
|
|
1167
|
+
if (timeSinceLastFlush >= ms) {
|
|
1168
|
+
ref2.lastFlushTime = now;
|
|
1169
|
+
originalSetValue(newValue, ...args);
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
ref2.pendingValue = newValue;
|
|
1173
|
+
ref2.pendingArgs = args;
|
|
1174
|
+
ref2.hasPending = true;
|
|
1175
|
+
if (!ref2.timeoutId) {
|
|
1176
|
+
const remainingTime = ms - timeSinceLastFlush;
|
|
1177
|
+
ref2.timeoutId = setTimeout(() => {
|
|
1178
|
+
ref2.timeoutId = null;
|
|
1179
|
+
ref2.lastFlushTime = Date.now();
|
|
1180
|
+
if (ref2.hasPending) {
|
|
1181
|
+
originalSetValue(
|
|
1182
|
+
ref2.pendingValue,
|
|
1183
|
+
...ref2.pendingArgs
|
|
1184
|
+
);
|
|
1185
|
+
ref2.hasPending = false;
|
|
1186
|
+
ref2.pendingValue = void 0;
|
|
1187
|
+
ref2.pendingArgs = void 0;
|
|
1188
|
+
}
|
|
1189
|
+
}, remainingTime);
|
|
1190
|
+
}
|
|
1191
|
+
},
|
|
1192
|
+
[originalSetValue, ms]
|
|
1193
|
+
);
|
|
1194
|
+
useEffect2(() => {
|
|
1195
|
+
return () => {
|
|
1196
|
+
if (throttleRef.current.timeoutId) {
|
|
1197
|
+
clearTimeout(throttleRef.current.timeoutId);
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}, []);
|
|
1201
|
+
return { ...rest, setValue };
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1204
|
+
// src/hooks/use-transformed-field.ts
|
|
1205
|
+
import { useCallback as useCallback5, useMemo as useMemo2 } from "react";
|
|
1206
|
+
var useTransformedField = (field, config) => {
|
|
1207
|
+
const { value: storedValue, setValue: setStoredValue, ...rest } = field;
|
|
1208
|
+
const { to, from } = config;
|
|
1209
|
+
const value = useMemo2(() => to(storedValue), [storedValue, to]);
|
|
1210
|
+
const setValue = useCallback5(
|
|
1211
|
+
(displayValue) => {
|
|
1212
|
+
const storedVal = from(displayValue);
|
|
1213
|
+
setStoredValue(storedVal);
|
|
1214
|
+
},
|
|
1215
|
+
[from, setStoredValue]
|
|
1216
|
+
);
|
|
1217
|
+
return { ...rest, value, setValue };
|
|
1218
|
+
};
|
|
1219
|
+
|
|
1220
|
+
// src/utils/hash-key.ts
|
|
1221
|
+
var _ = (id) => id;
|
|
1222
|
+
var rejectDynamic = (path) => {
|
|
1223
|
+
const parts = path.split(".");
|
|
1224
|
+
for (const part of parts) {
|
|
1225
|
+
if (part === "[*]") {
|
|
1226
|
+
throw new Error(
|
|
1227
|
+
`Path contains [*] hash key which is not allowed in store operations. Use concrete paths only.`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
var hashKey = {
|
|
1233
|
+
/** Reject paths with dynamic hash keys */
|
|
1234
|
+
rejectDynamic,
|
|
1235
|
+
/** Alias for _ function */
|
|
1236
|
+
_
|
|
1237
|
+
};
|
|
1238
|
+
|
|
1239
|
+
// src/utils/apply-changes.ts
|
|
1240
|
+
var applyChangesToObject = (obj, changes) => {
|
|
1241
|
+
const result = structuredClone(obj);
|
|
1242
|
+
for (const [path, value] of changes) {
|
|
1243
|
+
dot.set__unsafe(result, path, value);
|
|
1244
|
+
}
|
|
1245
|
+
return result;
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// src/testing/index.ts
|
|
1249
|
+
var __state = proxy2({
|
|
1250
|
+
/** Current store state (reactive valtio proxy) */
|
|
1251
|
+
value: {},
|
|
1252
|
+
/** Log of all setValue / setChanges calls */
|
|
1253
|
+
calls: [],
|
|
1254
|
+
/** Log of all useConcerns / useSideEffects registrations */
|
|
1255
|
+
effects: []
|
|
1256
|
+
});
|
|
1257
|
+
var __flush = async () => {
|
|
1258
|
+
await act(async () => {
|
|
1259
|
+
});
|
|
1260
|
+
};
|
|
1261
|
+
var __reset = () => {
|
|
1262
|
+
const keys = Object.keys(__state.value);
|
|
1263
|
+
keys.forEach((key) => {
|
|
1264
|
+
Reflect.deleteProperty(__state.value, key);
|
|
1265
|
+
});
|
|
1266
|
+
__state.calls.length = 0;
|
|
1267
|
+
__state.effects.length = 0;
|
|
1268
|
+
};
|
|
1269
|
+
var __typedMock = () => {
|
|
1270
|
+
const api = {
|
|
1271
|
+
set: (path, value) => {
|
|
1272
|
+
dot.set__unsafe(__state.value, path, value);
|
|
1273
|
+
return api;
|
|
1274
|
+
},
|
|
1275
|
+
state: __state,
|
|
1276
|
+
getState: () => snapshot4(__state.value),
|
|
1277
|
+
flush: __flush,
|
|
1278
|
+
reset: __reset
|
|
1279
|
+
};
|
|
1280
|
+
return api;
|
|
1281
|
+
};
|
|
1282
|
+
var __mocked = {
|
|
1283
|
+
/** Reactive proxy — access .value, .calls, .effects for assertions */
|
|
1284
|
+
state: __state,
|
|
1285
|
+
/**
|
|
1286
|
+
* Seed mock state and return typed chainable.
|
|
1287
|
+
* - `set<T>()` — establish type, no seeding
|
|
1288
|
+
* - `set<T>(data)` — merge data into state, establish type
|
|
1289
|
+
* Subsequent `.set(path, value)` calls are type-safe against T.
|
|
1290
|
+
*/
|
|
1291
|
+
set: (data) => {
|
|
1292
|
+
if (data) {
|
|
1293
|
+
Object.assign(__state.value, data);
|
|
1294
|
+
}
|
|
1295
|
+
return __typedMock();
|
|
1296
|
+
},
|
|
1297
|
+
/** Get an immutable snapshot of the current state */
|
|
1298
|
+
getState: () => snapshot4(__state.value),
|
|
1299
|
+
/** Flush pending valtio-triggered React renders */
|
|
1300
|
+
flush: __flush,
|
|
1301
|
+
/** Reset all mock state between tests */
|
|
1302
|
+
reset: __reset
|
|
1303
|
+
};
|
|
1304
|
+
var createGenericStore2 = (_config) => {
|
|
1305
|
+
const Provider = ({
|
|
1306
|
+
initialState,
|
|
1307
|
+
children
|
|
1308
|
+
}) => {
|
|
1309
|
+
if (initialState && typeof initialState === "object") {
|
|
1310
|
+
Object.assign(__state.value, initialState);
|
|
1311
|
+
}
|
|
1312
|
+
return React.createElement(React.Fragment, null, children);
|
|
1313
|
+
};
|
|
1314
|
+
Provider.displayName = "MockStoreProvider";
|
|
1315
|
+
const useStore = (path) => {
|
|
1316
|
+
const snap = useSnapshot2(__state);
|
|
1317
|
+
const value = dot.get__unsafe(snap.value, path);
|
|
1318
|
+
const setValue = (newValue, meta) => {
|
|
1319
|
+
__state.calls.push({ path, value: newValue, meta });
|
|
1320
|
+
dot.set__unsafe(__state.value, path, newValue);
|
|
1321
|
+
};
|
|
1322
|
+
return [value, setValue];
|
|
1323
|
+
};
|
|
1324
|
+
const useFieldStore = (path) => {
|
|
1325
|
+
const [value, setValue] = useStore(path);
|
|
1326
|
+
return { value, setValue };
|
|
1327
|
+
};
|
|
1328
|
+
const useJitStore = () => {
|
|
1329
|
+
const snap = useSnapshot2(__state);
|
|
1330
|
+
return {
|
|
1331
|
+
proxyValue: snap.value,
|
|
1332
|
+
setChanges: (changes) => {
|
|
1333
|
+
for (const [path, value, meta] of changes) {
|
|
1334
|
+
__state.calls.push({ path, value, meta });
|
|
1335
|
+
dot.set__unsafe(__state.value, path, value);
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1338
|
+
getState: () => snapshot4(__state.value)
|
|
1339
|
+
};
|
|
1340
|
+
};
|
|
1341
|
+
const useSideEffects = (id, effects) => {
|
|
1342
|
+
__state.effects.push({ id, type: "sideEffects", registration: effects });
|
|
1343
|
+
};
|
|
1344
|
+
const useConcerns = (id, registration) => {
|
|
1345
|
+
__state.effects.push({ id, type: "concerns", registration });
|
|
1346
|
+
};
|
|
1347
|
+
const withConcerns = () => ({
|
|
1348
|
+
useFieldStore
|
|
1349
|
+
});
|
|
1350
|
+
const api = {
|
|
1351
|
+
Provider,
|
|
1352
|
+
useStore,
|
|
1353
|
+
useFieldStore,
|
|
1354
|
+
useJitStore,
|
|
1355
|
+
useSideEffects,
|
|
1356
|
+
useConcerns,
|
|
1357
|
+
withConcerns
|
|
1358
|
+
};
|
|
1359
|
+
return api;
|
|
1360
|
+
};
|
|
1361
|
+
export {
|
|
1362
|
+
_,
|
|
1363
|
+
__mocked,
|
|
1364
|
+
applyChangesToObject,
|
|
1365
|
+
createGenericStore2 as createGenericStore,
|
|
1366
|
+
defaultConcerns,
|
|
1367
|
+
dot,
|
|
1368
|
+
evaluateBoolLogic,
|
|
1369
|
+
extractPlaceholders,
|
|
1370
|
+
findConcern,
|
|
1371
|
+
hashKey,
|
|
1372
|
+
interpolateTemplate,
|
|
1373
|
+
is,
|
|
1374
|
+
prebuilts_exports as prebuilts,
|
|
1375
|
+
registerFlipPair,
|
|
1376
|
+
registerListenerLegacy,
|
|
1377
|
+
registerSideEffects,
|
|
1378
|
+
registerSyncPairsBatch,
|
|
1379
|
+
useBufferedField,
|
|
1380
|
+
useKeyboardSelect,
|
|
1381
|
+
useThrottledField,
|
|
1382
|
+
useTransformedField
|
|
1383
|
+
};
|
|
1384
|
+
//# sourceMappingURL=index.js.map
|