@assistant-ui/store 0.2.2 → 0.2.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/RenderChildrenWithAccessor.d.ts +23 -0
- package/dist/RenderChildrenWithAccessor.d.ts.map +1 -0
- package/dist/RenderChildrenWithAccessor.js +53 -0
- package/dist/RenderChildrenWithAccessor.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/RenderChildrenWithAccessor.tsx +73 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { AssistantClient } from "./types/client.js";
|
|
3
|
+
export declare const useGetItemAccessor: <T>(getItemState: (aui: AssistantClient) => T) => () => T;
|
|
4
|
+
/**
|
|
5
|
+
* Component that sets up a lazy item accessor and memoizes propless children.
|
|
6
|
+
*
|
|
7
|
+
* For the common pattern where children returns a component without props
|
|
8
|
+
* (e.g. `<Foo />`), the output is memoized and not re-created on parent re-renders.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <RenderChildrenWithAccessor
|
|
13
|
+
* getItemState={(aui) => aui.fooList().foo({ index }).getState()}
|
|
14
|
+
* >
|
|
15
|
+
* {() => <Foo />}
|
|
16
|
+
* </RenderChildrenWithAccessor>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function RenderChildrenWithAccessor<T>({ getItemState, children, }: {
|
|
20
|
+
getItemState: (aui: AssistantClient) => T;
|
|
21
|
+
children: (getItem: () => T) => ReactNode;
|
|
22
|
+
}): ReactNode;
|
|
23
|
+
//# sourceMappingURL=RenderChildrenWithAccessor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RenderChildrenWithAccessor.d.ts","sourceRoot":"","sources":["../src/RenderChildrenWithAccessor.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,0BAAuB;AAItD,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAClC,cAAc,CAAC,GAAG,EAAE,eAAe,KAAK,CAAC,YAkB1C,CAAC;AAIF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,EAAE,EAC5C,YAAY,EACZ,QAAQ,GACT,EAAE;IACD,YAAY,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,CAAC,CAAC;IAC1C,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,SAAS,CAAC;CAC3C,GAAG,SAAS,CAGZ"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useMemo, useRef } from "react";
|
|
3
|
+
import { useAuiState } from "./useAuiState.js";
|
|
4
|
+
import { useAui } from "./useAui.js";
|
|
5
|
+
export const useGetItemAccessor = (getItemState) => {
|
|
6
|
+
const aui = useAui();
|
|
7
|
+
// if the consumer never accesses the item, do not trigger rerenders
|
|
8
|
+
const cacheRef = useRef(undefined);
|
|
9
|
+
useAuiState(() => {
|
|
10
|
+
if (cacheRef.current === undefined) {
|
|
11
|
+
cacheRef.current = getItemState(aui);
|
|
12
|
+
}
|
|
13
|
+
return cacheRef.current;
|
|
14
|
+
});
|
|
15
|
+
return () => {
|
|
16
|
+
cacheRef.current = undefined; // clear the cache (rerender on next state change)
|
|
17
|
+
return getItemState(aui);
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const EMPTY_OBJECT = Object.freeze({});
|
|
21
|
+
/**
|
|
22
|
+
* Component that sets up a lazy item accessor and memoizes propless children.
|
|
23
|
+
*
|
|
24
|
+
* For the common pattern where children returns a component without props
|
|
25
|
+
* (e.g. `<Foo />`), the output is memoized and not re-created on parent re-renders.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <RenderChildrenWithAccessor
|
|
30
|
+
* getItemState={(aui) => aui.fooList().foo({ index }).getState()}
|
|
31
|
+
* >
|
|
32
|
+
* {() => <Foo />}
|
|
33
|
+
* </RenderChildrenWithAccessor>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function RenderChildrenWithAccessor({ getItemState, children, }) {
|
|
37
|
+
const getItem = useGetItemAccessor(getItemState);
|
|
38
|
+
return useMemoizedProplessComponent(children(getItem));
|
|
39
|
+
}
|
|
40
|
+
const useMemoizedProplessComponent = (node) => {
|
|
41
|
+
const el = typeof node === "object" && node != null && "type" in node ? node : null;
|
|
42
|
+
const resultType = el?.type;
|
|
43
|
+
const resultKey = el?.key;
|
|
44
|
+
const resultProps = typeof el?.props === "object" &&
|
|
45
|
+
el.props != null &&
|
|
46
|
+
Object.entries(el.props).length === 0
|
|
47
|
+
? EMPTY_OBJECT
|
|
48
|
+
: el?.props;
|
|
49
|
+
return (
|
|
50
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: optimization
|
|
51
|
+
useMemo(() => el, [resultType, resultKey, resultProps]) ?? node);
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=RenderChildrenWithAccessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RenderChildrenWithAccessor.js","sourceRoot":"","sources":["../src/RenderChildrenWithAccessor.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAkB,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAElC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,YAAyC,EACzC,EAAE;IACF,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IAErB,oEAAoE;IACpE,MAAM,QAAQ,GAAG,MAAM,CAAgB,SAAS,CAAC,CAAC;IAClD,WAAW,CAAC,GAAG,EAAE;QACf,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACnC,QAAQ,CAAC,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,EAAE;QACV,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,kDAAkD;QAEhF,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,0BAA0B,CAAI,EAC5C,YAAY,EACZ,QAAQ,GAIT;IACC,MAAM,OAAO,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,4BAA4B,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,4BAA4B,GAAG,CAAC,IAAe,EAAE,EAAE;IACvD,MAAM,EAAE,GACN,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,MAAM,UAAU,GAAG,EAAE,EAAE,IAAI,CAAC;IAC5B,MAAM,SAAS,GAAG,EAAE,EAAE,GAAG,CAAC;IAC1B,MAAM,WAAW,GACf,OAAO,EAAE,EAAE,KAAK,KAAK,QAAQ;QAC7B,EAAE,CAAC,KAAK,IAAI,IAAI;QAChB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;QACnC,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC;IAEhB,OAAO;IACL,wEAAwE;IACxE,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,IAAI,CAChE,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { useAui } from "./useAui.js";
|
|
2
2
|
export { useAuiState } from "./useAuiState.js";
|
|
3
3
|
export { useAuiEvent } from "./useAuiEvent.js";
|
|
4
|
+
export { RenderChildrenWithAccessor } from "./RenderChildrenWithAccessor.js";
|
|
4
5
|
export { AuiIf } from "./AuiIf.js";
|
|
5
6
|
export { AuiProvider } from "./utils/react-assistant-context.js";
|
|
6
7
|
export { Derived } from "./Derived.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,0BAA0B,EAAE,wCAAqC;AAG1E,OAAO,EAAE,KAAK,EAAE,mBAAgB;AAChC,OAAO,EAAE,WAAW,EAAE,2CAAwC;AAG9D,OAAO,EAAE,OAAO,EAAE,qBAAkB;AACpC,OAAO,EAAE,qBAAqB,EAAE,mCAAgC;AAChE,YAAY,EAAE,YAAY,EAAE,mCAAgC;AAG5D,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,yCAAsC;AACvC,OAAO,EAAE,iBAAiB,EAAE,+BAA4B;AACxD,OAAO,EAAE,eAAe,EAAE,6BAA0B;AACpD,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAGhD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,eAAe,EACf,cAAc,GACf,0BAAuB;AACxB,OAAO,EACL,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,GACzB,0BAAuB"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export { useAui } from "./useAui.js";
|
|
3
3
|
export { useAuiState } from "./useAuiState.js";
|
|
4
4
|
export { useAuiEvent } from "./useAuiEvent.js";
|
|
5
|
+
export { RenderChildrenWithAccessor } from "./RenderChildrenWithAccessor.js";
|
|
5
6
|
// components
|
|
6
7
|
export { AuiIf } from "./AuiIf.js";
|
|
7
8
|
export { AuiProvider } from "./utils/react-assistant-context.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,OAAO,EAAE,MAAM,EAAE,oBAAiB;AAClC,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,0BAA0B,EAAE,wCAAqC;AAE1E,aAAa;AACb,OAAO,EAAE,KAAK,EAAE,mBAAgB;AAChC,OAAO,EAAE,WAAW,EAAE,2CAAwC;AAE9D,YAAY;AACZ,OAAO,EAAE,OAAO,EAAE,qBAAkB;AACpC,OAAO,EAAE,qBAAqB,EAAE,mCAAgC;AAGhE,YAAY;AACZ,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,yCAAsC;AACvC,OAAO,EAAE,iBAAiB,EAAE,+BAA4B;AACxD,OAAO,EAAE,eAAe,EAAE,6BAA0B;AACpD,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAiBhD,OAAO,EACL,sBAAsB,GAMvB,0BAAuB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/store",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Tap-based state management for @assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state-management",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"use-effect-event": "^2.0.3"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@assistant-ui/tap": "^0.5.
|
|
34
|
+
"@assistant-ui/tap": "^0.5.3",
|
|
35
35
|
"@types/react": "*",
|
|
36
36
|
"react": "^18 || ^19"
|
|
37
37
|
},
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"@types/react-dom": "^19.2.3",
|
|
47
47
|
"jsdom": "^28.1.0",
|
|
48
48
|
"react": "^19.2.4",
|
|
49
|
-
"vitest": "^4.0
|
|
50
|
-
"@assistant-ui/tap": "0.5.
|
|
51
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
49
|
+
"vitest": "^4.1.0",
|
|
50
|
+
"@assistant-ui/tap": "0.5.3",
|
|
51
|
+
"@assistant-ui/x-buildutils": "0.0.3"
|
|
52
52
|
},
|
|
53
53
|
"publishConfig": {
|
|
54
54
|
"access": "public",
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { type ReactNode, useMemo, useRef } from "react";
|
|
4
|
+
import type { AssistantClient } from "./types/client";
|
|
5
|
+
import { useAuiState } from "./useAuiState";
|
|
6
|
+
import { useAui } from "./useAui";
|
|
7
|
+
|
|
8
|
+
export const useGetItemAccessor = <T,>(
|
|
9
|
+
getItemState: (aui: AssistantClient) => T,
|
|
10
|
+
) => {
|
|
11
|
+
const aui = useAui();
|
|
12
|
+
|
|
13
|
+
// if the consumer never accesses the item, do not trigger rerenders
|
|
14
|
+
const cacheRef = useRef<T | undefined>(undefined);
|
|
15
|
+
useAuiState(() => {
|
|
16
|
+
if (cacheRef.current === undefined) {
|
|
17
|
+
cacheRef.current = getItemState(aui);
|
|
18
|
+
}
|
|
19
|
+
return cacheRef.current;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return () => {
|
|
23
|
+
cacheRef.current = undefined; // clear the cache (rerender on next state change)
|
|
24
|
+
|
|
25
|
+
return getItemState(aui);
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const EMPTY_OBJECT = Object.freeze({});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Component that sets up a lazy item accessor and memoizes propless children.
|
|
33
|
+
*
|
|
34
|
+
* For the common pattern where children returns a component without props
|
|
35
|
+
* (e.g. `<Foo />`), the output is memoized and not re-created on parent re-renders.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* <RenderChildrenWithAccessor
|
|
40
|
+
* getItemState={(aui) => aui.fooList().foo({ index }).getState()}
|
|
41
|
+
* >
|
|
42
|
+
* {() => <Foo />}
|
|
43
|
+
* </RenderChildrenWithAccessor>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function RenderChildrenWithAccessor<T>({
|
|
47
|
+
getItemState,
|
|
48
|
+
children,
|
|
49
|
+
}: {
|
|
50
|
+
getItemState: (aui: AssistantClient) => T;
|
|
51
|
+
children: (getItem: () => T) => ReactNode;
|
|
52
|
+
}): ReactNode {
|
|
53
|
+
const getItem = useGetItemAccessor(getItemState);
|
|
54
|
+
return useMemoizedProplessComponent(children(getItem));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const useMemoizedProplessComponent = (node: ReactNode) => {
|
|
58
|
+
const el =
|
|
59
|
+
typeof node === "object" && node != null && "type" in node ? node : null;
|
|
60
|
+
const resultType = el?.type;
|
|
61
|
+
const resultKey = el?.key;
|
|
62
|
+
const resultProps =
|
|
63
|
+
typeof el?.props === "object" &&
|
|
64
|
+
el.props != null &&
|
|
65
|
+
Object.entries(el.props).length === 0
|
|
66
|
+
? EMPTY_OBJECT
|
|
67
|
+
: el?.props;
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: optimization
|
|
71
|
+
useMemo(() => el, [resultType, resultKey, resultProps]) ?? node
|
|
72
|
+
);
|
|
73
|
+
};
|
package/src/index.ts
CHANGED