diff --git a/.changeset/bright-pandas-drag.md b/.changeset/bright-pandas-drag.md
new file mode 100644
index 00000000..a3a845de
--- /dev/null
+++ b/.changeset/bright-pandas-drag.md
@@ -0,0 +1,7 @@
+---
+'@ankhorage/studio': minor
+---
+
+Restore contextual Insert and Delete authoring, add placement-backed canvas drag and drop through
+the cross-platform adapter with deterministic session cleanup, and remove obsolete DnD wrappers
+and directional tree mutation APIs.
diff --git a/README.md b/README.md
index f9eb72f0..9c2d77b2 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
# @ankhorage/studio
-        
+        
Standalone Studio authoring package for Ankhorage apps.
@@ -29,7 +29,6 @@ Manage Studio development and projects through the Ankh CLI.
- [Architecture overview](././paradox/diagrams/architecture-overview.mmd)
- [Module relationships](././paradox/diagrams/module-relationships.mmd)
- [Export graph](././paradox/diagrams/export-graph.mmd)
-- [addNodeToTree sequence](././paradox/diagrams/sequences/add-node-to-tree.mmd)
- [appendStudioEventBinding sequence](././paradox/diagrams/sequences/append-studio-event-binding.mmd)
- [assessStudioBindingCompatibility sequence](././paradox/diagrams/sequences/assess-studio-binding-compatibility.mmd)
- [buildInsertCatalogEntries sequence](././paradox/diagrams/sequences/build-insert-catalog-entries.mmd)
@@ -40,6 +39,7 @@ Manage Studio development and projects through the Ankh CLI.
- [findNodeById sequence](././paradox/diagrams/sequences/find-node-by-id.mmd)
- [removeStudioEventBinding sequence](././paradox/diagrams/sequences/remove-studio-event-binding.mmd)
- [removeStudioPropBinding sequence](././paradox/diagrams/sequences/remove-studio-prop-binding.mmd)
+- [resolveInsertPlacement sequence](././paradox/diagrams/sequences/resolve-insert-placement.mmd)
- [resolveStudioInstancePropertyGroups sequence](././paradox/diagrams/sequences/resolve-studio-instance-property-groups.mmd)
- [resolveStudioSchemaValueMeta sequence](././paradox/diagrams/sequences/resolve-studio-schema-value-meta.mmd)
- [updateNodeInTree sequence](././paradox/diagrams/sequences/update-node-in-tree.mmd)
diff --git a/docs/studio-authoring-model.md b/docs/studio-authoring-model.md
index a537294b..6f39c8fc 100644
--- a/docs/studio-authoring-model.md
+++ b/docs/studio-authoring-model.md
@@ -10,7 +10,7 @@ This package now owns the package-neutral Studio authoring/model helpers used by
- component metadata contract shape used by authoring helpers
- empty screen starter template
- Studio ID generation helper
-- UI tree helpers for cloning, finding, updating, removing, adding, and moving nodes
+- UI tree helpers for cloning, finding, updating, removing, inserting, and placement-backed moving
- node placement validation/resolution
- insert catalog entry construction and placement resolution
- catalog entry node creation
@@ -19,7 +19,13 @@ This package now owns the package-neutral Studio authoring/model helpers used by
The package intentionally does not import Zora or any concrete component registry. Host packages pass component metadata through `StudioComponentMetaRegistry` when resolving placement, building insert catalog entries, or creating nodes.
-This keeps `@ankhorage/studio` as the authoring-model owner while letting `ankhorage4` and future hosts decide which component registry powers the Studio catalog.
+This keeps `@ankhorage/studio` as the authoring-model owner while letting the first-party Studio app
+and generated app hosts inject the same component registry that powers their Runtime rendering.
+
+Placement mutation is intentionally singular. `insertNodeAtPlacement`,
+`resolveMoveNodePlacement`, and `moveNodeToPlacement` are the canonical tree APIs. The older
+directional `addNodeToTree`, `moveNodeInTree`, and `moveStudioManifestNode` APIs are removed, as are
+the `@ankhorage/studio/dnd*` wrapper subpaths.
## Deliberately not moved here
@@ -32,11 +38,15 @@ This slice still does not move product shell or platform code. In particular, th
- panels
- React Native components
- Expo Router code
-- DnD provider/runtime implementation
+- package-neutral DnD provider/runtime implementation
- Supabase/storage implementation
- generated-app runtime composition code
- template catalog ownership
+The local generated Studio runtime may compose the shared cross-platform DnD adapter directly for
+its app-facing canvas UI. That integration does not change ownership of the package-neutral tree
+and placement model.
+
## Dependency rule
The authoring model may depend on `@ankhorage/contracts` for manifest and `UiNode` types. It must not import React, React Native, Expo, DnD, Supabase, Zora implementation modules, generated-app runtime composition code, or host-app implementation modules.
diff --git a/docs/studio-canvas-drag-model.md b/docs/studio-canvas-drag-model.md
index daf96fd8..3ff4148f 100644
--- a/docs/studio-canvas-drag-model.md
+++ b/docs/studio-canvas-drag-model.md
@@ -1,6 +1,7 @@
# Studio canvas interaction model
-`@ankhorage/studio/canvasDragModel` provides package-neutral helpers for Studio canvas node movement payloads and canvas placement slot selection.
+`@ankhorage/studio/canvasDragModel` provides package-neutral helpers for Studio canvas node
+movement payloads, placement slots, measured drop-zone geometry, and drag-preview text.
## Import
@@ -8,6 +9,9 @@
import {
createStudioCanvasDragPayload,
isStudioCanvasDragPayload,
+ resolveCanvasDragSession,
+ resolveCanvasDragPreviewText,
+ resolveCanvasDropZoneRect,
resolveCanvasDropZoneSlots,
} from '@ankhorage/studio/canvasDragModel';
```
@@ -18,7 +22,31 @@ import {
- runtime guard for canvas movement payloads
- valid canvas placement-zone detection
- resolving before, inside, and after placement slots
+- deriving drop-zone rectangles from measured Runtime node bounds
+- selecting concise authored text for the measured-bounds drag preview
+- resolving whether an active drag still belongs to the current edit selection and manifest tree
-## Host-owned concerns
+## Runtime integration
-Hosts still own the gesture implementation, React rendering, hover/focus state, styles, and concrete move execution.
+The generated local Studio host composes these helpers with `DropProvider`, `Draggable`,
+`Draggable.Handle`, and `Droppable` imported directly from
+`@ankhorage/react-native-reanimated-dnd-web`. It renders a 48-point handle only for the selected
+non-root node, keeps the rest of the canvas on the stationary-selection path, and shows a
+measured-bounds ghost while dragging.
+
+Every rendered Runtime node becomes a measured target while a drag is active. The screen surface
+supplies a synthetic root target on native, where the normal selection recorder intentionally does
+not wrap the root. More specific targets are registered before broad ancestor zones so nested
+placements win overlapping collision checks.
+
+The UI adapter owns transient drag and hover state and resets it after cancellation or commit. Each
+reset also advances the Draggable session identity, remounting the web adapter after it reports a
+drop so committed translation and `DROPPED` state cannot leak into the next interaction. The
+selected node ID is part of that identity, so changing selection also creates a fresh adapter
+instance.
+
+An active drag is exposed to Runtime measurement and the overlay only while Edit mode is active,
+the active node is still selected, and the node still exists in the current root. Selection loss,
+tree removal, and Preview transitions synchronously suppress drag geometry and clear transient
+state. A valid drop invokes the context's placement mutation exactly once. The package-neutral
+model remains free of gestures, React lifecycle, concrete ZORA metadata, and manifest persistence.
diff --git a/docs/studio-canvas-drop-zones.md b/docs/studio-canvas-drop-zones.md
index 2edd7d46..8cb89f65 100644
--- a/docs/studio-canvas-drop-zones.md
+++ b/docs/studio-canvas-drop-zones.md
@@ -1,6 +1,7 @@
# Studio canvas drop zones
-`@ankhorage/studio/canvasDropZones` provides package-neutral helpers for resolving valid canvas drop zones around a target node.
+`@ankhorage/studio/canvasDropZones` provides package-neutral helpers for resolving canvas drop zones
+around a rendered target node.
## Import
@@ -11,10 +12,14 @@ import { resolveCanvasDropZones, getValidCanvasDropZones } from '@ankhorage/stud
## Owned here
- resolving `before`, `inside`, and `after` drop zones
-- rejecting self-drops
-- validating placements through Studio component metadata
+- rejecting root, self, descendant, and no-op movement
+- validating placements through caller-provided Studio component metadata
+- preserving canonical placement failure codes and messages for invalid-zone feedback
- filtering valid drop zones
-## Host-owned concerns
+## Runtime integration
-Hosts still own pointer handling, drag/drop gestures, visual affordances, dialogs, and React lifecycle wiring.
+The package's generated Studio runtime owns pointer handling, direct adapter composition, visual
+affordances, and React lifecycle wiring. Other hosts may render the same package-neutral zone
+resolutions with their platform UI, but must execute successful drops through the canonical
+`NodePlacement` mutation instead of maintaining a second tree-moving algorithm.
diff --git a/docs/studio-insert-modal-model.md b/docs/studio-insert-modal-model.md
index 6bdfaed5..3101abcc 100644
--- a/docs/studio-insert-modal-model.md
+++ b/docs/studio-insert-modal-model.md
@@ -1,6 +1,7 @@
# Studio insert modal model
-`@ankhorage/studio/insertModalModel` provides package-neutral helpers for preparing insert catalog entries for insert modal UIs.
+`@ankhorage/studio/insertModalModel` provides package-neutral helpers for preparing insert catalog
+entries for contextual Insert UI.
## Import
@@ -19,6 +20,20 @@ import {
- resolving node display labels from aliases and component metadata
- formatting placement hints for enabled catalog entries
-## Host-owned concerns
+## Studio integration
-Hosts still own rendering modals, search input state, selected category UI, concrete component metadata such as Zora metadata, and insert execution.
+The first-party Studio shell renders the contextual Insert surface with ordinary ZORA `Modal`,
+`Input`, `ListSection`, and `ListRow` components. The app bar says **Add child** when the selected
+node accepts a direct child and **Insert** when placement falls back to an ancestor or sibling.
+Search and category state are transient; enabled rows show their resolved placement hint, while
+disabled rows retain the catalog's exact explanation.
+
+`StudioProvider` receives concrete component metadata from the generated app and exposes the
+package-neutral catalog, insert, delete, and placement-backed move capabilities through the Studio
+context. Insertion creates nodes from the catalog blueprint and defaults, persists through the
+canonical manifest placement mutation, and selects the inserted node. Deletion uses a ZORA
+confirmation dialog, rejects the screen root, removes the complete subtree and its bindings, and
+selects the deleted node's former parent.
+
+There is no parallel Toolbox or Studio-only component registry. Hosts still own which concrete
+metadata registry they inject and where the contextual app-bar augmentation is mounted.
diff --git a/docs/studio-manifest-state.md b/docs/studio-manifest-state.md
index 97865aab..4f007ff1 100644
--- a/docs/studio-manifest-state.md
+++ b/docs/studio-manifest-state.md
@@ -28,6 +28,15 @@ Host packages still own lifecycle and concrete integration inputs:
Where a mutation needs component placement rules, callers pass `StudioComponentMetaRegistry` instead of this package importing Zora.
+Insert and move wrappers delegate to the same canonical tree placement functions exported from the
+root authoring model. `resolveMoveNodePlacement` validates the requested parent, reference, index,
+component compatibility, root/self/descendant safety, and same-parent index adjustment before a
+move is applied. This keeps Insert UI and canvas DnD on one `NodePlacement` contract rather than
+directional or gesture-specific mutation APIs.
+
+Deleting a node removes the full subtree. Data and event bindings keyed by, or owned by, any node
+in that subtree are removed in the same immutable manifest mutation.
+
## Import path
Use the manifest-state subpath when consuming these helpers:
diff --git a/docs/studio-public-contracts.md b/docs/studio-public-contracts.md
index 8f3397b2..0b478aad 100644
--- a/docs/studio-public-contracts.md
+++ b/docs/studio-public-contracts.md
@@ -17,6 +17,17 @@ to integrate the Studio package boundary:
- Studio command/event contracts
- the type-only context value shape
+`StudioContextValue` now carries the caller-injected `componentMeta` registry and concrete
+`insertFromCatalogEntry`, `moveNodeToPlacement`, and `deleteNode` capabilities. `StudioProvider`
+requires that registry so the generated Studio app uses the same component rules as its Runtime.
+`resolveMoveNodePlacement` is public for validating and normalizing a placement before mutation;
+`invalid-reference` identifies incoherent sibling references.
+
+The obsolete `addNodeToTree`, `moveNodeInTree`, directional `moveStudioManifestNode`, and
+`StudioContextValue.moveNode` APIs have been removed. The `@ankhorage/studio/dnd`,
+`@ankhorage/studio/dnd/primitives`, and `@ankhorage/studio/dnd/state` exports are also removed;
+app-facing canvas code imports the maintained cross-platform adapter directly.
+
## Deliberately not moved here
This slice does not move product UI or app-host implementation code. In particular, this package
diff --git a/docs/studio-runtime-selection.md b/docs/studio-runtime-selection.md
index 8bc253f6..a3ceaaae 100644
--- a/docs/studio-runtime-selection.md
+++ b/docs/studio-runtime-selection.md
@@ -5,6 +5,20 @@ Generated apps compose Studio selection through the normal Runtime renderer conf
selection. Edit mode supplies `interactionPolicy="passive"` only to components that explicitly
support the canonical policy; Preview restores `enabled`.
+The same root selection surface owns canvas drag composition in Edit mode. A selected non-root node
+gets one 48-point `Draggable.Handle`; the selected component itself remains on the stationary tap
+path. The handle and every drop target use `@ankhorage/react-native-reanimated-dnd-web` directly,
+so native and web share the adapter contract without `@ankhorage/studio/dnd*` wrapper APIs. Preview
+mounts no drag overlay and clears an active drag if mode changes.
+
+Starting a drag activates public geometry measurement for every rendered Runtime node. Web uses
+DOM descendant bounds and native uses `measureInWindow`; the root surface contributes its own
+bounds when native root instrumentation is intentionally absent. Before, inside, and after zones
+are resolved through caller-injected component metadata and the canonical `NodePlacement` rules.
+Invalid zones remain visible with their structured reason. A measured-bounds ghost includes the
+component label and the first useful authored text property. Cancellation and commit both release
+drag geometry, hover state, and the ghost.
+
Stationary native Runtime selection remains supported and was validated on Android: stationary
Edit taps select the deepest intended node once, movement and scrolling cancel unintended
selection, passive interaction preserves nested scrolling and authored state, and Preview restores
@@ -41,7 +55,8 @@ refresh it without a layout-changing wrapper or private React Native/Fabric APIs
On web, Runtime-node registration stores a lazy `getResizeTargets()` callback. Descendants are not
traversed and are not observed merely because a node rendered. Inactive registration changes also
avoid a complete scan of the Runtime-node registry. Only the selected node and visible unsupported
-nodes activate resize targets. Selection or Edit/Preview changes compute the complete desired
+nodes activate resize targets while idle; an active canvas drag temporarily activates every
+rendered Runtime node. Selection, drag, or Edit/Preview changes compute the complete desired
target set, observe newly required elements, and unobserve elements no longer required. Because the
set is deduplicated before diffing, a shared descendant is observed once and remains observed while
any active measurement still requires it.
@@ -51,7 +66,8 @@ selection surface. Web selected chrome and unsupported overlays both use `pointe
never intercept authored input. Scroll, viewport resize, responsive layout, and authored-root
`onLayout` refresh applicable geometry. Changing or clearing selection immediately removes the
previous web outline. Preview releases authoring ResizeObserver targets and renders neither
-selected nor unsupported chrome. Unmount disconnects the observer and clears desired-target
+selected chrome, unsupported chrome, nor canvas drag affordances. Unmount disconnects the observer
+and clears desired-target
ownership; navigation and active measurement removal cancel pending work once no indicator remains.
The generated Studio shell synchronizes the current app pathname into `StudioProvider`. Studio
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 8015bc89..29726ccc 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -9,23 +9,4 @@ export default createConfig({
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
files: ['src/**/*.ts', 'scripts/**/*.ts'],
- overrides: [
- {
- files: ['src/dnd/**/*.ts'],
- rules: {
- 'no-restricted-imports': [
- 'error',
- {
- paths: [
- {
- name: 'react-native-reanimated-dnd',
- message:
- "Forbidden in Studio. Use '@ankhorage/react-native-reanimated-dnd-web' directly instead.",
- },
- ],
- },
- ],
- },
- },
- ],
});
diff --git a/knip.config.ts b/knip.config.ts
index f0d4e8f4..0a98d0a2 100644
--- a/knip.config.ts
+++ b/knip.config.ts
@@ -12,9 +12,6 @@ export default createKnipConfig({
'src/core/StudioContext.ts',
'src/core/StudioProvider.ts',
'src/core/studioPackageBoundary.ts',
- 'src/dnd/index.ts',
- 'src/dnd/primitives.ts',
- 'src/dnd/state.ts',
'src/runtime/index.ts',
'src/runtime/actionSuppression.ts',
'src/runtime/appExtensionRegistry.ts',
diff --git a/package.json b/package.json
index 461966da..c940f301 100644
--- a/package.json
+++ b/package.json
@@ -40,18 +40,6 @@
"types": "./dist/cli/index.d.ts",
"import": "./dist/cli/index.js"
},
- "./dnd": {
- "types": "./dist/dnd/index.d.ts",
- "import": "./dist/dnd/index.js"
- },
- "./dnd/primitives": {
- "types": "./dist/dnd/primitives.d.ts",
- "import": "./dist/dnd/primitives.js"
- },
- "./dnd/state": {
- "types": "./dist/dnd/state.d.ts",
- "import": "./dist/dnd/state.js"
- },
"./runtime": {
"types": "./dist/runtime/index.d.ts",
"import": "./dist/runtime/index.js"
diff --git a/paradox/badges/npm.svg b/paradox/badges/npm.svg
index 16f0aa77..c5e3a65b 100644
--- a/paradox/badges/npm.svg
+++ b/paradox/badges/npm.svg
@@ -1,7 +1,7 @@
-
-npm: v0.13.0
+
+npm: v0.14.0
npm
-v0.13.0
+v0.14.0
diff --git a/paradox/diagrams/architecture-overview.mmd b/paradox/diagrams/architecture-overview.mmd
index 7140244f..a996dabe 100644
--- a/paradox/diagrams/architecture-overview.mmd
+++ b/paradox/diagrams/architecture-overview.mmd
@@ -179,12 +179,6 @@ graph TD
module_src_core_StudioProvider_ts --> module_src_routeUtils_ts
module_src_core_StudioProvider_ts --> module_src_studioSelectionModel_ts
module_src_core_StudioProvider_ts --> module_src_ui_admin_AuthAdminSession_tsx
- module_src_dnd_index_ts["src/dnd/index.ts"]
- package__ankhorage_studio -.-> module_src_dnd_index_ts
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- package__ankhorage_studio -.-> module_src_dnd_primitives_ts
- module_src_dnd_state_ts["src/dnd/state.ts"]
- package__ankhorage_studio -.-> module_src_dnd_state_ts
module_src_externalApiApi_ts["src/externalApiApi.ts"]
package__ankhorage_studio -.-> module_src_externalApiApi_ts
module_src_externalApiApi_ts --> module_src_core_constants_ts
@@ -811,11 +805,14 @@ graph TD
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_test_ts
module_src_runtime_stationarySelection_ts["src/runtime/stationarySelection.ts"]
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_ts
+ module_src_runtime_stationarySelection_ts --> module_src_canvasDragModel_ts
+ module_src_runtime_stationarySelection_ts --> module_src_index_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorSettleCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts --> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts["src/runtime/stationarySelectionCoordinator.test.ts"]
package__ankhorage_studio -.-> module_src_runtime_stationarySelectionCoordinator_test_ts
module_src_runtime_stationarySelectionCoordinator_test_ts --> module_src_runtime_stationarySelectionCoordinator_ts
@@ -1100,17 +1097,46 @@ graph TD
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
package__ankhorage_studio -.-> module_src_ui_AnkhStudio_ts
module_src_ui_AnkhStudio_ts --> module_src_core_StudioContext_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_test_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_StudioCanvasDndOverlay_test_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_insertModalModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_ui_canvas_canvasDndInteraction_ts
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
package__ankhorage_studio -.-> module_src_ui_studioAppBarModel_ts
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioInsertDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx --> module_src_index_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_test_ts
module_src_ui_useStudioAppBarAugmentation_test_ts --> module_src_ui_studioAppBarModel_ts
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioAdminRouteModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_studioAppBarModel_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioInsertDialog_tsx
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
package__ankhorage_studio -.-> module_src_upsertExternalApiDataSource_ts
module_src_utils_treeUtils_ts["src/utils/treeUtils.ts"]
diff --git a/paradox/diagrams/export-graph.mmd b/paradox/diagrams/export-graph.mmd
index ad2820bb..7275df07 100644
--- a/paradox/diagrams/export-graph.mmd
+++ b/paradox/diagrams/export-graph.mmd
@@ -47,9 +47,6 @@ graph LR
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -301,7 +298,13 @@ graph LR
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -314,9 +317,6 @@ graph LR
export_ActionDefinition["ActionDefinition"]
module_src_index_ts --> export_ActionDefinition
export_ActionDefinition -.-> export_StudioActionPayloadSchema
- export_addNodeToTree["addNodeToTree"]
- module_src_index_ts --> export_addNodeToTree
- export_addNodeToTree -.-> export_StudioComponentMetaRegistry
export_appendStudioEventBinding["appendStudioEventBinding"]
module_src_bindingMutationModel_ts --> export_appendStudioEventBinding
export_assessStudioBindingCompatibility["assessStudioBindingCompatibility"]
@@ -413,8 +413,6 @@ graph LR
module_src_index_ts --> export_InsertRecipeNode
export_ModuleDefinition["ModuleDefinition"]
module_src_index_ts --> export_ModuleDefinition
- export_moveNodeInTree["moveNodeInTree"]
- module_src_index_ts --> export_moveNodeInTree
export_moveNodeToPlacement["moveNodeToPlacement"]
module_src_index_ts --> export_moveNodeToPlacement
export_moveNodeToPlacement -.-> export_MoveNodeToPlacementArgs
@@ -494,6 +492,10 @@ graph LR
export_resolveInsertPlacement -.-> export_PlacementKind
export_resolveInsertPlacement -.-> export_PlacementResolutionResult
export_resolveInsertPlacement -.-> export_StudioComponentMetaRegistry
+ export_resolveMoveNodePlacement["resolveMoveNodePlacement"]
+ module_src_index_ts --> export_resolveMoveNodePlacement
+ export_resolveMoveNodePlacement -.-> export_MoveNodeToPlacementArgs
+ export_resolveMoveNodePlacement -.-> export_PlacementResolutionResult
export_resolveStudioBindableEvents["resolveStudioBindableEvents"]
module_src_bindingMetadataModel_ts --> export_resolveStudioBindableEvents
export_resolveStudioBindableEvents -.-> export_StudioBindableEventOption
@@ -568,6 +570,7 @@ graph LR
export_StudioContextValue -.-> export_InsertCatalogEntry
export_StudioContextValue -.-> export_NodePlacement
export_StudioContextValue -.-> export_StudioAdminRouteId
+ export_StudioContextValue -.-> export_StudioComponentMetaRegistry
export_StudioContextValue -.-> export_StudioLocale
export_StudioContextValue -.-> export_StudioManifest
export_StudioContextValue -.-> export_StudioMode
diff --git a/paradox/diagrams/module-relationships.mmd b/paradox/diagrams/module-relationships.mmd
index eaf03b5e..32eb4519 100644
--- a/paradox/diagrams/module-relationships.mmd
+++ b/paradox/diagrams/module-relationships.mmd
@@ -47,9 +47,6 @@ graph LR
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -301,7 +298,13 @@ graph LR
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -657,11 +660,14 @@ graph LR
module_src_runtime_previewRuntimeConfig_ts --> module_src_runtime_previewRegistry_ts
module_src_runtime_runtimeNodeMeasurement_test_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_public_test_ts --> module_src_runtime_index_ts
+ module_src_runtime_stationarySelection_ts --> module_src_canvasDragModel_ts
+ module_src_runtime_stationarySelection_ts --> module_src_index_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorSettleCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts --> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelectionInputState_test_ts --> module_src_runtime_stationarySelectionInputState_ts
module_src_runtime_useRuntimeAction_ts --> module_src_runtime_runtimeActions_ts
@@ -804,11 +810,28 @@ graph LR
module_src_ui_admin_pages_ThemeAdminPage_tsx --> module_src_ui_admin_pages_adminThemeHarmony_ts
module_src_ui_admin_pages_ThemeAdminPage_tsx --> module_src_ui_admin_pages_adminThemeModel_ts
module_src_ui_AnkhStudio_ts --> module_src_core_StudioContext_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_insertModalModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_index_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_test_ts --> module_src_ui_studioAppBarModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioAdminRouteModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_studioAppBarModel_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioInsertDialog_tsx
module_src_utils_treeUtils_ts --> module_src_index_ts
module_src_workspacePlatform_test_ts --> module_src_workspacePlatform_ts
module_src_workspaceSearch_ts --> module_src_projectWorkspaceContracts_ts
diff --git a/paradox/diagrams/sequences/add-node-to-tree.mmd b/paradox/diagrams/sequences/add-node-to-tree.mmd
deleted file mode 100644
index a24e4a63..00000000
--- a/paradox/diagrams/sequences/add-node-to-tree.mmd
+++ /dev/null
@@ -1,5 +0,0 @@
-sequenceDiagram
- participant participant_addNodeToTree as addNodeToTree
- participant participant_canAcceptChild as canAcceptChild
- participant_addNodeToTree->>participant_canAcceptChild: canAcceptChild()
- participant_canAcceptChild-->>participant_addNodeToTree: return
diff --git a/paradox/diagrams/sequences/resolve-insert-placement.mmd b/paradox/diagrams/sequences/resolve-insert-placement.mmd
index b5ec5e20..f867ae52 100644
--- a/paradox/diagrams/sequences/resolve-insert-placement.mmd
+++ b/paradox/diagrams/sequences/resolve-insert-placement.mmd
@@ -12,6 +12,7 @@ sequenceDiagram
participant_visit->>participant_visit: visit()
participant_visit->>participant_visit: visit()
participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
participant_visit->>participant_resolveRouteScreenFilePath: resolveRouteScreenFilePath()
participant_resolveRouteScreenFilePath->>participant_normalizeRel: normalizeRel()
participant_normalizeRel-->>participant_resolveRouteScreenFilePath: return
@@ -19,8 +20,7 @@ sequenceDiagram
participant_visit-->>participant_visit: return
participant_visit-->>participant_visit: return
participant_visit-->>participant_visit: return
- participant_visit-->>participant_findNodeWithParent: return
- participant_findNodeWithParent->>participant_visit: visit()
+ participant_visit-->>participant_visit: return
participant_visit-->>participant_findNodeWithParent: return
participant_findNodeWithParent-->>participant_resolveInsertPlacement: return
participant_resolveInsertPlacement->>participant_validateNodePlacement: validateNodePlacement()
diff --git a/paradox/exports.json b/paradox/exports.json
index 8dbd6d96..82441ded 100644
--- a/paradox/exports.json
+++ b/paradox/exports.json
@@ -8,7 +8,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 384,
+ "line": 385,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -26,7 +26,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 290,
+ "line": 291,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -71,38 +71,6 @@
],
"structuredRows": []
},
- {
- "name": "addNodeToTree",
- "description": null,
- "isReadme": false,
- "examples": [],
- "kind": "value",
- "modulePath": "src/index.ts",
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 606,
- "column": 14
- },
- "exportPaths": ["src/index.ts"],
- "relatedSymbols": ["StudioComponentMetaRegistry"],
- "signatures": [
- {
- "label": "(args: { root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: \"append\" | \"prepend\"; }) => UiNode",
- "parameters": [
- {
- "name": "args",
- "type": "{ root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: \"append\" | \"prepend\"; }",
- "required": true,
- "description": null
- }
- ],
- "returnType": "UiNode",
- "returnDescription": null
- }
- ],
- "members": [],
- "structuredRows": []
- },
{
"name": "appendStudioEventBinding",
"description": null,
@@ -200,7 +168,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1318,
+ "line": 1327,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -232,7 +200,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 765,
+ "line": 703,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -264,7 +232,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 531,
+ "line": 532,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -372,7 +340,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1237,
+ "line": 1246,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -556,7 +524,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 548,
+ "line": 549,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -632,7 +600,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 524,
+ "line": 525,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -664,7 +632,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1163,
+ "line": 1172,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -696,7 +664,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 268,
+ "line": 269,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -785,7 +753,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 250,
+ "line": 251,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -825,7 +793,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 227,
+ "line": 228,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -843,7 +811,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 278,
+ "line": 279,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -861,7 +829,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 256,
+ "line": 257,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -948,7 +916,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 224,
+ "line": 225,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -966,7 +934,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 225,
+ "line": 226,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -984,7 +952,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 273,
+ "line": 274,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1078,7 +1046,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 995,
+ "line": 965,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1110,7 +1078,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 938,
+ "line": 908,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1157,7 +1125,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 945,
+ "line": 915,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1190,7 +1158,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 235,
+ "line": 236,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1244,7 +1212,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 243,
+ "line": 244,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1291,7 +1259,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 230,
+ "line": 231,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1324,7 +1292,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 298,
+ "line": 299,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1362,50 +1330,6 @@
],
"structuredRows": []
},
- {
- "name": "moveNodeInTree",
- "description": null,
- "isReadme": false,
- "examples": [],
- "kind": "value",
- "modulePath": "src/index.ts",
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 639,
- "column": 14
- },
- "exportPaths": ["src/index.ts"],
- "relatedSymbols": [],
- "signatures": [
- {
- "label": "(root: UiNode, nodeId: string, direction: \"up\" | \"down\") => UiNode",
- "parameters": [
- {
- "name": "direction",
- "type": "\"up\" | \"down\"",
- "required": true,
- "description": null
- },
- {
- "name": "nodeId",
- "type": "string",
- "required": true,
- "description": null
- },
- {
- "name": "root",
- "type": "UiNode",
- "required": true,
- "description": null
- }
- ],
- "returnType": "UiNode",
- "returnDescription": null
- }
- ],
- "members": [],
- "structuredRows": []
- },
{
"name": "moveNodeToPlacement",
"description": null,
@@ -1415,7 +1339,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1063,
+ "line": 1101,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1447,7 +1371,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1022,
+ "line": 992,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1494,7 +1418,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1029,
+ "line": 999,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1592,7 +1516,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 205,
+ "line": 206,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1643,7 +1567,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 217,
+ "line": 218,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -1661,7 +1585,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 210,
+ "line": 211,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2137,7 +2061,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 588,
+ "line": 589,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -2269,7 +2193,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 893,
+ "line": 863,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2301,7 +2225,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1360,
+ "line": 1369,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2333,7 +2257,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 832,
+ "line": 802,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2356,6 +2280,38 @@
"members": [],
"structuredRows": []
},
+ {
+ "name": "resolveMoveNodePlacement",
+ "description": null,
+ "isReadme": false,
+ "examples": [],
+ "kind": "function",
+ "modulePath": "src/index.ts",
+ "sourceLocation": {
+ "filePath": "src/index.ts",
+ "line": 1033,
+ "column": 1
+ },
+ "exportPaths": ["src/index.ts"],
+ "relatedSymbols": ["MoveNodeToPlacementArgs", "PlacementResolutionResult"],
+ "signatures": [
+ {
+ "label": "(args: MoveNodeToPlacementArgs) => PlacementResolutionResult",
+ "parameters": [
+ {
+ "name": "args",
+ "type": "MoveNodeToPlacementArgs",
+ "required": true,
+ "description": null
+ }
+ ],
+ "returnType": "PlacementResolutionResult",
+ "returnDescription": null
+ }
+ ],
+ "members": [],
+ "structuredRows": []
+ },
{
"name": "resolveStudioBindableEvents",
"description": null,
@@ -2561,7 +2517,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1130,
+ "line": 1139,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -2658,7 +2614,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 282,
+ "line": 283,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2698,7 +2654,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 280,
+ "line": 281,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -2716,7 +2672,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 288,
+ "line": 289,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3186,7 +3142,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 323,
+ "line": 324,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3204,7 +3160,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 307,
+ "line": 308,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3237,7 +3193,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 312,
+ "line": 313,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3284,7 +3240,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 319,
+ "line": 320,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3302,7 +3258,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 339,
+ "line": 340,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3310,6 +3266,7 @@
"InsertCatalogEntry",
"NodePlacement",
"StudioAdminRouteId",
+ "StudioComponentMetaRegistry",
"StudioLocale",
"StudioManifest",
"StudioMode",
@@ -3371,6 +3328,13 @@
"required": true,
"description": null
},
+ {
+ "name": "componentMeta",
+ "kind": "property",
+ "type": "StudioComponentMetaRegistry",
+ "required": true,
+ "description": null
+ },
{
"name": "deleteGeneratedApi",
"kind": "property",
@@ -3448,13 +3412,6 @@
"required": true,
"description": null
},
- {
- "name": "moveNode",
- "kind": "property",
- "type": "(id: StudioNodeId, direction: \"up\" | \"down\") => void",
- "required": true,
- "description": null
- },
{
"name": "moveNodeToPlacement",
"kind": "property",
@@ -3705,7 +3662,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 332,
+ "line": 333,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3723,7 +3680,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 321,
+ "line": 322,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4539,7 +4496,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 476,
+ "line": 477,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -4557,7 +4514,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 560,
+ "line": 561,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -4651,7 +4608,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1180,
+ "line": 1189,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4689,7 +4646,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 777,
+ "line": 715,
"column": 1
},
"exportPaths": ["src/index.ts"],
diff --git a/paradox/exports.md b/paradox/exports.md
index 59f993cc..876e08cf 100644
--- a/paradox/exports.md
+++ b/paradox/exports.md
@@ -4,13 +4,13 @@
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:384:14`
+Source: `src/index.ts:385:14`
## ActionDefinition
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:290:1`
+Source: `src/index.ts:291:1`
### Members
@@ -22,18 +22,6 @@ Source: `src/index.ts:290:1`
| requiresPayload | property | `boolean` | yes | |
| type | property | `ActionType` | yes | |
-## addNodeToTree
-
-Kind: `value`
-Module: `src/index.ts`
-Source: `src/index.ts:606:14`
-
-### Signatures
-
-- `(args: { root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: "append" | "prepend"; }) => UiNode`
- - args: `{ root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: "append" | "prepend"; }`
- - returns: `UiNode`
-
## appendStudioEventBinding
Kind: `function`
@@ -66,7 +54,7 @@ Source: `src/bindingSchemaModel.ts:43:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1318:1`
+Source: `src/index.ts:1327:1`
### Signatures
@@ -78,7 +66,7 @@ Source: `src/index.ts:1318:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:765:1`
+Source: `src/index.ts:703:1`
### Signatures
@@ -90,7 +78,7 @@ Source: `src/index.ts:765:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:531:14`
+Source: `src/index.ts:532:14`
### Signatures
@@ -128,7 +116,7 @@ Source: `src/bindingSchemaModel.ts:33:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1237:1`
+Source: `src/index.ts:1246:1`
### Signatures
@@ -192,7 +180,7 @@ Source: `src/bindingDiagnosticsModel.ts:20:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:548:14`
+Source: `src/index.ts:549:14`
### Signatures
@@ -218,7 +206,7 @@ Source: `src/bindingOperationModel.ts:24:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:524:14`
+Source: `src/index.ts:525:14`
### Signatures
@@ -230,7 +218,7 @@ Source: `src/index.ts:524:14`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1163:1`
+Source: `src/index.ts:1172:1`
### Signatures
@@ -242,7 +230,7 @@ Source: `src/index.ts:1163:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:268:1`
+Source: `src/index.ts:269:1`
### Members
@@ -263,7 +251,7 @@ Source: `src/index.ts:268:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:250:1`
+Source: `src/index.ts:251:1`
### Members
@@ -277,19 +265,19 @@ Source: `src/index.ts:250:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:227:1`
+Source: `src/index.ts:228:1`
## InsertCatalogEntry
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:278:1`
+Source: `src/index.ts:279:1`
## InsertCatalogEntryBase
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:256:1`
+Source: `src/index.ts:257:1`
### Members
@@ -309,19 +297,19 @@ Source: `src/index.ts:256:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:224:1`
+Source: `src/index.ts:225:1`
## InsertCatalogEntryStatus
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:225:1`
+Source: `src/index.ts:226:1`
## InsertCatalogRecipeEntry
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:273:1`
+Source: `src/index.ts:274:1`
### Members
@@ -342,7 +330,7 @@ Source: `src/index.ts:273:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:995:1`
+Source: `src/index.ts:965:1`
### Signatures
@@ -354,7 +342,7 @@ Source: `src/index.ts:995:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:938:1`
+Source: `src/index.ts:908:1`
### Members
@@ -369,7 +357,7 @@ Source: `src/index.ts:938:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:945:1`
+Source: `src/index.ts:915:1`
### Members
@@ -382,7 +370,7 @@ Source: `src/index.ts:945:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:235:1`
+Source: `src/index.ts:236:1`
### Members
@@ -398,7 +386,7 @@ Source: `src/index.ts:235:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:243:1`
+Source: `src/index.ts:244:1`
### Members
@@ -413,7 +401,7 @@ Source: `src/index.ts:243:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:230:1`
+Source: `src/index.ts:231:1`
### Members
@@ -426,7 +414,7 @@ Source: `src/index.ts:230:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:298:1`
+Source: `src/index.ts:299:1`
### Members
@@ -437,25 +425,11 @@ Source: `src/index.ts:298:1`
| name | property | `string` | yes | |
| ui | property | `{ modal?: { title: string; }; } \| undefined` | no | |
-## moveNodeInTree
-
-Kind: `value`
-Module: `src/index.ts`
-Source: `src/index.ts:639:14`
-
-### Signatures
-
-- `(root: UiNode, nodeId: string, direction: "up" | "down") => UiNode`
- - direction: `"up" | "down"`
- - nodeId: `string`
- - root: `UiNode`
- - returns: `UiNode`
-
## moveNodeToPlacement
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1063:1`
+Source: `src/index.ts:1101:1`
### Signatures
@@ -467,7 +441,7 @@ Source: `src/index.ts:1063:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:1022:1`
+Source: `src/index.ts:992:1`
### Members
@@ -482,7 +456,7 @@ Source: `src/index.ts:1022:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:1029:1`
+Source: `src/index.ts:999:1`
### Members
@@ -516,7 +490,7 @@ Source: `src/index.ts:193:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:205:1`
+Source: `src/index.ts:206:1`
### Members
@@ -535,13 +509,13 @@ Source: `src/index.ts:184:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:217:1`
+Source: `src/index.ts:218:1`
## PlacementValidationResult
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:210:1`
+Source: `src/index.ts:211:1`
## ProjectAuthDiagnostic
@@ -689,7 +663,7 @@ Source: `src/projectWorkspaceContracts.ts:16:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:588:14`
+Source: `src/index.ts:589:14`
### Signatures
@@ -731,7 +705,7 @@ Source: `src/bindingMutationModel.ts:22:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:893:1`
+Source: `src/index.ts:863:1`
### Signatures
@@ -743,7 +717,7 @@ Source: `src/index.ts:893:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1360:1`
+Source: `src/index.ts:1369:1`
### Signatures
@@ -755,7 +729,7 @@ Source: `src/index.ts:1360:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:832:1`
+Source: `src/index.ts:802:1`
### Signatures
@@ -763,6 +737,18 @@ Source: `src/index.ts:832:1`
- args: `{ root: UiNode; targetNodeId: string; childType: string; componentMeta: StudioComponentMetaRegistry; kind: PlacementKind; }`
- returns: `PlacementResolutionResult`
+## resolveMoveNodePlacement
+
+Kind: `function`
+Module: `src/index.ts`
+Source: `src/index.ts:1033:1`
+
+### Signatures
+
+- `(args: MoveNodeToPlacementArgs) => PlacementResolutionResult`
+ - args: `MoveNodeToPlacementArgs`
+ - returns: `PlacementResolutionResult`
+
## resolveStudioBindableEvents
Kind: `function`
@@ -833,7 +819,7 @@ Source: `src/bindingSchemaModel.ts:14:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:1130:14`
+Source: `src/index.ts:1139:14`
| id | label | description | category |
| -------------- | -------------- | ---------------------------------------- | -------- |
@@ -863,7 +849,7 @@ Source: `src/index.ts:88:14`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:282:1`
+Source: `src/index.ts:283:1`
### Members
@@ -877,13 +863,13 @@ Source: `src/index.ts:282:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:280:1`
+Source: `src/index.ts:281:1`
## StudioActionPayloadSchema
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:288:1`
+Source: `src/index.ts:289:1`
## StudioAdminRouteId
@@ -1037,13 +1023,13 @@ Source: `src/bindingAuthoringContracts.ts:29:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:323:1`
+Source: `src/index.ts:324:1`
## StudioComponentBlueprint
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:307:1`
+Source: `src/index.ts:308:1`
### Members
@@ -1056,7 +1042,7 @@ Source: `src/index.ts:307:1`
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:312:1`
+Source: `src/index.ts:313:1`
### Members
@@ -1071,13 +1057,13 @@ Source: `src/index.ts:312:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:319:1`
+Source: `src/index.ts:320:1`
## StudioContextValue
Kind: `type`
Module: `src/index.ts`
-Source: `src/index.ts:339:1`
+Source: `src/index.ts:340:1`
### Members
@@ -1090,6 +1076,7 @@ Source: `src/index.ts:339:1`
| activeScreenId | property | `string \| null` | yes | |
| addScreen | property | `(name: string) => void` | yes | |
| addTheme | property | `() => void` | yes | |
+| componentMeta | property | `StudioComponentMetaRegistry` | yes | |
| deleteGeneratedApi | property | `(id: string) => void` | yes | |
| deleteNode | property | `(id: StudioNodeId) => void` | yes | |
| deleteScreen | property | `(id: StudioScreenId) => void` | yes | |
@@ -1101,7 +1088,6 @@ Source: `src/index.ts:339:1`
| isLoading | property | `boolean` | yes | |
| lastNonAdminLocation | property | `string` | yes | |
| manifest | property | `StudioManifest \| null` | yes | |
-| moveNode | property | `(id: StudioNodeId, direction: "up" \| "down") => void` | yes | |
| moveNodeToPlacement | property | `(nodeId: StudioNodeId, placement: NodePlacement) => boolean` | yes | |
| mutateAuthSettings | property | `(mutation: StudioAuthSettingsMutation) => StudioAuthSettings \| null` | yes | |
| previewMode | property | `boolean` | yes | |
@@ -1141,13 +1127,13 @@ Source: `src/index.ts:339:1`
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:332:1`
+Source: `src/index.ts:333:1`
## StudioIdGenerator
Kind: `unknown`
Module: `src/index.ts`
-Source: `src/index.ts:321:1`
+Source: `src/index.ts:322:1`
## StudioInstancePropertyEditorKind
@@ -1393,13 +1379,13 @@ Source: `src/index.ts:159:1`
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:476:14`
+Source: `src/index.ts:477:14`
## updateNodeInTree
Kind: `value`
Module: `src/index.ts`
-Source: `src/index.ts:560:14`
+Source: `src/index.ts:561:14`
### Signatures
@@ -1428,7 +1414,7 @@ Source: `src/bindingMutationModel.ts:9:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:1180:1`
+Source: `src/index.ts:1189:1`
### Signatures
@@ -1441,7 +1427,7 @@ Source: `src/index.ts:1180:1`
Kind: `function`
Module: `src/index.ts`
-Source: `src/index.ts:777:1`
+Source: `src/index.ts:715:1`
### Signatures
diff --git a/paradox/index.html b/paradox/index.html
index a7a63fcd..960d42a7 100644
--- a/paradox/index.html
+++ b/paradox/index.html
@@ -352,7 +352,7 @@ @ankhorage/studio
src/canvasDragModel.ts
- 5 functions
+ 9 functions
@@ -433,12 +433,6 @@ @ankhorage/studio
9 functions
-
-
- src/dnd/state.ts
- 1 function
-
-
src/externalApiApi.ts
@@ -1338,7 +1332,7 @@ @ankhorage/studio
src/index.ts
- 33 functions
+ 32 functions
@@ -1404,7 +1398,7 @@ @ankhorage/studio
src/manifestState.ts
- 57 functions
+ 50 functions
@@ -2095,12 +2089,54 @@ @ankhorage/studio
1 function
+
+
+ src/ui/canvas/canvasDndInteraction.test.ts
+ 1 function
+
+
+
+
+ src/ui/canvas/canvasDndInteraction.ts
+ 6 functions
+
+
+
+
+ src/ui/canvas/StudioCanvasDndOverlay.tsx
+ 5 functions
+
+
src/ui/studioAppBarModel.ts
1 function
+
+
+ src/ui/StudioDeleteDialog.tsx
+ 1 function
+
+
+
+
+ src/ui/StudioInsertDialog.tsx
+ 1 function
+
+
@ankhorage/studio
data-target="src/ui/useStudioAppBarAugmentation.ts"
>
src/ui/useStudioAppBarAugmentation.ts
- 1 function
+ 2 functions
@@ -2141,9 +2177,9 @@ @ankhorage/studio
Package overview
-
126 public exports
+
125 public exports
0 components
-
310 modules
+
313 modules
1 entrypoints
Entrypoints
@@ -2551,7 +2587,7 @@ src/canvasDragModel.test.ts
src/canvasDragModel.ts
Referenced module
@@ -2560,10 +2596,12 @@ src/canvasDragModel.ts
src/index.ts
- Exports: CanvasDropZoneSlots,
+ Exports: CanvasDragSessionResolution,
+ CanvasDropZoneSlots, CanvasRect,
createStudioCanvasDragPayload, isStudioCanvasDragPayload,
- isValidCanvasDropZone, resolveCanvasDropZoneSlots,
- StudioCanvasDragPayload
+ isValidCanvasDropZone, resolveCanvasDragPreviewText,
+ resolveCanvasDragSession, resolveCanvasDropZoneRect,
+ resolveCanvasDropZoneSlots, StudioCanvasDragPayload
src/core/StudioProvider.ts
StudioProviderProps
-
- src/dnd/index.ts
- Referenced module
- Dependencies: None
-
- Exports: AnimationFunction, clamp,
- CollisionAlgorithm, createIdleStudioDragState,
- Draggable, DraggableContextValue,
- DraggableHandleProps, DraggableProps,
- DraggableState, DropAlignment, DropOffset,
- Droppable, DroppableProps, DroppedItemsMap,
- DropProvider, DropProviderProps,
- DropProviderRef, DropSlot,
- HorizontalScrollDirection, HorizontalSortableItemProps,
- HorizontalSortableProps,
- HorizontalSortableRenderItemProps, listToObject,
- objectMove, PositionUpdateListener,
- ScrollDirection, setAutoScroll, setPosition,
- SlotsContext, SlotsContextValue, Sortable,
- SortableContextValue, SortableDirection,
- SortableHandleProps, SortableItem,
- SortableItemProps, SortableProps,
- SortableRenderItemProps, StudioDragState,
- useDraggable, UseDraggableOptions,
- UseDraggableReturn, useDroppable,
- UseDroppableOptions, UseDroppableReturn,
- UseHorizontalSortableListOptions,
- UseHorizontalSortableListReturn,
- UseHorizontalSortableOptions, UseHorizontalSortableReturn,
- useSortable, useSortableList,
- UseSortableListOptions, UseSortableListReturn,
- UseSortableOptions, UseSortableReturn
-
-
-
- src/dnd/primitives.ts
- Referenced module
- Dependencies: None
-
- Exports: AnimationFunction, clamp,
- CollisionAlgorithm, Draggable,
- DraggableContextValue, DraggableHandleProps,
- DraggableProps, DraggableState,
- DropAlignment, DropOffset, Droppable,
- DroppableProps, DroppedItemsMap,
- DropProvider, DropProviderProps,
- DropProviderRef, DropSlot,
- HorizontalScrollDirection, HorizontalSortableItemProps,
- HorizontalSortableProps,
- HorizontalSortableRenderItemProps, listToObject,
- objectMove, PositionUpdateListener,
- ScrollDirection, setAutoScroll, setPosition,
- SlotsContext, SlotsContextValue, Sortable,
- SortableContextValue, SortableDirection,
- SortableHandleProps, SortableItem,
- SortableItemProps, SortableProps,
- SortableRenderItemProps, useDraggable,
- UseDraggableOptions, UseDraggableReturn,
- useDroppable, UseDroppableOptions,
- UseDroppableReturn, UseHorizontalSortableListOptions,
- UseHorizontalSortableListReturn,
- UseHorizontalSortableOptions, UseHorizontalSortableReturn,
- useSortable, useSortableList,
- UseSortableListOptions, UseSortableListReturn,
- UseSortableOptions, UseSortableReturn
-
-
-
- src/dnd/state.ts
- Referenced module
- Dependencies: None
-
- Exports: createIdleStudioDragState,
- StudioDragState
-
-
src/index.test.ts
src/index.ts
Configured entrypoint
Dependencies: src/authSettings.ts
Exports: ACTION_REGISTRY,
- ActionDefinition, addNodeToTree,
- appendStudioEventBinding,
+ ActionDefinition, appendStudioEventBinding,
assessStudioBindingCompatibility,
buildInsertCatalogEntries, canAcceptChild,
cloneWithNewIds, collectStudioBindingOperationOptions,
@@ -4397,14 +4349,14 @@
src/index.ts
insertNodeAtPlacement, InsertNodeAtPlacementArgs,
InsertNodeAtPlacementResult, InsertRecipe,
InsertRecipeIssue, InsertRecipeNode,
- ModuleDefinition, moveNodeInTree,
- moveNodeToPlacement, MoveNodeToPlacementArgs,
- MoveNodeToPlacementResult, NodePlacement,
- PlacementFailureCode, PlacementFailureReason,
- PlacementKind, PlacementResolutionResult,
- PlacementValidationResult, ProjectAuthDiagnostic,
- ProjectAuthDiagnosticSeverity, ProjectAuthHealth,
- ProjectAuthHealthStatus, ProjectCreationValidationCode,
+ ModuleDefinition, moveNodeToPlacement,
+ MoveNodeToPlacementArgs, MoveNodeToPlacementResult,
+ NodePlacement, PlacementFailureCode,
+ PlacementFailureReason, PlacementKind,
+ PlacementResolutionResult, PlacementValidationResult,
+ ProjectAuthDiagnostic, ProjectAuthDiagnosticSeverity,
+ ProjectAuthHealth, ProjectAuthHealthStatus,
+ ProjectCreationValidationCode,
ProjectCreationValidationError,
ProjectCreationValidationFailure,
ProjectCreationValidationResult,
@@ -4415,7 +4367,8 @@ src/index.ts
removeStudioEventBinding, removeStudioPropBinding,
resolveDefaultInsertPlacement,
resolveInsertCatalogEntries, resolveInsertPlacement,
- resolveStudioBindableEvents, resolveStudioBindableProps,
+ resolveMoveNodePlacement, resolveStudioBindableEvents,
+ resolveStudioBindableProps,
resolveStudioInstancePropertyFields,
resolveStudioInstancePropertyGroups,
resolveStudioSchemaValueMeta, STUDIO_INSERT_RECIPES,
@@ -4617,7 +4570,7 @@ src/manifestState.test.ts
src/manifestState.ts
Referenced module
@@ -4635,7 +4588,7 @@ src/manifestState.ts
insertRouteAtParentPath,
insertStudioManifestNodeAtPlacement, isRouteGroupSegment,
listScreenIdsInRouteOrder, makeUniqueRouteNameForParent,
- makeUniqueSiblingRouteName, moveStudioManifestNode,
+ makeUniqueSiblingRouteName,
moveStudioManifestNodeToPlacement, pathToKey,
removeScreenIdFromRoutes, reorderStudioManifestScreens,
resolveActiveRootNode, resolveInitialActiveScreenId,
@@ -4892,16 +4845,15 @@ src/root.test.ts
src/root.ts
Referenced module
Dependencies: None
Exports: ACTION_REGISTRY,
- ActionDefinition, addNodeToTree,
- analyzeProjectAuthHealth, AnkhAdminPage,
- AnkhAdminShell, AnkhStudio,
+ ActionDefinition, analyzeProjectAuthHealth,
+ AnkhAdminPage, AnkhAdminShell, AnkhStudio,
appendStudioEventBinding, assertMetadataOnlyResponse,
assessStudioBindingCompatibility,
buildInsertCatalogEntries, canAcceptChild,
@@ -4922,14 +4874,14 @@
src/root.ts
insertNodeAtPlacement, InsertNodeAtPlacementArgs,
InsertNodeAtPlacementResult, InsertRecipe,
InsertRecipeIssue, InsertRecipeNode,
- ModuleDefinition, moveNodeInTree,
- moveNodeToPlacement, MoveNodeToPlacementArgs,
- MoveNodeToPlacementResult, NodePlacement,
- PlacementFailureCode, PlacementFailureReason,
- PlacementKind, PlacementResolutionResult,
- PlacementValidationResult, ProjectAuthDiagnostic,
- ProjectAuthDiagnosticSeverity, ProjectAuthHealth,
- ProjectAuthHealthStatus, ProjectCreationValidationCode,
+ ModuleDefinition, moveNodeToPlacement,
+ MoveNodeToPlacementArgs, MoveNodeToPlacementResult,
+ NodePlacement, PlacementFailureCode,
+ PlacementFailureReason, PlacementKind,
+ PlacementResolutionResult, PlacementValidationResult,
+ ProjectAuthDiagnostic, ProjectAuthDiagnosticSeverity,
+ ProjectAuthHealth, ProjectAuthHealthStatus,
+ ProjectCreationValidationCode,
ProjectCreationValidationError,
ProjectCreationValidationFailure,
ProjectCreationValidationResult, ProjectDetailScreen,
@@ -4941,7 +4893,8 @@ src/root.ts
removeNodeFromTree, removeStudioEventBinding,
removeStudioPropBinding, resolveDefaultInsertPlacement,
resolveInsertCatalogEntries, resolveInsertPlacement,
- resolveStudioBindableEvents, resolveStudioBindableProps,
+ resolveMoveNodePlacement, resolveStudioBindableEvents,
+ resolveStudioBindableProps,
resolveStudioInstancePropertyFields,
resolveStudioInstancePropertyGroups,
resolveStudioSchemaValueMeta, STUDIO_INSERT_RECIPES,
@@ -5036,7 +4989,7 @@ src/runtime/appExtensionRegistry.ts
src/runtime/index.ts
Referenced module
@@ -5061,6 +5014,7 @@ src/runtime/index.ts
STUDIO_APP_EXTENSION_COMPONENT_REGISTRY,
STUDIO_APP_EXTENSION_INTERACTION_POLICY_SUPPORT,
STUDIO_PREVIEW_COMPONENT_REGISTRY,
+ StudioCanvasInteractionAdapter,
StudioInteractionPolicyResolverArgs,
StudioLocalizationPreview, StudioLocalizationPreviewInput,
StudioPreviewRegistryOptions,
@@ -5280,23 +5234,25 @@ src/runtime/stationarySelection.test.ts
src/runtime/stationarySelection.ts
Referenced module
- Dependencies:
- src/runtime/indicatorRefreshCoordinator.ts,
+ Dependencies: src/canvasDragModel.ts,
+ src/index.ts, src/runtime/indicatorRefreshCoordinator.ts,
src/runtime/indicatorSettleCoordinator.ts,
src/runtime/runtimeNodeMeasurement.ts,
src/runtime/stationarySelectionCoordinator.ts,
- src/runtime/stationarySelectionInputState.ts
+ src/runtime/stationarySelectionInputState.ts,
+ src/ui/canvas/StudioCanvasDndOverlay.tsx
Exports: CommitSelectionResult,
createStudioStationarySelectionWrapNode,
StationarySelectionCoordinator, StationaryTapSelector,
- TransactionState, useStudioUnsupportedNodeMeasurement
+ StudioCanvasInteractionAdapter, TransactionState,
+ useStudioUnsupportedNodeMeasurement
src/ui/AnkhStudio.ts
Dependencies: src/core/StudioContext.ts
Exports: AnkhStudio, AnkhStudioProps
+
+ src/ui/canvas/canvasDndInteraction.test.ts
+ Referenced module
+
+ Dependencies: src/canvasDropZones.ts,
+ src/ui/canvas/canvasDndInteraction.ts
+
+ Exports: None
+
+
+ src/ui/canvas/canvasDndInteraction.ts
+ Referenced module
+
+ Dependencies: src/canvasDragModel.ts,
+ src/canvasDropZones.ts, src/index.ts
+
+
+ Exports: activateCanvasDrag,
+ CanvasDragSessionCallbacks, commitCanvasDrop,
+ completeCanvasDropAfterAdapter,
+ createCanvasDraggableSessionKey, resetCanvasDragSession,
+ sortCanvasDropTargetsBySpecificity
+
+
+
+ src/ui/canvas/StudioCanvasDndOverlay.test.ts
+ Referenced module
+ Dependencies: None
+ Exports: None
+
+
+ src/ui/canvas/StudioCanvasDndOverlay.tsx
+ Referenced module
+
+ Dependencies: src/canvasDragModel.ts,
+ src/canvasDropZones.ts, src/index.ts,
+ src/insertModalModel.ts,
+ src/runtime/runtimeNodeMeasurement.ts,
+ src/ui/canvas/canvasDndInteraction.ts
+
+
+ Exports: StudioCanvasDndOverlay,
+ StudioCanvasDndOverlayProps
+
+
src/ui/studioAppBarModel.ts
StudioAppBarContextAction
+
+ src/ui/StudioDeleteDialog.tsx
+ Referenced module
+ Dependencies: None
+
+ Exports: StudioDeleteDialog,
+ StudioDeleteDialogProps
+
+
+
+ src/ui/StudioInsertDialog.tsx
+ Referenced module
+
+ Dependencies: src/index.ts,
+ src/insertModalModel.ts
+
+
+ Exports: StudioInsertDialog,
+ StudioInsertDialogProps
+
+
src/ui/useStudioAppBarAugmentation.test.ts
src/ui/useStudioAppBarAugmentation.ts
Referenced module
Dependencies: src/core/StudioContext.ts,
+ src/index.ts, src/insertModalModel.ts,
src/studioAdminRouteModel.ts, src/studioSelectionModel.ts,
- src/ui/studioAppBarModel.ts
+ src/ui/studioAppBarModel.ts,
+ src/ui/StudioDeleteDialog.tsx,
+ src/ui/StudioInsertDialog.tsx
Exports: StudioAppBarAugmentation,
@@ -6256,14 +6296,13 @@
src/upsertExternalApiDataSource.ts
src/utils/treeUtils.ts
Referenced module
Dependencies: src/index.ts
- Exports: addNodeToTree, cloneWithNewIds,
- findNodeById, moveNodeInTree,
+ Exports: cloneWithNewIds, findNodeById,
removeNodeFromTree, updateNodeInTree
@@ -7324,7 +7363,7 @@ src/index.ts
data-search="ACTION_REGISTRY value src/index.ts "
>
ACTION_REGISTRY
- value • src/index.ts:384:14
+ value • src/index.ts:385:14
Export paths: src/index.ts
Related symbols: None
@@ -7335,7 +7374,7 @@ ACTION_REGISTRY
data-search="ActionDefinition type src/index.ts StudioActionPayloadSchema"
>
ActionDefinition
- type • src/index.ts:290:1
+ type • src/index.ts:291:1
Export paths: src/index.ts
@@ -7394,59 +7433,13 @@
ActionDefinition
-
- addNodeToTree
- value • src/index.ts:606:14
-
- Export paths: src/index.ts
-
-
Related symbols:
-
- StudioComponentMetaRegistry
-
-
-
-
Signature
-
-(args: { root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: "append" | "prepend"; }) => UiNode
-
-
-
- Parameter
- Type
- Required
- Description
-
-
-
-
- args
-
- { root: UiNode; targetId: string; newNode: UiNode; componentMeta:
- StudioComponentMetaRegistry; mode?: "append" |
- "prepend"; }
-
- yes
-
-
-
-
-
Returns: UiNode
-
-
buildInsertCatalogEntries
- function • src/index.ts:1318:1
+ function • src/index.ts:1327:1
Export paths: src/index.ts
@@ -7493,7 +7486,7 @@
Signature
data-search="canAcceptChild function src/index.ts StudioComponentMetaRegistry (args: { parentType: string; childType: string; componentMeta: StudioComponentMetaRegistry; }) => boolean"
>
canAcceptChild
-
function • src/index.ts:765:1
+
function • src/index.ts:703:1
Export paths: src/index.ts
@@ -7538,7 +7531,7 @@
Signature
data-search="cloneWithNewIds value src/index.ts StudioIdGenerator (node: UiNode, createId?: StudioIdGenerator) => UiNode"
>
cloneWithNewIds
-
value • src/index.ts:531:14
+
value • src/index.ts:532:14
Export paths: src/index.ts
@@ -7583,7 +7576,7 @@
Signature
data-search="createNodeFromCatalogEntry function src/index.ts InsertCatalogEntry StudioComponentMetaRegistry StudioIdGenerator (entry: InsertCatalogEntry, componentMeta: StudioComponentMetaRegistry, createId?: StudioIdGenerator) => UiNode"
>
createNodeFromCatalogEntry
-
function • src/index.ts:1237:1
+
function • src/index.ts:1246:1
Export paths: src/index.ts
@@ -7637,7 +7630,7 @@
Signature
data-search="findNodeById value src/index.ts (root: UiNode, id: string) => UiNode | null"
>
findNodeById
-
value • src/index.ts:548:14
+
value • src/index.ts:549:14
Export paths: src/index.ts
Related symbols: None
@@ -7677,7 +7670,7 @@
Signature
data-search="generateStudioId value src/index.ts (prefix?: string | undefined) => string"
>
generateStudioId
-
value • src/index.ts:524:14
+
value • src/index.ts:525:14
Export paths: src/index.ts
Related symbols: None
@@ -7711,7 +7704,7 @@
Signature
data-search="getInsertCatalogCategoryLabel function src/index.ts (category: string) => string"
>
getInsertCatalogCategoryLabel
-
function • src/index.ts:1163:1
+
function • src/index.ts:1172:1
Export paths: src/index.ts
Related symbols: None
@@ -7745,7 +7738,7 @@
Signature
data-search="InsertCatalogComponentEntry type src/index.ts InsertCatalogDisabledReason InsertCatalogEntryStatus NodePlacement"
>
InsertCatalogComponentEntry
-
type • src/index.ts:268:1
+
type • src/index.ts:269:1
Export paths: src/index.ts
@@ -7847,7 +7840,7 @@
InsertCatalogComponentEntry
data-search="InsertCatalogDisabledReason type src/index.ts InsertCatalogDisabledReasonCode InsertRecipeIssue"
>
InsertCatalogDisabledReason
-
type • src/index.ts:250:1
+
type • src/index.ts:251:1
Export paths: src/index.ts
@@ -7899,7 +7892,7 @@
InsertCatalogDisabledReason
data-search="InsertCatalogDisabledReasonCode unknown src/index.ts "
>
InsertCatalogDisabledReasonCode
-
unknown • src/index.ts:227:1
+
unknown • src/index.ts:228:1
Export paths: src/index.ts
Related symbols: None
@@ -7910,7 +7903,7 @@
InsertCatalogDisabledReasonCode
data-search="InsertCatalogEntry unknown src/index.ts "
>
InsertCatalogEntry
-
unknown • src/index.ts:278:1
+
unknown • src/index.ts:279:1
Export paths: src/index.ts
Related symbols: None
@@ -7921,7 +7914,7 @@
InsertCatalogEntry
data-search="InsertCatalogEntryBase type src/index.ts InsertCatalogDisabledReason InsertCatalogEntryKind InsertCatalogEntryStatus NodePlacement"
>
InsertCatalogEntryBase
-
type • src/index.ts:256:1
+
type • src/index.ts:257:1
Export paths: src/index.ts
@@ -8017,7 +8010,7 @@
InsertCatalogEntryBase
data-search="InsertCatalogEntryKind unknown src/index.ts "
>
InsertCatalogEntryKind
-
unknown • src/index.ts:224:1
+
unknown • src/index.ts:225:1
Export paths: src/index.ts
Related symbols: None
@@ -8028,7 +8021,7 @@
InsertCatalogEntryKind
data-search="InsertCatalogEntryStatus unknown src/index.ts "
>
InsertCatalogEntryStatus
-
unknown • src/index.ts:225:1
+
unknown • src/index.ts:226:1
Export paths: src/index.ts
Related symbols: None
@@ -8039,7 +8032,7 @@
InsertCatalogEntryStatus
data-search="InsertCatalogRecipeEntry type src/index.ts InsertCatalogDisabledReason InsertCatalogEntryStatus InsertRecipe NodePlacement"
>
InsertCatalogRecipeEntry
-
type • src/index.ts:273:1
+
type • src/index.ts:274:1
Export paths: src/index.ts
@@ -8142,7 +8135,7 @@
InsertCatalogRecipeEntry
data-search="insertNodeAtPlacement function src/index.ts InsertNodeAtPlacementArgs InsertNodeAtPlacementResult (args: InsertNodeAtPlacementArgs) => InsertNodeAtPlacementResult | null"
>
insertNodeAtPlacement
-
function • src/index.ts:995:1
+
function • src/index.ts:965:1
Export paths: src/index.ts
@@ -8183,7 +8176,7 @@
Signature
data-search="InsertNodeAtPlacementArgs type src/index.ts NodePlacement StudioComponentMetaRegistry"
>
InsertNodeAtPlacementArgs
-
type • src/index.ts:938:1
+
type • src/index.ts:908:1
Export paths: src/index.ts
@@ -8242,7 +8235,7 @@
InsertNodeAtPlacementArgs
data-search="InsertNodeAtPlacementResult type src/index.ts "
>
InsertNodeAtPlacementResult
-
type • src/index.ts:945:1
+
type • src/index.ts:915:1
Export paths: src/index.ts
Related symbols: None
@@ -8281,7 +8274,7 @@
InsertNodeAtPlacementResult
data-search="InsertRecipe type src/index.ts InsertRecipeNode"
>
InsertRecipe
-
type • src/index.ts:235:1
+
type • src/index.ts:236:1
Export paths: src/index.ts
@@ -8346,7 +8339,7 @@
InsertRecipe
data-search="InsertRecipeIssue type src/index.ts "
>
InsertRecipeIssue
-
type • src/index.ts:243:1
+
type • src/index.ts:244:1
Export paths: src/index.ts
Related symbols: None
@@ -8399,7 +8392,7 @@
InsertRecipeIssue
data-search="InsertRecipeNode type src/index.ts "
>
InsertRecipeNode
-
type • src/index.ts:230:1
+
type • src/index.ts:231:1
Export paths: src/index.ts
Related symbols: None
@@ -8438,7 +8431,7 @@
InsertRecipeNode
data-search="ModuleDefinition type src/index.ts "
>
ModuleDefinition
-
type • src/index.ts:298:1
+
type • src/index.ts:299:1
Export paths: src/index.ts
Related symbols: None
@@ -8485,60 +8478,13 @@
ModuleDefinition
-
- moveNodeInTree
- value • src/index.ts:639:14
-
- Export paths: src/index.ts
- Related symbols: None
-
-
Signature
-
-(root: UiNode, nodeId: string, direction: "up" | "down") => UiNode
-
-
-
- Parameter
- Type
- Required
- Description
-
-
-
-
- direction
- "up" | "down"
- yes
-
-
-
- nodeId
- string
- yes
-
-
-
- root
- UiNode
- yes
-
-
-
-
-
Returns: UiNode
-
-
moveNodeToPlacement
- function • src/index.ts:1063:1
+ function • src/index.ts:1101:1
Export paths: src/index.ts
@@ -8578,7 +8524,7 @@
Signature
data-search="MoveNodeToPlacementArgs type src/index.ts NodePlacement StudioComponentMetaRegistry"
>
MoveNodeToPlacementArgs
-
type • src/index.ts:1022:1
+
type • src/index.ts:992:1
Export paths: src/index.ts
@@ -8637,7 +8583,7 @@
MoveNodeToPlacementArgs
data-search="MoveNodeToPlacementResult type src/index.ts "
>
MoveNodeToPlacementResult
-
type • src/index.ts:1029:1
+
type • src/index.ts:999:1
Export paths: src/index.ts
Related symbols: None
@@ -8745,7 +8691,7 @@
PlacementFailureCode
data-search="PlacementFailureReason type src/index.ts PlacementFailureCode"
>
PlacementFailureReason
-
type • src/index.ts:205:1
+
type • src/index.ts:206:1
Export paths: src/index.ts
@@ -8800,7 +8746,7 @@
PlacementKind
data-search="PlacementResolutionResult unknown src/index.ts "
>
PlacementResolutionResult
-
unknown • src/index.ts:217:1
+
unknown • src/index.ts:218:1
Export paths: src/index.ts
Related symbols: None
@@ -8811,7 +8757,7 @@
PlacementResolutionResult
data-search="PlacementValidationResult unknown src/index.ts "
>
PlacementValidationResult
-
unknown • src/index.ts:210:1
+
unknown • src/index.ts:211:1
Export paths: src/index.ts
Related symbols: None
@@ -8822,7 +8768,7 @@
PlacementValidationResult
data-search="removeNodeFromTree value src/index.ts (root: UiNode, nodeId: string) => UiNode | null"
>
removeNodeFromTree
-
value • src/index.ts:588:14
+
value • src/index.ts:589:14
Export paths: src/index.ts
Related symbols: None
@@ -8862,7 +8808,7 @@
Signature
data-search="resolveDefaultInsertPlacement function src/index.ts PlacementResolutionResult StudioComponentMetaRegistry (args: { root: UiNode; selectedNodeId: string | null; childType: string; componentMeta: StudioComponentMetaRegistry; }) => PlacementResolutionResult"
>
resolveDefaultInsertPlacement
-
function • src/index.ts:893:1
+
function • src/index.ts:863:1
Export paths: src/index.ts
@@ -8908,7 +8854,7 @@
Signature
data-search="resolveInsertCatalogEntries function src/index.ts InsertCatalogEntry StudioComponentMetaRegistry (args: { entries: readonly InsertCatalogEntry[]; root: UiNode | null; selectedNodeId: string | null; componentMeta: StudioComponentMetaRegistry; }) => InsertCatalogEntry[]"
>
resolveInsertCatalogEntries
-
function • src/index.ts:1360:1
+
function • src/index.ts:1369:1
Export paths: src/index.ts
@@ -8955,7 +8901,7 @@
Signature
data-search="resolveInsertPlacement function src/index.ts PlacementKind PlacementResolutionResult StudioComponentMetaRegistry (args: { root: UiNode; targetNodeId: string; childType: string; componentMeta: StudioComponentMetaRegistry; kind: PlacementKind; }) => PlacementResolutionResult"
>
resolveInsertPlacement
-
function • src/index.ts:832:1
+
function • src/index.ts:802:1
Export paths: src/index.ts
@@ -8996,13 +8942,53 @@
Signature
Returns: PlacementResolutionResult
+
+ resolveMoveNodePlacement
+ function • src/index.ts:1033:1
+
+ Export paths: src/index.ts
+
+
Related symbols:
+
+ MoveNodeToPlacementArgs
+ PlacementResolutionResult
+
+
+
+
Signature
+
(args: MoveNodeToPlacementArgs) => PlacementResolutionResult
+
+
+
+ Parameter
+ Type
+ Required
+ Description
+
+
+
+
+ args
+ MoveNodeToPlacementArgs
+ yes
+
+
+
+
+
Returns: PlacementResolutionResult
+
+
STUDIO_INSERT_RECIPES
- value • src/index.ts:1130:14
+ value • src/index.ts:1139:14
Export paths: src/index.ts
Related symbols: None
@@ -9046,7 +9032,7 @@ STUDIO_PUBLIC_CONTRACTS
data-search="StudioActionPayloadField type src/index.ts StudioActionPayloadPrimitive"
>
StudioActionPayloadField
- type • src/index.ts:282:1
+ type • src/index.ts:283:1
Export paths: src/index.ts
@@ -9097,7 +9083,7 @@
StudioActionPayloadField
data-search="StudioActionPayloadPrimitive unknown src/index.ts "
>
StudioActionPayloadPrimitive
-
unknown • src/index.ts:280:1
+
unknown • src/index.ts:281:1
Export paths: src/index.ts
Related symbols: None
@@ -9108,7 +9094,7 @@
StudioActionPayloadPrimitive
data-search="StudioActionPayloadSchema unknown src/index.ts "
>
StudioActionPayloadSchema
-
unknown • src/index.ts:288:1
+
unknown • src/index.ts:289:1
Export paths: src/index.ts
Related symbols: None
@@ -9152,7 +9138,7 @@
StudioAdminStaticRoutePath
data-search="StudioCommand unknown src/index.ts "
>
StudioCommand
-
unknown • src/index.ts:323:1
+
unknown • src/index.ts:324:1
Export paths: src/index.ts
Related symbols: None
@@ -9163,7 +9149,7 @@
StudioCommand
data-search="StudioComponentBlueprint type src/index.ts "
>
StudioComponentBlueprint
-
type • src/index.ts:307:1
+
type • src/index.ts:308:1
Export paths: src/index.ts
Related symbols: None
@@ -9202,7 +9188,7 @@
StudioComponentBlueprint
data-search="StudioComponentMeta type src/index.ts StudioComponentBlueprint"
>
StudioComponentMeta
-
type • src/index.ts:312:1
+
type • src/index.ts:313:1
Export paths: src/index.ts
@@ -9260,7 +9246,7 @@
StudioComponentMeta
data-search="StudioComponentMetaRegistry unknown src/index.ts "
>
StudioComponentMetaRegistry
-
unknown • src/index.ts:319:1
+
unknown • src/index.ts:320:1
Export paths: src/index.ts
Related symbols: None
@@ -9268,10 +9254,10 @@
StudioComponentMetaRegistry
StudioContextValue
- type • src/index.ts:339:1
+ type • src/index.ts:340:1
Export paths: src/index.ts
@@ -9280,6 +9266,7 @@
StudioContextValue
InsertCatalogEntry
NodePlacement
StudioAdminRouteId
+
StudioComponentMetaRegistry
StudioLocale
StudioManifest
StudioMode
@@ -9352,6 +9339,13 @@
StudioContextValue
yes
+
+ componentMeta
+ property
+ StudioComponentMetaRegistry
+ yes
+
+
deleteGeneratedApi
property
@@ -9429,18 +9423,6 @@ StudioContextValue
yes
-
- moveNode
- property
-
- (id: StudioNodeId, direction: "up" | "down") =>
- void
-
- yes
-
-
moveNodeToPlacement
property
@@ -9710,7 +9692,7 @@ StudioContextValue
data-search="StudioEvent unknown src/index.ts "
>
StudioEvent
- unknown • src/index.ts:332:1
+ unknown • src/index.ts:333:1
Export paths: src/index.ts
Related symbols: None
@@ -9721,7 +9703,7 @@ StudioEvent
data-search="StudioIdGenerator unknown src/index.ts "
>
StudioIdGenerator
- unknown • src/index.ts:321:1
+ unknown • src/index.ts:322:1
Export paths: src/index.ts
Related symbols: None
@@ -10070,7 +10052,7 @@ ThemeUpdates
data-search="TPL_SCREEN_EMPTY value src/index.ts "
>
TPL_SCREEN_EMPTY
- value • src/index.ts:476:14
+ value • src/index.ts:477:14
Export paths: src/index.ts
Related symbols: None
@@ -10081,7 +10063,7 @@ TPL_SCREEN_EMPTY
data-search="updateNodeInTree value src/index.ts (root: UiNode, id: string, newProps: Record<string, unknown>) => UiNode"
>
updateNodeInTree
- value • src/index.ts:560:14
+ value • src/index.ts:561:14
Export paths: src/index.ts
Related symbols: None
@@ -10128,7 +10110,7 @@ Signature
data-search="validateInsertRecipe function src/index.ts InsertRecipe InsertRecipeIssue StudioComponentMetaRegistry (recipe: InsertRecipe, componentMeta: StudioComponentMetaRegistry) => InsertRecipeIssue | null"
>
validateInsertRecipe
- function • src/index.ts:1180:1
+ function • src/index.ts:1189:1
Export paths: src/index.ts
@@ -10176,7 +10158,7 @@
Signature
data-search="validateNodePlacement function src/index.ts NodePlacement PlacementValidationResult StudioComponentMetaRegistry (args: { root: UiNode; placement: NodePlacement; childType: string; componentMeta: StudioComponentMetaRegistry; }) => PlacementValidationResult"
>
validateNodePlacement
-
function • src/index.ts:777:1
+
function • src/index.ts:715:1
Export paths: src/index.ts
@@ -11769,12 +11751,6 @@
Architecture overview
module_src_routeUtils_ts module_src_core_StudioProvider_ts -->
module_src_studioSelectionModel_ts module_src_core_StudioProvider_ts -->
module_src_ui_admin_AuthAdminSession_tsx
- module_src_dnd_index_ts["src/dnd/index.ts"] package__ankhorage_studio
- -.-> module_src_dnd_index_ts
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- package__ankhorage_studio -.-> module_src_dnd_primitives_ts
- module_src_dnd_state_ts["src/dnd/state.ts"] package__ankhorage_studio
- -.-> module_src_dnd_state_ts
module_src_externalApiApi_ts["src/externalApiApi.ts"]
package__ankhorage_studio -.-> module_src_externalApiApi_ts
module_src_externalApiApi_ts --> module_src_core_constants_ts
@@ -12624,6 +12600,8 @@
Architecture overview
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_test_ts
module_src_runtime_stationarySelection_ts["src/runtime/stationarySelection.ts"]
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_ts
+ module_src_runtime_stationarySelection_ts --> module_src_canvasDragModel_ts
+ module_src_runtime_stationarySelection_ts --> module_src_index_ts
module_src_runtime_stationarySelection_ts -->
module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts -->
@@ -12634,6 +12612,8 @@
Architecture overview
module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts -->
module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts -->
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts["src/runtime/stationarySelectionCoordinator.test.ts"]
package__ankhorage_studio -.->
module_src_runtime_stationarySelectionCoordinator_test_ts
@@ -13045,8 +13025,37 @@
Architecture overview
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
package__ankhorage_studio -.-> module_src_ui_AnkhStudio_ts
module_src_ui_AnkhStudio_ts --> module_src_core_StudioContext_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_test_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts -->
+ module_src_canvasDropZones_ts module_src_ui_canvas_canvasDndInteraction_test_ts
+ --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ package__ankhorage_studio -.->
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx -->
+ module_src_insertModalModel_ts module_src_ui_canvas_StudioCanvasDndOverlay_tsx
+ --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx -->
+ module_src_ui_canvas_canvasDndInteraction_ts
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
package__ankhorage_studio -.-> module_src_ui_studioAppBarModel_ts
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioInsertDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx --> module_src_index_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_test_ts
module_src_ui_useStudioAppBarAugmentation_test_ts -->
@@ -13054,11 +13063,16 @@
Architecture overview
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts -->
module_src_studioAdminRouteModel_ts module_src_ui_useStudioAppBarAugmentation_ts
--> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts -->
- module_src_ui_studioAppBarModel_ts
+ module_src_ui_studioAppBarModel_ts module_src_ui_useStudioAppBarAugmentation_ts
+ --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts -->
+ module_src_ui_StudioInsertDialog_tsx
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
package__ankhorage_studio -.-> module_src_upsertExternalApiDataSource_ts
module_src_utils_treeUtils_ts["src/utils/treeUtils.ts"]
@@ -13258,12 +13272,6 @@
Architecture overview
module_src_core_StudioProvider_ts --> module_src_routeUtils_ts
module_src_core_StudioProvider_ts --> module_src_studioSelectionModel_ts
module_src_core_StudioProvider_ts --> module_src_ui_admin_AuthAdminSession_tsx
- module_src_dnd_index_ts["src/dnd/index.ts"]
- package__ankhorage_studio -.-> module_src_dnd_index_ts
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- package__ankhorage_studio -.-> module_src_dnd_primitives_ts
- module_src_dnd_state_ts["src/dnd/state.ts"]
- package__ankhorage_studio -.-> module_src_dnd_state_ts
module_src_externalApiApi_ts["src/externalApiApi.ts"]
package__ankhorage_studio -.-> module_src_externalApiApi_ts
module_src_externalApiApi_ts --> module_src_core_constants_ts
@@ -13890,11 +13898,14 @@
Architecture overview
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_test_ts
module_src_runtime_stationarySelection_ts["src/runtime/stationarySelection.ts"]
package__ankhorage_studio -.-> module_src_runtime_stationarySelection_ts
+ module_src_runtime_stationarySelection_ts --> module_src_canvasDragModel_ts
+ module_src_runtime_stationarySelection_ts --> module_src_index_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorSettleCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts --> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts["src/runtime/stationarySelectionCoordinator.test.ts"]
package__ankhorage_studio -.-> module_src_runtime_stationarySelectionCoordinator_test_ts
module_src_runtime_stationarySelectionCoordinator_test_ts --> module_src_runtime_stationarySelectionCoordinator_ts
@@ -14179,17 +14190,46 @@
Architecture overview
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
package__ankhorage_studio -.-> module_src_ui_AnkhStudio_ts
module_src_ui_AnkhStudio_ts --> module_src_core_StudioContext_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_test_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_StudioCanvasDndOverlay_test_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_insertModalModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_ui_canvas_canvasDndInteraction_ts
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
package__ankhorage_studio -.-> module_src_ui_studioAppBarModel_ts
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
+ package__ankhorage_studio -.-> module_src_ui_StudioInsertDialog_tsx
+ module_src_ui_StudioInsertDialog_tsx --> module_src_index_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_test_ts
module_src_ui_useStudioAppBarAugmentation_test_ts --> module_src_ui_studioAppBarModel_ts
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
package__ankhorage_studio -.-> module_src_ui_useStudioAppBarAugmentation_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioAdminRouteModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_studioAppBarModel_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioInsertDialog_tsx
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
package__ankhorage_studio -.-> module_src_upsertExternalApiDataSource_ts
module_src_utils_treeUtils_ts["src/utils/treeUtils.ts"]
@@ -14262,9 +14302,6 @@
Module relationships
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -14516,7 +14553,13 @@
Module relationships
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -15055,6 +15098,8 @@
Module relationships
module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_public_test_ts -->
module_src_runtime_index_ts module_src_runtime_stationarySelection_ts -->
+ module_src_canvasDragModel_ts module_src_runtime_stationarySelection_ts -->
+ module_src_index_ts module_src_runtime_stationarySelection_ts -->
module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts -->
module_src_runtime_indicatorSettleCoordinator_ts
@@ -15064,6 +15109,8 @@
Module relationships
module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts -->
module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts -->
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts -->
module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelectionInputState_test_ts -->
@@ -15299,14 +15346,35 @@
Module relationships
module_src_ui_admin_pages_adminThemeHarmony_ts
module_src_ui_admin_pages_ThemeAdminPage_tsx -->
module_src_ui_admin_pages_adminThemeModel_ts module_src_ui_AnkhStudio_ts -->
- module_src_core_StudioContext_ts module_src_ui_useStudioAppBarAugmentation_test_ts
+ module_src_core_StudioContext_ts module_src_ui_canvas_canvasDndInteraction_test_ts
+ --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts -->
+ module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx -->
+ module_src_insertModalModel_ts module_src_ui_canvas_StudioCanvasDndOverlay_tsx
+ --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx -->
+ module_src_ui_canvas_canvasDndInteraction_ts module_src_ui_StudioInsertDialog_tsx
+ --> module_src_index_ts module_src_ui_StudioInsertDialog_tsx -->
+ module_src_insertModalModel_ts module_src_ui_useStudioAppBarAugmentation_test_ts
--> module_src_ui_studioAppBarModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts -->
module_src_studioAdminRouteModel_ts module_src_ui_useStudioAppBarAugmentation_ts
--> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts -->
- module_src_ui_studioAppBarModel_ts module_src_utils_treeUtils_ts -->
+ module_src_ui_studioAppBarModel_ts module_src_ui_useStudioAppBarAugmentation_ts
+ --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts -->
+ module_src_ui_StudioInsertDialog_tsx module_src_utils_treeUtils_ts -->
module_src_index_ts module_src_workspacePlatform_test_ts -->
module_src_workspacePlatform_ts module_src_workspaceSearch_ts -->
module_src_projectWorkspaceContracts_ts module_src_workspaceSearch_ts -->
@@ -15364,9 +15432,6 @@
Module relationships
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -15618,7 +15683,13 @@
Module relationships
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -15974,11 +16045,14 @@
Module relationships
module_src_runtime_previewRuntimeConfig_ts --> module_src_runtime_previewRegistry_ts
module_src_runtime_runtimeNodeMeasurement_test_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_public_test_ts --> module_src_runtime_index_ts
+ module_src_runtime_stationarySelection_ts --> module_src_canvasDragModel_ts
+ module_src_runtime_stationarySelection_ts --> module_src_index_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorRefreshCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_indicatorSettleCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_runtimeNodeMeasurement_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelection_ts --> module_src_runtime_stationarySelectionInputState_ts
+ module_src_runtime_stationarySelection_ts --> module_src_ui_canvas_StudioCanvasDndOverlay_tsx
module_src_runtime_stationarySelectionCoordinator_test_ts --> module_src_runtime_stationarySelectionCoordinator_ts
module_src_runtime_stationarySelectionInputState_test_ts --> module_src_runtime_stationarySelectionInputState_ts
module_src_runtime_useRuntimeAction_ts --> module_src_runtime_runtimeActions_ts
@@ -16121,11 +16195,28 @@
Module relationships
module_src_ui_admin_pages_ThemeAdminPage_tsx --> module_src_ui_admin_pages_adminThemeHarmony_ts
module_src_ui_admin_pages_ThemeAdminPage_tsx --> module_src_ui_admin_pages_adminThemeModel_ts
module_src_ui_AnkhStudio_ts --> module_src_core_StudioContext_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_test_ts --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_canvasDndInteraction_ts --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDragModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_canvasDropZones_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_index_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_insertModalModel_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_runtime_runtimeNodeMeasurement_ts
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx --> module_src_ui_canvas_canvasDndInteraction_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_index_ts
+ module_src_ui_StudioInsertDialog_tsx --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_test_ts --> module_src_ui_studioAppBarModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_core_StudioContext_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_index_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_insertModalModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioAdminRouteModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_studioSelectionModel_ts
module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_studioAppBarModel_ts
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioDeleteDialog_tsx
+ module_src_ui_useStudioAppBarAugmentation_ts --> module_src_ui_StudioInsertDialog_tsx
module_src_utils_treeUtils_ts --> module_src_index_ts
module_src_workspacePlatform_test_ts --> module_src_workspacePlatform_ts
module_src_workspaceSearch_ts --> module_src_projectWorkspaceContracts_ts
@@ -16185,9 +16276,6 @@
Export graph
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -16439,7 +16527,13 @@
Export graph
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -16450,9 +16544,7 @@
Export graph
export_ACTION_REGISTRY["ACTION_REGISTRY"] module_src_index_ts -->
export_ACTION_REGISTRY export_ActionDefinition["ActionDefinition"]
module_src_index_ts --> export_ActionDefinition export_ActionDefinition -.->
- export_StudioActionPayloadSchema export_addNodeToTree["addNodeToTree"]
- module_src_index_ts --> export_addNodeToTree export_addNodeToTree -.->
- export_StudioComponentMetaRegistry
+ export_StudioActionPayloadSchema
export_appendStudioEventBinding["appendStudioEventBinding"]
module_src_bindingMutationModel_ts --> export_appendStudioEventBinding
export_assessStudioBindingCompatibility["assessStudioBindingCompatibility"]
@@ -16548,11 +16640,9 @@
Export graph
export_InsertRecipeIssue export_InsertRecipeNode["InsertRecipeNode"]
module_src_index_ts --> export_InsertRecipeNode
export_ModuleDefinition["ModuleDefinition"] module_src_index_ts -->
- export_ModuleDefinition export_moveNodeInTree["moveNodeInTree"]
- module_src_index_ts --> export_moveNodeInTree
- export_moveNodeToPlacement["moveNodeToPlacement"] module_src_index_ts
- --> export_moveNodeToPlacement export_moveNodeToPlacement -.->
- export_MoveNodeToPlacementArgs export_moveNodeToPlacement -.->
+ export_ModuleDefinition export_moveNodeToPlacement["moveNodeToPlacement"]
+ module_src_index_ts --> export_moveNodeToPlacement export_moveNodeToPlacement
+ -.-> export_MoveNodeToPlacementArgs export_moveNodeToPlacement -.->
export_MoveNodeToPlacementResult
export_MoveNodeToPlacementArgs["MoveNodeToPlacementArgs"]
module_src_index_ts --> export_MoveNodeToPlacementArgs
@@ -16630,6 +16720,10 @@
Export graph
export_resolveInsertPlacement -.-> export_PlacementKind
export_resolveInsertPlacement -.-> export_PlacementResolutionResult
export_resolveInsertPlacement -.-> export_StudioComponentMetaRegistry
+ export_resolveMoveNodePlacement["resolveMoveNodePlacement"]
+ module_src_index_ts --> export_resolveMoveNodePlacement
+ export_resolveMoveNodePlacement -.-> export_MoveNodeToPlacementArgs
+ export_resolveMoveNodePlacement -.-> export_PlacementResolutionResult
export_resolveStudioBindableEvents["resolveStudioBindableEvents"]
module_src_bindingMetadataModel_ts --> export_resolveStudioBindableEvents
export_resolveStudioBindableEvents -.-> export_StudioBindableEventOption
@@ -16708,6 +16802,7 @@
Export graph
export_StudioContextValue export_StudioContextValue -.->
export_InsertCatalogEntry export_StudioContextValue -.-> export_NodePlacement
export_StudioContextValue -.-> export_StudioAdminRouteId
+ export_StudioContextValue -.-> export_StudioComponentMetaRegistry
export_StudioContextValue -.-> export_StudioLocale export_StudioContextValue
-.-> export_StudioManifest export_StudioContextValue -.-> export_StudioMode
export_StudioContextValue -.-> export_StudioModuleId export_StudioContextValue
@@ -16837,9 +16932,6 @@
Export graph
module_src_core_studioPackageBoundary_ts["src/core/studioPackageBoundary.ts"]
module_src_core_StudioProvider_test_ts["src/core/StudioProvider.test.ts"]
module_src_core_StudioProvider_ts["src/core/StudioProvider.ts"]
- module_src_dnd_index_ts["src/dnd/index.ts"]
- module_src_dnd_primitives_ts["src/dnd/primitives.ts"]
- module_src_dnd_state_ts["src/dnd/state.ts"]
module_src_externalApiApi_ts["src/externalApiApi.ts"]
module_src_externalApiAuthoring_public_test_ts["src/externalApiAuthoring.public.test.ts"]
module_src_externalApiAuthoring_ts["src/externalApiAuthoring.ts"]
@@ -17091,7 +17183,13 @@
Export graph
module_src_ui_admin_pages_ThemeAdminPage_test_ts["src/ui/admin/pages/ThemeAdminPage.test.ts"]
module_src_ui_admin_pages_ThemeAdminPage_tsx["src/ui/admin/pages/ThemeAdminPage.tsx"]
module_src_ui_AnkhStudio_ts["src/ui/AnkhStudio.ts"]
+ module_src_ui_canvas_canvasDndInteraction_test_ts["src/ui/canvas/canvasDndInteraction.test.ts"]
+ module_src_ui_canvas_canvasDndInteraction_ts["src/ui/canvas/canvasDndInteraction.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_test_ts["src/ui/canvas/StudioCanvasDndOverlay.test.ts"]
+ module_src_ui_canvas_StudioCanvasDndOverlay_tsx["src/ui/canvas/StudioCanvasDndOverlay.tsx"]
module_src_ui_studioAppBarModel_ts["src/ui/studioAppBarModel.ts"]
+ module_src_ui_StudioDeleteDialog_tsx["src/ui/StudioDeleteDialog.tsx"]
+ module_src_ui_StudioInsertDialog_tsx["src/ui/StudioInsertDialog.tsx"]
module_src_ui_useStudioAppBarAugmentation_test_ts["src/ui/useStudioAppBarAugmentation.test.ts"]
module_src_ui_useStudioAppBarAugmentation_ts["src/ui/useStudioAppBarAugmentation.ts"]
module_src_upsertExternalApiDataSource_ts["src/upsertExternalApiDataSource.ts"]
@@ -17104,9 +17202,6 @@
Export graph
export_ActionDefinition["ActionDefinition"]
module_src_index_ts --> export_ActionDefinition
export_ActionDefinition -.-> export_StudioActionPayloadSchema
- export_addNodeToTree["addNodeToTree"]
- module_src_index_ts --> export_addNodeToTree
- export_addNodeToTree -.-> export_StudioComponentMetaRegistry
export_appendStudioEventBinding["appendStudioEventBinding"]
module_src_bindingMutationModel_ts --> export_appendStudioEventBinding
export_assessStudioBindingCompatibility["assessStudioBindingCompatibility"]
@@ -17203,8 +17298,6 @@
Export graph
module_src_index_ts --> export_InsertRecipeNode
export_ModuleDefinition["ModuleDefinition"]
module_src_index_ts --> export_ModuleDefinition
- export_moveNodeInTree["moveNodeInTree"]
- module_src_index_ts --> export_moveNodeInTree
export_moveNodeToPlacement["moveNodeToPlacement"]
module_src_index_ts --> export_moveNodeToPlacement
export_moveNodeToPlacement -.-> export_MoveNodeToPlacementArgs
@@ -17284,6 +17377,10 @@
Export graph
export_resolveInsertPlacement -.-> export_PlacementKind
export_resolveInsertPlacement -.-> export_PlacementResolutionResult
export_resolveInsertPlacement -.-> export_StudioComponentMetaRegistry
+ export_resolveMoveNodePlacement["resolveMoveNodePlacement"]
+ module_src_index_ts --> export_resolveMoveNodePlacement
+ export_resolveMoveNodePlacement -.-> export_MoveNodeToPlacementArgs
+ export_resolveMoveNodePlacement -.-> export_PlacementResolutionResult
export_resolveStudioBindableEvents["resolveStudioBindableEvents"]
module_src_bindingMetadataModel_ts --> export_resolveStudioBindableEvents
export_resolveStudioBindableEvents -.-> export_StudioBindableEventOption
@@ -17358,6 +17455,7 @@
Export graph
export_StudioContextValue -.-> export_InsertCatalogEntry
export_StudioContextValue -.-> export_NodePlacement
export_StudioContextValue -.-> export_StudioAdminRouteId
+ export_StudioContextValue -.-> export_StudioComponentMetaRegistry
export_StudioContextValue -.-> export_StudioLocale
export_StudioContextValue -.-> export_StudioManifest
export_StudioContextValue -.-> export_StudioMode
@@ -17447,29 +17545,6 @@
Export graph
module_src_projectIdentity_ts --> export_validateProjectCreationInput
export_validateProjectCreationInput -.-> export_ProjectCreationValidationResult
export_validateProjectCreationInput -.-> export_StudioProjectSummary
-
-
-
-
- addNodeToTree sequence
- diagrams/sequences/add-node-to-tree.mmd
-
- sequenceDiagram participant participant_addNodeToTree as addNodeToTree participant
- participant_canAcceptChild as canAcceptChild
- participant_addNodeToTree->>participant_canAcceptChild: canAcceptChild()
- participant_canAcceptChild-->>participant_addNodeToTree: return
-
-
- View Mermaid source
-
-sequenceDiagram
- participant participant_addNodeToTree as addNodeToTree
- participant participant_canAcceptChild as canAcceptChild
- participant_addNodeToTree->>participant_canAcceptChild: canAcceptChild()
- participant_canAcceptChild-->>participant_addNodeToTree: return
@@ -17827,6 +17902,89 @@
removeStudioPropBinding sequence
participant_writeBinding->>participant_isEmptyBinding: isEmptyBinding()
participant_isEmptyBinding-->>participant_writeBinding: return
participant_writeBinding-->>participant_removeStudioPropBinding: return
+
+
+
+
+ resolveInsertPlacement sequence
+ diagrams/sequences/resolve-insert-placement.mmd
+
+ sequenceDiagram participant participant_canAcceptChild as canAcceptChild participant
+ participant_findNodeById as findNodeById participant participant_findNodeWithParent
+ as findNodeWithParent participant participant_normalizeRel as normalizeRel
+ participant participant_resolveInsertPlacement as resolveInsertPlacement participant
+ participant_resolveRouteScreenFilePath as resolveRouteScreenFilePath participant
+ participant_validateNodePlacement as validateNodePlacement participant
+ participant_visit as visit
+ participant_resolveInsertPlacement->>participant_findNodeWithParent:
+ findNodeWithParent() participant_findNodeWithParent->>participant_visit:
+ visit() participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_resolveRouteScreenFilePath:
+ resolveRouteScreenFilePath()
+ participant_resolveRouteScreenFilePath->>participant_normalizeRel:
+ normalizeRel()
+ participant_normalizeRel-->>participant_resolveRouteScreenFilePath: return
+ participant_resolveRouteScreenFilePath-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_findNodeWithParent: return
+ participant_findNodeWithParent-->>participant_resolveInsertPlacement: return
+ participant_resolveInsertPlacement->>participant_validateNodePlacement:
+ validateNodePlacement()
+ participant_validateNodePlacement->>participant_findNodeById: findNodeById()
+ participant_findNodeById->>participant_findNodeById: findNodeById()
+ participant_findNodeById-->>participant_findNodeById: return
+ participant_findNodeById-->>participant_validateNodePlacement: return
+ participant_validateNodePlacement->>participant_canAcceptChild:
+ canAcceptChild()
+ participant_canAcceptChild-->>participant_validateNodePlacement: return
+ participant_validateNodePlacement-->>participant_resolveInsertPlacement:
+ return
+
+
+ View Mermaid source
+
+sequenceDiagram
+ participant participant_canAcceptChild as canAcceptChild
+ participant participant_findNodeById as findNodeById
+ participant participant_findNodeWithParent as findNodeWithParent
+ participant participant_normalizeRel as normalizeRel
+ participant participant_resolveInsertPlacement as resolveInsertPlacement
+ participant participant_resolveRouteScreenFilePath as resolveRouteScreenFilePath
+ participant participant_validateNodePlacement as validateNodePlacement
+ participant participant_visit as visit
+ participant_resolveInsertPlacement->>participant_findNodeWithParent: findNodeWithParent()
+ participant_findNodeWithParent->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_visit: visit()
+ participant_visit->>participant_resolveRouteScreenFilePath: resolveRouteScreenFilePath()
+ participant_resolveRouteScreenFilePath->>participant_normalizeRel: normalizeRel()
+ participant_normalizeRel-->>participant_resolveRouteScreenFilePath: return
+ participant_resolveRouteScreenFilePath-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_visit: return
+ participant_visit-->>participant_findNodeWithParent: return
+ participant_findNodeWithParent-->>participant_resolveInsertPlacement: return
+ participant_resolveInsertPlacement->>participant_validateNodePlacement: validateNodePlacement()
+ participant_validateNodePlacement->>participant_findNodeById: findNodeById()
+ participant_findNodeById->>participant_findNodeById: findNodeById()
+ participant_findNodeById-->>participant_findNodeById: return
+ participant_findNodeById-->>participant_validateNodePlacement: return
+ participant_validateNodePlacement->>participant_canAcceptChild: canAcceptChild()
+ participant_canAcceptChild-->>participant_validateNodePlacement: return
+ participant_validateNodePlacement-->>participant_resolveInsertPlacement: return
@@ -18960,32 +19118,55 @@
isImageAssetShape
>
src/canvasDragModel.ts
+
+ treeContainsNode
+ src/canvasDragModel.ts:33:1
+ No description available.
+
+
+ resolveCanvasDragSession
+ src/canvasDragModel.ts:38:1
+ No description available.
+
createStudioCanvasDragPayload
- src/canvasDragModel.ts:16:1
+ src/canvasDragModel.ts:60:1
No description available.
isStudioCanvasDragPayload
- src/canvasDragModel.ts:20:1
+ src/canvasDragModel.ts:64:1
No description available.
isValidCanvasDropZone
- src/canvasDragModel.ts:28:1
+ src/canvasDragModel.ts:72:1
No description available.
resolveCanvasDropZoneSlots
- src/canvasDragModel.ts:34:1
+ src/canvasDragModel.ts:78:1
No description available.
findDropZoneByKind
- src/canvasDragModel.ts:47:1
+ src/canvasDragModel.ts:91:1
+ No description available.
+
+
+ resolveCanvasDropZoneRect
+ src/canvasDragModel.ts:98:1
+ No description available.
+
+
+ resolveCanvasDragPreviewText
+ src/canvasDragModel.ts:132:1
No description available.
@@ -19015,12 +19196,12 @@
buildRoot
src/canvasDropZones.ts
resolveCanvasDropZones
- src/canvasDropZones.ts:23:1
+ src/canvasDropZones.ts:28:1
No description available.
getValidCanvasDropZones
- src/canvasDropZones.ts:64:1
+ src/canvasDropZones.ts:86:1
No description available.
@@ -19619,17 +19800,17 @@
createDeferred
src/core/StudioProvider.ts
noop
- src/core/StudioProvider.ts:59:7
+ src/core/StudioProvider.ts:71:7
No description available.
noopAsync
- src/core/StudioProvider.ts:60:7
+ src/core/StudioProvider.ts:72:7
No description available.
StudioProvider
- src/core/StudioProvider.ts:63:14
+ src/core/StudioProvider.ts:75:14
No description available.
StudioProvider
data-search="useStudioManifestPersistence src/core/StudioProvider.ts "
>
useStudioManifestPersistence
- src/core/StudioProvider.ts:308:1
+ src/core/StudioProvider.ts:381:1
No description available.
requestStudioManifest
- src/core/StudioProvider.ts:409:1
+ src/core/StudioProvider.ts:482:1
No description available.
saveStudioManifest
- src/core/StudioProvider.ts:418:1
+ src/core/StudioProvider.ts:491:1
No description available.
readPersistenceJson
- src/core/StudioProvider.ts:431:1
+ src/core/StudioProvider.ts:504:1
No description available.
createPersistenceError
- src/core/StudioProvider.ts:439:1
+ src/core/StudioProvider.ts:512:1
No description available.
toPersistenceMessage
- src/core/StudioProvider.ts:446:1
- No description available.
-
-
-
-
-
- src/dnd/state.ts
-
- createIdleStudioDragState
- src/dnd/state.ts:6:14
+ src/core/StudioProvider.ts:519:1
No description available.
@@ -21902,7 +22073,7 @@ walk
data-search="getStudioAdminLayoutTsx src/host/layout/layoutGenerator.ts "
>
getStudioAdminLayoutTsx
- src/host/layout/layoutGenerator.ts:458:1
+ src/host/layout/layoutGenerator.ts:460:1
No description available.
getStudioAdminLayoutTsx
data-search="createStudioAdminRouteGeneratedFiles src/host/layout/layoutGenerator.ts "
>
createStudioAdminRouteGeneratedFiles
- src/host/layout/layoutGenerator.ts:472:1
+ src/host/layout/layoutGenerator.ts:474:1
No description available.
createStudioAdminRouteGeneratedFiles
data-search="resolveStudioAdminRouteFilePath src/host/layout/layoutGenerator.ts "
>
resolveStudioAdminRouteFilePath
- src/host/layout/layoutGenerator.ts:479:1
+ src/host/layout/layoutGenerator.ts:481:1
No description available.
resolveStudioAdminRouteFilePath
data-search="getStudioAdminRouteTsx src/host/layout/layoutGenerator.ts "
>
getStudioAdminRouteTsx
- src/host/layout/layoutGenerator.ts:502:1
+ src/host/layout/layoutGenerator.ts:504:1
No description available.
normalizeRel
- src/host/layout/layoutGenerator.ts:516:1
+ src/host/layout/layoutGenerator.ts:518:1
No description available.
normalizeRel
data-search="prepareNavigatorForGeneratedRoutes src/host/layout/layoutGenerator.ts "
>
prepareNavigatorForGeneratedRoutes
- src/host/layout/layoutGenerator.ts:520:1
+ src/host/layout/layoutGenerator.ts:522:1
No description available.
prepareNavigatorForGeneratedRoutes
data-search="prepareRouteForGeneratedRoutes src/host/layout/layoutGenerator.ts "
>
prepareRouteForGeneratedRoutes
- src/host/layout/layoutGenerator.ts:564:1
+ src/host/layout/layoutGenerator.ts:566:1
No description available.
prepareRouteForGeneratedRoutes
data-search="normalizeGeneratedRouteName src/host/layout/layoutGenerator.ts "
>
normalizeGeneratedRouteName
- src/host/layout/layoutGenerator.ts:572:1
+ src/host/layout/layoutGenerator.ts:574:1
No description available.
normalizeGeneratedRouteName
data-search="resolveValidGeneratedInitialRouteName src/host/layout/layoutGenerator.ts "
>
resolveValidGeneratedInitialRouteName
- src/host/layout/layoutGenerator.ts:577:1
+ src/host/layout/layoutGenerator.ts:579:1
No description available.
@@ -24351,7 +24522,7 @@
collectZoraExtensionDependencies
src/index.test.ts
createRoot
- src/index.test.ts:51:7
+ src/index.test.ts:53:7
No description available.
@@ -24361,167 +24532,162 @@
createRoot
src/index.ts
generateStudioId
- src/index.ts:524:14
+ src/index.ts:525:14
No description available.
cloneWithNewIds
- src/index.ts:531:14
+ src/index.ts:532:14
No description available.
findNodeById
- src/index.ts:548:14
+ src/index.ts:549:14
No description available.
updateNodeInTree
- src/index.ts:560:14
+ src/index.ts:561:14
No description available.
removeNodeFromTree
- src/index.ts:588:14
- No description available.
-
-
- addNodeToTree
- src/index.ts:606:14
- No description available.
-
-
- moveNodeInTree
- src/index.ts:639:14
+ src/index.ts:589:14
No description available.
findNodeWithParent
- src/index.ts:675:1
+ src/index.ts:613:1
No description available.
visit
- src/index.ts:680:9
+ src/index.ts:618:9
No description available.
isDescendantNode
- src/index.ts:699:1
+ src/index.ts:637:1
No description available.
removeNodeForMove
- src/index.ts:710:1
+ src/index.ts:648:1
No description available.
canAcceptChild
- src/index.ts:765:1
+ src/index.ts:703:1
No description available.
validateNodePlacement
- src/index.ts:777:1
+ src/index.ts:715:1
No description available.
resolveInsertPlacement
- src/index.ts:832:1
+ src/index.ts:802:1
No description available.
resolveDefaultInsertPlacement
- src/index.ts:893:1
+ src/index.ts:863:1
No description available.
insertChildAtIndex
- src/index.ts:950:1
+ src/index.ts:920:1
No description available.
insertNodeAtPlacement
- src/index.ts:995:1
+ src/index.ts:965:1
No description available.
getAdjustedMovePlacement
- src/index.ts:1034:1
+ src/index.ts:1004:1
+ No description available.
+
+
+ resolveMoveNodePlacement
+ src/index.ts:1033:1
No description available.
moveNodeToPlacement
- src/index.ts:1063:1
+ src/index.ts:1101:1
No description available.
getInsertCatalogCategoryLabel
- src/index.ts:1163:1
+ src/index.ts:1172:1
No description available.
resolveCategoryOrder
- src/index.ts:1167:1
+ src/index.ts:1176:1
No description available.
describeInsertRecipeIssue
- src/index.ts:1172:1
+ src/index.ts:1181:1
No description available.
validateInsertRecipe
- src/index.ts:1180:1
+ src/index.ts:1189:1
No description available.
visit
- src/index.ts:1184:9
+ src/index.ts:1193:9
No description available.
createNodeFromRecipe
- src/index.ts:1217:1
+ src/index.ts:1226:1
No description available.
buildNode
- src/index.ts:1222:9
+ src/index.ts:1231:9
No description available.
createNodeFromCatalogEntry
- src/index.ts:1237:1
+ src/index.ts:1246:1
No description available.
createComponentEntry
- src/index.ts:1257:1
+ src/index.ts:1266:1
No description available.
createRecipeEntry
- src/index.ts:1280:1
+ src/index.ts:1289:1
No description available.
buildInsertCatalogEntries
- src/index.ts:1318:1
+ src/index.ts:1327:1
No description available.
resolvePlacementForEntry
- src/index.ts:1344:1
+ src/index.ts:1353:1
No description available.
resolveInsertCatalogEntries
- src/index.ts:1360:1
+ src/index.ts:1369:1
No description available.
isStyleRecord
- src/index.ts:1409:1
+ src/index.ts:1418:1
No description available.
@@ -24815,17 +24981,17 @@
createManifest
src/manifestState.test.ts
createManifest
- src/manifestState.test.ts:37:1
+ src/manifestState.test.ts:36:1
No description available.
createScreens
- src/manifestState.test.ts:91:1
+ src/manifestState.test.ts:90:1
No description available.
createId
- src/manifestState.test.ts:310:11
+ src/manifestState.test.ts:313:11
No description available.
@@ -24840,7 +25006,7 @@
createId
src/manifestState.ts
generateManifestStateId
- src/manifestState.ts:95:14
+ src/manifestState.ts:96:14
No description available.
generateManifestStateId
data-search="createStudioManifestFingerprint src/manifestState.ts "
>
createStudioManifestFingerprint
- src/manifestState.ts:102:1
+ src/manifestState.ts:103:1
No description available.
pathToKey
- src/manifestState.ts:119:1
+ src/manifestState.ts:120:1
No description available.
isRouteGroupSegment
- src/manifestState.ts:123:1
+ src/manifestState.ts:124:1
No description available.
collectScreenRouteEntries
- src/manifestState.ts:127:1
+ src/manifestState.ts:128:1
No description available.
groupScreenRouteEntries
- src/manifestState.ts:153:1
+ src/manifestState.ts:154:1
No description available.
listScreenIdsInRouteOrder
- src/manifestState.ts:172:1
+ src/manifestState.ts:173:1
No description available.
resolveInitialScreenId
- src/manifestState.ts:181:1
+ src/manifestState.ts:182:1
No description available.
resolveInitialActiveScreenId
- src/manifestState.ts:206:1
+ src/manifestState.ts:207:1
No description available.
resolveActiveRootNode
- src/manifestState.ts:214:1
+ src/manifestState.ts:215:1
No description available.
findNodeInManifest
- src/manifestState.ts:222:1
+ src/manifestState.ts:223:1
No description available.
resolveSafeSelectedNodeId
- src/manifestState.ts:233:1
+ src/manifestState.ts:234:1
No description available.
findScreenIdForNode
- src/manifestState.ts:241:1
+ src/manifestState.ts:242:1
No description available.
updateStudioManifestNode
- src/manifestState.ts:251:1
+ src/manifestState.ts:252:1
No description available.
deleteStudioManifestNode
- src/manifestState.ts:276:1
- No description available.
-
-
- moveStudioManifestNode
- src/manifestState.ts:305:1
+ src/manifestState.ts:277:1
No description available.
moveStudioManifestNode
data-search="insertStudioManifestNodeAtPlacement src/manifestState.ts "
>
insertStudioManifestNodeAtPlacement
- src/manifestState.ts:330:1
+ src/manifestState.ts:314:1
No description available.
insertStudioManifestNodeAtPlacement
data-search="moveStudioManifestNodeToPlacement src/manifestState.ts "
>
moveStudioManifestNodeToPlacement
- src/manifestState.ts:367:1
+ src/manifestState.ts:348:1
No description available.
moveStudioManifestNodeToPlacement
data-search="updateStudioManifestDataBindings src/manifestState.ts "
>
updateStudioManifestDataBindings
- src/manifestState.ts:423:1
+ src/manifestState.ts:383:1
No description available.
updateStudioManifestDataBindings
data-search="updateStudioManifestDataSources src/manifestState.ts "
>
updateStudioManifestDataSources
- src/manifestState.ts:430:1
+ src/manifestState.ts:390:1
No description available.
createDefaultThemeConfig
- src/manifestState.ts:437:1
+ src/manifestState.ts:397:1
No description available.
addStudioManifestTheme
- src/manifestState.ts:455:1
+ src/manifestState.ts:415:1
No description available.
updateStudioManifestTheme
- src/manifestState.ts:462:1
+ src/manifestState.ts:422:1
No description available.
deleteStudioManifestTheme
- src/manifestState.ts:482:1
+ src/manifestState.ts:442:1
No description available.
deleteStudioManifestTheme
data-search="setStudioManifestActiveThemeId src/manifestState.ts "
>
setStudioManifestActiveThemeId
- src/manifestState.ts:497:1
+ src/manifestState.ts:457:1
No description available.
setStudioManifestActiveThemeId
data-search="setStudioManifestActiveThemeMode src/manifestState.ts "
>
setStudioManifestActiveThemeMode
- src/manifestState.ts:504:1
+ src/manifestState.ts:464:1
No description available.
setStudioManifestActiveThemeMode
data-search="updateStudioManifestModuleConfig src/manifestState.ts "
>
updateStudioManifestModuleConfig
- src/manifestState.ts:511:1
+ src/manifestState.ts:471:1
No description available.
updateStudioManifestModuleConfig
data-search="updateStudioManifestOAuthProviders src/manifestState.ts "
>
updateStudioManifestOAuthProviders
- src/manifestState.ts:567:1
+ src/manifestState.ts:527:1
No description available.
getPrimaryNavigatorPath
- src/manifestState.ts:598:1
+ src/manifestState.ts:558:1
No description available.
findParentPathForScreenId
- src/manifestState.ts:608:1
+ src/manifestState.ts:568:1
No description available.
findRoutesAtParentPath
- src/manifestState.ts:631:1
+ src/manifestState.ts:591:1
No description available.
insertRouteAtParentPath
- src/manifestState.ts:645:1
+ src/manifestState.ts:605:1
No description available.
findNavigatorAtPath
- src/manifestState.ts:666:1
+ src/manifestState.ts:626:1
No description available.
updateNavigatorAtPath
- src/manifestState.ts:680:1
+ src/manifestState.ts:640:1
No description available.
updateNavigatorAtPath
data-search="setStudioManifestNavigatorType src/manifestState.ts "
>
setStudioManifestNavigatorType
- src/manifestState.ts:701:1
+ src/manifestState.ts:661:1
No description available.
setStudioManifestNavigatorType
data-search="setStudioManifestNavigatorInitialRoute src/manifestState.ts "
>
setStudioManifestNavigatorInitialRoute
- src/manifestState.ts:718:1
+ src/manifestState.ts:678:1
No description available.
addStudioManifestScreen
- src/manifestState.ts:740:1
+ src/manifestState.ts:700:1
No description available.
deleteStudioManifestScreen
- src/manifestState.ts:807:1
+ src/manifestState.ts:767:1
No description available.
reorderStudioManifestScreens
- src/manifestState.ts:852:1
+ src/manifestState.ts:812:1
No description available.
removeScreenIdFromRoutes
- src/manifestState.ts:865:1
+ src/manifestState.ts:825:1
No description available.
makeUniqueSiblingRouteName
- src/manifestState.ts:897:1
+ src/manifestState.ts:857:1
No description available.
toCanonicalRoutePattern
- src/manifestState.ts:910:1
+ src/manifestState.ts:870:1
No description available.
makeUniqueRouteNameForParent
- src/manifestState.ts:917:1
+ src/manifestState.ts:877:1
No description available.
normalizeRouteName
- src/manifestState.ts:938:1
+ src/manifestState.ts:898:1
No description available.
cloneNodeWithNewIds
- src/manifestState.ts:948:1
+ src/manifestState.ts:908:1
No description available.
updateNodeInManifestTree
- src/manifestState.ts:962:1
+ src/manifestState.ts:922:1
No description available.
removeNodeFromManifestTree
- src/manifestState.ts:987:1
- No description available.
-
-
- moveNodeInManifestTree
- src/manifestState.ts:1003:1
+ src/manifestState.ts:947:1
No description available.
-
- findNodeWithParent
- src/manifestState.ts:1036:1
+
+ collectNodeIds
+ src/manifestState.ts:963:1
No description available.
visit
- src/manifestState.ts:1039:9
- No description available.
-
-
- validateManifestNodePlacement
- src/manifestState.ts:1054:1
- No description available.
-
-
- insertChildAtIndex
- src/manifestState.ts:1074:1
- No description available.
-
-
- isDescendantNode
- src/manifestState.ts:1105:1
- No description available.
-
-
- removeNodeForMove
- src/manifestState.ts:1113:1
- No description available.
-
-
- adjustMovePlacement
- src/manifestState.ts:1155:1
+ src/manifestState.ts:965:9
No description available.
adjustMovePlacement
data-search="normalizeNavigatorAfterRouteUpdate src/manifestState.ts "
>
normalizeNavigatorAfterRouteUpdate
- src/manifestState.ts:1170:1
+ src/manifestState.ts:973:1
No description available.
isStyleRecord
- src/manifestState.ts:1191:1
+ src/manifestState.ts:994:1
No description available.
@@ -26142,7 +26273,7 @@ runtimeNodeMeasurementChangeAffectsActiveIndicators
data-search="shouldRenderSelectedNodeChrome src/runtime/runtimeNodeMeasurement.ts "
>
shouldRenderSelectedNodeChrome
- src/runtime/runtimeNodeMeasurement.ts:63:1
+ src/runtime/runtimeNodeMeasurement.ts:65:1
No description available.
shouldRenderSelectedNodeChrome
data-search="unionMeasuredRects src/runtime/runtimeNodeMeasurement.ts "
>
unionMeasuredRects
- src/runtime/runtimeNodeMeasurement.ts:77:1
+ src/runtime/runtimeNodeMeasurement.ts:79:1
No description available.
unionMeasuredRects
data-search="measureNativeRuntimeNodeView src/runtime/runtimeNodeMeasurement.ts "
>
measureNativeRuntimeNodeView
- src/runtime/runtimeNodeMeasurement.ts:95:1
+ src/runtime/runtimeNodeMeasurement.ts:97:1
No description available.
measureNativeRuntimeNodeView
data-search="createNativeRuntimeNodeMeasurement src/runtime/runtimeNodeMeasurement.ts "
>
createNativeRuntimeNodeMeasurement
- src/runtime/runtimeNodeMeasurement.ts:105:1
+ src/runtime/runtimeNodeMeasurement.ts:107:1
No description available.
createNativeRuntimeNodeMeasurement
data-search="createRuntimeNodeMeasurementRegistry src/runtime/runtimeNodeMeasurement.ts "
>
createRuntimeNodeMeasurementRegistry
- src/runtime/runtimeNodeMeasurement.ts:116:1
+ src/runtime/runtimeNodeMeasurement.ts:118:1
No description available.
createRuntimeNodeMeasurementRegistry
data-search="selectPreferredRuntimeNodeMeasurements src/runtime/runtimeNodeMeasurement.ts "
>
selectPreferredRuntimeNodeMeasurements
- src/runtime/runtimeNodeMeasurement.ts:149:1
+ src/runtime/runtimeNodeMeasurement.ts:151:1
No description available.
selectPreferredRuntimeNodeMeasurements
data-search="getActiveRuntimeNodeMeasurements src/runtime/runtimeNodeMeasurement.ts "
>
getActiveRuntimeNodeMeasurements
- src/runtime/runtimeNodeMeasurement.ts:158:1
+ src/runtime/runtimeNodeMeasurement.ts:160:1
No description available.
getActiveRuntimeNodeMeasurements
data-search="hasActiveRuntimeNodeMeasurements src/runtime/runtimeNodeMeasurement.ts "
>
hasActiveRuntimeNodeMeasurements
- src/runtime/runtimeNodeMeasurement.ts:175:1
+ src/runtime/runtimeNodeMeasurement.ts:179:1
No description available.
hasActiveRuntimeNodeMeasurements
data-search="measureRuntimeNodeIndicators src/runtime/runtimeNodeMeasurement.ts "
>
measureRuntimeNodeIndicators
- src/runtime/runtimeNodeMeasurement.ts:183:1
+ src/runtime/runtimeNodeMeasurement.ts:191:1
No description available.
measureRuntimeNodeIndicators
data-search="createActiveResizeTargetCoordinator src/runtime/runtimeNodeMeasurement.ts "
>
createActiveResizeTargetCoordinator
- src/runtime/runtimeNodeMeasurement.ts:233:1
+ src/runtime/runtimeNodeMeasurement.ts:266:1
No description available.
createActiveResizeTargetCoordinator
data-search="createSelectedIndicatorViewProps src/runtime/runtimeNodeMeasurement.ts "
>
createSelectedIndicatorViewProps
- src/runtime/runtimeNodeMeasurement.ts:276:1
+ src/runtime/runtimeNodeMeasurement.ts:309:1
No description available.
@@ -26240,7 +26371,7 @@
src/runtime/stationarySelection.ts
data-search="isWebElementLike src/runtime/stationarySelection.ts "
>
isWebElementLike
-
src/runtime/stationarySelection.ts:85:1
+
src/runtime/stationarySelection.ts:89:1
No description available.
isWebElementLike
data-search="getWebResizeTarget src/runtime/stationarySelection.ts "
>
getWebResizeTarget
- src/runtime/stationarySelection.ts:95:1
+ src/runtime/stationarySelection.ts:99:1
No description available.
getWebResizeTarget
data-search="getWebDescendantResizeTargets src/runtime/stationarySelection.ts "
>
getWebDescendantResizeTargets
- src/runtime/stationarySelection.ts:99:1
+ src/runtime/stationarySelection.ts:103:1
No description available.
toMeasuredRect
- src/runtime/stationarySelection.ts:110:1
+ src/runtime/stationarySelection.ts:114:1
No description available.
toMeasuredRect
data-search="measureRenderedBoxes src/runtime/stationarySelection.ts "
>
measureRenderedBoxes
- src/runtime/stationarySelection.ts:119:1
+ src/runtime/stationarySelection.ts:123:1
No description available.
measureRootView
- src/runtime/stationarySelection.ts:128:1
+ src/runtime/stationarySelection.ts:132:1
No description available.
measureRootView
data-search="measureRuntimeNodeWebView src/runtime/stationarySelection.ts "
>
measureRuntimeNodeWebView
- src/runtime/stationarySelection.ts:140:1
+ src/runtime/stationarySelection.ts:144:1
No description available.
measureRuntimeNodeWebView
data-search="measureAuthoredWebView src/runtime/stationarySelection.ts "
>
measureAuthoredWebView
- src/runtime/stationarySelection.ts:154:1
+ src/runtime/stationarySelection.ts:158:1
No description available.
measureAuthoredWebView
data-search="areIndicatorRectsEqual src/runtime/stationarySelection.ts "
>
areIndicatorRectsEqual
- src/runtime/stationarySelection.ts:163:1
+ src/runtime/stationarySelection.ts:167:1
No description available.
areIndicatorRectsEqual
data-search="useStudioUnsupportedNodeMeasurement src/runtime/stationarySelection.ts "
>
useStudioUnsupportedNodeMeasurement
- src/runtime/stationarySelection.ts:187:1
+ src/runtime/stationarySelection.ts:191:1
No description available.
useStudioUnsupportedNodeMeasurement
data-search="StudioNodeTouchRecorder src/runtime/stationarySelection.ts "
>
StudioNodeTouchRecorder
- src/runtime/stationarySelection.ts:220:1
+ src/runtime/stationarySelection.ts:224:1
No description available.
StudioNodeTouchRecorder
data-search="recordInteraction src/runtime/stationarySelection.ts "
>
recordInteraction
- src/runtime/stationarySelection.ts:232:3
+ src/runtime/stationarySelection.ts:236:3
No description available.
recordInteraction
data-search="handlePointerDown src/runtime/stationarySelection.ts "
>
handlePointerDown
- src/runtime/stationarySelection.ts:246:3
+ src/runtime/stationarySelection.ts:250:3
No description available.
handlePointerDown
data-search="handleTouchStart src/runtime/stationarySelection.ts "
>
handleTouchStart
- src/runtime/stationarySelection.ts:257:3
+ src/runtime/stationarySelection.ts:261:3
No description available.
handleTouchStart
data-search="handleInteractionCompletion src/runtime/stationarySelection.ts "
>
handleInteractionCompletion
- src/runtime/stationarySelection.ts:266:3
+ src/runtime/stationarySelection.ts:270:3
No description available.
handleLayout
- src/runtime/stationarySelection.ts:270:3
+ src/runtime/stationarySelection.ts:274:3
No description available.
handleLayout
data-search="createStudioStationarySelectionWrapNode src/runtime/stationarySelection.ts "
>
createStudioStationarySelectionWrapNode
- src/runtime/stationarySelection.ts:350:1
+ src/runtime/stationarySelection.ts:363:1
No description available.
createStudioStationarySelectionWrapNode
data-search="StationaryTapSelector src/runtime/stationarySelection.ts "
>
StationaryTapSelector
- src/runtime/stationarySelection.ts:389:1
+ src/runtime/stationarySelection.ts:410:1
No description available.
handleScroll
- src/runtime/stationarySelection.ts:646:11
+ src/runtime/stationarySelection.ts:704:11
No description available.
handleResize
- src/runtime/stationarySelection.ts:647:11
+ src/runtime/stationarySelection.ts:705:11
No description available.
@@ -26999,7 +27130,7 @@
KeyValue
src/ui/admin/AnkhAdminPage.tsx
AnkhAdminPage
- src/ui/admin/AnkhAdminPage.tsx:74:1
+ src/ui/admin/AnkhAdminPage.tsx:72:1
No description available.
@@ -27899,7 +28030,7 @@
EventPayloadSummary
>
describeEventBinding
- src/ui/admin/pages/bindings/EventBindingsCard.tsx:89:1
+ src/ui/admin/pages/bindings/EventBindingsCard.tsx:93:1
No description available.
@@ -27909,7 +28040,7 @@
describeEventBinding
>
describeBindingInput
- src/ui/admin/pages/bindings/EventBindingsCard.tsx:100:1
+ src/ui/admin/pages/bindings/EventBindingsCard.tsx:111:1
No description available.
@@ -28732,6 +28863,129 @@
AnkhStudio
+
+
+ src/ui/canvas/canvasDndInteraction.test.ts
+
+ moveNode
+ src/ui/canvas/canvasDndInteraction.test.ts:43:11
+ No description available.
+
+
+
+
+
+ src/ui/canvas/canvasDndInteraction.ts
+
+ createCanvasDraggableSessionKey
+ src/ui/canvas/canvasDndInteraction.ts:11:1
+ No description available.
+
+
+ sortCanvasDropTargetsBySpecificity
+ src/ui/canvas/canvasDndInteraction.ts:15:1
+ No description available.
+
+
+ resetCanvasDragSession
+ src/ui/canvas/canvasDndInteraction.ts:23:1
+ No description available.
+
+
+ commitCanvasDrop
+ src/ui/canvas/canvasDndInteraction.ts:29:1
+ No description available.
+
+
+ completeCanvasDropAfterAdapter
+ src/ui/canvas/canvasDndInteraction.ts:41:1
+ No description available.
+
+
+ activateCanvasDrag
+ src/ui/canvas/canvasDndInteraction.ts:56:1
+ No description available.
+
+
+
+
+
+ src/ui/canvas/StudioCanvasDndOverlay.tsx
+
+ resolveDropZoneViews
+ src/ui/canvas/StudioCanvasDndOverlay.tsx:57:1
+ No description available.
+
+
+ CanvasDropZone
+ src/ui/canvas/StudioCanvasDndOverlay.tsx:87:1
+ No description available.
+
+
+ CanvasDragPreview
+ src/ui/canvas/StudioCanvasDndOverlay.tsx:140:1
+ No description available.
+
+
+ StudioCanvasDndOverlay
+ src/ui/canvas/StudioCanvasDndOverlay.tsx:179:1
+ No description available.
+
+
+ resetDrag
+ src/ui/canvas/StudioCanvasDndOverlay.tsx:211:9
+ No description available.
+
+
+
src/ui/studioAppBarModel.ts
data-search="resolveStudioAppBarContextActions src/ui/studioAppBarModel.ts "
>
resolveStudioAppBarContextActions
- src/ui/studioAppBarModel.ts:11:1
+ src/ui/studioAppBarModel.ts:14:1
+ No description available.
+
+
+
+
+
+ src/ui/StudioDeleteDialog.tsx
+
+ StudioDeleteDialog
+ src/ui/StudioDeleteDialog.tsx:11:1
+ No description available.
+
+
+
+
+
+ src/ui/StudioInsertDialog.tsx
+
+ StudioInsertDialog
+ src/ui/StudioInsertDialog.tsx:24:1
No description available.
@@ -28758,12 +29042,20 @@ resolveStudioAppBarContextActions
>
src/ui/useStudioAppBarAugmentation.ts
+
+ resolveContextActionIcon
+ src/ui/useStudioAppBarAugmentation.ts:32:1
+ No description available.
+
useStudioAppBarAugmentation
- src/ui/useStudioAppBarAugmentation.ts:22:1
+ src/ui/useStudioAppBarAugmentation.ts:41:1
No description available.
diff --git a/paradox/paradox.json b/paradox/paradox.json
index a6d55882..dbc693c1 100644
--- a/paradox/paradox.json
+++ b/paradox/paradox.json
@@ -12,7 +12,7 @@
{
"id": "npm",
"label": "npm",
- "value": "v0.13.0",
+ "value": "v0.14.0",
"color": "cb3837"
},
{
@@ -380,10 +380,15 @@
"isEntrypoint": false,
"dependencies": ["src/canvasDropZones.ts", "src/index.ts"],
"exports": [
+ "CanvasDragSessionResolution",
"CanvasDropZoneSlots",
+ "CanvasRect",
"createStudioCanvasDragPayload",
"isStudioCanvasDragPayload",
"isValidCanvasDropZone",
+ "resolveCanvasDragPreviewText",
+ "resolveCanvasDragSession",
+ "resolveCanvasDropZoneRect",
"resolveCanvasDropZoneSlots",
"StudioCanvasDragPayload"
]
@@ -522,134 +527,6 @@
],
"exports": ["StudioProvider", "StudioProviderProps"]
},
- {
- "path": "src/dnd/index.ts",
- "isEntrypoint": false,
- "dependencies": [],
- "exports": [
- "AnimationFunction",
- "clamp",
- "CollisionAlgorithm",
- "createIdleStudioDragState",
- "Draggable",
- "DraggableContextValue",
- "DraggableHandleProps",
- "DraggableProps",
- "DraggableState",
- "DropAlignment",
- "DropOffset",
- "Droppable",
- "DroppableProps",
- "DroppedItemsMap",
- "DropProvider",
- "DropProviderProps",
- "DropProviderRef",
- "DropSlot",
- "HorizontalScrollDirection",
- "HorizontalSortableItemProps",
- "HorizontalSortableProps",
- "HorizontalSortableRenderItemProps",
- "listToObject",
- "objectMove",
- "PositionUpdateListener",
- "ScrollDirection",
- "setAutoScroll",
- "setPosition",
- "SlotsContext",
- "SlotsContextValue",
- "Sortable",
- "SortableContextValue",
- "SortableDirection",
- "SortableHandleProps",
- "SortableItem",
- "SortableItemProps",
- "SortableProps",
- "SortableRenderItemProps",
- "StudioDragState",
- "useDraggable",
- "UseDraggableOptions",
- "UseDraggableReturn",
- "useDroppable",
- "UseDroppableOptions",
- "UseDroppableReturn",
- "UseHorizontalSortableListOptions",
- "UseHorizontalSortableListReturn",
- "UseHorizontalSortableOptions",
- "UseHorizontalSortableReturn",
- "useSortable",
- "useSortableList",
- "UseSortableListOptions",
- "UseSortableListReturn",
- "UseSortableOptions",
- "UseSortableReturn"
- ]
- },
- {
- "path": "src/dnd/primitives.ts",
- "isEntrypoint": false,
- "dependencies": [],
- "exports": [
- "AnimationFunction",
- "clamp",
- "CollisionAlgorithm",
- "Draggable",
- "DraggableContextValue",
- "DraggableHandleProps",
- "DraggableProps",
- "DraggableState",
- "DropAlignment",
- "DropOffset",
- "Droppable",
- "DroppableProps",
- "DroppedItemsMap",
- "DropProvider",
- "DropProviderProps",
- "DropProviderRef",
- "DropSlot",
- "HorizontalScrollDirection",
- "HorizontalSortableItemProps",
- "HorizontalSortableProps",
- "HorizontalSortableRenderItemProps",
- "listToObject",
- "objectMove",
- "PositionUpdateListener",
- "ScrollDirection",
- "setAutoScroll",
- "setPosition",
- "SlotsContext",
- "SlotsContextValue",
- "Sortable",
- "SortableContextValue",
- "SortableDirection",
- "SortableHandleProps",
- "SortableItem",
- "SortableItemProps",
- "SortableProps",
- "SortableRenderItemProps",
- "useDraggable",
- "UseDraggableOptions",
- "UseDraggableReturn",
- "useDroppable",
- "UseDroppableOptions",
- "UseDroppableReturn",
- "UseHorizontalSortableListOptions",
- "UseHorizontalSortableListReturn",
- "UseHorizontalSortableOptions",
- "UseHorizontalSortableReturn",
- "useSortable",
- "useSortableList",
- "UseSortableListOptions",
- "UseSortableListReturn",
- "UseSortableOptions",
- "UseSortableReturn"
- ]
- },
- {
- "path": "src/dnd/state.ts",
- "isEntrypoint": false,
- "dependencies": [],
- "exports": ["createIdleStudioDragState", "StudioDragState"]
- },
{
"path": "src/externalApiApi.ts",
"isEntrypoint": false,
@@ -1738,7 +1615,6 @@
"exports": [
"ACTION_REGISTRY",
"ActionDefinition",
- "addNodeToTree",
"appendStudioEventBinding",
"assessStudioBindingCompatibility",
"buildInsertCatalogEntries",
@@ -1770,7 +1646,6 @@
"InsertRecipeIssue",
"InsertRecipeNode",
"ModuleDefinition",
- "moveNodeInTree",
"moveNodeToPlacement",
"MoveNodeToPlacementArgs",
"MoveNodeToPlacementResult",
@@ -1800,6 +1675,7 @@
"resolveDefaultInsertPlacement",
"resolveInsertCatalogEntries",
"resolveInsertPlacement",
+ "resolveMoveNodePlacement",
"resolveStudioBindableEvents",
"resolveStudioBindableProps",
"resolveStudioInstancePropertyFields",
@@ -2006,7 +1882,6 @@
"listScreenIdsInRouteOrder",
"makeUniqueRouteNameForParent",
"makeUniqueSiblingRouteName",
- "moveStudioManifestNode",
"moveStudioManifestNodeToPlacement",
"pathToKey",
"removeScreenIdFromRoutes",
@@ -2216,7 +2091,6 @@
"exports": [
"ACTION_REGISTRY",
"ActionDefinition",
- "addNodeToTree",
"analyzeProjectAuthHealth",
"AnkhAdminPage",
"AnkhAdminShell",
@@ -2258,7 +2132,6 @@
"InsertRecipeIssue",
"InsertRecipeNode",
"ModuleDefinition",
- "moveNodeInTree",
"moveNodeToPlacement",
"MoveNodeToPlacementArgs",
"MoveNodeToPlacementResult",
@@ -2292,6 +2165,7 @@
"resolveDefaultInsertPlacement",
"resolveInsertCatalogEntries",
"resolveInsertPlacement",
+ "resolveMoveNodePlacement",
"resolveStudioBindableEvents",
"resolveStudioBindableProps",
"resolveStudioInstancePropertyFields",
@@ -2441,6 +2315,7 @@
"STUDIO_APP_EXTENSION_COMPONENT_REGISTRY",
"STUDIO_APP_EXTENSION_INTERACTION_POLICY_SUPPORT",
"STUDIO_PREVIEW_COMPONENT_REGISTRY",
+ "StudioCanvasInteractionAdapter",
"StudioInteractionPolicyResolverArgs",
"StudioLocalizationPreview",
"StudioLocalizationPreviewInput",
@@ -2614,17 +2489,21 @@
"path": "src/runtime/stationarySelection.ts",
"isEntrypoint": false,
"dependencies": [
+ "src/canvasDragModel.ts",
+ "src/index.ts",
"src/runtime/indicatorRefreshCoordinator.ts",
"src/runtime/indicatorSettleCoordinator.ts",
"src/runtime/runtimeNodeMeasurement.ts",
"src/runtime/stationarySelectionCoordinator.ts",
- "src/runtime/stationarySelectionInputState.ts"
+ "src/runtime/stationarySelectionInputState.ts",
+ "src/ui/canvas/StudioCanvasDndOverlay.tsx"
],
"exports": [
"CommitSelectionResult",
"createStudioStationarySelectionWrapNode",
"StationarySelectionCoordinator",
"StationaryTapSelector",
+ "StudioCanvasInteractionAdapter",
"TransactionState",
"useStudioUnsupportedNodeMeasurement"
]
@@ -3300,6 +3179,45 @@
"dependencies": ["src/core/StudioContext.ts"],
"exports": ["AnkhStudio", "AnkhStudioProps"]
},
+ {
+ "path": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "isEntrypoint": false,
+ "dependencies": ["src/canvasDropZones.ts", "src/ui/canvas/canvasDndInteraction.ts"],
+ "exports": []
+ },
+ {
+ "path": "src/ui/canvas/canvasDndInteraction.ts",
+ "isEntrypoint": false,
+ "dependencies": ["src/canvasDragModel.ts", "src/canvasDropZones.ts", "src/index.ts"],
+ "exports": [
+ "activateCanvasDrag",
+ "CanvasDragSessionCallbacks",
+ "commitCanvasDrop",
+ "completeCanvasDropAfterAdapter",
+ "createCanvasDraggableSessionKey",
+ "resetCanvasDragSession",
+ "sortCanvasDropTargetsBySpecificity"
+ ]
+ },
+ {
+ "path": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "isEntrypoint": false,
+ "dependencies": [],
+ "exports": []
+ },
+ {
+ "path": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "isEntrypoint": false,
+ "dependencies": [
+ "src/canvasDragModel.ts",
+ "src/canvasDropZones.ts",
+ "src/index.ts",
+ "src/insertModalModel.ts",
+ "src/runtime/runtimeNodeMeasurement.ts",
+ "src/ui/canvas/canvasDndInteraction.ts"
+ ],
+ "exports": ["StudioCanvasDndOverlay", "StudioCanvasDndOverlayProps"]
+ },
{
"path": "src/ui/studioAppBarModel.ts",
"isEntrypoint": false,
@@ -3310,6 +3228,18 @@
"StudioAppBarContextAction"
]
},
+ {
+ "path": "src/ui/StudioDeleteDialog.tsx",
+ "isEntrypoint": false,
+ "dependencies": [],
+ "exports": ["StudioDeleteDialog", "StudioDeleteDialogProps"]
+ },
+ {
+ "path": "src/ui/StudioInsertDialog.tsx",
+ "isEntrypoint": false,
+ "dependencies": ["src/index.ts", "src/insertModalModel.ts"],
+ "exports": ["StudioInsertDialog", "StudioInsertDialogProps"]
+ },
{
"path": "src/ui/useStudioAppBarAugmentation.test.ts",
"isEntrypoint": false,
@@ -3321,9 +3251,13 @@
"isEntrypoint": false,
"dependencies": [
"src/core/StudioContext.ts",
+ "src/index.ts",
+ "src/insertModalModel.ts",
"src/studioAdminRouteModel.ts",
"src/studioSelectionModel.ts",
- "src/ui/studioAppBarModel.ts"
+ "src/ui/studioAppBarModel.ts",
+ "src/ui/StudioDeleteDialog.tsx",
+ "src/ui/StudioInsertDialog.tsx"
],
"exports": ["StudioAppBarAugmentation", "useStudioAppBarAugmentation"]
},
@@ -3337,14 +3271,7 @@
"path": "src/utils/treeUtils.ts",
"isEntrypoint": false,
"dependencies": ["src/index.ts"],
- "exports": [
- "addNodeToTree",
- "cloneWithNewIds",
- "findNodeById",
- "moveNodeInTree",
- "removeNodeFromTree",
- "updateNodeInTree"
- ]
+ "exports": ["cloneWithNewIds", "findNodeById", "removeNodeFromTree", "updateNodeInTree"]
},
{
"path": "src/workspacePlatform.test.ts",
@@ -3382,7 +3309,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 384,
+ "line": 385,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -3400,7 +3327,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 290,
+ "line": 291,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3445,38 +3372,6 @@
],
"structuredRows": []
},
- {
- "name": "addNodeToTree",
- "description": null,
- "isReadme": false,
- "examples": [],
- "kind": "value",
- "modulePath": "src/index.ts",
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 606,
- "column": 14
- },
- "exportPaths": ["src/index.ts"],
- "relatedSymbols": ["StudioComponentMetaRegistry"],
- "signatures": [
- {
- "label": "(args: { root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: \"append\" | \"prepend\"; }) => UiNode",
- "parameters": [
- {
- "name": "args",
- "type": "{ root: UiNode; targetId: string; newNode: UiNode; componentMeta: StudioComponentMetaRegistry; mode?: \"append\" | \"prepend\"; }",
- "required": true,
- "description": null
- }
- ],
- "returnType": "UiNode",
- "returnDescription": null
- }
- ],
- "members": [],
- "structuredRows": []
- },
{
"name": "appendStudioEventBinding",
"description": null,
@@ -3574,7 +3469,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1318,
+ "line": 1327,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3606,7 +3501,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 765,
+ "line": 703,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3638,7 +3533,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 531,
+ "line": 532,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -3746,7 +3641,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1237,
+ "line": 1246,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -3930,7 +3825,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 548,
+ "line": 549,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -4006,7 +3901,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 524,
+ "line": 525,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -4038,7 +3933,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1163,
+ "line": 1172,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4070,7 +3965,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 268,
+ "line": 269,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4163,7 +4058,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 250,
+ "line": 251,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4203,7 +4098,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 227,
+ "line": 228,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4221,7 +4116,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 278,
+ "line": 279,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4239,7 +4134,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 256,
+ "line": 257,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4326,7 +4221,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 224,
+ "line": 225,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4344,7 +4239,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 225,
+ "line": 226,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4362,7 +4257,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 273,
+ "line": 274,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4456,7 +4351,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 995,
+ "line": 965,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4488,7 +4383,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 938,
+ "line": 908,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4535,7 +4430,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 945,
+ "line": 915,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4568,7 +4463,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 235,
+ "line": 236,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4622,7 +4517,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 243,
+ "line": 244,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4669,7 +4564,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 230,
+ "line": 231,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4702,7 +4597,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 298,
+ "line": 299,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4740,50 +4635,6 @@
],
"structuredRows": []
},
- {
- "name": "moveNodeInTree",
- "description": null,
- "isReadme": false,
- "examples": [],
- "kind": "value",
- "modulePath": "src/index.ts",
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 639,
- "column": 14
- },
- "exportPaths": ["src/index.ts"],
- "relatedSymbols": [],
- "signatures": [
- {
- "label": "(root: UiNode, nodeId: string, direction: \"up\" | \"down\") => UiNode",
- "parameters": [
- {
- "name": "direction",
- "type": "\"up\" | \"down\"",
- "required": true,
- "description": null
- },
- {
- "name": "nodeId",
- "type": "string",
- "required": true,
- "description": null
- },
- {
- "name": "root",
- "type": "UiNode",
- "required": true,
- "description": null
- }
- ],
- "returnType": "UiNode",
- "returnDescription": null
- }
- ],
- "members": [],
- "structuredRows": []
- },
{
"name": "moveNodeToPlacement",
"description": null,
@@ -4793,7 +4644,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1063,
+ "line": 1101,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4825,7 +4676,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1022,
+ "line": 992,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4872,7 +4723,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1029,
+ "line": 999,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -4970,7 +4821,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 205,
+ "line": 206,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5021,7 +4872,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 217,
+ "line": 218,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5039,7 +4890,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 210,
+ "line": 211,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5515,7 +5366,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 588,
+ "line": 589,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -5647,7 +5498,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 893,
+ "line": 863,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5679,7 +5530,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1360,
+ "line": 1369,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5711,7 +5562,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 832,
+ "line": 802,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -5738,6 +5589,38 @@
"members": [],
"structuredRows": []
},
+ {
+ "name": "resolveMoveNodePlacement",
+ "description": null,
+ "isReadme": false,
+ "examples": [],
+ "kind": "function",
+ "modulePath": "src/index.ts",
+ "sourceLocation": {
+ "filePath": "src/index.ts",
+ "line": 1033,
+ "column": 1
+ },
+ "exportPaths": ["src/index.ts"],
+ "relatedSymbols": ["MoveNodeToPlacementArgs", "PlacementResolutionResult"],
+ "signatures": [
+ {
+ "label": "(args: MoveNodeToPlacementArgs) => PlacementResolutionResult",
+ "parameters": [
+ {
+ "name": "args",
+ "type": "MoveNodeToPlacementArgs",
+ "required": true,
+ "description": null
+ }
+ ],
+ "returnType": "PlacementResolutionResult",
+ "returnDescription": null
+ }
+ ],
+ "members": [],
+ "structuredRows": []
+ },
{
"name": "resolveStudioBindableEvents",
"description": null,
@@ -5943,7 +5826,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1130,
+ "line": 1139,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -6040,7 +5923,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 282,
+ "line": 283,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6080,7 +5963,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 280,
+ "line": 281,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6098,7 +5981,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 288,
+ "line": 289,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6568,7 +6451,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 323,
+ "line": 324,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6586,7 +6469,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 307,
+ "line": 308,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6619,7 +6502,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 312,
+ "line": 313,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6666,7 +6549,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 319,
+ "line": 320,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6684,7 +6567,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 339,
+ "line": 340,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -6692,6 +6575,7 @@
"InsertCatalogEntry",
"NodePlacement",
"StudioAdminRouteId",
+ "StudioComponentMetaRegistry",
"StudioLocale",
"StudioManifest",
"StudioMode",
@@ -6753,6 +6637,13 @@
"required": true,
"description": null
},
+ {
+ "name": "componentMeta",
+ "kind": "property",
+ "type": "StudioComponentMetaRegistry",
+ "required": true,
+ "description": null
+ },
{
"name": "deleteGeneratedApi",
"kind": "property",
@@ -6830,13 +6721,6 @@
"required": true,
"description": null
},
- {
- "name": "moveNode",
- "kind": "property",
- "type": "(id: StudioNodeId, direction: \"up\" | \"down\") => void",
- "required": true,
- "description": null
- },
{
"name": "moveNodeToPlacement",
"kind": "property",
@@ -7087,7 +6971,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 332,
+ "line": 333,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -7105,7 +6989,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 321,
+ "line": 322,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -7921,7 +7805,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 476,
+ "line": 477,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -7939,7 +7823,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 560,
+ "line": 561,
"column": 14
},
"exportPaths": ["src/index.ts"],
@@ -8033,7 +7917,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1180,
+ "line": 1189,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -8071,7 +7955,7 @@
"modulePath": "src/index.ts",
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 777,
+ "line": 715,
"column": 1
},
"exportPaths": ["src/index.ts"],
@@ -9042,12 +8926,30 @@
"column": 1
}
},
+ {
+ "name": "treeContainsNode",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/canvasDragModel.ts",
+ "line": 33,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveCanvasDragSession",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/canvasDragModel.ts",
+ "line": 38,
+ "column": 1
+ }
+ },
{
"name": "createStudioCanvasDragPayload",
"description": null,
"sourceLocation": {
"filePath": "src/canvasDragModel.ts",
- "line": 16,
+ "line": 60,
"column": 1
}
},
@@ -9056,7 +8958,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDragModel.ts",
- "line": 20,
+ "line": 64,
"column": 1
}
},
@@ -9065,7 +8967,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDragModel.ts",
- "line": 28,
+ "line": 72,
"column": 1
}
},
@@ -9074,7 +8976,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDragModel.ts",
- "line": 34,
+ "line": 78,
"column": 1
}
},
@@ -9083,7 +8985,25 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDragModel.ts",
- "line": 47,
+ "line": 91,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveCanvasDropZoneRect",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/canvasDragModel.ts",
+ "line": 98,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveCanvasDragPreviewText",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/canvasDragModel.ts",
+ "line": 132,
"column": 1
}
},
@@ -9101,7 +9021,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDropZones.ts",
- "line": 23,
+ "line": 28,
"column": 1
}
},
@@ -9110,7 +9030,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/canvasDropZones.ts",
- "line": 64,
+ "line": 86,
"column": 1
}
},
@@ -9965,7 +9885,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 59,
+ "line": 71,
"column": 7
}
},
@@ -9974,7 +9894,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 60,
+ "line": 72,
"column": 7
}
},
@@ -9983,7 +9903,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 63,
+ "line": 75,
"column": 14
}
},
@@ -9992,7 +9912,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 308,
+ "line": 381,
"column": 1
}
},
@@ -10001,7 +9921,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 409,
+ "line": 482,
"column": 1
}
},
@@ -10010,7 +9930,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 418,
+ "line": 491,
"column": 1
}
},
@@ -10019,7 +9939,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 431,
+ "line": 504,
"column": 1
}
},
@@ -10028,7 +9948,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 439,
+ "line": 512,
"column": 1
}
},
@@ -10037,19 +9957,10 @@
"description": null,
"sourceLocation": {
"filePath": "src/core/StudioProvider.ts",
- "line": 446,
+ "line": 519,
"column": 1
}
},
- {
- "name": "createIdleStudioDragState",
- "description": null,
- "sourceLocation": {
- "filePath": "src/dnd/state.ts",
- "line": 6,
- "column": 14
- }
- },
{
"name": "connectExternalApi",
"description": null,
@@ -12260,7 +12171,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 458,
+ "line": 460,
"column": 1
}
},
@@ -12269,7 +12180,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 472,
+ "line": 474,
"column": 1
}
},
@@ -12278,7 +12189,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 479,
+ "line": 481,
"column": 1
}
},
@@ -12287,7 +12198,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 502,
+ "line": 504,
"column": 1
}
},
@@ -12296,7 +12207,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 516,
+ "line": 518,
"column": 1
}
},
@@ -12305,7 +12216,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 520,
+ "line": 522,
"column": 1
}
},
@@ -12314,7 +12225,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 564,
+ "line": 566,
"column": 1
}
},
@@ -12323,7 +12234,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 572,
+ "line": 574,
"column": 1
}
},
@@ -12332,7 +12243,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/host/layout/layoutGenerator.ts",
- "line": 577,
+ "line": 579,
"column": 1
}
},
@@ -14456,7 +14367,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.test.ts",
- "line": 51,
+ "line": 53,
"column": 7
}
},
@@ -14465,7 +14376,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 524,
+ "line": 525,
"column": 14
}
},
@@ -14474,7 +14385,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 531,
+ "line": 532,
"column": 14
}
},
@@ -14483,7 +14394,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 548,
+ "line": 549,
"column": 14
}
},
@@ -14492,7 +14403,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 560,
+ "line": 561,
"column": 14
}
},
@@ -14501,25 +14412,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 588,
- "column": 14
- }
- },
- {
- "name": "addNodeToTree",
- "description": null,
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 606,
- "column": 14
- }
- },
- {
- "name": "moveNodeInTree",
- "description": null,
- "sourceLocation": {
- "filePath": "src/index.ts",
- "line": 639,
+ "line": 589,
"column": 14
}
},
@@ -14528,7 +14421,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 675,
+ "line": 613,
"column": 1
}
},
@@ -14537,7 +14430,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 680,
+ "line": 618,
"column": 9
}
},
@@ -14546,7 +14439,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 699,
+ "line": 637,
"column": 1
}
},
@@ -14555,7 +14448,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 710,
+ "line": 648,
"column": 1
}
},
@@ -14564,7 +14457,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 765,
+ "line": 703,
"column": 1
}
},
@@ -14573,7 +14466,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 777,
+ "line": 715,
"column": 1
}
},
@@ -14582,7 +14475,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 832,
+ "line": 802,
"column": 1
}
},
@@ -14591,7 +14484,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 893,
+ "line": 863,
"column": 1
}
},
@@ -14600,7 +14493,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 950,
+ "line": 920,
"column": 1
}
},
@@ -14609,7 +14502,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 995,
+ "line": 965,
"column": 1
}
},
@@ -14618,7 +14511,16 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1034,
+ "line": 1004,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveMoveNodePlacement",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/index.ts",
+ "line": 1033,
"column": 1
}
},
@@ -14627,7 +14529,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1063,
+ "line": 1101,
"column": 1
}
},
@@ -14636,7 +14538,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1163,
+ "line": 1172,
"column": 1
}
},
@@ -14645,7 +14547,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1167,
+ "line": 1176,
"column": 1
}
},
@@ -14654,7 +14556,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1172,
+ "line": 1181,
"column": 1
}
},
@@ -14663,7 +14565,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1180,
+ "line": 1189,
"column": 1
}
},
@@ -14672,7 +14574,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1184,
+ "line": 1193,
"column": 9
}
},
@@ -14681,7 +14583,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1217,
+ "line": 1226,
"column": 1
}
},
@@ -14690,7 +14592,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1222,
+ "line": 1231,
"column": 9
}
},
@@ -14699,7 +14601,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1237,
+ "line": 1246,
"column": 1
}
},
@@ -14708,7 +14610,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1257,
+ "line": 1266,
"column": 1
}
},
@@ -14717,7 +14619,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1280,
+ "line": 1289,
"column": 1
}
},
@@ -14726,7 +14628,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1318,
+ "line": 1327,
"column": 1
}
},
@@ -14735,7 +14637,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1344,
+ "line": 1353,
"column": 1
}
},
@@ -14744,7 +14646,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1360,
+ "line": 1369,
"column": 1
}
},
@@ -14753,7 +14655,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/index.ts",
- "line": 1409,
+ "line": 1418,
"column": 1
}
},
@@ -15041,7 +14943,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.test.ts",
- "line": 37,
+ "line": 36,
"column": 1
}
},
@@ -15050,7 +14952,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.test.ts",
- "line": 91,
+ "line": 90,
"column": 1
}
},
@@ -15059,7 +14961,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.test.ts",
- "line": 310,
+ "line": 313,
"column": 11
}
},
@@ -15068,7 +14970,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 95,
+ "line": 96,
"column": 14
}
},
@@ -15077,7 +14979,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 102,
+ "line": 103,
"column": 1
}
},
@@ -15086,7 +14988,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 119,
+ "line": 120,
"column": 1
}
},
@@ -15095,7 +14997,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 123,
+ "line": 124,
"column": 1
}
},
@@ -15104,7 +15006,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 127,
+ "line": 128,
"column": 1
}
},
@@ -15113,7 +15015,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 153,
+ "line": 154,
"column": 1
}
},
@@ -15122,7 +15024,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 172,
+ "line": 173,
"column": 1
}
},
@@ -15131,7 +15033,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 181,
+ "line": 182,
"column": 1
}
},
@@ -15140,7 +15042,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 206,
+ "line": 207,
"column": 1
}
},
@@ -15149,7 +15051,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 214,
+ "line": 215,
"column": 1
}
},
@@ -15158,7 +15060,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 222,
+ "line": 223,
"column": 1
}
},
@@ -15167,7 +15069,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 233,
+ "line": 234,
"column": 1
}
},
@@ -15176,7 +15078,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 241,
+ "line": 242,
"column": 1
}
},
@@ -15185,7 +15087,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 251,
+ "line": 252,
"column": 1
}
},
@@ -15194,16 +15096,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 276,
- "column": 1
- }
- },
- {
- "name": "moveStudioManifestNode",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 305,
+ "line": 277,
"column": 1
}
},
@@ -15212,7 +15105,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 330,
+ "line": 314,
"column": 1
}
},
@@ -15221,7 +15114,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 367,
+ "line": 348,
"column": 1
}
},
@@ -15230,7 +15123,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 423,
+ "line": 383,
"column": 1
}
},
@@ -15239,7 +15132,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 430,
+ "line": 390,
"column": 1
}
},
@@ -15248,7 +15141,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 437,
+ "line": 397,
"column": 1
}
},
@@ -15257,7 +15150,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 455,
+ "line": 415,
"column": 1
}
},
@@ -15266,7 +15159,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 462,
+ "line": 422,
"column": 1
}
},
@@ -15275,7 +15168,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 482,
+ "line": 442,
"column": 1
}
},
@@ -15284,7 +15177,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 497,
+ "line": 457,
"column": 1
}
},
@@ -15293,7 +15186,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 504,
+ "line": 464,
"column": 1
}
},
@@ -15302,7 +15195,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 511,
+ "line": 471,
"column": 1
}
},
@@ -15311,7 +15204,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 567,
+ "line": 527,
"column": 1
}
},
@@ -15320,7 +15213,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 598,
+ "line": 558,
"column": 1
}
},
@@ -15329,7 +15222,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 608,
+ "line": 568,
"column": 1
}
},
@@ -15338,7 +15231,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 631,
+ "line": 591,
"column": 1
}
},
@@ -15347,7 +15240,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 645,
+ "line": 605,
"column": 1
}
},
@@ -15356,7 +15249,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 666,
+ "line": 626,
"column": 1
}
},
@@ -15365,7 +15258,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 680,
+ "line": 640,
"column": 1
}
},
@@ -15374,7 +15267,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 701,
+ "line": 661,
"column": 1
}
},
@@ -15383,7 +15276,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 718,
+ "line": 678,
"column": 1
}
},
@@ -15392,7 +15285,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 740,
+ "line": 700,
"column": 1
}
},
@@ -15401,7 +15294,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 807,
+ "line": 767,
"column": 1
}
},
@@ -15410,7 +15303,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 852,
+ "line": 812,
"column": 1
}
},
@@ -15419,7 +15312,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 865,
+ "line": 825,
"column": 1
}
},
@@ -15428,7 +15321,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 897,
+ "line": 857,
"column": 1
}
},
@@ -15437,7 +15330,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 910,
+ "line": 870,
"column": 1
}
},
@@ -15446,7 +15339,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 917,
+ "line": 877,
"column": 1
}
},
@@ -15455,7 +15348,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 938,
+ "line": 898,
"column": 1
}
},
@@ -15464,7 +15357,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 948,
+ "line": 908,
"column": 1
}
},
@@ -15473,7 +15366,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 962,
+ "line": 922,
"column": 1
}
},
@@ -15482,25 +15375,16 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 987,
- "column": 1
- }
- },
- {
- "name": "moveNodeInManifestTree",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1003,
+ "line": 947,
"column": 1
}
},
{
- "name": "findNodeWithParent",
+ "name": "collectNodeIds",
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 1036,
+ "line": 963,
"column": 1
}
},
@@ -15509,61 +15393,16 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 1039,
+ "line": 965,
"column": 9
}
},
- {
- "name": "validateManifestNodePlacement",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1054,
- "column": 1
- }
- },
- {
- "name": "insertChildAtIndex",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1074,
- "column": 1
- }
- },
- {
- "name": "isDescendantNode",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1105,
- "column": 1
- }
- },
- {
- "name": "removeNodeForMove",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1113,
- "column": 1
- }
- },
- {
- "name": "adjustMovePlacement",
- "description": null,
- "sourceLocation": {
- "filePath": "src/manifestState.ts",
- "line": 1155,
- "column": 1
- }
- },
{
"name": "normalizeNavigatorAfterRouteUpdate",
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 1170,
+ "line": 973,
"column": 1
}
},
@@ -15572,7 +15411,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/manifestState.ts",
- "line": 1191,
+ "line": 994,
"column": 1
}
},
@@ -16580,7 +16419,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 63,
+ "line": 65,
"column": 1
}
},
@@ -16589,7 +16428,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 77,
+ "line": 79,
"column": 1
}
},
@@ -16598,7 +16437,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 95,
+ "line": 97,
"column": 1
}
},
@@ -16607,7 +16446,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 105,
+ "line": 107,
"column": 1
}
},
@@ -16616,7 +16455,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 116,
+ "line": 118,
"column": 1
}
},
@@ -16625,7 +16464,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 149,
+ "line": 151,
"column": 1
}
},
@@ -16634,7 +16473,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 158,
+ "line": 160,
"column": 1
}
},
@@ -16643,7 +16482,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 175,
+ "line": 179,
"column": 1
}
},
@@ -16652,7 +16491,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 183,
+ "line": 191,
"column": 1
}
},
@@ -16661,7 +16500,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 233,
+ "line": 266,
"column": 1
}
},
@@ -16670,7 +16509,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/runtimeNodeMeasurement.ts",
- "line": 276,
+ "line": 309,
"column": 1
}
},
@@ -16679,7 +16518,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 85,
+ "line": 89,
"column": 1
}
},
@@ -16688,7 +16527,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 95,
+ "line": 99,
"column": 1
}
},
@@ -16697,7 +16536,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 99,
+ "line": 103,
"column": 1
}
},
@@ -16706,7 +16545,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 110,
+ "line": 114,
"column": 1
}
},
@@ -16715,7 +16554,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 119,
+ "line": 123,
"column": 1
}
},
@@ -16724,7 +16563,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 128,
+ "line": 132,
"column": 1
}
},
@@ -16733,7 +16572,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 140,
+ "line": 144,
"column": 1
}
},
@@ -16742,7 +16581,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 154,
+ "line": 158,
"column": 1
}
},
@@ -16751,7 +16590,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 163,
+ "line": 167,
"column": 1
}
},
@@ -16760,7 +16599,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 187,
+ "line": 191,
"column": 1
}
},
@@ -16769,7 +16608,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 220,
+ "line": 224,
"column": 1
}
},
@@ -16778,7 +16617,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 232,
+ "line": 236,
"column": 3
}
},
@@ -16787,7 +16626,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 246,
+ "line": 250,
"column": 3
}
},
@@ -16796,7 +16635,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 257,
+ "line": 261,
"column": 3
}
},
@@ -16805,7 +16644,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 266,
+ "line": 270,
"column": 3
}
},
@@ -16814,7 +16653,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 270,
+ "line": 274,
"column": 3
}
},
@@ -16823,7 +16662,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 350,
+ "line": 363,
"column": 1
}
},
@@ -16832,7 +16671,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 389,
+ "line": 410,
"column": 1
}
},
@@ -16841,7 +16680,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 646,
+ "line": 704,
"column": 11
}
},
@@ -16850,7 +16689,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/runtime/stationarySelection.ts",
- "line": 647,
+ "line": 705,
"column": 11
}
},
@@ -17471,7 +17310,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/ui/admin/AnkhAdminPage.tsx",
- "line": 74,
+ "line": 72,
"column": 1
}
},
@@ -18308,7 +18147,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/ui/admin/pages/bindings/EventBindingsCard.tsx",
- "line": 89,
+ "line": 93,
"column": 1
}
},
@@ -18317,7 +18156,7 @@
"description": null,
"sourceLocation": {
"filePath": "src/ui/admin/pages/bindings/EventBindingsCard.tsx",
- "line": 100,
+ "line": 111,
"column": 1
}
},
@@ -19005,21 +18844,156 @@
"column": 14
}
},
+ {
+ "name": "moveNode",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "line": 43,
+ "column": 11
+ }
+ },
+ {
+ "name": "createCanvasDraggableSessionKey",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 11,
+ "column": 1
+ }
+ },
+ {
+ "name": "sortCanvasDropTargetsBySpecificity",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 15,
+ "column": 1
+ }
+ },
+ {
+ "name": "resetCanvasDragSession",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 23,
+ "column": 1
+ }
+ },
+ {
+ "name": "commitCanvasDrop",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 29,
+ "column": 1
+ }
+ },
+ {
+ "name": "completeCanvasDropAfterAdapter",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 41,
+ "column": 1
+ }
+ },
+ {
+ "name": "activateCanvasDrag",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/canvasDndInteraction.ts",
+ "line": 56,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveDropZoneViews",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "line": 57,
+ "column": 1
+ }
+ },
+ {
+ "name": "CanvasDropZone",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "line": 87,
+ "column": 1
+ }
+ },
+ {
+ "name": "CanvasDragPreview",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "line": 140,
+ "column": 1
+ }
+ },
+ {
+ "name": "StudioCanvasDndOverlay",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "line": 179,
+ "column": 1
+ }
+ },
+ {
+ "name": "resetDrag",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "line": 211,
+ "column": 9
+ }
+ },
{
"name": "resolveStudioAppBarContextActions",
"description": null,
"sourceLocation": {
"filePath": "src/ui/studioAppBarModel.ts",
+ "line": 14,
+ "column": 1
+ }
+ },
+ {
+ "name": "StudioDeleteDialog",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/StudioDeleteDialog.tsx",
"line": 11,
"column": 1
}
},
+ {
+ "name": "StudioInsertDialog",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/StudioInsertDialog.tsx",
+ "line": 24,
+ "column": 1
+ }
+ },
+ {
+ "name": "resolveContextActionIcon",
+ "description": null,
+ "sourceLocation": {
+ "filePath": "src/ui/useStudioAppBarAugmentation.ts",
+ "line": 32,
+ "column": 1
+ }
+ },
{
"name": "useStudioAppBarAugmentation",
"description": null,
"sourceLocation": {
"filePath": "src/ui/useStudioAppBarAugmentation.ts",
- "line": 22,
+ "line": 41,
"column": 1
}
},
@@ -19124,14 +19098,6 @@
}
],
"sequenceScenarios": [
- {
- "kind": "export",
- "name": "addNodeToTree",
- "sourcePath": "src/index.ts",
- "symbolName": "addNodeToTree",
- "description": null,
- "isReadme": false
- },
{
"kind": "export",
"name": "appendStudioEventBinding",
@@ -19268,14 +19234,6 @@
"description": null,
"isReadme": false
},
- {
- "kind": "export",
- "name": "moveNodeInTree",
- "sourcePath": "src/index.ts",
- "symbolName": "moveNodeInTree",
- "description": null,
- "isReadme": false
- },
{
"kind": "export",
"name": "moveNodeToPlacement",
@@ -19332,6 +19290,14 @@
"description": null,
"isReadme": false
},
+ {
+ "kind": "export",
+ "name": "resolveMoveNodePlacement",
+ "sourcePath": "src/index.ts",
+ "symbolName": "resolveMoveNodePlacement",
+ "description": null,
+ "isReadme": false
+ },
{
"kind": "export",
"name": "resolveStudioBindableEvents",
@@ -20240,16 +20206,6 @@
"toPath": "src/core/studioManifestPersistenceModel.ts",
"sourcePath": "src/core/StudioProvider.ts"
},
- {
- "fromPath": "src/dnd/index.ts",
- "toPath": "src/dnd/primitives.ts",
- "sourcePath": "src/dnd/index.ts"
- },
- {
- "fromPath": "src/dnd/index.ts",
- "toPath": "src/dnd/state.ts",
- "sourcePath": "src/dnd/index.ts"
- },
{
"fromPath": "src/hooks/useProjects.ts",
"toPath": "src/contractGuards.ts",
@@ -20655,6 +20611,21 @@
"toPath": "src/runtime/index.ts",
"sourcePath": "src/runtime/stationarySelection.public.test.ts"
},
+ {
+ "fromPath": "src/runtime/stationarySelection.ts",
+ "toPath": "src/canvasDragModel.ts",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
+ {
+ "fromPath": "src/runtime/stationarySelection.ts",
+ "toPath": "src/index.ts",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
+ {
+ "fromPath": "src/runtime/stationarySelection.ts",
+ "toPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
{
"fromPath": "src/runtime/stationarySelection.ts",
"toPath": "src/runtime/indicatorRefreshCoordinator.ts",
@@ -20700,6 +20671,16 @@
"toPath": "src/core/StudioContext.ts",
"sourcePath": "src/ui/AnkhStudio.ts"
},
+ {
+ "fromPath": "src/ui/StudioInsertDialog.tsx",
+ "toPath": "src/index.ts",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromPath": "src/ui/StudioInsertDialog.tsx",
+ "toPath": "src/insertModalModel.ts",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
{
"fromPath": "src/ui/useStudioAppBarAugmentation.test.ts",
"toPath": "src/ui/studioAppBarModel.ts",
@@ -20710,6 +20691,16 @@
"toPath": "src/core/StudioContext.ts",
"sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
},
+ {
+ "fromPath": "src/ui/useStudioAppBarAugmentation.ts",
+ "toPath": "src/index.ts",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromPath": "src/ui/useStudioAppBarAugmentation.ts",
+ "toPath": "src/insertModalModel.ts",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
{
"fromPath": "src/ui/useStudioAppBarAugmentation.ts",
"toPath": "src/studioAdminRouteModel.ts",
@@ -20725,6 +20716,16 @@
"toPath": "src/ui/studioAppBarModel.ts",
"sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
},
+ {
+ "fromPath": "src/ui/useStudioAppBarAugmentation.ts",
+ "toPath": "src/ui/StudioDeleteDialog.tsx",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromPath": "src/ui/useStudioAppBarAugmentation.ts",
+ "toPath": "src/ui/StudioInsertDialog.tsx",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
{
"fromPath": "src/utils/treeUtils.ts",
"toPath": "src/index.ts",
@@ -21565,6 +21566,61 @@
"toPath": "src/ui/admin/pages/adminAuthSessionModel.ts",
"sourcePath": "src/ui/admin/AuthAdminSession.tsx"
},
+ {
+ "fromPath": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toPath": "src/canvasDropZones.ts",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromPath": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toPath": "src/ui/canvas/canvasDndInteraction.ts",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromPath": "src/ui/canvas/canvasDndInteraction.ts",
+ "toPath": "src/canvasDragModel.ts",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromPath": "src/ui/canvas/canvasDndInteraction.ts",
+ "toPath": "src/canvasDropZones.ts",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromPath": "src/ui/canvas/canvasDndInteraction.ts",
+ "toPath": "src/index.ts",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/canvasDragModel.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/canvasDropZones.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/index.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/insertModalModel.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/runtime/runtimeNodeMeasurement.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromPath": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toPath": "src/ui/canvas/canvasDndInteraction.ts",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
{
"fromPath": "src/host/layout/auth/resolveAuthLayoutPlan.test.ts",
"toPath": "src/host/layout/auth/resolveAuthLayoutPlan.ts",
@@ -23267,6 +23323,12 @@
"callExpression": "resolveCanvasDropZoneSlots",
"sourcePath": "src/canvasDragModel.public.test.ts"
},
+ {
+ "fromSymbol": "src/canvasDragModel.public.test.ts",
+ "toSymbol": "resolveCanvasDragSession",
+ "callExpression": "resolveCanvasDragSession",
+ "sourcePath": "src/canvasDragModel.public.test.ts"
+ },
{
"fromSymbol": "src/canvasDragModel.public.test.ts",
"toSymbol": "expect",
@@ -23321,6 +23383,36 @@
"callExpression": "resolveCanvasDropZoneSlots",
"sourcePath": "src/canvasDragModel.test.ts"
},
+ {
+ "fromSymbol": "src/canvasDragModel.test.ts",
+ "toSymbol": "resolveCanvasDropZoneRect",
+ "callExpression": "resolveCanvasDropZoneRect",
+ "sourcePath": "src/canvasDragModel.test.ts"
+ },
+ {
+ "fromSymbol": "src/canvasDragModel.test.ts",
+ "toSymbol": "resolveCanvasDragPreviewText",
+ "callExpression": "resolveCanvasDragPreviewText",
+ "sourcePath": "src/canvasDragModel.test.ts"
+ },
+ {
+ "fromSymbol": "src/canvasDragModel.test.ts",
+ "toSymbol": "resolveCanvasDragSession",
+ "callExpression": "resolveCanvasDragSession",
+ "sourcePath": "src/canvasDragModel.test.ts"
+ },
+ {
+ "fromSymbol": "src/canvasDragModel.ts",
+ "toSymbol": "treeContainsNode",
+ "callExpression": "treeContainsNode",
+ "sourcePath": "src/canvasDragModel.ts"
+ },
+ {
+ "fromSymbol": "resolveCanvasDragSession",
+ "toSymbol": "treeContainsNode",
+ "callExpression": "treeContainsNode",
+ "sourcePath": "src/canvasDragModel.ts"
+ },
{
"fromSymbol": "resolveCanvasDropZoneSlots",
"toSymbol": "findDropZoneByKind",
@@ -23369,6 +23461,12 @@
"callExpression": "resolveInsertPlacement",
"sourcePath": "src/canvasDropZones.ts"
},
+ {
+ "fromSymbol": "src/canvasDropZones.ts",
+ "toSymbol": "resolveMoveNodePlacement",
+ "callExpression": "resolveMoveNodePlacement",
+ "sourcePath": "src/canvasDropZones.ts"
+ },
{
"fromSymbol": "src/contractGuards.test.ts",
"toSymbol": "test",
@@ -24719,6 +24817,18 @@
"callExpression": "moveNodeToPlacement",
"sourcePath": "src/index.test.ts"
},
+ {
+ "fromSymbol": "src/index.test.ts",
+ "toSymbol": "validateNodePlacement",
+ "callExpression": "validateNodePlacement",
+ "sourcePath": "src/index.test.ts"
+ },
+ {
+ "fromSymbol": "src/index.test.ts",
+ "toSymbol": "resolveMoveNodePlacement",
+ "callExpression": "resolveMoveNodePlacement",
+ "sourcePath": "src/index.test.ts"
+ },
{
"fromSymbol": "src/index.test.ts",
"toSymbol": "updateNodeInTree",
@@ -24767,24 +24877,6 @@
"callExpression": "removeNodeFromTree",
"sourcePath": "src/index.ts"
},
- {
- "fromSymbol": "addNodeToTree",
- "toSymbol": "canAcceptChild",
- "callExpression": "canAcceptChild",
- "sourcePath": "src/index.ts"
- },
- {
- "fromSymbol": "src/index.ts",
- "toSymbol": "addNodeToTree",
- "callExpression": "addNodeToTree",
- "sourcePath": "src/index.ts"
- },
- {
- "fromSymbol": "src/index.ts",
- "toSymbol": "moveNodeInTree",
- "callExpression": "moveNodeInTree",
- "sourcePath": "src/index.ts"
- },
{
"fromSymbol": "visit",
"toSymbol": "visit",
@@ -24864,35 +24956,47 @@
"sourcePath": "src/index.ts"
},
{
- "fromSymbol": "moveNodeToPlacement",
+ "fromSymbol": "resolveMoveNodePlacement",
"toSymbol": "findNodeWithParent",
"callExpression": "findNodeWithParent",
"sourcePath": "src/index.ts"
},
{
- "fromSymbol": "moveNodeToPlacement",
+ "fromSymbol": "resolveMoveNodePlacement",
"toSymbol": "isDescendantNode",
"callExpression": "isDescendantNode",
"sourcePath": "src/index.ts"
},
{
- "fromSymbol": "moveNodeToPlacement",
+ "fromSymbol": "resolveMoveNodePlacement",
"toSymbol": "getAdjustedMovePlacement",
"callExpression": "getAdjustedMovePlacement",
"sourcePath": "src/index.ts"
},
{
- "fromSymbol": "moveNodeToPlacement",
+ "fromSymbol": "resolveMoveNodePlacement",
"toSymbol": "removeNodeForMove",
"callExpression": "removeNodeForMove",
"sourcePath": "src/index.ts"
},
{
- "fromSymbol": "moveNodeToPlacement",
+ "fromSymbol": "resolveMoveNodePlacement",
"toSymbol": "validateNodePlacement",
"callExpression": "validateNodePlacement",
"sourcePath": "src/index.ts"
},
+ {
+ "fromSymbol": "moveNodeToPlacement",
+ "toSymbol": "resolveMoveNodePlacement",
+ "callExpression": "resolveMoveNodePlacement",
+ "sourcePath": "src/index.ts"
+ },
+ {
+ "fromSymbol": "moveNodeToPlacement",
+ "toSymbol": "removeNodeForMove",
+ "callExpression": "removeNodeForMove",
+ "sourcePath": "src/index.ts"
+ },
{
"fromSymbol": "moveNodeToPlacement",
"toSymbol": "insertChildAtIndex",
@@ -25691,12 +25795,6 @@
"callExpression": "moveStudioManifestNodeToPlacement",
"sourcePath": "src/manifestState.test.ts"
},
- {
- "fromSymbol": "src/manifestState.test.ts",
- "toSymbol": "moveStudioManifestNode",
- "callExpression": "moveStudioManifestNode",
- "sourcePath": "src/manifestState.test.ts"
- },
{
"fromSymbol": "src/manifestState.test.ts",
"toSymbol": "deleteStudioManifestNode",
@@ -25807,62 +25905,32 @@
},
{
"fromSymbol": "deleteStudioManifestNode",
- "toSymbol": "removeNodeFromManifestTree",
- "callExpression": "removeNodeFromManifestTree",
+ "toSymbol": "findNodeInManifest",
+ "callExpression": "findNodeInManifest",
"sourcePath": "src/manifestState.ts"
},
{
- "fromSymbol": "moveStudioManifestNode",
- "toSymbol": "moveNodeInManifestTree",
- "callExpression": "moveNodeInManifestTree",
+ "fromSymbol": "deleteStudioManifestNode",
+ "toSymbol": "removeNodeFromManifestTree",
+ "callExpression": "removeNodeFromManifestTree",
"sourcePath": "src/manifestState.ts"
},
{
- "fromSymbol": "insertStudioManifestNodeAtPlacement",
- "toSymbol": "validateManifestNodePlacement",
- "callExpression": "validateManifestNodePlacement",
+ "fromSymbol": "deleteStudioManifestNode",
+ "toSymbol": "collectNodeIds",
+ "callExpression": "collectNodeIds",
"sourcePath": "src/manifestState.ts"
},
{
"fromSymbol": "insertStudioManifestNodeAtPlacement",
- "toSymbol": "insertChildAtIndex",
- "callExpression": "insertChildAtIndex",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "findNodeWithParent",
- "callExpression": "findNodeWithParent",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "isDescendantNode",
- "callExpression": "isDescendantNode",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "adjustMovePlacement",
- "callExpression": "adjustMovePlacement",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "removeNodeForMove",
- "callExpression": "removeNodeForMove",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "validateManifestNodePlacement",
- "callExpression": "validateManifestNodePlacement",
+ "toSymbol": "insertNodeAtPlacement",
+ "callExpression": "insertNodeAtPlacement",
"sourcePath": "src/manifestState.ts"
},
{
"fromSymbol": "moveStudioManifestNodeToPlacement",
- "toSymbol": "insertChildAtIndex",
- "callExpression": "insertChildAtIndex",
+ "toSymbol": "moveNodeToPlacement",
+ "callExpression": "moveNodeToPlacement",
"sourcePath": "src/manifestState.ts"
},
{
@@ -26087,12 +26155,6 @@
"callExpression": "removeNodeFromManifestTree",
"sourcePath": "src/manifestState.ts"
},
- {
- "fromSymbol": "src/manifestState.ts",
- "toSymbol": "moveNodeInManifestTree",
- "callExpression": "moveNodeInManifestTree",
- "sourcePath": "src/manifestState.ts"
- },
{
"fromSymbol": "visit",
"toSymbol": "visit",
@@ -26100,35 +26162,11 @@
"sourcePath": "src/manifestState.ts"
},
{
- "fromSymbol": "findNodeWithParent",
+ "fromSymbol": "collectNodeIds",
"toSymbol": "visit",
"callExpression": "visit",
"sourcePath": "src/manifestState.ts"
},
- {
- "fromSymbol": "validateManifestNodePlacement",
- "toSymbol": "findNodeInManifest",
- "callExpression": "findNodeInManifest",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "src/manifestState.ts",
- "toSymbol": "insertChildAtIndex",
- "callExpression": "insertChildAtIndex",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "isDescendantNode",
- "toSymbol": "isDescendantNode",
- "callExpression": "isDescendantNode",
- "sourcePath": "src/manifestState.ts"
- },
- {
- "fromSymbol": "removeNodeForMove",
- "toSymbol": "removeNodeForMove",
- "callExpression": "removeNodeForMove",
- "sourcePath": "src/manifestState.ts"
- },
{
"fromSymbol": "src/manifestSync.test.ts",
"toSymbol": "describe",
@@ -29033,6 +29071,48 @@
"callExpression": "deleteStudioGeneratedApi",
"sourcePath": "src/core/StudioProvider.ts"
},
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "insertStudioManifestNodeAtPlacement",
+ "callExpression": "insertStudioManifestNodeAtPlacement",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "createNodeFromCatalogEntry",
+ "callExpression": "createNodeFromCatalogEntry",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "moveStudioManifestNodeToPlacement",
+ "callExpression": "moveStudioManifestNodeToPlacement",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "findNodeById",
+ "callExpression": "findNodeById",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "resolveStudioSelectionParentNodeId",
+ "callExpression": "resolveStudioSelectionParentNodeId",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "deleteStudioManifestNode",
+ "callExpression": "deleteStudioManifestNode",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
+ {
+ "fromSymbol": "src/core/StudioProvider.ts",
+ "toSymbol": "setActiveCanvasDragNodeId",
+ "callExpression": "setActiveCanvasDragNodeId",
+ "sourcePath": "src/core/StudioProvider.ts"
+ },
{
"fromSymbol": "updateDataBindings",
"toSymbol": "updateManifest",
@@ -33023,6 +33103,12 @@
"callExpression": "measureRuntimeNodeWebView",
"sourcePath": "src/runtime/stationarySelection.ts"
},
+ {
+ "fromSymbol": "measure",
+ "toSymbol": "measureNativeRuntimeNodeView",
+ "callExpression": "measureNativeRuntimeNodeView",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
{
"fromSymbol": "registerView",
"toSymbol": "registerRuntimeNode",
@@ -33065,6 +33151,12 @@
"callExpression": "shouldRenderSelectedNodeChrome",
"sourcePath": "src/runtime/stationarySelection.ts"
},
+ {
+ "fromSymbol": "StationaryTapSelector",
+ "toSymbol": "resolveCanvasDragSession",
+ "callExpression": "resolveCanvasDragSession",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
{
"fromSymbol": "StationaryTapSelector",
"toSymbol": "createStationarySelectionInputState",
@@ -33185,6 +33277,12 @@
"callExpression": "areIndicatorRectsEqual",
"sourcePath": "src/runtime/stationarySelection.ts"
},
+ {
+ "fromSymbol": "src/runtime/stationarySelection.ts",
+ "toSymbol": "setActiveDragNodeId",
+ "callExpression": "props.canvasInteraction?.setActiveDragNodeId",
+ "sourcePath": "src/runtime/stationarySelection.ts"
+ },
{
"fromSymbol": "src/runtime/stationarySelection.ts",
"toSymbol": "cancelPendingRefresh",
@@ -33485,6 +33583,42 @@
"callExpression": "useStudio",
"sourcePath": "src/ui/AnkhStudio.ts"
},
+ {
+ "fromSymbol": "src/ui/StudioInsertDialog.tsx",
+ "toSymbol": "setQuery",
+ "callExpression": "setQuery",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromSymbol": "StudioInsertDialog",
+ "toSymbol": "groupInsertEntries",
+ "callExpression": "groupInsertEntries",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromSymbol": "StudioInsertDialog",
+ "toSymbol": "filterInsertCatalogEntries",
+ "callExpression": "filterInsertCatalogEntries",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/StudioInsertDialog.tsx",
+ "toSymbol": "getPlacementHint",
+ "callExpression": "getPlacementHint",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromSymbol": "findNode",
+ "toSymbol": "findNode",
+ "callExpression": "props.findNode",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/StudioInsertDialog.tsx",
+ "toSymbol": "onInsert",
+ "callExpression": "props.onInsert",
+ "sourcePath": "src/ui/StudioInsertDialog.tsx"
+ },
{
"fromSymbol": "src/ui/useStudioAppBarAugmentation.test.ts",
"toSymbol": "test",
@@ -33587,18 +33721,102 @@
"callExpression": "studio.selectNode",
"sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
},
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "buildInsertCatalogEntries",
+ "callExpression": "buildInsertCatalogEntries",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "resolveInsertCatalogEntries",
+ "callExpression": "resolveInsertCatalogEntries",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "useStudioAppBarAugmentation",
+ "toSymbol": "findNodeById",
+ "callExpression": "findNodeById",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
{
"fromSymbol": "useStudioAppBarAugmentation",
"toSymbol": "resolveStudioAppBarContextActions",
"callExpression": "resolveStudioAppBarContextActions",
"sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
},
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "setInsertVisible",
+ "callExpression": "setInsertVisible",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "setDeleteCandidateId",
+ "callExpression": "setDeleteCandidateId",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "deleteNode",
+ "callExpression": "studio.deleteNode",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
{
"fromSymbol": "useStudioAppBarAugmentation",
"toSymbol": "isStudioAdminPath",
"callExpression": "isStudioAdminPath",
"sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
},
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "resolveContextActionIcon",
+ "callExpression": "resolveContextActionIcon",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "src/ui/useStudioAppBarAugmentation.ts",
+ "toSymbol": "getActionHandler",
+ "callExpression": "getActionHandler",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "findNode",
+ "toSymbol": "findNode",
+ "callExpression": "studio.findNode",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "onDismiss",
+ "toSymbol": "setInsertVisible",
+ "callExpression": "setInsertVisible",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "onInsert",
+ "toSymbol": "insertFromCatalogEntry",
+ "callExpression": "studio.insertFromCatalogEntry",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "onInsert",
+ "toSymbol": "setInsertVisible",
+ "callExpression": "setInsertVisible",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "useStudioAppBarAugmentation",
+ "toSymbol": "resolveNodeLabel",
+ "callExpression": "resolveNodeLabel",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
+ {
+ "fromSymbol": "onCancel",
+ "toSymbol": "setDeleteCandidateId",
+ "callExpression": "setDeleteCandidateId",
+ "sourcePath": "src/ui/useStudioAppBarAugmentation.ts"
+ },
{
"fromSymbol": "src/app/workspace/createProjectFormState.test.ts",
"toSymbol": "test",
@@ -39089,6 +39307,258 @@
"callExpression": "useContext",
"sourcePath": "src/ui/admin/AuthAdminSession.tsx"
},
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "describe",
+ "callExpression": "describe",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "test",
+ "callExpression": "test",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "commitCanvasDrop",
+ "callExpression": "commitCanvasDrop",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "expect",
+ "callExpression": "expect",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "activateCanvasDrag",
+ "callExpression": "activateCanvasDrag",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "resetCanvasDragSession",
+ "callExpression": "resetCanvasDragSession",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "createCanvasDraggableSessionKey",
+ "callExpression": "createCanvasDraggableSessionKey",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "completeCanvasDropAfterAdapter",
+ "callExpression": "completeCanvasDropAfterAdapter",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.test.ts",
+ "toSymbol": "sortCanvasDropTargetsBySpecificity",
+ "callExpression": "sortCanvasDropTargetsBySpecificity",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.test.ts"
+ },
+ {
+ "fromSymbol": "resetCanvasDragSession",
+ "toSymbol": "setActiveDropZoneId",
+ "callExpression": "callbacks.setActiveDropZoneId",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "resetCanvasDragSession",
+ "toSymbol": "setActiveDragNodeId",
+ "callExpression": "callbacks.setActiveDragNodeId",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "resetCanvasDragSession",
+ "toSymbol": "restartDraggable",
+ "callExpression": "callbacks.restartDraggable",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "commitCanvasDrop",
+ "toSymbol": "isStudioCanvasDragPayload",
+ "callExpression": "isStudioCanvasDragPayload",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "commitCanvasDrop",
+ "toSymbol": "moveNodeToPlacement",
+ "callExpression": "moveNodeToPlacement",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.ts",
+ "toSymbol": "commitCanvasDrop",
+ "callExpression": "commitCanvasDrop",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/canvasDndInteraction.ts",
+ "toSymbol": "resetDrag",
+ "callExpression": "resetDrag",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "activateCanvasDrag",
+ "toSymbol": "setActiveDragNodeId",
+ "callExpression": "callbacks.setActiveDragNodeId",
+ "sourcePath": "src/ui/canvas/canvasDndInteraction.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "toSymbol": "readFileSync",
+ "callExpression": "readFileSync",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "toSymbol": "join",
+ "callExpression": "join",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "toSymbol": "describe",
+ "callExpression": "describe",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "toSymbol": "test",
+ "callExpression": "test",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.test.ts",
+ "toSymbol": "expect",
+ "callExpression": "expect",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.test.ts"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "findNodeById",
+ "callExpression": "findNodeById",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "resolveCanvasDropZones",
+ "callExpression": "resolveCanvasDropZones",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "resolveCanvasDropZoneRect",
+ "callExpression": "resolveCanvasDropZoneRect",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "resolveDropZoneViews",
+ "toSymbol": "sortCanvasDropTargetsBySpecificity",
+ "callExpression": "sortCanvasDropTargetsBySpecificity",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "CanvasDropZone",
+ "toSymbol": "useZoraTheme",
+ "callExpression": "useZoraTheme",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "setActiveDropZoneId",
+ "callExpression": "props.setActiveDropZoneId",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "completeCanvasDropAfterAdapter",
+ "callExpression": "completeCanvasDropAfterAdapter",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "CanvasDropZone",
+ "toSymbol": "resolveNodeLabel",
+ "callExpression": "resolveNodeLabel",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "CanvasDragPreview",
+ "toSymbol": "useZoraTheme",
+ "callExpression": "useZoraTheme",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "CanvasDragPreview",
+ "toSymbol": "resolveCanvasDragPreviewText",
+ "callExpression": "resolveCanvasDragPreviewText",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "StudioCanvasDndOverlay",
+ "toSymbol": "findNodeById",
+ "callExpression": "findNodeById",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "setActiveDropZoneId",
+ "callExpression": "setActiveDropZoneId",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "StudioCanvasDndOverlay",
+ "toSymbol": "createStudioCanvasDragPayload",
+ "callExpression": "createStudioCanvasDragPayload",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "StudioCanvasDndOverlay",
+ "toSymbol": "resolveNodeLabel",
+ "callExpression": "resolveNodeLabel",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "StudioCanvasDndOverlay",
+ "toSymbol": "resolveDropZoneViews",
+ "callExpression": "resolveDropZoneViews",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "resetDrag",
+ "toSymbol": "resetCanvasDragSession",
+ "callExpression": "resetCanvasDragSession",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "restartDraggable",
+ "toSymbol": "setDragSessionRevision",
+ "callExpression": "setDragSessionRevision",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "StudioCanvasDndOverlay",
+ "toSymbol": "createCanvasDraggableSessionKey",
+ "callExpression": "createCanvasDraggableSessionKey",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "activateCanvasDrag",
+ "callExpression": "activateCanvasDrag",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
+ {
+ "fromSymbol": "src/ui/canvas/StudioCanvasDndOverlay.tsx",
+ "toSymbol": "resetDrag",
+ "callExpression": "resetDrag",
+ "sourcePath": "src/ui/canvas/StudioCanvasDndOverlay.tsx"
+ },
{
"fromSymbol": "src/host/layout/auth/resolveAuthLayoutPlan.test.ts",
"toSymbol": "describe",
@@ -42515,6 +42985,16 @@
"toType": "InsertNodeAtPlacementResult",
"sourcePath": "src/index.ts"
},
+ {
+ "fromSymbol": "resolveMoveNodePlacement",
+ "toType": "MoveNodeToPlacementArgs",
+ "sourcePath": "src/index.ts"
+ },
+ {
+ "fromSymbol": "resolveMoveNodePlacement",
+ "toType": "PlacementResolutionResult",
+ "sourcePath": "src/index.ts"
+ },
{
"fromSymbol": "moveNodeToPlacement",
"toType": "MoveNodeToPlacementArgs",
@@ -42835,6 +43315,11 @@
"toType": "StudioAuthSettingsMutation",
"sourcePath": "src/index.ts"
},
+ {
+ "fromSymbol": "StudioContextValue",
+ "toType": "StudioComponentMetaRegistry",
+ "sourcePath": "src/index.ts"
+ },
{
"fromSymbol": "StudioContextValue",
"toType": "StudioLocale",
@@ -42910,21 +43395,6 @@
"toType": "UiNode",
"sourcePath": "src/index.ts"
},
- {
- "fromSymbol": "addNodeToTree",
- "toType": "StudioComponentMetaRegistry",
- "sourcePath": "src/index.ts"
- },
- {
- "fromSymbol": "addNodeToTree",
- "toType": "UiNode",
- "sourcePath": "src/index.ts"
- },
- {
- "fromSymbol": "moveNodeInTree",
- "toType": "UiNode",
- "sourcePath": "src/index.ts"
- },
{
"fromSymbol": "InsertNodeAtPlacementArgs",
"toType": "NodePlacement",
diff --git a/src/canvasDragModel.public.test.ts b/src/canvasDragModel.public.test.ts
index 211ad513..c2bfd2ae 100644
--- a/src/canvasDragModel.public.test.ts
+++ b/src/canvasDragModel.public.test.ts
@@ -1,10 +1,15 @@
import { describe, expect, test } from 'bun:test';
-import type { CanvasDropZoneSlots, StudioCanvasDragPayload } from './canvasDragModel';
+import type {
+ CanvasDragSessionResolution,
+ CanvasDropZoneSlots,
+ StudioCanvasDragPayload,
+} from './canvasDragModel';
import {
createStudioCanvasDragPayload,
isStudioCanvasDragPayload,
isValidCanvasDropZone,
+ resolveCanvasDragSession,
resolveCanvasDropZoneSlots,
} from './canvasDragModel';
import type { CanvasDropZoneResolution, ValidCanvasDropZoneResolution } from './canvasDropZones';
@@ -21,9 +26,16 @@ describe('canvas drag model public exports', () => {
? zone
: null;
const slots: CanvasDropZoneSlots = resolveCanvasDropZoneSlots([zone]);
+ const session: CanvasDragSessionResolution = resolveCanvasDragSession({
+ activeDragNodeId: 'node-1',
+ isEditMode: true,
+ rootNode: { id: 'root', type: 'Screen', children: [{ id: 'node-1', type: 'Text' }] },
+ selectedNodeId: 'node-1',
+ });
expect(isStudioCanvasDragPayload(payload)).toBe(true);
expect(validZone?.kind).toBe('inside');
expect(slots.insideDropZone?.kind).toBe('inside');
+ expect(session.activeDragNodeId).toBe('node-1');
});
});
diff --git a/src/canvasDragModel.test.ts b/src/canvasDragModel.test.ts
index c61400b2..35a76bd1 100644
--- a/src/canvasDragModel.test.ts
+++ b/src/canvasDragModel.test.ts
@@ -1,9 +1,13 @@
+import type { UiNode } from '@ankhorage/contracts';
import { describe, expect, test } from 'bun:test';
import {
createStudioCanvasDragPayload,
isStudioCanvasDragPayload,
isValidCanvasDropZone,
+ resolveCanvasDragPreviewText,
+ resolveCanvasDragSession,
+ resolveCanvasDropZoneRect,
resolveCanvasDropZoneSlots,
} from './canvasDragModel';
import type { CanvasDropZoneResolution } from './canvasDropZones';
@@ -17,7 +21,7 @@ const VALID_INSIDE_ZONE: CanvasDropZoneResolution = {
const INVALID_BEFORE_ZONE: CanvasDropZoneResolution = {
kind: 'before',
status: 'invalid',
- reason: 'Cannot insert here.',
+ reason: { code: 'child-not-allowed', message: 'Cannot insert here.' },
};
const VALID_AFTER_ZONE: CanvasDropZoneResolution = {
@@ -26,6 +30,15 @@ const VALID_AFTER_ZONE: CanvasDropZoneResolution = {
placement: { parentId: 'root', index: 1, kind: 'after', referenceId: 'child' },
};
+const ROOT_NODE: UiNode = {
+ id: 'root',
+ type: 'Screen',
+ children: [
+ { id: 'node-a', type: 'Text' },
+ { id: 'node-b', type: 'Text' },
+ ],
+};
+
describe('canvasDragModel', () => {
test('creates and detects Studio canvas drag payloads', () => {
const payload = createStudioCanvasDragPayload('node-1');
@@ -54,4 +67,97 @@ describe('canvasDragModel', () => {
expect(slots.insideDropZone).toBe(VALID_INSIDE_ZONE);
expect(slots.afterDropZone).toBe(VALID_AFTER_ZONE);
});
+
+ test('derives before, inside, and after geometry from measured Runtime bounds', () => {
+ const targetRect = { x: 20, y: 40, width: 200, height: 120 };
+ const draggedRect = { x: 0, y: 0, width: 100, height: 48 };
+
+ expect(resolveCanvasDropZoneRect({ kind: 'before', targetRect, draggedRect })).toEqual({
+ x: 20,
+ y: 16,
+ width: 200,
+ height: 48,
+ });
+ expect(resolveCanvasDropZoneRect({ kind: 'inside', targetRect, draggedRect })).toEqual({
+ x: 44,
+ y: 64,
+ width: 152,
+ height: 72,
+ });
+ expect(resolveCanvasDropZoneRect({ kind: 'after', targetRect, draggedRect })).toEqual({
+ x: 20,
+ y: 136,
+ width: 200,
+ height: 48,
+ });
+ });
+
+ test('uses authored text for the measured-bounds drag preview', () => {
+ expect(resolveCanvasDragPreviewText({ children: ' Welcome ', title: 'Fallback' })).toBe(
+ 'Welcome',
+ );
+ expect(resolveCanvasDragPreviewText({ children: 12, label: 'Card' })).toBe('Card');
+ expect(resolveCanvasDragPreviewText({ children: 12 })).toBeNull();
+ expect(resolveCanvasDragPreviewText(undefined)).toBeNull();
+ });
+
+ test('keeps a drag active while edit selection and the current tree own that node', () => {
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: 'node-a',
+ isEditMode: true,
+ rootNode: ROOT_NODE,
+ selectedNodeId: 'node-a',
+ }),
+ ).toEqual({ activeDragNodeId: 'node-a', shouldReset: false });
+ });
+
+ test('resets an active drag when selection changes or is lost', () => {
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: 'node-a',
+ isEditMode: true,
+ rootNode: ROOT_NODE,
+ selectedNodeId: 'node-b',
+ }),
+ ).toEqual({ activeDragNodeId: null, shouldReset: true });
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: 'node-a',
+ isEditMode: true,
+ rootNode: ROOT_NODE,
+ selectedNodeId: null,
+ }),
+ ).toEqual({ activeDragNodeId: null, shouldReset: true });
+ });
+
+ test('resets an active drag in Preview or when the node leaves the current root', () => {
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: 'node-a',
+ isEditMode: false,
+ rootNode: ROOT_NODE,
+ selectedNodeId: 'node-a',
+ }),
+ ).toEqual({ activeDragNodeId: null, shouldReset: true });
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: 'missing-node',
+ isEditMode: true,
+ rootNode: ROOT_NODE,
+ selectedNodeId: 'missing-node',
+ }),
+ ).toEqual({ activeDragNodeId: null, shouldReset: true });
+ });
+
+ test('does not request another reset after transient drag state is already clear', () => {
+ expect(
+ resolveCanvasDragSession({
+ activeDragNodeId: null,
+ isEditMode: false,
+ rootNode: null,
+ selectedNodeId: null,
+ }),
+ ).toEqual({ activeDragNodeId: null, shouldReset: false });
+ });
});
diff --git a/src/canvasDragModel.ts b/src/canvasDragModel.ts
index 1f5a2c9c..fe9b28cc 100644
--- a/src/canvasDragModel.ts
+++ b/src/canvasDragModel.ts
@@ -1,6 +1,18 @@
+import type { UiNode } from '@ankhorage/contracts';
+
import type { CanvasDropZoneResolution, ValidCanvasDropZoneResolution } from './canvasDropZones';
import type { PlacementKind } from './index';
+export interface CanvasRect {
+ readonly x: number;
+ readonly y: number;
+ readonly width: number;
+ readonly height: number;
+}
+
+const MIN_DROP_ZONE_SIZE = 24;
+const MAX_DROP_ZONE_SIZE = 96;
+
export interface StudioCanvasDragPayload {
kind: 'studio-canvas-node';
nodeId: string;
@@ -13,6 +25,38 @@ export interface CanvasDropZoneSlots {
afterDropZone: ValidCanvasDropZoneResolution | null;
}
+export interface CanvasDragSessionResolution {
+ readonly activeDragNodeId: string | null;
+ readonly shouldReset: boolean;
+}
+
+function treeContainsNode(root: UiNode, nodeId: string): boolean {
+ if (root.id === nodeId) return true;
+ return root.children?.some((child) => treeContainsNode(child, nodeId)) ?? false;
+}
+
+export function resolveCanvasDragSession(args: {
+ readonly activeDragNodeId: string | null;
+ readonly isEditMode: boolean;
+ readonly rootNode: UiNode | null;
+ readonly selectedNodeId: string | null;
+}): CanvasDragSessionResolution {
+ const { activeDragNodeId } = args;
+ if (!activeDragNodeId) {
+ return { activeDragNodeId: null, shouldReset: false };
+ }
+
+ const isValid =
+ args.isEditMode &&
+ args.selectedNodeId === activeDragNodeId &&
+ args.rootNode !== null &&
+ treeContainsNode(args.rootNode, activeDragNodeId);
+
+ return isValid
+ ? { activeDragNodeId, shouldReset: false }
+ : { activeDragNodeId: null, shouldReset: true };
+}
+
export function createStudioCanvasDragPayload(nodeId: string): StudioCanvasDragPayload {
return { kind: 'studio-canvas-node', nodeId };
}
@@ -50,3 +94,50 @@ function findDropZoneByKind(
): ValidCanvasDropZoneResolution | null {
return zones.find((zone) => zone.kind === kind) ?? null;
}
+
+export function resolveCanvasDropZoneRect(args: {
+ readonly kind: PlacementKind;
+ readonly targetRect: CanvasRect;
+ readonly draggedRect: CanvasRect;
+}): CanvasRect {
+ const { kind, targetRect, draggedRect } = args;
+ const edgeSize = Math.max(MIN_DROP_ZONE_SIZE, Math.min(MAX_DROP_ZONE_SIZE, draggedRect.height));
+
+ if (kind === 'before') {
+ return {
+ x: targetRect.x,
+ y: targetRect.y - edgeSize / 2,
+ width: targetRect.width,
+ height: edgeSize,
+ };
+ }
+ if (kind === 'after') {
+ return {
+ x: targetRect.x,
+ y: targetRect.y + targetRect.height - edgeSize / 2,
+ width: targetRect.width,
+ height: edgeSize,
+ };
+ }
+
+ const inset = Math.min(edgeSize / 2, targetRect.width / 4, targetRect.height / 4);
+ return {
+ x: targetRect.x + inset,
+ y: targetRect.y + inset,
+ width: Math.max(MIN_DROP_ZONE_SIZE, targetRect.width - inset * 2),
+ height: Math.max(MIN_DROP_ZONE_SIZE, targetRect.height - inset * 2),
+ };
+}
+
+export function resolveCanvasDragPreviewText(
+ props: Record | undefined,
+): string | null {
+ if (!props) return null;
+ for (const key of ['children', 'text', 'title', 'label', 'description']) {
+ const value = props[key];
+ if (typeof value === 'string' && value.trim().length > 0) {
+ return value.trim().slice(0, 80);
+ }
+ }
+ return null;
+}
diff --git a/src/canvasDropZones.test.ts b/src/canvasDropZones.test.ts
index 4c704a86..e797b910 100644
--- a/src/canvasDropZones.test.ts
+++ b/src/canvasDropZones.test.ts
@@ -25,6 +25,11 @@ function buildRoot(): UiNode {
type: 'Container',
children: [{ id: 'text', type: 'Text' }],
},
+ {
+ id: 'source-container',
+ type: 'Container',
+ children: [{ id: 'dragged-text', type: 'Text' }],
+ },
],
};
}
@@ -69,4 +74,35 @@ describe('canvasDropZones', () => {
expect.objectContaining({ kind: 'after', status: 'invalid' }),
]);
});
+
+ test('preserves canonical descendant and no-op movement failures', () => {
+ const descendantComponentMeta: StudioComponentMetaRegistry = {
+ ...componentMeta,
+ Container: { category: 'layout', allowedChildren: ['Container', 'Text'] },
+ Text: { category: 'content', allowedChildren: ['Container'] },
+ };
+ const descendantZones = resolveCanvasDropZones({
+ root: buildRoot(),
+ targetNodeId: 'text',
+ draggedNode: { id: 'container', type: 'Container' },
+ componentMeta: descendantComponentMeta,
+ });
+ const descendantInsideZone = descendantZones.find((zone) => zone.kind === 'inside');
+ expect(descendantInsideZone?.status).toBe('invalid');
+ if (descendantInsideZone?.status === 'invalid') {
+ expect(descendantInsideZone.reason.code).toBe('cannot-move-into-descendant');
+ }
+
+ const noOpZones = resolveCanvasDropZones({
+ root: buildRoot(),
+ targetNodeId: 'source-container',
+ draggedNode: { id: 'container', type: 'Container' },
+ componentMeta,
+ });
+ const noOpBeforeZone = noOpZones.find((zone) => zone.kind === 'before');
+ expect(noOpBeforeZone?.status).toBe('invalid');
+ if (noOpBeforeZone?.status === 'invalid') {
+ expect(noOpBeforeZone.reason.code).toBe('no-op');
+ }
+ });
});
diff --git a/src/canvasDropZones.ts b/src/canvasDropZones.ts
index 843e2881..1240b448 100644
--- a/src/canvasDropZones.ts
+++ b/src/canvasDropZones.ts
@@ -1,7 +1,12 @@
import type { UiNode } from '@ankhorage/contracts';
-import type { NodePlacement, PlacementKind, StudioComponentMetaRegistry } from './index';
-import { resolveInsertPlacement } from './index';
+import type {
+ NodePlacement,
+ PlacementFailureReason,
+ PlacementKind,
+ StudioComponentMetaRegistry,
+} from './index';
+import { resolveInsertPlacement, resolveMoveNodePlacement } from './index';
export interface ValidCanvasDropZoneResolution {
kind: PlacementKind;
@@ -12,7 +17,7 @@ export interface ValidCanvasDropZoneResolution {
interface InvalidCanvasDropZoneResolution {
kind: PlacementKind;
status: 'invalid';
- reason: string;
+ reason: PlacementFailureReason;
}
export type CanvasDropZoneResolution =
@@ -33,7 +38,10 @@ export function resolveCanvasDropZones(args: {
return {
kind,
status: 'invalid',
- reason: 'Cannot drop a node onto itself.',
+ reason: {
+ code: 'cannot-move-into-self',
+ message: 'Cannot drop a node onto itself.',
+ },
};
}
@@ -49,14 +57,28 @@ export function resolveCanvasDropZones(args: {
return {
kind,
status: 'invalid',
- reason: placement.reason.message,
+ reason: placement.reason,
+ };
+ }
+
+ const movement = resolveMoveNodePlacement({
+ root,
+ nodeId: draggedNode.id,
+ placement: placement.placement,
+ componentMeta,
+ });
+ if (!movement.ok) {
+ return {
+ kind,
+ status: 'invalid',
+ reason: movement.reason,
};
}
return {
kind,
status: 'valid',
- placement: placement.placement,
+ placement: movement.placement,
};
});
}
diff --git a/src/core/StudioProvider.test.ts b/src/core/StudioProvider.test.ts
index cee83853..e695b3ff 100644
--- a/src/core/StudioProvider.test.ts
+++ b/src/core/StudioProvider.test.ts
@@ -14,6 +14,19 @@ test('uses canonical manifestState mutations for provider authoring state', () =
expect(source).toContain('updateStudioManifestDraftAuthSettings');
expect(source).not.toContain('updateNode: noop');
expect(source).not.toContain('updateTheme: (_id: string, _updates: ThemeUpdates)');
+ expect(source).not.toContain('deleteNode: noop');
+ expect(source).not.toContain('insertFromCatalogEntry: (_entry');
+ expect(source).not.toContain('moveNodeToPlacement: (_nodeId');
+ expect(source).toContain('insertStudioManifestNodeAtPlacement');
+ expect(source).toContain('moveStudioManifestNodeToPlacement');
+ expect(source).toContain('deleteStudioManifestNode');
+ expect(source).toContain('createNodeFromCatalogEntry');
+});
+
+test('requires caller-injected component metadata for package-neutral placement', () => {
+ expect(source).toContain('componentMeta: StudioComponentMetaRegistry');
+ expect(source).toContain('componentMeta,');
+ expect(source).not.toContain("from '@ankhorage/zora'");
});
test('owns Studio draft hydration and autosave through the host manifest boundary', () => {
diff --git a/src/core/StudioProvider.ts b/src/core/StudioProvider.ts
index 624536bb..9963e056 100644
--- a/src/core/StudioProvider.ts
+++ b/src/core/StudioProvider.ts
@@ -18,10 +18,12 @@ import {
} from '../authSettings';
import { deleteStudioGeneratedApi, upsertStudioGeneratedApi } from '../generatedApiAuthoring';
import {
+ createNodeFromCatalogEntry,
findNodeById,
type InsertCatalogEntry,
type NodePlacement,
type StudioAdminRouteId,
+ type StudioComponentMetaRegistry,
type StudioContextValue,
type StudioManifest,
type StudioMode,
@@ -31,10 +33,19 @@ import {
type StudioScreenId,
type ThemeUpdates,
} from '../index';
-import { resolveActiveRootNode, resolveInitialActiveScreenId } from '../manifestState';
+import {
+ deleteStudioManifestNode,
+ insertStudioManifestNodeAtPlacement,
+ moveStudioManifestNodeToPlacement,
+ resolveActiveRootNode,
+ resolveInitialActiveScreenId,
+} from '../manifestState';
import { createStudioManifestSignature } from '../manifestSync';
import { resolveScreenIdForPathname } from '../routeUtils';
-import { resolveStudioSelectedNodeId } from '../studioSelectionModel';
+import {
+ resolveStudioSelectedNodeId,
+ resolveStudioSelectionParentNodeId,
+} from '../studioSelectionModel';
import { AuthAdminSessionProvider } from '../ui/admin/AuthAdminSession';
import { API_BASE } from './constants';
import { StudioContext } from './StudioContext';
@@ -54,6 +65,7 @@ export interface StudioProviderProps {
projectId: string;
initialManifest?: StudioManifest | null;
activePathname?: string;
+ componentMeta: StudioComponentMetaRegistry;
}
const noop = () => undefined;
@@ -65,6 +77,7 @@ export const StudioProvider = ({
projectId,
initialManifest = null,
activePathname,
+ componentMeta,
}: StudioProviderProps) => {
const [manifest, setManifest] = useState(initialManifest);
const [activePanelId, setActivePanelId] = useState(null);
@@ -211,6 +224,62 @@ export const StudioProvider = ({
[updateManifest],
);
+ const insertFromCatalogEntry = useCallback(
+ (entry: InsertCatalogEntry): boolean => {
+ if (entry.status !== 'enabled' || !entry.placement) return false;
+ const { placement } = entry;
+ const { current } = manifestRef;
+ if (!current) return false;
+ const insertion = insertStudioManifestNodeAtPlacement({
+ manifest: current,
+ activeScreenId,
+ placement,
+ newNode: createNodeFromCatalogEntry(entry, componentMeta),
+ componentMeta,
+ });
+ if (!insertion) return false;
+ updateManifest(() => insertion.manifest);
+ selectNode(insertion.insertedNodeId);
+ return true;
+ },
+ [activeScreenId, componentMeta, updateManifest],
+ );
+
+ const moveSelectedNodeToPlacement = useCallback(
+ (nodeId: StudioNodeId, placement: NodePlacement): boolean => {
+ const { current } = manifestRef;
+ if (!current) return false;
+ const movement = moveStudioManifestNodeToPlacement({
+ manifest: current,
+ activeScreenId,
+ nodeId,
+ placement,
+ componentMeta,
+ });
+ if (!movement) return false;
+ updateManifest(() => movement.manifest);
+ selectNode(movement.movedNodeId);
+ return true;
+ },
+ [activeScreenId, componentMeta, updateManifest],
+ );
+
+ const deleteNode = useCallback(
+ (nodeId: StudioNodeId) => {
+ const currentRoot = resolveActiveRootNode(manifestRef.current, activeScreenId);
+ if (!currentRoot || currentRoot.id === nodeId || !findNodeById(currentRoot, nodeId)) return;
+ const parentNodeId = resolveStudioSelectionParentNodeId(currentRoot, nodeId);
+ const { current } = manifestRef;
+ if (!current) return;
+ const next = deleteStudioManifestNode(current, activeScreenId, nodeId);
+ if (next === current) return;
+ updateManifest(() => next);
+ selectNode(parentNodeId);
+ setActiveCanvasDragNodeId((activeNodeId) => (activeNodeId === nodeId ? null : activeNodeId));
+ },
+ [activeScreenId, updateManifest],
+ );
+
const value = useMemo(
() => ({
projectId,
@@ -228,6 +297,7 @@ export const StudioProvider = ({
error,
manifest,
rootNode,
+ componentMeta,
selectNode,
setActivePanelId,
setActiveAdminRouteId,
@@ -240,9 +310,9 @@ export const StudioProvider = ({
updateManifest((current) => updateStudioManifestDraftDataSources(current, dataSources)),
upsertGeneratedApi,
deleteGeneratedApi,
- deleteNode: noop,
- insertFromCatalogEntry: (_entry: InsertCatalogEntry) => false,
- moveNodeToPlacement: (_nodeId: StudioNodeId, _placement: NodePlacement) => false,
+ deleteNode,
+ insertFromCatalogEntry,
+ moveNodeToPlacement: moveSelectedNodeToPlacement,
addScreen: noop,
deleteScreen: noop,
setNavigatorType: (_type: NavigatorType) => undefined,
@@ -257,7 +327,6 @@ export const StudioProvider = ({
updateModuleConfig: (_moduleId: StudioModuleId, _config: Record) =>
undefined,
updateOAuthProviders,
- moveNode: noop,
reorderScreens: (_newRoutes: RouteDefinition[]) => undefined,
setActiveScreenId: setRequestedActiveScreenId,
findNode: findNodeById,
@@ -282,6 +351,7 @@ export const StudioProvider = ({
previewMode,
projectId,
rootNode,
+ componentMeta,
saveStatus,
selectedNodeId,
studioMode,
@@ -292,6 +362,9 @@ export const StudioProvider = ({
updateOAuthProviders,
upsertGeneratedApi,
deleteGeneratedApi,
+ deleteNode,
+ insertFromCatalogEntry,
+ moveSelectedNodeToPlacement,
updateTheme,
persistence.refetchManifest,
persistence.flushManifest,
diff --git a/src/dnd/index.ts b/src/dnd/index.ts
deleted file mode 100644
index 75e88e12..00000000
--- a/src/dnd/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './primitives';
-export * from './state';
diff --git a/src/dnd/primitives.ts b/src/dnd/primitives.ts
deleted file mode 100644
index fb4cbe2f..00000000
--- a/src/dnd/primitives.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from '@ankhorage/react-native-reanimated-dnd-web';
diff --git a/src/dnd/state.ts b/src/dnd/state.ts
deleted file mode 100644
index 2bb65eb8..00000000
--- a/src/dnd/state.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export interface StudioDragState {
- readonly activeNodeId: string | null;
- readonly activeDropZoneId: string | null;
-}
-
-export const createIdleStudioDragState = (): StudioDragState => ({
- activeNodeId: null,
- activeDropZoneId: null,
-});
diff --git a/src/host/layout/layoutGenerator.test.ts b/src/host/layout/layoutGenerator.test.ts
index 90e001fb..97b5409c 100644
--- a/src/host/layout/layoutGenerator.test.ts
+++ b/src/host/layout/layoutGenerator.test.ts
@@ -201,7 +201,7 @@ describe('GeneratedAppFileGenerator', () => {
const screen = files.find((file) => file.path === 'src/app/index.tsx')?.content ?? '';
expect(rootLayout).toContain(
- "import { AppShell, ZoraProvider, ZORA_COMPONENT_REGISTRY, useZoraTheme, AppBar } from '@ankhorage/zora';",
+ "import { AppShell, ZoraProvider, ZORA_COMPONENT_REGISTRY, ZORA_COMPONENT_META, useZoraTheme, AppBar } from '@ankhorage/zora';",
);
expect(rootLayout).toContain('createComponentRegistry');
expect(rootLayout).toContain('STUDIO_APP_EXTENSION_COMPONENT_REGISTRY');
diff --git a/src/host/layout/layoutGenerator.ts b/src/host/layout/layoutGenerator.ts
index d6725298..d73a08b2 100644
--- a/src/host/layout/layoutGenerator.ts
+++ b/src/host/layout/layoutGenerator.ts
@@ -269,6 +269,7 @@ export class GeneratedAppFileGenerator {
'AppShell',
'ZoraProvider',
'ZORA_COMPONENT_REGISTRY',
+ includeStudio ? 'ZORA_COMPONENT_META' : '',
'useZoraTheme',
includeStudio ? 'AppBar' : '',
]
@@ -357,6 +358,7 @@ export class GeneratedAppFileGenerator {
'AppShell',
'ZoraProvider',
'ZORA_COMPONENT_REGISTRY',
+ includeStudio ? 'ZORA_COMPONENT_META' : '',
'useZoraTheme',
includeStudio ? 'AppBar' : '',
needsZoraTabBar ? 'ZoraTabBar' : '',
diff --git a/src/host/layout/templates/rootLayout.test.ts b/src/host/layout/templates/rootLayout.test.ts
index 972eaef3..84f899d8 100644
--- a/src/host/layout/templates/rootLayout.test.ts
+++ b/src/host/layout/templates/rootLayout.test.ts
@@ -72,6 +72,7 @@ test('initializes the Studio provider with the runtime manifest', () => {
});
expect(generated).toContain('initialManifest={runtimeManifest}');
+ expect(generated).toContain('componentMeta={ZORA_COMPONENT_META}');
expect(generated).toContain(
'activePathname={isStudioAdminPath(appPathname) ? undefined : appPathname}',
);
@@ -160,6 +161,10 @@ test('generates a root stationary tap selector for edit mode and excludes old Pr
expect(generated).toContain('wrapNode: studioWrapNode');
expect(generated).toContain('selectedNodeId');
expect(generated).toContain('selectNode');
+ expect(generated).toContain('canvasInteraction={{');
+ expect(generated).toContain('activeDragNodeId: activeCanvasDragNodeId');
+ expect(generated).toContain('moveNodeToPlacement');
+ expect(generated).toContain('setActiveDragNodeId: setActiveCanvasDragNodeId');
expect(generated).toContain('APP_EXTENSION_INTERACTION_POLICY_SUPPORT');
expect(generated).toContain('ZORA_COMPONENT_REGISTRY');
expect(generated).not.toContain('
{
@@ -639,6 +645,13 @@ function StudioShell({
);
const studioOutput = (
+ {studioAppBar.overlays}
>
);
}`
diff --git a/src/index.test.ts b/src/index.test.ts
index 355ce80f..caa8a6a4 100644
--- a/src/index.test.ts
+++ b/src/index.test.ts
@@ -13,12 +13,14 @@ import {
type ProjectSecretUsageSummary,
resolveDefaultInsertPlacement,
resolveInsertCatalogEntries,
+ resolveMoveNodePlacement,
STUDIO_PACKAGE_BOUNDARY,
STUDIO_PACKAGE_NAME,
STUDIO_PUBLIC_CONTRACTS,
type StudioComponentMetaRegistry,
TPL_SCREEN_EMPTY,
updateNodeInTree,
+ validateNodePlacement,
} from './index';
const componentMeta: StudioComponentMetaRegistry = {
@@ -242,6 +244,133 @@ describe('@ankhorage/studio', () => {
expect(findNodeById(movement.root, 'section-b')?.children?.[0]?.id).toBe('text-a');
});
+ test('rejects malformed placement references and indices', () => {
+ const root = createRoot();
+
+ const missingReference = validateNodePlacement({
+ root,
+ placement: { parentId: 'screen', index: 0, kind: 'before' },
+ childType: 'Text',
+ componentMeta,
+ });
+ expect(missingReference.ok).toBe(false);
+ if (missingReference.ok) throw new Error('Expected invalid reference.');
+ expect(missingReference.reason.code).toBe('invalid-reference');
+
+ const invalidIndex = validateNodePlacement({
+ root,
+ placement: {
+ parentId: 'screen',
+ index: 2,
+ kind: 'before',
+ referenceId: 'section-a',
+ },
+ childType: 'Text',
+ componentMeta,
+ });
+ expect(invalidIndex.ok).toBe(false);
+ if (invalidIndex.ok) throw new Error('Expected invalid index.');
+ expect(invalidIndex.reason.code).toBe('invalid-index');
+ });
+
+ test('rejects root, self, descendant, and no-op moves with stable diagnostics', () => {
+ const root = createRoot();
+ const nestedRoot: UiNode = {
+ ...root,
+ children: [
+ {
+ id: 'parent',
+ type: 'Section',
+ children: [{ id: 'descendant', type: 'Section', children: [] }],
+ },
+ ],
+ };
+
+ const cases = [
+ {
+ result: resolveMoveNodePlacement({
+ root,
+ nodeId: 'screen',
+ placement: { parentId: 'section-a', index: 0, kind: 'inside' },
+ componentMeta,
+ }),
+ code: 'cannot-move-root',
+ },
+ {
+ result: resolveMoveNodePlacement({
+ root,
+ nodeId: 'section-a',
+ placement: { parentId: 'section-a', index: 0, kind: 'inside' },
+ componentMeta,
+ }),
+ code: 'cannot-move-into-self',
+ },
+ {
+ result: resolveMoveNodePlacement({
+ root: nestedRoot,
+ nodeId: 'parent',
+ placement: { parentId: 'descendant', index: 0, kind: 'inside' },
+ componentMeta,
+ }),
+ code: 'cannot-move-into-descendant',
+ },
+ {
+ result: resolveMoveNodePlacement({
+ root,
+ nodeId: 'section-a',
+ placement: {
+ parentId: 'screen',
+ index: 0,
+ kind: 'before',
+ referenceId: 'section-a',
+ },
+ componentMeta,
+ }),
+ code: 'no-op',
+ },
+ ] as const;
+
+ for (const testCase of cases) {
+ expect(testCase.result.ok).toBe(false);
+ if (testCase.result.ok) throw new Error(`Expected ${testCase.code}.`);
+ expect(testCase.result.reason.code).toBe(testCase.code);
+ }
+ });
+
+ test('adjusts same-parent movement in both directions without partial invalid mutation', () => {
+ const root: UiNode = {
+ id: 'screen',
+ type: 'Screen',
+ children: ['a', 'b', 'c'].map((id) => ({ id, type: 'Text' })),
+ };
+ const down = moveNodeToPlacement({
+ root,
+ nodeId: 'a',
+ placement: { parentId: 'screen', index: 3, kind: 'after', referenceId: 'c' },
+ componentMeta,
+ });
+ expect(down?.root.children?.map((node) => node.id)).toEqual(['b', 'c', 'a']);
+
+ const up = moveNodeToPlacement({
+ root: down?.root ?? root,
+ nodeId: 'a',
+ placement: { parentId: 'screen', index: 0, kind: 'before', referenceId: 'b' },
+ componentMeta,
+ });
+ expect(up?.root.children?.map((node) => node.id)).toEqual(['a', 'b', 'c']);
+
+ const snapshot = JSON.stringify(root);
+ expect(
+ moveNodeToPlacement({
+ root,
+ nodeId: 'a',
+ placement: { parentId: 'missing', index: 0, kind: 'inside' },
+ componentMeta,
+ }),
+ ).toBeNull();
+ expect(JSON.stringify(root)).toBe(snapshot);
+ });
+
test('updates node props and clones empty screen templates with new ids', () => {
const updated = updateNodeInTree(createRoot(), 'text-a', {
children: 'Updated',
diff --git a/src/index.ts b/src/index.ts
index eabef7a8..2e17373a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -196,6 +196,7 @@ export type PlacementFailureCode =
| 'missing-parent'
| 'child-not-allowed'
| 'invalid-index'
+ | 'invalid-reference'
| 'no-valid-target'
| 'cannot-move-root'
| 'cannot-move-into-self'
@@ -339,6 +340,7 @@ export type StudioEvent =
export interface StudioContextValue extends StudioSelectionState, StudioSessionState {
manifest: StudioManifest | null;
rootNode: UiNode | null;
+ componentMeta: StudioComponentMetaRegistry;
selectNode: (id: StudioNodeId | null) => void;
setActivePanelId: (panelId: StudioPanelId | null) => void;
setActiveAdminRouteId: (routeId: StudioAdminRouteId) => void;
@@ -368,7 +370,6 @@ export interface StudioContextValue extends StudioSelectionState, StudioSessionS
mutateAuthSettings: (mutation: StudioAuthSettingsMutation) => StudioAuthSettings | null;
updateModuleConfig: (moduleId: StudioModuleId, config: Record) => void;
updateOAuthProviders: (providers: AuthOAuthProviderConfig[]) => void;
- moveNode: (id: StudioNodeId, direction: 'up' | 'down') => void;
reorderScreens: (newRoutes: RouteDefinition[]) => void;
setActiveScreenId: (id: StudioScreenId) => void;
findNode: (root: UiNode, id: StudioNodeId) => UiNode | null;
@@ -603,69 +604,6 @@ export const removeNodeFromTree = (root: UiNode, nodeId: string): UiNode | null
return hasChanged ? { ...root, children: nextChildren } : root;
};
-export const addNodeToTree = (args: {
- root: UiNode;
- targetId: string;
- newNode: UiNode;
- componentMeta: StudioComponentMetaRegistry;
- mode?: 'append' | 'prepend';
-}): UiNode => {
- const { root, targetId, newNode, componentMeta, mode = 'append' } = args;
-
- if (root.id === targetId) {
- if (!canAcceptChild({ parentType: root.type, childType: newNode.type, componentMeta })) {
- return root;
- }
-
- const children = root.children ?? [];
- return {
- ...root,
- children: mode === 'prepend' ? [newNode, ...children] : [...children, newNode],
- };
- }
-
- if (!root.children) {
- return root;
- }
-
- const nextChildren = root.children.map((child) =>
- addNodeToTree({ root: child, targetId, newNode, componentMeta, mode }),
- );
- const hasChanged = nextChildren.some((child, index) => child !== root.children?.[index]);
-
- return hasChanged ? { ...root, children: nextChildren } : root;
-};
-
-export const moveNodeInTree = (root: UiNode, nodeId: string, direction: 'up' | 'down'): UiNode => {
- if (root.id === nodeId || !root.children) return root;
-
- const index = root.children.findIndex((child) => child.id === nodeId);
- if (index !== -1) {
- const targetIndex = direction === 'up' ? index - 1 : index + 1;
- if (targetIndex < 0 || targetIndex >= root.children.length) {
- return root;
- }
-
- const currentNode = root.children[index];
- const targetNode = root.children[targetIndex];
- if (!currentNode || !targetNode) {
- return root;
- }
-
- const nextChildren = [...root.children];
- nextChildren[index] = targetNode;
- nextChildren[targetIndex] = currentNode;
- return { ...root, children: nextChildren };
- }
-
- const nextChildren = root.children.map((child) => moveNodeInTree(child, nodeId, direction));
- const hasChanged = nextChildren.some(
- (child, childIndex) => child !== root.children?.[childIndex],
- );
-
- return hasChanged ? { ...root, children: nextChildren } : root;
-};
-
interface NodeWithParent {
node: UiNode;
parent: UiNode | null;
@@ -803,25 +741,57 @@ export function validateNodePlacement(args: {
}
const children = parent.children ?? [];
- if (placement.referenceId) {
- const hasReference = children.some((child) => child.id === placement.referenceId);
- if (!hasReference) {
+ if (placement.index < 0 || placement.index > children.length) {
+ return {
+ ok: false,
+ reason: {
+ code: 'invalid-index',
+ message: `Index ${placement.index} is out of bounds for ${parent.id}.`,
+ },
+ };
+ }
+
+ if (placement.kind === 'inside') {
+ if (placement.referenceId) {
return {
ok: false,
reason: {
- code: 'missing-target',
- message: `Reference node ${placement.referenceId} was not found under ${parent.id}.`,
+ code: 'invalid-reference',
+ message: 'Inside placements cannot include a sibling reference.',
},
};
}
+ return { ok: true };
}
- if (placement.index < 0 || placement.index > children.length) {
+ if (!placement.referenceId) {
+ return {
+ ok: false,
+ reason: {
+ code: 'invalid-reference',
+ message: `${placement.kind} placements require a sibling reference.`,
+ },
+ };
+ }
+
+ const referenceIndex = children.findIndex((child) => child.id === placement.referenceId);
+ if (referenceIndex === -1) {
+ return {
+ ok: false,
+ reason: {
+ code: 'missing-target',
+ message: `Reference node ${placement.referenceId} was not found under ${parent.id}.`,
+ },
+ };
+ }
+
+ const expectedIndex = placement.kind === 'before' ? referenceIndex : referenceIndex + 1;
+ if (placement.index !== expectedIndex) {
return {
ok: false,
reason: {
code: 'invalid-index',
- message: `Index ${placement.index} is out of bounds for ${parent.id}.`,
+ message: `${placement.kind} placement index ${placement.index} does not match reference ${placement.referenceId}.`,
},
};
}
@@ -1060,35 +1030,61 @@ function getAdjustedMovePlacement(args: {
};
}
-export function moveNodeToPlacement(
- args: MoveNodeToPlacementArgs,
-): MoveNodeToPlacementResult | null {
+export function resolveMoveNodePlacement(args: MoveNodeToPlacementArgs): PlacementResolutionResult {
const { root, nodeId, placement, componentMeta } = args;
const source = findNodeWithParent(root, nodeId);
if (!source) {
- return null;
+ return {
+ ok: false,
+ reason: { code: 'missing-target', message: `Node ${nodeId} was not found.` },
+ };
}
if (!source.parent) {
- return null;
+ return {
+ ok: false,
+ reason: { code: 'cannot-move-root', message: 'The active screen root cannot be moved.' },
+ };
}
if (placement.parentId === nodeId) {
- return null;
+ return {
+ ok: false,
+ reason: { code: 'cannot-move-into-self', message: 'A node cannot be moved inside itself.' },
+ };
}
if (isDescendantNode(source.node, placement.parentId)) {
- return null;
+ return {
+ ok: false,
+ reason: {
+ code: 'cannot-move-into-descendant',
+ message: 'A node cannot be moved into one of its descendants.',
+ },
+ };
+ }
+
+ if (placement.referenceId === nodeId) {
+ return {
+ ok: false,
+ reason: { code: 'no-op', message: 'The node is already at that location.' },
+ };
}
const adjustedPlacement = getAdjustedMovePlacement({ source, placement });
if (!adjustedPlacement) {
- return null;
+ return {
+ ok: false,
+ reason: { code: 'no-op', message: 'The node is already at that location.' },
+ };
}
const removed = removeNodeForMove({ node: root, nodeId });
if (!removed.removedNode) {
- return null;
+ return {
+ ok: false,
+ reason: { code: 'missing-target', message: `Node ${nodeId} could not be removed.` },
+ };
}
const validation = validateNodePlacement({
@@ -1097,14 +1093,27 @@ export function moveNodeToPlacement(
childType: removed.removedNode.type,
componentMeta,
});
- if (!validation.ok) {
+ if (!validation.ok) return validation;
+
+ return { ok: true, placement: adjustedPlacement };
+}
+
+export function moveNodeToPlacement(
+ args: MoveNodeToPlacementArgs,
+): MoveNodeToPlacementResult | null {
+ const { root, nodeId, placement, componentMeta } = args;
+ const resolution = resolveMoveNodePlacement({ root, nodeId, placement, componentMeta });
+ if (!resolution.ok) return null;
+
+ const removed = removeNodeForMove({ node: root, nodeId });
+ if (!removed.removedNode) {
return null;
}
const inserted = insertChildAtIndex({
node: removed.node,
- parentId: adjustedPlacement.parentId,
- index: adjustedPlacement.index,
+ parentId: resolution.placement.parentId,
+ index: resolution.placement.index,
newNode: removed.removedNode,
});
if (!inserted.inserted) {
diff --git a/src/manifestState.test.ts b/src/manifestState.test.ts
index 9736a662..6d8e83bb 100644
--- a/src/manifestState.test.ts
+++ b/src/manifestState.test.ts
@@ -9,7 +9,6 @@ import {
deleteStudioManifestNode,
deleteStudioManifestScreen,
insertStudioManifestNodeAtPlacement,
- moveStudioManifestNode,
moveStudioManifestNodeToPlacement,
resolveActiveRootNode,
resolveInitialActiveScreenId,
@@ -294,17 +293,21 @@ describe('manifestState', () => {
});
expect(moved?.movedNodeId).toBe('button-1');
- const reordered = moveStudioManifestNode(
- moved?.manifest ?? updated,
- 'screen-home',
- 'text-1',
- 'down',
- );
- const deleted = deleteStudioManifestNode(reordered, 'screen-home', 'text-1');
+ const deleted = deleteStudioManifestNode(moved?.manifest ?? updated, 'screen-home', 'text-1');
expect(JSON.stringify(resolveActiveRootNode(deleted, 'screen-home'))).not.toContain('text-1');
expect(deleted.dataBindings?.['text-1']).toBeUndefined();
});
+ test('protects roots and removes bindings owned by an entire deleted subtree', () => {
+ const manifest = createManifest();
+ const rootProtected = deleteStudioManifestNode(manifest, 'screen-home', 'root-home');
+ expect(rootProtected).toBe(manifest);
+
+ const deleted = deleteStudioManifestNode(manifest, 'screen-home', 'section-1');
+ expect(resolveActiveRootNode(deleted, 'screen-home')?.children).toEqual([]);
+ expect(deleted.dataBindings?.['text-1']).toBeUndefined();
+ });
+
test('adds and deletes screens', () => {
let idIndex = 0;
const createId = (prefix = 'id') => {
diff --git a/src/manifestState.ts b/src/manifestState.ts
index 182d714c..6372b791 100644
--- a/src/manifestState.ts
+++ b/src/manifestState.ts
@@ -18,6 +18,7 @@ import type {
StudioMode,
ThemeUpdates,
} from './index';
+import { insertNodeAtPlacement, moveNodeToPlacement } from './index';
export interface ScreenRouteEntry {
route: RouteDefinition;
@@ -282,11 +283,19 @@ export function deleteStudioManifestNode(
const screen = manifest.screens[activeScreenId];
if (!screen || screen.root.id === nodeId) return manifest;
+ const deletedNode = findNodeInManifest(screen.root, nodeId);
+ if (!deletedNode) return manifest;
+
const newRoot = removeNodeFromManifestTree(screen.root, nodeId);
if (!newRoot || newRoot === screen.root) return manifest;
+ const deletedNodeIds = collectNodeIds(deletedNode);
+
const nextDataBindings = Object.fromEntries(
- Object.entries(manifest.dataBindings ?? {}).filter(([componentId]) => componentId !== nodeId),
+ Object.entries(manifest.dataBindings ?? {}).filter(
+ ([componentId, binding]) =>
+ !deletedNodeIds.has(componentId) && !deletedNodeIds.has(binding.componentId),
+ ),
);
return {
@@ -302,31 +311,6 @@ export function deleteStudioManifestNode(
};
}
-export function moveStudioManifestNode(
- manifest: StudioManifest,
- activeScreenId: string | null,
- nodeId: string,
- direction: 'up' | 'down',
-): StudioManifest {
- if (!activeScreenId) return manifest;
- const screen = manifest.screens[activeScreenId];
- if (!screen) return manifest;
-
- const newRoot = moveNodeInManifestTree(screen.root, nodeId, direction);
- if (newRoot === screen.root) return manifest;
-
- return {
- ...manifest,
- screens: {
- ...manifest.screens,
- [activeScreenId]: {
- ...screen,
- root: newRoot,
- },
- },
- };
-}
-
export function insertStudioManifestNodeAtPlacement(args: {
manifest: StudioManifest;
activeScreenId: string | null;
@@ -338,16 +322,13 @@ export function insertStudioManifestNodeAtPlacement(args: {
if (!activeScreenId) return null;
const screen = manifest.screens[activeScreenId];
if (!screen) return null;
- if (!validateManifestNodePlacement(screen.root, placement, newNode.type, componentMeta))
- return null;
-
- const insertion = insertChildAtIndex({
- node: screen.root,
- parentId: placement.parentId,
- index: placement.index,
- newNode,
+ const insertion = insertNodeAtPlacement({
+ root: screen.root,
+ placement,
+ componentMeta,
+ makeNode: () => newNode,
});
- if (!insertion.inserted) return null;
+ if (!insertion) return null;
return {
manifest: {
@@ -356,7 +337,7 @@ export function insertStudioManifestNodeAtPlacement(args: {
...manifest.screens,
[activeScreenId]: {
...screen,
- root: insertion.node,
+ root: insertion.root,
},
},
},
@@ -376,34 +357,13 @@ export function moveStudioManifestNodeToPlacement(args: {
const screen = manifest.screens[activeScreenId];
if (!screen) return null;
- const source = findNodeWithParent(screen.root, nodeId);
- if (!source?.parent) return null;
- if (placement.parentId === nodeId) return null;
- if (isDescendantNode(source.node, placement.parentId)) return null;
-
- const adjustedPlacement = adjustMovePlacement({ source, placement });
- if (!adjustedPlacement) return null;
-
- const removed = removeNodeForMove({ node: screen.root, nodeId });
- if (!removed.removedNode) return null;
- if (
- !validateManifestNodePlacement(
- removed.node,
- adjustedPlacement,
- removed.removedNode.type,
- componentMeta,
- )
- ) {
- return null;
- }
-
- const inserted = insertChildAtIndex({
- node: removed.node,
- parentId: adjustedPlacement.parentId,
- index: adjustedPlacement.index,
- newNode: removed.removedNode,
+ const movement = moveNodeToPlacement({
+ root: screen.root,
+ nodeId,
+ placement,
+ componentMeta,
});
- if (!inserted.inserted) return null;
+ if (!movement) return null;
return {
manifest: {
@@ -412,11 +372,11 @@ export function moveStudioManifestNodeToPlacement(args: {
...manifest.screens,
[activeScreenId]: {
...screen,
- root: inserted.node,
+ root: movement.root,
},
},
},
- movedNodeId: removed.removedNode.id,
+ movedNodeId: movement.movedNodeId,
};
}
@@ -1000,171 +960,14 @@ function removeNodeFromManifestTree(root: UiNode, nodeId: string): UiNode | null
return hasChanged ? { ...root, children: nextChildren } : root;
}
-function moveNodeInManifestTree(root: UiNode, nodeId: string, direction: 'up' | 'down'): UiNode {
- if (root.id === nodeId || !root.children) return root;
-
- const index = root.children.findIndex((child) => child.id === nodeId);
- if (index !== -1) {
- const targetIndex = direction === 'up' ? index - 1 : index + 1;
- if (targetIndex < 0 || targetIndex >= root.children.length) return root;
-
- const currentNode = root.children[index];
- const targetNode = root.children[targetIndex];
- if (!currentNode || !targetNode) return root;
-
- const nextChildren = [...root.children];
- nextChildren[index] = targetNode;
- nextChildren[targetIndex] = currentNode;
- return { ...root, children: nextChildren };
- }
-
- const nextChildren = root.children.map((child) =>
- moveNodeInManifestTree(child, nodeId, direction),
- );
- const hasChanged = nextChildren.some(
- (child, childIndex) => child !== root.children?.[childIndex],
- );
- return hasChanged ? { ...root, children: nextChildren } : root;
-}
-
-interface NodeWithParent {
- node: UiNode;
- parent: UiNode | null;
- index: number;
-}
-
-function findNodeWithParent(root: UiNode, nodeId: string): NodeWithParent | null {
- if (root.id === nodeId) return { node: root, parent: null, index: -1 };
-
- const visit = (node: UiNode): NodeWithParent | null => {
- const children = node.children ?? [];
- for (const [index, child] of children.entries()) {
- if (child.id === nodeId) return { node: child, parent: node, index };
-
- const nested = visit(child);
- if (nested) return nested;
- }
-
- return null;
+function collectNodeIds(root: UiNode): Set {
+ const ids = new Set();
+ const visit = (node: UiNode): void => {
+ ids.add(node.id);
+ for (const child of node.children ?? []) visit(child);
};
-
- return visit(root);
-}
-
-function validateManifestNodePlacement(
- root: UiNode,
- placement: NodePlacement,
- childType: string,
- componentMeta: StudioComponentMetaRegistry,
-): boolean {
- const parent = findNodeInManifest(root, placement.parentId);
- if (!parent) return false;
-
- const meta = componentMeta[parent.type];
- if (!meta?.allowedChildren.includes(childType)) return false;
-
- const children = parent.children ?? [];
- if (placement.referenceId && !children.some((child) => child.id === placement.referenceId)) {
- return false;
- }
-
- return placement.index >= 0 && placement.index <= children.length;
-}
-
-function insertChildAtIndex(args: {
- node: UiNode;
- parentId: string;
- index: number;
- newNode: UiNode;
-}): { node: UiNode; inserted: boolean } {
- const { node, parentId, index, newNode } = args;
- if (node.id === parentId) {
- const children = node.children ?? [];
- if (index < 0 || index > children.length) return { node, inserted: false };
-
- return {
- node: {
- ...node,
- children: [...children.slice(0, index), newNode, ...children.slice(index)],
- },
- inserted: true,
- };
- }
-
- if (!node.children?.length) return { node, inserted: false };
-
- const results = node.children.map((child) =>
- insertChildAtIndex({ node: child, parentId, index, newNode }),
- );
- const inserted = results.some((result) => result.inserted);
- return inserted
- ? { node: { ...node, children: results.map((result) => result.node) }, inserted }
- : { node, inserted };
-}
-
-function isDescendantNode(node: UiNode, descendantId: string): boolean {
- for (const child of node.children ?? []) {
- if (child.id === descendantId || isDescendantNode(child, descendantId)) return true;
- }
-
- return false;
-}
-
-function removeNodeForMove(args: { node: UiNode; nodeId: string }): {
- node: UiNode;
- removedNode: UiNode | null;
-} {
- const { node, nodeId } = args;
- const children = node.children ?? [];
- const directIndex = children.findIndex((child) => child.id === nodeId);
-
- if (directIndex !== -1) {
- const removedNode = children[directIndex];
- if (!removedNode) return { node, removedNode: null };
-
- return {
- node: {
- ...node,
- children: children.filter((child) => child.id !== nodeId),
- },
- removedNode,
- };
- }
-
- const nextChildren: UiNode[] = [];
- let removedNode: UiNode | null = null;
-
- for (const child of children) {
- if (removedNode) {
- nextChildren.push(child);
- continue;
- }
-
- const { node: nextChild, removedNode: nextRemovedNode } = removeNodeForMove({
- node: child,
- nodeId,
- });
- if (nextRemovedNode) removedNode = nextRemovedNode;
- nextChildren.push(nextChild);
- }
-
- if (!removedNode) return { node, removedNode: null };
- return { node: { ...node, children: nextChildren }, removedNode };
-}
-
-function adjustMovePlacement(args: {
- source: NodeWithParent;
- placement: NodePlacement;
-}): NodePlacement | null {
- const { source, placement } = args;
- if (!source.parent) return null;
- if (placement.referenceId === source.node.id) return null;
-
- if (placement.parentId !== source.parent.id) return placement;
-
- const adjustedIndex = source.index < placement.index ? placement.index - 1 : placement.index;
- if (adjustedIndex === source.index) return null;
- return { ...placement, index: adjustedIndex };
+ visit(root);
+ return ids;
}
function normalizeNavigatorAfterRouteUpdate(navigator: NavigatorSpec): NavigatorSpec {
diff --git a/src/runtime/runtimeNodeMeasurement.test.ts b/src/runtime/runtimeNodeMeasurement.test.ts
index 9d3035aa..66b8b678 100644
--- a/src/runtime/runtimeNodeMeasurement.test.ts
+++ b/src/runtime/runtimeNodeMeasurement.test.ts
@@ -61,7 +61,7 @@ function createTargetMeasurement(options: {
},
measure: () => Promise.resolve({ x: 0, y: 0, width: 20, height: 20 }),
showUnsupportedIndicator: options.unsupported === true,
- source: 'web-recorder',
+ source: 'runtime-recorder',
};
}
@@ -272,6 +272,49 @@ describe('active web Runtime node resize targets', () => {
expect(observer.observed()).toEqual([selectedTarget]);
});
+ it('activates every Runtime node measurement only while a canvas drag is active', async () => {
+ const firstTarget = { id: 'first-target' };
+ const secondTarget = { id: 'second-target' };
+ const registry = createRuntimeNodeMeasurementRegistry();
+ registry.register('first', createTargetMeasurement({ targets: [firstTarget] }));
+ registry.register('second', createTargetMeasurement({ targets: [secondTarget] }));
+
+ expect(
+ getActiveRuntimeNodeMeasurements(registry.getMeasurements(), true, 'first'),
+ ).toHaveLength(1);
+ expect(
+ getActiveRuntimeNodeMeasurements(registry.getMeasurements(), true, 'first', 'first'),
+ ).toHaveLength(2);
+ expect(
+ runtimeNodeMeasurementChangeAffectsActiveIndicators({
+ activeDragNodeId: 'first',
+ isEditMode: true,
+ measurements:
+ registry.getMeasurements().get('second') ?? new Set>(),
+ nodeId: 'second',
+ selectedNodeId: 'first',
+ }),
+ ).toBe(true);
+
+ expect(
+ await measureRuntimeNodeIndicators({
+ activeDragNodeId: 'first',
+ canvasRootNodeId: 'root',
+ isEditMode: true,
+ rootRect: { x: 0, y: 0, width: 400, height: 800 },
+ runtimeNodes: registry.getMeasurements(),
+ selectedNodeId: 'first',
+ }),
+ ).toEqual([
+ expect.objectContaining({ nodeId: 'first' }),
+ expect.objectContaining({ nodeId: 'root', x: 0, y: 0, width: 400, height: 800 }),
+ expect.objectContaining({ nodeId: 'second' }),
+ ]);
+ expect(
+ getActiveRuntimeNodeMeasurements(registry.getMeasurements(), false, 'first', 'first'),
+ ).toEqual([]);
+ });
+
it('diffs selection targets and observes overlapping ownership exactly once', () => {
const shared = { id: 'shared' };
const firstOnly = { id: 'first-only' };
diff --git a/src/runtime/runtimeNodeMeasurement.ts b/src/runtime/runtimeNodeMeasurement.ts
index c9ee76ae..038c9d7c 100644
--- a/src/runtime/runtimeNodeMeasurement.ts
+++ b/src/runtime/runtimeNodeMeasurement.ts
@@ -10,7 +10,7 @@ export interface RuntimeNodeIndicatorRect extends MeasuredRect {
readonly showUnsupportedIndicator: boolean;
}
-type RuntimeNodeMeasurementSource = 'authored-root' | 'web-recorder';
+type RuntimeNodeMeasurementSource = 'authored-root' | 'runtime-recorder';
export interface RuntimeNodeMeasurement {
readonly getResizeTargets?: () => readonly TResizeTarget[];
@@ -49,13 +49,15 @@ export interface RuntimeNodeMeasurementRegistry {
export function runtimeNodeMeasurementChangeAffectsActiveIndicators(options: {
readonly isEditMode: boolean;
+ readonly activeDragNodeId?: string | null;
readonly measurements: ReadonlySet>;
readonly nodeId: string;
readonly selectedNodeId: string | null;
}): boolean {
return (
options.isEditMode &&
- (options.nodeId === options.selectedNodeId ||
+ ((options.activeDragNodeId !== null && options.activeDragNodeId !== undefined) ||
+ options.nodeId === options.selectedNodeId ||
[...options.measurements].some((measurement) => measurement.showUnsupportedIndicator))
);
}
@@ -159,6 +161,7 @@ export function getActiveRuntimeNodeMeasurements(
runtimeNodes: RuntimeNodeMeasurements,
isEditMode: boolean,
selectedNodeId: string | null,
+ activeDragNodeId: string | null = null,
): readonly RuntimeNodeMeasurement[] {
if (!isEditMode) {
return [];
@@ -166,6 +169,7 @@ export function getActiveRuntimeNodeMeasurements(
return [...runtimeNodes.entries()].flatMap(([nodeId, measurements]) => {
const needsGeometry =
+ activeDragNodeId !== null ||
nodeId === selectedNodeId ||
[...measurements].some((measurement) => measurement.showUnsupportedIndicator);
return needsGeometry ? selectPreferredRuntimeNodeMeasurements(measurements) : [];
@@ -176,23 +180,37 @@ export function hasActiveRuntimeNodeMeasurements(
runtimeNodes: RuntimeNodeMeasurements,
isEditMode: boolean,
selectedNodeId: string | null,
+ activeDragNodeId: string | null = null,
): boolean {
- return getActiveRuntimeNodeMeasurements(runtimeNodes, isEditMode, selectedNodeId).length > 0;
+ return (
+ getActiveRuntimeNodeMeasurements(runtimeNodes, isEditMode, selectedNodeId, activeDragNodeId)
+ .length > 0
+ );
}
export async function measureRuntimeNodeIndicators(options: {
readonly isEditMode: boolean;
+ readonly activeDragNodeId?: string | null;
+ readonly canvasRootNodeId?: string | null;
readonly rootRect: MeasuredRect | null;
readonly runtimeNodes: RuntimeNodeMeasurements;
readonly selectedNodeId: string | null;
}): Promise {
- const { isEditMode, rootRect, runtimeNodes, selectedNodeId } = options;
+ const {
+ activeDragNodeId = null,
+ canvasRootNodeId = null,
+ isEditMode,
+ rootRect,
+ runtimeNodes,
+ selectedNodeId,
+ } = options;
if (!isEditMode || !rootRect) {
return [];
}
const activeNodes = [...runtimeNodes.entries()].filter(
([nodeId, measurements]) =>
+ activeDragNodeId !== null ||
nodeId === selectedNodeId ||
[...measurements].some((measurement) => measurement.showUnsupportedIndicator),
);
@@ -212,22 +230,37 @@ export async function measureRuntimeNodeIndicators(options: {
}),
);
- return measured
- .flatMap(({ nodeId, rect, showUnsupportedIndicator }) =>
- rect
- ? [
- {
- nodeId,
- showUnsupportedIndicator,
- x: rect.x - rootRect.x,
- y: rect.y - rootRect.y,
- width: rect.width,
- height: rect.height,
- },
- ]
- : [],
- )
- .sort((left, right) => left.nodeId.localeCompare(right.nodeId));
+ const indicators = measured.flatMap(({ nodeId, rect, showUnsupportedIndicator }) =>
+ rect
+ ? [
+ {
+ nodeId,
+ showUnsupportedIndicator,
+ x: rect.x - rootRect.x,
+ y: rect.y - rootRect.y,
+ width: rect.width,
+ height: rect.height,
+ },
+ ]
+ : [],
+ );
+
+ if (
+ activeDragNodeId !== null &&
+ canvasRootNodeId !== null &&
+ !indicators.some((rect) => rect.nodeId === canvasRootNodeId)
+ ) {
+ indicators.push({
+ nodeId: canvasRootNodeId,
+ showUnsupportedIndicator: false,
+ x: 0,
+ y: 0,
+ width: rootRect.width,
+ height: rootRect.height,
+ });
+ }
+
+ return indicators.sort((left, right) => left.nodeId.localeCompare(right.nodeId));
}
export function createActiveResizeTargetCoordinator(
diff --git a/src/runtime/stationarySelection.test.ts b/src/runtime/stationarySelection.test.ts
index 5ec8759a..cbdcabd1 100644
--- a/src/runtime/stationarySelection.test.ts
+++ b/src/runtime/stationarySelection.test.ts
@@ -115,12 +115,24 @@ describe('stationarySelection RN integration', () => {
expect(recorderSource).not.toContain('borderColor');
});
- it('measures supported Runtime nodes for web selected-state chrome', () => {
- expect(source).toContain('ctx.registerRuntimeNode(props.nodeId');
- expect(source).toContain("if (Platform.OS === 'web' && view && ctx && props.nodeId)");
+ it('measures every Runtime node with public geometry for selection and canvas drag zones', () => {
+ expect(source).toContain('ctx.registerRuntimeNode(');
+ expect(source).toContain('props.nodeId,');
+ expect(source).toContain('if (view && ctx && props.nodeId)');
expect(source).toContain('measureRuntimeNodeWebView(view)');
+ expect(source).toContain('measureNativeRuntimeNodeView(view)');
+ expect(source).toContain("source: 'runtime-recorder'");
expect(source).toContain('measureRuntimeNodeIndicators({');
- expect(source).toContain('selectedIndicatorNodeIdRef.current');
+ expect(source).toContain('activeDragNodeId: activeDragNodeIdRef.current');
+ expect(source).toContain('canvasRootNodeId: props.canvasInteraction?.rootNode?.id');
+ });
+
+ it('mounts direct adapter-backed canvas interaction only for a valid Edit drag session', () => {
+ expect(source).toContain('StudioCanvasDndOverlay');
+ expect(source).toContain('props.isEditMode && props.canvasInteraction');
+ expect(source).toContain('resolveCanvasDragSession({');
+ expect(source).toContain('activeDragNodeId,');
+ expect(source).toContain('setActiveDragNodeId(null)');
});
it('measures roots only on web without adding them to the stationary interaction path', () => {
diff --git a/src/runtime/stationarySelection.ts b/src/runtime/stationarySelection.ts
index 9651ec3e..b66216c7 100644
--- a/src/runtime/stationarySelection.ts
+++ b/src/runtime/stationarySelection.ts
@@ -1,3 +1,4 @@
+import type { UiNode } from '@ankhorage/contracts';
import { useZoraTheme, ZORA_COMPONENT_REGISTRY } from '@ankhorage/zora';
import React from 'react';
import {
@@ -9,6 +10,9 @@ import {
} from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
+import { resolveCanvasDragSession } from '../canvasDragModel.js';
+import type { NodePlacement, StudioComponentMetaRegistry } from '../index.js';
+import { StudioCanvasDndOverlay } from '../ui/canvas/StudioCanvasDndOverlay.js';
import {
createIndicatorRefreshCoordinator,
type IndicatorRefreshCoordinator,
@@ -275,13 +279,22 @@ function StudioNodeTouchRecorder(props: {
(view: ViewRef | null) => {
unregisterMeasurementRef.current?.();
unregisterMeasurementRef.current = null;
- if (Platform.OS === 'web' && view && ctx && props.nodeId) {
- unregisterMeasurementRef.current = ctx.registerRuntimeNode(props.nodeId, {
- getResizeTargets: () => getWebDescendantResizeTargets(view),
- measure: () => measureRuntimeNodeWebView(view),
- showUnsupportedIndicator: props.showUnsupportedIndicator,
- source: 'web-recorder',
- });
+ if (view && ctx && props.nodeId) {
+ unregisterMeasurementRef.current = ctx.registerRuntimeNode(
+ props.nodeId,
+ Platform.OS === 'web'
+ ? {
+ getResizeTargets: () => getWebDescendantResizeTargets(view),
+ measure: () => measureRuntimeNodeWebView(view),
+ showUnsupportedIndicator: props.showUnsupportedIndicator,
+ source: 'runtime-recorder',
+ }
+ : {
+ measure: () => measureNativeRuntimeNodeView(view),
+ showUnsupportedIndicator: props.showUnsupportedIndicator,
+ source: 'runtime-recorder',
+ },
+ );
}
},
[ctx, props.nodeId, props.showUnsupportedIndicator],
@@ -386,10 +399,19 @@ export function createStudioStationarySelectionWrapNode(options?: {
};
}
+export interface StudioCanvasInteractionAdapter {
+ readonly activeDragNodeId: string | null;
+ readonly componentMeta: StudioComponentMetaRegistry;
+ readonly moveNodeToPlacement: (nodeId: string, placement: NodePlacement) => boolean;
+ readonly rootNode: UiNode | null;
+ readonly setActiveDragNodeId: (nodeId: string | null) => void;
+}
+
function StationaryTapSelector(props: {
readonly isEditMode: boolean;
readonly selectedNodeId: string | null;
readonly selectNode: (id: string | null) => void;
+ readonly canvasInteraction?: StudioCanvasInteractionAdapter;
readonly children: React.ReactNode;
}): React.JSX.Element {
const { theme } = useZoraTheme();
@@ -410,7 +432,8 @@ function StationaryTapSelector(props: {
const isEditModeRef = React.useRef(props.isEditMode);
const selectedNodeIdRef = React.useRef(props.selectedNodeId);
- const selectedIndicatorNodeIdRef = React.useRef(null);
+ const measurementSelectedNodeIdRef = React.useRef(null);
+ const activeDragNodeIdRef = React.useRef(null);
const selectNodeRef = React.useRef(props.selectNode);
const selectionCommitCountRef = React.useRef(0);
const generationRef = React.useRef(0);
@@ -431,7 +454,17 @@ function StationaryTapSelector(props: {
props.selectedNodeId,
);
const selectedIndicatorNodeId = shouldRenderSelectedChrome ? props.selectedNodeId : null;
- selectedIndicatorNodeIdRef.current = selectedIndicatorNodeId;
+ const measurementSelectedNodeId = props.isEditMode ? props.selectedNodeId : null;
+ const requestedActiveDragNodeId = props.canvasInteraction?.activeDragNodeId ?? null;
+ const canvasDragSession = resolveCanvasDragSession({
+ activeDragNodeId: requestedActiveDragNodeId,
+ isEditMode: props.isEditMode,
+ rootNode: props.canvasInteraction?.rootNode ?? null,
+ selectedNodeId: props.selectedNodeId,
+ });
+ const { activeDragNodeId } = canvasDragSession;
+ measurementSelectedNodeIdRef.current = measurementSelectedNodeId;
+ activeDragNodeIdRef.current = activeDragNodeId;
selectNodeRef.current = props.selectNode;
inputStateRef.current ??= createStationarySelectionInputState({
@@ -462,7 +495,8 @@ function StationaryTapSelector(props: {
!hasActiveRuntimeNodeMeasurements(
runtimeNodesRef.current,
isEditModeRef.current,
- selectedIndicatorNodeIdRef.current,
+ measurementSelectedNodeIdRef.current,
+ activeDragNodeIdRef.current,
)
) {
return;
@@ -492,7 +526,8 @@ function StationaryTapSelector(props: {
const activeMeasurements = getActiveRuntimeNodeMeasurements(
runtimeNodesRef.current,
isEditModeRef.current,
- selectedIndicatorNodeIdRef.current,
+ measurementSelectedNodeIdRef.current,
+ activeDragNodeIdRef.current,
);
const rootTarget = getWebResizeTarget(rootViewRef.current);
resizeTargetCoordinatorRef.current?.sync(
@@ -510,7 +545,8 @@ function StationaryTapSelector(props: {
isEditMode: isEditModeRef.current,
measurements,
nodeId,
- selectedNodeId: selectedIndicatorNodeIdRef.current,
+ selectedNodeId: measurementSelectedNodeIdRef.current,
+ activeDragNodeId: activeDragNodeIdRef.current,
});
if (nodeIsActive) {
syncActiveResizeTargets();
@@ -526,7 +562,8 @@ function StationaryTapSelector(props: {
isEditMode: isEditModeRef.current,
measurements: registeredMeasurements,
nodeId,
- selectedNodeId: selectedIndicatorNodeIdRef.current,
+ selectedNodeId: measurementSelectedNodeIdRef.current,
+ activeDragNodeId: activeDragNodeIdRef.current,
});
if (!registeredMeasurements.delete(measurement)) {
return;
@@ -540,7 +577,8 @@ function StationaryTapSelector(props: {
!hasActiveRuntimeNodeMeasurements(
runtimeNodesRef.current,
isEditModeRef.current,
- selectedIndicatorNodeIdRef.current,
+ measurementSelectedNodeIdRef.current,
+ activeDragNodeIdRef.current,
)
) {
settleCoordinatorRef.current?.cancel();
@@ -573,7 +611,8 @@ function StationaryTapSelector(props: {
!hasActiveRuntimeNodeMeasurements(
runtimeNodesRef.current,
isEditModeRef.current,
- selectedIndicatorNodeIdRef.current,
+ measurementSelectedNodeIdRef.current,
+ activeDragNodeIdRef.current,
)
) {
latestIndicatorRectsRef.current = [];
@@ -588,9 +627,11 @@ function StationaryTapSelector(props: {
const nextRects = await measureRuntimeNodeIndicators({
isEditMode: isEditModeRef.current,
+ activeDragNodeId: activeDragNodeIdRef.current,
+ canvasRootNodeId: props.canvasInteraction?.rootNode?.id,
rootRect,
runtimeNodes: runtimeNodesRef.current,
- selectedNodeId: selectedIndicatorNodeIdRef.current,
+ selectedNodeId: measurementSelectedNodeIdRef.current,
});
if (!mountedRef.current || geometryRevision !== geometryRevisionRef.current) {
@@ -602,7 +643,7 @@ function StationaryTapSelector(props: {
areIndicatorRectsEqual(current, nextRects) ? current : nextRects,
);
return nextRects;
- }, []);
+ }, [props.canvasInteraction?.rootNode?.id]);
refreshIndicatorRectsRef.current = refreshIndicatorRects;
React.useEffect(() => {
@@ -610,14 +651,31 @@ function StationaryTapSelector(props: {
!hasActiveRuntimeNodeMeasurements(
runtimeNodesRef.current,
props.isEditMode,
- selectedIndicatorNodeId,
+ measurementSelectedNodeId,
+ activeDragNodeId,
)
) {
settleCoordinatorRef.current?.cancel();
}
syncActiveResizeTargets();
requestIndicatorRefresh();
- }, [props.isEditMode, selectedIndicatorNodeId, requestIndicatorRefresh, syncActiveResizeTargets]);
+ }, [
+ activeDragNodeId,
+ measurementSelectedNodeId,
+ props.isEditMode,
+ requestIndicatorRefresh,
+ syncActiveResizeTargets,
+ ]);
+
+ React.useEffect(() => {
+ if (canvasDragSession.shouldReset) {
+ props.canvasInteraction?.setActiveDragNodeId(null);
+ }
+ }, [
+ canvasDragSession.shouldReset,
+ props.canvasInteraction?.setActiveDragNodeId,
+ requestedActiveDragNodeId,
+ ]);
React.useEffect(() => {
mountedRef.current = true;
@@ -729,6 +787,18 @@ function StationaryTapSelector(props: {
style: { flex: 1, position: 'relative' },
},
props.children,
+ props.isEditMode && props.canvasInteraction
+ ? React.createElement(StudioCanvasDndOverlay, {
+ key: 'studio-canvas-dnd-overlay',
+ activeDragNodeId,
+ componentMeta: props.canvasInteraction.componentMeta,
+ indicatorRects,
+ moveNodeToPlacement: props.canvasInteraction.moveNodeToPlacement,
+ rootNode: props.canvasInteraction.rootNode,
+ selectedNodeId: props.selectedNodeId,
+ setActiveDragNodeId: props.canvasInteraction.setActiveDragNodeId,
+ })
+ : null,
...(props.isEditMode
? indicatorRects.filter((rect) => rect.showUnsupportedIndicator)
: []
diff --git a/src/ui/StudioDeleteDialog.tsx b/src/ui/StudioDeleteDialog.tsx
new file mode 100644
index 00000000..423d386b
--- /dev/null
+++ b/src/ui/StudioDeleteDialog.tsx
@@ -0,0 +1,24 @@
+import { ConfirmDialog } from '@ankhorage/zora';
+import React from 'react';
+
+export interface StudioDeleteDialogProps {
+ readonly label: string;
+ readonly onCancel: () => void;
+ readonly onConfirm: () => void;
+ readonly visible: boolean;
+}
+
+export function StudioDeleteDialog(props: StudioDeleteDialogProps): React.JSX.Element {
+ return (
+
+ );
+}
diff --git a/src/ui/StudioInsertDialog.tsx b/src/ui/StudioInsertDialog.tsx
new file mode 100644
index 00000000..763a96c6
--- /dev/null
+++ b/src/ui/StudioInsertDialog.tsx
@@ -0,0 +1,95 @@
+import { Button, Input, ListRow, ListSection, Modal, Stack } from '@ankhorage/zora';
+import type { UiNode } from '@ankhorage/contracts';
+import React from 'react';
+import { ScrollView } from 'react-native';
+
+import type { InsertCatalogEntry, StudioComponentMetaRegistry } from '../index';
+import { getInsertCatalogCategoryLabel } from '../index';
+import {
+ filterInsertCatalogEntries,
+ getPlacementHint,
+ groupInsertEntries,
+} from '../insertModalModel';
+
+export interface StudioInsertDialogProps {
+ readonly componentMeta: StudioComponentMetaRegistry;
+ readonly entries: InsertCatalogEntry[];
+ readonly findNode: (id: string) => UiNode | null;
+ readonly onDismiss: () => void;
+ readonly onInsert: (entry: InsertCatalogEntry) => boolean;
+ readonly rootNode: UiNode | null;
+ readonly visible: boolean;
+}
+
+export function StudioInsertDialog(props: StudioInsertDialogProps): React.JSX.Element {
+ const [query, setQuery] = React.useState('');
+
+ React.useEffect(() => {
+ if (!props.visible) setQuery('');
+ }, [props.visible]);
+
+ const groups = groupInsertEntries({
+ entries: filterInsertCatalogEntries(props.entries, query),
+ getCategoryLabel: getInsertCatalogCategoryLabel,
+ });
+
+ return (
+
+ Cancel
+
+ }
+ onDismiss={props.onDismiss}
+ title="Insert"
+ visible={props.visible}
+ width="wide"
+ >
+
+
+
+
+ {groups.map((group) => (
+
+ {group.entries.map((entry) => {
+ const placementHint = getPlacementHint({
+ entry,
+ rootNode: props.rootNode,
+ findNode: (root, id) => props.findNode(id) ?? (root.id === id ? root : null),
+ componentMeta: props.componentMeta,
+ });
+ const description =
+ entry.status === 'disabled' ? entry.disabledReason?.detail : entry.description;
+
+ return entry.status === 'enabled' ? (
+ props.onInsert(entry)}
+ title={entry.label}
+ />
+ ) : (
+
+ );
+ })}
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/src/ui/canvas/StudioCanvasDndOverlay.test.ts b/src/ui/canvas/StudioCanvasDndOverlay.test.ts
new file mode 100644
index 00000000..ebe1290e
--- /dev/null
+++ b/src/ui/canvas/StudioCanvasDndOverlay.test.ts
@@ -0,0 +1,33 @@
+import { readFileSync } from 'node:fs';
+import { join } from 'node:path';
+
+import { describe, expect, test } from 'bun:test';
+
+const source = readFileSync(join(import.meta.dir, 'StudioCanvasDndOverlay.tsx'), 'utf8');
+
+describe('Studio canvas DnD adapter integration', () => {
+ test('imports and composes the cross-platform adapter directly', () => {
+ expect(source).toContain("from '@ankhorage/react-native-reanimated-dnd-web'");
+ expect(source).not.toContain("from 'react-native-reanimated-dnd'");
+ expect(source).toContain('');
+ expect(source).toContain('');
+ expect(source).toContain(' {
+ expect(source).toContain('resolveCanvasDropZoneRect({');
+ expect(source).toContain('left: selectedRect.x + selectedRect.width - 24');
+ expect(source).toContain('width: 48');
+ expect(source).toContain(' {
+ expect(source).toContain('props.zone.resolution.reason.message');
+ expect(source).toContain('completeCanvasDropAfterAdapter(');
+ expect(source).toContain(
+ 'key={createCanvasDraggableSessionKey(selectedNode.id, dragSessionRevision)}',
+ );
+ });
+});
diff --git a/src/ui/canvas/StudioCanvasDndOverlay.tsx b/src/ui/canvas/StudioCanvasDndOverlay.tsx
new file mode 100644
index 00000000..7b2acdf3
--- /dev/null
+++ b/src/ui/canvas/StudioCanvasDndOverlay.tsx
@@ -0,0 +1,271 @@
+import type { UiNode } from '@ankhorage/contracts';
+import {
+ Draggable,
+ DraggableState,
+ Droppable,
+ DropProvider,
+} from '@ankhorage/react-native-reanimated-dnd-web';
+import { IconButton, Text, useZoraTheme } from '@ankhorage/zora';
+import React from 'react';
+import { View } from 'react-native';
+
+import {
+ createStudioCanvasDragPayload,
+ resolveCanvasDragPreviewText,
+ resolveCanvasDropZoneRect,
+} from '../../canvasDragModel';
+import { resolveCanvasDropZones, type CanvasDropZoneResolution } from '../../canvasDropZones';
+import { findNodeById, type NodePlacement, type StudioComponentMetaRegistry } from '../../index';
+import { resolveNodeLabel } from '../../insertModalModel';
+import type { RuntimeNodeIndicatorRect } from '../../runtime/runtimeNodeMeasurement';
+import {
+ activateCanvasDrag,
+ completeCanvasDropAfterAdapter,
+ createCanvasDraggableSessionKey,
+ resetCanvasDragSession,
+ sortCanvasDropTargetsBySpecificity,
+} from './canvasDndInteraction';
+
+export interface StudioCanvasDndOverlayProps {
+ readonly activeDragNodeId: string | null;
+ readonly componentMeta: StudioComponentMetaRegistry;
+ readonly indicatorRects: readonly RuntimeNodeIndicatorRect[];
+ readonly moveNodeToPlacement: (nodeId: string, placement: NodePlacement) => boolean;
+ readonly rootNode: UiNode | null;
+ readonly selectedNodeId: string | null;
+ readonly setActiveDragNodeId: (nodeId: string | null) => void;
+}
+
+interface CanvasDropZoneView {
+ readonly id: string;
+ readonly resolution: CanvasDropZoneResolution;
+ readonly rect: ReturnType;
+ readonly targetNode: UiNode;
+}
+
+interface CanvasDropZoneProps {
+ readonly activeDropZoneId: string | null;
+ readonly componentMeta: StudioComponentMetaRegistry;
+ readonly moveNodeToPlacement: StudioCanvasDndOverlayProps['moveNodeToPlacement'];
+ readonly resetDrag: () => void;
+ readonly setActiveDropZoneId: React.Dispatch>;
+ readonly zone: CanvasDropZoneView;
+}
+
+const MAX_DROP_CAPACITY = Number.MAX_SAFE_INTEGER;
+
+function resolveDropZoneViews(args: {
+ readonly componentMeta: StudioComponentMetaRegistry;
+ readonly draggedNode: UiNode;
+ readonly draggedRect: RuntimeNodeIndicatorRect;
+ readonly indicatorRects: readonly RuntimeNodeIndicatorRect[];
+ readonly rootNode: UiNode;
+}): readonly CanvasDropZoneView[] {
+ const zones = args.indicatorRects.flatMap((targetRect): CanvasDropZoneView[] => {
+ const targetNode = findNodeById(args.rootNode, targetRect.nodeId);
+ if (!targetNode) return [];
+
+ return resolveCanvasDropZones({
+ root: args.rootNode,
+ targetNodeId: targetNode.id,
+ draggedNode: args.draggedNode,
+ componentMeta: args.componentMeta,
+ }).map((resolution) => ({
+ id: `${targetNode.id}:${resolution.kind}`,
+ resolution,
+ targetNode,
+ rect: resolveCanvasDropZoneRect({
+ kind: resolution.kind,
+ targetRect,
+ draggedRect: args.draggedRect,
+ }),
+ }));
+ });
+ return sortCanvasDropTargetsBySpecificity(zones);
+}
+
+function CanvasDropZone(props: CanvasDropZoneProps): React.JSX.Element {
+ const { theme } = useZoraTheme();
+ const isActive = props.activeDropZoneId === props.zone.id;
+ const isValid = props.zone.resolution.status === 'valid';
+ const borderColor = isValid ? theme.semantics.action.primary.base : '#dc2626';
+
+ return (
+
+ props.setActiveDropZoneId((current) =>
+ active ? props.zone.id : current === props.zone.id ? null : current,
+ )
+ }
+ onDrop={(payload: unknown) => {
+ void completeCanvasDropAfterAdapter(
+ payload,
+ props.zone.resolution,
+ props.moveNodeToPlacement,
+ props.resetDrag,
+ );
+ }}
+ style={{
+ position: 'absolute',
+ left: props.zone.rect.x,
+ top: props.zone.rect.y,
+ width: props.zone.rect.width,
+ height: props.zone.rect.height,
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderWidth: isActive ? 3 : 1,
+ borderColor,
+ borderStyle: isValid ? 'solid' : 'dashed',
+ borderRadius: 4,
+ opacity: isActive ? 0.92 : 0.28,
+ zIndex: 1001,
+ }}
+ >
+ {isActive ? (
+
+ {isValid
+ ? `${props.zone.resolution.kind} ${resolveNodeLabel({ node: props.zone.targetNode, componentMeta: props.componentMeta })}`
+ : props.zone.resolution.reason.message}
+
+ ) : null}
+
+ );
+}
+
+function CanvasDragPreview(props: {
+ readonly active: boolean;
+ readonly label: string;
+ readonly node: UiNode;
+ readonly rect: RuntimeNodeIndicatorRect;
+}): React.JSX.Element {
+ const { theme } = useZoraTheme();
+ const previewText = resolveCanvasDragPreviewText(props.node.props);
+
+ return (
+
+
+ {props.label}
+
+ {previewText ? (
+
+ {previewText}
+
+ ) : null}
+
+ );
+}
+
+export function StudioCanvasDndOverlay(
+ props: StudioCanvasDndOverlayProps,
+): React.JSX.Element | null {
+ const [activeDropZoneId, setActiveDropZoneId] = React.useState(null);
+ const [dragSessionRevision, setDragSessionRevision] = React.useState(0);
+ const dragStartedRef = React.useRef(false);
+ const rootNode = props.rootNode;
+ const selectedNode =
+ rootNode && props.selectedNodeId ? findNodeById(rootNode, props.selectedNodeId) : null;
+ const selectedRect = props.indicatorRects.find((rect) => rect.nodeId === props.selectedNodeId);
+ const draggedNode =
+ rootNode && props.activeDragNodeId ? findNodeById(rootNode, props.activeDragNodeId) : null;
+ const draggedRect = props.indicatorRects.find((rect) => rect.nodeId === props.activeDragNodeId);
+
+ React.useEffect(() => {
+ if (!props.activeDragNodeId) setActiveDropZoneId(null);
+ }, [props.activeDragNodeId]);
+
+ if (!rootNode || !selectedNode || !selectedRect || selectedNode.id === rootNode.id) return null;
+
+ const payload = createStudioCanvasDragPayload(selectedNode.id);
+ const previewLabel = resolveNodeLabel({ node: selectedNode, componentMeta: props.componentMeta });
+ const dropZones =
+ draggedNode && draggedRect
+ ? resolveDropZoneViews({
+ componentMeta: props.componentMeta,
+ draggedNode,
+ draggedRect,
+ indicatorRects: props.indicatorRects,
+ rootNode,
+ })
+ : [];
+ const resetDrag = (): void => {
+ dragStartedRef.current = false;
+ resetCanvasDragSession({
+ restartDraggable: () => setDragSessionRevision((revision) => revision + 1),
+ setActiveDropZoneId,
+ setActiveDragNodeId: props.setActiveDragNodeId,
+ });
+ };
+
+ return (
+
+ activateCanvasDrag(payload, props)}
+ onStateChange={(state) => {
+ if (state === DraggableState.DRAGGING) dragStartedRef.current = true;
+ if (dragStartedRef.current && state === DraggableState.IDLE) resetDrag();
+ }}
+ style={{
+ position: 'absolute',
+ left: selectedRect.x + selectedRect.width - 24,
+ top: selectedRect.y - 24,
+ width: 48,
+ height: 48,
+ zIndex: 1002,
+ }}
+ >
+
+
+
+
+
+
+ {dropZones.map((zone) => (
+
+ ))}
+
+ );
+}
diff --git a/src/ui/canvas/canvasDndInteraction.test.ts b/src/ui/canvas/canvasDndInteraction.test.ts
new file mode 100644
index 00000000..de583f0b
--- /dev/null
+++ b/src/ui/canvas/canvasDndInteraction.test.ts
@@ -0,0 +1,155 @@
+import { describe, expect, test } from 'bun:test';
+
+import type { CanvasDropZoneResolution } from '../../canvasDropZones';
+import {
+ activateCanvasDrag,
+ commitCanvasDrop,
+ completeCanvasDropAfterAdapter,
+ createCanvasDraggableSessionKey,
+ resetCanvasDragSession,
+ sortCanvasDropTargetsBySpecificity,
+} from './canvasDndInteraction';
+
+const VALID_ZONE: CanvasDropZoneResolution = {
+ kind: 'inside',
+ status: 'valid',
+ placement: { parentId: 'root', index: 0, kind: 'inside' },
+};
+
+const INVALID_ZONE: CanvasDropZoneResolution = {
+ kind: 'inside',
+ status: 'invalid',
+ reason: { code: 'cannot-move-into-self', message: 'Cannot move into itself.' },
+};
+
+describe('canvas DnD interaction', () => {
+ test('commits a valid drop exactly once', () => {
+ const calls: unknown[][] = [];
+ const committed = commitCanvasDrop(
+ { kind: 'studio-canvas-node', nodeId: 'text' },
+ VALID_ZONE,
+ (...args) => {
+ calls.push(args);
+ return true;
+ },
+ );
+
+ expect(committed).toBe(true);
+ expect(calls).toEqual([['text', VALID_ZONE.placement]]);
+ });
+
+ test('never commits invalid zones or foreign payloads', () => {
+ let commitCount = 0;
+ const moveNode = () => {
+ commitCount += 1;
+ return true;
+ };
+
+ expect(
+ commitCanvasDrop({ kind: 'studio-canvas-node', nodeId: 'text' }, INVALID_ZONE, moveNode),
+ ).toBe(false);
+ expect(commitCanvasDrop({ kind: 'external', nodeId: 'text' }, VALID_ZONE, moveNode)).toBe(
+ false,
+ );
+ expect(commitCount).toBe(0);
+ });
+
+ test('activates the payload node and clears all transient state on reset', () => {
+ const activeNodeIds: (string | null)[] = [];
+ const activeZoneIds: (string | null)[] = ['target:inside'];
+ let revision = 0;
+ const callbacks = {
+ restartDraggable: () => {
+ revision += 1;
+ },
+ setActiveDragNodeId: (nodeId: string | null) => {
+ activeNodeIds.push(nodeId);
+ },
+ setActiveDropZoneId: (zoneId: string | null) => {
+ activeZoneIds.push(zoneId);
+ },
+ };
+
+ activateCanvasDrag({ kind: 'studio-canvas-node', nodeId: 'text' }, callbacks);
+ expect(activeNodeIds).toEqual(['text']);
+
+ resetCanvasDragSession(callbacks);
+ expect(activeNodeIds).toEqual(['text', null]);
+ expect(activeZoneIds).toEqual(['target:inside', null]);
+ expect(revision).toBe(1);
+ });
+
+ test('remounts a neutral draggable session after a successful adapter drop', async () => {
+ const activeNodeIds: (string | null)[] = [];
+ const activeZoneIds: (string | null)[] = [];
+ const moveCalls: unknown[][] = [];
+ let revision = 0;
+ const callbacks = {
+ restartDraggable: () => {
+ revision += 1;
+ },
+ setActiveDragNodeId: (nodeId: string | null) => activeNodeIds.push(nodeId),
+ setActiveDropZoneId: (zoneId: string | null) => activeZoneIds.push(zoneId),
+ };
+ const initialKey = createCanvasDraggableSessionKey('text', revision);
+
+ const completion = completeCanvasDropAfterAdapter(
+ { kind: 'studio-canvas-node', nodeId: 'text' },
+ VALID_ZONE,
+ (...args) => {
+ moveCalls.push(args);
+ return true;
+ },
+ () => resetCanvasDragSession(callbacks),
+ );
+
+ expect(moveCalls).toEqual([]);
+ expect(revision).toBe(0);
+ expect(await completion).toBe(true);
+ expect(moveCalls).toEqual([['text', VALID_ZONE.placement]]);
+ expect(activeNodeIds).toEqual([null]);
+ expect(activeZoneIds).toEqual([null]);
+ expect(createCanvasDraggableSessionKey('text', revision)).not.toBe(initialKey);
+ });
+
+ test('remounts away adapter translation after an invalid droppable hit', async () => {
+ let moveCount = 0;
+ let revision = 0;
+ const initialKey = createCanvasDraggableSessionKey('text', revision);
+
+ const committed = await completeCanvasDropAfterAdapter(
+ { kind: 'studio-canvas-node', nodeId: 'text' },
+ INVALID_ZONE,
+ () => {
+ moveCount += 1;
+ return true;
+ },
+ () =>
+ resetCanvasDragSession({
+ restartDraggable: () => {
+ revision += 1;
+ },
+ setActiveDragNodeId: () => undefined,
+ setActiveDropZoneId: () => undefined,
+ }),
+ );
+
+ expect(committed).toBe(false);
+ expect(moveCount).toBe(0);
+ expect(createCanvasDraggableSessionKey('text', revision)).not.toBe(initialKey);
+ });
+
+ test('uses selected node identity as part of the adapter session key', () => {
+ expect(createCanvasDraggableSessionKey('node-a', 3)).not.toBe(
+ createCanvasDraggableSessionKey('node-b', 3),
+ );
+ });
+
+ test('orders nested measured targets before broad ancestor targets', () => {
+ const root = { id: 'root', rect: { width: 400, height: 800 } };
+ const child = { id: 'child', rect: { width: 200, height: 80 } };
+ const edge = { id: 'child:before', rect: { width: 200, height: 24 } };
+
+ expect(sortCanvasDropTargetsBySpecificity([root, child, edge])).toEqual([edge, child, root]);
+ });
+});
diff --git a/src/ui/canvas/canvasDndInteraction.ts b/src/ui/canvas/canvasDndInteraction.ts
new file mode 100644
index 00000000..6647915c
--- /dev/null
+++ b/src/ui/canvas/canvasDndInteraction.ts
@@ -0,0 +1,61 @@
+import { isStudioCanvasDragPayload, type StudioCanvasDragPayload } from '../../canvasDragModel';
+import type { CanvasDropZoneResolution } from '../../canvasDropZones';
+import type { NodePlacement } from '../../index';
+
+export interface CanvasDragSessionCallbacks {
+ readonly restartDraggable: () => void;
+ readonly setActiveDragNodeId: (nodeId: string | null) => void;
+ readonly setActiveDropZoneId: (zoneId: string | null) => void;
+}
+
+export function createCanvasDraggableSessionKey(nodeId: string, revision: number): string {
+ return `${nodeId}:${revision}`;
+}
+
+export function sortCanvasDropTargetsBySpecificity<
+ T extends { readonly rect: { readonly width: number; readonly height: number } },
+>(targets: readonly T[]): readonly T[] {
+ return [...targets].sort(
+ (left, right) => left.rect.width * left.rect.height - right.rect.width * right.rect.height,
+ );
+}
+
+export function resetCanvasDragSession(callbacks: CanvasDragSessionCallbacks): void {
+ callbacks.setActiveDropZoneId(null);
+ callbacks.setActiveDragNodeId(null);
+ callbacks.restartDraggable();
+}
+
+export function commitCanvasDrop(
+ payload: unknown,
+ zone: CanvasDropZoneResolution,
+ moveNodeToPlacement: (nodeId: string, placement: NodePlacement) => boolean,
+): boolean {
+ if (zone.status !== 'valid' || !isStudioCanvasDragPayload(payload)) {
+ return false;
+ }
+
+ return moveNodeToPlacement(payload.nodeId, zone.placement);
+}
+
+export function completeCanvasDropAfterAdapter(
+ payload: unknown,
+ zone: CanvasDropZoneResolution,
+ moveNodeToPlacement: (nodeId: string, placement: NodePlacement) => boolean,
+ resetDrag: () => void,
+): Promise {
+ return Promise.resolve().then(() => {
+ try {
+ return commitCanvasDrop(payload, zone, moveNodeToPlacement);
+ } finally {
+ resetDrag();
+ }
+ });
+}
+
+export function activateCanvasDrag(
+ payload: StudioCanvasDragPayload,
+ callbacks: Pick,
+): void {
+ callbacks.setActiveDragNodeId(payload.nodeId);
+}
diff --git a/src/ui/studioAppBarModel.ts b/src/ui/studioAppBarModel.ts
index 530d8650..5c64c537 100644
--- a/src/ui/studioAppBarModel.ts
+++ b/src/ui/studioAppBarModel.ts
@@ -1,11 +1,14 @@
export interface StudioAppBarContextAction {
- readonly id: 'properties' | 'bindings' | 'selectParent' | 'clearSelection';
+ readonly id: 'properties' | 'bindings' | 'insert' | 'delete' | 'selectParent' | 'clearSelection';
readonly label: string;
}
export interface ResolveStudioAppBarContextActionsArgs {
readonly selectedNodeId: string | null;
readonly parentNodeId: string | null;
+ readonly canInsert: boolean;
+ readonly canInsertInside: boolean;
+ readonly canDelete: boolean;
}
export function resolveStudioAppBarContextActions(
@@ -20,6 +23,14 @@ export function resolveStudioAppBarContextActions(
{ id: 'bindings', label: 'Bindings' },
];
+ if (args.canInsert) {
+ actions.push({ id: 'insert', label: args.canInsertInside ? 'Add child' : 'Insert' });
+ }
+
+ if (args.canDelete) {
+ actions.push({ id: 'delete', label: 'Delete' });
+ }
+
if (args.parentNodeId) {
actions.push({ id: 'selectParent', label: 'Select parent' });
}
diff --git a/src/ui/useStudioAppBarAugmentation.test.ts b/src/ui/useStudioAppBarAugmentation.test.ts
index dead129e..d6328cc2 100644
--- a/src/ui/useStudioAppBarAugmentation.test.ts
+++ b/src/ui/useStudioAppBarAugmentation.test.ts
@@ -19,7 +19,6 @@ test('uses the URL as the admin route source of truth', () => {
expect(source).toContain('studio.setLastNonAdminLocation(appLocation)');
expect(source).toContain('Administration');
expect(source).toContain('isStudioAdminPath(pathname)');
- expect(source).not.toContain('useState<');
expect(source).not.toContain('setActiveRoute');
});
@@ -32,7 +31,9 @@ test('returns keyed AppBar actions as flat direct children in intentional order'
expect(source).toContain("key: 'administration'");
expect(source).toContain('...contextActions.map((action) =>');
expect(source).toContain('key: action.id');
- expect(source).not.toContain('React.Fragment');
+ expect(source).toContain('overlays: isStudioAdminPath(pathname)');
+ expect(source).toContain('StudioInsertDialog');
+ expect(source).toContain('StudioDeleteDialog');
expect(source.indexOf("key: 'administration'")).toBeLessThan(
source.indexOf('...contextActions.map((action) =>'),
);
@@ -42,11 +43,16 @@ test('resolves contextual app bar actions for selected nodes', () => {
const actions = resolveStudioAppBarContextActions({
selectedNodeId: 'child',
parentNodeId: 'root',
+ canInsert: true,
+ canInsertInside: true,
+ canDelete: true,
});
expect(actions).toEqual([
{ id: 'properties', label: 'Properties' },
{ id: 'bindings', label: 'Bindings' },
+ { id: 'insert', label: 'Add child' },
+ { id: 'delete', label: 'Delete' },
{ id: 'selectParent', label: 'Select parent' },
{ id: 'clearSelection', label: 'Clear selection' },
]);
@@ -56,11 +62,15 @@ test('omits parent selection when no parent is available', () => {
const actions = resolveStudioAppBarContextActions({
selectedNodeId: 'root',
parentNodeId: null,
+ canInsert: true,
+ canInsertInside: true,
+ canDelete: false,
});
expect(actions).toEqual([
{ id: 'properties', label: 'Properties' },
{ id: 'bindings', label: 'Bindings' },
+ { id: 'insert', label: 'Add child' },
{ id: 'clearSelection', label: 'Clear selection' },
]);
});
@@ -69,7 +79,30 @@ test('returns no contextual app bar actions when no valid selection exists', ()
const actions = resolveStudioAppBarContextActions({
selectedNodeId: null,
parentNodeId: null,
+ canInsert: false,
+ canInsertInside: false,
+ canDelete: false,
});
expect(actions).toEqual([]);
});
+
+test('uses generic Insert wording for sibling-only placement and omits unavailable actions', () => {
+ const actions = resolveStudioAppBarContextActions({
+ selectedNodeId: 'leaf',
+ parentNodeId: 'root',
+ canInsert: true,
+ canInsertInside: false,
+ canDelete: false,
+ });
+
+ expect(actions.map((action) => action.id)).toEqual([
+ 'properties',
+ 'bindings',
+ 'insert',
+ 'selectParent',
+ 'clearSelection',
+ ]);
+ expect(actions.find((action) => action.id === 'insert')?.label).toBe('Insert');
+ expect(actions.find((action) => action.id === 'delete')).toBeUndefined();
+});
diff --git a/src/ui/useStudioAppBarAugmentation.ts b/src/ui/useStudioAppBarAugmentation.ts
index f141ac04..8a0ed926 100644
--- a/src/ui/useStudioAppBarAugmentation.ts
+++ b/src/ui/useStudioAppBarAugmentation.ts
@@ -3,6 +3,13 @@ import { usePathname, useRouter } from 'expo-router';
import React, { useCallback } from 'react';
import { useStudio } from '../core/StudioContext';
+import {
+ buildInsertCatalogEntries,
+ findNodeById,
+ resolveInsertCatalogEntries,
+ type StudioNodeId,
+} from '../index';
+import { resolveNodeLabel } from '../insertModalModel';
import {
createStudioBindingsRoutePath,
createStudioPropertiesRoutePath,
@@ -12,17 +19,31 @@ import {
} from '../studioAdminRouteModel';
import { createStudioSelectionContext } from '../studioSelectionModel';
import { resolveStudioAppBarContextActions } from './studioAppBarModel';
+import { StudioDeleteDialog } from './StudioDeleteDialog';
+import { StudioInsertDialog } from './StudioInsertDialog';
export interface StudioAppBarAugmentation {
appMode?: unknown;
actions?: React.ReactNode;
overflow?: unknown;
+ overlays?: React.ReactNode;
+}
+
+function resolveContextActionIcon(id: string): { name: string } {
+ if (id === 'properties') return { name: 'options-outline' };
+ if (id === 'bindings') return { name: 'git-branch-outline' };
+ if (id === 'insert') return { name: 'add-outline' };
+ if (id === 'delete') return { name: 'trash-outline' };
+ if (id === 'selectParent') return { name: 'arrow-up-outline' };
+ return { name: 'close-outline' };
}
export function useStudioAppBarAugmentation(): StudioAppBarAugmentation {
const studio = useStudio();
const pathname = usePathname();
const router = useRouter();
+ const [insertVisible, setInsertVisible] = React.useState(false);
+ const [deleteCandidateId, setDeleteCandidateId] = React.useState(null);
const openAdministration = useCallback(() => {
const appLocation = resolveStudioLastNonAdminLocation({
@@ -60,11 +81,64 @@ export function useStudioAppBarAugmentation(): StudioAppBarAugmentation {
studio.selectNode(selection.parentNodeId);
}, [selection.parentNodeId, studio]);
+ const catalogEntries = React.useMemo(
+ () => buildInsertCatalogEntries({ componentMeta: studio.componentMeta }),
+ [studio.componentMeta],
+ );
+ const resolvedInsertEntries = React.useMemo(
+ () =>
+ resolveInsertCatalogEntries({
+ entries: catalogEntries,
+ root: studio.rootNode,
+ selectedNodeId: selection.selectedNodeId,
+ componentMeta: studio.componentMeta,
+ }),
+ [catalogEntries, selection.selectedNodeId, studio.componentMeta, studio.rootNode],
+ );
+ const enabledEntries = resolvedInsertEntries.filter((entry) => entry.status === 'enabled');
+ const canInsert = enabledEntries.length > 0;
+ const canInsertInside = enabledEntries.some(
+ (entry) =>
+ entry.placement?.kind === 'inside' && entry.placement.parentId === selection.selectedNodeId,
+ );
+ const canDelete = selection.selectedNodeId !== null && selection.parentNodeId !== null;
+
+ const selectedNode =
+ studio.rootNode && selection.selectedNodeId
+ ? findNodeById(studio.rootNode, selection.selectedNodeId)
+ : null;
+ const deleteCandidate =
+ studio.rootNode && deleteCandidateId ? findNodeById(studio.rootNode, deleteCandidateId) : null;
+
const contextActions = resolveStudioAppBarContextActions({
selectedNodeId: selection.selectedNodeId,
parentNodeId: selection.parentNodeId,
+ canInsert,
+ canInsertInside,
+ canDelete,
});
+ const openInsert = useCallback(() => setInsertVisible(true), []);
+ const openDelete = useCallback(() => {
+ if (selection.selectedNodeId) setDeleteCandidateId(selection.selectedNodeId);
+ }, [selection.selectedNodeId]);
+ const confirmDelete = useCallback(() => {
+ if (deleteCandidateId) studio.deleteNode(deleteCandidateId);
+ setDeleteCandidateId(null);
+ }, [deleteCandidateId, studio]);
+
+ const getActionHandler = useCallback(
+ (id: (typeof contextActions)[number]['id']) => {
+ if (id === 'properties') return openProperties;
+ if (id === 'bindings') return openBindings;
+ if (id === 'insert') return openInsert;
+ if (id === 'delete') return openDelete;
+ if (id === 'selectParent') return selectParent;
+ return clearSelection;
+ },
+ [clearSelection, openBindings, openDelete, openInsert, openProperties, selectParent],
+ );
+
const actions = isStudioAdminPath(pathname)
? null
: [
@@ -77,33 +151,47 @@ export function useStudioAppBarAugmentation(): StudioAppBarAugmentation {
onPress: openAdministration,
}),
...contextActions.map((action) => {
- const handler =
- action.id === 'properties'
- ? openProperties
- : action.id === 'bindings'
- ? openBindings
- : action.id === 'selectParent'
- ? selectParent
- : clearSelection;
return React.createElement(IconButton, {
key: action.id,
- icon:
- action.id === 'properties'
- ? { name: 'options-outline' }
- : action.id === 'bindings'
- ? { name: 'git-branch-outline' }
- : action.id === 'selectParent'
- ? { name: 'arrow-up-outline' }
- : { name: 'close-outline' },
+ icon: resolveContextActionIcon(action.id),
label: action.label,
variant: 'ghost',
color: 'neutral',
- onPress: handler,
+ onPress: getActionHandler(action.id),
});
}),
];
return {
actions,
+ overlays: isStudioAdminPath(pathname)
+ ? null
+ : React.createElement(
+ React.Fragment,
+ null,
+ React.createElement(StudioInsertDialog, {
+ componentMeta: studio.componentMeta,
+ entries: resolvedInsertEntries,
+ findNode: (id: string) =>
+ studio.rootNode ? studio.findNode(studio.rootNode, id) : null,
+ onDismiss: () => setInsertVisible(false),
+ onInsert: (entry) => {
+ const inserted = studio.insertFromCatalogEntry(entry);
+ if (inserted) setInsertVisible(false);
+ return inserted;
+ },
+ rootNode: studio.rootNode,
+ visible: insertVisible,
+ }),
+ React.createElement(StudioDeleteDialog, {
+ label: resolveNodeLabel({
+ node: deleteCandidate ?? selectedNode,
+ componentMeta: studio.componentMeta,
+ }),
+ onCancel: () => setDeleteCandidateId(null),
+ onConfirm: confirmDelete,
+ visible: deleteCandidate !== null,
+ }),
+ ),
} satisfies StudioAppBarAugmentation;
}
diff --git a/src/utils/treeUtils.ts b/src/utils/treeUtils.ts
index 9dc1d250..6b002f66 100644
--- a/src/utils/treeUtils.ts
+++ b/src/utils/treeUtils.ts
@@ -1,17 +1,3 @@
-import {
- addNodeToTree,
- cloneWithNewIds,
- findNodeById,
- moveNodeInTree,
- removeNodeFromTree,
- updateNodeInTree,
-} from '../index';
+import { cloneWithNewIds, findNodeById, removeNodeFromTree, updateNodeInTree } from '../index';
-export {
- addNodeToTree,
- cloneWithNewIds,
- findNodeById,
- moveNodeInTree,
- removeNodeFromTree,
- updateNodeInTree,
-};
+export { cloneWithNewIds, findNodeById, removeNodeFromTree, updateNodeInTree };