@agent-native/core-corpus 0.218.0 → 0.219.0

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.
Files changed (32) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/hubspot/SKILL.md +5 -3
  3. package/corpus/templates/community/qr/package.json +1 -1
  4. package/corpus/templates/content/CHANGELOG.md +5 -0
  5. package/corpus/templates/content/app/components/editor/CommentStack.tsx +301 -0
  6. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +651 -149
  7. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +19 -14
  8. package/corpus/templates/content/app/components/editor/block-field-comment-threads.ts +15 -0
  9. package/corpus/templates/content/app/components/editor/block-field-comments.tsx +5 -9
  10. package/corpus/templates/content/app/components/editor/comment-stacks.ts +143 -0
  11. package/corpus/templates/content/app/i18n-data.ts +8 -0
  12. package/corpus/templates/content/changelog/2026-10-22-blocks-with-several-comment-threads-fold-into-one-stack-in-t.md +6 -0
  13. package/corpus/templates/content/changelog/2026-10-22-opening-a-page-no-longer-saves-an-edit-again-after-another-o.md +6 -0
  14. package/corpus/templates/content/docs/product/capabilities/content.comment.page-owned.md +8 -1
  15. package/corpus/templates/design/.generated/bridge/interact-links.generated.ts +8 -8
  16. package/corpus/templates/design/CHANGELOG.md +5 -0
  17. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +18 -1
  18. package/corpus/templates/design/app/components/design/bridge/interact-links.bridge.ts +8 -8
  19. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +15 -13
  20. package/corpus/templates/design/app/i18n/en-US.ts +1 -1
  21. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-modes.ts +15 -6
  22. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-screen-rendering.tsx +29 -5
  23. package/corpus/templates/design/app/pages/design-editor/prototype-navigation-transition.ts +423 -0
  24. package/corpus/templates/design/app/pages/design-editor/view/single-screen-canvas.tsx +35 -9
  25. package/corpus/templates/design/changelog/2026-10-20-the-design-full-app-toggle-on-the-home-page-no-longer-hides-.md +6 -0
  26. package/corpus/templates/design/changelog/2026-10-22-prototype-links-can-play-code-authored-screen-transitions.md +6 -0
  27. package/corpus/templates/design/shared/motion-authored-css-import.ts +938 -7
  28. package/corpus/templates/design/shared/motion-html-source.ts +1689 -135
  29. package/corpus/templates/design/shared/motion-prototype-transition.ts +329 -0
  30. package/corpus/templates/design/shared/motion-react-source.ts +2154 -126
  31. package/corpus/templates/design/shared/motion-text-runtime-v1.fixture.txt +221 -0
  32. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -32,4 +32,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core-corpus/corpu
32
32
 
33
33
  ## Generated Counts
34
34
 
35
- - template files: 14570
35
+ - template files: 14579
@@ -45,9 +45,11 @@ actions do not expose, inspect the provider catalog/docs and call
45
45
  endpoint, call `provider-api-request` (provider `hubspot`, e.g.
46
46
  `/crm/v3/properties/deals`) via `provider-api-docs` **without `stageAs`**.
47
47
  Property definitions are read-only control metadata, not analysis rows; never
48
- stage them. `stageAs` writes result rows to shared staged-dataset storage,
49
- which can be at capacity and may evict existing datasets. Do not clear or
50
- evict existing staged datasets to make room. If a metadata request cannot be
48
+ stage them. `stageAs` writes result rows to staged-dataset storage, which
49
+ has a per-user quota and an app-wide limit. Going over either removes the
50
+ least recently written datasets (the user's own for the per-user quota, any
51
+ user's for the app-wide limit), and a write too large to fit even then fails.
52
+ Do not clear existing staged datasets to make room. If a metadata request cannot be
51
53
  read without staging, narrow the request or return only the required property
52
54
  names, labels, and types through a read-only path.
53
55
  - `provider-api-request` with `provider: "hubspot"` — arbitrary HubSpot HTTP
@@ -11,7 +11,7 @@
11
11
  "typecheck": "tsc --noEmit"
12
12
  },
13
13
  "dependencies": {
14
- "@agent-native/core": "^0.218.0",
14
+ "@agent-native/core": "^0.219.0",
15
15
  "postgres": "^3.4.9",
16
16
  "qrcode": "^1.5.4",
17
17
  "zod": "^4.6.7"
@@ -5,6 +5,10 @@ time from the command menu (Cmd+K → "What's new").
5
5
 
6
6
  ## 2026-10-22
7
7
 
8
+ ### Added
9
+
10
+ - Blocks with several comment threads fold into one stack in the margin, which opens in place when you click it or a highlight
11
+
8
12
  ### Improved
9
13
 
10
14
  - A collection linked to a big GitHub folder fills faster, and pushes to other linked collections aren't held up while it does
@@ -13,6 +17,7 @@ time from the command menu (Cmd+K → "What's new").
13
17
 
14
18
  ### Fixed
15
19
 
20
+ - Opening a page no longer saves an edit again after another open tab's save already stored it.
16
21
  - Changes made from a menu or popover, such as an image's alt text, are always saved.
17
22
  - Agents can read saved page titles and text after an unrelated icon change fails.
18
23
  - Text an agent writes inside a callout, column or synced block without indenting it now shows on the page and survives your edits.
@@ -0,0 +1,301 @@
1
+ import type { useT } from "@agent-native/core/client/i18n";
2
+ import { IconChevronUp } from "@tabler/icons-react";
3
+ import { forwardRef, useEffect, useId, useRef, type ReactNode } from "react";
4
+
5
+ import type { CommentThread } from "@/hooks/use-comments";
6
+ import { cn } from "@/lib/utils";
7
+
8
+ import {
9
+ CommentAvatar,
10
+ CommentRow,
11
+ renderCommentBody,
12
+ useCommentTimestamp,
13
+ } from "./CommentRow";
14
+
15
+ type Translate = ReturnType<typeof useT>;
16
+
17
+ /** Two cards' edges under a stack, so it reads as more than one thread. */
18
+ export function CommentStackSheets() {
19
+ return (
20
+ <>
21
+ <span
22
+ aria-hidden
23
+ className="pointer-events-none absolute bottom-0 left-6 right-8 top-8 rounded-xl bg-popover shadow-comment-card ring-1 ring-border/60"
24
+ data-comment-stack-sheet
25
+ />
26
+ <span
27
+ aria-hidden
28
+ className="pointer-events-none absolute bottom-1 left-4 right-6 top-4 rounded-xl bg-popover shadow-comment-card ring-1 ring-border/60"
29
+ data-comment-stack-sheet
30
+ />
31
+ </>
32
+ );
33
+ }
34
+
35
+ /** The first authors of a stack's threads, without repeats: email, name. */
36
+ function stackAuthors(threads: readonly CommentThread[]) {
37
+ const authors = new Map<string, string>();
38
+ for (const thread of threads) {
39
+ const first = thread.comments[0];
40
+ if (!first || authors.has(first.author_email)) continue;
41
+ authors.set(first.author_email, first.author_name ?? first.author_email);
42
+ if (authors.size === 3) break;
43
+ }
44
+ return [...authors];
45
+ }
46
+
47
+ function StackAvatars({ threads }: { threads: readonly CommentThread[] }) {
48
+ return (
49
+ <span className="flex -space-x-1">
50
+ {stackAuthors(threads).map(([email, name]) => (
51
+ <CommentAvatar
52
+ key={email}
53
+ email={email}
54
+ name={name}
55
+ className="size-5 text-[9px] ring-2 ring-popover"
56
+ />
57
+ ))}
58
+ </span>
59
+ );
60
+ }
61
+
62
+ /** "+N more" with the avatars of the threads it counts. */
63
+ export function CommentStackMore({
64
+ threads,
65
+ t,
66
+ }: {
67
+ threads: readonly CommentThread[];
68
+ t: Translate;
69
+ }) {
70
+ return (
71
+ <>
72
+ <StackAvatars threads={threads} />
73
+ <span className="font-medium">
74
+ {t("comments.stackMore", { count: threads.length })}
75
+ </span>
76
+ </>
77
+ );
78
+ }
79
+
80
+ const footerClass =
81
+ "flex h-9 w-full items-center gap-2 border-t border-border/60 px-4 text-xs text-muted-foreground";
82
+
83
+ /** A new comment's footer on a folded stack; it opens the stack. */
84
+ export const CommentStackShowAll = forwardRef<
85
+ HTMLButtonElement,
86
+ {
87
+ threads: readonly CommentThread[];
88
+ onOpen: () => void;
89
+ t: Translate;
90
+ }
91
+ >(function CommentStackShowAll({ threads, onOpen, t }, ref) {
92
+ return (
93
+ <button
94
+ ref={ref}
95
+ type="button"
96
+ className={cn(
97
+ footerClass,
98
+ "text-start hover:bg-accent/40 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
99
+ )}
100
+ aria-expanded={false}
101
+ aria-label={t("comments.stackShowAll", { count: threads.length })}
102
+ onClick={(event) => {
103
+ event.stopPropagation();
104
+ onOpen();
105
+ }}
106
+ data-comment-stack-show-all
107
+ >
108
+ <CommentStackMore threads={threads} t={t} />
109
+ </button>
110
+ );
111
+ });
112
+
113
+ /**
114
+ * A block's open threads folded into one card: the front thread's quote and
115
+ * first comment, with the others counted below.
116
+ */
117
+ export function CommentStackCard({
118
+ stackKey,
119
+ heightId,
120
+ threads,
121
+ front,
122
+ isActive,
123
+ onOpen,
124
+ onHoverChange,
125
+ onHeightChange,
126
+ t,
127
+ }: {
128
+ stackKey: string;
129
+ /** The id the margin lays this card out under. */
130
+ heightId: string;
131
+ threads: readonly CommentThread[];
132
+ front: CommentThread;
133
+ isActive: boolean;
134
+ onOpen: () => void;
135
+ onHoverChange: (hovered: boolean) => void;
136
+ onHeightChange: (threadId: string, height: number) => void;
137
+ t: Translate;
138
+ }) {
139
+ const ref = useRef<HTMLDivElement>(null);
140
+ const descriptionId = useId();
141
+ const timestamp = useCommentTimestamp();
142
+ useEffect(() => {
143
+ const element = ref.current;
144
+ if (!element) return;
145
+ const update = () =>
146
+ onHeightChange(heightId, element.getBoundingClientRect().height);
147
+ update();
148
+ if (typeof ResizeObserver === "undefined") return;
149
+ const observer = new ResizeObserver(update);
150
+ observer.observe(element);
151
+ return () => observer.disconnect();
152
+ }, [heightId, onHeightChange]);
153
+ const first = front.comments[0];
154
+ const firstName = first
155
+ ? (first.author_name ?? first.author_email.split("@")[0])
156
+ : null;
157
+ const replies = front.comments.length - 1;
158
+ const others = threads.filter((thread) => thread !== front);
159
+ return (
160
+ <div
161
+ ref={ref}
162
+ className="group/stack relative pb-2"
163
+ data-comment-stack={stackKey}
164
+ data-comment-stack-state="folded"
165
+ data-comment-stack-front={front.threadId}
166
+ onMouseEnter={() => onHoverChange(true)}
167
+ onMouseLeave={() => onHoverChange(false)}
168
+ >
169
+ <CommentStackSheets />
170
+ <div
171
+ className={cn(
172
+ "relative mx-2 mr-4 overflow-hidden rounded-xl bg-popover ring-1 ring-border/60 shadow-comment-card transition-[box-shadow,translate] duration-[260ms] ease-[var(--ease-drawer)] motion-reduce:transform-none motion-reduce:transition-none",
173
+ isActive
174
+ ? "-translate-x-2 shadow-comment-emphasis ring-foreground/15"
175
+ : "group-hover/stack:-translate-x-2 group-hover/stack:shadow-comment-emphasis group-focus-within/stack:-translate-x-2 group-focus-within/stack:shadow-comment-emphasis motion-reduce:group-hover/stack:translate-x-0 motion-reduce:group-focus-within/stack:translate-x-0",
176
+ )}
177
+ >
178
+ {/* Inert keeps the preview's links out of reach, and leaves it out of
179
+ the open button's description too; the hidden copy below is
180
+ what a screen reader hears. */}
181
+ <div inert className="grid grid-cols-1 gap-3.5 px-4 pb-3.5 pt-3.5">
182
+ {front.quotedText ? (
183
+ <p className="-mb-1 line-clamp-1 border-s-2 border-border ps-2.5 text-sm text-muted-foreground">
184
+ {front.quotedText}
185
+ </p>
186
+ ) : null}
187
+ {first ? (
188
+ <CommentRow
189
+ avatar={
190
+ <CommentAvatar
191
+ email={first.author_email}
192
+ name={first.author_name ?? first.author_email}
193
+ />
194
+ }
195
+ name={firstName}
196
+ timestamp={{
197
+ ...timestamp(first.created_at),
198
+ dateTime: first.created_at,
199
+ }}
200
+ >
201
+ <span className="line-clamp-3">
202
+ {renderCommentBody(first.content, first.mentions)}
203
+ </span>
204
+ </CommentRow>
205
+ ) : null}
206
+ {replies > 0 ? (
207
+ <p className="-mt-2 ps-9.5 text-xs text-muted-foreground">
208
+ {t("comments.replyCount", { count: replies })}
209
+ </p>
210
+ ) : null}
211
+ </div>
212
+ <div inert className={footerClass} data-comment-stack-footer>
213
+ <CommentStackMore threads={others} t={t} />
214
+ </div>
215
+ <div hidden id={descriptionId} data-comment-stack-description>
216
+ {front.quotedText ? <p>{front.quotedText}</p> : null}
217
+ {first ? (
218
+ <>
219
+ <p>{firstName}</p>
220
+ <p>{renderCommentBody(first.content, first.mentions)}</p>
221
+ </>
222
+ ) : null}
223
+ {replies > 0 ? (
224
+ <p>{t("comments.replyCount", { count: replies })}</p>
225
+ ) : null}
226
+ {stackAuthors(others).map(([email, name]) => (
227
+ <p key={email}>{name}</p>
228
+ ))}
229
+ <p>{t("comments.stackMore", { count: others.length })}</p>
230
+ </div>
231
+ <button
232
+ type="button"
233
+ className="absolute inset-0 rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
234
+ aria-expanded={false}
235
+ aria-label={t("comments.stackShowAll", { count: threads.length })}
236
+ aria-describedby={descriptionId}
237
+ onClick={(event) => {
238
+ event.stopPropagation();
239
+ onOpen();
240
+ }}
241
+ data-comment-stack-open
242
+ />
243
+ </div>
244
+ </div>
245
+ );
246
+ }
247
+
248
+ /** Above an open stack's cards: folds them back into one. */
249
+ export function CommentStackHeader({
250
+ stackKey,
251
+ top,
252
+ onCollapse,
253
+ t,
254
+ }: {
255
+ stackKey: string;
256
+ top: number;
257
+ onCollapse: () => void;
258
+ t: Translate;
259
+ }) {
260
+ return (
261
+ <div
262
+ className="absolute inset-x-2 flex h-7 items-center transition-[top] duration-[260ms] ease-[var(--ease-drawer)] motion-reduce:transition-none"
263
+ style={{ top }}
264
+ data-comment-stack={stackKey}
265
+ data-comment-stack-state="open"
266
+ >
267
+ <button
268
+ type="button"
269
+ className="-ms-1.5 inline-flex h-7 items-center gap-1 rounded-md px-1.5 text-xs font-medium text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
270
+ aria-expanded
271
+ onClick={(event) => {
272
+ event.stopPropagation();
273
+ onCollapse();
274
+ }}
275
+ data-comment-stack-collapse
276
+ >
277
+ <IconChevronUp className="size-3.5" aria-hidden />
278
+ {t("comments.stackCollapse")}
279
+ </button>
280
+ </div>
281
+ );
282
+ }
283
+
284
+ /** The line beside an open stack's cards that ties them to one block. */
285
+ export function CommentStackGuide({
286
+ top,
287
+ height,
288
+ }: {
289
+ top: number;
290
+ height: number;
291
+ }): ReactNode {
292
+ if (height <= 0) return null;
293
+ return (
294
+ <span
295
+ aria-hidden
296
+ className="absolute start-0.5 w-0.5 rounded-full bg-border transition-[top,height] duration-[260ms] ease-[var(--ease-drawer)] motion-reduce:transition-none"
297
+ style={{ top, height }}
298
+ data-comment-stack-guide
299
+ />
300
+ );
301
+ }