Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

129 lines
2.7 KiB
TypeScript

"use client";
import "./foo-scope";
import { type ReactNode, useMemo, useState } from "react";
import { resource } from "@assistant-ui/tap";
import {
useAui,
useAuiState,
AuiProvider,
useClientList,
Derived,
useAssistantEmit,
RenderChildrenWithAccessor,
type ClientOutput,
} from "@assistant-ui/store";
type FooData = { id: string; bar: string };
const useFooItemResource = ({
getInitialData,
remove,
}: useClientList.ResourceProps<FooData>): ClientOutput<"foo"> => {
const emit = useAssistantEmit();
const [state, setState] = useState<FooData>(getInitialData);
const updateBar = (newBar: string) => {
setState({ ...state, bar: newBar });
emit("foo.updated", { id: state.id, newValue: newBar });
};
const handleRemove = () => {
emit("foo.removed", { id: state.id });
remove();
};
return {
getState: () => state,
updateBar,
remove: handleRemove,
};
};
export const FooItemResource = resource(useFooItemResource);
let counter = 3;
const useFooListResource = ({
initialValues,
}: {
initialValues: boolean;
}): ClientOutput<"fooList"> => {
const emit = useAssistantEmit();
const foos = useClientList({
initialValues: initialValues
? [
{ id: "foo-1", bar: "First Foo" },
{ id: "foo-2", bar: "Second Foo" },
{ id: "foo-3", bar: "Third Foo" },
]
: [],
getKey: (foo) => foo.id,
resource: FooItemResource,
});
const addFoo = () => {
const id = `foo-${++counter}`;
foos.add({ id: id, bar: `New Foo` });
emit("fooList.added", { id: id });
};
const state = useMemo(() => ({ foos: foos.state }), [foos.state]);
return {
getState: () => state,
foo: foos.get,
addFoo,
};
};
export const FooListResource = resource(useFooListResource);
const FooProvider = ({
index,
children,
}: {
index: number;
children: ReactNode;
}) => {
const aui = useAui({
foo: Derived({
source: "fooList",
query: { index },
get: (aui) => aui.fooList().foo({ index }),
}),
});
return <AuiProvider value={aui}>{children}</AuiProvider>;
};
export const FooList = ({
children,
}: {
children: (item: { foo: FooData }) => ReactNode;
}) => {
const length = useAuiState((s) => s.fooList.foos.length);
return useMemo(
() =>
Array.from({ length }, (_, index) => (
<FooProvider key={index} index={index}>
<RenderChildrenWithAccessor
getItemState={(aui) => aui.fooList().foo({ index }).getState()}
>
{(getItem) =>
children({
get foo() {
return getItem();
},
})
}
</RenderChildrenWithAccessor>
</FooProvider>
)),
[length, children],
);
};