srasm 0.0.2 → 0.0.3
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/dist/index.cjs +3 -6
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -5
- package/package.json +5 -30
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -35,7 +34,7 @@ __export(index_exports, {
|
|
|
35
34
|
});
|
|
36
35
|
module.exports = __toCommonJS(index_exports);
|
|
37
36
|
|
|
38
|
-
// src/context/createStateStore.
|
|
37
|
+
// src/context/createStateStore.ts
|
|
39
38
|
var import_react = __toESM(require("react"), 1);
|
|
40
39
|
|
|
41
40
|
// src/utils/deepEqual.ts
|
|
@@ -55,9 +54,8 @@ function deepEqual(obj1, obj2) {
|
|
|
55
54
|
return true;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
// src/context/createStateStore.
|
|
57
|
+
// src/context/createStateStore.ts
|
|
59
58
|
var import_with_selector = require("use-sync-external-store/with-selector");
|
|
60
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
61
59
|
function createStateStore(initialSlices) {
|
|
62
60
|
let storeState = { ...initialSlices };
|
|
63
61
|
const sliceListeners = /* @__PURE__ */ new Map();
|
|
@@ -142,7 +140,7 @@ function createStateStore(initialSlices) {
|
|
|
142
140
|
const SRASMProvider = ({
|
|
143
141
|
children
|
|
144
142
|
}) => {
|
|
145
|
-
return
|
|
143
|
+
return children;
|
|
146
144
|
};
|
|
147
145
|
return { SRASMProvider, useSRASM, useSRASMAsync };
|
|
148
146
|
}
|
|
@@ -159,4 +157,3 @@ var logClick = (event) => {
|
|
|
159
157
|
createStateStore,
|
|
160
158
|
logClick
|
|
161
159
|
});
|
|
162
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -15,16 +14,18 @@ import React from 'react';
|
|
|
15
14
|
declare function createStateStore<Slices extends Record<string, any>>(initialSlices: Slices): {
|
|
16
15
|
SRASMProvider: ({ children, }: {
|
|
17
16
|
children: React.ReactNode;
|
|
18
|
-
}) =>
|
|
17
|
+
}) => React.ReactElement<{
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
}>;
|
|
19
20
|
useSRASM: <K extends keyof Slices, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: {
|
|
20
21
|
useDeepEqualCheck?: boolean;
|
|
21
22
|
isEqual?: (a: Selected, b: Selected) => boolean;
|
|
22
23
|
}) => {
|
|
23
|
-
state:
|
|
24
|
+
state: any;
|
|
24
25
|
setState: (payload: Partial<Slices[K]> | ((prev: Slices[K]) => Partial<Slices[K]>)) => void;
|
|
25
26
|
};
|
|
26
27
|
useSRASMAsync: <K extends keyof Slices>(slice: K, fetcher: () => Promise<Slices[K]>, tags?: any[]) => {
|
|
27
|
-
data:
|
|
28
|
+
data: any;
|
|
28
29
|
loading: boolean;
|
|
29
30
|
error: any;
|
|
30
31
|
refetch: () => Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import React from 'react';
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -15,16 +14,18 @@ import React from 'react';
|
|
|
15
14
|
declare function createStateStore<Slices extends Record<string, any>>(initialSlices: Slices): {
|
|
16
15
|
SRASMProvider: ({ children, }: {
|
|
17
16
|
children: React.ReactNode;
|
|
18
|
-
}) =>
|
|
17
|
+
}) => React.ReactElement<{
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
}>;
|
|
19
20
|
useSRASM: <K extends keyof Slices, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: {
|
|
20
21
|
useDeepEqualCheck?: boolean;
|
|
21
22
|
isEqual?: (a: Selected, b: Selected) => boolean;
|
|
22
23
|
}) => {
|
|
23
|
-
state:
|
|
24
|
+
state: any;
|
|
24
25
|
setState: (payload: Partial<Slices[K]> | ((prev: Slices[K]) => Partial<Slices[K]>)) => void;
|
|
25
26
|
};
|
|
26
27
|
useSRASMAsync: <K extends keyof Slices>(slice: K, fetcher: () => Promise<Slices[K]>, tags?: any[]) => {
|
|
27
|
-
data:
|
|
28
|
+
data: any;
|
|
28
29
|
loading: boolean;
|
|
29
30
|
error: any;
|
|
30
31
|
refetch: () => Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/context/createStateStore.
|
|
1
|
+
// src/context/createStateStore.ts
|
|
2
2
|
import React, { useCallback } from "react";
|
|
3
3
|
|
|
4
4
|
// src/utils/deepEqual.ts
|
|
@@ -18,9 +18,8 @@ function deepEqual(obj1, obj2) {
|
|
|
18
18
|
return true;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
// src/context/createStateStore.
|
|
21
|
+
// src/context/createStateStore.ts
|
|
22
22
|
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/with-selector";
|
|
23
|
-
import { Fragment, jsx } from "react/jsx-runtime";
|
|
24
23
|
function createStateStore(initialSlices) {
|
|
25
24
|
let storeState = { ...initialSlices };
|
|
26
25
|
const sliceListeners = /* @__PURE__ */ new Map();
|
|
@@ -105,7 +104,7 @@ function createStateStore(initialSlices) {
|
|
|
105
104
|
const SRASMProvider = ({
|
|
106
105
|
children
|
|
107
106
|
}) => {
|
|
108
|
-
return
|
|
107
|
+
return children;
|
|
109
108
|
};
|
|
110
109
|
return { SRASMProvider, useSRASM, useSRASMAsync };
|
|
111
110
|
}
|
|
@@ -121,4 +120,3 @@ export {
|
|
|
121
120
|
createStateStore,
|
|
122
121
|
logClick
|
|
123
122
|
};
|
|
124
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "srasm",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -24,35 +24,15 @@
|
|
|
24
24
|
"debug": " npx eslint . --debug"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@langchain/core": "^1.1.0",
|
|
28
|
-
"@langchain/openai": "^1.1.3",
|
|
29
|
-
"@tailwindcss/vite": "^4.1.17",
|
|
30
|
-
"@tensorflow/tfjs": "^4.22.0",
|
|
31
|
-
"axios": "^1.13.2",
|
|
32
27
|
"clsx": "^2.1.1",
|
|
33
|
-
"
|
|
34
|
-
"langchain": "^1.1.1",
|
|
35
|
-
"lucide-react": "^0.555.0",
|
|
36
|
-
"postcss": "^8.5.6",
|
|
37
|
-
"rc-tree": "^5.13.1",
|
|
38
|
-
"react": "^19.2.0",
|
|
39
|
-
"react-d3-tree": "^3.6.6",
|
|
40
|
-
"react-dom": "^19.2.0",
|
|
41
|
-
"react-hot-toast": "^2.6.0",
|
|
42
|
-
"react-markdown": "^10.1.0",
|
|
43
|
-
"react-router-dom": "^7.9.6",
|
|
28
|
+
"react": ">=18",
|
|
44
29
|
"react-virtuoso": "^4.16.1",
|
|
45
|
-
"rehype-highlight": "^7.0.2",
|
|
46
|
-
"remark-gfm": "^4.0.1",
|
|
47
|
-
"tailwindcss": "^4.1.18",
|
|
48
30
|
"use-sync-external-store": "^1.6.0"
|
|
49
31
|
},
|
|
50
32
|
"peerDependencies": {
|
|
51
|
-
"react": ">=18"
|
|
52
|
-
"react-dom": ">=18"
|
|
33
|
+
"react": ">=18"
|
|
53
34
|
},
|
|
54
35
|
"devDependencies": {
|
|
55
|
-
"@tailwindcss/postcss": "^4.1.18",
|
|
56
36
|
"@testing-library/dom": "^10.4.1",
|
|
57
37
|
"@testing-library/react": "^16.3.1",
|
|
58
38
|
"@types/bun": "latest",
|
|
@@ -60,14 +40,9 @@
|
|
|
60
40
|
"@types/react": "^19.2.2",
|
|
61
41
|
"@types/react-dom": "^19.2.2",
|
|
62
42
|
"@types/use-sync-external-store": "^1.5.0",
|
|
63
|
-
"
|
|
64
|
-
"baseline-browser-mapping": "^2.9.15",
|
|
65
|
-
"happy-dom": "^20.0.11",
|
|
66
|
-
"jsdom": "^27.0.1",
|
|
43
|
+
"esbuild": "^0.27.2",
|
|
67
44
|
"tsup": "^8.5.1",
|
|
68
|
-
"typescript": "~5.9.3"
|
|
69
|
-
"vite": "^7.2.2",
|
|
70
|
-
"vitest": "^4.0.16"
|
|
45
|
+
"typescript": "~5.9.3"
|
|
71
46
|
},
|
|
72
47
|
"module": "index.ts"
|
|
73
48
|
}
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/context/createStateStore.tsx","../src/utils/deepEqual.ts","../src/ml/globalLogs.ts"],"sourcesContent":["// Core state management\r\nexport { createStateStore } from \"./context\";\r\n\r\n// Utilities / ML helpers\r\nexport { logClick } from \"./ml\";\r\nexport type { ClickEvent } from \"./ml\";\r\n","import React, { useCallback } from \"react\";\r\nimport { deepEqual } from \"../utils\";\r\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\";\r\n/**\r\n * Creates a state store with the given initial state slices.\r\n * The state store is used by the `useSRASM` hook to provide a strongly-typed\r\n * way of accessing and updating the state.\r\n *\r\n * @param {Slices} initialSlices The initial state slices to be used by the state store.\r\n * @return {{ SRASMProvider: React.FC<{ children: React.ReactNode; relevantCode?: { fileName: string; code: string }[] | undefined; additionalSlices?: any[] | undefined }>; useSRASM: <K extends SliceKey, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: { useDeepEqualCheck?: boolean; isEqual?: (a: Selected, b: Selected) => boolean; }) => useSRASMReturn }}\r\n * The returned object contains the `SRASMProvider` context provider component and the `useSRASM` hook.\r\n * The `SRASMProvider` component should be used to wrap your application, providing the necessary state and error handling to SRASM components.\r\n * The `useSRASM` hook can be used by your React components to access and update the state.\r\n */\r\nexport function createStateStore<Slices extends Record<string, any>>(\r\n initialSlices: Slices,\r\n) {\r\n type SliceKey = keyof Slices;\r\n\r\n let storeState: Slices = { ...initialSlices };\r\n\r\n const sliceListeners = new Map<SliceKey, Set<() => void>>();\r\n // const activeRequests = new Map<SliceKey, Promise<any>>();\r\n\r\n /**\r\n * Returns a set of listeners for the given slice key.\r\n * If no listeners are registered for the key, a new set is created and stored.\r\n * @param {SliceKey} k\r\n * @returns {Set<() => void>}\r\n */\r\n const getSliceListeners = (k: SliceKey) => {\r\n let set = sliceListeners.get(k);\r\n if (!set) {\r\n set = new Set();\r\n sliceListeners.set(k, set);\r\n }\r\n return set;\r\n };\r\n\r\n /**\r\n * Subscribes to the slice with the given key, adding the given\r\n * listener to the set of listeners for that slice.\r\n *\r\n * Returns a function that can be used to unsubscribe the given\r\n * listener from the slice.\r\n *\r\n * @param {SliceKey} key The key of the slice to subscribe to.\r\n * @param {() => void} listener The listener to add to the slice.\r\n * @returns {() => void} A function to unsubscribe the listener from the slice.\r\n */\r\n const subscribeSlice = (key: SliceKey, listener: () => void) => {\r\n const set = getSliceListeners(key);\r\n set.add(listener);\r\n return () => set.delete(listener);\r\n };\r\n\r\n /**\r\n * Emits the slice with the given key, calling all listeners\r\n * that are currently subscribed to that slice.\r\n *\r\n * This is used internally by the `useSRASM` hook to notify\r\n * components when the slice they are subscribed to changes.\r\n *\r\n * @param {SliceKey} key The key of the slice to emit.\r\n */\r\n const emitSlice = (key: SliceKey) => {\r\n getSliceListeners(key).forEach((l) => l());\r\n };\r\n\r\n /**\r\n * Updates the slice with the given key, using the given payload to\r\n * determine the new value of the slice. If the payload is a function,\r\n * it will be called with the current value of the slice as its argument.\r\n *\r\n * If the payload is not a function, it will be used as the new value\r\n * of the slice. If the current and new values are equal (using a\r\n * deep equality check if useDeepEqualCheck is true), the slice will\r\n * not be updated.\r\n *\r\n * @param {SliceKey} key The key of the slice to update.\r\n * @param {any} payload The payload to use to update the slice.\r\n * @param {boolean} useDeepEqualCheck Whether to use a deep equality\r\n * check when comparing the current and new values of the slice.\r\n */\r\n const updateSlice = (\r\n key: SliceKey,\r\n payload: any,\r\n useDeepEqualCheck: boolean,\r\n ) => {\r\n const current = storeState[key];\r\n let next = current;\r\n\r\n if (typeof payload === \"function\") {\r\n next = payload(current);\r\n if (Object.is(current, next)) return;\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (\r\n typeof current === \"object\" &&\r\n current !== null &&\r\n typeof payload === \"object\" &&\r\n payload !== null\r\n ) {\r\n next = { ...(current as any), ...(payload as any) };\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (Object.is(current, payload)) return;\r\n if (useDeepEqualCheck && deepEqual(current, payload)) return;\r\n next = payload;\r\n }\r\n }\r\n\r\n if (!Object.is(storeState[key], next)) {\r\n storeState = { ...storeState, [key]: next };\r\n emitSlice(key);\r\n }\r\n };\r\n\r\n /**\r\n * Hook to use a slice of the global state.\r\n * @param {SliceKey} slice The key of the slice to use.\r\n * @param {((s: Slices[K]) => Selected) | undefined} selector\r\n * A function to select the desired value from the slice.\r\n * @param {useSRASMOptions} options Options for the hook.\r\n * @returns {useSRASMReturn} An object with the selected state and a\r\n * function to update the state.\r\n *\r\n * The `useSRASM` hook allows you to use a slice of the global state\r\n * in your React components. It takes a slice key as its first argument and\r\n * an optional selector function as its second argument. The selector function\r\n * is called with the slice state as its argument and should return the desired value\r\n * from the slice state.\r\n *\r\n * The hook returns an object with two properties: `state` and `setState`. The\r\n * `state` property contains the selected value from the slice state, and the\r\n * `setState` property is a function that can be used to update the slice state.\r\n *\r\n * The `options` object can be used to customize the behavior of the hook. It\r\n * accepts two properties: `useDeepEqualCheck` and `isEqual`. The\r\n * `useDeepEqualCheck` property is a boolean that indicates whether to use a deep\r\n * equality check when comparing the current and new values of the slice state.\r\n * The `isEqual` property is a function that is used to compare the current and\r\n * new values of the slice state. If not provided, the hook will use the `Object.is`\r\n * function to compare the values.\r\n */\r\n function useSRASM<K extends SliceKey, Selected = Slices[K]>(\r\n slice: K,\r\n selector?: (s: Slices[K]) => Selected,\r\n options?: {\r\n useDeepEqualCheck?: boolean;\r\n isEqual?: (a: Selected, b: Selected) => boolean;\r\n },\r\n ) {\r\n const selected = useSyncExternalStoreWithSelector(\r\n (listener) => subscribeSlice(slice, listener),\r\n () => storeState[slice],\r\n () => initialSlices[slice],\r\n selector ?? ((s: Selected) => s as Selected),\r\n options?.isEqual ?? Object.is,\r\n );\r\n\r\n type SliceUpdater<S> = Partial<S> | ((prev: S) => Partial<S>);\r\n\r\n const setState = useCallback(\r\n (payload: SliceUpdater<Slices[K]>) =>\r\n updateSlice(slice, payload, !!options?.useDeepEqualCheck),\r\n [slice, options?.useDeepEqualCheck],\r\n );\r\n\r\n return { state: selected, setState };\r\n }\r\n\r\n /**\r\n * Hook to asynchronously fetch and manage a slice state.\r\n * @param {SliceKey} slice The slice key.\r\n * @param {() => Promise<Slices[K]>} fetcher The async function to fetch data.\r\n * @param {any[]} tags Array of dependencies. specific tags that trigger refetch.\r\n * @returns {{ data: Slices[K]; loading: boolean; error: any; refetch: () => void }}\r\n */\r\n function useSRASMAsync<K extends SliceKey>(\r\n slice: K,\r\n fetcher: () => Promise<Slices[K]>,\r\n tags: any[] = [],\r\n ) {\r\n const { state, setState } = useSRASM(slice);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<any>(null);\r\n\r\n const fetchData = useCallback(async () => {\r\n // Deduping: if a request is already active for this slice, don't start another?\r\n // For now, let's allow it but simple tracking.\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await fetcher();\r\n setState(data);\r\n } catch (err) {\r\n setError(err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [slice, fetcher, setState]); // tags are handled in useEffect\r\n\r\n React.useEffect(() => {\r\n // Simple \"auto-fetch\" on mount or tag change\r\n // In a real lib we would check if data exists/is fresh.\r\n fetchData();\r\n }, [JSON.stringify(tags)]); // deeply compare tags simple approach\r\n\r\n return {\r\n data: state,\r\n loading,\r\n error,\r\n refetch: fetchData,\r\n };\r\n }\r\n\r\n /**\r\n * @note Can be need at the future\r\n * A context provider that wraps your application and provides\r\n * the necessary state and error handling to SRASM components.\r\n *\r\n * @param {React.ReactNode} children The components to be rendered within\r\n * the provider.\r\n * @param {({ fileName: string; code: string }[] | undefined} relevantCode\r\n * An optional array of objects containing the file name and code of the\r\n * relevant code snippets to be used for AI error debugging.\r\n * @param {any[] | undefined} additionalSlices An optional array of\r\n * additional slices to be passed to the AI error debugging system.\r\n */\r\n const SRASMProvider = ({\r\n children,\r\n }: {\r\n children: React.ReactNode;\r\n }) => {\r\n return <>{children}</>;\r\n };\r\n\r\n return { SRASMProvider, useSRASM, useSRASMAsync };\r\n}\r\n","export function deepEqual(\r\n obj1: Record<string, any>,\r\n obj2: Record<string, any>\r\n) {\r\n if (obj1 === obj2) return true; // Handles primitive values and same object references\r\n\r\n // If one is null or not object, compare with Object.is\r\n if (\r\n typeof obj1 !== \"object\" ||\r\n typeof obj2 !== \"object\" ||\r\n obj1 === null ||\r\n obj2 === null\r\n ) {\r\n return Object.is(obj1, obj2);\r\n }\r\n\r\n const keys1 = Object.keys(obj1);\r\n const keys2 = Object.keys(obj2);\r\n\r\n if (keys1.length !== keys2.length) return false; // Different number of properties\r\n\r\n for (const key of keys1) {\r\n if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {\r\n return false; // Key missing or values not deeply equal\r\n }\r\n }\r\n return true;\r\n}\r\n","export type ClickEvent = {\r\n itemId: string;\r\n categoryId: string;\r\n ts: number;\r\n};\r\n\r\nexport const logClick = (event: ClickEvent) => {\r\n const key = \"click_events\";\r\n const existing = JSON.parse(localStorage.getItem(key) || \"[]\");\r\n existing.push(event);\r\n localStorage.setItem(key, JSON.stringify(existing));\r\n};\r\n\r\n"],"mappings":"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","names":["React"]}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context/createStateStore.tsx","../src/utils/deepEqual.ts","../src/ml/globalLogs.ts"],"sourcesContent":["import React, { useCallback } from \"react\";\r\nimport { deepEqual } from \"../utils\";\r\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\";\r\n/**\r\n * Creates a state store with the given initial state slices.\r\n * The state store is used by the `useSRASM` hook to provide a strongly-typed\r\n * way of accessing and updating the state.\r\n *\r\n * @param {Slices} initialSlices The initial state slices to be used by the state store.\r\n * @return {{ SRASMProvider: React.FC<{ children: React.ReactNode; relevantCode?: { fileName: string; code: string }[] | undefined; additionalSlices?: any[] | undefined }>; useSRASM: <K extends SliceKey, Selected = Slices[K]>(slice: K, selector?: (s: Slices[K]) => Selected, options?: { useDeepEqualCheck?: boolean; isEqual?: (a: Selected, b: Selected) => boolean; }) => useSRASMReturn }}\r\n * The returned object contains the `SRASMProvider` context provider component and the `useSRASM` hook.\r\n * The `SRASMProvider` component should be used to wrap your application, providing the necessary state and error handling to SRASM components.\r\n * The `useSRASM` hook can be used by your React components to access and update the state.\r\n */\r\nexport function createStateStore<Slices extends Record<string, any>>(\r\n initialSlices: Slices,\r\n) {\r\n type SliceKey = keyof Slices;\r\n\r\n let storeState: Slices = { ...initialSlices };\r\n\r\n const sliceListeners = new Map<SliceKey, Set<() => void>>();\r\n // const activeRequests = new Map<SliceKey, Promise<any>>();\r\n\r\n /**\r\n * Returns a set of listeners for the given slice key.\r\n * If no listeners are registered for the key, a new set is created and stored.\r\n * @param {SliceKey} k\r\n * @returns {Set<() => void>}\r\n */\r\n const getSliceListeners = (k: SliceKey) => {\r\n let set = sliceListeners.get(k);\r\n if (!set) {\r\n set = new Set();\r\n sliceListeners.set(k, set);\r\n }\r\n return set;\r\n };\r\n\r\n /**\r\n * Subscribes to the slice with the given key, adding the given\r\n * listener to the set of listeners for that slice.\r\n *\r\n * Returns a function that can be used to unsubscribe the given\r\n * listener from the slice.\r\n *\r\n * @param {SliceKey} key The key of the slice to subscribe to.\r\n * @param {() => void} listener The listener to add to the slice.\r\n * @returns {() => void} A function to unsubscribe the listener from the slice.\r\n */\r\n const subscribeSlice = (key: SliceKey, listener: () => void) => {\r\n const set = getSliceListeners(key);\r\n set.add(listener);\r\n return () => set.delete(listener);\r\n };\r\n\r\n /**\r\n * Emits the slice with the given key, calling all listeners\r\n * that are currently subscribed to that slice.\r\n *\r\n * This is used internally by the `useSRASM` hook to notify\r\n * components when the slice they are subscribed to changes.\r\n *\r\n * @param {SliceKey} key The key of the slice to emit.\r\n */\r\n const emitSlice = (key: SliceKey) => {\r\n getSliceListeners(key).forEach((l) => l());\r\n };\r\n\r\n /**\r\n * Updates the slice with the given key, using the given payload to\r\n * determine the new value of the slice. If the payload is a function,\r\n * it will be called with the current value of the slice as its argument.\r\n *\r\n * If the payload is not a function, it will be used as the new value\r\n * of the slice. If the current and new values are equal (using a\r\n * deep equality check if useDeepEqualCheck is true), the slice will\r\n * not be updated.\r\n *\r\n * @param {SliceKey} key The key of the slice to update.\r\n * @param {any} payload The payload to use to update the slice.\r\n * @param {boolean} useDeepEqualCheck Whether to use a deep equality\r\n * check when comparing the current and new values of the slice.\r\n */\r\n const updateSlice = (\r\n key: SliceKey,\r\n payload: any,\r\n useDeepEqualCheck: boolean,\r\n ) => {\r\n const current = storeState[key];\r\n let next = current;\r\n\r\n if (typeof payload === \"function\") {\r\n next = payload(current);\r\n if (Object.is(current, next)) return;\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (\r\n typeof current === \"object\" &&\r\n current !== null &&\r\n typeof payload === \"object\" &&\r\n payload !== null\r\n ) {\r\n next = { ...(current as any), ...(payload as any) };\r\n if (useDeepEqualCheck && deepEqual(current, next)) return;\r\n } else {\r\n if (Object.is(current, payload)) return;\r\n if (useDeepEqualCheck && deepEqual(current, payload)) return;\r\n next = payload;\r\n }\r\n }\r\n\r\n if (!Object.is(storeState[key], next)) {\r\n storeState = { ...storeState, [key]: next };\r\n emitSlice(key);\r\n }\r\n };\r\n\r\n /**\r\n * Hook to use a slice of the global state.\r\n * @param {SliceKey} slice The key of the slice to use.\r\n * @param {((s: Slices[K]) => Selected) | undefined} selector\r\n * A function to select the desired value from the slice.\r\n * @param {useSRASMOptions} options Options for the hook.\r\n * @returns {useSRASMReturn} An object with the selected state and a\r\n * function to update the state.\r\n *\r\n * The `useSRASM` hook allows you to use a slice of the global state\r\n * in your React components. It takes a slice key as its first argument and\r\n * an optional selector function as its second argument. The selector function\r\n * is called with the slice state as its argument and should return the desired value\r\n * from the slice state.\r\n *\r\n * The hook returns an object with two properties: `state` and `setState`. The\r\n * `state` property contains the selected value from the slice state, and the\r\n * `setState` property is a function that can be used to update the slice state.\r\n *\r\n * The `options` object can be used to customize the behavior of the hook. It\r\n * accepts two properties: `useDeepEqualCheck` and `isEqual`. The\r\n * `useDeepEqualCheck` property is a boolean that indicates whether to use a deep\r\n * equality check when comparing the current and new values of the slice state.\r\n * The `isEqual` property is a function that is used to compare the current and\r\n * new values of the slice state. If not provided, the hook will use the `Object.is`\r\n * function to compare the values.\r\n */\r\n function useSRASM<K extends SliceKey, Selected = Slices[K]>(\r\n slice: K,\r\n selector?: (s: Slices[K]) => Selected,\r\n options?: {\r\n useDeepEqualCheck?: boolean;\r\n isEqual?: (a: Selected, b: Selected) => boolean;\r\n },\r\n ) {\r\n const selected = useSyncExternalStoreWithSelector(\r\n (listener) => subscribeSlice(slice, listener),\r\n () => storeState[slice],\r\n () => initialSlices[slice],\r\n selector ?? ((s: Selected) => s as Selected),\r\n options?.isEqual ?? Object.is,\r\n );\r\n\r\n type SliceUpdater<S> = Partial<S> | ((prev: S) => Partial<S>);\r\n\r\n const setState = useCallback(\r\n (payload: SliceUpdater<Slices[K]>) =>\r\n updateSlice(slice, payload, !!options?.useDeepEqualCheck),\r\n [slice, options?.useDeepEqualCheck],\r\n );\r\n\r\n return { state: selected, setState };\r\n }\r\n\r\n /**\r\n * Hook to asynchronously fetch and manage a slice state.\r\n * @param {SliceKey} slice The slice key.\r\n * @param {() => Promise<Slices[K]>} fetcher The async function to fetch data.\r\n * @param {any[]} tags Array of dependencies. specific tags that trigger refetch.\r\n * @returns {{ data: Slices[K]; loading: boolean; error: any; refetch: () => void }}\r\n */\r\n function useSRASMAsync<K extends SliceKey>(\r\n slice: K,\r\n fetcher: () => Promise<Slices[K]>,\r\n tags: any[] = [],\r\n ) {\r\n const { state, setState } = useSRASM(slice);\r\n const [loading, setLoading] = React.useState(false);\r\n const [error, setError] = React.useState<any>(null);\r\n\r\n const fetchData = useCallback(async () => {\r\n // Deduping: if a request is already active for this slice, don't start another?\r\n // For now, let's allow it but simple tracking.\r\n setLoading(true);\r\n setError(null);\r\n\r\n try {\r\n const data = await fetcher();\r\n setState(data);\r\n } catch (err) {\r\n setError(err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [slice, fetcher, setState]); // tags are handled in useEffect\r\n\r\n React.useEffect(() => {\r\n // Simple \"auto-fetch\" on mount or tag change\r\n // In a real lib we would check if data exists/is fresh.\r\n fetchData();\r\n }, [JSON.stringify(tags)]); // deeply compare tags simple approach\r\n\r\n return {\r\n data: state,\r\n loading,\r\n error,\r\n refetch: fetchData,\r\n };\r\n }\r\n\r\n /**\r\n * @note Can be need at the future\r\n * A context provider that wraps your application and provides\r\n * the necessary state and error handling to SRASM components.\r\n *\r\n * @param {React.ReactNode} children The components to be rendered within\r\n * the provider.\r\n * @param {({ fileName: string; code: string }[] | undefined} relevantCode\r\n * An optional array of objects containing the file name and code of the\r\n * relevant code snippets to be used for AI error debugging.\r\n * @param {any[] | undefined} additionalSlices An optional array of\r\n * additional slices to be passed to the AI error debugging system.\r\n */\r\n const SRASMProvider = ({\r\n children,\r\n }: {\r\n children: React.ReactNode;\r\n }) => {\r\n return <>{children}</>;\r\n };\r\n\r\n return { SRASMProvider, useSRASM, useSRASMAsync };\r\n}\r\n","export function deepEqual(\r\n obj1: Record<string, any>,\r\n obj2: Record<string, any>\r\n) {\r\n if (obj1 === obj2) return true; // Handles primitive values and same object references\r\n\r\n // If one is null or not object, compare with Object.is\r\n if (\r\n typeof obj1 !== \"object\" ||\r\n typeof obj2 !== \"object\" ||\r\n obj1 === null ||\r\n obj2 === null\r\n ) {\r\n return Object.is(obj1, obj2);\r\n }\r\n\r\n const keys1 = Object.keys(obj1);\r\n const keys2 = Object.keys(obj2);\r\n\r\n if (keys1.length !== keys2.length) return false; // Different number of properties\r\n\r\n for (const key of keys1) {\r\n if (!keys2.includes(key) || !deepEqual(obj1[key], obj2[key])) {\r\n return false; // Key missing or values not deeply equal\r\n }\r\n }\r\n return true;\r\n}\r\n","export type ClickEvent = {\r\n itemId: string;\r\n categoryId: string;\r\n ts: number;\r\n};\r\n\r\nexport const logClick = (event: ClickEvent) => {\r\n const key = \"click_events\";\r\n const existing = JSON.parse(localStorage.getItem(key) || \"[]\");\r\n existing.push(event);\r\n localStorage.setItem(key, JSON.stringify(existing));\r\n};\r\n\r\n"],"mappings":"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","names":[]}
|