@agent-native/core 0.169.0 → 0.170.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 (496) hide show
  1. package/agent-native.eject.json +4 -1
  2. package/bin/agent-native.js +23 -5
  3. package/corpus/README.md +1 -1
  4. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
  5. package/corpus/templates/analytics/actions/bigquery-table-info.ts +3 -2
  6. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  7. package/corpus/templates/analytics/actions/search-bigquery-schema.ts +130 -4
  8. package/corpus/templates/analytics/agent-native.config.ts +1 -0
  9. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +36 -23
  10. package/corpus/templates/analytics/app/i18n-data.ts +28 -0
  11. package/corpus/templates/analytics/app/lib/dashboard-visibility.ts +41 -0
  12. package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
  13. package/corpus/templates/analytics/app/pages/DashboardOverview.tsx +34 -9
  14. package/corpus/templates/analytics/app/routes/$.tsx +10 -0
  15. package/corpus/templates/analytics/app/routes.ts +3 -1
  16. package/corpus/templates/analytics/changelog/2026-08-21-dashboard-filters-keep-other-users-dashboards-out-of-mine.md +6 -0
  17. package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
  18. package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
  19. package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
  20. package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
  21. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
  22. package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
  23. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
  24. package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
  25. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
  26. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
  27. package/corpus/templates/analytics/server/lib/real-data-actions.ts +14 -3
  28. package/corpus/templates/analytics/server/lib/slack.ts +4 -2
  29. package/corpus/templates/analytics/server/plugins/agent-chat.ts +33 -3
  30. package/corpus/templates/analytics/vitest.config.ts +6 -1
  31. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
  32. package/corpus/templates/assets/app/routes/library.tsx +5 -3
  33. package/corpus/templates/assets/app/routes.ts +3 -1
  34. package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
  35. package/corpus/templates/assets/vitest.config.ts +6 -1
  36. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
  37. package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
  38. package/corpus/templates/brain/app/routes/sources.tsx +8 -3
  39. package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
  40. package/corpus/templates/brain/server/lib/brain.ts +27 -2
  41. package/corpus/templates/brain/vitest.config.ts +1 -0
  42. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
  43. package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
  44. package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
  45. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
  46. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
  47. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
  48. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
  49. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
  50. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
  51. package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
  52. package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
  53. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
  54. package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
  55. package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
  56. package/corpus/templates/calendar/app/routes.ts +3 -1
  57. package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
  58. package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
  59. package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
  60. package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
  61. package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
  62. package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
  63. package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
  64. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
  65. package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
  66. package/corpus/templates/calendar/server/onboarding.ts +85 -0
  67. package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
  68. package/corpus/templates/calendar/shared/api.ts +9 -1
  69. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  70. package/corpus/templates/chat/app/routes.ts +3 -1
  71. package/corpus/templates/chat/vitest.config.ts +8 -0
  72. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
  73. package/corpus/templates/clips/actions/get-meeting.ts +9 -4
  74. package/corpus/templates/clips/actions/list-recordings.ts +16 -3
  75. package/corpus/templates/clips/actions/search-meetings.ts +1 -0
  76. package/corpus/templates/clips/actions/stop-meeting-recording.ts +87 -6
  77. package/corpus/templates/clips/actions/view-screen.ts +8 -1
  78. package/corpus/templates/clips/app/components/library/search-bar.tsx +1 -1
  79. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
  80. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
  81. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
  82. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  83. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
  84. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
  85. package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
  86. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
  87. package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
  88. package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
  90. package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
  91. package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
  92. package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
  93. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
  94. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
  95. package/corpus/templates/clips/desktop/src/app.tsx +53 -24
  96. package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
  97. package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
  98. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
  99. package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
  100. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
  101. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
  102. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
  103. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
  104. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
  105. package/corpus/templates/clips/server/lib/emails.ts +17 -33
  106. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
  107. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
  108. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
  109. package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
  110. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
  111. package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
  112. package/corpus/templates/content/app/i18n-data.ts +25 -0
  113. package/corpus/templates/content/app/routes.ts +3 -1
  114. package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
  115. package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
  116. package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
  117. package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
  118. package/corpus/templates/content/vitest.config.ts +7 -1
  119. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
  120. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
  121. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1386 -92
  122. package/corpus/templates/design/actions/generate-design.ts +98 -47
  123. package/corpus/templates/design/actions/get-design-system.ts +6 -1
  124. package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
  125. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
  126. package/corpus/templates/design/app/components/design/EditPanel.tsx +15 -47
  127. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
  128. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2060 -144
  129. package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
  130. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
  131. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -8
  132. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
  133. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
  134. package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
  135. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
  136. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +13 -8
  137. package/corpus/templates/design/app/i18n-data.ts +11 -10
  138. package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
  139. package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
  140. package/corpus/templates/design/app/pages/DesignEditor.tsx +99 -57
  141. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +39 -8
  142. package/corpus/templates/design/app/pages/DesignSystems.tsx +137 -43
  143. package/corpus/templates/design/app/pages/Index.tsx +3 -1
  144. package/corpus/templates/design/app/pages/Templates.tsx +0 -10
  145. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
  146. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
  147. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
  148. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
  149. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
  150. package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
  151. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
  152. package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
  153. package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
  154. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
  155. package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
  156. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
  157. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
  158. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
  159. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
  160. package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
  161. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
  162. package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
  163. package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
  164. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
  165. package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
  166. package/corpus/templates/design/app/pages/design-editor/preview-navigation.ts +25 -0
  167. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
  168. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
  169. package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
  170. package/corpus/templates/design/app/routes.ts +3 -1
  171. package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
  172. package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
  173. package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
  174. package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
  175. package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
  176. package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
  177. package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
  178. package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
  179. package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
  180. package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
  181. package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
  182. package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
  183. package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
  184. package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
  185. package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
  186. package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
  187. package/corpus/templates/design/package.json +2 -0
  188. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
  189. package/corpus/templates/design/shared/canvas-math.ts +612 -206
  190. package/corpus/templates/design/shared/pen-path.ts +37 -0
  191. package/corpus/templates/design/vitest.config.ts +7 -1
  192. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
  193. package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
  194. package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
  195. package/corpus/templates/dispatch/app/routes.ts +3 -1
  196. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
  197. package/corpus/templates/factory/.env.example +2 -7
  198. package/corpus/templates/factory/AGENTS.md +3 -0
  199. package/corpus/templates/factory/README.md +5 -3
  200. package/corpus/templates/factory/actions/create-factory.ts +16 -3
  201. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
  202. package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
  203. package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
  204. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  205. package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
  206. package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
  207. package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
  208. package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
  209. package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
  210. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
  211. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
  212. package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
  213. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
  214. package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
  215. package/corpus/templates/factory/app/routes/factory.tsx +84 -11
  216. package/corpus/templates/factory/app/routes.ts +3 -1
  217. package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
  218. package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
  219. package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
  220. package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
  221. package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
  222. package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
  223. package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
  224. package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
  225. package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
  226. package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
  227. package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
  228. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
  229. package/corpus/templates/factory/vitest.config.ts +17 -2
  230. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
  231. package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
  232. package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  233. package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
  234. package/corpus/templates/forms/vitest.config.ts +1 -0
  235. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
  236. package/corpus/templates/macros/app/routes.ts +3 -1
  237. package/corpus/templates/macros/vitest.config.ts +6 -1
  238. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
  239. package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
  240. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
  241. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
  242. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
  243. package/corpus/templates/mail/app/hooks/use-emails.ts +13 -3
  244. package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
  245. package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
  246. package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
  247. package/corpus/templates/mail/app/routes/$.tsx +9 -0
  248. package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
  249. package/corpus/templates/mail/app/routes/$view.tsx +47 -1
  250. package/corpus/templates/mail/app/routes.ts +3 -1
  251. package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
  252. package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
  253. package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
  254. package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
  255. package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
  256. package/corpus/templates/mail/server/onboarding.ts +66 -18
  257. package/corpus/templates/mail/vitest.config.ts +6 -1
  258. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
  259. package/corpus/templates/plan/app/routes/settings.tsx +4 -1
  260. package/corpus/templates/plan/app/routes.ts +3 -1
  261. package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  262. package/corpus/templates/plan/netlify.toml +1 -1
  263. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
  264. package/corpus/templates/slides/actions/patch-deck.ts +79 -10
  265. package/corpus/templates/slides/actions/update-slide.ts +11 -1
  266. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
  267. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
  268. package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
  269. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
  270. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
  271. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
  272. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
  273. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
  274. package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
  275. package/corpus/templates/slides/app/routes.ts +3 -1
  276. package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
  277. package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
  278. package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
  279. package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
  280. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
  281. package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
  282. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
  283. package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
  284. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
  285. package/corpus/templates/slides/tsconfig.json +5 -0
  286. package/corpus/templates/slides/vitest.config.ts +6 -1
  287. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
  288. package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
  289. package/corpus/templates/tasks/app/routes.ts +3 -1
  290. package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  291. package/corpus/templates/tasks/vitest.config.ts +7 -1
  292. package/dist/action.d.ts +91 -0
  293. package/dist/action.js +50 -0
  294. package/dist/agent/abort-reasons.d.ts +38 -0
  295. package/dist/agent/abort-reasons.js +49 -0
  296. package/dist/agent/engine/ai-sdk-engine.js +8 -5
  297. package/dist/agent/engine/anthropic-engine.js +7 -5
  298. package/dist/agent/engine/credential-errors.d.ts +1 -1
  299. package/dist/agent/engine/credential-errors.js +2 -2
  300. package/dist/agent/engine/first-event-timeout.d.ts +42 -17
  301. package/dist/agent/engine/first-event-timeout.js +67 -25
  302. package/dist/agent/production-agent.d.ts +23 -0
  303. package/dist/agent/production-agent.js +107 -102
  304. package/dist/agent/run-loop-with-resume.d.ts +2 -28
  305. package/dist/agent/run-loop-with-resume.js +25 -40
  306. package/dist/agent/run-manager.js +5 -4
  307. package/dist/agent/run-store.d.ts +55 -0
  308. package/dist/agent/run-store.js +124 -1
  309. package/dist/agent/tool-search.js +2 -1
  310. package/dist/agent/types.d.ts +9 -4
  311. package/dist/app-config/configuration-error.d.ts +11 -0
  312. package/dist/app-config/configuration-error.js +14 -0
  313. package/dist/app-config/index.d.ts +1 -0
  314. package/dist/app-config/index.js +1 -0
  315. package/dist/app-config/integrations.d.ts +1 -0
  316. package/dist/app-config/integrations.js +10 -0
  317. package/dist/app-config/plugins.d.ts +34 -0
  318. package/dist/app-config/plugins.js +39 -0
  319. package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
  320. package/dist/app-config/run-lifecycle-invariants.js +18 -25
  321. package/dist/app-config/schema.d.ts +16 -0
  322. package/dist/app-config/schema.js +2 -0
  323. package/dist/chat-threads/schema-migrations.js +20 -0
  324. package/dist/chat-threads/store.js +21 -4
  325. package/dist/cli/native-dependencies.d.ts +4 -0
  326. package/dist/cli/native-dependencies.js +15 -0
  327. package/dist/client/AssistantChat.js +47 -15
  328. package/dist/client/ConnectBuilderCard.d.ts +3 -1
  329. package/dist/client/ConnectBuilderCard.js +6 -3
  330. package/dist/client/EnvironmentBadge.d.ts +1 -1
  331. package/dist/client/EnvironmentBadge.js +40 -5
  332. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  333. package/dist/client/MultiTabAssistantChat.js +35 -14
  334. package/dist/client/agent-chat/index.d.ts +1 -1
  335. package/dist/client/agent-chat/index.js +1 -1
  336. package/dist/client/agent-page/use-jobs.d.ts +2 -1
  337. package/dist/client/agent-page/use-jobs.js +3 -5
  338. package/dist/client/agent-sidebar-state.js +3 -1
  339. package/dist/client/blocks/library/code-tabs.js +5 -0
  340. package/dist/client/blocks/library/code.js +1 -0
  341. package/dist/client/chat/message-components.d.ts +7 -0
  342. package/dist/client/chat/message-components.js +1 -1
  343. package/dist/client/chat/run-recovery.js +5 -2
  344. package/dist/client/chat/tool-call-display.js +9 -3
  345. package/dist/client/chat-first/apps-rail.js +2 -2
  346. package/dist/client/chat-model-groups.d.ts +12 -0
  347. package/dist/client/chat-model-groups.js +3 -2
  348. package/dist/client/error-format.js +12 -0
  349. package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
  350. package/dist/client/integrations/GoogleProductLogo.js +45 -0
  351. package/dist/client/integrations/index.d.ts +2 -0
  352. package/dist/client/integrations/index.js +2 -0
  353. package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
  354. package/dist/client/integrations/workspace-provider-oauth.js +13 -0
  355. package/dist/client/navigation/index.d.ts +1 -0
  356. package/dist/client/navigation/index.js +1 -0
  357. package/dist/client/resources/mcp-integration-catalog.js +0 -29
  358. package/dist/client/route-state.js +6 -0
  359. package/dist/client/settings/SettingsTabsPage.js +10 -6
  360. package/dist/client/sharing/ShareButton.js +11 -2
  361. package/dist/client/use-chat-models.d.ts +6 -0
  362. package/dist/client/use-chat-models.js +10 -0
  363. package/dist/client/use-db-sync.js +27 -9
  364. package/dist/client/workspace-app-navigation.d.ts +10 -0
  365. package/dist/client/workspace-app-navigation.js +38 -0
  366. package/dist/collab/struct-routes.d.ts +1 -1
  367. package/dist/connections/catalog.d.ts +111 -9
  368. package/dist/connections/catalog.js +86 -30
  369. package/dist/db/create-get-db.js +18 -0
  370. package/dist/db/ddl-guard.d.ts +0 -4
  371. package/dist/db/ddl-guard.js +46 -0
  372. package/dist/deploy/build.d.ts +32 -0
  373. package/dist/deploy/build.js +241 -16
  374. package/dist/deploy/function-bundle.d.ts +45 -0
  375. package/dist/deploy/function-bundle.js +337 -0
  376. package/dist/deploy/workspace-deploy.js +19 -1
  377. package/dist/eject/workspace-connections.js +4 -0
  378. package/dist/email-catalog/registry.d.ts +4 -0
  379. package/dist/email-catalog/registry.js +79 -14
  380. package/dist/extensions/content-patch.js +14 -2
  381. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  382. package/dist/integrations/plugin.d.ts +10 -0
  383. package/dist/integrations/plugin.js +40 -6
  384. package/dist/jobs/actions/run-automation-now.d.ts +2 -1
  385. package/dist/jobs/actions/run-automation-now.js +11 -5
  386. package/dist/jobs/frontmatter.js +53 -2
  387. package/dist/jobs/run-now.d.ts +11 -1
  388. package/dist/jobs/run-now.js +42 -7
  389. package/dist/jobs/scheduler.d.ts +1 -0
  390. package/dist/jobs/scheduler.js +2 -1
  391. package/dist/localization/core-messages/ar-SA.js +4 -1
  392. package/dist/localization/core-messages/de-DE.js +4 -1
  393. package/dist/localization/core-messages/en-US.d.ts +4 -1
  394. package/dist/localization/core-messages/en-US.js +4 -1
  395. package/dist/localization/core-messages/es-ES.js +4 -1
  396. package/dist/localization/core-messages/fr-FR.js +4 -1
  397. package/dist/localization/core-messages/hi-IN.js +4 -1
  398. package/dist/localization/core-messages/ja-JP.js +4 -1
  399. package/dist/localization/core-messages/ko-KR.js +4 -1
  400. package/dist/localization/core-messages/pt-BR.js +4 -1
  401. package/dist/localization/core-messages/zh-CN.js +4 -1
  402. package/dist/localization/core-messages/zh-TW.js +4 -1
  403. package/dist/localization/core-messages.d.ts +4 -1
  404. package/dist/localization/default-messages.d.ts +2 -5
  405. package/dist/localization/default-messages.js +2 -5
  406. package/dist/mcp/build-server.d.ts +9 -0
  407. package/dist/mcp/build-server.js +37 -8
  408. package/dist/mcp-client/oauth-client.d.ts +7 -0
  409. package/dist/mcp-client/oauth-client.js +12 -1
  410. package/dist/notifications/routes.d.ts +1 -1
  411. package/dist/oauth-tokens/index.d.ts +1 -1
  412. package/dist/oauth-tokens/index.js +1 -1
  413. package/dist/oauth-tokens/lifecycle.d.ts +11 -0
  414. package/dist/oauth-tokens/lifecycle.js +17 -0
  415. package/dist/oauth-tokens/store.js +7 -0
  416. package/dist/observability/posthog-ai.d.ts +15 -1
  417. package/dist/observability/posthog-ai.js +24 -12
  418. package/dist/observability/traces.js +158 -28
  419. package/dist/onboarding/app-profile.js +2 -2
  420. package/dist/onboarding/plugin.js +10 -2
  421. package/dist/onboarding/types.d.ts +2 -0
  422. package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
  423. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  424. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  425. package/dist/provider-api/index.js +2 -0
  426. package/dist/resources/handlers.d.ts +1 -1
  427. package/dist/resources/store.js +13 -4
  428. package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
  429. package/dist/scripts/db/check-scoping.js +9 -6
  430. package/dist/secrets/register-framework-secrets.js +1 -1
  431. package/dist/secrets/routes.d.ts +6 -6
  432. package/dist/server/action-discovery.js +5 -0
  433. package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
  434. package/dist/server/agent-chat/action-filters-a2a.js +48 -9
  435. package/dist/server/agent-chat-plugin.js +36 -9
  436. package/dist/server/agent-discovery.js +43 -20
  437. package/dist/server/auth.js +18 -16
  438. package/dist/server/beta-opt-out-html.js +45 -4
  439. package/dist/server/better-auth-instance.d.ts +2 -1
  440. package/dist/server/better-auth-instance.js +23 -7
  441. package/dist/server/builder-browser.d.ts +4 -0
  442. package/dist/server/builder-browser.js +23 -1
  443. package/dist/server/builder-design-systems.d.ts +4 -1
  444. package/dist/server/builder-design-systems.js +87 -6
  445. package/dist/server/builder-oauth.d.ts +1 -7
  446. package/dist/server/builder-oauth.js +80 -163
  447. package/dist/server/core-routes-plugin.d.ts +29 -0
  448. package/dist/server/core-routes-plugin.js +113 -21
  449. package/dist/server/default-plugins.d.ts +18 -0
  450. package/dist/server/default-plugins.js +22 -0
  451. package/dist/server/edge.d.ts +1 -0
  452. package/dist/server/edge.js +1 -0
  453. package/dist/server/framework-request-handler.js +31 -3
  454. package/dist/server/google-oauth.d.ts +3 -0
  455. package/dist/server/google-oauth.js +3 -0
  456. package/dist/server/index.d.ts +4 -4
  457. package/dist/server/index.js +3 -3
  458. package/dist/server/onboarding-html.js +37 -3
  459. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  460. package/dist/server/workspace-provider-oauth.js +72 -20
  461. package/dist/shared/agent-sidebar-url.d.ts +1 -0
  462. package/dist/shared/agent-sidebar-url.js +1 -0
  463. package/dist/shared/environment-lanes.d.ts +2 -0
  464. package/dist/shared/environment-lanes.js +3 -1
  465. package/dist/shared/index.d.ts +3 -1
  466. package/dist/shared/index.js +3 -1
  467. package/dist/shared/surface-visibility.d.ts +31 -0
  468. package/dist/shared/surface-visibility.js +57 -0
  469. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  470. package/dist/templates/chat/app/routes.ts +3 -1
  471. package/dist/templates/chat/vitest.config.ts +8 -0
  472. package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  473. package/dist/templates/default/app/routes.ts +3 -1
  474. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  475. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  476. package/dist/tracking/registry.d.ts +11 -0
  477. package/dist/tracking/registry.js +5 -2
  478. package/dist/triggers/actions.js +10 -3
  479. package/dist/usage/store.js +23 -3
  480. package/dist/user-profile/actions/get-auth-methods.js +18 -5
  481. package/dist/vite/client.js +24 -5
  482. package/docs/content/actions-access-control.mdx +43 -4
  483. package/docs/content/actions-defining.mdx +16 -0
  484. package/docs/content/template-clips-capture-everywhere.mdx +29 -30
  485. package/docs/content/template-clips-developers.mdx +4 -4
  486. package/docs/content/template-clips.mdx +3 -1
  487. package/package.json +3 -3
  488. package/src/eject/workspace-connections.ts +4 -0
  489. package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  490. package/src/templates/chat/app/routes.ts +3 -1
  491. package/src/templates/chat/vitest.config.ts +8 -0
  492. package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  493. package/src/templates/default/app/routes.ts +3 -1
  494. package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  495. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  496. /package/corpus/templates/dispatch/app/routes/{apps.$appId.tsx → apps.$appId.$.tsx} +0 -0
@@ -584,7 +584,38 @@ export const editorChromeBridgeScript: string = `"use strict";
584
584
  }
585
585
  renderRuntimeInteractionStatePreviews();
586
586
  }
587
- var lastSourceHeadHtml = null;
587
+ var lastSourceHeadHtml = typeof __INITIAL_SOURCE_HEAD__ === "string" ? __INITIAL_SOURCE_HEAD__ || null : null;
588
+ function headNodeSignature(node) {
589
+ var tag = node.tagName.toLowerCase();
590
+ if (tag === "title" || tag === "base") return tag;
591
+ if (tag === "style") {
592
+ var attrs = node.attributes;
593
+ for (var i = 0; i < attrs.length; i += 1) {
594
+ var name = attrs[i].name;
595
+ if (name.indexOf("data-agent-native-") === 0) return "style:" + name;
596
+ }
597
+ return "";
598
+ }
599
+ if (tag === "meta") {
600
+ var meta = ["name", "property", "http-equiv", "charset"];
601
+ for (var m = 0; m < meta.length; m += 1) {
602
+ if (node.hasAttribute(meta[m])) {
603
+ return "meta:" + meta[m] + "=" + node.getAttribute(meta[m]);
604
+ }
605
+ }
606
+ return "";
607
+ }
608
+ return "";
609
+ }
610
+ function findHeadNodeBySignature(signature) {
611
+ var children = document.head ? document.head.children : null;
612
+ if (!children) return null;
613
+ for (var i = 0; i < children.length; i += 1) {
614
+ var candidate = children[i];
615
+ if (headNodeSignature(candidate) === signature) return candidate;
616
+ }
617
+ return null;
618
+ }
588
619
  function replaceSourceHeadNodes(previousSourceHtml, nextSourceHtml) {
589
620
  if (!document.head) return;
590
621
  var stale = document.createElement("head");
@@ -594,6 +625,12 @@ export const editorChromeBridgeScript: string = `"use strict";
594
625
  var key = node.outerHTML;
595
626
  staleCounts[key] = (staleCounts[key] || 0) + 1;
596
627
  });
628
+ var retained = document.createElement("head");
629
+ retained.innerHTML = nextSourceHtml || "";
630
+ Array.prototype.forEach.call(retained.children, function(node) {
631
+ var key = node.outerHTML;
632
+ if (staleCounts[key]) staleCounts[key] -= 1;
633
+ });
597
634
  Array.prototype.slice.call(document.head.children).forEach(function(node) {
598
635
  var key = node.outerHTML;
599
636
  if (!staleCounts[key]) return;
@@ -602,8 +639,29 @@ export const editorChromeBridgeScript: string = `"use strict";
602
639
  });
603
640
  var next = document.createElement("head");
604
641
  next.innerHTML = nextSourceHtml || "";
642
+ var present = {};
643
+ Array.prototype.forEach.call(
644
+ document.head.children,
645
+ function(node) {
646
+ var key = node.outerHTML;
647
+ present[key] = (present[key] || 0) + 1;
648
+ }
649
+ );
605
650
  var anchor = document.head.firstChild;
606
651
  Array.prototype.slice.call(next.children).forEach(function(node) {
652
+ var key = node.outerHTML;
653
+ if (present[key]) {
654
+ present[key] -= 1;
655
+ return;
656
+ }
657
+ var signature = previousSourceHtml === null ? headNodeSignature(node) : "";
658
+ if (signature) {
659
+ var existing = findHeadNodeBySignature(signature);
660
+ if (existing) {
661
+ document.head.replaceChild(document.importNode(node, true), existing);
662
+ return;
663
+ }
664
+ }
607
665
  document.head.insertBefore(document.importNode(node, true), anchor);
608
666
  });
609
667
  }
@@ -2117,6 +2175,17 @@ export const editorChromeBridgeScript: string = `"use strict";
2117
2175
  spacingBadge.setAttribute("data-agent-native-edit-overlay", "spacing-badge");
2118
2176
  spacingBadge.style.cssText = "position:fixed;z-index:100000;display:none;pointer-events:none;border-radius:3px;color:white;font:10px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:700;padding:2px 4px;box-shadow:0 4px 14px rgba(0,0,0,0.18);";
2119
2177
  document.body.appendChild(spacingBadge);
2178
+ var constraintGuideLayer = document.createElement("div");
2179
+ constraintGuideLayer.setAttribute(
2180
+ "data-agent-native-edit-overlay",
2181
+ "constraint-guide"
2182
+ );
2183
+ constraintGuideLayer.style.cssText = "position:fixed;inset:0;z-index:99999;display:none;pointer-events:none;";
2184
+ document.body.appendChild(constraintGuideLayer);
2185
+ var sizeBadge = document.createElement("div");
2186
+ sizeBadge.setAttribute("data-agent-native-edit-overlay", "size-badge");
2187
+ sizeBadge.style.cssText = "position:fixed;z-index:100000;display:none;pointer-events:none;border-radius:3px;background:var(--design-editor-accent-color);color:var(--design-editor-accent-contrast-color);font:10px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;padding:2px 4px;white-space:nowrap;";
2188
+ document.body.appendChild(sizeBadge);
2120
2189
  var insertionGuide = document.createElement("div");
2121
2190
  insertionGuide.setAttribute("data-agent-native-insertion-guide", "");
2122
2191
  insertionGuide.setAttribute(
@@ -2125,14 +2194,10 @@ export const editorChromeBridgeScript: string = `"use strict";
2125
2194
  );
2126
2195
  insertionGuide.style.cssText = "position:fixed;z-index:100000;display:none;pointer-events:none;background:var(--design-editor-accent-color);border-radius:999px;box-shadow:0 0 0 1px var(--design-editor-accent-color);";
2127
2196
  document.body.appendChild(insertionGuide);
2128
- var snapGuideV = document.createElement("div");
2129
- snapGuideV.setAttribute("data-agent-native-edit-overlay", "snap-guide");
2130
- snapGuideV.style.cssText = "position:fixed;z-index:100000;display:none;pointer-events:none;width:1px;background:hsl(var(--destructive) / 0.9);";
2131
- document.body.appendChild(snapGuideV);
2132
- var snapGuideH = document.createElement("div");
2133
- snapGuideH.setAttribute("data-agent-native-edit-overlay", "snap-guide");
2134
- snapGuideH.style.cssText = "position:fixed;z-index:100000;display:none;pointer-events:none;height:1px;background:hsl(var(--destructive) / 0.9);";
2135
- document.body.appendChild(snapGuideH);
2197
+ var snapGuideLayer = document.createElement("div");
2198
+ snapGuideLayer.setAttribute("data-agent-native-edit-overlay", "snap-guide");
2199
+ snapGuideLayer.style.cssText = "position:fixed;inset:0;z-index:100000;display:none;pointer-events:none;";
2200
+ document.body.appendChild(snapGuideLayer);
2136
2201
  var measurementOverlay = document.createElement("div");
2137
2202
  measurementOverlay.setAttribute("data-agent-native-measurement-overlay", "");
2138
2203
  measurementOverlay.setAttribute(
@@ -2274,6 +2339,7 @@ export const editorChromeBridgeScript: string = `"use strict";
2274
2339
  }
2275
2340
  function hideSelectionOverlay() {
2276
2341
  selectionOverlay.style.display = "none";
2342
+ hideSizeBadge();
2277
2343
  hideSpacingOverlay();
2278
2344
  hideParentAutoLayoutOverlay();
2279
2345
  clearComponentTag();
@@ -2404,7 +2470,7 @@ export const editorChromeBridgeScript: string = `"use strict";
2404
2470
  "multi-selection-handle"
2405
2471
  );
2406
2472
  handle.setAttribute("data-corner", pos);
2407
- handle.style.cssText = "position:absolute;z-index:1;width:7px;height:7px;border:1px solid var(--design-editor-accent-color);background:var(--design-editor-accent-contrast-color);box-sizing:border-box;border-radius:1px;pointer-events:none;";
2473
+ handle.style.cssText = "position:absolute;z-index:1;width:7px;height:7px;border:1px solid var(--design-editor-accent-color);background:var(--design-editor-accent-contrast-color);box-sizing:border-box;border-radius:1px;pointer-events:auto;cursor:" + (pos === "nw" || pos === "se" ? "nwse-resize" : "nesw-resize") + ";";
2408
2474
  if (pos.indexOf("n") !== -1) handle.style.top = "-4px";
2409
2475
  if (pos.indexOf("s") !== -1) handle.style.bottom = "-4px";
2410
2476
  if (pos.indexOf("w") !== -1) handle.style.left = "-4px";
@@ -2433,6 +2499,7 @@ export const editorChromeBridgeScript: string = `"use strict";
2433
2499
  "[data-agent-native-edit-overlay='multi-selection-handle']"
2434
2500
  ).forEach(function(handle) {
2435
2501
  var pos = handle.getAttribute("data-corner") || "";
2502
+ handle.style.pointerEvents = readOnly ? "none" : "auto";
2436
2503
  handle.style.width = 7 * sx + "px";
2437
2504
  handle.style.height = 7 * sy + "px";
2438
2505
  handle.style.borderWidth = 1 * line + "px";
@@ -2527,6 +2594,320 @@ export const editorChromeBridgeScript: string = `"use strict";
2527
2594
  }
2528
2595
  });
2529
2596
  }
2597
+ function sourceMetaFor(element) {
2598
+ return element.__anSourceMeta;
2599
+ }
2600
+ function isSourceOwned(node) {
2601
+ return node.__anSource === true;
2602
+ }
2603
+ function recordSourceOwnership(node) {
2604
+ node.__anSource = true;
2605
+ if (node.nodeType !== 1) return;
2606
+ var element = node;
2607
+ var names = [];
2608
+ for (var i = 0; i < element.attributes.length; i += 1) {
2609
+ names.push(element.attributes[i].name);
2610
+ }
2611
+ element.__anSourceMeta = {
2612
+ attrs: names,
2613
+ className: element.getAttribute("class") ?? "",
2614
+ style: element.getAttribute("style") ?? ""
2615
+ };
2616
+ }
2617
+ function recordSourceSubtree(root) {
2618
+ if (root.nodeType === 1 && root.hasAttribute("data-agent-native-edit-overlay")) {
2619
+ return;
2620
+ }
2621
+ recordSourceOwnership(root);
2622
+ if (root.nodeType !== 1) return;
2623
+ var template = templateContentOf(root);
2624
+ if (template) {
2625
+ var held = template.childNodes;
2626
+ for (var t = 0; t < held.length; t += 1) recordSourceSubtree(held[t]);
2627
+ return;
2628
+ }
2629
+ var children = root.childNodes;
2630
+ for (var i = 0; i < children.length; i += 1) {
2631
+ recordSourceSubtree(children[i]);
2632
+ }
2633
+ }
2634
+ function templateContentOf(element) {
2635
+ if (element.nodeName !== "TEMPLATE") return null;
2636
+ return element.content ?? null;
2637
+ }
2638
+ function scopedMorphContext(liveRoot, nextRoot) {
2639
+ var keyed = /* @__PURE__ */ new Map();
2640
+ liveRoot.querySelectorAll("[data-agent-native-node-id]").forEach(function(element) {
2641
+ if (!isSourceOwned(element)) return;
2642
+ var key = element.getAttribute("data-agent-native-node-id");
2643
+ if (key && !keyed.has(key)) keyed.set(key, element);
2644
+ });
2645
+ var nextKeys = /* @__PURE__ */ new Set();
2646
+ nextRoot.querySelectorAll("[data-agent-native-node-id]").forEach(function(element) {
2647
+ var key = element.getAttribute("data-agent-native-node-id");
2648
+ if (key) nextKeys.add(key);
2649
+ });
2650
+ return { keyed, nextKeys, obsolete: /* @__PURE__ */ new Set() };
2651
+ }
2652
+ function captureInitialSourceOwnership() {
2653
+ if (document.body) recordSourceSubtree(document.body);
2654
+ }
2655
+ function classTokens(value) {
2656
+ return value.split(/\\s+/).filter(function(token) {
2657
+ return token.length > 0;
2658
+ });
2659
+ }
2660
+ function applyClassAttribute(live, previousSource, nextSource) {
2661
+ var previous = classTokens(previousSource);
2662
+ var current = classTokens(live.getAttribute("class") ?? "");
2663
+ var result = classTokens(nextSource);
2664
+ for (var i = 0; i < current.length; i += 1) {
2665
+ var token = current[i];
2666
+ if (previous.indexOf(token) !== -1) continue;
2667
+ if (result.indexOf(token) === -1) result.push(token);
2668
+ }
2669
+ var value = result.join(" ");
2670
+ if ((live.getAttribute("class") ?? "") === value) return;
2671
+ if (value) live.setAttribute("class", value);
2672
+ else live.removeAttribute("class");
2673
+ }
2674
+ var styleProbe = null;
2675
+ function styleDeclarations(value) {
2676
+ var probe = styleProbe || (styleProbe = document.createElement("div"));
2677
+ probe.style.cssText = value || "";
2678
+ var out = [];
2679
+ for (var i = 0; i < probe.style.length; i += 1) {
2680
+ var property = probe.style.item(i);
2681
+ out.push([
2682
+ property,
2683
+ probe.style.getPropertyValue(property),
2684
+ probe.style.getPropertyPriority(property)
2685
+ ]);
2686
+ }
2687
+ return out;
2688
+ }
2689
+ function applyStyleAttribute(live, previousSource, nextSource) {
2690
+ var previousOwned = {};
2691
+ styleDeclarations(previousSource).forEach(function(entry) {
2692
+ previousOwned[entry[0]] = entry[1];
2693
+ });
2694
+ var nextOwned = {};
2695
+ styleDeclarations(nextSource).forEach(function(entry) {
2696
+ nextOwned[entry[0]] = true;
2697
+ });
2698
+ var target = document.createElement("div");
2699
+ target.style.cssText = nextSource || "";
2700
+ styleDeclarations(live.getAttribute("style") ?? "").forEach(
2701
+ function(entry) {
2702
+ if (nextOwned[entry[0]]) return;
2703
+ var wasSource = Object.prototype.hasOwnProperty.call(
2704
+ previousOwned,
2705
+ entry[0]
2706
+ );
2707
+ if (wasSource && previousOwned[entry[0]] === entry[1]) return;
2708
+ target.style.setProperty(entry[0], entry[1], entry[2]);
2709
+ }
2710
+ );
2711
+ var value = target.style.cssText;
2712
+ if ((live.getAttribute("style") ?? "") === value) return;
2713
+ if (value) live.setAttribute("style", value);
2714
+ else live.removeAttribute("style");
2715
+ }
2716
+ function morphFormState(live, next) {
2717
+ if (live.nodeName === "INPUT") {
2718
+ var input = live;
2719
+ var nextChecked = next.hasAttribute("checked");
2720
+ if (input.defaultChecked !== nextChecked) {
2721
+ input.defaultChecked = nextChecked;
2722
+ input.checked = nextChecked;
2723
+ }
2724
+ var nextValue = next.getAttribute("value");
2725
+ if (nextValue !== null && input.defaultValue !== nextValue) {
2726
+ input.defaultValue = nextValue;
2727
+ input.value = nextValue;
2728
+ }
2729
+ return;
2730
+ }
2731
+ if (live.nodeName === "TEXTAREA") {
2732
+ var area = live;
2733
+ var nextText = next.textContent ?? "";
2734
+ if (area.defaultValue !== nextText) {
2735
+ area.defaultValue = nextText;
2736
+ area.value = nextText;
2737
+ }
2738
+ return;
2739
+ }
2740
+ if (live.nodeName === "OPTION") {
2741
+ var option = live;
2742
+ var nextSelected = next.hasAttribute("selected");
2743
+ if (option.defaultSelected !== nextSelected) {
2744
+ option.defaultSelected = nextSelected;
2745
+ option.selected = nextSelected;
2746
+ }
2747
+ }
2748
+ }
2749
+ function declaresRuntimeChildren(element) {
2750
+ return element.hasAttribute("x-text") || element.hasAttribute("x-html") || element.hasAttribute("v-text") || element.hasAttribute("v-html");
2751
+ }
2752
+ function scopeDirectiveChanged(live, next) {
2753
+ return (live.getAttribute("x-data") ?? "") !== (next.getAttribute("x-data") ?? "");
2754
+ }
2755
+ function morphNodeKey(node) {
2756
+ if (node.nodeType !== 1) return null;
2757
+ return node.getAttribute("data-agent-native-node-id");
2758
+ }
2759
+ function morphAttributes(live, next) {
2760
+ var meta = sourceMetaFor(live);
2761
+ var previousAttrs = meta ? meta.attrs : [];
2762
+ var previousClass = meta ? meta.className : "";
2763
+ var previousStyle = meta ? meta.style : "";
2764
+ var nextNames = [];
2765
+ var nextAttrs = next.attributes;
2766
+ for (var i = 0; i < nextAttrs.length; i += 1) {
2767
+ var attr = nextAttrs[i];
2768
+ nextNames.push(attr.name);
2769
+ if (attr.name === "class") {
2770
+ applyClassAttribute(live, previousClass, attr.value);
2771
+ continue;
2772
+ }
2773
+ if (attr.name === "style") {
2774
+ applyStyleAttribute(live, previousStyle, attr.value);
2775
+ continue;
2776
+ }
2777
+ if (attr.name === "x-cloak" && !live.hasAttribute("x-cloak")) continue;
2778
+ if (live.getAttribute(attr.name) === attr.value) continue;
2779
+ if (attr.namespaceURI) {
2780
+ live.setAttributeNS(attr.namespaceURI, attr.name, attr.value);
2781
+ } else {
2782
+ live.setAttribute(attr.name, attr.value);
2783
+ }
2784
+ }
2785
+ for (var j = 0; j < previousAttrs.length; j += 1) {
2786
+ var name = previousAttrs[j];
2787
+ if (nextNames.indexOf(name) !== -1) continue;
2788
+ if (name === "class") {
2789
+ applyClassAttribute(live, previousClass, "");
2790
+ continue;
2791
+ }
2792
+ if (name === "style") {
2793
+ applyStyleAttribute(live, previousStyle, "");
2794
+ continue;
2795
+ }
2796
+ live.removeAttribute(name);
2797
+ }
2798
+ live.__anSourceMeta = {
2799
+ attrs: nextNames,
2800
+ className: next.getAttribute("class") ?? "",
2801
+ style: next.getAttribute("style") ?? ""
2802
+ };
2803
+ }
2804
+ function morphChildren(live, next, context) {
2805
+ var cursor = live.firstChild;
2806
+ var nextChild = next.firstChild;
2807
+ while (nextChild) {
2808
+ var key = morphNodeKey(nextChild);
2809
+ var reuse = null;
2810
+ if (key) {
2811
+ var candidate = context.keyed.get(key) ?? null;
2812
+ if (candidate && !candidate.contains(live) && candidate.nodeName === nextChild.nodeName && candidate.namespaceURI === nextChild.namespaceURI) {
2813
+ reuse = candidate;
2814
+ context.keyed.delete(key);
2815
+ } else if (candidate) {
2816
+ context.obsolete.add(key);
2817
+ }
2818
+ } else {
2819
+ var probe = cursor;
2820
+ while (probe) {
2821
+ var probeKey = morphNodeKey(probe);
2822
+ if (probeKey) {
2823
+ if (context.nextKeys.has(probeKey) && !context.obsolete.has(probeKey)) {
2824
+ break;
2825
+ }
2826
+ probe = probe.nextSibling;
2827
+ continue;
2828
+ }
2829
+ if (!isSourceOwned(probe)) {
2830
+ probe = probe.nextSibling;
2831
+ continue;
2832
+ }
2833
+ if (probe.nodeType === nextChild.nodeType && probe.nodeName === nextChild.nodeName) {
2834
+ reuse = probe;
2835
+ }
2836
+ break;
2837
+ }
2838
+ }
2839
+ if (reuse && reuse.nodeType === 1 && scopeDirectiveChanged(reuse, nextChild)) {
2840
+ var rebuilt = document.importNode(nextChild, true);
2841
+ live.insertBefore(rebuilt, cursor);
2842
+ if (reuse.parentNode) reuse.parentNode.removeChild(reuse);
2843
+ recordSourceSubtree(rebuilt);
2844
+ cursor = rebuilt.nextSibling;
2845
+ nextChild = nextChild.nextSibling;
2846
+ continue;
2847
+ }
2848
+ if (reuse) {
2849
+ if (reuse !== cursor) live.insertBefore(reuse, cursor);
2850
+ if (reuse.nodeType === 1) {
2851
+ morphElement(reuse, nextChild, context);
2852
+ } else if (reuse.nodeValue !== nextChild.nodeValue) {
2853
+ reuse.nodeValue = nextChild.nodeValue;
2854
+ }
2855
+ cursor = reuse.nextSibling;
2856
+ } else if (nextChild.nodeType === 1) {
2857
+ var shell = document.importNode(nextChild, false);
2858
+ live.insertBefore(shell, cursor);
2859
+ recordSourceOwnership(shell);
2860
+ morphElement(shell, nextChild, context);
2861
+ cursor = shell.nextSibling;
2862
+ } else {
2863
+ var imported = document.importNode(nextChild, true);
2864
+ live.insertBefore(imported, cursor);
2865
+ recordSourceSubtree(imported);
2866
+ }
2867
+ nextChild = nextChild.nextSibling;
2868
+ }
2869
+ while (cursor) {
2870
+ var stale = cursor;
2871
+ cursor = cursor.nextSibling;
2872
+ if (stale.parentNode !== live) continue;
2873
+ if (!isSourceOwned(stale)) continue;
2874
+ live.removeChild(stale);
2875
+ }
2876
+ }
2877
+ function morphElement(live, next, context) {
2878
+ morphFormState(live, next);
2879
+ morphAttributes(live, next);
2880
+ if (declaresRuntimeChildren(next) || declaresRuntimeChildren(live)) return;
2881
+ var liveTemplate = templateContentOf(live);
2882
+ var nextTemplate = templateContentOf(next);
2883
+ if (liveTemplate && nextTemplate) {
2884
+ morphChildren(
2885
+ liveTemplate,
2886
+ nextTemplate,
2887
+ scopedMorphContext(liveTemplate, nextTemplate)
2888
+ );
2889
+ return;
2890
+ }
2891
+ morphChildren(live, next, context);
2892
+ }
2893
+ function morphRuntimeBody(nextBody) {
2894
+ var keyed = /* @__PURE__ */ new Map();
2895
+ document.querySelectorAll("[data-agent-native-node-id]").forEach(function(element) {
2896
+ if (!isSourceOwned(element)) return;
2897
+ var key = element.getAttribute("data-agent-native-node-id");
2898
+ if (key && !keyed.has(key)) keyed.set(key, element);
2899
+ });
2900
+ var nextKeys = /* @__PURE__ */ new Set();
2901
+ nextBody.querySelectorAll("[data-agent-native-node-id]").forEach(function(element) {
2902
+ var key = element.getAttribute("data-agent-native-node-id");
2903
+ if (key) nextKeys.add(key);
2904
+ });
2905
+ morphElement(document.body, nextBody, {
2906
+ keyed,
2907
+ nextKeys,
2908
+ obsolete: /* @__PURE__ */ new Set()
2909
+ });
2910
+ }
2530
2911
  function replaceRuntimeDocument(html, preferredSelector, selectorCandidates, forceFullDocument, preserveTextEditingSession) {
2531
2912
  if (typeof html !== "string") return;
2532
2913
  exitStaleTextEditSession();
@@ -2571,6 +2952,7 @@ export const editorChromeBridgeScript: string = `"use strict";
2571
2952
  var nextHeadHtml = nextDoc.head ? nextDoc.head.innerHTML : "";
2572
2953
  ensureEditorChromeStyle();
2573
2954
  if (lastSourceHeadHtml === null) {
2955
+ replaceSourceHeadNodes(null, nextHeadHtml);
2574
2956
  lastSourceHeadHtml = nextHeadHtml;
2575
2957
  }
2576
2958
  var currentHeadHtml = lastSourceHeadHtml;
@@ -2639,13 +3021,10 @@ export const editorChromeBridgeScript: string = `"use strict";
2639
3021
  ensureEditorChromeStyle();
2640
3022
  lastSourceHeadHtml = nextHeadHtml;
2641
3023
  }
2642
- Array.prototype.slice.call(document.body.attributes).forEach(function(attribute) {
2643
- document.body.removeAttribute(attribute.name);
2644
- });
2645
- Array.prototype.slice.call(nextDoc.body.attributes).forEach(function(attribute) {
2646
- document.body.setAttribute(attribute.name, attribute.value);
3024
+ persistentNodes.forEach(function(node) {
3025
+ if (node.parentNode) node.parentNode.removeChild(node);
2647
3026
  });
2648
- document.body.innerHTML = nextDoc.body.innerHTML;
3027
+ morphRuntimeBody(nextDoc.body);
2649
3028
  persistentNodes.forEach(function(node) {
2650
3029
  document.body.appendChild(node);
2651
3030
  });
@@ -3428,6 +3807,16 @@ export const editorChromeBridgeScript: string = `"use strict";
3428
3807
  overlay.setAttribute("data-agent-native-multi-selection-bounds", "true");
3429
3808
  overlay.style.cssText = "position:fixed;pointer-events:none;z-index:99996;border:1.5px solid var(--design-editor-accent-color);background:transparent;display:none;box-sizing:border-box;";
3430
3809
  appendPassiveSelectionHandles(overlay);
3810
+ overlay.addEventListener(
3811
+ "mousedown",
3812
+ function(e) {
3813
+ if (readOnly) return;
3814
+ var corner = e.target && e.target.getAttribute && e.target.getAttribute("data-corner");
3815
+ if (!corner) return;
3816
+ startGroupResize(corner, e);
3817
+ },
3818
+ true
3819
+ );
3431
3820
  document.body.appendChild(overlay);
3432
3821
  multiSelectionBoundsOverlay = overlay;
3433
3822
  return overlay;
@@ -3440,6 +3829,9 @@ export const editorChromeBridgeScript: string = `"use strict";
3440
3829
  passiveSelectionEls.forEach(function(el) {
3441
3830
  if (el && document.documentElement.contains(el)) members.push(el);
3442
3831
  });
3832
+ setSelectionOverlayResizeChromeVisible(
3833
+ !readOnly && !activeTextEditEl && members.length < 2
3834
+ );
3443
3835
  if (members.length < 2 || selectionChromeHidden) {
3444
3836
  if (multiSelectionBoundsOverlay) {
3445
3837
  multiSelectionBoundsOverlay.style.display = "none";
@@ -3504,6 +3896,7 @@ export const editorChromeBridgeScript: string = `"use strict";
3504
3896
  updateSpacingOverlay(el);
3505
3897
  updateComponentTag(el, rect);
3506
3898
  updateParentAutoLayoutOverlay(el);
3899
+ showSizeBadge(el);
3507
3900
  } else {
3508
3901
  applyElementOverlayChrome(overlay, el);
3509
3902
  }
@@ -3541,6 +3934,7 @@ export const editorChromeBridgeScript: string = `"use strict";
3541
3934
  var overlay = passiveSelectionOverlays[index];
3542
3935
  if (overlay) positionOverlay(overlay, el);
3543
3936
  });
3937
+ if (passiveSelectionEls.length > 0) hideSizeBadge();
3544
3938
  positionMultiSelectionBounds();
3545
3939
  positionGradientOverlay();
3546
3940
  syncOverlayObservers();
@@ -3954,9 +4348,8 @@ export const editorChromeBridgeScript: string = `"use strict";
3954
4348
  // Cmd from Ctrl the way isPlatformPrimaryModifier does host-side, but
3955
4349
  // forwarding is harmless when the host has no match for the combo.
3956
4350
  "f",
3957
- // Cmd/Ctrl+R rename / Cmd/Ctrl+Shift+R paste-to-replace (onRename /
3958
- // onPasteToReplace) — both live under bare primary+r.
3959
- "r",
4351
+ // Cmd/Ctrl+Shift+R paste-to-replace. Bare primary+r stays native
4352
+ // so browser refresh keeps its expected meaning.
3960
4353
  // Cmd/Ctrl+K — open the host command menu even while the iframe has
3961
4354
  // focus. DesignEditor routes this chord to openCommandMenu().
3962
4355
  "k"
@@ -3965,7 +4358,7 @@ export const editorChromeBridgeScript: string = `"use strict";
3965
4358
  // Cmd+H / Cmd+L — common OS "Hide app" / browser "focus address bar"
3966
4359
  // shortcuts the host has no bare-primary binding for — are left
3967
4360
  // alone (see useDesignHotkeys.ts: both require event.shiftKey).
3968
- e.shiftKey && (normalized === "h" || normalized === "l") || // Cmd/Ctrl+Alt+B detach instance / Cmd/Ctrl+Alt+K create component
4361
+ e.shiftKey && (normalized === "h" || normalized === "l") || e.shiftKey && normalized === "r" || // Cmd/Ctrl+Alt+B detach instance / Cmd/Ctrl+Alt+K create component
3969
4362
  // (onDetachInstance / onCreateComponent). Gated on altKey so bare
3970
4363
  // Cmd+B is left alone — the host has no bare-primary binding for it.
3971
4364
  e.altKey && (normalized === "b" || normalized === "k") || // Ctrl+Alt+H / Ctrl+Alt+T — distribute horizontal / tidy up
@@ -5345,8 +5738,7 @@ export const editorChromeBridgeScript: string = `"use strict";
5345
5738
  if (cs.position === "absolute" || cs.position === "fixed") return false;
5346
5739
  return true;
5347
5740
  }
5348
- function collectMoveGroupMembers(gestureEl) {
5349
- if (!gestureEl) return [];
5741
+ function collectSelectionMembers() {
5350
5742
  var raw = [];
5351
5743
  if (selectedEl) raw.push(selectedEl);
5352
5744
  for (var i = 0; i < passiveSelectionEls.length; i += 1) {
@@ -5360,11 +5752,15 @@ export const editorChromeBridgeScript: string = `"use strict";
5360
5752
  }
5361
5753
  members.push(candidate);
5362
5754
  }
5363
- members = members.filter(function(member) {
5755
+ return members.filter(function(member) {
5364
5756
  return !members.some(function(other) {
5365
5757
  return other !== member && other.contains(member);
5366
5758
  });
5367
5759
  });
5760
+ }
5761
+ function collectMoveGroupMembers(gestureEl) {
5762
+ if (!gestureEl) return [];
5763
+ var members = collectSelectionMembers();
5368
5764
  var gestureMember = null;
5369
5765
  for (var k = 0; k < members.length; k += 1) {
5370
5766
  if (members[k] === gestureEl || members[k].contains && members[k].contains(gestureEl)) {
@@ -6365,84 +6761,584 @@ export const editorChromeBridgeScript: string = `"use strict";
6365
6761
  }
6366
6762
  return rects;
6367
6763
  }
6368
- function computeMoveSnapOffset(movingRect, candidates, threshold) {
6369
- var moving = rectBounds(movingRect);
6370
- var bestX = null;
6371
- var bestY = null;
6764
+ var SNAP_ALIGN_EPSILON = 1e-6;
6765
+ var SPACING_MATCH_EPSILON = 0.5;
6766
+ var PROXIMITY_RANGE_PX = 160;
6767
+ function axisSnapValues(bounds, axis) {
6768
+ return axis === "x" ? [bounds.left, bounds.centerX, bounds.right] : [bounds.top, bounds.centerY, bounds.bottom];
6769
+ }
6770
+ function axisStart(bounds, axis) {
6771
+ return axis === "x" ? bounds.left : bounds.top;
6772
+ }
6773
+ function axisEnd(bounds, axis) {
6774
+ return axis === "x" ? bounds.right : bounds.bottom;
6775
+ }
6776
+ function crossStart(bounds, axis) {
6777
+ return axis === "x" ? bounds.top : bounds.left;
6778
+ }
6779
+ function crossEnd(bounds, axis) {
6780
+ return axis === "x" ? bounds.bottom : bounds.right;
6781
+ }
6782
+ function crossAxisOverlaps(axis, a, b) {
6783
+ return crossStart(a, axis) < crossEnd(b, axis) && crossEnd(a, axis) > crossStart(b, axis);
6784
+ }
6785
+ function translateRectBounds(bounds, dx, dy) {
6786
+ return {
6787
+ left: bounds.left + dx,
6788
+ right: bounds.right + dx,
6789
+ centerX: bounds.centerX + dx,
6790
+ top: bounds.top + dy,
6791
+ bottom: bounds.bottom + dy,
6792
+ centerY: bounds.centerY + dy
6793
+ };
6794
+ }
6795
+ function findAxisSnapOffset(axis, moving, candidates, threshold) {
6796
+ var offset = null;
6797
+ var bestDistance = Infinity;
6798
+ var movingValues = axisSnapValues(moving, axis);
6799
+ for (var i = 0; i < candidates.length; i += 1) {
6800
+ var targets = axisSnapValues(candidates[i], axis);
6801
+ for (var mi = 0; mi < movingValues.length; mi += 1) {
6802
+ for (var ti = 0; ti < targets.length; ti += 1) {
6803
+ var candidate = targets[ti] - movingValues[mi];
6804
+ var distance = Math.abs(candidate);
6805
+ if (distance > threshold || distance >= bestDistance) continue;
6806
+ bestDistance = distance;
6807
+ offset = candidate;
6808
+ }
6809
+ }
6810
+ }
6811
+ return offset;
6812
+ }
6813
+ function buildAxisGuides(axis, moving, candidates) {
6814
+ var positions = [];
6815
+ var spans = [];
6816
+ var movingValues = axisSnapValues(moving, axis);
6372
6817
  for (var i = 0; i < candidates.length; i += 1) {
6373
6818
  var candidate = candidates[i];
6374
- var xValues = [moving.left, moving.centerX, moving.right];
6375
- var xTargets = [candidate.left, candidate.centerX, candidate.right];
6376
- for (var xi = 0; xi < xValues.length; xi += 1) {
6377
- for (var xj = 0; xj < xTargets.length; xj += 1) {
6378
- var offsetX = xTargets[xj] - xValues[xi];
6379
- var distanceX = Math.abs(offsetX);
6380
- if (distanceX > threshold) continue;
6381
- if (!bestX || distanceX < bestX.distance) {
6382
- bestX = {
6383
- distance: distanceX,
6384
- offset: offsetX,
6385
- guide: {
6386
- position: xTargets[xj],
6387
- start: Math.min(moving.top, candidate.top),
6388
- end: Math.max(moving.bottom, candidate.bottom)
6389
- }
6390
- };
6819
+ var targets = axisSnapValues(candidate, axis);
6820
+ for (var mi = 0; mi < movingValues.length; mi += 1) {
6821
+ for (var ti = 0; ti < targets.length; ti += 1) {
6822
+ if (Math.abs(targets[ti] - movingValues[mi]) > SNAP_ALIGN_EPSILON) {
6823
+ continue;
6824
+ }
6825
+ var slot = positions.indexOf(targets[ti]);
6826
+ if (slot === -1) {
6827
+ positions.push(targets[ti]);
6828
+ spans.push({
6829
+ start: Math.min(
6830
+ crossStart(moving, axis),
6831
+ crossStart(candidate, axis)
6832
+ ),
6833
+ end: Math.max(crossEnd(moving, axis), crossEnd(candidate, axis))
6834
+ });
6835
+ } else {
6836
+ spans[slot].start = Math.min(
6837
+ spans[slot].start,
6838
+ crossStart(candidate, axis)
6839
+ );
6840
+ spans[slot].end = Math.max(
6841
+ spans[slot].end,
6842
+ crossEnd(candidate, axis)
6843
+ );
6391
6844
  }
6392
6845
  }
6393
6846
  }
6394
- var yValues = [moving.top, moving.centerY, moving.bottom];
6395
- var yTargets = [candidate.top, candidate.centerY, candidate.bottom];
6396
- for (var yi = 0; yi < yValues.length; yi += 1) {
6397
- for (var yj = 0; yj < yTargets.length; yj += 1) {
6398
- var offsetY = yTargets[yj] - yValues[yi];
6399
- var distanceY = Math.abs(offsetY);
6400
- if (distanceY > threshold) continue;
6401
- if (!bestY || distanceY < bestY.distance) {
6402
- bestY = {
6403
- distance: distanceY,
6404
- offset: offsetY,
6405
- guide: {
6406
- position: yTargets[yj],
6407
- start: Math.min(moving.left, candidate.left),
6408
- end: Math.max(moving.right, candidate.right)
6409
- }
6410
- };
6847
+ }
6848
+ var guides = [];
6849
+ for (var g = 0; g < positions.length; g += 1) {
6850
+ guides.push({
6851
+ orientation: axis === "x" ? "vertical" : "horizontal",
6852
+ position: positions[g],
6853
+ start: spans[g].start,
6854
+ end: spans[g].end
6855
+ });
6856
+ }
6857
+ return guides;
6858
+ }
6859
+ function collectAxisGapCandidates(axis, moving, candidates) {
6860
+ var gaps = [];
6861
+ for (var i = 0; i < candidates.length; i += 1) {
6862
+ var bounds = candidates[i];
6863
+ if (!crossAxisOverlaps(axis, bounds, moving)) continue;
6864
+ var band = {
6865
+ crossStart: Math.max(
6866
+ crossStart(bounds, axis),
6867
+ crossStart(moving, axis)
6868
+ ),
6869
+ crossEnd: Math.min(crossEnd(bounds, axis), crossEnd(moving, axis))
6870
+ };
6871
+ if (axisEnd(bounds, axis) <= axisStart(moving, axis)) {
6872
+ gaps.push({
6873
+ side: "before",
6874
+ gap: axisStart(moving, axis) - axisEnd(bounds, axis),
6875
+ gapStart: axisEnd(bounds, axis),
6876
+ gapEnd: axisStart(moving, axis),
6877
+ crossStart: band.crossStart,
6878
+ crossEnd: band.crossEnd
6879
+ });
6880
+ } else if (axisStart(bounds, axis) >= axisEnd(moving, axis)) {
6881
+ gaps.push({
6882
+ side: "after",
6883
+ gap: axisStart(bounds, axis) - axisEnd(moving, axis),
6884
+ gapStart: axisEnd(moving, axis),
6885
+ gapEnd: axisStart(bounds, axis),
6886
+ crossStart: band.crossStart,
6887
+ crossEnd: band.crossEnd
6888
+ });
6889
+ }
6890
+ }
6891
+ return gaps;
6892
+ }
6893
+ function closestGapCandidate(gaps, side) {
6894
+ var best = null;
6895
+ for (var i = 0; i < gaps.length; i += 1) {
6896
+ if (gaps[i].side !== side) continue;
6897
+ if (!best || gaps[i].gap < best.gap) best = gaps[i];
6898
+ }
6899
+ return best;
6900
+ }
6901
+ function collectRhythmGaps(axis, moving, candidates) {
6902
+ var row = [];
6903
+ for (var i = 0; i < candidates.length; i += 1) {
6904
+ var entry = candidates[i];
6905
+ if (!crossAxisOverlaps(axis, entry, moving)) continue;
6906
+ if (axisStart(entry, axis) <= axisStart(moving, axis) && axisEnd(entry, axis) >= axisEnd(moving, axis)) {
6907
+ continue;
6908
+ }
6909
+ row.push(entry);
6910
+ }
6911
+ row.sort(function(a, b) {
6912
+ return axisStart(a, axis) - axisStart(b, axis);
6913
+ });
6914
+ var gaps = [];
6915
+ var previous = null;
6916
+ for (var r = 0; r < row.length; r += 1) {
6917
+ var bounds = row[r];
6918
+ var gap = previous ? axisStart(bounds, axis) - axisEnd(previous, axis) : 0;
6919
+ if (previous && gap > 0 && crossAxisOverlaps(axis, previous, bounds)) {
6920
+ gaps.push({
6921
+ gap,
6922
+ band: {
6923
+ gapStart: axisEnd(previous, axis),
6924
+ gapEnd: axisStart(bounds, axis),
6925
+ crossStart: Math.max(
6926
+ crossStart(previous, axis),
6927
+ crossStart(bounds, axis)
6928
+ ),
6929
+ crossEnd: Math.min(
6930
+ crossEnd(previous, axis),
6931
+ crossEnd(bounds, axis)
6932
+ )
6411
6933
  }
6934
+ });
6935
+ }
6936
+ if (!previous || axisEnd(bounds, axis) > axisEnd(previous, axis)) {
6937
+ previous = bounds;
6938
+ }
6939
+ }
6940
+ return gaps;
6941
+ }
6942
+ function findSpacingSnapOffset(axis, moving, candidates, tolerance) {
6943
+ var gaps = collectAxisGapCandidates(axis, moving, candidates);
6944
+ var before = closestGapCandidate(gaps, "before");
6945
+ var after = closestGapCandidate(gaps, "after");
6946
+ if (!before && !after) return { offset: 0, side: null };
6947
+ var offset = 0;
6948
+ var side = null;
6949
+ var bestDistance = Infinity;
6950
+ function consider(value, matched) {
6951
+ var distance = Math.abs(value);
6952
+ if (distance > tolerance || distance >= bestDistance) return;
6953
+ bestDistance = distance;
6954
+ offset = value;
6955
+ side = matched;
6956
+ }
6957
+ if (before && after) consider((after.gap - before.gap) / 2, "both");
6958
+ var rhythms = collectRhythmGaps(axis, moving, candidates);
6959
+ for (var i = 0; i < rhythms.length; i += 1) {
6960
+ if (before) consider(rhythms[i].gap - before.gap, "before");
6961
+ if (after) consider(after.gap - rhythms[i].gap, "after");
6962
+ }
6963
+ return { offset, side };
6964
+ }
6965
+ function gapCandidateBand(candidate) {
6966
+ return {
6967
+ gapStart: candidate.gapStart,
6968
+ gapEnd: candidate.gapEnd,
6969
+ crossStart: candidate.crossStart,
6970
+ crossEnd: candidate.crossEnd
6971
+ };
6972
+ }
6973
+ function matchingRhythmBands(rhythms, gap, tolerance) {
6974
+ var bands = [];
6975
+ for (var i = 0; i < rhythms.length; i += 1) {
6976
+ if (Math.abs(rhythms[i].gap - gap) <= tolerance)
6977
+ bands.push(rhythms[i].band);
6978
+ }
6979
+ return bands;
6980
+ }
6981
+ function buildSpacingGuides(axis, moving, candidates, tolerance, gaps, matchedSide) {
6982
+ gaps = gaps || collectAxisGapCandidates(axis, moving, candidates);
6983
+ var before = closestGapCandidate(gaps, "before");
6984
+ var after = closestGapCandidate(gaps, "after");
6985
+ var orientation = axis === "x" ? "vertical" : "horizontal";
6986
+ var rhythms = collectRhythmGaps(axis, moving, candidates);
6987
+ if (before && after && Math.abs(before.gap - after.gap) <= tolerance) {
6988
+ var pairGap = (before.gap + after.gap) / 2;
6989
+ return [
6990
+ {
6991
+ orientation,
6992
+ gap: pairGap,
6993
+ bands: [gapCandidateBand(before), gapCandidateBand(after)].concat(
6994
+ matchingRhythmBands(rhythms, pairGap, tolerance)
6995
+ )
6412
6996
  }
6997
+ ];
6998
+ }
6999
+ var neighbor = matchedSide === "after" ? after : matchedSide === "before" ? before : before || after;
7000
+ if (!neighbor) return [];
7001
+ var matched = matchingRhythmBands(rhythms, neighbor.gap, tolerance);
7002
+ if (!matched.length) return [];
7003
+ return [
7004
+ {
7005
+ orientation,
7006
+ gap: neighbor.gap,
7007
+ bands: [gapCandidateBand(neighbor)].concat(matched)
7008
+ }
7009
+ ];
7010
+ }
7011
+ function computeProximityMeasurements(moving, candidates, range, gapsByAxis) {
7012
+ var measurements = [];
7013
+ var axes = ["x", "y"];
7014
+ for (var a = 0; a < axes.length; a += 1) {
7015
+ var axis = axes[a];
7016
+ var gaps = gapsByAxis && gapsByAxis[axis] || collectAxisGapCandidates(axis, moving, candidates);
7017
+ var nearest = null;
7018
+ for (var i = 0; i < gaps.length; i += 1) {
7019
+ if (!nearest || gaps[i].gap < nearest.gap) nearest = gaps[i];
7020
+ }
7021
+ if (!nearest || nearest.gap > range) continue;
7022
+ measurements.push({
7023
+ orientation: axis === "x" ? "vertical" : "horizontal",
7024
+ gap: nearest.gap,
7025
+ band: gapCandidateBand(nearest)
7026
+ });
7027
+ }
7028
+ return measurements;
7029
+ }
7030
+ function computeMoveSnapOffset(movingRect, candidates, threshold, isGroup, locked) {
7031
+ var moving = rectBounds(movingRect);
7032
+ locked = locked || {};
7033
+ var dx = locked.x ? null : findAxisSnapOffset("x", moving, candidates, threshold);
7034
+ var dy = locked.y ? null : findAxisSnapOffset("y", moving, candidates, threshold);
7035
+ var snapped = translateRectBounds(moving, dx || 0, dy || 0);
7036
+ var guides = (locked.x ? [] : buildAxisGuides("x", snapped, candidates)).concat(locked.y ? [] : buildAxisGuides("y", snapped, candidates));
7037
+ if (isGroup) {
7038
+ return {
7039
+ dx: dx || 0,
7040
+ dy: dy || 0,
7041
+ guides,
7042
+ spacingGuides: [],
7043
+ measurements: []
7044
+ };
7045
+ }
7046
+ var idle = { offset: 0, side: null };
7047
+ var spacingXResult = guides.some(function(guide) {
7048
+ return guide.orientation === "vertical";
7049
+ }) ? idle : locked.x ? idle : findSpacingSnapOffset("x", snapped, candidates, threshold);
7050
+ var spacingYResult = guides.some(function(guide) {
7051
+ return guide.orientation === "horizontal";
7052
+ }) ? idle : locked.y ? idle : findSpacingSnapOffset("y", snapped, candidates, threshold);
7053
+ var spacingX = spacingXResult.offset;
7054
+ var spacingY = spacingYResult.offset;
7055
+ var spaced = translateRectBounds(snapped, spacingX, spacingY);
7056
+ var settledGaps = {
7057
+ x: collectAxisGapCandidates("x", spaced, candidates),
7058
+ y: collectAxisGapCandidates("y", spaced, candidates)
7059
+ };
7060
+ var spacingGuides = buildSpacingGuides(
7061
+ "x",
7062
+ spaced,
7063
+ candidates,
7064
+ SPACING_MATCH_EPSILON,
7065
+ settledGaps.x,
7066
+ spacingXResult.side
7067
+ ).concat(
7068
+ buildSpacingGuides(
7069
+ "y",
7070
+ spaced,
7071
+ candidates,
7072
+ SPACING_MATCH_EPSILON,
7073
+ settledGaps.y,
7074
+ spacingYResult.side
7075
+ )
7076
+ );
7077
+ var measurements = computeProximityMeasurements(
7078
+ spaced,
7079
+ candidates,
7080
+ PROXIMITY_RANGE_PX * threshold / SNAP_THRESHOLD_PX,
7081
+ settledGaps
7082
+ ).filter(function(measurement) {
7083
+ return !spacingGuides.some(function(guide) {
7084
+ return guide.orientation === measurement.orientation;
7085
+ });
7086
+ });
7087
+ return {
7088
+ dx: (dx || 0) + spacingX,
7089
+ dy: (dy || 0) + spacingY,
7090
+ guides,
7091
+ spacingGuides,
7092
+ measurements
7093
+ };
7094
+ }
7095
+ var snapGuideNodeCount = 0;
7096
+ function beginSnapGuideNodes() {
7097
+ snapGuideNodeCount = 0;
7098
+ }
7099
+ function appendSnapGuideNode(cssText) {
7100
+ var node = snapGuideLayer.children[snapGuideNodeCount];
7101
+ if (!node) {
7102
+ node = document.createElement("div");
7103
+ snapGuideLayer.appendChild(node);
7104
+ }
7105
+ node.style.cssText = "position:fixed;" + cssText;
7106
+ node.textContent = "";
7107
+ snapGuideNodeCount += 1;
7108
+ return node;
7109
+ }
7110
+ function endSnapGuideNodes() {
7111
+ while (snapGuideLayer.children.length > snapGuideNodeCount) {
7112
+ snapGuideLayer.removeChild(snapGuideLayer.lastChild);
7113
+ }
7114
+ }
7115
+ function showSnapGuides(guides, spacingGuides, measurements) {
7116
+ measurements = measurements || [];
7117
+ if (!guides.length && !spacingGuides.length && !measurements.length) {
7118
+ hideSnapGuides();
7119
+ return;
7120
+ }
7121
+ beginSnapGuideNodes();
7122
+ if (snapGuideLayer.style.display !== "block") {
7123
+ snapGuideLayer.style.display = "block";
7124
+ }
7125
+ var scale = chromeLineScale();
7126
+ var line = 1 * scale;
7127
+ var fill = "background:var(--design-editor-measure-color);";
7128
+ for (var i = 0; i < guides.length; i += 1) {
7129
+ var guide = guides[i];
7130
+ var span = Math.max(1, guide.end - guide.start);
7131
+ appendSnapGuideNode(
7132
+ guide.orientation === "vertical" ? "left:" + guide.position + "px;top:" + guide.start + "px;width:" + line + "px;height:" + span + "px;" + fill : "top:" + guide.position + "px;left:" + guide.start + "px;height:" + line + "px;width:" + span + "px;" + fill
7133
+ );
7134
+ }
7135
+ for (var s = 0; s < spacingGuides.length; s += 1) {
7136
+ var spacing = spacingGuides[s];
7137
+ for (var b = 0; b < spacing.bands.length; b += 1) {
7138
+ appendSnapGuideNode(
7139
+ spacingBandCss(spacing.orientation, spacing.bands[b], line, fill)
7140
+ );
7141
+ appendSnapGuideNode(
7142
+ spacingSerifCss(
7143
+ spacing.orientation,
7144
+ spacing.bands[b],
7145
+ line,
7146
+ 5 * scale,
7147
+ fill,
7148
+ true
7149
+ )
7150
+ );
7151
+ appendSnapGuideNode(
7152
+ spacingSerifCss(
7153
+ spacing.orientation,
7154
+ spacing.bands[b],
7155
+ line,
7156
+ 5 * scale,
7157
+ fill,
7158
+ false
7159
+ )
7160
+ );
6413
7161
  }
7162
+ var label = appendSnapGuideNode(
7163
+ spacingLabelCss(spacing.orientation, spacing.bands[0], scale)
7164
+ );
7165
+ label.textContent = String(Math.round(spacing.gap));
7166
+ }
7167
+ for (var m = 0; m < measurements.length; m += 1) {
7168
+ var measurement = measurements[m];
7169
+ appendSnapGuideNode(
7170
+ spacingBandCss(measurement.orientation, measurement.band, line, fill)
7171
+ );
7172
+ appendSnapGuideNode(
7173
+ spacingSerifCss(
7174
+ measurement.orientation,
7175
+ measurement.band,
7176
+ line,
7177
+ 5 * scale,
7178
+ fill,
7179
+ true
7180
+ )
7181
+ );
7182
+ appendSnapGuideNode(
7183
+ spacingSerifCss(
7184
+ measurement.orientation,
7185
+ measurement.band,
7186
+ line,
7187
+ 5 * scale,
7188
+ fill,
7189
+ false
7190
+ )
7191
+ );
7192
+ var measureLabel = appendSnapGuideNode(
7193
+ spacingLabelCss(measurement.orientation, measurement.band, scale)
7194
+ );
7195
+ measureLabel.textContent = String(Math.round(measurement.gap));
6414
7196
  }
7197
+ endSnapGuideNodes();
7198
+ }
7199
+ function spacingBandCss(orientation, band, line, fill) {
7200
+ var crossMid = (band.crossStart + band.crossEnd) / 2;
7201
+ var length = Math.max(0, band.gapEnd - band.gapStart);
7202
+ return orientation === "vertical" ? "left:" + band.gapStart + "px;top:" + (crossMid - line / 2) + "px;width:" + length + "px;height:" + line + "px;" + fill : "top:" + band.gapStart + "px;left:" + (crossMid - line / 2) + "px;height:" + length + "px;width:" + line + "px;" + fill;
7203
+ }
7204
+ function spacingSerifCss(orientation, band, line, serif, fill, atStart) {
7205
+ var crossMid = (band.crossStart + band.crossEnd) / 2;
7206
+ var along = atStart ? band.gapStart : band.gapEnd;
7207
+ return orientation === "vertical" ? "left:" + (along - line / 2) + "px;top:" + (crossMid - serif) + "px;width:" + line + "px;height:" + serif * 2 + "px;" + fill : "top:" + (along - line / 2) + "px;left:" + (crossMid - serif) + "px;height:" + line + "px;width:" + serif * 2 + "px;" + fill;
7208
+ }
7209
+ function spacingLabelCss(orientation, band, scale) {
7210
+ var crossMid = (band.crossStart + band.crossEnd) / 2;
7211
+ var alongMid = (band.gapStart + band.gapEnd) / 2;
7212
+ return (orientation === "vertical" ? "left:" + alongMid + "px;top:" + crossMid + "px;" : "left:" + crossMid + "px;top:" + alongMid + "px;") + "transform:translate(-50%,-50%);border-radius:" + 3 * scale + "px;padding:" + 1 * scale + "px " + 4 * scale + "px;font:" + 10 * scale + "px/1 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap;background:var(--design-editor-measure-color);color:white;";
7213
+ }
7214
+ function authoredOffset(value) {
7215
+ if (!value || value === "auto") return "";
7216
+ return value;
7217
+ }
7218
+ function elementConstraints(el) {
7219
+ var style = el.style;
7220
+ var left = authoredOffset(style.left);
7221
+ var right = authoredOffset(style.right);
7222
+ var top = authoredOffset(style.top);
7223
+ var bottom = authoredOffset(style.bottom);
7224
+ var transform = style.transform || "";
6415
7225
  return {
6416
- dx: bestX ? bestX.offset : 0,
6417
- dy: bestY ? bestY.offset : 0,
6418
- guideV: bestX ? bestX.guide : null,
6419
- guideH: bestY ? bestY.guide : null
7226
+ horizontal: style.width === "100%" ? "scale" : left && right ? "left-right" : right && !left ? "right" : transform.indexOf("translateX(-50%)") !== -1 ? "center" : "left",
7227
+ vertical: style.height === "100%" ? "scale" : top && bottom ? "top-bottom" : bottom && !top ? "bottom" : transform.indexOf("translateY(-50%)") !== -1 ? "center" : "top"
6420
7228
  };
6421
7229
  }
6422
- function showSnapGuides(guideV, guideH) {
6423
- var line = 1 * chromeLineScale();
6424
- if (guideV) {
6425
- snapGuideV.style.display = "block";
6426
- snapGuideV.style.width = line + "px";
6427
- snapGuideV.style.left = Math.round(guideV.position) + "px";
6428
- snapGuideV.style.top = Math.round(guideV.start) + "px";
6429
- snapGuideV.style.height = Math.max(1, guideV.end - guideV.start) + "px";
7230
+ var constraintNodeCount = 0;
7231
+ function appendConstraintLine(from, to, crossPosition, horizontal, thickness) {
7232
+ var start = Math.min(from, to);
7233
+ var length = Math.max(1, Math.abs(to - from));
7234
+ var node = constraintGuideLayer.children[constraintNodeCount];
7235
+ if (!node) {
7236
+ node = document.createElement("div");
7237
+ constraintGuideLayer.appendChild(node);
7238
+ }
7239
+ constraintNodeCount += 1;
7240
+ node.style.cssText = "position:fixed;" + (horizontal ? "left:" + start + "px;top:" + (crossPosition - thickness / 2) + "px;width:" + length + "px;height:0;border-top:" : "top:" + start + "px;left:" + (crossPosition - thickness / 2) + "px;height:" + length + "px;width:0;border-left:") + thickness + "px dashed var(--design-editor-accent-color);";
7241
+ }
7242
+ function showConstraintGuides(el) {
7243
+ if (!el || dragChromeSuppressed) return hideConstraintGuides();
7244
+ var parent = el.offsetParent || el.parentElement;
7245
+ if (!parent) return hideConstraintGuides();
7246
+ var rect = el.getBoundingClientRect();
7247
+ var frame = parent.getBoundingClientRect();
7248
+ if (rect.width <= 0 || rect.height <= 0) return hideConstraintGuides();
7249
+ if (!constraintGuideLayer.isConnected) {
7250
+ document.body.appendChild(constraintGuideLayer);
7251
+ }
7252
+ constraintNodeCount = 0;
7253
+ if (constraintGuideLayer.style.display !== "block") {
7254
+ constraintGuideLayer.style.display = "block";
7255
+ }
7256
+ var thickness = chromeLineScale();
7257
+ var midY = rect.top + rect.height / 2;
7258
+ var midX = rect.left + rect.width / 2;
7259
+ var constraints = elementConstraints(el);
7260
+ if (constraints.horizontal === "scale") {
7261
+ appendConstraintLine(frame.left, frame.right, midY, true, thickness);
6430
7262
  } else {
6431
- snapGuideV.style.display = "none";
6432
- }
6433
- if (guideH) {
6434
- snapGuideH.style.display = "block";
6435
- snapGuideH.style.height = line + "px";
6436
- snapGuideH.style.top = Math.round(guideH.position) + "px";
6437
- snapGuideH.style.left = Math.round(guideH.start) + "px";
6438
- snapGuideH.style.width = Math.max(1, guideH.end - guideH.start) + "px";
7263
+ if (constraints.horizontal !== "right" && constraints.horizontal !== "center") {
7264
+ appendConstraintLine(frame.left, rect.left, midY, true, thickness);
7265
+ }
7266
+ if (constraints.horizontal === "right" || constraints.horizontal === "left-right") {
7267
+ appendConstraintLine(rect.right, frame.right, midY, true, thickness);
7268
+ }
7269
+ if (constraints.horizontal === "center") {
7270
+ appendConstraintLine(
7271
+ frame.left + frame.width / 2,
7272
+ midX,
7273
+ midY,
7274
+ true,
7275
+ thickness
7276
+ );
7277
+ }
7278
+ }
7279
+ if (constraints.vertical === "scale") {
7280
+ appendConstraintLine(frame.top, frame.bottom, midX, false, thickness);
6439
7281
  } else {
6440
- snapGuideH.style.display = "none";
7282
+ if (constraints.vertical !== "bottom" && constraints.vertical !== "center") {
7283
+ appendConstraintLine(frame.top, rect.top, midX, false, thickness);
7284
+ }
7285
+ if (constraints.vertical === "bottom" || constraints.vertical === "top-bottom") {
7286
+ appendConstraintLine(rect.bottom, frame.bottom, midX, false, thickness);
7287
+ }
7288
+ if (constraints.vertical === "center") {
7289
+ appendConstraintLine(
7290
+ frame.top + frame.height / 2,
7291
+ midY,
7292
+ midX,
7293
+ false,
7294
+ thickness
7295
+ );
7296
+ }
7297
+ }
7298
+ trimConstraintNodes();
7299
+ }
7300
+ function trimConstraintNodes() {
7301
+ while (constraintGuideLayer.children.length > constraintNodeCount) {
7302
+ constraintGuideLayer.removeChild(constraintGuideLayer.lastChild);
6441
7303
  }
6442
7304
  }
7305
+ function hideConstraintGuides() {
7306
+ if (constraintGuideLayer.style.display === "none") return;
7307
+ constraintGuideLayer.style.display = "none";
7308
+ constraintGuideLayer.innerHTML = "";
7309
+ constraintNodeCount = 0;
7310
+ }
7311
+ var sizeBadgeKey = "";
7312
+ var dragChromeSuppressed = false;
7313
+ function showSizeBadge(el) {
7314
+ if (!el || dragChromeSuppressed) return hideSizeBadge();
7315
+ var rect = el.getBoundingClientRect();
7316
+ if (rect.width <= 0 || rect.height <= 0) return hideSizeBadge();
7317
+ var scale = chromeLineScale();
7318
+ var key = rect.left + "|" + rect.bottom + "|" + rect.width + "|" + rect.height + "|" + scale;
7319
+ if (key === sizeBadgeKey && sizeBadge.style.display === "block") return;
7320
+ sizeBadgeKey = key;
7321
+ if (!sizeBadge.isConnected) document.body.appendChild(sizeBadge);
7322
+ sizeBadge.textContent = Math.round(rect.width) + " \\xD7 " + Math.round(rect.height);
7323
+ sizeBadge.style.display = "block";
7324
+ sizeBadge.style.borderRadius = 3 * scale + "px";
7325
+ sizeBadge.style.padding = 2 * scale + "px " + 4 * scale + "px";
7326
+ sizeBadge.style.fontSize = 10 * scale + "px";
7327
+ sizeBadge.style.left = rect.left + rect.width / 2 + "px";
7328
+ sizeBadge.style.top = rect.bottom + 6 * scale + "px";
7329
+ sizeBadge.style.transform = "translateX(-50%)";
7330
+ }
7331
+ function hideSizeBadge() {
7332
+ if (sizeBadge.style.display === "none") return;
7333
+ sizeBadge.style.display = "none";
7334
+ sizeBadgeKey = "";
7335
+ }
6443
7336
  function hideSnapGuides() {
6444
- snapGuideV.style.display = "none";
6445
- snapGuideH.style.display = "none";
7337
+ dragChromeSuppressed = false;
7338
+ if (snapGuideLayer.style.display === "none") return;
7339
+ snapGuideLayer.style.display = "none";
7340
+ snapGuideLayer.innerHTML = "";
7341
+ snapGuideNodeCount = 0;
6446
7342
  }
6447
7343
  function startMove(e, gestureElParam, pointerStartParam) {
6448
7344
  if (readOnly) return;
@@ -7075,6 +7971,18 @@ export const editorChromeBridgeScript: string = `"use strict";
7075
7971
  var dragElStartRect = dragEl.getBoundingClientRect();
7076
7972
  var dragElStartWidth = dragElStartRect.width;
7077
7973
  var dragElStartHeight = dragElStartRect.height;
7974
+ function ancestorScale(el, axis) {
7975
+ var host = el && el.offsetParent;
7976
+ if (!host) return 1;
7977
+ var rect = host.getBoundingClientRect();
7978
+ var layout = axis === "x" ? host.offsetWidth : host.offsetHeight;
7979
+ var client = axis === "x" ? rect.width : rect.height;
7980
+ if (!(layout > 0)) return 1;
7981
+ var scale = client / layout;
7982
+ return scale > 0 && Number.isFinite(scale) ? scale : 1;
7983
+ }
7984
+ var dragElOffsetScaleX = ancestorScale(dragEl, "x");
7985
+ var dragElOffsetScaleY = ancestorScale(dragEl, "y");
7078
7986
  if (!duplicatedForDrag && !isGroupDrag) {
7079
7987
  postCrossScreenDrag("start", dragEl, e);
7080
7988
  }
@@ -7110,17 +8018,33 @@ export const editorChromeBridgeScript: string = `"use strict";
7110
8018
  var snapBypass = Boolean(ev.metaKey || ev.ctrlKey);
7111
8019
  var snapResult = !snapBypass && !duplicatedForDrag ? computeMoveSnapOffset(
7112
8020
  {
7113
- left: nextLeft,
7114
- top: nextTop,
8021
+ // snapCandidateRects are client space; nextLeft/nextTop are
8022
+ // offset-parent CSS space. Convert, or nothing ever matches.
8023
+ left: dragElStartRect.left + (nextLeft - originLeft) * dragElOffsetScaleX,
8024
+ top: dragElStartRect.top + (nextTop - originTop) * dragElOffsetScaleY,
7115
8025
  width: dragElStartWidth,
7116
8026
  height: dragElStartHeight
7117
8027
  },
7118
8028
  snapCandidateRects,
7119
8029
  // Convert the screen-space base to content px (1/zoom).
7120
- SNAP_THRESHOLD_PX * chromeLineScale()
7121
- ) : { dx: 0, dy: 0, guideV: null, guideH: null };
7122
- nextLeft += snapResult.dx;
7123
- nextTop += snapResult.dy;
8030
+ SNAP_THRESHOLD_PX * chromeLineScale(),
8031
+ isGroupDrag,
8032
+ ev.shiftKey ? { x: rawDx === 0, y: rawDy === 0 } : null
8033
+ ) : { dx: 0, dy: 0, guides: [], spacingGuides: [], measurements: [] };
8034
+ if (window.__DND_DEBUG)
8035
+ dndLog("snap:tick", {
8036
+ // Ordered so the fields that decide whether snapping ran at all come
8037
+ // first: the console collapses long objects behind an ellipsis.
8038
+ bypass: snapBypass,
8039
+ duplicated: duplicatedForDrag,
8040
+ mods: (ev.metaKey ? "M" : "") + (ev.ctrlKey ? "C" : "") + (ev.altKey ? "A" : "") + (ev.shiftKey ? "S" : "") || "none",
8041
+ guides: snapResult.guides.length,
8042
+ measurements: snapResult.measurements.length,
8043
+ candidates: snapCandidateRects.length,
8044
+ dropMode: currentAutoLayoutTarget ? currentAutoLayoutTarget.dropMode || "(none)" : "no-target"
8045
+ });
8046
+ nextLeft += snapResult.dx / dragElOffsetScaleX;
8047
+ nextTop += snapResult.dy / dragElOffsetScaleY;
7124
8048
  var appliedDx = nextLeft - originLeft;
7125
8049
  var appliedDy = nextTop - originTop;
7126
8050
  memberStates.forEach(function(state) {
@@ -7154,10 +8078,20 @@ export const editorChromeBridgeScript: string = `"use strict";
7154
8078
  setMembersOpacity(null);
7155
8079
  }
7156
8080
  }
7157
- if (currentAutoLayoutTarget || !duplicatedForDrag && isOutsideIframeViewport(ev.clientX, ev.clientY)) {
8081
+ var flowInsertPending = !!currentAutoLayoutTarget && currentAutoLayoutTarget.dropMode !== "absolute-container";
8082
+ if (flowInsertPending || !duplicatedForDrag && isOutsideIframeViewport(ev.clientX, ev.clientY)) {
7158
8083
  hideSnapGuides();
8084
+ dragChromeSuppressed = true;
8085
+ hideSizeBadge();
8086
+ hideConstraintGuides();
7159
8087
  } else {
7160
- showSnapGuides(snapResult.guideV, snapResult.guideH);
8088
+ dragChromeSuppressed = false;
8089
+ showSnapGuides(
8090
+ snapResult.guides,
8091
+ snapResult.spacingGuides,
8092
+ snapResult.measurements
8093
+ );
8094
+ showConstraintGuides(dragEl);
7161
8095
  }
7162
8096
  showTransformBadge(
7163
8097
  Math.round(nextLeft) + ", " + Math.round(nextTop),
@@ -7190,6 +8124,8 @@ export const editorChromeBridgeScript: string = `"use strict";
7190
8124
  hideTransformBadge();
7191
8125
  hideInsertionGuide();
7192
8126
  hideSnapGuides();
8127
+ hideSizeBadge();
8128
+ hideConstraintGuides();
7193
8129
  currentAutoLayoutTarget = null;
7194
8130
  if (duplicatedForDrag) {
7195
8131
  if (dragEl && dragEl.parentElement) {
@@ -7220,12 +8156,16 @@ export const editorChromeBridgeScript: string = `"use strict";
7220
8156
  hideTransformBadge();
7221
8157
  hideInsertionGuide();
7222
8158
  hideSnapGuides();
8159
+ hideSizeBadge();
8160
+ hideConstraintGuides();
7223
8161
  return;
7224
8162
  }
7225
8163
  cleanupMoveDrag();
7226
8164
  hideTransformBadge();
7227
8165
  hideInsertionGuide();
7228
8166
  hideSnapGuides();
8167
+ hideSizeBadge();
8168
+ hideConstraintGuides();
7229
8169
  if (!dragEl) return;
7230
8170
  var outsideOnDrop = ev ? isOutsideIframeViewport(ev.clientX, ev.clientY) : false;
7231
8171
  if (ev && !duplicatedForDrag && !isGroupDrag && (outsideOnDrop || designCanvasBoardSurface)) {
@@ -7323,6 +8263,30 @@ export const editorChromeBridgeScript: string = `"use strict";
7323
8263
  document.addEventListener("keydown", onMoveKeyDown, true);
7324
8264
  setActiveDragCancel(cancelMoveDrag);
7325
8265
  }
8266
+ function collectScaleFontTargets(root) {
8267
+ var targets = [];
8268
+ var nodes = root.querySelectorAll("*");
8269
+ for (var i = 0; i < nodes.length; i += 1) {
8270
+ var el = nodes[i];
8271
+ if (isOverlayElement(el)) continue;
8272
+ var inlineFontSize = el.style.fontSize || "";
8273
+ if (inlineFontSize && !/px\\s*$/i.test(inlineFontSize)) continue;
8274
+ var parent = el.parentElement;
8275
+ var cs = window.getComputedStyle(el);
8276
+ if (!inlineFontSize && parent && window.getComputedStyle(parent).fontSize === cs.fontSize) {
8277
+ continue;
8278
+ }
8279
+ var originFontSize = readPx(inlineFontSize || cs.fontSize);
8280
+ if (!(originFontSize > 0)) continue;
8281
+ rememberLiveVisualEditOriginalStyles(el);
8282
+ targets.push({
8283
+ el,
8284
+ originFontSize,
8285
+ originalInlineFontSize: el.style.fontSize
8286
+ });
8287
+ }
8288
+ return targets;
8289
+ }
7326
8290
  function startResize(handle, e) {
7327
8291
  if (readOnly) return;
7328
8292
  if (!selectedEl) return;
@@ -7393,6 +8357,13 @@ export const editorChromeBridgeScript: string = `"use strict";
7393
8357
  });
7394
8358
  var widthTouched = false;
7395
8359
  var heightTouched = false;
8360
+ var scaledTextTargetsCache = null;
8361
+ function scaledTextTargets() {
8362
+ if (!scaledTextTargetsCache) {
8363
+ scaledTextTargetsCache = collectScaleFontTargets(resizeEl);
8364
+ }
8365
+ return scaledTextTargetsCache;
8366
+ }
7396
8367
  function nextRect(ev) {
7397
8368
  var screenDx = ev.clientX - startX;
7398
8369
  var screenDy = ev.clientY - startY;
@@ -7493,6 +8464,12 @@ export const editorChromeBridgeScript: string = `"use strict";
7493
8464
  if (originFontSize > 0) {
7494
8465
  resizeEl.style.fontSize = Math.max(1, Math.round(originFontSize * kScaleFactor * 100) / 100) + "px";
7495
8466
  }
8467
+ scaledTextTargets().forEach(function(target) {
8468
+ target.el.style.fontSize = Math.max(
8469
+ 1,
8470
+ Math.round(target.originFontSize * kScaleFactor * 100) / 100
8471
+ ) + "px";
8472
+ });
7496
8473
  }
7497
8474
  showTransformBadge(
7498
8475
  Math.round(rect.width) + " x " + Math.round(rect.height),
@@ -7519,6 +8496,9 @@ export const editorChromeBridgeScript: string = `"use strict";
7519
8496
  resizeEl.style.height = originalInlineHeight;
7520
8497
  resizeEl.style.borderWidth = originalInlineBorderWidth;
7521
8498
  resizeEl.style.fontSize = originalInlineFontSize;
8499
+ (scaledTextTargetsCache || []).forEach(function(target) {
8500
+ target.el.style.fontSize = target.originalInlineFontSize;
8501
+ });
7522
8502
  selectedEl = resizeEl;
7523
8503
  positionOverlay(selectionOverlay, selectedEl);
7524
8504
  }
@@ -7566,12 +8546,313 @@ export const editorChromeBridgeScript: string = `"use strict";
7566
8546
  },
7567
8547
  "*"
7568
8548
  );
8549
+ if (scaleToolEnabled) {
8550
+ (scaledTextTargetsCache || []).forEach(function(target) {
8551
+ var textStyles = {
8552
+ fontSize: target.el.style.fontSize
8553
+ };
8554
+ window.parent.postMessage(
8555
+ {
8556
+ type: "visual-style-change",
8557
+ selector: getSelector(target.el),
8558
+ styles: textStyles,
8559
+ originalStyles: originalInlineStylesForPatch(
8560
+ target.el,
8561
+ textStyles
8562
+ ),
8563
+ payload: getElementInfo(target.el),
8564
+ preserveSelection: true
8565
+ },
8566
+ "*"
8567
+ );
8568
+ });
8569
+ }
7569
8570
  }
7570
8571
  document.addEventListener(events.move, onMove, true);
7571
8572
  document.addEventListener(events.up, onUp, true);
7572
8573
  document.addEventListener("keydown", onResizeKeyDown, true);
7573
8574
  setActiveDragCancel(cancelResizeDrag);
7574
8575
  }
8576
+ function startGroupResize(handle, e) {
8577
+ if (readOnly) return;
8578
+ var members = collectSelectionMembers();
8579
+ if (members.length < 2) return;
8580
+ e.preventDefault();
8581
+ e.stopPropagation();
8582
+ var events = dragEventNames(e);
8583
+ var groupLeft = Infinity;
8584
+ var groupTop = Infinity;
8585
+ var groupRight = -Infinity;
8586
+ var groupBottom = -Infinity;
8587
+ var memberStates = members.map(function(member) {
8588
+ var el = member;
8589
+ var snapshot = {
8590
+ el,
8591
+ originalInlinePosition: el.style.position,
8592
+ originalInlineLeft: el.style.left,
8593
+ originalInlineTop: el.style.top,
8594
+ originalInlineWidth: el.style.width,
8595
+ originalInlineHeight: el.style.height,
8596
+ originalInlineBorderWidth: el.style.borderWidth,
8597
+ originalInlineFontSize: el.style.fontSize,
8598
+ originLeft: 0,
8599
+ originTop: 0,
8600
+ originWidth: 0,
8601
+ originHeight: 0,
8602
+ // The center is the one point rotation leaves alone: a rotated
8603
+ // member's client rect is its inflated axis-aligned box, so corners
8604
+ // would scale it to the wrong place.
8605
+ originCenterX: 0,
8606
+ originCenterY: 0,
8607
+ originBorderWidth: 0,
8608
+ originFontSize: 0,
8609
+ textTargets: null
8610
+ };
8611
+ rememberLiveVisualEditOriginalStyles(el);
8612
+ ensurePositionable(el);
8613
+ var cs = window.getComputedStyle(el);
8614
+ var rect = el.getBoundingClientRect();
8615
+ groupLeft = Math.min(groupLeft, rect.left);
8616
+ groupTop = Math.min(groupTop, rect.top);
8617
+ groupRight = Math.max(groupRight, rect.right);
8618
+ groupBottom = Math.max(groupBottom, rect.bottom);
8619
+ snapshot.originLeft = readPx(el.style.left || cs.left);
8620
+ snapshot.originTop = readPx(el.style.top || cs.top);
8621
+ snapshot.originWidth = readPx(cs.width);
8622
+ snapshot.originHeight = readPx(cs.height);
8623
+ snapshot.originCenterX = rect.left + rect.width / 2;
8624
+ snapshot.originCenterY = rect.top + rect.height / 2;
8625
+ snapshot.originBorderWidth = readPx(
8626
+ el.style.borderWidth || cs.borderWidth
8627
+ );
8628
+ snapshot.originFontSize = readPx(el.style.fontSize || cs.fontSize);
8629
+ return snapshot;
8630
+ });
8631
+ var groupWidth = Math.max(1, groupRight - groupLeft);
8632
+ var groupHeight = Math.max(1, groupBottom - groupTop);
8633
+ var anchorX = handle.indexOf("w") !== -1 ? groupRight : groupLeft;
8634
+ var anchorY = handle.indexOf("n") !== -1 ? groupBottom : groupTop;
8635
+ var minMemberWidth = Math.max(
8636
+ 1,
8637
+ Math.min.apply(
8638
+ null,
8639
+ memberStates.map(function(state) {
8640
+ return Math.max(1, state.originWidth);
8641
+ })
8642
+ )
8643
+ );
8644
+ var minMemberHeight = Math.max(
8645
+ 1,
8646
+ Math.min.apply(
8647
+ null,
8648
+ memberStates.map(function(state) {
8649
+ return Math.max(1, state.originHeight);
8650
+ })
8651
+ )
8652
+ );
8653
+ var minFactorX = 8 / minMemberWidth;
8654
+ var minFactorY = 8 / minMemberHeight;
8655
+ var startX = e.clientX;
8656
+ var startY = e.clientY;
8657
+ var groupGestureViewport = bridgeGestureViewport();
8658
+ var bridgeGroupResizeController = createCanvasGestureController({
8659
+ capabilities: { move: true, resize: true },
8660
+ drag: { threshold: 3, duplicateModifier: "alt" },
8661
+ minSize: 8,
8662
+ adapter: {
8663
+ preview: function() {
8664
+ return { handled: true };
8665
+ },
8666
+ commit: function() {
8667
+ return { handled: true };
8668
+ },
8669
+ cancel: function() {
8670
+ return { handled: true };
8671
+ }
8672
+ }
8673
+ });
8674
+ bridgeGroupResizeController.pointerDown({
8675
+ kind: "resize",
8676
+ objectIds: memberStates.map(function(state) {
8677
+ return getSelector(state.el);
8678
+ }),
8679
+ pointer: bridgeGesturePointer(e),
8680
+ viewport: groupGestureViewport,
8681
+ canvas: {
8682
+ width: groupGestureViewport.width,
8683
+ height: groupGestureViewport.height
8684
+ },
8685
+ handle,
8686
+ rect: {
8687
+ x: groupLeft,
8688
+ y: groupTop,
8689
+ width: groupWidth,
8690
+ height: groupHeight
8691
+ }
8692
+ });
8693
+ function groupFactors(ev) {
8694
+ var dx = ev.clientX - startX;
8695
+ var dy = ev.clientY - startY;
8696
+ var nextWidth = handle.indexOf("e") !== -1 ? groupWidth + dx : groupWidth - dx;
8697
+ var nextHeight = handle.indexOf("s") !== -1 ? groupHeight + dy : groupHeight - dy;
8698
+ var factorX = nextWidth / groupWidth;
8699
+ var factorY = nextHeight / groupHeight;
8700
+ if (ev.shiftKey || scaleToolEnabled) {
8701
+ var uniform = Math.max(
8702
+ Math.max(minFactorX, minFactorY),
8703
+ Math.abs(dx) > Math.abs(dy) ? factorX : factorY
8704
+ );
8705
+ return { x: uniform, y: uniform };
8706
+ }
8707
+ return {
8708
+ x: Math.max(minFactorX, factorX),
8709
+ y: Math.max(minFactorY, factorY)
8710
+ };
8711
+ }
8712
+ function memberTextTargets(state) {
8713
+ if (!state.textTargets) {
8714
+ state.textTargets = collectScaleFontTargets(state.el);
8715
+ }
8716
+ return state.textTargets;
8717
+ }
8718
+ function onMove(ev) {
8719
+ var controllerMove = bridgeGroupResizeController.pointerMove(
8720
+ bridgeGesturePointer(ev)
8721
+ );
8722
+ if (controllerMove.phase !== "active") return;
8723
+ var factor = groupFactors(ev);
8724
+ memberStates.forEach(function(state) {
8725
+ var nextCenterX = anchorX + (state.originCenterX - anchorX) * factor.x;
8726
+ var nextCenterY = anchorY + (state.originCenterY - anchorY) * factor.y;
8727
+ var nextWidth = state.originWidth * factor.x;
8728
+ var nextHeight = state.originHeight * factor.y;
8729
+ state.el.style.left = Math.round(
8730
+ state.originLeft + (nextCenterX - state.originCenterX) - (nextWidth - state.originWidth) / 2
8731
+ ) + "px";
8732
+ state.el.style.top = Math.round(
8733
+ state.originTop + (nextCenterY - state.originCenterY) - (nextHeight - state.originHeight) / 2
8734
+ ) + "px";
8735
+ state.el.style.width = Math.round(nextWidth) + "px";
8736
+ state.el.style.height = Math.round(nextHeight) + "px";
8737
+ if (!scaleToolEnabled) return;
8738
+ if (state.originBorderWidth > 0) {
8739
+ state.el.style.borderWidth = Math.max(
8740
+ 0,
8741
+ Math.round(state.originBorderWidth * factor.x * 100) / 100
8742
+ ) + "px";
8743
+ }
8744
+ if (state.originFontSize > 0) {
8745
+ state.el.style.fontSize = Math.max(
8746
+ 1,
8747
+ Math.round(state.originFontSize * factor.x * 100) / 100
8748
+ ) + "px";
8749
+ }
8750
+ memberTextTargets(state).forEach(function(target) {
8751
+ target.el.style.fontSize = Math.max(
8752
+ 1,
8753
+ Math.round(target.originFontSize * factor.x * 100) / 100
8754
+ ) + "px";
8755
+ });
8756
+ });
8757
+ showTransformBadge(
8758
+ Math.round(groupWidth * factor.x) + " x " + Math.round(groupHeight * factor.y),
8759
+ ev.clientX,
8760
+ ev.clientY
8761
+ );
8762
+ refreshOverlays();
8763
+ }
8764
+ function cleanupGroupResizeDrag() {
8765
+ document.removeEventListener(events.move, onMove, true);
8766
+ document.removeEventListener(events.up, onUp, true);
8767
+ document.removeEventListener("keydown", onGroupResizeKeyDown, true);
8768
+ clearActiveDragCancel(cancelGroupResizeDrag);
8769
+ }
8770
+ function cancelGroupResizeDrag() {
8771
+ bridgeGroupResizeController.cancel();
8772
+ cleanupGroupResizeDrag();
8773
+ hideTransformBadge();
8774
+ memberStates.forEach(function(state) {
8775
+ if (!document.documentElement.contains(state.el)) return;
8776
+ state.el.style.position = state.originalInlinePosition;
8777
+ state.el.style.left = state.originalInlineLeft;
8778
+ state.el.style.top = state.originalInlineTop;
8779
+ state.el.style.width = state.originalInlineWidth;
8780
+ state.el.style.height = state.originalInlineHeight;
8781
+ state.el.style.borderWidth = state.originalInlineBorderWidth;
8782
+ state.el.style.fontSize = state.originalInlineFontSize;
8783
+ (state.textTargets || []).forEach(function(target) {
8784
+ target.el.style.fontSize = target.originalInlineFontSize;
8785
+ });
8786
+ });
8787
+ suppressNextShieldClickBriefly();
8788
+ refreshOverlays();
8789
+ return true;
8790
+ }
8791
+ function onGroupResizeKeyDown(ev) {
8792
+ if (ev.key !== "Escape") return;
8793
+ stopNativeInteraction(ev);
8794
+ cancelGroupResizeDrag();
8795
+ }
8796
+ function onUp(ev) {
8797
+ var controllerEnd = bridgeGroupResizeController.pointerUp(
8798
+ bridgeGesturePointer(ev)
8799
+ );
8800
+ cleanupGroupResizeDrag();
8801
+ hideTransformBadge();
8802
+ if (!controllerEnd.committed) return;
8803
+ memberStates.forEach(function(state) {
8804
+ var styles = {
8805
+ position: state.el.style.position,
8806
+ left: state.el.style.left,
8807
+ top: state.el.style.top,
8808
+ width: state.el.style.width,
8809
+ height: state.el.style.height
8810
+ };
8811
+ if (scaleToolEnabled && state.originBorderWidth > 0) {
8812
+ styles.borderWidth = state.el.style.borderWidth;
8813
+ }
8814
+ if (scaleToolEnabled && state.originFontSize > 0) {
8815
+ styles.fontSize = state.el.style.fontSize;
8816
+ }
8817
+ window.parent.postMessage(
8818
+ {
8819
+ type: "visual-style-change",
8820
+ selector: getSelector(state.el),
8821
+ styles,
8822
+ originalStyles: originalInlineStylesForPatch(state.el, styles),
8823
+ payload: getElementInfo(state.el)
8824
+ },
8825
+ "*"
8826
+ );
8827
+ if (!scaleToolEnabled) return;
8828
+ (state.textTargets || []).forEach(function(target) {
8829
+ var textStyles = {
8830
+ fontSize: target.el.style.fontSize
8831
+ };
8832
+ window.parent.postMessage(
8833
+ {
8834
+ type: "visual-style-change",
8835
+ selector: getSelector(target.el),
8836
+ styles: textStyles,
8837
+ originalStyles: originalInlineStylesForPatch(
8838
+ target.el,
8839
+ textStyles
8840
+ ),
8841
+ payload: getElementInfo(target.el),
8842
+ // A scaled descendant is a side effect of the gesture, not the
8843
+ // object the user is holding.
8844
+ preserveSelection: true
8845
+ },
8846
+ "*"
8847
+ );
8848
+ });
8849
+ });
8850
+ }
8851
+ document.addEventListener(events.move, onMove, true);
8852
+ document.addEventListener(events.up, onUp, true);
8853
+ document.addEventListener("keydown", onGroupResizeKeyDown, true);
8854
+ setActiveDragCancel(cancelGroupResizeDrag);
8855
+ }
7575
8856
  function startRotate(e) {
7576
8857
  if (readOnly) return;
7577
8858
  if (!selectedEl) return;
@@ -7710,7 +8991,17 @@ export const editorChromeBridgeScript: string = `"use strict";
7710
8991
  preferSelected: selectedLayerDragPriorityEnabled
7711
8992
  });
7712
8993
  var clickTarget = hitTarget;
8994
+ if (window.__DND_DEBUG)
8995
+ dndLog("shield:down", {
8996
+ hit: getSelector(hit),
8997
+ dragTarget: getSelector(dragTarget),
8998
+ board: designCanvasBoardSurface,
8999
+ readOnly,
9000
+ position: dragTarget ? window.getComputedStyle(dragTarget).position : null,
9001
+ flowCandidate: dragTarget ? isFlowReorderCandidate(dragTarget) : null
9002
+ });
7713
9003
  if (!dragTarget || dragTarget === document.body || dragTarget === document.documentElement || isLayerInteractionBlocked(dragTarget)) {
9004
+ dndLog("shield:reject", { reason: "no-drag-target" });
7714
9005
  return;
7715
9006
  }
7716
9007
  if (e.pointerId !== void 0 && shieldOverlay.setPointerCapture && !e.altKey) {
@@ -7743,6 +9034,8 @@ export const editorChromeBridgeScript: string = `"use strict";
7743
9034
  if (readOnly) return;
7744
9035
  if (Math.hypot(ev.clientX - startX, ev.clientY - startY) <= 3) return;
7745
9036
  clearPendingShieldDrag();
9037
+ if (!didStartDrag)
9038
+ dndLog("shield:drag-start", { board: designCanvasBoardSurface });
7746
9039
  didStartDrag = true;
7747
9040
  var groupGestureMember = !e.altKey ? groupMemberForGestureTarget(dragTarget) : null;
7748
9041
  if (groupGestureMember && collectMoveGroupMembers(groupGestureMember).length > 1) {
@@ -9399,6 +10692,7 @@ export const editorChromeBridgeScript: string = `"use strict";
9399
10692
  ]
9400
10693
  });
9401
10694
  }
10695
+ captureInitialSourceOwnership();
9402
10696
  if (runtimeLayerSnapshotEnabled) scheduleRuntimeLayerSnapshot();
9403
10697
  window.parent.postMessage(
9404
10698
  { type: "agent-native:editor-chrome-ready" },