atomirx 0.0.8 → 0.1.1
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 +198 -2234
- package/bin/cli.js +90 -0
- package/dist/core/derived.d.ts +2 -2
- package/dist/core/effect.d.ts +3 -2
- package/dist/core/onCreateHook.d.ts +15 -2
- package/dist/core/onErrorHook.d.ts +4 -1
- package/dist/core/pool.d.ts +78 -0
- package/dist/core/pool.test.d.ts +1 -0
- package/dist/core/select-boolean.test.d.ts +1 -0
- package/dist/core/select-pool.test.d.ts +1 -0
- package/dist/core/select.d.ts +278 -86
- package/dist/core/types.d.ts +233 -1
- package/dist/core/withAbort.d.ts +95 -0
- package/dist/core/withReady.d.ts +3 -3
- package/dist/devtools/constants.d.ts +41 -0
- package/dist/devtools/index.cjs +1 -0
- package/dist/devtools/index.d.ts +29 -0
- package/dist/devtools/index.js +429 -0
- package/dist/devtools/registry.d.ts +98 -0
- package/dist/devtools/registry.test.d.ts +1 -0
- package/dist/devtools/setup.d.ts +61 -0
- package/dist/devtools/types.d.ts +311 -0
- package/dist/index-BZEnfIcB.cjs +1 -0
- package/dist/index-BbPZhsDl.js +1653 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +18 -14
- package/dist/onDispatchHook-C8yLzr-o.cjs +1 -0
- package/dist/onDispatchHook-SKbiIUaJ.js +5 -0
- package/dist/onErrorHook-BGGy3tqK.js +38 -0
- package/dist/onErrorHook-DHBASmYw.cjs +1 -0
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.js +191 -151
- package/dist/react/onDispatchHook.d.ts +106 -0
- package/dist/react/useAction.d.ts +4 -1
- package/dist/react-devtools/DevToolsPanel.d.ts +93 -0
- package/dist/react-devtools/EntityDetails.d.ts +10 -0
- package/dist/react-devtools/EntityList.d.ts +15 -0
- package/dist/react-devtools/LogList.d.ts +12 -0
- package/dist/react-devtools/hooks.d.ts +50 -0
- package/dist/react-devtools/index.cjs +1 -0
- package/dist/react-devtools/index.d.ts +31 -0
- package/dist/react-devtools/index.js +1589 -0
- package/dist/react-devtools/styles.d.ts +148 -0
- package/package.json +26 -2
- package/skills/atomirx/SKILL.md +456 -0
- package/skills/atomirx/references/async-patterns.md +188 -0
- package/skills/atomirx/references/atom-patterns.md +238 -0
- package/skills/atomirx/references/deferred-loading.md +191 -0
- package/skills/atomirx/references/derived-patterns.md +428 -0
- package/skills/atomirx/references/effect-patterns.md +426 -0
- package/skills/atomirx/references/error-handling.md +140 -0
- package/skills/atomirx/references/hooks.md +322 -0
- package/skills/atomirx/references/pool-patterns.md +229 -0
- package/skills/atomirx/references/react-integration.md +411 -0
- package/skills/atomirx/references/rules.md +407 -0
- package/skills/atomirx/references/select-context.md +309 -0
- package/skills/atomirx/references/service-template.md +172 -0
- package/skills/atomirx/references/store-template.md +205 -0
- package/skills/atomirx/references/testing-patterns.md +431 -0
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -1440
- package/coverage/coverage-final.json +0 -14
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -131
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/core/atom.ts.html +0 -889
- package/coverage/src/core/batch.ts.html +0 -223
- package/coverage/src/core/define.ts.html +0 -805
- package/coverage/src/core/emitter.ts.html +0 -919
- package/coverage/src/core/equality.ts.html +0 -631
- package/coverage/src/core/hook.ts.html +0 -460
- package/coverage/src/core/index.html +0 -281
- package/coverage/src/core/isAtom.ts.html +0 -100
- package/coverage/src/core/isPromiseLike.ts.html +0 -133
- package/coverage/src/core/onCreateHook.ts.html +0 -138
- package/coverage/src/core/scheduleNotifyHook.ts.html +0 -94
- package/coverage/src/core/types.ts.html +0 -523
- package/coverage/src/core/withUse.ts.html +0 -253
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -106
- package/dist/index-CBVj1kSj.js +0 -1350
- package/dist/index-Cxk9v0um.cjs +0 -1
- package/scripts/publish.js +0 -198
- package/src/core/atom.test.ts +0 -633
- package/src/core/atom.ts +0 -311
- package/src/core/atomState.test.ts +0 -342
- package/src/core/atomState.ts +0 -256
- package/src/core/batch.test.ts +0 -257
- package/src/core/batch.ts +0 -172
- package/src/core/define.test.ts +0 -343
- package/src/core/define.ts +0 -243
- package/src/core/derived.test.ts +0 -1215
- package/src/core/derived.ts +0 -450
- package/src/core/effect.test.ts +0 -802
- package/src/core/effect.ts +0 -188
- package/src/core/emitter.test.ts +0 -364
- package/src/core/emitter.ts +0 -392
- package/src/core/equality.test.ts +0 -392
- package/src/core/equality.ts +0 -182
- package/src/core/getAtomState.ts +0 -69
- package/src/core/hook.test.ts +0 -227
- package/src/core/hook.ts +0 -177
- package/src/core/isAtom.ts +0 -27
- package/src/core/isPromiseLike.test.ts +0 -72
- package/src/core/isPromiseLike.ts +0 -16
- package/src/core/onCreateHook.ts +0 -107
- package/src/core/onErrorHook.test.ts +0 -350
- package/src/core/onErrorHook.ts +0 -52
- package/src/core/promiseCache.test.ts +0 -241
- package/src/core/promiseCache.ts +0 -284
- package/src/core/scheduleNotifyHook.ts +0 -53
- package/src/core/select.ts +0 -729
- package/src/core/selector.test.ts +0 -799
- package/src/core/types.ts +0 -389
- package/src/core/withReady.test.ts +0 -534
- package/src/core/withReady.ts +0 -191
- package/src/core/withUse.test.ts +0 -249
- package/src/core/withUse.ts +0 -56
- package/src/index.test.ts +0 -80
- package/src/index.ts +0 -65
- package/src/react/index.ts +0 -21
- package/src/react/rx.test.tsx +0 -571
- package/src/react/rx.tsx +0 -531
- package/src/react/strictModeTest.tsx +0 -71
- package/src/react/useAction.test.ts +0 -987
- package/src/react/useAction.ts +0 -607
- package/src/react/useSelector.test.ts +0 -182
- package/src/react/useSelector.ts +0 -292
- package/src/react/useStable.test.ts +0 -553
- package/src/react/useStable.ts +0 -288
- package/tsconfig.json +0 -9
- package/v2.md +0 -725
- package/vite.config.ts +0 -42
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ActionMeta } from './useAction';
|
|
2
|
+
/**
|
|
3
|
+
* Information provided when an action dispatch event occurs.
|
|
4
|
+
*
|
|
5
|
+
* ## Lifecycle Flow
|
|
6
|
+
*
|
|
7
|
+
* ```
|
|
8
|
+
* dispatch(deps)
|
|
9
|
+
* │
|
|
10
|
+
* ▼
|
|
11
|
+
* "start" ─── Action invoked
|
|
12
|
+
* │
|
|
13
|
+
* ▼
|
|
14
|
+
* "loading" ── Async operation in progress (if async)
|
|
15
|
+
* │
|
|
16
|
+
* ┌──┴──┐
|
|
17
|
+
* │ │
|
|
18
|
+
* ▼ ▼
|
|
19
|
+
* "success" "error" ── Sync result
|
|
20
|
+
* │ │
|
|
21
|
+
* │ │
|
|
22
|
+
* ▼ ▼
|
|
23
|
+
* "resolved" "rejected" ── Async result (if Promise)
|
|
24
|
+
*
|
|
25
|
+
* "abort" ── Called if action is cancelled mid-flight
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export interface DispatchInfo {
|
|
29
|
+
/**
|
|
30
|
+
* The current dispatch lifecycle state.
|
|
31
|
+
*
|
|
32
|
+
* - `start` - Action was invoked (always first event)
|
|
33
|
+
* - `loading` - Async operation is in progress
|
|
34
|
+
* - `abort` - Action was cancelled (e.g., deps changed, unmount)
|
|
35
|
+
* - `error` - Sync error thrown during execution
|
|
36
|
+
* - `success` - Sync execution completed successfully
|
|
37
|
+
* - `resolved` - Async Promise resolved successfully
|
|
38
|
+
* - `rejected` - Async Promise was rejected
|
|
39
|
+
*/
|
|
40
|
+
readonly type: "start" | "loading" | "abort" | "error" | "success" | "resolved" | "rejected";
|
|
41
|
+
/**
|
|
42
|
+
* Action metadata (key, description, etc.).
|
|
43
|
+
* Undefined if action was created without meta options.
|
|
44
|
+
*/
|
|
45
|
+
readonly meta: ActionMeta | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Dependencies passed to the action.
|
|
48
|
+
* Same deps array that was passed to dispatch().
|
|
49
|
+
*/
|
|
50
|
+
readonly deps: unknown[];
|
|
51
|
+
/**
|
|
52
|
+
* Error information (only present for "error" and "rejected" types).
|
|
53
|
+
*/
|
|
54
|
+
readonly error?: unknown | undefined;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Global hook that fires on action dispatch lifecycle events.
|
|
58
|
+
*
|
|
59
|
+
* This hook is useful for:
|
|
60
|
+
* - **DevTools integration** - Log action dispatches for debugging
|
|
61
|
+
* - **Analytics** - Track action usage patterns
|
|
62
|
+
* - **Error monitoring** - Capture action failures
|
|
63
|
+
* - **Performance monitoring** - Measure action duration
|
|
64
|
+
*
|
|
65
|
+
* **IMPORTANT**: Always use `.override()` to preserve the hook chain.
|
|
66
|
+
* Direct assignment to `.current` will break existing handlers.
|
|
67
|
+
*
|
|
68
|
+
* @example Basic logging
|
|
69
|
+
* ```ts
|
|
70
|
+
* onDispatchHook.override((prev) => (info) => {
|
|
71
|
+
* prev?.(info); // Call existing handlers first
|
|
72
|
+
* console.log(`Action ${info.meta?.key ?? "anonymous"}: ${info.type}`);
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Error tracking
|
|
77
|
+
* ```ts
|
|
78
|
+
* onDispatchHook.override((prev) => (info) => {
|
|
79
|
+
* prev?.(info);
|
|
80
|
+
* if (info.type === "error" || info.type === "rejected") {
|
|
81
|
+
* reportError(info.error, { action: info.meta?.key });
|
|
82
|
+
* }
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example Performance monitoring
|
|
87
|
+
* ```ts
|
|
88
|
+
* const actionTimings = new Map<string, number>();
|
|
89
|
+
*
|
|
90
|
+
* onDispatchHook.override((prev) => (info) => {
|
|
91
|
+
* prev?.(info);
|
|
92
|
+
* const key = info.meta?.key ?? "anonymous";
|
|
93
|
+
*
|
|
94
|
+
* if (info.type === "start") {
|
|
95
|
+
* actionTimings.set(key, Date.now());
|
|
96
|
+
* } else if (info.type === "resolved" || info.type === "rejected") {
|
|
97
|
+
* const start = actionTimings.get(key);
|
|
98
|
+
* if (start) {
|
|
99
|
+
* console.log(`Action ${key} took ${Date.now() - start}ms`);
|
|
100
|
+
* actionTimings.delete(key);
|
|
101
|
+
* }
|
|
102
|
+
* }
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare const onDispatchHook: import('../core/hook').Hook<((info: DispatchInfo) => void) | undefined>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Pipeable } from '../core/types';
|
|
1
|
+
import { AtomirxMeta, Pipeable } from '../core/types';
|
|
2
2
|
/**
|
|
3
3
|
* State for an action that hasn't been dispatched yet.
|
|
4
4
|
*/
|
|
@@ -45,6 +45,8 @@ export type ActionStateWithoutIdle<T> = Exclude<ActionState<T>, ActionIdleState>
|
|
|
45
45
|
export type AbortablePromise<T> = PromiseLike<T> & {
|
|
46
46
|
abort: () => void;
|
|
47
47
|
};
|
|
48
|
+
export interface ActionMeta extends AtomirxMeta {
|
|
49
|
+
}
|
|
48
50
|
/**
|
|
49
51
|
* Options for useAction hook.
|
|
50
52
|
*/
|
|
@@ -64,6 +66,7 @@ export interface UseActionOptions {
|
|
|
64
66
|
* @default []
|
|
65
67
|
*/
|
|
66
68
|
deps?: unknown[];
|
|
69
|
+
meta?: ActionMeta;
|
|
67
70
|
}
|
|
68
71
|
/**
|
|
69
72
|
* Context passed to the action function.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Root } from 'react-dom/client';
|
|
2
|
+
import { PanelPosition } from '../devtools/types';
|
|
3
|
+
/**
|
|
4
|
+
* Props for DevToolsPanel component.
|
|
5
|
+
*/
|
|
6
|
+
export interface DevToolsPanelProps {
|
|
7
|
+
/**
|
|
8
|
+
* Default panel position.
|
|
9
|
+
* @default "bottom"
|
|
10
|
+
*/
|
|
11
|
+
defaultPosition?: PanelPosition;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the panel is open by default.
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
defaultOpen?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether to auto-setup devtools on mount.
|
|
19
|
+
* If false, you must call setupDevtools() yourself.
|
|
20
|
+
* @default true
|
|
21
|
+
*/
|
|
22
|
+
autoSetup?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Enable devtools in production.
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
enableInProduction?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for renderDevtools function.
|
|
31
|
+
*/
|
|
32
|
+
export interface RenderDevtoolsOptions extends DevToolsPanelProps {
|
|
33
|
+
/**
|
|
34
|
+
* Custom container element ID.
|
|
35
|
+
* @default "atomirx-devtools-root"
|
|
36
|
+
*/
|
|
37
|
+
containerId?: string;
|
|
38
|
+
root?: Root;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Renders devtools in a separate React root.
|
|
42
|
+
*
|
|
43
|
+
* This isolates devtools from the main app's React tree to avoid:
|
|
44
|
+
* - Concurrent update issues
|
|
45
|
+
* - Bugs from app impacting devtools and vice versa
|
|
46
|
+
* - React tree conflicts
|
|
47
|
+
*
|
|
48
|
+
* @param options - Configuration options for devtools
|
|
49
|
+
* @returns Promise that resolves when devtools is mounted
|
|
50
|
+
*
|
|
51
|
+
* @example Basic usage
|
|
52
|
+
* ```tsx
|
|
53
|
+
* // In main.tsx
|
|
54
|
+
* import { renderDevtools } from 'atomirx/react-devtools';
|
|
55
|
+
*
|
|
56
|
+
* // Render devtools first (optional: wait for completion)
|
|
57
|
+
* await renderDevtools();
|
|
58
|
+
*
|
|
59
|
+
* // Then render your app
|
|
60
|
+
* ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @example With options
|
|
64
|
+
* ```tsx
|
|
65
|
+
* renderDevtools({
|
|
66
|
+
* defaultPosition: "right",
|
|
67
|
+
* defaultOpen: true,
|
|
68
|
+
* autoSetup: true,
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderDevtools(options?: RenderDevtoolsOptions): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Unmounts and cleans up devtools.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* import { unmountDevtools } from 'atomirx/react-devtools';
|
|
79
|
+
*
|
|
80
|
+
* // Clean up devtools
|
|
81
|
+
* unmountDevtools();
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function unmountDevtools(): void;
|
|
85
|
+
/**
|
|
86
|
+
* DevTools panel component (legacy - prefer renderDevtools).
|
|
87
|
+
*
|
|
88
|
+
* This component renders devtools within the app's React tree.
|
|
89
|
+
* For better isolation, use renderDevtools() instead.
|
|
90
|
+
*
|
|
91
|
+
* @deprecated Use renderDevtools() for better isolation from app React tree
|
|
92
|
+
*/
|
|
93
|
+
export declare const DevToolsPanel: import('react').NamedExoticComponent<DevToolsPanelProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EntityInfo } from '../devtools/types';
|
|
2
|
+
interface EntityDetailsProps {
|
|
3
|
+
entity: EntityInfo;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Entity details panel component.
|
|
8
|
+
*/
|
|
9
|
+
export declare const EntityDetails: import('react').NamedExoticComponent<EntityDetailsProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EntityInfo, DevtoolsTab, AtomFilter } from '../devtools/types';
|
|
2
|
+
interface EntityListProps {
|
|
3
|
+
entities: ReadonlyMap<string, EntityInfo>;
|
|
4
|
+
activeTab: DevtoolsTab;
|
|
5
|
+
searchText: string;
|
|
6
|
+
atomFilter: AtomFilter;
|
|
7
|
+
selectedEntityId: string | null;
|
|
8
|
+
onSelectEntity: (id: string | null) => void;
|
|
9
|
+
showValues: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Entity list component with filtering and search.
|
|
13
|
+
*/
|
|
14
|
+
export declare const EntityList: import('react').NamedExoticComponent<EntityListProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LogEntry } from '../devtools/types';
|
|
2
|
+
interface LogListProps {
|
|
3
|
+
logs: readonly LogEntry[];
|
|
4
|
+
searchText: string;
|
|
5
|
+
onClearLogs?: () => void;
|
|
6
|
+
showValues?: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Log list component with search.
|
|
10
|
+
*/
|
|
11
|
+
export declare const LogList: import('react').NamedExoticComponent<LogListProps>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DevtoolsPreferences, DevtoolsTab, PanelPosition, AtomFilter, DevtoolsRegistry } from '../devtools/types';
|
|
2
|
+
/**
|
|
3
|
+
* Hook for managing devtools preferences with localStorage persistence.
|
|
4
|
+
*/
|
|
5
|
+
export declare function useDevtoolsPreferences(): {
|
|
6
|
+
preferences: DevtoolsPreferences;
|
|
7
|
+
setIsOpen: (isOpen: boolean) => void;
|
|
8
|
+
setPosition: (position: PanelPosition) => void;
|
|
9
|
+
setActiveTab: (activeTab: DevtoolsTab) => void;
|
|
10
|
+
setPanelSize: (size: number) => void;
|
|
11
|
+
setSearchText: (tab: DevtoolsTab, text: string) => void;
|
|
12
|
+
setAtomFilter: (atomFilter: AtomFilter) => void;
|
|
13
|
+
setSelectedEntityId: (selectedEntityId: string | null) => void;
|
|
14
|
+
setShowAtomValues: (showAtomValues: boolean) => void;
|
|
15
|
+
togglePanel: () => void;
|
|
16
|
+
cyclePosition: () => void;
|
|
17
|
+
toggleShowAtomValues: () => void;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Hook for subscribing to devtools registry changes.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useDevtoolsRegistry(registry: DevtoolsRegistry | null): ReadonlyMap<string, import('.').EntityInfo> | null;
|
|
23
|
+
/**
|
|
24
|
+
* Hook for subscribing to devtools logs changes.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useDevtoolsLogs(registry: DevtoolsRegistry | null): readonly import('.').LogEntry[] | null;
|
|
27
|
+
/**
|
|
28
|
+
* Hook for keyboard shortcuts.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useKeyboardShortcuts(onToggle: () => void, enabled?: boolean): void;
|
|
31
|
+
/**
|
|
32
|
+
* Hook for panel resize handling.
|
|
33
|
+
*/
|
|
34
|
+
export declare function usePanelResize(position: PanelPosition, _initialSize: number, onSizeChange: (size: number) => void): {
|
|
35
|
+
isResizing: boolean;
|
|
36
|
+
handleMouseDown: (e: React.MouseEvent) => void;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Serialize a value for display in devtools.
|
|
40
|
+
* Handles circular references and non-serializable values.
|
|
41
|
+
*/
|
|
42
|
+
export declare function serializeValue(value: unknown, maxLength?: number): string;
|
|
43
|
+
/**
|
|
44
|
+
* Format a timestamp for display.
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatTimestamp(timestamp: number): string;
|
|
47
|
+
/**
|
|
48
|
+
* Format a relative time (e.g., "2s ago").
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatRelativeTime(timestamp: number): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),a=require("react"),se=require("react-dom/client"),d=require("../devtools/index.cjs");function ne(){try{const t=localStorage.getItem(d.STORAGE_KEY_PREFERENCES);if(t){const r=JSON.parse(t);return{...d.DEFAULT_PREFERENCES,...r}}}catch{}return d.DEFAULT_PREFERENCES}function ie(t){try{localStorage.setItem(d.STORAGE_KEY_PREFERENCES,JSON.stringify(t))}catch{}}function L(){const[t,r]=a.useState(()=>ne());a.useEffect(()=>{ie(t)},[t]);const s=a.useCallback(c=>{r(x=>({...x,isOpen:c}))},[]),o=a.useCallback(c=>{r(x=>({...x,position:c}))},[]),n=a.useCallback(c=>{r(x=>({...x,activeTab:c}))},[]),l=a.useCallback(c=>{const x=Math.max(d.MIN_PANEL_SIZE,Math.min(d.MAX_PANEL_SIZE,c));r(b=>({...b,panelSize:x}))},[]),u=a.useCallback((c,x)=>{r(b=>({...b,searchText:{...b.searchText,[c]:x}}))},[]),m=a.useCallback(c=>{r(x=>({...x,atomFilter:c}))},[]),h=a.useCallback(c=>{r(x=>({...x,selectedEntityId:c}))},[]),i=a.useCallback(c=>{r(x=>({...x,showAtomValues:c}))},[]),f=a.useCallback(()=>{r(c=>({...c,showAtomValues:!c.showAtomValues}))},[]),g=a.useCallback(()=>{r(c=>({...c,isOpen:!c.isOpen}))},[]),I=a.useCallback(()=>{r(c=>{const x=["bottom","right","left"],w=(x.indexOf(c.position)+1)%x.length;return{...c,position:x[w]}})},[]);return{preferences:t,setIsOpen:s,setPosition:o,setActiveTab:n,setPanelSize:l,setSearchText:u,setAtomFilter:m,setSelectedEntityId:h,setShowAtomValues:i,togglePanel:g,cyclePosition:I,toggleShowAtomValues:f}}function N(t){const r=a.useCallback(o=>t?t.subscribe(o):()=>{},[t]),s=a.useCallback(()=>t?t.entities:null,[t]);return a.useSyncExternalStore(r,s,s)}function _(t){const r=a.useCallback(o=>t?t.subscribe(o):()=>{},[t]),s=a.useCallback(()=>t?t.logs:null,[t]);return a.useSyncExternalStore(r,s,s)}function M(t,r=!0){a.useEffect(()=>{if(!r)return;const s=o=>{(o.ctrlKey||o.metaKey)&&o.shiftKey&&o.key.toLowerCase()==="d"&&(o.preventDefault(),t())};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[t,r])}function O(t,r,s){const[o,n]=a.useState(!1),l=a.useCallback(u=>{u.preventDefault(),n(!0)},[]);return a.useEffect(()=>{if(!o)return;const u=h=>{let i;switch(t){case"bottom":i=window.innerHeight-h.clientY;break;case"right":i=window.innerWidth-h.clientX;break;case"left":i=h.clientX;break}s(Math.max(d.MIN_PANEL_SIZE,Math.min(d.MAX_PANEL_SIZE,i)))},m=()=>{n(!1)};return document.addEventListener("mousemove",u),document.addEventListener("mouseup",m),()=>{document.removeEventListener("mousemove",u),document.removeEventListener("mouseup",m)}},[o,t,s]),{isResizing:o,handleMouseDown:l}}function S(t,r=500){if(t===void 0)return"undefined";if(t===null)return"null";try{const s=new WeakSet,o=JSON.stringify(t,(n,l)=>{if(typeof l=="object"&&l!==null){if(s.has(l))return"[Circular]";s.add(l)}return typeof l=="function"?"[Function]":typeof l=="symbol"?l.toString():l instanceof Error?`[Error: ${l.message}]`:l instanceof Map?`[Map(${l.size})]`:l instanceof Set?`[Set(${l.size})]`:l instanceof WeakMap?"[WeakMap]":l instanceof WeakSet?"[WeakSet]":l instanceof Promise?"[Promise]":l},2);return o.length>r?o.slice(0,r)+"...":o}catch{return"[unserializable]"}}function C(t){const r=new Date(t),s=r.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"}),o=String(r.getMilliseconds()).padStart(3,"0");return`${s}.${o}`}const ae={"--atomirx-bg-primary":"#1a1a2e","--atomirx-bg-secondary":"#16213e","--atomirx-bg-tertiary":"#0f3460","--atomirx-bg-hover":"#1f4287","--atomirx-text-primary":"#eaeaea","--atomirx-text-secondary":"#a0a0a0","--atomirx-text-muted":"#666666","--atomirx-border":"#2a2a4a","--atomirx-accent":"#e94560","--atomirx-accent-hover":"#ff6b6b","--atomirx-success":"#4ade80","--atomirx-warning":"#fbbf24","--atomirx-error":"#ef4444","--atomirx-info":"#3b82f6","--atomirx-badge-mutable":"#3b82f6","--atomirx-badge-derived":"#8b5cf6","--atomirx-badge-effect":"#f59e0b","--atomirx-badge-pool":"#10b981","--atomirx-badge-module":"#ec4899","--atomirx-radius":"6px","--atomirx-radius-lg":"8px","--atomirx-font-size":"11px","--atomirx-font-size-sm":"9px","--atomirx-font-mono":"ui-monospace, SFMono-Regular, SF Mono, Menlo, monospace"},le={...Object.fromEntries(Object.entries(ae).map(([t,r])=>[t,r])),fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',fontSize:"var(--atomirx-font-size)",color:"var(--atomirx-text-primary)",boxSizing:"border-box"},ce={position:"fixed",bottom:16,left:16,width:d.FLOATING_BUTTON_SIZE,height:d.FLOATING_BUTTON_SIZE,borderRadius:"50%",backgroundColor:"var(--atomirx-accent)",color:"white",border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.3)",zIndex:d.DEVTOOLS_Z_INDEX+1,transition:`transform ${d.ANIMATION_DURATION}ms ease, background-color ${d.ANIMATION_DURATION}ms ease`},de=(t,r,s)=>{const o={position:"fixed",backgroundColor:"var(--atomirx-bg-primary)",borderColor:"var(--atomirx-border)",borderStyle:"solid",borderTopWidth:0,borderRightWidth:0,borderBottomWidth:0,borderLeftWidth:0,zIndex:d.DEVTOOLS_Z_INDEX,display:"flex",flexDirection:"column",transition:`transform ${d.ANIMATION_DURATION}ms ease`,overflow:"hidden"};switch(t){case"bottom":return{...o,left:0,right:0,bottom:0,height:r,borderTopWidth:1,transform:s?"translateY(0)":"translateY(100%)"};case"right":return{...o,top:0,right:0,bottom:0,width:r,borderLeftWidth:1,transform:s?"translateX(0)":"translateX(100%)"};case"left":return{...o,top:0,left:0,bottom:0,width:r,borderRightWidth:1,transform:s?"translateX(0)":"translateX(-100%)"}}},ue={display:"flex",alignItems:"center",gap:0,backgroundColor:"var(--atomirx-bg-secondary)",borderBottom:"1px solid var(--atomirx-border)",padding:"0 8px",height:40,flexShrink:0},xe=t=>({padding:"8px 14px",background:"none",border:"none",color:t?"var(--atomirx-text-primary)":"var(--atomirx-text-secondary)",cursor:"pointer",fontSize:"var(--atomirx-font-size)",fontWeight:t?600:400,borderBottom:t?"2px solid var(--atomirx-accent)":"2px solid transparent",marginBottom:-1,transition:`color ${d.ANIMATION_DURATION}ms ease, border-color ${d.ANIMATION_DURATION}ms ease`}),me={display:"flex",alignItems:"center",gap:8,padding:"8px 12px",backgroundColor:"var(--atomirx-bg-secondary)",borderBottom:"1px solid var(--atomirx-border)",flexShrink:0},fe={flex:1,padding:"6px 10px",backgroundColor:"var(--atomirx-bg-tertiary)",border:"1px solid var(--atomirx-border)",borderRadius:"var(--atomirx-radius)",color:"var(--atomirx-text-primary)",fontSize:"var(--atomirx-font-size)",outline:"none",minWidth:0},pe={display:"flex",gap:0,borderRadius:"var(--atomirx-radius)",overflow:"hidden",border:"1px solid var(--atomirx-border)"},z=t=>({padding:"4px 10px",background:t?"var(--atomirx-bg-hover)":"var(--atomirx-bg-tertiary)",border:"none",color:t?"var(--atomirx-text-primary)":"var(--atomirx-text-secondary)",cursor:"pointer",fontSize:"var(--atomirx-font-size-sm)",transition:`background-color ${d.ANIMATION_DURATION}ms ease`}),P={flex:1,overflow:"auto",padding:0},he=t=>({display:"flex",alignItems:"center",gap:8,padding:"8px 12px",borderBottom:"1px solid var(--atomirx-border)",cursor:"pointer",backgroundColor:t?"var(--atomirx-bg-hover)":"transparent",transition:`background-color ${d.ANIMATION_DURATION}ms ease`}),F=t=>({display:"inline-flex",alignItems:"center",justifyContent:"center",width:22,height:22,borderRadius:"var(--atomirx-radius)",backgroundColor:{mutable:"var(--atomirx-badge-mutable)",derived:"var(--atomirx-badge-derived)",effect:"var(--atomirx-badge-effect)",pool:"var(--atomirx-badge-pool)",module:"var(--atomirx-badge-module)"}[t],color:"white",fontSize:"var(--atomirx-font-size-sm)",fontWeight:600,flexShrink:0}),B={flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontFamily:"var(--atomirx-font-mono)",fontSize:11},W={color:"var(--atomirx-text-muted)",fontSize:"var(--atomirx-font-size-sm)",fontFamily:"var(--atomirx-font-mono)",maxWidth:150,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},ve={position:"absolute",top:0,left:0,right:0,bottom:0,backgroundColor:"var(--atomirx-bg-primary)",display:"flex",flexDirection:"column",overflow:"hidden",zIndex:100},ge={padding:"10px",borderBottom:"1px solid var(--atomirx-border)",fontWeight:600},be={padding:"10px",borderBottom:"1px solid var(--atomirx-border)"},ye={fontSize:"var(--atomirx-font-size-sm)",color:"var(--atomirx-text-secondary)",marginBottom:4,textTransform:"uppercase",letterSpacing:"0.5px"},y={fontFamily:"var(--atomirx-font-mono)",fontSize:"var(--atomirx-font-size)",wordBreak:"break-all"},k={backgroundColor:"var(--atomirx-bg-tertiary)",padding:"6px 8px",borderRadius:"var(--atomirx-radius)",fontFamily:"var(--atomirx-font-mono)",fontSize:"var(--atomirx-font-size-sm)",whiteSpace:"pre-wrap",wordBreak:"break-all"},Se={padding:"4px 0",borderBottom:"1px solid var(--atomirx-border)",fontSize:"var(--atomirx-font-size-sm)"},je={color:"var(--atomirx-text-muted)",fontSize:"var(--atomirx-font-size-sm)"},Ee={padding:"4px 8px",background:"var(--atomirx-bg-tertiary)",border:"1px solid var(--atomirx-border)",borderRadius:"var(--atomirx-radius)",color:"var(--atomirx-text-secondary)",cursor:"pointer",fontSize:"var(--atomirx-font-size-sm)",marginLeft:"auto"},U={padding:"4px 8px",background:"none",border:"none",color:"var(--atomirx-text-secondary)",cursor:"pointer",fontSize:18,lineHeight:1},V={display:"flex",alignItems:"center",justifyContent:"center",padding:32,color:"var(--atomirx-text-muted)",fontStyle:"italic"},D=t=>({display:"inline-block",width:8,height:8,borderRadius:"50%",backgroundColor:{ready:"var(--atomirx-success)",loading:"var(--atomirx-warning)",error:"var(--atomirx-error)"}[t],marginRight:6}),Ie=t=>{const r={position:"absolute",backgroundColor:"transparent",zIndex:1};switch(t){case"bottom":return{...r,top:0,left:0,right:0,height:4,cursor:"ns-resize"};case"right":return{...r,top:0,left:0,bottom:0,width:4,cursor:"ew-resize"};case"left":return{...r,top:0,right:0,bottom:0,width:4,cursor:"ew-resize"}}},ke={display:"flex",flex:1,overflow:"hidden"};function Ce(t,r){const s=t.instanceRef.deref();if(!s)return"[disposed]";switch(t.type){case"mutable":return r?S(s.get(),50):"—";case"derived":return r?S(s.staleValue,50):"—";case"effect":return`runs: ${t.runCount}`;case"pool":return`entries: ${s.size()}`;case"module":return"[module]";default:return""}}function T(t){const r=t.instanceRef.deref();return r?r.state().status:"error"}const we=a.memo(function({entity:r,isSelected:s,onClick:o,showValues:n}){const[l,u]=a.useState(0);a.useEffect(()=>{const i=r.instanceRef.deref();if(i){if(r.type==="mutable"||r.type==="derived")return n?i.on(()=>{u(g=>g+1)}):void 0;if(r.type==="pool")return i.on(()=>{u(g=>g+1)})}},[r,n]);const m=a.useMemo(()=>Ce(r,n),[r,n,l]),h=r.key||`anonymous-${r.id.split("-").pop()}`;return e.jsxs("div",{style:{...he(s),flexDirection:"column",alignItems:"stretch",gap:4},onClick:o,onMouseEnter:i=>{s||(i.currentTarget.style.backgroundColor="var(--atomirx-bg-hover)")},onMouseLeave:i=>{s||(i.currentTarget.style.backgroundColor="transparent")},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:F(r.type),children:r.type==="mutable"?"M":r.type==="derived"?"D":r.type==="pool"?"P":r.type==="effect"?"E":"M"}),e.jsx("span",{style:{...B,...r.type==="derived"&&{color:T(r)==="ready"?"var(--atomirx-success)":T(r)==="loading"?"var(--atomirx-warning)":T(r)==="error"?"var(--atomirx-error)":void 0}},title:h,children:h}),e.jsx("span",{style:{color:"var(--atomirx-text-muted)",fontSize:"var(--atomirx-font-size-sm)",flexShrink:0,marginLeft:"auto"},children:C(r.lastUpdatedAt)})]}),n&&m!=="—"&&e.jsx("div",{style:{...W,marginLeft:30,maxWidth:"none"},title:m,children:m})]})}),Te=a.memo(function({entities:r,activeTab:s,searchText:o,atomFilter:n,selectedEntityId:l,onSelectEntity:u,showValues:m}){const h=a.useMemo(()=>{var I;const f=[],g=o.toLowerCase();for(const c of r.values()){switch(s){case"atoms":if(c.type!=="mutable"&&c.type!=="derived"||n==="mutable"&&c.type!=="mutable"||n==="derived"&&c.type!=="derived")continue;break;case"effects":if(c.type!=="effect")continue;break;case"pools":if(c.type!=="pool")continue;break;case"modules":if(c.type!=="module")continue;break}if(o){const x=(I=c.key)==null?void 0:I.toLowerCase().includes(g),b=c.id.toLowerCase().includes(g);if(!x&&!b)continue}f.push(c)}return f.sort((c,x)=>x.lastUpdatedAt-c.lastUpdatedAt),f},[r,s,o,n]),i=a.useCallback(f=>{u(l===f?null:f)},[l,u]);return h.length===0?e.jsx("div",{style:V,children:o?`No ${s} matching "${o}"`:`No ${s} registered`}):e.jsx("div",{style:P,children:h.map(f=>e.jsx(we,{entity:f,isSelected:f.id===l,onClick:()=>i(f.id),showValues:m},f.id))})});function $(t){const r=t.instanceRef.deref();if(!r)return{value:"[disposed]",status:"error"};switch(t.type){case"mutable":return{value:S(r.get()),status:"ready"};case"derived":{const o=r.state();return o.status==="loading"?{value:"[loading...]",status:"loading"}:o.status==="error"?{value:S(o.error),status:"error"}:{value:S(o.value),status:"ready"}}case"pool":{const s=r,o=[];return s.forEach((n,l)=>{o.push({params:l,value:n})}),{value:S(o),status:"ready"}}case"effect":case"module":return{value:"[N/A]",status:"ready"};default:return{value:"[unknown]"}}}function v({label:t,children:r}){return e.jsxs("div",{style:be,children:[e.jsx("div",{style:ye,children:t}),r]})}function Z({entry:t}){return e.jsxs("div",{style:Se,children:[e.jsx("div",{style:je,children:C(t.timestamp)}),e.jsxs("div",{style:{marginTop:4},children:[e.jsx("span",{style:{color:"var(--atomirx-error)"},children:"- "}),e.jsx("span",{style:{fontFamily:"var(--atomirx-font-mono)"},children:t.previousValue.length>100?t.previousValue.slice(0,100)+"...":t.previousValue})]}),e.jsxs("div",{children:[e.jsx("span",{style:{color:"var(--atomirx-success)"},children:"+ "}),e.jsx("span",{style:{fontFamily:"var(--atomirx-font-mono)"},children:t.newValue.length>100?t.newValue.slice(0,100)+"...":t.newValue})]})]})}function De({entity:t}){const{value:r,status:s}=a.useMemo(()=>$(t),[t]);return e.jsxs(e.Fragment,{children:[e.jsxs(v,{label:"Current Value",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",marginBottom:8},children:[e.jsx("span",{style:D(s||"ready")}),e.jsx("span",{style:y,children:s})]}),e.jsx("div",{style:k,children:r})]}),e.jsx(v,{label:"Stats",children:e.jsxs("div",{style:y,children:[e.jsxs("div",{children:["Changes: ",t.changeCount]}),e.jsxs("div",{children:["Subscribers: ",t.subscriberCount]})]})}),t.history.length>0&&e.jsx(v,{label:`History (${t.history.length})`,children:t.history.map((o,n)=>e.jsx(Z,{entry:o},n))})]})}function Ae({entity:t}){const{value:r,status:s}=a.useMemo(()=>$(t),[t]);return e.jsxs(e.Fragment,{children:[e.jsxs(v,{label:"Current Value",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",marginBottom:8},children:[e.jsx("span",{style:D(s||"ready")}),e.jsx("span",{style:y,children:s})]}),e.jsx("div",{style:k,children:r})]}),e.jsx(v,{label:"Stats",children:e.jsxs("div",{style:y,children:[e.jsxs("div",{children:["Changes: ",t.changeCount]}),e.jsxs("div",{children:["Subscribers: ",t.subscriberCount]}),e.jsxs("div",{children:["Dependencies: ",t.dependencyIds.length||"unknown"]})]})}),t.dependencyIds.length>0&&e.jsx(v,{label:"Dependencies",children:e.jsx("div",{style:k,children:t.dependencyIds.map(o=>e.jsx("div",{children:o},o))})}),t.history.length>0&&e.jsx(v,{label:`History (${t.history.length})`,children:t.history.map((o,n)=>e.jsx(Z,{entry:o},n))})]})}function Re({entity:t}){return e.jsxs(e.Fragment,{children:[e.jsx(v,{label:"Status",children:e.jsx("div",{style:y,children:e.jsxs("div",{style:{display:"flex",alignItems:"center"},children:[e.jsx("span",{style:D(t.isActive?"ready":"error")}),t.isActive?"Active":"Disposed"]})})}),e.jsx(v,{label:"Stats",children:e.jsxs("div",{style:y,children:[e.jsxs("div",{children:["Run count: ",t.runCount]}),e.jsxs("div",{children:["Changes: ",t.changeCount]})]})}),t.dependencyIds.length>0&&e.jsx(v,{label:"Dependencies",children:e.jsx("div",{style:k,children:t.dependencyIds.map(r=>e.jsx("div",{children:r},r))})})]})}function ze({params:t,value:r}){return e.jsxs("div",{style:{padding:"8px",borderBottom:"1px solid var(--atomirx-border)"},children:[e.jsxs("div",{style:{marginBottom:4},children:[e.jsx("span",{style:{fontSize:"var(--atomirx-font-size-sm)",color:"var(--atomirx-text-secondary)",marginRight:6},children:"params:"}),e.jsx("span",{style:{fontFamily:"var(--atomirx-font-mono)",fontSize:"var(--atomirx-font-size)",color:"var(--atomirx-info)"},children:S(t,100)})]}),e.jsxs("div",{children:[e.jsx("span",{style:{fontSize:"var(--atomirx-font-size-sm)",color:"var(--atomirx-text-secondary)",marginRight:6},children:"value:"}),e.jsx("span",{style:{fontFamily:"var(--atomirx-font-mono)",fontSize:"var(--atomirx-font-size)"},children:S(r,200)})]})]})}function Le({entity:t}){const[r,s]=a.useState(0);a.useEffect(()=>{const n=t.instanceRef.deref();return n?n.on(()=>{s(u=>u+1)}):void 0},[t]);const o=a.useMemo(()=>{const n=t.instanceRef.deref();if(!n)return[];const l=n,u=[];return l.forEach((m,h)=>{u.push({params:h,value:m})}),u},[t,r]);return e.jsxs(e.Fragment,{children:[e.jsx(v,{label:"Config",children:e.jsxs("div",{style:y,children:[e.jsxs("div",{children:["Entry count: ",o.length]}),e.jsxs("div",{children:["GC time: ",t.gcTime,"ms"]}),e.jsxs("div",{children:["Changes: ",t.changeCount]})]})}),e.jsx(v,{label:`Entries (${o.length})`,children:o.length===0?e.jsx("div",{style:{color:"var(--atomirx-text-muted)",fontStyle:"italic",padding:8},children:"No entries"}):e.jsx("div",{style:{backgroundColor:"var(--atomirx-bg-tertiary)",borderRadius:"var(--atomirx-radius)",overflow:"hidden"},children:o.map((n,l)=>e.jsx(ze,{params:n.params,value:n.value},l))})})]})}function Ne({entity:t}){const r=t.instanceRef.deref(),s=r?Object.keys(r):[];return e.jsxs(e.Fragment,{children:[e.jsx(v,{label:"Exports",children:e.jsx("div",{style:k,children:s.length>0?s.join(", "):"[empty or disposed]"})}),e.jsx(v,{label:"Stats",children:e.jsx("div",{style:y,children:e.jsxs("div",{children:["Changes: ",t.changeCount]})})})]})}const _e=a.memo(function({entity:r,onClose:s}){const o=r.key||`anonymous-${r.id.split("-").pop()}`;return e.jsxs("div",{style:ve,children:[e.jsxs("div",{style:{...ge,display:"flex",alignItems:"center",gap:8,flexShrink:0},children:[e.jsx("button",{style:U,onClick:s,title:"Back to list",children:"←"}),e.jsx("span",{style:F(r.type),children:r.type==="mutable"?"M":r.type==="derived"?"D":r.type==="pool"?"P":r.type==="effect"?"E":"M"}),e.jsx("span",{style:{flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",minWidth:0,fontSize:12},title:o,children:o})]}),e.jsxs("div",{style:{flex:"1 1 0",overflow:"auto",minHeight:0,height:0},children:[e.jsx(v,{label:"ID",children:e.jsx("div",{style:{...y,fontSize:"var(--atomirx-font-size-sm)"},children:r.id})}),e.jsx(v,{label:"Created",children:e.jsx("div",{style:y,children:C(r.createdAt)})}),r.type==="mutable"&&e.jsx(De,{entity:r}),r.type==="derived"&&e.jsx(Ae,{entity:r}),r.type==="effect"&&e.jsx(Re,{entity:r}),r.type==="pool"&&e.jsx(Le,{entity:r}),r.type==="module"&&e.jsx(Ne,{entity:r})]})]})}),X={"action.dispatch":{color:"#3b82f6",label:"A"},error:{color:"#ef4444",label:"E"},"mutable.change":{color:"#10b981",label:"M"},"mutable.reset":{color:"#10b981",label:"M"},"derived.change":{color:"#8b5cf6",label:"D"},"derived.refresh":{color:"#8b5cf6",label:"D"},"pool.create":{color:"#f97316",label:"P"},"pool.set":{color:"#f97316",label:"P"},"pool.remove":{color:"#f97316",label:"P"}};function Me(t){return{display:"inline-flex",alignItems:"center",justifyContent:"center",width:22,height:22,borderRadius:"var(--atomirx-radius)",backgroundColor:(X[t]??{color:"#6b7280"}).color,color:"white",fontSize:"var(--atomirx-font-size-sm)",fontWeight:600,flexShrink:0}}function Oe(t){var r;return((r=X[t])==null?void 0:r.label)??"?"}function K(t){switch(t.type){case"action.dispatch":return t.actionKey;case"error":return t.sourceKey||t.sourceType;case"mutable.change":case"mutable.reset":case"derived.change":case"derived.refresh":return t.atomKey;case"pool.create":case"pool.set":case"pool.remove":return t.poolKey;default:return"unknown"}}function G(t){switch(t.type){case"action.dispatch":return"dispatch";case"error":return"error";case"mutable.change":return"change";case"mutable.reset":return"reset";case"derived.change":return"change";case"derived.refresh":return"refresh";case"pool.create":return"create";case"pool.set":return"set";case"pool.remove":return"remove";default:return""}}function H(t){switch(t.type){case"action.dispatch":return t.deps;case"error":return t.error;case"pool.create":case"pool.set":case"pool.remove":return t.params;case"mutable.change":case"mutable.reset":case"derived.change":case"derived.refresh":return null;default:return null}}const Pe=a.memo(function({log:r,showValues:s}){const o=r.type==="error",n=H(r);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4,padding:"8px 12px",borderBottom:"1px solid var(--atomirx-border)",cursor:"default"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:Me(r.type),children:Oe(r.type)}),e.jsx("span",{style:{...B,color:o?"var(--atomirx-error)":"var(--atomirx-text-primary)"},children:K(r)}),e.jsx("span",{style:{color:"var(--atomirx-text-secondary)",fontSize:"var(--atomirx-font-size-sm)"},children:G(r)}),e.jsx("span",{style:{color:"var(--atomirx-text-muted)",fontSize:"var(--atomirx-font-size-sm)",flexShrink:0,marginLeft:"auto"},children:C(r.timestamp)})]}),s&&n&&e.jsx("div",{style:{...W,marginLeft:30,maxWidth:"none"},title:n,children:n})]})}),Fe={padding:"4px 8px",fontSize:"var(--atomirx-font-size-sm)",backgroundColor:"var(--atomirx-bg-tertiary)",border:"1px solid var(--atomirx-border)",borderRadius:"var(--atomirx-radius)",color:"var(--atomirx-text-secondary)",cursor:"pointer",display:"flex",alignItems:"center",gap:4},Be=a.memo(function({logs:r,searchText:s,onClearLogs:o,showValues:n=!0}){const l=a.useMemo(()=>{if(!s)return r;const u=s.toLowerCase();return r.filter(m=>{var g;const h=K(m).toLowerCase(),i=G(m).toLowerCase(),f=((g=H(m))==null?void 0:g.toLowerCase())??"";return h.includes(u)||i.includes(u)||f.includes(u)})},[r,s]);return l.length===0?e.jsx("div",{style:{...V,width:"100%"},children:s?`No logs matching "${s}"`:"No logs yet. Dispatch actions or trigger errors to see logs."}):e.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",width:"100%"},children:[e.jsxs("div",{style:{display:"flex",justifyContent:"flex-end",alignItems:"center",padding:"6px 12px",borderBottom:"1px solid var(--atomirx-border)",backgroundColor:"var(--atomirx-bg-secondary)",flexShrink:0},children:[e.jsxs("span",{style:{fontSize:"var(--atomirx-font-size-sm)",color:"var(--atomirx-text-muted)",marginRight:"auto"},children:[l.length," log",l.length!==1?"s":""]}),o&&e.jsxs("button",{style:Fe,onClick:o,title:"Clear all logs",children:[e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("polyline",{points:"3,6 5,6 21,6"}),e.jsx("path",{d:"M19,6v14a2,2,0,0,1-2,2H7a2,2,0,0,1-2-2V6m3,0V4a2,2,0,0,1,2-2h4a2,2,0,0,1,2,2v2"})]}),"Clear"]})]}),e.jsx("div",{style:{...P,flex:1},children:l.map(u=>e.jsx(Pe,{log:u,showValues:n},u.id))})]})});function We(){return e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e.jsx("circle",{cx:"12",cy:"12",r:"3",fill:"currentColor"}),e.jsx("ellipse",{cx:"12",cy:"12",rx:"10",ry:"4",stroke:"currentColor",strokeWidth:"1.5",fill:"none"}),e.jsx("ellipse",{cx:"12",cy:"12",rx:"10",ry:"4",stroke:"currentColor",strokeWidth:"1.5",fill:"none",transform:"rotate(60 12 12)"}),e.jsx("ellipse",{cx:"12",cy:"12",rx:"10",ry:"4",stroke:"currentColor",strokeWidth:"1.5",fill:"none",transform:"rotate(120 12 12)"})]})}function Ue(){return e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}),e.jsx("line",{x1:"9",y1:"3",x2:"9",y2:"21"})]})}const Ve=[{id:"atoms",label:"Atoms"},{id:"effects",label:"Effects"},{id:"pools",label:"Pools"},{id:"modules",label:"Modules"},{id:"logs",label:"Logs"}],$e=[{id:"all",label:"A"},{id:"mutable",label:"M"},{id:"derived",label:"D"}],Ze=a.memo(function({defaultPosition:r,defaultOpen:s,autoSetup:o=!0,enableInProduction:n=!1}){a.useEffect(()=>{if(o)return d.setupDevtools({enableInProduction:n})},[o,n]);const[l,u]=a.useState(()=>d.getDevtoolsRegistry());a.useEffect(()=>{const p=()=>{const R=d.getDevtoolsRegistry();R!==l&&u(R)};p();const oe=setTimeout(p,100);return()=>clearTimeout(oe)},[l]);const m=N(l),h=_(l),{preferences:i,setIsOpen:f,setActiveTab:g,setPanelSize:I,setSearchText:c,setAtomFilter:x,setSelectedEntityId:b,togglePanel:w,cyclePosition:J,toggleShowAtomValues:Q}=L();a.useEffect(()=>{r&&i.position,s!==void 0&&!i.isOpen&&s&&f(!0)},[]),M(w);const{handleMouseDown:ee}=O(i.position,i.panelSize,I),A=i.selectedEntityId?m==null?void 0:m.get(i.selectedEntityId):null,te=a.useCallback(p=>{c(i.activeTab,p.target.value)},[i.activeTab,c]),re=a.useCallback(p=>{g(p),b(null)},[g,b]);return l?e.jsxs("div",{style:le,children:[!i.isOpen&&e.jsx("button",{style:ce,onClick:w,title:"Toggle Atomirx DevTools (Ctrl+Shift+D)",onMouseEnter:p=>{p.currentTarget.style.backgroundColor="var(--atomirx-accent-hover)"},onMouseLeave:p=>{p.currentTarget.style.backgroundColor="var(--atomirx-accent)"},children:e.jsx(We,{})}),e.jsxs("div",{style:de(i.position,i.panelSize,i.isOpen),children:[e.jsx("div",{style:Ie(i.position),onMouseDown:ee}),e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:"8px 12px",backgroundColor:"var(--atomirx-bg-secondary)",borderBottom:"1px solid var(--atomirx-border)",flexShrink:0},children:[e.jsx("span",{style:{fontWeight:600,fontSize:"var(--atomirx-font-size)"},children:"Atomirx Devtools"}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4},children:[e.jsx("button",{style:Ee,onClick:J,title:`Position: ${i.position} (click to change)`,children:e.jsx(Ue,{})}),e.jsx("button",{style:U,onClick:()=>f(!1),title:"Close panel",children:"×"})]})]}),e.jsxs("div",{style:{flex:1,display:"flex",flexDirection:"column",position:"relative",minHeight:0},children:[e.jsx("div",{style:ue,children:Ve.map(p=>e.jsx("button",{style:xe(i.activeTab===p.id),onClick:()=>re(p.id),children:p.label},p.id))}),e.jsx("div",{style:{padding:"8px 12px",borderBottom:"1px solid var(--atomirx-border)"},children:e.jsx("input",{type:"text",style:{...fe,width:"100%"},placeholder:`Search ${i.activeTab}...`,value:i.searchText[i.activeTab],onChange:te})}),i.activeTab==="atoms"&&e.jsxs("div",{style:{...me,justifyContent:"space-between"},children:[e.jsx("div",{style:pe,children:$e.map(p=>e.jsx("button",{style:z(i.atomFilter===p.id),onClick:()=>x(p.id),children:p.label},p.id))}),e.jsx("button",{style:{...z(i.showAtomValues),display:"inline-flex",alignItems:"center",justifyContent:"center",padding:"4px 8px"},onClick:Q,title:i.showAtomValues?"Hide values (single line)":"Show values (two lines with data)",children:e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:i.showAtomValues?e.jsxs(e.Fragment,{children:[e.jsx("path",{d:"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"}),e.jsx("circle",{cx:"12",cy:"12",r:"3"})]}):e.jsxs(e.Fragment,{children:[e.jsx("path",{d:"M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"}),e.jsx("path",{d:"M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"}),e.jsx("path",{d:"M1 1l22 22"})]})})})]}),e.jsx("div",{style:ke,children:i.activeTab==="logs"?e.jsx(Be,{logs:h??[],searchText:i.searchText.logs,onClearLogs:()=>l.clearLogs()}):e.jsx(Te,{entities:m??new Map,activeTab:i.activeTab,searchText:i.searchText[i.activeTab],atomFilter:i.atomFilter,selectedEntityId:i.selectedEntityId,onSelectEntity:b,showValues:i.showAtomValues})}),A&&i.activeTab!=="logs"&&e.jsx(_e,{entity:A,onClose:()=>b(null)})]})]})]}):null});let j=null,E=null;function Y(t={}){return new Promise(r=>{const{containerId:s="atomirx-devtools-root",...o}=t;j&&(j.unmount(),j=null),E&&(E.remove(),E=null),o.autoSetup!==!1&&d.setupDevtools({enableInProduction:o.enableInProduction});const n=document.createElement("div");n.id=s,n.style.position="fixed",n.style.top="0",n.style.left="0",n.style.width="0",n.style.height="0",n.style.overflow="visible",n.style.zIndex="999999",n.style.pointerEvents="none",document.body.appendChild(n),E=n,j=t.root??se.createRoot(n),j.render(e.jsx("div",{style:{pointerEvents:"auto"},children:e.jsx(Ze,{...o,autoSetup:!1})})),queueMicrotask(r)})}function q(){j&&(j.unmount(),j=null),E&&(E.remove(),E=null)}const Xe=a.memo(function(r){const[s,o]=a.useState(!1);return a.useEffect(()=>(Y({...r,autoSetup:r.autoSetup}),o(!0),()=>{q()}),[]),null});exports.ANIMATION_DURATION=d.ANIMATION_DURATION;exports.DEFAULT_MAX_HISTORY_SIZE=d.DEFAULT_MAX_HISTORY_SIZE;exports.DEFAULT_PANEL_SIZE=d.DEFAULT_PANEL_SIZE;exports.DEFAULT_PREFERENCES=d.DEFAULT_PREFERENCES;exports.DEVTOOLS_Z_INDEX=d.DEVTOOLS_Z_INDEX;exports.ENTITY_ID_PREFIX=d.ENTITY_ID_PREFIX;exports.FLOATING_BUTTON_SIZE=d.FLOATING_BUTTON_SIZE;exports.MAX_PANEL_SIZE=d.MAX_PANEL_SIZE;exports.MIN_PANEL_SIZE=d.MIN_PANEL_SIZE;exports.STORAGE_KEY_PREFERENCES=d.STORAGE_KEY_PREFERENCES;exports.STORAGE_VERSION=d.STORAGE_VERSION;exports._resetDevtools=d._resetDevtools;exports.getDevtoolsRegistry=d.getDevtoolsRegistry;exports.getRegistry=d.getRegistry;exports.isDevtoolsEnabled=d.isDevtoolsEnabled;exports.resetRegistry=d.resetRegistry;exports.setupDevtools=d.setupDevtools;exports.DevToolsPanel=Xe;exports.formatTimestamp=C;exports.renderDevtools=Y;exports.serializeValue=S;exports.unmountDevtools=q;exports.useDevtoolsLogs=_;exports.useDevtoolsPreferences=L;exports.useDevtoolsRegistry=N;exports.useKeyboardShortcuts=M;exports.usePanelResize=O;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomirx React DevTools
|
|
3
|
+
*
|
|
4
|
+
* A React-based devtools UI for inspecting atomirx entities.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*
|
|
8
|
+
* @example Basic usage with renderDevtools (recommended)
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // In main.tsx - renders devtools in separate React root
|
|
11
|
+
* import { renderDevtools } from 'atomirx/react-devtools';
|
|
12
|
+
*
|
|
13
|
+
* renderDevtools().then(() => {
|
|
14
|
+
* // Devtools ready, now render your app
|
|
15
|
+
* ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
|
16
|
+
* });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example With custom options
|
|
20
|
+
* ```tsx
|
|
21
|
+
* renderDevtools({
|
|
22
|
+
* defaultPosition: "right",
|
|
23
|
+
* defaultOpen: process.env.NODE_ENV === 'development',
|
|
24
|
+
* enableInProduction: false,
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export { DevToolsPanel, renderDevtools, unmountDevtools, } from './DevToolsPanel';
|
|
29
|
+
export type { DevToolsPanelProps, RenderDevtoolsOptions } from './DevToolsPanel';
|
|
30
|
+
export * from '../devtools';
|
|
31
|
+
export { useDevtoolsPreferences, useDevtoolsRegistry, useDevtoolsLogs, useKeyboardShortcuts, usePanelResize, serializeValue, formatTimestamp, } from './hooks';
|