signalium 2.2.2 → 2.3.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/CHANGELOG.md +18 -0
- package/dist/cjs/development/config-B0MtLBgx.js.map +1 -1
- package/dist/cjs/development/{debug-DuXQhd5q.js → debug-gCDAvnLM.js} +237 -214
- package/dist/cjs/development/debug-gCDAvnLM.js.map +1 -0
- package/dist/cjs/development/debug.js +9 -3
- package/dist/cjs/development/debug.js.map +1 -1
- package/dist/cjs/development/index.js +8 -8
- package/dist/cjs/development/react/index.js +43 -38
- package/dist/cjs/development/react/index.js.map +1 -1
- package/dist/cjs/development/snapshot-Di0yziPX.js +147 -0
- package/dist/cjs/development/snapshot-Di0yziPX.js.map +1 -0
- package/dist/cjs/development/transform/index.js +137 -118
- package/dist/cjs/development/transform/index.js.map +1 -1
- package/dist/cjs/development/utils.js +5 -3
- package/dist/cjs/development/utils.js.map +1 -1
- package/dist/cjs/production/config-B0MtLBgx.js.map +1 -1
- package/dist/cjs/production/{contexts-DOH1tHd8.js → contexts-Wgq2NOVX.js} +156 -140
- package/dist/cjs/production/contexts-Wgq2NOVX.js.map +1 -0
- package/dist/cjs/production/debug.js +61 -66
- package/dist/cjs/production/debug.js.map +1 -1
- package/dist/cjs/production/index.js +8 -8
- package/dist/cjs/production/react/index.js +43 -38
- package/dist/cjs/production/react/index.js.map +1 -1
- package/dist/cjs/production/snapshot-YJJyLbxS.js +147 -0
- package/dist/cjs/production/snapshot-YJJyLbxS.js.map +1 -0
- package/dist/cjs/production/transform/index.js +137 -118
- package/dist/cjs/production/transform/index.js.map +1 -1
- package/dist/cjs/production/utils.js +5 -3
- package/dist/cjs/production/utils.js.map +1 -1
- package/dist/esm/development/config-CPQL7hX-.js.map +1 -1
- package/dist/esm/development/{debug-E2E1pZe5.js → debug-AoHfqs62.js} +221 -196
- package/dist/esm/development/debug-AoHfqs62.js.map +1 -0
- package/dist/esm/development/debug.js +1 -1
- package/dist/esm/development/index.js +6 -6
- package/dist/esm/development/react/index.js +43 -38
- package/dist/esm/development/react/index.js.map +1 -1
- package/dist/esm/development/snapshot-Bq0Um_hQ.js +148 -0
- package/dist/esm/development/snapshot-Bq0Um_hQ.js.map +1 -0
- package/dist/esm/development/transform/index.js +137 -118
- package/dist/esm/development/transform/index.js.map +1 -1
- package/dist/esm/development/utils.js +7 -4
- package/dist/esm/development/utils.js.map +1 -1
- package/dist/esm/internals/async.d.ts.map +1 -1
- package/dist/esm/internals/core-api.d.ts +2 -2
- package/dist/esm/internals/core-api.d.ts.map +1 -1
- package/dist/esm/internals/edge.d.ts +4 -4
- package/dist/esm/internals/edge.d.ts.map +1 -1
- package/dist/esm/internals/reactive.d.ts +14 -4
- package/dist/esm/internals/reactive.d.ts.map +1 -1
- package/dist/esm/internals/scheduling.d.ts.map +1 -1
- package/dist/esm/internals/signal.d.ts.map +1 -1
- package/dist/esm/internals/utils/snapshot.d.ts +29 -0
- package/dist/esm/internals/utils/snapshot.d.ts.map +1 -0
- package/dist/esm/production/config-CPQL7hX-.js.map +1 -1
- package/dist/esm/production/{contexts-Dj9Y86xW.js → contexts-X0gSj6rQ.js} +159 -143
- package/dist/esm/production/contexts-X0gSj6rQ.js.map +1 -0
- package/dist/esm/production/debug.js +51 -54
- package/dist/esm/production/debug.js.map +1 -1
- package/dist/esm/production/index.js +7 -7
- package/dist/esm/production/react/index.js +43 -38
- package/dist/esm/production/react/index.js.map +1 -1
- package/dist/esm/production/snapshot-CDS1d8mq.js +148 -0
- package/dist/esm/production/snapshot-CDS1d8mq.js.map +1 -0
- package/dist/esm/production/transform/index.js +137 -118
- package/dist/esm/production/transform/index.js.map +1 -1
- package/dist/esm/production/utils.js +7 -4
- package/dist/esm/production/utils.js.map +1 -1
- package/dist/esm/react/index.d.ts +1 -1
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/provider.d.ts.map +1 -1
- package/dist/esm/react/use-reactive.d.ts +1 -0
- package/dist/esm/react/use-reactive.d.ts.map +1 -1
- package/dist/esm/transform/callback.d.ts.map +1 -1
- package/dist/esm/transform/promise.d.ts.map +1 -1
- package/dist/esm/types.d.ts +5 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.d.ts.map +1 -1
- package/package.json +7 -5
- package/dist/cjs/development/core-api-C8J7lYBC.js +0 -55
- package/dist/cjs/development/core-api-C8J7lYBC.js.map +0 -1
- package/dist/cjs/development/debug-DuXQhd5q.js.map +0 -1
- package/dist/cjs/production/contexts-DOH1tHd8.js.map +0 -1
- package/dist/cjs/production/core-api-Cx2_AumW.js +0 -55
- package/dist/cjs/production/core-api-Cx2_AumW.js.map +0 -1
- package/dist/esm/development/core-api-CF5aK2Lx.js +0 -56
- package/dist/esm/development/core-api-CF5aK2Lx.js.map +0 -1
- package/dist/esm/development/debug-E2E1pZe5.js.map +0 -1
- package/dist/esm/production/contexts-Dj9Y86xW.js.map +0 -1
- package/dist/esm/production/core-api-D_uw3umM.js +0 -56
- package/dist/esm/production/core-api-D_uw3umM.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext as useContext$1,
|
|
3
|
-
import { f as getCurrentConsumer, h as getGlobalScope, S as SignalScope,
|
|
4
|
-
import { g as getReactiveFnAndDefinition } from "../
|
|
2
|
+
import { createContext, useContext as useContext$1, useMemo, useRef, useSyncExternalStore, useCallback } from "react";
|
|
3
|
+
import { f as getCurrentConsumer, h as getGlobalScope, S as SignalScope, j as hashValue, a as createReactiveSignal, r as runSignal, k as signal, i as isReactivePromise, l as isRelay } from "../contexts-X0gSj6rQ.js";
|
|
4
|
+
import { g as getReactiveFnAndDefinition, r as reactiveSignal, s as snapshot } from "../snapshot-CDS1d8mq.js";
|
|
5
5
|
const ScopeContext = createContext(void 0);
|
|
6
6
|
function useScope() {
|
|
7
7
|
return useContext$1(ScopeContext);
|
|
@@ -13,20 +13,14 @@ function useContext(context) {
|
|
|
13
13
|
}
|
|
14
14
|
return scope.getContext(context) ?? context.defaultValue;
|
|
15
15
|
}
|
|
16
|
-
function ContextProvider({
|
|
17
|
-
children,
|
|
18
|
-
contexts = [],
|
|
19
|
-
inherit = true
|
|
20
|
-
}) {
|
|
16
|
+
function ContextProvider({ children, contexts = [], inherit = true }) {
|
|
21
17
|
const parentScope = useContext$1(ScopeContext) ?? getGlobalScope();
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
return /* @__PURE__ */ jsx(ScopeContext.Provider, { value: scopeRef.current, children });
|
|
18
|
+
const scope = useMemo(
|
|
19
|
+
() => new SignalScope(contexts, inherit ? parentScope : void 0),
|
|
20
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21
|
+
[parentScope, inherit, hashValue(contexts)]
|
|
22
|
+
);
|
|
23
|
+
return jsx(ScopeContext.Provider, { value: scope, children });
|
|
30
24
|
}
|
|
31
25
|
const SuspendSignalsContext = createContext(false);
|
|
32
26
|
const SuspendSignalsProvider = SuspendSignalsContext.Provider;
|
|
@@ -42,31 +36,22 @@ function component(fn) {
|
|
|
42
36
|
propsRef.current = props;
|
|
43
37
|
let signal2 = fnSignalRef.current;
|
|
44
38
|
if (signal2 === void 0) {
|
|
45
|
-
fnSignalRef.current = signal2 = createReactiveSignal(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
[],
|
|
53
|
-
void 0,
|
|
54
|
-
scope
|
|
55
|
-
);
|
|
39
|
+
fnSignalRef.current = signal2 = createReactiveSignal({
|
|
40
|
+
compute: () => fn(propsRef.current),
|
|
41
|
+
equals: () => false,
|
|
42
|
+
isRelay: false,
|
|
43
|
+
tracer: void 0
|
|
44
|
+
}, [], void 0, scope);
|
|
56
45
|
signal2._isLazy = true;
|
|
57
46
|
}
|
|
58
47
|
signal2.setSuspended(suspended);
|
|
59
|
-
useSyncExternalStore(
|
|
60
|
-
signal2.addListenerLazy(),
|
|
61
|
-
() => signal2.updatedCount,
|
|
62
|
-
() => signal2.updatedCount
|
|
63
|
-
);
|
|
48
|
+
useSyncExternalStore(signal2.addListenerLazy(), () => signal2.updatedCount, () => signal2.updatedCount);
|
|
64
49
|
runSignal(signal2);
|
|
65
50
|
return signal2.value;
|
|
66
51
|
};
|
|
67
52
|
return (props) => {
|
|
68
53
|
const hash = hashValue(props);
|
|
69
|
-
return useMemo(() =>
|
|
54
|
+
return useMemo(() => jsx(Component, { ...props }), [hash]);
|
|
70
55
|
};
|
|
71
56
|
}
|
|
72
57
|
function useSignal(value, opts) {
|
|
@@ -92,11 +77,7 @@ const useStateSignal = (signal2) => {
|
|
|
92
77
|
const useReactiveFnSignal = (signal2) => {
|
|
93
78
|
const suspended = useSignalsSuspended();
|
|
94
79
|
signal2.setSuspended(suspended);
|
|
95
|
-
return useSyncExternalStore(
|
|
96
|
-
signal2.addListenerLazy(),
|
|
97
|
-
() => signal2.value,
|
|
98
|
-
() => signal2.value
|
|
99
|
-
);
|
|
80
|
+
return useSyncExternalStore(signal2.addListenerLazy(), () => signal2.value, () => signal2.value);
|
|
100
81
|
};
|
|
101
82
|
const useReactivePromise = (promise) => {
|
|
102
83
|
if (isRelay(promise)) {
|
|
@@ -136,12 +117,36 @@ function useReactive(signal2, ...args) {
|
|
|
136
117
|
return useStateSignal(signal2);
|
|
137
118
|
}
|
|
138
119
|
}
|
|
120
|
+
function useReactiveDeep(fn, ...args) {
|
|
121
|
+
if (getCurrentConsumer()) {
|
|
122
|
+
throw new Error("useReactiveDeep cannot be used inside of a reactive context. You can use the signal/function directly instead.");
|
|
123
|
+
}
|
|
124
|
+
const suspended = useSignalsSuspended();
|
|
125
|
+
const scope = useScope() ?? getGlobalScope();
|
|
126
|
+
const signalRef = useRef();
|
|
127
|
+
const cloneSignalRef = useRef();
|
|
128
|
+
const valueRef = useRef();
|
|
129
|
+
const [, def] = getReactiveFnAndDefinition(fn);
|
|
130
|
+
const signal2 = scope.get(def, args);
|
|
131
|
+
if (signalRef.current !== signal2) {
|
|
132
|
+
signalRef.current = signal2;
|
|
133
|
+
cloneSignalRef.current = reactiveSignal(() => {
|
|
134
|
+
const next = snapshot(signal2.value, valueRef.current);
|
|
135
|
+
valueRef.current = next;
|
|
136
|
+
return next;
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
const cloneSignal = cloneSignalRef.current;
|
|
140
|
+
cloneSignal.setSuspended(suspended);
|
|
141
|
+
return useSyncExternalStore(cloneSignal.addListenerLazy(), () => cloneSignal.value, () => cloneSignal.value);
|
|
142
|
+
}
|
|
139
143
|
export {
|
|
140
144
|
ContextProvider,
|
|
141
145
|
SuspendSignalsProvider,
|
|
142
146
|
component,
|
|
143
147
|
useContext,
|
|
144
148
|
useReactive,
|
|
149
|
+
useReactiveDeep,
|
|
145
150
|
useSignal,
|
|
146
151
|
useSignalsSuspended
|
|
147
152
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/react/context.ts","../../../../src/react/provider.tsx","../../../../src/react/suspend-signals-context.ts","../../../../src/react/component.tsx","../../../../src/react/use-signal.ts","../../../../src/react/use-reactive.ts"],"sourcesContent":["import { createContext, useContext as useReactContext } from 'react';\nimport { ContextImpl, SignalScope } from '../internals/contexts.js';\nimport { getCurrentConsumer } from '../internals/consumer.js';\nimport { Context } from '../types.js';\n\nexport const ScopeContext = createContext<SignalScope | undefined>(undefined);\n\nexport function useScope() {\n return useReactContext(ScopeContext);\n}\n\nexport function useContext<T>(context: Context<T>): T {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const scope = getCurrentConsumer()?.scope ?? useScope();\n\n if (!scope) {\n throw new Error('useContext must be used within a signal hook, a withContext, or a component');\n }\n\n return scope.getContext(context) ?? (context as unknown as ContextImpl<T>).defaultValue;\n}\n","import { useContext, useRef } from 'react';\nimport { ScopeContext } from './context.js';\nimport { ContextImpl, ContextPair, getGlobalScope, SignalScope } from '../internals/contexts.js';\n\nexport function ContextProvider<C extends unknown[]>({\n children,\n contexts = [],\n inherit = true,\n}: {\n children: React.ReactNode;\n contexts?: [...ContextPair<C>] | [];\n inherit?: boolean;\n}) {\n const parentScope = useContext(ScopeContext) ?? getGlobalScope();\n const scopeRef = useRef<SignalScope | null>(null);\n if (scopeRef.current === null) {\n scopeRef.current = new SignalScope(\n contexts as [ContextImpl<unknown>, unknown][],\n inherit ? parentScope : undefined,\n );\n }\n\n return <ScopeContext.Provider value={scopeRef.current}>{children}</ScopeContext.Provider>;\n}\n","import { createContext, useContext } from 'react';\n\nconst SuspendSignalsContext = createContext<boolean>(false);\n\nexport const SuspendSignalsProvider = SuspendSignalsContext.Provider;\n\nexport function useSignalsSuspended(): boolean {\n return useContext(SuspendSignalsContext);\n}\n","import { useMemo, useRef, useSyncExternalStore } from 'react';\nimport { useScope } from './context.js';\nimport { useSignalsSuspended } from './suspend-signals-context.js';\nimport { createReactiveSignal, ReactiveSignal } from '../internals/reactive.js';\nimport { runSignal } from '../internals/get.js';\nimport { hashValue } from '../internals/utils/hash.js';\n\nexport default function component<Props extends object>(\n fn: (props: Props) => React.ReactNode | React.ReactNode[] | null,\n) {\n const Component = (props: Props) => {\n const scope = useScope();\n const suspended = useSignalsSuspended();\n\n const fnSignalRef = useRef<ReactiveSignal<React.ReactNode | React.ReactNode[] | null, []> | undefined>(undefined);\n const propsRef = useRef<Props>(props);\n\n propsRef.current = props;\n\n let signal = fnSignalRef.current;\n\n if (signal === undefined) {\n fnSignalRef.current = signal = createReactiveSignal(\n {\n compute: () => fn(propsRef.current),\n equals: () => false,\n isRelay: false,\n tracer: undefined,\n },\n [],\n undefined,\n scope,\n );\n\n signal._isLazy = true;\n }\n\n signal.setSuspended(suspended);\n\n // We always want to re-render when the signal is updated, regardless of\n // whether or not the result changed. This is because the signal is lazy,\n // so it will not be updated until the next render.\n useSyncExternalStore(\n signal.addListenerLazy(),\n () => signal.updatedCount,\n () => signal.updatedCount,\n );\n\n runSignal(signal as ReactiveSignal<any, any[]>);\n\n return signal.value;\n };\n\n return (props: Props) => {\n const hash = hashValue(props);\n // Renders Comp only when hash changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => <Component {...props} />, [hash]);\n };\n}\n","import { useRef } from 'react';\nimport { SignalOptions, Signal } from '../types.js';\nimport { signal } from '../index.js';\n\nexport function useSignal<T>(value: T, opts?: SignalOptions<T>): Signal<T> {\n const ref = useRef<Signal<T> | undefined>(undefined);\n\n if (!ref.current) {\n ref.current = signal(value, opts);\n }\n\n return ref.current;\n}\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport { useCallback, useSyncExternalStore } from 'react';\nimport { ReactiveValue, Signal, ReactivePromise } from '../types.js';\nimport { getReactiveFnAndDefinition } from '../internals/core-api.js';\nimport { getCurrentConsumer } from '../internals/consumer.js';\nimport { ReactiveSignal } from '../internals/reactive.js';\nimport { isReactivePromise, isRelay, ReactivePromiseImpl } from '../internals/async.js';\nimport { StateSignal } from '../internals/signal.js';\nimport { useScope } from './context.js';\nimport { useSignalsSuspended } from './suspend-signals-context.js';\nimport { getGlobalScope } from '../internals/contexts.js';\n\nconst useStateSignal = <T>(signal: Signal<T>): T => {\n const suspended = useSignalsSuspended();\n return useSyncExternalStore(\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useCallback(suspended ? () => () => {} : onStoreChange => (signal as StateSignal<T>).addListener(onStoreChange), [\n signal,\n suspended,\n ]),\n () => signal.value,\n () => signal.value,\n );\n};\n\nconst useReactiveFnSignal = <R, Args extends unknown[]>(signal: ReactiveSignal<R, Args>): ReactiveValue<R> => {\n const suspended = useSignalsSuspended();\n\n signal.setSuspended(suspended);\n\n return useSyncExternalStore(\n signal.addListenerLazy(),\n () => signal.value,\n () => signal.value,\n );\n};\n\nconst useReactivePromise = <R>(promise: ReactivePromiseImpl<R>): ReactivePromise<R> => {\n if (isRelay(promise)) {\n useReactiveFnSignal(promise['_signal'] as ReactiveSignal<any, unknown[]>);\n }\n\n useStateSignal(promise['_version']);\n\n return promise as ReactivePromise<R>;\n};\n\nconst useReactiveFn = <R, Args extends readonly Narrowable[]>(fn: (...args: Args) => R, ...args: Args): R => {\n const [, def] = getReactiveFnAndDefinition(fn as any);\n\n const scope = useScope() ?? getGlobalScope();\n\n const signal = scope.get(def, args as any);\n const value = useReactiveFnSignal(signal);\n\n // Reactive promises can update their value independently of the signal, since\n // we reuse the same promise object for each result. We need to entangle the\n // version of the promise here so that we can trigger a re-render when the\n // promise value updates.\n //\n // If hooks could be called in dynamic order this would not be necessary, we\n // could entangle the promise when it is used. But, because that is not the\n // case, we need to eagerly entangle.\n if (typeof value === 'object' && value !== null && isReactivePromise(value)) {\n return useReactivePromise(value) as R;\n }\n\n return value as R;\n};\n\nconst isNonNullishAsyncSignal = (value: unknown): value is ReactivePromise<unknown> => {\n return typeof value === 'object' && value !== null && isReactivePromise(value as object);\n};\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\ntype Narrowable = string | number | boolean | null | undefined | bigint | symbol | {};\n\nexport function useReactive<R>(signal: Signal<R>): R;\nexport function useReactive<R>(signal: ReactivePromise<R>): ReactivePromise<R>;\nexport function useReactive<R, Args extends readonly Narrowable[]>(fn: (...args: Args) => R, ...args: Args): R;\nexport function useReactive<R, Args extends readonly Narrowable[]>(\n signal: Signal<R> | ReactivePromise<R> | ((...args: Args) => R),\n ...args: Args\n): R | ReactivePromise<R> {\n if (getCurrentConsumer()) {\n if (typeof signal === 'function') {\n return signal(...args);\n } else if (isNonNullishAsyncSignal(signal)) {\n return signal as ReactivePromise<R>;\n } else {\n return (signal as Signal<R>).value;\n }\n }\n\n if (typeof signal === 'function') {\n return useReactiveFn(signal, ...args);\n } else if (typeof signal === 'object' && signal !== null && isReactivePromise(signal)) {\n return useReactivePromise(signal) as ReactivePromise<R>;\n } else {\n return useStateSignal(signal as Signal<R>);\n }\n}\n"],"names":["useReactContext","useContext","signal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../.tsc-out/react/context.js","../../../../.tsc-out/react/provider.js","../../../../.tsc-out/react/suspend-signals-context.js","../../../../.tsc-out/react/component.js","../../../../.tsc-out/react/use-signal.js","../../../../.tsc-out/react/use-reactive.js"],"sourcesContent":["import { createContext, useContext as useReactContext } from 'react';\nimport { getCurrentConsumer } from '../internals/consumer.js';\nexport const ScopeContext = createContext(undefined);\nexport function useScope() {\n return useReactContext(ScopeContext);\n}\nexport function useContext(context) {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const scope = getCurrentConsumer()?.scope ?? useScope();\n if (!scope) {\n throw new Error('useContext must be used within a signal hook, a withContext, or a component');\n }\n return scope.getContext(context) ?? context.defaultValue;\n}\n","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useContext, useMemo } from 'react';\nimport { ScopeContext } from './context.js';\nimport { getGlobalScope, SignalScope } from '../internals/contexts.js';\nimport { hashValue } from '../internals/utils/hash.js';\nexport function ContextProvider({ children, contexts = [], inherit = true, }) {\n const parentScope = useContext(ScopeContext) ?? getGlobalScope();\n const scope = useMemo(() => new SignalScope(contexts, inherit ? parentScope : undefined), \n // eslint-disable-next-line react-hooks/exhaustive-deps\n [parentScope, inherit, hashValue(contexts)]);\n return _jsx(ScopeContext.Provider, { value: scope, children: children });\n}\n","import { createContext, useContext } from 'react';\nconst SuspendSignalsContext = createContext(false);\nexport const SuspendSignalsProvider = SuspendSignalsContext.Provider;\nexport function useSignalsSuspended() {\n return useContext(SuspendSignalsContext);\n}\n","import { jsx as _jsx } from \"react/jsx-runtime\";\nimport { useMemo, useRef, useSyncExternalStore } from 'react';\nimport { useScope } from './context.js';\nimport { useSignalsSuspended } from './suspend-signals-context.js';\nimport { createReactiveSignal } from '../internals/reactive.js';\nimport { runSignal } from '../internals/get.js';\nimport { hashValue } from '../internals/utils/hash.js';\nexport default function component(fn) {\n const Component = (props) => {\n const scope = useScope();\n const suspended = useSignalsSuspended();\n const fnSignalRef = useRef(undefined);\n const propsRef = useRef(props);\n propsRef.current = props;\n let signal = fnSignalRef.current;\n if (signal === undefined) {\n fnSignalRef.current = signal = createReactiveSignal({\n compute: () => fn(propsRef.current),\n equals: () => false,\n isRelay: false,\n tracer: undefined,\n }, [], undefined, scope);\n signal._isLazy = true;\n }\n signal.setSuspended(suspended);\n // We always want to re-render when the signal is updated, regardless of\n // whether or not the result changed. This is because the signal is lazy,\n // so it will not be updated until the next render.\n useSyncExternalStore(signal.addListenerLazy(), () => signal.updatedCount, () => signal.updatedCount);\n runSignal(signal);\n return signal.value;\n };\n return (props) => {\n const hash = hashValue(props);\n // Renders Comp only when hash changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => _jsx(Component, { ...props }), [hash]);\n };\n}\n","import { useRef } from 'react';\nimport { signal } from '../index.js';\nexport function useSignal(value, opts) {\n const ref = useRef(undefined);\n if (!ref.current) {\n ref.current = signal(value, opts);\n }\n return ref.current;\n}\n","/* eslint-disable react-hooks/rules-of-hooks */\nimport { useCallback, useRef, useSyncExternalStore } from 'react';\nimport { getReactiveFnAndDefinition, reactiveSignal } from '../internals/core-api.js';\nimport { getCurrentConsumer } from '../internals/consumer.js';\nimport { isReactivePromise, isRelay } from '../internals/async.js';\nimport { snapshot } from '../internals/utils/snapshot.js';\nimport { useScope } from './context.js';\nimport { useSignalsSuspended } from './suspend-signals-context.js';\nimport { getGlobalScope } from '../internals/contexts.js';\nconst useStateSignal = (signal) => {\n const suspended = useSignalsSuspended();\n return useSyncExternalStore(\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useCallback(suspended ? () => () => { } : onStoreChange => signal.addListener(onStoreChange), [\n signal,\n suspended,\n ]), () => signal.value, () => signal.value);\n};\nconst useReactiveFnSignal = (signal) => {\n const suspended = useSignalsSuspended();\n signal.setSuspended(suspended);\n return useSyncExternalStore(signal.addListenerLazy(), () => signal.value, () => signal.value);\n};\nconst useReactivePromise = (promise) => {\n if (isRelay(promise)) {\n useReactiveFnSignal(promise['_signal']);\n }\n useStateSignal(promise['_version']);\n return promise;\n};\nconst useReactiveFn = (fn, ...args) => {\n const [, def] = getReactiveFnAndDefinition(fn);\n const scope = useScope() ?? getGlobalScope();\n const signal = scope.get(def, args);\n const value = useReactiveFnSignal(signal);\n // Reactive promises can update their value independently of the signal, since\n // we reuse the same promise object for each result. We need to entangle the\n // version of the promise here so that we can trigger a re-render when the\n // promise value updates.\n //\n // If hooks could be called in dynamic order this would not be necessary, we\n // could entangle the promise when it is used. But, because that is not the\n // case, we need to eagerly entangle.\n if (typeof value === 'object' && value !== null && isReactivePromise(value)) {\n return useReactivePromise(value);\n }\n return value;\n};\nconst isNonNullishAsyncSignal = (value) => {\n return typeof value === 'object' && value !== null && isReactivePromise(value);\n};\nexport function useReactive(signal, ...args) {\n if (getCurrentConsumer()) {\n if (typeof signal === 'function') {\n return signal(...args);\n }\n else if (isNonNullishAsyncSignal(signal)) {\n return signal;\n }\n else {\n return signal.value;\n }\n }\n if (typeof signal === 'function') {\n return useReactiveFn(signal, ...args);\n }\n else if (typeof signal === 'object' && signal !== null && isReactivePromise(signal)) {\n return useReactivePromise(signal);\n }\n else {\n return useStateSignal(signal);\n }\n}\nexport function useReactiveDeep(fn, ...args) {\n if (getCurrentConsumer()) {\n throw new Error('useReactiveDeep cannot be used inside of a reactive context. You can use the signal/function directly instead.');\n }\n const suspended = useSignalsSuspended();\n const scope = useScope() ?? getGlobalScope();\n const signalRef = useRef();\n const cloneSignalRef = useRef();\n const valueRef = useRef();\n const [, def] = getReactiveFnAndDefinition(fn);\n const signal = scope.get(def, args);\n if (signalRef.current !== signal) {\n signalRef.current = signal;\n cloneSignalRef.current = reactiveSignal(() => {\n const next = snapshot(signal.value, valueRef.current);\n valueRef.current = next;\n return next;\n });\n }\n const cloneSignal = cloneSignalRef.current;\n cloneSignal.setSuspended(suspended);\n return useSyncExternalStore(cloneSignal.addListenerLazy(), () => cloneSignal.value, () => cloneSignal.value);\n}\n"],"names":["useReactContext","useContext","_jsx","signal"],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { c as createReactiveDefinition, S as SignalScope, g as getCurrentScope, a as createReactiveSignal, b as createTask, d as createRelay, e as getScopeOwner, i as isReactivePromise } from "./contexts-X0gSj6rQ.js";
|
|
2
|
+
const DERIVED_DEFINITION_MAP = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function getReactiveFnAndDefinition(fn, opts) {
|
|
4
|
+
let fnAndDef = DERIVED_DEFINITION_MAP.get(fn);
|
|
5
|
+
if (!fnAndDef) {
|
|
6
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey);
|
|
7
|
+
const defScope = getCurrentScope();
|
|
8
|
+
const reactiveFn = (...args) => {
|
|
9
|
+
const scope = getCurrentScope(defScope);
|
|
10
|
+
const signal = scope.get(def, args);
|
|
11
|
+
return signal.value;
|
|
12
|
+
};
|
|
13
|
+
fnAndDef = [reactiveFn, def];
|
|
14
|
+
DERIVED_DEFINITION_MAP.set(fn, fnAndDef);
|
|
15
|
+
}
|
|
16
|
+
return fnAndDef;
|
|
17
|
+
}
|
|
18
|
+
function reactive(fn, opts) {
|
|
19
|
+
return getReactiveFnAndDefinition(fn, opts)[0];
|
|
20
|
+
}
|
|
21
|
+
const reactiveMethod = (owner, fn, opts) => {
|
|
22
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey);
|
|
23
|
+
const reactiveFn = (...args) => {
|
|
24
|
+
return getScopeOwner(owner).get(def, args).value;
|
|
25
|
+
};
|
|
26
|
+
DERIVED_DEFINITION_MAP.set(reactiveFn, [reactiveFn, def]);
|
|
27
|
+
return reactiveFn;
|
|
28
|
+
};
|
|
29
|
+
function relay(activate, opts) {
|
|
30
|
+
const scope = getCurrentScope();
|
|
31
|
+
return createRelay(activate, scope, opts);
|
|
32
|
+
}
|
|
33
|
+
const task = (fn, opts) => {
|
|
34
|
+
const scope = getCurrentScope();
|
|
35
|
+
return createTask(fn, scope, opts);
|
|
36
|
+
};
|
|
37
|
+
function watcher(fn, opts) {
|
|
38
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, void 0, opts?.tracer);
|
|
39
|
+
const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();
|
|
40
|
+
return createReactiveSignal(def, void 0, void 0, scope);
|
|
41
|
+
}
|
|
42
|
+
const reactiveSignal = (compute, opts) => {
|
|
43
|
+
const def = createReactiveDefinition(opts?.id, opts?.desc, compute, opts?.equals, false, void 0);
|
|
44
|
+
const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();
|
|
45
|
+
return createReactiveSignal(def, void 0, void 0, scope);
|
|
46
|
+
};
|
|
47
|
+
const getProto = Object.getPrototypeOf;
|
|
48
|
+
function snapshotArray(current, prev, snap) {
|
|
49
|
+
const prevArr = Array.isArray(prev) ? prev : void 0;
|
|
50
|
+
let changed = !prevArr || prevArr.length !== current.length;
|
|
51
|
+
const result = new Array(current.length);
|
|
52
|
+
for (let i = 0; i < current.length; i++) {
|
|
53
|
+
result[i] = snap(current[i], prevArr?.[i]);
|
|
54
|
+
if (!changed && result[i] !== prevArr[i]) {
|
|
55
|
+
changed = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return changed ? result : prevArr;
|
|
59
|
+
}
|
|
60
|
+
function snapshotPlainObject(current, prev, snap) {
|
|
61
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" && !Array.isArray(prev) ? prev : void 0;
|
|
62
|
+
const keys = Object.keys(current);
|
|
63
|
+
let changed = !prevObj || Object.keys(prevObj).length !== keys.length;
|
|
64
|
+
const result = {};
|
|
65
|
+
for (let i = 0; i < keys.length; i++) {
|
|
66
|
+
const key = keys[i];
|
|
67
|
+
result[key] = snap(current[key], prevObj?.[key]);
|
|
68
|
+
if (!changed && result[key] !== prevObj[key]) {
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return changed ? result : prevObj;
|
|
73
|
+
}
|
|
74
|
+
function snapshotReactivePromise(current, prev, snap) {
|
|
75
|
+
const prevObj = prev !== null && prev !== void 0 && typeof prev === "object" ? prev : void 0;
|
|
76
|
+
const value = snap(current.value, prevObj?.value);
|
|
77
|
+
const error = current.error;
|
|
78
|
+
const isPending = current.isPending;
|
|
79
|
+
const isRejected = current.isRejected;
|
|
80
|
+
const isResolved = current.isResolved;
|
|
81
|
+
const isReady = current.isReady;
|
|
82
|
+
const isSettled = current.isSettled;
|
|
83
|
+
if (prevObj && value === prevObj.value && error === prevObj.error && isPending === prevObj.isPending && isRejected === prevObj.isRejected && isResolved === prevObj.isResolved && isReady === prevObj.isReady && isSettled === prevObj.isSettled) {
|
|
84
|
+
return prevObj;
|
|
85
|
+
}
|
|
86
|
+
return { value, error, isPending, isRejected, isResolved, isReady, isSettled };
|
|
87
|
+
}
|
|
88
|
+
function snapshotMap(current, prev, snap) {
|
|
89
|
+
const prevMap = prev instanceof Map ? prev : void 0;
|
|
90
|
+
let changed = !prevMap || prevMap.size !== current.size;
|
|
91
|
+
const result = /* @__PURE__ */ new Map();
|
|
92
|
+
for (const [key, val] of current) {
|
|
93
|
+
const snapped = snap(val, prevMap?.get(key));
|
|
94
|
+
result.set(key, snapped);
|
|
95
|
+
if (!changed && snapped !== prevMap.get(key)) {
|
|
96
|
+
changed = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return changed ? result : prevMap;
|
|
100
|
+
}
|
|
101
|
+
function snapshotSet(current, prev, _snap) {
|
|
102
|
+
const prevSet = prev instanceof Set ? prev : void 0;
|
|
103
|
+
let changed = !prevSet || prevSet.size !== current.size;
|
|
104
|
+
const result = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const val of current) {
|
|
106
|
+
const snapped = snapshot(val, prevSet?.has(val) ? val : void 0);
|
|
107
|
+
result.add(snapped);
|
|
108
|
+
if (!changed && !prevSet.has(snapped)) {
|
|
109
|
+
changed = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return changed ? result : prevSet;
|
|
113
|
+
}
|
|
114
|
+
const PROTO_TO_SNAPSHOT = /* @__PURE__ */ new Map([
|
|
115
|
+
[Object.prototype, snapshotPlainObject],
|
|
116
|
+
[Array.prototype, snapshotArray],
|
|
117
|
+
[Map.prototype, snapshotMap],
|
|
118
|
+
[Set.prototype, snapshotSet],
|
|
119
|
+
[null, snapshotPlainObject]
|
|
120
|
+
]);
|
|
121
|
+
const registerCustomSnapshot = (ctor, snapshotFn) => {
|
|
122
|
+
PROTO_TO_SNAPSHOT.set(ctor.prototype, snapshotFn);
|
|
123
|
+
};
|
|
124
|
+
function snapshot(currentValue, prevValue) {
|
|
125
|
+
if (currentValue === null || typeof currentValue !== "object") {
|
|
126
|
+
return currentValue;
|
|
127
|
+
}
|
|
128
|
+
if (isReactivePromise(currentValue)) {
|
|
129
|
+
return snapshotReactivePromise(currentValue, prevValue, snapshot);
|
|
130
|
+
}
|
|
131
|
+
const handler = PROTO_TO_SNAPSHOT.get(getProto(currentValue));
|
|
132
|
+
if (handler !== void 0) {
|
|
133
|
+
return handler(currentValue, prevValue, snapshot);
|
|
134
|
+
}
|
|
135
|
+
return currentValue;
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
registerCustomSnapshot as a,
|
|
139
|
+
reactive as b,
|
|
140
|
+
reactiveMethod as c,
|
|
141
|
+
relay as d,
|
|
142
|
+
getReactiveFnAndDefinition as g,
|
|
143
|
+
reactiveSignal as r,
|
|
144
|
+
snapshot as s,
|
|
145
|
+
task as t,
|
|
146
|
+
watcher as w
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=snapshot-CDS1d8mq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-CDS1d8mq.js","sources":["../../../.tsc-out/internals/core-api.js","../../../.tsc-out/internals/utils/snapshot.js"],"sourcesContent":["import { getCurrentScope, getScopeOwner, SignalScope } from './contexts.js';\nimport { createReactiveDefinition, createReactiveSignal, } from './reactive.js';\nimport { createRelay, createTask } from './async.js';\n// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\nexport const DERIVED_DEFINITION_MAP = new WeakMap();\nexport function getReactiveFnAndDefinition(fn, opts) {\n let fnAndDef = DERIVED_DEFINITION_MAP.get(fn);\n if (!fnAndDef) {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, undefined);\n const defScope = getCurrentScope();\n const reactiveFn = (...args) => {\n const scope = getCurrentScope(defScope);\n const signal = scope.get(def, args);\n return signal.value;\n };\n fnAndDef = [reactiveFn, def];\n DERIVED_DEFINITION_MAP.set(fn, fnAndDef);\n }\n return fnAndDef;\n}\nexport function reactive(fn, opts) {\n return getReactiveFnAndDefinition(fn, opts)[0];\n}\nexport const reactiveMethod = (owner, fn, opts) => {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, opts?.paramKey, undefined);\n const reactiveFn = (...args) => {\n return getScopeOwner(owner).get(def, args).value;\n };\n DERIVED_DEFINITION_MAP.set(reactiveFn, [reactiveFn, def]);\n return reactiveFn;\n};\nexport function relay(activate, opts) {\n const scope = getCurrentScope();\n return createRelay(activate, scope, opts);\n}\nexport const task = (fn, opts) => {\n const scope = getCurrentScope();\n return createTask(fn, scope, opts);\n};\nexport function watcher(fn, opts) {\n const def = createReactiveDefinition(opts?.id, opts?.desc, fn, opts?.equals, false, undefined, opts?.tracer);\n const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();\n return createReactiveSignal(def, undefined, undefined, scope);\n}\n/**\n * Creates a reactive signal from a compute function. This is useful for when you\n * want to create a signal that does not receive parameters, but is still reactive.\n *\n * @param compute\n * @param opts\n * @returns\n */\nexport const reactiveSignal = (compute, opts) => {\n const def = createReactiveDefinition(opts?.id, opts?.desc, compute, opts?.equals, false, undefined, undefined);\n const scope = opts?.isolate ? new SignalScope([]) : getCurrentScope();\n return createReactiveSignal(def, undefined, undefined, scope);\n};\n","import { isReactivePromise } from '../async.js';\nconst getProto = Object.getPrototypeOf;\nfunction snapshotArray(current, prev, snap) {\n const prevArr = Array.isArray(prev) ? prev : undefined;\n let changed = !prevArr || prevArr.length !== current.length;\n const result = new Array(current.length);\n for (let i = 0; i < current.length; i++) {\n result[i] = snap(current[i], prevArr?.[i]);\n if (!changed && result[i] !== prevArr[i]) {\n changed = true;\n }\n }\n return changed ? result : prevArr;\n}\nfunction snapshotPlainObject(current, prev, snap) {\n const prevObj = prev !== null && prev !== undefined && typeof prev === 'object' && !Array.isArray(prev)\n ? prev\n : undefined;\n const keys = Object.keys(current);\n let changed = !prevObj || Object.keys(prevObj).length !== keys.length;\n const result = {};\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n result[key] = snap(current[key], prevObj?.[key]);\n if (!changed && result[key] !== prevObj[key]) {\n changed = true;\n }\n }\n return changed ? result : prevObj;\n}\nfunction snapshotReactivePromise(current, prev, snap) {\n const prevObj = prev !== null && prev !== undefined && typeof prev === 'object' ? prev : undefined;\n const value = snap(current.value, prevObj?.value);\n const error = current.error;\n const isPending = current.isPending;\n const isRejected = current.isRejected;\n const isResolved = current.isResolved;\n const isReady = current.isReady;\n const isSettled = current.isSettled;\n if (prevObj &&\n value === prevObj.value &&\n error === prevObj.error &&\n isPending === prevObj.isPending &&\n isRejected === prevObj.isRejected &&\n isResolved === prevObj.isResolved &&\n isReady === prevObj.isReady &&\n isSettled === prevObj.isSettled) {\n return prevObj;\n }\n return { value, error, isPending, isRejected, isResolved, isReady, isSettled };\n}\nfunction snapshotMap(current, prev, snap) {\n const prevMap = prev instanceof Map ? prev : undefined;\n let changed = !prevMap || prevMap.size !== current.size;\n const result = new Map();\n for (const [key, val] of current) {\n const snapped = snap(val, prevMap?.get(key));\n result.set(key, snapped);\n if (!changed && snapped !== prevMap.get(key)) {\n changed = true;\n }\n }\n return changed ? result : prevMap;\n}\nfunction snapshotSet(current, prev, _snap) {\n const prevSet = prev instanceof Set ? prev : undefined;\n let changed = !prevSet || prevSet.size !== current.size;\n const result = new Set();\n for (const val of current) {\n const snapped = snapshot(val, prevSet?.has(val) ? val : undefined);\n result.add(snapped);\n if (!changed && !prevSet.has(snapped)) {\n changed = true;\n }\n }\n return changed ? result : prevSet;\n}\nconst PROTO_TO_SNAPSHOT = new Map([\n [Object.prototype, snapshotPlainObject],\n [Array.prototype, snapshotArray],\n [Map.prototype, snapshotMap],\n [Set.prototype, snapshotSet],\n [null, snapshotPlainObject],\n]);\n/**\n * Register a custom snapshot function for instances of a class.\n * The function receives the current value, the previous snapshot (or undefined),\n * and the recursive `snapshot` function for snapshotting nested values.\n *\n * Return `prev` when nothing has changed to preserve reference stability.\n *\n * @example\n * ```ts\n * registerCustomSnapshot(MyEntity, (current, prev, snapshot) => {\n * const name = snapshot(current.name, prev?.name);\n * const age = current.age;\n * if (prev && name === prev.name && age === prev.age) return prev;\n * return { name, age };\n * });\n * ```\n */\nexport const registerCustomSnapshot = (ctor, snapshotFn) => {\n PROTO_TO_SNAPSHOT.set(ctor.prototype, snapshotFn);\n};\n/**\n * Recursively snapshot a value with structural sharing.\n *\n * - Plain objects and arrays are deep-cloned; unchanged subtrees keep the same reference.\n * - ReactivePromise instances are read (establishing deps) and flattened to a plain object.\n * - Class instances (non-plain prototypes) are returned as-is unless a custom handler is registered.\n * - Primitives are returned directly.\n */\nexport function snapshot(currentValue, prevValue) {\n if (currentValue === null || typeof currentValue !== 'object') {\n return currentValue;\n }\n if (isReactivePromise(currentValue)) {\n return snapshotReactivePromise(currentValue, prevValue, snapshot);\n }\n const handler = PROTO_TO_SNAPSHOT.get(getProto(currentValue));\n if (handler !== undefined) {\n return handler(currentValue, prevValue, snapshot);\n }\n return currentValue;\n}\n"],"names":[],"mappings":";AAIO,MAAM,yBAAyB,oBAAI,QAAO;AAC1C,SAAS,2BAA2B,IAAI,MAAM;AACjD,MAAI,WAAW,uBAAuB,IAAI,EAAE;AAC5C,MAAI,CAAC,UAAU;AACX,UAAM,MAAM,yBAAyB,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAmB;AAC7G,UAAM,WAAW,gBAAe;AAChC,UAAM,aAAa,IAAI,SAAS;AAC5B,YAAM,QAAQ,gBAAgB,QAAQ;AACtC,YAAM,SAAS,MAAM,IAAI,KAAK,IAAI;AAClC,aAAO,OAAO;AAAA,IAClB;AACA,eAAW,CAAC,YAAY,GAAG;AAC3B,2BAAuB,IAAI,IAAI,QAAQ;AAAA,EAC3C;AACA,SAAO;AACX;AACO,SAAS,SAAS,IAAI,MAAM;AAC/B,SAAO,2BAA2B,IAAI,IAAI,EAAE,CAAC;AACjD;AACY,MAAC,iBAAiB,CAAC,OAAO,IAAI,SAAS;AAC/C,QAAM,MAAM,yBAAyB,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,QAAQ,OAAO,MAAM,QAAmB;AAC7G,QAAM,aAAa,IAAI,SAAS;AAC5B,WAAO,cAAc,KAAK,EAAE,IAAI,KAAK,IAAI,EAAE;AAAA,EAC/C;AACA,yBAAuB,IAAI,YAAY,CAAC,YAAY,GAAG,CAAC;AACxD,SAAO;AACX;AACO,SAAS,MAAM,UAAU,MAAM;AAClC,QAAM,QAAQ,gBAAe;AAC7B,SAAO,YAAY,UAAU,OAAO,IAAI;AAC5C;AACY,MAAC,OAAO,CAAC,IAAI,SAAS;AAC9B,QAAM,QAAQ,gBAAe;AAC7B,SAAO,WAAW,IAAI,OAAO,IAAI;AACrC;AACO,SAAS,QAAQ,IAAI,MAAM;AAC9B,QAAM,MAAM,yBAAyB,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,QAAQ,OAAO,QAAW,MAAM,MAAM;AAC3G,QAAM,QAAQ,MAAM,UAAU,IAAI,YAAY,CAAA,CAAE,IAAI,gBAAe;AACnE,SAAO,qBAAqB,KAAK,QAAW,QAAW,KAAK;AAChE;AASY,MAAC,iBAAiB,CAAC,SAAS,SAAS;AAC7C,QAAM,MAAM,yBAAyB,MAAM,IAAI,MAAM,MAAM,SAAS,MAAM,QAAQ,OAAO,MAAoB;AAC7G,QAAM,QAAQ,MAAM,UAAU,IAAI,YAAY,CAAA,CAAE,IAAI,gBAAe;AACnE,SAAO,qBAAqB,KAAK,QAAW,QAAW,KAAK;AAChE;ACvDA,MAAM,WAAW,OAAO;AACxB,SAAS,cAAc,SAAS,MAAM,MAAM;AACxC,QAAM,UAAU,MAAM,QAAQ,IAAI,IAAI,OAAO;AAC7C,MAAI,UAAU,CAAC,WAAW,QAAQ,WAAW,QAAQ;AACrD,QAAM,SAAS,IAAI,MAAM,QAAQ,MAAM;AACvC,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACrC,WAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,GAAG,UAAU,CAAC,CAAC;AACzC,QAAI,CAAC,WAAW,OAAO,CAAC,MAAM,QAAQ,CAAC,GAAG;AACtC,gBAAU;AAAA,IACd;AAAA,EACJ;AACA,SAAO,UAAU,SAAS;AAC9B;AACA,SAAS,oBAAoB,SAAS,MAAM,MAAM;AAC9C,QAAM,UAAU,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,IAChG,OACA;AACN,QAAM,OAAO,OAAO,KAAK,OAAO;AAChC,MAAI,UAAU,CAAC,WAAW,OAAO,KAAK,OAAO,EAAE,WAAW,KAAK;AAC/D,QAAM,SAAS,CAAA;AACf,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AAClC,UAAM,MAAM,KAAK,CAAC;AAClB,WAAO,GAAG,IAAI,KAAK,QAAQ,GAAG,GAAG,UAAU,GAAG,CAAC;AAC/C,QAAI,CAAC,WAAW,OAAO,GAAG,MAAM,QAAQ,GAAG,GAAG;AAC1C,gBAAU;AAAA,IACd;AAAA,EACJ;AACA,SAAO,UAAU,SAAS;AAC9B;AACA,SAAS,wBAAwB,SAAS,MAAM,MAAM;AAClD,QAAM,UAAU,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,WAAW,OAAO;AACzF,QAAM,QAAQ,KAAK,QAAQ,OAAO,SAAS,KAAK;AAChD,QAAM,QAAQ,QAAQ;AACtB,QAAM,YAAY,QAAQ;AAC1B,QAAM,aAAa,QAAQ;AAC3B,QAAM,aAAa,QAAQ;AAC3B,QAAM,UAAU,QAAQ;AACxB,QAAM,YAAY,QAAQ;AAC1B,MAAI,WACA,UAAU,QAAQ,SAClB,UAAU,QAAQ,SAClB,cAAc,QAAQ,aACtB,eAAe,QAAQ,cACvB,eAAe,QAAQ,cACvB,YAAY,QAAQ,WACpB,cAAc,QAAQ,WAAW;AACjC,WAAO;AAAA,EACX;AACA,SAAO,EAAE,OAAO,OAAO,WAAW,YAAY,YAAY,SAAS,UAAS;AAChF;AACA,SAAS,YAAY,SAAS,MAAM,MAAM;AACtC,QAAM,UAAU,gBAAgB,MAAM,OAAO;AAC7C,MAAI,UAAU,CAAC,WAAW,QAAQ,SAAS,QAAQ;AACnD,QAAM,SAAS,oBAAI,IAAG;AACtB,aAAW,CAAC,KAAK,GAAG,KAAK,SAAS;AAC9B,UAAM,UAAU,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC;AAC3C,WAAO,IAAI,KAAK,OAAO;AACvB,QAAI,CAAC,WAAW,YAAY,QAAQ,IAAI,GAAG,GAAG;AAC1C,gBAAU;AAAA,IACd;AAAA,EACJ;AACA,SAAO,UAAU,SAAS;AAC9B;AACA,SAAS,YAAY,SAAS,MAAM,OAAO;AACvC,QAAM,UAAU,gBAAgB,MAAM,OAAO;AAC7C,MAAI,UAAU,CAAC,WAAW,QAAQ,SAAS,QAAQ;AACnD,QAAM,SAAS,oBAAI,IAAG;AACtB,aAAW,OAAO,SAAS;AACvB,UAAM,UAAU,SAAS,KAAK,SAAS,IAAI,GAAG,IAAI,MAAM,MAAS;AACjE,WAAO,IAAI,OAAO;AAClB,QAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,OAAO,GAAG;AACnC,gBAAU;AAAA,IACd;AAAA,EACJ;AACA,SAAO,UAAU,SAAS;AAC9B;AACA,MAAM,oBAAoB,oBAAI,IAAI;AAAA,EAC9B,CAAC,OAAO,WAAW,mBAAmB;AAAA,EACtC,CAAC,MAAM,WAAW,aAAa;AAAA,EAC/B,CAAC,IAAI,WAAW,WAAW;AAAA,EAC3B,CAAC,IAAI,WAAW,WAAW;AAAA,EAC3B,CAAC,MAAM,mBAAmB;AAC9B,CAAC;AAkBW,MAAC,yBAAyB,CAAC,MAAM,eAAe;AACxD,oBAAkB,IAAI,KAAK,WAAW,UAAU;AACpD;AASO,SAAS,SAAS,cAAc,WAAW;AAC9C,MAAI,iBAAiB,QAAQ,OAAO,iBAAiB,UAAU;AAC3D,WAAO;AAAA,EACX;AACA,MAAI,kBAAkB,YAAY,GAAG;AACjC,WAAO,wBAAwB,cAAc,WAAW,QAAQ;AAAA,EACpE;AACA,QAAM,UAAU,kBAAkB,IAAI,SAAS,YAAY,CAAC;AAC5D,MAAI,YAAY,QAAW;AACvB,WAAO,QAAQ,cAAc,WAAW,QAAQ;AAAA,EACpD;AACA,SAAO;AACX;"}
|