@agent-native/core 0.163.4 → 0.164.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/corpus/README.md +1 -1
- package/corpus/templates/analytics/app/components/agents/FeatureFlagsFleetPanel.tsx +78 -19
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +29 -0
- package/corpus/templates/analytics/app/lib/use-auto-focus-select.ts +4 -4
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +3 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +6 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -2
- package/corpus/templates/analytics/app/routes/_index.tsx +3 -2
- package/corpus/templates/analytics/app/routes/adhoc.$id.tsx +7 -2
- package/corpus/templates/analytics/app/routes/dashboard.tsx +3 -2
- package/corpus/templates/analytics/app/routes/overview.tsx +3 -2
- package/corpus/templates/analytics/app/routes/traffic.tsx +3 -2
- package/corpus/templates/analytics/changelog/2026-08-18-verify-cross-app-feature-flag-changes.md +6 -0
- package/corpus/templates/analytics/netlify.toml +2 -0
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +196 -48
- package/corpus/templates/analytics/server/plugins/feature-flags.ts +5 -0
- package/corpus/templates/analytics/shared/feature-flags.ts +10 -0
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +5 -1
- package/corpus/templates/assets/app/routes/brand-kits._index.tsx +4 -1
- package/corpus/templates/assets/app/routes/libraries.tsx +4 -1
- package/corpus/templates/assets/app/routes/picker.tsx +4 -1
- package/corpus/templates/assets/netlify.toml +2 -0
- package/corpus/templates/brain/netlify.toml +2 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +2 -1
- package/corpus/templates/calendar/changelog/2026-08-19-calendar-page-loads-stay-fast-after-idle-periods.md +6 -0
- package/corpus/templates/calendar/netlify.toml +2 -0
- package/corpus/templates/chat/netlify.toml +2 -0
- package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -3
- package/corpus/templates/clips/app/components/player/reaction-emojis.ts +12 -0
- package/corpus/templates/clips/app/components/player/reactions-tray.tsx +90 -9
- package/corpus/templates/clips/app/components/player/scrubber.tsx +43 -10
- package/corpus/templates/clips/app/components/player/video-player.tsx +105 -15
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -2
- package/corpus/templates/clips/app/routes/_app.wispr.tsx +2 -1
- package/corpus/templates/clips/app/routes/_index.tsx +7 -3
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +13 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +15 -8
- package/corpus/templates/clips/netlify.toml +2 -0
- package/corpus/templates/clips/server/routes/[...page].head.ts +5 -0
- package/corpus/templates/content/netlify.toml +2 -0
- package/corpus/templates/design/.agents/skills/design-editor-architecture/SKILL.md +103 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +2 -1
- package/corpus/templates/design/AGENTS.md +3 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +3 -2
- package/corpus/templates/design/app/components/design/editor/AgentNativeMenuMark.tsx +25 -0
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +411 -0
- package/corpus/templates/design/app/components/design/editor/DesignCollaborators.tsx +153 -0
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +231 -0
- package/corpus/templates/design/app/components/design/editor/MakeRealDialog.tsx +223 -0
- package/corpus/templates/design/app/components/design/editor/PendingScreenDeletionDialog.tsx +58 -0
- package/corpus/templates/design/app/components/design/editor/PendingVisualStyleWarningDialog.tsx +56 -0
- package/corpus/templates/design/app/components/design/editor/ReadOnlyEditorPanel.tsx +23 -0
- package/corpus/templates/design/app/components/design/editor/SaveTemplateDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/editor/toolbar-controls.tsx +185 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +20913 -0
- package/corpus/templates/design/app/pages/design-editor/command-types.ts +120 -0
- package/corpus/templates/design/app/pages/design-editor/commands/README.md +193 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-auto-layout.ts +416 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-screen.ts +112 -0
- package/corpus/templates/design/app/pages/design-editor/commands/align-selection.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +243 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +236 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +304 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +376 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-to-source.ts +132 -0
- package/corpus/templates/design/app/pages/design-editor/commands/can-move-layer.ts +117 -0
- package/corpus/templates/design/app/pages/design-editor/commands/change-selected-z-index.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-relative-style-delta-to-selected-layers.ts +176 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-styles-to-selected-layers.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +710 -0
- package/corpus/templates/design/app/pages/design-editor/commands/confirm-make-real.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-as-figma-svg.ts +95 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-selection.ts +156 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-primitive.ts +291 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-screen-frame.ts +131 -0
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +577 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-files.ts +364 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-selection.ts +521 -0
- package/corpus/templates/design/app/pages/design-editor/commands/detach-instance-menu-action.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/distribute-selection.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-all-screens-pdf.ts +116 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-pdf.ts +103 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-svg.ts +159 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-screen.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-selection.ts +279 -0
- package/corpus/templates/design/app/pages/design-editor/commands/editor-paste.ts +81 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-hotkey.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-single-screen.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/frame-selection.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/geometry-commit.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/commands/get-selected-layer-snapshots.ts +177 -0
- package/corpus/templates/design/app/pages/design-editor/commands/group-selection.ts +127 -0
- package/corpus/templates/design/app/pages/design-editor/commands/iframe-context-menu.ts +121 -0
- package/corpus/templates/design/app/pages/design-editor/commands/import-figma-clipboard-into-design.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +163 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move-to-screen.ts +331 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move.ts +517 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-rename.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +161 -0
- package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/nudge-selection.ts +213 -0
- package/corpus/templates/design/app/pages/design-editor/commands/overview-primitive-reparent.ts +318 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-copied-screens.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-over-selection.ts +70 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +436 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-to-replace.ts +135 -0
- package/corpus/templates/design/app/pages/design-editor/commands/pasted-image-files.ts +209 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-frame-geometry-save.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-tweak-save.ts +160 -0
- package/corpus/templates/design/app/pages/design-editor/commands/primitive-created.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-layer-state-edit.ts +149 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-structure-edit.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-text-edit.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-visual-style-edit.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/redo.ts +1086 -0
- package/corpus/templates/design/app/pages/design-editor/commands/render-png-blob.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/save-file-content.ts +207 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +262 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-text-content-change.ts +216 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-duplicate-change.ts +108 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts +280 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +151 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-overview-annotations.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +143 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-retry-generation.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/style-change.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/styles-change.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/suggest-auto-layout.ts +125 -0
- package/corpus/templates/design/app/pages/design-editor/commands/text-content-change.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tidy-up.ts +123 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-hidden.ts +167 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-locked.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-motion-keyframe.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tweak-prompt-submit.ts +84 -0
- package/corpus/templates/design/app/pages/design-editor/commands/undo.ts +906 -0
- package/corpus/templates/design/app/pages/design-editor/commands/ungroup-selection.ts +170 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-duplicate-change.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-structure-change.ts +274 -0
- package/corpus/templates/design/app/pages/design-editor/commands/write-frame-geometry-snapshot.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/derive/design-breakpoints.ts +56 -0
- package/corpus/templates/design/app/pages/design-editor/derive/overview-screens.ts +146 -0
- package/corpus/templates/design/app/pages/design-editor/domains/use-tweaks.ts +326 -0
- package/corpus/templates/design/app/pages/design-editor/editor-constants.ts +54 -0
- package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +270 -0
- package/corpus/templates/design/app/pages/design-editor/effects/mirror-selection-to-agent-chat.ts +134 -0
- package/corpus/templates/design/app/pages/design-editor/effects/motion-autosave.ts +335 -0
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +252 -0
- package/corpus/templates/design/app/pages/design-editor/effects/resume-pending-generation.ts +178 -0
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/preview-html.ts +19 -0
- package/corpus/templates/design/app/routes/examples.tsx +2 -1
- package/corpus/templates/design/netlify.toml +2 -0
- package/corpus/templates/design/shared/board-file.ts +2 -1
- package/corpus/templates/dispatch/netlify.toml +2 -0
- package/corpus/templates/forms/app/routes/_index.tsx +3 -2
- package/corpus/templates/forms/netlify.toml +2 -0
- package/corpus/templates/mail/app/routes/_index.tsx +3 -2
- package/corpus/templates/mail/netlify.toml +2 -0
- package/corpus/templates/plan/netlify.toml +2 -0
- package/corpus/templates/slides/netlify.toml +2 -0
- package/corpus/templates/tasks/app/routes/_index.tsx +2 -1
- package/dist/agent/engine/builder-engine.d.ts +6 -4
- package/dist/agent/engine/builder-engine.js +91 -26
- package/dist/agent/engine/registry.js +16 -0
- package/dist/cli/code-agent-agent-tools.d.ts +2 -0
- package/dist/cli/code-agent-agent-tools.js +188 -0
- package/dist/cli/code-agent-collaboration.d.ts +34 -0
- package/dist/cli/code-agent-collaboration.js +104 -0
- package/dist/cli/code-agent-executor.js +6 -0
- package/dist/cli/code-agent-schedules.d.ts +54 -0
- package/dist/cli/code-agent-schedules.js +198 -0
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/ConnectBuilderCard.js +5 -2
- package/dist/client/EnvironmentBadge.js +6 -5
- package/dist/client/chat/run-recovery.js +3 -2
- package/dist/client/chat/tool-call-display.js +2 -3
- package/dist/client/components/CodeRequiredDialog.js +4 -2
- package/dist/client/i18n.js +5 -4
- package/dist/client/settings/SettingsPanel.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +6 -1
- package/dist/client/settings/useBuilderStatus.js +22 -33
- package/dist/client/transcription/BuilderTranscriptionCta.js +1 -1
- package/dist/code-agents/index.d.ts +2 -0
- package/dist/code-agents/index.js +2 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/deploy/build.js +10 -4
- package/dist/localization/shared.d.ts +2 -0
- package/dist/localization/shared.js +5 -0
- package/dist/mcp-client/oauth-client.d.ts +1 -0
- package/dist/mcp-client/oauth-client.js +50 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/server/auth-marketing-locales.d.ts +7 -0
- package/dist/server/auth-marketing-locales.js +1322 -0
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +35 -6
- package/dist/server/auth.js +4 -17
- package/dist/server/builder-browser.d.ts +22 -0
- package/dist/server/builder-browser.js +77 -1
- package/dist/server/builder-oauth.d.ts +50 -0
- package/dist/server/builder-oauth.js +263 -0
- package/dist/server/core-routes-plugin.d.ts +11 -0
- package/dist/server/core-routes-plugin.js +291 -415
- package/dist/server/credential-provider.d.ts +1 -1
- package/dist/server/credential-provider.js +1 -1
- package/dist/server/csrf.js +2 -2
- package/dist/server/onboarding-html.js +52 -120
- package/dist/server/ssr-handler.js +13 -4
- package/dist/settings/store.d.ts +9 -0
- package/dist/settings/store.js +19 -0
- package/dist/shared/cache-control.d.ts +22 -0
- package/dist/shared/cache-control.js +25 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/templates/chat/netlify.toml +2 -0
- package/docs/content/deployment.mdx +2 -0
- package/docs/content/multi-app-workspace.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/netlify.toml +2 -0
|
@@ -28,6 +28,7 @@ export function Scrubber(props: ScrubberProps) {
|
|
|
28
28
|
const [tooltip, setTooltip] = useState<
|
|
29
29
|
| { kind: "comment"; content: string; ms: number }
|
|
30
30
|
| { kind: "chapter"; title: string; ms: number }
|
|
31
|
+
| { kind: "reaction"; content: string; ms: number }
|
|
31
32
|
| null
|
|
32
33
|
>(null);
|
|
33
34
|
|
|
@@ -109,6 +110,17 @@ export function Scrubber(props: ScrubberProps) {
|
|
|
109
110
|
return map;
|
|
110
111
|
}, [comments]);
|
|
111
112
|
|
|
113
|
+
const reactionsByMs = useMemo(() => {
|
|
114
|
+
const map = new Map<number, { id: string; emoji: string }[]>();
|
|
115
|
+
recentReactions.forEach((reaction) => {
|
|
116
|
+
const key = Math.round(reaction.videoTimestampMs / 500) * 500;
|
|
117
|
+
const list = map.get(key) ?? [];
|
|
118
|
+
list.push({ id: reaction.id, emoji: reaction.emoji });
|
|
119
|
+
map.set(key, list);
|
|
120
|
+
});
|
|
121
|
+
return map;
|
|
122
|
+
}, [recentReactions]);
|
|
123
|
+
|
|
112
124
|
return (
|
|
113
125
|
<div
|
|
114
126
|
className="relative h-10 flex items-center touch-none cursor-pointer"
|
|
@@ -142,7 +154,9 @@ export function Scrubber(props: ScrubberProps) {
|
|
|
142
154
|
className="absolute -top-10 -translate-x-1/2 max-w-[240px] rounded bg-primary px-2 py-1 text-[11px] text-primary-foreground"
|
|
143
155
|
style={{ left: (tooltip.ms / Math.max(1, durationMs)) * 100 + "%" }}
|
|
144
156
|
>
|
|
145
|
-
{tooltip.kind === "comment"
|
|
157
|
+
{tooltip.kind === "comment" || tooltip.kind === "reaction"
|
|
158
|
+
? tooltip.content
|
|
159
|
+
: tooltip.title}
|
|
146
160
|
</div>
|
|
147
161
|
) : null}
|
|
148
162
|
|
|
@@ -208,17 +222,36 @@ export function Scrubber(props: ScrubberProps) {
|
|
|
208
222
|
</button>
|
|
209
223
|
))}
|
|
210
224
|
|
|
211
|
-
{/* Reaction
|
|
212
|
-
{
|
|
213
|
-
<
|
|
214
|
-
key={
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
225
|
+
{/* Reaction markers */}
|
|
226
|
+
{Array.from(reactionsByMs.entries()).map(([ms, list]) => (
|
|
227
|
+
<button
|
|
228
|
+
key={`reaction-${ms}`}
|
|
229
|
+
type="button"
|
|
230
|
+
data-player-reaction-marker
|
|
231
|
+
onPointerDown={(event) => event.stopPropagation()}
|
|
232
|
+
onMouseEnter={() =>
|
|
233
|
+
setTooltip({
|
|
234
|
+
kind: "reaction",
|
|
235
|
+
content: `${list.map((reaction) => reaction.emoji).join(" ")} · ${list.length} reaction${list.length === 1 ? "" : "s"}`,
|
|
236
|
+
ms,
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
onMouseLeave={() => setTooltip(null)}
|
|
240
|
+
onClick={(event) => {
|
|
241
|
+
event.stopPropagation();
|
|
242
|
+
onSeek(ms);
|
|
218
243
|
}}
|
|
244
|
+
className="absolute -bottom-5 flex h-5 min-w-5 -translate-x-1/2 items-center justify-center rounded-full bg-background/95 px-1 text-sm shadow-md ring-1 ring-primary/40 transition-transform hover:scale-125"
|
|
245
|
+
style={{ left: (ms / Math.max(1, durationMs)) * 100 + "%" }}
|
|
246
|
+
aria-label={`${list.length} reaction${list.length === 1 ? "" : "s"} at ${msToClock(ms)}`}
|
|
219
247
|
>
|
|
220
|
-
{
|
|
221
|
-
|
|
248
|
+
{list[0].emoji}
|
|
249
|
+
{list.length > 1 ? (
|
|
250
|
+
<span className="absolute -right-1.5 -top-1.5 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-primary px-0.5 text-[8px] font-bold leading-none text-primary-foreground ring-1 ring-background">
|
|
251
|
+
{list.length}
|
|
252
|
+
</span>
|
|
253
|
+
) : null}
|
|
254
|
+
</button>
|
|
222
255
|
))}
|
|
223
256
|
|
|
224
257
|
{/* Thumb */}
|
|
@@ -57,6 +57,11 @@ import {
|
|
|
57
57
|
type PlaybackComment,
|
|
58
58
|
} from "./playback-comment-overlay";
|
|
59
59
|
import { PlayerControls, SPEED_OPTIONS } from "./player-controls";
|
|
60
|
+
import type {
|
|
61
|
+
ReactionHandler,
|
|
62
|
+
ReactionHandlerResult,
|
|
63
|
+
ReactionSummary,
|
|
64
|
+
} from "./reactions-tray";
|
|
60
65
|
|
|
61
66
|
function resolveLocalUrl(url: string | null | undefined): string | undefined {
|
|
62
67
|
if (!url) return undefined;
|
|
@@ -251,7 +256,7 @@ export interface VideoPlayerProps {
|
|
|
251
256
|
* visible only while `isFullscreen` is true.
|
|
252
257
|
*/
|
|
253
258
|
enableReactions?: boolean;
|
|
254
|
-
onReact?:
|
|
259
|
+
onReact?: ReactionHandler;
|
|
255
260
|
enableComments?: boolean;
|
|
256
261
|
/**
|
|
257
262
|
* Opens the existing comment composer/panel. While fullscreen, the caller
|
|
@@ -374,6 +379,10 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
374
379
|
const [currentMs, setCurrentMs] = useState(startMs ?? 0);
|
|
375
380
|
currentMsRef.current = currentMs;
|
|
376
381
|
isPlayingRef.current = isPlaying;
|
|
382
|
+
const [optimisticReactions, setOptimisticReactions] = useState<
|
|
383
|
+
ReactionSummary[]
|
|
384
|
+
>([]);
|
|
385
|
+
const optimisticReactionIdRef = useRef(0);
|
|
377
386
|
const [loomStartMs, setLoomStartMs] = useState<number | null>(null);
|
|
378
387
|
const [volume, setVolume] = useState(1);
|
|
379
388
|
// Autoplaying players (e.g. the Slack unfurl embed, `?autoplay=1`) must
|
|
@@ -492,20 +501,101 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
492
501
|
? []
|
|
493
502
|
: [{ startMs: editedMs, title: chapter.title }];
|
|
494
503
|
}),
|
|
495
|
-
reactions:
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
504
|
+
reactions: [
|
|
505
|
+
...(reactions ?? []).flatMap((reaction) => {
|
|
506
|
+
const editedMs = mapMarker(reaction.videoTimestampMs);
|
|
507
|
+
return editedMs === null
|
|
508
|
+
? []
|
|
509
|
+
: [
|
|
510
|
+
{
|
|
511
|
+
id: reaction.id,
|
|
512
|
+
emoji: reaction.emoji,
|
|
513
|
+
videoTimestampMs: editedMs,
|
|
514
|
+
},
|
|
515
|
+
];
|
|
516
|
+
}),
|
|
517
|
+
...optimisticReactions.flatMap((reaction) => {
|
|
518
|
+
const editedMs = mapMarker(reaction.videoTimestampMs);
|
|
519
|
+
return editedMs === null
|
|
520
|
+
? []
|
|
521
|
+
: [
|
|
522
|
+
{
|
|
523
|
+
id: reaction.id,
|
|
524
|
+
emoji: reaction.emoji,
|
|
525
|
+
videoTimestampMs: editedMs,
|
|
526
|
+
},
|
|
527
|
+
];
|
|
528
|
+
}),
|
|
529
|
+
],
|
|
507
530
|
};
|
|
508
|
-
}, [
|
|
531
|
+
}, [
|
|
532
|
+
chapters,
|
|
533
|
+
comments,
|
|
534
|
+
currentMs,
|
|
535
|
+
edits,
|
|
536
|
+
optimisticReactions,
|
|
537
|
+
reactions,
|
|
538
|
+
resolvedDurationMs,
|
|
539
|
+
]);
|
|
540
|
+
|
|
541
|
+
useEffect(() => {
|
|
542
|
+
if (!optimisticReactions.length || !reactions?.length) return;
|
|
543
|
+
setOptimisticReactions((current) => {
|
|
544
|
+
const next = current.filter(
|
|
545
|
+
(optimistic) =>
|
|
546
|
+
!reactions.some(
|
|
547
|
+
(persisted) =>
|
|
548
|
+
persisted.emoji === optimistic.emoji &&
|
|
549
|
+
Math.abs(
|
|
550
|
+
persisted.videoTimestampMs - optimistic.videoTimestampMs,
|
|
551
|
+
) < 1000,
|
|
552
|
+
),
|
|
553
|
+
);
|
|
554
|
+
return next.length === current.length ? current : next;
|
|
555
|
+
});
|
|
556
|
+
}, [optimisticReactions.length, reactions]);
|
|
557
|
+
|
|
558
|
+
const handleReact = useCallback<ReactionHandler>(
|
|
559
|
+
(emoji) => {
|
|
560
|
+
const optimistic = {
|
|
561
|
+
id: `optimistic-reaction-${++optimisticReactionIdRef.current}`,
|
|
562
|
+
emoji,
|
|
563
|
+
videoTimestampMs: currentMsRef.current,
|
|
564
|
+
};
|
|
565
|
+
setOptimisticReactions((current) => [...current, optimistic]);
|
|
566
|
+
|
|
567
|
+
const removeOptimistic = () => {
|
|
568
|
+
setOptimisticReactions((current) =>
|
|
569
|
+
current.filter((reaction) => reaction.id !== optimistic.id),
|
|
570
|
+
);
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
let result: ReactionHandlerResult | undefined;
|
|
574
|
+
try {
|
|
575
|
+
result = onReact?.(emoji);
|
|
576
|
+
} catch {
|
|
577
|
+
removeOptimistic();
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
if (result && typeof result === "object" && "then" in result) {
|
|
582
|
+
return Promise.resolve(result).then(
|
|
583
|
+
(saved) => {
|
|
584
|
+
if (saved === false) removeOptimistic();
|
|
585
|
+
return saved !== false;
|
|
586
|
+
},
|
|
587
|
+
() => {
|
|
588
|
+
removeOptimistic();
|
|
589
|
+
return false;
|
|
590
|
+
},
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
if (result === false) removeOptimistic();
|
|
595
|
+
return result !== false;
|
|
596
|
+
},
|
|
597
|
+
[onReact],
|
|
598
|
+
);
|
|
509
599
|
const activeVideoSourceIdentity = useMemo(
|
|
510
600
|
() => videoSourceIdentity(activeVideoSrc),
|
|
511
601
|
[activeVideoSrc],
|
|
@@ -2016,7 +2106,7 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
|
|
|
2016
2106
|
menuPortalContainer={fullscreenMenuContainer}
|
|
2017
2107
|
showReactionsAndComment={isFullscreen}
|
|
2018
2108
|
enableReactions={enableReactions}
|
|
2019
|
-
onReact={
|
|
2109
|
+
onReact={handleReact}
|
|
2020
2110
|
enableComments={enableComments}
|
|
2021
2111
|
onAddComment={onAddComment}
|
|
2022
2112
|
/>
|
|
@@ -106,8 +106,7 @@ export default function SettingsIndexRoute() {
|
|
|
106
106
|
const builderStatus = useBuilderStatus();
|
|
107
107
|
const connectRequestedRef = useRef(false);
|
|
108
108
|
const builderConnect = useBuilderConnectFlow({
|
|
109
|
-
popupUrl:
|
|
110
|
-
builderStatus.status?.cliAuthUrl ?? builderStatus.status?.connectUrl,
|
|
109
|
+
popupUrl: builderStatus.status?.connectUrl,
|
|
111
110
|
trackingSource: "clips_settings",
|
|
112
111
|
trackingFlow: "clips_setup",
|
|
113
112
|
onConnected: async () => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { withSsrHtmlContentType } from "@agent-native/core/shared";
|
|
1
2
|
import { redirect } from "react-router";
|
|
2
3
|
|
|
3
4
|
export function loader() {
|
|
4
|
-
return redirect("/dictate");
|
|
5
|
+
return withSsrHtmlContentType(redirect("/dictate"));
|
|
5
6
|
}
|
|
6
7
|
|
|
7
8
|
export default function LegacyWisprRedirect() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DefaultSpinner } from "@agent-native/core/client/ui";
|
|
2
|
+
import { withSsrHtmlContentType } from "@agent-native/core/shared";
|
|
2
3
|
import { redirect, type LoaderFunctionArgs } from "react-router";
|
|
3
4
|
|
|
4
5
|
const SEO_TITLE = "Clips - Open Source screen recorder";
|
|
5
6
|
const SEO_DESCRIPTION =
|
|
6
7
|
"Open Source screen recorder and meeting-notes app with AI transcripts, summaries, search, dictation, and agent-readable share links.";
|
|
7
|
-
|
|
8
8
|
export function meta() {
|
|
9
9
|
return [
|
|
10
10
|
{ title: SEO_TITLE },
|
|
@@ -38,11 +38,15 @@ function buildTarget(url: URL): string {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function loader({ url }: LoaderFunctionArgs) {
|
|
41
|
-
throw redirect(buildTarget(url))
|
|
41
|
+
throw withSsrHtmlContentType(redirect(buildTarget(url)), {
|
|
42
|
+
varyByQuery: true,
|
|
43
|
+
});
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
export function clientLoader({ url }: LoaderFunctionArgs) {
|
|
45
|
-
throw redirect(buildTarget(url))
|
|
47
|
+
throw withSsrHtmlContentType(redirect(buildTarget(url)), {
|
|
48
|
+
varyByQuery: true,
|
|
49
|
+
});
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
export function HydrateFallback() {
|
|
@@ -1628,7 +1628,7 @@ export default function RecordingPage() {
|
|
|
1628
1628
|
onReact={(emoji) => {
|
|
1629
1629
|
tracking.reportReaction(emoji);
|
|
1630
1630
|
const liveMs = resolvePlaybackMs();
|
|
1631
|
-
fetch(
|
|
1631
|
+
return fetch(
|
|
1632
1632
|
agentNativePath(
|
|
1633
1633
|
"/_agent-native/actions/react-to-recording",
|
|
1634
1634
|
),
|
|
@@ -1647,9 +1647,11 @@ export default function RecordingPage() {
|
|
|
1647
1647
|
throw new Error(`react failed: ${res.status}`);
|
|
1648
1648
|
return playerDataQ.refetch();
|
|
1649
1649
|
})
|
|
1650
|
-
.
|
|
1651
|
-
|
|
1652
|
-
|
|
1650
|
+
.then(() => true)
|
|
1651
|
+
.catch((err) => {
|
|
1652
|
+
console.warn("[clips] react failed", err);
|
|
1653
|
+
return false;
|
|
1654
|
+
});
|
|
1653
1655
|
}}
|
|
1654
1656
|
className="h-full w-full rounded-none sm:rounded-xl"
|
|
1655
1657
|
/>
|
|
@@ -1736,11 +1738,12 @@ export default function RecordingPage() {
|
|
|
1736
1738
|
) : null}
|
|
1737
1739
|
{recording.enableReactions ? (
|
|
1738
1740
|
<ReactionsTray
|
|
1741
|
+
reactions={reactions}
|
|
1739
1742
|
disabled={!recording.enableReactions || !canComment}
|
|
1740
1743
|
onReact={(emoji) => {
|
|
1741
1744
|
tracking.reportReaction(emoji);
|
|
1742
1745
|
const liveMs = resolvePlaybackMs();
|
|
1743
|
-
fetch(
|
|
1746
|
+
return fetch(
|
|
1744
1747
|
agentNativePath(
|
|
1745
1748
|
"/_agent-native/actions/react-to-recording",
|
|
1746
1749
|
),
|
|
@@ -1759,9 +1762,11 @@ export default function RecordingPage() {
|
|
|
1759
1762
|
throw new Error(`react failed: ${res.status}`);
|
|
1760
1763
|
return playerDataQ.refetch();
|
|
1761
1764
|
})
|
|
1762
|
-
.
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
+
.then(() => true)
|
|
1766
|
+
.catch((err) => {
|
|
1767
|
+
console.warn("[clips] react failed", err);
|
|
1768
|
+
return false;
|
|
1769
|
+
});
|
|
1765
1770
|
}}
|
|
1766
1771
|
/>
|
|
1767
1772
|
) : null}
|
|
@@ -1274,7 +1274,7 @@ export default function ShareRoute() {
|
|
|
1274
1274
|
onReact={(emoji) => {
|
|
1275
1275
|
if (!session) {
|
|
1276
1276
|
requireSignIn("react");
|
|
1277
|
-
return;
|
|
1277
|
+
return false;
|
|
1278
1278
|
}
|
|
1279
1279
|
tracking.reportReaction(emoji);
|
|
1280
1280
|
const liveCt = isLoomEmbedBacked
|
|
@@ -1287,7 +1287,7 @@ export default function ShareRoute() {
|
|
|
1287
1287
|
liveCt < 1e7
|
|
1288
1288
|
? Math.floor(liveCt * 1000)
|
|
1289
1289
|
: currentMs;
|
|
1290
|
-
fetch(
|
|
1290
|
+
return fetch(
|
|
1291
1291
|
agentNativePath("/_agent-native/actions/react-to-recording"),
|
|
1292
1292
|
{
|
|
1293
1293
|
method: "POST",
|
|
@@ -1303,7 +1303,11 @@ export default function ShareRoute() {
|
|
|
1303
1303
|
if (!res.ok) throw new Error(`react failed: ${res.status}`);
|
|
1304
1304
|
return dataQ.refetch();
|
|
1305
1305
|
})
|
|
1306
|
-
.
|
|
1306
|
+
.then(() => true)
|
|
1307
|
+
.catch((err) => {
|
|
1308
|
+
console.warn("[clips] react failed", err);
|
|
1309
|
+
return false;
|
|
1310
|
+
});
|
|
1307
1311
|
}}
|
|
1308
1312
|
className="h-full w-full rounded-none sm:rounded-xl"
|
|
1309
1313
|
/>
|
|
@@ -1371,10 +1375,11 @@ export default function ShareRoute() {
|
|
|
1371
1375
|
) : null}
|
|
1372
1376
|
{recording.enableReactions ? (
|
|
1373
1377
|
<ReactionsTray
|
|
1378
|
+
reactions={reactions}
|
|
1374
1379
|
onReact={(emoji) => {
|
|
1375
1380
|
if (!session) {
|
|
1376
1381
|
requireSignIn("react");
|
|
1377
|
-
return;
|
|
1382
|
+
return false;
|
|
1378
1383
|
}
|
|
1379
1384
|
tracking.reportReaction(emoji);
|
|
1380
1385
|
const liveCt = isLoomEmbedBacked
|
|
@@ -1387,7 +1392,7 @@ export default function ShareRoute() {
|
|
|
1387
1392
|
liveCt < 1e7
|
|
1388
1393
|
? Math.floor(liveCt * 1000)
|
|
1389
1394
|
: currentMs;
|
|
1390
|
-
fetch(
|
|
1395
|
+
return fetch(
|
|
1391
1396
|
agentNativePath(
|
|
1392
1397
|
"/_agent-native/actions/react-to-recording",
|
|
1393
1398
|
),
|
|
@@ -1406,9 +1411,11 @@ export default function ShareRoute() {
|
|
|
1406
1411
|
throw new Error(`react failed: ${res.status}`);
|
|
1407
1412
|
return dataQ.refetch();
|
|
1408
1413
|
})
|
|
1409
|
-
.
|
|
1410
|
-
|
|
1411
|
-
|
|
1414
|
+
.then(() => true)
|
|
1415
|
+
.catch((err) => {
|
|
1416
|
+
console.warn("[clips] react failed", err);
|
|
1417
|
+
return false;
|
|
1418
|
+
});
|
|
1412
1419
|
}}
|
|
1413
1420
|
/>
|
|
1414
1421
|
) : null}
|
|
@@ -16,6 +16,8 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
|
|
|
16
16
|
|
|
17
17
|
[context.production.environment]
|
|
18
18
|
AGENT_NATIVE_HOSTED_HARNESS = "true"
|
|
19
|
+
AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
|
|
20
|
+
AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
|
|
19
21
|
|
|
20
22
|
# Netlify Functions run on linux/x64 (AWS Lambda). This tells the deploy build
|
|
21
23
|
# to bundle the matching ffmpeg-static binary into the server bundle so frame
|
|
@@ -16,6 +16,11 @@ export default defineEventHandler((event) => {
|
|
|
16
16
|
return new Response(null, {
|
|
17
17
|
status: 302,
|
|
18
18
|
headers: {
|
|
19
|
+
// Keep this redirect on the same public SSR-cache path as the shell.
|
|
20
|
+
// Without a content type the deploy adapter cannot apply the canonical
|
|
21
|
+
// cache policy, so every visit to `/` reaches the origin before the
|
|
22
|
+
// already-cached `/library` shell can load.
|
|
23
|
+
"content-type": "text/html; charset=utf-8",
|
|
19
24
|
location: "/library",
|
|
20
25
|
"Permissions-Policy": MEDIA_CAPTURE_PERMISSIONS_POLICY,
|
|
21
26
|
},
|
|
@@ -16,6 +16,8 @@ AGENT_CHAT_DURABLE_BACKGROUND = "true"
|
|
|
16
16
|
|
|
17
17
|
[context.production.environment]
|
|
18
18
|
AGENT_NATIVE_HOSTED_HARNESS = "true"
|
|
19
|
+
AGENT_NATIVE_ENABLE_KEEP_WARM = "1"
|
|
20
|
+
AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND = "1"
|
|
19
21
|
|
|
20
22
|
# A2A delegation calls run a full agent loop (LLM + tool calls + DB queries).
|
|
21
23
|
# The framework does not impose a default agent-run timeout; if a template sets
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-editor-architecture
|
|
3
|
+
description: >-
|
|
4
|
+
Where design editor behavior lives and how to navigate DesignEditor.tsx. Use
|
|
5
|
+
before changing any editor behavior — undo/redo, paste, delete, duplicate,
|
|
6
|
+
style commit, layer move/rename, export, structure change — or before opening
|
|
7
|
+
`app/pages/DesignEditor.tsx`.
|
|
8
|
+
scope: dev
|
|
9
|
+
metadata:
|
|
10
|
+
internal: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Design Editor Architecture
|
|
14
|
+
|
|
15
|
+
## The routing rule
|
|
16
|
+
|
|
17
|
+
Editor **behavior** lives in `app/pages/design-editor/`, not in
|
|
18
|
+
`app/pages/DesignEditor.tsx`.
|
|
19
|
+
|
|
20
|
+
`DesignEditor.tsx` is ~20,900 lines and holds only three things: state
|
|
21
|
+
declarations, the `useCallback` wrappers that gather arguments, and the JSX.
|
|
22
|
+
Every wrapper delegates to a `run<Name>()` command module.
|
|
23
|
+
|
|
24
|
+
**To change what an editor action does, edit the command module.** Opening
|
|
25
|
+
`DesignEditor.tsx` to change behavior is almost always the wrong move — it will
|
|
26
|
+
exhaust your context before you find the code.
|
|
27
|
+
|
|
28
|
+
| Directory | Holds |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| `design-editor/commands/` | 86 one-per-action modules, each exporting `run<Name>(args, …)`. Start at `commands/README.md` |
|
|
31
|
+
| `design-editor/effects/` | Subscription and autosave loops (collab text, motion autosave, agent selection mirroring) |
|
|
32
|
+
| `design-editor/derive/` | Pure derivations (`overview-screens.ts`, `design-breakpoints.ts`) |
|
|
33
|
+
| `design-editor/domains/` | Whole-domain hooks owning state + refs + effects + handlers together (`use-tweaks.ts`) |
|
|
34
|
+
| `design-editor/*.ts` | Shared helpers: `history.ts`, `selection-state.ts`, `pending-edits.ts`, `editor-state.ts`, `editor-helpers.ts`, … |
|
|
35
|
+
|
|
36
|
+
## Common task → file
|
|
37
|
+
|
|
38
|
+
| Task | File |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| Undo / redo | `commands/undo.ts`, `commands/redo.ts` |
|
|
41
|
+
| Paste | `commands/editor-paste.ts` routes; `commands/paste-selection.ts` and `commands/paste-over-selection.ts` do layers |
|
|
42
|
+
| Copy | `commands/copy-selection.ts` |
|
|
43
|
+
| Delete | `commands/delete-selection.ts` (layers), `commands/delete-files.ts` (screens) |
|
|
44
|
+
| Duplicate | `commands/duplicate-selection.ts`, `commands/duplicate-screen.ts` |
|
|
45
|
+
| Style commit | `commands/commit-visual-styles.ts` |
|
|
46
|
+
| Inspector style edit | `commands/style-change.ts` (one property), `commands/styles-change.ts` (many) |
|
|
47
|
+
| Structure change | `commands/visual-structure-change.ts`, `commands/screen-visual-structure-change.ts` |
|
|
48
|
+
| Layer move / rename | `commands/layer-move.ts`, `commands/layer-move-to-screen.ts`, `commands/layer-rename.ts` |
|
|
49
|
+
| Lock / hide a layer | `commands/toggle-layer-locked.ts`, `commands/toggle-layer-hidden.ts` |
|
|
50
|
+
| Export | `commands/render-png-blob.ts`, `download-pdf.ts`, `download-svg.ts`, `copy-as-figma-svg.ts` |
|
|
51
|
+
| Save / persistence | `commands/save-file-content.ts`, `commands/apply-file-content-update.ts` |
|
|
52
|
+
| Breakpoints | `responsive-breakpoints` skill; `derive/design-breakpoints.ts` |
|
|
53
|
+
|
|
54
|
+
A `screen-` prefix means the command is addressed by an explicit `screenId`
|
|
55
|
+
(overview canvas or board). The unprefixed twin acts on the focused screen.
|
|
56
|
+
|
|
57
|
+
Before adding a `domains/` hook, count what it would expose. Past roughly 16
|
|
58
|
+
returned values the hook stops hiding anything and just relocates the wiring —
|
|
59
|
+
measured surfaces for share/export (20), generation (18), and motion (48) are
|
|
60
|
+
all why those still live inline. Also check no input it needs is declared after
|
|
61
|
+
the point where its own outputs are first consumed; responsive-interact fails
|
|
62
|
+
that test and cannot be extracted without changing when values are read.
|
|
63
|
+
|
|
64
|
+
## Navigating DesignEditor.tsx when you must
|
|
65
|
+
|
|
66
|
+
The file carries ~82 section banners. This prints a table of contents:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
grep -n "──" app/pages/DesignEditor.tsx
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Read one region with an offset and a limit instead of opening the file. Every
|
|
73
|
+
section is under ~800 lines. Banners use `// ── Name ──` in the component body
|
|
74
|
+
and `{/* ── Render: name ── */}` inside the JSX.
|
|
75
|
+
|
|
76
|
+
When you add or move a region, add a banner for it.
|
|
77
|
+
|
|
78
|
+
## Hard constraints
|
|
79
|
+
|
|
80
|
+
**`DesignEditor.tsx` must keep exactly one runtime export — the default — and
|
|
81
|
+
zero runtime named exports.** Type-only exports are fine. Both routes
|
|
82
|
+
(`app/routes/design.$id.tsx`, `app/routes/visual-edit.$id.tsx`) import that
|
|
83
|
+
default. A named export breaks React Fast Refresh for the whole editor.
|
|
84
|
+
|
|
85
|
+
**The render-callback trio's dependency arrays are load-bearing.**
|
|
86
|
+
`DesignEditor.routeRefreshBoundary.test.ts` parses the file with the TypeScript
|
|
87
|
+
compiler and enforces:
|
|
88
|
+
|
|
89
|
+
- `renderScreenContent` deps are exactly `[renderEditableScreenContent]`
|
|
90
|
+
- `renderBreakpointContent` deps are exactly `[renderEditableScreenContent]`
|
|
91
|
+
- `renderEditableScreenContent` deps include `activeBreakpointWidthState`,
|
|
92
|
+
`motionDefaultEase`, `motionDurationMs`, `inScreenGradientEditTarget`,
|
|
93
|
+
`handleInScreenGradientEditChange`, and `statePreviewTarget`
|
|
94
|
+
|
|
95
|
+
That last one exists because cached overview canvases must invalidate on
|
|
96
|
+
preview-only state changes. Dropping a name from it renders a stale canvas.
|
|
97
|
+
|
|
98
|
+
**Many specs read source as text.** ~20 specs `readFileSync` either
|
|
99
|
+
`DesignEditor.tsx` or a command module and slice it with `indexOf` markers, then
|
|
100
|
+
assert on the source string. Moving code breaks them with a confusing failure.
|
|
101
|
+
Re-point the path and the marker in the same commit that moves the code. Prefer
|
|
102
|
+
asserting against the command module (`commandSource("undo.ts")`) over the
|
|
103
|
+
editor file.
|
|
@@ -907,7 +907,8 @@ read `references/code-layers.md`. For the VS Code-style source workbench
|
|
|
907
907
|
reserved for editor-internal state (selection chrome, editor-chrome scale
|
|
908
908
|
compensation, clipboard/surface tokens) — the editor strips any property
|
|
909
909
|
under those prefixes before persisting a cross-screen style capture
|
|
910
|
-
(`isEditorInternalCssVar` in `app/pages/
|
|
910
|
+
(`isEditorInternalCssVar` in `app/pages/design-editor/portable-style.ts`),
|
|
911
|
+
so a design that
|
|
911
912
|
defines its own theming under that namespace would silently lose those
|
|
912
913
|
values on a cross-screen move. Use `--color-*`, `--font-*`, or another
|
|
913
914
|
design-owned prefix for tokens/tweaks instead.
|
|
@@ -99,4 +99,6 @@ Read the relevant skill before deeper work in that area.
|
|
|
99
99
|
## Source Changes
|
|
100
100
|
|
|
101
101
|
Before building common workspace or agent UI, read `agent-native-toolkit`; read
|
|
102
|
-
`customizing-agent-native` before adapting shared UI.
|
|
102
|
+
`customizing-agent-native` before adapting shared UI. Editor behavior lives in
|
|
103
|
+
`app/pages/design-editor/commands/*.ts`, not `DesignEditor.tsx` — read
|
|
104
|
+
`design-editor-architecture` before changing it.
|
|
@@ -1768,14 +1768,15 @@ declare var __SELECTED_LAYER_DRAG_PRIORITY__: boolean;
|
|
|
1768
1768
|
// Editor-internal CSS custom-property prefixes — selection chrome colors,
|
|
1769
1769
|
// editor-chrome scale compensation, framework clipboard/surface tokens.
|
|
1770
1770
|
// These have no meaning outside this editor session and must never leak
|
|
1771
|
-
// into persisted user HTML/exports.
|
|
1771
|
+
// into persisted user HTML/exports. design-editor/portable-style.ts's
|
|
1772
1772
|
// applyPortableStyleSnapshotToHtml (isEditorInternalCssVar /
|
|
1773
1773
|
// EDITOR_INTERNAL_CSS_VAR_PREFIXES) already filters them back out on the
|
|
1774
1774
|
// apply side; filtering here too at COLLECTION time is pure bloat
|
|
1775
1775
|
// reduction (skips carrying them across the postMessage boundary at all)
|
|
1776
1776
|
// and changes no observable behavior on the apply side.
|
|
1777
1777
|
//
|
|
1778
|
-
// keep in sync with
|
|
1778
|
+
// keep in sync with design-editor/portable-style.ts's
|
|
1779
|
+
// EDITOR_INTERNAL_CSS_VAR_PREFIXES
|
|
1779
1780
|
var EDITOR_INTERNAL_CSS_VAR_PREFIXES = [
|
|
1780
1781
|
"--design-editor-",
|
|
1781
1782
|
"--agent-native-editor-chrome-",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function AgentNativeMenuMark({ className }: { className?: string }) {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
viewBox="-5 -5 145 88"
|
|
5
|
+
fill="none"
|
|
6
|
+
aria-hidden="true"
|
|
7
|
+
className={className}
|
|
8
|
+
>
|
|
9
|
+
<path
|
|
10
|
+
d="M29.0771 77.8838H2.5L18.9 48.9L43.2 6.6C44 5.2 45.9 5.2 46.7 6.6L69.1 44.2C69.9 45.5 69 46.7305 67.5 46.7305H48.3C47.6 46.7305 46.9 47.1 46.6 47.7L30.8 76.9C30.45 77.5 29.8 77.8838 29.0771 77.8838Z"
|
|
11
|
+
stroke="currentColor"
|
|
12
|
+
strokeWidth="10.5"
|
|
13
|
+
strokeLinecap="round"
|
|
14
|
+
strokeLinejoin="round"
|
|
15
|
+
/>
|
|
16
|
+
<path
|
|
17
|
+
d="M105.927 0H132.5C134 0 134.9 1.6 134.15 2.9L91.5 76.9C91.15 77.5 90.5 77.8853 89.8 77.8853H63.8C62.3 77.8853 61.4 76.3 62.15 75L104.2 1C104.55 0.38 105.2 0 105.927 0Z"
|
|
18
|
+
stroke="currentColor"
|
|
19
|
+
strokeWidth="10.5"
|
|
20
|
+
strokeLinecap="round"
|
|
21
|
+
strokeLinejoin="round"
|
|
22
|
+
/>
|
|
23
|
+
</svg>
|
|
24
|
+
);
|
|
25
|
+
}
|