@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
@@ -0,0 +1,329 @@
1
+ export const MOTION_PROTOTYPE_TRANSITION_ATTRIBUTE =
2
+ "data-an-prototype-transition" as const;
3
+ export const MOTION_PROTOTYPE_TRANSITION_VERSION = 1 as const;
4
+
5
+ export const MOTION_PROTOTYPE_TRANSITION_KINDS = [
6
+ "instant",
7
+ "dissolve",
8
+ "smart-animate",
9
+ "move-in",
10
+ "move-out",
11
+ "push",
12
+ "slide-in",
13
+ "slide-out",
14
+ ] as const;
15
+
16
+ export type MotionPrototypeTransitionKind =
17
+ (typeof MOTION_PROTOTYPE_TRANSITION_KINDS)[number];
18
+ export type MotionPrototypeDirection = "left" | "right" | "top" | "bottom";
19
+ export type MotionPrototypeEasePreset =
20
+ | "linear"
21
+ | "ease"
22
+ | "ease-in"
23
+ | "ease-out"
24
+ | "ease-in-out";
25
+
26
+ export type MotionPrototypeEase =
27
+ | { kind: "preset"; preset: MotionPrototypeEasePreset }
28
+ | {
29
+ kind: "custom-bezier";
30
+ x1: number;
31
+ y1: number;
32
+ x2: number;
33
+ y2: number;
34
+ };
35
+
36
+ export interface MotionPrototypeNavigationTransition {
37
+ version: typeof MOTION_PROTOTYPE_TRANSITION_VERSION;
38
+ trigger: "click";
39
+ action: "navigate";
40
+ transition: MotionPrototypeTransitionKind;
41
+ direction?: MotionPrototypeDirection;
42
+ durationMs?: number;
43
+ ease?: MotionPrototypeEase;
44
+ }
45
+
46
+ export type MotionPrototypeTransitionErrorCode =
47
+ | "not-a-string"
48
+ | "malformed-json"
49
+ | "invalid-document"
50
+ | "unsupported-version"
51
+ | "invalid-value"
52
+ | "unserializable-document";
53
+
54
+ export class MotionPrototypeTransitionError extends Error {
55
+ constructor(
56
+ readonly code: MotionPrototypeTransitionErrorCode,
57
+ message: string,
58
+ readonly path?: string,
59
+ ) {
60
+ super(message);
61
+ this.name = "MotionPrototypeTransitionError";
62
+ }
63
+ }
64
+
65
+ export type MotionPrototypeTransitionDecodeResult =
66
+ | { status: "absent" }
67
+ | { status: "valid"; transition: MotionPrototypeNavigationTransition }
68
+ | { status: "invalid"; error: MotionPrototypeTransitionError };
69
+
70
+ export type MotionPrototypeTransitionValidationResult =
71
+ | { valid: true; transition: MotionPrototypeNavigationTransition }
72
+ | { valid: false; error: MotionPrototypeTransitionError };
73
+
74
+ const ROOT_FIELDS = new Set([
75
+ "version",
76
+ "trigger",
77
+ "action",
78
+ "transition",
79
+ "direction",
80
+ "durationMs",
81
+ "ease",
82
+ ]);
83
+ const DIRECTIONAL_TRANSITIONS = new Set<MotionPrototypeTransitionKind>([
84
+ "move-in",
85
+ "move-out",
86
+ "push",
87
+ "slide-in",
88
+ "slide-out",
89
+ ]);
90
+ const EASE_PRESETS = new Set<MotionPrototypeEasePreset>([
91
+ "linear",
92
+ "ease",
93
+ "ease-in",
94
+ "ease-out",
95
+ "ease-in-out",
96
+ ]);
97
+ const DIRECTIONS = new Set<MotionPrototypeDirection>([
98
+ "left",
99
+ "right",
100
+ "top",
101
+ "bottom",
102
+ ]);
103
+
104
+ function isRecord(value: unknown): value is Record<string, unknown> {
105
+ return typeof value === "object" && value !== null && !Array.isArray(value);
106
+ }
107
+
108
+ function invalid(
109
+ code: MotionPrototypeTransitionErrorCode,
110
+ message: string,
111
+ path?: string,
112
+ ): MotionPrototypeTransitionValidationResult {
113
+ return {
114
+ valid: false,
115
+ error: new MotionPrototypeTransitionError(code, message, path),
116
+ };
117
+ }
118
+
119
+ function hasOnlyFields(
120
+ value: Record<string, unknown>,
121
+ fields: ReadonlySet<string>,
122
+ path: string,
123
+ ): MotionPrototypeTransitionValidationResult | null {
124
+ const unknown = Object.keys(value).find((key) => !fields.has(key));
125
+ return unknown === undefined
126
+ ? null
127
+ : invalid(
128
+ "invalid-document",
129
+ `Unsupported field "${unknown}" in ${path}.`,
130
+ `${path}.${unknown}`,
131
+ );
132
+ }
133
+
134
+ function validateEase(
135
+ value: unknown,
136
+ ): MotionPrototypeTransitionValidationResult | null {
137
+ if (!isRecord(value)) {
138
+ return invalid("invalid-value", "Ease must be an object.", "ease");
139
+ }
140
+
141
+ if (value.kind === "preset") {
142
+ const fields = hasOnlyFields(value, new Set(["kind", "preset"]), "ease");
143
+ if (fields) return fields;
144
+ return EASE_PRESETS.has(value.preset as MotionPrototypeEasePreset)
145
+ ? null
146
+ : invalid("invalid-value", "Ease preset is unsupported.", "ease.preset");
147
+ }
148
+
149
+ if (value.kind === "custom-bezier") {
150
+ const fields = hasOnlyFields(
151
+ value,
152
+ new Set(["kind", "x1", "y1", "x2", "y2"]),
153
+ "ease",
154
+ );
155
+ if (fields) return fields;
156
+ for (const coordinate of ["x1", "y1", "x2", "y2"] as const) {
157
+ if (
158
+ typeof value[coordinate] !== "number" ||
159
+ !Number.isFinite(value[coordinate])
160
+ ) {
161
+ return invalid(
162
+ "invalid-value",
163
+ `Bezier coordinate ${coordinate} must be finite.`,
164
+ `ease.${coordinate}`,
165
+ );
166
+ }
167
+ }
168
+ for (const coordinate of ["x1", "x2"] as const) {
169
+ const control = value[coordinate] as number;
170
+ if (control < 0 || control > 1) {
171
+ return invalid(
172
+ "invalid-value",
173
+ `Bezier coordinate ${coordinate} must be between 0 and 1.`,
174
+ `ease.${coordinate}`,
175
+ );
176
+ }
177
+ }
178
+ return null;
179
+ }
180
+
181
+ return invalid("invalid-value", "Ease kind is unsupported.", "ease.kind");
182
+ }
183
+
184
+ /** Validates explicit transition data without guessing missing timing values. */
185
+ export function validateMotionPrototypeNavigationTransition(
186
+ value: unknown,
187
+ ): MotionPrototypeTransitionValidationResult {
188
+ if (!isRecord(value)) {
189
+ return invalid("invalid-document", "Transition must be an object.");
190
+ }
191
+ const unknown = hasOnlyFields(value, ROOT_FIELDS, "transition");
192
+ if (unknown) return unknown;
193
+ if (value.version !== MOTION_PROTOTYPE_TRANSITION_VERSION) {
194
+ return invalid(
195
+ "unsupported-version",
196
+ "Transition version is unsupported.",
197
+ "transition.version",
198
+ );
199
+ }
200
+ if (value.trigger !== "click") {
201
+ return invalid(
202
+ "invalid-value",
203
+ "Only click navigation is supported by this document version.",
204
+ "transition.trigger",
205
+ );
206
+ }
207
+ if (value.action !== "navigate") {
208
+ return invalid(
209
+ "invalid-value",
210
+ "Only navigation is supported by this document version.",
211
+ "transition.action",
212
+ );
213
+ }
214
+ if (
215
+ typeof value.transition !== "string" ||
216
+ !MOTION_PROTOTYPE_TRANSITION_KINDS.includes(
217
+ value.transition as MotionPrototypeTransitionKind,
218
+ )
219
+ ) {
220
+ return invalid(
221
+ "invalid-value",
222
+ "Transition kind is unsupported.",
223
+ "transition.transition",
224
+ );
225
+ }
226
+
227
+ const transition = value.transition as MotionPrototypeTransitionKind;
228
+ if (transition === "instant") {
229
+ for (const field of ["direction", "durationMs", "ease"] as const) {
230
+ if (Object.prototype.hasOwnProperty.call(value, field)) {
231
+ return invalid(
232
+ "invalid-value",
233
+ `Instant transitions do not accept ${field}.`,
234
+ `transition.${field}`,
235
+ );
236
+ }
237
+ }
238
+ } else {
239
+ if (
240
+ typeof value.durationMs !== "number" ||
241
+ !Number.isFinite(value.durationMs) ||
242
+ value.durationMs <= 0
243
+ ) {
244
+ return invalid(
245
+ "invalid-value",
246
+ "Timed transitions require a finite positive durationMs.",
247
+ "transition.durationMs",
248
+ );
249
+ }
250
+ if (value.ease === undefined) {
251
+ return invalid(
252
+ "invalid-value",
253
+ "Timed transitions require an explicit ease.",
254
+ "transition.ease",
255
+ );
256
+ }
257
+ const easeError = validateEase(value.ease);
258
+ if (easeError) return easeError;
259
+
260
+ if (DIRECTIONAL_TRANSITIONS.has(transition)) {
261
+ if (!DIRECTIONS.has(value.direction as MotionPrototypeDirection)) {
262
+ return invalid(
263
+ "invalid-value",
264
+ "Directional transitions require a supported direction.",
265
+ "transition.direction",
266
+ );
267
+ }
268
+ } else if (value.direction !== undefined) {
269
+ return invalid(
270
+ "invalid-value",
271
+ "This transition does not accept a direction.",
272
+ "transition.direction",
273
+ );
274
+ }
275
+ }
276
+
277
+ return {
278
+ valid: true,
279
+ transition: value as unknown as MotionPrototypeNavigationTransition,
280
+ };
281
+ }
282
+
283
+ /** Reads the source attribute while preserving absent and invalid as distinct states. */
284
+ export function decodeMotionPrototypeTransitionAttribute(
285
+ value: unknown,
286
+ ): MotionPrototypeTransitionDecodeResult {
287
+ if (value === undefined || value === null) return { status: "absent" };
288
+ if (typeof value !== "string") {
289
+ return {
290
+ status: "invalid",
291
+ error: new MotionPrototypeTransitionError(
292
+ "not-a-string",
293
+ "Transition attribute must be a string.",
294
+ ),
295
+ };
296
+ }
297
+ let parsed: unknown;
298
+ try {
299
+ parsed = JSON.parse(value);
300
+ } catch {
301
+ return {
302
+ status: "invalid",
303
+ error: new MotionPrototypeTransitionError(
304
+ "malformed-json",
305
+ "Transition attribute contains malformed JSON.",
306
+ ),
307
+ };
308
+ }
309
+ const result = validateMotionPrototypeNavigationTransition(parsed);
310
+ return result.valid
311
+ ? { status: "valid", transition: result.transition }
312
+ : { status: "invalid", error: result.error };
313
+ }
314
+
315
+ /** Serializes only a validated document and never inserts inferred defaults. */
316
+ export function encodeMotionPrototypeTransitionAttribute(
317
+ value: unknown,
318
+ ): string {
319
+ const result = validateMotionPrototypeNavigationTransition(value);
320
+ if (!result.valid) throw result.error;
321
+ try {
322
+ return JSON.stringify(result.transition);
323
+ } catch {
324
+ throw new MotionPrototypeTransitionError(
325
+ "unserializable-document",
326
+ "Transition document could not be serialized.",
327
+ );
328
+ }
329
+ }