Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
739 changes: 492 additions & 247 deletions deno.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion packages/charm/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,12 @@ export class CharmManager {
);
// Use the space DID as the cause - it's derived from the space name
// and consistently available everywhere
this.spaceCell = this.runtime.getSpaceCell(this.space);
// For home space (where space DID = user identity DID), getHomeSpaceCell()
// uses homeSpaceCellSchema which includes favorites for proper sync/query behavior.
const isHomeSpace = this.space === this.runtime.userIdentityDID;
this.spaceCell = isHomeSpace
? this.runtime.getHomeSpaceCell()
: this.runtime.getSpaceCell(this.space);

const syncSpaceCell = Promise.resolve(this.spaceCell.sync());

Expand Down
23 changes: 23 additions & 0 deletions packages/html/src/jsx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2888,7 +2888,9 @@ interface CTToolbarElement extends CTHTMLElement {}
interface CTKbdElement extends CTHTMLElement {}
interface CTKeybindElement extends CTHTMLElement {}
interface CTRenderElement extends CTHTMLElement {}
interface CTCellContextElement extends CTHTMLElement {}
interface CTChatMessageElement extends CTHTMLElement {}
interface CTMarkdownElement extends CTHTMLElement {}
interface CTVScrollElement extends CTHTMLElement {}
interface CTSendMessageElement extends CTHTMLElement {}
interface CTTextElement extends CTHTMLElement {}
Expand Down Expand Up @@ -3107,6 +3109,13 @@ interface CTChatMessageAttributes<T> extends CTHTMLAttributes<T> {
"pending"?: boolean;
}

interface CTMarkdownAttributes<T> extends CTHTMLAttributes<T> {
"content"?: string;
"$content"?: CellLike<string>;
"variant"?: "default" | "inverse";
"streaming"?: boolean;
}

interface CTButtonAttributes<T> extends CTHTMLAttributes<T> {
"variant"?:
| "default"
Expand Down Expand Up @@ -3148,6 +3157,12 @@ interface CTRenderAttributes<T> extends CTHTMLAttributes<T> {
"$cell": CellLike<any>;
}

interface CTCellContextAttributes<T> extends CTHTMLAttributes<T> {
"$cell": CellLike<any>;
"label"?: string;
"inline"?: boolean;
}

interface CTListAttributes<T> extends CTHTMLAttributes<T> {
"$value": CellLike<CtListItem[]>;
/** setting this allows editing items inline */
Expand Down Expand Up @@ -3847,6 +3862,10 @@ declare global {
CTChatMessageAttributes<CTChatMessageElement>,
CTChatMessageElement
>;
"ct-markdown": CTDOM.DetailedHTMLProps<
CTMarkdownAttributes<CTMarkdownElement>,
CTMarkdownElement
>;
"ct-card": CTDOM.DetailedHTMLProps<
CTHTMLAttributes<CTCardElement>,
CTCardElement
Expand All @@ -3867,6 +3886,10 @@ declare global {
CTRenderAttributes<CTRenderElement>,
CTRenderElement
>;
"ct-cell-context": CTDOM.DetailedHTMLProps<
CTCellContextAttributes<CTCellContextElement>,
CTCellContextElement
>;
"ct-vscroll": CTDOM.DetailedHTMLProps<
CTScrollAttributes<CTVScrollElement>,
CTVScrollElement
Expand Down
25 changes: 24 additions & 1 deletion packages/html/src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export type SetPropHandler = <T>(
export interface RenderOptions {
setProp?: SetPropHandler;
document?: Document;
/** The root cell for auto-wrapping with ct-cell-context on [UI] traversal */
rootCell?: Cell;
}

export const vdomSchema: JSONSchema = {
Expand Down Expand Up @@ -63,13 +65,20 @@ export const render = (
): Cancel => {
// Initialize visited set with the original cell for cycle detection
const visited = new Set<object>();
let rootCell: Cell | undefined;

if (isCell(view)) {
visited.add(view);
rootCell = view; // Capture the original cell for ct-cell-context wrapping
view = view.asSchema(vdomSchema);
}

// Pass rootCell through options if we have one
const optionsWithCell = rootCell ? { ...options, rootCell } : options;

return effect(
view,
(view: VNode) => renderImpl(parent, view, options, visited),
(view: VNode) => renderImpl(parent, view, optionsWithCell, visited),
);
};

Expand Down Expand Up @@ -141,6 +150,10 @@ const renderNode = (

const document = options.document ?? globalThis.document;

// Check if we should wrap with ct-cell-context (when traversing [UI] with a rootCell)
const shouldWrapWithContext = node[UI] && options.rootCell;
const cellForContext = shouldWrapWithContext ? options.rootCell : undefined;

// Follow `[UI]` to actual vdom. Do this before otherwise parsing the vnode,
// so that if there are both, the `[UI]` annotation takes precedence (avoids
// accidental collision with the otherwise quite generic property names)
Expand Down Expand Up @@ -190,6 +203,16 @@ const renderNode = (
addCancel(cancelChildren);
}

// Wrap with ct-cell-context if we traversed [UI] with a rootCell
if (cellForContext && element) {
const wrapper = document.createElement(
"ct-cell-context",
) as HTMLElement & { cell?: Cell };
wrapper.cell = cellForContext;
wrapper.appendChild(element);
return [wrapper, cancel];
}

return [element, cancel];
};

Expand Down
4 changes: 3 additions & 1 deletion packages/patterns/chatbot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ export default pattern<ChatInput, ChatOutput>(

const attachmentsAndTools = (
<ct-hstack align="center" gap="1">
<ct-attachments-bar pinnedCells={pinnedCells} />
<ct-cell-context $cell={pinnedCells}>
<ct-attachments-bar pinnedCells={pinnedCells} />
</ct-cell-context>
<ct-tools-chip tools={flattenedTools} />
<ct-button
variant="pill"
Expand Down
34 changes: 19 additions & 15 deletions packages/patterns/compiler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,25 @@ export default recipe<Input>(
[NAME]: "My First Compiler",
[UI]: (
<div>
<ct-code-editor
value={code}
language="text/x.typescript"
onChange={updateCode({ code })}
//errors={errors}
/>
{ifElse(
error,
<b>fix the error: {error}</b>,
<ct-button
onClick={visit({ result })}
>
Navigate To Charm
</ct-button>,
)}
<ct-cell-context $cell={code} label="Source Code">
<ct-code-editor
value={code}
language="text/x.typescript"
onChange={updateCode({ code })}
//errors={errors}
/>
</ct-cell-context>
<ct-cell-context $cell={result} label="Compile Result">
{ifElse(
error,
<b>fix the error: {error}</b>,
<ct-button
onClick={visit({ result })}
>
Navigate To Charm
</ct-button>,
)}
</ct-cell-context>
</div>
),
code,
Expand Down
8 changes: 5 additions & 3 deletions packages/patterns/counter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export default recipe<RecipeState, RecipeOutput>((state) => {
<ct-button onClick={decrement(state)}>
dec to {previous(state.value)}
</ct-button>
<span id="counter-result">
Counter is the {nth(state.value)} number
</span>
<ct-cell-context $cell={state.value} inline>
<span id="counter-result">
Counter is the {nth(state.value)} number
</span>
</ct-cell-context>
<ct-button onClick={increment({ value: state.value })}>
inc to {(state.value ?? 0) + 1}
</ct-button>
Expand Down
11 changes: 4 additions & 7 deletions packages/patterns/default-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface CharmsListOutput {
fabUI: unknown;
}

const visit = handler<
const _visit = handler<
Record<string, never>,
{ charm: Cell<MinimalCharm> }
>((_, state) => {
Expand Down Expand Up @@ -177,12 +177,9 @@ export default recipe<CharmsListInput, CharmsListOutput>(
{allCharms.map((charm) => (
<tr>
<td>
<a
className="pattern-link"
onClick={visit({ charm })}
>
{charm?.[NAME] || "Untitled Charm"}
</a>
<ct-cell-context $cell={charm}>
<ct-cell-link $cell={charm} />
</ct-cell-context>
</td>
<td>
<ct-button
Expand Down
26 changes: 14 additions & 12 deletions packages/patterns/favorites-manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ export default pattern<Record<string, never>>((_) => {
[UI]: (
<div>
{wishResult.result.map((item) => (
<div>
<ct-cell-link $cell={item.cell} />
<ct-button
onClick={onRemoveFavorite({
favorites: wishResult.result,
item: item.cell,
})}
>
Remove
</ct-button>
<pre>{item.description}</pre>
</div>
<ct-cell-context $cell={item.cell}>
<div>
<ct-cell-link $cell={item.cell} />
<ct-button
onClick={onRemoveFavorite({
favorites: wishResult.result,
item: item.cell,
})}
>
Remove
</ct-button>
<pre>{item.description}</pre>
</div>
</ct-cell-context>
))}
</div>
),
Expand Down
56 changes: 29 additions & 27 deletions packages/patterns/fetch-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,37 +203,39 @@ export default recipe<
/>
</div>

<div>
<h3 id="github-title">
{validData.name}
</h3>
<p>
by {validData.owner.login}
</p>
<p>{validData.description}</p>
<ct-cell-context $cell={validData}>
<div>
<h3 id="github-title">
{validData.name}
</h3>
<p>
by {validData.owner.login}
</p>
<p>{validData.description}</p>
<div>
<span>⭐</span>
<strong>{validData.stargazers_count}</strong> stars
</div>
<div>
<span>🍴</span>
<strong>{validData.forks_count}</strong> forks
</div>
<div>
<span>🔤</span>
<strong>{validData.language}</strong>
</div>
<div>
<a
href={validData.html_url}
target="_blank"
>
View on GitHub →
</a>
<div>
<span>⭐</span>
<strong>{validData.stargazers_count}</strong> stars
</div>
<div>
<span>🍴</span>
<strong>{validData.forks_count}</strong> forks
</div>
<div>
<span>🔤</span>
<strong>{validData.language}</strong>
</div>
<div>
<a
href={validData.html_url}
target="_blank"
>
View on GitHub →
</a>
</div>
</div>
</div>
</div>
</ct-cell-context>
</div>
),
repo: validData,
Expand Down
Loading
Loading