@agent-native/core 0.187.0 → 0.187.1-nightly-20260925003003
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +4 -3
- package/corpus/templates/analytics/changelog/2026-09-24-analytics-sidebar-footer-aligns-consistently.md +6 -0
- package/corpus/templates/analytics/changelog/2026-09-24-dashboard-emails-match-stacked-area-totals.md +6 -0
- package/corpus/templates/analytics/server/lib/report-chart-svg.ts +47 -20
- package/corpus/templates/calendar/app/components/calendar/AttendeeAutocomplete.tsx +1 -1
- package/corpus/templates/calendar/changelog/2026-09-24-guest-inputs-wrap-beneath-existing-guests-so-the-active-inpu.md +6 -0
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +8 -3
- package/corpus/templates/clips/app/lib/recording-link.ts +21 -0
- package/corpus/templates/clips/app/routes/record.tsx +27 -8
- package/corpus/templates/clips/changelog/2026-09-24-the-camera-bubble-stays-visible-while-you-reposition-it-befo.md +6 -0
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -0
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +63 -55
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +251 -74
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +66 -56
- package/corpus/templates/design/app/components/design/EditPanel.tsx +19 -0
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +59 -9
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +4 -0
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +119 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +48 -51
- package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +1 -0
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +298 -187
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +2 -2
- package/corpus/templates/design/app/components/design/inspector/index.ts +4 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +4 -2
- package/corpus/templates/design/app/i18n/en-US.ts +6 -0
- package/corpus/templates/design/app/pages/Present.tsx +101 -87
- package/corpus/templates/design/app/pages/design-editor/clone-and-pen-edit.ts +75 -14
- package/corpus/templates/design/app/pages/design-editor/commands/README.md +1 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-relative-style-delta-to-selected-layers.ts +69 -56
- package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +16 -0
- package/corpus/templates/design/app/pages/design-editor/commands/scale-selection.ts +17 -2
- package/corpus/templates/design/app/pages/design-editor/commands/styles-change.ts +23 -30
- package/corpus/templates/design/app/pages/design-editor/commands/swap-fill-stroke.ts +105 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +21 -0
- package/corpus/templates/design/app/pages/present-review-state.ts +7 -1
- package/corpus/templates/design/changelog/2026-09-24-a-vector-s-stroke-row-shows-position-beside-weight-instead-o.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-css-margins-can-be-adjusted-on-the-canvas-and-in-the-layout-.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-design-reviews-show-the-real-canvas-beside-its-conversation.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-double-clicking-text-or-a-vector-on-the-board-starts-editing.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-interact-opens-a-focused-responsive-preview-without-reloadin.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-keep-gradient-values-visible-and-limit-canvas-paints-to-supp.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-open-pen-paths-no-longer-paint-a-filled-triangle-after-shift.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-re-clicking-the-active-responsive-preview-returns-to-the-can.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-resized-vectors-can-be-point-edited-and-the-k-scale-tool-sho.md +6 -0
- package/corpus/templates/design/changelog/2026-09-24-while-editing-text-click-to-place-the-caret-and-double-click.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +19 -2
- package/corpus/templates/mail/app/components/email/ComposeModal.tsx +1 -1
- package/corpus/templates/mail/changelog/2026-09-24-gmail-push-ack.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-24-the-composer-keeps-its-taller-layout-in-a-narrower-window.md +6 -0
- package/corpus/templates/mail/server/db/schema.ts +26 -1
- package/corpus/templates/mail/server/lib/inbox-store.ts +68 -23
- package/corpus/templates/mail/server/lib/inbox-sync.ts +43 -17
- package/corpus/templates/mail/server/plugins/db.ts +19 -0
- package/corpus/templates/mail/server/routes/api/gmail/push.post.ts +4 -15
- package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +45 -30
- package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +18 -2
- package/corpus/templates/slides/actions/export-html.ts +28 -17
- package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +27 -15
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-09-23-decks-with-no-design-system-now-follow-a-theme-chosen-for-th.md +6 -0
- package/corpus/templates/slides/shared/slide-background.ts +3 -1
- package/dist/agent/engine/builder-engine.js +11 -0
- package/dist/agent/engine/types.d.ts +1 -0
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.js +32 -4
- package/dist/agent/run-loop-with-resume.js +6 -0
- package/dist/cli/index.js +4 -4
- package/dist/cli/process.d.ts +10 -1
- package/dist/cli/process.js +66 -0
- package/dist/cli/workspace-dev.js +2 -0
- package/dist/client/agent-chat.js +13 -14
- package/dist/client/error-format.js +4 -4
- package/dist/client/observability/ObservabilityDashboard.js +95 -65
- package/dist/client/observability/OutputPreview.d.ts +2 -1
- package/dist/client/observability/OutputPreview.js +64 -7
- package/dist/client/observability/useObservability.d.ts +2 -1
- package/dist/client/observability/useObservability.js +5 -1
- package/dist/client/settings/UsageSection.js +105 -17
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/client.d.ts +44 -0
- package/dist/db/client.js +62 -3
- package/dist/db/create-get-db.js +23 -1
- package/dist/db/embedded-runtime.d.ts +21 -0
- package/dist/db/embedded-runtime.js +27 -0
- package/dist/db/migrations.js +2 -0
- package/dist/db/server-runtime.d.ts +22 -0
- package/dist/db/server-runtime.js +26 -0
- package/dist/deploy/build.d.ts +29 -0
- package/dist/deploy/build.js +204 -121
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/registry.d.ts +1 -0
- package/dist/feature-flags/registry.js +5 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/webhook-handler.js +4 -1
- package/dist/jobs/background-automation-runner.js +6 -1
- package/dist/localization/core-messages/ar-SA.js +9 -1
- package/dist/localization/core-messages/de-DE.js +9 -1
- package/dist/localization/core-messages/en-US.d.ts +9 -1
- package/dist/localization/core-messages/en-US.js +9 -1
- package/dist/localization/core-messages/es-ES.js +9 -1
- package/dist/localization/core-messages/fr-FR.js +9 -1
- package/dist/localization/core-messages/hi-IN.js +9 -1
- package/dist/localization/core-messages/ja-JP.js +9 -1
- package/dist/localization/core-messages/ko-KR.js +9 -1
- package/dist/localization/core-messages/pt-BR.js +9 -1
- package/dist/localization/core-messages/supplemental/ar-SA.js +1 -0
- package/dist/localization/core-messages/supplemental/de-DE.js +1 -0
- package/dist/localization/core-messages/supplemental/en-US.js +1 -0
- package/dist/localization/core-messages/supplemental/es-ES.js +1 -0
- package/dist/localization/core-messages/supplemental/fr-FR.js +1 -0
- package/dist/localization/core-messages/supplemental/hi-IN.js +1 -0
- package/dist/localization/core-messages/supplemental/ja-JP.js +1 -0
- package/dist/localization/core-messages/supplemental/ko-KR.js +1 -0
- package/dist/localization/core-messages/supplemental/pt-BR.js +1 -0
- package/dist/localization/core-messages/supplemental/zh-CN.js +1 -0
- package/dist/localization/core-messages/supplemental/zh-TW.js +1 -0
- package/dist/localization/core-messages/zh-CN.js +9 -1
- package/dist/localization/core-messages/zh-TW.js +9 -1
- package/dist/localization/core-messages.d.ts +9 -1
- package/dist/localization/mcp-settings-messages.d.ts +1 -0
- package/dist/mcp/connect-route.js +45 -8
- package/dist/mcp/connect-store.d.ts +7 -5
- package/dist/mcp/connect-store.js +30 -39
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/actions/get-observability-review-detail.d.ts +7 -0
- package/dist/observability/actions/get-observability-review-detail.js +25 -0
- package/dist/observability/reviews.d.ts +9 -1
- package/dist/observability/reviews.js +20 -0
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/types.d.ts +8 -0
- package/dist/org/handlers.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +9 -9
- package/dist/scripts/db/query.js +6 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/agent-teams.js +4 -1
- package/dist/server/auth.js +60 -20
- package/dist/server/better-auth-instance.js +7 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.js +2 -0
- package/dist/server/embedded.js +6 -0
- package/dist/server/framework-request-handler.js +6 -0
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/usage/actions/get-usage-metrics.js +4 -1
- package/dist/usage/metrics-store.d.ts +19 -0
- package/dist/usage/metrics-store.js +106 -14
- package/dist/usage/store.d.ts +7 -2
- package/dist/usage/store.js +25 -4
- package/dist/vite/action-types-plugin.js +4 -0
- package/dist/vite/client.d.ts +6 -1
- package/dist/vite/client.js +40 -1
- package/package.json +4 -3
|
@@ -2369,15 +2369,19 @@ export function DesignCanvas({
|
|
|
2369
2369
|
// srcdoc is rebuilt per document, so unlike the keyed live-edit bundle above
|
|
2370
2370
|
// it can carry the real first-paint value: forwarding that arrives only by
|
|
2371
2371
|
// postMessage stays dead until the handshake, and is stranded by a swap.
|
|
2372
|
+
const initialInteractModeRef = useRef(interactMode);
|
|
2372
2373
|
const embeddedGestureBridgeForSrcdoc = useMemo(
|
|
2373
2374
|
() =>
|
|
2374
2375
|
EMBEDDED_WHEEL_BRIDGE_SCRIPT.replace(
|
|
2375
2376
|
"__EMBEDDED_WHEEL_FORWARDING_ENABLED__",
|
|
2376
|
-
isEmbeddedFrame && !
|
|
2377
|
+
isEmbeddedFrame && !initialInteractModeRef.current ? "true" : "false",
|
|
2377
2378
|
)
|
|
2378
2379
|
.replace("__EMBEDDED_SPACE_KEY_FORWARDING_ENABLED__", "false")
|
|
2379
|
-
.replace(
|
|
2380
|
-
|
|
2380
|
+
.replace(
|
|
2381
|
+
"__EDITING_SAFETY_ENABLED__",
|
|
2382
|
+
initialInteractModeRef.current ? "false" : "true",
|
|
2383
|
+
),
|
|
2384
|
+
[isEmbeddedFrame],
|
|
2381
2385
|
);
|
|
2382
2386
|
const includeLiveEditEditorChrome = !readOnly;
|
|
2383
2387
|
const liveEditBridgeScript = useMemo(() => {
|
|
@@ -3571,15 +3575,13 @@ export function DesignCanvas({
|
|
|
3571
3575
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3572
3576
|
}, [centerInteractPreview, deviceFrame, contentKey, previewWidthPx]);
|
|
3573
3577
|
|
|
3574
|
-
// Build the srcdoc.
|
|
3575
|
-
//
|
|
3576
|
-
// so preview/app users can interact with the app normally.
|
|
3578
|
+
// Build the srcdoc. Both mode bridges stay installed; live postMessages
|
|
3579
|
+
// switch pointer ownership without replacing the iframe document.
|
|
3577
3580
|
//
|
|
3578
|
-
// readOnly and editMode are intentionally NOT deps here: the
|
|
3579
|
-
//
|
|
3580
|
-
//
|
|
3581
|
-
//
|
|
3582
|
-
// readOnly / editMode changes flow through the set-read-only and
|
|
3581
|
+
// readOnly and editMode are intentionally NOT deps here: the initial
|
|
3582
|
+
// __READ_ONLY__ / __TEXT_EDITING_ENABLED__ placeholders are baked from the
|
|
3583
|
+
// first render only (so first paint never flashes the wrong mode). After
|
|
3584
|
+
// that, live readOnly / editMode changes flow through set-read-only and
|
|
3583
3585
|
// set-text-editing-enabled postMessages (see the useEffects below) so
|
|
3584
3586
|
// switching the active surface (board ↔ screen) or toggling Edit ⇄ Preview
|
|
3585
3587
|
// never rebuilds srcdoc / reloads every screen iframe.
|
|
@@ -3589,50 +3591,49 @@ export function DesignCanvas({
|
|
|
3589
3591
|
// mounting an iframe, then mounts the real `src` exactly once.
|
|
3590
3592
|
if (rawExternalPreviewUrl) return undefined;
|
|
3591
3593
|
const localizedContent = withLocalRuntimes(iframeRenderContent);
|
|
3592
|
-
const editorChromeBridge =
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3594
|
+
const editorChromeBridge =
|
|
3595
|
+
createEditorBridgeThemeScript(readEditorBridgeThemeVars()) +
|
|
3596
|
+
EDITOR_CHROME_BRIDGE_SCRIPT.replace(
|
|
3597
|
+
"__READ_ONLY__",
|
|
3598
|
+
readOnly ? "true" : "false",
|
|
3599
|
+
)
|
|
3600
|
+
.replace("__TEXT_EDITING_ENABLED__", editMode ? "true" : "false")
|
|
3601
|
+
.replace(
|
|
3602
|
+
"__EDITOR_CHROME_SCALE_X__",
|
|
3603
|
+
String(effectiveEditorChromeScaleX),
|
|
3598
3604
|
)
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
3632
|
-
)
|
|
3633
|
-
.replace(/__INITIAL_SOURCE_HEAD__/g, () =>
|
|
3634
|
-
inlineScriptJson(sourceHeadInnerHtml(localizedContent)),
|
|
3635
|
-
);
|
|
3605
|
+
.replace(
|
|
3606
|
+
"__EDITOR_CHROME_SCALE_Y__",
|
|
3607
|
+
String(effectiveEditorChromeScaleY),
|
|
3608
|
+
)
|
|
3609
|
+
.replace(
|
|
3610
|
+
"__DESIGN_CANVAS_SCREEN_ID__",
|
|
3611
|
+
JSON.stringify(screenId ?? contentKey ?? ""),
|
|
3612
|
+
)
|
|
3613
|
+
.replace(
|
|
3614
|
+
"__DESIGN_CANVAS_BOARD_SURFACE__",
|
|
3615
|
+
boardSurface ? "true" : "false",
|
|
3616
|
+
)
|
|
3617
|
+
.replace(
|
|
3618
|
+
"__DESIGN_CANVAS_CONTENT_OFFSET_X__",
|
|
3619
|
+
String(Math.round(embeddedFrame?.contentOffsetX ?? 0)),
|
|
3620
|
+
)
|
|
3621
|
+
.replace(
|
|
3622
|
+
"__DESIGN_CANVAS_CONTENT_OFFSET_Y__",
|
|
3623
|
+
String(Math.round(embeddedFrame?.contentOffsetY ?? 0)),
|
|
3624
|
+
)
|
|
3625
|
+
.replace("__RUNTIME_LAYER_SNAPSHOT_ENABLED__", "false")
|
|
3626
|
+
.replace(
|
|
3627
|
+
"__LIVE_REFLOW_ENABLED__",
|
|
3628
|
+
LIVE_REFLOW_ENABLED ? "true" : "false",
|
|
3629
|
+
)
|
|
3630
|
+
.replace(
|
|
3631
|
+
"__SELECTED_LAYER_DRAG_PRIORITY__",
|
|
3632
|
+
SELECTED_LAYER_DRAG_PRIORITY_ENABLED ? "true" : "false",
|
|
3633
|
+
)
|
|
3634
|
+
.replace(/__INITIAL_SOURCE_HEAD__/g, () =>
|
|
3635
|
+
inlineScriptJson(sourceHeadInnerHtml(localizedContent)),
|
|
3636
|
+
);
|
|
3636
3637
|
// ALWAYS injected (like the other always-on bridges above) so
|
|
3637
3638
|
// MultiScreenCanvas's cross-screen drag hit-testing
|
|
3638
3639
|
// (agent-native:hit-test / agent-native:hit-test-result) resolves an
|
|
@@ -3696,7 +3697,6 @@ export function DesignCanvas({
|
|
|
3696
3697
|
boardSurface,
|
|
3697
3698
|
fitRootBodyToFrame,
|
|
3698
3699
|
rawExternalPreviewUrl,
|
|
3699
|
-
interactMode,
|
|
3700
3700
|
isEmbeddedFrame,
|
|
3701
3701
|
embeddedFrameBackground,
|
|
3702
3702
|
embeddedGestureBridgeForSrcdoc,
|
|
@@ -4102,6 +4102,7 @@ export function DesignCanvas({
|
|
|
4102
4102
|
return;
|
|
4103
4103
|
}
|
|
4104
4104
|
if (e.data.type === "clear-selection") {
|
|
4105
|
+
iframeClearedSelectorRef.current = selectedSelectorRef.current ?? null;
|
|
4105
4106
|
onClearSelection?.();
|
|
4106
4107
|
return;
|
|
4107
4108
|
}
|
|
@@ -5188,6 +5189,9 @@ export function DesignCanvas({
|
|
|
5188
5189
|
// Selectors from the iframe's own click; skip mirroring them back once to
|
|
5189
5190
|
// avoid the fast-click bounce.
|
|
5190
5191
|
const suppressMirrorSelectorsRef = useRef<string[] | null>(null);
|
|
5192
|
+
// The iframe cleared this selection itself. A ready handshake can land
|
|
5193
|
+
// before the parent renders the clear, and replaying then re-selects it.
|
|
5194
|
+
const iframeClearedSelectorRef = useRef<string | null>(null);
|
|
5191
5195
|
// Latest replayIframeEditorState, synced during render (below) so the message
|
|
5192
5196
|
// handler can force a corrective resync without a stale closure.
|
|
5193
5197
|
const replayIframeEditorStateRef = useRef<(() => void) | null>(null);
|
|
@@ -5256,7 +5260,13 @@ export function DesignCanvas({
|
|
|
5256
5260
|
!forceSelectionMirrorResyncRef.current &&
|
|
5257
5261
|
!!selectedSelector &&
|
|
5258
5262
|
(suppressMirrorSelectorsRef.current?.includes(selectedSelector) ?? false);
|
|
5259
|
-
|
|
5263
|
+
const staleIframeClear =
|
|
5264
|
+
!!selectedSelector &&
|
|
5265
|
+
iframeClearedSelectorRef.current === selectedSelector;
|
|
5266
|
+
if (!staleIframeClear) iframeClearedSelectorRef.current = null;
|
|
5267
|
+
if (staleIframeClear) {
|
|
5268
|
+
// Wait for the parent's clear to render; it mirrors down on its own.
|
|
5269
|
+
} else if (isIframeOriginatedEcho) {
|
|
5260
5270
|
lastSelectionMirrorSignatureRef.current = selectionMirrorSignature;
|
|
5261
5271
|
suppressMirrorSelectorsRef.current = null;
|
|
5262
5272
|
} else if (
|
|
@@ -162,6 +162,10 @@ import {
|
|
|
162
162
|
textStrokeIsVisible,
|
|
163
163
|
} from "./edit-panel/position-helpers";
|
|
164
164
|
import { PositionLayoutProperties } from "./edit-panel/position-layout-properties";
|
|
165
|
+
import {
|
|
166
|
+
ScaleProperties,
|
|
167
|
+
type ScaleToolControls,
|
|
168
|
+
} from "./edit-panel/scale-properties";
|
|
165
169
|
import { mixedElementFromSelection } from "./edit-panel/selection-helpers";
|
|
166
170
|
import { StrokeProperties } from "./edit-panel/stroke-properties";
|
|
167
171
|
import {
|
|
@@ -538,6 +542,8 @@ interface EditPanelProps {
|
|
|
538
542
|
* type without EditPanel importing it.
|
|
539
543
|
*/
|
|
540
544
|
activeTool?: string;
|
|
545
|
+
/** Shows Figma's Scale section while `activeTool === "scale"`. */
|
|
546
|
+
scaleToolControls?: ScaleToolControls;
|
|
541
547
|
/**
|
|
542
548
|
* Creates a new screen sized to the clicked preset. Only takes effect while
|
|
543
549
|
* `activeTool === "frame"`; when omitted the frame tool falls back to the
|
|
@@ -1913,6 +1919,7 @@ function PageProperties({
|
|
|
1913
1919
|
<ColorInput
|
|
1914
1920
|
label={t("editPanel.labels.background")}
|
|
1915
1921
|
value={canvasBackground ?? canvasBackgroundFallback ?? ""}
|
|
1922
|
+
supportedPaintTypes={["solid", "none"]}
|
|
1916
1923
|
// meta carries phase: "preview" while dragging vs "commit" on
|
|
1917
1924
|
// release. Dropping it persists every tick and the picker jumps.
|
|
1918
1925
|
onChange={(value, meta) => onCanvasBackgroundChange(value, meta)}
|
|
@@ -2568,6 +2575,7 @@ export const EditPanel = memo(function EditPanel({
|
|
|
2568
2575
|
inspectCode,
|
|
2569
2576
|
aiActions,
|
|
2570
2577
|
activeTool,
|
|
2578
|
+
scaleToolControls,
|
|
2571
2579
|
onCreateScreenFromPreset,
|
|
2572
2580
|
onAlignSelection,
|
|
2573
2581
|
alignSelectionDisabled = false,
|
|
@@ -3371,6 +3379,17 @@ export const EditPanel = memo(function EditPanel({
|
|
|
3371
3379
|
motionKeyframeContext={motionKeyframeFieldContext}
|
|
3372
3380
|
breakpointOverrideContext={breakpointOverrideFieldContext}
|
|
3373
3381
|
/>
|
|
3382
|
+
{activeTool === "scale" &&
|
|
3383
|
+
scaleToolControls &&
|
|
3384
|
+
effectiveSelectedElements.length === 1 ? (
|
|
3385
|
+
<ScaleProperties
|
|
3386
|
+
key={`scale:${inspectorElementSectionKey}`}
|
|
3387
|
+
element={
|
|
3388
|
+
stateResolvedInspectorElement ?? inspectorElement
|
|
3389
|
+
}
|
|
3390
|
+
controls={scaleToolControls}
|
|
3391
|
+
/>
|
|
3392
|
+
) : null}
|
|
3374
3393
|
<LayoutContextProperties
|
|
3375
3394
|
key={`layout-context:${inspectorElementSectionKey}`}
|
|
3376
3395
|
element={stateResolvedInspectorElement ?? inspectorElement}
|
|
@@ -616,6 +616,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
616
616
|
onReviewPendingScreen,
|
|
617
617
|
interactMode = false,
|
|
618
618
|
interactScreenId = null,
|
|
619
|
+
focusedInteractViewport = null,
|
|
619
620
|
readOnly = false,
|
|
620
621
|
editableScreenIds,
|
|
621
622
|
activeScreenHasHoveredChild = false,
|
|
@@ -8936,6 +8937,11 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
8936
8937
|
if (pressTarget) {
|
|
8937
8938
|
dispatchAt(pressTarget, "mousedown", point, ev, 1);
|
|
8938
8939
|
dispatchAt(pressTarget, "mouseup", point, ev, 0);
|
|
8940
|
+
// This surface covers the selected object, so the native dblclick
|
|
8941
|
+
// that starts text editing never reaches the board bridge.
|
|
8942
|
+
if (ev.detail >= 2) {
|
|
8943
|
+
dispatchAt(pressTarget, "dblclick", point, ev, 0);
|
|
8944
|
+
}
|
|
8939
8945
|
}
|
|
8940
8946
|
finishDrag();
|
|
8941
8947
|
return;
|
|
@@ -10840,7 +10846,16 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
10840
10846
|
!autoHeight || autoHeight === rawGeometry.height
|
|
10841
10847
|
? rawGeometry
|
|
10842
10848
|
: { ...rawGeometry, height: autoHeight };
|
|
10843
|
-
const
|
|
10849
|
+
const baseGeometry = clampScreenFrameSize(sizedGeometry, sizeConstraints);
|
|
10850
|
+
const geometry =
|
|
10851
|
+
screen.id === interactScreenId && focusedInteractViewport
|
|
10852
|
+
? {
|
|
10853
|
+
...baseGeometry,
|
|
10854
|
+
width: Math.max(1, Math.round(focusedInteractViewport.width)),
|
|
10855
|
+
height: Math.max(1, Math.round(focusedInteractViewport.height)),
|
|
10856
|
+
rotation: undefined,
|
|
10857
|
+
}
|
|
10858
|
+
: baseGeometry;
|
|
10844
10859
|
const prior = cache.get(screen.id);
|
|
10845
10860
|
if (
|
|
10846
10861
|
prior &&
|
|
@@ -10866,15 +10881,23 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
10866
10881
|
return next;
|
|
10867
10882
|
}, [
|
|
10868
10883
|
frameGeometry,
|
|
10884
|
+
focusedInteractViewport?.height,
|
|
10885
|
+
focusedInteractViewport?.width,
|
|
10869
10886
|
geometryById,
|
|
10870
10887
|
geometryOverridesById,
|
|
10871
10888
|
getResolvedMetadata,
|
|
10889
|
+
interactScreenId,
|
|
10872
10890
|
measuredIframeHeights,
|
|
10873
10891
|
measuredIframeNaturalHeights,
|
|
10874
10892
|
renderedScreens,
|
|
10875
10893
|
screenIndexById,
|
|
10876
10894
|
screenRootComputedStylesById,
|
|
10877
10895
|
]);
|
|
10896
|
+
const focusedInteractFrame =
|
|
10897
|
+
focusedInteractViewport && interactScreenId
|
|
10898
|
+
? canvasFrames.find(({ screen }) => screen.id === interactScreenId)
|
|
10899
|
+
: undefined;
|
|
10900
|
+
const focusedInteract = Boolean(focusedInteractFrame);
|
|
10878
10901
|
useLayoutEffect(() => {
|
|
10879
10902
|
renderedFrameGeometryRef.current = Object.fromEntries(
|
|
10880
10903
|
canvasFrames.map(({ screen, geometry }) => [screen.id, geometry]),
|
|
@@ -11448,6 +11471,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
11448
11471
|
: null;
|
|
11449
11472
|
const boardSelectionBoxVisible =
|
|
11450
11473
|
!boardTextEditing &&
|
|
11474
|
+
!vectorEdit &&
|
|
11451
11475
|
(boardFileId
|
|
11452
11476
|
? (selectedLayerSelectorGroupsByScreen[boardFileId]?.length ?? 0)
|
|
11453
11477
|
: 0) <= 1 &&
|
|
@@ -11491,9 +11515,10 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
11491
11515
|
isolation: "isolate",
|
|
11492
11516
|
overscrollBehavior: "none",
|
|
11493
11517
|
touchAction: "none",
|
|
11518
|
+
visibility: focusedInteract ? "hidden" : undefined,
|
|
11494
11519
|
}}
|
|
11495
11520
|
>
|
|
11496
|
-
{showPixelGrid ? (
|
|
11521
|
+
{showPixelGrid && !focusedInteract ? (
|
|
11497
11522
|
<div
|
|
11498
11523
|
ref={pixelGridRef}
|
|
11499
11524
|
className="pointer-events-none absolute inset-0 opacity-60"
|
|
@@ -11506,7 +11531,8 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
11506
11531
|
/>
|
|
11507
11532
|
) : null}
|
|
11508
11533
|
|
|
11509
|
-
{
|
|
11534
|
+
{!focusedInteract &&
|
|
11535
|
+
showBoardStaticPreview &&
|
|
11510
11536
|
boardFrameGeometry &&
|
|
11511
11537
|
boardStaticPreviewViewport &&
|
|
11512
11538
|
boardStaticPreviewContent ? (
|
|
@@ -11570,8 +11596,13 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
11570
11596
|
{
|
|
11571
11597
|
left: 0,
|
|
11572
11598
|
top: 0,
|
|
11573
|
-
|
|
11599
|
+
right: focusedInteract ? 0 : undefined,
|
|
11600
|
+
bottom: focusedInteract ? 0 : undefined,
|
|
11601
|
+
transform: focusedInteractFrame
|
|
11602
|
+
? `translate(${surfaceSize.width / 2 - (SURFACE_PADDING + focusedInteractFrame.geometry.x + focusedInteractFrame.geometry.width / 2) * scale}px, ${surfaceSize.height / 2 - (SURFACE_PADDING + focusedInteractFrame.geometry.y + focusedInteractFrame.geometry.height / 2) * scale}px) scale(${scale})`
|
|
11603
|
+
: `translate(${pan.x}px, ${pan.y}px) scale(${scale})`,
|
|
11574
11604
|
transformOrigin: "top left",
|
|
11605
|
+
visibility: focusedInteract ? "hidden" : undefined,
|
|
11575
11606
|
// Controlled zoom also renders the world transform, so it must
|
|
11576
11607
|
// replace any counter-scale left by an imperative camera tick.
|
|
11577
11608
|
[CHROME_SCALE_CSS_VAR]: chromeScale,
|
|
@@ -11842,6 +11873,9 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
11842
11873
|
}
|
|
11843
11874
|
geometry={geometry}
|
|
11844
11875
|
measuredIframeHeights={measuredIframeHeights}
|
|
11876
|
+
focusedInteract={
|
|
11877
|
+
screen.id === interactScreenId && focusedInteract
|
|
11878
|
+
}
|
|
11845
11879
|
locked={lockedScreenIdSet.has(screen.id)}
|
|
11846
11880
|
screenContent={screenContentById.get(screen.id)}
|
|
11847
11881
|
bootDeferred={bootDeferredScreenIds.has(screen.id)}
|
|
@@ -12002,7 +12036,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
12002
12036
|
geometry={singleSelectedFrame.geometry}
|
|
12003
12037
|
chromeScale={chromeScale}
|
|
12004
12038
|
chromeSettling={chromeSettling}
|
|
12005
|
-
handlesEnabled={!readOnly}
|
|
12039
|
+
handlesEnabled={!readOnly && !focusedInteract}
|
|
12006
12040
|
showRotate
|
|
12007
12041
|
onStartResize={(handle, event) =>
|
|
12008
12042
|
beginResize(singleSelectedFrame.id, handle, event)
|
|
@@ -13389,6 +13423,7 @@ interface ScreenProps {
|
|
|
13389
13423
|
locked: boolean;
|
|
13390
13424
|
isActive: boolean;
|
|
13391
13425
|
interactMode: boolean;
|
|
13426
|
+
focusedInteract: boolean;
|
|
13392
13427
|
isSelected: boolean;
|
|
13393
13428
|
/** True while the current selection is an element INSIDE this screen (not
|
|
13394
13429
|
* the screen/frame itself) — see selectedElementScreenId. The screen's own
|
|
@@ -13490,6 +13525,7 @@ const Screen = memo(function Screen({
|
|
|
13490
13525
|
locked,
|
|
13491
13526
|
isActive,
|
|
13492
13527
|
interactMode,
|
|
13528
|
+
focusedInteract,
|
|
13493
13529
|
isSelected,
|
|
13494
13530
|
elementSelectedInScreen,
|
|
13495
13531
|
isTopScreen,
|
|
@@ -13538,7 +13574,10 @@ const Screen = memo(function Screen({
|
|
|
13538
13574
|
const display = screenDisplayName(screen, metadata);
|
|
13539
13575
|
const previewUrl = metadata.previewUrl ?? getPreviewUrl(screen.content);
|
|
13540
13576
|
const externalPreviewPendingOrigin = Boolean(previewUrl && !browserOrigin);
|
|
13541
|
-
const previewViewport = getScreenPreviewViewport(
|
|
13577
|
+
const previewViewport = getScreenPreviewViewport(
|
|
13578
|
+
focusedInteract ? geometry : metadata,
|
|
13579
|
+
geometry,
|
|
13580
|
+
);
|
|
13542
13581
|
const suppressNextClick = useRef(false);
|
|
13543
13582
|
// Overview viewport culling (PF22): mounting only. Unmounting a culled screen
|
|
13544
13583
|
// would lose its iframe's scroll/form/Alpine state, so it stays mounted and
|
|
@@ -13669,7 +13708,9 @@ const Screen = memo(function Screen({
|
|
|
13669
13708
|
useEffect(() => {
|
|
13670
13709
|
onHoverIntent?.(screen.id, hoverWantsLiveEditor);
|
|
13671
13710
|
}, [hoverWantsLiveEditor, onHoverIntent, screen.id]);
|
|
13672
|
-
const frameLabelHeight =
|
|
13711
|
+
const frameLabelHeight = focusedInteract
|
|
13712
|
+
? 0
|
|
13713
|
+
: FRAME_LABEL_HEIGHT * chromeScale;
|
|
13673
13714
|
const frameScreenWidth = geometry.width / Math.max(chromeScale, 0.001);
|
|
13674
13715
|
// Keep frame actions inside their own frame so closely spaced screens cannot
|
|
13675
13716
|
// cover one another. Narrow frames collapse the action to its familiar icon;
|
|
@@ -13710,6 +13751,7 @@ const Screen = memo(function Screen({
|
|
|
13710
13751
|
transform: geometry.rotation
|
|
13711
13752
|
? `rotate(${geometry.rotation}deg)`
|
|
13712
13753
|
: undefined,
|
|
13754
|
+
visibility: focusedInteract ? "visible" : undefined,
|
|
13713
13755
|
transformOrigin: `${geometry.width / 2}px ${frameLabelHeight + geometry.height / 2}px`,
|
|
13714
13756
|
zIndex: isTopScreen
|
|
13715
13757
|
? (geometry.z ?? 0) + TOP_SCREEN_Z_BOOST
|
|
@@ -13718,7 +13760,10 @@ const Screen = memo(function Screen({
|
|
|
13718
13760
|
>
|
|
13719
13761
|
<div
|
|
13720
13762
|
className="relative w-full cursor-default"
|
|
13721
|
-
style={{
|
|
13763
|
+
style={{
|
|
13764
|
+
height: frameLabelHeight,
|
|
13765
|
+
display: focusedInteract ? "none" : undefined,
|
|
13766
|
+
}}
|
|
13722
13767
|
onClick={(e) => {
|
|
13723
13768
|
e.stopPropagation();
|
|
13724
13769
|
if (suppressNextClick.current) {
|
|
@@ -13839,6 +13884,7 @@ const Screen = memo(function Screen({
|
|
|
13839
13884
|
fullViewVisible && "opacity-100",
|
|
13840
13885
|
)}
|
|
13841
13886
|
style={{
|
|
13887
|
+
display: focusedInteract ? "none" : undefined,
|
|
13842
13888
|
maxWidth: fullViewMaxWidth,
|
|
13843
13889
|
transform: `translate(-50%, -50%) scale(var(${CHROME_SCALE_CSS_VAR}, ${chromeScale}))`,
|
|
13844
13890
|
transformOrigin: "center center",
|
|
@@ -14097,6 +14143,7 @@ const Screen = memo(function Screen({
|
|
|
14097
14143
|
<ResizeHandles
|
|
14098
14144
|
active={false}
|
|
14099
14145
|
enabled={
|
|
14146
|
+
!focusedInteract &&
|
|
14100
14147
|
!selectionOutlined &&
|
|
14101
14148
|
!elementSelectedInScreen &&
|
|
14102
14149
|
!penActive &&
|
|
@@ -14120,7 +14167,9 @@ const Screen = memo(function Screen({
|
|
|
14120
14167
|
the screen has breakpointWidths set. Each frame shares the same
|
|
14121
14168
|
srcdoc content at a different viewport width. The active breakpoint
|
|
14122
14169
|
is highlighted and clicking a frame header sets the edit scope. */}
|
|
14123
|
-
{
|
|
14170
|
+
{!focusedInteract &&
|
|
14171
|
+
screen.breakpointWidths &&
|
|
14172
|
+
screen.breakpointWidths.length > 0 ? (
|
|
14124
14173
|
<BreakpointPreviewRow
|
|
14125
14174
|
screen={screen}
|
|
14126
14175
|
primaryGeometry={geometry}
|
|
@@ -14227,6 +14276,7 @@ function areScreenPropsEqual(prev: ScreenProps, next: ScreenProps) {
|
|
|
14227
14276
|
sameResolvedMetadata(prev.metadata, next.metadata) &&
|
|
14228
14277
|
sameFrameGeometry(prev.geometry, next.geometry) &&
|
|
14229
14278
|
prev.isActive === next.isActive &&
|
|
14279
|
+
prev.focusedInteract === next.focusedInteract &&
|
|
14230
14280
|
prev.isSelected === next.isSelected &&
|
|
14231
14281
|
prev.elementSelectedInScreen === next.elementSelectedInScreen &&
|
|
14232
14282
|
prev.isTopScreen === next.isTopScreen &&
|
|
@@ -23,11 +23,16 @@ import { cn } from "@/lib/utils";
|
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
25
|
AutoLayoutMatrix,
|
|
26
|
+
MarginProperties,
|
|
26
27
|
SizingField,
|
|
27
28
|
type AutoLayoutFlow,
|
|
28
29
|
type AutoLayoutGridTrackSizing,
|
|
29
30
|
type AutoLayoutGridValue,
|
|
31
|
+
type AutoLayoutMargin,
|
|
32
|
+
type AutoLayoutMarginTextValues,
|
|
33
|
+
type AutoLayoutMatrixLabels,
|
|
30
34
|
type AutoLayoutMatrixValue,
|
|
35
|
+
type AutoLayoutSidesMixed,
|
|
31
36
|
type ScrubInputChangeMeta,
|
|
32
37
|
} from "../inspector";
|
|
33
38
|
import { IconLayoutSettings } from "../inspector/design-icons";
|
|
@@ -367,6 +372,71 @@ export function gridValueForElement(element: ElementInfo): AutoLayoutGridValue {
|
|
|
367
372
|
};
|
|
368
373
|
}
|
|
369
374
|
|
|
375
|
+
function marginValuesForStyles(
|
|
376
|
+
styles: Record<string, string>,
|
|
377
|
+
inlineStyles?: Record<string, string>,
|
|
378
|
+
) {
|
|
379
|
+
const marginValue = (property: string) => {
|
|
380
|
+
const authored = inlineStyles?.[property];
|
|
381
|
+
return (
|
|
382
|
+
(isMixedValue(authored) || authored?.trim().toLowerCase() === "auto"
|
|
383
|
+
? authored
|
|
384
|
+
: styles[property]) || "0"
|
|
385
|
+
);
|
|
386
|
+
};
|
|
387
|
+
const raw = {
|
|
388
|
+
top: marginValue("marginTop"),
|
|
389
|
+
right: marginValue("marginRight"),
|
|
390
|
+
bottom: marginValue("marginBottom"),
|
|
391
|
+
left: marginValue("marginLeft"),
|
|
392
|
+
};
|
|
393
|
+
const value: AutoLayoutMargin = {
|
|
394
|
+
top: parseNumericValue(raw.top),
|
|
395
|
+
right: parseNumericValue(raw.right),
|
|
396
|
+
bottom: parseNumericValue(raw.bottom),
|
|
397
|
+
left: parseNumericValue(raw.left),
|
|
398
|
+
};
|
|
399
|
+
const mixed: AutoLayoutSidesMixed = {
|
|
400
|
+
top: isMixedValue(raw.top),
|
|
401
|
+
right: isMixedValue(raw.right),
|
|
402
|
+
bottom: isMixedValue(raw.bottom),
|
|
403
|
+
left: isMixedValue(raw.left),
|
|
404
|
+
};
|
|
405
|
+
const textValues: AutoLayoutMarginTextValues = {
|
|
406
|
+
top: !mixed.top && raw.top.trim() === "auto" ? "auto" : undefined,
|
|
407
|
+
right: !mixed.right && raw.right.trim() === "auto" ? "auto" : undefined,
|
|
408
|
+
bottom: !mixed.bottom && raw.bottom.trim() === "auto" ? "auto" : undefined,
|
|
409
|
+
left: !mixed.left && raw.left.trim() === "auto" ? "auto" : undefined,
|
|
410
|
+
};
|
|
411
|
+
return { value, mixed, textValues };
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function marginStylesForSides(
|
|
415
|
+
margin: AutoLayoutMargin,
|
|
416
|
+
sides: Array<keyof AutoLayoutMargin>,
|
|
417
|
+
): Record<string, string> {
|
|
418
|
+
const styles: Record<string, string> = {};
|
|
419
|
+
for (const side of sides) {
|
|
420
|
+
const property = `margin${side[0].toUpperCase()}${side.slice(1)}`;
|
|
421
|
+
styles[property] = `${margin[side]}px`;
|
|
422
|
+
}
|
|
423
|
+
return styles;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function marginInspectorLabels(
|
|
427
|
+
t: ReturnType<typeof useT>,
|
|
428
|
+
): Partial<AutoLayoutMatrixLabels> {
|
|
429
|
+
return {
|
|
430
|
+
margin: t("editPanel.labels.margin"),
|
|
431
|
+
linkMargin: t("editPanel.labels.linkMarginSides"),
|
|
432
|
+
unlinkMargin: t("editPanel.labels.unlinkMarginSides"),
|
|
433
|
+
marginTop: t("editPanel.labels.marginTop"),
|
|
434
|
+
marginRight: t("editPanel.labels.marginRight"),
|
|
435
|
+
marginBottom: t("editPanel.labels.marginBottom"),
|
|
436
|
+
marginLeft: t("editPanel.labels.marginLeft"),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
370
440
|
/**
|
|
371
441
|
* Style patch for a Grid-control change: template writes plus gap, with
|
|
372
442
|
* `gridAutoFlow: "row"` included only when converting a non-grid element
|
|
@@ -405,7 +475,10 @@ function FlexContainerControls({
|
|
|
405
475
|
onApplyLayoutFlow?: ApplyLayoutFlowHandler;
|
|
406
476
|
showSizingControls: boolean;
|
|
407
477
|
}) {
|
|
478
|
+
const t = useT();
|
|
408
479
|
const styles = element.computedStyles;
|
|
480
|
+
const marginLabels = marginInspectorLabels(t);
|
|
481
|
+
const marginProperties = marginValuesForStyles(styles, element.inlineStyles);
|
|
409
482
|
// The element's CURRENT layout flow as authored in code, read from its own
|
|
410
483
|
// computed `display`: block/flow-root/grid/etc. = "normal flow",
|
|
411
484
|
// flex/inline-flex = auto layout. We forward it so the AutoLayoutMatrix Flow
|
|
@@ -542,6 +615,9 @@ function FlexContainerControls({
|
|
|
542
615
|
left: isMixedValue(styles.paddingLeft),
|
|
543
616
|
},
|
|
544
617
|
paddingLinked,
|
|
618
|
+
margin: marginProperties.value,
|
|
619
|
+
marginMixed: marginProperties.mixed,
|
|
620
|
+
marginTextValues: marginProperties.textValues,
|
|
545
621
|
childSizing: {
|
|
546
622
|
horizontal: inferElementSizing(element, "horizontal"),
|
|
547
623
|
vertical: inferElementSizing(element, "vertical"),
|
|
@@ -570,6 +646,7 @@ function FlexContainerControls({
|
|
|
570
646
|
<div className="space-y-2">
|
|
571
647
|
<AutoLayoutMatrix
|
|
572
648
|
value={autoLayoutValue}
|
|
649
|
+
labels={marginLabels}
|
|
573
650
|
onFlowChange={(flow) => {
|
|
574
651
|
const nodeId = element.sourceId ?? element.pendingNodeId;
|
|
575
652
|
// A raw display:block leaves the children in flow, so they re-stack
|
|
@@ -694,6 +771,21 @@ function FlexContainerControls({
|
|
|
694
771
|
// each linked axis's representative value and applies both sides on
|
|
695
772
|
// the next real field edit, so no style write belongs here.
|
|
696
773
|
}}
|
|
774
|
+
onMarginChange={(nextMargin, meta, changedSides) => {
|
|
775
|
+
const patch = marginStylesForSides(nextMargin, changedSides);
|
|
776
|
+
const changeMeta =
|
|
777
|
+
meta &&
|
|
778
|
+
(meta.relativeDelta !== undefined || meta.relativeExpression)
|
|
779
|
+
? { ...meta, relativeDeltaProperties: Object.keys(patch) }
|
|
780
|
+
: meta;
|
|
781
|
+
if (onStylesChange) {
|
|
782
|
+
onStylesChange(patch, changeMeta);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
Object.entries(patch).forEach(([property, value]) =>
|
|
786
|
+
onStyleChange(property, value, changeMeta),
|
|
787
|
+
);
|
|
788
|
+
}}
|
|
697
789
|
onClipContentChange={(clipContent) =>
|
|
698
790
|
onStyleChange("overflow", clipContent ? "hidden" : "visible")
|
|
699
791
|
}
|
|
@@ -934,6 +1026,11 @@ export function LayoutContextProperties({
|
|
|
934
1026
|
const availableSizing = availableSizingForElement(element);
|
|
935
1027
|
const isContainer = isContainerElement(element);
|
|
936
1028
|
const aspectLock = useAspectRatioLock(element);
|
|
1029
|
+
const marginLabels = marginInspectorLabels(t);
|
|
1030
|
+
const marginProperties = marginValuesForStyles(
|
|
1031
|
+
element.computedStyles,
|
|
1032
|
+
element.inlineStyles,
|
|
1033
|
+
);
|
|
937
1034
|
|
|
938
1035
|
const childActions =
|
|
939
1036
|
flexChild || gridChild ? (
|
|
@@ -1170,6 +1267,28 @@ export function LayoutContextProperties({
|
|
|
1170
1267
|
</Tooltip>
|
|
1171
1268
|
</InspectorGridCell>
|
|
1172
1269
|
</InspectorGrid>
|
|
1270
|
+
<MarginProperties
|
|
1271
|
+
key={elementStableKey(element)}
|
|
1272
|
+
value={marginProperties.value}
|
|
1273
|
+
mixed={marginProperties.mixed}
|
|
1274
|
+
textValues={marginProperties.textValues}
|
|
1275
|
+
labels={marginLabels}
|
|
1276
|
+
onChange={(margin, meta, changedSides) => {
|
|
1277
|
+
const patch = marginStylesForSides(margin, changedSides);
|
|
1278
|
+
const changeMeta =
|
|
1279
|
+
meta &&
|
|
1280
|
+
(meta.relativeDelta !== undefined || meta.relativeExpression)
|
|
1281
|
+
? { ...meta, relativeDeltaProperties: Object.keys(patch) }
|
|
1282
|
+
: meta;
|
|
1283
|
+
if (onStylesChange) {
|
|
1284
|
+
onStylesChange(patch, changeMeta);
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
Object.entries(patch).forEach(([property, value]) =>
|
|
1288
|
+
onStyleChange(property, value, changeMeta),
|
|
1289
|
+
);
|
|
1290
|
+
}}
|
|
1291
|
+
/>
|
|
1173
1292
|
</PanelSection>
|
|
1174
1293
|
);
|
|
1175
1294
|
}
|