@miragon/wardley-renderer 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -32
- package/dist/Modeler.d.ts.map +1 -1
- package/dist/WardleyBaseViewer.d.ts.map +1 -1
- package/dist/a11y/canvasFocus.d.ts +28 -0
- package/dist/a11y/canvasFocus.d.ts.map +1 -1
- package/dist/a11y/index.d.ts +1 -1
- package/dist/a11y/index.d.ts.map +1 -1
- package/dist/appearance/index.d.ts +10 -0
- package/dist/appearance/index.d.ts.map +1 -0
- package/dist/appearance/index.js +5 -0
- package/dist/appearance/index.js.map +1 -0
- package/dist/append/WardleyAppendBehavior.d.ts.map +1 -1
- package/dist/collaborative/CollaborativeWardley.d.ts +5 -3
- package/dist/collaborative/CollaborativeWardley.d.ts.map +1 -1
- package/dist/color-picker/WardleyColorPicker.d.ts.map +1 -1
- package/dist/draw/WardleyRenderer.d.ts.map +1 -1
- package/dist/draw/index.d.ts +1 -1
- package/dist/draw/index.d.ts.map +1 -1
- package/dist/draw/label-layout.d.ts +13 -4
- package/dist/draw/label-layout.d.ts.map +1 -1
- package/dist/draw-tool/WardleyDrawTool.d.ts +23 -4
- package/dist/draw-tool/WardleyDrawTool.d.ts.map +1 -1
- package/dist/draw-tool/WardleyDrawingHandles.d.ts +17 -3
- package/dist/draw-tool/WardleyDrawingHandles.d.ts.map +1 -1
- package/dist/draw-tool/index.d.ts.map +1 -1
- package/dist/evolution-grid/EvolutionConstraintBehavior.d.ts.map +1 -1
- package/dist/evolve/WardleyEvolveDragging.d.ts +10 -3
- package/dist/evolve/WardleyEvolveDragging.d.ts.map +1 -1
- package/dist/evolve/index.d.ts.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2066 -1502
- package/dist/index.js.map +1 -1
- package/dist/interaction/WardleyInteraction.d.ts +92 -0
- package/dist/interaction/WardleyInteraction.d.ts.map +1 -0
- package/dist/interaction/index.d.ts +5 -0
- package/dist/interaction/index.d.ts.map +1 -0
- package/dist/io/WardleyExporter.d.ts +12 -2
- package/dist/io/WardleyExporter.d.ts.map +1 -1
- package/dist/io/blobToBase64.d.ts +3 -0
- package/dist/io/blobToBase64.d.ts.map +1 -0
- package/dist/io/index.d.ts +1 -2
- package/dist/io/index.d.ts.map +1 -1
- package/dist/keyboard/WardleyKeyboard.d.ts +19 -1
- package/dist/keyboard/WardleyKeyboard.d.ts.map +1 -1
- package/dist/label-drag/WardleyLabelDragging.d.ts +9 -3
- package/dist/label-drag/WardleyLabelDragging.d.ts.map +1 -1
- package/dist/label-drag/index.d.ts.map +1 -1
- package/dist/label-editing/WardleyLabelEditing.d.ts.map +1 -1
- package/dist/label-editing/fieldError.d.ts +6 -0
- package/dist/label-editing/fieldError.d.ts.map +1 -1
- package/dist/label-editing/imeComposition.d.ts +7 -0
- package/dist/label-editing/imeComposition.d.ts.map +1 -0
- package/dist/label-editing/index.d.ts +2 -1
- package/dist/label-editing/index.d.ts.map +1 -1
- package/dist/lasso/WardleyLassoBehavior.d.ts +5 -1
- package/dist/lasso/WardleyLassoBehavior.d.ts.map +1 -1
- package/dist/lasso/index.d.ts +1 -1
- package/dist/lasso/index.d.ts.map +1 -1
- package/dist/link-editing/WardleyLinkEditing.d.ts.map +1 -1
- package/dist/live-preview/LivePreview.d.ts +18 -3
- package/dist/live-preview/LivePreview.d.ts.map +1 -1
- package/dist/live-preview/index.d.ts +1 -1
- package/dist/live-preview/index.d.ts.map +1 -1
- package/dist/map-menu/AxisLabelsPopover.d.ts.map +1 -1
- package/dist/map-menu/MapSizePopover.d.ts.map +1 -1
- package/dist/map-menu/TitleDialog.d.ts.map +1 -1
- package/dist/map-menu/index.d.ts +0 -2
- package/dist/map-menu/index.d.ts.map +1 -1
- package/dist/map-menu/popover.d.ts.map +1 -1
- package/dist/palette/WardleyHoverTooltipTeardown.d.ts +18 -0
- package/dist/palette/WardleyHoverTooltipTeardown.d.ts.map +1 -0
- package/dist/palette/WardleyPaletteArmedTool.d.ts +19 -0
- package/dist/palette/WardleyPaletteArmedTool.d.ts.map +1 -0
- package/dist/palette/WardleyPaletteKeyboard.d.ts +4 -2
- package/dist/palette/WardleyPaletteKeyboard.d.ts.map +1 -1
- package/dist/palette/WardleyPaletteProvider.d.ts +8 -3
- package/dist/palette/WardleyPaletteProvider.d.ts.map +1 -1
- package/dist/palette/WardleyPaletteReadOnly.d.ts +26 -0
- package/dist/palette/WardleyPaletteReadOnly.d.ts.map +1 -0
- package/dist/palette/WardleyPaletteTooltip.d.ts +52 -0
- package/dist/palette/WardleyPaletteTooltip.d.ts.map +1 -0
- package/dist/palette/index.d.ts +8 -1
- package/dist/palette/index.d.ts.map +1 -1
- package/dist/popup/WardleyElementSettingsProvider.d.ts.map +1 -1
- package/dist/read-only/WardleyReadOnly.d.ts +26 -4
- package/dist/read-only/WardleyReadOnly.d.ts.map +1 -1
- package/dist/read-only/index.d.ts +3 -0
- package/dist/read-only/index.d.ts.map +1 -1
- package/dist/wardley.css +1 -1
- package/package.json +8 -4
- package/dist/io/rasterize.d.ts +0 -25
- package/dist/io/rasterize.d.ts.map +0 -1
- package/dist/map-menu/ShortcutsDialog.d.ts +0 -14
- package/dist/map-menu/ShortcutsDialog.d.ts.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["AXES_LAYER","compact","clamp","PLOT_MIN","PLOT_MAX","normalizeMapSize","MAP_SIZE_PRESETS","svgCreate","normalizeMapSize","presetIdForSize","clamp01","line","text","svgAttr","svgCreate","clamp01","svgCreate","EPSILON","clamp01","svgCreate","svgAttr","NAME_LABEL_CLASS","svgAttr","svgCreate","movementDeltaX","movementDeltaXOf","clamp","PLOT_INSET","escapeAttribute","AFTER_REDRAW_PRIORITY","CAPTION_GAP","svgCreate","svgAttr","svgCreate","svgAttr","svgCreate","CUSTOM","MAP_SIZE_PRESETS","PLOT_MIN","PLOT_MAX","Diagram","MAP_SIZE_PRESETS$1","PLOT_MAX$1","PLOT_MIN$1","normalizeMapSize$1","presetIdForSize$1","DraggingModule","RuleProvider","AutoScroll","BaseLayouter","CommandInterceptor","ModelingModule","MouseModule","CreateModule","BaseRenderer","SelectionModule","ZoomScrollModule","MoveCanvasModule","KeyboardModule","MoveModule","AutoScrollModule","ConnectModule","ContextPadModule","PaletteModule","RulesModule","OutlineModule","ResizeModule","PopupMenuModule","LassoToolModule","ContextPad","ConnectionPreviewModule","OrderingProvider","MIRAGON","PLOT","DEFAULT_PLOT_SIZE","NOTE_CHAR_W","noteMetrics","lines","label","maxLen","l","NOTATION_STATUS","COLORS","NOTE_COLORS","ATTITUDE_COLORS","ATTITUDE_TITLES","FONT","saveSVG","source","canvas","clone","layer","decoration","element","box","bounds","attribute","viewport","AXES_LAYER$1","AXES_PADDING","exportBounds","boxes","grid","content","drawnContentBox","padding","axes","axesBox","left","top","right","bottom","width","height","layerToScreen","screenToLayer","visuals","visual","local","visualToScreen","toLayer","x","y","layerX","layerY","ROOT_ID","NO_INSETS","fitViewbox","container","horizontal","freeExtent","insets","vertical","scale","extent","total","before","after","FRAME_TYPES","TYPE_ORDER","WardleyImporter","elementFactory","factory","eventBus","elementRegistry","config","injector","warnings","map","meta","existing","root","shapeById","ordered","a","b","frames","el","nodes","frameCount","shape","resolvedEdges","edge","target","connectionPaintOrder","insertedConnections","conn","plot","roots","e","isObject","isWardleyShape","\"wardleyType\"","CONNECTION_TYPES","isWardleyConnection","isComponent","isPipeline","isAttitude","compact$1","out","k","v","obj","WardleyExporter","sourceOrder","DEFAULT_MAP_TITLE","unorderedElements","unorderedEdges","base","built","elements","edges","pipelineIds","consolidated","_stale","rest","childIds","CURRENT_SCHEMA_VERSION","validateMap","position","bo","extraPositions","points","p","WardleySourceOrder","event","index","sortBySourceIndex","indexOf","sourceIndex","item","items","FALLBACK_SIZE","MAX_CANVAS_SIDE","MAX_CANVAS_AREA","svgToPng","options","svgSize","svg","url","image","resolve","reject","pixels","rasterSize","context","png","fittingScale","blobToBase64","reader","blob","absoluteLength","viewBox","viewBoxWidth","viewBoxHeight","match","value","length","ioModule","configWithSize","_previous","size","wardleyRootOf","withoutRawSizeStatements","withoutRawStatements","rawPassthrough","MapProjection","exporter","layouter","livePreview","businessObject","changed","model","template","assignGeometry","shapes","waypoints","point","snapshot","id","geometry","connection","transient","connections","COMMAND_START_EVENTS","PUT_BACK_PRIORITY","livePreviewModule","field","live","committedConfig","READ_ONLY_CHANGED","LOCKED_CLASS","VETO_PRIORITY","EDIT_RULES","WardleyReadOnly","readOnly","name","readOnlyModule","isReadOnly","canvasSvg","focusCanvasWithoutRing","lastInteraction","modalityTracked","trackInputModality","lastInteractionWasPointer","describeCanvas","canvasAccessibilityModule","MAP_RESIZE_PREFIX","LAYER_NAME","LAYER_INDEX","SNAP_STEP","PRESET_SNAP_DISTANCE","EDGE_HIT_WIDTH","CORNER_HIT_SIZE","CORNER_VISUAL_SIZE","BADGE_OFFSET","CURSORS","round","step","clamp$2","min","max","withoutPaint","sizeForDrag","axis","start","dx","dy","keys","ratio","preset","candidate","sizeLabel","MapResizeHandles","dragging","projection","modeling","create","append","drag","group","hit","visible","attr","screenPixel","edgeHitWidth","half","cornerHitSize","cornerHalf","cornerVisualSize","startSize","originalEvent","ResizeAwareAutoScroll","mapProjectionModule","mapResizeModule","applyConfigUpdate","previous","key","update","nextConfig","UpdateConfigHandler","properties","diagramConfig","undoRedo","freeArea","IMPLICIT_ROOT_PREFIX","importableMap","checked","reserved","sizeToCss","ARMED_TOOL_PREFIXES","DROP_MARK_PRIORITY","cancelGesture","diagram","gesture","dropping","WardleyBaseViewer","modules","priority","callback","importer","commandStack","error","parseDSLWithDiagnostics","text","diagnostics","d","presetId","current","cleaned","title","labels","normalizeEvolutionLabels","requested","sameEvolutionLabels","serializeDSL","connectionAnchorOf","WardleyLayouter","hints","\"source\"","\"target\"","wardleyLayoutModule","LINKABLE_TYPES","isLinkableType","type","nextFreeLabel","taken","counterMatch","stem","counter","WardleyElementFactory","excludeId","entries","unique","wardleyType","wardleyLabel","pairableType","renamed","other","center","end","pos","canvasPoints","xs","ys","first","firstNorm","extra","rawLabel","decorators","annotationNumber","bidirectional","color","flowValue","wardleyModelModule","AXES_LAYER","DEFAULT_Y_AXIS_END_LABELS","AXIS_CLASS","AXIS_TEXT_CLASS","clamp01$3","n","EvolutionGrid","DEFAULT_STAGE_BOUNDARIES","DEFAULT_EVOLUTION_LABELS","drawnPlotLength","coord","evolutionStage","evolution","rect","i","x0","x1","line$1","midX","text$1","arrowHead","yLabel","w","h","attrs","dir","MIN_EVOLVE_DELTA","PREFIX","HANDLE_CLASS","clamp01$2","WardleyEvolveDragging","preview","movement","forwardTarget","evolutionAtClientX","vb","canvasX","clientX","cy","isDrawing","dom","original","onMove","onUp","ctx","wardleyEvolveModule","centerOf","pipelineContains","pipeline","allPipelines","registry","membersOf","anchorComponentOf","pipelineAnchoredBy","component","pipelineFollowers","anchor","pipelineAt","candidates","excluded","COLLECT_FOLLOWERS_PRIORITY","VERTICAL_PREVIEW_PRIORITY","DROP_TARGET_PRIORITY","EXTEND_CLOSURE_PRIORITY","VERTICAL_PREVIEW_LAYER","VERTICAL_PREVIEW_LAYER_INDEX","DROP_TARGET_MARKER","PipelineGroupBehavior","previewSupport","\"wardleyLabel\"","counterpart","closure","follower","carried","translate","remove","all","dragged","member","pipelineGroupModule","SHAPE_GEOMETRY_COMMANDS","GEOMETRY_COMMANDS","COMPONENT_LABEL_COMMANDS","TOP_LEVEL_PRIORITY","DELTA_CLAMP_PRIORITY","MIN_RESIZE_EXTENT","EPSILON$1","EvolutionConstraintBehavior","wardleyModeling","derive","directShapes","moved","closureShapes","refreshPipelineLabels","topLeft","coordinate","evolutionStart","evolutionEnd","clampRange","clamp01$1","command","delta","followers","created","correction","movedShapes","verticalDelta","groupShape","host","evolutionsBefore","evolutionBefore","shiftedTarget","bottomRight","clampToRange","plotStart","plotEnd","clampedStart","clampedLength","range","RANGE_EPS","setOrDelete","UpdatePropertiesHandler","old","oldProperties","ResizeMapHandler","withRawPassthrough","UPDATE_PROPERTIES","RESIZE_MAP","UPDATE_CONFIG","compact","WardleyModeling","cx","clamp01","targetEvolution","opts","dec","\"inertia\"","method","\"method\"","\"market\"","\"ecosystem\"","kind","sameSize","PASTE_OFFSET","SHAPE_PROPS","CONNECTION_PROPS","snapshotProps","WardleyCopyPaste","selection","mouse","wardleyElementFactory","s","seen","sourceIdx","targetIdx","clones","lastMove","clipboard","snap","cloneIdByOriginalId","pipelineId","c","pipelineIndexByAnchor","anchorIndex","snapshots","pipelineIndex","independent","uniqueLabels","offset","bbox","groupBBox","minX","minY","maxX","maxY","wardleyModelingModule","evolutionGridModule","evolutionConstraintModule","ICON_PERSON","ICON_FAST_FORWARD","ICON_FAST_REWIND","drawIcon","g","path","LABEL_CHAR_WIDTH","movementDeltaX","here","estimatedLabelWidth","nameLines","line","firstLineBaseline","lineCount","slotY","growth","lastLineBaseline","componentLabelSlot","isShortRightwardMovement","componentLabelPlacement","slot","inertiaShift","movementLabelSlot","movementLabelPlacement","labelOffset","anchorLabelSlot","anchorLabelPlacement","normalizeLabelOffset","clamp","WARDLEY_RENDER_PRIORITY","NAME_LABEL_CLASS$1","MOVEMENT_CLASS","LABEL_HANDLE_CLASS","LABEL_ROLE_ATTRIBUTE","ATTITUDE_TITLE_CLEARANCE","WardleyRenderer","pts","dash","isFlow","endpoints","connectionArrow","mx","my","movementDeltaX$1","drawInertiaMarker","tint","ring","circle","drawComponentSymbols","drawComponentLabel","mv","tx","tipX","placement","targetName","lastLineY","icon","y0","\"pioneers\"","stroke","plotTop","titleAbove","marker","accelerate","sym","outer","bx","lx","ly","firstLineY","haloAttrs","halo","row","angle","to","from","len","by","radiusOf","t","wp","sc","tc","dist","ux","uy","sr","tr","wardleyDrawModule","Viewer","PAD_TOP","PAD_BOTTOM","PAD_SIDE","INSET_SLACK","EPSILON","clamp$1","lo","hi","constrainAxis","lowest","highest","recentre","viewSize","freeAreaRange","freeEnd","free","constrainAxisToFreeArea","byContent","byPlot","PanConstraint","invalidate","view","slack","viewbox","pads","clampedX","clampedY","PanConstraintModule","FreeRect","side","reported","freeRectModule","NavigatedViewer","WardleyLassoBehavior","lassoTool","wardleyLassoModule","CONNECTABLE","HORIZONTAL_RESIZE_DIRECTIONS","isConnectable","alreadyConnected","WardleyRules","wardleyRulesModule","stageSnappingModule","tolerance","boundaryXs","setSnappedX","sx","mid","maxDistance","wrap","inner","toolIcon","LUCIDE_SQUARE_DASHED_MOUSE_POINTER","LINE_SEGMENT","eventCircle","PALETTE_ICONS","ATTITUDE_INITIALS","attitudeIcon","initial","GROUP_BLOCKS","GROUP_STRATEGY","SPECS","LASSO_TOOL","DRAW_TOOL","PLOT_INSET$1","STACK_OFFSET","MAX_STACK_STEPS","escapeAttribute$1","isKeyboardClick","WardleyPaletteProvider","drawTool","palette","spec","click","entryId","freeCenter","plotTopLeft","plotBottomRight","clampAxis","low","high","occupied","shortcut","nativeTitle","keyShortcut","draggable","ENTRY_SELECTOR","PREVIOUS_KEYS","NEXT_KEYS","ACTIVATE_KEYS","wardleyPaletteModule","provider","entry","active","next","action","PAD_MARGIN","FALLBACK_PAD_WIDTH","WardleyContextPad","nodeRects","nodeBounds","union","padReach","movementRects","targets","graphics","child","part","rects","createFieldError","caption","message","place","focusField","NAME_LABEL_CLASS","EDITING_MARKER","NOT_EDITABLE","AFTER_REDRAW_PRIORITY$1","FIELD_PADDING_X","FIELD_PADDING_Y","FIELD_BORDER","FIELD_LINE_HEIGHT","MIN_FONT_SIZE","CAPTION_GAP$1","isImeCompositionKey","NOTE_EDIT_HINT","duplicateNameMessage","sanitizeLabel","raw","measureContext","measureTextWidth","font","fontSizePx","WardleyLabelEditing","isNote","openedByPointer","requiresUniqueName","classedByFallback","lineHeightOf","fontSize","lineHeight","createNameField","hint","createCaption","layout","fieldBox","captionTop","showDuplicateError","clearError","done","cleanup","onKey","onBlur","onInput","commit","applied","trigger","relayout","last","nextBo","selected","gfx","marked","texts","drawnLabel","matched","containerRect","reference","labelElements","referenceStyle","typography","textWidth","className","labelEditingModule","ALLOWED_SCHEMES","SCHEME_PATTERN","CONTROL_CHARACTERS","sanitizeLinkUrl","isAllowedLinkUrl","scheme","safeLinkUrl","CONTEXT_PAD_CLEARANCE","AFTER_REDRAW_PRIORITY","CAPTION_GAP","INVALID_HINT","canHaveLink","linkOf","WardleyLinkEditing","rawUrl","placeField","clearInvalid","placeCaption","markInvalid","tryCommit","linkEditingModule","POPUP_PROVIDER_ID","TYPE_GROUP","METHOD_GROUP","PROP_GROUP","keepKeysInsidePopup","mark","WardleyElementSettingsProvider","popupMenu","wardleyPopupModule","LUCIDE","chromeIcon","GROUP_PRIMARY","GROUP_PROPERTIES","GROUP_DANGER","KEYBOARD_APPEND_OFFSET","PAD_PREVIOUS_KEYS","PAD_NEXT_KEYS","escapeAttribute","cpHtml","iconSvg","wardleyContextPadModule","contextPad","connect","labelEditing","evolveDragging","colorPicker","keyEvent","\"delete\"","editTitle","startAppend","\"append\"","startConnect","\"connect\"","startEvolve","\"evolve\"","\"settings\"","\"color\"","linkEditing","storedLink","\"link\"","openableLink","pad","focused","containerBounds","plotBottom","NUDGE_STEP","NUDGE_STEP_COARSE","ARROW_DELTAS","QUICK_CREATE","PLOT_INSET","STACK_STEP","STACK_COLUMN_STEP","STACK_CLEARANCE","STACK_ATTEMPTS","isCanvasKey","WardleyKeyboard","undoRedoEnabled","rules","onPointerMove","onPointerLeave","escapeOwnedByOverlay","onKeydownCapture","deleteSelection","internalClipboardIsNewest","deferredPaste","markSystemClipboardNewer","pasteFromInternalClipboard","copyPaste","onPaste","locked","onModifierShortcut","onPlainKey","toolKey","onKeydown","attempt","canvasPoint","wardleyKeyboardModule","NAMED_TYPES","AFTER_CREATE","WardleyAppendBehavior","connectionPreview","canConnect","wardleyAppendModule","GRID_STEPS","WardleyColorPicker","pop","swatches","buttons","activeButton","btn","isActive","ev","cw","ch","pw","ph","clientY","hadFocus","wardleyColorPickerModule","isFrame","WardleyOrderingProvider","siblings","newParent","wardleyOrderingModule","CLOSE_RADIUS","DRAW_TOOL_ENTRY","WardleyDrawTool","distance","WardleyDrawingHandles","sel","only","handle","closed","WardleyDrawingHitProvider","createStrokeHit","interactionEvents","wardleyDrawToolModule","DRAG_THRESHOLD","SNAP_HOME_DISTANCE","ARMED_CLASS","DRAGGING_CLASS","WardleyLabelDragging","role","startOffset","deltaX","deltaY","sameOffset","swallow","home","imported","_clearedOffset","\"businessObject\"","_previousOffset","offsetFromPlacement","centerX","wardleyLabelDragModule","resizeAwareAutoScrollModule","Modeler","documentIdsOf","ids","readBackIds","modeler","canvasId","keyOf","documentId","findConnection","setAsideEditorState","canvasIds","readBack","edit","nameEdit","linkEdit","restoreEditorState","state","lookup","connectionOf","reselected","WARDLEY_NOTATION","ADDRESSABLE_TYPES","isAddressable","createCollaborativeModeler","collaborative","diagramOptions","createCollaborativeViewer","documentIds","byCanvasId","byDocumentId","read","panConstraint","editable","contentListeners","importsRunning","destroyed","lastExport","MODELER_API_VERSION","listener","elementInfo","listedElement","committedText","committed","importText","editorState","warning","isViewState","isFiniteNumber","EXPORT_LABELS","exportEntry","exportEntries","exports","mapMenu","actions","mapTitle","shortcutsKey","ARROWS","percentOfActualSize","lang","keysOf","platform","what","names","ctrl","shift","plus","minus","fileGroup","chrome","mapShortcuts","messages","CLOSE_ICON","tag","nextId","uniqueId","prefix","dialogButton","\"variant\"","variant","header","head","heading","titleId","close","onClose","createMapDialog","dialog","build","parts","panel","pressedOnBackdrop","DIALOG_CLASS","shortcutTable","section","table","body","createShortcutsDialog","currentTitle","createTitleDialog","form","wrapper","footer","cancel","apply","onReadOnly","createPopover","onPointerDown","onWindowBlur","onKeyDown","why","control","withMapListeners","onImport","popover","CUSTOM$1","numberInput","input","createMapSizePopover","choice","option","custom","reset","sizeField","widthField","heightField","atOpen","show","applyLength","fieldOf","parsePlotLength","plotLengthMessage","lengths","times","doneButton","previewed","sizeOf","info","CUSTOM","presetIdFor","EVOLUTION_PRESETS","createAxisLabelsPopover","inputs","labelsAtOpen","fill","typedLabels","MAP_SIZE_PRESETS","PLOT_MAX","PLOT_MIN","normalizeMapSize","presetIdForSize"],"sources":["../src/theme/palette.ts","../src/draw/styles.ts","../src/io/saveSvg.ts","../src/io/exportBounds.ts","../src/io/types.ts","../src/io/fitViewbox.ts","../src/io/WardleyImporter.ts","../src/model/di-types.ts","../src/io/WardleyExporter.ts","../src/io/WardleySourceOrder.ts","../src/io/rasterize.ts","../src/io/index.ts","../src/map-resize/MapProjection.ts","../src/live-preview/LivePreview.ts","../src/live-preview/index.ts","../src/read-only/WardleyReadOnly.ts","../src/read-only/index.ts","../src/a11y/canvasFocus.ts","../src/a11y/describeCanvas.ts","../src/a11y/index.ts","../src/map-resize/MapResizeHandles.ts","../src/map-resize/ResizeAwareAutoScroll.ts","../src/map-resize/index.ts","../src/modeling/cmd/UpdateConfigHandler.ts","../src/WardleyBaseViewer.ts","../src/layout/WardleyLayouter.ts","../src/layout/index.ts","../src/model/WardleyElementFactory.ts","../src/model/index.ts","../src/evolution-grid/EvolutionGrid.ts","../src/evolve/constants.ts","../src/evolve/WardleyEvolveDragging.ts","../src/evolve/index.ts","../src/pipeline/pipelineMembership.ts","../src/pipeline/PipelineGroupBehavior.ts","../src/pipeline/index.ts","../src/evolution-grid/EvolutionConstraintBehavior.ts","../src/modeling/cmd/UpdatePropertiesHandler.ts","../src/modeling/cmd/ResizeMapHandler.ts","../src/modeling/WardleyModeling.ts","../src/modeling/WardleyCopyPaste.ts","../src/modeling/index.ts","../src/evolution-grid/index.ts","../src/draw/icons.ts","../src/draw/label-layout.ts","../src/draw/WardleyRenderer.ts","../src/draw/index.ts","../src/Viewer.ts","../src/pan-constraint/PanConstraint.ts","../src/pan-constraint/index.ts","../src/free-rect/FreeRect.ts","../src/free-rect/index.ts","../src/NavigatedViewer.ts","../src/lasso/WardleyLassoBehavior.ts","../src/lasso/index.ts","../src/rules/WardleyRules.ts","../src/rules/index.ts","../src/snapping/StageSnapping.ts","../src/snapping/index.ts","../src/draw/palette-icons.ts","../src/palette/WardleyPaletteProvider.ts","../src/palette/WardleyPaletteKeyboard.ts","../src/palette/index.ts","../src/context-pad/WardleyContextPad.ts","../src/label-editing/fieldError.ts","../src/label-editing/WardleyLabelEditing.ts","../src/label-editing/index.ts","../src/link-editing/link-url.ts","../src/link-editing/WardleyLinkEditing.ts","../src/link-editing/index.ts","../src/popup/WardleyElementSettingsProvider.ts","../src/popup/index.ts","../src/draw/lucide.ts","../src/context-pad/WardleyContextPadProvider.ts","../src/context-pad/index.ts","../src/keyboard/WardleyKeyboard.ts","../src/keyboard/index.ts","../src/append/WardleyAppendBehavior.ts","../src/append/index.ts","../src/color-picker/WardleyColorPicker.ts","../src/color-picker/index.ts","../src/ordering/WardleyOrderingProvider.ts","../src/ordering/index.ts","../src/draw-tool/WardleyDrawTool.ts","../src/draw-tool/WardleyDrawingHandles.ts","../src/draw-tool/WardleyDrawingHitProvider.ts","../src/draw-tool/index.ts","../src/label-drag/WardleyLabelDragging.ts","../src/label-drag/index.ts","../src/Modeler.ts","../src/editor-state.ts","../src/collaborative/CollaborativeWardley.ts","../src/map-menu/menu.ts","../src/map-menu/shortcuts.ts","../src/map-menu/dom.ts","../src/map-menu/dialog.ts","../src/map-menu/ShortcutsDialog.ts","../src/map-menu/TitleDialog.ts","../src/map-menu/popover.ts","../src/map-menu/MapSizePopover.ts","../src/map-menu/AxisLabelsPopover.ts"],"sourcesContent":["/**\n * Miragon design tokens — the single source of truth for every colour the renderer draws.\n *\n * Values mirror the Miragon design system — the `miragon-brand:modeler-tool-design` skill in\n * `Miragon/corporate-identity`, whose files are vendored unchanged next to this module\n * (`cd-tokens.generated.css`, `cd-tokens.generated.json`, `cd-canvas.css`; design system 1.27.0).\n * Re-copy them from the skill to update; never fork the hex values by hand. The SVG drawing needs\n * literal values (exports carry presentation attributes, never `var()`), so `draw/styles.ts`\n * derives the public `COLORS`/`FONT`/… from `MIRAGON`; the in-canvas chrome in\n * `assets/wardley.css` reads the `--cd-ui-*` roles directly. The unit test\n * `test/theme.sync.test.ts` fails if a `MIRAGON` value drifts from its `--cd-*` counterpart or the\n * CSS declares a colour of its own.\n *\n * Pure data — no DOM, no imports — so it stays inside the P1 DOM-free discipline.\n *\n * The renderer draws light only (the modelers switch to dark together, guide §13.3). Brand rule:\n * blue leads (`blau` — surfaces, buttons, links), green accents (`gruen` — key visual, highlights;\n * never body text on white).\n */\n\n/** Raw Miragon brand ramp — exact `brand/tokens.json` values. */\nexport const MIRAGON = {\n /** Primary: surfaces, buttons, links, backgrounds. */\n blau: \"#335DE5\",\n /** Deeper blue for links / accent text on white (WCAG AA, ~5.5:1). */\n blauLink: \"#2B50D4\",\n /** Lightened blue for links / accents on dark surfaces. */\n blauHell: \"#6B8AFF\",\n /** Accent: key visual, highlights, one emphasised word. Bright — a fill, never text on white. */\n gruen: \"#00E676\",\n /** Calm neutral surface (warm off-white). */\n grau: \"#F9F7F7\",\n /** Text on light, monochrome logo. Not pure black. */\n schwarz: \"#1D1D1D\",\n weiss: \"#FFFFFF\",\n /**\n * Status layer (guide §3.3): the brand colours plus amber and red. Fills, borders, icons and\n * dots; as text on white only `danger` and `info` reach AA.\n */\n success: \"#00E676\",\n warning: \"#FFB000\",\n danger: \"#CD1839\",\n info: \"#335DE5\",\n /** UI grey (`--cd-linie`) for hairlines, guides and decorative borders. The CI allows no other greys. */\n linie: \"#E6E2E2\",\n /** Structural strokes that must stay visible (≥ 3:1 on white): axes, dependency edges. */\n kontur: \"#8F8A8A\",\n /** Secondary text (≥ 4.5:1 on white and on paper). */\n textLeise: \"#6B6666\",\n /** Signature brand gradient — hero, large surfaces, brand moments. Use verbatim. */\n gradientBrand: \"linear-gradient(120deg, #335DE5 30%, #00E676)\",\n} as const;\n","/** Central rendering constants (geometry, colors, typography) — Miragon corporate identity. */\n\nimport { DEFAULT_PLOT_SIZE } from \"@miragon/wardley-schema-model\";\nimport { MIRAGON } from \"../theme/index.js\";\n\n/**\n * Default plot area in diagram px (interior without axis margins). Changeable at runtime via\n * config.size. Width/height come from schema-model (single source, also used for migrations).\n */\nexport const PLOT = {\n width: DEFAULT_PLOT_SIZE.width,\n height: DEFAULT_PLOT_SIZE.height,\n marginLeft: 66,\n marginTop: 38,\n marginRight: 44,\n marginBottom: 58,\n} as const;\n\n/** Smallest drawn plot — the size policy lives in schema-model (shared with the DSL parser). */\nexport { PLOT_MIN } from \"@miragon/wardley-schema-model\";\n\nexport const NODE_SIZE = 34;\nexport const COMPONENT_RADIUS = 15;\nexport const COMPONENT_INNER_RADIUS = 12;\nexport const ANCHOR_ICON_SIZE = 26;\nexport const PIPELINE_HEIGHT = 30;\nexport const PIPELINE_ANCHOR_SIZE = 16;\n\nexport const NOTE_LINE_HEIGHT = 17;\nconst NOTE_PAD_X = 8;\nconst NOTE_PAD_Y = 6;\nconst NOTE_CHAR_W = 7.5;\n\n/**\n * Box dimensions of a note from its (possibly multi-line) text. The note shape grows as large as\n * its text -> the move/click hitbox grows with it (instead of a fixed 34px). Minimum = NODE_SIZE.\n */\nexport function noteMetrics(label: string): { lines: string[]; width: number; height: number } {\n const lines = (label && label.length ? label : \"note\").split(\"\\n\");\n const maxLen = Math.max(1, ...lines.map((l) => l.length));\n return {\n lines,\n width: Math.max(NODE_SIZE, Math.round(maxLen * NOTE_CHAR_W) + NOTE_PAD_X * 2),\n height: Math.max(NODE_SIZE, lines.length * NOTE_LINE_HEIGHT + NOTE_PAD_Y * 2),\n };\n}\n\n/**\n * The status colours the notation drew with before design system 1.13.0 brightened its status\n * layer. Maps store note colours as hex, the accelerator needs 4.5:1 as text and the SVG export\n * must not change, so the notation keeps them as its own literals.\n */\n// Notation colours until the joint dark mode maps them onto the status roles (guide §3.6).\n// brand-lint-disable\nconst NOTATION_STATUS = {\n success: \"#0B7A55\",\n warning: \"#92610A\",\n danger: \"#C92A2A\",\n info: \"#2B50D4\",\n} as const;\n// brand-lint-enable\n\n/**\n * Canvas colours — Miragon palette (blue = interactive/flow, green = accelerate/positive,\n * red = movement/decelerate). Keys are the public contract; brand values come from the single source\n * of truth in `theme/palette.ts` (`MIRAGON`). Referenced (not spread) so the literal-string types\n * survive into the published `.d.ts`.\n */\nexport const COLORS = {\n paper: MIRAGON.grau,\n ink: MIRAGON.schwarz,\n inkSoft: MIRAGON.textLeise,\n axis: MIRAGON.kontur,\n axisText: MIRAGON.textLeise,\n grid: MIRAGON.linie,\n band: \"rgba(29,29,29,0.025)\",\n stroke: MIRAGON.schwarz,\n componentFill: MIRAGON.weiss,\n anchorFill: MIRAGON.schwarz,\n dependency: MIRAGON.kontur,\n accent: MIRAGON.blau,\n accentSoft: \"rgba(51,93,229,0.12)\",\n flow: MIRAGON.blau,\n movement: NOTATION_STATUS.danger,\n inertia: MIRAGON.schwarz,\n noteText: MIRAGON.textLeise,\n pipeline: MIRAGON.schwarz,\n // An element surface like the components (guide §10.1); its stroke and number set it apart.\n annotationFill: MIRAGON.weiss,\n plotBackground: MIRAGON.weiss,\n accelerator: NOTATION_STATUS.success,\n deaccelerator: NOTATION_STATUS.danger,\n} as const;\n\n/**\n * Note color palette (bpmn.io-style mini picker; deliberately NOT a full color picker). Values are\n * hex and are rendered 1:1 as CSS color, or serialized in the DSL as `(color …)`.\n * Convention (also used in the Wardley-mapping skill): green = good, red = problem/risk,\n * amber = watch, blue = info, purple = idea, slate = neutral.\n */\nexport const NOTE_COLORS = [\n { id: \"green\", name: \"Green · good\", value: NOTATION_STATUS.success },\n { id: \"amber\", name: \"Amber · watch\", value: NOTATION_STATUS.warning },\n { id: \"red\", name: \"Red · problem\", value: NOTATION_STATUS.danger },\n { id: \"blue\", name: \"Blue · info\", value: NOTATION_STATUS.info },\n // Maps store these as hex; guide §3.6 retires them with the joint dark mode.\n // brand-lint-disable\n { id: \"teal\", name: \"Teal\", value: \"#0E8181\" },\n { id: \"purple\", name: \"Purple · idea\", value: \"#6A3DB8\" },\n { id: \"pink\", name: \"Pink\", value: \"#C2185B\" },\n { id: \"slate\", name: \"Slate · neutral\", value: \"#4A4A4A\" },\n // brand-lint-enable\n] as const;\n\n/**\n * Colors of the attitude regions per kind (shared by renderer + palette icons). Miragon palette:\n * pioneers = blue (explore), settlers = amber (stabilise), town planners = green (industrialise).\n */\nexport const ATTITUDE_COLORS: Record<string, { fill: string; stroke: string }> = {\n pioneers: { fill: \"rgba(51,93,229,0.07)\", stroke: MIRAGON.blau },\n // The notation's warning as a tint, until the joint dark mode draws Settlers per guide §3.6.\n // brand-lint-disable-next-line\n settlers: { fill: \"rgba(146,97,10,0.10)\", stroke: NOTATION_STATUS.warning },\n // Bright brand green only as the fill; the title and outline need the darker success value (AA).\n townplanners: { fill: \"rgba(0,230,118,0.10)\", stroke: NOTATION_STATUS.success },\n};\n\n/** Canonical region titles (Wardley's Pioneers / Settlers / Town Planners), keyed by kind. */\nexport const ATTITUDE_TITLES: Record<string, string> = {\n pioneers: \"Pioneers\",\n settlers: \"Settlers\",\n townplanners: \"Town Planners\",\n};\n\nexport const FONT = {\n /**\n * Set as the `font-family` attribute DIRECTLY on all SVG text elements (canvas labels,\n * axis/stage text and consequently the SVG export too) – not inherited from a CSS container.\n * 'Geist Variable' comes first because that is the family name `@fontsource-variable/geist`\n * registers; 'Geist' matches a locally installed (static) Geist. Without either it falls back to a\n * system sans. The library does NOT ship the font – consumers self-host it, see README.\n */\n family:\n \"'Geist Variable', 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif\",\n label: 13,\n axis: 12,\n stage: 12,\n} as const;\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport { PLOT } from \"../draw/styles.js\";\n\nexport interface SvgBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Serializes the current canvas into standalone SVG (snapshot/export).\n * `bounds` is the outer plot boundary (typically `exportBounds(canvas, grid)`), so that\n * maps enlarged via `config.size` are exported completely; if omitted, the default plot\n * area is used. Independent of the current zoom/scroll.\n */\nexport function saveSVG(canvas: Canvas, bounds?: SvgBounds): { svg: string } {\n // The canvas's own <svg> child: a host chrome may move a palette with <svg> icons in front of it.\n const source = canvas.getContainer().querySelector(\":scope > svg\");\n if (!source) throw new Error(\"No SVG found in the canvas container.\");\n\n const clone = source.cloneNode(true) as SVGSVGElement;\n // Editor chrome, sized to the current zoom: not part of the map.\n clone.querySelectorAll(\".layer-wardley-map-resize\").forEach((layer) => layer.remove());\n // Interaction state is not part of the map either: the picture looks the same whatever the user\n // has selected or hovers, so hosts need not deselect (and lose the selection) to export.\n clone.querySelectorAll(\".layer-wardley-drawing-handles\").forEach((layer) => layer.remove());\n clone\n .querySelectorAll(\".djs-outline, .layer-selectionOutline > *, .layer-resizers > *\")\n .forEach((decoration) => decoration.remove());\n clone.querySelectorAll(\".selected, .hover\").forEach((element) => {\n element.classList.remove(\"selected\", \"hover\");\n if (!element.classList.length) element.removeAttribute(\"class\");\n });\n\n const box = bounds ?? {\n x: 0,\n y: 0,\n width: PLOT.marginLeft + PLOT.width + PLOT.marginRight,\n height: PLOT.marginTop + PLOT.height + PLOT.marginBottom,\n };\n // The editor's canvas semantics (an interactive, focusable application) do not apply to a\n // static image.\n for (const attribute of [\"tabindex\", \"role\", \"aria-roledescription\", \"aria-label\"]) {\n clone.removeAttribute(attribute);\n }\n clone.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n clone.setAttribute(\"viewBox\", `${box.x} ${box.y} ${box.width} ${box.height}`);\n clone.setAttribute(\"width\", String(box.width));\n clone.setAttribute(\"height\", String(box.height));\n\n // diagram-js sets a viewbox transform on the outermost layer; for the static export we\n // neutralize pan/zoom by letting the viewBox (above) determine the geometry.\n const viewport = clone.querySelector<SVGGElement>(\".viewport\");\n if (viewport) viewport.removeAttribute(\"transform\");\n\n const svg = new XMLSerializer().serializeToString(clone);\n return { svg: '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' + svg };\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { SvgBounds } from \"./saveSvg.js\";\n\n/** Name of the diagram-js layer the evolution grid draws its axes into. */\nconst AXES_LAYER = \"wardley-axes\";\n\n/** Small enough that the default axes stay inside the plot margins: the axis text has no halo. */\nconst AXES_PADDING = 4;\n\n/** Covers what getBBox ignores, chiefly the label halo stroke. */\nexport const EXPORT_CONTENT_PADDING = 12;\n\ninterface OuterBoundsSource {\n outerBounds(): SvgBounds;\n}\n\n/**\n * The area an image export must cover: the plot frame plus everything drawn on the element layer\n * and the axes. Labels of commodity components (evolution near 1) and notes run past the plot's\n * right edge, so exporting only the plot frame crops them.\n */\nexport function exportBounds(\n canvas: Canvas,\n grid: OuterBoundsSource,\n padding = EXPORT_CONTENT_PADDING,\n): SvgBounds {\n const boxes = [grid.outerBounds()];\n const content = drawnContentBox(canvas);\n if (content) {\n boxes.push({\n x: content.x - padding,\n y: content.y - padding,\n width: content.width + 2 * padding,\n height: content.height + 2 * padding,\n });\n }\n const axes = axesBox(canvas);\n if (axes) {\n boxes.push({\n x: axes.x - AXES_PADDING,\n y: axes.y - AXES_PADDING,\n width: axes.width + 2 * AXES_PADDING,\n height: axes.height + 2 * AXES_PADDING,\n });\n }\n\n const left = Math.floor(Math.min(...boxes.map((box) => box.x)));\n const top = Math.floor(Math.min(...boxes.map((box) => box.y)));\n const right = Math.ceil(Math.max(...boxes.map((box) => box.x + box.width)));\n const bottom = Math.ceil(Math.max(...boxes.map((box) => box.y + box.height)));\n return { x: left, y: top, width: right - left, height: bottom - top };\n}\n\n/**\n * The axes layer drawn by the evolution grid. Custom `y-axis` end labels and long `evolution`\n * stage names run past the fixed plot margins. Looked up in the DOM rather than via\n * `canvas.getLayer`, which would create the layer if it were missing.\n */\nfunction axesBox(canvas: Canvas): SvgBounds | undefined {\n try {\n const axes = canvas\n .getContainer()\n .querySelector<SVGGraphicsElement>(`.viewport > .layer-${AXES_LAYER}`);\n if (!axes) return undefined;\n const { x, y, width, height } = axes.getBBox();\n return width === 0 && height === 0 ? undefined : { x, y, width, height };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Union of the `.djs-visual` boxes in layer (= diagram) coordinates. Measuring the whole layer\n * would also count the invisible hit areas and selection outlines, which follow the estimated\n * shape size rather than the rendered text and would pad the export with empty space.\n */\nfunction drawnContentBox(canvas: Canvas): SvgBounds | undefined {\n // The typings declare a CanvasLayer record, but diagram-js returns the layer's <g> itself.\n const layer = canvas.getActiveLayer() as unknown as SVGGraphicsElement | null;\n if (!layer) return undefined;\n try {\n const layerToScreen = layer.getCTM();\n if (!layerToScreen) return undefined;\n const screenToLayer = layerToScreen.inverse();\n\n let left = Infinity;\n let top = Infinity;\n let right = -Infinity;\n let bottom = -Infinity;\n // diagram-js draws the previews of a move or create into the same layer; they are no part of\n // the document, and a cancelled drag would otherwise leave its box behind.\n const visuals = layer.querySelectorAll<SVGGraphicsElement>(\n \".djs-visual:not(.djs-drag-group .djs-visual)\",\n );\n for (const visual of visuals) {\n const local = visual.getBBox();\n const visualToScreen = visual.getCTM();\n if ((local.width === 0 && local.height === 0) || !visualToScreen) continue;\n const toLayer = screenToLayer.multiply(visualToScreen);\n for (const [x, y] of [\n [local.x, local.y],\n [local.x + local.width, local.y],\n [local.x, local.y + local.height],\n [local.x + local.width, local.y + local.height],\n ] as const) {\n const layerX = toLayer.a * x + toLayer.c * y + toLayer.e;\n const layerY = toLayer.b * x + toLayer.d * y + toLayer.f;\n left = Math.min(left, layerX);\n top = Math.min(top, layerY);\n right = Math.max(right, layerX);\n bottom = Math.max(bottom, layerY);\n }\n }\n if (![left, top, right, bottom].every(Number.isFinite)) return undefined;\n return { x: left, y: top, width: right - left, height: bottom - top };\n } catch {\n // getBBox/getCTM are unavailable outside a rendering engine (jsdom); the plot frame alone is\n // still a correct, if tighter, export.\n return undefined;\n }\n}\n","import type { MapConfig } from \"@miragon/wardley-schema-model\";\n\n/** ID of the diagram-js root element of the Wardley map. */\nexport const ROOT_ID = \"wardley-root\";\n\nexport interface ImportWarning {\n /** Human-readable, already including the line and source text for DSL findings. */\n readonly message: string;\n readonly elementId?: string;\n /** 1-based line of the DSL finding, for listing or jumping to the offending line. */\n readonly line?: number;\n /** The offending DSL source line as written. */\n readonly source?: string;\n}\n\n/** Map metadata stored on the root element (config + lossless passthrough). */\nexport interface RootBusinessObject {\n readonly config: MapConfig;\n readonly rawPassthrough?: readonly string[];\n}\n","import type { FreeRectInsets } from \"../free-rect/index.js\";\n\n/** An import never opens the map above 100 %, like the shell's fit and the other renderers. */\nexport const MAX_IMPORT_ZOOM = 1;\n\ninterface Box {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nconst NO_INSETS: FreeRectInsets = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/**\n * The viewbox that shows `bounds` centred in the free rectangle (`container` minus `insets`) at the\n * largest scale that fits, never above `MAX_IMPORT_ZOOM`. The box has the container's aspect\n * ratio, so `canvas.viewbox(box)` sets exactly this view. An axis the insets leave no room on\n * centres in the whole container. `undefined` for a 0 × 0 container or empty bounds.\n */\nexport function fitViewbox(\n bounds: Box,\n container: { width: number; height: number },\n insets: FreeRectInsets = NO_INSETS,\n): Box | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n if (!(bounds.width > 0 && bounds.height > 0)) return undefined;\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n const scale = Math.min(\n MAX_IMPORT_ZOOM,\n horizontal.extent / bounds.width,\n vertical.extent / bounds.height,\n );\n const box = {\n x: bounds.x + bounds.width / 2 - (horizontal.start + horizontal.extent / 2) / scale,\n y: bounds.y + bounds.height / 2 - (vertical.start + vertical.extent / 2) / scale,\n width: container.width / scale,\n height: container.height / scale,\n };\n return Object.values(box).every(Number.isFinite) ? box : undefined;\n}\n\nfunction freeExtent(\n total: number,\n before: number,\n after: number,\n): { start: number; extent: number } {\n const extent = total - before - after;\n return extent > 0 ? { start: before, extent } : { start: 0, extent: total };\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type { MapEdge, MapElement, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./types.js\";\nimport { fitViewbox } from \"./fitViewbox.js\";\n\n/** \"Frame\" types sit behind the connections (concept doc requirement: frames at the very back). */\nconst FRAME_TYPES: ReadonlySet<string> = new Set([\"attitude\", \"pipeline\"]);\n\n/** Z-order of the nodes among themselves: smaller number = further back. */\nconst TYPE_ORDER: Record<string, number> = {\n attitude: 0,\n pipeline: 1,\n note: 2,\n component: 3,\n anchor: 4,\n annotation: 5,\n submap: 3,\n accelerator: 3,\n};\n\n/** Diagram config `wardleyImport` (viewer option `fitOnImport`). */\nexport interface WardleyImportConfig {\n /** `false`: the host fits the view itself, the import leaves it alone. */\n fit?: boolean;\n}\n\n/**\n * Bridges the WardleyMap model into the diagram-js canvas.\n * Uses `evolutionGrid` exclusively for the pixel projection (P7). Deliberately bypasses the\n * commandStack (import path, P4 exception): no undo, no dirty (concept doc §5.6).\n */\nexport default class WardleyImporter {\n static $inject = [\n \"canvas\",\n \"elementFactory\",\n \"wardleyElementFactory\",\n \"evolutionGrid\",\n \"eventBus\",\n \"elementRegistry\",\n \"injector\",\n \"config.wardleyImport\",\n ];\n\n private readonly freeRect: FreeRect | null;\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementFactory: ElementFactory,\n private readonly factory: WardleyElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n injector: Injector,\n private readonly config: WardleyImportConfig | undefined,\n ) {\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n }\n\n import(map: WardleyMap): ImportWarning[] {\n const warnings: ImportWarning[] = [];\n this.eventBus.fire(\"import.render.start\", { map });\n\n this.grid.configure(map.config);\n\n const meta: RootBusinessObject = {\n config: map.config,\n ...(map.rawPassthrough ? { rawPassthrough: map.rawPassthrough } : {}),\n };\n\n // Reuse the existing root (re-import), otherwise create a new one.\n let existing: (Root & { businessObject?: RootBusinessObject }) | undefined;\n try {\n existing = this.canvas.getRootElement() as Root & { businessObject?: RootBusinessObject };\n } catch {\n existing = undefined;\n }\n let root: Root & { businessObject?: RootBusinessObject };\n if (existing && existing.id === ROOT_ID) {\n root = existing;\n } else {\n root = this.elementFactory.createRoot({ id: ROOT_ID }) as Root & {\n businessObject?: RootBusinessObject;\n };\n this.canvas.setRootElement(root);\n }\n root.businessObject = meta;\n\n this.grid.render();\n\n const shapeById = new Map<string, WardleyShape>();\n const ordered = [...map.elements].sort(\n (a, b) => (TYPE_ORDER[a.elementType] ?? 9) - (TYPE_ORDER[b.elementType] ?? 9),\n );\n\n // Z-order (back -> front): frames (attitude/pipeline) -> connections -> nodes.\n // Frames + nodes must be registered before the connections; the connections are then\n // inserted via parentIndex BEHIND the nodes (but before them in the DOM).\n const frames = ordered.filter((el) => FRAME_TYPES.has(el.elementType));\n const nodes = ordered.filter((el) => !FRAME_TYPES.has(el.elementType));\n\n let frameCount = 0;\n for (const el of frames) {\n const shape = this.createShape(el);\n if (!shape) continue;\n this.canvas.addShape(shape, root);\n shapeById.set(el.id, shape);\n frameCount++;\n }\n for (const el of nodes) {\n const shape = this.createShape(el);\n if (!shape) continue;\n this.canvas.addShape(shape, root);\n shapeById.set(el.id, shape);\n }\n\n const resolvedEdges: { edge: MapEdge; source: WardleyShape; target: WardleyShape }[] = [];\n for (const edge of map.edges) {\n const source = shapeById.get(edge.from);\n const target = shapeById.get(edge.to);\n if (!source || !target) {\n warnings.push({ message: `Edge ${edge.id}: endpoint missing.`, elementId: edge.id });\n continue;\n }\n resolvedEdges.push({ edge, source, target });\n }\n\n // Flows sit above dependencies so a dependency on the same pair cannot strike through the flow\n // value; within each group, a later declaration paints on top (like interactive creation).\n const connectionPaintOrder = [\n ...resolvedEdges.filter(({ edge }) => edge.edgeType !== \"flow\"),\n ...resolvedEdges.filter(({ edge }) => edge.edgeType === \"flow\"),\n ];\n let insertedConnections = 0;\n for (const { edge, source, target } of connectionPaintOrder) {\n const conn =\n edge.edgeType === \"flow\"\n ? this.factory.createFlow(edge, source, target)\n : this.factory.createDependency(edge, source, target);\n // Behind all nodes, in front of the frames and the connections inserted so far.\n this.canvas.addConnection(conn, root, frameCount + insertedConnections);\n insertedConnections++;\n }\n\n // Frames render BEFORE the nodes exist, but pipeline visuals depend on whether a\n // same-named anchor component exists — re-render them now that everything is in place.\n for (const el of frames) {\n const shape = shapeById.get(el.id);\n if (shape && el.elementType === \"pipeline\") {\n this.eventBus.fire(\"element.changed\", { element: shape });\n }\n }\n\n if (this.config?.fit !== false) this.fitPlot();\n this.eventBus.fire(\"import.render.done\", { warnings });\n return warnings;\n }\n\n /**\n * The plot with its axis margins, centred in the host's free rectangle, at most at 100 %: where\n * the host's own fit puts it. With a free area the pan constraint leaves it there; without one\n * it may still move a map smaller than the view to keep its own margins around it.\n */\n private fitPlot(): void {\n const plot = this.grid.outerBounds();\n const insets = this.freeRect?.insets();\n this.canvas.viewbox(fitViewbox(plot, this.canvas.getSize(), insets) ?? plot);\n }\n\n private createShape(el: MapElement): WardleyShape | undefined {\n return this.factory.createFromModel(el);\n }\n\n clear(): void {\n // Root elements are planes, not shapes: removing diagram-js's implicit root (created by any canvas\n // access before the first import) as a shape corrupts the canvas and breaks setRootElement.\n const roots = new Set<unknown>(this.canvas.getRootElements());\n for (const el of [...this.elementRegistry.getAll()]) {\n const e = el as { waypoints?: unknown; id: string };\n if (roots.has(el)) continue;\n try {\n if (e.waypoints) this.canvas.removeConnection(e.id);\n else this.canvas.removeShape(e.id);\n } catch {\n // already removed (e.g. edge on a removed shape) — ignore\n }\n }\n }\n}\n","import type { Shape, Connection } from \"diagram-js/lib/model/Types\";\nimport type {\n AcceleratorDirection,\n AttitudeKind,\n ComponentDecorators,\n DrawingStrokeStyle,\n LabelOffset,\n MapEdge,\n MapElement,\n Movement,\n} from \"@miragon/wardley-schema-model\";\n\n/**\n * diagram-js runtime model with Wardley extensions.\n *\n * The positional truth while editing is `evolution`/`visibility` (normalized), NOT `x`/`y` (pixels)\n * and NOT the `businessObject` (concept doc §2.2, §5.6).\n * `businessObject` is the identity/metadata backref to the original model element.\n */\n\nexport type WardleyShapeType =\n | \"component\"\n | \"anchor\"\n | \"pipeline\"\n | \"note\"\n | \"annotation\"\n | \"attitude\"\n | \"submap\"\n | \"accelerator\"\n | \"drawing\";\n\nexport type WardleyConnectionType = \"dependency\" | \"flow\";\n\nexport interface WardleyShape extends Shape {\n wardleyType: WardleyShapeType;\n /** normalized [0,1] — runtime truth of the X position. */\n evolution: number;\n /** normalized [0,1] — runtime truth of the Y position. */\n visibility: number;\n /** Display text (separate from diagram-js `label`, which references a label element). */\n wardleyLabel: string;\n /** OWM `label [dx, dy]` — px offset relative to the default label position. */\n labelOffset?: LabelOffset;\n decorators?: ComponentDecorators;\n movement?: Movement;\n /** pipeline only: evolution range. */\n evolutionStart?: number;\n evolutionEnd?: number;\n /** component only: membership in a pipeline (id) — runtime truth, maintained via drag. */\n pipelineId?: string;\n /** annotation only. */\n annotationNumber?: number;\n /** attitude region only. */\n attitudeKind?: AttitudeKind;\n /** attitude only: opposite corner (normalized), maintained by the EvolutionConstraintBehavior. */\n corner2?: { visibility: number; evolution: number };\n /** accelerator only. */\n acceleratorDirection?: AcceleratorDirection;\n /** drawing only: points in px RELATIVE to the shape's x/y (moving the shape moves them all). */\n drawingPoints?: Array<{ x: number; y: number }>;\n /** drawing only: closed polygon vs. open polyline. */\n closed?: boolean;\n /** drawing only. */\n strokeStyle?: DrawingStrokeStyle;\n /** Optional element color (CSS color/hex from the swatch palette) — any element type. */\n color?: string;\n businessObject?: MapElement;\n}\n\nexport interface WardleyConnection extends Connection {\n wardleyType: WardleyConnectionType;\n bidirectional?: boolean;\n flowValue?: string;\n /** annotation text after `;` (e.g. \"limited by\"). */\n linkLabel?: string;\n businessObject?: MapEdge;\n}\n\nfunction isObject(el: unknown): el is Record<string, unknown> {\n return typeof el === \"object\" && el !== null;\n}\n\nexport function isWardleyShape(el: unknown): el is WardleyShape {\n return isObject(el) && typeof el[\"wardleyType\"] === \"string\" && \"evolution\" in el;\n}\n\nconst CONNECTION_TYPES: ReadonlySet<unknown> = new Set<WardleyConnectionType>([\n \"dependency\",\n \"flow\",\n]);\n\n/**\n * Keyed on the type, not on `waypoints`: diagram-js lays out an interactively created connection only\n * inside `connection.create`'s execute, so pre-execute hooks (e.g. ordering) see it without them.\n */\nexport function isWardleyConnection(el: unknown): el is WardleyConnection {\n return isObject(el) && CONNECTION_TYPES.has(el[\"wardleyType\"]);\n}\n\nexport function isComponent(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"component\";\n}\n\nexport function isPipeline(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"pipeline\";\n}\n\nexport function isAttitude(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"attitude\";\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport {\n validateMap,\n CURRENT_SCHEMA_VERSION,\n DEFAULT_MAP_TITLE,\n type AnchorElement,\n type AnnotationElement,\n type AttitudeElement,\n type ComponentElement,\n type MapConfig,\n type MapEdge,\n type MapElement,\n type NoteElement,\n type PipelineElement,\n type SubmapElement,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleySourceOrder from \"./WardleySourceOrder.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"./types.js\";\n\nfunction compact<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\n/**\n * Reconstructs a WardleyMap from the diagram-js runtime model. The source of truth for positions are\n * the DI properties `evolution`/`visibility`; editable fields (label, decorators, movement,\n * pipeline range) are likewise read from the DI properties (concept doc §5.6). The\n * `businessObject` serves only as a fallback for type-specific fields that are not (yet) editable.\n */\nexport default class WardleyExporter {\n static $inject = [\"elementRegistry\", \"canvas\", \"evolutionGrid\", \"wardleySourceOrder\"];\n\n constructor(\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly sourceOrder: WardleySourceOrder,\n ) {}\n\n export(): WardleyMap {\n const root = this.canvas.getRootElement() as Root & { businessObject?: RootBusinessObject };\n const meta = root.businessObject;\n const config: MapConfig = meta?.config ?? { title: DEFAULT_MAP_TITLE };\n\n const unorderedElements: MapElement[] = [];\n const unorderedEdges: MapEdge[] = [];\n\n for (const el of this.elementRegistry.getAll()) {\n if (el.id === ROOT_ID) continue;\n if (isWardleyConnection(el)) {\n if (el.businessObject) {\n unorderedEdges.push(el.businessObject);\n } else {\n const base = { id: el.id, from: el.source?.id ?? \"\", to: el.target?.id ?? \"\" };\n unorderedEdges.push(\n el.wardleyType === \"flow\"\n ? { ...base, edgeType: \"flow\", ...(el.bidirectional ? { bidirectional: true } : {}) }\n : { ...base, edgeType: \"dependency\" },\n );\n }\n } else if (isWardleyShape(el)) {\n const built = this.buildElement(el);\n if (built) unorderedElements.push(built);\n }\n }\n const elements = this.sourceOrder.sortElements(unorderedElements);\n const edges = this.sourceOrder.sortEdges(unorderedEdges);\n\n // Consolidate pipeline membership: childIds are derived from component.pipelineId\n // (single source of truth); pipelineId references to deleted pipelines are discarded.\n const pipelineIds = new Set(\n elements.filter((e) => e.elementType === \"pipeline\").map((e) => e.id),\n );\n const consolidated = elements.map((el) => {\n if (el.elementType === \"component\" && el.pipelineId && !pipelineIds.has(el.pipelineId)) {\n const { pipelineId: _stale, ...rest } = el;\n return rest as MapElement;\n }\n if (el.elementType === \"pipeline\") {\n const childIds = elements\n .filter((e) => e.elementType === \"component\" && e.pipelineId === el.id)\n .map((e) => e.id);\n return { ...el, childIds };\n }\n return el;\n });\n\n const map: WardleyMap = {\n schemaVersion: CURRENT_SCHEMA_VERSION,\n config,\n elements: consolidated,\n edges,\n ...(meta?.rawPassthrough ? { rawPassthrough: meta.rawPassthrough } : {}),\n };\n\n return validateMap(map);\n }\n\n /** Builds a MapElement from the DI properties (common types) or the businessObject (the rest). */\n private buildElement(el: WardleyShape): MapElement | undefined {\n const position = { visibility: el.visibility, evolution: el.evolution };\n const bo = el.businessObject;\n\n switch (el.wardleyType) {\n case \"component\":\n return compact({\n id: el.id,\n elementType: \"component\",\n label: el.wardleyLabel,\n position,\n // labelOffset is not editable (yet); without the fallback it would be lost on\n // every export round trip.\n labelOffset: el.labelOffset ?? (bo as ComponentElement | undefined)?.labelOffset,\n decorators: el.decorators,\n movement: el.movement,\n // Membership is geometry-derived runtime truth (set on import, cleared when the box\n // moves away) — deliberately NO businessObject fallback.\n pipelineId: el.pipelineId,\n url: (bo as ComponentElement | undefined)?.url,\n color: el.color,\n }) as ComponentElement;\n case \"anchor\":\n return compact({\n id: el.id,\n elementType: \"anchor\",\n label: el.wardleyLabel,\n position,\n labelOffset: el.labelOffset ?? (bo as AnchorElement | undefined)?.labelOffset,\n color: el.color,\n }) as AnchorElement;\n case \"note\":\n return compact({\n id: el.id,\n elementType: \"note\",\n label: el.wardleyLabel,\n position,\n patternType: (bo as NoteElement | undefined)?.patternType,\n color: el.color,\n }) as NoteElement;\n case \"pipeline\":\n return {\n id: el.id,\n elementType: \"pipeline\",\n label: el.wardleyLabel,\n position,\n evolutionStart: el.evolutionStart ?? 0,\n evolutionEnd: el.evolutionEnd ?? 1,\n childIds: (bo as PipelineElement | undefined)?.childIds ?? [],\n ...(el.color ? { color: el.color } : {}),\n };\n case \"attitude\":\n return {\n id: el.id,\n elementType: \"attitude\",\n kind: el.attitudeKind ?? \"pioneers\",\n label: el.wardleyLabel,\n position,\n // corner2 is maintained by the EvolutionConstraintBehavior on move/resize/create.\n corner2: el.corner2 ??\n (bo as AttitudeElement | undefined)?.corner2 ?? {\n visibility: Math.max(0, position.visibility - 0.1),\n evolution: Math.min(1, position.evolution + 0.15),\n },\n ...(el.color ? { color: el.color } : {}),\n };\n case \"accelerator\":\n return {\n id: el.id,\n elementType: \"accelerator\",\n direction: el.acceleratorDirection ?? \"accelerate\",\n label: el.wardleyLabel,\n position,\n ...(el.color ? { color: el.color } : {}),\n };\n case \"annotation\": {\n // The marker shows positions[0]; additional positions (multi-point annotation) are\n // preserved from the businessObject instead of collapsing to a single point on round trip.\n const extraPositions = ((bo as AnnotationElement | undefined)?.positions ?? []).slice(1);\n return {\n id: el.id,\n elementType: \"annotation\",\n label: el.wardleyLabel,\n position,\n number: el.annotationNumber ?? 0,\n positions: [position, ...extraPositions],\n text: el.wardleyLabel,\n ...(el.color ? { color: el.color } : {}),\n };\n }\n case \"submap\":\n return compact({\n id: el.id,\n elementType: \"submap\",\n label: el.wardleyLabel,\n position,\n urlRef: (bo as SubmapElement | undefined)?.urlRef,\n color: el.color,\n }) as SubmapElement;\n case \"drawing\": {\n // Points are stored relative to the shape in px — convert back per point.\n const points = (el.drawingPoints ?? []).map((p) =>\n this.grid.fromCanvas({ x: el.x + p.x, y: el.y + p.y }),\n );\n if (points.length < 2) return undefined;\n return {\n id: el.id,\n elementType: \"drawing\",\n label: \"\",\n position: points[0]!,\n points,\n ...(el.closed ? { closed: true } : {}),\n ...(el.strokeStyle ? { strokeStyle: el.strokeStyle } : {}),\n ...(el.color ? { color: el.color } : {}),\n };\n }\n default: {\n const exhaustive: never = el.wardleyType;\n void exhaustive;\n return bo ? ({ ...bo, position } as MapElement) : undefined;\n }\n }\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { WardleyMap } from \"@miragon/wardley-schema-model\";\n\ninterface Identified {\n readonly id: string;\n}\n\n/**\n * Remembers the order in which elements and edges appeared in the imported map, so the export can\n * write them back in that order. The registry/DOM order cannot serve: it is the z-order (frames,\n * connections, nodes), and exporting in it reshuffles every hand-written file on the first edit.\n */\nexport default class WardleySourceOrder {\n static $inject = [\"eventBus\"];\n\n private elementIndex = new Map<string, number>();\n private edgeIndex = new Map<string, number>();\n\n constructor(eventBus: EventBus) {\n eventBus.on(\"import.render.start\", (event: { map: WardleyMap }) => this.remember(event.map));\n eventBus.on(\"diagram.clear\", () => this.remember({ elements: [], edges: [] }));\n }\n\n remember(map: Pick<WardleyMap, \"elements\" | \"edges\">): void {\n this.elementIndex = new Map(map.elements.map((element, index) => [element.id, index]));\n this.edgeIndex = new Map(map.edges.map((edge, index) => [edge.id, index]));\n }\n\n /** Imported elements in source order, followed by the rest in their given (creation) order. */\n sortElements<T extends Identified>(elements: readonly T[]): T[] {\n return sortBySourceIndex(elements, this.elementIndex);\n }\n\n /** Imported edges in source order, followed by the rest in their given (creation) order. */\n sortEdges<T extends Identified>(edges: readonly T[]): T[] {\n return sortBySourceIndex(edges, this.edgeIndex);\n }\n}\n\nfunction sortBySourceIndex<T extends Identified>(\n items: readonly T[],\n sourceIndex: ReadonlyMap<string, number>,\n): T[] {\n const indexOf = (item: T): number => sourceIndex.get(item.id) ?? Number.POSITIVE_INFINITY;\n // Array.prototype.sort is stable, so items without a source index keep their relative order.\n return [...items].sort((a, b) => {\n const left = indexOf(a);\n const right = indexOf(b);\n return left === right ? 0 : left < right ? -1 : 1;\n });\n}\n","import { COLORS } from \"../draw/styles.js\";\n\nexport interface SvgToPngOptions {\n /**\n * Pixel density factor relative to the SVG's own size (default 2). Lowered automatically where\n * the PNG would exceed the browser's canvas size limits.\n */\n readonly scale?: number;\n /** Leave the background transparent instead of filling it with the paper colour (slides, docs). */\n readonly transparent?: boolean;\n}\n\n/** Used when the SVG declares neither a usable width/height nor a viewBox. */\nconst FALLBACK_SIZE = { width: 1000, height: 700 } as const;\n\n/**\n * Stays below the canvas limits of current desktop browsers; beyond them `toBlob` yields nothing\n * and the export fails outright (e.g. a 5000 x 5000 plot at scale 4).\n */\nconst MAX_CANVAS_SIDE = 32_767;\nconst MAX_CANVAS_AREA = 2 ** 27;\n\n/**\n * Rasterizes a standalone SVG (e.g. from `saveSVG()`) into a PNG picture. Browser-only: needs\n * `Image`, `<canvas>` and object URLs. The PNG carries no embedded map source.\n */\nexport async function svgToPng(svg: string, options: SvgToPngOptions = {}): Promise<Blob> {\n const scale = options.scale ?? 2;\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(`PNG scale must be a positive number, got ${scale}.`);\n }\n const { width, height } = svgSize(svg);\n const url = URL.createObjectURL(new Blob([svg], { type: \"image/svg+xml\" }));\n try {\n const image = new Image();\n image.width = width;\n image.height = height;\n await new Promise<void>((resolve, reject) => {\n image.onload = () => resolve();\n image.onerror = () => reject(new Error(\"Could not render the SVG.\"));\n image.src = url;\n });\n const canvas = document.createElement(\"canvas\");\n const pixels = rasterSize(width, height, scale);\n canvas.width = pixels.width;\n canvas.height = pixels.height;\n const context = canvas.getContext(\"2d\");\n if (!context) throw new Error(\"Canvas 2D context not available.\");\n if (!options.transparent) {\n context.fillStyle = COLORS.paper;\n context.fillRect(0, 0, canvas.width, canvas.height);\n }\n context.drawImage(image, 0, 0, canvas.width, canvas.height);\n const png = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, \"image/png\"));\n if (!png) throw new Error(\"PNG generation failed.\");\n return png;\n } finally {\n URL.revokeObjectURL(url);\n }\n}\n\n/**\n * Pixel size of the PNG: the SVG size times `scale`, reduced proportionally where it would exceed\n * the browser's canvas limits, so a huge map still exports, just at a lower density.\n */\nexport function rasterSize(\n width: number,\n height: number,\n scale: number,\n): { width: number; height: number } {\n const fittingScale = Math.min(\n scale,\n MAX_CANVAS_SIDE / width,\n MAX_CANVAS_SIDE / height,\n Math.sqrt(MAX_CANVAS_AREA / (width * height)),\n );\n return {\n width: Math.max(1, Math.min(MAX_CANVAS_SIDE, Math.round(width * fittingScale))),\n height: Math.max(1, Math.min(MAX_CANVAS_SIDE, Math.round(height * fittingScale))),\n };\n}\n\n/** Blob -> Base64 without the data-URL prefix, e.g. to post an export to a VS Code extension host. */\nexport function blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result).split(\",\")[1] ?? \"\");\n reader.onerror = () => reject(new Error(\"Could not read the export blob.\"));\n reader.readAsDataURL(blob);\n });\n}\n\n/**\n * Reads the size from the root <svg> element only: a regex over the text would also match the\n * width of the first nested rect when the root has a relative size such as `100%`.\n */\nfunction svgSize(svg: string): { width: number; height: number } {\n const root = new DOMParser().parseFromString(svg, \"image/svg+xml\").documentElement;\n const width = absoluteLength(root.getAttribute(\"width\"));\n const height = absoluteLength(root.getAttribute(\"height\"));\n if (width && height) return { width, height };\n\n const viewBox = (root.getAttribute(\"viewBox\") ?? \"\")\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const [, , viewBoxWidth, viewBoxHeight] = viewBox;\n if (\n viewBox.length === 4 &&\n viewBoxWidth !== undefined &&\n viewBoxHeight !== undefined &&\n viewBoxWidth > 0 &&\n viewBoxHeight > 0\n ) {\n return { width: width ?? viewBoxWidth, height: height ?? viewBoxHeight };\n }\n return { width: width ?? FALLBACK_SIZE.width, height: height ?? FALLBACK_SIZE.height };\n}\n\nfunction absoluteLength(value: string | null): number | undefined {\n const match = /^\\s*(\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s*$/.exec(value ?? \"\");\n const length = match ? Number(match[1]) : NaN;\n return length > 0 ? length : undefined;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyImporter from \"./WardleyImporter.js\";\nimport WardleyExporter from \"./WardleyExporter.js\";\nimport WardleySourceOrder from \"./WardleySourceOrder.js\";\n\nexport const ioModule: ModuleDeclaration = {\n // Instantiated eagerly: it must observe the first import, long before anything exports.\n __init__: [\"wardleySourceOrder\"],\n wardleySourceOrder: [\"type\", WardleySourceOrder],\n wardleyImporter: [\"type\", WardleyImporter],\n wardleyExporter: [\"type\", WardleyExporter],\n};\n\nexport { default as WardleyImporter } from \"./WardleyImporter.js\";\nexport { default as WardleyExporter } from \"./WardleyExporter.js\";\nexport { default as WardleySourceOrder } from \"./WardleySourceOrder.js\";\nexport { saveSVG } from \"./saveSvg.js\";\nexport type { SvgBounds } from \"./saveSvg.js\";\nexport { exportBounds, EXPORT_CONTENT_PADDING } from \"./exportBounds.js\";\nexport { svgToPng, blobToBase64 } from \"./rasterize.js\";\nexport type { SvgToPngOptions } from \"./rasterize.js\";\nexport { ROOT_ID } from \"./types.js\";\nexport type { ImportWarning, RootBusinessObject } from \"./types.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type BaseLayouter from \"diagram-js/lib/layout/BaseLayouter\";\nimport type { Element, Root } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport type { MapConfig, MapSize, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport { withoutRawStatements } from \"@miragon/wardley-dsl\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyExporter from \"../io/WardleyExporter.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"../io/index.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { LivePreview } from \"../live-preview/index.js\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\nexport type WardleyRoot = Root & { businessObject?: RootBusinessObject };\n\ninterface ShapeGeometry {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n readonly drawingPoints?: Array<{ x: number; y: number }>;\n}\n\n/** Exact pixel state of the map, to undo a live preview without any rounding or clamping. */\nexport interface ProjectionSnapshot {\n readonly businessObject: RootBusinessObject;\n readonly shapes: ReadonlyMap<string, ShapeGeometry>;\n readonly waypoints: ReadonlyMap<string, Point[]>;\n}\n\n/** `config` with `size` set, or without the key when `size` is undefined. */\nexport function configWithSize(config: MapConfig, size: MapSize | undefined): MapConfig {\n const { size: _previous, ...rest } = config;\n return size ? { ...rest, size: { width: size.width, height: size.height } } : rest;\n}\n\n/**\n * The imported Wardley root, or undefined before the first import. Unlike\n * `canvas.getRootElement()` this never creates diagram-js's implicit root, which the next\n * import's `clear()` would remove and so break `setRootElement`.\n */\nexport function wardleyRootOf(canvas: Canvas): WardleyRoot | undefined {\n return canvas.getRootElements().find((root) => root.id === ROOT_ID) as WardleyRoot | undefined;\n}\n\n/**\n * `rawPassthrough` without unreadable `size` statements: once the map writes a valid size, a kept\n * one would be written after it, and OWM lets the last size line win. Comment text is never dropped.\n */\nexport function withoutRawSizeStatements(\n rawPassthrough: readonly string[] | undefined,\n): readonly string[] | undefined {\n return withoutRawStatements(rawPassthrough, \"size\");\n}\n\n/**\n * Re-projects the live shapes onto a new plot size in place — no re-import, so the shape objects,\n * the selection and the undo history survive. The normalized model is the truth; every element is\n * placed by the same factory projection the importer uses (P7), so a resize looks exactly like a\n * fresh import at the new size.\n */\nexport default class MapProjection {\n static $inject = [\n \"canvas\",\n \"elementRegistry\",\n \"evolutionGrid\",\n \"wardleyElementFactory\",\n \"wardleyExporter\",\n \"layouter\",\n \"eventBus\",\n \"wardleyLivePreview\",\n ];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly grid: EvolutionGrid,\n private readonly factory: WardleyElementFactory,\n private readonly exporter: WardleyExporter,\n private readonly layouter: BaseLayouter,\n private readonly eventBus: EventBus,\n private readonly livePreview: LivePreview,\n ) {}\n\n /** The Wardley root, or undefined before the first import. */\n root(): WardleyRoot | undefined {\n const root = wardleyRootOf(this.canvas);\n return root?.businessObject ? root : undefined;\n }\n\n /** The normalized truth, read under the CURRENT grid (drawings keep px-relative points). */\n captureModel(): WardleyMap {\n return this.exporter.export();\n }\n\n /**\n * Stores `businessObject` on the root, redraws the grid for its config and re-projects every\n * element of `model` onto it. Fires `wardley.config.changed`; returns the changed elements so\n * the caller (command stack or live preview) can redraw them.\n */\n apply(\n businessObject: RootBusinessObject,\n model: WardleyMap = this.captureModel(),\n options: { transient?: boolean } = {},\n ): Element[] {\n const root = this.root();\n if (!root) return [];\n if (options.transient) this.livePreview.begin(\"size\");\n root.businessObject = businessObject;\n this.grid.configure(businessObject.config);\n this.grid.render();\n\n const changed: Element[] = [];\n for (const element of model.elements) {\n const shape = this.elementRegistry.get(element.id);\n if (!isWardleyShape(shape)) continue;\n const template = this.factory.createFromModel(element);\n if (!template) continue;\n assignGeometry(shape, template);\n changed.push(shape);\n }\n changed.push(...this.layoutConnections());\n this.fireConfigChanged(businessObject.config, options.transient === true);\n return changed;\n }\n\n snapshot(): ProjectionSnapshot | undefined {\n const root = this.root();\n if (!root?.businessObject) return undefined;\n const shapes = new Map<string, ShapeGeometry>();\n const waypoints = new Map<string, Point[]>();\n for (const element of this.elementRegistry.getAll()) {\n if (isWardleyShape(element)) {\n shapes.set(element.id, {\n x: element.x,\n y: element.y,\n width: element.width,\n height: element.height,\n ...(element.drawingPoints\n ? { drawingPoints: element.drawingPoints.map((point) => ({ ...point })) }\n : {}),\n });\n } else if (isWardleyConnection(element)) {\n waypoints.set(\n element.id,\n element.waypoints.map((point) => ({ x: point.x, y: point.y })),\n );\n }\n }\n return { businessObject: root.businessObject, shapes, waypoints };\n }\n\n /**\n * Puts the size and every element's geometry back exactly as they were when `snapshot` was\n * taken. The rest of the root stays: an axis-label preview opened since then is no part of it.\n */\n restore(snapshot: ProjectionSnapshot, options: { transient?: boolean } = {}): Element[] {\n const root = this.root();\n const businessObject = this.withSize(snapshot.businessObject.config.size);\n if (!root || !businessObject) return [];\n root.businessObject = businessObject;\n this.grid.configure(businessObject.config);\n this.grid.render();\n const changed: Element[] = [];\n for (const [id, geometry] of snapshot.shapes) {\n const shape = this.elementRegistry.get(id);\n if (!isWardleyShape(shape)) continue;\n assignGeometry(shape, geometry);\n changed.push(shape);\n }\n for (const [id, points] of snapshot.waypoints) {\n const connection = this.elementRegistry.get(id);\n if (!isWardleyConnection(connection)) continue;\n connection.waypoints = points.map((point) => ({ ...point }));\n changed.push(connection);\n }\n this.livePreview.end(\"size\");\n this.fireConfigChanged(businessObject.config, options.transient === true);\n return changed;\n }\n\n /**\n * The live root with `size` set (removed when undefined), for a size preview; undefined before\n * the first import.\n */\n withSize(size: MapSize | undefined): RootBusinessObject | undefined {\n const businessObject = this.root()?.businessObject;\n return (\n businessObject && { ...businessObject, config: configWithSize(businessObject.config, size) }\n );\n }\n\n /** `transient` marks a live preview that is not part of the document (yet). */\n private fireConfigChanged(config: MapConfig, transient: boolean): void {\n this.eventBus.fire(\"wardley.config.changed\", { config, ...(transient ? { transient } : {}) });\n }\n\n /** Redraws elements changed outside the command stack (the live preview). */\n redraw(elements: readonly Element[]): void {\n for (const element of elements) this.eventBus.fire(\"element.changed\", { element });\n }\n\n private layoutConnections(): Element[] {\n const connections: Element[] = [];\n for (const element of this.elementRegistry.getAll()) {\n if (!isWardleyConnection(element)) continue;\n element.waypoints = this.layouter.layoutConnection(element);\n connections.push(element);\n }\n return connections;\n }\n}\n\nfunction assignGeometry(shape: WardleyShape, geometry: ShapeGeometry): void {\n shape.x = geometry.x;\n shape.y = geometry.y;\n shape.width = geometry.width;\n shape.height = geometry.height;\n if (geometry.drawingPoints) {\n shape.drawingPoints = geometry.drawingPoints.map((point) => ({ ...point }));\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { MapConfig, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport type WardleyExporter from \"../io/WardleyExporter.js\";\n\n/** The config fields a live preview changes: the plot size, the X-axis stage labels. */\nexport type PreviewedField = \"size\" | \"evolutionLabels\";\n\n/**\n * Fired before a command changes the document: `preExecute` for a command, `execute` for a redo\n * (which skips `preExecute`), `revert` for an undo.\n */\nexport const COMMAND_START_EVENTS = [\n \"commandStack.preExecute\",\n \"commandStack.execute\",\n \"commandStack.revert\",\n];\n\n/** Ahead of the other listeners of these events; the command's handler runs after all of them. */\nexport const PUT_BACK_PRIORITY = 10_000;\n\n/**\n * The document as it was committed while a live preview (a plot-resize drag, the size or the axis\n * labels being typed into a popover) shows something else on the canvas. A host autosaves the\n * export at any moment, also mid-drag, and must store the document, never the preview.\n */\nexport default class LivePreview {\n static $inject = [\"eventBus\", \"wardleyExporter\"];\n\n private committed: WardleyMap | undefined;\n private readonly previewed = new Set<PreviewedField>();\n\n constructor(\n eventBus: EventBus,\n private readonly exporter: WardleyExporter,\n ) {\n eventBus.on([\"import.render.start\", \"diagram.clear\"], () => this.endAll());\n // A command can land under an axis-label preview (a title a host sets) and changes the\n // document there; the preview itself only ever changes its own fields. A size preview is put\n // back before any command instead (MapResizeHandles, WardleyBaseViewer).\n eventBus.on(\"commandStack.changed\", () => {\n if (this.committed) this.committed = this.withCommittedFields(this.exporter.export());\n });\n }\n\n /** Before a preview changes `field` on the canvas: keeps the document as it is now. */\n begin(field: PreviewedField): void {\n this.committed ??= this.exporter.export();\n this.previewed.add(field);\n }\n\n /**\n * The canvas shows the committed `field` again (its preview was put back or is being\n * committed). The preview of the other field may still be open and keeps its committed value.\n */\n end(field: PreviewedField): void {\n this.previewed.delete(field);\n if (!this.previewed.size) this.committed = undefined;\n }\n\n /** The committed document while a preview is open, `undefined` while none is. */\n committedMap(): WardleyMap | undefined {\n return this.committed;\n }\n\n private endAll(): void {\n this.previewed.clear();\n this.committed = undefined;\n }\n\n private withCommittedFields(live: WardleyMap): WardleyMap {\n const config: Record<string, unknown> = { ...live.config };\n const committedConfig = this.committed?.config as Partial<MapConfig> | undefined;\n for (const field of this.previewed) {\n if (committedConfig?.[field] === undefined) delete config[field];\n else config[field] = committedConfig[field];\n }\n return { ...live, config: config as unknown as MapConfig };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport LivePreview from \"./LivePreview.js\";\n\n/** The committed document behind a live preview (map size, axis labels). */\nexport const livePreviewModule: ModuleDeclaration = {\n wardleyLivePreview: [\"type\", LivePreview],\n};\n\nexport { default as LivePreview, COMMAND_START_EVENTS, PUT_BACK_PRIORITY } from \"./LivePreview.js\";\n","import RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\n\n/** Fired with `{ readOnly }` whenever the lock changes. */\nexport const READ_ONLY_CHANGED = \"wardley.readOnly.changed\";\n\n/** On the viewer container while locked: the CSS hides the editing handles. */\nconst LOCKED_CLASS = \"wardley-read-only\";\n\n/** Ahead of every rule of the notation, so nothing can allow what the lock forbids. */\nconst VETO_PRIORITY = 5000;\n\nconst EDIT_RULES = [\n \"elements.move\",\n \"shape.move\",\n \"shape.create\",\n \"elements.create\",\n \"shape.resize\",\n \"shape.append\",\n \"shape.replace\",\n \"connection.start\",\n \"connection.create\",\n \"connection.reconnect\",\n \"connection.reconnectStart\",\n \"connection.reconnectEnd\",\n \"connection.updateWaypoints\",\n \"elements.delete\",\n];\n\ninterface Closable {\n close(): void;\n}\n\ninterface Cancellable {\n cancel(): void;\n}\n\n/**\n * Locks every edit on the canvas while a host cannot save what the canvas would change: an\n * invalid file in an IDE shows the last valid map read-only until the text is valid again (guide\n * §13.5). The rules veto move, resize, create, connect and delete; the context pad, the label,\n * link and colour editors, the evolve, label and drawing handles, the map-size handles, the draw\n * tool and the edit keys ask `isReadOnly()`. Selection, zoom, pan, copy and export stay.\n */\nexport default class WardleyReadOnly extends RuleProvider {\n static override $inject = [\"eventBus\", \"canvas\", \"injector\"];\n\n private locked = false;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly injector: Injector,\n ) {\n super(eventBus);\n }\n\n override init(): void {\n // `this.locked` is read when a rule runs; the field is not initialized yet while init() runs.\n this.addRule(EDIT_RULES, VETO_PRIORITY, () => (this.locked ? false : undefined));\n }\n\n isReadOnly(): boolean {\n return this.locked;\n }\n\n setReadOnly(readOnly: boolean): void {\n if (this.locked === readOnly) return;\n this.locked = readOnly;\n this.outerContainer().classList.toggle(LOCKED_CLASS, readOnly);\n if (readOnly) this.endInteractions();\n this.injector.get<EventBus>(\"eventBus\").fire(READ_ONLY_CHANGED, { readOnly });\n }\n\n /** Whatever is open or running would otherwise still change the map. */\n private endInteractions(): void {\n this.injector.get<Cancellable | null>(\"dragging\", false)?.cancel();\n for (const name of [\"contextPad\", \"popupMenu\", \"wardleyColorPicker\"]) {\n this.injector.get<Closable | null>(name, false)?.close();\n }\n for (const name of [\"wardleyLabelEditing\", \"wardleyLinkEditing\", \"wardleyDrawTool\"]) {\n this.injector.get<Cancellable | null>(name, false)?.cancel();\n }\n }\n\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n}\n","import type { Injector } from \"didi\";\nimport type { ModuleDeclaration } from \"didi\";\nimport WardleyReadOnly from \"./WardleyReadOnly.js\";\n\n/** The edit lock of a canvas that shows a map the host cannot save (guide §13.5). */\nexport const readOnlyModule: ModuleDeclaration = {\n __init__: [\"wardleyReadOnly\"],\n wardleyReadOnly: [\"type\", WardleyReadOnly],\n};\n\n/** Whether the canvas is locked; false where the editor has no lock. */\nexport function isReadOnly(injector: Injector): boolean {\n return injector.get<WardleyReadOnly | null>(\"wardleyReadOnly\", false)?.isReadOnly() === true;\n}\n\nexport { default as WardleyReadOnly, READ_ONLY_CHANGED } from \"./WardleyReadOnly.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\n\n/** The focusable canvas svg diagram-js renders into its container. */\nexport function canvasSvg(canvas: Canvas): SVGElement | null {\n return (\n (canvas as unknown as { _svg?: SVGElement })._svg ??\n canvas.getContainer().querySelector<SVGElement>(\":scope > svg\")\n );\n}\n\n/**\n * Moves keyboard focus to the canvas after a pointer gesture or an editor commit. Pointer work\n * must not light up the keyboard focus ring around the whole viewport, and a press that suppressed\n * the browser's own focus change must still take focus away from host inputs (title, size\n * fields), or Delete/Undo would edit those instead of the map.\n */\nexport function focusCanvasWithoutRing(canvas: Canvas): void {\n const svg = canvasSvg(canvas);\n if (!svg) {\n canvas.focus();\n return;\n }\n svg.focus({ preventScroll: true, focusVisible: false } as FocusOptions);\n}\n\nlet lastInteraction: \"pointer\" | \"keyboard\" = \"pointer\";\nlet modalityTracked = false;\n\n/**\n * Starts following whether the user last used the pointer or the keyboard (idempotent). Editors\n * opened with the pointer hand focus back without the keyboard focus ring.\n */\nexport function trackInputModality(): void {\n if (modalityTracked || typeof document === \"undefined\") return;\n modalityTracked = true;\n document.addEventListener(\"pointerdown\", () => (lastInteraction = \"pointer\"), true);\n document.addEventListener(\"mousedown\", () => (lastInteraction = \"pointer\"), true);\n document.addEventListener(\n \"keydown\",\n (event) => {\n // Typing into an editor says nothing about how it was opened.\n if (!(event.target instanceof HTMLElement && event.target.closest(\"input, textarea\"))) {\n lastInteraction = \"keyboard\";\n }\n },\n true,\n );\n}\n\nexport function lastInteractionWasPointer(): boolean {\n return lastInteraction === \"pointer\";\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport { canvasSvg } from \"./canvasFocus.js\";\n\n/** Names the focusable canvas for assistive technology (it is otherwise an anonymous svg). */\nexport default function describeCanvas(canvas: Canvas): void {\n const svg = canvasSvg(canvas);\n if (!svg) return;\n svg.setAttribute(\"role\", \"application\");\n svg.setAttribute(\"aria-roledescription\", \"Wardley map\");\n svg.setAttribute(\"aria-label\", \"Map canvas\");\n}\ndescribeCanvas.$inject = [\"canvas\"];\n","import type { ModuleDeclaration } from \"didi\";\nimport describeCanvas from \"./describeCanvas.js\";\n\n/** Names the canvas for assistive technology (role, role description, label). */\nexport const canvasAccessibilityModule: ModuleDeclaration = {\n __init__: [describeCanvas],\n};\n\nexport {\n canvasSvg,\n focusCanvasWithoutRing,\n lastInteractionWasPointer,\n trackInputModality,\n} from \"./canvasFocus.js\";\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport {\n MAP_SIZE_PRESETS,\n PLOT_MAX,\n PLOT_MIN,\n normalizeMapSize,\n type MapSize,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { PLOT } from \"../draw/styles.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type MapProjection from \"./MapProjection.js\";\nimport type { ProjectionSnapshot } from \"./MapProjection.js\";\nimport { COMMAND_START_EVENTS, PUT_BACK_PRIORITY } from \"../live-preview/index.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\n\nexport const MAP_RESIZE_PREFIX = \"wardley.mapResize\";\n\n/** Above the axes (-1), below the element planes (0): elements at the plot edge win hit tests. */\nconst LAYER_NAME = \"wardley-map-resize\";\nconst LAYER_INDEX = -0.5;\n\nconst SNAP_STEP = 10;\nconst PRESET_SNAP_DISTANCE = 12;\n/** Handle sizes in screen px: they keep a grabbable size at every zoom level. */\nconst EDGE_HIT_WIDTH = 8;\nconst CORNER_HIT_SIZE = 16;\nconst CORNER_VISUAL_SIZE = 10;\nconst BADGE_OFFSET = 16;\n\nexport type ResizeAxis = \"x\" | \"y\" | \"xy\";\n\nconst CURSORS: Record<ResizeAxis, string> = {\n x: \"ew-resize\",\n y: \"ns-resize\",\n xy: \"nwse-resize\",\n};\n\ninterface MapResizeContext {\n axis: ResizeAxis;\n startSize: MapSize;\n snapshot?: ProjectionSnapshot;\n model?: WardleyMap;\n size?: MapSize;\n committed?: boolean;\n}\n\ninterface MapResizeEvent {\n context: MapResizeContext;\n dx: number;\n dy: number;\n originalEvent?: MouseEvent;\n}\n\ninterface ModifierKeys {\n /** Keep the start aspect ratio. */\n keepAspectRatio: boolean;\n /** Free size: no 10px steps, no preset magnet. */\n disableSnapping: boolean;\n}\n\n/** The part of `wardleyModeling` the handles use (by DI name, to keep the features decoupled). */\ninterface MapResizeModeling {\n resizeMap(size: MapSize | undefined): void;\n}\n\ninterface Handle {\n readonly group: SVGGElement;\n readonly hit: SVGRectElement;\n readonly visual: SVGElement;\n}\n\nfunction round(value: number, step: number): number {\n return Math.round(value / step) * step;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n/**\n * Paint-free presentation attributes: the SVG export clones this layer without the stylesheet,\n * where a bare rect would fill black. Set as attributes (tiny-svg would inline them as style),\n * so the stylesheet still wins and shows the handles on hover.\n */\nfunction withoutPaint<T extends SVGElement>(element: T): T {\n element.setAttribute(\"fill\", \"none\");\n element.setAttribute(\"stroke\", \"none\");\n element.setAttribute(\"opacity\", \"0\");\n return element;\n}\n\n/**\n * The size a drag from `start` by (dx, dy) on `axis` asks for: 10px steps with a magnetic pull\n * towards the presets, Shift keeps the start aspect ratio, always whole pixels within the limits.\n */\nexport function sizeForDrag(\n start: MapSize,\n axis: ResizeAxis,\n dx: number,\n dy: number,\n keys: ModifierKeys = { keepAspectRatio: false, disableSnapping: false },\n): MapSize {\n let width = axis === \"y\" ? start.width : start.width + dx;\n let height = axis === \"x\" ? start.height : start.height + dy;\n const step = keys.disableSnapping ? 1 : SNAP_STEP;\n\n if (keys.keepAspectRatio) {\n const ratio = start.width / start.height;\n const widthDrives =\n axis === \"x\" ||\n (axis === \"xy\" &&\n Math.abs(width - start.width) / start.width >=\n Math.abs(height - start.height) / start.height);\n if (widthDrives) {\n width = clamp(round(width, step), PLOT_MIN.width, PLOT_MAX.width);\n height = width / ratio;\n } else {\n height = clamp(round(height, step), PLOT_MIN.height, PLOT_MAX.height);\n width = height * ratio;\n }\n return normalizeMapSize(width, height);\n }\n\n if (!keys.disableSnapping) {\n const preset = MAP_SIZE_PRESETS.find(\n (candidate) =>\n Math.abs(width - candidate.width) <= PRESET_SNAP_DISTANCE &&\n Math.abs(height - candidate.height) <= PRESET_SNAP_DISTANCE,\n );\n if (preset) return { width: preset.width, height: preset.height };\n }\n return normalizeMapSize(\n axis === \"y\" ? width : round(width, step),\n axis === \"x\" ? height : round(height, step),\n );\n}\n\n/** \"1440 × 900 · Large\" — the preset name only when the size matches one exactly. */\nexport function sizeLabel(size: MapSize): string {\n const preset = MAP_SIZE_PRESETS.find(\n (candidate) => candidate.width === size.width && candidate.height === size.height,\n );\n return `${size.width} × ${size.height}${preset ? ` · ${preset.name}` : \"\"}`;\n}\n\n/**\n * Direct manipulation of the map size: handles on the plot's right edge, bottom edge and\n * bottom-right corner. The drag previews live (grid and shapes re-projected, no command stack);\n * on release the preview is undone and exactly ONE `wardley.map.resize` runs, so a drag is one\n * undo step. Esc cancels; a double-click on the corner resets to the default size.\n */\nexport default class MapResizeHandles {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"evolutionGrid\",\n \"dragging\",\n \"wardleyMapProjection\",\n \"wardleyModeling\",\n \"injector\",\n ];\n\n private readonly layer: SVGGElement;\n private readonly handles: Record<ResizeAxis, Handle>;\n private badge: HTMLElement | undefined;\n private scale: number | undefined;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly dragging: Dragging,\n private readonly projection: MapProjection,\n private readonly modeling: MapResizeModeling,\n private readonly injector: Injector,\n ) {\n this.layer = svgCreate(\"g\", { class: \"wardley-map-resize\" }) as SVGGElement;\n svgAppend(canvas.getLayer(LAYER_NAME, LAYER_INDEX), this.layer);\n this.handles = {\n x: this.createHandle(\"x\"),\n y: this.createHandle(\"y\"),\n xy: this.createHandle(\"xy\"),\n };\n this.handles.xy.group.addEventListener(\"dblclick\", (event) => {\n event.stopPropagation();\n event.preventDefault();\n if (isReadOnly(this.injector)) return;\n this.modeling.resizeMap(undefined);\n });\n\n eventBus.on([\"import.done\", \"wardley.config.changed\"], () => this.render());\n eventBus.on(\"canvas.viewbox.changed\", (event: { viewbox?: { scale?: number } }) => {\n const scale = event.viewbox?.scale;\n if (scale === this.scale) return;\n this.scale = scale;\n this.render();\n });\n eventBus.on(`${MAP_RESIZE_PREFIX}.start`, (event: MapResizeEvent) => this.onStart(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.move`, (event: MapResizeEvent) => this.onMove(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.end`, (event: MapResizeEvent) => this.onEnd(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.cleanup`, (event: MapResizeEvent) => this.onCleanup(event));\n // The preview re-projects the map the drag started with and puts it back on release, which\n // would overwrite a command in between (an undo or a delete pressed mid-drag) and leave the\n // history out of step with the document: the drag ends first, without resizing.\n eventBus.on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => this.cancelPreviewingDrag());\n this.render();\n }\n\n private cancelPreviewingDrag(): void {\n const drag = this.dragging.context() as {\n prefix?: string;\n data?: { context?: MapResizeContext };\n } | null;\n if (drag?.prefix !== MAP_RESIZE_PREFIX) return;\n const context = drag.data?.context;\n if (context?.snapshot && !context.committed) this.dragging.cancel(true);\n }\n\n /** Starts a resize drag on `axis` (also usable programmatically, e.g. from tests). */\n start(event: MouseEvent, axis: ResizeAxis): void {\n if (isReadOnly(this.injector)) return;\n const context: MapResizeContext = { axis, startSize: this.grid.getPlotSize() };\n this.dragging.init(event, MAP_RESIZE_PREFIX, {\n cursor: CURSORS[axis],\n keepSelection: true,\n data: { context },\n });\n }\n\n private createHandle(axis: ResizeAxis): Handle {\n const group = svgCreate(\"g\", {\n class: `wardley-map-resize-handle wardley-map-resize-${axis}`,\n \"data-axis\": axis,\n }) as SVGGElement;\n const visual = withoutPaint(\n svgCreate(axis === \"xy\" ? \"rect\" : \"line\", { class: \"wardley-map-resize-visual\" }),\n );\n const hit = withoutPaint(\n svgCreate(\"rect\", { class: \"wardley-map-resize-hit\" }) as SVGRectElement,\n );\n svgAppend(group, visual);\n svgAppend(group, hit);\n svgAppend(this.layer, group);\n // Own listener on the handle: stopping here keeps the canvas (pan, lasso, deselect) from\n // also reacting to this mousedown, and the prevented default from focusing it, whose keys\n // (Cmd/Ctrl+Z) act only while it has the focus.\n group.addEventListener(\"mousedown\", (event: MouseEvent) => {\n if (event.button !== 0 || this.dragging.context()) return;\n event.stopPropagation();\n event.preventDefault();\n focusCanvasWithoutRing(this.canvas);\n this.start(event, axis);\n });\n return { group, hit, visual };\n }\n\n private render(): void {\n const visible = this.projection.root() !== undefined;\n svgAttr(this.layer, { display: visible ? \"inline\" : \"none\" });\n if (!visible) return;\n\n const { width, height } = this.grid.getPlotSize();\n const left = PLOT.marginLeft;\n const top = PLOT.marginTop;\n const right = left + width;\n const bottom = top + height;\n const screenPixel = 1 / this.currentScale();\n const edgeHitWidth = EDGE_HIT_WIDTH * screenPixel;\n const half = edgeHitWidth / 2;\n const cornerHitSize = CORNER_HIT_SIZE * screenPixel;\n const cornerHalf = cornerHitSize / 2;\n const cornerVisualSize = CORNER_VISUAL_SIZE * screenPixel;\n\n // The edges stop short of the corner (its own handle) and of the axis arrowheads.\n svgAttr(this.handles.x.hit, {\n x: right - half,\n y: top,\n width: edgeHitWidth,\n height: Math.max(height - cornerHalf, 0),\n });\n svgAttr(this.handles.x.visual, { x1: right, y1: top, x2: right, y2: bottom });\n svgAttr(this.handles.y.hit, {\n x: left,\n y: bottom - half,\n width: Math.max(width - cornerHalf, 0),\n height: edgeHitWidth,\n });\n svgAttr(this.handles.y.visual, { x1: left, y1: bottom, x2: right, y2: bottom });\n svgAttr(this.handles.xy.hit, {\n x: right - cornerHalf,\n y: bottom - cornerHalf,\n width: cornerHitSize,\n height: cornerHitSize,\n });\n svgAttr(this.handles.xy.visual, {\n x: right - cornerVisualSize / 2,\n y: bottom - cornerVisualSize / 2,\n width: cornerVisualSize,\n height: cornerVisualSize,\n });\n }\n\n private currentScale(): number {\n if (this.scale === undefined) {\n try {\n this.scale = this.canvas.viewbox().scale;\n } catch {\n return 1; // detached container: nothing to measure yet\n }\n }\n return Number.isFinite(this.scale) && this.scale > 0 ? this.scale : 1;\n }\n\n private onStart(event: MapResizeEvent): void {\n const context = event.context;\n const snapshot = this.projection.snapshot();\n if (!snapshot) return;\n context.snapshot = snapshot;\n context.model = this.projection.captureModel();\n this.layer.classList.add(\"is-dragging\");\n }\n\n private onMove(event: MapResizeEvent): void {\n const context = event.context;\n if (!context.snapshot || !context.model) return;\n const size = sizeForDrag(context.startSize, context.axis, event.dx, event.dy, {\n keepAspectRatio: event.originalEvent?.shiftKey === true,\n disableSnapping: event.originalEvent?.altKey === true,\n });\n this.showBadge(size, event.originalEvent);\n if (context.size?.width === size.width && context.size.height === size.height) return;\n context.size = size;\n const businessObject = this.projection.withSize(size);\n if (!businessObject) return;\n this.projection.redraw(\n this.projection.apply(businessObject, context.model, { transient: true }),\n );\n }\n\n private onEnd(event: MapResizeEvent): void {\n const context = event.context;\n if (!context.snapshot) return;\n // Undo the preview first: the command must capture the real start state as its old state.\n this.projection.redraw(this.projection.restore(context.snapshot, { transient: true }));\n context.committed = true;\n const { size, startSize } = context;\n if (size && (size.width !== startSize.width || size.height !== startSize.height)) {\n this.modeling.resizeMap(size);\n }\n }\n\n private onCleanup(event: MapResizeEvent): void {\n const context = event.context;\n // Transient like the preview it undoes: the document never changed, so the view stays put.\n if (context.snapshot && !context.committed) {\n this.projection.redraw(this.projection.restore(context.snapshot, { transient: true }));\n }\n this.layer.classList.remove(\"is-dragging\");\n this.hideBadge();\n }\n\n private showBadge(size: MapSize, originalEvent: MouseEvent | undefined): void {\n const container = this.canvas.getContainer();\n if (!this.badge) {\n this.badge = document.createElement(\"div\");\n this.badge.className = \"wardley-map-resize-badge\";\n this.badge.setAttribute(\"role\", \"status\");\n container.appendChild(this.badge);\n }\n this.badge.textContent = sizeLabel(size);\n this.badge.hidden = false;\n if (originalEvent) {\n const bounds = container.getBoundingClientRect();\n this.badge.style.left = `${originalEvent.clientX - bounds.left + BADGE_OFFSET}px`;\n this.badge.style.top = `${originalEvent.clientY - bounds.top + BADGE_OFFSET}px`;\n }\n }\n\n private hideBadge(): void {\n if (this.badge) this.badge.hidden = true;\n }\n}\n","import AutoScroll from \"diagram-js/lib/features/auto-scroll/AutoScroll\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Injector } from \"didi\";\nimport { MAP_RESIZE_PREFIX } from \"./MapResizeHandles.js\";\n\n/**\n * diagram-js AutoScroll, except while the map is being resized: scrolling under a dragged plot\n * corner detaches it from the pointer, and the size jumps on the next move.\n */\nexport default class ResizeAwareAutoScroll extends AutoScroll {\n static override $inject = [\"config.autoScroll\", \"eventBus\", \"canvas\", \"injector\"];\n\n constructor(\n config: unknown,\n eventBus: EventBus,\n canvas: Canvas,\n private readonly injector: Injector,\n ) {\n super(config, eventBus, canvas);\n }\n\n override startScroll(point: Parameters<AutoScroll[\"startScroll\"]>[0]): void {\n const dragging = this.injector.get<Dragging | null>(\"dragging\", false);\n if (dragging?.context()?.prefix === MAP_RESIZE_PREFIX) {\n this.stopScroll();\n return;\n }\n super.startScroll(point);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport DraggingModule from \"diagram-js/lib/features/dragging\";\nimport MapProjection from \"./MapProjection.js\";\nimport MapResizeHandles from \"./MapResizeHandles.js\";\nimport { livePreviewModule } from \"../live-preview/index.js\";\n\n/** In-place re-projection of all shapes onto a new plot size (used by `wardley.map.resize`). */\nexport const mapProjectionModule: ModuleDeclaration = {\n __depends__: [livePreviewModule],\n wardleyMapProjection: [\"type\", MapProjection],\n};\n\n/**\n * Plot edge/corner handles to resize the map by dragging (Modeler only). Needs the\n * `wardleyModeling` service, i.e. load it together with `wardleyModelingModule`.\n */\nexport const mapResizeModule: ModuleDeclaration = {\n __depends__: [DraggingModule, mapProjectionModule],\n __init__: [\"mapResizeHandles\"],\n mapResizeHandles: [\"type\", MapResizeHandles],\n};\n\nexport {\n default as MapResizeHandles,\n MAP_RESIZE_PREFIX,\n sizeForDrag,\n sizeLabel,\n} from \"./MapResizeHandles.js\";\nexport type { ResizeAxis } from \"./MapResizeHandles.js\";\nexport {\n default as MapProjection,\n configWithSize,\n withoutRawSizeStatements,\n wardleyRootOf,\n} from \"./MapProjection.js\";\nexport type { ProjectionSnapshot, WardleyRoot } from \"./MapProjection.js\";\nexport { default as ResizeAwareAutoScroll } from \"./ResizeAwareAutoScroll.js\";\n","import type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type { MapConfig } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../../evolution-grid/EvolutionGrid.js\";\nimport { wardleyRootOf } from \"../../map-resize/index.js\";\n\n/**\n * Config fields a `wardley.config.update` may change; `undefined` removes the field. The size is\n * excluded on purpose: it needs the re-projection of `wardley.map.resize`.\n */\nexport type MapConfigUpdate = {\n -readonly [Key in Exclude<keyof MapConfig, \"size\">]?: MapConfig[Key] | undefined;\n};\n\nexport interface UpdateConfigContext {\n properties: MapConfigUpdate;\n /** set internally by the handler (for revert). */\n oldProperties?: MapConfigUpdate;\n}\n\n/**\n * Writes `update` into the root's config (`undefined` removes a field; `size` is left alone, it\n * needs the re-projection of `wardley.map.resize`), redraws the axes and fires\n * `wardley.config.changed`. Returns the previous values of exactly the written fields. The one place\n * a config changes in place: the undoable command and the viewers' direct path both use it.\n */\nexport function applyConfigUpdate(\n canvas: Canvas,\n grid: EvolutionGrid,\n eventBus: EventBus,\n update: MapConfigUpdate,\n options: { transient?: boolean } = {},\n): MapConfigUpdate {\n const root = wardleyRootOf(canvas);\n if (!root?.businessObject) return {};\n const previous: Record<string, unknown> = {};\n const config: Record<string, unknown> = { ...root.businessObject.config };\n for (const [key, value] of Object.entries(update)) {\n if (key === \"size\") continue;\n previous[key] = config[key];\n if (value === undefined) delete config[key];\n else config[key] = value;\n }\n const nextConfig = config as unknown as MapConfig;\n root.businessObject = { ...root.businessObject, config: nextConfig };\n grid.configure(nextConfig);\n grid.render();\n eventBus.fire(\"wardley.config.changed\", {\n config: nextConfig,\n ...(options.transient ? { transient: true } : {}),\n });\n return previous as MapConfigUpdate;\n}\n\n/**\n * Undoable change of map config fields (title, evolution labels, …). Only the given fields are\n * swapped, so it composes with any other config change in the undo history.\n */\nexport default class UpdateConfigHandler implements CommandHandler {\n static $inject = [\"canvas\", \"evolutionGrid\", \"eventBus\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly eventBus: EventBus,\n ) {}\n\n execute(context: UpdateConfigContext): ElementLike[] {\n context.oldProperties = this.apply(context.properties);\n return [];\n }\n\n revert(context: UpdateConfigContext): ElementLike[] {\n if (context.oldProperties) this.apply(context.oldProperties);\n return [];\n }\n\n private apply(properties: MapConfigUpdate): MapConfigUpdate {\n return applyConfigUpdate(this.canvas, this.grid, this.eventBus, properties);\n }\n}\n","import Diagram from \"diagram-js/lib/Diagram\";\nimport type { ModuleDeclaration } from \"didi\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport {\n DEFAULT_MAP_TITLE,\n normalizeEvolutionLabels,\n normalizeMapSize,\n sameEvolutionLabels,\n presetIdForSize,\n validateMap,\n type MapConfig,\n type MapSize,\n type MapSizePresetId,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { parseDSLWithDiagnostics, serializeDSL } from \"@miragon/wardley-dsl\";\nimport { saveSVG } from \"./io/saveSvg.js\";\nimport { exportBounds } from \"./io/exportBounds.js\";\nimport type WardleyImporter from \"./io/WardleyImporter.js\";\nimport type WardleyExporter from \"./io/WardleyExporter.js\";\nimport type EvolutionGrid from \"./evolution-grid/EvolutionGrid.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./io/types.js\";\nimport {\n configWithSize,\n wardleyRootOf,\n withoutRawSizeStatements,\n type default as MapProjection,\n type ProjectionSnapshot,\n} from \"./map-resize/MapProjection.js\";\nimport type WardleyModeling from \"./modeling/WardleyModeling.js\";\nimport type { FreeArea } from \"@miragon/modeler-api\";\nimport type { FreeRectConfig } from \"./free-rect/index.js\";\nimport { COMMAND_START_EVENTS, PUT_BACK_PRIORITY, type LivePreview } from \"./live-preview/index.js\";\nimport { applyConfigUpdate, type MapConfigUpdate } from \"./modeling/cmd/UpdateConfigHandler.js\";\n\nexport interface WardleyViewerOptions {\n /** Host element. If missing, a detached <div> is created (can be attached later via attachTo). */\n container?: HTMLElement;\n width?: number | string;\n height?: number | string;\n /** Concatenated to the end of the module list (extension point, §12). */\n additionalModules?: ModuleDeclaration[];\n /**\n * The part of the canvas no host chrome covers (`@miragon/modeler-api` `freeArea`), read\n * whenever it is needed. `{ insets }` names what the chrome covers along the container's edges,\n * in px (e.g. `() => shell.fitInsets()` of the Miragon modeler shell): the import fits the plot\n * into the rest, panning keeps the map inside it, and keyboard creation places elements in its\n * centre. `{ center }` gives only that centre, in diagram coordinates. Default: the whole\n * container.\n */\n freeArea?: FreeArea | undefined;\n /**\n * Fit the plot into the view after every import. Default `true`; `false` when the host's chrome\n * fits the view itself.\n */\n fitOnImport?: boolean | undefined;\n /**\n * Bind Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z and Cmd/Ctrl+Y to the canvas history. Default `true`;\n * `false` leaves them to the host (e.g. VS Code, which owns the document's undo stack).\n */\n undoRedoKeys?: boolean | undefined;\n}\n\n/** The diagram config the viewer options stand for. */\nfunction diagramConfig(options: WardleyViewerOptions): Record<string, unknown> {\n const undoRedo = options.undoRedoKeys;\n const freeArea: FreeRectConfig | undefined = options.freeArea\n ? options.freeArea.insets\n ? { insets: options.freeArea.insets }\n : { center: options.freeArea.center }\n : undefined;\n return {\n ...(undoRedo === undefined ? {} : { wardleyKeyboard: { undoRedo } }),\n ...(freeArea ? { wardleyFreeRect: freeArea } : {}),\n ...(options.fitOnImport === false ? { wardleyImport: { fit: false } } : {}),\n };\n}\n\nexport type EventCallback<T = unknown> = (event: T) => void;\n\n/** The plot size as drawn, plus whether the map writes it explicitly (`size [w, h]`). */\nexport interface MapSizeInfo {\n width: number;\n height: number;\n isExplicit: boolean;\n presetId?: MapSizePresetId;\n}\n\n/** Payload of `wardley.config.changed`: title, size or axis labels changed. */\nexport interface WardleyConfigChangedEvent {\n config: MapConfig;\n /** A live preview (typing, dragging the plot corner): not a change to persist. */\n transient?: true;\n}\n\nexport interface SetEvolutionLabelsOptions {\n /** Live preview: applied directly, without an undo step (commit later without this flag). */\n transient?: boolean;\n}\n\nexport interface SetMapSizeOptions {\n /** Live preview: drawn at once, without an undo step (commit later without this flag). */\n transient?: boolean;\n}\n\ntype EvolutionLabels = readonly [string, string, string, string];\n\n/** diagram-js names its implicit roots so; an element of that id would replace the plane. */\nconst IMPLICIT_ROOT_PREFIX = \"__implicitroot\";\n\n/** `map`, validated, or a throw when the canvas cannot hold it. */\nfunction importableMap(map: WardleyMap): WardleyMap {\n const checked = validateMap(map);\n const reserved = [...checked.elements, ...checked.edges].find(\n ({ id }) => id === ROOT_ID || id.startsWith(IMPLICIT_ROOT_PREFIX),\n );\n if (reserved) throw new Error(`The id \"${reserved.id}\" is reserved for the canvas itself.`);\n return checked;\n}\n\nfunction sizeToCss(value: number | string): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\n/**\n * The drag of a palette tool that only waits for its next press (the lasso from the palette or\n * `L`): no gesture yet. It holds no element of the map, so an import leaves the tool armed, and the\n * user's next press still draws a lasso instead of panning or moving the element under the pointer.\n */\nconst ARMED_TOOL_PREFIXES: ReadonlySet<string> = new Set([\"lasso.selection\"]);\n\n/** Ahead of every other listener of a drop, so that the command it runs finds the drop marked. */\nconst DROP_MARK_PRIORITY = 100_000;\n\ntype DragContext = { prefix: string } | null;\n\n/**\n * Ends a running diagram-js drag (a move, resize, connect, lasso, evolve or plot-resize drag, a\n * create from the palette or the context pad) the way Escape does. The gesture holds the elements an\n * import is about to replace, and diagram-js keeps it running across the import: released after it,\n * its command would fail half-way and leave the command stack stuck, so no later edit would fire\n * `commandStack.changed` again. The selection is not restored, since it holds those elements too.\n * A drawing's point drag is no diagram-js drag: it ends by itself when the import removes its\n * drawing.\n *\n * A drop that runs (`dropping`) is left to finish: its command has applied, and a host that imports\n * from that command's change listener would otherwise cancel the drag inside diagram-js's own end\n * of it, which then cleans up a drag that is gone and throws.\n */\nfunction cancelGesture(diagram: Diagram, dropping: DragContext): void {\n const dragging = diagram.get<Dragging | null>(\"dragging\", false);\n const gesture = dragging?.context() as DragContext | undefined;\n if (!dragging || !gesture || gesture === dropping) return;\n if (!ARMED_TOOL_PREFIXES.has(gesture.prefix)) dragging.cancel(false);\n}\n\n/**\n * Shared lifecycle & DI bootstrap for all Wardley viewers (analogous to bpmn-js BaseViewer, but OUR\n * OWN code — no bpmn-js as a dependency, §3.3). Subclasses only override `_getModules()` (a method\n * rather than a field, to sidestep the constructor/field initialization order). `attachTo`/`detach`\n * are own implementations (not a diagram-js primitive, §6.1).\n */\nexport abstract class WardleyBaseViewer {\n protected abstract _getModules(): ModuleDeclaration[];\n\n private _diagram: Diagram | undefined;\n private readonly _container: HTMLElement;\n private readonly _options: WardleyViewerOptions;\n /** Labels before the first transient preview, so the commit becomes one undo step from there. */\n private _labelsBeforePreview: { labels: EvolutionLabels | undefined } | undefined;\n /** The map before the first transient size preview, put back before the size is committed. */\n private _sizePreview: { snapshot: ProjectionSnapshot; model: WardleyMap } | undefined;\n /** The drag whose drop runs now, from its end until its cleanup. */\n private _dropping: DragContext = null;\n\n constructor(options: WardleyViewerOptions = {}) {\n this._options = options;\n this._container = this._createContainer(options);\n }\n\n private _createContainer(options: WardleyViewerOptions): HTMLElement {\n const container = options.container ?? document.createElement(\"div\");\n container.classList.add(\"wardley-container\");\n container.style.width = sizeToCss(options.width ?? \"100%\");\n container.style.height = sizeToCss(options.height ?? (options.container ? \"100%\" : \"600px\"));\n return container;\n }\n\n private _ensureDiagram(): Diagram {\n if (!this._diagram) {\n const modules = [...this._getModules(), ...(this._options.additionalModules ?? [])];\n this._diagram = new Diagram({\n canvas: { container: this._container },\n modules,\n ...diagramConfig(this._options),\n });\n // The size preview re-projects the map it started with and puts it back before its commit,\n // which would overwrite a command in between (a title a host sets mid-preview) and leave\n // the history out of step with the document: the preview goes first.\n this._diagram\n .get<EventBus>(\"eventBus\")\n .on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => this._putBackSizePreview());\n this._markDrops(this._diagram);\n }\n return this._diagram;\n }\n\n private _markDrops(diagram: Diagram): void {\n const dragging = diagram.get<Dragging | null>(\"dragging\", false);\n if (!dragging) return;\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n eventBus.on(\"drag.end\", DROP_MARK_PRIORITY, () => {\n this._dropping = dragging.context() as DragContext;\n });\n eventBus.on(\"drag.cleanup\", DROP_MARK_PRIORITY, () => {\n this._dropping = null;\n });\n }\n\n get<T>(name: string): T {\n return this._ensureDiagram().get<T>(name);\n }\n\n on<T = unknown>(event: string, callback: EventCallback<T>, priority = 1000): void {\n this.get<EventBus>(\"eventBus\").on(event, priority, callback as EventCallback);\n }\n\n off(event: string, callback: EventCallback): void {\n this.get<EventBus>(\"eventBus\").off(event, callback);\n }\n\n /**\n * Load a model into the canvas (replaces existing content). Rejects a map the canvas cannot\n * hold (invalid, or ids the canvas reserves for itself) before anything changes, so the current\n * map, its rendering and its undo history stay as they were. A gesture that runs ends first, as\n * on Escape, so its release applies nothing; an armed lasso tool stays armed, and an import from\n * the change listener of a drop leaves that drop to finish, with its change applied.\n */\n async importMap(map: WardleyMap): Promise<{ warnings: ImportWarning[] }> {\n const checked = importableMap(map);\n const diagram = this._ensureDiagram();\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const importer = diagram.get<WardleyImporter>(\"wardleyImporter\");\n const commandStack = diagram.get<CommandStack>(\"commandStack\", false);\n // Kept to put back if rendering fails half-way: a blank canvas is no way to fail an import.\n const previous = this._rootBusinessObject() ? this.exportMap() : undefined;\n this._labelsBeforePreview = undefined;\n this._sizePreview = undefined;\n cancelGesture(diagram, this._dropping);\n importer.clear();\n let warnings: ImportWarning[];\n try {\n warnings = importer.import(checked);\n } catch (error) {\n importer.clear();\n if (previous) importer.import(previous);\n // The history pointed at the shapes the failed render removed.\n commandStack?.clear();\n eventBus.fire(\"import.done\", { warnings: [] });\n throw error;\n }\n // Discard the PREVIOUS map's undo history (concept doc §5.6): undo on orphaned\n // elements would otherwise crash or insert zombie elements into the new map.\n // The read-only Viewer has no command stack.\n commandStack?.clear();\n eventBus.fire(\"import.done\", { warnings });\n return { warnings };\n }\n\n /** Load OWM DSL text (internally parse -> importMap). Parser findings land in the warnings. */\n async importDSL(text: string): Promise<{ warnings: ImportWarning[] }> {\n const eventBus = this._ensureDiagram().get<EventBus>(\"eventBus\");\n eventBus.fire(\"import.parse.start\", { text });\n const { map, diagnostics } = parseDSLWithDiagnostics(text);\n eventBus.fire(\"import.parse.done\", { map, diagnostics });\n const { warnings } = await this.importMap(map);\n return {\n warnings: [\n ...diagnostics.map((d) => ({\n message: `Line ${d.line}: ${d.message} (\"${d.text}\")`,\n line: d.line,\n source: d.text,\n })),\n ...warnings,\n ],\n };\n }\n\n /** Current state as the canonical model (from the DI properties). */\n exportMap(): WardleyMap {\n return this.get<WardleyExporter>(\"wardleyExporter\").export();\n }\n\n /**\n * Sets the plot size in diagram-px. The size is normalized first (whole pixels, clamped to\n * PLOT_MIN..PLOT_MAX); non-finite input throws a RangeError before anything changes. In the\n * Modeler this is one undoable step that re-projects the shapes in place (selection, viewport and\n * history survive); the read-only viewers re-import. An explicit size line is written even for\n * the default size — only `resetMapSize` removes it. In the Modeler `{ transient: true }` shows\n * a live preview without an undo step, and the next call without it commits ONE step from the\n * size before the preview (none when the size ends where the preview started), like\n * `setEvolutionLabels`. A command before that call (e.g. `setTitle`) puts the preview back first.\n */\n async setMapSize(\n width: number,\n height: number,\n options: SetMapSizeOptions = {},\n ): Promise<{ warnings: ImportWarning[] }> {\n return this._resizeMap(normalizeMapSize(width, height), options);\n }\n\n /** Removes the `size` line: the map is drawn at the default plot size again. */\n async resetMapSize(options: SetMapSizeOptions = {}): Promise<{ warnings: ImportWarning[] }> {\n return this._resizeMap(undefined, options);\n }\n\n private async _resizeMap(\n size: MapSize | undefined,\n options: SetMapSizeOptions,\n ): Promise<{ warnings: ImportWarning[] }> {\n const modeling = this._wardleyModeling();\n if (!modeling) return this._reimportWithSize(size);\n const projection = this.get<MapProjection>(\"wardleyMapProjection\");\n if (options.transient) {\n if (!this._sizePreview) {\n const snapshot = projection.snapshot();\n if (!snapshot) return { warnings: [] };\n this._sizePreview = { snapshot, model: projection.captureModel() };\n }\n const businessObject = projection.withSize(size);\n if (!businessObject) return { warnings: [] };\n projection.redraw(\n projection.apply(businessObject, this._sizePreview.model, { transient: true }),\n );\n return { warnings: [] };\n }\n // The command must take the size before the preview as its old state.\n this._putBackSizePreview();\n modeling.resizeMap(size);\n return { warnings: [] };\n }\n\n /** Shows the map without the size preview again, if one is open. */\n private _putBackSizePreview(): void {\n if (!this._sizePreview) return;\n const projection = this.get<MapProjection>(\"wardleyMapProjection\");\n const { snapshot } = this._sizePreview;\n this._sizePreview = undefined;\n projection.redraw(projection.restore(snapshot, { transient: true }));\n }\n\n getMapSize(): MapSizeInfo {\n const { width, height } = this.get<EvolutionGrid>(\"evolutionGrid\").getPlotSize();\n const presetId = presetIdForSize({ width, height });\n return {\n width,\n height,\n isExplicit: this._rootBusinessObject()?.config.size !== undefined,\n ...(presetId ? { presetId } : {}),\n };\n }\n\n private async _reimportWithSize(\n size: { width: number; height: number } | undefined,\n ): Promise<{ warnings: ImportWarning[] }> {\n if (!this._rootBusinessObject()) return { warnings: [] };\n const map = this.exportMap();\n const current = map.config.size;\n const unchanged = size\n ? current?.width === size.width && current.height === size.height\n : current === undefined;\n if (unchanged) return { warnings: [] };\n const rawPassthrough = withoutRawSizeStatements(map.rawPassthrough);\n const { rawPassthrough: _previous, ...rest } = map;\n return this.importMap({\n ...rest,\n config: configWithSize(map.config, size),\n ...(rawPassthrough?.length ? { rawPassthrough } : {}),\n });\n }\n\n /**\n * Sets the map title (one undoable step in the Modeler). Line breaks become spaces so the DSL\n * `title` line stays one line; an empty title falls back to the default.\n */\n setTitle(title: string): void {\n const cleaned = title.replace(/\\s*[\\r\\n]+\\s*/g, \" \").trim() || DEFAULT_MAP_TITLE;\n const modeling = this._wardleyModeling();\n if (modeling) modeling.updateConfig({ title: cleaned });\n else this._applyConfigDirectly({ title: cleaned });\n }\n\n /**\n * Sets the four X-axis stage labels (`undefined` = default Genesis/Custom/Product/Commodity).\n * Empty stages fall back to their default and a `->` becomes `→`, so the labels always write a\n * valid `evolution` line; the default set is stored as `undefined`.\n * Changes only the labeling, not the geometry (no re-import -> no view jump, no selection loss).\n * In the Modeler this is one undoable step; `{ transient: true }` applies a live preview without\n * an undo step, and the next non-transient call commits it as ONE step from the state before the\n * preview (no step at all when the labels end where the preview started). Fires\n * `wardley.config.changed` (`{ config, transient? }`): transient events are live previews and\n * must not be persisted; in the Modeler every committed change is followed by\n * `commandStack.changed`.\n */\n setEvolutionLabels(\n requested: readonly string[] | undefined,\n options: SetEvolutionLabelsOptions = {},\n ): void {\n // Labels that would break the `evolution` line (empty stage, `->`) never reach the map.\n const labels = normalizeEvolutionLabels(requested);\n const modeling = this._wardleyModeling();\n if (options.transient && modeling) {\n if (!this._labelsBeforePreview) {\n const businessObject = this._rootBusinessObject();\n if (!businessObject) return;\n this._labelsBeforePreview = { labels: businessObject.config.evolutionLabels };\n }\n this._livePreview()?.begin(\"evolutionLabels\");\n this._applyConfigDirectly({ evolutionLabels: labels }, { transient: true });\n return;\n }\n if (modeling) {\n if (this._labelsBeforePreview) {\n const before = this._labelsBeforePreview.labels;\n this._applyConfigDirectly({ evolutionLabels: before });\n this._livePreview()?.end(\"evolutionLabels\");\n this._labelsBeforePreview = undefined;\n // A preview that ends where it started (typed, then reverted) is no edit: no undo step.\n if (sameEvolutionLabels(before, labels)) return;\n }\n modeling.updateConfig({ evolutionLabels: labels });\n return;\n }\n this._applyConfigDirectly({ evolutionLabels: labels });\n }\n\n /**\n * Config change without the command stack (read-only viewers, live previews): updates the root\n * config in place and re-renders only the axis background.\n */\n private _applyConfigDirectly(\n update: MapConfigUpdate,\n options: { transient?: boolean } = {},\n ): void {\n applyConfigUpdate(\n this.get<Canvas>(\"canvas\"),\n this.get<EvolutionGrid>(\"evolutionGrid\"),\n this.get<EventBus>(\"eventBus\"),\n update,\n options,\n );\n }\n\n /** The Modeler's command API, or null in the read-only viewers. */\n private _wardleyModeling(): WardleyModeling | null {\n return this._ensureDiagram().get<WardleyModeling>(\"wardleyModeling\", false);\n }\n\n private _livePreview(): LivePreview | null {\n return this._ensureDiagram().get<LivePreview>(\"wardleyLivePreview\", false);\n }\n\n private _root(): (Root & { businessObject?: RootBusinessObject }) | undefined {\n return wardleyRootOf(this.get<Canvas>(\"canvas\"));\n }\n\n private _rootBusinessObject(): RootBusinessObject | undefined {\n return this._root()?.businessObject;\n }\n\n exportDSL(): string {\n return serializeDSL(this.exportMap());\n }\n\n /**\n * Static, standalone SVG covering the whole plot (at its actual `config.size`) plus any content\n * drawn beyond it, such as long labels of commodity components.\n */\n async saveSVG(): Promise<{ svg: string }> {\n const canvas = this.get<Canvas>(\"canvas\");\n return saveSVG(canvas, exportBounds(canvas, this.get<EvolutionGrid>(\"evolutionGrid\")));\n }\n\n /** Own implementation (not a diagram-js primitive): attach the container to `target`. */\n attachTo(target: HTMLElement): void {\n target.appendChild(this._container);\n this.get<Canvas>(\"canvas\").resized();\n }\n\n /** Own implementation: detach the container from the DOM, keeping state. */\n detach(): void {\n this._container.remove();\n }\n\n clear(): void {\n this._ensureDiagram().clear();\n }\n\n destroy(): void {\n if (this._diagram) {\n this._diagram.destroy();\n this._diagram = undefined;\n }\n this._container.remove();\n }\n\n get container(): HTMLElement {\n return this._container;\n }\n}\n","import BaseLayouter, { type LayoutConnectionHints } from \"diagram-js/lib/layout/BaseLayouter\";\nimport type { ConnectionLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { isPipeline } from \"../model/di-types.js\";\n\ninterface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Docking point of a node: pipelines dock at their ■ anchor (top-edge center), not the box. */\nexport function connectionAnchorOf(shape: Bounds): Point {\n if (isPipeline(shape)) return { x: shape.x + shape.width / 2, y: shape.y };\n return { x: shape.x + shape.width / 2, y: shape.y + shape.height / 2 };\n}\n\n/**\n * The renderer draws every connection from docking point to docking point, ignoring its waypoints —\n * but diagram-js builds the connection's hit band from the waypoints. So they must always span the\n * same docking points, not diagram-js's hints (box mid, or the point where a connect drag ended).\n * The hints only count for an endpoint without a node (connection preview following the cursor).\n */\nexport default class WardleyLayouter extends BaseLayouter {\n override layoutConnection(\n connection: ConnectionLike,\n hints: LayoutConnectionHints = {},\n ): Point[] {\n const source = hints.source ?? connection[\"source\"];\n const target = hints.target ?? connection[\"target\"];\n return super.layoutConnection(connection, {\n ...hints,\n ...(source ? { connectionStart: connectionAnchorOf(source) } : {}),\n ...(target ? { connectionEnd: connectionAnchorOf(target) } : {}),\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLayouter from \"./WardleyLayouter.js\";\n\n/** Replaces diagram-js's mid-to-mid `layouter` — load after the diagram-js ModelingModule. */\nexport const wardleyLayoutModule: ModuleDeclaration = {\n layouter: [\"type\", WardleyLayouter],\n};\n\nexport { default as WardleyLayouter, connectionAnchorOf } from \"./WardleyLayouter.js\";\n","import type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type {\n AcceleratorDirection,\n AcceleratorElement,\n AnchorElement,\n AnnotationElement,\n AttitudeElement,\n AttitudeKind,\n ComponentElement,\n DrawingElement,\n MapEdge,\n MapElement,\n NoteElement,\n PipelineElement,\n SubmapElement,\n} from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport { NODE_SIZE, PIPELINE_HEIGHT, noteMetrics } from \"../draw/styles.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\nimport type { WardleyConnection, WardleyShape } from \"./di-types.js\";\n\n/** Element types that edges and DSL lines reference by name — their labels must be unique. */\nconst LINKABLE_TYPES: ReadonlySet<string> = new Set([\n \"component\",\n \"anchor\",\n \"submap\",\n \"pipeline\",\n \"accelerator\",\n]);\n\nfunction isLinkableType(type: unknown): boolean {\n return typeof type === \"string\" && LINKABLE_TYPES.has(type);\n}\n\n/**\n * First label not in `taken`: `base` itself, otherwise the next counter. A base that already ends\n * in a counter continues it ('Cup 2' -> 'Cup 3') instead of stacking ('Cup 2 2').\n */\nexport function nextFreeLabel(base: string, taken: ReadonlySet<string>): string {\n if (!taken.has(base)) return base;\n const counterMatch = / (\\d+)$/.exec(base);\n const stem = counterMatch ? base.slice(0, counterMatch.index) : base;\n let counter = counterMatch ? Number(counterMatch[1]) + 1 : 2;\n while (taken.has(`${stem} ${counter}`)) counter++;\n return `${stem} ${counter}`;\n}\n\nexport interface CreateNewExtra {\n attitudeKind?: AttitudeKind;\n acceleratorDirection?: AcceleratorDirection;\n annotationNumber?: number;\n market?: boolean;\n ecosystem?: boolean;\n}\n\n/**\n * Creates diagram-js runtime elements with Wardley markers. Projects normalized coordinates to\n * pixels via the SINGLE math source (EvolutionGrid, P7).\n */\nexport default class WardleyElementFactory {\n static $inject = [\"elementFactory\", \"evolutionGrid\", \"elementRegistry\"];\n\n constructor(\n private readonly elementFactory: ElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n ) {}\n\n /**\n * Returns a unique label: `base`, otherwise `base 2`, `base 3`, … Unique labels are mandatory\n * because the OWM DSL references elements BY THEIR NAME — duplicate names would cause ID\n * collisions on serialize/re-import and lose edges (lines). Only linkable elements count:\n * notes and regions are never referenced, so their text must not force a suffix.\n *\n * @param excludeId optional ID of the element currently being renamed (does NOT count its own\n * current name as a collision — otherwise every rename would add a suffix).\n */\n uniqueLabel(base: string, excludeId?: string): string {\n return nextFreeLabel(\n base,\n this.takenLinkableLabels(excludeId, this.pairableTypeFor(excludeId)),\n );\n }\n\n /**\n * Batch variant for pasted copies: linkable labels unique against the map AND each other;\n * everything else keeps its text.\n */\n uniqueLabels(entries: ReadonlyArray<{ type: unknown; label: string }>): string[] {\n const taken = this.takenLinkableLabels();\n return entries.map(({ type, label }) => {\n if (!isLinkableType(type)) return label;\n const unique = nextFreeLabel(label, taken);\n taken.add(unique);\n return unique;\n });\n }\n\n /** Whether elements of `type` are referenced by name (and so need a unique label). */\n isLinkable(type: unknown): boolean {\n return isLinkableType(type);\n }\n\n /**\n * @param pairableType elements of this type that still lack their OWM partner do not block a\n * name: a standalone component may take the name of a pipeline without an anchor (and so\n * anchor it), and such a pipeline may take the name of a free standalone component.\n */\n private takenLinkableLabels(excludeId?: string, pairableType?: \"component\" | \"pipeline\") {\n const taken = new Set<string>();\n for (const el of this.elementRegistry.getAll()) {\n if (excludeId && el.id === excludeId) continue;\n const { wardleyType, wardleyLabel } = el as { wardleyType?: unknown; wardleyLabel?: unknown };\n if (!isLinkableType(wardleyType) || typeof wardleyLabel !== \"string\") continue;\n if (wardleyType === pairableType && this.isUnpaired(el as WardleyShape)) continue;\n taken.add(wardleyLabel);\n }\n return taken;\n }\n\n /** Which partner type the element being renamed may share its new name with. */\n private pairableTypeFor(excludeId?: string): \"component\" | \"pipeline\" | undefined {\n const renamed = excludeId\n ? (this.elementRegistry.getAll().find((el) => el.id === excludeId) as\n WardleyShape | undefined)\n : undefined;\n if (!renamed || !this.isUnpaired(renamed)) return undefined;\n if (renamed.wardleyType === \"component\") return \"pipeline\";\n if (renamed.wardleyType === \"pipeline\") return \"component\";\n return undefined;\n }\n\n /**\n * A pipeline without an anchor component, or a standalone (non-member) component that anchors\n * no pipeline. Members never pair: they belong to their own pipeline.\n */\n private isUnpaired(shape: WardleyShape): boolean {\n const shapes = this.elementRegistry.getAll() as WardleyShape[];\n if (shape.wardleyType === \"pipeline\") {\n return !shapes.some(\n (other) =>\n other.wardleyType === \"component\" &&\n other.wardleyLabel === shape.wardleyLabel &&\n other.pipelineId !== shape.id,\n );\n }\n if (shape.wardleyType !== \"component\" || shape.pipelineId) return false;\n return !shapes.some(\n (other) => other.wardleyType === \"pipeline\" && other.wardleyLabel === shape.wardleyLabel,\n );\n }\n\n /** Next free annotation number (max + 1) — palette annotations therefore never collide. */\n private nextAnnotationNumber(): number {\n let max = 0;\n for (const el of this.elementRegistry.getAll()) {\n const n = (el as { annotationNumber?: unknown }).annotationNumber;\n if (typeof n === \"number\" && n > max) max = n;\n }\n return max + 1;\n }\n\n createComponent(el: ComponentElement): WardleyShape {\n const shape = this.node(\n \"component\",\n el.id,\n el.label,\n el.position.visibility,\n el.position.evolution,\n el,\n {\n ...(el.decorators ? { decorators: el.decorators } : {}),\n ...(el.movement ? { movement: el.movement } : {}),\n ...(el.labelOffset ? { labelOffset: el.labelOffset } : {}),\n ...(el.pipelineId ? { pipelineId: el.pipelineId } : {}),\n },\n );\n // Pipeline children sit INSIDE the box (whose top edge is the anchor line) — shift their\n // pixel position to the box center; visibility (model truth) stays the pipeline's.\n if (el.pipelineId) shape.y += PIPELINE_HEIGHT / 2;\n return shape;\n }\n\n createAnchor(el: AnchorElement): WardleyShape {\n return this.node(\"anchor\", el.id, el.label, el.position.visibility, el.position.evolution, el, {\n ...(el.labelOffset ? { labelOffset: el.labelOffset } : {}),\n });\n }\n\n createNote(el: NoteElement): WardleyShape {\n // Note box grows with the (possibly multiline) text -> move/click hitbox covers the text.\n // Centered on the position (consistent with the center back-calculation on move).\n const { width, height } = noteMetrics(el.label);\n const center = this.grid.toCanvas(el.position);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x: center.x - width / 2,\n y: center.y - height / 2,\n width,\n height,\n wardleyType: \"note\",\n wardleyLabel: el.label,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createPipeline(el: PipelineElement): WardleyShape {\n const start = this.grid.toCanvas({\n visibility: el.position.visibility,\n evolution: el.evolutionStart,\n });\n const end = this.grid.toCanvas({\n visibility: el.position.visibility,\n evolution: el.evolutionEnd,\n });\n const width = Math.max(end.x - start.x, 2);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x: start.x,\n // The box's TOP EDGE is the anchor line — the ■ square straddles it (drawn by the renderer).\n y: start.y,\n width,\n height: PIPELINE_HEIGHT,\n wardleyType: \"pipeline\",\n wardleyLabel: el.label,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n evolutionStart: el.evolutionStart,\n evolutionEnd: el.evolutionEnd,\n // Frame: only the border is clickable -> inner clicks reach the nodes (diagram-js isFrame).\n isFrame: true,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createAnnotation(el: AnnotationElement): WardleyShape {\n const pos = el.positions[0] ?? el.position;\n return this.node(\"annotation\", el.id, el.text, pos.visibility, pos.evolution, el, {\n annotationNumber: el.number,\n });\n }\n\n createAccelerator(el: AcceleratorElement): WardleyShape {\n return this.node(\n \"accelerator\",\n el.id,\n el.label,\n el.position.visibility,\n el.position.evolution,\n el,\n {\n acceleratorDirection: el.direction,\n },\n );\n }\n\n createAttitude(el: AttitudeElement): WardleyShape {\n // OWM canon: position = top-left corner, corner2 = bottom-right corner (both normalized).\n const a = this.grid.toCanvas(el.position);\n const b = this.grid.toCanvas(el.corner2);\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x,\n y,\n width: Math.max(Math.abs(b.x - a.x), 4),\n height: Math.max(Math.abs(b.y - a.y), 4),\n wardleyType: \"attitude\",\n wardleyLabel: el.label || el.kind,\n attitudeKind: el.kind,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n corner2: el.corner2,\n isFrame: true,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createSubmap(el: SubmapElement): WardleyShape {\n return this.node(\"submap\", el.id, el.label, el.position.visibility, el.position.evolution, el);\n }\n\n createDrawing(el: DrawingElement): WardleyShape {\n const canvasPoints = el.points.map((p) => this.grid.toCanvas(p));\n return this.drawingFromCanvasPoints(canvasPoints, {\n id: el.id,\n ...(el.closed ? { closed: true } : {}),\n ...(el.strokeStyle ? { strokeStyle: el.strokeStyle } : {}),\n ...(el.color ? { color: el.color } : {}),\n businessObject: el,\n });\n }\n\n /**\n * The shape for any model element, projected with the current grid. Shared by the importer and\n * the in-place map resize, so both place every element type identically.\n */\n createFromModel(el: MapElement): WardleyShape | undefined {\n switch (el.elementType) {\n case \"component\":\n return this.createComponent(el);\n case \"anchor\":\n return this.createAnchor(el);\n case \"note\":\n return this.createNote(el);\n case \"pipeline\":\n return this.createPipeline(el);\n case \"annotation\":\n return this.createAnnotation(el);\n case \"attitude\":\n return this.createAttitude(el);\n case \"accelerator\":\n return this.createAccelerator(el);\n case \"submap\":\n return this.createSubmap(el);\n case \"drawing\":\n return this.createDrawing(el);\n default: {\n const exhaustive: never = el;\n void exhaustive;\n return undefined;\n }\n }\n }\n\n /** Builds a drawing shape from ABSOLUTE canvas points (bbox shape + relative points). */\n drawingFromCanvasPoints(\n canvasPoints: ReadonlyArray<{ x: number; y: number }>,\n extra: {\n id?: string;\n closed?: boolean;\n strokeStyle?: DrawingElement[\"strokeStyle\"];\n color?: string;\n businessObject?: DrawingElement;\n } = {},\n ): WardleyShape {\n const xs = canvasPoints.map((p) => p.x);\n const ys = canvasPoints.map((p) => p.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n const width = Math.max(Math.max(...xs) - x, 4);\n const height = Math.max(Math.max(...ys) - y, 4);\n const first = canvasPoints[0]!;\n const firstNorm = this.grid.fromCanvas(first);\n const shape = this.elementFactory.createShape({\n ...(extra.id ? { id: extra.id } : {}),\n x,\n y,\n width,\n height,\n wardleyType: \"drawing\",\n wardleyLabel: \"\",\n evolution: firstNorm.evolution,\n visibility: firstNorm.visibility,\n drawingPoints: canvasPoints.map((p) => ({ x: p.x - x, y: p.y - y })),\n ...(extra.closed ? { closed: true } : {}),\n ...(extra.strokeStyle ? { strokeStyle: extra.strokeStyle } : {}),\n ...(extra.color ? { color: extra.color } : {}),\n ...(extra.businessObject ? { businessObject: extra.businessObject } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createNew(\n type: WardleyShape[\"wardleyType\"],\n rawLabel: string,\n extra: CreateNewExtra = {},\n ): WardleyShape {\n // Enforce a unique label -> lossless DSL round-trip (see uniqueLabel). Attitude regions are\n // unlabelled like in OWM: their title is the canonical kind name.\n const label =\n type === \"attitude\"\n ? (extra.attitudeKind ?? \"pioneers\")\n : isLinkableType(type)\n ? this.uniqueLabel(rawLabel)\n : rawLabel;\n if (type === \"pipeline\") {\n const shape = this.elementFactory.createShape({\n width: 200,\n height: PIPELINE_HEIGHT,\n wardleyType: \"pipeline\",\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n evolutionStart: 0.4,\n evolutionEnd: 0.6,\n isFrame: true,\n });\n return shape as unknown as WardleyShape;\n }\n if (type === \"attitude\") {\n const shape = this.elementFactory.createShape({\n width: 180,\n height: 48,\n wardleyType: \"attitude\",\n wardleyLabel: label,\n attitudeKind: extra.attitudeKind ?? \"pioneers\",\n evolution: 0.5,\n visibility: 0.5,\n isFrame: true,\n });\n return shape as unknown as WardleyShape;\n }\n if (type === \"note\") {\n const { width, height } = noteMetrics(label);\n const shape = this.elementFactory.createShape({\n width,\n height,\n wardleyType: \"note\",\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n });\n return shape as unknown as WardleyShape;\n }\n const decorators = extra.market\n ? { market: true }\n : extra.ecosystem\n ? { ecosystem: true }\n : undefined;\n // Annotations automatically get the next free number (instead of a fixed \"1\").\n const annotationNumber =\n type === \"annotation\" ? (extra.annotationNumber ?? this.nextAnnotationNumber()) : undefined;\n const shape = this.elementFactory.createShape({\n width: NODE_SIZE,\n height: NODE_SIZE,\n wardleyType: type,\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n ...(extra.acceleratorDirection ? { acceleratorDirection: extra.acceleratorDirection } : {}),\n ...(annotationNumber !== undefined ? { annotationNumber } : {}),\n ...(decorators ? { decorators } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createDependency(edge: MapEdge, source: WardleyShape, target: WardleyShape): WardleyConnection {\n return this.connection(\"dependency\", edge, source, target);\n }\n\n createFlow(edge: MapEdge, source: WardleyShape, target: WardleyShape): WardleyConnection {\n const bidirectional = edge.edgeType === \"flow\" && edge.bidirectional === true;\n return this.connection(\"flow\", edge, source, target, bidirectional);\n }\n\n private node(\n type: WardleyShape[\"wardleyType\"],\n id: string,\n label: string,\n visibility: number,\n evolution: number,\n businessObject: WardleyShape[\"businessObject\"],\n extra: Partial<WardleyShape> = {},\n ): WardleyShape {\n const center = this.grid.toCanvas({ visibility, evolution });\n const color = (businessObject as { color?: string } | undefined)?.color;\n const shape = this.elementFactory.createShape({\n id,\n x: center.x - NODE_SIZE / 2,\n y: center.y - NODE_SIZE / 2,\n width: NODE_SIZE,\n height: NODE_SIZE,\n wardleyType: type,\n wardleyLabel: label,\n evolution,\n visibility,\n businessObject,\n ...(color ? { color } : {}),\n ...extra,\n });\n return shape as unknown as WardleyShape;\n }\n\n private connection(\n type: WardleyConnection[\"wardleyType\"],\n edge: MapEdge,\n source: WardleyShape,\n target: WardleyShape,\n bidirectional = false,\n ): WardleyConnection {\n const flowValue = edge.edgeType === \"flow\" ? edge.flowValue : undefined;\n const conn = this.elementFactory.createConnection({\n id: edge.id,\n source,\n target,\n waypoints: [connectionAnchorOf(source), connectionAnchorOf(target)],\n wardleyType: type,\n bidirectional,\n ...(flowValue ? { flowValue } : {}),\n ...(edge.label ? { linkLabel: edge.label } : {}),\n businessObject: edge,\n });\n return conn as unknown as WardleyConnection;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyElementFactory from \"./WardleyElementFactory.js\";\n\n/** Custom ElementFactory with Wardley defaults and pixel projection. */\nexport const wardleyModelModule: ModuleDeclaration = {\n wardleyElementFactory: [\"type\", WardleyElementFactory],\n};\n\nexport { default as WardleyElementFactory } from \"./WardleyElementFactory.js\";\nexport * from \"./di-types.js\";\n","import {\n append as svgAppend,\n create as svgCreate,\n attr as svgAttr,\n clear as svgClear,\n} from \"tiny-svg\";\nimport {\n drawnPlotLength,\n evolutionStage,\n DEFAULT_STAGE_BOUNDARIES,\n DEFAULT_EVOLUTION_LABELS,\n type Coordinate,\n type EvolutionStage,\n type MapConfig,\n} from \"@miragon/wardley-schema-model\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { PLOT, COLORS, FONT } from \"../draw/styles.js\";\n\nconst AXES_LAYER = \"wardley-axes\";\n/** Value-chain end labels [bottom, top] unless the map sets `y-axis Label->Bottom->Top`. */\nexport const DEFAULT_Y_AXIS_END_LABELS: readonly [string, string] = [\"Invisible\", \"Visible\"];\n/** Axis lines/arrowheads and margin texts — styling hooks, kept in the export's markup. */\nconst AXIS_CLASS = \"wardley-axis\";\nconst AXIS_TEXT_CLASS = \"wardley-axis-text\";\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/**\n * Holds the SINGLE pixel<->normalized transform (guiding principle P7) and renders the\n * non-interactive axis/grid background into its own diagram-js layer (z below the\n * elements). The plot size is changeable at runtime via `config.size` (\"scale map\").\n */\nexport default class EvolutionGrid {\n static $inject = [\"canvas\"];\n\n private boundaries: readonly [number, number, number] = DEFAULT_STAGE_BOUNDARIES;\n private labels: readonly [string, string, string, string] = DEFAULT_EVOLUTION_LABELS;\n private yAxisLabel = \"Value Chain\";\n private yAxisEndLabels: readonly [string, string] = DEFAULT_Y_AXIS_END_LABELS;\n private plotWidth: number = PLOT.width;\n private plotHeight: number = PLOT.height;\n\n constructor(private readonly canvas: Canvas) {}\n\n configure(config: MapConfig): void {\n this.boundaries = config.stageBoundaries ?? DEFAULT_STAGE_BOUNDARIES;\n this.labels = config.evolutionLabels ?? DEFAULT_EVOLUTION_LABELS;\n this.yAxisLabel = config.yAxisLabel ?? \"Value Chain\";\n this.yAxisEndLabels = config.yAxisEndLabels ?? DEFAULT_Y_AXIS_END_LABELS;\n // A written size stays in the config as is; the grid draws it within the limits (NaN-safe).\n this.plotWidth = drawnPlotLength(config.size?.width, \"width\");\n this.plotHeight = drawnPlotLength(config.size?.height, \"height\");\n }\n\n /** Normalized -> diagram px (center of the node). */\n toCanvas(coord: Coordinate): Point {\n return {\n x: PLOT.marginLeft + coord.evolution * this.plotWidth,\n y: PLOT.marginTop + (1 - coord.visibility) * this.plotHeight,\n };\n }\n\n /** diagram px -> normalized, clamped to [0,1]. */\n fromCanvas(point: Point): Coordinate {\n return {\n evolution: clamp01((point.x - PLOT.marginLeft) / this.plotWidth),\n visibility: clamp01(1 - (point.y - PLOT.marginTop) / this.plotHeight),\n };\n }\n\n stageOf(evolution: number): EvolutionStage {\n return evolutionStage(evolution, this.boundaries);\n }\n\n /** The three stage boundaries (evolution values) — for snapping. */\n getBoundaries(): readonly [number, number, number] {\n return this.boundaries;\n }\n\n getPlotSize(): { width: number; height: number } {\n return { width: this.plotWidth, height: this.plotHeight };\n }\n\n /** Outer bounds including margins (for the initial viewbox). */\n outerBounds(): { x: number; y: number; width: number; height: number } {\n return {\n x: 0,\n y: 0,\n width: PLOT.marginLeft + this.plotWidth + PLOT.marginRight,\n height: PLOT.marginTop + this.plotHeight + PLOT.marginBottom,\n };\n }\n\n render(): void {\n const layer = this.canvas.getLayer(AXES_LAYER, -1);\n svgClear(layer);\n\n const left = PLOT.marginLeft;\n const top = PLOT.marginTop;\n const right = left + this.plotWidth;\n const bottom = top + this.plotHeight;\n\n // Plot background\n svgAppend(\n layer,\n rect(left, top, this.plotWidth, this.plotHeight, {\n fill: COLORS.plotBackground,\n stroke: COLORS.grid,\n }),\n );\n\n const edges = [0, ...this.boundaries, 1];\n for (let i = 0; i < 4; i++) {\n const x0 = left + edges[i]! * this.plotWidth;\n const x1 = left + edges[i + 1]! * this.plotWidth;\n if (i % 2 === 1) {\n svgAppend(\n layer,\n rect(x0, top, x1 - x0, this.plotHeight, { fill: COLORS.band, stroke: \"none\" }),\n );\n }\n if (i > 0) {\n svgAppend(\n layer,\n line(x0, top, x0, bottom, { stroke: COLORS.grid, \"stroke-dasharray\": \"3 5\" }),\n );\n }\n const midX = (x0 + x1) / 2;\n svgAppend(\n layer,\n text(this.labels[i]!.toUpperCase(), midX, bottom + 18, {\n \"text-anchor\": \"middle\",\n \"font-size\": FONT.stage,\n \"letter-spacing\": \"0.08em\",\n fill: COLORS.axisText,\n }),\n );\n }\n\n svgAppend(\n layer,\n line(left, bottom, right + 10, bottom, { stroke: COLORS.axis, class: AXIS_CLASS }),\n );\n svgAppend(layer, arrowHead(right + 10, bottom, \"right\"));\n svgAppend(\n layer,\n text(\"Evolution\", right + 6, bottom + 38, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.axis,\n fill: COLORS.axisText,\n \"font-style\": \"italic\",\n }),\n );\n\n svgAppend(\n layer,\n line(left, bottom, left, top - 10, { stroke: COLORS.axis, class: AXIS_CLASS }),\n );\n svgAppend(layer, arrowHead(left, top - 10, \"up\"));\n const yLabel = text(this.yAxisLabel, 0, 0, {\n \"text-anchor\": \"middle\",\n \"font-size\": FONT.axis,\n fill: COLORS.axisText,\n \"font-style\": \"italic\",\n });\n svgAttr(yLabel, { transform: `translate(${left - 46}, ${(top + bottom) / 2}) rotate(-90)` });\n svgAppend(layer, yLabel);\n\n // Axis end labels [bottom, top] — configurable via `y-axis Label->Bottom->Top`.\n svgAppend(\n layer,\n text(this.yAxisEndLabels[1], left - 10, top + 11, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.stage,\n fill: COLORS.axisText,\n }),\n );\n svgAppend(\n layer,\n text(this.yAxisEndLabels[0], left - 10, bottom - 2, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.stage,\n fill: COLORS.axisText,\n }),\n );\n }\n}\n\ntype Attrs = Record<string, string | number>;\n\nfunction rect(x: number, y: number, w: number, h: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"rect\"), { x, y, width: w, height: h, \"stroke-width\": 1, ...attrs });\n}\n\nfunction line(x1: number, y1: number, x2: number, y2: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"line\"), { x1, y1, x2, y2, \"stroke-width\": 1, ...attrs });\n}\n\nfunction text(content: string, x: number, y: number, attrs: Attrs): SVGElement {\n const el = svgAttr(svgCreate(\"text\"), {\n x,\n y,\n \"font-family\": FONT.family,\n class: AXIS_TEXT_CLASS,\n ...attrs,\n });\n el.textContent = content;\n return el;\n}\n\nfunction arrowHead(x: number, y: number, dir: \"right\" | \"up\"): SVGElement {\n const s = 5;\n const points =\n dir === \"right\"\n ? `${x - s},${y - s} ${x + 2},${y} ${x - s},${y + s}`\n : `${x - s},${y + s} ${x},${y - 2} ${x + s},${y + s}`;\n return svgAttr(svgCreate(\"polygon\"), { points, fill: COLORS.axis, class: AXIS_CLASS });\n}\n","/** Shortest evolve arrow (normalized evolution): anything shorter is not a movement. */\nexport const MIN_EVOLVE_DELTA = 0.005;\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type { Movement } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { MIN_EVOLVE_DELTA } from \"./constants.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\n\nconst PREFIX = \"wardley.evolve\";\n/** CSS class of the red target circle (set by the renderer) — direct drag handle. */\nconst HANDLE_CLASS = \"wardley-evolve-handle\";\n\ninterface EvolveContext {\n shape: WardleyShape;\n originalMovement?: Movement;\n target?: number;\n committed?: boolean;\n}\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/**\n * Sets a component's evolve target by dragging along the evolution axis (instead of a text field).\n * During the drag a live preview (direct mutation + re-render); on release exactly ONE\n * undoable commit via the commandStack (P4). ESC cancels and restores the original state.\n */\nexport default class WardleyEvolveDragging {\n static $inject = [\n \"eventBus\",\n \"dragging\",\n \"evolutionGrid\",\n \"wardleyModeling\",\n \"canvas\",\n \"elementRegistry\",\n \"injector\",\n ];\n\n constructor(\n eventBus: EventBus,\n private readonly dragging: Dragging,\n grid: EvolutionGrid,\n modeling: WardleyModeling,\n canvas: Canvas,\n elementRegistry: ElementRegistry,\n private readonly injector: Injector,\n ) {\n const preview = (shape: WardleyShape, movement: Movement | undefined) => {\n if (movement === undefined) delete shape.movement;\n else shape.movement = movement;\n eventBus.fire(\"element.changed\", { element: shape });\n };\n\n // Evolution only moves forward: the preview stops at the component instead of flipping\n // backwards, and such a stub stays below the commit threshold.\n const forwardTarget = (shape: WardleyShape, evolution: number): number =>\n Math.max(clamp01(evolution), Math.min(1, shape.evolution + MIN_EVOLVE_DELTA));\n\n // Screen pixels -> normalized evolution (via the single source of math, P7).\n const evolutionAtClientX = (clientX: number, cy: number): number => {\n const rect = canvas.getContainer().getBoundingClientRect();\n const vb = canvas.viewbox();\n const canvasX = vb.x + (clientX - rect.left) * (vb.width / rect.width);\n return clamp01(grid.fromCanvas({ x: canvasX, y: cy }).evolution);\n };\n\n // The draw tool owns every press while it is active (its listener registers after this one).\n const isDrawing = (): boolean => {\n const container = canvas.getContainer();\n const outer = container.closest(\".wardley-container\") ?? container;\n return outer.classList.contains(\"wardley-draw-mode\");\n };\n\n // Direct handle: mousedown on the red target circle moves the evolve target by dragging.\n // Capture phase + stopPropagation so that diagram-js does NOT move the node instead.\n // Own document listeners (instead of dragging.init) — reliable, testable mousedown dragging.\n // Delegated on the container -> survives the re-rendering of the circle during the preview.\n canvas.getContainer().addEventListener(\n \"mousedown\",\n (event: MouseEvent) => {\n const dom = event.target as Element | null;\n if (!dom?.closest(`.${HANDLE_CLASS}`) || isDrawing() || isReadOnly(injector)) return;\n const id = dom.closest(\"[data-element-id]\")?.getAttribute(\"data-element-id\");\n const shape = id ? (elementRegistry.get(id) as WardleyShape | undefined) : undefined;\n if (!shape || shape.wardleyType !== \"component\") return;\n event.stopPropagation();\n event.preventDefault();\n focusCanvasWithoutRing(canvas);\n\n const original = shape.movement;\n const cy = shape.y + shape.height / 2;\n let target: number | undefined;\n const onMove = (e: MouseEvent) => {\n target = forwardTarget(shape, evolutionAtClientX(e.clientX, cy));\n preview(shape, { ...original, targetEvolution: target });\n };\n const onUp = () => {\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n preview(shape, original); // reset preview, then ONE undoable commit (P4)\n // The shape may be gone (deleted mid-drag, or replaced by a re-import).\n if (elementRegistry.get(shape.id) !== shape) return;\n if (target !== undefined && target > shape.evolution + MIN_EVOLVE_DELTA) {\n modeling.evolveComponent(shape, target);\n }\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n },\n true,\n );\n\n eventBus.on(`${PREFIX}.move`, (event: { context: EvolveContext; x: number }) => {\n const { shape } = event.context;\n const cy = shape.y + shape.height / 2;\n const target = forwardTarget(shape, grid.fromCanvas({ x: event.x, y: cy }).evolution);\n event.context.target = target;\n preview(shape, { ...event.context.originalMovement, targetEvolution: target });\n });\n\n eventBus.on(`${PREFIX}.end`, (event: { context: EvolveContext }) => {\n const ctx = event.context;\n const { shape, target } = ctx;\n // Reset the preview, then execute as ONE command (clean undo).\n preview(shape, ctx.originalMovement);\n if (target !== undefined && target > shape.evolution + MIN_EVOLVE_DELTA) {\n modeling.evolveComponent(shape, target);\n }\n ctx.committed = true;\n });\n\n eventBus.on(`${PREFIX}.cleanup`, (event: { context?: EvolveContext }) => {\n const ctx = event.context;\n if (ctx && !ctx.committed) preview(ctx.shape, ctx.originalMovement);\n });\n }\n\n /**\n * Starts the evolve drag for `shape` (from the context pad): set the target by dragging along\n * the axis, or move it afterwards, with live preview; commit on release.\n */\n start(event: Event, shape: WardleyShape): void {\n if (isReadOnly(this.injector)) return;\n const context: EvolveContext = {\n shape,\n ...(shape.movement ? { originalMovement: shape.movement } : {}),\n };\n this.dragging.init(event as MouseEvent, PREFIX, { cursor: \"ew-resize\", data: { context } });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyEvolveDragging from \"./WardleyEvolveDragging.js\";\n\nexport const wardleyEvolveModule: ModuleDeclaration = {\n __init__: [\"wardleyEvolveDragging\"],\n wardleyEvolveDragging: [\"type\", WardleyEvolveDragging],\n};\n\nexport { default as WardleyEvolveDragging } from \"./WardleyEvolveDragging.js\";\nexport { MIN_EVOLVE_DELTA } from \"./constants.js\";\n","import type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport { isComponent, isPipeline, type WardleyShape } from \"../model/di-types.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\nexport function centerOf(shape: WardleyShape): Point {\n return { x: shape.x + shape.width / 2, y: shape.y + shape.height / 2 };\n}\n\nexport function pipelineContains(pipeline: WardleyShape, point: Point): boolean {\n return (\n point.x >= pipeline.x &&\n point.x <= pipeline.x + pipeline.width &&\n point.y >= pipeline.y &&\n point.y <= pipeline.y + pipeline.height\n );\n}\n\nexport function allPipelines(registry: ElementRegistry): WardleyShape[] {\n return registry.filter((el) => isPipeline(el)) as WardleyShape[];\n}\n\nexport function membersOf(registry: ElementRegistry, pipeline: WardleyShape): WardleyShape[] {\n return registry.filter(\n (el) => isComponent(el) && el.pipelineId === pipeline.id,\n ) as WardleyShape[];\n}\n\n/** The OWM anchor: the standalone component written under the pipeline's name. */\nexport function anchorComponentOf(\n registry: ElementRegistry,\n pipeline: WardleyShape,\n): WardleyShape | undefined {\n return registry.find(\n (el) =>\n isComponent(el) && el.wardleyLabel === pipeline.wardleyLabel && el.pipelineId !== pipeline.id,\n ) as WardleyShape | undefined;\n}\n\n/** The pipeline a component anchors (same name, not one of its members). */\nexport function pipelineAnchoredBy(\n registry: ElementRegistry,\n component: WardleyShape,\n): WardleyShape | undefined {\n if (!isComponent(component)) return undefined;\n return allPipelines(registry).find(\n (pipeline) =>\n pipeline.wardleyLabel === component.wardleyLabel && component.pipelineId !== pipeline.id,\n );\n}\n\n/** Everything that moves together with a pipeline box: its members and its anchor component. */\nexport function pipelineFollowers(\n registry: ElementRegistry,\n pipeline: WardleyShape,\n): WardleyShape[] {\n const anchor = anchorComponentOf(registry, pipeline);\n return [...membersOf(registry, pipeline), ...(anchor ? [anchor] : [])];\n}\n\n/**\n * The pipeline a component would join when its centre sits at `point`. The pipeline it anchors is\n * never a candidate, and its current pipeline wins over overlapping boxes.\n */\nexport function pipelineAt(\n registry: ElementRegistry,\n component: WardleyShape,\n point: Point,\n excluded: ReadonlySet<unknown> = new Set(),\n): WardleyShape | undefined {\n const candidates = allPipelines(registry).filter(\n (pipeline) =>\n !excluded.has(pipeline) &&\n pipeline.wardleyLabel !== component.wardleyLabel &&\n pipelineContains(pipeline, point),\n );\n return candidates.find((pipeline) => pipeline.id === component.pipelineId) ?? candidates[0];\n}\n","import CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport type PreviewSupport from \"diagram-js/lib/features/preview-support/PreviewSupport\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport { translate } from \"diagram-js/lib/util/SvgTransformUtil\";\nimport { isComponent, isPipeline, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport {\n anchorComponentOf,\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"./pipelineMembership.js\";\n\n/** After diagram-js Move collected the selection (1500), before the preview is drawn (499). */\nconst COLLECT_FOLLOWERS_PRIORITY = 1400;\n/** After diagram-js MovePreview built its drag group. */\nconst VERTICAL_PREVIEW_PRIORITY = 450;\n/** After stage snapping (1500) and Move (500) settled the delta of this mouse move. */\nconst DROP_TARGET_PRIORITY = 400;\n/** Before the constraint behavior clamps the delta of the extended closure (1000). */\nconst EXTEND_CLOSURE_PRIORITY = 1500;\n\nconst VERTICAL_PREVIEW_LAYER = \"wardley-pipeline-drag\";\nconst VERTICAL_PREVIEW_LAYER_INDEX = 900;\n\nexport const DROP_TARGET_MARKER = \"wardley-drop-target\";\n\ninterface MoveContext {\n shape?: unknown;\n shapes?: unknown[];\n pipelineVerticalPreview?: SVGElement;\n pipelineDropTarget?: WardleyShape;\n}\n\ninterface RenameContext {\n element: WardleyShape;\n properties: Record<string, unknown>;\n renamedCounterpart?: WardleyShape;\n}\n\ninterface MoveEvent {\n context: MoveContext;\n dx: number;\n dy: number;\n}\n\ninterface MoveClosureLike {\n allShapes: Record<string, unknown>;\n topLevel: Record<string, unknown>;\n add(element: unknown, isTopLevel?: boolean): void;\n}\n\n/**\n * Makes a pipeline behave like a group (diagram-js AttachSupport pattern): dragging or nudging the\n * box carries its member components and its anchor component, dragging the anchor component shows\n * the box following vertically (the constraint behavior moves it on drop), and a dragged component\n * highlights the pipeline it would join.\n */\nexport default class PipelineGroupBehavior extends CommandInterceptor {\n static override $inject = [\"eventBus\", \"elementRegistry\", \"canvas\", \"injector\"];\n\n constructor(\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n injector: Injector,\n ) {\n super(eventBus);\n const previewSupport = injector.get<PreviewSupport | null>(\"previewSupport\", false);\n\n // A pipeline and its anchor component are one OWM pair, linked by their shared name: renaming\n // one renames the other in the same undo step, or the box silently stops following.\n this.preExecute(\"element.updateProperties\", (event: { context: RenameContext }) => {\n const { context } = event;\n const element = context.element;\n const label = context.properties[\"wardleyLabel\"];\n if (typeof label !== \"string\" || label === element.wardleyLabel) return;\n const counterpart = isPipeline(element)\n ? anchorComponentOf(this.elementRegistry, element)\n : pipelineAnchoredBy(this.elementRegistry, element);\n if (counterpart) context.renamedCounterpart = counterpart;\n });\n this.postExecute(\"element.updateProperties\", (event: { context: RenameContext }) => {\n const { context } = event;\n const counterpart = context.renamedCounterpart;\n const label = context.properties[\"wardleyLabel\"];\n if (!counterpart || typeof label !== \"string\" || counterpart.wardleyLabel === label) return;\n injector.get<WardleyModeling>(\"wardleyModeling\").updateProperties(counterpart, {\n wardleyLabel: label,\n });\n });\n\n eventBus.on(\"shape.move.start\", COLLECT_FOLLOWERS_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n context.shapes = this.withFollowers(context.shapes ?? []);\n });\n\n // Keyboard nudges and API moves never pass through shape.move.start.\n this.preExecuted(\n \"elements.move\",\n EXTEND_CLOSURE_PRIORITY,\n (event: { context: { closure?: MoveClosureLike } }) => {\n const closure = event.context.closure;\n if (!closure) return;\n for (const shape of Object.values(closure.allShapes)) {\n if (!isPipeline(shape)) continue;\n for (const follower of pipelineFollowers(this.elementRegistry, shape)) {\n if (!closure.allShapes[follower.id])\n closure.add(follower, !!closure.topLevel[shape.id]);\n }\n }\n },\n );\n\n if (previewSupport) {\n eventBus.on(\"shape.move.start\", VERTICAL_PREVIEW_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n const carried = this.carriedVertically(context.shapes ?? []);\n if (!carried.length) return;\n const group = svgCreate(\"g\");\n svgAttr(group, { class: \"djs-drag-group\" });\n svgAppend(\n this.canvas.getLayer(VERTICAL_PREVIEW_LAYER, VERTICAL_PREVIEW_LAYER_INDEX),\n group,\n );\n for (const shape of carried) previewSupport.addDragger(shape as unknown as Element, group);\n context.pipelineVerticalPreview = group;\n });\n }\n\n eventBus.on(\"shape.move.move\", DROP_TARGET_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n if (context.pipelineVerticalPreview) {\n translate(context.pipelineVerticalPreview, 0, event.dy);\n }\n this.markDropTarget(context, this.dropTargetFor(context, event.dx, event.dy));\n });\n\n eventBus.on(\"shape.move.cleanup\", (event: MoveEvent) => {\n const { context } = event;\n if (context.pipelineVerticalPreview) {\n svgRemove(context.pipelineVerticalPreview);\n delete context.pipelineVerticalPreview;\n }\n this.markDropTarget(context, undefined);\n });\n }\n\n private withFollowers(shapes: unknown[]): unknown[] {\n const all = new Set<unknown>(shapes);\n for (const shape of shapes) {\n if (!isPipeline(shape)) continue;\n for (const follower of pipelineFollowers(this.elementRegistry, shape)) all.add(follower);\n }\n return [...all];\n }\n\n /** Pipelines (and their members) whose anchor component is dragged without them. */\n private carriedVertically(shapes: unknown[]): WardleyShape[] {\n const dragged = new Set(shapes);\n const carried: WardleyShape[] = [];\n for (const shape of shapes) {\n if (!isComponent(shape)) continue;\n const pipeline = pipelineAnchoredBy(this.elementRegistry, shape);\n if (!pipeline || dragged.has(pipeline)) continue;\n carried.push(\n pipeline,\n ...membersOf(this.elementRegistry, pipeline).filter((member) => !dragged.has(member)),\n );\n }\n return carried;\n }\n\n private dropTargetFor(context: MoveContext, dx: number, dy: number): WardleyShape | undefined {\n const shape = context.shape;\n if (!isComponent(shape) || pipelineAnchoredBy(this.elementRegistry, shape)) return undefined;\n const center = centerOf(shape);\n return pipelineAt(\n this.elementRegistry,\n shape,\n { x: center.x + dx, y: center.y + dy },\n new Set(context.shapes ?? []),\n );\n }\n\n private markDropTarget(context: MoveContext, target: WardleyShape | undefined): void {\n const previous = context.pipelineDropTarget;\n if (previous === target) return;\n if (previous) this.canvas.removeMarker(previous as unknown as Shape, DROP_TARGET_MARKER);\n if (target) this.canvas.addMarker(target as unknown as Shape, DROP_TARGET_MARKER);\n if (target) context.pipelineDropTarget = target;\n else delete context.pipelineDropTarget;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PipelineGroupBehavior from \"./PipelineGroupBehavior.js\";\n\n/** Pipelines move as groups with their members and anchor component (editor-only). */\nexport const pipelineGroupModule: ModuleDeclaration = {\n __init__: [\"pipelineGroupBehavior\"],\n pipelineGroupBehavior: [\"type\", PipelineGroupBehavior],\n};\n\nexport { default as PipelineGroupBehavior, DROP_TARGET_MARKER } from \"./PipelineGroupBehavior.js\";\nexport {\n anchorComponentOf,\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"./pipelineMembership.js\";\n","import CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Shape } from \"diagram-js/lib/model/Types\";\nimport { isComponent, isPipeline, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { MIN_EVOLVE_DELTA } from \"../evolve/index.js\";\nimport {\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"../pipeline/index.js\";\nimport type EvolutionGrid from \"./EvolutionGrid.js\";\n\n/** Commands whose handler changes the geometry of exactly one shape (`context.shape`). */\nconst SHAPE_GEOMETRY_COMMANDS = [\"shape.move\", \"shape.create\", \"shape.resize\"];\nconst GEOMETRY_COMMANDS = [...SHAPE_GEOMETRY_COMMANDS, \"elements.move\", \"elements.create\"];\nconst COMPONENT_LABEL_COMMANDS = [\"shape.create\", \"shape.delete\", \"element.updateProperties\"];\n\n/** Runs before every other pre-execute listener, so nesting is known before anyone acts on it. */\nconst TOP_LEVEL_PRIORITY = 2000;\n/** Below the pipeline group behavior (1500), which first extends the move closure by the members. */\nconst DELTA_CLAMP_PRIORITY = 1000;\n/** diagram-js ResizeShapeHandler rejects anything smaller. */\nconst MIN_RESIZE_EXTENT = 10;\nconst EPSILON = 1e-6;\n\ninterface Point {\n x: number;\n y: number;\n}\n\ninterface Bounds extends Point {\n width: number;\n height: number;\n}\n\ninterface Range {\n min: number;\n max: number;\n}\n\ninterface GeometryContext {\n shape?: unknown;\n shapes?: unknown[];\n elements?: unknown[];\n closure?: { allShapes: Record<string, unknown> };\n delta?: Point;\n newBounds?: Bounds;\n parent?: object & { parent?: unknown };\n}\n\ninterface CommandEvent {\n command: string;\n context: GeometryContext;\n}\n\n/**\n * Keeps the normalized Wardley coordinates and the pixel geometry consistent across execute, undo\n * AND redo (concept doc §5.3). `EvolutionGrid` is the single source of math (P7).\n *\n * Two strictly separated parts, because diagram-js replays only `execute`/`revert` on redo and\n * skips every pre/post hook:\n *\n * 1. Derivation (`executed` + `reverted`): evolution, visibility, the pipeline range and the\n * attitude corner are pure functions of the current geometry and membership. It never writes\n * geometry, so replaying it on redo or undo always lands on the same model.\n * 2. Corrections (pre/post hooks of the outermost geometry command only): moves are clamped by\n * replacing the command's delta before it runs, resizes by replacing its bounds; pipeline glue,\n * membership changes and shifted evolve targets are nested commands. All of them join the same\n * undo step and are replayed exactly on redo.\n *\n * Pipelines behave like groups: moving the box carries its members and its anchor component (the\n * pipeline group behavior adds them to the move), and moving the anchor component vertically\n * carries the box. A component dropped into a box joins it and is glued onto its row; dragging it\n * out ends the membership.\n */\nexport default class EvolutionConstraintBehavior extends CommandInterceptor {\n static override $inject = [\n \"eventBus\",\n \"evolutionGrid\",\n \"elementRegistry\",\n \"canvas\",\n \"modeling\",\n \"wardleyModeling\",\n ];\n\n private topLevelContext: GeometryContext | null = null;\n private readonly evolutionsBefore = new WeakMap<GeometryContext, Map<WardleyShape, number>>();\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n private readonly modeling: Modeling,\n private readonly wardleyModeling: WardleyModeling,\n ) {\n super(eventBus);\n\n const derive = (event: CommandEvent) => {\n for (const shape of directShapes(event.context)) this.deriveFromGeometry(shape);\n };\n this.executed(SHAPE_GEOMETRY_COMMANDS, derive);\n this.reverted(SHAPE_GEOMETRY_COMMANDS, derive);\n\n // Corrections issue nested geometry commands themselves; only the outermost one is corrected,\n // which also stops the recursion.\n this.preExecute(GEOMETRY_COMMANDS, TOP_LEVEL_PRIORITY, (event: CommandEvent) => {\n if (!this.topLevelContext) this.topLevelContext = event.context;\n });\n eventBus.on(\"commandStack.changed\", () => {\n this.topLevelContext = null;\n });\n\n this.preExecute(\"shape.move\", (event: CommandEvent) => {\n const { context } = event;\n if (!this.isTopLevel(context) || !isWardleyShape(context.shape) || !context.delta) return;\n const moved = [context.shape, ...this.followersOf(context.shape)];\n this.rememberEvolutions(context, moved);\n context.delta = this.clampDelta(context.delta, moved);\n });\n this.preExecuted(\"elements.move\", DELTA_CLAMP_PRIORITY, (event: CommandEvent) => {\n const { context } = event;\n if (!this.isTopLevel(context) || !context.delta) return;\n const moved = closureShapes(context);\n this.rememberEvolutions(context, moved);\n // A fresh object: the same delta is later handed to every nested shape.move of the closure.\n context.delta = this.clampDelta(context.delta, moved);\n });\n this.preExecute([\"shape.create\", \"elements.create\"], (event: CommandEvent) => {\n const { context } = event;\n // Wardley shapes never nest: a drop onto another element must not make it the parent.\n if (context.parent?.parent) context.parent = this.canvas.getRootElement();\n if (this.isTopLevel(context)) this.rememberEvolutions(context, directShapes(context));\n });\n this.preExecute(\"shape.resize\", (event: CommandEvent) => {\n const { context } = event;\n const shape = context.shape;\n if (!isWardleyShape(shape) || !context.newBounds) return;\n if (shape.wardleyType === \"pipeline\") {\n context.newBounds = this.horizontalPipelineBounds(shape, context.newBounds);\n } else if (shape.wardleyType === \"attitude\") {\n context.newBounds = this.boundsInsidePlot(context.newBounds);\n }\n });\n\n this.postExecuted(GEOMETRY_COMMANDS, (event: CommandEvent) => {\n if (event.context !== this.topLevelContext) return;\n try {\n this.applyCorrections(event.command, event.context);\n } finally {\n this.evolutionsBefore.delete(event.context);\n this.topLevelContext = null;\n }\n });\n\n // The pipeline label is suppressed when a same-named component exists — whenever a\n // component is created/deleted/renamed, re-render the pipelines so labels toggle.\n const refreshPipelineLabels = (event: {\n context?: { shape?: unknown; element?: unknown; elements?: unknown[] };\n }) => {\n const candidates = [\n event.context?.shape,\n event.context?.element,\n ...(event.context?.elements ?? []),\n ];\n if (!candidates.some((element) => isComponent(element))) return;\n for (const pipeline of this.elementRegistry.filter((element) => isPipeline(element))) {\n this.eventBus.fire(\"element.changed\", { element: pipeline });\n }\n };\n this.executed(COMPONENT_LABEL_COMMANDS, refreshPipelineLabels);\n this.reverted(COMPONENT_LABEL_COMMANDS, refreshPipelineLabels);\n }\n\n private isTopLevel(context: GeometryContext): boolean {\n return context === this.topLevelContext;\n }\n\n private followersOf(shape: WardleyShape): WardleyShape[] {\n return isPipeline(shape) ? pipelineFollowers(this.elementRegistry, shape) : [];\n }\n\n private rememberEvolutions(context: GeometryContext, shapes: WardleyShape[]): void {\n this.evolutionsBefore.set(context, new Map(shapes.map((shape) => [shape, shape.evolution])));\n }\n\n // --- derivation (pure: geometry + membership -> normalized model) ----------------------------\n\n private deriveFromGeometry(shape: WardleyShape): void {\n switch (shape.wardleyType) {\n case \"pipeline\":\n this.derivePipeline(shape);\n return;\n case \"attitude\": {\n // Attitude position = anchor point (top left), corner2 = bottom-right corner (OWM semantics).\n const topLeft = this.grid.fromCanvas({ x: shape.x, y: shape.y });\n shape.evolution = topLeft.evolution;\n shape.visibility = topLeft.visibility;\n shape.corner2 = this.grid.fromCanvas({\n x: shape.x + shape.width,\n y: shape.y + shape.height,\n });\n return;\n }\n case \"drawing\": {\n const first = shape.drawingPoints?.[0] ?? { x: 0, y: 0 };\n const coordinate = this.grid.fromCanvas({ x: shape.x + first.x, y: shape.y + first.y });\n shape.evolution = coordinate.evolution;\n shape.visibility = coordinate.visibility;\n return;\n }\n default: {\n const coordinate = this.grid.fromCanvas(centerOf(shape));\n shape.evolution = coordinate.evolution;\n // Members share their pipeline's visibility; they are drawn centred in the box below it.\n const pipeline = this.pipelineOfMember(shape);\n shape.visibility = pipeline ? this.pipelineVisibility(pipeline) : coordinate.visibility;\n }\n }\n }\n\n private derivePipeline(pipeline: WardleyShape): void {\n // The anchor line (■ on the box) is the box's TOP EDGE.\n const start = this.grid.fromCanvas({ x: pipeline.x, y: pipeline.y });\n const end = this.grid.fromCanvas({ x: pipeline.x + pipeline.width, y: pipeline.y });\n const [evolutionStart, evolutionEnd] = clampRange(start.evolution, end.evolution);\n pipeline.evolutionStart = evolutionStart;\n pipeline.evolutionEnd = evolutionEnd;\n pipeline.evolution = clamp01((evolutionStart + evolutionEnd) / 2);\n pipeline.visibility = start.visibility;\n for (const member of membersOf(this.elementRegistry, pipeline)) {\n member.visibility = pipeline.visibility;\n }\n }\n\n private pipelineOfMember(shape: WardleyShape): WardleyShape | undefined {\n if (!isComponent(shape) || !shape.pipelineId) return undefined;\n const pipeline = this.elementRegistry.get(shape.pipelineId);\n return isPipeline(pipeline) ? pipeline : undefined;\n }\n\n private pipelineVisibility(pipeline: WardleyShape): number {\n return this.grid.fromCanvas({ x: pipeline.x, y: pipeline.y }).visibility;\n }\n\n // --- corrections (outermost command only, recorded as nested commands) -----------------------\n\n private applyCorrections(command: string, context: GeometryContext): void {\n switch (command) {\n case \"shape.move\": {\n const shape = context.shape;\n if (!isWardleyShape(shape)) return;\n const delta = context.delta ?? { x: 0, y: 0 };\n const followers = this.followersOf(shape);\n for (const follower of followers) this.moveBy(follower, delta);\n this.completeMove([shape, ...followers], delta, context);\n return;\n }\n case \"elements.move\":\n this.completeMove(closureShapes(context), context.delta ?? { x: 0, y: 0 }, context);\n return;\n case \"shape.create\":\n case \"elements.create\": {\n const created = directShapes(context);\n const correction = this.clampDelta({ x: 0, y: 0 }, created);\n for (const shape of created) this.moveBy(shape, correction);\n this.reconcileMembership(created);\n this.shiftPassedEvolveTargets(context);\n return;\n }\n case \"shape.resize\":\n if (isPipeline(context.shape)) this.releaseMembersOutside(context.shape);\n return;\n }\n }\n\n private completeMove(moved: WardleyShape[], delta: Point, context: GeometryContext): void {\n this.carryPipelinesOfMovedAnchors(moved, delta);\n this.reconcileMembership(moved);\n this.shiftPassedEvolveTargets(context);\n }\n\n /** Moving an anchor component up or down takes its pipeline box and the members along. */\n private carryPipelinesOfMovedAnchors(moved: WardleyShape[], delta: Point): void {\n if (Math.abs(delta.y) < EPSILON) return;\n const movedShapes = new Set<WardleyShape>(moved);\n for (const shape of moved) {\n const pipeline = pipelineAnchoredBy(this.elementRegistry, shape);\n if (!pipeline || movedShapes.has(pipeline)) continue;\n const group = [\n pipeline,\n ...membersOf(this.elementRegistry, pipeline).filter((member) => !movedShapes.has(member)),\n ];\n const verticalDelta = this.clampDelta({ x: 0, y: delta.y }, group);\n for (const groupShape of group) {\n this.moveBy(groupShape, verticalDelta);\n movedShapes.add(groupShape);\n }\n }\n }\n\n /**\n * A moved component whose centre lands in a pipeline box joins it and is glued onto its row; one\n * that leaves its box is released. Anchor components never join (they anchor the box itself).\n */\n private reconcileMembership(moved: WardleyShape[]): void {\n for (const component of moved) {\n if (!isComponent(component) || pipelineAnchoredBy(this.elementRegistry, component)) continue;\n const center = centerOf(component);\n const host = pipelineAt(this.elementRegistry, component, center);\n if (host) {\n this.moveBy(component, { x: 0, y: host.y + host.height / 2 - center.y });\n if (component.pipelineId !== host.id) {\n this.wardleyModeling.updateProperties(component, {\n pipelineId: host.id,\n visibility: this.pipelineVisibility(host),\n });\n }\n } else if (component.pipelineId) {\n this.release(component);\n }\n }\n }\n\n /** A narrowed pipeline lets go of the members whose centre is no longer inside the box. */\n private releaseMembersOutside(pipeline: WardleyShape): void {\n for (const member of membersOf(this.elementRegistry, pipeline)) {\n const center = centerOf(member);\n if (center.x < pipeline.x || center.x > pipeline.x + pipeline.width) this.release(member);\n }\n }\n\n private release(component: WardleyShape): void {\n this.wardleyModeling.updateProperties(component, {\n pipelineId: undefined,\n visibility: this.grid.fromCanvas(centerOf(component)).visibility,\n });\n }\n\n /**\n * A component moved onto or past its evolve target keeps the planned distance instead of\n * pointing backwards; at the right edge, where no forward target is left, the movement goes.\n */\n private shiftPassedEvolveTargets(context: GeometryContext): void {\n const evolutionsBefore = this.evolutionsBefore.get(context);\n if (!evolutionsBefore) return;\n for (const [shape, evolutionBefore] of evolutionsBefore) {\n const movement = shape.movement;\n if (!isComponent(shape) || !movement) continue;\n const evolution = shape.evolution;\n if (movement.targetEvolution - evolution > MIN_EVOLVE_DELTA) continue;\n const shiftedTarget = Math.min(1, evolution + (movement.targetEvolution - evolutionBefore));\n this.wardleyModeling.updateProperties(shape, {\n movement:\n shiftedTarget - evolution > MIN_EVOLVE_DELTA\n ? { ...movement, targetEvolution: shiftedTarget }\n : undefined,\n });\n }\n }\n\n private moveBy(shape: WardleyShape, delta: Point): void {\n if (Math.abs(delta.x) < EPSILON && Math.abs(delta.y) < EPSILON) return;\n this.modeling.moveShape(shape as unknown as Shape, { x: delta.x, y: delta.y });\n }\n\n // --- plot clamping ---------------------------------------------------------------------------\n\n private plotBounds(): Bounds {\n const topLeft = this.grid.toCanvas({ evolution: 0, visibility: 1 });\n const bottomRight = this.grid.toCanvas({ evolution: 1, visibility: 0 });\n return {\n x: topLeft.x,\n y: topLeft.y,\n width: bottomRight.x - topLeft.x,\n height: bottomRight.y - topLeft.y,\n };\n }\n\n /**\n * The part of a shape that has to stay inside the plot: the centre of a node, the anchor line of\n * a pipeline, the whole rectangle of an attitude and every point of a drawing.\n */\n private extentInsidePlot(shape: WardleyShape): Bounds {\n switch (shape.wardleyType) {\n case \"pipeline\":\n return { x: shape.x, y: shape.y, width: shape.width, height: 0 };\n case \"attitude\":\n return { x: shape.x, y: shape.y, width: shape.width, height: shape.height };\n case \"drawing\": {\n const points = shape.drawingPoints ?? [];\n if (!points.length) return { ...centerOf(shape), width: 0, height: 0 };\n const xs = points.map((point) => shape.x + point.x);\n const ys = points.map((point) => shape.y + point.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y };\n }\n default:\n return { ...centerOf(shape), width: 0, height: 0 };\n }\n }\n\n /** The largest part of `delta` that keeps every shape's extent inside the plot. */\n private clampDelta(delta: Point, shapes: WardleyShape[]): Point {\n const plot = this.plotBounds();\n const horizontal: Range = { min: -Infinity, max: Infinity };\n const vertical: Range = { min: -Infinity, max: Infinity };\n for (const shape of shapes) {\n const extent = this.extentInsidePlot(shape);\n horizontal.min = Math.max(horizontal.min, plot.x - extent.x);\n horizontal.max = Math.min(horizontal.max, plot.x + plot.width - (extent.x + extent.width));\n vertical.min = Math.max(vertical.min, plot.y - extent.y);\n vertical.max = Math.min(vertical.max, plot.y + plot.height - (extent.y + extent.height));\n }\n return { x: clampToRange(delta.x, horizontal), y: clampToRange(delta.y, vertical) };\n }\n\n /** Pipelines only stretch along the evolution axis, and only within the plot. */\n private horizontalPipelineBounds(pipeline: WardleyShape, bounds: Bounds): Bounds {\n const [x, width] = this.spanInside(bounds.x, bounds.width, \"x\");\n return { x, y: pipeline.y, width, height: pipeline.height };\n }\n\n private boundsInsidePlot(bounds: Bounds): Bounds {\n const [x, width] = this.spanInside(bounds.x, bounds.width, \"x\");\n const [y, height] = this.spanInside(bounds.y, bounds.height, \"y\");\n return { x, y, width, height };\n }\n\n private spanInside(start: number, length: number, axis: \"x\" | \"y\"): [number, number] {\n const plot = this.plotBounds();\n const plotStart = axis === \"x\" ? plot.x : plot.y;\n const plotEnd = plotStart + (axis === \"x\" ? plot.width : plot.height);\n const clampedStart = Math.max(start, plotStart);\n const clampedLength = Math.max(\n Math.min(start + length, plotEnd) - clampedStart,\n MIN_RESIZE_EXTENT,\n );\n return [Math.min(clampedStart, plotEnd - clampedLength), clampedLength];\n }\n}\n\nfunction directShapes(context: GeometryContext): WardleyShape[] {\n const candidates = [\n ...(context.shape ? [context.shape] : []),\n ...(context.shapes ?? []),\n ...(context.elements ?? []),\n ];\n return [...new Set(candidates)].filter(isWardleyShape);\n}\n\nfunction closureShapes(context: GeometryContext): WardleyShape[] {\n if (!context.closure) return directShapes(context);\n return Object.values(context.closure.allShapes).filter(isWardleyShape);\n}\n\nfunction clampToRange(value: number, range: Range): number {\n // An empty range means a shape already sits outside the plot — leave such moves alone.\n if (range.min > range.max) return value;\n return Math.min(Math.max(value, range.min), range.max);\n}\n\nconst RANGE_EPS = 0.001;\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/** Clamps an evolution range to [0,1] while guaranteeing `start < end` (schema invariant). */\nexport function clampRange(start: number, end: number): [number, number] {\n const e = clamp01(Math.max(end, start + RANGE_EPS));\n const s = Math.max(0, Math.min(start, e - RANGE_EPS));\n return [s, e];\n}\n","import type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\n\nexport interface UpdatePropertiesContext {\n element: ElementLike & Record<string, unknown>;\n properties: Record<string, unknown>;\n /** set internally by the handler (for revert). */\n oldProperties?: Record<string, unknown>;\n}\n\nfunction setOrDelete(obj: Record<string, unknown>, key: string, value: unknown): void {\n if (value === undefined) delete obj[key];\n else obj[key] = value;\n}\n\n/**\n * Generic, undoable command handler for setting arbitrary Wardley properties\n * (wardleyLabel, decorators, movement, evolutionStart/End, ...). Returns the changed element\n * -> CommandStack fires `elements.changed` -> re-render.\n */\nexport default class UpdatePropertiesHandler implements CommandHandler {\n execute(context: UpdatePropertiesContext): ElementLike[] {\n const { element, properties } = context;\n const target = element as unknown as Record<string, unknown>;\n const old: Record<string, unknown> = {};\n for (const key of Object.keys(properties)) {\n old[key] = target[key];\n setOrDelete(target, key, properties[key]);\n }\n context.oldProperties = old;\n return [element];\n }\n\n revert(context: UpdatePropertiesContext): ElementLike[] {\n const { element, oldProperties } = context;\n const target = element as unknown as Record<string, unknown>;\n if (oldProperties) {\n for (const key of Object.keys(oldProperties)) setOrDelete(target, key, oldProperties[key]);\n }\n return [element];\n }\n}\n","import type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type { MapSize } from \"@miragon/wardley-schema-model\";\nimport type { RootBusinessObject } from \"../../io/index.js\";\nimport {\n configWithSize,\n withoutRawSizeStatements,\n type MapProjection,\n} from \"../../map-resize/index.js\";\n\nexport interface ResizeMapContext {\n /** New explicit size; `undefined` removes the `size` line (default plot). */\n size: MapSize | undefined;\n /** set internally by the handler (for revert). */\n oldSize?: MapSize | undefined;\n oldRawPassthrough?: readonly string[] | undefined;\n}\n\n/**\n * Undoable map resize: changes `config.size` and re-projects the existing shapes in place from\n * their normalized model. Only the size (and superseded raw `size` lines) is touched, so the DSL\n * changes in exactly one line.\n */\nexport default class ResizeMapHandler implements CommandHandler {\n static $inject = [\"wardleyMapProjection\"];\n\n constructor(private readonly projection: MapProjection) {}\n\n execute(context: ResizeMapContext): ElementLike[] {\n const businessObject = this.projection.root()?.businessObject;\n if (!businessObject) return [];\n context.oldSize = businessObject.config.size;\n context.oldRawPassthrough = businessObject.rawPassthrough;\n // An unreadable `size` line kept in the passthrough would be written after the new one, and\n // OWM lets the last size line win.\n return this.projection.apply(\n withRawPassthrough(\n { ...businessObject, config: configWithSize(businessObject.config, context.size) },\n withoutRawSizeStatements(businessObject.rawPassthrough),\n ),\n );\n }\n\n revert(context: ResizeMapContext): ElementLike[] {\n const businessObject = this.projection.root()?.businessObject;\n if (!businessObject) return [];\n return this.projection.apply(\n withRawPassthrough(\n { ...businessObject, config: configWithSize(businessObject.config, context.oldSize) },\n context.oldRawPassthrough,\n ),\n );\n }\n}\n\nfunction withRawPassthrough(\n businessObject: RootBusinessObject,\n rawPassthrough: readonly string[] | undefined,\n): RootBusinessObject {\n const { rawPassthrough: _previous, ...rest } = businessObject;\n return rawPassthrough ? { ...rest, rawPassthrough } : rest;\n}\n","import type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { MapConfig, MapSize, Method } from \"@miragon/wardley-schema-model\";\nimport type { WardleyConnection, WardleyShape } from \"../model/di-types.js\";\nimport { noteMetrics } from \"../draw/styles.js\";\nimport { wardleyRootOf } from \"../map-resize/index.js\";\nimport UpdatePropertiesHandler from \"./cmd/UpdatePropertiesHandler.js\";\nimport ResizeMapHandler from \"./cmd/ResizeMapHandler.js\";\nimport UpdateConfigHandler, { type MapConfigUpdate } from \"./cmd/UpdateConfigHandler.js\";\n\nconst UPDATE_PROPERTIES = \"element.updateProperties\";\nexport const RESIZE_MAP = \"wardley.map.resize\";\nexport const UPDATE_CONFIG = \"wardley.config.update\";\n\nfunction compact<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\nexport interface EvolveOptions {\n newLabel?: string;\n method?: Method;\n}\n\n/**\n * High-level mutations on Wardley shapes that run through the commandStack (undo/redo, P4).\n * Registers the generic UpdatePropertiesHandler at bootstrap.\n */\nexport default class WardleyModeling {\n static $inject = [\"commandStack\", \"canvas\"];\n\n constructor(\n private readonly commandStack: CommandStack,\n private readonly canvas: Canvas,\n ) {\n commandStack.registerHandler(UPDATE_PROPERTIES, UpdatePropertiesHandler);\n commandStack.registerHandler(RESIZE_MAP, ResizeMapHandler);\n commandStack.registerHandler(UPDATE_CONFIG, UpdateConfigHandler);\n }\n\n /**\n * Sets the plot size (`undefined` removes the `size` line) as one undoable step that re-projects\n * the shapes in place. Pass an already normalized size (see `normalizeMapSize`). Does nothing\n * when the config would not change.\n */\n resizeMap(size: MapSize | undefined): void {\n const config = this.currentConfig();\n if (!config || sameSize(config.size, size)) return;\n this.commandStack.execute(RESIZE_MAP, { size });\n }\n\n /** Changes config fields (title, labels, …) as one undoable step; `undefined` removes a field. */\n updateConfig(properties: MapConfigUpdate): void {\n const config = this.currentConfig();\n if (!config) return;\n const current = config as unknown as Record<string, unknown>;\n const changed = Object.fromEntries(\n Object.entries(properties).filter(\n ([key, value]) => key !== \"size\" && JSON.stringify(current[key]) !== JSON.stringify(value),\n ),\n ) as MapConfigUpdate;\n if (Object.keys(changed).length === 0) return;\n this.commandStack.execute(UPDATE_CONFIG, { properties: changed });\n }\n\n private currentConfig(): MapConfig | undefined {\n return wardleyRootOf(this.canvas)?.businessObject?.config;\n }\n\n updateProperties(\n element: WardleyShape | WardleyConnection,\n properties: Record<string, unknown>,\n ): void {\n this.commandStack.execute(UPDATE_PROPERTIES, { element, properties });\n }\n\n updateLabel(element: WardleyShape, label: string): void {\n // Notes: resize the box (and thus the move/click hitbox) to the new text, keeping the center.\n if (element.wardleyType === \"note\") {\n const { width, height } = noteMetrics(label);\n const cx = element.x + element.width / 2;\n const cy = element.y + element.height / 2;\n this.updateProperties(element, {\n wardleyLabel: label,\n width,\n height,\n x: cx - width / 2,\n y: cy - height / 2,\n });\n return;\n }\n this.updateProperties(element, { wardleyLabel: label });\n }\n\n evolveComponent(element: WardleyShape, targetEvolution: number, opts: EvolveOptions = {}): void {\n const target = clamp01(targetEvolution);\n // Evolution only moves forward (canon) — silently ignore targets left of the current position.\n if (target <= element.evolution) return;\n // Retargeting keeps what the user already gave the evolve line (new name, method, label offset).\n this.updateProperties(element, {\n movement: compact({\n ...element.movement,\n targetEvolution: target,\n ...compact({ newLabel: opts.newLabel, method: opts.method }),\n }),\n });\n }\n\n clearMovement(element: WardleyShape): void {\n this.updateProperties(element, { movement: undefined });\n }\n\n toggleInertia(element: WardleyShape): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n if (dec[\"inertia\"]) delete dec[\"inertia\"];\n else dec[\"inertia\"] = true;\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n setMethod(element: WardleyShape, method: Method | undefined): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n if (method) dec[\"method\"] = method;\n else delete dec[\"method\"];\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n /** Sets market/ecosystem (mutually exclusive) or removes both (`undefined`). */\n setMarketEcosystem(element: WardleyShape, kind: \"market\" | \"ecosystem\" | undefined): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n delete dec[\"market\"];\n delete dec[\"ecosystem\"];\n if (kind) dec[kind] = true;\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n /** Sets the element color (CSS color/hex) or removes it (`undefined` = default color). */\n setColor(element: WardleyShape, color: string | undefined): void {\n this.updateProperties(element, { color });\n }\n}\n\nfunction sameSize(a: MapSize | undefined, b: MapSize | undefined): boolean {\n if (!a || !b) return a === b;\n return a.width === b.width && a.height === b.height;\n}\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n","import type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Mouse from \"diagram-js/lib/features/mouse/Mouse\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\n\n/** Offset (px) accumulated per paste operation. */\nconst PASTE_OFFSET = 24;\n\ninterface ShapeSnapshot {\n readonly id: string;\n readonly pipelineId?: string;\n readonly props: Record<string, unknown>;\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n readonly label: string;\n}\ninterface ConnectionSnapshot {\n readonly sourceIdx: number;\n readonly targetIdx: number;\n readonly props: Record<string, unknown>;\n}\n\n/** Wardley properties carried along when copying (geometry handled separately). */\nconst SHAPE_PROPS = [\n \"wardleyType\",\n \"evolution\",\n \"visibility\",\n \"decorators\",\n \"movement\",\n \"evolutionStart\",\n \"evolutionEnd\",\n \"annotationNumber\",\n \"attitudeKind\",\n \"corner2\",\n \"acceleratorDirection\",\n \"labelOffset\",\n \"color\",\n \"drawingPoints\",\n \"closed\",\n \"strokeStyle\",\n] as const;\nconst CONNECTION_PROPS = [\"wardleyType\", \"bidirectional\", \"flowValue\", \"linkLabel\"] as const;\n\nfunction snapshotProps(\n el: Record<string, unknown>,\n keys: readonly string[],\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const key of keys) {\n const value = el[key];\n if (value !== undefined) out[key] = structuredClone(value);\n }\n return out;\n}\n\n/**\n * Custom copy/paste for Wardley shapes: copies the selection including the connections BETWEEN\n * selected shapes and assigns unique labels (the DSL references by name!).\n * Paste attaches the clones to the cursor like palette create (live preview, click places,\n * Escape cancels); duplicate inserts immediately with an offset. Either way the insert is ONE\n * undoable `elements.create` command.\n */\nexport default class WardleyCopyPaste {\n static $inject = [\n \"selection\",\n \"modeling\",\n \"elementFactory\",\n \"canvas\",\n \"create\",\n \"mouse\",\n \"wardleyElementFactory\",\n ];\n\n private clipboard: { shapes: ShapeSnapshot[]; connections: ConnectionSnapshot[] } | null = null;\n private pasteCount = 0;\n\n constructor(\n private readonly selection: Selection,\n private readonly modeling: Modeling,\n private readonly elementFactory: ElementFactory,\n private readonly canvas: Canvas,\n private readonly create: Create,\n private readonly mouse: Mouse,\n private readonly wardleyElementFactory: WardleyElementFactory,\n ) {}\n\n /** Copies the current selection. Returns false if nothing copyable is selected. */\n copy(): boolean {\n const selected = this.selection.get() as Element[];\n const shapes = selected.filter((el) => isWardleyShape(el)) as WardleyShape[];\n if (!shapes.length) return false;\n\n const indexOf = new Map<WardleyShape, number>(shapes.map((s, i) => [s, i]));\n const connections: ConnectionSnapshot[] = [];\n const seen = new Set<WardleyConnection>();\n for (const shape of shapes) {\n for (const conn of [...(shape.incoming ?? []), ...(shape.outgoing ?? [])]) {\n if (!isWardleyConnection(conn) || seen.has(conn)) continue;\n const sourceIdx = indexOf.get(conn.source as unknown as WardleyShape);\n const targetIdx = indexOf.get(conn.target as unknown as WardleyShape);\n if (sourceIdx === undefined || targetIdx === undefined) continue;\n seen.add(conn);\n connections.push({\n sourceIdx,\n targetIdx,\n props: snapshotProps(conn as unknown as Record<string, unknown>, CONNECTION_PROPS),\n });\n }\n }\n\n this.clipboard = {\n shapes: shapes.map((s) => ({\n id: s.id,\n ...(s.pipelineId ? { pipelineId: s.pipelineId } : {}),\n props: snapshotProps(s as unknown as Record<string, unknown>, SHAPE_PROPS),\n x: s.x,\n y: s.y,\n width: s.width,\n height: s.height,\n label: s.wardleyLabel ?? \"\",\n })),\n connections,\n };\n this.pasteCount = 0;\n return true;\n }\n\n /**\n * Paste with placement preview: the clones attach to the cursor exactly like palette create —\n * click places them, Escape cancels. Falls back to an offset insert when the mouse position\n * is unknown (e.g. paste before the pointer ever entered the canvas).\n */\n paste(): boolean {\n if (!this.clipboard?.shapes.length) return false;\n const clones = this.buildClones();\n const lastMove = this.mouse.getLastMoveEvent();\n if (lastMove) {\n // The flag keeps WardleyAppendBehavior from opening the name editor on pasted copies.\n this.create.start(lastMove, [...clones.shapes, ...clones.connections] as Element[], {\n wardleyPaste: true,\n });\n return true;\n }\n return this.insertWithOffset(clones);\n }\n\n /** Copy + immediate offset insert of the selection (Ctrl+D) — no placement step. */\n duplicate(): boolean {\n if (!this.copy()) return false;\n return this.insertWithOffset(this.buildClones());\n }\n\n /** Builds fresh clone elements (unique labels, internal connections rewired). */\n private buildClones(): { shapes: Shape[]; connections: Element[] } {\n const clipboard = this.clipboard!;\n const labels = this.cloneLabels(clipboard.shapes);\n const shapes = clipboard.shapes.map((snap, i) =>\n this.elementFactory.createShape({\n ...structuredClone(snap.props),\n x: snap.x,\n y: snap.y,\n width: snap.width,\n height: snap.height,\n wardleyLabel: labels[i]!,\n ...(snap.props[\"wardleyType\"] === \"pipeline\" || snap.props[\"wardleyType\"] === \"attitude\"\n ? { isFrame: true }\n : {}),\n }),\n );\n // Members follow their copied pipeline by id, not by where they happen to land.\n const cloneIdByOriginalId = new Map(\n clipboard.shapes.map((snap, i) => [snap.id, shapes[i]!.id]),\n );\n clipboard.shapes.forEach((snap, i) => {\n const pipelineId = snap.pipelineId && cloneIdByOriginalId.get(snap.pipelineId);\n if (pipelineId) (shapes[i] as unknown as WardleyShape).pipelineId = pipelineId;\n });\n const connections = clipboard.connections.map((c) =>\n this.elementFactory.createConnection({\n ...structuredClone(c.props),\n source: shapes[c.sourceIdx]!,\n target: shapes[c.targetIdx]!,\n waypoints: [\n connectionAnchorOf(shapes[c.sourceIdx]!),\n connectionAnchorOf(shapes[c.targetIdx]!),\n ],\n }),\n );\n return { shapes, connections: connections as Element[] };\n }\n\n /**\n * Unique labels for the clones. A pipeline copied together with its anchor component (the\n * component written under the pipeline's name) keeps that pairing: both get the same new name,\n * otherwise the copy loses its anchor and the renamed component would join a box as a member.\n */\n private cloneLabels(snapshots: readonly ShapeSnapshot[]): string[] {\n const pipelineIndexByAnchor = new Map<number, number>();\n snapshots.forEach((pipeline, pipelineIndex) => {\n if (pipeline.props[\"wardleyType\"] !== \"pipeline\") return;\n const anchorIndex = snapshots.findIndex(\n (candidate, index) =>\n !pipelineIndexByAnchor.has(index) &&\n candidate.props[\"wardleyType\"] === \"component\" &&\n candidate.label === pipeline.label &&\n candidate.pipelineId !== pipeline.id,\n );\n if (anchorIndex >= 0) pipelineIndexByAnchor.set(anchorIndex, pipelineIndex);\n });\n const independent = snapshots\n .map((snapshot, index) => ({ snapshot, index }))\n .filter(({ index }) => !pipelineIndexByAnchor.has(index));\n const uniqueLabels = this.wardleyElementFactory.uniqueLabels(\n independent.map(({ snapshot }) => ({\n type: snapshot.props[\"wardleyType\"],\n label: snapshot.label,\n })),\n );\n const labels: string[] = [];\n independent.forEach(({ index }, position) => (labels[index] = uniqueLabels[position]!));\n for (const [anchorIndex, pipelineIndex] of pipelineIndexByAnchor) {\n labels[anchorIndex] = labels[pipelineIndex]!;\n }\n return labels;\n }\n\n /** One `elements.create` command = one undo step; position = group center + offset. */\n private insertWithOffset(clones: { shapes: Shape[]; connections: Element[] }): boolean {\n this.pasteCount++;\n const offset = PASTE_OFFSET * this.pasteCount;\n const bbox = groupBBox(clones.shapes);\n const created = this.modeling.createElements(\n [...clones.shapes, ...clones.connections] as Element[],\n { x: bbox.cx + offset, y: bbox.cy + offset },\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created as Element[]);\n return true;\n }\n}\n\nfunction groupBBox(shapes: Array<{ x: number; y: number; width: number; height: number }>): {\n cx: number;\n cy: number;\n} {\n const minX = Math.min(...shapes.map((s) => s.x));\n const minY = Math.min(...shapes.map((s) => s.y));\n const maxX = Math.max(...shapes.map((s) => s.x + s.width));\n const maxY = Math.max(...shapes.map((s) => s.y + s.height));\n return { cx: (minX + maxX) / 2, cy: (minY + maxY) / 2 };\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport MouseModule from \"diagram-js/lib/features/mouse\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport WardleyModeling from \"./WardleyModeling.js\";\nimport WardleyCopyPaste from \"./WardleyCopyPaste.js\";\nimport { mapProjectionModule } from \"../map-resize/index.js\";\n\n/** High-level Wardley mutations + registration of the custom command handlers. */\nexport const wardleyModelingModule: ModuleDeclaration = {\n // Mouse/Create are needed by the paste preview (clones attach to the cursor).\n __depends__: [MouseModule, CreateModule, mapProjectionModule],\n __init__: [\"wardleyModeling\"],\n wardleyModeling: [\"type\", WardleyModeling],\n wardleyCopyPaste: [\"type\", WardleyCopyPaste],\n};\n\nexport { default as WardleyModeling } from \"./WardleyModeling.js\";\nexport { default as WardleyCopyPaste } from \"./WardleyCopyPaste.js\";\nexport { RESIZE_MAP, UPDATE_CONFIG } from \"./WardleyModeling.js\";\nexport type { EvolveOptions } from \"./WardleyModeling.js\";\nexport type { MapConfigUpdate } from \"./cmd/UpdateConfigHandler.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport EvolutionGrid from \"./EvolutionGrid.js\";\nimport EvolutionConstraintBehavior from \"./EvolutionConstraintBehavior.js\";\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport { wardleyLayoutModule } from \"../layout/index.js\";\nimport { wardleyModelingModule } from \"../modeling/index.js\";\n\n/** Axis background + single pixel<->normalized math (P7). */\nexport const evolutionGridModule: ModuleDeclaration = {\n evolutionGrid: [\"type\", EvolutionGrid],\n};\n\n/** Keeps normalized coordinates in sync with the geometry (editor-only). */\nexport const evolutionConstraintModule: ModuleDeclaration = {\n __init__: [\"evolutionConstraintBehavior\"],\n __depends__: [evolutionGridModule, wardleyLayoutModule, ModelingModule, wardleyModelingModule],\n evolutionConstraintBehavior: [\"type\", EvolutionConstraintBehavior],\n};\n\nexport { default as EvolutionGrid } from \"./EvolutionGrid.js\";\nexport { default as EvolutionConstraintBehavior } from \"./EvolutionConstraintBehavior.js\";\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\n\n/**\n * The notation glyphs the canvas and the palette draw (anchor, accelerator, deaccelerator; guide\n * §3.6 keeps them until the modelers' dark mode), 24x24-viewBox paths from Google Material Icons\n * (Apache-2.0, © Google). `drawIcon` renders them as SVG. The context pad draws Lucide icons\n * (`lucide.ts`).\n * Source: https://github.com/google/material-design-icons (Apache License 2.0).\n */\n\nexport const ICON_PERSON =\n \"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\";\n/** fast_forward — Accelerator. */\nexport const ICON_FAST_FORWARD = \"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\";\n/** fast_rewind — Deaccelerator. */\nexport const ICON_FAST_REWIND = \"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\";\n\n/** Draws a 24x24 icon as an SVG group centered on (cx, cy), scaled to `size`. */\nexport function drawIcon(\n path: string,\n cx: number,\n cy: number,\n size: number,\n fill: string,\n): SVGElement {\n const g = svgCreate(\"g\");\n const s = size / 24;\n svgAttr(g, {\n transform: `translate(${cx - size / 2}, ${cy - size / 2}) scale(${s})`,\n fill,\n stroke: \"none\",\n });\n svgAppend(g, svgAttr(svgCreate(\"path\"), { d: path }));\n return g;\n}\n","import type { LabelOffset } from \"@miragon/wardley-schema-model\";\nimport { ANCHOR_ICON_SIZE, COMPONENT_RADIUS } from \"./styles.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\n\n/**\n * Where the renderer puts component, anchor and evolve-target labels. Shared by the renderer and the\n * label-drag interaction so a dragged label lands exactly where the stored offset renders it.\n *\n * All positions are relative to the owning node's centre. An explicit OWM `label [dx, dy]` offset is\n * always relative to the canonical OWM slot (right of the circle, or centred above an anchor) — the\n * automatic placements below only apply while no offset is set, so imported OWM maps keep their look.\n */\n\nexport const LABEL_GAP = 7;\n/** Rough average advance of a 13px/500 label glyph; the renderer never measures text (jsdom). */\nexport const LABEL_CHAR_WIDTH = 7.5;\n/** Keeps the default label clear of the inertia bar (drawn right next to the circle). */\nexport const INERTIA_LABEL_SHIFT = 6;\nexport const LABEL_BASELINE_SHIFT = -4;\n/** Second line (sourcing method) below a name label. */\nexport const LABEL_METHOD_LINE_SHIFT = 15;\n/** Distance between the lines of a name that holds line breaks; the name editor follows it. */\nexport const LABEL_LINE_HEIGHT = 16;\nexport const LABEL_OFFSET_LIMIT = 200;\n\nexport type TextAnchor = \"start\" | \"middle\" | \"end\";\n\nexport interface LabelPlacement {\n x: number;\n y: number;\n anchor: TextAnchor;\n}\n\n/** px from a component to its evolve target along the evolution axis (undefined without evolve). */\nexport function movementDeltaX(\n shape: WardleyShape,\n grid: Pick<EvolutionGrid, \"toCanvas\">,\n): number | undefined {\n const movement = shape.movement;\n if (!movement) return undefined;\n const here = grid.toCanvas({ visibility: shape.visibility, evolution: shape.evolution });\n const there = grid.toCanvas({\n visibility: shape.visibility,\n evolution: movement.targetEvolution,\n });\n return there.x - here.x;\n}\n\nexport function estimatedLabelWidth(text: string): number {\n return Math.max(...nameLines(text).map((line) => line.length)) * LABEL_CHAR_WIDTH;\n}\n\nexport function nameLines(text: string | undefined): string[] {\n return (text ?? \"\").split(\"\\n\");\n}\n\n/**\n * How the lines of a name that holds line breaks spread around the slot of its first line:\n * `centered` keeps the block's middle on the slot (names beside a circle or a symbol), `up` keeps\n * the last line on it (a name above an icon, a pipeline's edge or an evolve arrow, which the lines\n * must stay clear of).\n */\nexport type LineGrowth = \"centered\" | \"up\";\n\nexport function firstLineBaseline(slotY: number, lineCount: number, growth: LineGrowth): number {\n const extra = (lineCount - 1) * LABEL_LINE_HEIGHT;\n return slotY - (growth === \"up\" ? extra : extra / 2);\n}\n\nexport function lastLineBaseline(slotY: number, lineCount: number, growth: LineGrowth): number {\n return firstLineBaseline(slotY, lineCount, growth) + (lineCount - 1) * LABEL_LINE_HEIGHT;\n}\n\n/** The canonical OWM slot of a component name — the origin of its `label [dx, dy]`. */\nexport function componentLabelSlot(): { x: number; y: number } {\n return { x: COMPONENT_RADIUS + LABEL_GAP, y: LABEL_BASELINE_SHIFT };\n}\n\n/**\n * A short rightward evolve would run the arrow, the target circle and the red target name into the\n * source name, so the source name moves to the left of its circle.\n */\nexport function isShortRightwardMovement(shape: WardleyShape, movementDeltaX: number): boolean {\n return (\n movementDeltaX > 0 &&\n movementDeltaX < estimatedLabelWidth(shape.wardleyLabel) + 2 * COMPONENT_RADIUS + 2 * LABEL_GAP\n );\n}\n\n/**\n * @param movementDeltaX px from the component to its evolve target (undefined without an evolve).\n */\nexport function componentLabelPlacement(\n shape: WardleyShape,\n movementDeltaX: number | undefined,\n): LabelPlacement {\n const slot = componentLabelSlot();\n if (shape.labelOffset) {\n return {\n x: slot.x + shape.labelOffset.dx,\n y: slot.y + shape.labelOffset.dy,\n anchor: \"start\",\n };\n }\n if (movementDeltaX !== undefined && isShortRightwardMovement(shape, movementDeltaX)) {\n return { x: -slot.x, y: slot.y, anchor: \"end\" };\n }\n const inertiaShift = shape.decorators?.inertia ? INERTIA_LABEL_SHIFT : 0;\n return { x: slot.x + inertiaShift, y: slot.y, anchor: \"start\" };\n}\n\n/** The canonical OWM slot of the evolve target name — the origin of the evolve's `label [dx, dy]`. */\nexport function movementLabelSlot(movementDeltaX: number): { x: number; y: number } {\n return { x: movementDeltaX + COMPONENT_RADIUS + LABEL_GAP, y: LABEL_BASELINE_SHIFT };\n}\n\n/** A leftward evolve puts the target name on the far side, away from the arrow. */\nexport function movementLabelPlacement(\n labelOffset: LabelOffset | undefined,\n movementDeltaX: number,\n): LabelPlacement {\n const slot = movementLabelSlot(movementDeltaX);\n if (labelOffset) {\n return { x: slot.x + labelOffset.dx, y: slot.y + labelOffset.dy, anchor: \"start\" };\n }\n if (movementDeltaX < 0) {\n return { x: movementDeltaX - COMPONENT_RADIUS - LABEL_GAP, y: slot.y, anchor: \"end\" };\n }\n return { x: slot.x, y: slot.y, anchor: \"start\" };\n}\n\n/** The canonical slot of an anchor name: centred above the person icon. */\nexport function anchorLabelSlot(): { x: number; y: number } {\n return { x: 0, y: -ANCHOR_ICON_SIZE / 2 + LABEL_BASELINE_SHIFT };\n}\n\nexport function anchorLabelPlacement(shape: WardleyShape): LabelPlacement {\n const slot = anchorLabelSlot();\n return {\n x: slot.x + (shape.labelOffset?.dx ?? 0),\n y: slot.y + (shape.labelOffset?.dy ?? 0),\n anchor: \"middle\",\n };\n}\n\n/** Integer px, clamped to ±LABEL_OFFSET_LIMIT; `undefined` when the label is back in its slot. */\nexport function normalizeLabelOffset(dx: number, dy: number): LabelOffset | undefined {\n const clamp = (value: number) =>\n Math.max(-LABEL_OFFSET_LIMIT, Math.min(LABEL_OFFSET_LIMIT, Math.round(value)));\n const offset = { dx: clamp(dx) || 0, dy: clamp(dy) || 0 };\n return offset.dx === 0 && offset.dy === 0 ? undefined : offset;\n}\n","import BaseRenderer from \"diagram-js/lib/draw/BaseRenderer\";\nimport { append as svgAppend, create as svgCreate, attr as svgAttr } from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike, ShapeLike, ConnectionLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport {\n COLORS,\n FONT,\n COMPONENT_RADIUS,\n COMPONENT_INNER_RADIUS,\n ANCHOR_ICON_SIZE,\n ATTITUDE_COLORS,\n ATTITUDE_TITLES,\n NOTE_LINE_HEIGHT,\n PIPELINE_ANCHOR_SIZE,\n} from \"./styles.js\";\nimport { drawIcon, ICON_FAST_FORWARD, ICON_FAST_REWIND, ICON_PERSON } from \"./icons.js\";\nimport {\n LABEL_LINE_HEIGHT,\n LABEL_METHOD_LINE_SHIFT,\n anchorLabelPlacement,\n componentLabelPlacement,\n firstLineBaseline,\n lastLineBaseline,\n movementDeltaX as movementDeltaXOf,\n movementLabelPlacement,\n nameLines,\n type LabelPlacement,\n type LineGrowth,\n} from \"./label-layout.js\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\n\n/** BaseRenderer default is 1000; 1500 wins the render.shape/render.connection event. */\nconst WARDLEY_RENDER_PRIORITY = 1500;\n\n/** Primary name text of a node (contract shared with other modules and consumers' CSS). */\nexport const NAME_LABEL_CLASS = \"wardley-name-label\";\n/** Groups every evolve visual so tools (e.g. the context pad) can tell the node from its movement. */\nexport const MOVEMENT_CLASS = \"wardley-movement\";\n/** Labels the user may drag to set an OWM `label [dx, dy]` offset (see the label-drag module). */\nexport const LABEL_HANDLE_CLASS = \"wardley-label-handle\";\n/** Which offset a dragged label writes: the node's own `labelOffset` or its evolve's. */\nexport const LABEL_ROLE_ATTRIBUTE = \"data-label-role\";\nconst ATTITUDE_TITLE_CLEARANCE = 6;\n\ntype Attrs = Record<string, string | number>;\n\nexport default class WardleyRenderer extends BaseRenderer {\n static $inject = [\"eventBus\", \"evolutionGrid\", \"elementRegistry\"];\n\n constructor(\n eventBus: EventBus,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n ) {\n super(eventBus, WARDLEY_RENDER_PRIORITY);\n }\n\n override canRender(element: ElementLike): boolean {\n return isWardleyShape(element) || isWardleyConnection(element);\n }\n\n override drawShape(visuals: SVGElement, element: ShapeLike): SVGElement {\n const shape = element as unknown as WardleyShape;\n switch (shape.wardleyType) {\n case \"pipeline\":\n return this.drawPipeline(visuals, shape);\n case \"anchor\":\n return this.drawAnchor(visuals, shape);\n case \"note\":\n return this.drawNote(visuals, shape);\n case \"attitude\":\n return this.drawAttitude(visuals, shape);\n case \"annotation\":\n return this.drawAnnotation(visuals, shape);\n case \"accelerator\":\n return this.drawAccelerator(visuals, shape);\n case \"submap\":\n return this.drawSubmap(visuals, shape);\n case \"drawing\":\n return this.drawDrawing(visuals, shape);\n case \"component\":\n default:\n return this.drawComponent(visuals, shape);\n }\n }\n\n /** Freeform drawing: polyline/polygon from relative points (see WardleyDrawTool). */\n private drawDrawing(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const pts = shape.drawingPoints ?? [];\n const dash =\n shape.strokeStyle === \"dashed\" ? \"8 5\" : shape.strokeStyle === \"dotted\" ? \"2 4\" : undefined;\n const path = svgAttr(svgCreate(shape.closed ? \"polygon\" : \"polyline\"), {\n points: pts.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: shape.color ?? COLORS.ink,\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n ...(dash ? { \"stroke-dasharray\": dash } : {}),\n });\n svgAppend(visuals, path);\n return path;\n }\n\n override drawConnection(visuals: SVGElement, element: ConnectionLike): SVGElement {\n const conn = element as unknown as WardleyConnection;\n const isFlow = conn.wardleyType === \"flow\";\n const color = isFlow ? COLORS.flow : COLORS.dependency;\n const [start, end] = endpoints(conn);\n\n const path = svgAttr(svgCreate(\"polyline\"), {\n points: `${start.x},${start.y} ${end.x},${end.y}`,\n fill: \"none\",\n stroke: color,\n \"stroke-width\": isFlow ? 2.5 : 1.5,\n \"stroke-linecap\": \"round\",\n });\n svgAppend(visuals, path);\n\n // Canon: dependencies are plain lines WITHOUT an arrowhead (direction follows from the value\n // chain, concept doc §8.3); only flow links carry arrowheads (bidirectional: on both ends).\n if (isFlow) {\n svgAppend(visuals, connectionArrow(start, end, color, 11, 5));\n if (conn.bidirectional) {\n svgAppend(visuals, connectionArrow(end, start, color, 11, 5));\n }\n }\n const mx = (start.x + end.x) / 2;\n const my = (start.y + end.y) / 2;\n if (isFlow && conn.flowValue) {\n svgAppend(\n visuals,\n label(conn.flowValue, mx, my - 5, {\n \"text-anchor\": \"middle\",\n \"font-size\": 11,\n fill: COLORS.flow,\n }),\n );\n }\n // Link annotation (`; …`) at the midpoint (a bit lower if a flow value is also present).\n if (conn.linkLabel) {\n svgAppend(\n visuals,\n label(conn.linkLabel, mx, my + (conn.flowValue ? 12 : -4), {\n \"text-anchor\": \"middle\",\n \"font-size\": 11,\n \"font-style\": \"italic\",\n fill: COLORS.axisText,\n }),\n );\n }\n return path;\n }\n\n override getShapePath(shape: ShapeLike): string {\n const { x, y, width, height } = shape;\n return `M${x},${y}l${width},0l0,${height}l${-width},0z`;\n }\n\n override getConnectionPath(connection: ConnectionLike): string {\n const [first, ...rest] = connection.waypoints;\n if (!first) return \"\";\n return `M${first.x},${first.y}` + rest.map((p: Point) => `L${p.x},${p.y}`).join(\"\");\n }\n\n private drawComponent(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const dec = shape.decorators;\n const movementDeltaX = movementDeltaXOf(shape, this.grid);\n\n if (movementDeltaX !== undefined) this.drawMovement(visuals, shape, cx, cy, movementDeltaX);\n if (dec?.inertia) drawInertiaMarker(visuals, cx, cy);\n\n // User-picked element color tints stroke and label (default: ink-on-paper look).\n const tint = shape.color ?? COLORS.stroke;\n const ring = circle(cx, cy, COMPONENT_RADIUS, {\n fill: COLORS.componentFill,\n stroke: tint,\n \"stroke-width\": 2,\n });\n svgAppend(visuals, ring);\n\n // \"evolving\" = double ring (echoing the BPMN intermediate event).\n if (shape.movement) {\n svgAppend(\n visuals,\n circle(cx, cy, COMPONENT_INNER_RADIUS, { fill: \"none\", stroke: tint, \"stroke-width\": 1.5 }),\n );\n }\n\n drawComponentSymbols(visuals, cx, cy, tint, dec);\n // The evolve arrow runs along the circle's centre line, which centred lines would cross.\n drawComponentLabel(\n visuals,\n shape,\n cx,\n cy,\n componentLabelPlacement(shape, movementDeltaX),\n movementDeltaX === undefined ? \"centered\" : \"up\",\n );\n return ring;\n }\n\n /** Planned evolution (canon: DASHED red line with arrow, target label in red). */\n private drawMovement(\n visuals: SVGElement,\n shape: WardleyShape,\n cx: number,\n cy: number,\n movementDeltaX: number,\n ): void {\n const mv = shape.movement;\n if (!mv) return;\n const group = svgAttr(svgCreate(\"g\"), { class: MOVEMENT_CLASS });\n svgAppend(visuals, group);\n const tx = cx + movementDeltaX;\n // End the arrowhead BEFORE the target circle's edge — otherwise the circle hides it entirely.\n const dir = Math.sign(movementDeltaX) || 1;\n const tipX = tx - dir * (COMPONENT_RADIUS + 2);\n // Paper-coloured knock-out: a pipeline's dashed top edge runs through its anchor component's\n // centre line, and two interleaved dash patterns read as one broken line.\n svgAppend(\n group,\n line(cx, cy, tipX, cy, {\n stroke: COLORS.plotBackground,\n \"stroke-width\": 4,\n \"stroke-linecap\": \"butt\",\n class: \"wardley-movement-underlay\",\n }),\n );\n svgAppend(\n group,\n line(cx, cy, tipX, cy, {\n stroke: COLORS.movement,\n \"stroke-width\": 1.5,\n \"stroke-dasharray\": \"6 4\",\n }),\n );\n svgAppend(group, connectionArrow({ x: cx, y: cy }, { x: tipX, y: cy }, COLORS.movement));\n // Target circle = direct drag handle: marked by class so the evolve module can intercept a\n // mousedown on it and let the target be moved by dragging (see WardleyEvolveDragging).\n svgAppend(\n group,\n circle(tx, cy, COMPONENT_RADIUS, {\n fill: COLORS.paper,\n stroke: COLORS.movement,\n \"stroke-width\": 2,\n class: \"wardley-evolve-handle\",\n }),\n );\n // Target label (evolve Old->New) or the component's name — canonically red at the target circle.\n const placement = movementLabelPlacement(mv.labelOffset, movementDeltaX);\n const targetName = mv.newLabel ?? shape.wardleyLabel;\n svgAppend(\n group,\n label(\n targetName,\n cx + placement.x,\n cy + placement.y,\n {\n \"font-weight\": \"500\",\n fill: COLORS.movement,\n \"text-anchor\": placement.anchor,\n class: `wardley-movement-label ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"movement\",\n },\n true,\n \"centered\",\n ),\n );\n if (mv.method) {\n const lastLineY = lastLineBaseline(\n cy + placement.y,\n nameLines(targetName).length,\n \"centered\",\n );\n svgAppend(\n group,\n label(mv.method, cx + placement.x, lastLineY + LABEL_METHOD_LINE_SHIFT, {\n \"font-size\": 10.5,\n fill: COLORS.movement,\n \"text-anchor\": placement.anchor,\n }),\n );\n }\n }\n\n private drawAnchor(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const icon = drawIcon(ICON_PERSON, cx, cy, ANCHOR_ICON_SIZE, shape.color ?? COLORS.ink);\n svgAppend(visuals, icon);\n const placement = anchorLabelPlacement(shape);\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + placement.x,\n cy + placement.y,\n {\n \"text-anchor\": placement.anchor,\n \"font-weight\": \"700\",\n class: `${NAME_LABEL_CLASS} ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"name\",\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n \"up\",\n ),\n );\n return icon;\n }\n\n private drawPipeline(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const width = Math.max(shape.width, 1);\n const tint = shape.color;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: 0,\n y: 0,\n width,\n height: Math.max(shape.height, 1),\n rx: 4,\n // No background fill — the box is a pure outline (the variants stay fully visible).\n fill: \"none\",\n stroke: tint ?? COLORS.pipeline,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"6 3\",\n });\n svgAppend(visuals, box);\n // OWM anchor convention: if a same-named component exists, THAT component is the anchor —\n // drawing a second ■ (and a duplicate label) on the box would just clutter the line.\n // Only standalone pipelines render their own ■ anchor + name on the top edge.\n const hasNamedComponent = this.elementRegistry\n .filter(\n (el) => isWardleyShape(el) && (el as unknown as WardleyShape).wardleyType === \"component\",\n )\n .some((c) => (c as unknown as WardleyShape).wardleyLabel === shape.wardleyLabel);\n if (!hasNamedComponent) {\n const half = PIPELINE_ANCHOR_SIZE / 2;\n svgAppend(\n visuals,\n svgAttr(svgCreate(\"rect\"), {\n x: width / 2 - half,\n y: -half,\n width: PIPELINE_ANCHOR_SIZE,\n height: PIPELINE_ANCHOR_SIZE,\n fill: COLORS.componentFill,\n stroke: tint ?? COLORS.stroke,\n \"stroke-width\": 2,\n }),\n );\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n width / 2 + half + 6,\n -4,\n {\n \"font-weight\": \"500\",\n class: NAME_LABEL_CLASS,\n ...(tint ? { fill: tint } : {}),\n },\n true,\n \"up\",\n ),\n );\n }\n return box;\n }\n\n private drawNote(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const color = shape.color;\n const lines = (shape.wardleyLabel ?? \"\").split(\"\\n\");\n const cx = shape.width / 2;\n // Center the block of lines vertically in the box (+4 ~ baseline offset for 13px).\n const y0 = shape.height / 2 - ((lines.length - 1) * NOTE_LINE_HEIGHT) / 2 + 4;\n const attrs = {\n \"text-anchor\": \"middle\",\n class: NAME_LABEL_CLASS,\n fill: color ?? COLORS.noteText,\n \"font-style\": \"italic\",\n // Colored notes are slightly bolder -> feedback (good/bad) stands out.\n ...(color ? { \"font-weight\": \"600\" } : {}),\n };\n let first: SVGElement | undefined;\n lines.forEach((line, i) => {\n const el = label(line, cx, y0 + i * NOTE_LINE_HEIGHT, attrs);\n svgAppend(visuals, el);\n if (!first) first = el;\n });\n return first ?? svgCreate(\"text\");\n }\n\n private drawAttitude(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const kind = shape.attitudeKind ?? \"pioneers\";\n const c = ATTITUDE_COLORS[kind] ?? ATTITUDE_COLORS[\"pioneers\"]!;\n // A user-picked color overrides the kind palette (stroke + label; the soft fill stays).\n const stroke = shape.color ?? c.stroke;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: 0,\n y: 0,\n width: Math.max(shape.width, 1),\n height: Math.max(shape.height, 1),\n rx: 10,\n fill: c.fill,\n stroke,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"5 4\",\n });\n svgAppend(visuals, box);\n // Regions sit behind every line, so a title inside the box gets struck through by dependencies.\n // Above the top edge it stays clear — unless that would leave the plot (then it stays inside).\n const plotTop = this.grid.toCanvas({ visibility: 1, evolution: 0 }).y;\n const titleAbove = shape.y - ATTITUDE_TITLE_CLEARANCE - FONT.label >= plotTop;\n // Regions are unlabelled as in OWM: the title is always the canonical kind name.\n svgAppend(\n visuals,\n label(\n ATTITUDE_TITLES[kind] ?? kind,\n titleAbove ? 4 : 10,\n titleAbove ? -ATTITUDE_TITLE_CLEARANCE : 18,\n {\n fill: stroke,\n \"font-weight\": \"700\",\n \"letter-spacing\": \"0.04em\",\n class: \"wardley-attitude-title\",\n },\n ),\n );\n return box;\n }\n\n private drawAnnotation(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const marker = circle(cx, cy, 10, {\n fill: COLORS.annotationFill,\n stroke: shape.color ?? COLORS.stroke,\n \"stroke-width\": 1.25,\n });\n svgAppend(visuals, marker);\n svgAppend(\n visuals,\n label(\n String(shape.annotationNumber ?? \"\"),\n cx,\n cy + 4,\n { \"text-anchor\": \"middle\", \"font-size\": 11, \"font-weight\": \"700\" },\n false,\n ),\n );\n if (shape.wardleyLabel) {\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + 15,\n cy + 4,\n { \"font-size\": 12, fill: COLORS.noteText, class: NAME_LABEL_CLASS },\n true,\n \"centered\",\n ),\n );\n }\n return marker;\n }\n\n private drawAccelerator(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const accelerate = shape.acceleratorDirection !== \"deaccelerate\";\n // Real arrow symbol (OWM canon: a clearly visible market force, not a text glyph).\n const sym = drawIcon(\n accelerate ? ICON_FAST_FORWARD : ICON_FAST_REWIND,\n cx,\n cy,\n 24,\n shape.color ?? (accelerate ? COLORS.accelerator : COLORS.deaccelerator),\n );\n svgAppend(visuals, sym);\n if (shape.wardleyLabel) {\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + 15,\n cy + 5,\n { \"font-size\": 12, class: NAME_LABEL_CLASS },\n true,\n \"centered\",\n ),\n );\n }\n return sym;\n }\n\n private drawSubmap(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const r = COMPONENT_RADIUS + 1;\n const tint = shape.color ?? COLORS.stroke;\n const outer = svgAttr(svgCreate(\"rect\"), {\n x: cx - r,\n y: cy - r,\n width: r * 2,\n height: r * 2,\n rx: 3,\n fill: COLORS.componentFill,\n stroke: tint,\n \"stroke-width\": 2,\n });\n svgAppend(visuals, outer);\n svgAppend(\n visuals,\n svgAttr(svgCreate(\"rect\"), {\n x: cx - r + 3,\n y: cy - r + 3,\n width: r * 2 - 6,\n height: r * 2 - 6,\n rx: 1.5,\n fill: \"none\",\n stroke: tint,\n \"stroke-width\": 1,\n }),\n );\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + r + 6,\n cy - 6,\n {\n \"font-weight\": \"500\",\n class: NAME_LABEL_CLASS,\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n \"centered\",\n ),\n );\n return outer;\n }\n}\n\nfunction drawInertiaMarker(visuals: SVGElement, cx: number, cy: number): void {\n const bx = cx + COMPONENT_RADIUS + 3;\n svgAppend(\n visuals,\n line(bx, cy - 13, bx, cy + 13, {\n stroke: COLORS.inertia,\n \"stroke-width\": 3,\n \"stroke-linecap\": \"round\",\n }),\n );\n}\n\n/** Canon symbols: market = three dots in a triangle, ecosystem = dotted outer ring. */\nfunction drawComponentSymbols(\n visuals: SVGElement,\n cx: number,\n cy: number,\n tint: string,\n dec: WardleyShape[\"decorators\"],\n): void {\n if (dec?.ecosystem) {\n svgAppend(\n visuals,\n circle(cx, cy, COMPONENT_RADIUS + 3.5, {\n fill: \"none\",\n stroke: tint,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"1.5 3\",\n \"stroke-linecap\": \"round\",\n }),\n );\n }\n if (dec?.market) {\n for (const [mx, my] of [\n [0, -3.8],\n [-3.4, 2.4],\n [3.4, 2.4],\n ] as const) {\n svgAppend(visuals, circle(cx + mx, cy + my, 1.7, { fill: tint }));\n }\n }\n}\n\n/**\n * Name label (honoring the OWM `label [dx, dy]` offset) plus the optional sourcing method below it.\n * Sourcing stays a subtle text label — deliberately no marker box (product decision: calm canvas).\n */\nfunction drawComponentLabel(\n visuals: SVGElement,\n shape: WardleyShape,\n cx: number,\n cy: number,\n placement: LabelPlacement,\n growth: LineGrowth,\n): void {\n const lx = cx + placement.x;\n const ly = cy + placement.y;\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n lx,\n ly,\n {\n \"font-weight\": \"500\",\n \"text-anchor\": placement.anchor,\n class: `${NAME_LABEL_CLASS} ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"name\",\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n growth,\n ),\n );\n const method = shape.decorators?.method;\n if (method) {\n const lastLineY = lastLineBaseline(ly, nameLines(shape.wardleyLabel).length, growth);\n svgAppend(\n visuals,\n label(method, lx, lastLineY + LABEL_METHOD_LINE_SHIFT, {\n \"font-size\": 10.5,\n \"text-anchor\": placement.anchor,\n fill: COLORS.axisText,\n }),\n );\n }\n}\n\nfunction circle(cx: number, cy: number, r: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"circle\"), { cx, cy, r, \"stroke-width\": 1, ...attrs });\n}\n\nfunction line(x1: number, y1: number, x2: number, y2: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"line\"), { x1, y1, x2, y2, ...attrs });\n}\n\n/**\n * Text label with a paper halo (paint-order: stroke) for legibility over lines/bands.\n * `halo=false` disables the halo (e.g. for annotation numbers on a filled marker). With `growth`\n * the content is a name whose line breaks make lines of their own (one `<tspan>` each, so it\n * stays a single text for dragging and editing); `y` is the baseline of a name of one line.\n */\nfunction label(\n content: string,\n x: number,\n y: number,\n attrs: Attrs = {},\n halo = true,\n growth?: LineGrowth,\n): SVGElement {\n const lines = growth ? nameLines(content) : [content];\n const firstLineY = growth ? firstLineBaseline(y, lines.length, growth) : y;\n const haloAttrs: Attrs = halo\n ? {\n stroke: COLORS.paper,\n \"stroke-width\": 3.5,\n \"paint-order\": \"stroke\",\n \"stroke-linejoin\": \"round\",\n }\n : {};\n const el = svgAttr(svgCreate(\"text\"), {\n x,\n y: firstLineY,\n \"font-family\": FONT.family,\n \"font-size\": FONT.label,\n fill: COLORS.ink,\n ...haloAttrs,\n ...attrs,\n });\n if (lines.length === 1) {\n el.textContent = lines[0]!;\n return el;\n }\n lines.forEach((line, index) => {\n const row = svgAttr(svgCreate(\"tspan\"), { x, y: firstLineY + index * LABEL_LINE_HEIGHT });\n row.textContent = line;\n svgAppend(el, row);\n });\n return el;\n}\n\nfunction connectionArrow(from: Point, to: Point, color: string, len = 10, w = 5): SVGElement {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const bx = to.x - len * Math.cos(angle);\n const by = to.y - len * Math.sin(angle);\n const points =\n `${to.x},${to.y} ` +\n `${bx - w * Math.sin(angle)},${by + w * Math.cos(angle)} ` +\n `${bx + w * Math.sin(angle)},${by - w * Math.cos(angle)}`;\n return svgAttr(svgCreate(\"polygon\"), { points, fill: color });\n}\n\n/** Effective radius of a node for cropping the connection at its boundary. */\nfunction radiusOf(s: WardleyShape): number {\n if (s.wardleyType === \"component\") return COMPONENT_RADIUS + 2;\n if (s.wardleyType === \"anchor\") return ANCHOR_ICON_SIZE / 2 + 1;\n if (s.wardleyType === \"pipeline\") return PIPELINE_ANCHOR_SIZE / 2 + 2;\n return Math.min(s.width, s.height) / 2;\n}\n\n/**\n * Connection endpoints from the CURRENT node centers, cropped at their boundary\n * (BPMN look: line ends at the edge, arrowhead visible — independent of z-order, and\n * correct after moving, since recomputed on every render).\n */\nfunction endpoints(conn: WardleyConnection): [Point, Point] {\n const s = conn.source as unknown as WardleyShape | undefined;\n const t = conn.target as unknown as WardleyShape | undefined;\n const wp = conn.waypoints;\n if (!s || !t) {\n const a = wp[0] ?? { x: 0, y: 0 };\n return [a, wp[wp.length - 1] ?? a];\n }\n const sc = connectionAnchorOf(s);\n const tc = connectionAnchorOf(t);\n const dx = tc.x - sc.x;\n const dy = tc.y - sc.y;\n const dist = Math.hypot(dx, dy) || 1;\n const ux = dx / dist;\n const uy = dy / dist;\n const sr = radiusOf(s);\n const tr = radiusOf(t);\n if (dist <= sr + tr + 2) return [sc, tc];\n return [\n { x: sc.x + ux * sr, y: sc.y + uy * sr },\n { x: tc.x - ux * tr, y: tc.y - uy * tr },\n ];\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyRenderer from \"./WardleyRenderer.js\";\n\n/** SVG rendering of all Wardley types (BaseRenderer subclass, priority 1500). */\nexport const wardleyDrawModule: ModuleDeclaration = {\n __init__: [\"wardleyRenderer\"],\n wardleyRenderer: [\"type\", WardleyRenderer],\n};\n\nexport {\n default as WardleyRenderer,\n LABEL_HANDLE_CLASS,\n LABEL_ROLE_ATTRIBUTE,\n MOVEMENT_CLASS,\n NAME_LABEL_CLASS,\n} from \"./WardleyRenderer.js\";\nexport {\n componentLabelPlacement,\n componentLabelSlot,\n movementDeltaX,\n movementLabelPlacement,\n movementLabelSlot,\n normalizeLabelOffset,\n type LabelPlacement,\n} from \"./label-layout.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport { WardleyBaseViewer } from \"./WardleyBaseViewer.js\";\nimport { wardleyModelModule } from \"./model/index.js\";\nimport { evolutionGridModule } from \"./evolution-grid/index.js\";\nimport { wardleyDrawModule } from \"./draw/index.js\";\nimport { ioModule } from \"./io/index.js\";\n\nexport class Viewer extends WardleyBaseViewer {\n protected _getModules(): ModuleDeclaration[] {\n return [wardleyModelModule, evolutionGridModule, wardleyDrawModule, ioModule];\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { FreeRect, FreeRectInsets } from \"../free-rect/index.js\";\nimport { exportBounds } from \"../io/index.js\";\n\n/** Margins in diagram px, for hosts that report no chrome insets. */\nconst PAD_TOP = 180;\nconst PAD_BOTTOM = 80;\nconst PAD_SIDE = 120;\n/**\n * Screen px of empty space the view may show beyond the content inside the host's free rectangle.\n * Room on both sides of an axis, so a view the host fitted into its free rectangle (guide §5.9)\n * is never pulled away: the host would take the pull for a user move and stop keeping the view\n * fitted.\n */\nconst INSET_SLACK = 96;\nconst EPSILON = 0.5;\n\ninterface Pads {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** The free rectangle along one axis, in diagram px at the view's scale. */\ninterface FreeAxis {\n /** Covered by the host's chrome before and after the free part. */\n before: number;\n after: number;\n slack: number;\n}\n\ntype ViewBox = { x: number; y: number; width: number; height: number; scale?: number };\ntype Bounds = { x: number; y: number; width: number; height: number };\n\nconst clamp = (value: number, lo: number, hi: number): number =>\n value < lo ? lo : value > hi ? hi : value;\n\n/**\n * Clamps one axis of the view into `[min, max]` widened by the padding on both sides.\n *\n * @param recentre a view larger than the padded bounds is centred on them; without it the view\n * only moves as far as needed to keep `[min, max]` fully visible (after a resize the plot\n * must not jump away from the corner the user just dragged).\n */\nfunction constrainAxis(\n position: number,\n viewSize: number,\n bounds: { min: number; max: number; padBefore: number; padAfter: number },\n recentre: boolean,\n): number {\n const lowest = bounds.min - bounds.padBefore;\n const highest = bounds.max + bounds.padAfter;\n if (!recentre && viewSize >= bounds.max - bounds.min) {\n // Either stay within the padded bounds, or show the whole content: whichever moves less.\n return clamp(\n position,\n Math.min(bounds.max - viewSize, lowest),\n Math.max(bounds.min, highest - viewSize),\n );\n }\n if (viewSize <= highest - lowest) return clamp(position, lowest, highest - viewSize);\n return (lowest + highest) / 2 - viewSize / 2;\n}\n\n/**\n * The view positions along one axis that keep `bounds` in the host's free rectangle: bounds\n * smaller than the free part may sit anywhere inside it, larger ones may be panned along it, each\n * up to `slack` beyond.\n */\nfunction freeAreaRange(\n viewSize: number,\n bounds: { min: number; max: number },\n free: FreeAxis,\n): { lowest: number; highest: number } {\n const freeEnd = viewSize - free.after;\n return {\n lowest: Math.min(bounds.min - free.before - free.slack, bounds.max - freeEnd - free.slack),\n highest: Math.max(bounds.max - freeEnd + free.slack, bounds.min - free.before + free.slack),\n };\n}\n\n/**\n * Clamps one axis of the view so the content stays in the host's free rectangle. Never centres,\n * so a view the host placed in its free rectangle stays put. A view that keeps the plot there is\n * accepted as well: the import and hosts fit the plot, and a long label beyond it that makes the\n * content wider than the free part must not pull that fit sideways. The plot lies inside the\n * content, so the two ranges overlap and their hull is one range.\n */\nfunction constrainAxisToFreeArea(\n position: number,\n viewSize: number,\n content: { min: number; max: number },\n plot: { min: number; max: number },\n free: FreeAxis,\n): number {\n const byContent = freeAreaRange(viewSize, content, free);\n const byPlot = freeAreaRange(viewSize, plot, free);\n return clamp(\n position,\n Math.min(byContent.lowest, byPlot.lowest),\n Math.max(byContent.highest, byPlot.highest),\n );\n}\n\n/**\n * Keeps the map in view while scrolling and zooming.\n * Without this the user could scroll the map completely off-screen into empty space.\n * After every move we pull the visible area back so it stays close to the map,\n * leaving only a small margin of empty space around it. \"The map\" is the plot plus any content\n * reaching beyond it (long labels at the commodity edge, notes in the margin): `contentBounds()`,\n * which hosts also fit the view to. With the insets of a host's chrome (`freeArea: { insets }`)\n * the margin is measured inside the free rectangle, so the map never slips under the chrome, and a\n * view the host or the import fitted there, to the content or to the plot, is left alone.\n */\nexport default class PanConstraint {\n static $inject = [\"eventBus\", \"canvas\", \"evolutionGrid\", \"injector\"];\n\n private applying = false;\n /** Content bounds are measured lazily (getBBox), at most once per change of the map. */\n private measured: Bounds | undefined;\n /** A config change (resize) happened; re-check once its elements are redrawn. */\n private constrainAfterCommand = false;\n private readonly freeRect: FreeRect | null;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n injector: Injector,\n ) {\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n eventBus.on(\"canvas.viewbox.changed\", (event: { viewbox?: ViewBox }) => {\n if (this.applying) return;\n this.constrain(event?.viewbox);\n });\n const invalidate = () => {\n this.measured = undefined;\n };\n eventBus.on([\"element.changed\", \"import.done\"], invalidate);\n // Shrinking the plot while scrolled into its far corner must never leave a blank viewport.\n // A transient change (live resize preview) is skipped: moving the viewport under a dragged\n // plot corner would feed back into the drag.\n eventBus.on(\"wardley.config.changed\", (event?: { transient?: boolean }) => {\n invalidate();\n if (event?.transient) return;\n this.constrain(undefined, { recentre: false });\n // The command's elements are redrawn only after this event — measure again once they are.\n this.constrainAfterCommand = true;\n });\n eventBus.on(\"commandStack.changed\", () => {\n if (!this.constrainAfterCommand) return;\n invalidate();\n this.constrain(undefined, { recentre: false });\n });\n }\n\n /**\n * The plot (with its axis margins) united with everything drawn on it or beyond it, tight (no\n * padding): what a host fits the view to.\n */\n contentBounds(): Bounds {\n this.measured ??= exportBounds(this.canvas, this.grid, 0);\n return this.measured;\n }\n\n /** The host's free rectangle along both axes at the view's scale, if the host reports one. */\n private freeArea(view: ViewBox): { x: FreeAxis; y: FreeAxis } | undefined {\n const insets: FreeRectInsets | undefined = this.freeRect?.insets();\n const scale = insets ? (view.scale ?? this.canvas.zoom()) : 0;\n if (!insets || !(scale > 0)) return undefined;\n const slack = INSET_SLACK / scale;\n // An axis the chrome leaves no room on counts as free across the whole container, as the\n // host's fit and keyboard creation treat it.\n const axis = (size: number, before: number, after: number): FreeAxis =>\n size * scale - before - after > 0\n ? { before: before / scale, after: after / scale, slack }\n : { before: 0, after: 0, slack };\n return {\n x: axis(view.width, insets.left, insets.right),\n y: axis(view.height, insets.top, insets.bottom),\n };\n }\n\n private constrain(viewbox?: ViewBox, { recentre = true }: { recentre?: boolean } = {}): void {\n this.constrainAfterCommand = false;\n const current = viewbox ?? (this.canvas.viewbox() as unknown as ViewBox);\n const bounds = this.contentBounds();\n if (\n !(bounds.width > 0) ||\n !(bounds.height > 0) ||\n !(current.width > 0) ||\n !(current.height > 0)\n )\n return;\n\n const horizontal = { min: bounds.x, max: bounds.x + bounds.width };\n const vertical = { min: bounds.y, max: bounds.y + bounds.height };\n const free = this.freeArea(current);\n const plot = this.grid.outerBounds();\n const pads: Pads = { top: PAD_TOP, right: PAD_SIDE, bottom: PAD_BOTTOM, left: PAD_SIDE };\n const clampedX = free\n ? constrainAxisToFreeArea(\n current.x,\n current.width,\n horizontal,\n { min: plot.x, max: plot.x + plot.width },\n free.x,\n )\n : constrainAxis(\n current.x,\n current.width,\n { ...horizontal, padBefore: pads.left, padAfter: pads.right },\n recentre,\n );\n const clampedY = free\n ? constrainAxisToFreeArea(\n current.y,\n current.height,\n vertical,\n { min: plot.y, max: plot.y + plot.height },\n free.y,\n )\n : constrainAxis(\n current.y,\n current.height,\n { ...vertical, padBefore: pads.top, padAfter: pads.bottom },\n recentre,\n );\n\n if (Math.abs(clampedX - current.x) < EPSILON && Math.abs(clampedY - current.y) < EPSILON)\n return;\n\n this.applying = true;\n try {\n this.canvas.viewbox({\n x: clampedX,\n y: clampedY,\n width: current.width,\n height: current.height,\n });\n } finally {\n this.applying = false;\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PanConstraint from \"./PanConstraint.js\";\n\nexport const PanConstraintModule: ModuleDeclaration = {\n __init__: [\"panConstraint\"],\n panConstraint: [\"type\", PanConstraint],\n};\n\nexport { default as PanConstraint } from \"./PanConstraint.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\n\n/** What a host's chrome covers along the container's edges, in px (Miragon guide §5.9). */\nexport interface FreeRectInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** Diagram config `wardleyFreeRect` (viewer option `freeArea`). */\nexport interface FreeRectConfig {\n /** What the chrome covers, in px from the container's edges. */\n insets?: () => FreeRectInsets;\n /** The centre of the free rectangle in diagram coordinates, `undefined` while there is none. */\n center?: () => { x: number; y: number } | undefined;\n}\n\n/**\n * The part of the canvas no host chrome covers. Keyboard creation places new elements in its\n * centre (guide §5.5) and the pan constraint keeps the map reachable around it, so both agree with\n * a host that fits the map into the same rectangle.\n */\nexport default class FreeRect {\n static $inject = [\"canvas\", \"config.wardleyFreeRect\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly config: FreeRectConfig | undefined,\n ) {}\n\n /** The host's insets, or `undefined` when it reports none. */\n insets(): FreeRectInsets | undefined {\n const insets = this.config?.insets?.();\n if (!insets) return undefined;\n const sides = [insets.top, insets.right, insets.bottom, insets.left];\n return sides.every((side) => Number.isFinite(side) && side >= 0) ? insets : undefined;\n }\n\n /**\n * The centre of the free rectangle in diagram coordinates: the host's own when it reports one,\n * else the whole visible area without insets. An axis whose insets leave no room centres in the\n * whole container, as fitting does.\n */\n center(): { x: number; y: number } {\n const reported = this.config?.center?.();\n if (reported && Number.isFinite(reported.x) && Number.isFinite(reported.y)) return reported;\n const viewbox = this.canvas.viewbox();\n const insets = this.insets() ?? { top: 0, right: 0, bottom: 0, left: 0 };\n // The viewbox caches the container size until its next change; the canvas measures afresh.\n const { width, height } = this.canvas.getSize();\n const centerOf = (size: number, before: number, after: number) =>\n size - before - after > 0 ? before + (size - before - after) / 2 : size / 2;\n return {\n x: viewbox.x + centerOf(width, insets.left, insets.right) / viewbox.scale,\n y: viewbox.y + centerOf(height, insets.top, insets.bottom) / viewbox.scale,\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport FreeRect from \"./FreeRect.js\";\n\n/** The canvas area a host's chrome leaves free (keyboard creation, pan constraint). */\nexport const freeRectModule: ModuleDeclaration = {\n wardleyFreeRect: [\"type\", FreeRect],\n};\n\nexport { default as FreeRect } from \"./FreeRect.js\";\nexport type { FreeRectConfig, FreeRectInsets } from \"./FreeRect.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport SelectionModule from \"diagram-js/lib/features/selection\";\nimport ZoomScrollModule from \"diagram-js/lib/navigation/zoomscroll\";\nimport MoveCanvasModule from \"diagram-js/lib/navigation/movecanvas\";\nimport KeyboardModule from \"diagram-js/lib/features/keyboard\";\nimport { Viewer } from \"./Viewer.js\";\nimport { PanConstraintModule } from \"./pan-constraint/index.js\";\nimport { freeRectModule } from \"./free-rect/index.js\";\n\n/**\n * `keyboard-move-selection` depends on `modeling` and therefore belongs in the (later) Modeler,\n * not in the read-only NavigatedViewer.\n */\nexport class NavigatedViewer extends Viewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n SelectionModule,\n ZoomScrollModule,\n MoveCanvasModule,\n KeyboardModule,\n freeRectModule,\n PanConstraintModule,\n ];\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\n\ninterface ElementMouseEvent {\n element?: unknown;\n originalEvent?: MouseEvent;\n}\n\n/**\n * Activates the diagram-js lasso via Shift+drag on the empty canvas.\n * Plain drag stays canvas pan (MoveCanvas); Shift+click on elements stays multi-select.\n */\nexport default class WardleyLassoBehavior {\n static $inject = [\"eventBus\", \"canvas\", \"lassoTool\"];\n\n constructor(eventBus: EventBus, canvas: Canvas, lassoTool: LassoTool) {\n eventBus.on(\"element.mousedown\", 1500, (event: ElementMouseEvent) => {\n const original = event.originalEvent;\n if (!original?.shiftKey) return undefined;\n let root: unknown;\n try {\n root = canvas.getRootElement();\n } catch {\n return undefined;\n }\n if (event.element !== root) return undefined;\n lassoTool.activateLasso(original);\n // Returning false stops lower-priority listeners (canvas pan).\n return false;\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport LassoToolModule from \"diagram-js/lib/features/lasso-tool\";\nimport WardleyLassoBehavior from \"./WardleyLassoBehavior.js\";\n\n/** Lasso multi-select: diagram-js lasso-tool plus Shift+drag activation on an empty canvas. */\nexport const wardleyLassoModule: ModuleDeclaration = {\n __depends__: [LassoToolModule],\n __init__: [\"wardleyLassoBehavior\"],\n wardleyLassoBehavior: [\"type\", WardleyLassoBehavior],\n};\n\nexport { default as WardleyLassoBehavior } from \"./WardleyLassoBehavior.js\";\n","import RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { isWardleyShape, isPipeline, isAttitude, type WardleyShape } from \"../model/di-types.js\";\n\n// Submaps are referenceable nodes on the parent map (OWM serializes their edges by name);\n// pipelines connect via their ■ anchor.\nconst CONNECTABLE: ReadonlySet<string> = new Set([\"component\", \"anchor\", \"submap\", \"pipeline\"]);\n\nconst HORIZONTAL_RESIZE_DIRECTIONS: ReadonlySet<string> = new Set([\"e\", \"w\"]);\n\nfunction isConnectable(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && CONNECTABLE.has(el.wardleyType);\n}\n\n/** Is there already a connection between the two shapes (in either direction)? */\nfunction alreadyConnected(source: WardleyShape, target: WardleyShape): boolean {\n return (\n (source.outgoing ?? []).some((c) => c.target === (target as unknown)) ||\n (source.incoming ?? []).some((c) => c.source === (target as unknown))\n );\n}\n\n/**\n * Allowed edit operations (concept doc §5.4). On success the `connection.create` rule returns\n * the new connection's attributes. The editor deliberately only creates dependencies — flow\n * links (`+>`) exist for OWM import compatibility but are not authored interactively.\n */\nexport default class WardleyRules extends RuleProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override init(): void {\n this.addRule(\"connection.start\", (context: { source?: unknown }) =>\n isConnectable(context.source),\n );\n\n this.addRule(\"connection.create\", (context: { source?: unknown; target?: unknown }) => {\n const { source, target } = context;\n if (!isConnectable(source) || !isConnectable(target)) return false;\n if (source === target) return false;\n // Duplicate lines between the same endpoints are never meaningful (and indistinguishable\n // in the DSL) — prevent them instead of silently stacking.\n if (alreadyConnected(source, target)) return false;\n return { wardleyType: \"dependency\" };\n });\n\n this.addRule(\"shape.move\", () => true);\n // Shapes never nest: hovering another element during a drag must neither re-parent the moved\n // shapes under it nor mark it as a drop target, so such hovers are ignored (null), not refused.\n this.addRule(\"elements.move\", (context: { target?: { parent?: unknown } | null }) =>\n context.target?.parent ? null : true,\n );\n this.addRule(\"shape.create\", () => true);\n // Group create (paste preview): diagram-js Create checks this rule for element arrays.\n this.addRule(\"elements.create\", () => true);\n // Pipelines only stretch along the evolution axis — their height is not part of the model.\n this.addRule(\"shape.resize\", (context: { shape?: unknown; direction?: string }) => {\n if (isPipeline(context.shape)) {\n return !context.direction || HORIZONTAL_RESIZE_DIRECTIONS.has(context.direction);\n }\n return isAttitude(context.shape);\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyRules from \"./WardleyRules.js\";\n\n/** Allowed Wardley operations (RuleProvider). */\nexport const wardleyRulesModule: ModuleDeclaration = {\n __init__: [\"wardleyRules\"],\n wardleyRules: [\"type\", WardleyRules],\n};\n\nexport { default as WardleyRules } from \"./WardleyRules.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\n\n/** Snap distance in SCREEN px, so the pull feels the same at every zoom level. */\nexport const SNAP_TOLERANCE_SCREEN_PX = 8;\n\ninterface DragMoveEvent {\n x?: number;\n /** Delta since drag start — diagram-js move/resize works ONLY with dx/dy, never with x. */\n dx?: number;\n originalEvent?: { shiftKey?: boolean };\n context?: { shape?: { x: number; width: number } };\n}\n\n/**\n * Snaps the X position (evolution) during move/create/resize to the stage boundaries, within\n * `SNAP_TOLERANCE_SCREEN_PX` on screen (converted to diagram units with the current zoom).\n * Disabled while the Shift key is held. Important: `x` and `dx` must be adjusted TOGETHER\n * (like diagram-js' `setSnapped`) — move takes the final position from `dx`, so a mutated\n * `x` alone would have no effect.\n */\nexport default class StageSnapping {\n static $inject = [\"eventBus\", \"evolutionGrid\", \"canvas\"];\n\n constructor(eventBus: EventBus, grid: EvolutionGrid, canvas: Canvas) {\n const tolerance = () => SNAP_TOLERANCE_SCREEN_PX / (canvas.zoom() || 1);\n const boundaryXs = () =>\n grid.getBoundaries().map((b) => grid.toCanvas({ visibility: 0.5, evolution: b }).x);\n\n const setSnappedX = (event: DragMoveEvent, sx: number) => {\n if (typeof event.dx === \"number\" && typeof event.x === \"number\") {\n event.dx += sx - event.x;\n }\n event.x = sx;\n };\n\n // Move: snap the SHAPE MIDPOINT (not the cursor) — the user rarely grabs the shape exactly at its centre.\n eventBus.on([\"shape.move.move\", \"shape.move.end\"], 1500, (event: DragMoveEvent) => {\n if (event.originalEvent?.shiftKey) return;\n if (typeof event.x !== \"number\" || typeof event.dx !== \"number\") return;\n const shape = event.context?.shape;\n if (!shape) return;\n const mid = shape.x + shape.width / 2 + event.dx;\n const maxDistance = tolerance();\n for (const sx of boundaryXs()) {\n if (Math.abs(mid - sx) <= maxDistance) {\n const d = sx - mid;\n event.dx += d;\n event.x += d;\n break;\n }\n }\n });\n\n // Create (cursor = shape midpoint) and resize (cursor = dragged edge): snap the cursor.\n eventBus.on(\n [\"create.move\", \"create.end\", \"resize.move\", \"resize.end\"],\n 1500,\n (event: DragMoveEvent) => {\n if (event.originalEvent?.shiftKey) return;\n if (typeof event.x !== \"number\") return;\n const maxDistance = tolerance();\n for (const sx of boundaryXs()) {\n if (Math.abs(event.x - sx) <= maxDistance) {\n setSnappedX(event, sx);\n break;\n }\n }\n },\n );\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport StageSnapping from \"./StageSnapping.js\";\n\n/** Snapping to the evolution stage boundaries (editor-only). */\nexport const stageSnappingModule: ModuleDeclaration = {\n __init__: [\"stageSnapping\"],\n stageSnapping: [\"type\", StageSnapping],\n};\n\nexport { default as StageSnapping } from \"./StageSnapping.js\";\n","/*! @miragon/wardley-renderer icon geometry: square-dashed-mouse-pointer, and spline drawn with a\n * straight segment. Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Full notice: README.md of @miragon/wardley-renderer */\nimport { COLORS, ATTITUDE_COLORS, FONT } from \"./styles.js\";\nimport { ICON_FAST_FORWARD, ICON_FAST_REWIND, ICON_PERSON } from \"./icons.js\";\n\n/**\n * Palette icons: the creating entries are a mini preview of the ACTUAL canvas rendering\n * (WYSIWYG) — same colors and shapes as the WardleyRenderer, so the palette shows what will be\n * created.\n */\n\nconst wrap = (inner: string): string =>\n `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" class=\"wardley-palette-svg\">${inner}</svg>`;\n\n/**\n * A Lucide outline icon (lucide-static 1.59.0, ISC, © Lucide Icons and Contributors) at the palette\n * tool size of guide §5.5 (20px, stroke 2): it draws in `currentColor`, so the chrome around the\n * entry decides the colour (hover, pressed tool, read-only).\n */\nconst toolIcon = (inner: string): string =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\" class=\"wardley-palette-svg\">${inner}</svg>`;\n\nconst LUCIDE_SQUARE_DASHED_MOUSE_POINTER =\n '<path d=\"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z\"/>' +\n '<path d=\"M5 3a2 2 0 0 0-2 2\"/>' +\n '<path d=\"M19 3a2 2 0 0 1 2 2\"/>' +\n '<path d=\"M5 21a2 2 0 0 1-2-2\"/>' +\n '<path d=\"M9 3h1\"/>' +\n '<path d=\"M9 21h2\"/>' +\n '<path d=\"M14 3h1\"/>' +\n '<path d=\"M3 9v1\"/>' +\n '<path d=\"M21 9v2\"/>' +\n '<path d=\"M3 14v1\"/>';\n\n// Lucide's spline with a straight segment between its end points (guide §5.14, line-segment): the\n// curve read as a telephone receiver at 20px.\nconst LINE_SEGMENT =\n '<circle cx=\"19\" cy=\"5\" r=\"2\"/>' +\n '<circle cx=\"5\" cy=\"19\" r=\"2\"/>' +\n '<path d=\"M6.5 17.5 17.5 6.5\"/>';\n\nconst eventCircle = (extra = \"\"): string =>\n `<circle cx=\"12\" cy=\"12\" r=\"7\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"2\"/>${extra}`;\n\nconst text = (content: string, attrs: string): string =>\n `<text x=\"12\" text-anchor=\"middle\" font-family=\"${FONT.family}\" ${attrs}>${content}</text>`;\n\nexport const PALETTE_ICONS: Record<string, string> = {\n // The tools use the common Lucide icons of the Miragon modelers; the create glyphs keep the\n // notation colours because they preview the element.\n draw: toolIcon(LINE_SEGMENT),\n lasso: toolIcon(LUCIDE_SQUARE_DASHED_MOUSE_POINTER),\n component: wrap(eventCircle()),\n // Canon: market = three dots in a triangle (like drawComponent).\n market: wrap(\n eventCircle(\n `<circle cx=\"12\" cy=\"10\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>` +\n `<circle cx=\"10.2\" cy=\"13.4\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>` +\n `<circle cx=\"13.8\" cy=\"13.4\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>`,\n ),\n ),\n // Canon: ecosystem = dotted outer ring (like drawComponent).\n ecosystem: wrap(\n eventCircle(\n `<circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.25\" stroke-dasharray=\"1.5 3\" stroke-linecap=\"round\"/>`,\n ),\n ),\n anchor: wrap(`<path d=\"${ICON_PERSON}\" fill=\"${COLORS.ink}\"/>`),\n // Pipeline = ■ anchor on top, box with variant circles hanging below (Wardley notation).\n pipeline: wrap(\n `<rect x=\"9.5\" y=\"2.5\" width=\"5.5\" height=\"5.5\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.5\"/>` +\n `<rect x=\"2\" y=\"10\" width=\"20\" height=\"9\" rx=\"2\" fill=\"none\" stroke=\"${COLORS.pipeline}\" stroke-width=\"1.25\" stroke-dasharray=\"3 2\"/>` +\n `<circle cx=\"7\" cy=\"14.5\" r=\"2.2\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.2\"/>` +\n `<circle cx=\"17\" cy=\"14.5\" r=\"2.2\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.2\"/>`,\n ),\n // Sticky note with a folded corner (distinct from the hamburger menu glyph).\n note: wrap(\n `<g fill=\"none\" stroke=\"${COLORS.noteText}\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">` +\n `<path d=\"M5 4h14v11l-5 5H5z\" fill=\"${COLORS.componentFill}\"/><path d=\"M14 20v-5h5\"/>` +\n `<line x1=\"8\" y1=\"8.5\" x2=\"16\" y2=\"8.5\"/><line x1=\"8\" y1=\"12\" x2=\"13\" y2=\"12\"/></g>`,\n ),\n annotation: wrap(\n `<circle cx=\"12\" cy=\"12\" r=\"8\" fill=\"${COLORS.annotationFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.25\"/>` +\n text(\"1\", `y=\"16\" font-size=\"11\" font-weight=\"700\" fill=\"${COLORS.stroke}\"`),\n ),\n accelerator: wrap(`<path d=\"${ICON_FAST_FORWARD}\" fill=\"${COLORS.accelerator}\"/>`),\n deaccelerator: wrap(`<path d=\"${ICON_FAST_REWIND}\" fill=\"${COLORS.deaccelerator}\"/>`),\n submap: wrap(\n `<rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"2\"/>` +\n `<rect x=\"7.5\" y=\"7.5\" width=\"9\" height=\"9\" rx=\"1.5\" fill=\"none\" stroke=\"${COLORS.stroke}\" stroke-width=\"1\"/>`,\n ),\n};\n\nconst ATTITUDE_INITIALS: Record<string, string> = {\n pioneers: \"P\",\n settlers: \"S\",\n townplanners: \"T\",\n};\n\n/** Region glyph; the initial letter tells the three kinds apart without relying on colour. */\nexport function attitudeIcon(kind: string): string {\n const c = ATTITUDE_COLORS[kind] ?? { fill: COLORS.band, stroke: COLORS.dependency };\n const initial = ATTITUDE_INITIALS[kind] ?? \"\";\n return wrap(\n `<rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"3\" fill=\"${c.fill}\" stroke=\"${c.stroke}\" stroke-width=\"1.5\" stroke-dasharray=\"3 2\"/>` +\n text(initial, `y=\"15.3\" font-size=\"9\" font-weight=\"700\" fill=\"${COLORS.ink}\"`),\n );\n}\n","import type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\nimport type WardleyDrawTool from \"../draw-tool/WardleyDrawTool.js\";\nimport type {\n PaletteEntries,\n PaletteEntry,\n default as PaletteProvider,\n} from \"diagram-js/lib/features/palette/PaletteProvider\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { CreateNewExtra } from \"../model/WardleyElementFactory.js\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Parent, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { isWardleyShape, type WardleyShape, type WardleyShapeType } from \"../model/di-types.js\";\nimport { PALETTE_ICONS, attitudeIcon } from \"../draw/palette-icons.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\n\ninterface PaletteSpec {\n key: string;\n type: WardleyShapeType;\n label: string;\n title: string;\n /** Single-key shortcut (bound by the keyboard module); shown in the palette tooltip. */\n shortcut?: string;\n icon: string;\n group: string;\n extra?: CreateNewExtra;\n}\n\n// Group IDs with a prefix number -> stable, visible ordering of the palette groups.\nconst GROUP_BLOCKS = \"wardley-1-blocks\";\nconst GROUP_STRATEGY = \"wardley-2-strategy\";\nconst GROUP_NOTES = \"wardley-3-notes\";\n\nconst SPECS: readonly PaletteSpec[] = [\n {\n key: \"component\",\n type: \"component\",\n label: \"Component\",\n title: \"Component\",\n shortcut: \"C\",\n icon: PALETTE_ICONS.component!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"market\",\n type: \"component\",\n label: \"Market\",\n title: \"Market component\",\n icon: PALETTE_ICONS.market!,\n group: GROUP_BLOCKS,\n extra: { market: true },\n },\n {\n key: \"ecosystem\",\n type: \"component\",\n label: \"Ecosystem\",\n title: \"Ecosystem component\",\n icon: PALETTE_ICONS.ecosystem!,\n group: GROUP_BLOCKS,\n extra: { ecosystem: true },\n },\n {\n key: \"anchor\",\n type: \"anchor\",\n label: \"User\",\n title: \"Anchor / User\",\n shortcut: \"U\",\n icon: PALETTE_ICONS.anchor!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"pipeline\",\n type: \"pipeline\",\n label: \"Pipeline\",\n title: \"Pipeline\",\n shortcut: \"P\",\n icon: PALETTE_ICONS.pipeline!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"submap\",\n type: \"submap\",\n label: \"Submap\",\n title: \"Submap\",\n icon: PALETTE_ICONS.submap!,\n group: GROUP_BLOCKS,\n },\n\n {\n key: \"pioneers\",\n type: \"attitude\",\n label: \"Pioneers\",\n title: \"Pioneers region\",\n icon: attitudeIcon(\"pioneers\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"pioneers\" },\n },\n {\n key: \"settlers\",\n type: \"attitude\",\n label: \"Settlers\",\n title: \"Settlers region\",\n icon: attitudeIcon(\"settlers\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"settlers\" },\n },\n {\n key: \"townplanners\",\n type: \"attitude\",\n label: \"Town Planners\",\n title: \"Town Planners region\",\n icon: attitudeIcon(\"townplanners\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"townplanners\" },\n },\n {\n key: \"accelerator\",\n type: \"accelerator\",\n label: \"Accelerate\",\n title: \"Accelerator\",\n icon: PALETTE_ICONS.accelerator!,\n group: GROUP_STRATEGY,\n extra: { acceleratorDirection: \"accelerate\" },\n },\n {\n key: \"deaccelerator\",\n type: \"accelerator\",\n label: \"Deaccelerate\",\n title: \"Deaccelerator\",\n icon: PALETTE_ICONS.deaccelerator!,\n group: GROUP_STRATEGY,\n extra: { acceleratorDirection: \"deaccelerate\" },\n },\n\n // Annotations (numbered markers + legend) are deliberately NOT in the palette: Note covers\n // free text; imported OWM maps still render annotations (viewer compatibility).\n {\n key: \"note\",\n type: \"note\",\n label: \"Note\",\n title: \"Note\",\n shortcut: \"N\",\n icon: PALETTE_ICONS.note!,\n group: GROUP_NOTES,\n },\n];\n\ninterface ToolSpec {\n key: string;\n title: string;\n shortcut?: string;\n icon: string;\n}\n\n// Names in sentence case, keys apart (guide §5.6): the chrome tooltip shows the key as a chip, and\n// the gestures (Shift+drag, how a drawing ends) are listed in the keyboard shortcuts.\nconst LASSO_TOOL: ToolSpec = {\n key: \"lasso-tool\",\n title: \"Lasso\",\n shortcut: \"L\",\n icon: PALETTE_ICONS.lasso!,\n};\n\nconst DRAW_TOOL: ToolSpec = {\n key: \"draw-tool\",\n title: \"Draw\",\n icon: PALETTE_ICONS.draw!,\n};\n\n/** Leaves room so a keyboard-created shape is not clipped by the plot edge. */\nconst PLOT_INSET = 24;\n/** Diagonal step while the free centre is taken (guide §5.5). */\nconst STACK_OFFSET = 24;\nconst MAX_STACK_STEPS = 12;\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\n/**\n * Enter or Space on an entry arrives as a click without a pointer: the keyboard of the Miragon\n * modeler shell dispatches it with `detail === 0`, every pointer click has 1 or more.\n */\nfunction isKeyboardClick(event: Event): boolean {\n return event.type === \"click\" && (event as MouseEvent).detail === 0;\n}\n\nexport default class WardleyPaletteProvider implements PaletteProvider {\n static $inject = [\n \"palette\",\n \"create\",\n \"wardleyElementFactory\",\n \"lassoTool\",\n \"wardleyDrawTool\",\n \"injector\",\n ];\n\n /**\n * diagram-js >= 15.28 renders `title` + `shortcut` as a styled tooltip, and the Miragon modeler\n * shell shows its chrome tooltip instead; only without either does an entry need a native title.\n */\n private readonly needsNativeTitle: boolean;\n\n constructor(\n palette: Palette,\n private readonly create: Create,\n private readonly factory: WardleyElementFactory,\n private readonly lassoTool: LassoTool,\n private readonly drawTool: WardleyDrawTool,\n private readonly injector: Injector,\n ) {\n // The horizontal toolbar never needs diagram-js' vertical two-column collapse, which would\n // squeeze it to 94px on canvases lower than ~694px and spill the entries out of the bar.\n (palette as unknown as { _needsCollapse: () => boolean })._needsCollapse = () => false;\n this.needsNativeTitle =\n !injector.get(\"paletteTooltip\", false) && !injector.get(\"modelerShell\", false);\n palette.registerProvider(this);\n }\n\n getPaletteEntries(): PaletteEntries {\n const entries: Record<string, PaletteEntry> = {};\n\n // Selection tool first. Group MUST be called \"tools\" and the key end in \"-tool\" — that is\n // what diagram-js' palette uses to highlight the active tool (tool-manager.update).\n entries[LASSO_TOOL.key] = {\n group: \"tools\",\n ...this.describe(LASSO_TOOL.title, LASSO_TOOL.shortcut),\n html: this.entryHtml(LASSO_TOOL.title, LASSO_TOOL.icon, LASSO_TOOL.shortcut),\n action: {\n click: (event: Event) => {\n this.lassoTool.activateSelection(event as MouseEvent);\n this.focusCanvasAfterPointer(event);\n },\n },\n };\n\n entries[DRAW_TOOL.key] = {\n group: \"tools\",\n ...this.describe(DRAW_TOOL.title, DRAW_TOOL.shortcut),\n html: this.entryHtml(DRAW_TOOL.title, DRAW_TOOL.icon, DRAW_TOOL.shortcut),\n action: {\n click: (event: Event) => {\n this.drawTool.toggle();\n this.focusCanvasAfterPointer(event);\n },\n },\n };\n\n for (const spec of SPECS) {\n const start = (event: Event) => {\n this.create.start(event, this.createShapeFor(spec));\n this.focusCanvasAfterPointer(event);\n };\n // diagram-js's create follows the pointer and never ends without one.\n const click = (event: Event) => {\n if (isKeyboardClick(event)) this.createAtFreeCenter(`create.${spec.key}`);\n else start(event);\n };\n entries[`create.${spec.key}`] = {\n group: spec.group,\n ...this.describe(spec.title, spec.shortcut),\n html: this.entryHtml(spec.title, spec.icon, spec.shortcut, true),\n action: { dragstart: start, click },\n };\n }\n return entries;\n }\n\n /**\n * Keyboard path for a create entry (guide §5.5): places the new element in the centre of the\n * free rectangle (no pointer position to attach it to), 24px further diagonally while that spot\n * is taken, selects it and opens its label editor, or focuses the canvas where there is nothing\n * to name. Returns the created shape, or undefined for non-create entries.\n */\n createAtFreeCenter(entryId: string): WardleyShape | undefined {\n const spec = SPECS.find((candidate) => `create.${candidate.key}` === entryId);\n if (!spec) return undefined;\n const modeling = this.injector.get<Modeling>(\"modeling\");\n const canvas = this.injector.get<Canvas>(\"canvas\");\n const grid = this.injector.get<EvolutionGrid>(\"evolutionGrid\");\n\n const shape = this.createShapeFor(spec);\n const position = this.freeCenterPosition(shape, canvas, grid);\n modeling.createShape(\n shape as unknown as Shape,\n position,\n canvas.getRootElement() as unknown as Parent,\n );\n\n this.injector.get<Selection>(\"selection\", false)?.select(shape as unknown as Shape);\n canvas.focus();\n // Regions are unlabelled (OWM canon), so there is nothing to name.\n if (spec.type !== \"attitude\") {\n this.injector.get<LabelEditingLike>(\"wardleyLabelEditing\", false)?.activate(shape);\n }\n return shape;\n }\n\n /**\n * Guide §5.8: an entry clicked or dragged with a pointer hands the focus to the canvas, whose keys\n * act only while it has the focus, so Delete, the arrows and Cmd/Ctrl+Z work right away. Enter\n * and Space leave it on the entry. The Miragon modeler shell does the same for its palette.\n */\n private focusCanvasAfterPointer(event: Event): void {\n if (!isKeyboardClick(event)) focusCanvasWithoutRing(this.injector.get<Canvas>(\"canvas\"));\n }\n\n private createShapeFor(spec: PaletteSpec): WardleyShape {\n return this.factory.createNew(spec.type, spec.label, spec.extra ?? {});\n }\n\n private freeCenterPosition(\n shape: WardleyShape,\n canvas: Canvas,\n grid: EvolutionGrid,\n ): { x: number; y: number } {\n const freeCenter =\n this.injector.get<FreeRect | null>(\"wardleyFreeRect\", false)?.center() ??\n (({ x, y, width, height }) => ({ x: x + width / 2, y: y + height / 2 }))(canvas.viewbox());\n const plotTopLeft = grid.toCanvas({ evolution: 0, visibility: 1 });\n const plotBottomRight = grid.toCanvas({ evolution: 1, visibility: 0 });\n const clampAxis = (value: number, min: number, max: number, extent: number) => {\n const low = min + extent / 2 + PLOT_INSET;\n const high = max - extent / 2 - PLOT_INSET;\n return low > high ? (min + max) / 2 : Math.min(high, Math.max(low, value));\n };\n const centerOf = (step: number) => ({\n x: clampAxis(\n freeCenter.x + step * STACK_OFFSET,\n plotTopLeft.x,\n plotBottomRight.x,\n shape.width,\n ),\n y: clampAxis(\n freeCenter.y + step * STACK_OFFSET,\n plotTopLeft.y,\n plotBottomRight.y,\n shape.height,\n ),\n });\n const registry = this.injector.get<ElementRegistry>(\"elementRegistry\");\n // Regions and drawings are backgrounds that other elements sit on, so only nodes block a spot.\n const occupied = (point: { x: number; y: number }) =>\n registry.find(\n (element: unknown) =>\n isWardleyShape(element) &&\n element.wardleyType !== \"attitude\" &&\n element.wardleyType !== \"drawing\" &&\n Math.abs(element.x + element.width / 2 - point.x) < (element.width + shape.width) / 2 &&\n Math.abs(element.y + element.height / 2 - point.y) < (element.height + shape.height) / 2,\n ) !== undefined;\n for (let step = 0; step < MAX_STACK_STEPS; step++) {\n const candidate = centerOf(step);\n if (!occupied(candidate)) return candidate;\n }\n return centerOf(0);\n }\n\n private describe(\n title: string,\n shortcut: string | undefined,\n ): Pick<PaletteEntry, \"title\" | \"shortcut\"> {\n return shortcut ? { title, shortcut } : { title };\n }\n\n private entryHtml(title: string, icon: string, shortcut?: string, draggable = false): string {\n // Next to a styled tooltip a native `title` would pop up a second, slower one.\n const nativeTitle = this.needsNativeTitle\n ? ` title=\"${escapeAttribute(shortcut ? `${title} (${shortcut})` : title)}\"`\n : \"\";\n const keyShortcut = shortcut ? ` aria-keyshortcuts=\"${escapeAttribute(shortcut)}\"` : \"\";\n return `<div class=\"entry wardley-palette-entry\"${draggable ? ' draggable=\"true\"' : \"\"}${nativeTitle}${keyShortcut}>${icon}</div>`;\n }\n}\n\ninterface LabelEditingLike {\n activate(element: WardleyShape): void;\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type { Injector } from \"didi\";\nimport type WardleyPaletteProvider from \"./WardleyPaletteProvider.js\";\n\nconst ENTRY_SELECTOR = \".djs-palette-entries .entry\";\n\nconst PREVIOUS_KEYS = new Set([\"ArrowLeft\", \"ArrowUp\"]);\nconst NEXT_KEYS = new Set([\"ArrowRight\", \"ArrowDown\"]);\nconst ACTIVATE_KEYS = new Set([\"Enter\", \" \"]);\n\n/**\n * Makes the palette a keyboard-operable toolbar (WAI-ARIA toolbar pattern): one Tab stop with a\n * roving tabindex, arrow keys / Home / End move between tools, Enter or Space activates the focused\n * one. A create tool has no pointer position to attach the new element to, so it is placed at the\n * centre of the free rectangle instead (see `WardleyPaletteProvider.createAtFreeCenter`). Only for\n * hosts without the Miragon modeler shell, which brings these keys itself.\n */\nexport default class WardleyPaletteKeyboard {\n static $inject = [\"eventBus\", \"palette\", \"wardleyPaletteProvider\", \"injector\"];\n\n private container: HTMLElement | undefined;\n private activeAction: string | undefined;\n\n constructor(\n eventBus: EventBus,\n private readonly palette: Palette,\n private readonly provider: WardleyPaletteProvider,\n injector: Injector,\n ) {\n // The Miragon modeler shell skins the palette and brings the same keys; a second roving tab\n // stop and a second Enter handler would create every element twice.\n if (injector.get(\"modelerShell\", false)) return;\n eventBus.on(\"palette.create\", (event: { container: HTMLElement }) =>\n this.attach(event.container),\n );\n eventBus.on(\"palette.changed\", () => this.updateTabStops());\n const existing = (palette as unknown as { _container?: HTMLElement })._container;\n if (existing) this.attach(existing);\n }\n\n private attach(container: HTMLElement): void {\n if (this.container === container) return;\n this.container = container;\n // Scopes the toolbar styling to this palette, not every diagram-js palette on the page.\n container.classList.add(\"wardley-palette\");\n container.setAttribute(\"role\", \"toolbar\");\n container.setAttribute(\"aria-label\", \"Tools\");\n container.setAttribute(\"aria-orientation\", \"horizontal\");\n container.addEventListener(\"keydown\", (event) => this.onKeydown(event));\n container.addEventListener(\"focusin\", (event) => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n this.activeAction = entry.getAttribute(\"data-action\") ?? undefined;\n this.updateTabStops();\n });\n this.updateTabStops();\n }\n\n private entries(): HTMLElement[] {\n return this.container\n ? Array.from(this.container.querySelectorAll<HTMLElement>(ENTRY_SELECTOR))\n : [];\n }\n\n private entryOf(target: EventTarget | null): HTMLElement | null {\n if (!(target instanceof Element) || !this.container) return null;\n const entry = target.closest<HTMLElement>(\".entry\");\n return entry && this.container.contains(entry) ? entry : null;\n }\n\n private updateTabStops(): void {\n const entries = this.entries();\n if (!entries.length) return;\n const active =\n entries.find((entry) => entry.getAttribute(\"data-action\") === this.activeAction) ??\n entries[0]!;\n for (const entry of entries) entry.tabIndex = entry === active ? 0 : -1;\n }\n\n private onKeydown(event: KeyboardEvent): void {\n const entry = this.entryOf(event.target);\n if (!entry || event.altKey || event.ctrlKey || event.metaKey) return;\n const entries = this.entries();\n const index = entries.indexOf(entry);\n\n let next: HTMLElement | undefined;\n if (PREVIOUS_KEYS.has(event.key)) next = entries[(index - 1 + entries.length) % entries.length];\n else if (NEXT_KEYS.has(event.key)) next = entries[(index + 1) % entries.length];\n else if (event.key === \"Home\") next = entries[0];\n else if (event.key === \"End\") next = entries[entries.length - 1];\n\n if (next) {\n // The toolbar's own keys: no listener further up acts on them too.\n event.preventDefault();\n event.stopPropagation();\n next.focus();\n return;\n }\n\n if (ACTIVATE_KEYS.has(event.key)) {\n event.preventDefault();\n event.stopPropagation();\n this.activate(entry);\n }\n }\n\n private activate(entry: HTMLElement): void {\n const action = entry.getAttribute(\"data-action\");\n if (!action) return;\n if (this.provider.createAtFreeCenter(action)) return;\n const bounds = entry.getBoundingClientRect();\n const click = new MouseEvent(\"click\", {\n bubbles: true,\n clientX: bounds.left + bounds.width / 2,\n clientY: bounds.top + bounds.height / 2,\n });\n this.palette.triggerEntry(action, \"click\", click);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyPaletteProvider from \"./WardleyPaletteProvider.js\";\nimport WardleyPaletteKeyboard from \"./WardleyPaletteKeyboard.js\";\n\n/** Tool palette (drag-to-create, keyboard-operable toolbar). */\nexport const wardleyPaletteModule: ModuleDeclaration = {\n __init__: [\"wardleyPaletteProvider\", \"wardleyPaletteKeyboard\"],\n wardleyPaletteProvider: [\"type\", WardleyPaletteProvider],\n wardleyPaletteKeyboard: [\"type\", WardleyPaletteKeyboard],\n};\n\nexport { default as WardleyPaletteProvider } from \"./WardleyPaletteProvider.js\";\nexport { default as WardleyPaletteKeyboard } from \"./WardleyPaletteKeyboard.js\";\n","import ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Element, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport { MOVEMENT_CLASS } from \"../draw/index.js\";\n\ninterface TargetBounds {\n left: number;\n top: number;\n right: number;\n bottom: number;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** diagram-js internals this override relies on (not part of the published typings). */\ninterface ContextPadInternals {\n _canvas: Canvas;\n _current?: { html?: HTMLElement } | null;\n _getTargetBounds(target: Element | Element[]): TargetBounds;\n}\n\n/** Screen px between the target and the pad (diagram-js' CONTEXT_PAD_MARGIN at 100 %). */\nconst PAD_MARGIN = 8;\n/** Pad width assumed before the pad is laid out: a component's pad (four 28px entries per row). */\nconst FALLBACK_PAD_WIDTH = 134;\n\n/**\n * Anchors the pad to a node and its own label instead of the whole graphics group: an evolving\n * component's group also holds the evolve arrow, target circle and target name, which would push the\n * pad hundreds of pixels away from the node the user selected. When the evolve target lies where\n * the pad would open, the pad clears the whole movement instead — otherwise it would hide the target\n * circle, which is the evolve's drag handle.\n *\n * Overrides diagram-js's private `_getTargetBounds` (guarded by a browser test).\n */\nexport default class WardleyContextPad extends ContextPad {\n _getTargetBounds(target: Element | Element[]): TargetBounds {\n const elements = Array.isArray(target) ? target : [target];\n const nodeRects = elements.flatMap((element) => this.visualRects(element, \"node\"));\n if (!nodeRects.length) {\n const base = ContextPad.prototype as unknown as ContextPadInternals;\n return base._getTargetBounds.call(this, target);\n }\n const nodeBounds = union(nodeRects);\n const padReach =\n nodeBounds.right + this.padWidth() + PAD_MARGIN * this.internals()._canvas.zoom();\n const movementRects = elements.flatMap((element) => this.visualRects(element, \"movement\"));\n // Only the target circle and texts count: the evolve line itself starts inside the node.\n const movementUnderPad = elements\n .flatMap((element) => this.movementTargetRects(element))\n .some((rect) => rect.right > nodeBounds.right && rect.left < padReach);\n return movementUnderPad ? union([...nodeRects, ...movementRects]) : nodeBounds;\n }\n\n private internals(): ContextPadInternals {\n return this as unknown as ContextPadInternals;\n }\n\n private padWidth(): number {\n const width = this.internals()._current?.html?.getBoundingClientRect().width;\n return width || FALLBACK_PAD_WIDTH;\n }\n\n private movementTargetRects(element: Element): DOMRect[] {\n const graphics = this.internals()._canvas.getGraphics(element as unknown as ShapeLike);\n const targets = graphics?.querySelectorAll(\n `.djs-visual > .${MOVEMENT_CLASS} > :is(.wardley-evolve-handle, text)`,\n );\n return Array.from(targets ?? []).map((target) => target.getBoundingClientRect());\n }\n\n private visualRects(element: Element, part: \"node\" | \"movement\"): DOMRect[] {\n const graphics = this.internals()._canvas.getGraphics(element as unknown as ShapeLike);\n if (!graphics) return [];\n const children = Array.from(graphics.children).flatMap((child) =>\n child.classList.contains(\"djs-visual\")\n ? Array.from(child.children).filter(\n (visual) => visual.classList.contains(MOVEMENT_CLASS) === (part === \"movement\"),\n )\n : part === \"node\"\n ? [child]\n : [],\n );\n return children\n .map((child) => child.getBoundingClientRect())\n .filter((rect) => rect.width > 0 || rect.height > 0);\n }\n}\n\nfunction union(rects: DOMRect[]): TargetBounds {\n const left = Math.min(...rects.map((rect) => rect.left));\n const top = Math.min(...rects.map((rect) => rect.top));\n const right = Math.max(...rects.map((rect) => rect.right));\n const bottom = Math.max(...rects.map((rect) => rect.bottom));\n return { left, top, right, bottom, x: left, y: top, width: right - left, height: bottom - top };\n}\n","/**\n * A refused value in an inline editor: the field turns red and a caption under it says why. One look\n * and one accessible pattern (role=alert, aria-describedby) for every editor, also for keyboard and\n * touch users who never see a tooltip.\n */\nexport interface FieldError {\n show(message: string): void;\n clear(): void;\n /** The caption while shown, for hosts that lay out further captions below it. */\n readonly caption: HTMLElement | undefined;\n}\n\nexport function createFieldError(\n container: HTMLElement,\n field: HTMLInputElement | HTMLTextAreaElement,\n id: string,\n place: (caption: HTMLElement) => void,\n): FieldError {\n let caption: HTMLElement | undefined;\n return {\n get caption() {\n return caption;\n },\n show(message) {\n if (!caption) {\n caption = document.createElement(\"div\");\n caption.className = \"wardley-label-caption wardley-label-error\";\n caption.setAttribute(\"role\", \"alert\");\n caption.id = id;\n container.appendChild(caption);\n field.setAttribute(\"aria-describedby\", id);\n }\n caption.textContent = message;\n field.classList.add(\"wardley-label-input--error\");\n field.setAttribute(\"aria-invalid\", \"true\");\n place(caption);\n },\n clear() {\n if (!caption) return;\n caption.remove();\n caption = undefined;\n field.classList.remove(\"wardley-label-input--error\");\n field.removeAttribute(\"aria-invalid\");\n field.removeAttribute(\"aria-describedby\");\n },\n };\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Injector } from \"didi\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport { FONT, NOTE_LINE_HEIGHT } from \"../draw/styles.js\";\nimport { createFieldError } from \"./fieldError.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n focusCanvasWithoutRing,\n lastInteractionWasPointer,\n trackInputModality,\n} from \"../a11y/index.js\";\n\n/** How an edit ends: Enter/Cmd+Enter (can be refused) or focus leaving the field (cannot). */\ntype CommitTrigger = \"enter\" | \"outside\";\n\ninterface ActiveEdit {\n elementId: string;\n field: HTMLInputElement | HTMLTextAreaElement;\n /** Saves the current value and closes (for Enter, blur, click outside). */\n commit: (trigger: CommitTrigger) => void;\n /** Discards and closes (only for Escape). */\n cleanup: () => void;\n /** Places the field over its element again after the view changed. */\n relayout: () => void;\n connection?: boolean;\n}\n\n/** Text selection (caret when start = end) inside an editor field. */\nexport interface FieldSelection {\n start: number;\n end: number;\n}\n\n/** Snapshot of an open name editor (hosts use it to survive a re-import). */\nexport interface ActiveLabelEdit {\n elementId: string;\n value: string;\n /** Where the caret or text selection was. */\n selection?: FieldSelection;\n /** A link annotation or flow value editor instead of a name editor. */\n connection?: boolean;\n}\n\nexport interface ActivateOptions {\n /** Initial field content instead of the element's current label (e.g. restoring an edit). */\n value?: string;\n /** Caret or selection to restore; without it the whole text is selected. */\n selection?: FieldSelection;\n}\n\n/**\n * A field the user opens selects its whole text; a field reopened by a re-import keeps the caret\n * and selection the user had, so the next key does not replace what was typed.\n */\nexport function focusField(\n field: HTMLInputElement | HTMLTextAreaElement,\n options: ActivateOptions,\n): void {\n field.focus();\n if (options.selection) {\n const length = field.value.length;\n field.setSelectionRange(\n Math.min(options.selection.start, length),\n Math.min(options.selection.end, length),\n );\n } else {\n field.select();\n }\n}\n\n/** Fired when a name was changed to a free variant because the requested one is taken. */\nexport interface LabelDeduplicatedEvent {\n element: WardleyShape;\n requested: string;\n applied: string;\n}\n\n/** Contract with the renderer: the element's primary name <text> carries this class. */\nconst NAME_LABEL_CLASS = \"wardley-name-label\";\n/** Canvas marker while editing — CSS hides the name label so the field replaces it. */\nconst EDITING_MARKER = \"wardley-label-editing\";\n\n/** Regions are unlabelled like in OWM (title = kind) and drawings have no text at all. */\nconst NOT_EDITABLE: ReadonlySet<string> = new Set([\"attitude\", \"drawing\"]);\n\n/** Below diagram-js's own `shape.changed` listener, which redraws the element. */\nconst AFTER_REDRAW_PRIORITY = 500;\n\nconst FIELD_PADDING_X = 6;\nconst FIELD_PADDING_Y = 2;\nconst FIELD_BORDER = 1.5;\nconst FIELD_LINE_HEIGHT = 1.25;\nconst MIN_FONT_SIZE = 11;\nconst CAPTION_GAP = 4;\nconst CARET_ROOM = 2;\n\n/**\n * Enter and Escape that confirm or cancel an IME candidate belong to the composition. `isComposing`\n * alone misses Safari: it sends the confirming Enter after `compositionend`, with `isComposing`\n * false and the `keyCode` 229 that every engine gives a key the IME took.\n */\nfunction isImeCompositionKey(event: KeyboardEvent): boolean {\n return event.isComposing || event.keyCode === 229;\n}\n\nexport const NOTE_EDIT_HINT = \"Cmd/Ctrl+Enter to save · Esc to cancel\";\n\nexport function duplicateNameMessage(name: string): string {\n return `“${name}” already exists. Names must be unique because links refer to them.`;\n}\n\n/**\n * Defuses DSL metacharacters in labels: in the OWM DSL, names double as references —\n * `->`, `;` and square brackets would corrupt edge/coordinate lines on re-import. Line breaks stay\n * (the DSL writes them as `\\n`); leading and trailing ones go with the other whitespace.\n */\nfunction sanitizeLabel(raw: string): string {\n return raw\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(/->/g, \"→\") // -> would be the edge operator\n .replace(/;/g, \",\") // ; separates link annotations\n .replace(/\\[/g, \"(\") // [..] would be a coordinate tuple\n .replace(/\\]/g, \")\")\n .trim();\n}\n\nlet measureContext: CanvasRenderingContext2D | null | undefined;\n\nfunction measureTextWidth(text: string, font: string, fontSizePx: number): number {\n if (measureContext === undefined)\n measureContext = document.createElement(\"canvas\").getContext(\"2d\");\n if (!measureContext) return text.length * fontSizePx * 0.6;\n measureContext.font = font;\n return measureContext.measureText(text).width;\n}\n\n/** Screen geometry of the label being replaced, relative to the canvas container. */\ninterface LabelGeometry {\n left: number;\n top: number;\n width: number;\n height: number;\n centered: boolean;\n fontSize: number;\n fontWeight: string;\n fontStyle: string;\n fontFamily: string;\n}\n\n/**\n * Custom inline label editing as an HTML overlay (deliberately not diagram-js direct-editing, §8.5).\n * The field sits exactly over the label it replaces (which is hidden meanwhile), scales with the\n * zoom and grows with its content. Commit goes through `wardleyModeling.updateLabel` ->\n * commandStack (undo, P4). Notes are edited in a `<textarea>` over the note itself (Enter = line\n * break, Cmd/Ctrl+Enter or click outside = save); every other name in a `<textarea>` over its label\n * (Enter = save, Shift+Enter = line break). Escape always discards.\n */\nexport default class WardleyLabelEditing {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"elementRegistry\",\n \"wardleyModeling\",\n \"wardleyElementFactory\",\n \"injector\",\n ];\n\n private active: ActiveEdit | null = null;\n private relayoutPending = false;\n private readonly contextPad: ContextPad | null;\n private readonly selection: Selection | null;\n private readonly locked: () => boolean;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly modeling: WardleyModeling,\n private readonly factory: WardleyElementFactory,\n injector: Injector,\n ) {\n trackInputModality();\n this.contextPad = injector.get<ContextPad | null>(\"contextPad\", false) ?? null;\n this.selection = injector.get<Selection | null>(\"selection\", false) ?? null;\n this.locked = () => isReadOnly(injector);\n\n eventBus.on(\"element.dblclick\", (event: { element?: unknown }) => {\n if (isWardleyShape(event.element)) this.activate(event.element);\n else if (isWardleyConnection(event.element)) this.activateConnection(event.element);\n });\n // Click or drag outside the field = SAVE (not discard). Only Escape discards.\n eventBus.on([\"element.mousedown\", \"drag.init\"], () => this.active?.commit(\"outside\"));\n // A view change is no gesture of the user's: a host restores the view after a peer's re-import\n // and refits when its chrome changes, and committing then would write the half-typed name into\n // the shared document (modeler-api L5). The field follows the element instead.\n eventBus.on(\"canvas.viewbox.changing\", () => this.relayoutAfterViewChange());\n eventBus.on(\"canvas.viewbox.changed\", () => this.active?.relayout());\n // A redraw of the edited element (a host resizing the map while the field is open) moves it\n // without a view change; the priority waits for the redraw.\n eventBus.on(\n [\"shape.changed\", \"connection.changed\"],\n AFTER_REDRAW_PRIORITY,\n (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.active.relayout();\n },\n );\n // The edited element vanished (delete, re-import): nothing left to save into.\n eventBus.on([\"shape.remove\", \"connection.remove\"], (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.cancel();\n });\n eventBus.on(\"diagram.destroy\", () => this.cancel());\n }\n\n /**\n * Opens the in-place name editor for `element` (no-op for regions and drawings, and for an\n * element an import has replaced).\n */\n activate(element: WardleyShape, options: ActivateOptions = {}): void {\n if (!isWardleyShape(element) || NOT_EDITABLE.has(element.wardleyType) || this.locked()) return;\n // A host that re-imports from the change listener of a create has replaced the new shape before\n // the caller opens the editor, and a name typed into it would commit onto the removed shape.\n if (this.elementRegistry.get(element.id) !== element) return;\n this.active?.commit(\"outside\");\n\n const container = this.canvas.getContainer();\n const isNote = element.wardleyType === \"note\";\n const openedByPointer = lastInteractionWasPointer();\n const requiresUniqueName = this.factory.isLinkable(element.wardleyType);\n const labels = this.nameLabelElements(element);\n const classedByFallback = [...labels.classedByFallback];\n let geometry = this.labelGeometry(element, labels.labelElements);\n\n const lineHeightOf = (fontSize: number) =>\n Math.max(fontSize * FIELD_LINE_HEIGHT, isNote ? NOTE_LINE_HEIGHT * this.canvas.zoom() : 0);\n let lineHeight = lineHeightOf(geometry.fontSize);\n const field = createNameField(\n isNote,\n options.value ?? element.wardleyLabel ?? \"\",\n geometry,\n lineHeight,\n );\n const hint = isNote ? createCaption(\"wardley-label-hint\", NOTE_EDIT_HINT) : undefined;\n\n const layout = () => {\n const { left, top, width, height } = fieldBox(field.value, geometry, lineHeight, isNote);\n Object.assign(field.style, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n });\n // A new line made the field scroll to the caret before it grew to hold it.\n field.scrollTop = 0;\n let captionTop = top + height + CAPTION_GAP;\n for (const caption of [error.caption, hint]) {\n if (!caption) continue;\n caption.style.left = `${left}px`;\n caption.style.top = `${captionTop}px`;\n captionTop += caption.offsetHeight + CAPTION_GAP;\n }\n };\n\n const error = createFieldError(container, field, `wardley-label-error-${element.id}`, () =>\n layout(),\n );\n const showDuplicateError = (requested: string) => {\n error.show(duplicateNameMessage(requested));\n field.select();\n };\n const clearError = () => error.clear();\n\n this.contextPad?.close();\n this.canvas.addMarker(element, EDITING_MARKER);\n container.appendChild(field);\n if (hint) container.appendChild(hint);\n layout();\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey as EventListener);\n field.removeEventListener(\"blur\", onBlur);\n field.removeEventListener(\"input\", onInput);\n field.remove();\n hint?.remove();\n error.clear();\n this.canvas.removeMarker(element, EDITING_MARKER);\n for (const text of classedByFallback) {\n text.classList.remove(NAME_LABEL_CLASS);\n if (!text.classList.length) text.removeAttribute(\"class\");\n }\n this.active = null;\n };\n const commit = (trigger: CommitTrigger) => {\n if (done) return;\n // Enforce metacharacter protection also on RENAME — the DSL references elements by their\n // name; unescaped `->`, `;` or brackets would corrupt edge/coordinate lines on re-import.\n const requested = sanitizeLabel(field.value);\n if (!requested || requested === element.wardleyLabel) {\n cleanup();\n return;\n }\n // Duplicate names would collapse nodes on the DSL round-trip (arrows disappear). On Enter the\n // user can still fix it, so refuse; when focus leaves, fall back to a free variant and tell\n // the host. Notes and other unreferenced elements may repeat (e.g. several \"Risk\" hints).\n const applied = requiresUniqueName\n ? this.factory.uniqueLabel(requested, element.id)\n : requested;\n if (applied !== requested && trigger === \"enter\") {\n showDuplicateError(requested);\n return;\n }\n cleanup();\n this.modeling.updateLabel(element, applied);\n if (applied !== requested) {\n this.eventBus.fire(\"wardley.label.deduplicated\", {\n element,\n requested,\n applied,\n } satisfies LabelDeduplicatedEvent);\n }\n };\n const onKey = (e: KeyboardEvent) => {\n if (isImeCompositionKey(e)) return;\n if (e.key === \"Escape\") {\n e.preventDefault();\n cleanup();\n this.returnToCanvas(element, openedByPointer);\n return;\n }\n if (e.key === \"Enter\") {\n // Note: save only with Cmd/Ctrl -> otherwise line break. Others: Enter saves, Shift+Enter\n // breaks the line.\n if (isNote ? !(e.metaKey || e.ctrlKey) : e.shiftKey) return;\n e.preventDefault();\n commit(\"enter\");\n if (done) this.returnToCanvas(element, openedByPointer);\n }\n };\n const onInput = () => {\n clearError();\n layout();\n };\n const onBlur = () => commit(\"outside\");\n field.addEventListener(\"keydown\", onKey as EventListener);\n field.addEventListener(\"blur\", onBlur);\n field.addEventListener(\"input\", onInput);\n\n const relayout = () => {\n if (done) return;\n // A redraw replaces the label nodes, and a detached node measures as an empty box at 0,0.\n const current = this.nameLabelElements(element);\n classedByFallback.push(...current.classedByFallback);\n geometry = this.labelGeometry(element, current.labelElements);\n lineHeight = lineHeightOf(geometry.fontSize);\n Object.assign(field.style, {\n fontSize: `${geometry.fontSize}px`,\n lineHeight: `${lineHeight}px`,\n });\n layout();\n };\n\n this.active = { elementId: element.id, field, commit, cleanup, relayout };\n }\n\n /**\n * Inline editing for connections: a flow edits its value (`+'value'>`), a dependency its\n * `; annotation` text. An empty input clears the field. Undo-safe via updateProperties.\n */\n activateConnection(conn: WardleyConnection, options: ActivateOptions = {}): void {\n if (this.locked()) return;\n this.active?.commit(\"outside\");\n\n const container = this.canvas.getContainer();\n if (conn.waypoints.length < 1) return;\n const isFlow = conn.wardleyType === \"flow\";\n const openedByPointer = lastInteractionWasPointer();\n\n const field = document.createElement(\"input\");\n field.type = \"text\";\n field.className = \"wardley-label-input\";\n field.placeholder = isFlow ? \"flow value (e.g. $0.10)\" : \"link annotation\";\n field.value = options.value ?? (isFlow ? conn.flowValue : conn.linkLabel) ?? \"\";\n field.style.position = \"absolute\";\n const place = () => {\n // Read afresh: a redraw of the connection replaces its waypoints.\n const first = conn.waypoints[0];\n const last = conn.waypoints[conn.waypoints.length - 1];\n if (!first || !last) return;\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n field.style.left = `${((first.x + last.x) / 2 - 60 - viewbox.x) * scale}px`;\n field.style.top = `${((first.y + last.y) / 2 - 26 - viewbox.y) * scale}px`;\n };\n place();\n container.appendChild(field);\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey as EventListener);\n field.removeEventListener(\"blur\", onBlur);\n field.remove();\n this.active = null;\n };\n const commit = () => {\n if (done) return;\n // Defuse DSL metacharacters: `'` delimits the flow value, `;` starts the annotation.\n const value = field.value.replace(/'/g, \"’\").replace(/;/g, \",\").trim();\n const current = (isFlow ? conn.flowValue : conn.linkLabel) ?? \"\";\n cleanup();\n if (value === current) return;\n // Keep the businessObject in sync — the exporter prefers it for imported edges.\n const bo = conn.businessObject;\n const nextBo = bo\n ? isFlow\n ? { ...bo, ...(value ? { flowValue: value } : {}) }\n : { ...bo, ...(value ? { label: value } : {}) }\n : undefined;\n if (nextBo && !value) {\n if (isFlow) delete (nextBo as { flowValue?: string }).flowValue;\n else delete (nextBo as { label?: string }).label;\n }\n this.modeling.updateProperties(conn, {\n [isFlow ? \"flowValue\" : \"linkLabel\"]: value || undefined,\n ...(nextBo ? { businessObject: nextBo } : {}),\n });\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n cleanup();\n this.returnToCanvas(conn, openedByPointer);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n commit();\n this.returnToCanvas(conn, openedByPointer);\n }\n };\n const onBlur = () => commit();\n field.addEventListener(\"keydown\", onKey as EventListener);\n field.addEventListener(\"blur\", onBlur);\n\n const relayout = () => {\n if (!done) place();\n };\n this.active = { elementId: conn.id, field, commit, cleanup, relayout, connection: true };\n }\n\n /** Discards the open edit (if any) without saving. */\n cancel(): void {\n this.active?.cleanup();\n }\n\n /** `canvas.viewbox.changing` fires before the change, and `changed` waits 300ms under `deferUpdate`. */\n private relayoutAfterViewChange(): void {\n if (!this.active || this.relayoutPending) return;\n this.relayoutPending = true;\n queueMicrotask(() => {\n this.relayoutPending = false;\n this.active?.relayout();\n });\n }\n\n /**\n * Saves the open edit (if any) as if focus had left the field, e.g. before the host saves or\n * exports the map, so the file contains the text the user sees.\n */\n commitActiveEdit(): void {\n this.active?.commit(\"outside\");\n }\n\n /** The open editor's element and current (unsaved) text, or null when nothing is edited. */\n getActiveEdit(): ActiveLabelEdit | null {\n if (!this.active) return null;\n const { elementId, field, connection } = this.active;\n return {\n elementId,\n value: field.value,\n selection: { start: field.selectionStart ?? 0, end: field.selectionEnd ?? 0 },\n ...(connection ? { connection } : {}),\n };\n }\n\n /**\n * After Enter/Escape the removed field leaves focus on <body>; hand it back to the canvas so\n * keyboard users keep their place, and bring back the context pad a name editor had closed.\n */\n private returnToCanvas(\n element: WardleyShape | WardleyConnection,\n openedByPointer: boolean,\n ): void {\n // A name typed after a click or placement must not leave a keyboard focus ring around the\n // whole viewport; an editor opened from the keyboard (F2, Enter) keeps the visible ring. Right\n // away, not on the next task: the canvas takes keys only while it has the focus, so the next\n // key (N for a note after naming a component) would otherwise go to <body>.\n if (openedByPointer) focusCanvasWithoutRing(this.canvas);\n else this.canvas.focus();\n const selected = this.selection?.get() ?? [];\n if (selected.length === 1 && selected[0] === element) this.contextPad?.open(element);\n }\n\n /**\n * The <text> nodes showing the element's name. Falls back to matching by content when the\n * renderer does not mark them; the LAST match skips a component's movement target label, which\n * is drawn first and may repeat the name. Fallback matches carry the class only while editing so\n * the CSS hides them.\n */\n private nameLabelElements(element: WardleyShape): {\n labelElements: SVGTextElement[];\n classedByFallback: SVGTextElement[];\n } {\n const gfx = this.canvas.getGraphics(element);\n if (!gfx) return { labelElements: [], classedByFallback: [] };\n const marked = [...gfx.querySelectorAll<SVGTextElement>(`.${NAME_LABEL_CLASS}`)];\n if (marked.length) return { labelElements: marked, classedByFallback: [] };\n const texts = [...gfx.querySelectorAll<SVGTextElement>(\"text\")].filter(\n (text) => !text.closest(\".wardley-movement\"),\n );\n // The lines of a name are tspans of one text, whose content joins them without a break.\n const drawnLabel = (element.wardleyLabel ?? \"\").split(\"\\n\").join(\"\");\n const matched =\n element.wardleyType === \"note\"\n ? texts\n : texts.filter((text) => text.textContent === drawnLabel).slice(-1);\n for (const text of matched) text.classList.add(NAME_LABEL_CLASS);\n return { labelElements: matched, classedByFallback: matched };\n }\n\n private labelGeometry(element: WardleyShape, labelElements: SVGTextElement[]): LabelGeometry {\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n const containerRect = this.canvas.getContainer().getBoundingClientRect();\n const reference = labelElements[0];\n // tiny-svg writes presentation attributes such as font-size or text-anchor as inline styles,\n // so only the computed style knows them.\n const referenceStyle = reference ? getComputedStyle(reference) : undefined;\n const fontSize = Math.max(\n MIN_FONT_SIZE,\n (Number.parseFloat(referenceStyle?.fontSize ?? \"\") || FONT.label) * scale,\n );\n const typography = {\n fontSize,\n fontWeight: referenceStyle?.fontWeight || \"normal\",\n fontStyle: referenceStyle?.fontStyle || \"normal\",\n fontFamily: referenceStyle?.fontFamily || FONT.family,\n };\n\n if (element.wardleyType === \"note\") {\n return {\n left: (element.x - viewbox.x) * scale,\n top: (element.y - viewbox.y) * scale,\n width: element.width * scale,\n height: element.height * scale,\n centered: true,\n ...typography,\n };\n }\n if (labelElements.length) {\n const boxes = labelElements.map((text) => text.getBoundingClientRect());\n const left = Math.min(...boxes.map((box) => box.left));\n const top = Math.min(...boxes.map((box) => box.top));\n return {\n left: left - containerRect.left,\n top: top - containerRect.top,\n width: Math.max(...boxes.map((box) => box.right)) - left,\n height: Math.max(...boxes.map((box) => box.bottom)) - top,\n centered: referenceStyle?.textAnchor === \"middle\",\n ...typography,\n };\n }\n // No visible label (e.g. a pipeline whose name is shown by its same-named component).\n return {\n left: (element.x + element.width + 6 - viewbox.x) * scale,\n top: (element.y + element.height / 2 - viewbox.y) * scale - fontSize / 2,\n width: 0,\n height: fontSize,\n centered: false,\n ...typography,\n };\n }\n}\n\nfunction createNameField(\n isNote: boolean,\n value: string,\n geometry: LabelGeometry,\n lineHeight: number,\n): HTMLTextAreaElement {\n const field = document.createElement(\"textarea\");\n field.className = \"wardley-label-input wardley-label-input--name wardley-label-textarea\";\n field.value = value;\n field.rows = 1;\n field.setAttribute(\"aria-label\", isNote ? \"Note text\" : \"Name\");\n field.spellcheck = false;\n field.wrap = \"off\";\n Object.assign(field.style, {\n position: \"absolute\",\n fontFamily: geometry.fontFamily,\n fontSize: `${geometry.fontSize}px`,\n fontWeight: geometry.fontWeight,\n fontStyle: geometry.fontStyle,\n lineHeight: `${lineHeight}px`,\n padding: `${FIELD_PADDING_Y}px ${FIELD_PADDING_X}px`,\n textAlign: geometry.centered ? \"center\" : \"left\",\n });\n return field;\n}\n\n/**\n * Field box over the label: as wide as its content (never narrower than a note's own box), centred\n * on centred labels, otherwise starting where the label text starts.\n */\nfunction fieldBox(\n value: string,\n geometry: LabelGeometry,\n lineHeight: number,\n isNote: boolean,\n): { left: number; top: number; width: number; height: number } {\n const font = `${geometry.fontStyle} ${geometry.fontWeight} ${geometry.fontSize}px ${geometry.fontFamily}`;\n const chrome = 2 * (FIELD_PADDING_X + FIELD_BORDER) + CARET_ROOM;\n const lines = (value || \" \").split(\"\\n\");\n const textWidth = Math.max(\n ...lines.map((line) => measureTextWidth(line, font, geometry.fontSize)),\n );\n const width = Math.max(\n textWidth + chrome,\n geometry.fontSize * 2 + chrome,\n isNote ? geometry.width : 0,\n );\n const height = Math.max(\n lines.length * lineHeight + 2 * (FIELD_PADDING_Y + FIELD_BORDER),\n isNote ? geometry.height : 0,\n );\n const left = geometry.centered\n ? geometry.left + geometry.width / 2 - width / 2\n : geometry.left - FIELD_PADDING_X - FIELD_BORDER;\n const top = geometry.top + geometry.height / 2 - height / 2;\n return { left, top, width, height };\n}\n\nfunction createCaption(className: string, text: string): HTMLElement {\n const caption = document.createElement(\"div\");\n caption.className = `wardley-label-caption ${className}`;\n caption.textContent = text;\n return caption;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLabelEditing from \"./WardleyLabelEditing.js\";\n\n/** Custom inline label editing (HTML overlay). */\nexport const labelEditingModule: ModuleDeclaration = {\n __init__: [\"wardleyLabelEditing\"],\n wardleyLabelEditing: [\"type\", WardleyLabelEditing],\n};\n\nexport { default as WardleyLabelEditing } from \"./WardleyLabelEditing.js\";\nexport { createFieldError, type FieldError } from \"./fieldError.js\";\nexport { focusField, type FieldSelection } from \"./WardleyLabelEditing.js\";\n","const ALLOWED_SCHEMES = new Set([\"http:\", \"https:\", \"mailto:\"]);\n\n/** RFC 3986 scheme prefix; anything without one is a relative reference (e.g. `./other.wmap`). */\nconst SCHEME_PATTERN = /^([a-z][a-z0-9+.-]*):/i;\n\n// Control characters (incl. tab and line breaks) — browsers drop them while parsing a URL, so\n// `java\\nscript:` would otherwise slip past the scheme check.\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001f\\u007f]/g;\n\n/**\n * Normalises user or file input into an address the OWM DSL can carry losslessly:\n * `url Name [address]` ends at `]`, and a line break would end the definition line.\n */\nexport function sanitizeLinkUrl(raw: string): string {\n return raw.replace(CONTROL_CHARACTERS, \"\").replace(/[[\\]]/g, \"\").trim();\n}\n\n/**\n * Allowlist for addresses the modeler stores or opens: http(s), mailto, or a relative reference.\n * Shared maps arrive through URLs and files, so a `javascript:` or `data:` address must never reach\n * `window.open`.\n */\nexport function isAllowedLinkUrl(url: string): boolean {\n const scheme = SCHEME_PATTERN.exec(url)?.[1];\n return scheme === undefined || ALLOWED_SCHEMES.has(`${scheme.toLowerCase()}:`);\n}\n\n/** Sanitised address if it is non-empty and allowed, otherwise `undefined`. */\nexport function safeLinkUrl(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const url = sanitizeLinkUrl(raw);\n return url && isAllowedLinkUrl(url) ? url : undefined;\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ComponentElement, MapElement, SubmapElement } from \"@miragon/wardley-schema-model\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { createFieldError, focusField, type FieldSelection } from \"../label-editing/index.js\";\nimport { isAllowedLinkUrl, sanitizeLinkUrl } from \"./link-url.js\";\n\ninterface ActiveLinkEdit {\n elementId: string;\n field: HTMLInputElement;\n commit: () => void;\n cleanup: () => void;\n /** Places the field below its element again after the view changed. */\n relayout: () => void;\n}\n\n/** Screen px from the element's top edge: two 28px pad rows plus their gap and a margin. */\nconst CONTEXT_PAD_CLEARANCE = 72;\n\n/** Below diagram-js's own `shape.changed` listener, which redraws the element. */\nconst AFTER_REDRAW_PRIORITY = 500;\n\n/** Screen px between the field and its error caption. */\nconst CAPTION_GAP = 4;\n\nconst INVALID_HINT = \"Use an http(s) or mailto address, or a relative path such as ./other.wmap\";\n\n/** Element types that carry an OWM `url(...)` reference. */\nexport function canHaveLink(shape: WardleyShape): boolean {\n return shape.wardleyType === \"component\" || shape.wardleyType === \"submap\";\n}\n\n/** The stored address: `url` on components, `urlRef` on submaps (both live on the businessObject). */\nexport function linkOf(shape: WardleyShape): string | undefined {\n const businessObject = shape.businessObject;\n if (shape.wardleyType === \"submap\") return (businessObject as SubmapElement | undefined)?.urlRef;\n if (shape.wardleyType === \"component\")\n return (businessObject as ComponentElement | undefined)?.url;\n return undefined;\n}\n\n/**\n * Inline editor for the link of a component or submap (OWM `url Name [address]` + `url(Name)`).\n * Commits exactly one undoable `updateProperties`; addresses outside the allowlist (http, https,\n * mailto, relative) are rejected and the field stays open marked invalid.\n */\nexport default class WardleyLinkEditing {\n static $inject = [\"eventBus\", \"canvas\", \"wardleyModeling\", \"injector\"];\n\n private active: ActiveLinkEdit | null = null;\n private relayoutPending = false;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly modeling: WardleyModeling,\n private readonly injector: Injector,\n ) {\n eventBus.on([\"element.mousedown\", \"drag.init\"], () => this.active?.commit());\n // A host's view change (restoring the view after a peer's re-import, a refit) must not commit\n // the half-typed address into the shared document (modeler-api L5): the field follows instead.\n eventBus.on(\"canvas.viewbox.changing\", () => this.relayoutAfterViewChange());\n eventBus.on(\"canvas.viewbox.changed\", () => this.active?.relayout());\n // A redraw of the edited element (a host resizing the map while the field is open) moves it\n // without a view change; the priority waits for the redraw.\n eventBus.on(\"shape.changed\", AFTER_REDRAW_PRIORITY, (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.active.relayout();\n });\n eventBus.on([\"diagram.clear\", \"diagram.destroy\"], () => this.cancel());\n }\n\n /**\n * Sets (or with an empty value removes) the link. Returns false when the address is not allowed.\n * The exporter reads the link from the businessObject, which palette-created shapes do not have\n * yet — so a minimal one is built from the shape.\n */\n setLink(shape: WardleyShape, rawUrl: string | undefined): boolean {\n if (!canHaveLink(shape)) return false;\n const url = sanitizeLinkUrl(rawUrl ?? \"\");\n if (url && !isAllowedLinkUrl(url)) return false;\n if ((linkOf(shape) ?? \"\") === url) return true;\n\n const key = shape.wardleyType === \"submap\" ? \"urlRef\" : \"url\";\n if (!shape.businessObject) {\n // diagram-js defines `businessObject` as non-deletable, so undo could not restore \"absent\".\n // A link-less base carries nothing the exporter reads, so attaching it outside the command\n // stack changes no output and lets undo fall back to it instead.\n shape.businessObject = {\n id: shape.id,\n elementType: shape.wardleyType,\n label: shape.wardleyLabel,\n position: { visibility: shape.visibility, evolution: shape.evolution },\n } as MapElement;\n }\n const base = shape.businessObject;\n const next: Record<string, unknown> = { ...base };\n if (url) next[key] = url;\n else delete next[key];\n this.modeling.updateProperties(shape, { businessObject: next });\n return true;\n }\n\n /**\n * @param options.value field content to restore instead of the current link (re-import).\n * @param options.selection caret or selection to restore; without it the whole text is selected.\n */\n activate(\n shape: WardleyShape,\n options: { value?: string; selection?: FieldSelection } = {},\n ): void {\n if (!canHaveLink(shape) || isReadOnly(this.injector)) return;\n this.active?.commit();\n\n const container = this.canvas.getContainer();\n const field = document.createElement(\"input\");\n // type=\"url\" would flag relative paths such as ./other.wmap as :invalid.\n field.type = \"text\";\n field.inputMode = \"url\";\n field.spellcheck = false;\n field.autocomplete = \"off\";\n field.className = \"wardley-label-input wardley-link-input\";\n field.placeholder = \"https://… or ./other.wmap\";\n field.setAttribute(\"aria-label\", `Link of ${shape.wardleyLabel || shape.wardleyType}`);\n field.value = options.value ?? linkOf(shape) ?? \"\";\n field.style.position = \"absolute\";\n const placeField = () => {\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n // Below the element and its two-row context pad, which sit to the right of the element's top.\n field.style.left = `${(shape.x - viewbox.x) * scale}px`;\n field.style.top = `${(shape.y - viewbox.y) * scale + CONTEXT_PAD_CLEARANCE}px`;\n };\n placeField();\n container.appendChild(field);\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey);\n field.removeEventListener(\"blur\", onBlur);\n field.removeEventListener(\"input\", clearInvalid);\n error.clear();\n field.remove();\n this.active = null;\n };\n const placeCaption = (caption: HTMLElement) => {\n caption.style.left = field.style.left;\n caption.style.top = `${field.offsetTop + field.offsetHeight + CAPTION_GAP}px`;\n };\n const error = createFieldError(\n container,\n field,\n `wardley-link-error-${shape.id}`,\n placeCaption,\n );\n const markInvalid = () => error.show(INVALID_HINT);\n const clearInvalid = () => error.clear();\n const tryCommit = (): boolean => {\n if (done) return true;\n const url = sanitizeLinkUrl(field.value);\n if (url && !isAllowedLinkUrl(url)) {\n markInvalid();\n return false;\n }\n cleanup();\n this.setLink(shape, url);\n return true;\n };\n // Leaving the field with a rejected address discards it rather than trapping the user.\n const commit = () => {\n if (!tryCommit()) cleanup();\n };\n const onKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n cleanup();\n this.canvas.focus();\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n if (tryCommit()) this.canvas.focus();\n }\n };\n const onBlur = () => commit();\n field.addEventListener(\"keydown\", onKey);\n field.addEventListener(\"blur\", onBlur);\n field.addEventListener(\"input\", clearInvalid);\n\n const relayout = () => {\n if (done) return;\n placeField();\n if (error.caption) placeCaption(error.caption);\n };\n this.active = { elementId: shape.id, field, commit, cleanup, relayout };\n }\n\n cancel(): void {\n this.active?.cleanup();\n }\n\n /** `canvas.viewbox.changing` fires before the change, and `changed` waits 300ms under `deferUpdate`. */\n private relayoutAfterViewChange(): void {\n if (!this.active || this.relayoutPending) return;\n this.relayoutPending = true;\n queueMicrotask(() => {\n this.relayoutPending = false;\n this.active?.relayout();\n });\n }\n\n /** Saves the open link edit (if any) as if focus had left the field; a rejected address is dropped. */\n commitActiveEdit(): void {\n this.active?.commit();\n }\n\n getActiveEdit(): { elementId: string; value: string; selection: FieldSelection } | null {\n if (!this.active) return null;\n const { elementId, field } = this.active;\n return {\n elementId,\n value: field.value,\n selection: { start: field.selectionStart ?? 0, end: field.selectionEnd ?? 0 },\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLinkEditing from \"./WardleyLinkEditing.js\";\n\n/** Inline link (url) editing for components and submaps. */\nexport const linkEditingModule: ModuleDeclaration = {\n __init__: [\"wardleyLinkEditing\"],\n wardleyLinkEditing: [\"type\", WardleyLinkEditing],\n};\n\nexport { default as WardleyLinkEditing, canHaveLink, linkOf } from \"./WardleyLinkEditing.js\";\nexport { sanitizeLinkUrl, isAllowedLinkUrl, safeLinkUrl } from \"./link-url.js\";\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type { PopupMenuTarget } from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type {\n PopupMenuEntries,\n default as PopupMenuProvider,\n} from \"diagram-js/lib/features/popup-menu/PopupMenuProvider\";\nimport { isComponent, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\n\nexport const POPUP_PROVIDER_ID = \"wardley-element-settings\";\n\nconst TYPE_GROUP = { id: \"type\", name: \"Type\" };\nconst METHOD_GROUP = { id: \"method\", name: \"Sourcing\" };\nconst PROP_GROUP = { id: \"props\", name: \"Properties\" };\n\n/**\n * The menu handles its own keys (arrows select, Enter picks), so no listener further up acts on\n * them too. Escape must still bubble: diagram-js closes the menu from a document listener.\n */\nfunction keepKeysInsidePopup(event: KeyboardEvent): void {\n if (event.key !== \"Escape\") event.stopPropagation();\n}\n\nfunction mark(active: boolean, label: string): string {\n return active ? `✓ ${label}` : label;\n}\n\n/**\n * Popup submenu (opened via the context pad gear) for directly setting type (normal/market/\n * ecosystem), sourcing (build/buy/outsource) and inertia — instead of cycle buttons.\n * All actions go through `wardleyModeling` (undo/redo).\n */\nexport default class WardleyElementSettingsProvider implements PopupMenuProvider {\n static $inject = [\"popupMenu\", \"wardleyModeling\", \"eventBus\"];\n\n constructor(\n popupMenu: PopupMenu,\n private readonly modeling: WardleyModeling,\n eventBus: EventBus,\n ) {\n popupMenu.registerProvider(POPUP_PROVIDER_ID, this);\n eventBus.on(\"popupMenu.open\", () => {\n const container = (popupMenu as unknown as { _current?: { container?: HTMLElement } })\n ._current?.container;\n if (container?.getAttribute(\"data-popup\") !== POPUP_PROVIDER_ID) return;\n container.addEventListener(\"keydown\", keepKeysInsidePopup);\n });\n }\n\n getPopupMenuEntries(target: PopupMenuTarget): PopupMenuEntries {\n const shape = (Array.isArray(target) ? target[0] : target) as WardleyShape | undefined;\n if (!isComponent(shape)) return {};\n return this.componentEntries(shape);\n }\n\n private componentEntries(shape: WardleyShape): PopupMenuEntries {\n const dec = shape.decorators ?? {};\n const kind = dec.ecosystem ? \"ecosystem\" : dec.market ? \"market\" : \"normal\";\n const method = dec.method;\n\n return {\n \"type-normal\": {\n label: mark(kind === \"normal\", \"Normal\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, undefined),\n },\n \"type-market\": {\n label: mark(kind === \"market\", \"Market\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, \"market\"),\n },\n \"type-ecosystem\": {\n label: mark(kind === \"ecosystem\", \"Ecosystem\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, \"ecosystem\"),\n },\n \"method-none\": {\n label: mark(!method, \"None\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, undefined),\n },\n \"method-build\": {\n label: mark(method === \"build\", \"Build\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"build\"),\n },\n \"method-buy\": {\n label: mark(method === \"buy\", \"Buy\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"buy\"),\n },\n \"method-outsource\": {\n label: mark(method === \"outsource\", \"Outsource\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"outsource\"),\n },\n \"prop-inertia\": {\n label: mark(!!dec.inertia, \"Inertia\"),\n group: PROP_GROUP,\n action: () => this.modeling.toggleInertia(shape),\n },\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyElementSettingsProvider from \"./WardleyElementSettingsProvider.js\";\n\n/** Popup submenu for element settings (type/sourcing/inertia). */\nexport const wardleyPopupModule: ModuleDeclaration = {\n __init__: [\"wardleyElementSettings\"],\n wardleyElementSettings: [\"type\", WardleyElementSettingsProvider],\n};\n\nexport {\n default as WardleyElementSettingsProvider,\n POPUP_PROVIDER_ID,\n} from \"./WardleyElementSettingsProvider.js\";\n","/*! @miragon/wardley-renderer icon geometry: the context pad icons. Lucide (lucide-static 1.59.0)\n * @license ISC Copyright (c) 2026 Lucide Icons and Contributors\n * arrow-right, chevrons-right, circle-plus, external-link, link and trash derive from Feather\n * @license MIT, Copyright (c) 2013-present Cole Bemis\n * Full notices: README.md of @miragon/wardley-renderer */\n\n/**\n * The Lucide icons of the context pad (guide §5.14), inlined so the renderer has no icon runtime\n * dependency. Copied unchanged from lucide-static 1.59.0 (`icon-nodes.json`), except\n * `chevrons-right-x`.\n */\nexport const LUCIDE = {\n pencil:\n '<path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\"/><path d=\"m15 5 4 4\"/>',\n trash:\n '<path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\"/><path d=\"M3 6h18\"/><path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>',\n \"circle-plus\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 12h8\"/><path d=\"M12 8v8\"/>',\n \"arrow-right\": '<path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/>',\n \"chevrons-right\": '<path d=\"m6 17 5-5-5-5\"/><path d=\"m13 17 5-5-5-5\"/>',\n // Lucide has no crossed-out chevrons-right, and its `m2 2 20 20` slash runs parallel to the\n // chevrons' upper strokes, so at 16px a slashed variant no longer reads as chevrons. Drawn after\n // icon-design §C instead: `chevrons-right` moved up and left by (2, 1), with the corner `x` of\n // Lucide's `calendar-x-2`.\n \"chevrons-right-x\":\n '<path d=\"m4 16 5-5-5-5\"/><path d=\"m11 16 5-5-5-5\"/><path d=\"m17 16 5 5\"/><path d=\"m17 21 5-5\"/>',\n \"sliders-horizontal\":\n '<path d=\"M10 5H3\"/><path d=\"M12 19H3\"/><path d=\"M14 3v4\"/><path d=\"M16 17v4\"/><path d=\"M21 12h-9\"/><path d=\"M21 19h-5\"/><path d=\"M21 5h-7\"/><path d=\"M8 10v4\"/><path d=\"M8 12H3\"/>',\n \"line-style\":\n '<path d=\"M11 5h2\"/><path d=\"M15 12h6\"/><path d=\"M19 5h2\"/><path d=\"M3 12h6\"/><path d=\"M3 19h18\"/><path d=\"M3 5h2\"/>',\n palette:\n '<path d=\"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\"/><circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/>',\n link: '<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>',\n \"external-link\":\n '<path d=\"M15 3h6v6\"/><path d=\"M10 14 21 3\"/><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>',\n} as const;\n\nexport type LucideIconName = keyof typeof LUCIDE;\n\n/**\n * A chrome icon (guide §5.14, §11): 16px with stroke 2.5 on the 24 grid, so the stroke matches the\n * shell's chrome icons; `currentColor`, so the surrounding role decides the colour.\n */\nexport function chromeIcon(name: LucideIconName): string {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">${LUCIDE[name]}</svg>`;\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type {\n ContextPadEntries,\n default as ContextPadProvider,\n} from \"diagram-js/lib/features/context-pad/ContextPadProvider\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport {\n isWardleyShape,\n isWardleyConnection,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type WardleyLabelEditing from \"../label-editing/WardleyLabelEditing.js\";\nimport type WardleyEvolveDragging from \"../evolve/WardleyEvolveDragging.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type WardleyColorPicker from \"../color-picker/WardleyColorPicker.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyLinkEditing from \"../link-editing/WardleyLinkEditing.js\";\nimport { canHaveLink, linkOf, safeLinkUrl } from \"../link-editing/index.js\";\nimport { POPUP_PROVIDER_ID } from \"../popup/index.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\nimport { chromeIcon } from \"../draw/lucide.js\";\n\n/** Rows of the compact pad: primary actions, then properties, then the destructive action. */\nconst GROUP_PRIMARY = \"edit\";\nconst GROUP_PROPERTIES = \"wardley\";\nconst GROUP_DANGER = \"danger\";\n\n/** Distance (diagram px) below the source at which a keyboard-appended component is placed. */\nconst KEYBOARD_APPEND_OFFSET = 80;\n\nconst PAD_PREVIOUS_KEYS = new Set([\"ArrowLeft\", \"ArrowUp\"]);\nconst PAD_NEXT_KEYS = new Set([\"ArrowRight\", \"ArrowDown\"]);\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\");\n}\n\n/**\n * ContextPad entry as a focusable icon button. `draggable=true` is mandatory for entries with a\n * `dragstart` action — otherwise diagram-js does not fire the drag.\n */\nfunction cpHtml(iconSvg: string, label: string, draggable = false): string {\n const name = escapeAttribute(label);\n return `<div class=\"entry wardley-cp-entry\" role=\"button\" tabindex=\"0\" aria-label=\"${name}\"${draggable ? ' draggable=\"true\"' : \"\"} title=\"${name}\">${iconSvg}</div>`;\n}\n\n/** Context actions per element (concept doc §5.5). */\nexport default class WardleyContextPadProvider implements ContextPadProvider {\n static $inject = [\n \"contextPad\",\n \"modeling\",\n \"connect\",\n \"create\",\n \"popupMenu\",\n \"wardleyModeling\",\n \"wardleyLabelEditing\",\n \"wardleyEvolveDragging\",\n \"wardleyElementFactory\",\n \"wardleyColorPicker\",\n \"eventBus\",\n \"canvas\",\n \"injector\",\n ];\n\n /** Synthetic clicks created for Enter/Space, so actions can pick a pointer-free variant. */\n private readonly keyboardEvents = new WeakSet<Event>();\n\n constructor(\n private readonly contextPad: ContextPad,\n private readonly modeling: Modeling,\n private readonly connect: Connect,\n private readonly create: Create,\n private readonly popupMenu: PopupMenu,\n private readonly wardleyModeling: WardleyModeling,\n private readonly labelEditing: WardleyLabelEditing,\n private readonly evolveDragging: WardleyEvolveDragging,\n private readonly factory: WardleyElementFactory,\n private readonly colorPicker: WardleyColorPicker,\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly injector: Injector,\n ) {\n contextPad.registerProvider(this);\n eventBus.on(\"contextPad.create\", (event: { pad: HTMLElement }) => {\n event.pad.setAttribute(\"role\", \"toolbar\");\n event.pad.setAttribute(\"aria-label\", \"Element actions\");\n event.pad.addEventListener(\"keydown\", (keyEvent) => this.onPadKeydown(keyEvent, event.pad));\n });\n }\n\n getContextPadEntries(element: Element): ContextPadEntries {\n if (isReadOnly(this.injector)) return {};\n if (isWardleyConnection(element)) return this.connectionEntries(element);\n if (!isWardleyShape(element)) return {};\n const shape = element as WardleyShape;\n // Insertion order is render order: diagram-js creates a group row on its first entry.\n const entries: ContextPadEntries = {};\n this.addPrimaryEntries(shape, entries);\n this.addPropertyEntries(shape, entries);\n entries[\"delete\"] = {\n group: GROUP_DANGER,\n title: \"Delete\",\n html: cpHtml(chromeIcon(\"trash\"), \"Delete\"),\n action: {\n click: this.focusingCanvas(() =>\n this.modeling.removeElements([shape as unknown as Element]),\n ),\n },\n };\n return entries;\n }\n\n /** Connections: edit the annotation (or the flow value of an imported flow link) + delete. */\n private connectionEntries(conn: WardleyConnection): ContextPadEntries {\n const isFlow = conn.wardleyType === \"flow\";\n const editTitle = isFlow ? \"Edit flow value\" : \"Edit link annotation\";\n return {\n \"edit-value\": {\n group: GROUP_PRIMARY,\n title: editTitle,\n html: cpHtml(chromeIcon(\"pencil\"), editTitle),\n action: { click: () => this.labelEditing.activateConnection(conn) },\n },\n delete: {\n group: GROUP_DANGER,\n title: \"Delete connection\",\n html: cpHtml(chromeIcon(\"trash\"), \"Delete connection\"),\n action: {\n click: this.focusingCanvas(() =>\n this.modeling.removeElements([conn as unknown as Element]),\n ),\n },\n },\n };\n }\n\n /** Row 1: edit label, append, connect, evolve. */\n private addPrimaryEntries(shape: WardleyShape, entries: ContextPadEntries): void {\n // Drawings have no label (pure geometry); regions are unlabelled like in OWM.\n if (shape.wardleyType !== \"drawing\" && shape.wardleyType !== \"attitude\") {\n entries[\"edit-label\"] = {\n group: GROUP_PRIMARY,\n title: \"Edit label\",\n html: cpHtml(chromeIcon(\"pencil\"), \"Edit label\"),\n action: { click: () => this.labelEditing.activate(shape) },\n };\n }\n\n const connectable =\n shape.wardleyType === \"component\" ||\n shape.wardleyType === \"anchor\" ||\n shape.wardleyType === \"submap\" ||\n shape.wardleyType === \"pipeline\";\n if (connectable) {\n // Append component: drags out a new (blank) component and creates the arrow automatically\n // (diagram-js Create with `source` -> modeling.appendShape). Configurable via ⚙.\n const startAppend = this.focusingCanvas((event: Event) => {\n if (this.keyboardEvents.has(event)) {\n this.appendBelow(shape);\n return;\n }\n const next = this.factory.createNew(\"component\", \"Component\");\n this.create.start(event as MouseEvent, next as unknown as Element, {\n source: shape as unknown as Element,\n });\n });\n entries[\"append\"] = {\n group: GROUP_PRIMARY,\n title: \"Append component (auto-connect)\",\n html: cpHtml(chromeIcon(\"circle-plus\"), \"Append component\", true),\n action: { click: startAppend, dragstart: startAppend },\n };\n\n const startConnect = this.focusingCanvas((event: Event) => {\n this.connect.start(event as MouseEvent, shape as unknown as Element);\n });\n entries[\"connect\"] = {\n group: GROUP_PRIMARY,\n title: \"Connect to existing element (A)\",\n html: cpHtml(chromeIcon(\"arrow-right\"), \"Connect to existing element (A)\", true),\n action: { click: startConnect, dragstart: startConnect },\n };\n }\n\n if (shape.wardleyType === \"component\") {\n if (shape.movement) {\n // Target is set -> drag the red target circle directly to MOVE it\n // (see WardleyEvolveDragging). Here we only offer removal.\n entries[\"evolve-clear\"] = {\n group: GROUP_PRIMARY,\n title: \"Remove evolve\",\n html: cpHtml(chromeIcon(\"chevrons-right-x\"), \"Remove evolve\"),\n action: { click: this.focusingCanvas(() => this.wardleyModeling.clearMovement(shape)) },\n };\n } else if (shape.evolution < 0.999) {\n // Drag the target out along the axis (live preview). The click does NOT model immediately\n // (no automatic +0.2 anymore) — it only starts the placement. At evolution ~ 1 there is\n // no meaningful target left — the entry is omitted (instead of creating a null movement).\n const startEvolve = this.focusingCanvas((event: Event) =>\n this.evolveDragging.start(event, shape),\n );\n entries[\"evolve\"] = {\n group: GROUP_PRIMARY,\n title: \"Evolve: drag to set the target maturity\",\n html: cpHtml(\n chromeIcon(\"chevrons-right\"),\n \"Evolve: drag to set the target maturity\",\n true,\n ),\n action: { click: startEvolve, dragstart: startEvolve },\n };\n }\n }\n }\n\n /** Row 2: settings, line style, colour, link. */\n private addPropertyEntries(shape: WardleyShape, entries: ContextPadEntries): void {\n if (shape.wardleyType === \"component\") {\n entries[\"settings\"] = {\n group: GROUP_PROPERTIES,\n title: \"Settings (type, sourcing, inertia)\",\n html: cpHtml(chromeIcon(\"sliders-horizontal\"), \"Settings (type, sourcing, inertia)\"),\n action: {\n click: (event: Event) => {\n const e = event as MouseEvent;\n this.popupMenu.open(shape as unknown as Element, POPUP_PROVIDER_ID, {\n x: e.clientX,\n y: e.clientY,\n });\n },\n },\n };\n }\n\n // Drawings: cycle the stroke style (solid -> dashed -> dotted).\n if (shape.wardleyType === \"drawing\") {\n const next =\n shape.strokeStyle === \"dashed\"\n ? \"dotted\"\n : shape.strokeStyle === \"dotted\"\n ? undefined\n : \"dashed\";\n const title = `Line style: ${shape.strokeStyle ?? \"solid\"} (click to change)`;\n entries[\"stroke-style\"] = {\n group: GROUP_PROPERTIES,\n title,\n html: cpHtml(chromeIcon(\"line-style\"), title),\n action: {\n click: this.focusingCanvas(() =>\n this.wardleyModeling.updateProperties(shape, { strokeStyle: next }),\n ),\n },\n };\n }\n\n // Color is available on EVERY element (model-wide `color`, DSL extension `(color ...)`).\n entries[\"color\"] = {\n group: GROUP_PROPERTIES,\n title: \"Color\",\n html: cpHtml(chromeIcon(\"palette\"), \"Color\"),\n action: {\n click: (event: Event) => {\n const e = event as MouseEvent;\n this.colorPicker.open(shape, e.clientX, e.clientY);\n },\n },\n };\n\n // OWM `url(...)`: set the address (submap drill-down / component link) and open it.\n const linkEditing = this.injector.get<WardleyLinkEditing>(\"wardleyLinkEditing\", false);\n const storedLink = linkOf(shape);\n if (linkEditing && canHaveLink(shape)) {\n const title = storedLink ? \"Edit link…\" : \"Set link…\";\n entries[\"link\"] = {\n group: GROUP_PROPERTIES,\n title,\n html: cpHtml(chromeIcon(\"link\"), title),\n action: { click: () => linkEditing.activate(shape) },\n };\n }\n // Shared maps can carry any address, so only allowlisted ones are ever opened.\n const openableLink = safeLinkUrl(storedLink);\n if (openableLink) {\n entries[\"open-link\"] = {\n group: GROUP_PROPERTIES,\n title: `Open link (${openableLink})`,\n html: cpHtml(chromeIcon(\"external-link\"), `Open link (${openableLink})`),\n action: {\n click: this.focusingCanvas(() =>\n window.open(openableLink, \"_blank\", \"noopener,noreferrer\"),\n ),\n },\n };\n }\n }\n\n /**\n * For an entry that opens no editor or popup: after a pointer click or drag it hands the focus to\n * the canvas (guide §5.8), whose keys act only while it has the focus. The clicked entry took the\n * focus and goes away when the pad re-renders or closes, which would leave it on `<body>`. Enter\n * and Space keep it in the pad (`onPadKeydown`).\n */\n private focusingCanvas(action: (event: Event) => void): (event: Event) => void {\n return (event) => {\n action(event);\n if (!this.keyboardEvents.has(event)) focusCanvasWithoutRing(this.canvas);\n };\n }\n\n /** Enter/Space on a focused entry = a click at the element's centre. */\n private onPadKeydown(event: KeyboardEvent, pad: HTMLElement): void {\n if (event.altKey || event.ctrlKey || event.metaKey) return;\n const entry = (event.target as Element | null)?.closest?.(\".entry\");\n const action = entry?.getAttribute(\"data-action\");\n if (!entry || !action || !pad.contains(entry)) return;\n\n // Toolbar navigation, stopped here: no listener further up acts on these keys too.\n const entries = Array.from(pad.querySelectorAll<HTMLElement>(\".entry\"));\n const index = entries.indexOf(entry as HTMLElement);\n let next: HTMLElement | undefined;\n if (PAD_PREVIOUS_KEYS.has(event.key))\n next = entries[(index - 1 + entries.length) % entries.length];\n else if (PAD_NEXT_KEYS.has(event.key)) next = entries[(index + 1) % entries.length];\n else if (event.key === \"Home\") next = entries[0];\n else if (event.key === \"End\") next = entries[entries.length - 1];\n if (next || event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n if (next) next.focus();\n else this.canvas.focus();\n return;\n }\n\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n event.stopPropagation();\n\n const target = (this.contextPad as unknown as { _current?: { target?: unknown } })._current\n ?.target;\n const point = this.clientCenterOf(Array.isArray(target) ? target[0] : target);\n const click = new MouseEvent(\"click\", { bubbles: true, clientX: point.x, clientY: point.y });\n this.keyboardEvents.add(click);\n this.contextPad.triggerEntry(action, \"click\", click);\n\n // Actions that close the pad (delete, …) would otherwise drop focus onto <body>.\n const focused = document.activeElement;\n if (!pad.isConnected && (!focused || focused === document.body)) this.canvas.focus();\n }\n\n private clientCenterOf(element: unknown): { x: number; y: number } {\n const containerBounds = this.canvas.getContainer().getBoundingClientRect();\n const viewbox = this.canvas.viewbox();\n let center = { x: viewbox.x + viewbox.width / 2, y: viewbox.y + viewbox.height / 2 };\n if (isWardleyConnection(element)) {\n const first = element.waypoints[0];\n const last = element.waypoints[element.waypoints.length - 1];\n if (first && last) center = { x: (first.x + last.x) / 2, y: (first.y + last.y) / 2 };\n } else if (isWardleyShape(element)) {\n center = { x: element.x + element.width / 2, y: element.y + element.height / 2 };\n }\n return {\n x: containerBounds.left + (center.x - viewbox.x) * viewbox.scale,\n y: containerBounds.top + (center.y - viewbox.y) * viewbox.scale,\n };\n }\n\n /**\n * Keyboard append: there is no pointer to drag the new component to, so it is placed one step\n * further down the value chain, connected, selected and opened for naming.\n */\n private appendBelow(source: WardleyShape): void {\n const grid = this.injector.get<EvolutionGrid>(\"evolutionGrid\");\n const plotBottom = grid.toCanvas({ evolution: 0, visibility: 0 }).y;\n const next = this.factory.createNew(\"component\", \"Component\");\n const position = {\n x: source.x + source.width / 2,\n y: Math.min(\n source.y + source.height / 2 + KEYBOARD_APPEND_OFFSET,\n plotBottom - next.height / 2,\n ),\n };\n const created = this.modeling.appendShape(\n source as unknown as Shape,\n next as unknown as Shape,\n position,\n (source as unknown as Shape).parent!,\n { connection: { wardleyType: \"dependency\" } },\n );\n this.injector\n .get<{ select(element: unknown): void }>(\"selection\", false)\n ?.select(created ?? next);\n this.labelEditing.activate((created ?? next) as unknown as WardleyShape);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ContextPadModule from \"diagram-js/lib/features/context-pad\";\nimport WardleyContextPad from \"./WardleyContextPad.js\";\nimport WardleyContextPadProvider from \"./WardleyContextPadProvider.js\";\n\n/** Context actions per element. */\nexport const wardleyContextPadModule: ModuleDeclaration = {\n // Depending on the diagram-js module guarantees our 'contextPad' registration overrides its own.\n __depends__: [ContextPadModule],\n __init__: [\"wardleyContextPadProvider\"],\n contextPad: [\"type\", WardleyContextPad],\n wardleyContextPadProvider: [\"type\", WardleyContextPadProvider],\n};\n\nexport { default as WardleyContextPadProvider } from \"./WardleyContextPadProvider.js\";\nexport { default as WardleyContextPad } from \"./WardleyContextPad.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\nimport type Mouse from \"diagram-js/lib/features/mouse/Mouse\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type Rules from \"diagram-js/lib/features/rules/Rules\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type WardleyCopyPaste from \"../modeling/WardleyCopyPaste.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyDrawTool from \"../draw-tool/WardleyDrawTool.js\";\nimport type WardleyLabelEditing from \"../label-editing/WardleyLabelEditing.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport { canvasSvg } from \"../a11y/index.js\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyShape,\n type WardleyShapeType,\n} from \"../model/di-types.js\";\n\n/** Diagram config `wardleyKeyboard` (viewer option `undoRedoKeys`). */\nexport interface WardleyKeyboardConfig {\n /**\n * Handle Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z and Cmd/Ctrl+Y on the canvas (default true). Hosts that own\n * undo themselves (VS Code custom editors) set this to false and receive the keys untouched.\n */\n undoRedo?: boolean;\n}\n\n/** Arrow-key nudge in diagram px (Shift = coarse). */\nconst NUDGE_STEP = 2;\nconst NUDGE_STEP_COARSE = 10;\n\nconst ARROW_DELTAS: Record<string, { x: number; y: number }> = {\n arrowleft: { x: -1, y: 0 },\n arrowright: { x: 1, y: 0 },\n arrowup: { x: 0, y: -1 },\n arrowdown: { x: 0, y: 1 },\n};\n\nconst QUICK_CREATE: Record<string, { type: WardleyShapeType; label: string }> = {\n c: { type: \"component\", label: \"Component\" },\n u: { type: \"anchor\", label: \"User\" },\n n: { type: \"note\", label: \"Note\" },\n p: { type: \"pipeline\", label: \"Pipeline\" },\n};\n\n/** Keyboard-created shapes stay this far inside the plot edge. */\nconst PLOT_INSET = 40;\n/**\n * Repeated keyboard creates step downwards so they do not stack on one spot; labels sit to the\n * right of nodes, so a vertical step keeps every name readable. At the plot bottom the next\n * column starts, leaving room for the labels.\n */\nconst STACK_STEP = 56;\nconst STACK_COLUMN_STEP = 160;\nconst STACK_CLEARANCE = { x: 48, y: 40 };\nconst STACK_ATTEMPTS = 40;\n\ninterface PlotBounds {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n/**\n * A key is the canvas's only while the canvas `<svg>` has the focus, as with diagram-js' own\n * keyboard: the svg holds no editor, palette, context pad or popup, so they keep their keys,\n * and so do a host's controls and a page with nothing focused. A keydown without a key (autofill)\n * or one a listener before this one took stays with the page, and so does IME composition.\n */\nfunction isCanvasKey(event: KeyboardEvent, svg: SVGElement | null): boolean {\n const target = event.target;\n return (\n typeof event.key === \"string\" &&\n !event.defaultPrevented &&\n !event.isComposing &&\n target instanceof Node &&\n !!svg?.contains(target)\n );\n}\n\n/**\n * Keyboard binding: undo/redo, delete, copy/paste/duplicate, arrow-key nudge, Escape (deselect),\n * Cmd/Ctrl+A (select all), the single-key tools C (component), U (user), N (note), P (pipeline),\n * L (lasso) and A (connect from the selected node), all only while the canvas has the focus.\n * Deliberately a DOM listener (no diagram-js keyboard-service binding needed).\n */\nexport default class WardleyKeyboard {\n static $inject = [\n \"canvas\",\n \"commandStack\",\n \"selection\",\n \"modeling\",\n \"wardleyCopyPaste\",\n \"wardleyElementFactory\",\n \"create\",\n \"mouse\",\n \"lassoTool\",\n \"eventBus\",\n \"elementRegistry\",\n \"injector\",\n \"config.wardleyKeyboard\",\n ];\n\n private pointerOverCanvas = false;\n private readonly labelEditing: WardleyLabelEditing | null;\n private readonly grid: EvolutionGrid | null;\n private readonly freeRect: FreeRect | null;\n\n constructor(\n private readonly canvas: Canvas,\n commandStack: CommandStack,\n private readonly selection: Selection,\n private readonly modeling: Modeling,\n copyPaste: WardleyCopyPaste,\n private readonly factory: WardleyElementFactory,\n private readonly create: Create,\n private readonly mouse: Mouse,\n lassoTool: LassoTool,\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n injector: Injector,\n config: WardleyKeyboardConfig | undefined,\n ) {\n const container = canvas.getContainer();\n const undoRedoEnabled = config?.undoRedo !== false;\n const dragging = injector.get<Dragging | null>(\"dragging\", false);\n const connect = injector.get<Connect | null>(\"connect\", false);\n const rules = injector.get<Rules | null>(\"rules\", false);\n const popupMenu = injector.get<PopupMenu | null>(\"popupMenu\", false);\n const drawTool = injector.get<WardleyDrawTool | null>(\"wardleyDrawTool\", false);\n this.labelEditing =\n injector.get<WardleyLabelEditing | null>(\"wardleyLabelEditing\", false) ?? null;\n this.grid = injector.get<EvolutionGrid | null>(\"evolutionGrid\", false) ?? null;\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n const svg = canvasSvg(canvas);\n\n // getLastMoveEvent() never returns null (it fabricates an event at 0,0), so whether the\n // pointer really is over the canvas has to be tracked here.\n const onPointerMove = () => (this.pointerOverCanvas = true);\n const onPointerLeave = () => (this.pointerOverCanvas = false);\n container.addEventListener(\"mousemove\", onPointerMove);\n container.addEventListener(\"mouseleave\", onPointerLeave);\n\n // Escape is consumed by drags, the draw tool and popups, which react in the capture phase or\n // on keyup — their state is snapshotted before any of them runs.\n let escapeOwnedByOverlay = false;\n const onKeydownCapture = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n escapeOwnedByOverlay =\n !!dragging?.context() ||\n !!drawTool?.isActive() ||\n !!popupMenu?.isOpen() ||\n !!container.querySelector(\".wardley-color-picker\");\n };\n\n const deleteSelection = (e: KeyboardEvent) => {\n const selected = selection.get() as Element[];\n if (!selected.length) return;\n e.preventDefault();\n modeling.removeElements(selected);\n };\n\n // The element clipboard lives in memory, so the browser cannot tell whether it or the system\n // clipboard is newer. After the page lost focus or saw a text copy, the system clipboard may\n // hold something newer (e.g. map text to import): let the browser's paste event reach the host\n // first and only paste the copied elements when nobody consumed it.\n let internalClipboardIsNewest = false;\n let deferredPaste: ReturnType<typeof setTimeout> | undefined;\n const markSystemClipboardNewer = () => (internalClipboardIsNewest = false);\n const pasteFromInternalClipboard = (e: KeyboardEvent) => {\n if (internalClipboardIsNewest) {\n if (copyPaste.paste()) e.preventDefault();\n return;\n }\n clearTimeout(deferredPaste);\n deferredPaste = setTimeout(() => {\n deferredPaste = undefined;\n copyPaste.paste();\n }, 0);\n };\n const onPaste = (e: ClipboardEvent) => {\n if (deferredPaste === undefined || !e.defaultPrevented) return;\n clearTimeout(deferredPaste);\n deferredPaste = undefined;\n };\n\n // A locked canvas (an invalid file in an IDE) keeps selection, copy and the lasso.\n const locked = () => isReadOnly(injector);\n const onModifierShortcut = (e: KeyboardEvent, key: string) => {\n if (locked() && ![\"a\", \"c\"].includes(key)) return;\n if (key === \"z\" || key === \"y\") {\n if (!undoRedoEnabled) return;\n e.preventDefault();\n if (key === \"z\" && !e.shiftKey) commandStack.undo();\n else commandStack.redo();\n } else if (key === \"a\") {\n e.preventDefault();\n selection.select(\n elementRegistry.filter((el) => isWardleyShape(el) || isWardleyConnection(el)),\n );\n } else if (key === \"c\") {\n if (copyPaste.copy()) {\n e.preventDefault();\n internalClipboardIsNewest = true;\n }\n } else if (key === \"v\") {\n pasteFromInternalClipboard(e);\n } else if (key === \"d\") {\n e.preventDefault();\n if (copyPaste.duplicate()) internalClipboardIsNewest = true;\n } else if (key === \"delete\" || key === \"backspace\") {\n deleteSelection(e);\n }\n };\n\n const onPlainKey = (e: KeyboardEvent, key: string) => {\n const toolKey = !e.altKey;\n if (locked() && key !== \"escape\" && key !== \"l\") return;\n if (key === \"escape\") {\n if (!escapeOwnedByOverlay && selection.get().length) selection.select(null);\n } else if (key === \"delete\" || key === \"backspace\") {\n deleteSelection(e);\n } else if (toolKey && key in QUICK_CREATE) {\n e.preventDefault();\n const { type, label } = QUICK_CREATE[key]!;\n this.quickCreate(type, label);\n } else if (toolKey && key === \"a\") {\n const source = this.singleSelectedShape();\n if (!source || !connect || !rules?.allowed(\"connection.start\", { source })) return;\n e.preventDefault();\n const center = { x: source.x + source.width / 2, y: source.y + source.height / 2 };\n connect.start(this.pointerEventOr(center), source as unknown as Element, center, true);\n } else if (toolKey && key === \"l\") {\n e.preventDefault();\n lassoTool.activateSelection(mouse.getLastMoveEvent(), true);\n } else if (key in ARROW_DELTAS) {\n const selected = selection.get() as Element[];\n if (!selected.length) return;\n e.preventDefault();\n const step = e.shiftKey ? NUDGE_STEP_COARSE : NUDGE_STEP;\n const delta = ARROW_DELTAS[key]!;\n modeling.moveElements(selected, { x: delta.x * step, y: delta.y * step });\n }\n };\n\n // On the document, not the svg: a listener on the way up (a host's wrapper around the canvas)\n // runs first and can take a key (defaultPrevented) before the canvas acts on it.\n const onKeydown = (e: KeyboardEvent) => {\n if (!isCanvasKey(e, svg)) return;\n const key = e.key.toLowerCase();\n if (e.ctrlKey || e.metaKey) onModifierShortcut(e, key);\n else onPlainKey(e, key);\n };\n\n window.addEventListener(\"keydown\", onKeydownCapture, true);\n document.addEventListener(\"keydown\", onKeydown);\n window.addEventListener(\"blur\", markSystemClipboardNewer);\n document.addEventListener(\"copy\", markSystemClipboardNewer);\n document.addEventListener(\"cut\", markSystemClipboardNewer);\n window.addEventListener(\"paste\", onPaste);\n eventBus.on(\"diagram.destroy\", () => {\n clearTimeout(deferredPaste);\n window.removeEventListener(\"keydown\", onKeydownCapture, true);\n document.removeEventListener(\"keydown\", onKeydown);\n window.removeEventListener(\"blur\", markSystemClipboardNewer);\n document.removeEventListener(\"copy\", markSystemClipboardNewer);\n document.removeEventListener(\"cut\", markSystemClipboardNewer);\n window.removeEventListener(\"paste\", onPaste);\n container.removeEventListener(\"mousemove\", onPointerMove);\n container.removeEventListener(\"mouseleave\", onPointerLeave);\n });\n }\n\n /**\n * With the pointer over the canvas the new node attaches to it (like palette create; placing it\n * opens the name editor). Without one — keyboard only — it lands in the centre of the free\n * rectangle (within the plot) and the name editor opens right away.\n */\n private quickCreate(type: WardleyShapeType, label: string): void {\n const shape = this.factory.createNew(type, label) as unknown as Shape;\n if (this.pointerOverCanvas) {\n this.create.start(this.mouse.getLastMoveEvent(), shape);\n return;\n }\n const bounds = this.insetPlotBounds();\n const created = this.modeling.createShape(\n shape,\n this.freeSpotNear(this.visiblePlotCenter(bounds), bounds),\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created);\n this.labelEditing?.activate(created as unknown as WardleyShape);\n }\n\n private insetPlotBounds(): PlotBounds | null {\n if (!this.grid) return null;\n const topLeft = this.grid.toCanvas({ visibility: 1, evolution: 0 });\n const bottomRight = this.grid.toCanvas({ visibility: 0, evolution: 1 });\n return {\n left: topLeft.x + PLOT_INSET,\n top: topLeft.y + PLOT_INSET,\n right: bottomRight.x - PLOT_INSET,\n bottom: bottomRight.y - PLOT_INSET,\n };\n }\n\n private visiblePlotCenter(bounds: PlotBounds | null): { x: number; y: number } {\n const viewbox = this.canvas.viewbox();\n const center = this.freeRect?.center() ?? {\n x: viewbox.x + viewbox.width / 2,\n y: viewbox.y + viewbox.height / 2,\n };\n if (!bounds) return center;\n return {\n x: clamp(center.x, bounds.left, bounds.right),\n y: clamp(center.y, bounds.top, bounds.bottom),\n };\n }\n\n private freeSpotNear(\n point: { x: number; y: number },\n bounds: PlotBounds | null,\n ): { x: number; y: number } {\n const occupied = (candidate: { x: number; y: number }) =>\n !!this.elementRegistry.find(\n (el) =>\n isWardleyShape(el) &&\n Math.abs(el.x + el.width / 2 - candidate.x) < STACK_CLEARANCE.x &&\n Math.abs(el.y + el.height / 2 - candidate.y) < STACK_CLEARANCE.y,\n );\n let candidate = point;\n for (let attempt = 0; attempt < STACK_ATTEMPTS && occupied(candidate); attempt++) {\n candidate = { x: candidate.x, y: candidate.y + STACK_STEP };\n if (bounds && candidate.y > bounds.bottom) {\n candidate = { x: candidate.x + STACK_COLUMN_STEP, y: point.y };\n if (candidate.x > bounds.right) return point;\n }\n }\n return candidate;\n }\n\n private singleSelectedShape(): WardleyShape | undefined {\n const selected = this.selection.get();\n return selected.length === 1 && isWardleyShape(selected[0]) ? selected[0] : undefined;\n }\n\n /** The real pointer event, or a synthetic one at `canvasPoint` when the pointer is elsewhere. */\n private pointerEventOr(canvasPoint: { x: number; y: number }): MouseEvent {\n if (this.pointerOverCanvas) return this.mouse.getLastMoveEvent();\n const viewbox = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n const rect = this.canvas.getContainer().getBoundingClientRect();\n return new MouseEvent(\"mousemove\", {\n clientX: rect.left + (canvasPoint.x - viewbox.x) * scale,\n clientY: rect.top + (canvasPoint.y - viewbox.y) * scale,\n });\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return min > max ? (min + max) / 2 : Math.min(Math.max(value, min), max);\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyKeyboard from \"./WardleyKeyboard.js\";\n\n/** Undo/redo/delete and the single-key tools on the focused canvas. */\nexport const wardleyKeyboardModule: ModuleDeclaration = {\n __init__: [\"wardleyKeyboard\"],\n wardleyKeyboard: [\"type\", WardleyKeyboard],\n};\n\nexport { default as WardleyKeyboard } from \"./WardleyKeyboard.js\";\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\n\ninterface ConnectionPreviewLike {\n drawPreview(context: object, canConnect: unknown, hints: object): void;\n cleanUp(context: object): void;\n}\n\ninterface LabelEditingLike {\n activate(element: object): void;\n}\n\ninterface SourceShape {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface CreateEvent {\n x: number;\n y: number;\n context: {\n source?: SourceShape;\n shape?: { wardleyType?: unknown };\n elements?: readonly object[];\n canExecute?: { connect?: unknown } | false | null;\n /** Set by WardleyCopyPaste: pasted copies keep their names, no editor. */\n wardleyPaste?: boolean;\n };\n}\n\n/** Types that carry a visible name — placing one goes straight into naming it. */\nconst NAMED_TYPES: ReadonlySet<unknown> = new Set([\n \"component\",\n \"anchor\",\n \"submap\",\n \"pipeline\",\n \"accelerator\",\n \"note\",\n]);\n\n// diagram-js runs listeners in descending priority order; the default create.end handler (creation)\n// sits at 1000 -> with < 1000 we run AFTERWARDS, once the shape already exists.\nconst AFTER_CREATE = 500;\n\n/**\n * Create behavior for palette, keyboard and \"append component\" (`create.start`, the latter with\n * `context.source`):\n * 1. Append only: LIVE arrow preview from the source to the cursor (analogous to diagram-js\n * ConnectPreview, but in the create flow) — requires the `connectionPreview` service.\n * 2. After placing a single named element (component, user, submap, pipeline, accelerator, note)\n * the label editor opens with the placeholder selected, so typing names it right away.\n * Regions, drawings and pasted copies are left alone.\n */\nexport default class WardleyAppendBehavior {\n static $inject = [\"injector\", \"eventBus\"];\n\n constructor(injector: Injector, eventBus: EventBus) {\n const connectionPreview = injector.get(\n \"connectionPreview\",\n false,\n ) as ConnectionPreviewLike | null;\n const labelEditing = injector.get(\"wardleyLabelEditing\", false) as LabelEditingLike | null;\n\n // (1) arrow preview\n if (connectionPreview) {\n eventBus.on(\"create.move\", (event: CreateEvent) => {\n const { context } = event;\n const source = context.source;\n if (!source) return;\n const canConnect =\n context.canExecute && (context.canExecute as { connect?: unknown }).connect;\n connectionPreview.drawPreview(context, canConnect ?? false, {\n source,\n connectionStart: { x: source.x + source.width / 2, y: source.y + source.height / 2 },\n connectionEnd: { x: event.x, y: event.y },\n });\n });\n\n eventBus.on(\n [\"create.end\", \"create.cancel\", \"create.cleanup\"],\n (event: { context: object }) => {\n connectionPreview.cleanUp(event.context);\n },\n );\n }\n\n // (2) automatically open the label editor after placing a named element\n if (labelEditing) {\n eventBus.on(\"create.end\", AFTER_CREATE, (event: CreateEvent) => {\n const { context } = event;\n const shape = context.shape;\n if (!context.canExecute || !shape || context.wardleyPaste) return;\n if ((context.elements?.length ?? 1) !== 1 || !NAMED_TYPES.has(shape.wardleyType)) return;\n // Activate only after render/cleanup so the editor is positioned correctly.\n setTimeout(() => labelEditing.activate(shape), 0);\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ConnectionPreviewModule from \"diagram-js/lib/features/connection-preview\";\nimport WardleyAppendBehavior from \"./WardleyAppendBehavior.js\";\n\n/**\n * \"Append component\": pulls in the `connectionPreview` service (thereby also enabling the connect\n * tool's arrow preview) and registers the append behavior (live arrow preview + automatically\n * opening the label editor after creation).\n */\nexport const wardleyAppendModule: ModuleDeclaration = {\n __depends__: [ConnectionPreviewModule],\n __init__: [\"wardleyAppendBehavior\"],\n wardleyAppendBehavior: [\"type\", WardleyAppendBehavior],\n};\n\nexport { default as WardleyAppendBehavior } from \"./WardleyAppendBehavior.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { NOTE_COLORS } from \"../draw/styles.js\";\n\n/** Must match `grid-template-columns` of `.wardley-color-picker` (arrow-key navigation). */\nconst GRID_COLUMNS = 3;\n\nconst GRID_STEPS: Record<string, number> = {\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -GRID_COLUMNS,\n ArrowDown: GRID_COLUMNS,\n};\n\n/**\n * Compact color picker (bpmn.io-style): a 3x3 grid of small color squares (no text), opened from a\n * note's context pad. Uses its own popover (instead of diagram-js PopupMenu) so the swatch grid can\n * be rendered exactly and without text. Sets the color via `wardleyModeling` (undo/redo). First\n * cell = \"no color\". Keyboard: focus starts on the active swatch, arrow keys move through the grid,\n * Enter/Space picks, Escape closes; focus then returns to the canvas.\n */\nexport default class WardleyColorPicker {\n static $inject = [\"canvas\", \"eventBus\", \"wardleyModeling\", \"injector\"];\n\n private popover: HTMLElement | undefined;\n\n private readonly onDocPointer = (e: MouseEvent): void => {\n if (this.popover && !this.popover.contains(e.target as Node)) this.close();\n };\n // A capture listener on the document: only an Escape aimed at the modeler (the swatches, the\n // canvas) is the picker's, never one that closes a host's menu or dialog.\n private readonly onKey = (e: KeyboardEvent): void => {\n if (e.key !== \"Escape\" || !(e.target instanceof Node)) return;\n if (!this.canvas.getContainer().contains(e.target)) return;\n e.preventDefault();\n e.stopPropagation();\n this.close({ restoreFocus: true });\n };\n\n constructor(\n private readonly canvas: Canvas,\n eventBus: EventBus,\n private readonly modeling: WardleyModeling,\n private readonly injector: Injector,\n ) {\n // Close on pan/zoom, drag or re-import (otherwise the popover ends up misplaced), and with the\n // modeler, whose document listeners would otherwise outlive it.\n eventBus.on([\"canvas.viewbox.changing\", \"drag.init\", \"diagram.clear\", \"diagram.destroy\"], () =>\n this.close(),\n );\n }\n\n /** Opens the swatch grid for `shape` at the click position (viewport coordinates). */\n open(shape: WardleyShape, clientX: number, clientY: number): void {\n this.close();\n if (isReadOnly(this.injector)) return;\n const container = this.canvas.getContainer();\n const rect = container.getBoundingClientRect();\n\n const pop = document.createElement(\"div\");\n pop.className = \"wardley-color-picker\";\n pop.setAttribute(\"role\", \"dialog\");\n pop.setAttribute(\"aria-label\", \"Color\");\n\n const swatches: ReadonlyArray<{ value: string | undefined; title: string; cls: string }> = [\n { value: undefined, title: \"No color\", cls: \"wardley-cp-none\" },\n ...NOTE_COLORS.map((c) => ({ value: c.value as string, title: c.name, cls: \"\" })),\n ];\n const buttons: HTMLButtonElement[] = [];\n let activeButton: HTMLButtonElement | undefined;\n for (const s of swatches) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = `wardley-cp-swatch ${s.cls}`.trim();\n btn.title = s.title;\n btn.setAttribute(\"aria-label\", s.title);\n if (s.value) btn.style.background = s.value;\n const isActive = (shape.color ?? undefined) === s.value;\n btn.setAttribute(\"aria-pressed\", String(isActive));\n if (isActive) {\n btn.classList.add(\"wardley-cp-active\");\n activeButton = btn;\n }\n btn.addEventListener(\"click\", (ev) => {\n ev.stopPropagation();\n this.modeling.setColor(shape, s.value);\n this.close({ restoreFocus: true });\n });\n buttons.push(btn);\n pop.append(btn);\n }\n pop.addEventListener(\"keydown\", (event) => this.onGridKeydown(event, buttons));\n\n container.appendChild(pop);\n\n // Keep it within the (overflow:hidden) container.\n const cw = container.clientWidth;\n const ch = container.clientHeight;\n const pw = pop.offsetWidth;\n const ph = pop.offsetHeight;\n const left = Math.max(4, Math.min(clientX - rect.left, cw - pw - 4));\n const top = Math.max(4, Math.min(clientY - rect.top, ch - ph - 4));\n pop.style.left = `${left}px`;\n pop.style.top = `${top}px`;\n\n this.popover = pop;\n (activeButton ?? buttons[0])?.focus({ preventScroll: true });\n // Attach listeners with a delay so the opening click does not immediately close the popover,\n // and not at all once it closed in the meantime.\n setTimeout(() => {\n if (this.popover !== pop) return;\n document.addEventListener(\"click\", this.onDocPointer, true);\n document.addEventListener(\"keydown\", this.onKey, true);\n }, 0);\n }\n\n isOpen(): boolean {\n return !!this.popover;\n }\n\n close(options: { restoreFocus?: boolean } = {}): void {\n if (!this.popover) return;\n const hadFocus = this.popover.contains(document.activeElement);\n this.popover.remove();\n this.popover = undefined;\n document.removeEventListener(\"click\", this.onDocPointer, true);\n document.removeEventListener(\"keydown\", this.onKey, true);\n if (options.restoreFocus || hadFocus) this.canvas.focus();\n }\n\n private onGridKeydown(event: KeyboardEvent, buttons: HTMLButtonElement[]): void {\n const step = GRID_STEPS[event.key];\n const index = buttons.indexOf(document.activeElement as HTMLButtonElement);\n let next: number | undefined;\n if (step !== undefined) next = index < 0 ? 0 : index + step;\n else if (event.key === \"Home\") next = 0;\n else if (event.key === \"End\") next = buttons.length - 1;\n else if (event.key === \"Tab\") {\n // Keep focus inside the dialog while it is open.\n next = index + (event.shiftKey ? -1 : 1);\n next = (next + buttons.length) % buttons.length;\n }\n if (next === undefined) return;\n // The grid's own keys: no listener further up acts on them too.\n event.preventDefault();\n event.stopPropagation();\n buttons[Math.min(buttons.length - 1, Math.max(0, next))]?.focus();\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyColorPicker from \"./WardleyColorPicker.js\";\n\n/** Note color picker (3x3 swatch popover). */\nexport const wardleyColorPickerModule: ModuleDeclaration = {\n __init__: [\"wardleyColorPicker\"],\n wardleyColorPicker: [\"type\", WardleyColorPicker],\n};\n\nexport { default as WardleyColorPicker } from \"./WardleyColorPicker.js\";\n","import OrderingProvider from \"diagram-js/lib/features/ordering/OrderingProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\n/** Frame types sit at the very back (concept doc: frames -> connections -> nodes). */\nfunction isFrame(el: unknown): boolean {\n return (\n isWardleyShape(el) &&\n ((el as WardleyShape).wardleyType === \"attitude\" ||\n (el as WardleyShape).wardleyType === \"pipeline\")\n );\n}\n\n/**\n * Keeps the z-order stable for INTERACTIVELY created/moved elements, matching the import order:\n * frames (attitude/pipeline) at the back, then dependencies, then flows, nodes on top. Without this,\n * connections drawn in the editor would land above the nodes (unlike imported ones).\n */\nexport default class WardleyOrderingProvider extends OrderingProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override getOrdering(\n element: ElementLike,\n newParent: ShapeLike,\n ): { parent: ShapeLike; index?: number } {\n const siblings = (newParent.children ?? []) as ElementLike[];\n if (isWardleyConnection(element)) {\n // Behind the nodes. A flow goes on top of all connections; a dependency stays below the\n // flows, so it cannot strike through a flow value (matches the import order).\n const isFlow = element.wardleyType === \"flow\";\n const index = siblings.filter(\n (c) =>\n c !== element &&\n (isFrame(c) || (isWardleyConnection(c) && (isFlow || c.wardleyType !== \"flow\"))),\n ).length;\n return { parent: newParent, index };\n }\n if (isFrame(element)) {\n // All the way to the back (after the other frames).\n const index = siblings.filter((c) => c !== element && isFrame(c)).length;\n return { parent: newParent, index };\n }\n // Nodes: on top (append).\n return { parent: newParent };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyOrderingProvider from \"./WardleyOrderingProvider.js\";\n\n/** Z-order for interactive edits: frames -> connections -> nodes (like the import). */\nexport const wardleyOrderingModule: ModuleDeclaration = {\n __init__: [\"wardleyOrderingProvider\"],\n wardleyOrderingProvider: [\"type\", WardleyOrderingProvider],\n};\n\nexport { default as WardleyOrderingProvider } from \"./WardleyOrderingProvider.js\";\n","import type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport { COLORS } from \"../draw/styles.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { canvasSvg, focusCanvasWithoutRing } from \"../a11y/index.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Clicking this close (px, canvas coords) to the FIRST/LAST point finishes/closes. */\nconst CLOSE_RADIUS = 12;\n\nconst DRAW_TOOL_ENTRY = '.djs-palette .entry[data-action=\"draw-tool\"]';\n\n/**\n * Excalidraw-style polyline tool: activate, click point by point (rubber-band preview).\n * Finishing (like Excalidraw): click the LAST point again, double-click, Enter or Escape\n * commits the open line; clicking the FIRST point closes the shape. Escape with fewer than\n * two points cancels. The result is ONE undoable `drawing` shape that moves as a whole.\n */\nexport default class WardleyDrawTool {\n static $inject = [\n \"canvas\",\n \"eventBus\",\n \"modeling\",\n \"selection\",\n \"wardleyElementFactory\",\n \"evolutionGrid\",\n \"injector\",\n ];\n\n private active = false;\n private points: Point[] = [];\n private cursor: Point | null = null;\n private layer: SVGElement | null = null;\n\n constructor(\n private readonly canvas: Canvas,\n private readonly eventBus: EventBus,\n private readonly modeling: Modeling,\n private readonly selection: Selection,\n private readonly factory: WardleyElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n ) {\n eventBus.on(\"diagram.destroy\", () => this.cancel());\n }\n\n isActive(): boolean {\n return this.active;\n }\n\n toggle(): void {\n if (this.active) this.cancel();\n else this.activate();\n }\n\n /**\n * The OUTER viewer container — getContainer() returns the inner .djs-container, but the\n * mode class must sit on .wardley-container for the crosshair/empty-state CSS to match.\n */\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n\n activate(): void {\n if (this.active || isReadOnly(this.injector)) return;\n this.active = true;\n this.points = [];\n this.cursor = null;\n const container = this.canvas.getContainer();\n this.outerContainer().classList.add(\"wardley-draw-mode\");\n // Capture phase: while drawing, clicks must NOT select/move elements underneath.\n container.addEventListener(\"mousedown\", this.onMouseDown, true);\n container.addEventListener(\"dblclick\", this.onDblClick, true);\n container.addEventListener(\"mousemove\", this.onMouseMove, true);\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n // Light up the palette entry (same channel the tool manager uses).\n this.eventBus.fire(\"tool-manager.update\", { tool: \"draw\" });\n }\n\n /** Finishes the current polyline (>= 2 points) and deactivates the tool. */\n finish(): void {\n const pts = [...this.points];\n this.deactivate();\n if (pts.length < 2) return;\n this.create(this.factory.drawingFromCanvasPoints(pts));\n }\n\n /** Closes the shape (polygon) using the collected points. */\n private finishClosed(): void {\n const pts = [...this.points];\n this.deactivate();\n if (pts.length < 3) return;\n this.create(this.factory.drawingFromCanvasPoints(pts, { closed: true }));\n }\n\n /**\n * Created at its exact bounds: a centre position would be rounded by diagram-js and could push\n * points that sit on the plot edge half a pixel outside.\n */\n private create(shape: WardleyShape): void {\n const { x, y, width, height } = shape;\n const bounds = { x, y, width, height };\n const created = this.modeling.createShape(\n shape as unknown as Shape,\n bounds,\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created as unknown as Element);\n }\n\n cancel(): void {\n this.deactivate();\n }\n\n private deactivate(): void {\n if (!this.active) return;\n this.active = false;\n const container = this.canvas.getContainer();\n this.outerContainer().classList.remove(\"wardley-draw-mode\");\n container.removeEventListener(\"mousedown\", this.onMouseDown, true);\n container.removeEventListener(\"dblclick\", this.onDblClick, true);\n container.removeEventListener(\"mousemove\", this.onMouseMove, true);\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.points = [];\n this.cursor = null;\n this.clearPreview();\n this.eventBus.fire(\"tool-manager.update\", { tool: null });\n }\n\n /**\n * Clamped into the plot: drawings are saved as normalized [0,1] points, so the preview must not\n * show anything the saved shape cannot hold.\n */\n private toCanvasPoint(e: MouseEvent): Point {\n const rect = this.canvas.getContainer().getBoundingClientRect();\n const vb = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n return this.grid.toCanvas(\n this.grid.fromCanvas({\n x: (e.clientX - rect.left) / scale + vb.x,\n y: (e.clientY - rect.top) / scale + vb.y,\n }),\n );\n }\n\n /** Palette/context-pad/menus live INSIDE the container — let their clicks through. */\n private isChromeTarget(e: MouseEvent): boolean {\n const target = e.target as HTMLElement | null;\n return !!target?.closest(\".djs-palette, .djs-context-pad, .wardley-color-picker\");\n }\n\n private readonly onMouseDown = (e: MouseEvent): void => {\n if (e.button !== 0 || this.isChromeTarget(e)) return;\n e.preventDefault();\n e.stopPropagation();\n // The prevented default also keeps the browser from focusing the canvas, whose Enter and\n // Escape end the drawing.\n focusCanvasWithoutRing(this.canvas);\n const p = this.toCanvasPoint(e);\n const first = this.points[0];\n if (first && this.points.length >= 3 && distance(p, first) <= CLOSE_RADIUS) {\n this.finishClosed();\n return;\n }\n // Clicking the LAST point again finishes the open line (Excalidraw behavior) — this is\n // the discoverable way out; double-click/Enter/Escape work as well.\n const last = this.points[this.points.length - 1];\n if (last && distance(p, last) <= CLOSE_RADIUS) {\n if (this.points.length >= 2) this.finish();\n return;\n }\n this.points.push(p);\n this.renderPreview();\n };\n\n private readonly onDblClick = (e: MouseEvent): void => {\n if (this.isChromeTarget(e)) return;\n e.preventDefault();\n e.stopPropagation();\n this.finish();\n };\n\n private readonly onMouseMove = (e: MouseEvent): void => {\n if (!this.points.length) return;\n this.cursor = this.toCanvasPoint(e);\n this.renderPreview();\n };\n\n /**\n * Enter and Escape end the drawing only when aimed at the canvas `<svg>`, or at the palette entry\n * that starts this tool, where a tool started with Enter leaves the focus (guide §5.5). Every\n * other target keeps them, inside the container too: a host's fields, buttons, menus and dialogs,\n * its zoom panel, a focusable element in an overlay next to the canvas, and `<body>`. A capture\n * listener on the document would otherwise take them from all of these.\n */\n private ownsKey(e: KeyboardEvent): boolean {\n const target = e.target;\n if (typeof e.key !== \"string\" || e.defaultPrevented || e.isComposing) return false;\n if (!(target instanceof globalThis.Element)) return false;\n if (canvasSvg(this.canvas)?.contains(target)) return true;\n // Scoped to this canvas's container: another modeler on the page has its own draw entry.\n const entry = target.closest(DRAW_TOOL_ENTRY);\n return !!entry && this.canvas.getContainer().contains(entry);\n }\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (!this.ownsKey(e)) return;\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n // Excalidraw semantics: Escape COMMITS what is there (undo removes it); it only\n // cancels while no line exists yet.\n if (this.points.length >= 2) this.finish();\n else this.cancel();\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n e.stopPropagation();\n this.finish();\n }\n };\n\n private renderPreview(): void {\n this.clearPreview();\n if (!this.points.length) return;\n const layer = this.canvas.getLayer(\"wardley-draw-preview\", 1000);\n const group = svgCreate(\"g\");\n const pts = this.cursor ? [...this.points, this.cursor] : this.points;\n svgAppend(\n group,\n svgAttr(svgCreate(\"polyline\"), {\n points: pts.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: COLORS.ink,\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"stroke-dasharray\": \"5 4\",\n }),\n );\n // First point = \"close the shape here\", last point = \"finish the line here\".\n const first = this.points[0]!;\n svgAppend(\n group,\n svgAttr(svgCreate(\"circle\"), {\n cx: first.x,\n cy: first.y,\n r: this.points.length >= 3 ? 5 : 3,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n }),\n );\n if (this.points.length >= 2) {\n const last = this.points[this.points.length - 1]!;\n svgAppend(\n group,\n svgAttr(svgCreate(\"circle\"), {\n cx: last.x,\n cy: last.y,\n r: 5,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n }),\n );\n }\n svgAppend(layer, group);\n this.layer = group;\n }\n\n private clearPreview(): void {\n if (this.layer) {\n svgRemove(this.layer);\n this.layer = null;\n }\n }\n}\n\nfunction distance(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n","import type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { COLORS } from \"../draw/styles.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\n/**\n * Vertex handles for drawings: when exactly one drawing is selected, every point gets a small\n * draggable handle. Dragging shows a live preview; releasing commits the new geometry (points +\n * recomputed bbox) as ONE undoable command.\n */\nexport default class WardleyDrawingHandles {\n static $inject = [\"eventBus\", \"canvas\", \"wardleyModeling\", \"evolutionGrid\", \"injector\"];\n\n private shape: WardleyShape | null = null;\n private group: SVGElement | null = null;\n private dragPreview: SVGElement | null = null;\n private pointDrag: { shape: WardleyShape; unbind: () => void } | null = null;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly modeling: WardleyModeling,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n ) {\n eventBus.on(\"selection.changed\", (event: { newSelection?: unknown[] }) => {\n const sel = event.newSelection ?? [];\n const only = sel.length === 1 ? sel[0] : null;\n this.attach(\n isWardleyShape(only) && only.wardleyType === \"drawing\" ? (only as WardleyShape) : null,\n );\n });\n // Keep the handles glued to the shape while it is moved/changed.\n eventBus.on(\"element.changed\", (event: { element?: unknown }) => {\n if (this.shape && event.element === this.shape) this.render();\n });\n // An import, a delete or an undo removes the drawing mid-drag: the release must not commit\n // onto the removed shape.\n eventBus.on(\"shape.remove\", (event: { element?: unknown }) => {\n if (this.pointDrag?.shape === event.element) this.endPointDrag();\n });\n eventBus.on([\"diagram.clear\", \"diagram.destroy\"], () => {\n this.endPointDrag();\n this.attach(null);\n });\n }\n\n private attach(shape: WardleyShape | null): void {\n this.shape = shape;\n this.render();\n }\n\n private absolutePoints(): Point[] {\n const s = this.shape!;\n return (s.drawingPoints ?? []).map((p) => ({ x: s.x + p.x, y: s.y + p.y }));\n }\n\n private render(): void {\n this.clear();\n if (!this.shape) return;\n const layer = this.canvas.getLayer(\"wardley-drawing-handles\", 1100);\n const group = svgCreate(\"g\");\n this.absolutePoints().forEach((p, index) => {\n const handle = svgAttr(svgCreate(\"circle\"), {\n cx: p.x,\n cy: p.y,\n r: 5,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n class: \"wardley-drawing-handle\",\n });\n handle.addEventListener(\"mousedown\", (e) => this.startDrag(e as MouseEvent, index));\n svgAppend(group, handle);\n });\n svgAppend(layer, group);\n this.group = group;\n }\n\n private startDrag(e: MouseEvent, index: number): void {\n if (e.button !== 0 || !this.shape || isReadOnly(this.injector)) return;\n e.preventDefault();\n e.stopPropagation();\n // The prevented default keeps the browser from focusing the canvas, whose keys act only while\n // it has the focus.\n focusCanvasWithoutRing(this.canvas);\n this.endPointDrag();\n const shape = this.shape;\n const points = this.absolutePoints();\n\n const onMove = (ev: MouseEvent): void => {\n points[index] = this.toCanvasPoint(ev);\n this.renderDragPreview(points, !!shape.closed);\n };\n const onUp = (ev: MouseEvent): void => {\n points[index] = this.toCanvasPoint(ev);\n this.endPointDrag();\n this.commit(shape, points);\n };\n document.addEventListener(\"mousemove\", onMove, true);\n document.addEventListener(\"mouseup\", onUp, true);\n this.pointDrag = {\n shape,\n unbind: () => {\n document.removeEventListener(\"mousemove\", onMove, true);\n document.removeEventListener(\"mouseup\", onUp, true);\n },\n };\n }\n\n /**\n * Ends a running point drag without committing it. The point drag is this renderer's own gesture,\n * outside diagram-js dragging, so the import's drag cancel does not reach it: the removal of its\n * drawing ends it.\n */\n private endPointDrag(): void {\n const drag = this.pointDrag;\n if (!drag) return;\n this.pointDrag = null;\n drag.unbind();\n this.clearDragPreview();\n }\n\n /** New bbox + relative points + normalized anchor — ONE undoable updateProperties command. */\n private commit(shape: WardleyShape, points: Point[]): void {\n const xs = points.map((p) => p.x);\n const ys = points.map((p) => p.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n const firstNorm = this.grid.fromCanvas(points[0]!);\n this.modeling.updateProperties(shape, {\n x,\n y,\n width: Math.max(Math.max(...xs) - x, 4),\n height: Math.max(Math.max(...ys) - y, 4),\n drawingPoints: points.map((p) => ({ x: p.x - x, y: p.y - y })),\n evolution: firstNorm.evolution,\n visibility: firstNorm.visibility,\n });\n this.render();\n }\n\n private renderDragPreview(points: Point[], closed: boolean): void {\n this.clearDragPreview();\n const layer = this.canvas.getLayer(\"wardley-drawing-handles\", 1100);\n const preview = svgAttr(svgCreate(closed ? \"polygon\" : \"polyline\"), {\n points: points.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n \"stroke-dasharray\": \"5 4\",\n \"pointer-events\": \"none\",\n });\n svgAppend(layer, preview);\n this.dragPreview = preview;\n }\n\n private clearDragPreview(): void {\n if (this.dragPreview) {\n svgRemove(this.dragPreview);\n this.dragPreview = null;\n }\n }\n\n private clear(): void {\n this.clearDragPreview();\n if (this.group) {\n svgRemove(this.group);\n this.group = null;\n }\n }\n\n /** Clamped into the plot, like the draw tool: what the preview shows is what gets saved. */\n private toCanvasPoint(e: MouseEvent): Point {\n const rect = this.canvas.getContainer().getBoundingClientRect();\n const vb = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n return this.grid.toCanvas(\n this.grid.fromCanvas({\n x: (e.clientX - rect.left) / scale + vb.x,\n y: (e.clientY - rect.top) / scale + vb.y,\n }),\n );\n }\n}\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type InteractionEvents from \"diagram-js/lib/features/interaction-events/InteractionEvents\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\nfunction isDrawing(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"drawing\";\n}\n\n/**\n * Drawings get a hit zone along their STROKE only (generous 15px band, like the default\n * stroke hit) instead of the default full-bbox hit — a shape drawn AROUND elements must not\n * swallow the clicks for everything inside it. The interior stays click-through; the drawing\n * itself is selected/moved by grabbing its line.\n */\nexport default class WardleyDrawingHitProvider {\n static $inject = [\"eventBus\", \"interactionEvents\"];\n\n constructor(eventBus: EventBus, interactionEvents: InteractionEvents) {\n // The diagram-js default (box hit) listens on LOW_PRIORITY — returning false here\n // suppresses it (same pattern bpmn-js uses for its custom hits).\n eventBus.on(\"interactionEvents.createHit\", (event: { element?: unknown; gfx?: SVGElement }) => {\n if (!isDrawing(event.element) || !event.gfx) return;\n createStrokeHit(event.element, event.gfx);\n return false;\n });\n eventBus.on(\"interactionEvents.updateHit\", (event: { element?: unknown; gfx?: SVGElement }) => {\n if (!isDrawing(event.element) || !event.gfx) return;\n interactionEvents.removeHits(event.gfx);\n createStrokeHit(event.element, event.gfx);\n return false;\n });\n }\n}\n\nfunction createStrokeHit(shape: WardleyShape, gfx: SVGElement): void {\n const points = shape.drawingPoints ?? [];\n const hit = svgCreate(shape.closed ? \"polygon\" : \"polyline\");\n svgAttr(hit, {\n points: points.map((p) => `${p.x},${p.y}`).join(\" \"),\n class: \"djs-hit djs-hit-stroke\",\n fill: \"none\",\n stroke: \"white\",\n \"stroke-width\": 15,\n // diagram-js makes hits invisible via this INLINE attribute (its \"no-border\" trait),\n // not via CSS — without it the 15px white band is visible.\n \"stroke-opacity\": 0,\n });\n svgAppend(gfx, hit);\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyDrawTool from \"./WardleyDrawTool.js\";\nimport WardleyDrawingHandles from \"./WardleyDrawingHandles.js\";\nimport WardleyDrawingHitProvider from \"./WardleyDrawingHitProvider.js\";\n\nexport const wardleyDrawToolModule: ModuleDeclaration = {\n __init__: [\"wardleyDrawTool\", \"wardleyDrawingHandles\", \"wardleyDrawingHitProvider\"],\n wardleyDrawTool: [\"type\", WardleyDrawTool],\n wardleyDrawingHandles: [\"type\", WardleyDrawingHandles],\n wardleyDrawingHitProvider: [\"type\", WardleyDrawingHitProvider],\n};\n\nexport { default as WardleyDrawTool } from \"./WardleyDrawTool.js\";\nexport { default as WardleyDrawingHandles } from \"./WardleyDrawingHandles.js\";\nexport { default as WardleyDrawingHitProvider } from \"./WardleyDrawingHitProvider.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { LabelOffset, MapElement, Movement } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\nimport {\n LABEL_HANDLE_CLASS,\n LABEL_ROLE_ATTRIBUTE,\n componentLabelPlacement,\n componentLabelSlot,\n movementDeltaX,\n movementLabelPlacement,\n movementLabelSlot,\n normalizeLabelOffset,\n type LabelPlacement,\n} from \"../draw/index.js\";\n\n/** Which offset a label writes: the node's own `label [dx, dy]` or its evolve line's. */\nexport type LabelRole = \"name\" | \"movement\";\n\n/** Screen px the pointer must travel before a press on a label becomes a drag. */\nconst DRAG_THRESHOLD = 3;\n/** A label dropped this close to its default slot snaps back and clears the offset. */\nconst SNAP_HOME_DISTANCE = 4;\nconst ARMED_CLASS = \"wardley-labels-draggable\";\nconst DRAGGING_CLASS = \"wardley-label-dragging\";\n\ninterface LabelDrag {\n shape: WardleyShape;\n role: LabelRole;\n startClient: { x: number; y: number };\n startOffset: LabelOffset;\n homeOffset: LabelOffset;\n originalOffset: LabelOffset | undefined;\n originalMovement: Movement | undefined;\n zoom: number;\n latest?: LabelOffset;\n dragging: boolean;\n}\n\n/**\n * OWM-style draggable labels: drag a component/anchor name or an evolve target name to store an\n * OWM `label [dx, dy]` offset (integers, clamped to ±200px) as ONE undoable command. A press without\n * movement selects the owner; double-click still edits the name.\n *\n * Reset paths: Alt+double-click on a label, dropping it back onto its default slot, or\n * `resetLabelOffset(shape, role)`.\n */\nexport default class WardleyLabelDragging {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"elementRegistry\",\n \"wardleyModeling\",\n \"selection\",\n \"evolutionGrid\",\n \"injector\",\n ];\n\n private active: LabelDrag | null = null;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly modeling: WardleyModeling,\n private readonly selection: Selection,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n ) {\n const container = canvas.getContainer();\n this.outerContainer().classList.add(ARMED_CLASS);\n // Capture phase: diagram-js must neither start a move/lasso/pan nor open the label editor.\n container.addEventListener(\"mousedown\", this.onMouseDown, true);\n container.addEventListener(\"dblclick\", this.onDoubleClick, true);\n // Deleting the owner mid-drag (Delete/Backspace, an external import) ends the gesture, or the\n // release would put an invisible offset change on the undo stack.\n eventBus.on(\"shape.remove\", ({ element }: { element: unknown }) => {\n if (this.active?.shape === element) this.cancel();\n });\n eventBus.on(\"diagram.destroy\", () => {\n this.cancel();\n container.removeEventListener(\"mousedown\", this.onMouseDown, true);\n container.removeEventListener(\"dblclick\", this.onDoubleClick, true);\n });\n }\n\n /** Puts a label back into its default slot (undoable). */\n resetLabelOffset(shape: WardleyShape, role: LabelRole = \"name\"): void {\n if (role === \"movement\") {\n if (shape.movement?.labelOffset) this.commitMovementOffset(shape, undefined);\n return;\n }\n if (shape.labelOffset) this.commitNameOffset(shape, undefined);\n }\n\n private readonly onMouseDown = (event: MouseEvent): void => {\n if (event.button !== 0 || this.outerContainer().classList.contains(\"wardley-draw-mode\")) return;\n if (isReadOnly(this.injector)) return;\n const target = this.labelTarget(event);\n if (!target) return;\n event.stopPropagation();\n event.preventDefault();\n // preventDefault keeps focus where it is; commit an open inline edit like any other click would,\n // and take focus to the canvas so Delete/Undo act on the map, not on a focused host input.\n const focused = document.activeElement;\n if (focused instanceof HTMLElement && this.outerContainer().contains(focused)) focused.blur();\n focusCanvasWithoutRing(this.canvas);\n\n const { shape, role, handle } = target;\n const startOffset = this.renderedOffset(shape, role, handle);\n this.active = {\n shape,\n role,\n startClient: { x: event.clientX, y: event.clientY },\n startOffset,\n homeOffset: this.defaultOffset(shape, role, handle),\n originalOffset: shape.labelOffset,\n originalMovement: shape.movement,\n zoom: this.canvas.zoom(),\n dragging: false,\n };\n document.addEventListener(\"mousemove\", this.onMouseMove);\n document.addEventListener(\"mouseup\", this.onMouseUp);\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n };\n\n private readonly onMouseMove = (event: MouseEvent): void => {\n const drag = this.active;\n if (!drag) return;\n const deltaX = event.clientX - drag.startClient.x;\n const deltaY = event.clientY - drag.startClient.y;\n if (!drag.dragging) {\n if (Math.hypot(deltaX, deltaY) < DRAG_THRESHOLD) return;\n drag.dragging = true;\n this.outerContainer().classList.add(DRAGGING_CLASS);\n }\n drag.latest = {\n dx: Math.round(drag.startOffset.dx + deltaX / drag.zoom),\n dy: Math.round(drag.startOffset.dy + deltaY / drag.zoom),\n };\n this.preview(drag, drag.latest);\n };\n\n private readonly onMouseUp = (): void => {\n const drag = this.active;\n if (!drag) return;\n this.finish();\n // A plain press falls through to diagram-js's own click selection (incl. Shift to add).\n if (!drag.dragging || !drag.latest) return;\n if (this.elementRegistry.get(drag.shape.id) !== drag.shape) return;\n const next = this.snapHome(drag.latest, drag.homeOffset);\n const previous =\n drag.role === \"name\" ? drag.originalOffset : drag.originalMovement?.labelOffset;\n if (!sameOffset(next, previous)) {\n if (drag.role === \"name\") this.commitNameOffset(drag.shape, next);\n else this.commitMovementOffset(drag.shape, next);\n }\n this.suppressNextClick();\n this.selection.select(drag.shape);\n };\n\n /** The click that ends a drag would toggle the owner's selection off again. */\n private suppressNextClick(): void {\n const container = this.canvas.getContainer();\n const swallow = (event: MouseEvent) => event.stopPropagation();\n container.addEventListener(\"click\", swallow, { capture: true, once: true });\n setTimeout(() => container.removeEventListener(\"click\", swallow, true), 0);\n }\n\n private readonly onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\" || !this.active) return;\n event.stopPropagation();\n this.cancel();\n };\n\n private readonly onDoubleClick = (event: MouseEvent): void => {\n if (!event.altKey || isReadOnly(this.injector)) return;\n const target = this.labelTarget(event);\n if (!target) return;\n event.stopPropagation();\n event.preventDefault();\n this.resetLabelOffset(target.shape, target.role);\n };\n\n private cancel(): void {\n if (this.active) this.finish();\n }\n\n /** Ends the gesture and restores the pre-drag state (commits run through the command stack). */\n private finish(): void {\n const drag = this.active;\n if (!drag) return;\n this.active = null;\n document.removeEventListener(\"mousemove\", this.onMouseMove);\n document.removeEventListener(\"mouseup\", this.onMouseUp);\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.outerContainer().classList.remove(DRAGGING_CLASS);\n if (drag.dragging) {\n if (drag.originalOffset) drag.shape.labelOffset = drag.originalOffset;\n else delete drag.shape.labelOffset;\n if (drag.originalMovement) drag.shape.movement = drag.originalMovement;\n this.eventBus.fire(\"element.changed\", { element: drag.shape });\n }\n }\n\n private preview(drag: LabelDrag, offset: LabelOffset): void {\n if (drag.role === \"name\") drag.shape.labelOffset = offset;\n else if (drag.originalMovement) {\n drag.shape.movement = { ...drag.originalMovement, labelOffset: offset };\n }\n this.eventBus.fire(\"element.changed\", { element: drag.shape });\n }\n\n private snapHome(offset: LabelOffset, home: LabelOffset): LabelOffset | undefined {\n const nearHome =\n Math.abs(offset.dx - home.dx) <= SNAP_HOME_DISTANCE &&\n Math.abs(offset.dy - home.dy) <= SNAP_HOME_DISTANCE;\n return nearHome ? undefined : normalizeLabelOffset(offset.dx, offset.dy);\n }\n\n private commitNameOffset(shape: WardleyShape, offset: LabelOffset | undefined): void {\n const properties: Record<string, unknown> = { labelOffset: offset };\n // The exporter falls back to the imported element's offset; clear it there too, or a reset\n // would come back on the next export.\n const imported = shape.businessObject as\n (MapElement & { labelOffset?: LabelOffset }) | undefined;\n if (!offset && imported?.labelOffset) {\n const { labelOffset: _clearedOffset, ...rest } = imported;\n properties[\"businessObject\"] = rest;\n }\n this.modeling.updateProperties(shape, properties);\n }\n\n private commitMovementOffset(shape: WardleyShape, offset: LabelOffset | undefined): void {\n const movement = shape.movement;\n if (!movement) return;\n const { labelOffset: _previousOffset, ...rest } = movement;\n this.modeling.updateProperties(shape, {\n movement: offset ? { ...rest, labelOffset: offset } : rest,\n });\n }\n\n /**\n * The offset that reproduces the label exactly where it is drawn now, in the OWM frame (relative to\n * the canonical slot). Automatic placements (left of the circle, inertia shift) are converted so\n * the first drag doesn't make the label jump.\n */\n private renderedOffset(\n shape: WardleyShape,\n role: LabelRole,\n handle: SVGTextElement,\n ): LabelOffset {\n if (role === \"movement\" && shape.movement?.labelOffset) return shape.movement.labelOffset;\n if (role === \"name\" && shape.labelOffset) return shape.labelOffset;\n return this.defaultOffset(shape, role, handle);\n }\n\n /** The offset (OWM frame) of the label's automatic, offset-free position. */\n private defaultOffset(shape: WardleyShape, role: LabelRole, handle: SVGTextElement): LabelOffset {\n if (shape.wardleyType === \"anchor\") return { dx: 0, dy: 0 };\n const deltaX = movementDeltaX(shape, this.grid);\n if (role === \"movement\") {\n if (deltaX === undefined) return { dx: 0, dy: 0 };\n const placement = movementLabelPlacement(undefined, deltaX);\n return offsetFromPlacement(placement, movementLabelSlot(deltaX), handle, shape);\n }\n const withoutOffset = { ...shape, labelOffset: undefined } as unknown as WardleyShape;\n const placement = componentLabelPlacement(withoutOffset, deltaX);\n return offsetFromPlacement(placement, componentLabelSlot(), handle, shape);\n }\n\n private labelTarget(\n event: MouseEvent,\n ): { shape: WardleyShape; role: LabelRole; handle: SVGTextElement } | null {\n const handle = (event.target as Element | null)?.closest?.(`.${LABEL_HANDLE_CLASS}`);\n if (!(handle instanceof SVGTextElement)) return null;\n const id = handle.closest(\"[data-element-id]\")?.getAttribute(\"data-element-id\");\n const shape = id ? this.elementRegistry.get(id) : undefined;\n if (!isWardleyShape(shape)) return null;\n const role: LabelRole =\n handle.getAttribute(LABEL_ROLE_ATTRIBUTE) === \"movement\" ? \"movement\" : \"name\";\n if (role === \"movement\" && !shape.movement) return null;\n if (role === \"name\" && shape.wardleyType !== \"component\" && shape.wardleyType !== \"anchor\") {\n return null;\n }\n return { shape, role, handle };\n }\n\n /** The `.wardley-container` the viewer mounts into (diagram-js renders into a child of it). */\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n}\n\n/**\n * Explicit offsets render start-anchored at `slot + offset`, so an end-anchored automatic label is\n * converted via its measured left edge (only possible in the browser, hence not in the renderer).\n */\nfunction offsetFromPlacement(\n placement: LabelPlacement,\n slot: { x: number; y: number },\n handle: SVGTextElement,\n shape: WardleyShape,\n): LabelOffset {\n const centerX = shape.width / 2;\n const left = placement.anchor === \"end\" ? handle.getBBox().x - centerX : placement.x;\n return { dx: Math.round(left - slot.x), dy: Math.round(placement.y - slot.y) };\n}\n\nfunction sameOffset(a: LabelOffset | undefined, b: LabelOffset | undefined): boolean {\n if (!a || !b) return !a && !b;\n return a.dx === b.dx && a.dy === b.dy;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLabelDragging from \"./WardleyLabelDragging.js\";\n\n/** OWM-style draggable labels persisted as `label [dx, dy]` (undoable). */\nexport const wardleyLabelDragModule: ModuleDeclaration = {\n __init__: [\"wardleyLabelDragging\"],\n wardleyLabelDragging: [\"type\", WardleyLabelDragging],\n};\n\nexport { default as WardleyLabelDragging, type LabelRole } from \"./WardleyLabelDragging.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type WardleyLabelEditing from \"./label-editing/WardleyLabelEditing.js\";\nimport type WardleyLinkEditing from \"./link-editing/WardleyLinkEditing.js\";\n\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport MoveModule from \"diagram-js/lib/features/move\";\nimport AutoScrollModule from \"diagram-js/lib/features/auto-scroll\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport ContextPadModule from \"diagram-js/lib/features/context-pad\";\nimport PaletteModule from \"diagram-js/lib/features/palette\";\nimport RulesModule from \"diagram-js/lib/features/rules\";\nimport OutlineModule from \"diagram-js/lib/features/outline\";\nimport ResizeModule from \"diagram-js/lib/features/resize\";\nimport PopupMenuModule from \"diagram-js/lib/features/popup-menu\";\n\nimport { NavigatedViewer } from \"./NavigatedViewer.js\";\nimport { wardleyModelingModule } from \"./modeling/index.js\";\nimport { wardleyLayoutModule } from \"./layout/index.js\";\nimport { wardleyLassoModule } from \"./lasso/index.js\";\nimport { wardleyRulesModule } from \"./rules/index.js\";\nimport { evolutionConstraintModule } from \"./evolution-grid/index.js\";\nimport { stageSnappingModule } from \"./snapping/index.js\";\nimport { wardleyPaletteModule } from \"./palette/index.js\";\nimport { wardleyContextPadModule } from \"./context-pad/index.js\";\nimport { labelEditingModule } from \"./label-editing/index.js\";\nimport { wardleyKeyboardModule } from \"./keyboard/index.js\";\nimport { wardleyEvolveModule } from \"./evolve/index.js\";\nimport { wardleyPopupModule } from \"./popup/index.js\";\nimport { wardleyAppendModule } from \"./append/index.js\";\nimport { wardleyColorPickerModule } from \"./color-picker/index.js\";\nimport { wardleyOrderingModule } from \"./ordering/index.js\";\nimport { wardleyDrawToolModule } from \"./draw-tool/index.js\";\nimport { pipelineGroupModule } from \"./pipeline/index.js\";\nimport { ResizeAwareAutoScroll, mapResizeModule } from \"./map-resize/index.js\";\nimport { linkEditingModule } from \"./link-editing/index.js\";\nimport { wardleyLabelDragModule } from \"./label-drag/index.js\";\nimport { canvasAccessibilityModule } from \"./a11y/index.js\";\nimport { readOnlyModule } from \"./read-only/index.js\";\n\n/** Replaces diagram-js AutoScroll: no scrolling under a map-resize drag. */\nconst resizeAwareAutoScrollModule: ModuleDeclaration = {\n autoScroll: [\"type\", ResizeAwareAutoScroll],\n};\n\n/**\n * Full Wardley editor: palette/create, move with EvolutionConstraint + stage snapping, connect with\n * rules, context pad, inline label editing, undo/redo (concept doc §6.1, roadmap M3).\n */\nexport class Modeler extends NavigatedViewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n ModelingModule,\n wardleyLayoutModule,\n RulesModule,\n MoveModule,\n // Default 20px bands on every side; a larger top band would scroll as soon as an element is\n // dragged out of the top-centred palette.\n AutoScrollModule,\n resizeAwareAutoScrollModule,\n CreateModule,\n ConnectModule,\n ContextPadModule,\n PaletteModule,\n OutlineModule,\n ResizeModule,\n PopupMenuModule,\n wardleyModelingModule,\n wardleyRulesModule,\n evolutionConstraintModule,\n stageSnappingModule,\n wardleyPaletteModule,\n wardleyContextPadModule,\n labelEditingModule,\n wardleyKeyboardModule,\n wardleyEvolveModule,\n wardleyPopupModule,\n wardleyAppendModule,\n wardleyColorPickerModule,\n wardleyLassoModule,\n wardleyOrderingModule,\n wardleyDrawToolModule,\n pipelineGroupModule,\n mapResizeModule,\n linkEditingModule,\n canvasAccessibilityModule,\n wardleyLabelDragModule,\n readOnlyModule,\n ];\n }\n\n /**\n * Saves any open inline editor (name, note, link annotation, flow value, link address). Call it\n * before saving or exporting from a keyboard shortcut, which does not take focus off the editor.\n */\n commitPendingEdits(): void {\n this.get<WardleyLabelEditing>(\"wardleyLabelEditing\").commitActiveEdit();\n this.get<WardleyLinkEditing>(\"wardleyLinkEditing\").commitActiveEdit();\n }\n\n undo(): void {\n this.get<CommandStack>(\"commandStack\").undo();\n }\n\n redo(): void {\n this.get<CommandStack>(\"commandStack\").redo();\n }\n\n canUndo(): boolean {\n return this.get<CommandStack>(\"commandStack\").canUndo();\n }\n\n canRedo(): boolean {\n return this.get<CommandStack>(\"commandStack\").canRedo();\n }\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport type { Modeler } from \"./Modeler.js\";\nimport type WardleyLabelEditing from \"./label-editing/WardleyLabelEditing.js\";\nimport type { FieldSelection } from \"./label-editing/WardleyLabelEditing.js\";\nimport type WardleyLinkEditing from \"./link-editing/WardleyLinkEditing.js\";\nimport { isWardleyConnection, isWardleyShape, type WardleyConnection } from \"./model/di-types.js\";\nimport { focusCanvasWithoutRing } from \"./a11y/index.js\";\nimport { readBackIds } from \"@miragon/wardley-dsl\";\n\n/**\n * A connection by what it joins: dependency ids are positional (`dep_3`), so after a re-import the\n * same id may name a different link.\n */\ninterface ConnectionKey {\n sourceId: string;\n targetId: string;\n wardleyType: string;\n}\n\ntype OpenEdit =\n | { kind: \"name\"; elementId: string; value: string; selection?: FieldSelection }\n | { kind: \"connection\"; key: ConnectionKey; value: string; selection?: FieldSelection }\n | { kind: \"link\"; elementId: string; value: string; selection?: FieldSelection };\n\n/**\n * What the user had selected and was typing, put aside across a re-import. Element ids are the\n * ids the document gives the elements (`readBackIds`): an element created or renamed on the\n * canvas holds another id until the text is read again, and a re-import reads it.\n */\nexport interface EditorState {\n readonly shapeIds: readonly string[];\n readonly connections: readonly ConnectionKey[];\n readonly edit?: OpenEdit;\n /** The canvas's own id of each element above, by its document id, for an import that failed. */\n readonly canvasIds?: ReadonlyMap<string, string>;\n}\n\nexport interface RestoreOptions {\n /** The re-import was rejected: the canvas still holds the elements under their own ids. */\n importRejected?: boolean;\n}\n\n/** Document id by canvas id (identity where the map cannot be read). */\nfunction documentIdsOf(modeler: Modeler): (canvasId: string) => string {\n let ids: ReadonlyMap<string, string>;\n try {\n ids = readBackIds(modeler.exportMap());\n } catch {\n ids = new Map();\n }\n return (canvasId) => ids.get(canvasId) ?? canvasId;\n}\n\nfunction keyOf(\n connection: WardleyConnection,\n documentId: (canvasId: string) => string = (id) => id,\n): ConnectionKey {\n return {\n sourceId: documentId(connection.source?.id ?? \"\"),\n targetId: documentId(connection.target?.id ?? \"\"),\n wardleyType: connection.wardleyType,\n };\n}\n\nfunction findConnection(\n registry: ElementRegistry,\n key: ConnectionKey,\n): WardleyConnection | undefined {\n return registry.find(\n (element) =>\n isWardleyConnection(element) &&\n element.source?.id === key.sourceId &&\n element.target?.id === key.targetId &&\n element.wardleyType === key.wardleyType,\n ) as WardleyConnection | undefined;\n}\n\n/**\n * Captures the selection and any open inline editor, and closes the editor without saving (a save\n * would push a command onto a stack the import is about to clear). Call before re-importing a map\n * that changed outside the editor, then `restoreEditorState` afterwards.\n */\nexport function setAsideEditorState(modeler: Modeler): EditorState {\n const selected = modeler.get<Selection>(\"selection\").get() as unknown[];\n const registry = modeler.get<ElementRegistry>(\"elementRegistry\");\n const labelEditing = modeler.get<WardleyLabelEditing>(\"wardleyLabelEditing\");\n const linkEditing = modeler.get<WardleyLinkEditing>(\"wardleyLinkEditing\");\n const canvasIds = new Map<string, string>();\n const readBack = documentIdsOf(modeler);\n const documentId = (canvasId: string) => {\n const id = readBack(canvasId);\n canvasIds.set(id, canvasId);\n return id;\n };\n\n let edit: OpenEdit | undefined;\n const nameEdit = labelEditing.getActiveEdit();\n const linkEdit = linkEditing.getActiveEdit();\n if (nameEdit?.connection) {\n const connection = registry.get(nameEdit.elementId);\n if (isWardleyConnection(connection)) {\n edit = {\n kind: \"connection\",\n key: keyOf(connection, documentId),\n value: nameEdit.value,\n ...(nameEdit.selection ? { selection: nameEdit.selection } : {}),\n };\n }\n } else if (nameEdit) {\n edit = {\n kind: \"name\",\n elementId: documentId(nameEdit.elementId),\n value: nameEdit.value,\n ...(nameEdit.selection ? { selection: nameEdit.selection } : {}),\n };\n } else if (linkEdit) {\n edit = {\n kind: \"link\",\n elementId: documentId(linkEdit.elementId),\n value: linkEdit.value,\n selection: linkEdit.selection,\n };\n }\n labelEditing.cancel();\n linkEditing.cancel();\n\n return {\n shapeIds: selected.filter(isWardleyShape).map((shape) => documentId(shape.id)),\n connections: selected\n .filter(isWardleyConnection)\n .map((connection) => keyOf(connection, documentId)),\n ...(edit ? { edit } : {}),\n canvasIds,\n };\n}\n\n/**\n * Brings back what `setAsideEditorState` captured, for the elements that still exist: names are\n * stable ids (`cmp_tea`), connections are matched by their ends. An editor whose element is gone\n * leaves keyboard focus on the canvas rather than on the page.\n */\nexport function restoreEditorState(\n modeler: Modeler,\n state: EditorState,\n options: RestoreOptions = {},\n): void {\n const registry = modeler.get<ElementRegistry>(\"elementRegistry\");\n const canvasId = (id: string) => (options.importRejected ? (state.canvasIds?.get(id) ?? id) : id);\n const lookup = (id: string) => registry.get(canvasId(id));\n const connectionOf = (key: ConnectionKey) =>\n findConnection(registry, {\n ...key,\n sourceId: canvasId(key.sourceId),\n targetId: canvasId(key.targetId),\n });\n const shapes = state.shapeIds.map(lookup).filter(isWardleyShape);\n const connections = state.connections\n .map(connectionOf)\n .filter((connection): connection is WardleyConnection => connection !== undefined);\n const reselected = [...shapes, ...connections] as unknown as Element[];\n if (reselected.length) modeler.get<Selection>(\"selection\").select(reselected);\n\n const { edit } = state;\n if (!edit) return;\n const labelEditing = modeler.get<WardleyLabelEditing>(\"wardleyLabelEditing\");\n const restored = (() => {\n if (edit.kind === \"connection\") {\n const connection = connectionOf(edit.key);\n if (!connection) return false;\n labelEditing.activateConnection(connection, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n return true;\n }\n const shape = lookup(edit.elementId);\n if (!isWardleyShape(shape)) return false;\n if (edit.kind === \"link\") {\n modeler.get<WardleyLinkEditing>(\"wardleyLinkEditing\").activate(shape, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n } else {\n labelEditing.activate(shape, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n }\n return true;\n })();\n if (!restored) focusCanvasWithoutRing(modeler.get<Canvas>(\"canvas\"));\n}\n","import {\n MODELER_API_VERSION,\n type CollaborativeModeler,\n type CollaborativeModelerOptions,\n type ElementBounds,\n type ElementInfo,\n type ElementsSurface,\n type ImportResult,\n type ModelerMeta,\n} from \"@miragon/modeler-api\";\nimport { readBackIds, serializeDSL } from \"@miragon/wardley-dsl\";\nimport type { ModuleDeclaration } from \"didi\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { Modeler } from \"../Modeler.js\";\nimport { NavigatedViewer } from \"../NavigatedViewer.js\";\nimport type { WardleyViewerOptions } from \"../WardleyBaseViewer.js\";\nimport { restoreEditorState, setAsideEditorState, type EditorState } from \"../editor-state.js\";\nimport type { LivePreview } from \"../live-preview/index.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type { PanConstraint } from \"../pan-constraint/index.js\";\n\n/** Stable notation id in `meta.notation` of the collaborative-modeler contract. */\nexport const WARDLEY_NOTATION = \"wardley\";\n\n/**\n * The contract's factory options (`freeArea`, `fitOnImport`, `undoRedoKeys`, see\n * `WardleyViewerOptions`) plus the renderer's own. The viewer ignores `undoRedoKeys`.\n */\nexport interface CollaborativeWardleyOptions extends CollaborativeModelerOptions {\n /** Appended to the renderer's own modules (e.g. a host's chrome module). */\n additionalModules?: ModuleDeclaration[] | undefined;\n}\n\n/** The contract's element surface, with the optional `bounds` of contract 1.2 always present. */\nexport interface WardleyElementsSurface extends ElementsSurface {\n bounds(id: string): ElementBounds | undefined;\n}\n\n/**\n * The contract surface, with the optional `contentBounds` of contract 1.3 always present, plus the\n * wrapped diagram for host-specific wiring.\n */\nexport interface CollaborativeWardleyModeler extends CollaborativeModeler {\n readonly elements: WardleyElementsSurface;\n readonly diagram: Modeler | NavigatedViewer;\n contentBounds(): ElementBounds | undefined;\n}\n\ninterface ViewState {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * The named elements: components, anchors, pipelines, submaps and accelerators. Their names are\n * unique on a map, so the id the document derives from a name survives edits to other elements.\n * Notes, annotations, regions and drawings may repeat their text, number or kind, and the parser\n * tells repeats apart by line order, so their ids would move to another element.\n */\nconst ADDRESSABLE_TYPES: ReadonlySet<string> = new Set([\n \"component\",\n \"anchor\",\n \"pipeline\",\n \"submap\",\n \"accelerator\",\n]);\n\nfunction isAddressable(element: unknown): element is WardleyShape {\n return isWardleyShape(element) && ADDRESSABLE_TYPES.has(element.wardleyType);\n}\n\n/** The editing mount (`meta.editable: true`) of the collaborative-modeler contract. */\nexport function createCollaborativeModeler(\n options: CollaborativeWardleyOptions = {},\n): CollaborativeWardleyModeler {\n return collaborative(\n new Modeler({\n ...diagramOptions(options),\n undoRedoKeys: options.undoRedoKeys,\n }),\n true,\n );\n}\n\n/** The read-only mount (`meta.editable: false`): imports, exports and reveals, never edits. */\nexport function createCollaborativeViewer(\n options: CollaborativeWardleyOptions = {},\n): CollaborativeWardleyModeler {\n return collaborative(new NavigatedViewer(diagramOptions(options)), false);\n}\n\nfunction diagramOptions(options: CollaborativeWardleyOptions): WardleyViewerOptions {\n return {\n width: \"100%\",\n height: \"100%\",\n additionalModules: options.additionalModules ?? [],\n freeArea: options.freeArea,\n fitOnImport: options.fitOnImport,\n };\n}\n\n/**\n * The document ids of the canvas's elements and back, read once per content change: an element\n * created or renamed on the canvas keeps its canvas id until the text is read again.\n */\nfunction documentIds(diagram: Modeler | NavigatedViewer, eventBus: EventBus) {\n let byCanvasId: Map<string, string> | undefined;\n let byDocumentId: Map<string, string> | undefined;\n eventBus.on(\n [\"elements.changed\", \"import.done\", \"diagram.clear\", \"commandStack.changed\"],\n () => (byCanvasId = byDocumentId = undefined),\n );\n const read = () => {\n if (!byCanvasId) {\n try {\n byCanvasId = readBackIds(diagram.exportMap());\n } catch {\n byCanvasId = new Map();\n }\n byDocumentId = new Map([...byCanvasId].map(([canvasId, id]) => [id, canvasId]));\n }\n return { byCanvasId, byDocumentId: byDocumentId! };\n };\n return {\n of: (canvasId: string) => read().byCanvasId.get(canvasId) ?? canvasId,\n canvasIdOf: (documentId: string) => read().byDocumentId.get(documentId) ?? documentId,\n };\n}\n\nfunction collaborative(\n diagram: Modeler | NavigatedViewer,\n editable: boolean,\n): CollaborativeWardleyModeler {\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const canvas = diagram.get<Canvas>(\"canvas\");\n const elementRegistry = diagram.get<ElementRegistry>(\"elementRegistry\");\n const selection = diagram.get<Selection>(\"selection\");\n const panConstraint = diagram.get<PanConstraint>(\"panConstraint\");\n const ids = documentIds(diagram, eventBus);\n const livePreview = editable ? diagram.get<LivePreview>(\"wardleyLivePreview\") : undefined;\n const contentListeners = new Set<() => void>();\n let importsRunning = 0;\n let imported = false;\n let destroyed = false;\n let lastExport = \"\";\n\n const meta: ModelerMeta = {\n notation: WARDLEY_NOTATION,\n apiVersion: MODELER_API_VERSION,\n editable,\n };\n\n // The command stack is the one channel of every user-visible change, config edits included;\n // an import clears it, which is housekeeping, not a change (L1, L3).\n if (editable) {\n eventBus.on(\"commandStack.changed\", () => {\n if (importsRunning > 0) return;\n for (const listener of [...contentListeners]) listener();\n });\n }\n\n const documentIdsOf = (elements: readonly unknown[]): string[] =>\n elements.filter(isAddressable).map((element) => ids.of(element.id));\n\n const elementInfo = (element: WardleyShape): ElementInfo => {\n const id = ids.of(element.id);\n return element.wardleyLabel ? { id, name: element.wardleyLabel } : { id };\n };\n\n /** The element `list()` reports under `id`, read from the live canvas. */\n const listedElement = (id: string): WardleyShape | undefined => {\n if (destroyed) return undefined;\n const element: unknown = elementRegistry.get(ids.canvasIdOf(id));\n return isAddressable(element) && ids.of(element.id) === id ? element : undefined;\n };\n\n const elements: WardleyElementsSurface = {\n list: () =>\n destroyed\n ? []\n : (elementRegistry.getAll() as unknown[]).filter(isAddressable).map(elementInfo),\n reveal(id) {\n if (destroyed) return false;\n const element = elementRegistry.get(ids.canvasIdOf(id));\n if (!isAddressable(element)) return false;\n selection.select(element as unknown as Element);\n canvas.scrollToElement(element as unknown as Element);\n return true;\n },\n selection: () => (destroyed ? [] : documentIdsOf(selection.get())),\n onSelection(callback) {\n const listener = (event: unknown) =>\n callback(documentIdsOf((event as { newSelection?: unknown[] }).newSelection ?? []));\n eventBus.on(\"selection.changed\", listener);\n return () => eventBus.off(\"selection.changed\", listener);\n },\n bounds(id) {\n const element = listedElement(id);\n if (!element) return undefined;\n const { x, y, width, height } = element;\n return { x, y, width, height };\n },\n };\n\n // Never a live preview: a host saves the export at any moment, also during a plot-resize drag.\n const committedText = (): string => {\n const committed = livePreview?.committedMap();\n return committed ? serializeDSL(committed) : diagram.exportDSL();\n };\n\n async function importText(text: string): Promise<ImportResult> {\n if (destroyed) throw new Error(\"The modeler was destroyed.\");\n importsRunning += 1;\n // An open label editor neither commits during the import nor loses what was typed (L1): it\n // is taken down and reopened on the element with the same id.\n const editorState: EditorState | undefined =\n editable && imported ? setAsideEditorState(diagram as Modeler) : undefined;\n try {\n const { warnings } = await diagram.importDSL(text);\n imported = true;\n if (editorState) restoreEditorState(diagram as Modeler, editorState);\n return { warnings: warnings.map((warning) => warning.message) };\n } catch (error) {\n if (editorState)\n restoreEditorState(diagram as Modeler, editorState, { importRejected: true });\n throw error;\n } finally {\n importsRunning -= 1;\n }\n }\n\n return {\n meta,\n elements,\n diagram,\n attachTo(host) {\n diagram.attachTo(host as HTMLElement);\n },\n importText,\n exportText() {\n // Asking a destroyed diagram would build a new one on the detached container.\n if (destroyed) return lastExport;\n return committedText();\n },\n onContentChanged(callback) {\n if (!editable) return () => undefined;\n contentListeners.add(callback);\n return () => contentListeners.delete(callback);\n },\n getViewState(): ViewState | undefined {\n if (destroyed) return undefined;\n try {\n const { x, y, width, height } = canvas.viewbox();\n const state = { x, y, width, height };\n return isViewState(state) ? state : undefined;\n } catch {\n return undefined;\n }\n },\n setViewState(state) {\n if (destroyed || !isViewState(state)) return;\n canvas.viewbox({ x: state.x, y: state.y, width: state.width, height: state.height });\n },\n // Every map draws its plot, also one without elements, so there is always a box to fit (before\n // the first import the default plot's). A host fits to the box the pan constraint keeps in view.\n contentBounds() {\n if (destroyed) return undefined;\n const { x, y, width, height } = panConstraint.contentBounds();\n return { x, y, width, height };\n },\n destroy() {\n if (destroyed) return;\n try {\n lastExport = committedText();\n } catch {\n lastExport = \"\";\n }\n destroyed = true;\n contentListeners.clear();\n diagram.destroy();\n },\n };\n}\n\nfunction isViewState(state: unknown): state is ViewState {\n if (typeof state !== \"object\" || state === null) return false;\n const { x, y, width, height } = state as Record<string, unknown>;\n return (\n isFiniteNumber(x) &&\n isFiniteNumber(y) &&\n isFiniteNumber(width) &&\n isFiniteNumber(height) &&\n width > 0 &&\n height > 0\n );\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n","/*\n * The map's entries of the chrome menu (guide §5.4), the same in every host. The types mirror\n * the menu groups of `@miragon/modeler-shell` structurally, so an app hands the result to the\n * shell as it is while the renderer never imports the shell.\n */\n\n/** The icons the guide gives these entries (guide §5.14, the shell's common set). */\nexport type MapMenuIcon = \"file-image\" | \"file-code-corner\" | \"keyboard\";\n\ninterface MapMenuItem {\n readonly id: string;\n readonly label: string;\n readonly icon?: MapMenuIcon;\n readonly keepEnabledWhenReadOnly?: boolean;\n}\n\nexport interface MapMenuAction extends MapMenuItem {\n readonly kind: \"action\";\n readonly shortcut?: string;\n onSelect(): void;\n}\n\nexport interface MapMenuDialog extends MapMenuItem {\n readonly kind: \"dialog\";\n /** The chip of a key that opens the dialog as well, e.g. \"?\". */\n readonly shortcut?: string;\n onSelect(): void;\n}\n\nexport type MapMenuEntry = MapMenuAction | MapMenuDialog;\n\nexport interface MapMenu {\n readonly model: readonly MapMenuEntry[];\n readonly export: readonly MapMenuEntry[];\n readonly help: readonly MapMenuEntry[];\n}\n\nexport interface MapExport {\n onSelect(): void;\n /** The chip of an app key that runs the same export, e.g. \"⌘S\". */\n readonly shortcut?: string | undefined;\n}\n\n/**\n * The exports a host offers, in the guide's order: PNG first (the more frequent target), then\n * SVG, then the variants, then further formats. Only the web app adds the map file itself, which\n * in VS Code is the document.\n */\nexport interface MapExports {\n readonly png: MapExport;\n readonly svg: MapExport;\n readonly transparentPng?: MapExport | undefined;\n readonly json?: MapExport | undefined;\n readonly wmap?: MapExport | undefined;\n}\n\nexport interface MapMenuActions {\n /** Opens the \"Map title…\" dialog; without it the Model group has no title entry. */\n mapTitle?: (() => void) | undefined;\n /** Opens the \"Map size…\" popover. */\n mapSize(): void;\n /** Opens the \"X-axis labels…\" popover. */\n axisLabels(): void;\n readonly exports: MapExports;\n showKeyboardShortcuts(): void;\n /** The chip of a key the host binds to the shortcuts dialog as well, e.g. \"?\" in the web app. */\n readonly shortcutsKey?: string | undefined;\n}\n\n/** The labels of the export entries, also used by the hosts' commands and notifications. */\nexport const EXPORT_LABELS = {\n png: \"Export as PNG\",\n svg: \"Export as SVG\",\n transparentPng: \"Export as PNG (4×, transparent)\",\n json: \"Export as JSON\",\n wmap: \"Export as .wmap\",\n} as const;\n\nfunction exportEntry(\n id: string,\n label: string,\n action: MapExport,\n icon?: MapMenuIcon,\n): MapMenuAction {\n return {\n kind: \"action\",\n id,\n label,\n ...(icon ? { icon } : {}),\n ...(action.shortcut ? { shortcut: action.shortcut } : {}),\n onSelect: () => action.onSelect(),\n };\n}\n\nfunction exportEntries(exports: MapExports): MapMenuAction[] {\n const entries = [\n exportEntry(\"export-png\", EXPORT_LABELS.png, exports.png, \"file-image\"),\n exportEntry(\"export-svg\", EXPORT_LABELS.svg, exports.svg, \"file-code-corner\"),\n ];\n if (exports.transparentPng) {\n entries.push(\n exportEntry(\"export-png-transparent\", EXPORT_LABELS.transparentPng, exports.transparentPng),\n );\n }\n if (exports.json) entries.push(exportEntry(\"export-json\", EXPORT_LABELS.json, exports.json));\n if (exports.wmap) entries.push(exportEntry(\"export-wmap\", EXPORT_LABELS.wmap, exports.wmap));\n return entries;\n}\n\n/**\n * The menu groups of a map (guide §5.4): Model with the title dialog where the host offers it and\n * the two popovers (all three change the document, so a read-only canvas disables them), Export\n * with PNG first, Help with the shortcuts dialog.\n */\nexport function mapMenu(actions: MapMenuActions): MapMenu {\n const { mapTitle, shortcutsKey } = actions;\n const titleEntries: MapMenuEntry[] = mapTitle\n ? [{ kind: \"dialog\", id: \"map-title\", label: \"Map title…\", onSelect: () => mapTitle() }]\n : [];\n return {\n model: [\n ...titleEntries,\n { kind: \"dialog\", id: \"map-size\", label: \"Map size…\", onSelect: () => actions.mapSize() },\n {\n kind: \"dialog\",\n id: \"x-axis-labels\",\n label: \"X-axis labels…\",\n onSelect: () => actions.axisLabels(),\n },\n ],\n export: exportEntries(actions.exports),\n help: [\n {\n kind: \"dialog\",\n id: \"keyboard-shortcuts\",\n label: \"Keyboard shortcuts…\",\n icon: \"keyboard\",\n ...(shortcutsKey ? { shortcut: shortcutsKey } : {}),\n onSelect: () => actions.showKeyboardShortcuts(),\n },\n ],\n };\n}\n","import { EXPORT_LABELS } from \"./menu.js\";\n\n/*\n * Every shortcut and gesture of a map for the \"Keyboard shortcuts…\" dialog (guide §5.4): one\n * table per group, the keys as chips like the chrome tooltip's (guide §5.6). The chrome's texts\n * and key names come in structurally (a `@miragon/modeler-shell` handle fits), so the View rows\n * say what the zoom panel's tooltips say.\n */\n\nexport type ShortcutPlatform = \"mac\" | \"other\";\n\nexport interface ShortcutKeyNames {\n readonly ctrl: string;\n readonly shift: string;\n readonly plus: string;\n readonly minus: string;\n}\n\n/** What the shortcuts need of the chrome around the map. */\nexport interface ShortcutsChrome {\n readonly platform: ShortcutPlatform;\n /** The tool's UI language, for the percentage in \"Zoom to 100%\". */\n readonly lang: string;\n readonly messages: {\n readonly zoomIn: string;\n readonly zoomOut: string;\n zoomToActual(percent: string): string;\n readonly fit: string;\n /** The File group's \"Open…\" (the shell's `messages.openFile`); default \"Open…\". */\n readonly openFile?: string | undefined;\n readonly keyNames: ShortcutKeyNames;\n };\n}\n\n/** Keys a web app binds itself, next to the canvas's and the chrome's. */\nexport interface MapShortcutOptions {\n /**\n * Cmd/Ctrl+O opens a file, Cmd/Ctrl+S exports the .wmap file and Cmd/Ctrl+V opens OWM text or a\n * share link pasted onto the canvas: a File group comes first.\n */\n readonly fileKeys?: boolean | undefined;\n /** The key that opens the dialog itself, e.g. \"?\", listed in the View group. */\n readonly shortcutsKey?: string | undefined;\n}\n\nexport interface ShortcutRow {\n readonly action: string;\n /** Alternative keys or gestures, each shown as its own chip. */\n readonly keys: readonly string[];\n}\n\nexport interface ShortcutGroup {\n readonly title: string;\n readonly rows: readonly ShortcutRow[];\n}\n\nconst ARROWS = \"←↑→↓\";\n\nfunction percentOfActualSize(lang: string): string {\n try {\n return new Intl.NumberFormat(lang, { style: \"percent\" }).format(1);\n } catch {\n return new Intl.NumberFormat(\"en\", { style: \"percent\" }).format(1);\n }\n}\n\n/** The chips of one platform: modifier symbols on macOS, names elsewhere. */\nfunction keysOf(platform: ShortcutPlatform, names: ShortcutKeyNames) {\n if (platform === \"mac\") {\n return {\n command: (key: string) => `⌘${key}`,\n shiftCommand: (key: string) => `⌘⇧${key}`,\n shift: (what: string) => `⇧ ${what}`,\n alt: (what: string) => `⌥ ${what}`,\n zoomIn: \"⌘+\",\n zoomOut: \"⌘−\",\n zoomToActual: \"⌘0\",\n fit: \"⇧1\",\n remove: [\"⌫\"],\n enter: \"↵\",\n breakLine: \"⇧↵\",\n };\n }\n const { ctrl, shift, plus, minus } = names;\n return {\n command: (key: string) => `${ctrl}+${key}`,\n shiftCommand: (key: string) => `${ctrl}+${shift}+${key}`,\n shift: (what: string) => `${shift}+${what}`,\n alt: (what: string) => `Alt+${what}`,\n zoomIn: `${ctrl}+${plus}`,\n zoomOut: `${ctrl}+${minus}`,\n zoomToActual: `${ctrl}+0`,\n fit: `${shift}+1`,\n remove: [\"Del\", \"Backspace\"],\n enter: \"Enter\",\n breakLine: `${shift}+Enter`,\n };\n}\n\nfunction fileGroup(chrome: ShortcutsChrome, command: (key: string) => string): ShortcutGroup {\n return {\n title: \"File\",\n rows: [\n { action: chrome.messages.openFile ?? \"Open…\", keys: [command(\"O\")] },\n { action: EXPORT_LABELS.wmap, keys: [command(\"S\")] },\n { action: \"Paste OWM text or a share link\", keys: [command(\"V\")] },\n ],\n };\n}\n\n/**\n * Every shortcut of a map, grouped as guide §5.4 asks: View (the chrome's zoom keys), Edit, the\n * notation's tools and the gestures on the map itself, after the web app's File keys where it\n * binds them.\n */\nexport function mapShortcuts(\n chrome: ShortcutsChrome,\n options: MapShortcutOptions = {},\n): ShortcutGroup[] {\n const { platform, messages } = chrome;\n const keys = keysOf(platform, messages.keyNames);\n return [\n ...(options.fileKeys ? [fileGroup(chrome, keys.command)] : []),\n {\n title: \"View\",\n rows: [\n { action: messages.zoomIn, keys: [keys.zoomIn] },\n { action: messages.zoomOut, keys: [keys.zoomOut] },\n {\n action: messages.zoomToActual(percentOfActualSize(chrome.lang)),\n keys: [keys.zoomToActual],\n },\n { action: messages.fit, keys: [keys.fit] },\n ...(options.shortcutsKey\n ? [{ action: \"Keyboard shortcuts\", keys: [options.shortcutsKey] }]\n : []),\n ],\n },\n {\n title: \"Edit\",\n rows: [\n { action: \"Undo\", keys: [keys.command(\"Z\")] },\n {\n action: \"Redo\",\n keys:\n platform === \"mac\"\n ? [keys.shiftCommand(\"Z\")]\n : [keys.shiftCommand(\"Z\"), keys.command(\"Y\")],\n },\n { action: \"Rename\", keys: [\"Double-click\"] },\n { action: \"Break the line in a name\", keys: [keys.breakLine] },\n { action: \"Save a note while editing\", keys: [keys.command(keys.enter)] },\n { action: \"Copy\", keys: [keys.command(\"C\")] },\n { action: \"Paste (a click places it, Esc cancels)\", keys: [keys.command(\"V\")] },\n { action: \"Duplicate\", keys: [keys.command(\"D\")] },\n { action: \"Delete\", keys: keys.remove },\n { action: \"Move the selection\", keys: [ARROWS] },\n { action: \"Move the selection further\", keys: [keys.shift(ARROWS)] },\n { action: \"Select all\", keys: [keys.command(\"A\")] },\n { action: \"Add to the selection\", keys: [keys.shift(\"Click\")] },\n { action: \"Deselect, cancel\", keys: [\"Esc\"] },\n ],\n },\n {\n title: \"Tools\",\n rows: [\n { action: \"Component\", keys: [\"C\"] },\n { action: \"User (anchor)\", keys: [\"U\"] },\n { action: \"Note\", keys: [\"N\"] },\n { action: \"Pipeline\", keys: [\"P\"] },\n { action: \"Connect from the selected node\", keys: [\"A\"] },\n { action: \"Lasso\", keys: [\"L\"] },\n { action: \"Lasso by dragging\", keys: [keys.shift(\"Drag\")] },\n { action: \"Draw: place a point\", keys: [\"Click\"] },\n { action: \"Finish a drawing\", keys: [keys.enter, \"Double-click\"] },\n { action: \"Close a drawing\", keys: [\"Click the first point\"] },\n ],\n },\n {\n title: \"Map\",\n rows: [\n { action: \"Move a label\", keys: [\"Drag the label\"] },\n { action: \"Reset a label’s position\", keys: [keys.alt(\"Double-click\")] },\n { action: \"Resize the map\", keys: [\"Drag the right or bottom edge\"] },\n { action: \"Resize, keeping the ratio\", keys: [keys.shift(\"Drag\")] },\n { action: \"Resize without snapping\", keys: [keys.alt(\"Drag\")] },\n { action: \"Reset the map size\", keys: [\"Double-click the corner\"] },\n ],\n },\n ];\n}\n","/*! @miragon/wardley-renderer icon geometry: x. Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Derived from Feather @license MIT, Copyright (c) 2013-present Cole Bemis\n * Full notices: README.md of @miragon/wardley-renderer */\n/** Lucide `x` (lucide-static 1.59.0, ISC; derived from Feather, MIT) at the chrome size of §5.14. */\nexport const CLOSE_ICON =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>';\n\nexport function element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className: string,\n text?: string,\n): HTMLElementTagNameMap[K] {\n const created = document.createElement(tag);\n created.className = className;\n if (text !== undefined) created.textContent = text;\n return created;\n}\n\n/** Ids stay unique when two maps share a page (two webviews never do, a web page may). */\nlet nextId = 0;\nexport function uniqueId(prefix: string): string {\n nextId += 1;\n return `${prefix}-${nextId}`;\n}\n","import { CLOSE_ICON, element, uniqueId } from \"./dom.js\";\n\n/** What a dialog needs of the chrome around the map; a `@miragon/modeler-shell` handle fits. */\nexport interface DialogChrome {\n /** Where the dialog lives (the shell root), so it shares the chrome's mode and fonts. */\n readonly root: HTMLElement;\n readonly messages: { readonly close: string };\n /** The control the focus returns to once the dialog closes. */\n readonly menu: { readonly trigger: HTMLElement };\n}\n\nexport interface MapDialog {\n open(): void;\n isOpen(): boolean;\n close(): void;\n destroy(): void;\n}\n\nexport interface MapDialogParts {\n /** Class of the `<dialog>` next to `wardley-dialog`, for the dialog's own rules. */\n readonly className: string;\n readonly title: string;\n /** The parts below the header (body, footer), built once on the first open. */\n content(close: () => void): Node[];\n /** Runs before every open, while the dialog is still closed. */\n beforeOpen?(): void;\n /** Runs after every open, once the dialog shows and holds the focus. */\n afterOpen?(): void;\n /** Runs after every close, before the focus goes back. */\n afterClose?(): void;\n}\n\n/** A footer button of guide §8: primary (the confirming action), secondary or ghost. */\nexport function dialogButton(\n label: string,\n variant: \"primary\" | \"secondary\" | \"ghost\",\n): HTMLButtonElement {\n const created = element(\"button\", \"wardley-button\", label);\n created.type = \"button\";\n created.dataset[\"variant\"] = variant;\n return created;\n}\n\nfunction header(\n chrome: DialogChrome,\n title: string,\n titleId: string,\n onClose: () => void,\n): HTMLElement {\n const head = element(\"header\", \"wardley-dialog-header\");\n const heading = element(\"h3\", \"wardley-dialog-title\", title);\n heading.id = titleId;\n const close = element(\"button\", \"wardley-dialog-close\");\n close.type = \"button\";\n close.setAttribute(\"aria-label\", chrome.messages.close);\n close.innerHTML = CLOSE_ICON;\n close.addEventListener(\"click\", onClose);\n head.append(heading, close);\n return head;\n}\n\n/**\n * A dialog of the map's chrome (guide §8, \"Modeler dialogs\" of the shell's API): a native modal\n * <dialog> inside the chrome's root, so the browser keeps the focus inside it and closes it on\n * Escape. Built on the first open and kept (closed) afterwards; `destroy()` removes it. The host\n * calls it with the diagram's teardown, since the chrome removes only what it added itself.\n */\nexport function createMapDialog(chrome: DialogChrome, parts: MapDialogParts): MapDialog {\n let dialog: HTMLDialogElement | undefined;\n\n function build(): HTMLDialogElement {\n const titleId = uniqueId(`${parts.className}-title`);\n const created = element(\"dialog\", `wardley-dialog ${parts.className}`);\n created.setAttribute(\"aria-labelledby\", titleId);\n const close = () => created.close();\n const panel = element(\"div\", \"wardley-dialog-panel\");\n panel.append(header(chrome, parts.title, titleId, close), ...parts.content(close));\n created.append(panel);\n // A press that started on the panel (selecting text, then releasing outside) is no backdrop\n // click; the panel covers all of the dialog's own box, so the backdrop is the dialog itself.\n let pressedOnBackdrop = false;\n created.addEventListener(\"pointerdown\", (event) => {\n pressedOnBackdrop = event.target === created;\n });\n created.addEventListener(\"click\", (event) => {\n if (event.target === created && pressedOnBackdrop) created.close();\n pressedOnBackdrop = false;\n });\n created.addEventListener(\"close\", () => {\n parts.afterClose?.();\n if (!chrome.menu.trigger.hidden) chrome.menu.trigger.focus({ preventScroll: true });\n });\n chrome.root.append(created);\n return created;\n }\n\n return {\n open() {\n dialog ??= build();\n if (dialog.open) return;\n parts.beforeOpen?.();\n dialog.showModal();\n parts.afterOpen?.();\n },\n close() {\n dialog?.close();\n },\n isOpen: () => dialog?.open === true,\n destroy() {\n dialog?.remove();\n dialog = undefined;\n },\n };\n}\n","import { createMapDialog, type DialogChrome, type MapDialog } from \"./dialog.js\";\nimport { element, uniqueId } from \"./dom.js\";\nimport {\n mapShortcuts,\n type MapShortcutOptions,\n type ShortcutGroup,\n type ShortcutsChrome,\n} from \"./shortcuts.js\";\n\nconst DIALOG_CLASS = \"wardley-shortcuts\";\n\n/** What the dialog needs of the chrome around the map; a `@miragon/modeler-shell` handle fits. */\nexport interface ShortcutsDialogChrome extends ShortcutsChrome, DialogChrome {\n readonly messages: ShortcutsChrome[\"messages\"] & DialogChrome[\"messages\"];\n}\n\nexport type ShortcutsDialog = MapDialog;\n\nfunction shortcutTable(group: ShortcutGroup, titleId: string): HTMLElement {\n const section = element(\"section\", `${DIALOG_CLASS}-group`);\n const heading = element(\"h4\", `${DIALOG_CLASS}-group-title`, group.title);\n heading.id = titleId;\n const table = element(\"table\", `${DIALOG_CLASS}-table`);\n table.setAttribute(\"aria-labelledby\", titleId);\n const body = table.createTBody();\n for (const row of group.rows) {\n const line = body.insertRow();\n const action = element(\"th\", `${DIALOG_CLASS}-action`, row.action);\n action.scope = \"row\";\n const keys = element(\"td\", `${DIALOG_CLASS}-keys`);\n for (const key of row.keys) keys.append(element(\"kbd\", `${DIALOG_CLASS}-key`, key));\n line.append(action, keys);\n }\n section.append(heading, table);\n return section;\n}\n\n/**\n * The \"Keyboard shortcuts…\" dialog of the Help group (guide §5.4, §8): one table per group, the\n * keys as chips like the chrome tooltip's. A web app that binds keys of its own (Open…, the map\n * file's export, `?`) passes them in `options`, so the dialog lists them as well.\n */\nexport function createShortcutsDialog(\n chrome: ShortcutsDialogChrome,\n options: MapShortcutOptions = {},\n): ShortcutsDialog {\n return createMapDialog(chrome, {\n className: DIALOG_CLASS,\n title: \"Keyboard shortcuts\",\n content() {\n const body = element(\"div\", `wardley-dialog-body ${DIALOG_CLASS}-body`);\n const prefix = uniqueId(`${DIALOG_CLASS}-group`);\n body.append(\n ...mapShortcuts(chrome, options).map((group, index) =>\n shortcutTable(group, `${prefix}-${index}`),\n ),\n );\n return [body];\n },\n });\n}\n","import { DEFAULT_MAP_TITLE } from \"@miragon/wardley-schema-model\";\nimport type { Modeler } from \"../Modeler.js\";\nimport { READ_ONLY_CHANGED } from \"../read-only/index.js\";\nimport { createMapDialog, dialogButton, type DialogChrome, type MapDialog } from \"./dialog.js\";\nimport { element, uniqueId } from \"./dom.js\";\n\nexport type TitleDialogChrome = DialogChrome;\nexport type TitleDialog = MapDialog;\n\nfunction currentTitle(modeler: Modeler): string {\n return modeler.exportMap().config.title ?? DEFAULT_MAP_TITLE;\n}\n\n/**\n * The \"Map title…\" dialog of the Model group: guide §5.4 keeps form fields out of the menu, so the\n * entry opens a dialog (§8) with the title field, Cancel and Apply. Enter applies, Escape and\n * Cancel keep the title; an unchanged title writes nothing, so the map's history gets no empty\n * step. A canvas that turns read-only closes it without writing, as it locks the entry.\n */\nexport function createTitleDialog(chrome: TitleDialogChrome, modeler: Modeler): TitleDialog {\n const field = element(\"input\", \"wardley-field-input\");\n field.id = uniqueId(\"wardley-title-field\");\n field.type = \"text\";\n field.autocomplete = \"off\";\n field.spellcheck = false;\n field.maxLength = 120;\n // showModal() focuses the first focusable element, which would be the header's Close button.\n field.autofocus = true;\n\n const dialog = createMapDialog(chrome, {\n className: \"wardley-title-dialog\",\n title: \"Map title\",\n beforeOpen() {\n field.value = currentTitle(modeler);\n },\n afterOpen() {\n field.select();\n },\n content(close) {\n const form = element(\"form\", \"wardley-dialog-form\");\n form.noValidate = true;\n const body = element(\"div\", \"wardley-dialog-body\");\n const wrapper = element(\"div\", \"wardley-field\");\n const label = element(\"label\", \"wardley-field-label\", \"Title\");\n label.htmlFor = field.id;\n wrapper.append(label, field);\n body.append(wrapper);\n const footer = element(\"div\", \"wardley-dialog-footer\");\n const cancel = dialogButton(\"Cancel\", \"secondary\");\n cancel.addEventListener(\"click\", close);\n const apply = dialogButton(\"Apply\", \"primary\");\n apply.type = \"submit\";\n footer.append(cancel, apply);\n form.append(body, footer);\n form.addEventListener(\"submit\", (event) => {\n event.preventDefault();\n const title = field.value.replace(/\\s+/g, \" \").trim() || DEFAULT_MAP_TITLE;\n close();\n if (title !== currentTitle(modeler)) modeler.setTitle(title);\n });\n return [form];\n },\n });\n\n const onReadOnly = (event: unknown) => {\n if ((event as { readOnly?: boolean }).readOnly) dialog.close();\n };\n modeler.on(READ_ONLY_CHANGED, onReadOnly);\n return {\n open: () => dialog.open(),\n isOpen: () => dialog.isOpen(),\n close: () => dialog.close(),\n destroy() {\n modeler.off(READ_ONLY_CHANGED, onReadOnly);\n dialog.destroy();\n },\n };\n}\n","import type { Modeler } from \"../Modeler.js\";\nimport { READ_ONLY_CHANGED } from \"../read-only/index.js\";\nimport { element, uniqueId } from \"./dom.js\";\n\n/** What a popover needs of the chrome around the map; a `@miragon/modeler-shell` handle fits. */\nexport interface PopoverChrome {\n /** Where the popover lives (the shell root): it anchors at the dropdown's place there. */\n readonly root: HTMLElement;\n /** The control the focus returns to after Escape or Done. */\n readonly menu: { readonly trigger: HTMLElement };\n}\n\n/** Why a popover closes: the user is done, an import replaced the map, or the canvas locked. */\nexport type PopoverEnd = \"done\" | \"import\" | \"cancel\";\n\nexport interface PopoverHandle {\n open(): void;\n isOpen(): boolean;\n /** Closes as if the user were done: the previewed change becomes one edit. */\n close(): void;\n destroy(): void;\n}\n\nexport interface PopoverParts {\n readonly className: string;\n readonly title: string;\n /** Fills the body (fields) and the footer (buttons) once; `done` closes like Done. */\n build(body: HTMLElement, footer: HTMLElement, done: () => void): void;\n /** Reads the map into the fields on every open; returns the field to focus. */\n opened(): HTMLElement | undefined;\n /** Commits the preview (`done`) or drops it (`import`: the map is gone, `cancel`: revert). */\n closed(end: PopoverEnd): void;\n}\n\n/**\n * A popover of guide §5.4: a menu entry that needs the canvas preview opens it at the dropdown's\n * place, without a backdrop, as a non-modal `role=\"dialog\"` labelled by its title. Escape and a\n * click outside close it; the focus returns to the menu trigger after Escape and Done, while a\n * click outside leaves it on what was clicked.\n */\nexport function createPopover(\n chrome: PopoverChrome,\n parts: PopoverParts,\n): PopoverHandle & { end(end: PopoverEnd): void } {\n let panel: HTMLElement | undefined;\n\n const onPointerDown = (event: PointerEvent) => {\n if (panel && !panel.contains(event.target as Node)) end(\"done\");\n };\n // A click into the IDE's workbench or another frame takes the focus without a pointerdown here.\n const onWindowBlur = () => end(\"done\");\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || event.isComposing) return;\n event.preventDefault();\n event.stopPropagation();\n end(\"done\", { returnFocus: true });\n };\n\n function build(): HTMLElement {\n const titleId = uniqueId(`${parts.className}-title`);\n const created = element(\"div\", `wardley-popover ${parts.className}`);\n created.setAttribute(\"role\", \"dialog\");\n created.setAttribute(\"aria-labelledby\", titleId);\n created.hidden = true;\n const title = element(\"h2\", \"wardley-popover-title\", parts.title);\n title.id = titleId;\n const body = element(\"div\", \"wardley-popover-body\");\n const footer = element(\"div\", \"wardley-popover-footer\");\n parts.build(body, footer, () => end(\"done\", { returnFocus: true }));\n created.append(title, body, footer);\n created.addEventListener(\"keydown\", onKeyDown);\n chrome.root.append(created);\n return created;\n }\n\n function end(why: PopoverEnd, options: { returnFocus?: boolean } = {}): void {\n if (!panel || panel.hidden) return;\n panel.hidden = true;\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n window.removeEventListener(\"blur\", onWindowBlur);\n parts.closed(why);\n if (options.returnFocus && !chrome.menu.trigger.hidden) {\n chrome.menu.trigger.focus({ preventScroll: true });\n }\n }\n\n return {\n open() {\n panel ??= build();\n if (!panel.hidden) return;\n panel.hidden = false;\n const field = parts.opened();\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n window.addEventListener(\"blur\", onWindowBlur);\n field?.focus();\n if (field instanceof HTMLInputElement) field.select();\n },\n isOpen: () => panel?.hidden === false,\n close: () => end(\"done\"),\n end: (why) => end(why),\n destroy() {\n end(\"cancel\");\n panel?.remove();\n panel = undefined;\n },\n };\n}\n\n/** A labelled field of guide §8: the label above, 4px apart, an error below it when refused. */\nexport function field(\n label: string,\n control: HTMLInputElement | HTMLSelectElement,\n): { wrapper: HTMLElement; showError(message: string): void; clearError(): void } {\n const wrapper = element(\"div\", \"wardley-field\");\n const id = uniqueId(\"wardley-field\");\n const caption = element(\"label\", \"wardley-field-label\", label);\n caption.htmlFor = id;\n control.id = id;\n control.classList.add(\"wardley-field-input\");\n wrapper.append(caption, control);\n let error: HTMLElement | undefined;\n return {\n wrapper,\n showError(message) {\n if (!error) {\n error = element(\"p\", \"wardley-field-error\");\n error.id = `${id}-error`;\n error.setAttribute(\"role\", \"alert\");\n wrapper.append(error);\n }\n error.textContent = message;\n control.setAttribute(\"aria-invalid\", \"true\");\n control.setAttribute(\"aria-describedby\", error.id);\n },\n clearError() {\n error?.remove();\n error = undefined;\n control.removeAttribute(\"aria-invalid\");\n control.removeAttribute(\"aria-describedby\");\n },\n };\n}\n\n/**\n * Closes `popover` without committing when the map is replaced (an import: the preview went with\n * the old map) or turns read-only (the preview is put back), and stops listening on destroy.\n */\nexport function withMapListeners(\n modeler: Modeler,\n popover: PopoverHandle & { end(end: PopoverEnd): void },\n): PopoverHandle {\n const onImport = () => popover.end(\"import\");\n const onReadOnly = (event: unknown) => {\n if ((event as { readOnly?: boolean }).readOnly) popover.end(\"cancel\");\n };\n modeler.on(\"import.done\", onImport);\n modeler.on(READ_ONLY_CHANGED, onReadOnly);\n return {\n open: () => popover.open(),\n isOpen: () => popover.isOpen(),\n close: () => popover.close(),\n destroy() {\n modeler.off(\"import.done\", onImport);\n modeler.off(READ_ONLY_CHANGED, onReadOnly);\n popover.destroy();\n },\n };\n}\n","import {\n MAP_SIZE_PRESETS,\n PLOT_MAX,\n PLOT_MIN,\n parsePlotLength,\n plotLengthMessage,\n} from \"@miragon/wardley-schema-model\";\nimport type { Modeler } from \"../Modeler.js\";\nimport type { MapSizeInfo } from \"../WardleyBaseViewer.js\";\nimport { element } from \"./dom.js\";\nimport { dialogButton } from \"./dialog.js\";\nimport {\n createPopover,\n field,\n withMapListeners,\n type PopoverChrome,\n type PopoverHandle,\n} from \"./popover.js\";\n\nconst CUSTOM = \"custom\";\n\n/** The size the popover last drew; `undefined` = the default size without a `size` line. */\ntype Target = { width: number; height: number } | undefined;\n\nfunction numberInput(min: number, max: number): HTMLInputElement {\n const input = element(\"input\", \"\");\n input.type = \"number\";\n input.inputMode = \"numeric\";\n input.min = String(min);\n input.max = String(max);\n input.step = \"10\";\n return input;\n}\n\n/**\n * \"Map size…\" (guide §5.4): presets, a custom width × height and a reset to the default size. Every\n * choice is drawn at once as a preview without an undo step; closing writes ONE edit (none when the\n * map ends at the size it had). An import while it is open closes it without writing, and so does\n * a canvas that turns read-only, after putting the previous size back.\n */\nexport function createMapSizePopover(chrome: PopoverChrome, modeler: Modeler): PopoverHandle {\n const preset = element(\"select\", \"\");\n for (const choice of MAP_SIZE_PRESETS) {\n const option = element(\"option\", \"\", `${choice.name} (${choice.width} × ${choice.height})`);\n option.value = choice.id;\n preset.append(option);\n }\n const custom = element(\"option\", \"\", \"Custom\");\n custom.value = CUSTOM;\n preset.append(custom);\n const width = numberInput(PLOT_MIN.width, PLOT_MAX.width);\n const height = numberInput(PLOT_MIN.height, PLOT_MAX.height);\n const reset = dialogButton(\"Reset to default\", \"ghost\");\n const sizeField = field(\"Size\", preset);\n const widthField = field(\"Width\", width);\n const heightField = field(\"Height\", height);\n\n let atOpen: MapSizeInfo | undefined;\n let target: { size: Target } | undefined;\n\n const show = (size: MapSizeInfo) => {\n preset.value = size.presetId ?? CUSTOM;\n width.value = String(size.width);\n height.value = String(size.height);\n reset.disabled = !size.isExplicit;\n widthField.clearError();\n heightField.clearError();\n };\n\n const preview = (size: Target) => {\n target = { size };\n const applied = size\n ? modeler.setMapSize(size.width, size.height, { transient: true })\n : modeler.resetMapSize({ transient: true });\n void applied.then(() => show(modeler.getMapSize()));\n };\n\n const applyLength = (input: HTMLInputElement, axis: \"width\" | \"height\") => {\n const fieldOf = axis === \"width\" ? widthField : heightField;\n const length = parsePlotLength(input.value, axis);\n if (length === undefined) {\n fieldOf.showError(plotLengthMessage(axis));\n return;\n }\n fieldOf.clearError();\n const current = modeler.getMapSize();\n if (length === current[axis]) return;\n preview({ width: current.width, height: current.height, [axis]: length });\n };\n\n const popover = createPopover(chrome, {\n className: \"wardley-map-size\",\n title: \"Map size\",\n build(body, footer, done) {\n const lengths = element(\"div\", \"wardley-field-row\");\n const times = element(\"span\", \"wardley-field-times\", \"×\");\n times.setAttribute(\"aria-hidden\", \"true\");\n lengths.append(widthField.wrapper, times, heightField.wrapper);\n const hint = element(\"p\", \"wardley-popover-hint\", \"Or drag the plot’s right or bottom edge.\");\n body.append(sizeField.wrapper, lengths, hint);\n const doneButton = dialogButton(\"Done\", \"secondary\");\n doneButton.addEventListener(\"click\", done);\n footer.append(reset, doneButton);\n\n preset.addEventListener(\"change\", () => {\n const choice = MAP_SIZE_PRESETS.find((candidate) => candidate.id === preset.value);\n if (choice) preview({ width: choice.width, height: choice.height });\n else width.focus();\n });\n width.addEventListener(\"change\", () => applyLength(width, \"width\"));\n height.addEventListener(\"change\", () => applyLength(height, \"height\"));\n reset.addEventListener(\"click\", () => {\n // Reset disables itself, which would drop the focus out of the popover.\n preset.focus();\n preview(undefined);\n });\n },\n opened() {\n atOpen = modeler.getMapSize();\n target = undefined;\n show(atOpen);\n return preset;\n },\n closed(end) {\n const previewed = target;\n target = undefined;\n // An import already dropped the preview together with the map it was drawn on.\n if (!previewed || end === \"import\") return;\n // Committing the size at open puts it back without an undo step.\n const size = end === \"done\" ? previewed.size : sizeOf(atOpen);\n void (size ? modeler.setMapSize(size.width, size.height) : modeler.resetMapSize());\n },\n });\n\n return withMapListeners(modeler, popover);\n}\n\nfunction sizeOf(info: MapSizeInfo | undefined): Target {\n return info?.isExplicit ? { width: info.width, height: info.height } : undefined;\n}\n","import {\n DEFAULT_EVOLUTION_LABELS,\n EVOLUTION_PRESETS,\n normalizeEvolutionLabels,\n} from \"@miragon/wardley-schema-model\";\nimport type { Modeler } from \"../Modeler.js\";\nimport { element } from \"./dom.js\";\nimport { dialogButton } from \"./dialog.js\";\nimport {\n createPopover,\n field,\n withMapListeners,\n type PopoverChrome,\n type PopoverHandle,\n} from \"./popover.js\";\n\nconst CUSTOM = \"custom\";\n\nfunction presetIdFor(labels: readonly string[]): string {\n return (\n EVOLUTION_PRESETS.find((preset) => preset.labels.every((label, i) => label === labels[i]))\n ?.id ?? CUSTOM\n );\n}\n\n/**\n * \"X-axis labels…\" (guide §5.4): a preset or four free stage names. Typing previews on the axis\n * without touching the document; closing commits ONE edit, so the document gets one change and\n * an IDE one undo step per session. An import while it is open closes it without committing, and\n * so does a canvas that turns read-only, after putting the previous labels back.\n */\nexport function createAxisLabelsPopover(chrome: PopoverChrome, modeler: Modeler): PopoverHandle {\n const preset = element(\"select\", \"\");\n for (const choice of EVOLUTION_PRESETS) {\n const option = element(\"option\", \"\", choice.name);\n option.value = choice.id;\n option.title = choice.labels.join(\" · \");\n preset.append(option);\n }\n const custom = element(\"option\", \"\", \"Custom\");\n custom.value = CUSTOM;\n preset.append(custom);\n const inputs = [1, 2, 3, 4].map(() => {\n const input = element(\"input\", \"\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n return input;\n });\n\n let labelsAtOpen: readonly string[] = DEFAULT_EVOLUTION_LABELS;\n let previewed = false;\n\n const fill = (labels: readonly string[]) => {\n inputs.forEach((input, index) => (input.value = labels[index] ?? \"\"));\n preset.value = presetIdFor(labels);\n };\n const typedLabels = () => normalizeEvolutionLabels(inputs.map((input) => input.value));\n const preview = () => {\n previewed = true;\n const labels = typedLabels();\n modeler.setEvolutionLabels(labels, { transient: true });\n preset.value = presetIdFor(labels ?? DEFAULT_EVOLUTION_LABELS);\n };\n\n const popover = createPopover(chrome, {\n className: \"wardley-axis-labels\",\n title: \"X-axis labels\",\n build(body, footer, done) {\n const hint = element(\"p\", \"wardley-popover-hint\");\n const source = element(\"a\", \"wardley-popover-link\", \"Learn Wardley Mapping\");\n source.href = \"https://learnwardleymapping.com/landscape/\";\n source.target = \"_blank\";\n source.rel = \"noopener noreferrer\";\n hint.append(\"Label sets from \", source, \". Pick a set, or name each stage.\");\n body.append(field(\"Preset\", preset).wrapper, hint);\n inputs.forEach((input, index) => body.append(field(`Stage ${index + 1}`, input).wrapper));\n const reset = dialogButton(\"Reset to default\", \"ghost\");\n const doneButton = dialogButton(\"Done\", \"secondary\");\n footer.append(reset, doneButton);\n\n preset.addEventListener(\"change\", () => {\n const choice = EVOLUTION_PRESETS.find((candidate) => candidate.id === preset.value);\n if (!choice) return; // \"Custom\" keeps the fields as they are\n fill(choice.labels);\n preview();\n });\n for (const input of inputs) {\n input.addEventListener(\"input\", preview);\n input.addEventListener(\"keydown\", (event) => {\n if (event.key !== \"Enter\" || event.isComposing) return;\n event.preventDefault();\n done();\n });\n }\n reset.addEventListener(\"click\", () => {\n fill(DEFAULT_EVOLUTION_LABELS);\n preview();\n });\n doneButton.addEventListener(\"click\", done);\n },\n opened() {\n labelsAtOpen = modeler.exportMap().config.evolutionLabels ?? DEFAULT_EVOLUTION_LABELS;\n previewed = false;\n fill(labelsAtOpen);\n return inputs[0];\n },\n closed(end) {\n if (!previewed || end === \"import\") return;\n previewed = false;\n // Committing the labels at open puts them back without an undo step.\n modeler.setEvolutionLabels(\n end === \"done\" ? typedLabels() : normalizeEvolutionLabels(labelsAtOpen),\n );\n },\n });\n\n return withMapListeners(modeler, popover);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["AXES_LAYER","compact","VETO_PRIORITY","clamp","PLOT_MIN","PLOT_MAX","normalizeMapSize","MAP_SIZE_PRESETS","svgCreate","normalizeMapSize","presetIdForSize","clamp01","line","text","svgAttr","svgCreate","clamp01","svgCreate","EPSILON","clamp01","svgCreate","svgAttr","NAME_LABEL_CLASS","svgAttr","svgCreate","movementDeltaX","movementDeltaXOf","clamp","LASSO_TOOL","DRAW_TOOL","PLOT_INSET","escapeAttribute","ENTRY_SELECTOR","ENTRY_SELECTOR","AFTER_REDRAW_PRIORITY","svgCreate","svgAttr","svgCreate","svgAttr","svgCreate","CUSTOM","MAP_SIZE_PRESETS","PLOT_MIN","PLOT_MAX","Diagram","MAP_SIZE_PRESETS$1","PLOT_MAX$1","PLOT_MIN$1","normalizeMapSize$1","presetIdForSize$1","DraggingModule","RuleProvider","AutoScroll","BaseLayouter","CommandInterceptor","ModelingModule","MouseModule","CreateModule","BaseRenderer","SelectionModule","ZoomScrollModule","MoveCanvasModule","KeyboardModule","MoveModule","AutoScrollModule","ConnectModule","ContextPadModule","PaletteModule","RulesModule","OutlineModule","ResizeModule","PopupMenuModule","LassoToolModule","HoverTooltipModule","ContextPad","ConnectionPreviewModule","OrderingProvider","MIRAGON","PLOT","DEFAULT_PLOT_SIZE","NOTE_CHAR_W","noteMetrics","lines","label","maxLen","l","NOTATION_STATUS","COLORS","NOTE_COLORS","ATTITUDE_COLORS","ATTITUDE_TITLES","FONT","saveSVG","source","canvas","clone","layer","decoration","element","box","bounds","attribute","viewport","AXES_LAYER$1","AXES_PADDING","exportBounds","boxes","grid","content","drawnContentBox","padding","axes","axesBox","left","top","right","bottom","width","height","layerToScreen","screenToLayer","visuals","visual","local","visualToScreen","toLayer","x","y","layerX","layerY","ROOT_ID","NO_INSETS","fitViewbox","container","horizontal","freeExtent","insets","vertical","scale","extent","total","before","after","FRAME_TYPES","TYPE_ORDER","WardleyImporter","elementFactory","factory","eventBus","elementRegistry","config","injector","warnings","map","meta","existing","root","shapeById","ordered","a","b","frames","el","nodes","frameCount","shape","resolvedEdges","edge","target","connectionPaintOrder","insertedConnections","conn","plot","roots","e","isObject","isWardleyShape","\"wardleyType\"","CONNECTION_TYPES","isWardleyConnection","isComponent","isPipeline","isAttitude","compact$1","out","k","v","obj","WardleyExporter","sourceOrder","DEFAULT_MAP_TITLE","unorderedElements","unorderedEdges","base","built","committed","elements","edges","pipelineIds","consolidated","_stale","rest","childIds","CURRENT_SCHEMA_VERSION","validateMap","position","bo","labelOffset","extraPositions","points","p","WardleySourceOrder","event","index","sortBySourceIndex","indexOf","sourceIndex","item","items","blobToBase64","reader","resolve","reject","blob","ioModule","configWithSize","_previous","size","wardleyRootOf","withoutRawSizeStatements","withoutRawStatements","rawPassthrough","MapProjection","exporter","layouter","livePreview","options","businessObject","changed","model","template","assignGeometry","shapes","waypoints","point","snapshot","id","geometry","connection","transient","connections","COMMAND_START_EVENTS","PUT_BACK_PRIORITY","livePreviewModule","field","live","committedConfig","READ_ONLY_CHANGED","LOCKED_CLASS","VETO_PRIORITY$1","EDIT_RULES","WardleyReadOnly","bus","readOnly","locking","delayMs","shownOrWaiting","showsNow","name","readOnlyModule","isReadOnly","isReadOnlyShown","canvasSvg","isKeyAimedAt","liesInInertSubtree","isRendered","isKeyOnHiddenTarget","menusLeavingHiddenKeys","leaveKeysOnHiddenMenuToPage","popupMenu","trigger","entry","action","node","isCanvasKey","focusCanvasWithoutRing","svg","lastInteraction","modalityTracked","trackInputModality","lastInteractionWasPointer","describeCanvas","canvasAccessibilityModule","MAP_RESIZE_PREFIX","LAYER_NAME","LAYER_INDEX","SNAP_STEP","PRESET_SNAP_DISTANCE","EDGE_HIT_WIDTH","CORNER_HIT_SIZE","CORNER_VISUAL_SIZE","BADGE_OFFSET","CURSORS","round","value","step","clamp$2","min","max","withoutPaint","sizeForDrag","axis","start","dx","dy","keys","ratio","preset","candidate","sizeLabel","MapResizeHandles","dragging","projection","modeling","create","append","drag","context","group","hit","visible","attr","screenPixel","edgeHitWidth","half","cornerHitSize","cornerHalf","cornerVisualSize","startSize","originalEvent","ResizeAwareAutoScroll","mapProjectionModule","mapResizeModule","applyConfigUpdate","previous","key","update","nextConfig","UpdateConfigHandler","properties","INTERACTION_CHANGED","ARMED_TOOL_PREFIXES","ACTION_MARK_PRIORITY","HANDLER_GOES_ON_EVENTS","WardleyInteraction","wasActive","gesture","teardown","current","dropping","ending","ended","wardleyInteractionModule","diagramConfig","undoRedo","freeArea","IMPLICIT_ROOT_PREFIX","importableMap","checked","reserved","sizeToCss","cancelGesture","diagram","WardleyBaseViewer","modules","priority","callback","importer","commandStack","error","parseDSLWithDiagnostics","text","diagnostics","d","presetId","cleaned","title","labels","normalizeEvolutionLabels","requested","sameEvolutionLabels","serializeDSL","connectionAnchorOf","WardleyLayouter","hints","\"source\"","\"target\"","wardleyLayoutModule","LINKABLE_TYPES","isLinkableType","type","nextFreeLabel","taken","counterMatch","stem","counter","WardleyElementFactory","excludeId","entries","unique","wardleyType","wardleyLabel","pairableType","renamed","other","center","end","pos","canvasPoints","xs","ys","first","firstNorm","extra","rawLabel","decorators","annotationNumber","bidirectional","color","flowValue","wardleyModelModule","AXES_LAYER","DEFAULT_Y_AXIS_END_LABELS","AXIS_CLASS","AXIS_TEXT_CLASS","clamp01$3","n","EvolutionGrid","DEFAULT_STAGE_BOUNDARIES","DEFAULT_EVOLUTION_LABELS","drawnPlotLength","coord","evolutionStage","evolution","rect","i","x0","x1","line$1","midX","text$1","arrowHead","yLabel","w","h","attrs","dir","MIN_EVOLVE_DELTA","PREFIX","HANDLE_CLASS","clamp01$2","WardleyEvolveDragging","preview","movement","forwardTarget","evolutionAtClientX","vb","canvasX","clientX","cy","isDrawing","dom","stop","onMove","onUp","onKey","interaction","handleDrag","placement","wardleyEvolveModule","centerOf","pipelineContains","pipeline","allPipelines","registry","membersOf","anchorComponentOf","pipelineAnchoredBy","component","pipelineFollowers","anchor","pipelineAt","candidates","excluded","COLLECT_FOLLOWERS_PRIORITY","VERTICAL_PREVIEW_PRIORITY","DROP_TARGET_PRIORITY","EXTEND_CLOSURE_PRIORITY","VERTICAL_PREVIEW_LAYER","VERTICAL_PREVIEW_LAYER_INDEX","DROP_TARGET_MARKER","PipelineGroupBehavior","previewSupport","\"wardleyLabel\"","counterpart","closure","follower","carried","translate","remove","all","dragged","member","pipelineGroupModule","SHAPE_GEOMETRY_COMMANDS","GEOMETRY_COMMANDS","COMPONENT_LABEL_COMMANDS","TOP_LEVEL_PRIORITY","DELTA_CLAMP_PRIORITY","MIN_RESIZE_EXTENT","EPSILON$1","EvolutionConstraintBehavior","wardleyModeling","derive","directShapes","moved","closureShapes","refreshPairedLabels","pipelines","nameChanged","pairedNames","pairedComponents","topLeft","coordinate","evolutionStart","evolutionEnd","clampRange","clamp01$1","command","delta","followers","created","correction","movedShapes","verticalDelta","groupShape","host","evolutionsBefore","evolutionBefore","shiftedTarget","bottomRight","clampToRange","plotStart","plotEnd","clampedStart","clampedLength","length","range","RANGE_EPS","setOrDelete","UpdatePropertiesHandler","old","oldProperties","ResizeMapHandler","withRawPassthrough","UPDATE_PROPERTIES","RESIZE_MAP","UPDATE_CONFIG","compact","WardleyModeling","cx","clamp01","targetEvolution","opts","dec","\"inertia\"","method","\"method\"","\"market\"","\"ecosystem\"","kind","sameSize","PASTE_OFFSET","SHAPE_PROPS","CONNECTION_PROPS","snapshotProps","WardleyCopyPaste","selection","mouse","wardleyElementFactory","s","seen","sourceIdx","targetIdx","clones","lastMove","clipboard","snap","cloneIdByOriginalId","pipelineId","c","pipelineIndexByAnchor","anchorIndex","snapshots","pipelineIndex","independent","uniqueLabels","offset","bbox","groupBBox","minX","minY","maxX","maxY","wardleyModelingModule","evolutionGridModule","evolutionConstraintModule","ICON_PERSON","ICON_FAST_FORWARD","ICON_FAST_REWIND","drawIcon","g","path","LABEL_CHAR_WIDTH","movementDeltaX","here","estimatedLabelWidth","nameLines","line","firstLineBaseline","lineCount","growth","slotY","lastLineBaseline","nameLineGrowth","anchorsPipeline","componentLabelSlot","isShortRightwardMovement","componentLabelPlacement","slot","inertiaShift","movementLabelSlot","movementLabelPlacement","anchorLabelSlot","anchorLabelPlacement","normalizeLabelOffset","clamp","WARDLEY_RENDER_PRIORITY","NAME_LABEL_CLASS$1","MOVEMENT_CLASS","LABEL_HANDLE_CLASS","LABEL_ROLE_ATTRIBUTE","ATTITUDE_TITLE_CLEARANCE","WardleyRenderer","pts","dash","isFlow","endpoints","connectionArrow","mx","my","movementDeltaX$1","drawInertiaMarker","tint","ring","circle","drawComponentSymbols","drawComponentLabel","mv","tx","tipX","targetName","lastLineY","icon","y0","\"pioneers\"","stroke","plotTop","titleAbove","marker","accelerate","sym","outer","bx","lx","ly","firstLineY","haloAttrs","halo","row","angle","to","from","len","by","radiusOf","t","wp","sc","tc","dist","ux","uy","sr","tr","wardleyDrawModule","Viewer","PAD_TOP","PAD_BOTTOM","PAD_SIDE","INSET_SLACK","EPSILON","clamp$1","lo","hi","constrainAxis","lowest","highest","recentre","viewSize","freeAreaRange","freeEnd","free","constrainAxisToFreeArea","byContent","byPlot","PanConstraint","invalidate","view","slack","viewbox","pads","clampedX","clampedY","PanConstraintModule","FreeRect","side","reported","freeRectModule","NavigatedViewer","LASSO_TOOL$1","LASSO_SELECTION","WardleyLassoBehavior","original","lassoTool","toolManager","wardleyLassoModule","CONNECTABLE","HORIZONTAL_RESIZE_DIRECTIONS","isConnectable","alreadyConnected","WardleyRules","wardleyRulesModule","stageSnappingModule","tolerance","boundaryXs","setSnappedX","sx","mid","maxDistance","wrap","inner","toolIcon","LUCIDE_SQUARE_DASHED_MOUSE_POINTER","LINE_SEGMENT","eventCircle","PALETTE_ICONS","ATTITUDE_INITIALS","attitudeIcon","initial","GROUP_BLOCKS","GROUP_STRATEGY","SPECS","LASSO_TOOL","DRAW_TOOL$1","PLOT_INSET$1","STACK_OFFSET","MAX_STACK_STEPS","escapeAttribute$1","isKeyboardClick","WardleyPaletteProvider","drawTool","palette","spec","click","entryId","freeCenter","plotTopLeft","plotBottomRight","clampAxis","low","high","occupied","shortcut","nativeTitle","keyShortcut","draggable","ENTRY_SELECTOR$2","PREVIOUS_KEYS","NEXT_KEYS","ACTIVATE_KEYS","WardleyPaletteKeyboard","provider","parent","child","active","next","TOOL_ENTRY_SELECTOR","TOOL_ACTION_SUFFIX","WardleyPaletteArmedTool","tool","ENTRY_SELECTOR$1","PRESS_KEYS","SHOW_DELAY_MS","PALETTE_GAP","CONTAINER_EDGE","ENTRY_GAP","tooltipCount","WardleyPaletteTooltip","paletteContainer","shown","liesOutside","paletteEntry","tooltipElement","isSkinned","describedBy","saysMoreThanName","placeRightOfEntry","containerBox","entryBox","paletteBox","halfWidth","centre","kept","ownerDocument","skinned","chip","ENTRY_SELECTOR","ACTIVE_WHILE_LOCKED","VETO_PRIORITY","WardleyPaletteReadOnly","refusedWhileLocked","BEFORE_CANVAS_TEARDOWN","wardleyPaletteModule","hoverTooltip","pending","PAD_MARGIN","FALLBACK_PAD_WIDTH","WardleyContextPad","nodeRects","nodeBounds","union","padReach","movementRects","targets","graphics","part","rects","createFieldError","caption","message","place","isImeCompositionKey","focusField","NAME_LABEL_CLASS","EDITING_MARKER","NOT_EDITABLE","AFTER_REDRAW_PRIORITY$1","FIELD_PADDING_X","FIELD_PADDING_Y","FIELD_BORDER","FIELD_LINE_HEIGHT","MIN_FONT_SIZE","BETWEEN_CAPTIONS_GAP","NOTE_EDIT_HINT","duplicateNameMessage","SET_MINUS","sanitizeLabel","raw","isName","measureContext","measureTextWidth","font","fontSizePx","WardleyLabelEditing","isNote","openedByPointer","requiresUniqueName","classedByFallback","growthOf","lineHeightOf","fontSize","lineHeight","createNameField","hint","createCaption","layout","fieldBox","captionTop","showDuplicateError","clearError","done","cleanup","onBlur","onInput","commit","applied","relayout","last","nextBo","selected","gfx","marked","texts","drawnLabel","matched","containerRect","reference","labelElements","referenceStyle","typography","textWidth","labelMiddle","drawnLinesHeight","className","labelEditingModule","ALLOWED_SCHEMES","SCHEME_PATTERN","CONTROL_CHARACTERS","sanitizeLinkUrl","isAllowedLinkUrl","scheme","url","safeLinkUrl","CONTEXT_PAD_CLEARANCE","AFTER_REDRAW_PRIORITY","INVALID_HINT","canHaveLink","linkOf","WardleyLinkEditing","rawUrl","placeField","clearInvalid","placeCaption","markInvalid","tryCommit","linkEditingModule","POPUP_PROVIDER_ID","TYPE_GROUP","METHOD_GROUP","PROP_GROUP","keepKeysInsidePopup","mark","WardleyElementSettingsProvider","wardleyPopupModule","LUCIDE","chromeIcon","GROUP_PRIMARY","GROUP_PROPERTIES","GROUP_DANGER","KEYBOARD_APPEND_OFFSET","PAD_PREVIOUS_KEYS","PAD_NEXT_KEYS","escapeAttribute","cpHtml","iconSvg","wardleyContextPadModule","contextPad","connect","labelEditing","evolveDragging","colorPicker","keyEvent","\"delete\"","editTitle","startAppend","\"append\"","startConnect","\"connect\"","startEvolve","\"evolve\"","\"settings\"","\"color\"","linkEditing","storedLink","\"link\"","openableLink","pad","focused","containerBounds","plotBottom","NUDGE_STEP","NUDGE_STEP_COARSE","ARROW_DELTAS","QUICK_CREATE","isSingleKeyTool","PLOT_INSET","STACK_STEP","STACK_COLUMN_STEP","STACK_CLEARANCE","STACK_ATTEMPTS","WardleyKeyboard","undoRedoEnabled","rules","onPointerMove","onPointerLeave","escapeOwnedByOverlay","onKeydownCapture","deleteSelection","internalClipboardIsNewest","deferredPaste","markSystemClipboardNewer","pasteFromInternalClipboard","copyPaste","onPaste","locked","onModifierShortcut","onPlainKey","toolKey","onKeydown","attempt","canvasPoint","wardleyKeyboardModule","NAMED_TYPES","AFTER_CREATE","WardleyAppendBehavior","connectionPreview","canConnect","destroyed","wardleyAppendModule","GRID_STEPS","WardleyColorPicker","pop","swatches","buttons","activeButton","btn","isActive","ev","cw","ch","pw","ph","clientY","hadFocus","wardleyColorPickerModule","isFrame","WardleyOrderingProvider","siblings","newParent","wardleyOrderingModule","CLOSE_RADIUS","DRAW_TOOL_ENTRY","DRAW_TOOL","WardleyDrawTool","reportRelease","distance","WardleyDrawingHandles","sel","only","handle","swallow","onRelease","onPress","closed","WardleyDrawingHitProvider","createStrokeHit","interactionEvents","wardleyDrawToolModule","DRAG_THRESHOLD","SNAP_HOME_DISTANCE","ARMED_CLASS","DRAGGING_CLASS","WardleyLabelDragging","role","startOffset","deltaX","deltaY","sameOffset","home","imported","_clearedOffset","\"businessObject\"","_previousOffset","offsetFromPlacement","centerX","wardleyLabelDragModule","resizeAwareAutoScrollModule","Modeler","documentIdsOf","ids","readBackIds","modeler","canvasId","keyOf","documentId","findConnection","setAsideEditorState","canvasIds","readBack","edit","nameEdit","linkEdit","restoreEditorState","state","lookup","connectionOf","reselected","WARDLEY_NOTATION","ADDRESSABLE_TYPES","isAddressable","createCollaborativeModeler","collaborative","diagramOptions","createCollaborativeViewer","documentIds","byCanvasId","byDocumentId","read","interactionOf","service","editable","listeners","listener","selectionListeners","deliveries","subscribed","appearanceOf","WARDLEY_THEMES","isDestroyed","request","drawn","listed","theme","contrast","importTurns","lastWaiting","wait","ahead","afterUserAction","destroyedError","turn","panConstraint","contentListeners","importsRunning","lastExport","selections","untilItsTurn","MODELER_API_VERSION","elementInfo","listedElement","committedText","importText","editorState","importing","destroyedWhenDrawn","restoring","warning","isViewState","textToKeep","tearDown","isFiniteNumber","EXPORT_LABELS","exportEntry","exportEntries","exports","mapMenu","actions","mapTitle","shortcutsKey","ARROWS","percentOfActualSize","lang","keysOf","platform","what","names","ctrl","shift","plus","minus","fileGroup","chrome","mapShortcuts","messages","CLOSE_ICON","tag","nextId","uniqueId","prefix","dialogButton","\"variant\"","variant","header","head","heading","titleId","close","onClose","createMapDialog","dialog","build","parts","panel","pressedOnBackdrop","currentTitle","createTitleDialog","form","body","wrapper","footer","cancel","apply","onReadOnly","stopEscapeKeyup","onKeyup","release","createPopover","onPointerDown","onWindowBlur","onKeyDown","why","control","withMapListeners","onImport","popover","CUSTOM$1","numberInput","input","createMapSizePopover","choice","option","custom","reset","sizeField","widthField","heightField","atOpen","show","applyLength","fieldOf","parsePlotLength","plotLengthMessage","lengths","times","doneButton","previewed","sizeOf","info","CUSTOM","presetIdFor","EVOLUTION_PRESETS","createAxisLabelsPopover","inputs","labelsAtOpen","fill","typedLabels","MAP_SIZE_PRESETS","PLOT_MAX","PLOT_MIN","normalizeMapSize","presetIdForSize"],"sources":["../src/theme/palette.ts","../src/draw/styles.ts","../src/io/saveSvg.ts","../src/io/exportBounds.ts","../src/io/types.ts","../src/io/fitViewbox.ts","../src/io/WardleyImporter.ts","../src/model/di-types.ts","../src/io/WardleyExporter.ts","../src/io/WardleySourceOrder.ts","../src/io/blobToBase64.ts","../src/io/index.ts","../src/map-resize/MapProjection.ts","../src/live-preview/LivePreview.ts","../src/live-preview/index.ts","../src/read-only/WardleyReadOnly.ts","../src/read-only/index.ts","../src/a11y/canvasFocus.ts","../src/a11y/describeCanvas.ts","../src/a11y/index.ts","../src/map-resize/MapResizeHandles.ts","../src/map-resize/ResizeAwareAutoScroll.ts","../src/map-resize/index.ts","../src/modeling/cmd/UpdateConfigHandler.ts","../src/interaction/WardleyInteraction.ts","../src/interaction/index.ts","../src/WardleyBaseViewer.ts","../src/layout/WardleyLayouter.ts","../src/layout/index.ts","../src/model/WardleyElementFactory.ts","../src/model/index.ts","../src/evolution-grid/EvolutionGrid.ts","../src/evolve/constants.ts","../src/evolve/WardleyEvolveDragging.ts","../src/evolve/index.ts","../src/pipeline/pipelineMembership.ts","../src/pipeline/PipelineGroupBehavior.ts","../src/pipeline/index.ts","../src/evolution-grid/EvolutionConstraintBehavior.ts","../src/modeling/cmd/UpdatePropertiesHandler.ts","../src/modeling/cmd/ResizeMapHandler.ts","../src/modeling/WardleyModeling.ts","../src/modeling/WardleyCopyPaste.ts","../src/modeling/index.ts","../src/evolution-grid/index.ts","../src/draw/icons.ts","../src/draw/label-layout.ts","../src/draw/WardleyRenderer.ts","../src/draw/index.ts","../src/Viewer.ts","../src/pan-constraint/PanConstraint.ts","../src/pan-constraint/index.ts","../src/free-rect/FreeRect.ts","../src/free-rect/index.ts","../src/NavigatedViewer.ts","../src/lasso/WardleyLassoBehavior.ts","../src/lasso/index.ts","../src/rules/WardleyRules.ts","../src/rules/index.ts","../src/snapping/StageSnapping.ts","../src/snapping/index.ts","../src/draw/palette-icons.ts","../src/palette/WardleyPaletteProvider.ts","../src/palette/WardleyPaletteKeyboard.ts","../src/palette/WardleyPaletteArmedTool.ts","../src/palette/WardleyPaletteTooltip.ts","../src/palette/WardleyPaletteReadOnly.ts","../src/palette/WardleyHoverTooltipTeardown.ts","../src/palette/index.ts","../src/context-pad/WardleyContextPad.ts","../src/label-editing/fieldError.ts","../src/label-editing/imeComposition.ts","../src/label-editing/WardleyLabelEditing.ts","../src/label-editing/index.ts","../src/link-editing/link-url.ts","../src/link-editing/WardleyLinkEditing.ts","../src/link-editing/index.ts","../src/popup/WardleyElementSettingsProvider.ts","../src/popup/index.ts","../src/draw/lucide.ts","../src/context-pad/WardleyContextPadProvider.ts","../src/context-pad/index.ts","../src/keyboard/WardleyKeyboard.ts","../src/keyboard/index.ts","../src/append/WardleyAppendBehavior.ts","../src/append/index.ts","../src/color-picker/WardleyColorPicker.ts","../src/color-picker/index.ts","../src/ordering/WardleyOrderingProvider.ts","../src/ordering/index.ts","../src/draw-tool/WardleyDrawTool.ts","../src/draw-tool/WardleyDrawingHandles.ts","../src/draw-tool/WardleyDrawingHitProvider.ts","../src/draw-tool/index.ts","../src/label-drag/WardleyLabelDragging.ts","../src/label-drag/index.ts","../src/Modeler.ts","../src/editor-state.ts","../src/collaborative/CollaborativeWardley.ts","../src/map-menu/menu.ts","../src/map-menu/shortcuts.ts","../src/map-menu/dom.ts","../src/map-menu/dialog.ts","../src/map-menu/TitleDialog.ts","../src/map-menu/popover.ts","../src/map-menu/MapSizePopover.ts","../src/map-menu/AxisLabelsPopover.ts"],"sourcesContent":["/**\n * Miragon design tokens — the single source of truth for every colour the renderer draws.\n *\n * Values mirror the Miragon design system — the `miragon-brand:modeler-tool-design` skill in\n * `Miragon/corporate-identity`, whose files are vendored unchanged next to this module\n * (`cd-tokens.generated.css`, `cd-tokens.generated.json`, `cd-canvas.css`; design system 1.27.0).\n * Re-copy them from the skill to update; never fork the hex values by hand. The SVG drawing needs\n * literal values (exports carry presentation attributes, never `var()`), so `draw/styles.ts`\n * derives the public `COLORS`/`FONT`/… from `MIRAGON`; the in-canvas chrome in\n * `assets/wardley.css` reads the `--cd-ui-*` roles directly. The unit test\n * `test/theme.sync.test.ts` fails if a `MIRAGON` value drifts from its `--cd-*` counterpart or the\n * CSS declares a colour of its own.\n *\n * Pure data — no DOM, no imports — so it stays inside the P1 DOM-free discipline.\n *\n * The renderer draws light only (the modelers switch to dark together, guide §13.3). Brand rule:\n * blue leads (`blau` — surfaces, buttons, links), green accents (`gruen` — key visual, highlights;\n * never body text on white).\n */\n\n/** Raw Miragon brand ramp — exact `brand/tokens.json` values. */\nexport const MIRAGON = {\n /** Primary: surfaces, buttons, links, backgrounds. */\n blau: \"#335DE5\",\n /** Deeper blue for links / accent text on white (WCAG AA, ~5.5:1). */\n blauLink: \"#2B50D4\",\n /** Lightened blue for links / accents on dark surfaces. */\n blauHell: \"#6B8AFF\",\n /** Accent: key visual, highlights, one emphasised word. Bright — a fill, never text on white. */\n gruen: \"#00E676\",\n /** Calm neutral surface (warm off-white). */\n grau: \"#F9F7F7\",\n /** Text on light, monochrome logo. Not pure black. */\n schwarz: \"#1D1D1D\",\n weiss: \"#FFFFFF\",\n /**\n * Status layer (guide §3.3): the brand colours plus amber and red. Fills, borders, icons and\n * dots; as text on white only `danger` and `info` reach AA.\n */\n success: \"#00E676\",\n warning: \"#FFB000\",\n danger: \"#CD1839\",\n info: \"#335DE5\",\n /** UI grey (`--cd-linie`) for hairlines, guides and decorative borders. The CI allows no other greys. */\n linie: \"#E6E2E2\",\n /** Structural strokes that must stay visible (≥ 3:1 on white): axes, dependency edges. */\n kontur: \"#8F8A8A\",\n /** Secondary text (≥ 4.5:1 on white and on paper). */\n textLeise: \"#6B6666\",\n /** Signature brand gradient — hero, large surfaces, brand moments. Use verbatim. */\n gradientBrand: \"linear-gradient(120deg, #335DE5 30%, #00E676)\",\n} as const;\n","/** Central rendering constants (geometry, colors, typography) — Miragon corporate identity. */\n\nimport { DEFAULT_PLOT_SIZE } from \"@miragon/wardley-schema-model\";\nimport { MIRAGON } from \"../theme/index.js\";\n\n/**\n * Default plot area in diagram px (interior without axis margins). Changeable at runtime via\n * config.size. Width/height come from schema-model (single source, also used for migrations).\n */\nexport const PLOT = {\n width: DEFAULT_PLOT_SIZE.width,\n height: DEFAULT_PLOT_SIZE.height,\n marginLeft: 66,\n marginTop: 38,\n marginRight: 44,\n marginBottom: 58,\n} as const;\n\n/** Smallest drawn plot — the size policy lives in schema-model (shared with the DSL parser). */\nexport { PLOT_MIN } from \"@miragon/wardley-schema-model\";\n\nexport const NODE_SIZE = 34;\nexport const COMPONENT_RADIUS = 15;\nexport const COMPONENT_INNER_RADIUS = 12;\nexport const ANCHOR_ICON_SIZE = 26;\nexport const PIPELINE_HEIGHT = 30;\nexport const PIPELINE_ANCHOR_SIZE = 16;\n\nexport const NOTE_LINE_HEIGHT = 17;\nconst NOTE_PAD_X = 8;\nconst NOTE_PAD_Y = 6;\nconst NOTE_CHAR_W = 7.5;\n\n/**\n * Box dimensions of a note from its (possibly multi-line) text. The note shape grows as large as\n * its text -> the move/click hitbox grows with it (instead of a fixed 34px). Minimum = NODE_SIZE.\n */\nexport function noteMetrics(label: string): { lines: string[]; width: number; height: number } {\n const lines = (label && label.length ? label : \"note\").split(\"\\n\");\n const maxLen = Math.max(1, ...lines.map((l) => l.length));\n return {\n lines,\n width: Math.max(NODE_SIZE, Math.round(maxLen * NOTE_CHAR_W) + NOTE_PAD_X * 2),\n height: Math.max(NODE_SIZE, lines.length * NOTE_LINE_HEIGHT + NOTE_PAD_Y * 2),\n };\n}\n\n/**\n * The status colours the notation drew with before design system 1.13.0 brightened its status\n * layer. Maps store note colours as hex, the accelerator needs 4.5:1 as text and the SVG export\n * must not change, so the notation keeps them as its own literals.\n */\n// Notation colours until the joint dark mode maps them onto the status roles (guide §3.6).\n// brand-lint-disable\nconst NOTATION_STATUS = {\n success: \"#0B7A55\",\n warning: \"#92610A\",\n danger: \"#C92A2A\",\n info: \"#2B50D4\",\n} as const;\n// brand-lint-enable\n\n/**\n * Canvas colours — Miragon palette (blue = interactive/flow, green = accelerate/positive,\n * red = movement/decelerate). Keys are the public contract; brand values come from the single source\n * of truth in `theme/palette.ts` (`MIRAGON`). Referenced (not spread) so the literal-string types\n * survive into the published `.d.ts`.\n */\nexport const COLORS = {\n paper: MIRAGON.grau,\n ink: MIRAGON.schwarz,\n inkSoft: MIRAGON.textLeise,\n axis: MIRAGON.kontur,\n axisText: MIRAGON.textLeise,\n grid: MIRAGON.linie,\n band: \"rgba(29,29,29,0.025)\",\n stroke: MIRAGON.schwarz,\n componentFill: MIRAGON.weiss,\n anchorFill: MIRAGON.schwarz,\n dependency: MIRAGON.kontur,\n accent: MIRAGON.blau,\n accentSoft: \"rgba(51,93,229,0.12)\",\n flow: MIRAGON.blau,\n movement: NOTATION_STATUS.danger,\n inertia: MIRAGON.schwarz,\n noteText: MIRAGON.textLeise,\n pipeline: MIRAGON.schwarz,\n // An element surface like the components (guide §10.1); its stroke and number set it apart.\n annotationFill: MIRAGON.weiss,\n plotBackground: MIRAGON.weiss,\n accelerator: NOTATION_STATUS.success,\n deaccelerator: NOTATION_STATUS.danger,\n} as const;\n\n/**\n * Note color palette (bpmn.io-style mini picker; deliberately NOT a full color picker). Values are\n * hex and are rendered 1:1 as CSS color, or serialized in the DSL as `(color …)`.\n * Convention (also used in the Wardley-mapping skill): green = good, red = problem/risk,\n * amber = watch, blue = info, purple = idea, slate = neutral.\n */\nexport const NOTE_COLORS = [\n { id: \"green\", name: \"Green · good\", value: NOTATION_STATUS.success },\n { id: \"amber\", name: \"Amber · watch\", value: NOTATION_STATUS.warning },\n { id: \"red\", name: \"Red · problem\", value: NOTATION_STATUS.danger },\n { id: \"blue\", name: \"Blue · info\", value: NOTATION_STATUS.info },\n // Maps store these as hex; guide §3.6 retires them with the joint dark mode.\n // brand-lint-disable\n { id: \"teal\", name: \"Teal\", value: \"#0E8181\" },\n { id: \"purple\", name: \"Purple · idea\", value: \"#6A3DB8\" },\n { id: \"pink\", name: \"Pink\", value: \"#C2185B\" },\n { id: \"slate\", name: \"Slate · neutral\", value: \"#4A4A4A\" },\n // brand-lint-enable\n] as const;\n\n/**\n * Colors of the attitude regions per kind (shared by renderer + palette icons). Miragon palette:\n * pioneers = blue (explore), settlers = amber (stabilise), town planners = green (industrialise).\n */\nexport const ATTITUDE_COLORS: Record<string, { fill: string; stroke: string }> = {\n pioneers: { fill: \"rgba(51,93,229,0.07)\", stroke: MIRAGON.blau },\n // The notation's warning as a tint, until the joint dark mode draws Settlers per guide §3.6.\n // brand-lint-disable-next-line\n settlers: { fill: \"rgba(146,97,10,0.10)\", stroke: NOTATION_STATUS.warning },\n // Bright brand green only as the fill; the title and outline need the darker success value (AA).\n townplanners: { fill: \"rgba(0,230,118,0.10)\", stroke: NOTATION_STATUS.success },\n};\n\n/** Canonical region titles (Wardley's Pioneers / Settlers / Town Planners), keyed by kind. */\nexport const ATTITUDE_TITLES: Record<string, string> = {\n pioneers: \"Pioneers\",\n settlers: \"Settlers\",\n townplanners: \"Town Planners\",\n};\n\nexport const FONT = {\n /**\n * Set as the `font-family` attribute DIRECTLY on all SVG text elements (canvas labels,\n * axis/stage text and consequently the SVG export too) – not inherited from a CSS container.\n * 'Geist Variable' comes first because that is the family name `@fontsource-variable/geist`\n * registers; 'Geist' matches a locally installed (static) Geist. Without either it falls back to a\n * system sans. The library does NOT ship the font – consumers self-host it, see README.\n */\n family:\n \"'Geist Variable', 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif\",\n label: 13,\n axis: 12,\n stage: 12,\n} as const;\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport { PLOT } from \"../draw/styles.js\";\n\nexport interface SvgBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Serializes the current canvas into standalone SVG (snapshot/export).\n * `bounds` is the outer plot boundary (typically `exportBounds(canvas, grid)`), so that\n * maps enlarged via `config.size` are exported completely; if omitted, the default plot\n * area is used. Independent of the current zoom/scroll.\n */\nexport function saveSVG(canvas: Canvas, bounds?: SvgBounds): { svg: string } {\n // The canvas's own <svg> child: a host chrome may move a palette with <svg> icons in front of it.\n const source = canvas.getContainer().querySelector(\":scope > svg\");\n if (!source) throw new Error(\"No SVG found in the canvas container.\");\n\n const clone = source.cloneNode(true) as SVGSVGElement;\n // Editor chrome, sized to the current zoom: not part of the map.\n clone.querySelectorAll(\".layer-wardley-map-resize\").forEach((layer) => layer.remove());\n // Interaction state is not part of the map either: the picture looks the same whatever the user\n // has selected or hovers, so hosts need not deselect (and lose the selection) to export.\n clone.querySelectorAll(\".layer-wardley-drawing-handles\").forEach((layer) => layer.remove());\n clone\n .querySelectorAll(\".djs-outline, .layer-selectionOutline > *, .layer-resizers > *\")\n .forEach((decoration) => decoration.remove());\n clone.querySelectorAll(\".selected, .hover\").forEach((element) => {\n element.classList.remove(\"selected\", \"hover\");\n if (!element.classList.length) element.removeAttribute(\"class\");\n });\n\n const box = bounds ?? {\n x: 0,\n y: 0,\n width: PLOT.marginLeft + PLOT.width + PLOT.marginRight,\n height: PLOT.marginTop + PLOT.height + PLOT.marginBottom,\n };\n // The editor's canvas semantics (an interactive, focusable application) do not apply to a\n // static image.\n for (const attribute of [\"tabindex\", \"role\", \"aria-roledescription\", \"aria-label\"]) {\n clone.removeAttribute(attribute);\n }\n clone.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n clone.setAttribute(\"viewBox\", `${box.x} ${box.y} ${box.width} ${box.height}`);\n clone.setAttribute(\"width\", String(box.width));\n clone.setAttribute(\"height\", String(box.height));\n\n // diagram-js sets a viewbox transform on the outermost layer; for the static export we\n // neutralize pan/zoom by letting the viewBox (above) determine the geometry.\n const viewport = clone.querySelector<SVGGElement>(\".viewport\");\n if (viewport) viewport.removeAttribute(\"transform\");\n\n const svg = new XMLSerializer().serializeToString(clone);\n return { svg: '<?xml version=\"1.0\" encoding=\"utf-8\"?>\\n' + svg };\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { SvgBounds } from \"./saveSvg.js\";\n\n/** Name of the diagram-js layer the evolution grid draws its axes into. */\nconst AXES_LAYER = \"wardley-axes\";\n\n/** Small enough that the default axes stay inside the plot margins: the axis text has no halo. */\nconst AXES_PADDING = 4;\n\n/** Covers what getBBox ignores, chiefly the label halo stroke. */\nexport const EXPORT_CONTENT_PADDING = 12;\n\ninterface OuterBoundsSource {\n outerBounds(): SvgBounds;\n}\n\n/**\n * The area an image export must cover: the plot frame plus everything drawn on the element layer\n * and the axes. Labels of commodity components (evolution near 1) and notes run past the plot's\n * right edge, so exporting only the plot frame crops them.\n */\nexport function exportBounds(\n canvas: Canvas,\n grid: OuterBoundsSource,\n padding = EXPORT_CONTENT_PADDING,\n): SvgBounds {\n const boxes = [grid.outerBounds()];\n const content = drawnContentBox(canvas);\n if (content) {\n boxes.push({\n x: content.x - padding,\n y: content.y - padding,\n width: content.width + 2 * padding,\n height: content.height + 2 * padding,\n });\n }\n const axes = axesBox(canvas);\n if (axes) {\n boxes.push({\n x: axes.x - AXES_PADDING,\n y: axes.y - AXES_PADDING,\n width: axes.width + 2 * AXES_PADDING,\n height: axes.height + 2 * AXES_PADDING,\n });\n }\n\n const left = Math.floor(Math.min(...boxes.map((box) => box.x)));\n const top = Math.floor(Math.min(...boxes.map((box) => box.y)));\n const right = Math.ceil(Math.max(...boxes.map((box) => box.x + box.width)));\n const bottom = Math.ceil(Math.max(...boxes.map((box) => box.y + box.height)));\n return { x: left, y: top, width: right - left, height: bottom - top };\n}\n\n/**\n * The axes layer drawn by the evolution grid. Custom `y-axis` end labels and long `evolution`\n * stage names run past the fixed plot margins. Looked up in the DOM rather than via\n * `canvas.getLayer`, which would create the layer if it were missing.\n */\nfunction axesBox(canvas: Canvas): SvgBounds | undefined {\n try {\n const axes = canvas\n .getContainer()\n .querySelector<SVGGraphicsElement>(`.viewport > .layer-${AXES_LAYER}`);\n if (!axes) return undefined;\n const { x, y, width, height } = axes.getBBox();\n return width === 0 && height === 0 ? undefined : { x, y, width, height };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Union of the `.djs-visual` boxes in layer (= diagram) coordinates. Measuring the whole layer\n * would also count the invisible hit areas and selection outlines, which follow the estimated\n * shape size rather than the rendered text and would pad the export with empty space.\n */\nfunction drawnContentBox(canvas: Canvas): SvgBounds | undefined {\n // The typings declare a CanvasLayer record, but diagram-js returns the layer's <g> itself.\n const layer = canvas.getActiveLayer() as unknown as SVGGraphicsElement | null;\n if (!layer) return undefined;\n try {\n const layerToScreen = layer.getCTM();\n if (!layerToScreen) return undefined;\n const screenToLayer = layerToScreen.inverse();\n\n let left = Infinity;\n let top = Infinity;\n let right = -Infinity;\n let bottom = -Infinity;\n // diagram-js draws the previews of a move or create into the same layer; they are no part of\n // the document, and a cancelled drag would otherwise leave its box behind.\n const visuals = layer.querySelectorAll<SVGGraphicsElement>(\n \".djs-visual:not(.djs-drag-group .djs-visual)\",\n );\n for (const visual of visuals) {\n const local = visual.getBBox();\n const visualToScreen = visual.getCTM();\n if ((local.width === 0 && local.height === 0) || !visualToScreen) continue;\n const toLayer = screenToLayer.multiply(visualToScreen);\n for (const [x, y] of [\n [local.x, local.y],\n [local.x + local.width, local.y],\n [local.x, local.y + local.height],\n [local.x + local.width, local.y + local.height],\n ] as const) {\n const layerX = toLayer.a * x + toLayer.c * y + toLayer.e;\n const layerY = toLayer.b * x + toLayer.d * y + toLayer.f;\n left = Math.min(left, layerX);\n top = Math.min(top, layerY);\n right = Math.max(right, layerX);\n bottom = Math.max(bottom, layerY);\n }\n }\n if (![left, top, right, bottom].every(Number.isFinite)) return undefined;\n return { x: left, y: top, width: right - left, height: bottom - top };\n } catch {\n // getBBox/getCTM are unavailable outside a rendering engine (jsdom); the plot frame alone is\n // still a correct, if tighter, export.\n return undefined;\n }\n}\n","import type { MapConfig } from \"@miragon/wardley-schema-model\";\n\n/** ID of the diagram-js root element of the Wardley map. */\nexport const ROOT_ID = \"wardley-root\";\n\nexport interface ImportWarning {\n /** Human-readable, already including the line and source text for DSL findings. */\n readonly message: string;\n readonly elementId?: string;\n /** 1-based line of the DSL finding, for listing or jumping to the offending line. */\n readonly line?: number;\n /** The offending DSL source line as written. */\n readonly source?: string;\n}\n\n/** Map metadata stored on the root element (config + lossless passthrough). */\nexport interface RootBusinessObject {\n readonly config: MapConfig;\n readonly rawPassthrough?: readonly string[];\n}\n","import type { FreeRectInsets } from \"../free-rect/index.js\";\n\n/** An import never opens the map above 100 %, like the shell's fit and the other renderers. */\nexport const MAX_IMPORT_ZOOM = 1;\n\ninterface Box {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nconst NO_INSETS: FreeRectInsets = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/**\n * The viewbox that shows `bounds` centred in the free rectangle (`container` minus `insets`) at the\n * largest scale that fits, never above `MAX_IMPORT_ZOOM`. The box has the container's aspect\n * ratio, so `canvas.viewbox(box)` sets exactly this view. An axis the insets leave no room on\n * centres in the whole container. `undefined` for a 0 × 0 container or empty bounds.\n */\nexport function fitViewbox(\n bounds: Box,\n container: { width: number; height: number },\n insets: FreeRectInsets = NO_INSETS,\n): Box | undefined {\n if (!(container.width > 0 && container.height > 0)) return undefined;\n if (!(bounds.width > 0 && bounds.height > 0)) return undefined;\n const horizontal = freeExtent(container.width, insets.left, insets.right);\n const vertical = freeExtent(container.height, insets.top, insets.bottom);\n const scale = Math.min(\n MAX_IMPORT_ZOOM,\n horizontal.extent / bounds.width,\n vertical.extent / bounds.height,\n );\n const box = {\n x: bounds.x + bounds.width / 2 - (horizontal.start + horizontal.extent / 2) / scale,\n y: bounds.y + bounds.height / 2 - (vertical.start + vertical.extent / 2) / scale,\n width: container.width / scale,\n height: container.height / scale,\n };\n return Object.values(box).every(Number.isFinite) ? box : undefined;\n}\n\nfunction freeExtent(\n total: number,\n before: number,\n after: number,\n): { start: number; extent: number } {\n const extent = total - before - after;\n return extent > 0 ? { start: before, extent } : { start: 0, extent: total };\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type { MapEdge, MapElement, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./types.js\";\nimport { fitViewbox } from \"./fitViewbox.js\";\n\n/** \"Frame\" types sit behind the connections (concept doc requirement: frames at the very back). */\nconst FRAME_TYPES: ReadonlySet<string> = new Set([\"attitude\", \"pipeline\"]);\n\n/** Z-order of the nodes among themselves: smaller number = further back. */\nconst TYPE_ORDER: Record<string, number> = {\n attitude: 0,\n pipeline: 1,\n note: 2,\n component: 3,\n anchor: 4,\n annotation: 5,\n submap: 3,\n accelerator: 3,\n};\n\n/** Diagram config `wardleyImport` (viewer option `fitOnImport`). */\nexport interface WardleyImportConfig {\n /** `false`: the host fits the view itself, the import leaves it alone. */\n fit?: boolean;\n}\n\n/**\n * Bridges the WardleyMap model into the diagram-js canvas.\n * Uses `evolutionGrid` exclusively for the pixel projection (P7). Deliberately bypasses the\n * commandStack (import path, P4 exception): no undo, no dirty (concept doc §5.6).\n */\nexport default class WardleyImporter {\n static $inject = [\n \"canvas\",\n \"elementFactory\",\n \"wardleyElementFactory\",\n \"evolutionGrid\",\n \"eventBus\",\n \"elementRegistry\",\n \"injector\",\n \"config.wardleyImport\",\n ];\n\n private readonly freeRect: FreeRect | null;\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementFactory: ElementFactory,\n private readonly factory: WardleyElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n injector: Injector,\n private readonly config: WardleyImportConfig | undefined,\n ) {\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n }\n\n import(map: WardleyMap): ImportWarning[] {\n const warnings: ImportWarning[] = [];\n this.eventBus.fire(\"import.render.start\", { map });\n\n this.grid.configure(map.config);\n\n const meta: RootBusinessObject = {\n config: map.config,\n ...(map.rawPassthrough ? { rawPassthrough: map.rawPassthrough } : {}),\n };\n\n // Reuse the existing root (re-import), otherwise create a new one.\n let existing: (Root & { businessObject?: RootBusinessObject }) | undefined;\n try {\n existing = this.canvas.getRootElement() as Root & { businessObject?: RootBusinessObject };\n } catch {\n existing = undefined;\n }\n let root: Root & { businessObject?: RootBusinessObject };\n if (existing && existing.id === ROOT_ID) {\n root = existing;\n } else {\n root = this.elementFactory.createRoot({ id: ROOT_ID }) as Root & {\n businessObject?: RootBusinessObject;\n };\n this.canvas.setRootElement(root);\n }\n root.businessObject = meta;\n\n this.grid.render();\n\n const shapeById = new Map<string, WardleyShape>();\n const ordered = [...map.elements].sort(\n (a, b) => (TYPE_ORDER[a.elementType] ?? 9) - (TYPE_ORDER[b.elementType] ?? 9),\n );\n\n // Z-order (back -> front): frames (attitude/pipeline) -> connections -> nodes.\n // Frames + nodes must be registered before the connections; the connections are then\n // inserted via parentIndex BEHIND the nodes (but before them in the DOM).\n const frames = ordered.filter((el) => FRAME_TYPES.has(el.elementType));\n const nodes = ordered.filter((el) => !FRAME_TYPES.has(el.elementType));\n\n let frameCount = 0;\n for (const el of frames) {\n const shape = this.createShape(el);\n if (!shape) continue;\n this.canvas.addShape(shape, root);\n shapeById.set(el.id, shape);\n frameCount++;\n }\n for (const el of nodes) {\n const shape = this.createShape(el);\n if (!shape) continue;\n this.canvas.addShape(shape, root);\n shapeById.set(el.id, shape);\n }\n\n const resolvedEdges: { edge: MapEdge; source: WardleyShape; target: WardleyShape }[] = [];\n for (const edge of map.edges) {\n const source = shapeById.get(edge.from);\n const target = shapeById.get(edge.to);\n if (!source || !target) {\n warnings.push({ message: `Edge ${edge.id}: endpoint missing.`, elementId: edge.id });\n continue;\n }\n resolvedEdges.push({ edge, source, target });\n }\n\n // Flows sit above dependencies so a dependency on the same pair cannot strike through the flow\n // value; within each group, a later declaration paints on top (like interactive creation).\n const connectionPaintOrder = [\n ...resolvedEdges.filter(({ edge }) => edge.edgeType !== \"flow\"),\n ...resolvedEdges.filter(({ edge }) => edge.edgeType === \"flow\"),\n ];\n let insertedConnections = 0;\n for (const { edge, source, target } of connectionPaintOrder) {\n const conn =\n edge.edgeType === \"flow\"\n ? this.factory.createFlow(edge, source, target)\n : this.factory.createDependency(edge, source, target);\n // Behind all nodes, in front of the frames and the connections inserted so far.\n this.canvas.addConnection(conn, root, frameCount + insertedConnections);\n insertedConnections++;\n }\n\n // Frames render BEFORE the nodes exist, but pipeline visuals depend on whether a\n // same-named anchor component exists — re-render them now that everything is in place.\n for (const el of frames) {\n const shape = shapeById.get(el.id);\n if (shape && el.elementType === \"pipeline\") {\n this.eventBus.fire(\"element.changed\", { element: shape });\n }\n }\n\n if (this.config?.fit !== false) this.fitPlot();\n this.eventBus.fire(\"import.render.done\", { warnings });\n return warnings;\n }\n\n /**\n * The plot with its axis margins, centred in the host's free rectangle, at most at 100 %: where\n * the host's own fit puts it. With a free area the pan constraint leaves it there; without one\n * it may still move a map smaller than the view to keep its own margins around it.\n */\n private fitPlot(): void {\n const plot = this.grid.outerBounds();\n const insets = this.freeRect?.insets();\n this.canvas.viewbox(fitViewbox(plot, this.canvas.getSize(), insets) ?? plot);\n }\n\n private createShape(el: MapElement): WardleyShape | undefined {\n return this.factory.createFromModel(el);\n }\n\n clear(): void {\n // Root elements are planes, not shapes: removing diagram-js's implicit root (created by any canvas\n // access before the first import) as a shape corrupts the canvas and breaks setRootElement.\n const roots = new Set<unknown>(this.canvas.getRootElements());\n for (const el of [...this.elementRegistry.getAll()]) {\n const e = el as { waypoints?: unknown; id: string };\n if (roots.has(el)) continue;\n try {\n if (e.waypoints) this.canvas.removeConnection(e.id);\n else this.canvas.removeShape(e.id);\n } catch {\n // already removed (e.g. edge on a removed shape) — ignore\n }\n }\n }\n}\n","import type { Shape, Connection } from \"diagram-js/lib/model/Types\";\nimport type {\n AcceleratorDirection,\n AttitudeKind,\n ComponentDecorators,\n DrawingStrokeStyle,\n LabelOffset,\n MapEdge,\n MapElement,\n Movement,\n} from \"@miragon/wardley-schema-model\";\n\n/**\n * diagram-js runtime model with Wardley extensions.\n *\n * The positional truth while editing is `evolution`/`visibility` (normalized), NOT `x`/`y` (pixels)\n * and NOT the `businessObject` (concept doc §2.2, §5.6).\n * `businessObject` is the identity/metadata backref to the original model element.\n */\n\nexport type WardleyShapeType =\n | \"component\"\n | \"anchor\"\n | \"pipeline\"\n | \"note\"\n | \"annotation\"\n | \"attitude\"\n | \"submap\"\n | \"accelerator\"\n | \"drawing\";\n\nexport type WardleyConnectionType = \"dependency\" | \"flow\";\n\nexport interface WardleyShape extends Shape {\n wardleyType: WardleyShapeType;\n /** normalized [0,1] — runtime truth of the X position. */\n evolution: number;\n /** normalized [0,1] — runtime truth of the Y position. */\n visibility: number;\n /** Display text (separate from diagram-js `label`, which references a label element). */\n wardleyLabel: string;\n /** OWM `label [dx, dy]` — px offset relative to the default label position. */\n labelOffset?: LabelOffset;\n decorators?: ComponentDecorators;\n movement?: Movement;\n /** pipeline only: evolution range. */\n evolutionStart?: number;\n evolutionEnd?: number;\n /** component only: membership in a pipeline (id) — runtime truth, maintained via drag. */\n pipelineId?: string;\n /** annotation only. */\n annotationNumber?: number;\n /** attitude region only. */\n attitudeKind?: AttitudeKind;\n /** attitude only: opposite corner (normalized), maintained by the EvolutionConstraintBehavior. */\n corner2?: { visibility: number; evolution: number };\n /** accelerator only. */\n acceleratorDirection?: AcceleratorDirection;\n /** drawing only: points in px RELATIVE to the shape's x/y (moving the shape moves them all). */\n drawingPoints?: Array<{ x: number; y: number }>;\n /** drawing only: closed polygon vs. open polyline. */\n closed?: boolean;\n /** drawing only. */\n strokeStyle?: DrawingStrokeStyle;\n /** Optional element color (CSS color/hex from the swatch palette) — any element type. */\n color?: string;\n businessObject?: MapElement;\n}\n\nexport interface WardleyConnection extends Connection {\n wardleyType: WardleyConnectionType;\n bidirectional?: boolean;\n flowValue?: string;\n /** annotation text after `;` (e.g. \"limited by\"). */\n linkLabel?: string;\n businessObject?: MapEdge;\n}\n\nfunction isObject(el: unknown): el is Record<string, unknown> {\n return typeof el === \"object\" && el !== null;\n}\n\nexport function isWardleyShape(el: unknown): el is WardleyShape {\n return isObject(el) && typeof el[\"wardleyType\"] === \"string\" && \"evolution\" in el;\n}\n\nconst CONNECTION_TYPES: ReadonlySet<unknown> = new Set<WardleyConnectionType>([\n \"dependency\",\n \"flow\",\n]);\n\n/**\n * Keyed on the type, not on `waypoints`: diagram-js lays out an interactively created connection only\n * inside `connection.create`'s execute, so pre-execute hooks (e.g. ordering) see it without them.\n */\nexport function isWardleyConnection(el: unknown): el is WardleyConnection {\n return isObject(el) && CONNECTION_TYPES.has(el[\"wardleyType\"]);\n}\n\nexport function isComponent(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"component\";\n}\n\nexport function isPipeline(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"pipeline\";\n}\n\nexport function isAttitude(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"attitude\";\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport {\n validateMap,\n CURRENT_SCHEMA_VERSION,\n DEFAULT_MAP_TITLE,\n type AnchorElement,\n type AnnotationElement,\n type AttitudeElement,\n type ComponentElement,\n type LabelOffset,\n type MapConfig,\n type MapEdge,\n type MapElement,\n type Movement,\n type NoteElement,\n type PipelineElement,\n type SubmapElement,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleySourceOrder from \"./WardleySourceOrder.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"./types.js\";\n\nfunction compact<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\n/** A shape's evolve target and label offset as the document has them. */\nexport interface CommittedShapeFields {\n readonly movement: Movement | undefined;\n readonly labelOffset: LabelOffset | undefined;\n}\n\n/**\n * Reconstructs a WardleyMap from the diagram-js runtime model. The source of truth for positions are\n * the DI properties `evolution`/`visibility`; editable fields (label, decorators, movement,\n * pipeline range) are likewise read from the DI properties (concept doc §5.6). The\n * `businessObject` serves only as a fallback for type-specific fields that are not (yet) editable.\n */\nexport default class WardleyExporter {\n static $inject = [\"elementRegistry\", \"canvas\", \"evolutionGrid\", \"wardleySourceOrder\"];\n\n constructor(\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly sourceOrder: WardleySourceOrder,\n ) {}\n\n /**\n * `committed` gives the evolve target and label offset the document has for each shape a drag\n * previews on; the map takes them instead of the ones the canvas shows.\n */\n export(committed?: ReadonlyMap<WardleyShape, CommittedShapeFields>): WardleyMap {\n const root = this.canvas.getRootElement() as Root & { businessObject?: RootBusinessObject };\n const meta = root.businessObject;\n const config: MapConfig = meta?.config ?? { title: DEFAULT_MAP_TITLE };\n\n const unorderedElements: MapElement[] = [];\n const unorderedEdges: MapEdge[] = [];\n\n for (const el of this.elementRegistry.getAll()) {\n if (el.id === ROOT_ID) continue;\n if (isWardleyConnection(el)) {\n if (el.businessObject) {\n unorderedEdges.push(el.businessObject);\n } else {\n const base = { id: el.id, from: el.source?.id ?? \"\", to: el.target?.id ?? \"\" };\n unorderedEdges.push(\n el.wardleyType === \"flow\"\n ? { ...base, edgeType: \"flow\", ...(el.bidirectional ? { bidirectional: true } : {}) }\n : { ...base, edgeType: \"dependency\" },\n );\n }\n } else if (isWardleyShape(el)) {\n const built = this.buildElement(el, committed?.get(el));\n if (built) unorderedElements.push(built);\n }\n }\n const elements = this.sourceOrder.sortElements(unorderedElements);\n const edges = this.sourceOrder.sortEdges(unorderedEdges);\n\n // Consolidate pipeline membership: childIds are derived from component.pipelineId\n // (single source of truth); pipelineId references to deleted pipelines are discarded.\n const pipelineIds = new Set(\n elements.filter((e) => e.elementType === \"pipeline\").map((e) => e.id),\n );\n const consolidated = elements.map((el) => {\n if (el.elementType === \"component\" && el.pipelineId && !pipelineIds.has(el.pipelineId)) {\n const { pipelineId: _stale, ...rest } = el;\n return rest as MapElement;\n }\n if (el.elementType === \"pipeline\") {\n const childIds = elements\n .filter((e) => e.elementType === \"component\" && e.pipelineId === el.id)\n .map((e) => e.id);\n return { ...el, childIds };\n }\n return el;\n });\n\n const map: WardleyMap = {\n schemaVersion: CURRENT_SCHEMA_VERSION,\n config,\n elements: consolidated,\n edges,\n ...(meta?.rawPassthrough ? { rawPassthrough: meta.rawPassthrough } : {}),\n };\n\n return validateMap(map);\n }\n\n /** Builds a MapElement from the DI properties (common types) or the businessObject (the rest). */\n private buildElement(\n el: WardleyShape,\n committed: CommittedShapeFields | undefined,\n ): MapElement | undefined {\n const position = { visibility: el.visibility, evolution: el.evolution };\n const bo = el.businessObject;\n const { movement, labelOffset } = committed ?? el;\n\n switch (el.wardleyType) {\n case \"component\":\n return compact({\n id: el.id,\n elementType: \"component\",\n label: el.wardleyLabel,\n position,\n // labelOffset is not editable (yet); without the fallback it would be lost on\n // every export round trip.\n labelOffset: labelOffset ?? (bo as ComponentElement | undefined)?.labelOffset,\n decorators: el.decorators,\n movement,\n // Membership is geometry-derived runtime truth (set on import, cleared when the box\n // moves away) — deliberately NO businessObject fallback.\n pipelineId: el.pipelineId,\n url: (bo as ComponentElement | undefined)?.url,\n color: el.color,\n }) as ComponentElement;\n case \"anchor\":\n return compact({\n id: el.id,\n elementType: \"anchor\",\n label: el.wardleyLabel,\n position,\n labelOffset: labelOffset ?? (bo as AnchorElement | undefined)?.labelOffset,\n color: el.color,\n }) as AnchorElement;\n case \"note\":\n return compact({\n id: el.id,\n elementType: \"note\",\n label: el.wardleyLabel,\n position,\n patternType: (bo as NoteElement | undefined)?.patternType,\n color: el.color,\n }) as NoteElement;\n case \"pipeline\":\n return {\n id: el.id,\n elementType: \"pipeline\",\n label: el.wardleyLabel,\n position,\n evolutionStart: el.evolutionStart ?? 0,\n evolutionEnd: el.evolutionEnd ?? 1,\n childIds: (bo as PipelineElement | undefined)?.childIds ?? [],\n ...(el.color ? { color: el.color } : {}),\n };\n case \"attitude\":\n return {\n id: el.id,\n elementType: \"attitude\",\n kind: el.attitudeKind ?? \"pioneers\",\n label: el.wardleyLabel,\n position,\n // corner2 is maintained by the EvolutionConstraintBehavior on move/resize/create.\n corner2: el.corner2 ??\n (bo as AttitudeElement | undefined)?.corner2 ?? {\n visibility: Math.max(0, position.visibility - 0.1),\n evolution: Math.min(1, position.evolution + 0.15),\n },\n ...(el.color ? { color: el.color } : {}),\n };\n case \"accelerator\":\n return {\n id: el.id,\n elementType: \"accelerator\",\n direction: el.acceleratorDirection ?? \"accelerate\",\n label: el.wardleyLabel,\n position,\n ...(el.color ? { color: el.color } : {}),\n };\n case \"annotation\": {\n // The marker shows positions[0]; additional positions (multi-point annotation) are\n // preserved from the businessObject instead of collapsing to a single point on round trip.\n const extraPositions = ((bo as AnnotationElement | undefined)?.positions ?? []).slice(1);\n return {\n id: el.id,\n elementType: \"annotation\",\n label: el.wardleyLabel,\n position,\n number: el.annotationNumber ?? 0,\n positions: [position, ...extraPositions],\n text: el.wardleyLabel,\n ...(el.color ? { color: el.color } : {}),\n };\n }\n case \"submap\":\n return compact({\n id: el.id,\n elementType: \"submap\",\n label: el.wardleyLabel,\n position,\n urlRef: (bo as SubmapElement | undefined)?.urlRef,\n color: el.color,\n }) as SubmapElement;\n case \"drawing\": {\n // Points are stored relative to the shape in px — convert back per point.\n const points = (el.drawingPoints ?? []).map((p) =>\n this.grid.fromCanvas({ x: el.x + p.x, y: el.y + p.y }),\n );\n if (points.length < 2) return undefined;\n return {\n id: el.id,\n elementType: \"drawing\",\n label: \"\",\n position: points[0]!,\n points,\n ...(el.closed ? { closed: true } : {}),\n ...(el.strokeStyle ? { strokeStyle: el.strokeStyle } : {}),\n ...(el.color ? { color: el.color } : {}),\n };\n }\n default: {\n const exhaustive: never = el.wardleyType;\n void exhaustive;\n return bo ? ({ ...bo, position } as MapElement) : undefined;\n }\n }\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { WardleyMap } from \"@miragon/wardley-schema-model\";\n\ninterface Identified {\n readonly id: string;\n}\n\n/**\n * Remembers the order in which elements and edges appeared in the imported map, so the export can\n * write them back in that order. The registry/DOM order cannot serve: it is the z-order (frames,\n * connections, nodes), and exporting in it reshuffles every hand-written file on the first edit.\n */\nexport default class WardleySourceOrder {\n static $inject = [\"eventBus\"];\n\n private elementIndex = new Map<string, number>();\n private edgeIndex = new Map<string, number>();\n\n constructor(eventBus: EventBus) {\n eventBus.on(\"import.render.start\", (event: { map: WardleyMap }) => this.remember(event.map));\n eventBus.on(\"diagram.clear\", () => this.remember({ elements: [], edges: [] }));\n }\n\n remember(map: Pick<WardleyMap, \"elements\" | \"edges\">): void {\n this.elementIndex = new Map(map.elements.map((element, index) => [element.id, index]));\n this.edgeIndex = new Map(map.edges.map((edge, index) => [edge.id, index]));\n }\n\n /** Imported elements in source order, followed by the rest in their given (creation) order. */\n sortElements<T extends Identified>(elements: readonly T[]): T[] {\n return sortBySourceIndex(elements, this.elementIndex);\n }\n\n /** Imported edges in source order, followed by the rest in their given (creation) order. */\n sortEdges<T extends Identified>(edges: readonly T[]): T[] {\n return sortBySourceIndex(edges, this.edgeIndex);\n }\n}\n\nfunction sortBySourceIndex<T extends Identified>(\n items: readonly T[],\n sourceIndex: ReadonlyMap<string, number>,\n): T[] {\n const indexOf = (item: T): number => sourceIndex.get(item.id) ?? Number.POSITIVE_INFINITY;\n // Array.prototype.sort is stable, so items without a source index keep their relative order.\n return [...items].sort((a, b) => {\n const left = indexOf(a);\n const right = indexOf(b);\n return left === right ? 0 : left < right ? -1 : 1;\n });\n}\n","/** Blob -> Base64 without the data-URL prefix, e.g. to post an export to a VS Code extension host. */\nexport function blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(String(reader.result).split(\",\")[1] ?? \"\");\n reader.onerror = () => reject(new Error(\"Could not read the export blob.\"));\n reader.readAsDataURL(blob);\n });\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyImporter from \"./WardleyImporter.js\";\nimport WardleyExporter from \"./WardleyExporter.js\";\nimport WardleySourceOrder from \"./WardleySourceOrder.js\";\n\nexport const ioModule: ModuleDeclaration = {\n // Instantiated eagerly: it must observe the first import, long before anything exports.\n __init__: [\"wardleySourceOrder\"],\n wardleySourceOrder: [\"type\", WardleySourceOrder],\n wardleyImporter: [\"type\", WardleyImporter],\n wardleyExporter: [\"type\", WardleyExporter],\n};\n\nexport { default as WardleyImporter } from \"./WardleyImporter.js\";\nexport { default as WardleyExporter } from \"./WardleyExporter.js\";\nexport { default as WardleySourceOrder } from \"./WardleySourceOrder.js\";\nexport { saveSVG } from \"./saveSvg.js\";\nexport type { SvgBounds } from \"./saveSvg.js\";\nexport { exportBounds, EXPORT_CONTENT_PADDING } from \"./exportBounds.js\";\nexport { blobToBase64 } from \"./blobToBase64.js\";\nexport { ROOT_ID } from \"./types.js\";\nexport type { ImportWarning, RootBusinessObject } from \"./types.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type BaseLayouter from \"diagram-js/lib/layout/BaseLayouter\";\nimport type { Element, Root } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport type { MapConfig, MapSize, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport { withoutRawStatements } from \"@miragon/wardley-dsl\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyExporter from \"../io/WardleyExporter.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"../io/index.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { LivePreview } from \"../live-preview/index.js\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\nexport type WardleyRoot = Root & { businessObject?: RootBusinessObject };\n\ninterface ShapeGeometry {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n readonly drawingPoints?: Array<{ x: number; y: number }>;\n}\n\n/** Exact pixel state of the map, to undo a live preview without any rounding or clamping. */\nexport interface ProjectionSnapshot {\n readonly businessObject: RootBusinessObject;\n readonly shapes: ReadonlyMap<string, ShapeGeometry>;\n readonly waypoints: ReadonlyMap<string, Point[]>;\n}\n\n/** `config` with `size` set, or without the key when `size` is undefined. */\nexport function configWithSize(config: MapConfig, size: MapSize | undefined): MapConfig {\n const { size: _previous, ...rest } = config;\n return size ? { ...rest, size: { width: size.width, height: size.height } } : rest;\n}\n\n/**\n * The imported Wardley root, or undefined before the first import. Unlike\n * `canvas.getRootElement()` this never creates diagram-js's implicit root, which the next\n * import's `clear()` would remove and so break `setRootElement`.\n */\nexport function wardleyRootOf(canvas: Canvas): WardleyRoot | undefined {\n return canvas.getRootElements().find((root) => root.id === ROOT_ID) as WardleyRoot | undefined;\n}\n\n/**\n * `rawPassthrough` without unreadable `size` statements: once the map writes a valid size, a kept\n * one would be written after it, and OWM lets the last size line win. Comment text is never dropped.\n */\nexport function withoutRawSizeStatements(\n rawPassthrough: readonly string[] | undefined,\n): readonly string[] | undefined {\n return withoutRawStatements(rawPassthrough, \"size\");\n}\n\n/**\n * Re-projects the live shapes onto a new plot size in place — no re-import, so the shape objects,\n * the selection and the undo history survive. The normalized model is the truth; every element is\n * placed by the same factory projection the importer uses (P7), so a resize looks exactly like a\n * fresh import at the new size.\n */\nexport default class MapProjection {\n static $inject = [\n \"canvas\",\n \"elementRegistry\",\n \"evolutionGrid\",\n \"wardleyElementFactory\",\n \"wardleyExporter\",\n \"layouter\",\n \"eventBus\",\n \"wardleyLivePreview\",\n ];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly grid: EvolutionGrid,\n private readonly factory: WardleyElementFactory,\n private readonly exporter: WardleyExporter,\n private readonly layouter: BaseLayouter,\n private readonly eventBus: EventBus,\n private readonly livePreview: LivePreview,\n ) {}\n\n /** The Wardley root, or undefined before the first import. */\n root(): WardleyRoot | undefined {\n const root = wardleyRootOf(this.canvas);\n return root?.businessObject ? root : undefined;\n }\n\n /** The normalized truth, read under the CURRENT grid (drawings keep px-relative points). */\n captureModel(): WardleyMap {\n return this.exporter.export();\n }\n\n /**\n * Stores `businessObject` on the root, redraws the grid for its config and re-projects every\n * element of `model` onto it. Fires `wardley.config.changed`; returns the changed elements so\n * the caller (command stack or live preview) can redraw them.\n */\n apply(\n businessObject: RootBusinessObject,\n model: WardleyMap = this.captureModel(),\n options: { transient?: boolean } = {},\n ): Element[] {\n const root = this.root();\n if (!root) return [];\n if (options.transient) this.livePreview.begin(\"size\");\n root.businessObject = businessObject;\n this.grid.configure(businessObject.config);\n this.grid.render();\n\n const changed: Element[] = [];\n for (const element of model.elements) {\n const shape = this.elementRegistry.get(element.id);\n if (!isWardleyShape(shape)) continue;\n const template = this.factory.createFromModel(element);\n if (!template) continue;\n assignGeometry(shape, template);\n changed.push(shape);\n }\n changed.push(...this.layoutConnections());\n this.fireConfigChanged(businessObject.config, options.transient === true);\n return changed;\n }\n\n snapshot(): ProjectionSnapshot | undefined {\n const root = this.root();\n if (!root?.businessObject) return undefined;\n const shapes = new Map<string, ShapeGeometry>();\n const waypoints = new Map<string, Point[]>();\n for (const element of this.elementRegistry.getAll()) {\n if (isWardleyShape(element)) {\n shapes.set(element.id, {\n x: element.x,\n y: element.y,\n width: element.width,\n height: element.height,\n ...(element.drawingPoints\n ? { drawingPoints: element.drawingPoints.map((point) => ({ ...point })) }\n : {}),\n });\n } else if (isWardleyConnection(element)) {\n waypoints.set(\n element.id,\n element.waypoints.map((point) => ({ x: point.x, y: point.y })),\n );\n }\n }\n return { businessObject: root.businessObject, shapes, waypoints };\n }\n\n /**\n * Puts the size and every element's geometry back exactly as they were when `snapshot` was\n * taken. The rest of the root stays: an axis-label preview opened since then is no part of it.\n */\n restore(snapshot: ProjectionSnapshot, options: { transient?: boolean } = {}): Element[] {\n const root = this.root();\n const businessObject = this.withSize(snapshot.businessObject.config.size);\n if (!root || !businessObject) return [];\n root.businessObject = businessObject;\n this.grid.configure(businessObject.config);\n this.grid.render();\n const changed: Element[] = [];\n for (const [id, geometry] of snapshot.shapes) {\n const shape = this.elementRegistry.get(id);\n if (!isWardleyShape(shape)) continue;\n assignGeometry(shape, geometry);\n changed.push(shape);\n }\n for (const [id, points] of snapshot.waypoints) {\n const connection = this.elementRegistry.get(id);\n if (!isWardleyConnection(connection)) continue;\n connection.waypoints = points.map((point) => ({ ...point }));\n changed.push(connection);\n }\n this.livePreview.end(\"size\");\n this.fireConfigChanged(businessObject.config, options.transient === true);\n return changed;\n }\n\n /**\n * The live root with `size` set (removed when undefined), for a size preview; undefined before\n * the first import.\n */\n withSize(size: MapSize | undefined): RootBusinessObject | undefined {\n const businessObject = this.root()?.businessObject;\n return (\n businessObject && { ...businessObject, config: configWithSize(businessObject.config, size) }\n );\n }\n\n /** `transient` marks a live preview that is not part of the document (yet). */\n private fireConfigChanged(config: MapConfig, transient: boolean): void {\n this.eventBus.fire(\"wardley.config.changed\", { config, ...(transient ? { transient } : {}) });\n }\n\n /** Redraws elements changed outside the command stack (the live preview). */\n redraw(elements: readonly Element[]): void {\n for (const element of elements) this.eventBus.fire(\"element.changed\", { element });\n }\n\n private layoutConnections(): Element[] {\n const connections: Element[] = [];\n for (const element of this.elementRegistry.getAll()) {\n if (!isWardleyConnection(element)) continue;\n element.waypoints = this.layouter.layoutConnection(element);\n connections.push(element);\n }\n return connections;\n }\n}\n\nfunction assignGeometry(shape: WardleyShape, geometry: ShapeGeometry): void {\n shape.x = geometry.x;\n shape.y = geometry.y;\n shape.width = geometry.width;\n shape.height = geometry.height;\n if (geometry.drawingPoints) {\n shape.drawingPoints = geometry.drawingPoints.map((point) => ({ ...point }));\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { MapConfig, WardleyMap } from \"@miragon/wardley-schema-model\";\nimport type WardleyExporter from \"../io/WardleyExporter.js\";\nimport type { CommittedShapeFields } from \"../io/WardleyExporter.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\n\n/** The config fields a live preview changes: the plot size, the X-axis stage labels. */\nexport type PreviewedField = \"size\" | \"evolutionLabels\";\n\n/**\n * Fired before a command changes the document: `preExecute` for a command, `execute` for a redo\n * (which skips `preExecute`), `revert` for an undo.\n */\nexport const COMMAND_START_EVENTS = [\n \"commandStack.preExecute\",\n \"commandStack.execute\",\n \"commandStack.revert\",\n];\n\n/** Ahead of the other listeners of these events; the command's handler runs after all of them. */\nexport const PUT_BACK_PRIORITY = 10_000;\n\n/**\n * The document as it was committed while a live preview (a plot-resize drag, the size or the axis\n * labels being typed into a popover, the drag of an evolve target or a label) shows something else\n * on the canvas. A host autosaves the export at any moment, also mid-drag, and must store the\n * document, never the preview.\n */\nexport default class LivePreview {\n static $inject = [\"eventBus\", \"wardleyExporter\"];\n\n private committed: WardleyMap | undefined;\n private readonly previewed = new Set<PreviewedField>();\n private readonly committedShapes = new Map<WardleyShape, CommittedShapeFields>();\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly exporter: WardleyExporter,\n ) {\n eventBus.on([\"import.render.start\", \"diagram.clear\"], () => this.endAll());\n // A command can land under an axis-label preview (a title a host sets) and changes the\n // document there; the preview itself only ever changes its own fields. A size preview is put\n // back before any command instead (MapResizeHandles, WardleyBaseViewer), and so is a shape's.\n eventBus.on(\"commandStack.changed\", () => {\n if (this.committed) this.committed = this.withCommittedFields(this.exportCommitted());\n });\n }\n\n /** Before a preview changes `field` on the canvas: keeps the document as it is now. */\n begin(field: PreviewedField): void {\n this.committed ??= this.exportCommitted();\n this.previewed.add(field);\n }\n\n /**\n * The canvas shows the committed `field` again (its preview was put back or is being\n * committed). The preview of the other field may still be open and keeps its committed value.\n */\n end(field: PreviewedField): void {\n this.previewed.delete(field);\n if (!this.previewed.size) this.committed = undefined;\n }\n\n /**\n * Before a drag previews an evolve target or a label offset on `shape`: keeps both as the\n * document has them, from the first preview until `putBackShape`. Returns the kept ones, which\n * the preview builds on.\n */\n beginShape(shape: WardleyShape): CommittedShapeFields {\n let committed = this.committedShapes.get(shape);\n if (!committed) {\n committed = { movement: shape.movement, labelOffset: shape.labelOffset };\n this.committedShapes.set(shape, committed);\n }\n return committed;\n }\n\n /** Whether a drag previews on `shape`. */\n previewsShape(shape: WardleyShape): boolean {\n return this.committedShapes.has(shape);\n }\n\n /** Shows `shape` as the document has it again, if a drag previews on it. */\n putBackShape(shape: WardleyShape): void {\n const committed = this.committedShapes.get(shape);\n if (!committed) return;\n this.committedShapes.delete(shape);\n if (committed.movement) shape.movement = committed.movement;\n else delete shape.movement;\n if (committed.labelOffset) shape.labelOffset = committed.labelOffset;\n else delete shape.labelOffset;\n this.eventBus.fire(\"element.changed\", { element: shape });\n }\n\n /** The committed document while a preview is open, `undefined` while none is. */\n committedMap(): WardleyMap | undefined {\n if (this.committed) return this.committed;\n return this.committedShapes.size ? this.exportCommitted() : undefined;\n }\n\n private exportCommitted(): WardleyMap {\n return this.exporter.export(this.committedShapes);\n }\n\n private endAll(): void {\n this.previewed.clear();\n this.committed = undefined;\n this.committedShapes.clear();\n }\n\n private withCommittedFields(live: WardleyMap): WardleyMap {\n const config: Record<string, unknown> = { ...live.config };\n const committedConfig = this.committed?.config as Partial<MapConfig> | undefined;\n for (const field of this.previewed) {\n if (committedConfig?.[field] === undefined) delete config[field];\n else config[field] = committedConfig[field];\n }\n return { ...live, config: config as unknown as MapConfig };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport LivePreview from \"./LivePreview.js\";\n\n/** The committed document behind a live preview (map size, axis labels, evolve targets, labels). */\nexport const livePreviewModule: ModuleDeclaration = {\n wardleyLivePreview: [\"type\", LivePreview],\n};\n\nexport { default as LivePreview, COMMAND_START_EVENTS, PUT_BACK_PRIORITY } from \"./LivePreview.js\";\n","import RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\n\n/**\n * Fired with `{ readOnly, shown }` whenever the lock changes, and once more when the marks of a lock\n * set with `delayMs` show.\n */\nexport const READ_ONLY_CHANGED = \"wardley.readOnly.changed\";\n\nexport interface WardleyReadOnlyOptions {\n /** How long the palette's marks of the lock wait (default 0); the lock itself holds at once. */\n delayMs?: number | undefined;\n}\n\n/** On the viewer container while locked: the CSS hides the editing handles. */\nconst LOCKED_CLASS = \"wardley-read-only\";\n\n/** Ahead of every rule of the notation, so nothing can allow what the lock forbids. */\nconst VETO_PRIORITY = 5000;\n\nconst EDIT_RULES = [\n \"elements.move\",\n \"shape.move\",\n \"shape.create\",\n \"elements.create\",\n \"shape.resize\",\n \"shape.append\",\n \"shape.replace\",\n \"connection.start\",\n \"connection.create\",\n \"connection.reconnect\",\n \"connection.reconnectStart\",\n \"connection.reconnectEnd\",\n \"connection.updateWaypoints\",\n \"elements.delete\",\n];\n\ninterface Closable {\n close(): void;\n}\n\ninterface Cancellable {\n cancel(): void;\n}\n\n/**\n * Locks every edit on the canvas while a host cannot save what the canvas would change: an\n * invalid file in an IDE shows the last valid map read-only until the text is valid again (guide\n * §13.5). The rules veto move, resize, create, connect and delete; the context pad, the label,\n * link and colour editors, the evolve, label and drawing handles, the map-size handles, the draw\n * tool and the edit keys ask `isReadOnly()`. Selection, zoom, pan, copy and export stay. Guide\n * §13.5 shows the lock of an invalid import only after 800ms without a valid one, so typing beside\n * the canvas does not flicker: `delayMs` holds back the palette's marks (`isReadOnlyShown()`), as\n * the shell's `setReadOnly` does.\n */\nexport default class WardleyReadOnly extends RuleProvider {\n static override $inject = [\"eventBus\", \"canvas\", \"injector\"];\n\n private locked = false;\n private shown = false;\n private showTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n private readonly bus: EventBus,\n private readonly canvas: Canvas,\n private readonly injector: Injector,\n ) {\n super(bus);\n bus.on(\"diagram.destroy\", () => this.stopShowTimer());\n }\n\n override init(): void {\n // `this.locked` is read when a rule runs; the field is not initialized yet while init() runs.\n this.addRule(EDIT_RULES, VETO_PRIORITY, () => (this.locked ? false : undefined));\n }\n\n isReadOnly(): boolean {\n return this.locked;\n }\n\n /** Whether the palette marks the lock: from `setReadOnly(true)` on, or once its `delayMs` passed. */\n isReadOnlyShown(): boolean {\n return this.shown;\n }\n\n /**\n * `true` locks at once and shows the palette's marks after `delayMs` (default 0); a call while the\n * delay runs keeps its timer, as typing sends one invalid import after the other. `false` unlocks\n * and takes the marks off at once.\n */\n setReadOnly(readOnly: boolean, options?: WardleyReadOnlyOptions): void {\n if (!readOnly) {\n this.stopShowTimer();\n if (!this.locked) return;\n this.locked = false;\n this.shown = false;\n this.outerContainer().classList.remove(LOCKED_CLASS);\n this.announce();\n return;\n }\n const locking = !this.locked;\n if (locking) {\n this.locked = true;\n this.outerContainer().classList.add(LOCKED_CLASS);\n this.endInteractions();\n }\n const delayMs = options?.delayMs ?? 0;\n const shownOrWaiting = this.shown || this.showTimer !== undefined;\n if (!shownOrWaiting && delayMs > 0) {\n this.showTimer = setTimeout(() => {\n this.showTimer = undefined;\n this.shown = true;\n this.announce();\n }, delayMs);\n }\n const showsNow = !shownOrWaiting && !(delayMs > 0);\n if (showsNow) this.shown = true;\n if (locking || showsNow) this.announce();\n }\n\n private announce(): void {\n this.bus.fire(READ_ONLY_CHANGED, { readOnly: this.locked, shown: this.shown });\n }\n\n private stopShowTimer(): void {\n clearTimeout(this.showTimer);\n this.showTimer = undefined;\n }\n\n /** Whatever is open or running would otherwise still change the map. */\n private endInteractions(): void {\n this.injector.get<Cancellable | null>(\"dragging\", false)?.cancel();\n for (const name of [\"contextPad\", \"popupMenu\", \"wardleyColorPicker\"]) {\n this.injector.get<Closable | null>(name, false)?.close();\n }\n for (const name of [\"wardleyLabelEditing\", \"wardleyLinkEditing\", \"wardleyDrawTool\"]) {\n this.injector.get<Cancellable | null>(name, false)?.cancel();\n }\n }\n\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n}\n","import type { Injector } from \"didi\";\nimport type { ModuleDeclaration } from \"didi\";\nimport WardleyReadOnly from \"./WardleyReadOnly.js\";\n\n/** The edit lock of a canvas that shows a map the host cannot save (guide §13.5). */\nexport const readOnlyModule: ModuleDeclaration = {\n __init__: [\"wardleyReadOnly\"],\n wardleyReadOnly: [\"type\", WardleyReadOnly],\n};\n\n/** Whether the canvas is locked; false where the editor has no lock. */\nexport function isReadOnly(injector: Injector): boolean {\n return injector.get<WardleyReadOnly | null>(\"wardleyReadOnly\", false)?.isReadOnly() === true;\n}\n\n/** Whether the palette marks the lock, at once or after its `delayMs`; false without a lock. */\nexport function isReadOnlyShown(injector: Injector): boolean {\n return injector.get<WardleyReadOnly | null>(\"wardleyReadOnly\", false)?.isReadOnlyShown() === true;\n}\n\nexport { default as WardleyReadOnly, READ_ONLY_CHANGED } from \"./WardleyReadOnly.js\";\nexport type { WardleyReadOnlyOptions } from \"./WardleyReadOnly.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\n\n/** The focusable canvas svg diagram-js renders into its container. */\nexport function canvasSvg(canvas: Canvas): SVGElement | null {\n return (\n (canvas as unknown as { _svg?: SVGElement })._svg ??\n canvas.getContainer().querySelector<SVGElement>(\":scope > svg\")\n );\n}\n\n/**\n * Whether a keydown is aimed at `root` or an element inside it and still free to act on. A keydown\n * without a key (autofill), one a listener before this one took, and IME composition stay with the\n * page, and so does a key inside an `inert` subtree or on a `root` that an ancestor with\n * `display: none` or `visibility: hidden` hides: Chromium moves the focus off an element the host\n * made inert or hid only at its next rendering update, so until then the key still reaches it.\n */\nexport function isKeyAimedAt(event: KeyboardEvent, root: Node | null | undefined): boolean {\n const target = event.target;\n return (\n typeof event.key === \"string\" &&\n !event.defaultPrevented &&\n !event.isComposing &&\n target instanceof Node &&\n !!root?.contains(target) &&\n !liesInInertSubtree(target) &&\n isRendered(root)\n );\n}\n\n/**\n * Whether a key reaches an element the host made inert or hid, before the browser moved the focus\n * off it. The map's own chrome (context pad, editors, popovers, colour picker, popup menu) leaves\n * such a key to the page, as the canvas and the palette do. Its buttons ask it of their click too:\n * Enter on a focused button still clicks it once the host hid it.\n */\nexport function isKeyOnHiddenTarget(event: Event): boolean {\n const target = event.target;\n return target instanceof Node && (liesInInertSubtree(target) || !isRendered(target));\n}\n\nconst menusLeavingHiddenKeys = new WeakSet<object>();\n\n/**\n * diagram-js's popup menu runs its selected entry on Enter, also on one the browser still sends to\n * a menu the host made inert or hid: such a key picks nothing and goes on to the page unprevented.\n */\nexport function leaveKeysOnHiddenMenuToPage(popupMenu: Pick<PopupMenu, \"trigger\">): void {\n if (menusLeavingHiddenKeys.has(popupMenu)) return;\n menusLeavingHiddenKeys.add(popupMenu);\n const trigger = popupMenu.trigger.bind(popupMenu);\n popupMenu.trigger = (event, entry, action) =>\n isKeyOnHiddenTarget(event) ? undefined : trigger(event, entry, action);\n}\n\nfunction liesInInertSubtree(node: Node): boolean {\n const element = node instanceof Element ? node : node.parentElement;\n return !!element?.closest(\"[inert]\");\n}\n\n/**\n * A key is the canvas's only while the canvas `<svg>` has the focus, as with diagram-js' own\n * keyboard: the svg holds no editor, palette, context pad or popup, so they keep their keys, and so\n * do a host's controls inside the container or next to it, a page with nothing focused and a canvas\n * the host made inert or hid.\n */\nexport function isCanvasKey(event: KeyboardEvent, canvas: Canvas): boolean {\n return isKeyAimedAt(event, canvasSvg(canvas));\n}\n\n/**\n * `opacity: 0` keeps the focus and the keys. Without `checkVisibility` (Safari before 17.4) the\n * browser's focus fixup alone has to do.\n */\nfunction isRendered(node: Node): boolean {\n return (\n !(node instanceof Element) ||\n typeof node.checkVisibility !== \"function\" ||\n node.checkVisibility({ visibilityProperty: true })\n );\n}\n\n/**\n * Moves keyboard focus to the canvas after a pointer gesture or an editor commit. Pointer work\n * must not light up the keyboard focus ring around the whole viewport, and a press that suppressed\n * the browser's own focus change must still take focus away from host inputs (title, size\n * fields), or Delete/Undo would edit those instead of the map.\n */\nexport function focusCanvasWithoutRing(canvas: Canvas): void {\n const svg = canvasSvg(canvas);\n if (!svg) {\n canvas.focus();\n return;\n }\n svg.focus({ preventScroll: true, focusVisible: false } as FocusOptions);\n}\n\nlet lastInteraction: \"pointer\" | \"keyboard\" = \"pointer\";\nlet modalityTracked = false;\n\n/**\n * Starts following whether the user last used the pointer or the keyboard (idempotent). Editors\n * opened with the pointer hand focus back without the keyboard focus ring.\n */\nexport function trackInputModality(): void {\n if (modalityTracked || typeof document === \"undefined\") return;\n modalityTracked = true;\n document.addEventListener(\"pointerdown\", () => (lastInteraction = \"pointer\"), true);\n document.addEventListener(\"mousedown\", () => (lastInteraction = \"pointer\"), true);\n document.addEventListener(\n \"keydown\",\n (event) => {\n // Typing into an editor says nothing about how it was opened.\n if (!(event.target instanceof HTMLElement && event.target.closest(\"input, textarea\"))) {\n lastInteraction = \"keyboard\";\n }\n },\n true,\n );\n}\n\nexport function lastInteractionWasPointer(): boolean {\n return lastInteraction === \"pointer\";\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport { canvasSvg } from \"./canvasFocus.js\";\n\n/** Names the focusable canvas for assistive technology (it is otherwise an anonymous svg). */\nexport default function describeCanvas(canvas: Canvas): void {\n const svg = canvasSvg(canvas);\n if (!svg) return;\n svg.setAttribute(\"role\", \"application\");\n svg.setAttribute(\"aria-roledescription\", \"Wardley map\");\n svg.setAttribute(\"aria-label\", \"Map canvas\");\n}\ndescribeCanvas.$inject = [\"canvas\"];\n","import type { ModuleDeclaration } from \"didi\";\nimport describeCanvas from \"./describeCanvas.js\";\n\n/** Names the canvas for assistive technology (role, role description, label). */\nexport const canvasAccessibilityModule: ModuleDeclaration = {\n __init__: [describeCanvas],\n};\n\nexport {\n canvasSvg,\n focusCanvasWithoutRing,\n isCanvasKey,\n isKeyAimedAt,\n isKeyOnHiddenTarget,\n lastInteractionWasPointer,\n leaveKeysOnHiddenMenuToPage,\n trackInputModality,\n} from \"./canvasFocus.js\";\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport {\n MAP_SIZE_PRESETS,\n PLOT_MAX,\n PLOT_MIN,\n normalizeMapSize,\n type MapSize,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { PLOT } from \"../draw/styles.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type MapProjection from \"./MapProjection.js\";\nimport type { ProjectionSnapshot } from \"./MapProjection.js\";\nimport { COMMAND_START_EVENTS, PUT_BACK_PRIORITY } from \"../live-preview/index.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\n\nexport const MAP_RESIZE_PREFIX = \"wardley.mapResize\";\n\n/** Above the axes (-1), below the element planes (0): elements at the plot edge win hit tests. */\nconst LAYER_NAME = \"wardley-map-resize\";\nconst LAYER_INDEX = -0.5;\n\nconst SNAP_STEP = 10;\nconst PRESET_SNAP_DISTANCE = 12;\n/** Handle sizes in screen px: they keep a grabbable size at every zoom level. */\nconst EDGE_HIT_WIDTH = 8;\nconst CORNER_HIT_SIZE = 16;\nconst CORNER_VISUAL_SIZE = 10;\nconst BADGE_OFFSET = 16;\n\nexport type ResizeAxis = \"x\" | \"y\" | \"xy\";\n\nconst CURSORS: Record<ResizeAxis, string> = {\n x: \"ew-resize\",\n y: \"ns-resize\",\n xy: \"nwse-resize\",\n};\n\ninterface MapResizeContext {\n axis: ResizeAxis;\n startSize: MapSize;\n snapshot?: ProjectionSnapshot;\n model?: WardleyMap;\n size?: MapSize;\n committed?: boolean;\n}\n\ninterface MapResizeEvent {\n context: MapResizeContext;\n dx: number;\n dy: number;\n originalEvent?: MouseEvent;\n}\n\ninterface ModifierKeys {\n /** Keep the start aspect ratio. */\n keepAspectRatio: boolean;\n /** Free size: no 10px steps, no preset magnet. */\n disableSnapping: boolean;\n}\n\n/** The part of `wardleyModeling` the handles use (by DI name, to keep the features decoupled). */\ninterface MapResizeModeling {\n resizeMap(size: MapSize | undefined): void;\n}\n\ninterface Handle {\n readonly group: SVGGElement;\n readonly hit: SVGRectElement;\n readonly visual: SVGElement;\n}\n\nfunction round(value: number, step: number): number {\n return Math.round(value / step) * step;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return value < min ? min : value > max ? max : value;\n}\n\n/**\n * Paint-free presentation attributes: the SVG export clones this layer without the stylesheet,\n * where a bare rect would fill black. Set as attributes (tiny-svg would inline them as style),\n * so the stylesheet still wins and shows the handles on hover.\n */\nfunction withoutPaint<T extends SVGElement>(element: T): T {\n element.setAttribute(\"fill\", \"none\");\n element.setAttribute(\"stroke\", \"none\");\n element.setAttribute(\"opacity\", \"0\");\n return element;\n}\n\n/**\n * The size a drag from `start` by (dx, dy) on `axis` asks for: 10px steps with a magnetic pull\n * towards the presets, Shift keeps the start aspect ratio, always whole pixels within the limits.\n */\nexport function sizeForDrag(\n start: MapSize,\n axis: ResizeAxis,\n dx: number,\n dy: number,\n keys: ModifierKeys = { keepAspectRatio: false, disableSnapping: false },\n): MapSize {\n let width = axis === \"y\" ? start.width : start.width + dx;\n let height = axis === \"x\" ? start.height : start.height + dy;\n const step = keys.disableSnapping ? 1 : SNAP_STEP;\n\n if (keys.keepAspectRatio) {\n const ratio = start.width / start.height;\n const widthDrives =\n axis === \"x\" ||\n (axis === \"xy\" &&\n Math.abs(width - start.width) / start.width >=\n Math.abs(height - start.height) / start.height);\n if (widthDrives) {\n width = clamp(round(width, step), PLOT_MIN.width, PLOT_MAX.width);\n height = width / ratio;\n } else {\n height = clamp(round(height, step), PLOT_MIN.height, PLOT_MAX.height);\n width = height * ratio;\n }\n return normalizeMapSize(width, height);\n }\n\n if (!keys.disableSnapping) {\n const preset = MAP_SIZE_PRESETS.find(\n (candidate) =>\n Math.abs(width - candidate.width) <= PRESET_SNAP_DISTANCE &&\n Math.abs(height - candidate.height) <= PRESET_SNAP_DISTANCE,\n );\n if (preset) return { width: preset.width, height: preset.height };\n }\n return normalizeMapSize(\n axis === \"y\" ? width : round(width, step),\n axis === \"x\" ? height : round(height, step),\n );\n}\n\n/** \"1440 × 900 · Large\" — the preset name only when the size matches one exactly. */\nexport function sizeLabel(size: MapSize): string {\n const preset = MAP_SIZE_PRESETS.find(\n (candidate) => candidate.width === size.width && candidate.height === size.height,\n );\n return `${size.width} × ${size.height}${preset ? ` · ${preset.name}` : \"\"}`;\n}\n\n/**\n * Direct manipulation of the map size: handles on the plot's right edge, bottom edge and\n * bottom-right corner. The drag previews live (grid and shapes re-projected, no command stack);\n * on release the preview is undone and exactly ONE `wardley.map.resize` runs, so a drag is one\n * undo step. Esc cancels; a double-click on the corner resets to the default size.\n */\nexport default class MapResizeHandles {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"evolutionGrid\",\n \"dragging\",\n \"wardleyMapProjection\",\n \"wardleyModeling\",\n \"injector\",\n ];\n\n private readonly layer: SVGGElement;\n private readonly handles: Record<ResizeAxis, Handle>;\n private badge: HTMLElement | undefined;\n private scale: number | undefined;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly dragging: Dragging,\n private readonly projection: MapProjection,\n private readonly modeling: MapResizeModeling,\n private readonly injector: Injector,\n ) {\n this.layer = svgCreate(\"g\", { class: \"wardley-map-resize\" }) as SVGGElement;\n svgAppend(canvas.getLayer(LAYER_NAME, LAYER_INDEX), this.layer);\n this.handles = {\n x: this.createHandle(\"x\"),\n y: this.createHandle(\"y\"),\n xy: this.createHandle(\"xy\"),\n };\n this.handles.xy.group.addEventListener(\"dblclick\", (event) => {\n event.stopPropagation();\n event.preventDefault();\n if (isReadOnly(this.injector)) return;\n this.modeling.resizeMap(undefined);\n });\n\n eventBus.on([\"import.done\", \"wardley.config.changed\"], () => this.render());\n eventBus.on(\"canvas.viewbox.changed\", (event: { viewbox?: { scale?: number } }) => {\n const scale = event.viewbox?.scale;\n if (scale === this.scale) return;\n this.scale = scale;\n this.render();\n });\n eventBus.on(`${MAP_RESIZE_PREFIX}.start`, (event: MapResizeEvent) => this.onStart(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.move`, (event: MapResizeEvent) => this.onMove(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.end`, (event: MapResizeEvent) => this.onEnd(event));\n eventBus.on(`${MAP_RESIZE_PREFIX}.cleanup`, (event: MapResizeEvent) => this.onCleanup(event));\n // The preview re-projects the map the drag started with and puts it back on release, which\n // would overwrite a command in between (an undo or a delete pressed mid-drag) and leave the\n // history out of step with the document: the drag ends first, without resizing.\n eventBus.on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => this.cancelPreviewingDrag());\n this.render();\n }\n\n private cancelPreviewingDrag(): void {\n const drag = this.dragging.context() as {\n prefix?: string;\n data?: { context?: MapResizeContext };\n } | null;\n if (drag?.prefix !== MAP_RESIZE_PREFIX) return;\n const context = drag.data?.context;\n if (context?.snapshot && !context.committed) this.dragging.cancel(true);\n }\n\n /** Starts a resize drag on `axis` (also usable programmatically, e.g. from tests). */\n start(event: MouseEvent, axis: ResizeAxis): void {\n if (isReadOnly(this.injector)) return;\n const context: MapResizeContext = { axis, startSize: this.grid.getPlotSize() };\n this.dragging.init(event, MAP_RESIZE_PREFIX, {\n cursor: CURSORS[axis],\n keepSelection: true,\n data: { context },\n });\n }\n\n private createHandle(axis: ResizeAxis): Handle {\n const group = svgCreate(\"g\", {\n class: `wardley-map-resize-handle wardley-map-resize-${axis}`,\n \"data-axis\": axis,\n }) as SVGGElement;\n const visual = withoutPaint(\n svgCreate(axis === \"xy\" ? \"rect\" : \"line\", { class: \"wardley-map-resize-visual\" }),\n );\n const hit = withoutPaint(\n svgCreate(\"rect\", { class: \"wardley-map-resize-hit\" }) as SVGRectElement,\n );\n svgAppend(group, visual);\n svgAppend(group, hit);\n svgAppend(this.layer, group);\n // Own listener on the handle: stopping here keeps the canvas (pan, lasso, deselect) from\n // also reacting to this mousedown, and the prevented default from focusing it, whose keys\n // (Cmd/Ctrl+Z) act only while it has the focus.\n group.addEventListener(\"mousedown\", (event: MouseEvent) => {\n if (event.button !== 0 || this.dragging.context()) return;\n event.stopPropagation();\n event.preventDefault();\n focusCanvasWithoutRing(this.canvas);\n this.start(event, axis);\n });\n return { group, hit, visual };\n }\n\n private render(): void {\n const visible = this.projection.root() !== undefined;\n svgAttr(this.layer, { display: visible ? \"inline\" : \"none\" });\n if (!visible) return;\n\n const { width, height } = this.grid.getPlotSize();\n const left = PLOT.marginLeft;\n const top = PLOT.marginTop;\n const right = left + width;\n const bottom = top + height;\n const screenPixel = 1 / this.currentScale();\n const edgeHitWidth = EDGE_HIT_WIDTH * screenPixel;\n const half = edgeHitWidth / 2;\n const cornerHitSize = CORNER_HIT_SIZE * screenPixel;\n const cornerHalf = cornerHitSize / 2;\n const cornerVisualSize = CORNER_VISUAL_SIZE * screenPixel;\n\n // The edges stop short of the corner (its own handle) and of the axis arrowheads.\n svgAttr(this.handles.x.hit, {\n x: right - half,\n y: top,\n width: edgeHitWidth,\n height: Math.max(height - cornerHalf, 0),\n });\n svgAttr(this.handles.x.visual, { x1: right, y1: top, x2: right, y2: bottom });\n svgAttr(this.handles.y.hit, {\n x: left,\n y: bottom - half,\n width: Math.max(width - cornerHalf, 0),\n height: edgeHitWidth,\n });\n svgAttr(this.handles.y.visual, { x1: left, y1: bottom, x2: right, y2: bottom });\n svgAttr(this.handles.xy.hit, {\n x: right - cornerHalf,\n y: bottom - cornerHalf,\n width: cornerHitSize,\n height: cornerHitSize,\n });\n svgAttr(this.handles.xy.visual, {\n x: right - cornerVisualSize / 2,\n y: bottom - cornerVisualSize / 2,\n width: cornerVisualSize,\n height: cornerVisualSize,\n });\n }\n\n private currentScale(): number {\n if (this.scale === undefined) {\n try {\n this.scale = this.canvas.viewbox().scale;\n } catch {\n return 1; // detached container: nothing to measure yet\n }\n }\n return Number.isFinite(this.scale) && this.scale > 0 ? this.scale : 1;\n }\n\n private onStart(event: MapResizeEvent): void {\n const context = event.context;\n const snapshot = this.projection.snapshot();\n if (!snapshot) return;\n context.snapshot = snapshot;\n context.model = this.projection.captureModel();\n this.layer.classList.add(\"is-dragging\");\n }\n\n private onMove(event: MapResizeEvent): void {\n const context = event.context;\n if (!context.snapshot || !context.model) return;\n const size = sizeForDrag(context.startSize, context.axis, event.dx, event.dy, {\n keepAspectRatio: event.originalEvent?.shiftKey === true,\n disableSnapping: event.originalEvent?.altKey === true,\n });\n this.showBadge(size, event.originalEvent);\n if (context.size?.width === size.width && context.size.height === size.height) return;\n context.size = size;\n const businessObject = this.projection.withSize(size);\n if (!businessObject) return;\n this.projection.redraw(\n this.projection.apply(businessObject, context.model, { transient: true }),\n );\n }\n\n private onEnd(event: MapResizeEvent): void {\n const context = event.context;\n if (!context.snapshot) return;\n // Undo the preview first: the command must capture the real start state as its old state.\n this.projection.redraw(this.projection.restore(context.snapshot, { transient: true }));\n context.committed = true;\n const { size, startSize } = context;\n if (size && (size.width !== startSize.width || size.height !== startSize.height)) {\n this.modeling.resizeMap(size);\n }\n }\n\n private onCleanup(event: MapResizeEvent): void {\n const context = event.context;\n // Transient like the preview it undoes: the document never changed, so the view stays put.\n if (context.snapshot && !context.committed) {\n this.projection.redraw(this.projection.restore(context.snapshot, { transient: true }));\n }\n this.layer.classList.remove(\"is-dragging\");\n this.hideBadge();\n }\n\n private showBadge(size: MapSize, originalEvent: MouseEvent | undefined): void {\n const container = this.canvas.getContainer();\n if (!this.badge) {\n this.badge = document.createElement(\"div\");\n this.badge.className = \"wardley-map-resize-badge\";\n this.badge.setAttribute(\"role\", \"status\");\n container.appendChild(this.badge);\n }\n this.badge.textContent = sizeLabel(size);\n this.badge.hidden = false;\n if (originalEvent) {\n const bounds = container.getBoundingClientRect();\n this.badge.style.left = `${originalEvent.clientX - bounds.left + BADGE_OFFSET}px`;\n this.badge.style.top = `${originalEvent.clientY - bounds.top + BADGE_OFFSET}px`;\n }\n }\n\n private hideBadge(): void {\n if (this.badge) this.badge.hidden = true;\n }\n}\n","import AutoScroll from \"diagram-js/lib/features/auto-scroll/AutoScroll\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Injector } from \"didi\";\nimport { MAP_RESIZE_PREFIX } from \"./MapResizeHandles.js\";\n\n/**\n * diagram-js AutoScroll, except while the map is being resized: scrolling under a dragged plot\n * corner detaches it from the pointer, and the size jumps on the next move.\n */\nexport default class ResizeAwareAutoScroll extends AutoScroll {\n static override $inject = [\"config.autoScroll\", \"eventBus\", \"canvas\", \"injector\"];\n\n constructor(\n config: unknown,\n eventBus: EventBus,\n canvas: Canvas,\n private readonly injector: Injector,\n ) {\n super(config, eventBus, canvas);\n }\n\n override startScroll(point: Parameters<AutoScroll[\"startScroll\"]>[0]): void {\n const dragging = this.injector.get<Dragging | null>(\"dragging\", false);\n if (dragging?.context()?.prefix === MAP_RESIZE_PREFIX) {\n this.stopScroll();\n return;\n }\n super.startScroll(point);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport DraggingModule from \"diagram-js/lib/features/dragging\";\nimport MapProjection from \"./MapProjection.js\";\nimport MapResizeHandles from \"./MapResizeHandles.js\";\nimport { livePreviewModule } from \"../live-preview/index.js\";\n\n/** In-place re-projection of all shapes onto a new plot size (used by `wardley.map.resize`). */\nexport const mapProjectionModule: ModuleDeclaration = {\n __depends__: [livePreviewModule],\n wardleyMapProjection: [\"type\", MapProjection],\n};\n\n/**\n * Plot edge/corner handles to resize the map by dragging (Modeler only). Needs the\n * `wardleyModeling` service, i.e. load it together with `wardleyModelingModule`.\n */\nexport const mapResizeModule: ModuleDeclaration = {\n __depends__: [DraggingModule, mapProjectionModule],\n __init__: [\"mapResizeHandles\"],\n mapResizeHandles: [\"type\", MapResizeHandles],\n};\n\nexport {\n default as MapResizeHandles,\n MAP_RESIZE_PREFIX,\n sizeForDrag,\n sizeLabel,\n} from \"./MapResizeHandles.js\";\nexport type { ResizeAxis } from \"./MapResizeHandles.js\";\nexport {\n default as MapProjection,\n configWithSize,\n withoutRawSizeStatements,\n wardleyRootOf,\n} from \"./MapProjection.js\";\nexport type { ProjectionSnapshot, WardleyRoot } from \"./MapProjection.js\";\nexport { default as ResizeAwareAutoScroll } from \"./ResizeAwareAutoScroll.js\";\n","import type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type { MapConfig } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../../evolution-grid/EvolutionGrid.js\";\nimport { wardleyRootOf } from \"../../map-resize/index.js\";\n\n/**\n * Config fields a `wardley.config.update` may change; `undefined` removes the field. The size is\n * excluded on purpose: it needs the re-projection of `wardley.map.resize`.\n */\nexport type MapConfigUpdate = {\n -readonly [Key in Exclude<keyof MapConfig, \"size\">]?: MapConfig[Key] | undefined;\n};\n\nexport interface UpdateConfigContext {\n properties: MapConfigUpdate;\n /** set internally by the handler (for revert). */\n oldProperties?: MapConfigUpdate;\n}\n\n/**\n * Writes `update` into the root's config (`undefined` removes a field; `size` is left alone, it\n * needs the re-projection of `wardley.map.resize`), redraws the axes and fires\n * `wardley.config.changed`. Returns the previous values of exactly the written fields. The one place\n * a config changes in place: the undoable command and the viewers' direct path both use it.\n */\nexport function applyConfigUpdate(\n canvas: Canvas,\n grid: EvolutionGrid,\n eventBus: EventBus,\n update: MapConfigUpdate,\n options: { transient?: boolean } = {},\n): MapConfigUpdate {\n const root = wardleyRootOf(canvas);\n if (!root?.businessObject) return {};\n const previous: Record<string, unknown> = {};\n const config: Record<string, unknown> = { ...root.businessObject.config };\n for (const [key, value] of Object.entries(update)) {\n if (key === \"size\") continue;\n previous[key] = config[key];\n if (value === undefined) delete config[key];\n else config[key] = value;\n }\n const nextConfig = config as unknown as MapConfig;\n root.businessObject = { ...root.businessObject, config: nextConfig };\n grid.configure(nextConfig);\n grid.render();\n eventBus.fire(\"wardley.config.changed\", {\n config: nextConfig,\n ...(options.transient ? { transient: true } : {}),\n });\n return previous as MapConfigUpdate;\n}\n\n/**\n * Undoable change of map config fields (title, evolution labels, …). Only the given fields are\n * swapped, so it composes with any other config change in the undo history.\n */\nexport default class UpdateConfigHandler implements CommandHandler {\n static $inject = [\"canvas\", \"evolutionGrid\", \"eventBus\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n private readonly eventBus: EventBus,\n ) {}\n\n execute(context: UpdateConfigContext): ElementLike[] {\n context.oldProperties = this.apply(context.properties);\n return [];\n }\n\n revert(context: UpdateConfigContext): ElementLike[] {\n if (context.oldProperties) this.apply(context.oldProperties);\n return [];\n }\n\n private apply(properties: MapConfigUpdate): MapConfigUpdate {\n return applyConfigUpdate(this.canvas, this.grid, this.eventBus, properties);\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Injector } from \"didi\";\nimport { COMMAND_START_EVENTS } from \"../live-preview/index.js\";\n\n/** Fired as `{ active }` each time a gesture starts or ends (`InteractionChangedEvent`). */\nexport const INTERACTION_CHANGED = \"wardley.interaction.changed\";\n\nexport interface InteractionChangedEvent {\n active: boolean;\n}\n\n/**\n * The drags of a palette tool that only waits for its next press (the lasso from the palette or\n * `L`): no gesture yet. They hold no element of the map, so an import leaves such a tool armed, and\n * the user's next press still draws a lasso instead of panning or moving the element under the\n * pointer.\n */\nexport const ARMED_TOOL_PREFIXES: ReadonlySet<string> = new Set([\"lasso.selection\"]);\n\n/**\n * Ahead of every other listener of a drag or a command, so that what a drop or a command runs finds\n * the user's action marked.\n */\nexport const ACTION_MARK_PRIORITY = 100_000;\n\n/**\n * The steps after which the handler of the user's input goes on with the map: diagram-js's drag\n * after its init, start, drop, cancel and cleanup, and the code that ran a command after it.\n */\nconst HANDLER_GOES_ON_EVENTS = [\n \"drag.init\",\n \"drag.start\",\n \"drag.end\",\n \"drag.cancel\",\n \"drag.cleanup\",\n ...COMMAND_START_EVENTS,\n];\n\ntype DragContext = { prefix: string } | null;\n\n/**\n * Whether the user holds a gesture on the canvas, the `interaction` of `@miragon/modeler-api`: a\n * diagram-js drag past its threshold (a move, resize, connect, lasso, evolve or plot-corner drag, a\n * create from the palette or the context pad, also while its preview is over the palette) or one of\n * this renderer's own drags (a label, a point of a drawing, the evolve target), from its start until\n * its drop or cancel. A tool that only waits for its next press is none, and neither is a pan.\n *\n * It also marks the user's actions, and `afterUserAction()` lets an import wait until the running\n * one has finished, so that no step of it finds the map replaced under it (#248, #285, #305, #336):\n * - a drop, from the release until the drop has ended and the follow-ups it deferred to a later task\n * (the name editor of a create or an append with the pointer) have run;\n * - every other command, an undo or a redo, from its start until the code that ran it has returned:\n * a create without a pointer, the context pad's append with Enter, the save of a name editor, also\n * the one a press on the canvas makes, a delete, an undo or a redo that deselects what it removes.\n * Such an action defers no step: the next microtask ends it;\n * - the activation of a diagram-js drag (a move, a connect or the evolve placement of the context pad\n * past its threshold; a resize, a create from the palette, the context pad or a key, and a connect\n * with the key A at once), from its start until diagram-js's `Dragging.move` has returned: it\n * clears the selection after the start and goes on with the drag, so an import from the selection\n * listener there would cancel the drag under it. The import then ends the drag, as it ends any\n * running gesture. The next microtask ends this action too.\n */\nexport default class WardleyInteraction {\n static $inject = [\"eventBus\", \"injector\"];\n\n private gesture: object | null = null;\n private dropsRunning = 0;\n private settling: ReturnType<typeof setTimeout> | undefined;\n private handlerRunning = false;\n /** From one of `HANDLER_GOES_ON_EVENTS` or a gesture's start or end until its handler returned. */\n private handlerGoesOn = false;\n private readonly waiting: Array<() => void> = [];\n\n constructor(\n private readonly eventBus: EventBus,\n injector: Injector,\n ) {\n const dragging = injector.get<Dragging | null>(\"dragging\", false);\n if (dragging) this.followDragging(dragging);\n eventBus.on(COMMAND_START_EVENTS, ACTION_MARK_PRIORITY, () => this.handlerRuns());\n eventBus.on(HANDLER_GOES_ON_EVENTS, ACTION_MARK_PRIORITY, () => this.noteHandlerGoesOn());\n eventBus.on(\"diagram.destroy\", () => {\n clearTimeout(this.settling);\n this.settling = undefined;\n this.settled();\n });\n }\n\n /** True from a gesture's start until its drop or cancel. */\n isActive(): boolean {\n return this.gesture !== null;\n }\n\n /** One of the renderer's own drags passed its threshold. */\n begin(gesture: object): void {\n const wasActive = this.gesture !== null;\n this.gesture = gesture;\n if (!wasActive) this.changed(true);\n }\n\n /** The gesture ended without a drop: Escape, or its element was removed. */\n end(gesture: object): void {\n if (this.gesture !== gesture) return;\n this.gesture = null;\n this.changed(false);\n }\n\n /** The gesture's release: runs its drop, then ends it. */\n drop(gesture: object, run: () => void): void {\n this.dropStarts();\n try {\n run();\n } finally {\n this.endDrop(() => this.end(gesture));\n }\n }\n\n /**\n * Resolves once the user's running action has finished: a drop with the follow-ups it deferred to\n * a later task, and the code that ran a command or activated a drag; `undefined` while no action\n * runs.\n */\n afterUserAction(): Promise<void> | undefined {\n if (!this.actionRunning()) return undefined;\n return new Promise((resolve) => this.waiting.push(resolve));\n }\n\n /**\n * Runs `teardown` (the modeler's destroy) at once, or, while the handler of the user's input goes\n * on with the map, once that handler has returned. A host may destroy the modeler from any\n * listener, and these handlers read the canvas after one: diagram-js's `Dragging.move` clears\n * the selection after a drag's start and reads the drag again (#346), a drop's command runs\n * inside `Dragging.end`, whose `SelectionBehavior` then selects the new shape and whose cleanup\n * reads the canvas, a cancel cleans the drag up after the listeners of its `drag.cleanup` (#380),\n * a create without a pointer selects its element and opens its name editor (#373), and the\n * palette focuses the canvas after it started a create. The renderer's own drags (a label, a\n * point of a drawing, the evolve target) read the canvas after they reported their start or end\n * in the same way. The rest of the handler runs on the live map, which the teardown then takes\n * down, together with a drag that still runs.\n */\n tearDownAfterHandler(teardown: () => void): void {\n if (this.handlerGoesOn) queueMicrotask(teardown);\n else teardown();\n }\n\n private actionRunning(): boolean {\n return this.dropsRunning > 0 || this.settling !== undefined || this.handlerRunning;\n }\n\n private followDragging(dragging: Dragging): void {\n const current = () => dragging.context() as DragContext;\n let dropping: DragContext = null;\n let ending: DragContext = null;\n // diagram-js's Dragging.move fires the start, then clears the selection, then reads the drag's\n // context again, which a cancel from a selection listener would have emptied.\n this.eventBus.on(\"drag.start\", ACTION_MARK_PRIORITY, () => this.handlerRuns());\n // diagram-js fires the first move right after a start, also the start of a create that it\n // activates at once, and never after a start a listener refused.\n this.eventBus.on(\"drag.move\", ACTION_MARK_PRIORITY, () => {\n const context = current();\n if (!context || context === this.gesture || ARMED_TOOL_PREFIXES.has(context.prefix)) return;\n this.begin(context);\n });\n this.eventBus.on(\"drag.end\", ACTION_MARK_PRIORITY, () => {\n const context = current();\n if (!context || context !== this.gesture) return;\n dropping = context;\n this.dropStarts();\n });\n const ended = () => {\n const context = ending;\n ending = null;\n if (!context) return;\n if (context !== dropping) {\n this.end(context);\n return;\n }\n dropping = null;\n this.endDrop(() => this.end(context));\n };\n this.eventBus.on(\"drag.cleanup\", ACTION_MARK_PRIORITY, () => {\n const context = current();\n ending = context;\n // A cleanup listener that throws keeps diagram-js from firing the drag's end, and every\n // later import would wait for this drop.\n queueMicrotask(() => {\n if (ending === context) ended();\n });\n });\n // After the cleanup, once diagram-js has let go of the drag: a listener that imports from here\n // finds no drag left to cancel.\n this.eventBus.on([\"drag.ended\", \"drag.canceled\"], ACTION_MARK_PRIORITY, ended);\n }\n\n // A microtask runs only once the handler of the user's input has returned.\n private noteHandlerGoesOn(): void {\n if (this.handlerGoesOn) return;\n this.handlerGoesOn = true;\n queueMicrotask(() => {\n this.handlerGoesOn = false;\n });\n }\n\n private dropStarts(): void {\n this.dropsRunning += 1;\n }\n\n // The handler of the user's input goes on after the command it ran (a create selects its element\n // and opens its name editor, a press that saved a name starts its drag) and after the start of the\n // drag it activated, and a microtask runs only once it returned.\n private handlerRuns(): void {\n if (this.handlerRunning) return;\n this.handlerRunning = true;\n queueMicrotask(() => {\n this.handlerRunning = false;\n this.settleWhenIdle();\n });\n }\n\n // A listener of the gesture's end that throws must not keep the drop marked: every later import\n // would wait for it.\n private endDrop(endGesture: () => void): void {\n try {\n endGesture();\n } finally {\n this.dropEnds();\n }\n }\n\n // A drop defers some of its own steps by a task (the name editor of a create opens with\n // setTimeout), so the wait ends one task later, behind them.\n private dropEnds(): void {\n this.dropsRunning -= 1;\n if (this.dropsRunning > 0) return;\n clearTimeout(this.settling);\n this.settling = setTimeout(() => {\n this.settling = undefined;\n this.settleWhenIdle();\n }, 0);\n }\n\n private settleWhenIdle(): void {\n if (!this.actionRunning()) this.settled();\n }\n\n private settled(): void {\n for (const resolve of this.waiting.splice(0)) resolve();\n }\n\n // The renderer's own drags go on with the canvas after they reported their start or end, as\n // diagram-js's do.\n private changed(active: boolean): void {\n this.noteHandlerGoesOn();\n this.eventBus.fire(INTERACTION_CHANGED, { active } satisfies InteractionChangedEvent);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyInteraction from \"./WardleyInteraction.js\";\n\n/** Whether the user holds a gesture on the canvas, and when the user's action has finished. */\nexport const wardleyInteractionModule: ModuleDeclaration = {\n __init__: [\"wardleyInteraction\"],\n wardleyInteraction: [\"type\", WardleyInteraction],\n};\n\nexport {\n default as WardleyInteraction,\n ACTION_MARK_PRIORITY,\n ARMED_TOOL_PREFIXES,\n INTERACTION_CHANGED,\n type InteractionChangedEvent,\n} from \"./WardleyInteraction.js\";\n","import Diagram from \"diagram-js/lib/Diagram\";\nimport type { ModuleDeclaration } from \"didi\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Root } from \"diagram-js/lib/model/Types\";\nimport {\n DEFAULT_MAP_TITLE,\n normalizeEvolutionLabels,\n normalizeMapSize,\n sameEvolutionLabels,\n presetIdForSize,\n validateMap,\n type MapConfig,\n type MapSize,\n type MapSizePresetId,\n type WardleyMap,\n} from \"@miragon/wardley-schema-model\";\nimport { parseDSLWithDiagnostics, serializeDSL } from \"@miragon/wardley-dsl\";\nimport { saveSVG } from \"./io/saveSvg.js\";\nimport { exportBounds } from \"./io/exportBounds.js\";\nimport type WardleyImporter from \"./io/WardleyImporter.js\";\nimport type WardleyExporter from \"./io/WardleyExporter.js\";\nimport type EvolutionGrid from \"./evolution-grid/EvolutionGrid.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./io/types.js\";\nimport {\n configWithSize,\n wardleyRootOf,\n withoutRawSizeStatements,\n type default as MapProjection,\n type ProjectionSnapshot,\n} from \"./map-resize/MapProjection.js\";\nimport type WardleyModeling from \"./modeling/WardleyModeling.js\";\nimport type { FreeArea } from \"@miragon/modeler-api\";\nimport type { FreeRectConfig } from \"./free-rect/index.js\";\nimport { COMMAND_START_EVENTS, PUT_BACK_PRIORITY, type LivePreview } from \"./live-preview/index.js\";\nimport { applyConfigUpdate, type MapConfigUpdate } from \"./modeling/cmd/UpdateConfigHandler.js\";\nimport { ACTION_MARK_PRIORITY, ARMED_TOOL_PREFIXES } from \"./interaction/index.js\";\n\nexport interface WardleyViewerOptions {\n /** Host element. If missing, a detached <div> is created (can be attached later via attachTo). */\n container?: HTMLElement;\n width?: number | string;\n height?: number | string;\n /** Concatenated to the end of the module list (extension point, §12). */\n additionalModules?: ModuleDeclaration[];\n /**\n * The part of the canvas no host chrome covers (`@miragon/modeler-api` `freeArea`), read\n * whenever it is needed. `{ insets }` names what the chrome covers along the container's edges,\n * in px (e.g. `() => shell.fitInsets()` of the Miragon modeler shell): the import fits the plot\n * into the rest, panning keeps the map inside it, and keyboard creation places elements in its\n * centre. `{ center }` gives only that centre, in diagram coordinates. Default: the whole\n * container.\n */\n freeArea?: FreeArea | undefined;\n /**\n * Fit the plot into the view after every import. Default `true`; `false` when the host's chrome\n * fits the view itself.\n */\n fitOnImport?: boolean | undefined;\n /**\n * Bind Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z and Cmd/Ctrl+Y to the canvas history. Default `true`;\n * `false` leaves them to the host (e.g. VS Code, which owns the document's undo stack).\n */\n undoRedoKeys?: boolean | undefined;\n}\n\n/** The diagram config the viewer options stand for. */\nfunction diagramConfig(options: WardleyViewerOptions): Record<string, unknown> {\n const undoRedo = options.undoRedoKeys;\n const freeArea: FreeRectConfig | undefined = options.freeArea\n ? options.freeArea.insets\n ? { insets: options.freeArea.insets }\n : { center: options.freeArea.center }\n : undefined;\n return {\n ...(undoRedo === undefined ? {} : { wardleyKeyboard: { undoRedo } }),\n ...(freeArea ? { wardleyFreeRect: freeArea } : {}),\n ...(options.fitOnImport === false ? { wardleyImport: { fit: false } } : {}),\n };\n}\n\nexport type EventCallback<T = unknown> = (event: T) => void;\n\n/** The plot size as drawn, plus whether the map writes it explicitly (`size [w, h]`). */\nexport interface MapSizeInfo {\n width: number;\n height: number;\n isExplicit: boolean;\n presetId?: MapSizePresetId;\n}\n\n/** Payload of `wardley.config.changed`: title, size or axis labels changed. */\nexport interface WardleyConfigChangedEvent {\n config: MapConfig;\n /** A live preview (typing, dragging the plot corner): not a change to persist. */\n transient?: true;\n}\n\nexport interface SetEvolutionLabelsOptions {\n /** Live preview: applied directly, without an undo step (commit later without this flag). */\n transient?: boolean;\n}\n\nexport interface SetMapSizeOptions {\n /** Live preview: drawn at once, without an undo step (commit later without this flag). */\n transient?: boolean;\n}\n\ntype EvolutionLabels = readonly [string, string, string, string];\n\n/** diagram-js names its implicit roots so; an element of that id would replace the plane. */\nconst IMPLICIT_ROOT_PREFIX = \"__implicitroot\";\n\n/** `map`, validated, or a throw when the canvas cannot hold it. */\nfunction importableMap(map: WardleyMap): WardleyMap {\n const checked = validateMap(map);\n const reserved = [...checked.elements, ...checked.edges].find(\n ({ id }) => id === ROOT_ID || id.startsWith(IMPLICIT_ROOT_PREFIX),\n );\n if (reserved) throw new Error(`The id \"${reserved.id}\" is reserved for the canvas itself.`);\n return checked;\n}\n\nfunction sizeToCss(value: number | string): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\ntype DragContext = { prefix: string } | null;\n\n/**\n * Ends a running diagram-js drag (a move, resize, connect, lasso, evolve or plot-resize drag, a\n * create from the palette, the context pad or a quick-create key) the way Escape does. The gesture\n * holds the elements an import is about to replace, and diagram-js keeps it running across the\n * import: released after it, its command would fail half-way and leave the command stack stuck, so\n * no later edit would fire `commandStack.changed` again. The selection is not restored, since it\n * holds those elements too. The renderer's own drags (a label, a point of a drawing, the evolve\n * target) are no diagram-js drags: each ends by itself when the import removes its element.\n *\n * A drop that runs (`dropping`) is left to finish: its command has applied, and a caller of\n * `importDSL` or `importMap` that imports from that command's change listener would otherwise\n * cancel the drag inside diagram-js's own end of it, which then cleans up a drag that is gone and\n * throws. The collaborative `importText` waits until the drop has ended instead.\n */\nfunction cancelGesture(diagram: Diagram, dropping: DragContext): void {\n const dragging = diagram.get<Dragging | null>(\"dragging\", false);\n const gesture = dragging?.context() as DragContext | undefined;\n if (!dragging || !gesture || gesture === dropping) return;\n if (!ARMED_TOOL_PREFIXES.has(gesture.prefix)) dragging.cancel(false);\n}\n\n/**\n * Shared lifecycle & DI bootstrap for all Wardley viewers (analogous to bpmn-js BaseViewer, but OUR\n * OWN code — no bpmn-js as a dependency, §3.3). Subclasses only override `_getModules()` (a method\n * rather than a field, to sidestep the constructor/field initialization order). `attachTo`/`detach`\n * are own implementations (not a diagram-js primitive, §6.1).\n */\nexport abstract class WardleyBaseViewer {\n protected abstract _getModules(): ModuleDeclaration[];\n\n private _diagram: Diagram | undefined;\n private readonly _container: HTMLElement;\n private readonly _options: WardleyViewerOptions;\n /** Labels before the first transient preview, so the commit becomes one undo step from there. */\n private _labelsBeforePreview: { labels: EvolutionLabels | undefined } | undefined;\n /** The map before the first transient size preview, put back before the size is committed. */\n private _sizePreview: { snapshot: ProjectionSnapshot; model: WardleyMap } | undefined;\n /** The drag whose drop runs now, from its end until its cleanup. */\n private _dropping: DragContext = null;\n\n constructor(options: WardleyViewerOptions = {}) {\n this._options = options;\n this._container = this._createContainer(options);\n }\n\n private _createContainer(options: WardleyViewerOptions): HTMLElement {\n const container = options.container ?? document.createElement(\"div\");\n container.classList.add(\"wardley-container\");\n container.style.width = sizeToCss(options.width ?? \"100%\");\n container.style.height = sizeToCss(options.height ?? (options.container ? \"100%\" : \"600px\"));\n return container;\n }\n\n private _ensureDiagram(): Diagram {\n if (!this._diagram) {\n const modules = [...this._getModules(), ...(this._options.additionalModules ?? [])];\n this._diagram = new Diagram({\n canvas: { container: this._container },\n modules,\n ...diagramConfig(this._options),\n });\n // The size preview re-projects the map it started with and puts it back before its commit,\n // which would overwrite a command in between (a title a host sets mid-preview) and leave\n // the history out of step with the document: the preview goes first.\n this._diagram\n .get<EventBus>(\"eventBus\")\n .on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => this._putBackSizePreview());\n this._markDrops(this._diagram);\n }\n return this._diagram;\n }\n\n private _markDrops(diagram: Diagram): void {\n const dragging = diagram.get<Dragging | null>(\"dragging\", false);\n if (!dragging) return;\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n eventBus.on(\"drag.end\", ACTION_MARK_PRIORITY, () => {\n this._dropping = dragging.context() as DragContext;\n });\n eventBus.on(\"drag.cleanup\", ACTION_MARK_PRIORITY, () => {\n this._dropping = null;\n });\n }\n\n get<T>(name: string): T {\n return this._ensureDiagram().get<T>(name);\n }\n\n on<T = unknown>(event: string, callback: EventCallback<T>, priority = 1000): void {\n this.get<EventBus>(\"eventBus\").on(event, priority, callback as EventCallback);\n }\n\n off(event: string, callback: EventCallback): void {\n this.get<EventBus>(\"eventBus\").off(event, callback);\n }\n\n /**\n * Load a model into the canvas (replaces existing content). Rejects a map the canvas cannot\n * hold (invalid, or ids the canvas reserves for itself) before anything changes, so the current\n * map, its rendering and its undo history stay as they were. A gesture that runs ends first, as\n * on Escape, so its release applies nothing; an armed lasso tool stays armed, and an import from\n * the change listener of a drop leaves that drop to finish, with its change applied.\n */\n async importMap(map: WardleyMap): Promise<{ warnings: ImportWarning[] }> {\n const checked = importableMap(map);\n const diagram = this._ensureDiagram();\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const importer = diagram.get<WardleyImporter>(\"wardleyImporter\");\n const commandStack = diagram.get<CommandStack>(\"commandStack\", false);\n // Kept to put back if rendering fails half-way: a blank canvas is no way to fail an import. The\n // committed document, since the import ends a running live preview without its commit.\n const previous = this._rootBusinessObject()\n ? (this._livePreview()?.committedMap() ?? this.exportMap())\n : undefined;\n this._labelsBeforePreview = undefined;\n this._sizePreview = undefined;\n cancelGesture(diagram, this._dropping);\n importer.clear();\n let warnings: ImportWarning[];\n try {\n warnings = importer.import(checked);\n } catch (error) {\n importer.clear();\n if (previous) importer.import(previous);\n // The history pointed at the shapes the failed render removed.\n commandStack?.clear();\n eventBus.fire(\"import.done\", { warnings: [] });\n throw error;\n }\n // Discard the PREVIOUS map's undo history (concept doc §5.6): undo on orphaned\n // elements would otherwise crash or insert zombie elements into the new map.\n // The read-only Viewer has no command stack.\n commandStack?.clear();\n eventBus.fire(\"import.done\", { warnings });\n return { warnings };\n }\n\n /** Load OWM DSL text (internally parse -> importMap). Parser findings land in the warnings. */\n async importDSL(text: string): Promise<{ warnings: ImportWarning[] }> {\n const eventBus = this._ensureDiagram().get<EventBus>(\"eventBus\");\n eventBus.fire(\"import.parse.start\", { text });\n const { map, diagnostics } = parseDSLWithDiagnostics(text);\n eventBus.fire(\"import.parse.done\", { map, diagnostics });\n const { warnings } = await this.importMap(map);\n return {\n warnings: [\n ...diagnostics.map((d) => ({\n message: `Line ${d.line}: ${d.message} (\"${d.text}\")`,\n line: d.line,\n source: d.text,\n })),\n ...warnings,\n ],\n };\n }\n\n /** Current state as the canonical model (from the DI properties). */\n exportMap(): WardleyMap {\n return this.get<WardleyExporter>(\"wardleyExporter\").export();\n }\n\n /**\n * Sets the plot size in diagram-px. The size is normalized first (whole pixels, clamped to\n * PLOT_MIN..PLOT_MAX); non-finite input throws a RangeError before anything changes. In the\n * Modeler this is one undoable step that re-projects the shapes in place (selection, viewport and\n * history survive); the read-only viewers re-import. An explicit size line is written even for\n * the default size — only `resetMapSize` removes it. In the Modeler `{ transient: true }` shows\n * a live preview without an undo step, and the next call without it commits ONE step from the\n * size before the preview (none when the size ends where the preview started), like\n * `setEvolutionLabels`. A command before that call (e.g. `setTitle`) puts the preview back first.\n */\n async setMapSize(\n width: number,\n height: number,\n options: SetMapSizeOptions = {},\n ): Promise<{ warnings: ImportWarning[] }> {\n return this._resizeMap(normalizeMapSize(width, height), options);\n }\n\n /** Removes the `size` line: the map is drawn at the default plot size again. */\n async resetMapSize(options: SetMapSizeOptions = {}): Promise<{ warnings: ImportWarning[] }> {\n return this._resizeMap(undefined, options);\n }\n\n private async _resizeMap(\n size: MapSize | undefined,\n options: SetMapSizeOptions,\n ): Promise<{ warnings: ImportWarning[] }> {\n const modeling = this._wardleyModeling();\n if (!modeling) return this._reimportWithSize(size);\n const projection = this.get<MapProjection>(\"wardleyMapProjection\");\n if (options.transient) {\n if (!this._sizePreview) {\n const snapshot = projection.snapshot();\n if (!snapshot) return { warnings: [] };\n this._sizePreview = { snapshot, model: projection.captureModel() };\n }\n const businessObject = projection.withSize(size);\n if (!businessObject) return { warnings: [] };\n projection.redraw(\n projection.apply(businessObject, this._sizePreview.model, { transient: true }),\n );\n return { warnings: [] };\n }\n // The command must take the size before the preview as its old state.\n this._putBackSizePreview();\n modeling.resizeMap(size);\n return { warnings: [] };\n }\n\n /** Shows the map without the size preview again, if one is open. */\n private _putBackSizePreview(): void {\n if (!this._sizePreview) return;\n const projection = this.get<MapProjection>(\"wardleyMapProjection\");\n const { snapshot } = this._sizePreview;\n this._sizePreview = undefined;\n projection.redraw(projection.restore(snapshot, { transient: true }));\n }\n\n getMapSize(): MapSizeInfo {\n const { width, height } = this.get<EvolutionGrid>(\"evolutionGrid\").getPlotSize();\n const presetId = presetIdForSize({ width, height });\n return {\n width,\n height,\n isExplicit: this._rootBusinessObject()?.config.size !== undefined,\n ...(presetId ? { presetId } : {}),\n };\n }\n\n private async _reimportWithSize(\n size: { width: number; height: number } | undefined,\n ): Promise<{ warnings: ImportWarning[] }> {\n if (!this._rootBusinessObject()) return { warnings: [] };\n const map = this.exportMap();\n const current = map.config.size;\n const unchanged = size\n ? current?.width === size.width && current.height === size.height\n : current === undefined;\n if (unchanged) return { warnings: [] };\n const rawPassthrough = withoutRawSizeStatements(map.rawPassthrough);\n const { rawPassthrough: _previous, ...rest } = map;\n return this.importMap({\n ...rest,\n config: configWithSize(map.config, size),\n ...(rawPassthrough?.length ? { rawPassthrough } : {}),\n });\n }\n\n /**\n * Sets the map title (one undoable step in the Modeler). Line breaks become spaces so the DSL\n * `title` line stays one line; an empty title falls back to the default.\n */\n setTitle(title: string): void {\n const cleaned = title.replace(/\\s*[\\r\\n]+\\s*/g, \" \").trim() || DEFAULT_MAP_TITLE;\n const modeling = this._wardleyModeling();\n if (modeling) modeling.updateConfig({ title: cleaned });\n else this._applyConfigDirectly({ title: cleaned });\n }\n\n /**\n * Sets the four X-axis stage labels (`undefined` = default Genesis/Custom/Product/Commodity).\n * Empty stages fall back to their default and a `->` becomes `→`, so the labels always write a\n * valid `evolution` line; the default set is stored as `undefined`.\n * Changes only the labeling, not the geometry (no re-import -> no view jump, no selection loss).\n * In the Modeler this is one undoable step; `{ transient: true }` applies a live preview without\n * an undo step, and the next non-transient call commits it as ONE step from the state before the\n * preview (no step at all when the labels end where the preview started). Fires\n * `wardley.config.changed` (`{ config, transient? }`): transient events are live previews and\n * must not be persisted; in the Modeler every committed change is followed by\n * `commandStack.changed`.\n */\n setEvolutionLabels(\n requested: readonly string[] | undefined,\n options: SetEvolutionLabelsOptions = {},\n ): void {\n // Labels that would break the `evolution` line (empty stage, `->`) never reach the map.\n const labels = normalizeEvolutionLabels(requested);\n const modeling = this._wardleyModeling();\n if (options.transient && modeling) {\n if (!this._labelsBeforePreview) {\n const businessObject = this._rootBusinessObject();\n if (!businessObject) return;\n this._labelsBeforePreview = { labels: businessObject.config.evolutionLabels };\n }\n this._livePreview()?.begin(\"evolutionLabels\");\n this._applyConfigDirectly({ evolutionLabels: labels }, { transient: true });\n return;\n }\n if (modeling) {\n if (this._labelsBeforePreview) {\n const before = this._labelsBeforePreview.labels;\n this._applyConfigDirectly({ evolutionLabels: before });\n this._livePreview()?.end(\"evolutionLabels\");\n this._labelsBeforePreview = undefined;\n // A preview that ends where it started (typed, then reverted) is no edit: no undo step.\n if (sameEvolutionLabels(before, labels)) return;\n }\n modeling.updateConfig({ evolutionLabels: labels });\n return;\n }\n this._applyConfigDirectly({ evolutionLabels: labels });\n }\n\n /**\n * Config change without the command stack (read-only viewers, live previews): updates the root\n * config in place and re-renders only the axis background.\n */\n private _applyConfigDirectly(\n update: MapConfigUpdate,\n options: { transient?: boolean } = {},\n ): void {\n applyConfigUpdate(\n this.get<Canvas>(\"canvas\"),\n this.get<EvolutionGrid>(\"evolutionGrid\"),\n this.get<EventBus>(\"eventBus\"),\n update,\n options,\n );\n }\n\n /** The Modeler's command API, or null in the read-only viewers. */\n private _wardleyModeling(): WardleyModeling | null {\n return this._ensureDiagram().get<WardleyModeling>(\"wardleyModeling\", false);\n }\n\n private _livePreview(): LivePreview | null {\n return this._ensureDiagram().get<LivePreview>(\"wardleyLivePreview\", false);\n }\n\n private _root(): (Root & { businessObject?: RootBusinessObject }) | undefined {\n return wardleyRootOf(this.get<Canvas>(\"canvas\"));\n }\n\n private _rootBusinessObject(): RootBusinessObject | undefined {\n return this._root()?.businessObject;\n }\n\n exportDSL(): string {\n return serializeDSL(this.exportMap());\n }\n\n /**\n * Static, standalone SVG covering the whole plot (at its actual `config.size`) plus any content\n * drawn beyond it, such as long labels of commodity components.\n */\n async saveSVG(): Promise<{ svg: string }> {\n const canvas = this.get<Canvas>(\"canvas\");\n return saveSVG(canvas, exportBounds(canvas, this.get<EvolutionGrid>(\"evolutionGrid\")));\n }\n\n /** Own implementation (not a diagram-js primitive): attach the container to `target`. */\n attachTo(target: HTMLElement): void {\n target.appendChild(this._container);\n this.get<Canvas>(\"canvas\").resized();\n }\n\n /** Own implementation: detach the container from the DOM, keeping state. */\n detach(): void {\n this._container.remove();\n }\n\n clear(): void {\n this._ensureDiagram().clear();\n }\n\n destroy(): void {\n if (this._diagram) {\n this._diagram.destroy();\n this._diagram = undefined;\n }\n this._container.remove();\n }\n\n get container(): HTMLElement {\n return this._container;\n }\n}\n","import BaseLayouter, { type LayoutConnectionHints } from \"diagram-js/lib/layout/BaseLayouter\";\nimport type { ConnectionLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { isPipeline } from \"../model/di-types.js\";\n\ninterface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Docking point of a node: pipelines dock at their ■ anchor (top-edge center), not the box. */\nexport function connectionAnchorOf(shape: Bounds): Point {\n if (isPipeline(shape)) return { x: shape.x + shape.width / 2, y: shape.y };\n return { x: shape.x + shape.width / 2, y: shape.y + shape.height / 2 };\n}\n\n/**\n * The renderer draws every connection from docking point to docking point, ignoring its waypoints —\n * but diagram-js builds the connection's hit band from the waypoints. So they must always span the\n * same docking points, not diagram-js's hints (box mid, or the point where a connect drag ended).\n * The hints only count for an endpoint without a node (connection preview following the cursor).\n */\nexport default class WardleyLayouter extends BaseLayouter {\n override layoutConnection(\n connection: ConnectionLike,\n hints: LayoutConnectionHints = {},\n ): Point[] {\n const source = hints.source ?? connection[\"source\"];\n const target = hints.target ?? connection[\"target\"];\n return super.layoutConnection(connection, {\n ...hints,\n ...(source ? { connectionStart: connectionAnchorOf(source) } : {}),\n ...(target ? { connectionEnd: connectionAnchorOf(target) } : {}),\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLayouter from \"./WardleyLayouter.js\";\n\n/** Replaces diagram-js's mid-to-mid `layouter` — load after the diagram-js ModelingModule. */\nexport const wardleyLayoutModule: ModuleDeclaration = {\n layouter: [\"type\", WardleyLayouter],\n};\n\nexport { default as WardleyLayouter, connectionAnchorOf } from \"./WardleyLayouter.js\";\n","import type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type {\n AcceleratorDirection,\n AcceleratorElement,\n AnchorElement,\n AnnotationElement,\n AttitudeElement,\n AttitudeKind,\n ComponentElement,\n DrawingElement,\n MapEdge,\n MapElement,\n NoteElement,\n PipelineElement,\n SubmapElement,\n} from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport { NODE_SIZE, PIPELINE_HEIGHT, noteMetrics } from \"../draw/styles.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\nimport type { WardleyConnection, WardleyShape } from \"./di-types.js\";\n\n/** Element types that edges and DSL lines reference by name — their labels must be unique. */\nconst LINKABLE_TYPES: ReadonlySet<string> = new Set([\n \"component\",\n \"anchor\",\n \"submap\",\n \"pipeline\",\n \"accelerator\",\n]);\n\nfunction isLinkableType(type: unknown): boolean {\n return typeof type === \"string\" && LINKABLE_TYPES.has(type);\n}\n\n/**\n * First label not in `taken`: `base` itself, otherwise the next counter. A base that already ends\n * in a counter continues it ('Cup 2' -> 'Cup 3') instead of stacking ('Cup 2 2').\n */\nexport function nextFreeLabel(base: string, taken: ReadonlySet<string>): string {\n if (!taken.has(base)) return base;\n const counterMatch = / (\\d+)$/.exec(base);\n const stem = counterMatch ? base.slice(0, counterMatch.index) : base;\n let counter = counterMatch ? Number(counterMatch[1]) + 1 : 2;\n while (taken.has(`${stem} ${counter}`)) counter++;\n return `${stem} ${counter}`;\n}\n\nexport interface CreateNewExtra {\n attitudeKind?: AttitudeKind;\n acceleratorDirection?: AcceleratorDirection;\n annotationNumber?: number;\n market?: boolean;\n ecosystem?: boolean;\n}\n\n/**\n * Creates diagram-js runtime elements with Wardley markers. Projects normalized coordinates to\n * pixels via the SINGLE math source (EvolutionGrid, P7).\n */\nexport default class WardleyElementFactory {\n static $inject = [\"elementFactory\", \"evolutionGrid\", \"elementRegistry\"];\n\n constructor(\n private readonly elementFactory: ElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n ) {}\n\n /**\n * Returns a unique label: `base`, otherwise `base 2`, `base 3`, … Unique labels are mandatory\n * because the OWM DSL references elements BY THEIR NAME — duplicate names would cause ID\n * collisions on serialize/re-import and lose edges (lines). Only linkable elements count:\n * notes and regions are never referenced, so their text must not force a suffix.\n *\n * @param excludeId optional ID of the element currently being renamed (does NOT count its own\n * current name as a collision — otherwise every rename would add a suffix).\n */\n uniqueLabel(base: string, excludeId?: string): string {\n return nextFreeLabel(\n base,\n this.takenLinkableLabels(excludeId, this.pairableTypeFor(excludeId)),\n );\n }\n\n /**\n * Batch variant for pasted copies: linkable labels unique against the map AND each other;\n * everything else keeps its text.\n */\n uniqueLabels(entries: ReadonlyArray<{ type: unknown; label: string }>): string[] {\n const taken = this.takenLinkableLabels();\n return entries.map(({ type, label }) => {\n if (!isLinkableType(type)) return label;\n const unique = nextFreeLabel(label, taken);\n taken.add(unique);\n return unique;\n });\n }\n\n /** Whether elements of `type` are referenced by name (and so need a unique label). */\n isLinkable(type: unknown): boolean {\n return isLinkableType(type);\n }\n\n /**\n * @param pairableType elements of this type that still lack their OWM partner do not block a\n * name: a standalone component may take the name of a pipeline without an anchor (and so\n * anchor it), and such a pipeline may take the name of a free standalone component.\n */\n private takenLinkableLabels(excludeId?: string, pairableType?: \"component\" | \"pipeline\") {\n const taken = new Set<string>();\n for (const el of this.elementRegistry.getAll()) {\n if (excludeId && el.id === excludeId) continue;\n const { wardleyType, wardleyLabel } = el as { wardleyType?: unknown; wardleyLabel?: unknown };\n if (!isLinkableType(wardleyType) || typeof wardleyLabel !== \"string\") continue;\n if (wardleyType === pairableType && this.isUnpaired(el as WardleyShape)) continue;\n taken.add(wardleyLabel);\n }\n return taken;\n }\n\n /** Which partner type the element being renamed may share its new name with. */\n private pairableTypeFor(excludeId?: string): \"component\" | \"pipeline\" | undefined {\n const renamed = excludeId\n ? (this.elementRegistry.getAll().find((el) => el.id === excludeId) as\n WardleyShape | undefined)\n : undefined;\n if (!renamed || !this.isUnpaired(renamed)) return undefined;\n if (renamed.wardleyType === \"component\") return \"pipeline\";\n if (renamed.wardleyType === \"pipeline\") return \"component\";\n return undefined;\n }\n\n /**\n * A pipeline without an anchor component, or a standalone (non-member) component that anchors\n * no pipeline. Members never pair: they belong to their own pipeline.\n */\n private isUnpaired(shape: WardleyShape): boolean {\n const shapes = this.elementRegistry.getAll() as WardleyShape[];\n if (shape.wardleyType === \"pipeline\") {\n return !shapes.some(\n (other) =>\n other.wardleyType === \"component\" &&\n other.wardleyLabel === shape.wardleyLabel &&\n other.pipelineId !== shape.id,\n );\n }\n if (shape.wardleyType !== \"component\" || shape.pipelineId) return false;\n return !shapes.some(\n (other) => other.wardleyType === \"pipeline\" && other.wardleyLabel === shape.wardleyLabel,\n );\n }\n\n /** Next free annotation number (max + 1) — palette annotations therefore never collide. */\n private nextAnnotationNumber(): number {\n let max = 0;\n for (const el of this.elementRegistry.getAll()) {\n const n = (el as { annotationNumber?: unknown }).annotationNumber;\n if (typeof n === \"number\" && n > max) max = n;\n }\n return max + 1;\n }\n\n createComponent(el: ComponentElement): WardleyShape {\n const shape = this.node(\n \"component\",\n el.id,\n el.label,\n el.position.visibility,\n el.position.evolution,\n el,\n {\n ...(el.decorators ? { decorators: el.decorators } : {}),\n ...(el.movement ? { movement: el.movement } : {}),\n ...(el.labelOffset ? { labelOffset: el.labelOffset } : {}),\n ...(el.pipelineId ? { pipelineId: el.pipelineId } : {}),\n },\n );\n // Pipeline children sit INSIDE the box (whose top edge is the anchor line) — shift their\n // pixel position to the box center; visibility (model truth) stays the pipeline's.\n if (el.pipelineId) shape.y += PIPELINE_HEIGHT / 2;\n return shape;\n }\n\n createAnchor(el: AnchorElement): WardleyShape {\n return this.node(\"anchor\", el.id, el.label, el.position.visibility, el.position.evolution, el, {\n ...(el.labelOffset ? { labelOffset: el.labelOffset } : {}),\n });\n }\n\n createNote(el: NoteElement): WardleyShape {\n // Note box grows with the (possibly multiline) text -> move/click hitbox covers the text.\n // Centered on the position (consistent with the center back-calculation on move).\n const { width, height } = noteMetrics(el.label);\n const center = this.grid.toCanvas(el.position);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x: center.x - width / 2,\n y: center.y - height / 2,\n width,\n height,\n wardleyType: \"note\",\n wardleyLabel: el.label,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createPipeline(el: PipelineElement): WardleyShape {\n const start = this.grid.toCanvas({\n visibility: el.position.visibility,\n evolution: el.evolutionStart,\n });\n const end = this.grid.toCanvas({\n visibility: el.position.visibility,\n evolution: el.evolutionEnd,\n });\n const width = Math.max(end.x - start.x, 2);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x: start.x,\n // The box's TOP EDGE is the anchor line — the ■ square straddles it (drawn by the renderer).\n y: start.y,\n width,\n height: PIPELINE_HEIGHT,\n wardleyType: \"pipeline\",\n wardleyLabel: el.label,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n evolutionStart: el.evolutionStart,\n evolutionEnd: el.evolutionEnd,\n // Frame: only the border is clickable -> inner clicks reach the nodes (diagram-js isFrame).\n isFrame: true,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createAnnotation(el: AnnotationElement): WardleyShape {\n const pos = el.positions[0] ?? el.position;\n return this.node(\"annotation\", el.id, el.text, pos.visibility, pos.evolution, el, {\n annotationNumber: el.number,\n });\n }\n\n createAccelerator(el: AcceleratorElement): WardleyShape {\n return this.node(\n \"accelerator\",\n el.id,\n el.label,\n el.position.visibility,\n el.position.evolution,\n el,\n {\n acceleratorDirection: el.direction,\n },\n );\n }\n\n createAttitude(el: AttitudeElement): WardleyShape {\n // OWM canon: position = top-left corner, corner2 = bottom-right corner (both normalized).\n const a = this.grid.toCanvas(el.position);\n const b = this.grid.toCanvas(el.corner2);\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n const shape = this.elementFactory.createShape({\n id: el.id,\n x,\n y,\n width: Math.max(Math.abs(b.x - a.x), 4),\n height: Math.max(Math.abs(b.y - a.y), 4),\n wardleyType: \"attitude\",\n wardleyLabel: el.label || el.kind,\n attitudeKind: el.kind,\n evolution: el.position.evolution,\n visibility: el.position.visibility,\n corner2: el.corner2,\n isFrame: true,\n businessObject: el,\n ...(el.color ? { color: el.color } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createSubmap(el: SubmapElement): WardleyShape {\n return this.node(\"submap\", el.id, el.label, el.position.visibility, el.position.evolution, el);\n }\n\n createDrawing(el: DrawingElement): WardleyShape {\n const canvasPoints = el.points.map((p) => this.grid.toCanvas(p));\n return this.drawingFromCanvasPoints(canvasPoints, {\n id: el.id,\n ...(el.closed ? { closed: true } : {}),\n ...(el.strokeStyle ? { strokeStyle: el.strokeStyle } : {}),\n ...(el.color ? { color: el.color } : {}),\n businessObject: el,\n });\n }\n\n /**\n * The shape for any model element, projected with the current grid. Shared by the importer and\n * the in-place map resize, so both place every element type identically.\n */\n createFromModel(el: MapElement): WardleyShape | undefined {\n switch (el.elementType) {\n case \"component\":\n return this.createComponent(el);\n case \"anchor\":\n return this.createAnchor(el);\n case \"note\":\n return this.createNote(el);\n case \"pipeline\":\n return this.createPipeline(el);\n case \"annotation\":\n return this.createAnnotation(el);\n case \"attitude\":\n return this.createAttitude(el);\n case \"accelerator\":\n return this.createAccelerator(el);\n case \"submap\":\n return this.createSubmap(el);\n case \"drawing\":\n return this.createDrawing(el);\n default: {\n const exhaustive: never = el;\n void exhaustive;\n return undefined;\n }\n }\n }\n\n /** Builds a drawing shape from ABSOLUTE canvas points (bbox shape + relative points). */\n drawingFromCanvasPoints(\n canvasPoints: ReadonlyArray<{ x: number; y: number }>,\n extra: {\n id?: string;\n closed?: boolean;\n strokeStyle?: DrawingElement[\"strokeStyle\"];\n color?: string;\n businessObject?: DrawingElement;\n } = {},\n ): WardleyShape {\n const xs = canvasPoints.map((p) => p.x);\n const ys = canvasPoints.map((p) => p.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n const width = Math.max(Math.max(...xs) - x, 4);\n const height = Math.max(Math.max(...ys) - y, 4);\n const first = canvasPoints[0]!;\n const firstNorm = this.grid.fromCanvas(first);\n const shape = this.elementFactory.createShape({\n ...(extra.id ? { id: extra.id } : {}),\n x,\n y,\n width,\n height,\n wardleyType: \"drawing\",\n wardleyLabel: \"\",\n evolution: firstNorm.evolution,\n visibility: firstNorm.visibility,\n drawingPoints: canvasPoints.map((p) => ({ x: p.x - x, y: p.y - y })),\n ...(extra.closed ? { closed: true } : {}),\n ...(extra.strokeStyle ? { strokeStyle: extra.strokeStyle } : {}),\n ...(extra.color ? { color: extra.color } : {}),\n ...(extra.businessObject ? { businessObject: extra.businessObject } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createNew(\n type: WardleyShape[\"wardleyType\"],\n rawLabel: string,\n extra: CreateNewExtra = {},\n ): WardleyShape {\n // Enforce a unique label -> lossless DSL round-trip (see uniqueLabel). Attitude regions are\n // unlabelled like in OWM: their title is the canonical kind name.\n const label =\n type === \"attitude\"\n ? (extra.attitudeKind ?? \"pioneers\")\n : isLinkableType(type)\n ? this.uniqueLabel(rawLabel)\n : rawLabel;\n if (type === \"pipeline\") {\n const shape = this.elementFactory.createShape({\n width: 200,\n height: PIPELINE_HEIGHT,\n wardleyType: \"pipeline\",\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n evolutionStart: 0.4,\n evolutionEnd: 0.6,\n isFrame: true,\n });\n return shape as unknown as WardleyShape;\n }\n if (type === \"attitude\") {\n const shape = this.elementFactory.createShape({\n width: 180,\n height: 48,\n wardleyType: \"attitude\",\n wardleyLabel: label,\n attitudeKind: extra.attitudeKind ?? \"pioneers\",\n evolution: 0.5,\n visibility: 0.5,\n isFrame: true,\n });\n return shape as unknown as WardleyShape;\n }\n if (type === \"note\") {\n const { width, height } = noteMetrics(label);\n const shape = this.elementFactory.createShape({\n width,\n height,\n wardleyType: \"note\",\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n });\n return shape as unknown as WardleyShape;\n }\n const decorators = extra.market\n ? { market: true }\n : extra.ecosystem\n ? { ecosystem: true }\n : undefined;\n // Annotations automatically get the next free number (instead of a fixed \"1\").\n const annotationNumber =\n type === \"annotation\" ? (extra.annotationNumber ?? this.nextAnnotationNumber()) : undefined;\n const shape = this.elementFactory.createShape({\n width: NODE_SIZE,\n height: NODE_SIZE,\n wardleyType: type,\n wardleyLabel: label,\n evolution: 0.5,\n visibility: 0.5,\n ...(extra.acceleratorDirection ? { acceleratorDirection: extra.acceleratorDirection } : {}),\n ...(annotationNumber !== undefined ? { annotationNumber } : {}),\n ...(decorators ? { decorators } : {}),\n });\n return shape as unknown as WardleyShape;\n }\n\n createDependency(edge: MapEdge, source: WardleyShape, target: WardleyShape): WardleyConnection {\n return this.connection(\"dependency\", edge, source, target);\n }\n\n createFlow(edge: MapEdge, source: WardleyShape, target: WardleyShape): WardleyConnection {\n const bidirectional = edge.edgeType === \"flow\" && edge.bidirectional === true;\n return this.connection(\"flow\", edge, source, target, bidirectional);\n }\n\n private node(\n type: WardleyShape[\"wardleyType\"],\n id: string,\n label: string,\n visibility: number,\n evolution: number,\n businessObject: WardleyShape[\"businessObject\"],\n extra: Partial<WardleyShape> = {},\n ): WardleyShape {\n const center = this.grid.toCanvas({ visibility, evolution });\n const color = (businessObject as { color?: string } | undefined)?.color;\n const shape = this.elementFactory.createShape({\n id,\n x: center.x - NODE_SIZE / 2,\n y: center.y - NODE_SIZE / 2,\n width: NODE_SIZE,\n height: NODE_SIZE,\n wardleyType: type,\n wardleyLabel: label,\n evolution,\n visibility,\n businessObject,\n ...(color ? { color } : {}),\n ...extra,\n });\n return shape as unknown as WardleyShape;\n }\n\n private connection(\n type: WardleyConnection[\"wardleyType\"],\n edge: MapEdge,\n source: WardleyShape,\n target: WardleyShape,\n bidirectional = false,\n ): WardleyConnection {\n const flowValue = edge.edgeType === \"flow\" ? edge.flowValue : undefined;\n const conn = this.elementFactory.createConnection({\n id: edge.id,\n source,\n target,\n waypoints: [connectionAnchorOf(source), connectionAnchorOf(target)],\n wardleyType: type,\n bidirectional,\n ...(flowValue ? { flowValue } : {}),\n ...(edge.label ? { linkLabel: edge.label } : {}),\n businessObject: edge,\n });\n return conn as unknown as WardleyConnection;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyElementFactory from \"./WardleyElementFactory.js\";\n\n/** Custom ElementFactory with Wardley defaults and pixel projection. */\nexport const wardleyModelModule: ModuleDeclaration = {\n wardleyElementFactory: [\"type\", WardleyElementFactory],\n};\n\nexport { default as WardleyElementFactory } from \"./WardleyElementFactory.js\";\nexport * from \"./di-types.js\";\n","import {\n append as svgAppend,\n create as svgCreate,\n attr as svgAttr,\n clear as svgClear,\n} from \"tiny-svg\";\nimport {\n drawnPlotLength,\n evolutionStage,\n DEFAULT_STAGE_BOUNDARIES,\n DEFAULT_EVOLUTION_LABELS,\n type Coordinate,\n type EvolutionStage,\n type MapConfig,\n} from \"@miragon/wardley-schema-model\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { PLOT, COLORS, FONT } from \"../draw/styles.js\";\n\nconst AXES_LAYER = \"wardley-axes\";\n/** Value-chain end labels [bottom, top] unless the map sets `y-axis Label->Bottom->Top`. */\nexport const DEFAULT_Y_AXIS_END_LABELS: readonly [string, string] = [\"Invisible\", \"Visible\"];\n/** Axis lines/arrowheads and margin texts — styling hooks, kept in the export's markup. */\nconst AXIS_CLASS = \"wardley-axis\";\nconst AXIS_TEXT_CLASS = \"wardley-axis-text\";\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/**\n * Holds the SINGLE pixel<->normalized transform (guiding principle P7) and renders the\n * non-interactive axis/grid background into its own diagram-js layer (z below the\n * elements). The plot size is changeable at runtime via `config.size` (\"scale map\").\n */\nexport default class EvolutionGrid {\n static $inject = [\"canvas\"];\n\n private boundaries: readonly [number, number, number] = DEFAULT_STAGE_BOUNDARIES;\n private labels: readonly [string, string, string, string] = DEFAULT_EVOLUTION_LABELS;\n private yAxisLabel = \"Value Chain\";\n private yAxisEndLabels: readonly [string, string] = DEFAULT_Y_AXIS_END_LABELS;\n private plotWidth: number = PLOT.width;\n private plotHeight: number = PLOT.height;\n\n constructor(private readonly canvas: Canvas) {}\n\n configure(config: MapConfig): void {\n this.boundaries = config.stageBoundaries ?? DEFAULT_STAGE_BOUNDARIES;\n this.labels = config.evolutionLabels ?? DEFAULT_EVOLUTION_LABELS;\n this.yAxisLabel = config.yAxisLabel ?? \"Value Chain\";\n this.yAxisEndLabels = config.yAxisEndLabels ?? DEFAULT_Y_AXIS_END_LABELS;\n // A written size stays in the config as is; the grid draws it within the limits (NaN-safe).\n this.plotWidth = drawnPlotLength(config.size?.width, \"width\");\n this.plotHeight = drawnPlotLength(config.size?.height, \"height\");\n }\n\n /** Normalized -> diagram px (center of the node). */\n toCanvas(coord: Coordinate): Point {\n return {\n x: PLOT.marginLeft + coord.evolution * this.plotWidth,\n y: PLOT.marginTop + (1 - coord.visibility) * this.plotHeight,\n };\n }\n\n /** diagram px -> normalized, clamped to [0,1]. */\n fromCanvas(point: Point): Coordinate {\n return {\n evolution: clamp01((point.x - PLOT.marginLeft) / this.plotWidth),\n visibility: clamp01(1 - (point.y - PLOT.marginTop) / this.plotHeight),\n };\n }\n\n stageOf(evolution: number): EvolutionStage {\n return evolutionStage(evolution, this.boundaries);\n }\n\n /** The three stage boundaries (evolution values) — for snapping. */\n getBoundaries(): readonly [number, number, number] {\n return this.boundaries;\n }\n\n getPlotSize(): { width: number; height: number } {\n return { width: this.plotWidth, height: this.plotHeight };\n }\n\n /** Outer bounds including margins (for the initial viewbox). */\n outerBounds(): { x: number; y: number; width: number; height: number } {\n return {\n x: 0,\n y: 0,\n width: PLOT.marginLeft + this.plotWidth + PLOT.marginRight,\n height: PLOT.marginTop + this.plotHeight + PLOT.marginBottom,\n };\n }\n\n render(): void {\n const layer = this.canvas.getLayer(AXES_LAYER, -1);\n svgClear(layer);\n\n const left = PLOT.marginLeft;\n const top = PLOT.marginTop;\n const right = left + this.plotWidth;\n const bottom = top + this.plotHeight;\n\n // Plot background\n svgAppend(\n layer,\n rect(left, top, this.plotWidth, this.plotHeight, {\n fill: COLORS.plotBackground,\n stroke: COLORS.grid,\n }),\n );\n\n const edges = [0, ...this.boundaries, 1];\n for (let i = 0; i < 4; i++) {\n const x0 = left + edges[i]! * this.plotWidth;\n const x1 = left + edges[i + 1]! * this.plotWidth;\n if (i % 2 === 1) {\n svgAppend(\n layer,\n rect(x0, top, x1 - x0, this.plotHeight, { fill: COLORS.band, stroke: \"none\" }),\n );\n }\n if (i > 0) {\n svgAppend(\n layer,\n line(x0, top, x0, bottom, { stroke: COLORS.grid, \"stroke-dasharray\": \"3 5\" }),\n );\n }\n const midX = (x0 + x1) / 2;\n svgAppend(\n layer,\n text(this.labels[i]!.toUpperCase(), midX, bottom + 18, {\n \"text-anchor\": \"middle\",\n \"font-size\": FONT.stage,\n \"letter-spacing\": \"0.08em\",\n fill: COLORS.axisText,\n }),\n );\n }\n\n svgAppend(\n layer,\n line(left, bottom, right + 10, bottom, { stroke: COLORS.axis, class: AXIS_CLASS }),\n );\n svgAppend(layer, arrowHead(right + 10, bottom, \"right\"));\n svgAppend(\n layer,\n text(\"Evolution\", right + 6, bottom + 38, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.axis,\n fill: COLORS.axisText,\n \"font-style\": \"italic\",\n }),\n );\n\n svgAppend(\n layer,\n line(left, bottom, left, top - 10, { stroke: COLORS.axis, class: AXIS_CLASS }),\n );\n svgAppend(layer, arrowHead(left, top - 10, \"up\"));\n const yLabel = text(this.yAxisLabel, 0, 0, {\n \"text-anchor\": \"middle\",\n \"font-size\": FONT.axis,\n fill: COLORS.axisText,\n \"font-style\": \"italic\",\n });\n svgAttr(yLabel, { transform: `translate(${left - 46}, ${(top + bottom) / 2}) rotate(-90)` });\n svgAppend(layer, yLabel);\n\n // Axis end labels [bottom, top] — configurable via `y-axis Label->Bottom->Top`.\n svgAppend(\n layer,\n text(this.yAxisEndLabels[1], left - 10, top + 11, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.stage,\n fill: COLORS.axisText,\n }),\n );\n svgAppend(\n layer,\n text(this.yAxisEndLabels[0], left - 10, bottom - 2, {\n \"text-anchor\": \"end\",\n \"font-size\": FONT.stage,\n fill: COLORS.axisText,\n }),\n );\n }\n}\n\ntype Attrs = Record<string, string | number>;\n\nfunction rect(x: number, y: number, w: number, h: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"rect\"), { x, y, width: w, height: h, \"stroke-width\": 1, ...attrs });\n}\n\nfunction line(x1: number, y1: number, x2: number, y2: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"line\"), { x1, y1, x2, y2, \"stroke-width\": 1, ...attrs });\n}\n\nfunction text(content: string, x: number, y: number, attrs: Attrs): SVGElement {\n const el = svgAttr(svgCreate(\"text\"), {\n x,\n y,\n \"font-family\": FONT.family,\n class: AXIS_TEXT_CLASS,\n ...attrs,\n });\n el.textContent = content;\n return el;\n}\n\nfunction arrowHead(x: number, y: number, dir: \"right\" | \"up\"): SVGElement {\n const s = 5;\n const points =\n dir === \"right\"\n ? `${x - s},${y - s} ${x + 2},${y} ${x - s},${y + s}`\n : `${x - s},${y + s} ${x},${y - 2} ${x + s},${y + s}`;\n return svgAttr(svgCreate(\"polygon\"), { points, fill: COLORS.axis, class: AXIS_CLASS });\n}\n","/** Shortest evolve arrow (normalized evolution): anything shorter is not a movement. */\nexport const MIN_EVOLVE_DELTA = 0.005;\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { MIN_EVOLVE_DELTA } from \"./constants.js\";\nimport { focusCanvasWithoutRing, isCanvasKey } from \"../a11y/index.js\";\nimport type { WardleyInteraction } from \"../interaction/index.js\";\nimport {\n COMMAND_START_EVENTS,\n PUT_BACK_PRIORITY,\n type LivePreview,\n} from \"../live-preview/index.js\";\n\nconst PREFIX = \"wardley.evolve\";\n/** CSS class of the red target circle (set by the renderer) — direct drag handle. */\nconst HANDLE_CLASS = \"wardley-evolve-handle\";\n\ninterface EvolveContext {\n shape: WardleyShape;\n target?: number;\n}\n\n/** A drag of the evolve target's handle, ended without a commit by `cancel`. */\ninterface HandleDrag {\n shape: WardleyShape;\n cancel: () => void;\n}\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/**\n * Sets a component's evolve target by dragging along the evolution axis (instead of a text field).\n * During the drag a live preview (direct mutation + re-render) that the export holds back\n * (`LivePreview`); on release exactly ONE undoable commit via the commandStack (P4). Escape cancels\n * both the drag of the target's handle and the placement from the context pad, and restores the\n * original state.\n */\nexport default class WardleyEvolveDragging {\n static $inject = [\n \"eventBus\",\n \"dragging\",\n \"evolutionGrid\",\n \"wardleyModeling\",\n \"canvas\",\n \"elementRegistry\",\n \"injector\",\n \"wardleyInteraction\",\n \"wardleyLivePreview\",\n ];\n\n private handleDrag: HandleDrag | null = null;\n\n constructor(\n eventBus: EventBus,\n private readonly dragging: Dragging,\n grid: EvolutionGrid,\n modeling: WardleyModeling,\n canvas: Canvas,\n elementRegistry: ElementRegistry,\n private readonly injector: Injector,\n interaction: WardleyInteraction,\n livePreview: LivePreview,\n ) {\n const preview = (shape: WardleyShape, target: number) => {\n const { movement } = livePreview.beginShape(shape);\n shape.movement = { ...movement, targetEvolution: target };\n eventBus.fire(\"element.changed\", { element: shape });\n };\n\n // Evolution only moves forward: the preview stops at the component instead of flipping\n // backwards, and such a stub stays below the commit threshold.\n const forwardTarget = (shape: WardleyShape, evolution: number): number =>\n Math.max(clamp01(evolution), Math.min(1, shape.evolution + MIN_EVOLVE_DELTA));\n\n // Screen pixels -> normalized evolution (via the single source of math, P7).\n const evolutionAtClientX = (clientX: number, cy: number): number => {\n const rect = canvas.getContainer().getBoundingClientRect();\n const vb = canvas.viewbox();\n const canvasX = vb.x + (clientX - rect.left) * (vb.width / rect.width);\n return clamp01(grid.fromCanvas({ x: canvasX, y: cy }).evolution);\n };\n\n // The draw tool owns every press while it is active (its listener registers after this one).\n const isDrawing = (): boolean => {\n const container = canvas.getContainer();\n const outer = container.closest(\".wardley-container\") ?? container;\n return outer.classList.contains(\"wardley-draw-mode\");\n };\n\n // Direct handle: mousedown on the red target circle moves the evolve target by dragging.\n // Capture phase + stopPropagation so that diagram-js does NOT move the node instead.\n // Own document listeners (instead of dragging.init) — reliable, testable mousedown dragging.\n // Delegated on the container -> survives the re-rendering of the circle during the preview.\n canvas.getContainer().addEventListener(\n \"mousedown\",\n (event: MouseEvent) => {\n const dom = event.target as Element | null;\n if (!dom?.closest(`.${HANDLE_CLASS}`) || isDrawing() || isReadOnly(injector)) return;\n const id = dom.closest(\"[data-element-id]\")?.getAttribute(\"data-element-id\");\n const shape = id ? (elementRegistry.get(id) as WardleyShape | undefined) : undefined;\n if (!shape || shape.wardleyType !== \"component\") return;\n event.stopPropagation();\n event.preventDefault();\n focusCanvasWithoutRing(canvas);\n\n this.handleDrag?.cancel();\n\n const cy = shape.y + shape.height / 2;\n let target: number | undefined;\n const stop = () => {\n this.handleDrag = null;\n document.removeEventListener(\"mousemove\", onMove);\n document.removeEventListener(\"mouseup\", onUp);\n document.removeEventListener(\"keydown\", onKey, true);\n livePreview.putBackShape(shape);\n };\n const drag: HandleDrag = {\n shape,\n cancel: () => {\n stop();\n interaction.end(drag);\n },\n };\n const onMove = (e: MouseEvent) => {\n interaction.begin(drag);\n target = forwardTarget(shape, evolutionAtClientX(e.clientX, cy));\n preview(shape, target);\n };\n // The preview is reset first, then ONE undoable commit (P4).\n const onUp = () =>\n interaction.drop(drag, () => {\n stop();\n if (target !== undefined && target > shape.evolution + MIN_EVOLVE_DELTA) {\n modeling.evolveComponent(shape, target);\n }\n });\n // Escape puts the target back as it ends a diagram-js drag. Only an Escape aimed at the\n // canvas, which the press focused: a host's field, menu or dialog keeps its own.\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || !isCanvasKey(e, canvas)) return;\n e.preventDefault();\n e.stopPropagation();\n drag.cancel();\n };\n document.addEventListener(\"mousemove\", onMove);\n document.addEventListener(\"mouseup\", onUp);\n document.addEventListener(\"keydown\", onKey, true);\n this.handleDrag = drag;\n },\n true,\n );\n // Deleting the component mid-drag or an import that replaces it ends the drag, or the release\n // would evolve a removed shape.\n eventBus.on(\"shape.remove\", ({ element }: { element: unknown }) => {\n const drag = this.handleDrag;\n if (drag && drag.shape === element) drag.cancel();\n });\n eventBus.on(\"diagram.destroy\", () => this.handleDrag?.cancel());\n // The release puts back the evolve target the drag started from, which would undo a command in\n // between (an undo pressed mid-drag) and leave the history out of step with the document: a\n // drag that previews ends first, without a commit. The release puts back before its command.\n eventBus.on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => {\n const handleDrag = this.handleDrag;\n if (handleDrag && livePreview.previewsShape(handleDrag.shape)) handleDrag.cancel();\n const placement = this.runningPlacement();\n if (placement && livePreview.previewsShape(placement.shape)) dragging.cancel(true);\n });\n\n eventBus.on(`${PREFIX}.move`, (event: { context: EvolveContext; x: number }) => {\n const { shape } = event.context;\n const cy = shape.y + shape.height / 2;\n const target = forwardTarget(shape, grid.fromCanvas({ x: event.x, y: cy }).evolution);\n event.context.target = target;\n preview(shape, target);\n });\n\n eventBus.on(`${PREFIX}.end`, (event: { context: EvolveContext }) => {\n const { shape, target } = event.context;\n // Reset the preview, then execute as ONE command (clean undo).\n livePreview.putBackShape(shape);\n if (target !== undefined && target > shape.evolution + MIN_EVOLVE_DELTA) {\n modeling.evolveComponent(shape, target);\n }\n });\n\n eventBus.on(`${PREFIX}.cleanup`, (event: { context?: EvolveContext }) => {\n if (event.context) livePreview.putBackShape(event.context.shape);\n });\n }\n\n /** The evolve drag the context pad started, while it runs. */\n private runningPlacement(): EvolveContext | undefined {\n const drag = this.dragging.context() as {\n prefix?: string;\n data?: { context?: EvolveContext };\n } | null;\n return drag?.prefix === PREFIX ? drag.data?.context : undefined;\n }\n\n /**\n * Starts the evolve drag for `shape` (from the context pad): set the target by dragging along\n * the axis, or move it afterwards, with live preview; commit on release.\n */\n start(event: Event, shape: WardleyShape): void {\n if (isReadOnly(this.injector)) return;\n const context: EvolveContext = { shape };\n this.dragging.init(event as MouseEvent, PREFIX, { cursor: \"ew-resize\", data: { context } });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport { wardleyInteractionModule } from \"../interaction/index.js\";\nimport { livePreviewModule } from \"../live-preview/index.js\";\nimport WardleyEvolveDragging from \"./WardleyEvolveDragging.js\";\n\nexport const wardleyEvolveModule: ModuleDeclaration = {\n __depends__: [wardleyInteractionModule, livePreviewModule],\n __init__: [\"wardleyEvolveDragging\"],\n wardleyEvolveDragging: [\"type\", WardleyEvolveDragging],\n};\n\nexport { default as WardleyEvolveDragging } from \"./WardleyEvolveDragging.js\";\nexport { MIN_EVOLVE_DELTA } from \"./constants.js\";\n","import type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport { isComponent, isPipeline, type WardleyShape } from \"../model/di-types.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\nexport function centerOf(shape: WardleyShape): Point {\n return { x: shape.x + shape.width / 2, y: shape.y + shape.height / 2 };\n}\n\nexport function pipelineContains(pipeline: WardleyShape, point: Point): boolean {\n return (\n point.x >= pipeline.x &&\n point.x <= pipeline.x + pipeline.width &&\n point.y >= pipeline.y &&\n point.y <= pipeline.y + pipeline.height\n );\n}\n\nexport function allPipelines(registry: ElementRegistry): WardleyShape[] {\n return registry.filter((el) => isPipeline(el)) as WardleyShape[];\n}\n\nexport function membersOf(registry: ElementRegistry, pipeline: WardleyShape): WardleyShape[] {\n return registry.filter(\n (el) => isComponent(el) && el.pipelineId === pipeline.id,\n ) as WardleyShape[];\n}\n\n/** The OWM anchor: the standalone component written under the pipeline's name. */\nexport function anchorComponentOf(\n registry: ElementRegistry,\n pipeline: WardleyShape,\n): WardleyShape | undefined {\n return registry.find(\n (el) =>\n isComponent(el) && el.wardleyLabel === pipeline.wardleyLabel && el.pipelineId !== pipeline.id,\n ) as WardleyShape | undefined;\n}\n\n/** The pipeline a component anchors (same name, not one of its members). */\nexport function pipelineAnchoredBy(\n registry: ElementRegistry,\n component: WardleyShape,\n): WardleyShape | undefined {\n if (!isComponent(component)) return undefined;\n return allPipelines(registry).find(\n (pipeline) =>\n pipeline.wardleyLabel === component.wardleyLabel && component.pipelineId !== pipeline.id,\n );\n}\n\n/** Everything that moves together with a pipeline box: its members and its anchor component. */\nexport function pipelineFollowers(\n registry: ElementRegistry,\n pipeline: WardleyShape,\n): WardleyShape[] {\n const anchor = anchorComponentOf(registry, pipeline);\n return [...membersOf(registry, pipeline), ...(anchor ? [anchor] : [])];\n}\n\n/**\n * The pipeline a component would join when its centre sits at `point`. The pipeline it anchors is\n * never a candidate, and its current pipeline wins over overlapping boxes.\n */\nexport function pipelineAt(\n registry: ElementRegistry,\n component: WardleyShape,\n point: Point,\n excluded: ReadonlySet<unknown> = new Set(),\n): WardleyShape | undefined {\n const candidates = allPipelines(registry).filter(\n (pipeline) =>\n !excluded.has(pipeline) &&\n pipeline.wardleyLabel !== component.wardleyLabel &&\n pipelineContains(pipeline, point),\n );\n return candidates.find((pipeline) => pipeline.id === component.pipelineId) ?? candidates[0];\n}\n","import CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport type PreviewSupport from \"diagram-js/lib/features/preview-support/PreviewSupport\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport { translate } from \"diagram-js/lib/util/SvgTransformUtil\";\nimport { isComponent, isPipeline, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport {\n anchorComponentOf,\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"./pipelineMembership.js\";\n\n/** After diagram-js Move collected the selection (1500), before the preview is drawn (499). */\nconst COLLECT_FOLLOWERS_PRIORITY = 1400;\n/** After diagram-js MovePreview built its drag group. */\nconst VERTICAL_PREVIEW_PRIORITY = 450;\n/** After stage snapping (1500) and Move (500) settled the delta of this mouse move. */\nconst DROP_TARGET_PRIORITY = 400;\n/** Before the constraint behavior clamps the delta of the extended closure (1000). */\nconst EXTEND_CLOSURE_PRIORITY = 1500;\n\nconst VERTICAL_PREVIEW_LAYER = \"wardley-pipeline-drag\";\nconst VERTICAL_PREVIEW_LAYER_INDEX = 900;\n\nexport const DROP_TARGET_MARKER = \"wardley-drop-target\";\n\ninterface MoveContext {\n shape?: unknown;\n shapes?: unknown[];\n pipelineVerticalPreview?: SVGElement;\n pipelineDropTarget?: WardleyShape;\n}\n\ninterface RenameContext {\n element: WardleyShape;\n properties: Record<string, unknown>;\n renamedCounterpart?: WardleyShape;\n}\n\ninterface MoveEvent {\n context: MoveContext;\n dx: number;\n dy: number;\n}\n\ninterface MoveClosureLike {\n allShapes: Record<string, unknown>;\n topLevel: Record<string, unknown>;\n add(element: unknown, isTopLevel?: boolean): void;\n}\n\n/**\n * Makes a pipeline behave like a group (diagram-js AttachSupport pattern): dragging or nudging the\n * box carries its member components and its anchor component, dragging the anchor component shows\n * the box following vertically (the constraint behavior moves it on drop), and a dragged component\n * highlights the pipeline it would join.\n */\nexport default class PipelineGroupBehavior extends CommandInterceptor {\n static override $inject = [\"eventBus\", \"elementRegistry\", \"canvas\", \"injector\"];\n\n constructor(\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n injector: Injector,\n ) {\n super(eventBus);\n const previewSupport = injector.get<PreviewSupport | null>(\"previewSupport\", false);\n\n // A pipeline and its anchor component are one OWM pair, linked by their shared name: renaming\n // one renames the other in the same undo step, or the box silently stops following.\n this.preExecute(\"element.updateProperties\", (event: { context: RenameContext }) => {\n const { context } = event;\n const element = context.element;\n const label = context.properties[\"wardleyLabel\"];\n if (typeof label !== \"string\" || label === element.wardleyLabel) return;\n const counterpart = isPipeline(element)\n ? anchorComponentOf(this.elementRegistry, element)\n : pipelineAnchoredBy(this.elementRegistry, element);\n if (counterpart) context.renamedCounterpart = counterpart;\n });\n this.postExecute(\"element.updateProperties\", (event: { context: RenameContext }) => {\n const { context } = event;\n const counterpart = context.renamedCounterpart;\n const label = context.properties[\"wardleyLabel\"];\n if (!counterpart || typeof label !== \"string\" || counterpart.wardleyLabel === label) return;\n injector.get<WardleyModeling>(\"wardleyModeling\").updateProperties(counterpart, {\n wardleyLabel: label,\n });\n });\n\n eventBus.on(\"shape.move.start\", COLLECT_FOLLOWERS_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n context.shapes = this.withFollowers(context.shapes ?? []);\n });\n\n // Keyboard nudges and API moves never pass through shape.move.start.\n this.preExecuted(\n \"elements.move\",\n EXTEND_CLOSURE_PRIORITY,\n (event: { context: { closure?: MoveClosureLike } }) => {\n const closure = event.context.closure;\n if (!closure) return;\n for (const shape of Object.values(closure.allShapes)) {\n if (!isPipeline(shape)) continue;\n for (const follower of pipelineFollowers(this.elementRegistry, shape)) {\n if (!closure.allShapes[follower.id])\n closure.add(follower, !!closure.topLevel[shape.id]);\n }\n }\n },\n );\n\n if (previewSupport) {\n eventBus.on(\"shape.move.start\", VERTICAL_PREVIEW_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n const carried = this.carriedVertically(context.shapes ?? []);\n if (!carried.length) return;\n const group = svgCreate(\"g\");\n svgAttr(group, { class: \"djs-drag-group\" });\n svgAppend(\n this.canvas.getLayer(VERTICAL_PREVIEW_LAYER, VERTICAL_PREVIEW_LAYER_INDEX),\n group,\n );\n for (const shape of carried) previewSupport.addDragger(shape as unknown as Element, group);\n context.pipelineVerticalPreview = group;\n });\n }\n\n eventBus.on(\"shape.move.move\", DROP_TARGET_PRIORITY, (event: MoveEvent) => {\n const { context } = event;\n if (context.pipelineVerticalPreview) {\n translate(context.pipelineVerticalPreview, 0, event.dy);\n }\n this.markDropTarget(context, this.dropTargetFor(context, event.dx, event.dy));\n });\n\n eventBus.on(\"shape.move.cleanup\", (event: MoveEvent) => {\n const { context } = event;\n if (context.pipelineVerticalPreview) {\n svgRemove(context.pipelineVerticalPreview);\n delete context.pipelineVerticalPreview;\n }\n this.markDropTarget(context, undefined);\n });\n }\n\n private withFollowers(shapes: unknown[]): unknown[] {\n const all = new Set<unknown>(shapes);\n for (const shape of shapes) {\n if (!isPipeline(shape)) continue;\n for (const follower of pipelineFollowers(this.elementRegistry, shape)) all.add(follower);\n }\n return [...all];\n }\n\n /** Pipelines (and their members) whose anchor component is dragged without them. */\n private carriedVertically(shapes: unknown[]): WardleyShape[] {\n const dragged = new Set(shapes);\n const carried: WardleyShape[] = [];\n for (const shape of shapes) {\n if (!isComponent(shape)) continue;\n const pipeline = pipelineAnchoredBy(this.elementRegistry, shape);\n if (!pipeline || dragged.has(pipeline)) continue;\n carried.push(\n pipeline,\n ...membersOf(this.elementRegistry, pipeline).filter((member) => !dragged.has(member)),\n );\n }\n return carried;\n }\n\n private dropTargetFor(context: MoveContext, dx: number, dy: number): WardleyShape | undefined {\n const shape = context.shape;\n if (!isComponent(shape) || pipelineAnchoredBy(this.elementRegistry, shape)) return undefined;\n const center = centerOf(shape);\n return pipelineAt(\n this.elementRegistry,\n shape,\n { x: center.x + dx, y: center.y + dy },\n new Set(context.shapes ?? []),\n );\n }\n\n private markDropTarget(context: MoveContext, target: WardleyShape | undefined): void {\n const previous = context.pipelineDropTarget;\n if (previous === target) return;\n if (previous) this.canvas.removeMarker(previous as unknown as Shape, DROP_TARGET_MARKER);\n if (target) this.canvas.addMarker(target as unknown as Shape, DROP_TARGET_MARKER);\n if (target) context.pipelineDropTarget = target;\n else delete context.pipelineDropTarget;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PipelineGroupBehavior from \"./PipelineGroupBehavior.js\";\n\n/** Pipelines move as groups with their members and anchor component (editor-only). */\nexport const pipelineGroupModule: ModuleDeclaration = {\n __init__: [\"pipelineGroupBehavior\"],\n pipelineGroupBehavior: [\"type\", PipelineGroupBehavior],\n};\n\nexport { default as PipelineGroupBehavior, DROP_TARGET_MARKER } from \"./PipelineGroupBehavior.js\";\nexport {\n anchorComponentOf,\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"./pipelineMembership.js\";\n","import CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Shape } from \"diagram-js/lib/model/Types\";\nimport { isComponent, isPipeline, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { MIN_EVOLVE_DELTA } from \"../evolve/index.js\";\nimport {\n centerOf,\n membersOf,\n pipelineAnchoredBy,\n pipelineAt,\n pipelineFollowers,\n} from \"../pipeline/index.js\";\nimport type EvolutionGrid from \"./EvolutionGrid.js\";\n\n/** Commands whose handler changes the geometry of exactly one shape (`context.shape`). */\nconst SHAPE_GEOMETRY_COMMANDS = [\"shape.move\", \"shape.create\", \"shape.resize\"];\nconst GEOMETRY_COMMANDS = [...SHAPE_GEOMETRY_COMMANDS, \"elements.move\", \"elements.create\"];\nconst COMPONENT_LABEL_COMMANDS = [\"shape.create\", \"shape.delete\", \"element.updateProperties\"];\n\n/** Runs before every other pre-execute listener, so nesting is known before anyone acts on it. */\nconst TOP_LEVEL_PRIORITY = 2000;\n/** Below the pipeline group behavior (1500), which first extends the move closure by the members. */\nconst DELTA_CLAMP_PRIORITY = 1000;\n/** diagram-js ResizeShapeHandler rejects anything smaller. */\nconst MIN_RESIZE_EXTENT = 10;\nconst EPSILON = 1e-6;\n\ninterface Point {\n x: number;\n y: number;\n}\n\ninterface Bounds extends Point {\n width: number;\n height: number;\n}\n\ninterface Range {\n min: number;\n max: number;\n}\n\ninterface GeometryContext {\n shape?: unknown;\n shapes?: unknown[];\n elements?: unknown[];\n closure?: { allShapes: Record<string, unknown> };\n delta?: Point;\n newBounds?: Bounds;\n parent?: object & { parent?: unknown };\n}\n\ninterface CommandEvent {\n command: string;\n context: GeometryContext;\n}\n\n/** The parts of a create, delete or property update that tell which pairing it may change. */\ninterface PairingContext {\n shape?: unknown;\n element?: unknown;\n elements?: unknown[];\n properties?: Record<string, unknown>;\n oldProperties?: Record<string, unknown>;\n}\n\n/**\n * Keeps the normalized Wardley coordinates and the pixel geometry consistent across execute, undo\n * AND redo (concept doc §5.3). `EvolutionGrid` is the single source of math (P7).\n *\n * Two strictly separated parts, because diagram-js replays only `execute`/`revert` on redo and\n * skips every pre/post hook:\n *\n * 1. Derivation (`executed` + `reverted`): evolution, visibility, the pipeline range and the\n * attitude corner are pure functions of the current geometry and membership. It never writes\n * geometry, so replaying it on redo or undo always lands on the same model.\n * 2. Corrections (pre/post hooks of the outermost geometry command only): moves are clamped by\n * replacing the command's delta before it runs, resizes by replacing its bounds; pipeline glue,\n * membership changes and shifted evolve targets are nested commands. All of them join the same\n * undo step and are replayed exactly on redo.\n *\n * Pipelines behave like groups: moving the box carries its members and its anchor component (the\n * pipeline group behavior adds them to the move), and moving the anchor component vertically\n * carries the box. A component dropped into a box joins it and is glued onto its row; dragging it\n * out ends the membership.\n */\nexport default class EvolutionConstraintBehavior extends CommandInterceptor {\n static override $inject = [\n \"eventBus\",\n \"evolutionGrid\",\n \"elementRegistry\",\n \"canvas\",\n \"modeling\",\n \"wardleyModeling\",\n ];\n\n private topLevelContext: GeometryContext | null = null;\n private readonly evolutionsBefore = new WeakMap<GeometryContext, Map<WardleyShape, number>>();\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n private readonly modeling: Modeling,\n private readonly wardleyModeling: WardleyModeling,\n ) {\n super(eventBus);\n\n const derive = (event: CommandEvent) => {\n for (const shape of directShapes(event.context)) this.deriveFromGeometry(shape);\n };\n this.executed(SHAPE_GEOMETRY_COMMANDS, derive);\n this.reverted(SHAPE_GEOMETRY_COMMANDS, derive);\n\n // Corrections issue nested geometry commands themselves; only the outermost one is corrected,\n // which also stops the recursion.\n this.preExecute(GEOMETRY_COMMANDS, TOP_LEVEL_PRIORITY, (event: CommandEvent) => {\n if (!this.topLevelContext) this.topLevelContext = event.context;\n });\n eventBus.on(\"commandStack.changed\", () => {\n this.topLevelContext = null;\n });\n\n this.preExecute(\"shape.move\", (event: CommandEvent) => {\n const { context } = event;\n if (!this.isTopLevel(context) || !isWardleyShape(context.shape) || !context.delta) return;\n const moved = [context.shape, ...this.followersOf(context.shape)];\n this.rememberEvolutions(context, moved);\n context.delta = this.clampDelta(context.delta, moved);\n });\n this.preExecuted(\"elements.move\", DELTA_CLAMP_PRIORITY, (event: CommandEvent) => {\n const { context } = event;\n if (!this.isTopLevel(context) || !context.delta) return;\n const moved = closureShapes(context);\n this.rememberEvolutions(context, moved);\n // A fresh object: the same delta is later handed to every nested shape.move of the closure.\n context.delta = this.clampDelta(context.delta, moved);\n });\n this.preExecute([\"shape.create\", \"elements.create\"], (event: CommandEvent) => {\n const { context } = event;\n // Wardley shapes never nest: a drop onto another element must not make it the parent.\n if (context.parent?.parent) context.parent = this.canvas.getRootElement();\n if (this.isTopLevel(context)) this.rememberEvolutions(context, directShapes(context));\n });\n this.preExecute(\"shape.resize\", (event: CommandEvent) => {\n const { context } = event;\n const shape = context.shape;\n if (!isWardleyShape(shape) || !context.newBounds) return;\n if (shape.wardleyType === \"pipeline\") {\n context.newBounds = this.horizontalPipelineBounds(shape, context.newBounds);\n } else if (shape.wardleyType === \"attitude\") {\n context.newBounds = this.boundsInsidePlot(context.newBounds);\n }\n });\n\n this.postExecuted(GEOMETRY_COMMANDS, (event: CommandEvent) => {\n if (event.context !== this.topLevelContext) return;\n try {\n this.applyCorrections(event.command, event.context);\n } finally {\n this.evolutionsBefore.delete(event.context);\n this.topLevelContext = null;\n }\n });\n\n // The pipeline label is suppressed when a same-named component exists — whenever a\n // component is created/deleted/renamed, re-render the pipelines so labels toggle. That\n // component's name grows upward, clear of the box's top edge, so a pipeline created, deleted\n // or renamed re-renders the components of its old and its new name.\n const refreshPairedLabels = (event: { context?: PairingContext }) => {\n const context = event.context;\n const changed = [context?.shape, context?.element, ...(context?.elements ?? [])];\n if (changed.some((element) => isComponent(element))) {\n for (const pipeline of this.elementRegistry.filter((element) => isPipeline(element))) {\n this.eventBus.fire(\"element.changed\", { element: pipeline });\n }\n }\n const pipelines = changed.filter((element) => isPipeline(element));\n const nameChanged = !context?.properties || \"wardleyLabel\" in context.properties;\n if (!pipelines.length || !nameChanged) return;\n const pairedNames = new Set<unknown>([\n ...pipelines.map((pipeline) => pipeline.wardleyLabel),\n context?.properties?.[\"wardleyLabel\"],\n context?.oldProperties?.[\"wardleyLabel\"],\n ]);\n const pairedComponents = this.elementRegistry.filter(\n (element) => isComponent(element) && pairedNames.has(element.wardleyLabel),\n );\n for (const component of pairedComponents) {\n this.eventBus.fire(\"element.changed\", { element: component });\n }\n };\n this.executed(COMPONENT_LABEL_COMMANDS, refreshPairedLabels);\n this.reverted(COMPONENT_LABEL_COMMANDS, refreshPairedLabels);\n }\n\n private isTopLevel(context: GeometryContext): boolean {\n return context === this.topLevelContext;\n }\n\n private followersOf(shape: WardleyShape): WardleyShape[] {\n return isPipeline(shape) ? pipelineFollowers(this.elementRegistry, shape) : [];\n }\n\n private rememberEvolutions(context: GeometryContext, shapes: WardleyShape[]): void {\n this.evolutionsBefore.set(context, new Map(shapes.map((shape) => [shape, shape.evolution])));\n }\n\n // --- derivation (pure: geometry + membership -> normalized model) ----------------------------\n\n private deriveFromGeometry(shape: WardleyShape): void {\n switch (shape.wardleyType) {\n case \"pipeline\":\n this.derivePipeline(shape);\n return;\n case \"attitude\": {\n // Attitude position = anchor point (top left), corner2 = bottom-right corner (OWM semantics).\n const topLeft = this.grid.fromCanvas({ x: shape.x, y: shape.y });\n shape.evolution = topLeft.evolution;\n shape.visibility = topLeft.visibility;\n shape.corner2 = this.grid.fromCanvas({\n x: shape.x + shape.width,\n y: shape.y + shape.height,\n });\n return;\n }\n case \"drawing\": {\n const first = shape.drawingPoints?.[0] ?? { x: 0, y: 0 };\n const coordinate = this.grid.fromCanvas({ x: shape.x + first.x, y: shape.y + first.y });\n shape.evolution = coordinate.evolution;\n shape.visibility = coordinate.visibility;\n return;\n }\n default: {\n const coordinate = this.grid.fromCanvas(centerOf(shape));\n shape.evolution = coordinate.evolution;\n // Members share their pipeline's visibility; they are drawn centred in the box below it.\n const pipeline = this.pipelineOfMember(shape);\n shape.visibility = pipeline ? this.pipelineVisibility(pipeline) : coordinate.visibility;\n }\n }\n }\n\n private derivePipeline(pipeline: WardleyShape): void {\n // The anchor line (■ on the box) is the box's TOP EDGE.\n const start = this.grid.fromCanvas({ x: pipeline.x, y: pipeline.y });\n const end = this.grid.fromCanvas({ x: pipeline.x + pipeline.width, y: pipeline.y });\n const [evolutionStart, evolutionEnd] = clampRange(start.evolution, end.evolution);\n pipeline.evolutionStart = evolutionStart;\n pipeline.evolutionEnd = evolutionEnd;\n pipeline.evolution = clamp01((evolutionStart + evolutionEnd) / 2);\n pipeline.visibility = start.visibility;\n for (const member of membersOf(this.elementRegistry, pipeline)) {\n member.visibility = pipeline.visibility;\n }\n }\n\n private pipelineOfMember(shape: WardleyShape): WardleyShape | undefined {\n if (!isComponent(shape) || !shape.pipelineId) return undefined;\n const pipeline = this.elementRegistry.get(shape.pipelineId);\n return isPipeline(pipeline) ? pipeline : undefined;\n }\n\n private pipelineVisibility(pipeline: WardleyShape): number {\n return this.grid.fromCanvas({ x: pipeline.x, y: pipeline.y }).visibility;\n }\n\n // --- corrections (outermost command only, recorded as nested commands) -----------------------\n\n private applyCorrections(command: string, context: GeometryContext): void {\n switch (command) {\n case \"shape.move\": {\n const shape = context.shape;\n if (!isWardleyShape(shape)) return;\n const delta = context.delta ?? { x: 0, y: 0 };\n const followers = this.followersOf(shape);\n for (const follower of followers) this.moveBy(follower, delta);\n this.completeMove([shape, ...followers], delta, context);\n return;\n }\n case \"elements.move\":\n this.completeMove(closureShapes(context), context.delta ?? { x: 0, y: 0 }, context);\n return;\n case \"shape.create\":\n case \"elements.create\": {\n const created = directShapes(context);\n const correction = this.clampDelta({ x: 0, y: 0 }, created);\n for (const shape of created) this.moveBy(shape, correction);\n this.reconcileMembership(created);\n this.shiftPassedEvolveTargets(context);\n return;\n }\n case \"shape.resize\":\n if (isPipeline(context.shape)) this.releaseMembersOutside(context.shape);\n return;\n }\n }\n\n private completeMove(moved: WardleyShape[], delta: Point, context: GeometryContext): void {\n this.carryPipelinesOfMovedAnchors(moved, delta);\n this.reconcileMembership(moved);\n this.shiftPassedEvolveTargets(context);\n }\n\n /** Moving an anchor component up or down takes its pipeline box and the members along. */\n private carryPipelinesOfMovedAnchors(moved: WardleyShape[], delta: Point): void {\n if (Math.abs(delta.y) < EPSILON) return;\n const movedShapes = new Set<WardleyShape>(moved);\n for (const shape of moved) {\n const pipeline = pipelineAnchoredBy(this.elementRegistry, shape);\n if (!pipeline || movedShapes.has(pipeline)) continue;\n const group = [\n pipeline,\n ...membersOf(this.elementRegistry, pipeline).filter((member) => !movedShapes.has(member)),\n ];\n const verticalDelta = this.clampDelta({ x: 0, y: delta.y }, group);\n for (const groupShape of group) {\n this.moveBy(groupShape, verticalDelta);\n movedShapes.add(groupShape);\n }\n }\n }\n\n /**\n * A moved component whose centre lands in a pipeline box joins it and is glued onto its row; one\n * that leaves its box is released. Anchor components never join (they anchor the box itself).\n */\n private reconcileMembership(moved: WardleyShape[]): void {\n for (const component of moved) {\n if (!isComponent(component) || pipelineAnchoredBy(this.elementRegistry, component)) continue;\n const center = centerOf(component);\n const host = pipelineAt(this.elementRegistry, component, center);\n if (host) {\n this.moveBy(component, { x: 0, y: host.y + host.height / 2 - center.y });\n if (component.pipelineId !== host.id) {\n this.wardleyModeling.updateProperties(component, {\n pipelineId: host.id,\n visibility: this.pipelineVisibility(host),\n });\n }\n } else if (component.pipelineId) {\n this.release(component);\n }\n }\n }\n\n /** A narrowed pipeline lets go of the members whose centre is no longer inside the box. */\n private releaseMembersOutside(pipeline: WardleyShape): void {\n for (const member of membersOf(this.elementRegistry, pipeline)) {\n const center = centerOf(member);\n if (center.x < pipeline.x || center.x > pipeline.x + pipeline.width) this.release(member);\n }\n }\n\n private release(component: WardleyShape): void {\n this.wardleyModeling.updateProperties(component, {\n pipelineId: undefined,\n visibility: this.grid.fromCanvas(centerOf(component)).visibility,\n });\n }\n\n /**\n * A component moved onto or past its evolve target keeps the planned distance instead of\n * pointing backwards; at the right edge, where no forward target is left, the movement goes.\n */\n private shiftPassedEvolveTargets(context: GeometryContext): void {\n const evolutionsBefore = this.evolutionsBefore.get(context);\n if (!evolutionsBefore) return;\n for (const [shape, evolutionBefore] of evolutionsBefore) {\n const movement = shape.movement;\n if (!isComponent(shape) || !movement) continue;\n const evolution = shape.evolution;\n if (movement.targetEvolution - evolution > MIN_EVOLVE_DELTA) continue;\n const shiftedTarget = Math.min(1, evolution + (movement.targetEvolution - evolutionBefore));\n this.wardleyModeling.updateProperties(shape, {\n movement:\n shiftedTarget - evolution > MIN_EVOLVE_DELTA\n ? { ...movement, targetEvolution: shiftedTarget }\n : undefined,\n });\n }\n }\n\n private moveBy(shape: WardleyShape, delta: Point): void {\n if (Math.abs(delta.x) < EPSILON && Math.abs(delta.y) < EPSILON) return;\n this.modeling.moveShape(shape as unknown as Shape, { x: delta.x, y: delta.y });\n }\n\n // --- plot clamping ---------------------------------------------------------------------------\n\n private plotBounds(): Bounds {\n const topLeft = this.grid.toCanvas({ evolution: 0, visibility: 1 });\n const bottomRight = this.grid.toCanvas({ evolution: 1, visibility: 0 });\n return {\n x: topLeft.x,\n y: topLeft.y,\n width: bottomRight.x - topLeft.x,\n height: bottomRight.y - topLeft.y,\n };\n }\n\n /**\n * The part of a shape that has to stay inside the plot: the centre of a node, the anchor line of\n * a pipeline, the whole rectangle of an attitude and every point of a drawing.\n */\n private extentInsidePlot(shape: WardleyShape): Bounds {\n switch (shape.wardleyType) {\n case \"pipeline\":\n return { x: shape.x, y: shape.y, width: shape.width, height: 0 };\n case \"attitude\":\n return { x: shape.x, y: shape.y, width: shape.width, height: shape.height };\n case \"drawing\": {\n const points = shape.drawingPoints ?? [];\n if (!points.length) return { ...centerOf(shape), width: 0, height: 0 };\n const xs = points.map((point) => shape.x + point.x);\n const ys = points.map((point) => shape.y + point.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n return { x, y, width: Math.max(...xs) - x, height: Math.max(...ys) - y };\n }\n default:\n return { ...centerOf(shape), width: 0, height: 0 };\n }\n }\n\n /** The largest part of `delta` that keeps every shape's extent inside the plot. */\n private clampDelta(delta: Point, shapes: WardleyShape[]): Point {\n const plot = this.plotBounds();\n const horizontal: Range = { min: -Infinity, max: Infinity };\n const vertical: Range = { min: -Infinity, max: Infinity };\n for (const shape of shapes) {\n const extent = this.extentInsidePlot(shape);\n horizontal.min = Math.max(horizontal.min, plot.x - extent.x);\n horizontal.max = Math.min(horizontal.max, plot.x + plot.width - (extent.x + extent.width));\n vertical.min = Math.max(vertical.min, plot.y - extent.y);\n vertical.max = Math.min(vertical.max, plot.y + plot.height - (extent.y + extent.height));\n }\n return { x: clampToRange(delta.x, horizontal), y: clampToRange(delta.y, vertical) };\n }\n\n /** Pipelines only stretch along the evolution axis, and only within the plot. */\n private horizontalPipelineBounds(pipeline: WardleyShape, bounds: Bounds): Bounds {\n const [x, width] = this.spanInside(bounds.x, bounds.width, \"x\");\n return { x, y: pipeline.y, width, height: pipeline.height };\n }\n\n private boundsInsidePlot(bounds: Bounds): Bounds {\n const [x, width] = this.spanInside(bounds.x, bounds.width, \"x\");\n const [y, height] = this.spanInside(bounds.y, bounds.height, \"y\");\n return { x, y, width, height };\n }\n\n private spanInside(start: number, length: number, axis: \"x\" | \"y\"): [number, number] {\n const plot = this.plotBounds();\n const plotStart = axis === \"x\" ? plot.x : plot.y;\n const plotEnd = plotStart + (axis === \"x\" ? plot.width : plot.height);\n const clampedStart = Math.max(start, plotStart);\n const clampedLength = Math.max(\n Math.min(start + length, plotEnd) - clampedStart,\n MIN_RESIZE_EXTENT,\n );\n return [Math.min(clampedStart, plotEnd - clampedLength), clampedLength];\n }\n}\n\nfunction directShapes(context: GeometryContext): WardleyShape[] {\n const candidates = [\n ...(context.shape ? [context.shape] : []),\n ...(context.shapes ?? []),\n ...(context.elements ?? []),\n ];\n return [...new Set(candidates)].filter(isWardleyShape);\n}\n\nfunction closureShapes(context: GeometryContext): WardleyShape[] {\n if (!context.closure) return directShapes(context);\n return Object.values(context.closure.allShapes).filter(isWardleyShape);\n}\n\nfunction clampToRange(value: number, range: Range): number {\n // An empty range means a shape already sits outside the plot — leave such moves alone.\n if (range.min > range.max) return value;\n return Math.min(Math.max(value, range.min), range.max);\n}\n\nconst RANGE_EPS = 0.001;\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n\n/** Clamps an evolution range to [0,1] while guaranteeing `start < end` (schema invariant). */\nexport function clampRange(start: number, end: number): [number, number] {\n const e = clamp01(Math.max(end, start + RANGE_EPS));\n const s = Math.max(0, Math.min(start, e - RANGE_EPS));\n return [s, e];\n}\n","import type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\n\nexport interface UpdatePropertiesContext {\n element: ElementLike & Record<string, unknown>;\n properties: Record<string, unknown>;\n /** set internally by the handler (for revert). */\n oldProperties?: Record<string, unknown>;\n}\n\nfunction setOrDelete(obj: Record<string, unknown>, key: string, value: unknown): void {\n if (value === undefined) delete obj[key];\n else obj[key] = value;\n}\n\n/**\n * Generic, undoable command handler for setting arbitrary Wardley properties\n * (wardleyLabel, decorators, movement, evolutionStart/End, ...). Returns the changed element\n * -> CommandStack fires `elements.changed` -> re-render.\n */\nexport default class UpdatePropertiesHandler implements CommandHandler {\n execute(context: UpdatePropertiesContext): ElementLike[] {\n const { element, properties } = context;\n const target = element as unknown as Record<string, unknown>;\n const old: Record<string, unknown> = {};\n for (const key of Object.keys(properties)) {\n old[key] = target[key];\n setOrDelete(target, key, properties[key]);\n }\n context.oldProperties = old;\n return [element];\n }\n\n revert(context: UpdatePropertiesContext): ElementLike[] {\n const { element, oldProperties } = context;\n const target = element as unknown as Record<string, unknown>;\n if (oldProperties) {\n for (const key of Object.keys(oldProperties)) setOrDelete(target, key, oldProperties[key]);\n }\n return [element];\n }\n}\n","import type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type { ElementLike } from \"diagram-js/lib/core/Types\";\nimport type { MapSize } from \"@miragon/wardley-schema-model\";\nimport type { RootBusinessObject } from \"../../io/index.js\";\nimport {\n configWithSize,\n withoutRawSizeStatements,\n type MapProjection,\n} from \"../../map-resize/index.js\";\n\nexport interface ResizeMapContext {\n /** New explicit size; `undefined` removes the `size` line (default plot). */\n size: MapSize | undefined;\n /** set internally by the handler (for revert). */\n oldSize?: MapSize | undefined;\n oldRawPassthrough?: readonly string[] | undefined;\n}\n\n/**\n * Undoable map resize: changes `config.size` and re-projects the existing shapes in place from\n * their normalized model. Only the size (and superseded raw `size` lines) is touched, so the DSL\n * changes in exactly one line.\n */\nexport default class ResizeMapHandler implements CommandHandler {\n static $inject = [\"wardleyMapProjection\"];\n\n constructor(private readonly projection: MapProjection) {}\n\n execute(context: ResizeMapContext): ElementLike[] {\n const businessObject = this.projection.root()?.businessObject;\n if (!businessObject) return [];\n context.oldSize = businessObject.config.size;\n context.oldRawPassthrough = businessObject.rawPassthrough;\n // An unreadable `size` line kept in the passthrough would be written after the new one, and\n // OWM lets the last size line win.\n return this.projection.apply(\n withRawPassthrough(\n { ...businessObject, config: configWithSize(businessObject.config, context.size) },\n withoutRawSizeStatements(businessObject.rawPassthrough),\n ),\n );\n }\n\n revert(context: ResizeMapContext): ElementLike[] {\n const businessObject = this.projection.root()?.businessObject;\n if (!businessObject) return [];\n return this.projection.apply(\n withRawPassthrough(\n { ...businessObject, config: configWithSize(businessObject.config, context.oldSize) },\n context.oldRawPassthrough,\n ),\n );\n }\n}\n\nfunction withRawPassthrough(\n businessObject: RootBusinessObject,\n rawPassthrough: readonly string[] | undefined,\n): RootBusinessObject {\n const { rawPassthrough: _previous, ...rest } = businessObject;\n return rawPassthrough ? { ...rest, rawPassthrough } : rest;\n}\n","import type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { MapConfig, MapSize, Method } from \"@miragon/wardley-schema-model\";\nimport type { WardleyConnection, WardleyShape } from \"../model/di-types.js\";\nimport { noteMetrics } from \"../draw/styles.js\";\nimport { wardleyRootOf } from \"../map-resize/index.js\";\nimport UpdatePropertiesHandler from \"./cmd/UpdatePropertiesHandler.js\";\nimport ResizeMapHandler from \"./cmd/ResizeMapHandler.js\";\nimport UpdateConfigHandler, { type MapConfigUpdate } from \"./cmd/UpdateConfigHandler.js\";\n\nconst UPDATE_PROPERTIES = \"element.updateProperties\";\nexport const RESIZE_MAP = \"wardley.map.resize\";\nexport const UPDATE_CONFIG = \"wardley.config.update\";\n\nfunction compact<T extends Record<string, unknown>>(obj: T): T {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) if (v !== undefined) out[k] = v;\n return out as T;\n}\n\nexport interface EvolveOptions {\n newLabel?: string;\n method?: Method;\n}\n\n/**\n * High-level mutations on Wardley shapes that run through the commandStack (undo/redo, P4).\n * Registers the generic UpdatePropertiesHandler at bootstrap.\n */\nexport default class WardleyModeling {\n static $inject = [\"commandStack\", \"canvas\"];\n\n constructor(\n private readonly commandStack: CommandStack,\n private readonly canvas: Canvas,\n ) {\n commandStack.registerHandler(UPDATE_PROPERTIES, UpdatePropertiesHandler);\n commandStack.registerHandler(RESIZE_MAP, ResizeMapHandler);\n commandStack.registerHandler(UPDATE_CONFIG, UpdateConfigHandler);\n }\n\n /**\n * Sets the plot size (`undefined` removes the `size` line) as one undoable step that re-projects\n * the shapes in place. Pass an already normalized size (see `normalizeMapSize`). Does nothing\n * when the config would not change.\n */\n resizeMap(size: MapSize | undefined): void {\n const config = this.currentConfig();\n if (!config || sameSize(config.size, size)) return;\n this.commandStack.execute(RESIZE_MAP, { size });\n }\n\n /** Changes config fields (title, labels, …) as one undoable step; `undefined` removes a field. */\n updateConfig(properties: MapConfigUpdate): void {\n const config = this.currentConfig();\n if (!config) return;\n const current = config as unknown as Record<string, unknown>;\n const changed = Object.fromEntries(\n Object.entries(properties).filter(\n ([key, value]) => key !== \"size\" && JSON.stringify(current[key]) !== JSON.stringify(value),\n ),\n ) as MapConfigUpdate;\n if (Object.keys(changed).length === 0) return;\n this.commandStack.execute(UPDATE_CONFIG, { properties: changed });\n }\n\n private currentConfig(): MapConfig | undefined {\n return wardleyRootOf(this.canvas)?.businessObject?.config;\n }\n\n updateProperties(\n element: WardleyShape | WardleyConnection,\n properties: Record<string, unknown>,\n ): void {\n this.commandStack.execute(UPDATE_PROPERTIES, { element, properties });\n }\n\n updateLabel(element: WardleyShape, label: string): void {\n // Notes: resize the box (and thus the move/click hitbox) to the new text, keeping the center.\n if (element.wardleyType === \"note\") {\n const { width, height } = noteMetrics(label);\n const cx = element.x + element.width / 2;\n const cy = element.y + element.height / 2;\n this.updateProperties(element, {\n wardleyLabel: label,\n width,\n height,\n x: cx - width / 2,\n y: cy - height / 2,\n });\n return;\n }\n this.updateProperties(element, { wardleyLabel: label });\n }\n\n evolveComponent(element: WardleyShape, targetEvolution: number, opts: EvolveOptions = {}): void {\n const target = clamp01(targetEvolution);\n // Evolution only moves forward (canon) — silently ignore targets left of the current position.\n if (target <= element.evolution) return;\n // Retargeting keeps what the user already gave the evolve line (new name, method, label offset).\n this.updateProperties(element, {\n movement: compact({\n ...element.movement,\n targetEvolution: target,\n ...compact({ newLabel: opts.newLabel, method: opts.method }),\n }),\n });\n }\n\n clearMovement(element: WardleyShape): void {\n this.updateProperties(element, { movement: undefined });\n }\n\n toggleInertia(element: WardleyShape): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n if (dec[\"inertia\"]) delete dec[\"inertia\"];\n else dec[\"inertia\"] = true;\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n setMethod(element: WardleyShape, method: Method | undefined): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n if (method) dec[\"method\"] = method;\n else delete dec[\"method\"];\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n /** Sets market/ecosystem (mutually exclusive) or removes both (`undefined`). */\n setMarketEcosystem(element: WardleyShape, kind: \"market\" | \"ecosystem\" | undefined): void {\n const dec: Record<string, unknown> = { ...(element.decorators ?? {}) };\n delete dec[\"market\"];\n delete dec[\"ecosystem\"];\n if (kind) dec[kind] = true;\n this.updateProperties(element, { decorators: Object.keys(dec).length ? dec : undefined });\n }\n\n /** Sets the element color (CSS color/hex) or removes it (`undefined` = default color). */\n setColor(element: WardleyShape, color: string | undefined): void {\n this.updateProperties(element, { color });\n }\n}\n\nfunction sameSize(a: MapSize | undefined, b: MapSize | undefined): boolean {\n if (!a || !b) return a === b;\n return a.width === b.width && a.height === b.height;\n}\n\nfunction clamp01(n: number): number {\n return n < 0 ? 0 : n > 1 ? 1 : n;\n}\n","import type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Mouse from \"diagram-js/lib/features/mouse/Mouse\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\n\n/** Offset (px) accumulated per paste operation. */\nconst PASTE_OFFSET = 24;\n\ninterface ShapeSnapshot {\n readonly id: string;\n readonly pipelineId?: string;\n readonly props: Record<string, unknown>;\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n readonly label: string;\n}\ninterface ConnectionSnapshot {\n readonly sourceIdx: number;\n readonly targetIdx: number;\n readonly props: Record<string, unknown>;\n}\n\n/** Wardley properties carried along when copying (geometry handled separately). */\nconst SHAPE_PROPS = [\n \"wardleyType\",\n \"evolution\",\n \"visibility\",\n \"decorators\",\n \"movement\",\n \"evolutionStart\",\n \"evolutionEnd\",\n \"annotationNumber\",\n \"attitudeKind\",\n \"corner2\",\n \"acceleratorDirection\",\n \"labelOffset\",\n \"color\",\n \"drawingPoints\",\n \"closed\",\n \"strokeStyle\",\n] as const;\nconst CONNECTION_PROPS = [\"wardleyType\", \"bidirectional\", \"flowValue\", \"linkLabel\"] as const;\n\nfunction snapshotProps(\n el: Record<string, unknown>,\n keys: readonly string[],\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const key of keys) {\n const value = el[key];\n if (value !== undefined) out[key] = structuredClone(value);\n }\n return out;\n}\n\n/**\n * Custom copy/paste for Wardley shapes: copies the selection including the connections BETWEEN\n * selected shapes and assigns unique labels (the DSL references by name!).\n * Paste attaches the clones to the cursor like palette create (live preview, click places,\n * Escape cancels); duplicate inserts immediately with an offset. Either way the insert is ONE\n * undoable `elements.create` command.\n */\nexport default class WardleyCopyPaste {\n static $inject = [\n \"selection\",\n \"modeling\",\n \"elementFactory\",\n \"canvas\",\n \"create\",\n \"mouse\",\n \"wardleyElementFactory\",\n ];\n\n private clipboard: { shapes: ShapeSnapshot[]; connections: ConnectionSnapshot[] } | null = null;\n private pasteCount = 0;\n\n constructor(\n private readonly selection: Selection,\n private readonly modeling: Modeling,\n private readonly elementFactory: ElementFactory,\n private readonly canvas: Canvas,\n private readonly create: Create,\n private readonly mouse: Mouse,\n private readonly wardleyElementFactory: WardleyElementFactory,\n ) {}\n\n /** Copies the current selection. Returns false if nothing copyable is selected. */\n copy(): boolean {\n const selected = this.selection.get() as Element[];\n const shapes = selected.filter((el) => isWardleyShape(el)) as WardleyShape[];\n if (!shapes.length) return false;\n\n const indexOf = new Map<WardleyShape, number>(shapes.map((s, i) => [s, i]));\n const connections: ConnectionSnapshot[] = [];\n const seen = new Set<WardleyConnection>();\n for (const shape of shapes) {\n for (const conn of [...(shape.incoming ?? []), ...(shape.outgoing ?? [])]) {\n if (!isWardleyConnection(conn) || seen.has(conn)) continue;\n const sourceIdx = indexOf.get(conn.source as unknown as WardleyShape);\n const targetIdx = indexOf.get(conn.target as unknown as WardleyShape);\n if (sourceIdx === undefined || targetIdx === undefined) continue;\n seen.add(conn);\n connections.push({\n sourceIdx,\n targetIdx,\n props: snapshotProps(conn as unknown as Record<string, unknown>, CONNECTION_PROPS),\n });\n }\n }\n\n this.clipboard = {\n shapes: shapes.map((s) => ({\n id: s.id,\n ...(s.pipelineId ? { pipelineId: s.pipelineId } : {}),\n props: snapshotProps(s as unknown as Record<string, unknown>, SHAPE_PROPS),\n x: s.x,\n y: s.y,\n width: s.width,\n height: s.height,\n label: s.wardleyLabel ?? \"\",\n })),\n connections,\n };\n this.pasteCount = 0;\n return true;\n }\n\n /**\n * Paste with placement preview: the clones attach to the cursor exactly like palette create —\n * click places them, Escape cancels. Falls back to an offset insert when the mouse position\n * is unknown (e.g. paste before the pointer ever entered the canvas).\n */\n paste(): boolean {\n if (!this.clipboard?.shapes.length) return false;\n const clones = this.buildClones();\n const lastMove = this.mouse.getLastMoveEvent();\n if (lastMove) {\n // The flag keeps WardleyAppendBehavior from opening the name editor on pasted copies.\n this.create.start(lastMove, [...clones.shapes, ...clones.connections] as Element[], {\n wardleyPaste: true,\n });\n return true;\n }\n return this.insertWithOffset(clones);\n }\n\n /** Copy + immediate offset insert of the selection (Ctrl+D) — no placement step. */\n duplicate(): boolean {\n if (!this.copy()) return false;\n return this.insertWithOffset(this.buildClones());\n }\n\n /** Builds fresh clone elements (unique labels, internal connections rewired). */\n private buildClones(): { shapes: Shape[]; connections: Element[] } {\n const clipboard = this.clipboard!;\n const labels = this.cloneLabels(clipboard.shapes);\n const shapes = clipboard.shapes.map((snap, i) =>\n this.elementFactory.createShape({\n ...structuredClone(snap.props),\n x: snap.x,\n y: snap.y,\n width: snap.width,\n height: snap.height,\n wardleyLabel: labels[i]!,\n ...(snap.props[\"wardleyType\"] === \"pipeline\" || snap.props[\"wardleyType\"] === \"attitude\"\n ? { isFrame: true }\n : {}),\n }),\n );\n // Members follow their copied pipeline by id, not by where they happen to land.\n const cloneIdByOriginalId = new Map(\n clipboard.shapes.map((snap, i) => [snap.id, shapes[i]!.id]),\n );\n clipboard.shapes.forEach((snap, i) => {\n const pipelineId = snap.pipelineId && cloneIdByOriginalId.get(snap.pipelineId);\n if (pipelineId) (shapes[i] as unknown as WardleyShape).pipelineId = pipelineId;\n });\n const connections = clipboard.connections.map((c) =>\n this.elementFactory.createConnection({\n ...structuredClone(c.props),\n source: shapes[c.sourceIdx]!,\n target: shapes[c.targetIdx]!,\n waypoints: [\n connectionAnchorOf(shapes[c.sourceIdx]!),\n connectionAnchorOf(shapes[c.targetIdx]!),\n ],\n }),\n );\n return { shapes, connections: connections as Element[] };\n }\n\n /**\n * Unique labels for the clones. A pipeline copied together with its anchor component (the\n * component written under the pipeline's name) keeps that pairing: both get the same new name,\n * otherwise the copy loses its anchor and the renamed component would join a box as a member.\n */\n private cloneLabels(snapshots: readonly ShapeSnapshot[]): string[] {\n const pipelineIndexByAnchor = new Map<number, number>();\n snapshots.forEach((pipeline, pipelineIndex) => {\n if (pipeline.props[\"wardleyType\"] !== \"pipeline\") return;\n const anchorIndex = snapshots.findIndex(\n (candidate, index) =>\n !pipelineIndexByAnchor.has(index) &&\n candidate.props[\"wardleyType\"] === \"component\" &&\n candidate.label === pipeline.label &&\n candidate.pipelineId !== pipeline.id,\n );\n if (anchorIndex >= 0) pipelineIndexByAnchor.set(anchorIndex, pipelineIndex);\n });\n const independent = snapshots\n .map((snapshot, index) => ({ snapshot, index }))\n .filter(({ index }) => !pipelineIndexByAnchor.has(index));\n const uniqueLabels = this.wardleyElementFactory.uniqueLabels(\n independent.map(({ snapshot }) => ({\n type: snapshot.props[\"wardleyType\"],\n label: snapshot.label,\n })),\n );\n const labels: string[] = [];\n independent.forEach(({ index }, position) => (labels[index] = uniqueLabels[position]!));\n for (const [anchorIndex, pipelineIndex] of pipelineIndexByAnchor) {\n labels[anchorIndex] = labels[pipelineIndex]!;\n }\n return labels;\n }\n\n /** One `elements.create` command = one undo step; position = group center + offset. */\n private insertWithOffset(clones: { shapes: Shape[]; connections: Element[] }): boolean {\n this.pasteCount++;\n const offset = PASTE_OFFSET * this.pasteCount;\n const bbox = groupBBox(clones.shapes);\n const created = this.modeling.createElements(\n [...clones.shapes, ...clones.connections] as Element[],\n { x: bbox.cx + offset, y: bbox.cy + offset },\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created as Element[]);\n return true;\n }\n}\n\nfunction groupBBox(shapes: Array<{ x: number; y: number; width: number; height: number }>): {\n cx: number;\n cy: number;\n} {\n const minX = Math.min(...shapes.map((s) => s.x));\n const minY = Math.min(...shapes.map((s) => s.y));\n const maxX = Math.max(...shapes.map((s) => s.x + s.width));\n const maxY = Math.max(...shapes.map((s) => s.y + s.height));\n return { cx: (minX + maxX) / 2, cy: (minY + maxY) / 2 };\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport MouseModule from \"diagram-js/lib/features/mouse\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport WardleyModeling from \"./WardleyModeling.js\";\nimport WardleyCopyPaste from \"./WardleyCopyPaste.js\";\nimport { mapProjectionModule } from \"../map-resize/index.js\";\n\n/** High-level Wardley mutations + registration of the custom command handlers. */\nexport const wardleyModelingModule: ModuleDeclaration = {\n // Mouse/Create are needed by the paste preview (clones attach to the cursor).\n __depends__: [MouseModule, CreateModule, mapProjectionModule],\n __init__: [\"wardleyModeling\"],\n wardleyModeling: [\"type\", WardleyModeling],\n wardleyCopyPaste: [\"type\", WardleyCopyPaste],\n};\n\nexport { default as WardleyModeling } from \"./WardleyModeling.js\";\nexport { default as WardleyCopyPaste } from \"./WardleyCopyPaste.js\";\nexport { RESIZE_MAP, UPDATE_CONFIG } from \"./WardleyModeling.js\";\nexport type { EvolveOptions } from \"./WardleyModeling.js\";\nexport type { MapConfigUpdate } from \"./cmd/UpdateConfigHandler.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport EvolutionGrid from \"./EvolutionGrid.js\";\nimport EvolutionConstraintBehavior from \"./EvolutionConstraintBehavior.js\";\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport { wardleyLayoutModule } from \"../layout/index.js\";\nimport { wardleyModelingModule } from \"../modeling/index.js\";\n\n/** Axis background + single pixel<->normalized math (P7). */\nexport const evolutionGridModule: ModuleDeclaration = {\n evolutionGrid: [\"type\", EvolutionGrid],\n};\n\n/** Keeps normalized coordinates in sync with the geometry (editor-only). */\nexport const evolutionConstraintModule: ModuleDeclaration = {\n __init__: [\"evolutionConstraintBehavior\"],\n __depends__: [evolutionGridModule, wardleyLayoutModule, ModelingModule, wardleyModelingModule],\n evolutionConstraintBehavior: [\"type\", EvolutionConstraintBehavior],\n};\n\nexport { default as EvolutionGrid } from \"./EvolutionGrid.js\";\nexport { default as EvolutionConstraintBehavior } from \"./EvolutionConstraintBehavior.js\";\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\n\n/**\n * The notation glyphs the canvas and the palette draw (anchor, accelerator, deaccelerator; guide\n * §3.6 keeps them until the modelers' dark mode), 24x24-viewBox paths from Google Material Icons\n * (Apache-2.0, © Google). `drawIcon` renders them as SVG. The context pad draws Lucide icons\n * (`lucide.ts`).\n * Source: https://github.com/google/material-design-icons (Apache License 2.0).\n */\n\nexport const ICON_PERSON =\n \"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\";\n/** fast_forward — Accelerator. */\nexport const ICON_FAST_FORWARD = \"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\";\n/** fast_rewind — Deaccelerator. */\nexport const ICON_FAST_REWIND = \"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\";\n\n/** Draws a 24x24 icon as an SVG group centered on (cx, cy), scaled to `size`. */\nexport function drawIcon(\n path: string,\n cx: number,\n cy: number,\n size: number,\n fill: string,\n): SVGElement {\n const g = svgCreate(\"g\");\n const s = size / 24;\n svgAttr(g, {\n transform: `translate(${cx - size / 2}, ${cy - size / 2}) scale(${s})`,\n fill,\n stroke: \"none\",\n });\n svgAppend(g, svgAttr(svgCreate(\"path\"), { d: path }));\n return g;\n}\n","import type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type { LabelOffset } from \"@miragon/wardley-schema-model\";\nimport { ANCHOR_ICON_SIZE, COMPONENT_RADIUS } from \"./styles.js\";\nimport { isPipeline, type WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\n\n/**\n * Where the renderer puts component, anchor and evolve-target labels. Shared by the renderer and the\n * label-drag interaction so a dragged label lands exactly where the stored offset renders it.\n *\n * All positions are relative to the owning node's centre. An explicit OWM `label [dx, dy]` offset is\n * always relative to the canonical OWM slot (right of the circle, or centred above an anchor) — the\n * automatic placements below only apply while no offset is set, so imported OWM maps keep their look.\n */\n\nexport const LABEL_GAP = 7;\n/** Rough average advance of a 13px/500 label glyph; the renderer never measures text (jsdom). */\nexport const LABEL_CHAR_WIDTH = 7.5;\n/** Keeps the default label clear of the inertia bar (drawn right next to the circle). */\nexport const INERTIA_LABEL_SHIFT = 6;\nexport const LABEL_BASELINE_SHIFT = -4;\n/** Second line (sourcing method) below a name label. */\nexport const LABEL_METHOD_LINE_SHIFT = 15;\n/** Distance between the lines of a name that holds line breaks; the name editor follows it. */\nexport const LABEL_LINE_HEIGHT = 16;\nexport const LABEL_OFFSET_LIMIT = 200;\n\nexport type TextAnchor = \"start\" | \"middle\" | \"end\";\n\nexport interface LabelPlacement {\n x: number;\n y: number;\n anchor: TextAnchor;\n}\n\n/** px from a component to its evolve target along the evolution axis (undefined without evolve). */\nexport function movementDeltaX(\n shape: WardleyShape,\n grid: Pick<EvolutionGrid, \"toCanvas\">,\n): number | undefined {\n const movement = shape.movement;\n if (!movement) return undefined;\n const here = grid.toCanvas({ visibility: shape.visibility, evolution: shape.evolution });\n const there = grid.toCanvas({\n visibility: shape.visibility,\n evolution: movement.targetEvolution,\n });\n return there.x - here.x;\n}\n\nexport function estimatedLabelWidth(text: string): number {\n return Math.max(...nameLines(text).map((line) => line.length)) * LABEL_CHAR_WIDTH;\n}\n\nexport function nameLines(text: string | undefined): string[] {\n return (text ?? \"\").split(\"\\n\");\n}\n\n/**\n * How the lines of a name that holds line breaks spread around the slot of a one-line name:\n * `centered` keeps the block's middle on the slot (names beside a circle or a symbol), `up` keeps\n * the last line on it (a name above an icon, a pipeline's top edge or an evolve arrow, which the\n * lines must stay clear of), `down` keeps the first line on it (a name below a pipeline's top edge).\n */\nexport type LineGrowth = \"centered\" | \"up\" | \"down\";\n\nexport function firstLineBaseline(slotY: number, lineCount: number, growth: LineGrowth): number {\n const extra = (lineCount - 1) * LABEL_LINE_HEIGHT;\n if (growth === \"up\") return slotY - extra;\n if (growth === \"down\") return slotY;\n return slotY - extra / 2;\n}\n\nexport function lastLineBaseline(slotY: number, lineCount: number, growth: LineGrowth): number {\n return firstLineBaseline(slotY, lineCount, growth) + (lineCount - 1) * LABEL_LINE_HEIGHT;\n}\n\n/**\n * How the lines of an element's own name grow, shared by the renderer and the name editor. A\n * pipeline's dashed top edge runs through the centre of its anchor component, whose name grows\n * upward as it does over an evolve arrow. The edge runs 11 px above the slot of a member's name:\n * upward, its lines would straddle the edge and run into the anchor component's name, so they grow\n * downward inside the box.\n */\nexport function nameLineGrowth(\n shape: WardleyShape,\n elementRegistry: Pick<ElementRegistry, \"find\">,\n): LineGrowth {\n switch (shape.wardleyType) {\n case \"anchor\":\n case \"pipeline\":\n return \"up\";\n case \"component\":\n if (shape.pipelineId !== undefined) return \"down\";\n return shape.movement || anchorsPipeline(shape, elementRegistry) ? \"up\" : \"centered\";\n default:\n return \"centered\";\n }\n}\n\nfunction anchorsPipeline(\n component: WardleyShape,\n elementRegistry: Pick<ElementRegistry, \"find\">,\n): boolean {\n const pipeline = elementRegistry.find(\n (element) => isPipeline(element) && element.wardleyLabel === component.wardleyLabel,\n );\n return pipeline !== undefined;\n}\n\n/** The canonical OWM slot of a component name — the origin of its `label [dx, dy]`. */\nexport function componentLabelSlot(): { x: number; y: number } {\n return { x: COMPONENT_RADIUS + LABEL_GAP, y: LABEL_BASELINE_SHIFT };\n}\n\n/**\n * A short rightward evolve would run the arrow, the target circle and the red target name into the\n * source name, so the source name moves to the left of its circle.\n */\nexport function isShortRightwardMovement(shape: WardleyShape, movementDeltaX: number): boolean {\n return (\n movementDeltaX > 0 &&\n movementDeltaX < estimatedLabelWidth(shape.wardleyLabel) + 2 * COMPONENT_RADIUS + 2 * LABEL_GAP\n );\n}\n\n/**\n * @param movementDeltaX px from the component to its evolve target (undefined without an evolve).\n */\nexport function componentLabelPlacement(\n shape: WardleyShape,\n movementDeltaX: number | undefined,\n): LabelPlacement {\n const slot = componentLabelSlot();\n if (shape.labelOffset) {\n return {\n x: slot.x + shape.labelOffset.dx,\n y: slot.y + shape.labelOffset.dy,\n anchor: \"start\",\n };\n }\n if (movementDeltaX !== undefined && isShortRightwardMovement(shape, movementDeltaX)) {\n return { x: -slot.x, y: slot.y, anchor: \"end\" };\n }\n const inertiaShift = shape.decorators?.inertia ? INERTIA_LABEL_SHIFT : 0;\n return { x: slot.x + inertiaShift, y: slot.y, anchor: \"start\" };\n}\n\n/** The canonical OWM slot of the evolve target name — the origin of the evolve's `label [dx, dy]`. */\nexport function movementLabelSlot(movementDeltaX: number): { x: number; y: number } {\n return { x: movementDeltaX + COMPONENT_RADIUS + LABEL_GAP, y: LABEL_BASELINE_SHIFT };\n}\n\n/** A leftward evolve puts the target name on the far side, away from the arrow. */\nexport function movementLabelPlacement(\n labelOffset: LabelOffset | undefined,\n movementDeltaX: number,\n): LabelPlacement {\n const slot = movementLabelSlot(movementDeltaX);\n if (labelOffset) {\n return { x: slot.x + labelOffset.dx, y: slot.y + labelOffset.dy, anchor: \"start\" };\n }\n if (movementDeltaX < 0) {\n return { x: movementDeltaX - COMPONENT_RADIUS - LABEL_GAP, y: slot.y, anchor: \"end\" };\n }\n return { x: slot.x, y: slot.y, anchor: \"start\" };\n}\n\n/** The canonical slot of an anchor name: centred above the person icon. */\nexport function anchorLabelSlot(): { x: number; y: number } {\n return { x: 0, y: -ANCHOR_ICON_SIZE / 2 + LABEL_BASELINE_SHIFT };\n}\n\nexport function anchorLabelPlacement(shape: WardleyShape): LabelPlacement {\n const slot = anchorLabelSlot();\n return {\n x: slot.x + (shape.labelOffset?.dx ?? 0),\n y: slot.y + (shape.labelOffset?.dy ?? 0),\n anchor: \"middle\",\n };\n}\n\n/** Integer px, clamped to ±LABEL_OFFSET_LIMIT; `undefined` when the label is back in its slot. */\nexport function normalizeLabelOffset(dx: number, dy: number): LabelOffset | undefined {\n const clamp = (value: number) =>\n Math.max(-LABEL_OFFSET_LIMIT, Math.min(LABEL_OFFSET_LIMIT, Math.round(value)));\n const offset = { dx: clamp(dx) || 0, dy: clamp(dy) || 0 };\n return offset.dx === 0 && offset.dy === 0 ? undefined : offset;\n}\n","import BaseRenderer from \"diagram-js/lib/draw/BaseRenderer\";\nimport { append as svgAppend, create as svgCreate, attr as svgAttr } from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike, ShapeLike, ConnectionLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport {\n COLORS,\n FONT,\n COMPONENT_RADIUS,\n COMPONENT_INNER_RADIUS,\n ANCHOR_ICON_SIZE,\n ATTITUDE_COLORS,\n ATTITUDE_TITLES,\n NOTE_LINE_HEIGHT,\n PIPELINE_ANCHOR_SIZE,\n} from \"./styles.js\";\nimport { drawIcon, ICON_FAST_FORWARD, ICON_FAST_REWIND, ICON_PERSON } from \"./icons.js\";\nimport {\n LABEL_LINE_HEIGHT,\n LABEL_METHOD_LINE_SHIFT,\n anchorLabelPlacement,\n componentLabelPlacement,\n firstLineBaseline,\n lastLineBaseline,\n movementDeltaX as movementDeltaXOf,\n movementLabelPlacement,\n nameLineGrowth,\n nameLines,\n type LabelPlacement,\n type LineGrowth,\n} from \"./label-layout.js\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport { connectionAnchorOf } from \"../layout/index.js\";\n\n/** BaseRenderer default is 1000; 1500 wins the render.shape/render.connection event. */\nconst WARDLEY_RENDER_PRIORITY = 1500;\n\n/** Primary name text of a node (contract shared with other modules and consumers' CSS). */\nexport const NAME_LABEL_CLASS = \"wardley-name-label\";\n/** Groups every evolve visual so tools (e.g. the context pad) can tell the node from its movement. */\nexport const MOVEMENT_CLASS = \"wardley-movement\";\n/** Labels the user may drag to set an OWM `label [dx, dy]` offset (see the label-drag module). */\nexport const LABEL_HANDLE_CLASS = \"wardley-label-handle\";\n/** Which offset a dragged label writes: the node's own `labelOffset` or its evolve's. */\nexport const LABEL_ROLE_ATTRIBUTE = \"data-label-role\";\nconst ATTITUDE_TITLE_CLEARANCE = 6;\n\ntype Attrs = Record<string, string | number>;\n\nexport default class WardleyRenderer extends BaseRenderer {\n static $inject = [\"eventBus\", \"evolutionGrid\", \"elementRegistry\"];\n\n constructor(\n eventBus: EventBus,\n private readonly grid: EvolutionGrid,\n private readonly elementRegistry: ElementRegistry,\n ) {\n super(eventBus, WARDLEY_RENDER_PRIORITY);\n }\n\n override canRender(element: ElementLike): boolean {\n return isWardleyShape(element) || isWardleyConnection(element);\n }\n\n override drawShape(visuals: SVGElement, element: ShapeLike): SVGElement {\n const shape = element as unknown as WardleyShape;\n switch (shape.wardleyType) {\n case \"pipeline\":\n return this.drawPipeline(visuals, shape);\n case \"anchor\":\n return this.drawAnchor(visuals, shape);\n case \"note\":\n return this.drawNote(visuals, shape);\n case \"attitude\":\n return this.drawAttitude(visuals, shape);\n case \"annotation\":\n return this.drawAnnotation(visuals, shape);\n case \"accelerator\":\n return this.drawAccelerator(visuals, shape);\n case \"submap\":\n return this.drawSubmap(visuals, shape);\n case \"drawing\":\n return this.drawDrawing(visuals, shape);\n case \"component\":\n default:\n return this.drawComponent(visuals, shape);\n }\n }\n\n /** Freeform drawing: polyline/polygon from relative points (see WardleyDrawTool). */\n private drawDrawing(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const pts = shape.drawingPoints ?? [];\n const dash =\n shape.strokeStyle === \"dashed\" ? \"8 5\" : shape.strokeStyle === \"dotted\" ? \"2 4\" : undefined;\n const path = svgAttr(svgCreate(shape.closed ? \"polygon\" : \"polyline\"), {\n points: pts.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: shape.color ?? COLORS.ink,\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n ...(dash ? { \"stroke-dasharray\": dash } : {}),\n });\n svgAppend(visuals, path);\n return path;\n }\n\n override drawConnection(visuals: SVGElement, element: ConnectionLike): SVGElement {\n const conn = element as unknown as WardleyConnection;\n const isFlow = conn.wardleyType === \"flow\";\n const color = isFlow ? COLORS.flow : COLORS.dependency;\n const [start, end] = endpoints(conn);\n\n const path = svgAttr(svgCreate(\"polyline\"), {\n points: `${start.x},${start.y} ${end.x},${end.y}`,\n fill: \"none\",\n stroke: color,\n \"stroke-width\": isFlow ? 2.5 : 1.5,\n \"stroke-linecap\": \"round\",\n });\n svgAppend(visuals, path);\n\n // Canon: dependencies are plain lines WITHOUT an arrowhead (direction follows from the value\n // chain, concept doc §8.3); only flow links carry arrowheads (bidirectional: on both ends).\n if (isFlow) {\n svgAppend(visuals, connectionArrow(start, end, color, 11, 5));\n if (conn.bidirectional) {\n svgAppend(visuals, connectionArrow(end, start, color, 11, 5));\n }\n }\n const mx = (start.x + end.x) / 2;\n const my = (start.y + end.y) / 2;\n if (isFlow && conn.flowValue) {\n svgAppend(\n visuals,\n label(conn.flowValue, mx, my - 5, {\n \"text-anchor\": \"middle\",\n \"font-size\": 11,\n fill: COLORS.flow,\n }),\n );\n }\n // Link annotation (`; …`) at the midpoint (a bit lower if a flow value is also present).\n if (conn.linkLabel) {\n svgAppend(\n visuals,\n label(conn.linkLabel, mx, my + (conn.flowValue ? 12 : -4), {\n \"text-anchor\": \"middle\",\n \"font-size\": 11,\n \"font-style\": \"italic\",\n fill: COLORS.axisText,\n }),\n );\n }\n return path;\n }\n\n override getShapePath(shape: ShapeLike): string {\n const { x, y, width, height } = shape;\n return `M${x},${y}l${width},0l0,${height}l${-width},0z`;\n }\n\n override getConnectionPath(connection: ConnectionLike): string {\n const [first, ...rest] = connection.waypoints;\n if (!first) return \"\";\n return `M${first.x},${first.y}` + rest.map((p: Point) => `L${p.x},${p.y}`).join(\"\");\n }\n\n private drawComponent(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const dec = shape.decorators;\n const movementDeltaX = movementDeltaXOf(shape, this.grid);\n\n if (movementDeltaX !== undefined) this.drawMovement(visuals, shape, cx, cy, movementDeltaX);\n if (dec?.inertia) drawInertiaMarker(visuals, cx, cy);\n\n // User-picked element color tints stroke and label (default: ink-on-paper look).\n const tint = shape.color ?? COLORS.stroke;\n const ring = circle(cx, cy, COMPONENT_RADIUS, {\n fill: COLORS.componentFill,\n stroke: tint,\n \"stroke-width\": 2,\n });\n svgAppend(visuals, ring);\n\n // \"evolving\" = double ring (echoing the BPMN intermediate event).\n if (shape.movement) {\n svgAppend(\n visuals,\n circle(cx, cy, COMPONENT_INNER_RADIUS, { fill: \"none\", stroke: tint, \"stroke-width\": 1.5 }),\n );\n }\n\n drawComponentSymbols(visuals, cx, cy, tint, dec);\n drawComponentLabel(\n visuals,\n shape,\n cx,\n cy,\n componentLabelPlacement(shape, movementDeltaX),\n nameLineGrowth(shape, this.elementRegistry),\n );\n return ring;\n }\n\n /** Planned evolution (canon: DASHED red line with arrow, target label in red). */\n private drawMovement(\n visuals: SVGElement,\n shape: WardleyShape,\n cx: number,\n cy: number,\n movementDeltaX: number,\n ): void {\n const mv = shape.movement;\n if (!mv) return;\n const group = svgAttr(svgCreate(\"g\"), { class: MOVEMENT_CLASS });\n svgAppend(visuals, group);\n const tx = cx + movementDeltaX;\n // End the arrowhead BEFORE the target circle's edge — otherwise the circle hides it entirely.\n const dir = Math.sign(movementDeltaX) || 1;\n const tipX = tx - dir * (COMPONENT_RADIUS + 2);\n // Paper-coloured knock-out: a pipeline's dashed top edge runs through its anchor component's\n // centre line, and two interleaved dash patterns read as one broken line.\n svgAppend(\n group,\n line(cx, cy, tipX, cy, {\n stroke: COLORS.plotBackground,\n \"stroke-width\": 4,\n \"stroke-linecap\": \"butt\",\n class: \"wardley-movement-underlay\",\n }),\n );\n svgAppend(\n group,\n line(cx, cy, tipX, cy, {\n stroke: COLORS.movement,\n \"stroke-width\": 1.5,\n \"stroke-dasharray\": \"6 4\",\n }),\n );\n svgAppend(group, connectionArrow({ x: cx, y: cy }, { x: tipX, y: cy }, COLORS.movement));\n // Target circle = direct drag handle: marked by class so the evolve module can intercept a\n // mousedown on it and let the target be moved by dragging (see WardleyEvolveDragging).\n svgAppend(\n group,\n circle(tx, cy, COMPONENT_RADIUS, {\n fill: COLORS.paper,\n stroke: COLORS.movement,\n \"stroke-width\": 2,\n class: \"wardley-evolve-handle\",\n }),\n );\n // Target label (evolve Old->New) or the component's name — canonically red at the target circle.\n const placement = movementLabelPlacement(mv.labelOffset, movementDeltaX);\n const targetName = mv.newLabel ?? shape.wardleyLabel;\n svgAppend(\n group,\n label(\n targetName,\n cx + placement.x,\n cy + placement.y,\n {\n \"font-weight\": \"500\",\n fill: COLORS.movement,\n \"text-anchor\": placement.anchor,\n class: `wardley-movement-label ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"movement\",\n },\n true,\n \"centered\",\n ),\n );\n if (mv.method) {\n const lastLineY = lastLineBaseline(\n cy + placement.y,\n nameLines(targetName).length,\n \"centered\",\n );\n svgAppend(\n group,\n label(mv.method, cx + placement.x, lastLineY + LABEL_METHOD_LINE_SHIFT, {\n \"font-size\": 10.5,\n fill: COLORS.movement,\n \"text-anchor\": placement.anchor,\n }),\n );\n }\n }\n\n private drawAnchor(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const icon = drawIcon(ICON_PERSON, cx, cy, ANCHOR_ICON_SIZE, shape.color ?? COLORS.ink);\n svgAppend(visuals, icon);\n const placement = anchorLabelPlacement(shape);\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + placement.x,\n cy + placement.y,\n {\n \"text-anchor\": placement.anchor,\n \"font-weight\": \"700\",\n class: `${NAME_LABEL_CLASS} ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"name\",\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n nameLineGrowth(shape, this.elementRegistry),\n ),\n );\n return icon;\n }\n\n private drawPipeline(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const width = Math.max(shape.width, 1);\n const tint = shape.color;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: 0,\n y: 0,\n width,\n height: Math.max(shape.height, 1),\n rx: 4,\n // No background fill — the box is a pure outline (the variants stay fully visible).\n fill: \"none\",\n stroke: tint ?? COLORS.pipeline,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"6 3\",\n });\n svgAppend(visuals, box);\n // OWM anchor convention: if a same-named component exists, THAT component is the anchor —\n // drawing a second ■ (and a duplicate label) on the box would just clutter the line.\n // Only standalone pipelines render their own ■ anchor + name on the top edge.\n const hasNamedComponent = this.elementRegistry\n .filter(\n (el) => isWardleyShape(el) && (el as unknown as WardleyShape).wardleyType === \"component\",\n )\n .some((c) => (c as unknown as WardleyShape).wardleyLabel === shape.wardleyLabel);\n if (!hasNamedComponent) {\n const half = PIPELINE_ANCHOR_SIZE / 2;\n svgAppend(\n visuals,\n svgAttr(svgCreate(\"rect\"), {\n x: width / 2 - half,\n y: -half,\n width: PIPELINE_ANCHOR_SIZE,\n height: PIPELINE_ANCHOR_SIZE,\n fill: COLORS.componentFill,\n stroke: tint ?? COLORS.stroke,\n \"stroke-width\": 2,\n }),\n );\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n width / 2 + half + 6,\n -4,\n {\n \"font-weight\": \"500\",\n class: NAME_LABEL_CLASS,\n ...(tint ? { fill: tint } : {}),\n },\n true,\n nameLineGrowth(shape, this.elementRegistry),\n ),\n );\n }\n return box;\n }\n\n private drawNote(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const color = shape.color;\n const lines = (shape.wardleyLabel ?? \"\").split(\"\\n\");\n const cx = shape.width / 2;\n // Center the block of lines vertically in the box (+4 ~ baseline offset for 13px).\n const y0 = shape.height / 2 - ((lines.length - 1) * NOTE_LINE_HEIGHT) / 2 + 4;\n const attrs = {\n \"text-anchor\": \"middle\",\n class: NAME_LABEL_CLASS,\n fill: color ?? COLORS.noteText,\n \"font-style\": \"italic\",\n // Colored notes are slightly bolder -> feedback (good/bad) stands out.\n ...(color ? { \"font-weight\": \"600\" } : {}),\n };\n let first: SVGElement | undefined;\n lines.forEach((line, i) => {\n const el = label(line, cx, y0 + i * NOTE_LINE_HEIGHT, attrs);\n svgAppend(visuals, el);\n if (!first) first = el;\n });\n return first ?? svgCreate(\"text\");\n }\n\n private drawAttitude(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const kind = shape.attitudeKind ?? \"pioneers\";\n const c = ATTITUDE_COLORS[kind] ?? ATTITUDE_COLORS[\"pioneers\"]!;\n // A user-picked color overrides the kind palette (stroke + label; the soft fill stays).\n const stroke = shape.color ?? c.stroke;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: 0,\n y: 0,\n width: Math.max(shape.width, 1),\n height: Math.max(shape.height, 1),\n rx: 10,\n fill: c.fill,\n stroke,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"5 4\",\n });\n svgAppend(visuals, box);\n // Regions sit behind every line, so a title inside the box gets struck through by dependencies.\n // Above the top edge it stays clear — unless that would leave the plot (then it stays inside).\n const plotTop = this.grid.toCanvas({ visibility: 1, evolution: 0 }).y;\n const titleAbove = shape.y - ATTITUDE_TITLE_CLEARANCE - FONT.label >= plotTop;\n // Regions are unlabelled as in OWM: the title is always the canonical kind name.\n svgAppend(\n visuals,\n label(\n ATTITUDE_TITLES[kind] ?? kind,\n titleAbove ? 4 : 10,\n titleAbove ? -ATTITUDE_TITLE_CLEARANCE : 18,\n {\n fill: stroke,\n \"font-weight\": \"700\",\n \"letter-spacing\": \"0.04em\",\n class: \"wardley-attitude-title\",\n },\n ),\n );\n return box;\n }\n\n private drawAnnotation(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const marker = circle(cx, cy, 10, {\n fill: COLORS.annotationFill,\n stroke: shape.color ?? COLORS.stroke,\n \"stroke-width\": 1.25,\n });\n svgAppend(visuals, marker);\n svgAppend(\n visuals,\n label(\n String(shape.annotationNumber ?? \"\"),\n cx,\n cy + 4,\n { \"text-anchor\": \"middle\", \"font-size\": 11, \"font-weight\": \"700\" },\n false,\n ),\n );\n if (shape.wardleyLabel) {\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + 15,\n cy + 4,\n { \"font-size\": 12, fill: COLORS.noteText, class: NAME_LABEL_CLASS },\n true,\n nameLineGrowth(shape, this.elementRegistry),\n ),\n );\n }\n return marker;\n }\n\n private drawAccelerator(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const accelerate = shape.acceleratorDirection !== \"deaccelerate\";\n // Real arrow symbol (OWM canon: a clearly visible market force, not a text glyph).\n const sym = drawIcon(\n accelerate ? ICON_FAST_FORWARD : ICON_FAST_REWIND,\n cx,\n cy,\n 24,\n shape.color ?? (accelerate ? COLORS.accelerator : COLORS.deaccelerator),\n );\n svgAppend(visuals, sym);\n if (shape.wardleyLabel) {\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + 15,\n cy + 5,\n { \"font-size\": 12, class: NAME_LABEL_CLASS },\n true,\n nameLineGrowth(shape, this.elementRegistry),\n ),\n );\n }\n return sym;\n }\n\n private drawSubmap(visuals: SVGElement, shape: WardleyShape): SVGElement {\n const cx = shape.width / 2;\n const cy = shape.height / 2;\n const r = COMPONENT_RADIUS + 1;\n const tint = shape.color ?? COLORS.stroke;\n const outer = svgAttr(svgCreate(\"rect\"), {\n x: cx - r,\n y: cy - r,\n width: r * 2,\n height: r * 2,\n rx: 3,\n fill: COLORS.componentFill,\n stroke: tint,\n \"stroke-width\": 2,\n });\n svgAppend(visuals, outer);\n svgAppend(\n visuals,\n svgAttr(svgCreate(\"rect\"), {\n x: cx - r + 3,\n y: cy - r + 3,\n width: r * 2 - 6,\n height: r * 2 - 6,\n rx: 1.5,\n fill: \"none\",\n stroke: tint,\n \"stroke-width\": 1,\n }),\n );\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n cx + r + 6,\n cy - 6,\n {\n \"font-weight\": \"500\",\n class: NAME_LABEL_CLASS,\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n nameLineGrowth(shape, this.elementRegistry),\n ),\n );\n return outer;\n }\n}\n\nfunction drawInertiaMarker(visuals: SVGElement, cx: number, cy: number): void {\n const bx = cx + COMPONENT_RADIUS + 3;\n svgAppend(\n visuals,\n line(bx, cy - 13, bx, cy + 13, {\n stroke: COLORS.inertia,\n \"stroke-width\": 3,\n \"stroke-linecap\": \"round\",\n }),\n );\n}\n\n/** Canon symbols: market = three dots in a triangle, ecosystem = dotted outer ring. */\nfunction drawComponentSymbols(\n visuals: SVGElement,\n cx: number,\n cy: number,\n tint: string,\n dec: WardleyShape[\"decorators\"],\n): void {\n if (dec?.ecosystem) {\n svgAppend(\n visuals,\n circle(cx, cy, COMPONENT_RADIUS + 3.5, {\n fill: \"none\",\n stroke: tint,\n \"stroke-width\": 1.25,\n \"stroke-dasharray\": \"1.5 3\",\n \"stroke-linecap\": \"round\",\n }),\n );\n }\n if (dec?.market) {\n for (const [mx, my] of [\n [0, -3.8],\n [-3.4, 2.4],\n [3.4, 2.4],\n ] as const) {\n svgAppend(visuals, circle(cx + mx, cy + my, 1.7, { fill: tint }));\n }\n }\n}\n\n/**\n * Name label (honoring the OWM `label [dx, dy]` offset) plus the optional sourcing method below it.\n * Sourcing stays a subtle text label — deliberately no marker box (product decision: calm canvas).\n */\nfunction drawComponentLabel(\n visuals: SVGElement,\n shape: WardleyShape,\n cx: number,\n cy: number,\n placement: LabelPlacement,\n growth: LineGrowth,\n): void {\n const lx = cx + placement.x;\n const ly = cy + placement.y;\n svgAppend(\n visuals,\n label(\n shape.wardleyLabel,\n lx,\n ly,\n {\n \"font-weight\": \"500\",\n \"text-anchor\": placement.anchor,\n class: `${NAME_LABEL_CLASS} ${LABEL_HANDLE_CLASS}`,\n [LABEL_ROLE_ATTRIBUTE]: \"name\",\n ...(shape.color ? { fill: shape.color } : {}),\n },\n true,\n growth,\n ),\n );\n const method = shape.decorators?.method;\n if (method) {\n const lastLineY = lastLineBaseline(ly, nameLines(shape.wardleyLabel).length, growth);\n svgAppend(\n visuals,\n label(method, lx, lastLineY + LABEL_METHOD_LINE_SHIFT, {\n \"font-size\": 10.5,\n \"text-anchor\": placement.anchor,\n fill: COLORS.axisText,\n }),\n );\n }\n}\n\nfunction circle(cx: number, cy: number, r: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"circle\"), { cx, cy, r, \"stroke-width\": 1, ...attrs });\n}\n\nfunction line(x1: number, y1: number, x2: number, y2: number, attrs: Attrs): SVGElement {\n return svgAttr(svgCreate(\"line\"), { x1, y1, x2, y2, ...attrs });\n}\n\n/**\n * Text label with a paper halo (paint-order: stroke) for legibility over lines/bands.\n * `halo=false` disables the halo (e.g. for annotation numbers on a filled marker). With `growth`\n * the content is a name whose line breaks make lines of their own (one `<tspan>` each, so it\n * stays a single text for dragging and editing); `y` is the baseline of a name of one line.\n */\nfunction label(\n content: string,\n x: number,\n y: number,\n attrs: Attrs = {},\n halo = true,\n growth?: LineGrowth,\n): SVGElement {\n const lines = growth ? nameLines(content) : [content];\n const firstLineY = growth ? firstLineBaseline(y, lines.length, growth) : y;\n const haloAttrs: Attrs = halo\n ? {\n stroke: COLORS.paper,\n \"stroke-width\": 3.5,\n \"paint-order\": \"stroke\",\n \"stroke-linejoin\": \"round\",\n }\n : {};\n const el = svgAttr(svgCreate(\"text\"), {\n x,\n y: firstLineY,\n \"font-family\": FONT.family,\n \"font-size\": FONT.label,\n fill: COLORS.ink,\n ...haloAttrs,\n ...attrs,\n });\n if (lines.length === 1) {\n el.textContent = lines[0]!;\n return el;\n }\n lines.forEach((line, index) => {\n const row = svgAttr(svgCreate(\"tspan\"), { x, y: firstLineY + index * LABEL_LINE_HEIGHT });\n row.textContent = line;\n svgAppend(el, row);\n });\n return el;\n}\n\nfunction connectionArrow(from: Point, to: Point, color: string, len = 10, w = 5): SVGElement {\n const angle = Math.atan2(to.y - from.y, to.x - from.x);\n const bx = to.x - len * Math.cos(angle);\n const by = to.y - len * Math.sin(angle);\n const points =\n `${to.x},${to.y} ` +\n `${bx - w * Math.sin(angle)},${by + w * Math.cos(angle)} ` +\n `${bx + w * Math.sin(angle)},${by - w * Math.cos(angle)}`;\n return svgAttr(svgCreate(\"polygon\"), { points, fill: color });\n}\n\n/** Effective radius of a node for cropping the connection at its boundary. */\nfunction radiusOf(s: WardleyShape): number {\n if (s.wardleyType === \"component\") return COMPONENT_RADIUS + 2;\n if (s.wardleyType === \"anchor\") return ANCHOR_ICON_SIZE / 2 + 1;\n if (s.wardleyType === \"pipeline\") return PIPELINE_ANCHOR_SIZE / 2 + 2;\n return Math.min(s.width, s.height) / 2;\n}\n\n/**\n * Connection endpoints from the CURRENT node centers, cropped at their boundary\n * (BPMN look: line ends at the edge, arrowhead visible — independent of z-order, and\n * correct after moving, since recomputed on every render).\n */\nfunction endpoints(conn: WardleyConnection): [Point, Point] {\n const s = conn.source as unknown as WardleyShape | undefined;\n const t = conn.target as unknown as WardleyShape | undefined;\n const wp = conn.waypoints;\n if (!s || !t) {\n const a = wp[0] ?? { x: 0, y: 0 };\n return [a, wp[wp.length - 1] ?? a];\n }\n const sc = connectionAnchorOf(s);\n const tc = connectionAnchorOf(t);\n const dx = tc.x - sc.x;\n const dy = tc.y - sc.y;\n const dist = Math.hypot(dx, dy) || 1;\n const ux = dx / dist;\n const uy = dy / dist;\n const sr = radiusOf(s);\n const tr = radiusOf(t);\n if (dist <= sr + tr + 2) return [sc, tc];\n return [\n { x: sc.x + ux * sr, y: sc.y + uy * sr },\n { x: tc.x - ux * tr, y: tc.y - uy * tr },\n ];\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyRenderer from \"./WardleyRenderer.js\";\n\n/** SVG rendering of all Wardley types (BaseRenderer subclass, priority 1500). */\nexport const wardleyDrawModule: ModuleDeclaration = {\n __init__: [\"wardleyRenderer\"],\n wardleyRenderer: [\"type\", WardleyRenderer],\n};\n\nexport {\n default as WardleyRenderer,\n LABEL_HANDLE_CLASS,\n LABEL_ROLE_ATTRIBUTE,\n MOVEMENT_CLASS,\n NAME_LABEL_CLASS,\n} from \"./WardleyRenderer.js\";\nexport {\n componentLabelPlacement,\n componentLabelSlot,\n movementDeltaX,\n movementLabelPlacement,\n movementLabelSlot,\n nameLineGrowth,\n normalizeLabelOffset,\n type LabelPlacement,\n type LineGrowth,\n} from \"./label-layout.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport { WardleyBaseViewer } from \"./WardleyBaseViewer.js\";\nimport { wardleyModelModule } from \"./model/index.js\";\nimport { evolutionGridModule } from \"./evolution-grid/index.js\";\nimport { wardleyDrawModule } from \"./draw/index.js\";\nimport { ioModule } from \"./io/index.js\";\n\nexport class Viewer extends WardleyBaseViewer {\n protected _getModules(): ModuleDeclaration[] {\n return [wardleyModelModule, evolutionGridModule, wardleyDrawModule, ioModule];\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { FreeRect, FreeRectInsets } from \"../free-rect/index.js\";\nimport { exportBounds } from \"../io/index.js\";\n\n/** Margins in diagram px, for hosts that report no chrome insets. */\nconst PAD_TOP = 180;\nconst PAD_BOTTOM = 80;\nconst PAD_SIDE = 120;\n/**\n * Screen px of empty space the view may show beyond the content inside the host's free rectangle.\n * Room on both sides of an axis, so a view the host fitted into its free rectangle (guide §5.9)\n * is never pulled away: the host would take the pull for a user move and stop keeping the view\n * fitted.\n */\nconst INSET_SLACK = 96;\nconst EPSILON = 0.5;\n\ninterface Pads {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** The free rectangle along one axis, in diagram px at the view's scale. */\ninterface FreeAxis {\n /** Covered by the host's chrome before and after the free part. */\n before: number;\n after: number;\n slack: number;\n}\n\ntype ViewBox = { x: number; y: number; width: number; height: number; scale?: number };\ntype Bounds = { x: number; y: number; width: number; height: number };\n\nconst clamp = (value: number, lo: number, hi: number): number =>\n value < lo ? lo : value > hi ? hi : value;\n\n/**\n * Clamps one axis of the view into `[min, max]` widened by the padding on both sides.\n *\n * @param recentre a view larger than the padded bounds is centred on them; without it the view\n * only moves as far as needed to keep `[min, max]` fully visible (after a resize the plot\n * must not jump away from the corner the user just dragged).\n */\nfunction constrainAxis(\n position: number,\n viewSize: number,\n bounds: { min: number; max: number; padBefore: number; padAfter: number },\n recentre: boolean,\n): number {\n const lowest = bounds.min - bounds.padBefore;\n const highest = bounds.max + bounds.padAfter;\n if (!recentre && viewSize >= bounds.max - bounds.min) {\n // Either stay within the padded bounds, or show the whole content: whichever moves less.\n return clamp(\n position,\n Math.min(bounds.max - viewSize, lowest),\n Math.max(bounds.min, highest - viewSize),\n );\n }\n if (viewSize <= highest - lowest) return clamp(position, lowest, highest - viewSize);\n return (lowest + highest) / 2 - viewSize / 2;\n}\n\n/**\n * The view positions along one axis that keep `bounds` in the host's free rectangle: bounds\n * smaller than the free part may sit anywhere inside it, larger ones may be panned along it, each\n * up to `slack` beyond.\n */\nfunction freeAreaRange(\n viewSize: number,\n bounds: { min: number; max: number },\n free: FreeAxis,\n): { lowest: number; highest: number } {\n const freeEnd = viewSize - free.after;\n return {\n lowest: Math.min(bounds.min - free.before - free.slack, bounds.max - freeEnd - free.slack),\n highest: Math.max(bounds.max - freeEnd + free.slack, bounds.min - free.before + free.slack),\n };\n}\n\n/**\n * Clamps one axis of the view so the content stays in the host's free rectangle. Never centres,\n * so a view the host placed in its free rectangle stays put. A view that keeps the plot there is\n * accepted as well: the import and hosts fit the plot, and a long label beyond it that makes the\n * content wider than the free part must not pull that fit sideways. The plot lies inside the\n * content, so the two ranges overlap and their hull is one range.\n */\nfunction constrainAxisToFreeArea(\n position: number,\n viewSize: number,\n content: { min: number; max: number },\n plot: { min: number; max: number },\n free: FreeAxis,\n): number {\n const byContent = freeAreaRange(viewSize, content, free);\n const byPlot = freeAreaRange(viewSize, plot, free);\n return clamp(\n position,\n Math.min(byContent.lowest, byPlot.lowest),\n Math.max(byContent.highest, byPlot.highest),\n );\n}\n\n/**\n * Keeps the map in view while scrolling and zooming.\n * Without this the user could scroll the map completely off-screen into empty space.\n * After every move we pull the visible area back so it stays close to the map,\n * leaving only a small margin of empty space around it. \"The map\" is the plot plus any content\n * reaching beyond it (long labels at the commodity edge, notes in the margin): `contentBounds()`,\n * which hosts also fit the view to. With the insets of a host's chrome (`freeArea: { insets }`)\n * the margin is measured inside the free rectangle, so the map never slips under the chrome, and a\n * view the host or the import fitted there, to the content or to the plot, is left alone.\n */\nexport default class PanConstraint {\n static $inject = [\"eventBus\", \"canvas\", \"evolutionGrid\", \"injector\"];\n\n private applying = false;\n /** Content bounds are measured lazily (getBBox), at most once per change of the map. */\n private measured: Bounds | undefined;\n /** A config change (resize) happened; re-check once its elements are redrawn. */\n private constrainAfterCommand = false;\n private readonly freeRect: FreeRect | null;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly grid: EvolutionGrid,\n injector: Injector,\n ) {\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n eventBus.on(\"canvas.viewbox.changed\", (event: { viewbox?: ViewBox }) => {\n if (this.applying) return;\n this.constrain(event?.viewbox);\n });\n const invalidate = () => {\n this.measured = undefined;\n };\n eventBus.on([\"element.changed\", \"import.done\"], invalidate);\n // Shrinking the plot while scrolled into its far corner must never leave a blank viewport.\n // A transient change (live resize preview) is skipped: moving the viewport under a dragged\n // plot corner would feed back into the drag.\n eventBus.on(\"wardley.config.changed\", (event?: { transient?: boolean }) => {\n invalidate();\n if (event?.transient) return;\n this.constrain(undefined, { recentre: false });\n // The command's elements are redrawn only after this event — measure again once they are.\n this.constrainAfterCommand = true;\n });\n eventBus.on(\"commandStack.changed\", () => {\n if (!this.constrainAfterCommand) return;\n invalidate();\n this.constrain(undefined, { recentre: false });\n });\n }\n\n /**\n * The plot (with its axis margins) united with everything drawn on it or beyond it, tight (no\n * padding): what a host fits the view to.\n */\n contentBounds(): Bounds {\n this.measured ??= exportBounds(this.canvas, this.grid, 0);\n return this.measured;\n }\n\n /** The host's free rectangle along both axes at the view's scale, if the host reports one. */\n private freeArea(view: ViewBox): { x: FreeAxis; y: FreeAxis } | undefined {\n const insets: FreeRectInsets | undefined = this.freeRect?.insets();\n const scale = insets ? (view.scale ?? this.canvas.zoom()) : 0;\n if (!insets || !(scale > 0)) return undefined;\n const slack = INSET_SLACK / scale;\n // An axis the chrome leaves no room on counts as free across the whole container, as the\n // host's fit and keyboard creation treat it.\n const axis = (size: number, before: number, after: number): FreeAxis =>\n size * scale - before - after > 0\n ? { before: before / scale, after: after / scale, slack }\n : { before: 0, after: 0, slack };\n return {\n x: axis(view.width, insets.left, insets.right),\n y: axis(view.height, insets.top, insets.bottom),\n };\n }\n\n private constrain(viewbox?: ViewBox, { recentre = true }: { recentre?: boolean } = {}): void {\n this.constrainAfterCommand = false;\n const current = viewbox ?? (this.canvas.viewbox() as unknown as ViewBox);\n const bounds = this.contentBounds();\n if (\n !(bounds.width > 0) ||\n !(bounds.height > 0) ||\n !(current.width > 0) ||\n !(current.height > 0)\n )\n return;\n\n const horizontal = { min: bounds.x, max: bounds.x + bounds.width };\n const vertical = { min: bounds.y, max: bounds.y + bounds.height };\n const free = this.freeArea(current);\n const plot = this.grid.outerBounds();\n const pads: Pads = { top: PAD_TOP, right: PAD_SIDE, bottom: PAD_BOTTOM, left: PAD_SIDE };\n const clampedX = free\n ? constrainAxisToFreeArea(\n current.x,\n current.width,\n horizontal,\n { min: plot.x, max: plot.x + plot.width },\n free.x,\n )\n : constrainAxis(\n current.x,\n current.width,\n { ...horizontal, padBefore: pads.left, padAfter: pads.right },\n recentre,\n );\n const clampedY = free\n ? constrainAxisToFreeArea(\n current.y,\n current.height,\n vertical,\n { min: plot.y, max: plot.y + plot.height },\n free.y,\n )\n : constrainAxis(\n current.y,\n current.height,\n { ...vertical, padBefore: pads.top, padAfter: pads.bottom },\n recentre,\n );\n\n if (Math.abs(clampedX - current.x) < EPSILON && Math.abs(clampedY - current.y) < EPSILON)\n return;\n\n this.applying = true;\n try {\n this.canvas.viewbox({\n x: clampedX,\n y: clampedY,\n width: current.width,\n height: current.height,\n });\n } finally {\n this.applying = false;\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PanConstraint from \"./PanConstraint.js\";\n\nexport const PanConstraintModule: ModuleDeclaration = {\n __init__: [\"panConstraint\"],\n panConstraint: [\"type\", PanConstraint],\n};\n\nexport { default as PanConstraint } from \"./PanConstraint.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\n\n/** What a host's chrome covers along the container's edges, in px (Miragon guide §5.9). */\nexport interface FreeRectInsets {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\n/** Diagram config `wardleyFreeRect` (viewer option `freeArea`). */\nexport interface FreeRectConfig {\n /** What the chrome covers, in px from the container's edges. */\n insets?: () => FreeRectInsets;\n /** The centre of the free rectangle in diagram coordinates, `undefined` while there is none. */\n center?: () => { x: number; y: number } | undefined;\n}\n\n/**\n * The part of the canvas no host chrome covers. Keyboard creation places new elements in its\n * centre (guide §5.5) and the pan constraint keeps the map reachable around it, so both agree with\n * a host that fits the map into the same rectangle.\n */\nexport default class FreeRect {\n static $inject = [\"canvas\", \"config.wardleyFreeRect\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly config: FreeRectConfig | undefined,\n ) {}\n\n /** The host's insets, or `undefined` when it reports none. */\n insets(): FreeRectInsets | undefined {\n const insets = this.config?.insets?.();\n if (!insets) return undefined;\n const sides = [insets.top, insets.right, insets.bottom, insets.left];\n return sides.every((side) => Number.isFinite(side) && side >= 0) ? insets : undefined;\n }\n\n /**\n * The centre of the free rectangle in diagram coordinates: the host's own when it reports one,\n * else the whole visible area without insets. An axis whose insets leave no room centres in the\n * whole container, as fitting does.\n */\n center(): { x: number; y: number } {\n const reported = this.config?.center?.();\n if (reported && Number.isFinite(reported.x) && Number.isFinite(reported.y)) return reported;\n const viewbox = this.canvas.viewbox();\n const insets = this.insets() ?? { top: 0, right: 0, bottom: 0, left: 0 };\n // The viewbox caches the container size until its next change; the canvas measures afresh.\n const { width, height } = this.canvas.getSize();\n const centerOf = (size: number, before: number, after: number) =>\n size - before - after > 0 ? before + (size - before - after) / 2 : size / 2;\n return {\n x: viewbox.x + centerOf(width, insets.left, insets.right) / viewbox.scale,\n y: viewbox.y + centerOf(height, insets.top, insets.bottom) / viewbox.scale,\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport FreeRect from \"./FreeRect.js\";\n\n/** The canvas area a host's chrome leaves free (keyboard creation, pan constraint). */\nexport const freeRectModule: ModuleDeclaration = {\n wardleyFreeRect: [\"type\", FreeRect],\n};\n\nexport { default as FreeRect } from \"./FreeRect.js\";\nexport type { FreeRectConfig, FreeRectInsets } from \"./FreeRect.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport SelectionModule from \"diagram-js/lib/features/selection\";\nimport ZoomScrollModule from \"diagram-js/lib/navigation/zoomscroll\";\nimport MoveCanvasModule from \"diagram-js/lib/navigation/movecanvas\";\nimport KeyboardModule from \"diagram-js/lib/features/keyboard\";\nimport { Viewer } from \"./Viewer.js\";\nimport { PanConstraintModule } from \"./pan-constraint/index.js\";\nimport { freeRectModule } from \"./free-rect/index.js\";\n\n/**\n * `keyboard-move-selection` depends on `modeling` and therefore belongs in the (later) Modeler,\n * not in the read-only NavigatedViewer.\n */\nexport class NavigatedViewer extends Viewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n SelectionModule,\n ZoomScrollModule,\n MoveCanvasModule,\n KeyboardModule,\n freeRectModule,\n PanConstraintModule,\n ];\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\nimport type ToolManager from \"diagram-js/lib/features/tool-manager/ToolManager\";\n\ninterface ElementMouseEvent {\n element?: unknown;\n originalEvent?: MouseEvent;\n}\n\n/** The lasso's tool name in diagram-js's tool manager, and the drag that holds it armed. */\nconst LASSO_TOOL = \"lasso\";\nexport const LASSO_SELECTION = \"lasso.selection\";\n\n/**\n * Activates the diagram-js lasso via Shift+drag on the empty canvas.\n * Plain drag stays canvas pan (MoveCanvas); Shift+click on elements stays multi-select.\n * The lasso tool counts as active exactly while its drag holds it armed, so a palette's pressed\n * state (`tool-manager.update`) follows it.\n */\nexport default class WardleyLassoBehavior {\n static $inject = [\"eventBus\", \"canvas\", \"lassoTool\", \"toolManager\"];\n\n constructor(eventBus: EventBus, canvas: Canvas, lassoTool: LassoTool, toolManager: ToolManager) {\n eventBus.on(\"element.mousedown\", 1500, (event: ElementMouseEvent) => {\n const original = event.originalEvent;\n if (!original?.shiftKey) return undefined;\n let root: unknown;\n try {\n root = canvas.getRootElement();\n } catch {\n return undefined;\n }\n if (event.element !== root) return undefined;\n lassoTool.activateLasso(original);\n // Returning false stops lower-priority listeners (canvas pan).\n return false;\n });\n // diagram-js releases a tool when its drag ends, but on a cancel only once the pointer has moved\n // the drag, so a lasso that only waited, put down by Escape or from its entry, stayed pressed.\n eventBus.on(`${LASSO_SELECTION}.cleanup`, () => {\n if (toolManager.isActive(LASSO_TOOL)) toolManager.setActive(null);\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport LassoToolModule from \"diagram-js/lib/features/lasso-tool\";\nimport WardleyLassoBehavior from \"./WardleyLassoBehavior.js\";\n\n/** Lasso multi-select: diagram-js lasso-tool plus Shift+drag activation on an empty canvas. */\nexport const wardleyLassoModule: ModuleDeclaration = {\n __depends__: [LassoToolModule],\n __init__: [\"wardleyLassoBehavior\"],\n wardleyLassoBehavior: [\"type\", WardleyLassoBehavior],\n};\n\nexport { default as WardleyLassoBehavior, LASSO_SELECTION } from \"./WardleyLassoBehavior.js\";\n","import RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { isWardleyShape, isPipeline, isAttitude, type WardleyShape } from \"../model/di-types.js\";\n\n// Submaps are referenceable nodes on the parent map (OWM serializes their edges by name);\n// pipelines connect via their ■ anchor.\nconst CONNECTABLE: ReadonlySet<string> = new Set([\"component\", \"anchor\", \"submap\", \"pipeline\"]);\n\nconst HORIZONTAL_RESIZE_DIRECTIONS: ReadonlySet<string> = new Set([\"e\", \"w\"]);\n\nfunction isConnectable(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && CONNECTABLE.has(el.wardleyType);\n}\n\n/** Is there already a connection between the two shapes (in either direction)? */\nfunction alreadyConnected(source: WardleyShape, target: WardleyShape): boolean {\n return (\n (source.outgoing ?? []).some((c) => c.target === (target as unknown)) ||\n (source.incoming ?? []).some((c) => c.source === (target as unknown))\n );\n}\n\n/**\n * Allowed edit operations (concept doc §5.4). On success the `connection.create` rule returns\n * the new connection's attributes. The editor deliberately only creates dependencies — flow\n * links (`+>`) exist for OWM import compatibility but are not authored interactively.\n */\nexport default class WardleyRules extends RuleProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override init(): void {\n this.addRule(\"connection.start\", (context: { source?: unknown }) =>\n isConnectable(context.source),\n );\n\n this.addRule(\"connection.create\", (context: { source?: unknown; target?: unknown }) => {\n const { source, target } = context;\n if (!isConnectable(source) || !isConnectable(target)) return false;\n if (source === target) return false;\n // Duplicate lines between the same endpoints are never meaningful (and indistinguishable\n // in the DSL) — prevent them instead of silently stacking.\n if (alreadyConnected(source, target)) return false;\n return { wardleyType: \"dependency\" };\n });\n\n this.addRule(\"shape.move\", () => true);\n // Shapes never nest: hovering another element during a drag must neither re-parent the moved\n // shapes under it nor mark it as a drop target, so such hovers are ignored (null), not refused.\n this.addRule(\"elements.move\", (context: { target?: { parent?: unknown } | null }) =>\n context.target?.parent ? null : true,\n );\n this.addRule(\"shape.create\", () => true);\n // Group create (paste preview): diagram-js Create checks this rule for element arrays.\n this.addRule(\"elements.create\", () => true);\n // Pipelines only stretch along the evolution axis — their height is not part of the model.\n this.addRule(\"shape.resize\", (context: { shape?: unknown; direction?: string }) => {\n if (isPipeline(context.shape)) {\n return !context.direction || HORIZONTAL_RESIZE_DIRECTIONS.has(context.direction);\n }\n return isAttitude(context.shape);\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyRules from \"./WardleyRules.js\";\n\n/** Allowed Wardley operations (RuleProvider). */\nexport const wardleyRulesModule: ModuleDeclaration = {\n __init__: [\"wardleyRules\"],\n wardleyRules: [\"type\", WardleyRules],\n};\n\nexport { default as WardleyRules } from \"./WardleyRules.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\n\n/** Snap distance in SCREEN px, so the pull feels the same at every zoom level. */\nexport const SNAP_TOLERANCE_SCREEN_PX = 8;\n\ninterface DragMoveEvent {\n x?: number;\n /** Delta since drag start — diagram-js move/resize works ONLY with dx/dy, never with x. */\n dx?: number;\n originalEvent?: { shiftKey?: boolean };\n context?: { shape?: { x: number; width: number } };\n}\n\n/**\n * Snaps the X position (evolution) during move/create/resize to the stage boundaries, within\n * `SNAP_TOLERANCE_SCREEN_PX` on screen (converted to diagram units with the current zoom).\n * Disabled while the Shift key is held. Important: `x` and `dx` must be adjusted TOGETHER\n * (like diagram-js' `setSnapped`) — move takes the final position from `dx`, so a mutated\n * `x` alone would have no effect.\n */\nexport default class StageSnapping {\n static $inject = [\"eventBus\", \"evolutionGrid\", \"canvas\"];\n\n constructor(eventBus: EventBus, grid: EvolutionGrid, canvas: Canvas) {\n const tolerance = () => SNAP_TOLERANCE_SCREEN_PX / (canvas.zoom() || 1);\n const boundaryXs = () =>\n grid.getBoundaries().map((b) => grid.toCanvas({ visibility: 0.5, evolution: b }).x);\n\n const setSnappedX = (event: DragMoveEvent, sx: number) => {\n if (typeof event.dx === \"number\" && typeof event.x === \"number\") {\n event.dx += sx - event.x;\n }\n event.x = sx;\n };\n\n // Move: snap the SHAPE MIDPOINT (not the cursor) — the user rarely grabs the shape exactly at its centre.\n eventBus.on([\"shape.move.move\", \"shape.move.end\"], 1500, (event: DragMoveEvent) => {\n if (event.originalEvent?.shiftKey) return;\n if (typeof event.x !== \"number\" || typeof event.dx !== \"number\") return;\n const shape = event.context?.shape;\n if (!shape) return;\n const mid = shape.x + shape.width / 2 + event.dx;\n const maxDistance = tolerance();\n for (const sx of boundaryXs()) {\n if (Math.abs(mid - sx) <= maxDistance) {\n const d = sx - mid;\n event.dx += d;\n event.x += d;\n break;\n }\n }\n });\n\n // Create (cursor = shape midpoint) and resize (cursor = dragged edge): snap the cursor.\n eventBus.on(\n [\"create.move\", \"create.end\", \"resize.move\", \"resize.end\"],\n 1500,\n (event: DragMoveEvent) => {\n if (event.originalEvent?.shiftKey) return;\n if (typeof event.x !== \"number\") return;\n const maxDistance = tolerance();\n for (const sx of boundaryXs()) {\n if (Math.abs(event.x - sx) <= maxDistance) {\n setSnappedX(event, sx);\n break;\n }\n }\n },\n );\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport StageSnapping from \"./StageSnapping.js\";\n\n/** Snapping to the evolution stage boundaries (editor-only). */\nexport const stageSnappingModule: ModuleDeclaration = {\n __init__: [\"stageSnapping\"],\n stageSnapping: [\"type\", StageSnapping],\n};\n\nexport { default as StageSnapping } from \"./StageSnapping.js\";\n","/*! @miragon/wardley-renderer icon geometry: square-dashed-mouse-pointer, and spline drawn with a\n * straight segment. Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Full notice: README.md of @miragon/wardley-renderer */\nimport { COLORS, ATTITUDE_COLORS, FONT } from \"./styles.js\";\nimport { ICON_FAST_FORWARD, ICON_FAST_REWIND, ICON_PERSON } from \"./icons.js\";\n\n/**\n * Palette icons: the creating entries are a mini preview of the ACTUAL canvas rendering\n * (WYSIWYG) — same colors and shapes as the WardleyRenderer, so the palette shows what will be\n * created.\n */\n\nconst wrap = (inner: string): string =>\n `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" class=\"wardley-palette-svg\">${inner}</svg>`;\n\n/**\n * A Lucide outline icon (lucide-static 1.59.0, ISC, © Lucide Icons and Contributors) at the palette\n * tool size of guide §5.5 (20px, stroke 2): it draws in `currentColor`, so the chrome around the\n * entry decides the colour (hover, pressed tool, read-only).\n */\nconst toolIcon = (inner: string): string =>\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\" class=\"wardley-palette-svg\">${inner}</svg>`;\n\nconst LUCIDE_SQUARE_DASHED_MOUSE_POINTER =\n '<path d=\"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z\"/>' +\n '<path d=\"M5 3a2 2 0 0 0-2 2\"/>' +\n '<path d=\"M19 3a2 2 0 0 1 2 2\"/>' +\n '<path d=\"M5 21a2 2 0 0 1-2-2\"/>' +\n '<path d=\"M9 3h1\"/>' +\n '<path d=\"M9 21h2\"/>' +\n '<path d=\"M14 3h1\"/>' +\n '<path d=\"M3 9v1\"/>' +\n '<path d=\"M21 9v2\"/>' +\n '<path d=\"M3 14v1\"/>';\n\n// Lucide's spline with a straight segment between its end points (guide §5.14, line-segment): the\n// curve read as a telephone receiver at 20px.\nconst LINE_SEGMENT =\n '<circle cx=\"19\" cy=\"5\" r=\"2\"/>' +\n '<circle cx=\"5\" cy=\"19\" r=\"2\"/>' +\n '<path d=\"M6.5 17.5 17.5 6.5\"/>';\n\nconst eventCircle = (extra = \"\"): string =>\n `<circle cx=\"12\" cy=\"12\" r=\"7\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"2\"/>${extra}`;\n\nconst text = (content: string, attrs: string): string =>\n `<text x=\"12\" text-anchor=\"middle\" font-family=\"${FONT.family}\" ${attrs}>${content}</text>`;\n\nexport const PALETTE_ICONS: Record<string, string> = {\n // The tools use the common Lucide icons of the Miragon modelers; the create glyphs keep the\n // notation colours because they preview the element.\n draw: toolIcon(LINE_SEGMENT),\n lasso: toolIcon(LUCIDE_SQUARE_DASHED_MOUSE_POINTER),\n component: wrap(eventCircle()),\n // Canon: market = three dots in a triangle (like drawComponent).\n market: wrap(\n eventCircle(\n `<circle cx=\"12\" cy=\"10\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>` +\n `<circle cx=\"10.2\" cy=\"13.4\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>` +\n `<circle cx=\"13.8\" cy=\"13.4\" r=\"1.4\" fill=\"${COLORS.stroke}\"/>`,\n ),\n ),\n // Canon: ecosystem = dotted outer ring (like drawComponent).\n ecosystem: wrap(\n eventCircle(\n `<circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.25\" stroke-dasharray=\"1.5 3\" stroke-linecap=\"round\"/>`,\n ),\n ),\n anchor: wrap(`<path d=\"${ICON_PERSON}\" fill=\"${COLORS.ink}\"/>`),\n // Pipeline = ■ anchor on top, box with variant circles hanging below (Wardley notation).\n pipeline: wrap(\n `<rect x=\"9.5\" y=\"2.5\" width=\"5.5\" height=\"5.5\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.5\"/>` +\n `<rect x=\"2\" y=\"10\" width=\"20\" height=\"9\" rx=\"2\" fill=\"none\" stroke=\"${COLORS.pipeline}\" stroke-width=\"1.25\" stroke-dasharray=\"3 2\"/>` +\n `<circle cx=\"7\" cy=\"14.5\" r=\"2.2\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.2\"/>` +\n `<circle cx=\"17\" cy=\"14.5\" r=\"2.2\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.2\"/>`,\n ),\n // Sticky note with a folded corner (distinct from the hamburger menu glyph).\n note: wrap(\n `<g fill=\"none\" stroke=\"${COLORS.noteText}\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">` +\n `<path d=\"M5 4h14v11l-5 5H5z\" fill=\"${COLORS.componentFill}\"/><path d=\"M14 20v-5h5\"/>` +\n `<line x1=\"8\" y1=\"8.5\" x2=\"16\" y2=\"8.5\"/><line x1=\"8\" y1=\"12\" x2=\"13\" y2=\"12\"/></g>`,\n ),\n annotation: wrap(\n `<circle cx=\"12\" cy=\"12\" r=\"8\" fill=\"${COLORS.annotationFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"1.25\"/>` +\n text(\"1\", `y=\"16\" font-size=\"11\" font-weight=\"700\" fill=\"${COLORS.stroke}\"`),\n ),\n accelerator: wrap(`<path d=\"${ICON_FAST_FORWARD}\" fill=\"${COLORS.accelerator}\"/>`),\n deaccelerator: wrap(`<path d=\"${ICON_FAST_REWIND}\" fill=\"${COLORS.deaccelerator}\"/>`),\n submap: wrap(\n `<rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" fill=\"${COLORS.componentFill}\" stroke=\"${COLORS.stroke}\" stroke-width=\"2\"/>` +\n `<rect x=\"7.5\" y=\"7.5\" width=\"9\" height=\"9\" rx=\"1.5\" fill=\"none\" stroke=\"${COLORS.stroke}\" stroke-width=\"1\"/>`,\n ),\n};\n\nconst ATTITUDE_INITIALS: Record<string, string> = {\n pioneers: \"P\",\n settlers: \"S\",\n townplanners: \"T\",\n};\n\n/** Region glyph; the initial letter tells the three kinds apart without relying on colour. */\nexport function attitudeIcon(kind: string): string {\n const c = ATTITUDE_COLORS[kind] ?? { fill: COLORS.band, stroke: COLORS.dependency };\n const initial = ATTITUDE_INITIALS[kind] ?? \"\";\n return wrap(\n `<rect x=\"2\" y=\"6\" width=\"20\" height=\"12\" rx=\"3\" fill=\"${c.fill}\" stroke=\"${c.stroke}\" stroke-width=\"1.5\" stroke-dasharray=\"3 2\"/>` +\n text(initial, `y=\"15.3\" font-size=\"9\" font-weight=\"700\" fill=\"${COLORS.ink}\"`),\n );\n}\n","import type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\nimport type WardleyDrawTool from \"../draw-tool/WardleyDrawTool.js\";\nimport type {\n PaletteEntries,\n PaletteEntry,\n default as PaletteProvider,\n} from \"diagram-js/lib/features/palette/PaletteProvider\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type { CreateNewExtra } from \"../model/WardleyElementFactory.js\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Parent, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { isWardleyShape, type WardleyShape, type WardleyShapeType } from \"../model/di-types.js\";\nimport { PALETTE_ICONS, attitudeIcon } from \"../draw/palette-icons.js\";\nimport { focusCanvasWithoutRing } from \"../a11y/index.js\";\nimport { LASSO_SELECTION } from \"../lasso/index.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\n\ninterface PaletteSpec {\n key: string;\n type: WardleyShapeType;\n label: string;\n title: string;\n /** Single-key shortcut (bound by the keyboard module); shown in the palette tooltip. */\n shortcut?: string;\n icon: string;\n group: string;\n extra?: CreateNewExtra;\n}\n\n// Group IDs with a prefix number -> stable, visible ordering of the palette groups.\nconst GROUP_BLOCKS = \"wardley-1-blocks\";\nconst GROUP_STRATEGY = \"wardley-2-strategy\";\nconst GROUP_NOTES = \"wardley-3-notes\";\n\nconst SPECS: readonly PaletteSpec[] = [\n {\n key: \"component\",\n type: \"component\",\n label: \"Component\",\n title: \"Component\",\n shortcut: \"C\",\n icon: PALETTE_ICONS.component!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"market\",\n type: \"component\",\n label: \"Market\",\n title: \"Market component\",\n icon: PALETTE_ICONS.market!,\n group: GROUP_BLOCKS,\n extra: { market: true },\n },\n {\n key: \"ecosystem\",\n type: \"component\",\n label: \"Ecosystem\",\n title: \"Ecosystem component\",\n icon: PALETTE_ICONS.ecosystem!,\n group: GROUP_BLOCKS,\n extra: { ecosystem: true },\n },\n {\n key: \"anchor\",\n type: \"anchor\",\n label: \"User\",\n title: \"Anchor / User\",\n shortcut: \"U\",\n icon: PALETTE_ICONS.anchor!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"pipeline\",\n type: \"pipeline\",\n label: \"Pipeline\",\n title: \"Pipeline\",\n shortcut: \"P\",\n icon: PALETTE_ICONS.pipeline!,\n group: GROUP_BLOCKS,\n },\n {\n key: \"submap\",\n type: \"submap\",\n label: \"Submap\",\n title: \"Submap\",\n icon: PALETTE_ICONS.submap!,\n group: GROUP_BLOCKS,\n },\n\n {\n key: \"pioneers\",\n type: \"attitude\",\n label: \"Pioneers\",\n title: \"Pioneers region\",\n icon: attitudeIcon(\"pioneers\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"pioneers\" },\n },\n {\n key: \"settlers\",\n type: \"attitude\",\n label: \"Settlers\",\n title: \"Settlers region\",\n icon: attitudeIcon(\"settlers\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"settlers\" },\n },\n {\n key: \"townplanners\",\n type: \"attitude\",\n label: \"Town Planners\",\n title: \"Town Planners region\",\n icon: attitudeIcon(\"townplanners\"),\n group: GROUP_STRATEGY,\n extra: { attitudeKind: \"townplanners\" },\n },\n {\n key: \"accelerator\",\n type: \"accelerator\",\n label: \"Accelerate\",\n title: \"Accelerator\",\n icon: PALETTE_ICONS.accelerator!,\n group: GROUP_STRATEGY,\n extra: { acceleratorDirection: \"accelerate\" },\n },\n {\n key: \"deaccelerator\",\n type: \"accelerator\",\n label: \"Deaccelerate\",\n title: \"Deaccelerator\",\n icon: PALETTE_ICONS.deaccelerator!,\n group: GROUP_STRATEGY,\n extra: { acceleratorDirection: \"deaccelerate\" },\n },\n\n // Annotations (numbered markers + legend) are deliberately NOT in the palette: Note covers\n // free text; imported OWM maps still render annotations (viewer compatibility).\n {\n key: \"note\",\n type: \"note\",\n label: \"Note\",\n title: \"Note\",\n shortcut: \"N\",\n icon: PALETTE_ICONS.note!,\n group: GROUP_NOTES,\n },\n];\n\ninterface ToolSpec {\n key: string;\n title: string;\n shortcut?: string;\n icon: string;\n}\n\n// Names in sentence case, keys apart (guide §5.6): the chrome tooltip shows the key as a chip, and\n// the gestures (Shift+drag, how a drawing ends) are listed in the keyboard shortcuts.\nconst LASSO_TOOL: ToolSpec = {\n key: \"lasso-tool\",\n title: \"Lasso\",\n shortcut: \"L\",\n icon: PALETTE_ICONS.lasso!,\n};\n\nconst DRAW_TOOL: ToolSpec = {\n key: \"draw-tool\",\n title: \"Draw\",\n icon: PALETTE_ICONS.draw!,\n};\n\n/** Leaves room so a keyboard-created shape is not clipped by the plot edge. */\nconst PLOT_INSET = 24;\n/** Diagonal step while the free centre is taken (guide §5.5). */\nconst STACK_OFFSET = 24;\nconst MAX_STACK_STEPS = 12;\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\");\n}\n\n/**\n * Enter or Space on an entry arrives as a click without a pointer: the keyboard of the Miragon\n * modeler shell dispatches it with `detail === 0`, every pointer click has 1 or more.\n */\nfunction isKeyboardClick(event: Event): boolean {\n return event.type === \"click\" && (event as MouseEvent).detail === 0;\n}\n\nexport default class WardleyPaletteProvider implements PaletteProvider {\n static $inject = [\n \"palette\",\n \"create\",\n \"wardleyElementFactory\",\n \"lassoTool\",\n \"wardleyDrawTool\",\n \"injector\",\n ];\n\n /**\n * The palette tooltip (`WardleyPaletteTooltip`, or one a host puts in its place) shows `title` and\n * `shortcut`, and the Miragon modeler shell shows its chrome tooltip instead; only without either\n * does an entry need a native title.\n */\n private readonly needsNativeTitle: boolean;\n\n constructor(\n palette: Palette,\n private readonly create: Create,\n private readonly factory: WardleyElementFactory,\n private readonly lassoTool: LassoTool,\n private readonly drawTool: WardleyDrawTool,\n private readonly injector: Injector,\n ) {\n // The horizontal toolbar never needs diagram-js' vertical two-column collapse, which would\n // squeeze it to 94px on canvases lower than ~694px and spill the entries out of the bar.\n (palette as unknown as { _needsCollapse: () => boolean })._needsCollapse = () => false;\n this.needsNativeTitle =\n !injector.get(\"paletteTooltip\", false) && !injector.get(\"modelerShell\", false);\n palette.registerProvider(this);\n }\n\n getPaletteEntries(): PaletteEntries {\n const entries: Record<string, PaletteEntry> = {};\n\n // Selection tool first. Group MUST be called \"tools\" and the key end in \"-tool\" — that is\n // what diagram-js' palette uses to highlight the active tool (tool-manager.update).\n entries[LASSO_TOOL.key] = {\n group: \"tools\",\n ...this.describe(LASSO_TOOL.title, LASSO_TOOL.shortcut),\n html: this.entryHtml(LASSO_TOOL.title, LASSO_TOOL.icon, LASSO_TOOL.shortcut),\n action: {\n click: (event: Event) => {\n // A pointer's press has already ended the waiting drag, so its click arms the lasso again.\n if (isKeyboardClick(event) && this.lassoArmed()) {\n this.putLassoDown();\n return;\n }\n this.lassoTool.activateSelection(event as MouseEvent);\n this.focusCanvasAfterPointer(event);\n },\n },\n };\n\n entries[DRAW_TOOL.key] = {\n group: \"tools\",\n ...this.describe(DRAW_TOOL.title, DRAW_TOOL.shortcut),\n html: this.entryHtml(DRAW_TOOL.title, DRAW_TOOL.icon, DRAW_TOOL.shortcut),\n action: {\n click: (event: Event) => {\n // A pointer's press ends the lasso's waiting drag first; without one, that drag would wait\n // on behind the draw tool and take the canvas's next press as well. The lock refuses the\n // draw tool and leaves the lasso active, so the lasso stays armed then.\n if (isKeyboardClick(event) && !isReadOnly(this.injector)) this.putLassoDown();\n this.drawTool.toggle();\n this.focusCanvasAfterPointer(event);\n },\n },\n };\n\n for (const spec of SPECS) {\n const start = (event: Event) => {\n this.create.start(event, this.createShapeFor(spec));\n this.focusCanvasAfterPointer(event);\n };\n // diagram-js's create follows the pointer and never ends without one.\n const click = (event: Event) => {\n if (isKeyboardClick(event)) this.createAtFreeCenter(`create.${spec.key}`);\n else start(event);\n };\n entries[`create.${spec.key}`] = {\n group: spec.group,\n ...this.describe(spec.title, spec.shortcut),\n html: this.entryHtml(spec.title, spec.icon, spec.shortcut, true),\n action: { dragstart: start, click },\n };\n }\n return entries;\n }\n\n /**\n * Keyboard path for a create entry (guide §5.5): places the new element in the centre of the\n * free rectangle (no pointer position to attach it to), 24px further diagonally while that spot\n * is taken, selects it and opens its label editor, or focuses the canvas where there is nothing\n * to name. Returns the created shape, or undefined for non-create entries and while the read-only\n * lock holds the map, whose rules `modeling.createShape` does not ask.\n */\n createAtFreeCenter(entryId: string): WardleyShape | undefined {\n const spec = SPECS.find((candidate) => `create.${candidate.key}` === entryId);\n if (!spec || isReadOnly(this.injector)) return undefined;\n const modeling = this.injector.get<Modeling>(\"modeling\");\n const canvas = this.injector.get<Canvas>(\"canvas\");\n const grid = this.injector.get<EvolutionGrid>(\"evolutionGrid\");\n\n const shape = this.createShapeFor(spec);\n const position = this.freeCenterPosition(shape, canvas, grid);\n modeling.createShape(\n shape as unknown as Shape,\n position,\n canvas.getRootElement() as unknown as Parent,\n );\n\n this.injector.get<Selection>(\"selection\", false)?.select(shape as unknown as Shape);\n canvas.focus();\n // Regions are unlabelled (OWM canon), so there is nothing to name.\n if (spec.type !== \"attitude\") {\n this.injector.get<LabelEditingLike>(\"wardleyLabelEditing\", false)?.activate(shape);\n }\n return shape;\n }\n\n /**\n * Guide §5.8: an entry clicked or dragged with a pointer hands the focus to the canvas, whose keys\n * act only while it has the focus, so Delete, the arrows and Cmd/Ctrl+Z work right away. Enter\n * and Space leave it on the entry. The Miragon modeler shell does the same for its palette.\n */\n private focusCanvasAfterPointer(event: Event): void {\n if (!isKeyboardClick(event)) focusCanvasWithoutRing(this.injector.get<Canvas>(\"canvas\"));\n }\n\n /** Whether the lasso's drag waits for the next press on the canvas. */\n private lassoArmed(): boolean {\n return this.injector.get<Dragging>(\"dragging\").context()?.prefix === LASSO_SELECTION;\n }\n\n private putLassoDown(): void {\n if (this.lassoArmed()) this.injector.get<Dragging>(\"dragging\").cancel(false);\n }\n\n private createShapeFor(spec: PaletteSpec): WardleyShape {\n return this.factory.createNew(spec.type, spec.label, spec.extra ?? {});\n }\n\n private freeCenterPosition(\n shape: WardleyShape,\n canvas: Canvas,\n grid: EvolutionGrid,\n ): { x: number; y: number } {\n const freeCenter =\n this.injector.get<FreeRect | null>(\"wardleyFreeRect\", false)?.center() ??\n (({ x, y, width, height }) => ({ x: x + width / 2, y: y + height / 2 }))(canvas.viewbox());\n const plotTopLeft = grid.toCanvas({ evolution: 0, visibility: 1 });\n const plotBottomRight = grid.toCanvas({ evolution: 1, visibility: 0 });\n const clampAxis = (value: number, min: number, max: number, extent: number) => {\n const low = min + extent / 2 + PLOT_INSET;\n const high = max - extent / 2 - PLOT_INSET;\n return low > high ? (min + max) / 2 : Math.min(high, Math.max(low, value));\n };\n const centerOf = (step: number) => ({\n x: clampAxis(\n freeCenter.x + step * STACK_OFFSET,\n plotTopLeft.x,\n plotBottomRight.x,\n shape.width,\n ),\n y: clampAxis(\n freeCenter.y + step * STACK_OFFSET,\n plotTopLeft.y,\n plotBottomRight.y,\n shape.height,\n ),\n });\n const registry = this.injector.get<ElementRegistry>(\"elementRegistry\");\n // Regions and drawings are backgrounds that other elements sit on, so only nodes block a spot.\n const occupied = (point: { x: number; y: number }) =>\n registry.find(\n (element: unknown) =>\n isWardleyShape(element) &&\n element.wardleyType !== \"attitude\" &&\n element.wardleyType !== \"drawing\" &&\n Math.abs(element.x + element.width / 2 - point.x) < (element.width + shape.width) / 2 &&\n Math.abs(element.y + element.height / 2 - point.y) < (element.height + shape.height) / 2,\n ) !== undefined;\n for (let step = 0; step < MAX_STACK_STEPS; step++) {\n const candidate = centerOf(step);\n if (!occupied(candidate)) return candidate;\n }\n return centerOf(0);\n }\n\n private describe(\n title: string,\n shortcut: string | undefined,\n ): Pick<PaletteEntry, \"title\" | \"shortcut\"> {\n return shortcut ? { title, shortcut } : { title };\n }\n\n private entryHtml(title: string, icon: string, shortcut?: string, draggable = false): string {\n // Next to a styled tooltip a native `title` would pop up a second, slower one.\n const nativeTitle = this.needsNativeTitle\n ? ` title=\"${escapeAttribute(shortcut ? `${title} (${shortcut})` : title)}\"`\n : \"\";\n const keyShortcut = shortcut ? ` aria-keyshortcuts=\"${escapeAttribute(shortcut)}\"` : \"\";\n return `<div class=\"entry wardley-palette-entry\"${draggable ? ' draggable=\"true\"' : \"\"}${nativeTitle}${keyShortcut}>${icon}</div>`;\n }\n}\n\ninterface LabelEditingLike {\n activate(element: WardleyShape): void;\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type { Injector } from \"didi\";\nimport { isKeyAimedAt } from \"../a11y/index.js\";\nimport type WardleyPaletteProvider from \"./WardleyPaletteProvider.js\";\n\nconst ENTRY_SELECTOR = \".djs-palette-entries .entry\";\n\nconst PREVIOUS_KEYS = new Set([\"ArrowLeft\", \"ArrowUp\"]);\nconst NEXT_KEYS = new Set([\"ArrowRight\", \"ArrowDown\"]);\nconst ACTIVATE_KEYS = new Set([\"Enter\", \" \"]);\n\n/**\n * Makes the palette a keyboard-operable toolbar (WAI-ARIA toolbar pattern): one Tab stop with a\n * roving tabindex, arrow keys / Home / End move between tools, Enter or Space activates the focused\n * one. A create tool has no pointer position to attach the new element to, so it is placed at the\n * centre of the free rectangle instead (see `WardleyPaletteProvider.createAtFreeCenter`). The\n * palette comes before the canvas in the tab order. Only for hosts without the Miragon modeler\n * shell, which brings these keys and that order itself.\n */\nexport default class WardleyPaletteKeyboard {\n static $inject = [\"eventBus\", \"palette\", \"wardleyPaletteProvider\", \"injector\"];\n\n private container: HTMLElement | undefined;\n private activeAction: string | undefined;\n\n constructor(\n eventBus: EventBus,\n private readonly palette: Palette,\n private readonly provider: WardleyPaletteProvider,\n injector: Injector,\n ) {\n // The Miragon modeler shell skins the palette and brings the same keys; a second roving tab\n // stop and a second Enter handler would create every element twice.\n if (injector.get(\"modelerShell\", false)) return;\n eventBus.on(\"palette.create\", (event: { container: HTMLElement }) =>\n this.attach(event.container),\n );\n eventBus.on(\"palette.changed\", () => {\n this.moveBeforeCanvas();\n this.updateTabStops();\n });\n const existing = (palette as unknown as { _container?: HTMLElement })._container;\n if (existing) {\n this.attach(existing);\n this.moveBeforeCanvas();\n }\n }\n\n // diagram-js appends the palette after the canvas <svg>, so Tab would reach the canvas first\n // (guide §5.5, §5.14). Moved only while it lies there: a move takes the focus off a focused\n // entry. A chrome marks a palette it skins in its own listener of `palette.create`, so the move\n // waits for the `palette.changed` that follows and leaves such a palette to that chrome.\n private moveBeforeCanvas(): void {\n const container = this.container;\n if (!container || container.getAttribute(\"data-chrome\") === \"palette\") return;\n const parent = container.parentElement;\n const svg = parent && Array.from(parent.children).find((child) => child.localName === \"svg\");\n if (\n parent &&\n svg &&\n container.compareDocumentPosition(svg) & Node.DOCUMENT_POSITION_PRECEDING\n ) {\n parent.insertBefore(container, svg);\n }\n }\n\n private attach(container: HTMLElement): void {\n if (this.container === container) return;\n this.container = container;\n // Scopes the toolbar styling to this palette, not every diagram-js palette on the page.\n container.classList.add(\"wardley-palette\");\n container.setAttribute(\"role\", \"toolbar\");\n container.setAttribute(\"aria-label\", \"Tools\");\n container.setAttribute(\"aria-orientation\", \"horizontal\");\n container.addEventListener(\"keydown\", (event) => this.onKeydown(event));\n container.addEventListener(\"focusin\", (event) => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n this.activeAction = entry.getAttribute(\"data-action\") ?? undefined;\n this.updateTabStops();\n });\n this.updateTabStops();\n }\n\n private entries(): HTMLElement[] {\n return this.container\n ? Array.from(this.container.querySelectorAll<HTMLElement>(ENTRY_SELECTOR))\n : [];\n }\n\n private entryOf(target: EventTarget | null): HTMLElement | null {\n if (!(target instanceof Element) || !this.container) return null;\n const entry = target.closest<HTMLElement>(\".entry\");\n return entry && this.container.contains(entry) ? entry : null;\n }\n\n private updateTabStops(): void {\n const entries = this.entries();\n if (!entries.length) return;\n const active =\n entries.find((entry) => entry.getAttribute(\"data-action\") === this.activeAction) ??\n entries[0]!;\n for (const entry of entries) entry.tabIndex = entry === active ? 0 : -1;\n }\n\n private onKeydown(event: KeyboardEvent): void {\n const entry = this.entryOf(event.target);\n if (!entry || event.altKey || event.ctrlKey || event.metaKey) return;\n // The draw tool's check on its entry: a key it leaves to the page (Chromium sends it to an entry\n // the host made inert or hid until its next rendering update) would otherwise activate the draw\n // entry and throw away the line the tool holds.\n if (!isKeyAimedAt(event, entry)) return;\n const entries = this.entries();\n const index = entries.indexOf(entry);\n\n let next: HTMLElement | undefined;\n if (PREVIOUS_KEYS.has(event.key)) next = entries[(index - 1 + entries.length) % entries.length];\n else if (NEXT_KEYS.has(event.key)) next = entries[(index + 1) % entries.length];\n else if (event.key === \"Home\") next = entries[0];\n else if (event.key === \"End\") next = entries[entries.length - 1];\n\n if (next) {\n // The toolbar's own keys: no listener further up acts on them too.\n event.preventDefault();\n event.stopPropagation();\n next.focus();\n return;\n }\n\n if (ACTIVATE_KEYS.has(event.key)) {\n event.preventDefault();\n event.stopPropagation();\n this.activate(entry);\n }\n }\n\n private activate(entry: HTMLElement): void {\n const action = entry.getAttribute(\"data-action\");\n if (!action || entry.getAttribute(\"aria-disabled\") === \"true\") return;\n if (this.provider.createAtFreeCenter(action)) return;\n const bounds = entry.getBoundingClientRect();\n const click = new MouseEvent(\"click\", {\n bubbles: true,\n clientX: bounds.left + bounds.width / 2,\n clientY: bounds.top + bounds.height / 2,\n });\n this.palette.triggerEntry(action, \"click\", click);\n }\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\n\nconst TOOL_ENTRY_SELECTOR = '.djs-palette-entries .group[data-group=\"tools\"] .entry[data-action]';\nconst TOOL_ACTION_SUFFIX = \"-tool\";\n\n/**\n * `aria-pressed` on the tools of the renderer's own palette (lasso, draw), `\"true\"` on the armed one\n * (guide §5.5, §5.14), for a host without the Miragon modeler shell, whose palette skin does the\n * same. diagram-js marks the armed tool with its `highlighted-entry` class only, and after it rebuilt\n * the entries that class no longer reaches them: diagram-js keeps the tools group it found first. So\n * the armed tool comes from `tool-manager.update`, and every rebuild (`palette.changed`) gets the\n * state again; `wardley.css` keys the armed ring on it. A palette any chrome skins\n * (`data-chrome=\"palette\"`) is left to that chrome.\n */\nexport default class WardleyPaletteArmedTool {\n static $inject = [\"eventBus\", \"injector\"];\n\n private container: HTMLElement | undefined;\n private armedTool: string | null = null;\n\n constructor(eventBus: EventBus, injector: Injector) {\n if (injector.get(\"modelerShell\", false)) return;\n eventBus.on(\"palette.create\", (event: { container: HTMLElement }) => {\n this.container = event.container;\n });\n eventBus.on(\"palette.changed\", () => this.apply());\n eventBus.on(\"tool-manager.update\", (event: { tool?: string | null }) => {\n this.armedTool = event.tool ?? null;\n this.apply();\n });\n }\n\n private apply(): void {\n const container = this.container;\n if (!container || container.getAttribute(\"data-chrome\") === \"palette\") return;\n for (const entry of container.querySelectorAll<HTMLElement>(TOOL_ENTRY_SELECTOR)) {\n const action = entry.getAttribute(\"data-action\")!;\n if (!action.endsWith(TOOL_ACTION_SUFFIX)) continue;\n const tool = action.slice(0, -TOOL_ACTION_SUFFIX.length);\n entry.setAttribute(\"aria-pressed\", String(tool === this.armedTool));\n }\n }\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type { PaletteEntries } from \"diagram-js/lib/features/palette/PaletteProvider\";\n\nconst ENTRY_SELECTOR = \".djs-palette-entries .entry\";\nconst PRESS_KEYS = new Set([\"Enter\", \" \"]);\n/** Guide §5.6: the hover delay, the gap to the palette and the distance to the container's sides. */\nconst SHOW_DELAY_MS = 300;\nconst PALETTE_GAP = 8;\nconst CONTAINER_EDGE = 12;\n/** diagram-js's gap between an entry and its tooltip, for a palette a chrome skins. */\nconst ENTRY_GAP = 8;\n\nlet tooltipCount = 0;\n\ninterface Shown {\n entry: HTMLElement;\n element: HTMLElement;\n describedBy: string | null;\n}\n\n/**\n * The palette tooltip for a host without a chrome of its own; the Miragon modeler shell replaces it\n * with its own. diagram-js's `paletteTooltip` stands right of the entry, made for a vertical\n * palette, where it would cover the next tool of this horizontal one, and shows on hover only.\n * This one is the chrome's tooltip of guide §5.6: 8px below the palette, centred on its entry and\n * shifted to keep 12px from the sides of the canvas container, in the container's coordinates, so\n * a map in a part of a wide page shows it at its entry, also with the palette in the second row of\n * a narrow container (§5.15). It shows after 300ms of hover, at once on keyboard focus and at once\n * for a neighbour while one is shown, never for touch, and hides on a press (a click, or Enter or\n * Space on the focused entry), Escape, leaving and blur; `role=\"tooltip\"`. A palette that scrolls\n * sideways (guide §5.15) takes it along with its entry, and an entry scrolled out of view takes it\n * away. Surface, type and key chip are §5.6 too (wardley.css). A palette a chrome skins\n * (`data-chrome=\"palette\"`) keeps diagram-js's place right of the entry.\n */\nexport default class WardleyPaletteTooltip {\n static $inject = [\"eventBus\", \"palette\", \"canvas\"];\n\n private entries: PaletteEntries = {};\n private paletteContainer: HTMLElement | undefined;\n private readonly id = `wardley-palette-tooltip-${++tooltipCount}`;\n private shown: Shown | undefined;\n private pending: { entry: HTMLElement; timer: ReturnType<typeof setTimeout> } | undefined;\n private hovered: HTMLElement | undefined;\n // A pressed entry keeps its tooltip hidden until the pointer leaves it.\n private pressed: HTMLElement | undefined;\n // After a pointer leaves a shown tooltip's entry, the next entry shows at once (guide §5.6).\n private warmUntil = 0;\n\n constructor(\n eventBus: EventBus,\n private readonly palette: Palette,\n private readonly canvas: Canvas,\n ) {\n eventBus.on(\"palette.create\", (event: { container: HTMLElement }) =>\n this.attachTo(event.container),\n );\n eventBus.on(\"palette.changed\", () => {\n this.refreshEntries();\n if (this.shown && !this.shown.entry.isConnected) this.hide();\n });\n eventBus.on(\"diagram.destroy\", () => this.detach());\n }\n\n private attachTo(paletteContainer: HTMLElement): void {\n this.paletteContainer = paletteContainer;\n this.refreshEntries();\n paletteContainer.addEventListener(\"pointerover\", this.onPointerOver);\n paletteContainer.addEventListener(\"pointerout\", this.onPointerOut);\n paletteContainer.addEventListener(\"focusin\", this.onFocusIn);\n paletteContainer.addEventListener(\"focusout\", this.onFocusOut);\n paletteContainer.addEventListener(\"pointerdown\", this.onPress);\n paletteContainer.addEventListener(\"click\", this.onPress);\n paletteContainer.addEventListener(\"scroll\", this.onPaletteScroll);\n // Escape hides the tooltip wherever the focus is, and leaves the key to whoever handles it. The\n // capture phase also sees Enter and Space before the toolbar or the draw tool takes them.\n paletteContainer.ownerDocument.addEventListener(\"keydown\", this.onKeydown, true);\n }\n\n private detach(): void {\n this.hide();\n const container = this.paletteContainer;\n if (!container) return;\n container.removeEventListener(\"pointerover\", this.onPointerOver);\n container.removeEventListener(\"pointerout\", this.onPointerOut);\n container.removeEventListener(\"focusin\", this.onFocusIn);\n container.removeEventListener(\"focusout\", this.onFocusOut);\n container.removeEventListener(\"pointerdown\", this.onPress);\n container.removeEventListener(\"click\", this.onPress);\n container.removeEventListener(\"scroll\", this.onPaletteScroll);\n container.ownerDocument.removeEventListener(\"keydown\", this.onKeydown, true);\n this.paletteContainer = undefined;\n this.hovered = undefined;\n this.pressed = undefined;\n }\n\n private refreshEntries(): void {\n this.entries = this.palette.getEntries();\n }\n\n private entryOf(target: EventTarget | null): HTMLElement | undefined {\n if (!(target instanceof Element)) return undefined;\n const entry = target.closest<HTMLElement>(ENTRY_SELECTOR);\n return entry && this.paletteContainer?.contains(entry) ? entry : undefined;\n }\n\n private readonly onPointerOver = (event: PointerEvent): void => {\n const entry = this.entryOf(event.target);\n if (entry === this.hovered) return;\n if (this.hovered) this.leave(this.hovered);\n this.hovered = entry;\n if (entry) this.enter(entry, event);\n };\n\n private readonly onPointerOut = (event: PointerEvent): void => {\n if (!this.hovered || this.entryOf(event.relatedTarget) === this.hovered) return;\n this.leave(this.hovered);\n this.hovered = undefined;\n };\n\n private readonly onFocusIn = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (entry?.matches(\":focus-visible\")) this.show(entry);\n };\n\n private readonly onFocusOut = (event: FocusEvent): void => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n if (this.pending?.entry === entry) this.cancelPending();\n if (this.shown?.entry === entry) this.hide();\n };\n\n private readonly onPress = (event: Event): void => {\n const entry = this.entryOf(event.target);\n if (!entry) return;\n if (event.type === \"pointerdown\") this.pressed = entry;\n this.hide();\n };\n\n private readonly onKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\" || this.pressesEntry(event)) this.hide();\n };\n\n // A palette that scrolls sideways (guide §5.15) carries the entries away under a shown tooltip,\n // which would then name an entry it no longer stands below.\n private readonly onPaletteScroll = (): void => {\n const shown = this.shown;\n const palette = this.paletteContainer;\n if (!shown || !palette) return;\n if (liesOutside(shown.entry, palette)) this.hide();\n else this.place(shown.element, shown.entry);\n };\n\n // Enter and Space press the focused entry as a click does (guide §5.5, §5.6), but the toolbar and\n // the draw tool act on them without dispatching a click, so the click listener never sees them.\n private pressesEntry(event: KeyboardEvent): boolean {\n return (\n PRESS_KEYS.has(event.key) &&\n !event.altKey &&\n !event.ctrlKey &&\n !event.metaKey &&\n this.entryOf(event.target) !== undefined\n );\n }\n\n private enter(entry: HTMLElement, event: PointerEvent): void {\n if (event.pointerType === \"touch\" || this.pressed === entry) return;\n if (this.shown || Date.now() < this.warmUntil) {\n this.show(entry);\n return;\n }\n this.cancelPending();\n this.pending = { entry, timer: setTimeout(() => this.show(entry), SHOW_DELAY_MS) };\n }\n\n private leave(entry: HTMLElement): void {\n if (this.pressed === entry) this.pressed = undefined;\n if (this.pending?.entry === entry) this.cancelPending();\n if (this.shown?.entry === entry) {\n this.hide();\n this.warmUntil = Date.now() + SHOW_DELAY_MS;\n }\n }\n\n private cancelPending(): void {\n if (this.pending) clearTimeout(this.pending.timer);\n this.pending = undefined;\n }\n\n private show(entry: HTMLElement): void {\n this.cancelPending();\n const paletteEntry = this.entries[entry.getAttribute(\"data-action\") ?? \"\"];\n if (!paletteEntry?.title || !entry.isConnected) {\n if (this.shown?.entry === entry) this.hide();\n return;\n }\n this.hide();\n const element = tooltipElement(\n entry.ownerDocument,\n this.id,\n isSkinned(entry),\n paletteEntry.title,\n paletteEntry.shortcut,\n );\n this.canvas.getContainer().append(element);\n const describedBy = entry.getAttribute(\"aria-describedby\");\n this.shown = { entry, element, describedBy };\n if (saysMoreThanName(entry, paletteEntry.title, paletteEntry.shortcut)) {\n entry.setAttribute(\"aria-describedby\", [describedBy, this.id].filter(Boolean).join(\" \"));\n }\n this.place(element, entry);\n }\n\n private place(element: HTMLElement, entry: HTMLElement): void {\n if (isSkinned(entry)) placeRightOfEntry(element, entry);\n else this.placeBelowPalette(element, entry);\n }\n\n private hide(): void {\n this.cancelPending();\n if (!this.shown) return;\n const { entry, element, describedBy } = this.shown;\n this.shown = undefined;\n element.remove();\n if (describedBy === null) entry.removeAttribute(\"aria-describedby\");\n else entry.setAttribute(\"aria-describedby\", describedBy);\n }\n\n /** The middle of the tooltip's top edge in px from the canvas container's top left. */\n private placeBelowPalette(element: HTMLElement, entry: HTMLElement): void {\n const containerBox = this.canvas.getContainer().getBoundingClientRect();\n const entryBox = entry.getBoundingClientRect();\n const paletteBox = (entry.closest(\".djs-palette\") ?? entry).getBoundingClientRect();\n const halfWidth = element.getBoundingClientRect().width / 2;\n const centre = entryBox.left + entryBox.width / 2 - containerBox.left;\n // In a container narrower than the tooltip plus both edges, the left edge wins.\n const kept = Math.max(\n CONTAINER_EDGE + halfWidth,\n Math.min(centre, containerBox.width - CONTAINER_EDGE - halfWidth),\n );\n element.style.left = `${kept}px`;\n element.style.top = `${paletteBox.bottom + PALETTE_GAP - containerBox.top}px`;\n }\n}\n\nfunction tooltipElement(\n ownerDocument: Document,\n id: string,\n skinned: boolean,\n title: string,\n shortcut: string | undefined,\n): HTMLElement {\n const element = ownerDocument.createElement(\"div\");\n element.id = id;\n element.setAttribute(\"role\", \"tooltip\");\n element.className = `djs-hover-tooltip djs-hover-tooltip--${skinned ? \"right\" : \"bottom\"}`;\n const label = ownerDocument.createElement(\"span\");\n label.className = \"djs-palette-tooltip-label\";\n label.textContent = title;\n element.append(label);\n if (shortcut) {\n const chip = ownerDocument.createElement(\"kbd\");\n chip.className = \"djs-palette-tooltip-shortcut\";\n chip.textContent = shortcut;\n element.append(chip);\n }\n return element;\n}\n\nfunction isSkinned(entry: HTMLElement): boolean {\n return entry.closest(\".djs-palette\")?.getAttribute(\"data-chrome\") === \"palette\";\n}\n\n/** Whether no part of `entry` lies in the visible part of the palette that scrolls it. */\nfunction liesOutside(entry: HTMLElement, palette: HTMLElement): boolean {\n const view = palette.getBoundingClientRect();\n const start = view.left + palette.clientLeft;\n const box = entry.getBoundingClientRect();\n return box.right <= start || box.left >= start + palette.clientWidth;\n}\n\n// diagram-js's own place, in page coordinates: its stylesheet fixes the tooltip to the viewport.\nfunction placeRightOfEntry(element: HTMLElement, entry: HTMLElement): void {\n const box = entry.getBoundingClientRect();\n element.style.left = `${box.right + ENTRY_GAP}px`;\n element.style.top = `${box.top + box.height / 2}px`;\n}\n\n// Only a tooltip that says more than the entry's name describes it (guide §5.6); a key chip does,\n// unless the entry names its keys in aria-keyshortcuts.\nfunction saysMoreThanName(\n entry: HTMLElement,\n title: string,\n shortcut: string | undefined,\n): boolean {\n const name = entry.getAttribute(\"aria-label\") ?? entry.textContent ?? \"\";\n return !name.includes(title) || (Boolean(shortcut) && !entry.hasAttribute(\"aria-keyshortcuts\"));\n}\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly, isReadOnlyShown, READ_ONLY_CHANGED } from \"../read-only/index.js\";\n\nconst ENTRY_SELECTOR = \".djs-palette-entries .entry[data-action]\";\n\n/** The entries a locked map leaves active (guide §13.5): the lasso changes only the selection. */\nconst ACTIVE_WHILE_LOCKED: ReadonlySet<string> = new Set([\"lasso-tool\"]);\n\n/** Ahead of the palette's own handling of the entry, as the shell's veto is. */\nconst VETO_PRIORITY = 2000;\n\ninterface PaletteTriggerEvent {\n entry?: { group?: string };\n event?: Event & { delegateTarget?: EventTarget };\n}\n\n/**\n * Shows the read-only lock on the renderer's own palette, for a host without the Miragon modeler\n * shell, whose palette skin does the same: every entry that would change the map, the draw tool\n * too, is `aria-disabled=\"true\"` while the lock shows, at once with it or after the lock's\n * `delayMs`, and again after every rebuild of the entries; its click, drag or Enter does nothing\n * from the lock on, and it stays focusable. The lasso stays active (guide §13.5). `wardley.css`\n * mutes the marked entries. A palette any chrome skins (`data-chrome=\"palette\"`) is left to that\n * chrome.\n */\nexport default class WardleyPaletteReadOnly {\n static $inject = [\"eventBus\", \"injector\"];\n\n private container: HTMLElement | undefined;\n /** The `aria-disabled` an entry had before the lock marked it (`null`: none). */\n private readonly ownMarks = new WeakMap<Element, string | null>();\n\n constructor(\n eventBus: EventBus,\n private readonly injector: Injector,\n ) {\n if (injector.get(\"modelerShell\", false)) return;\n eventBus.on(\"palette.create\", (event: { container: HTMLElement }) => {\n this.container = event.container;\n });\n eventBus.on([\"palette.changed\", READ_ONLY_CHANGED], () => this.apply());\n eventBus.on(\"palette.trigger\", VETO_PRIORITY, (event: PaletteTriggerEvent) =>\n this.vetoes(event) ? this.refuse(event) : undefined,\n );\n }\n\n /** Whether `entry` does nothing while the lock holds, read from its element where there is one. */\n isDisabled(entry: Element): boolean {\n return this.ownsPalette() && isReadOnly(this.injector) && refusedWhileLocked(entry);\n }\n\n private ownsPalette(): boolean {\n const container = this.container;\n return !!container && container.getAttribute(\"data-chrome\") !== \"palette\";\n }\n\n // The marks follow the lock as shown, which a host may delay (guide §13.5); the refusal does not.\n private apply(): void {\n const container = this.container;\n if (!container || !this.ownsPalette()) return;\n const shown = isReadOnlyShown(this.injector);\n for (const entry of container.querySelectorAll<HTMLElement>(ENTRY_SELECTOR)) {\n if (shown && refusedWhileLocked(entry)) {\n if (!this.ownMarks.has(entry)) {\n this.ownMarks.set(entry, entry.getAttribute(\"aria-disabled\"));\n }\n entry.setAttribute(\"aria-disabled\", \"true\");\n } else if (this.ownMarks.has(entry)) {\n const previous = this.ownMarks.get(entry);\n this.ownMarks.delete(entry);\n if (previous === null || previous === undefined) entry.removeAttribute(\"aria-disabled\");\n else entry.setAttribute(\"aria-disabled\", previous);\n }\n }\n }\n\n // A trigger without an entry element in this palette (a host's `triggerEntry`) passes only for\n // the tools, whose draw tool refuses the lock by itself.\n private vetoes({ entry, event }: PaletteTriggerEvent): boolean {\n if (!this.ownsPalette() || !isReadOnly(this.injector)) return false;\n const target = event?.delegateTarget ?? event?.target;\n const element =\n target instanceof Element ? target.closest<HTMLElement>(\".entry[data-action]\") : null;\n if (element && this.container!.contains(element)) return this.isDisabled(element);\n return entry?.group !== \"tools\";\n }\n\n private refuse({ event }: PaletteTriggerEvent): false {\n // A refused dragstart would otherwise still start the browser's own drag of the entry.\n event?.preventDefault();\n return false;\n }\n}\n\nfunction refusedWhileLocked(entry: Element): boolean {\n return !ACTIVE_WHILE_LOCKED.has(entry.getAttribute(\"data-action\") ?? \"\");\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport HoverTooltipModule from \"diagram-js/lib/features/hover-tooltip\";\nimport type HoverTooltip from \"diagram-js/lib/features/hover-tooltip/HoverTooltip\";\n\n/** The private fields in which diagram-js's HoverTooltip keeps a tooltip it is about to show. */\ninterface PendingTooltip {\n _showTimer: ReturnType<typeof setTimeout> | null;\n _current: unknown;\n}\n\n/** Ahead of the canvas's own `diagram.destroy` listener (500), which removes its container. */\nconst BEFORE_CANVAS_TEARDOWN = 1500;\n\n/**\n * diagram-js's palette brings its hover tooltip along, which `WardleyPaletteTooltip` does not use,\n * but a host may (diagram-js's own palette tooltip, say). That tooltip (checked up to 15.28.1)\n * shows 300ms after the pointer enters an entry and cancels that only when the pointer leaves,\n * never on `diagram.destroy`: the timer then renders into the destroyed canvas and throws a\n * TypeError in the host's page. HoverTooltip has no public way to cancel a show, so this clears its timer and the\n * content it would render. A host that replaced the service with `null` has nothing to cancel.\n */\nexport default class WardleyHoverTooltipTeardown {\n static $inject = [\"eventBus\", \"hoverTooltip\"];\n\n constructor(eventBus: EventBus, hoverTooltip: HoverTooltip | null) {\n if (!hoverTooltip) return;\n const pending = hoverTooltip as unknown as PendingTooltip;\n eventBus.on(\"diagram.destroy\", BEFORE_CANVAS_TEARDOWN, () => {\n clearTimeout(pending._showTimer ?? undefined);\n pending._showTimer = null;\n pending._current = null;\n });\n }\n}\n\n/** Cancels a hover tooltip that waits to show when the modeler is destroyed. */\nexport const wardleyHoverTooltipTeardownModule: ModuleDeclaration = {\n __depends__: [HoverTooltipModule],\n __init__: [\"wardleyHoverTooltipTeardown\"],\n wardleyHoverTooltipTeardown: [\"type\", WardleyHoverTooltipTeardown],\n};\n","import type { ModuleDeclaration } from \"didi\";\nimport PaletteModule from \"diagram-js/lib/features/palette\";\nimport WardleyPaletteProvider from \"./WardleyPaletteProvider.js\";\nimport WardleyPaletteKeyboard from \"./WardleyPaletteKeyboard.js\";\nimport WardleyPaletteArmedTool from \"./WardleyPaletteArmedTool.js\";\nimport WardleyPaletteTooltip from \"./WardleyPaletteTooltip.js\";\nimport WardleyPaletteReadOnly from \"./WardleyPaletteReadOnly.js\";\nimport { wardleyHoverTooltipTeardownModule } from \"./WardleyHoverTooltipTeardown.js\";\n\n/**\n * Tool palette (drag-to-create, keyboard-operable toolbar). `paletteTooltip` overrides the\n * diagram-js service of that name; diagram-js's palette module is a dependency, so it loads first\n * even where a host lists it after this one, and cannot put its own tooltip back.\n */\nexport const wardleyPaletteModule: ModuleDeclaration = {\n __depends__: [PaletteModule, wardleyHoverTooltipTeardownModule],\n __init__: [\n \"wardleyPaletteProvider\",\n \"wardleyPaletteKeyboard\",\n \"wardleyPaletteArmedTool\",\n \"wardleyPaletteReadOnly\",\n \"paletteTooltip\",\n ],\n wardleyPaletteProvider: [\"type\", WardleyPaletteProvider],\n wardleyPaletteKeyboard: [\"type\", WardleyPaletteKeyboard],\n wardleyPaletteArmedTool: [\"type\", WardleyPaletteArmedTool],\n wardleyPaletteReadOnly: [\"type\", WardleyPaletteReadOnly],\n paletteTooltip: [\"type\", WardleyPaletteTooltip],\n};\n\nexport { default as WardleyPaletteProvider } from \"./WardleyPaletteProvider.js\";\nexport { default as WardleyPaletteKeyboard } from \"./WardleyPaletteKeyboard.js\";\nexport { default as WardleyPaletteArmedTool } from \"./WardleyPaletteArmedTool.js\";\nexport { default as WardleyPaletteTooltip } from \"./WardleyPaletteTooltip.js\";\nexport { default as WardleyPaletteReadOnly } from \"./WardleyPaletteReadOnly.js\";\n","import ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Element, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport { MOVEMENT_CLASS } from \"../draw/index.js\";\n\ninterface TargetBounds {\n left: number;\n top: number;\n right: number;\n bottom: number;\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** diagram-js internals this override relies on (not part of the published typings). */\ninterface ContextPadInternals {\n _canvas: Canvas;\n _current?: { html?: HTMLElement } | null;\n _getTargetBounds(target: Element | Element[]): TargetBounds;\n}\n\n/** Screen px between the target and the pad (diagram-js' CONTEXT_PAD_MARGIN at 100 %). */\nconst PAD_MARGIN = 8;\n/** Pad width assumed before the pad is laid out: a component's pad (four 28px entries per row). */\nconst FALLBACK_PAD_WIDTH = 134;\n\n/**\n * Anchors the pad to a node and its own label instead of the whole graphics group: an evolving\n * component's group also holds the evolve arrow, target circle and target name, which would push the\n * pad hundreds of pixels away from the node the user selected. When the evolve target lies where\n * the pad would open, the pad clears the whole movement instead — otherwise it would hide the target\n * circle, which is the evolve's drag handle.\n *\n * Overrides diagram-js's private `_getTargetBounds` (guarded by a browser test).\n */\nexport default class WardleyContextPad extends ContextPad {\n _getTargetBounds(target: Element | Element[]): TargetBounds {\n const elements = Array.isArray(target) ? target : [target];\n const nodeRects = elements.flatMap((element) => this.visualRects(element, \"node\"));\n if (!nodeRects.length) {\n const base = ContextPad.prototype as unknown as ContextPadInternals;\n return base._getTargetBounds.call(this, target);\n }\n const nodeBounds = union(nodeRects);\n const padReach =\n nodeBounds.right + this.padWidth() + PAD_MARGIN * this.internals()._canvas.zoom();\n const movementRects = elements.flatMap((element) => this.visualRects(element, \"movement\"));\n // Only the target circle and texts count: the evolve line itself starts inside the node.\n const movementUnderPad = elements\n .flatMap((element) => this.movementTargetRects(element))\n .some((rect) => rect.right > nodeBounds.right && rect.left < padReach);\n return movementUnderPad ? union([...nodeRects, ...movementRects]) : nodeBounds;\n }\n\n private internals(): ContextPadInternals {\n return this as unknown as ContextPadInternals;\n }\n\n private padWidth(): number {\n const width = this.internals()._current?.html?.getBoundingClientRect().width;\n return width || FALLBACK_PAD_WIDTH;\n }\n\n private movementTargetRects(element: Element): DOMRect[] {\n const graphics = this.internals()._canvas.getGraphics(element as unknown as ShapeLike);\n const targets = graphics?.querySelectorAll(\n `.djs-visual > .${MOVEMENT_CLASS} > :is(.wardley-evolve-handle, text)`,\n );\n return Array.from(targets ?? []).map((target) => target.getBoundingClientRect());\n }\n\n private visualRects(element: Element, part: \"node\" | \"movement\"): DOMRect[] {\n const graphics = this.internals()._canvas.getGraphics(element as unknown as ShapeLike);\n if (!graphics) return [];\n const children = Array.from(graphics.children).flatMap((child) =>\n child.classList.contains(\"djs-visual\")\n ? Array.from(child.children).filter(\n (visual) => visual.classList.contains(MOVEMENT_CLASS) === (part === \"movement\"),\n )\n : part === \"node\"\n ? [child]\n : [],\n );\n return children\n .map((child) => child.getBoundingClientRect())\n .filter((rect) => rect.width > 0 || rect.height > 0);\n }\n}\n\nfunction union(rects: DOMRect[]): TargetBounds {\n const left = Math.min(...rects.map((rect) => rect.left));\n const top = Math.min(...rects.map((rect) => rect.top));\n const right = Math.max(...rects.map((rect) => rect.right));\n const bottom = Math.max(...rects.map((rect) => rect.bottom));\n return { left, top, right, bottom, x: left, y: top, width: right - left, height: bottom - top };\n}\n","/**\n * Screen px from an inline editor's field to the first caption under it. The field's focus ring\n * reaches 4px below it (5px in high contrast), and a caption at the same layer would cover it; the\n * guide keeps the label editor's suggestions 8px from the field too.\n */\nexport const FIELD_TO_CAPTION_GAP = 8;\n\n/**\n * A refused value in an inline editor: the field turns red and a caption under it says why. One look\n * and one accessible pattern (role=alert, aria-describedby) for every editor, also for keyboard and\n * touch users who never see a tooltip.\n */\nexport interface FieldError {\n show(message: string): void;\n clear(): void;\n /** The caption while shown, for hosts that lay out further captions below it. */\n readonly caption: HTMLElement | undefined;\n}\n\nexport function createFieldError(\n container: HTMLElement,\n field: HTMLInputElement | HTMLTextAreaElement,\n id: string,\n place: (caption: HTMLElement) => void,\n): FieldError {\n let caption: HTMLElement | undefined;\n return {\n get caption() {\n return caption;\n },\n show(message) {\n if (!caption) {\n caption = document.createElement(\"div\");\n caption.className = \"wardley-label-caption wardley-label-error\";\n caption.setAttribute(\"role\", \"alert\");\n caption.id = id;\n container.appendChild(caption);\n field.setAttribute(\"aria-describedby\", id);\n }\n caption.textContent = message;\n field.classList.add(\"wardley-label-input--error\");\n field.setAttribute(\"aria-invalid\", \"true\");\n place(caption);\n },\n clear() {\n if (!caption) return;\n caption.remove();\n caption = undefined;\n field.classList.remove(\"wardley-label-input--error\");\n field.removeAttribute(\"aria-invalid\");\n field.removeAttribute(\"aria-describedby\");\n },\n };\n}\n","/**\n * Enter and Escape that confirm or cancel an IME candidate belong to the composition. `isComposing`\n * alone misses Safari: it sends the confirming Enter after `compositionend`, with `isComposing`\n * false and the `keyCode` 229 that every engine gives a key the IME took.\n */\nexport function isImeCompositionKey(event: KeyboardEvent): boolean {\n return event.isComposing || event.keyCode === 229;\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Injector } from \"didi\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport { FONT, NOTE_LINE_HEIGHT } from \"../draw/styles.js\";\nimport { nameLineGrowth, type LineGrowth } from \"../draw/index.js\";\nimport { createFieldError, FIELD_TO_CAPTION_GAP } from \"./fieldError.js\";\nimport { isImeCompositionKey } from \"./imeComposition.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n focusCanvasWithoutRing,\n isKeyOnHiddenTarget,\n lastInteractionWasPointer,\n trackInputModality,\n} from \"../a11y/index.js\";\n\n/** How an edit ends: Enter/Cmd+Enter (can be refused) or focus leaving the field (cannot). */\ntype CommitTrigger = \"enter\" | \"outside\";\n\ninterface ActiveEdit {\n elementId: string;\n field: HTMLInputElement | HTMLTextAreaElement;\n /** Saves the current value and closes (for Enter, blur, click outside). */\n commit: (trigger: CommitTrigger) => void;\n /** Discards and closes (only for Escape). */\n cleanup: () => void;\n /** Places the field over its element again after the view changed. */\n relayout: () => void;\n connection?: boolean;\n}\n\n/** Text selection (caret when start = end) inside an editor field. */\nexport interface FieldSelection {\n start: number;\n end: number;\n}\n\n/** Snapshot of an open name editor (hosts use it to survive a re-import). */\nexport interface ActiveLabelEdit {\n elementId: string;\n value: string;\n /** Where the caret or text selection was. */\n selection?: FieldSelection;\n /** A link annotation or flow value editor instead of a name editor. */\n connection?: boolean;\n}\n\nexport interface ActivateOptions {\n /** Initial field content instead of the element's current label (e.g. restoring an edit). */\n value?: string;\n /** Caret or selection to restore; without it the whole text is selected. */\n selection?: FieldSelection;\n}\n\n/**\n * A field the user opens selects its whole text; a field reopened by a re-import keeps the caret\n * and selection the user had, so the next key does not replace what was typed.\n */\nexport function focusField(\n field: HTMLInputElement | HTMLTextAreaElement,\n options: ActivateOptions,\n): void {\n field.focus();\n if (options.selection) {\n const length = field.value.length;\n field.setSelectionRange(\n Math.min(options.selection.start, length),\n Math.min(options.selection.end, length),\n );\n } else {\n field.select();\n }\n}\n\n/** Fired when a name was changed to a free variant because the requested one is taken. */\nexport interface LabelDeduplicatedEvent {\n element: WardleyShape;\n requested: string;\n applied: string;\n}\n\n/** Contract with the renderer: the element's primary name <text> carries this class. */\nconst NAME_LABEL_CLASS = \"wardley-name-label\";\n/** Canvas marker while editing — CSS hides the name label so the field replaces it. */\nconst EDITING_MARKER = \"wardley-label-editing\";\n\n/** Regions are unlabelled like in OWM (title = kind) and drawings have no text at all. */\nconst NOT_EDITABLE: ReadonlySet<string> = new Set([\"attitude\", \"drawing\"]);\n\n/** Below diagram-js's own `shape.changed` listener, which redraws the element. */\nconst AFTER_REDRAW_PRIORITY = 500;\n\nconst FIELD_PADDING_X = 6;\nconst FIELD_PADDING_Y = 2;\nconst FIELD_BORDER = 1.5;\nconst FIELD_LINE_HEIGHT = 1.25;\nconst MIN_FONT_SIZE = 11;\nconst BETWEEN_CAPTIONS_GAP = 4;\nconst CARET_ROOM = 2;\n\nexport const NOTE_EDIT_HINT = \"Cmd/Ctrl+Enter to save · Esc to cancel\";\n\nexport function duplicateNameMessage(name: string): string {\n return `“${name}” already exists. Names must be unique because links refer to them.`;\n}\n\n/** U+2216, the look-alike of `\\`, as U+2215 is the DSL's look-alike of `/`. */\nconst SET_MINUS = \"∖\";\n\n/**\n * Defuses DSL metacharacters in labels: in the OWM DSL, names double as references —\n * `->`, `;` and square brackets would corrupt edge/coordinate lines on re-import. Line breaks stay\n * (the DSL writes them as `\\n`); leading and trailing ones go with the other whitespace. A name's\n * backslash before \"n\" (`C:\\new`) would read back as a line break and could then collide with a\n * name that holds a real one, so it becomes a look-alike. Notes and annotations keep it: nothing\n * refers to them, so a break there only changes how they look.\n */\nfunction sanitizeLabel(raw: string, isName: boolean): string {\n const label = raw\n .replace(/\\r\\n?/g, \"\\n\")\n .replace(/->/g, \"→\") // -> would be the edge operator\n .replace(/;/g, \",\") // ; separates link annotations\n .replace(/\\[/g, \"(\") // [..] would be a coordinate tuple\n .replace(/\\]/g, \")\")\n .trim();\n return isName ? label.replace(/\\\\(?=n)/g, SET_MINUS) : label;\n}\n\nlet measureContext: CanvasRenderingContext2D | null | undefined;\n\nfunction measureTextWidth(text: string, font: string, fontSizePx: number): number {\n if (measureContext === undefined)\n measureContext = document.createElement(\"canvas\").getContext(\"2d\");\n if (!measureContext) return text.length * fontSizePx * 0.6;\n measureContext.font = font;\n return measureContext.measureText(text).width;\n}\n\n/** Screen geometry of the label being replaced, relative to the canvas container. */\ninterface LabelGeometry {\n left: number;\n top: number;\n width: number;\n height: number;\n centered: boolean;\n /** Lines the label is drawn with. */\n lineCount: number;\n fontSize: number;\n fontWeight: string;\n fontStyle: string;\n fontFamily: string;\n}\n\n/**\n * Custom inline label editing as an HTML overlay (deliberately not diagram-js direct-editing, §8.5).\n * The field sits exactly over the label it replaces (which is hidden meanwhile), scales with the\n * zoom and grows with its content. Commit goes through `wardleyModeling.updateLabel` ->\n * commandStack (undo, P4). Notes are edited in a `<textarea>` over the note itself (Enter = line\n * break, Cmd/Ctrl+Enter or click outside = save); every other name in a `<textarea>` over its label\n * (Enter = save, Shift+Enter = line break). Escape always discards.\n */\nexport default class WardleyLabelEditing {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"elementRegistry\",\n \"wardleyModeling\",\n \"wardleyElementFactory\",\n \"injector\",\n ];\n\n private active: ActiveEdit | null = null;\n private relayoutPending = false;\n private readonly contextPad: ContextPad | null;\n private readonly selection: Selection | null;\n private readonly locked: () => boolean;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly modeling: WardleyModeling,\n private readonly factory: WardleyElementFactory,\n injector: Injector,\n ) {\n trackInputModality();\n this.contextPad = injector.get<ContextPad | null>(\"contextPad\", false) ?? null;\n this.selection = injector.get<Selection | null>(\"selection\", false) ?? null;\n this.locked = () => isReadOnly(injector);\n\n eventBus.on(\"element.dblclick\", (event: { element?: unknown }) => {\n if (isWardleyShape(event.element)) this.activate(event.element);\n else if (isWardleyConnection(event.element)) this.activateConnection(event.element);\n });\n // Click or drag outside the field = SAVE (not discard). Only Escape discards.\n eventBus.on([\"element.mousedown\", \"drag.init\"], () => this.active?.commit(\"outside\"));\n // A view change is no gesture of the user's: a host restores the view after a peer's re-import\n // and refits when its chrome changes, and committing then would write the half-typed name into\n // the shared document (modeler-api L5). The field follows the element instead.\n eventBus.on(\"canvas.viewbox.changing\", () => this.relayoutAfterViewChange());\n eventBus.on(\"canvas.viewbox.changed\", () => this.active?.relayout());\n // A redraw of the edited element (a host resizing the map while the field is open) moves it\n // without a view change; the priority waits for the redraw.\n eventBus.on(\n [\"shape.changed\", \"connection.changed\"],\n AFTER_REDRAW_PRIORITY,\n (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.active.relayout();\n },\n );\n // The edited element vanished (delete, re-import): nothing left to save into.\n eventBus.on([\"shape.remove\", \"connection.remove\"], (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.cancel();\n });\n eventBus.on(\"diagram.destroy\", () => this.cancel());\n }\n\n /**\n * Opens the in-place name editor for `element` (no-op for regions and drawings, and for an\n * element an import has replaced).\n */\n activate(element: WardleyShape, options: ActivateOptions = {}): void {\n if (!isWardleyShape(element) || NOT_EDITABLE.has(element.wardleyType) || this.locked()) return;\n // A caller of the Modeler's own `importDSL` or `importMap` that re-imports from the change\n // listener of a create with the pointer has replaced the new shape by the time the editor opens\n // after the drop (the collaborative `importText` waits for the drop instead), and a name typed\n // into it would commit onto the removed shape.\n if (this.elementRegistry.get(element.id) !== element) return;\n this.active?.commit(\"outside\");\n\n const container = this.canvas.getContainer();\n const isNote = element.wardleyType === \"note\";\n const openedByPointer = lastInteractionWasPointer();\n const requiresUniqueName = this.factory.isLinkable(element.wardleyType);\n const labels = this.nameLabelElements(element);\n const classedByFallback = [...labels.classedByFallback];\n let geometry = this.labelGeometry(element, labels.labelElements);\n const growthOf = (): LineGrowth =>\n isNote ? \"centered\" : nameLineGrowth(element, this.elementRegistry);\n let growth = growthOf();\n\n const lineHeightOf = (fontSize: number) =>\n Math.max(fontSize * FIELD_LINE_HEIGHT, isNote ? NOTE_LINE_HEIGHT * this.canvas.zoom() : 0);\n let lineHeight = lineHeightOf(geometry.fontSize);\n const field = createNameField(\n isNote,\n options.value ?? element.wardleyLabel ?? \"\",\n geometry,\n lineHeight,\n );\n const hint = isNote ? createCaption(\"wardley-label-hint\", NOTE_EDIT_HINT) : undefined;\n\n const layout = () => {\n const { left, top, width, height } = fieldBox(\n field.value,\n geometry,\n lineHeight,\n isNote,\n growth,\n );\n Object.assign(field.style, {\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n });\n // A new line made the field scroll to the caret before it grew to hold it.\n field.scrollTop = 0;\n let captionTop = top + height + FIELD_TO_CAPTION_GAP;\n for (const caption of [error.caption, hint]) {\n if (!caption) continue;\n caption.style.left = `${left}px`;\n caption.style.top = `${captionTop}px`;\n captionTop += caption.offsetHeight + BETWEEN_CAPTIONS_GAP;\n }\n };\n\n const error = createFieldError(container, field, `wardley-label-error-${element.id}`, () =>\n layout(),\n );\n const showDuplicateError = (requested: string) => {\n error.show(duplicateNameMessage(requested));\n field.select();\n };\n const clearError = () => error.clear();\n\n this.contextPad?.close();\n this.canvas.addMarker(element, EDITING_MARKER);\n container.appendChild(field);\n if (hint) container.appendChild(hint);\n layout();\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey as EventListener);\n field.removeEventListener(\"blur\", onBlur);\n field.removeEventListener(\"input\", onInput);\n field.remove();\n hint?.remove();\n error.clear();\n this.canvas.removeMarker(element, EDITING_MARKER);\n for (const text of classedByFallback) {\n text.classList.remove(NAME_LABEL_CLASS);\n if (!text.classList.length) text.removeAttribute(\"class\");\n }\n this.active = null;\n };\n const commit = (trigger: CommitTrigger) => {\n if (done) return;\n // Enforce metacharacter protection also on RENAME — the DSL references elements by their\n // name; unescaped `->`, `;` or brackets would corrupt edge/coordinate lines on re-import.\n const requested = sanitizeLabel(field.value, requiresUniqueName);\n if (!requested || requested === element.wardleyLabel) {\n cleanup();\n return;\n }\n // Duplicate names would collapse nodes on the DSL round-trip (arrows disappear). On Enter the\n // user can still fix it, so refuse; when focus leaves, fall back to a free variant and tell\n // the host. Notes and other unreferenced elements may repeat (e.g. several \"Risk\" hints).\n const applied = requiresUniqueName\n ? this.factory.uniqueLabel(requested, element.id)\n : requested;\n if (applied !== requested && trigger === \"enter\") {\n showDuplicateError(requested);\n return;\n }\n cleanup();\n this.modeling.updateLabel(element, applied);\n if (applied !== requested) {\n this.eventBus.fire(\"wardley.label.deduplicated\", {\n element,\n requested,\n applied,\n } satisfies LabelDeduplicatedEvent);\n }\n };\n const onKey = (e: KeyboardEvent) => {\n if (isImeCompositionKey(e) || isKeyOnHiddenTarget(e)) return;\n if (e.key === \"Escape\") {\n e.preventDefault();\n cleanup();\n this.returnToCanvas(element, openedByPointer);\n return;\n }\n if (e.key === \"Enter\") {\n // Note: save only with Cmd/Ctrl -> otherwise line break. Others: Enter saves, Shift+Enter\n // breaks the line.\n if (isNote ? !(e.metaKey || e.ctrlKey) : e.shiftKey) return;\n e.preventDefault();\n commit(\"enter\");\n if (done) this.returnToCanvas(element, openedByPointer);\n }\n };\n const onInput = () => {\n clearError();\n layout();\n };\n const onBlur = () => commit(\"outside\");\n field.addEventListener(\"keydown\", onKey as EventListener);\n field.addEventListener(\"blur\", onBlur);\n field.addEventListener(\"input\", onInput);\n\n const relayout = () => {\n if (done) return;\n // A redraw replaces the label nodes, and a detached node measures as an empty box at 0,0.\n const current = this.nameLabelElements(element);\n classedByFallback.push(...current.classedByFallback);\n geometry = this.labelGeometry(element, current.labelElements);\n growth = growthOf();\n lineHeight = lineHeightOf(geometry.fontSize);\n Object.assign(field.style, {\n fontSize: `${geometry.fontSize}px`,\n lineHeight: `${lineHeight}px`,\n });\n layout();\n };\n\n this.active = { elementId: element.id, field, commit, cleanup, relayout };\n }\n\n /**\n * Inline editing for connections: a flow edits its value (`+'value'>`), a dependency its\n * `; annotation` text. An empty input clears the field. Undo-safe via updateProperties.\n */\n activateConnection(conn: WardleyConnection, options: ActivateOptions = {}): void {\n if (this.locked()) return;\n this.active?.commit(\"outside\");\n\n const container = this.canvas.getContainer();\n if (conn.waypoints.length < 1) return;\n const isFlow = conn.wardleyType === \"flow\";\n const openedByPointer = lastInteractionWasPointer();\n\n const field = document.createElement(\"input\");\n field.type = \"text\";\n field.className = \"wardley-label-input\";\n field.placeholder = isFlow ? \"flow value (e.g. $0.10)\" : \"link annotation\";\n field.value = options.value ?? (isFlow ? conn.flowValue : conn.linkLabel) ?? \"\";\n field.style.position = \"absolute\";\n const place = () => {\n // Read afresh: a redraw of the connection replaces its waypoints.\n const first = conn.waypoints[0];\n const last = conn.waypoints[conn.waypoints.length - 1];\n if (!first || !last) return;\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n field.style.left = `${((first.x + last.x) / 2 - 60 - viewbox.x) * scale}px`;\n field.style.top = `${((first.y + last.y) / 2 - 26 - viewbox.y) * scale}px`;\n };\n place();\n container.appendChild(field);\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey as EventListener);\n field.removeEventListener(\"blur\", onBlur);\n field.remove();\n this.active = null;\n };\n const commit = () => {\n if (done) return;\n // Defuse DSL metacharacters: `'` delimits the flow value, `;` starts the annotation.\n const value = field.value.replace(/'/g, \"’\").replace(/;/g, \",\").trim();\n const current = (isFlow ? conn.flowValue : conn.linkLabel) ?? \"\";\n cleanup();\n if (value === current) return;\n // Keep the businessObject in sync — the exporter prefers it for imported edges.\n const bo = conn.businessObject;\n const nextBo = bo\n ? isFlow\n ? { ...bo, ...(value ? { flowValue: value } : {}) }\n : { ...bo, ...(value ? { label: value } : {}) }\n : undefined;\n if (nextBo && !value) {\n if (isFlow) delete (nextBo as { flowValue?: string }).flowValue;\n else delete (nextBo as { label?: string }).label;\n }\n this.modeling.updateProperties(conn, {\n [isFlow ? \"flowValue\" : \"linkLabel\"]: value || undefined,\n ...(nextBo ? { businessObject: nextBo } : {}),\n });\n };\n const onKey = (e: KeyboardEvent) => {\n if (isImeCompositionKey(e) || isKeyOnHiddenTarget(e)) return;\n if (e.key === \"Escape\") {\n e.preventDefault();\n cleanup();\n this.returnToCanvas(conn, openedByPointer);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n commit();\n this.returnToCanvas(conn, openedByPointer);\n }\n };\n const onBlur = () => commit();\n field.addEventListener(\"keydown\", onKey as EventListener);\n field.addEventListener(\"blur\", onBlur);\n\n const relayout = () => {\n if (!done) place();\n };\n this.active = { elementId: conn.id, field, commit, cleanup, relayout, connection: true };\n }\n\n /** Discards the open edit (if any) without saving. */\n cancel(): void {\n this.active?.cleanup();\n }\n\n /** `canvas.viewbox.changing` fires before the change, and `changed` waits 300ms under `deferUpdate`. */\n private relayoutAfterViewChange(): void {\n if (!this.active || this.relayoutPending) return;\n this.relayoutPending = true;\n queueMicrotask(() => {\n this.relayoutPending = false;\n this.active?.relayout();\n });\n }\n\n /**\n * Saves the open edit (if any) as if focus had left the field, e.g. before the host saves or\n * exports the map, so the file contains the text the user sees.\n */\n commitActiveEdit(): void {\n this.active?.commit(\"outside\");\n }\n\n /** The open editor's element and current (unsaved) text, or null when nothing is edited. */\n getActiveEdit(): ActiveLabelEdit | null {\n if (!this.active) return null;\n const { elementId, field, connection } = this.active;\n return {\n elementId,\n value: field.value,\n selection: { start: field.selectionStart ?? 0, end: field.selectionEnd ?? 0 },\n ...(connection ? { connection } : {}),\n };\n }\n\n /**\n * After Enter/Escape the removed field leaves focus on <body>; hand it back to the canvas so\n * keyboard users keep their place, and bring back the context pad a name editor had closed.\n */\n private returnToCanvas(\n element: WardleyShape | WardleyConnection,\n openedByPointer: boolean,\n ): void {\n // A name typed after a click or placement must not leave a keyboard focus ring around the\n // whole viewport; an editor opened from the keyboard (F2, Enter) keeps the visible ring. Right\n // away, not on the next task: the canvas takes keys only while it has the focus, so the next\n // key (N for a note after naming a component) would otherwise go to <body>.\n if (openedByPointer) focusCanvasWithoutRing(this.canvas);\n else this.canvas.focus();\n const selected = this.selection?.get() ?? [];\n if (selected.length === 1 && selected[0] === element) this.contextPad?.open(element);\n }\n\n /**\n * The <text> nodes showing the element's name. Falls back to matching by content when the\n * renderer does not mark them; the LAST match skips a component's movement target label, which\n * is drawn first and may repeat the name. Fallback matches carry the class only while editing so\n * the CSS hides them.\n */\n private nameLabelElements(element: WardleyShape): {\n labelElements: SVGTextElement[];\n classedByFallback: SVGTextElement[];\n } {\n const gfx = this.canvas.getGraphics(element);\n if (!gfx) return { labelElements: [], classedByFallback: [] };\n const marked = [...gfx.querySelectorAll<SVGTextElement>(`.${NAME_LABEL_CLASS}`)];\n if (marked.length) return { labelElements: marked, classedByFallback: [] };\n const texts = [...gfx.querySelectorAll<SVGTextElement>(\"text\")].filter(\n (text) => !text.closest(\".wardley-movement\"),\n );\n // The lines of a name are tspans of one text, whose content joins them without a break.\n const drawnLabel = (element.wardleyLabel ?? \"\").split(\"\\n\").join(\"\");\n const matched =\n element.wardleyType === \"note\"\n ? texts\n : texts.filter((text) => text.textContent === drawnLabel).slice(-1);\n for (const text of matched) text.classList.add(NAME_LABEL_CLASS);\n return { labelElements: matched, classedByFallback: matched };\n }\n\n private labelGeometry(element: WardleyShape, labelElements: SVGTextElement[]): LabelGeometry {\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n const containerRect = this.canvas.getContainer().getBoundingClientRect();\n const reference = labelElements[0];\n // tiny-svg writes presentation attributes such as font-size or text-anchor as inline styles,\n // so only the computed style knows them.\n const referenceStyle = reference ? getComputedStyle(reference) : undefined;\n const fontSize = Math.max(\n MIN_FONT_SIZE,\n (Number.parseFloat(referenceStyle?.fontSize ?? \"\") || FONT.label) * scale,\n );\n const typography = {\n fontSize,\n fontWeight: referenceStyle?.fontWeight || \"normal\",\n fontStyle: referenceStyle?.fontStyle || \"normal\",\n fontFamily: referenceStyle?.fontFamily || FONT.family,\n };\n\n if (element.wardleyType === \"note\") {\n return {\n left: (element.x - viewbox.x) * scale,\n top: (element.y - viewbox.y) * scale,\n width: element.width * scale,\n height: element.height * scale,\n centered: true,\n lineCount: Math.max(1, labelElements.length),\n ...typography,\n };\n }\n if (reference) {\n const boxes = labelElements.map((text) => text.getBoundingClientRect());\n const left = Math.min(...boxes.map((box) => box.left));\n const top = Math.min(...boxes.map((box) => box.top));\n return {\n left: left - containerRect.left,\n top: top - containerRect.top,\n width: Math.max(...boxes.map((box) => box.right)) - left,\n height: Math.max(...boxes.map((box) => box.bottom)) - top,\n centered: referenceStyle?.textAnchor === \"middle\",\n lineCount: Math.max(1, reference.querySelectorAll(\"tspan\").length),\n ...typography,\n };\n }\n // No visible label (e.g. a pipeline whose name is shown by its same-named component).\n return {\n left: (element.x + element.width + 6 - viewbox.x) * scale,\n top: (element.y + element.height / 2 - viewbox.y) * scale - fontSize / 2,\n width: 0,\n height: fontSize,\n centered: false,\n lineCount: 1,\n ...typography,\n };\n }\n}\n\nfunction createNameField(\n isNote: boolean,\n value: string,\n geometry: LabelGeometry,\n lineHeight: number,\n): HTMLTextAreaElement {\n const field = document.createElement(\"textarea\");\n field.className = \"wardley-label-input wardley-label-input--name wardley-label-textarea\";\n field.value = value;\n field.rows = 1;\n field.setAttribute(\"aria-label\", isNote ? \"Note text\" : \"Name\");\n field.spellcheck = false;\n field.wrap = \"off\";\n Object.assign(field.style, {\n position: \"absolute\",\n fontFamily: geometry.fontFamily,\n fontSize: `${geometry.fontSize}px`,\n fontWeight: geometry.fontWeight,\n fontStyle: geometry.fontStyle,\n lineHeight: `${lineHeight}px`,\n padding: `${FIELD_PADDING_Y}px ${FIELD_PADDING_X}px`,\n textAlign: geometry.centered ? \"center\" : \"left\",\n });\n return field;\n}\n\n/**\n * Field box over the label: as wide as its content (never narrower than a note's own box), centred\n * on centred labels, otherwise starting where the label text starts. New lines spread as the saved\n * label's will: around the label's middle, upward with the field's last line kept on the label's\n * last, or downward with its first line kept on the label's first.\n */\nfunction fieldBox(\n value: string,\n geometry: LabelGeometry,\n lineHeight: number,\n isNote: boolean,\n growth: LineGrowth,\n): { left: number; top: number; width: number; height: number } {\n const font = `${geometry.fontStyle} ${geometry.fontWeight} ${geometry.fontSize}px ${geometry.fontFamily}`;\n const chrome = 2 * (FIELD_PADDING_X + FIELD_BORDER) + CARET_ROOM;\n const lines = (value || \" \").split(\"\\n\");\n const textWidth = Math.max(\n ...lines.map((line) => measureTextWidth(line, font, geometry.fontSize)),\n );\n const width = Math.max(\n textWidth + chrome,\n geometry.fontSize * 2 + chrome,\n isNote ? geometry.width : 0,\n );\n const chromeHeight = 2 * (FIELD_PADDING_Y + FIELD_BORDER);\n const height = Math.max(lines.length * lineHeight + chromeHeight, isNote ? geometry.height : 0);\n const left = geometry.centered\n ? geometry.left + geometry.width / 2 - width / 2\n : geometry.left - FIELD_PADDING_X - FIELD_BORDER;\n const labelMiddle = geometry.top + geometry.height / 2;\n const drawnLinesHeight = geometry.lineCount * lineHeight + chromeHeight;\n const top =\n growth === \"up\"\n ? labelMiddle + drawnLinesHeight / 2 - height\n : growth === \"down\"\n ? labelMiddle - drawnLinesHeight / 2\n : labelMiddle - height / 2;\n return { left, top, width, height };\n}\n\nfunction createCaption(className: string, text: string): HTMLElement {\n const caption = document.createElement(\"div\");\n caption.className = `wardley-label-caption ${className}`;\n caption.textContent = text;\n return caption;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLabelEditing from \"./WardleyLabelEditing.js\";\n\n/** Custom inline label editing (HTML overlay). */\nexport const labelEditingModule: ModuleDeclaration = {\n __init__: [\"wardleyLabelEditing\"],\n wardleyLabelEditing: [\"type\", WardleyLabelEditing],\n};\n\nexport { default as WardleyLabelEditing } from \"./WardleyLabelEditing.js\";\nexport { createFieldError, FIELD_TO_CAPTION_GAP, type FieldError } from \"./fieldError.js\";\nexport { focusField, type FieldSelection } from \"./WardleyLabelEditing.js\";\nexport { isImeCompositionKey } from \"./imeComposition.js\";\n","const ALLOWED_SCHEMES = new Set([\"http:\", \"https:\", \"mailto:\"]);\n\n/** RFC 3986 scheme prefix; anything without one is a relative reference (e.g. `./other.wmap`). */\nconst SCHEME_PATTERN = /^([a-z][a-z0-9+.-]*):/i;\n\n// Control characters (incl. tab and line breaks) — browsers drop them while parsing a URL, so\n// `java\\nscript:` would otherwise slip past the scheme check.\n// eslint-disable-next-line no-control-regex\nconst CONTROL_CHARACTERS = /[\\u0000-\\u001f\\u007f]/g;\n\n/**\n * Normalises user or file input into an address the OWM DSL can carry losslessly:\n * `url Name [address]` ends at `]`, and a line break would end the definition line.\n */\nexport function sanitizeLinkUrl(raw: string): string {\n return raw.replace(CONTROL_CHARACTERS, \"\").replace(/[[\\]]/g, \"\").trim();\n}\n\n/**\n * Allowlist for addresses the modeler stores or opens: http(s), mailto, or a relative reference.\n * Shared maps arrive through URLs and files, so a `javascript:` or `data:` address must never reach\n * `window.open`.\n */\nexport function isAllowedLinkUrl(url: string): boolean {\n const scheme = SCHEME_PATTERN.exec(url)?.[1];\n return scheme === undefined || ALLOWED_SCHEMES.has(`${scheme.toLowerCase()}:`);\n}\n\n/** Sanitised address if it is non-empty and allowed, otherwise `undefined`. */\nexport function safeLinkUrl(raw: string | undefined): string | undefined {\n if (raw === undefined) return undefined;\n const url = sanitizeLinkUrl(raw);\n return url && isAllowedLinkUrl(url) ? url : undefined;\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ComponentElement, MapElement, SubmapElement } from \"@miragon/wardley-schema-model\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport {\n createFieldError,\n FIELD_TO_CAPTION_GAP,\n focusField,\n isImeCompositionKey,\n type FieldSelection,\n} from \"../label-editing/index.js\";\nimport { isAllowedLinkUrl, sanitizeLinkUrl } from \"./link-url.js\";\nimport { isKeyOnHiddenTarget } from \"../a11y/index.js\";\n\ninterface ActiveLinkEdit {\n elementId: string;\n field: HTMLInputElement;\n commit: () => void;\n cleanup: () => void;\n /** Places the field below its element again after the view changed. */\n relayout: () => void;\n}\n\n/** Screen px from the element's top edge: two 28px pad rows plus their gap and a margin. */\nconst CONTEXT_PAD_CLEARANCE = 72;\n\n/** Below diagram-js's own `shape.changed` listener, which redraws the element. */\nconst AFTER_REDRAW_PRIORITY = 500;\n\nconst INVALID_HINT = \"Use an http(s) or mailto address, or a relative path such as ./other.wmap\";\n\n/** Element types that carry an OWM `url(...)` reference. */\nexport function canHaveLink(shape: WardleyShape): boolean {\n return shape.wardleyType === \"component\" || shape.wardleyType === \"submap\";\n}\n\n/** The stored address: `url` on components, `urlRef` on submaps (both live on the businessObject). */\nexport function linkOf(shape: WardleyShape): string | undefined {\n const businessObject = shape.businessObject;\n if (shape.wardleyType === \"submap\") return (businessObject as SubmapElement | undefined)?.urlRef;\n if (shape.wardleyType === \"component\")\n return (businessObject as ComponentElement | undefined)?.url;\n return undefined;\n}\n\n/**\n * Inline editor for the link of a component or submap (OWM `url Name [address]` + `url(Name)`).\n * Commits exactly one undoable `updateProperties`; addresses outside the allowlist (http, https,\n * mailto, relative) are rejected and the field stays open marked invalid.\n */\nexport default class WardleyLinkEditing {\n static $inject = [\"eventBus\", \"canvas\", \"wardleyModeling\", \"injector\"];\n\n private active: ActiveLinkEdit | null = null;\n private relayoutPending = false;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly modeling: WardleyModeling,\n private readonly injector: Injector,\n ) {\n eventBus.on([\"element.mousedown\", \"drag.init\"], () => this.active?.commit());\n // A host's view change (restoring the view after a peer's re-import, a refit) must not commit\n // the half-typed address into the shared document (modeler-api L5): the field follows instead.\n eventBus.on(\"canvas.viewbox.changing\", () => this.relayoutAfterViewChange());\n eventBus.on(\"canvas.viewbox.changed\", () => this.active?.relayout());\n // A redraw of the edited element (a host resizing the map while the field is open) moves it\n // without a view change; the priority waits for the redraw.\n eventBus.on(\"shape.changed\", AFTER_REDRAW_PRIORITY, (event: { element?: { id?: string } }) => {\n if (this.active && event.element?.id === this.active.elementId) this.active.relayout();\n });\n eventBus.on([\"diagram.clear\", \"diagram.destroy\"], () => this.cancel());\n }\n\n /**\n * Sets (or with an empty value removes) the link. Returns false when the address is not allowed.\n * The exporter reads the link from the businessObject, which palette-created shapes do not have\n * yet — so a minimal one is built from the shape.\n */\n setLink(shape: WardleyShape, rawUrl: string | undefined): boolean {\n if (!canHaveLink(shape)) return false;\n const url = sanitizeLinkUrl(rawUrl ?? \"\");\n if (url && !isAllowedLinkUrl(url)) return false;\n if ((linkOf(shape) ?? \"\") === url) return true;\n\n const key = shape.wardleyType === \"submap\" ? \"urlRef\" : \"url\";\n if (!shape.businessObject) {\n // diagram-js defines `businessObject` as non-deletable, so undo could not restore \"absent\".\n // A link-less base carries nothing the exporter reads, so attaching it outside the command\n // stack changes no output and lets undo fall back to it instead.\n shape.businessObject = {\n id: shape.id,\n elementType: shape.wardleyType,\n label: shape.wardleyLabel,\n position: { visibility: shape.visibility, evolution: shape.evolution },\n } as MapElement;\n }\n const base = shape.businessObject;\n const next: Record<string, unknown> = { ...base };\n if (url) next[key] = url;\n else delete next[key];\n this.modeling.updateProperties(shape, { businessObject: next });\n return true;\n }\n\n /**\n * @param options.value field content to restore instead of the current link (re-import).\n * @param options.selection caret or selection to restore; without it the whole text is selected.\n */\n activate(\n shape: WardleyShape,\n options: { value?: string; selection?: FieldSelection } = {},\n ): void {\n if (!canHaveLink(shape) || isReadOnly(this.injector)) return;\n this.active?.commit();\n\n const container = this.canvas.getContainer();\n const field = document.createElement(\"input\");\n // type=\"url\" would flag relative paths such as ./other.wmap as :invalid.\n field.type = \"text\";\n field.inputMode = \"url\";\n field.spellcheck = false;\n field.autocomplete = \"off\";\n field.className = \"wardley-label-input wardley-link-input\";\n field.placeholder = \"https://… or ./other.wmap\";\n field.setAttribute(\"aria-label\", `Link of ${shape.wardleyLabel || shape.wardleyType}`);\n field.value = options.value ?? linkOf(shape) ?? \"\";\n field.style.position = \"absolute\";\n const placeField = () => {\n const scale = this.canvas.zoom();\n const viewbox = this.canvas.viewbox();\n // Below the element and its two-row context pad, which sit to the right of the element's top.\n field.style.left = `${(shape.x - viewbox.x) * scale}px`;\n field.style.top = `${(shape.y - viewbox.y) * scale + CONTEXT_PAD_CLEARANCE}px`;\n };\n placeField();\n container.appendChild(field);\n focusField(field, options);\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n field.removeEventListener(\"keydown\", onKey);\n field.removeEventListener(\"blur\", onBlur);\n field.removeEventListener(\"input\", clearInvalid);\n error.clear();\n field.remove();\n this.active = null;\n };\n const placeCaption = (caption: HTMLElement) => {\n caption.style.left = field.style.left;\n caption.style.top = `${field.offsetTop + field.offsetHeight + FIELD_TO_CAPTION_GAP}px`;\n };\n const error = createFieldError(\n container,\n field,\n `wardley-link-error-${shape.id}`,\n placeCaption,\n );\n const markInvalid = () => error.show(INVALID_HINT);\n const clearInvalid = () => error.clear();\n const tryCommit = (): boolean => {\n if (done) return true;\n const url = sanitizeLinkUrl(field.value);\n if (url && !isAllowedLinkUrl(url)) {\n markInvalid();\n return false;\n }\n cleanup();\n this.setLink(shape, url);\n return true;\n };\n // Leaving the field with a rejected address discards it rather than trapping the user.\n const commit = () => {\n if (!tryCommit()) cleanup();\n };\n const onKey = (event: KeyboardEvent) => {\n if (isImeCompositionKey(event) || isKeyOnHiddenTarget(event)) return;\n if (event.key === \"Escape\") {\n event.preventDefault();\n cleanup();\n this.canvas.focus();\n } else if (event.key === \"Enter\") {\n event.preventDefault();\n if (tryCommit()) this.canvas.focus();\n }\n };\n const onBlur = () => commit();\n field.addEventListener(\"keydown\", onKey);\n field.addEventListener(\"blur\", onBlur);\n field.addEventListener(\"input\", clearInvalid);\n\n const relayout = () => {\n if (done) return;\n placeField();\n if (error.caption) placeCaption(error.caption);\n };\n this.active = { elementId: shape.id, field, commit, cleanup, relayout };\n }\n\n cancel(): void {\n this.active?.cleanup();\n }\n\n /** `canvas.viewbox.changing` fires before the change, and `changed` waits 300ms under `deferUpdate`. */\n private relayoutAfterViewChange(): void {\n if (!this.active || this.relayoutPending) return;\n this.relayoutPending = true;\n queueMicrotask(() => {\n this.relayoutPending = false;\n this.active?.relayout();\n });\n }\n\n /** Saves the open link edit (if any) as if focus had left the field; a rejected address is dropped. */\n commitActiveEdit(): void {\n this.active?.commit();\n }\n\n getActiveEdit(): { elementId: string; value: string; selection: FieldSelection } | null {\n if (!this.active) return null;\n const { elementId, field } = this.active;\n return {\n elementId,\n value: field.value,\n selection: { start: field.selectionStart ?? 0, end: field.selectionEnd ?? 0 },\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyLinkEditing from \"./WardleyLinkEditing.js\";\n\n/** Inline link (url) editing for components and submaps. */\nexport const linkEditingModule: ModuleDeclaration = {\n __init__: [\"wardleyLinkEditing\"],\n wardleyLinkEditing: [\"type\", WardleyLinkEditing],\n};\n\nexport { default as WardleyLinkEditing, canHaveLink, linkOf } from \"./WardleyLinkEditing.js\";\nexport { sanitizeLinkUrl, isAllowedLinkUrl, safeLinkUrl } from \"./link-url.js\";\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type { PopupMenuTarget } from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type {\n PopupMenuEntries,\n default as PopupMenuProvider,\n} from \"diagram-js/lib/features/popup-menu/PopupMenuProvider\";\nimport { isComponent, type WardleyShape } from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { isKeyOnHiddenTarget, leaveKeysOnHiddenMenuToPage } from \"../a11y/index.js\";\n\nexport const POPUP_PROVIDER_ID = \"wardley-element-settings\";\n\nconst TYPE_GROUP = { id: \"type\", name: \"Type\" };\nconst METHOD_GROUP = { id: \"method\", name: \"Sourcing\" };\nconst PROP_GROUP = { id: \"props\", name: \"Properties\" };\n\n/**\n * The menu handles its own keys (arrows select, Enter picks), so no listener further up acts on\n * them too. Escape must still bubble: diagram-js closes the menu from a document listener. A key\n * on a menu the host made inert or hid is the page's.\n */\nfunction keepKeysInsidePopup(event: KeyboardEvent): void {\n if (event.key !== \"Escape\" && !isKeyOnHiddenTarget(event)) event.stopPropagation();\n}\n\nfunction mark(active: boolean, label: string): string {\n return active ? `✓ ${label}` : label;\n}\n\n/**\n * Popup submenu (opened via the context pad gear) for directly setting type (normal/market/\n * ecosystem), sourcing (build/buy/outsource) and inertia — instead of cycle buttons.\n * All actions go through `wardleyModeling` (undo/redo).\n */\nexport default class WardleyElementSettingsProvider implements PopupMenuProvider {\n static $inject = [\"popupMenu\", \"wardleyModeling\", \"eventBus\"];\n\n constructor(\n popupMenu: PopupMenu,\n private readonly modeling: WardleyModeling,\n eventBus: EventBus,\n ) {\n popupMenu.registerProvider(POPUP_PROVIDER_ID, this);\n leaveKeysOnHiddenMenuToPage(popupMenu);\n eventBus.on(\"popupMenu.open\", () => {\n const container = (popupMenu as unknown as { _current?: { container?: HTMLElement } })\n ._current?.container;\n if (container?.getAttribute(\"data-popup\") !== POPUP_PROVIDER_ID) return;\n container.addEventListener(\"keydown\", keepKeysInsidePopup);\n });\n }\n\n getPopupMenuEntries(target: PopupMenuTarget): PopupMenuEntries {\n const shape = (Array.isArray(target) ? target[0] : target) as WardleyShape | undefined;\n if (!isComponent(shape)) return {};\n return this.componentEntries(shape);\n }\n\n private componentEntries(shape: WardleyShape): PopupMenuEntries {\n const dec = shape.decorators ?? {};\n const kind = dec.ecosystem ? \"ecosystem\" : dec.market ? \"market\" : \"normal\";\n const method = dec.method;\n\n return {\n \"type-normal\": {\n label: mark(kind === \"normal\", \"Normal\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, undefined),\n },\n \"type-market\": {\n label: mark(kind === \"market\", \"Market\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, \"market\"),\n },\n \"type-ecosystem\": {\n label: mark(kind === \"ecosystem\", \"Ecosystem\"),\n group: TYPE_GROUP,\n action: () => this.modeling.setMarketEcosystem(shape, \"ecosystem\"),\n },\n \"method-none\": {\n label: mark(!method, \"None\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, undefined),\n },\n \"method-build\": {\n label: mark(method === \"build\", \"Build\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"build\"),\n },\n \"method-buy\": {\n label: mark(method === \"buy\", \"Buy\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"buy\"),\n },\n \"method-outsource\": {\n label: mark(method === \"outsource\", \"Outsource\"),\n group: METHOD_GROUP,\n action: () => this.modeling.setMethod(shape, \"outsource\"),\n },\n \"prop-inertia\": {\n label: mark(!!dec.inertia, \"Inertia\"),\n group: PROP_GROUP,\n action: () => this.modeling.toggleInertia(shape),\n },\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyElementSettingsProvider from \"./WardleyElementSettingsProvider.js\";\n\n/** Popup submenu for element settings (type/sourcing/inertia). */\nexport const wardleyPopupModule: ModuleDeclaration = {\n __init__: [\"wardleyElementSettings\"],\n wardleyElementSettings: [\"type\", WardleyElementSettingsProvider],\n};\n\nexport {\n default as WardleyElementSettingsProvider,\n POPUP_PROVIDER_ID,\n} from \"./WardleyElementSettingsProvider.js\";\n","/*! @miragon/wardley-renderer icon geometry: the context pad icons. Lucide (lucide-static 1.59.0)\n * @license ISC Copyright (c) 2026 Lucide Icons and Contributors\n * arrow-right, chevrons-right, circle-plus, external-link, link and trash derive from Feather\n * @license MIT, Copyright (c) 2013-present Cole Bemis\n * Full notices: README.md of @miragon/wardley-renderer */\n\n/**\n * The Lucide icons of the context pad (guide §5.14), inlined so the renderer has no icon runtime\n * dependency. Copied unchanged from lucide-static 1.59.0 (`icon-nodes.json`), except\n * `chevrons-right-x`.\n */\nexport const LUCIDE = {\n pencil:\n '<path d=\"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\"/><path d=\"m15 5 4 4\"/>',\n trash:\n '<path d=\"M10 11v6\"/><path d=\"M14 11v6\"/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\"/><path d=\"M3 6h18\"/><path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"/>',\n \"circle-plus\": '<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 12h8\"/><path d=\"M12 8v8\"/>',\n \"arrow-right\": '<path d=\"M5 12h14\"/><path d=\"m12 5 7 7-7 7\"/>',\n \"chevrons-right\": '<path d=\"m6 17 5-5-5-5\"/><path d=\"m13 17 5-5-5-5\"/>',\n // Lucide has no crossed-out chevrons-right, and its `m2 2 20 20` slash runs parallel to the\n // chevrons' upper strokes, so at 16px a slashed variant no longer reads as chevrons. Drawn after\n // icon-design §C instead: `chevrons-right` moved up and left by (2, 1), with the corner `x` of\n // Lucide's `calendar-x-2`.\n \"chevrons-right-x\":\n '<path d=\"m4 16 5-5-5-5\"/><path d=\"m11 16 5-5-5-5\"/><path d=\"m17 16 5 5\"/><path d=\"m17 21 5-5\"/>',\n \"sliders-horizontal\":\n '<path d=\"M10 5H3\"/><path d=\"M12 19H3\"/><path d=\"M14 3v4\"/><path d=\"M16 17v4\"/><path d=\"M21 12h-9\"/><path d=\"M21 19h-5\"/><path d=\"M21 5h-7\"/><path d=\"M8 10v4\"/><path d=\"M8 12H3\"/>',\n \"line-style\":\n '<path d=\"M11 5h2\"/><path d=\"M15 12h6\"/><path d=\"M19 5h2\"/><path d=\"M3 12h6\"/><path d=\"M3 19h18\"/><path d=\"M3 5h2\"/>',\n palette:\n '<path d=\"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\"/><circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/>',\n link: '<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>',\n \"external-link\":\n '<path d=\"M15 3h6v6\"/><path d=\"M10 14 21 3\"/><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/>',\n} as const;\n\nexport type LucideIconName = keyof typeof LUCIDE;\n\n/**\n * A chrome icon (guide §5.14, §11): 16px with stroke 2.5 on the 24 grid, so the stroke matches the\n * shell's chrome icons; `currentColor`, so the surrounding role decides the colour.\n */\nexport function chromeIcon(name: LucideIconName): string {\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">${LUCIDE[name]}</svg>`;\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type {\n ContextPadEntries,\n default as ContextPadProvider,\n} from \"diagram-js/lib/features/context-pad/ContextPadProvider\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport {\n isWardleyShape,\n isWardleyConnection,\n type WardleyConnection,\n type WardleyShape,\n} from \"../model/di-types.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type WardleyLabelEditing from \"../label-editing/WardleyLabelEditing.js\";\nimport type WardleyEvolveDragging from \"../evolve/WardleyEvolveDragging.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type WardleyColorPicker from \"../color-picker/WardleyColorPicker.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyLinkEditing from \"../link-editing/WardleyLinkEditing.js\";\nimport { canHaveLink, linkOf, safeLinkUrl } from \"../link-editing/index.js\";\nimport { POPUP_PROVIDER_ID } from \"../popup/index.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport { focusCanvasWithoutRing, isKeyOnHiddenTarget } from \"../a11y/index.js\";\nimport { chromeIcon } from \"../draw/lucide.js\";\n\n/** Rows of the compact pad: primary actions, then properties, then the destructive action. */\nconst GROUP_PRIMARY = \"edit\";\nconst GROUP_PROPERTIES = \"wardley\";\nconst GROUP_DANGER = \"danger\";\n\n/** Distance (diagram px) below the source at which a keyboard-appended component is placed. */\nconst KEYBOARD_APPEND_OFFSET = 80;\n\nconst PAD_PREVIOUS_KEYS = new Set([\"ArrowLeft\", \"ArrowUp\"]);\nconst PAD_NEXT_KEYS = new Set([\"ArrowRight\", \"ArrowDown\"]);\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\");\n}\n\n/**\n * ContextPad entry as a focusable icon button. `draggable=true` is mandatory for entries with a\n * `dragstart` action — otherwise diagram-js does not fire the drag.\n */\nfunction cpHtml(iconSvg: string, label: string, draggable = false): string {\n const name = escapeAttribute(label);\n return `<div class=\"entry wardley-cp-entry\" role=\"button\" tabindex=\"0\" aria-label=\"${name}\"${draggable ? ' draggable=\"true\"' : \"\"} title=\"${name}\">${iconSvg}</div>`;\n}\n\n/** Context actions per element (concept doc §5.5). */\nexport default class WardleyContextPadProvider implements ContextPadProvider {\n static $inject = [\n \"contextPad\",\n \"modeling\",\n \"connect\",\n \"create\",\n \"popupMenu\",\n \"wardleyModeling\",\n \"wardleyLabelEditing\",\n \"wardleyEvolveDragging\",\n \"wardleyElementFactory\",\n \"wardleyColorPicker\",\n \"eventBus\",\n \"canvas\",\n \"injector\",\n ];\n\n /** Synthetic clicks created for Enter/Space, so actions can pick a pointer-free variant. */\n private readonly keyboardEvents = new WeakSet<Event>();\n\n constructor(\n private readonly contextPad: ContextPad,\n private readonly modeling: Modeling,\n private readonly connect: Connect,\n private readonly create: Create,\n private readonly popupMenu: PopupMenu,\n private readonly wardleyModeling: WardleyModeling,\n private readonly labelEditing: WardleyLabelEditing,\n private readonly evolveDragging: WardleyEvolveDragging,\n private readonly factory: WardleyElementFactory,\n private readonly colorPicker: WardleyColorPicker,\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly injector: Injector,\n ) {\n contextPad.registerProvider(this);\n eventBus.on(\"contextPad.create\", (event: { pad: HTMLElement }) => {\n event.pad.setAttribute(\"role\", \"toolbar\");\n event.pad.setAttribute(\"aria-label\", \"Element actions\");\n event.pad.addEventListener(\"keydown\", (keyEvent) => this.onPadKeydown(keyEvent, event.pad));\n });\n }\n\n getContextPadEntries(element: Element): ContextPadEntries {\n if (isReadOnly(this.injector)) return {};\n if (isWardleyConnection(element)) return this.connectionEntries(element);\n if (!isWardleyShape(element)) return {};\n const shape = element as WardleyShape;\n // Insertion order is render order: diagram-js creates a group row on its first entry.\n const entries: ContextPadEntries = {};\n this.addPrimaryEntries(shape, entries);\n this.addPropertyEntries(shape, entries);\n entries[\"delete\"] = {\n group: GROUP_DANGER,\n title: \"Delete\",\n html: cpHtml(chromeIcon(\"trash\"), \"Delete\"),\n action: {\n click: this.focusingCanvas(() =>\n this.modeling.removeElements([shape as unknown as Element]),\n ),\n },\n };\n return entries;\n }\n\n /** Connections: edit the annotation (or the flow value of an imported flow link) + delete. */\n private connectionEntries(conn: WardleyConnection): ContextPadEntries {\n const isFlow = conn.wardleyType === \"flow\";\n const editTitle = isFlow ? \"Edit flow value\" : \"Edit link annotation\";\n return {\n \"edit-value\": {\n group: GROUP_PRIMARY,\n title: editTitle,\n html: cpHtml(chromeIcon(\"pencil\"), editTitle),\n action: { click: () => this.labelEditing.activateConnection(conn) },\n },\n delete: {\n group: GROUP_DANGER,\n title: \"Delete connection\",\n html: cpHtml(chromeIcon(\"trash\"), \"Delete connection\"),\n action: {\n click: this.focusingCanvas(() =>\n this.modeling.removeElements([conn as unknown as Element]),\n ),\n },\n },\n };\n }\n\n /** Row 1: edit label, append, connect, evolve. */\n private addPrimaryEntries(shape: WardleyShape, entries: ContextPadEntries): void {\n // Drawings have no label (pure geometry); regions are unlabelled like in OWM.\n if (shape.wardleyType !== \"drawing\" && shape.wardleyType !== \"attitude\") {\n entries[\"edit-label\"] = {\n group: GROUP_PRIMARY,\n title: \"Edit label\",\n html: cpHtml(chromeIcon(\"pencil\"), \"Edit label\"),\n action: { click: () => this.labelEditing.activate(shape) },\n };\n }\n\n const connectable =\n shape.wardleyType === \"component\" ||\n shape.wardleyType === \"anchor\" ||\n shape.wardleyType === \"submap\" ||\n shape.wardleyType === \"pipeline\";\n if (connectable) {\n // Append component: drags out a new (blank) component and creates the arrow automatically\n // (diagram-js Create with `source` -> modeling.appendShape). Configurable via ⚙.\n const startAppend = this.focusingCanvas((event: Event) => {\n if (this.keyboardEvents.has(event)) {\n this.appendBelow(shape);\n return;\n }\n const next = this.factory.createNew(\"component\", \"Component\");\n this.create.start(event as MouseEvent, next as unknown as Element, {\n source: shape as unknown as Element,\n });\n });\n entries[\"append\"] = {\n group: GROUP_PRIMARY,\n title: \"Append component (auto-connect)\",\n html: cpHtml(chromeIcon(\"circle-plus\"), \"Append component\", true),\n action: { click: startAppend, dragstart: startAppend },\n };\n\n const startConnect = this.focusingCanvas((event: Event) => {\n this.connect.start(event as MouseEvent, shape as unknown as Element);\n });\n entries[\"connect\"] = {\n group: GROUP_PRIMARY,\n title: \"Connect to existing element (A)\",\n html: cpHtml(chromeIcon(\"arrow-right\"), \"Connect to existing element (A)\", true),\n action: { click: startConnect, dragstart: startConnect },\n };\n }\n\n if (shape.wardleyType === \"component\") {\n if (shape.movement) {\n // Target is set -> drag the red target circle directly to MOVE it\n // (see WardleyEvolveDragging). Here we only offer removal.\n entries[\"evolve-clear\"] = {\n group: GROUP_PRIMARY,\n title: \"Remove evolve\",\n html: cpHtml(chromeIcon(\"chevrons-right-x\"), \"Remove evolve\"),\n action: { click: this.focusingCanvas(() => this.wardleyModeling.clearMovement(shape)) },\n };\n } else if (shape.evolution < 0.999) {\n // Drag the target out along the axis (live preview). The click does NOT model immediately\n // (no automatic +0.2 anymore) — it only starts the placement. At evolution ~ 1 there is\n // no meaningful target left — the entry is omitted (instead of creating a null movement).\n const startEvolve = this.focusingCanvas((event: Event) =>\n this.evolveDragging.start(event, shape),\n );\n entries[\"evolve\"] = {\n group: GROUP_PRIMARY,\n title: \"Evolve: drag to set the target maturity\",\n html: cpHtml(\n chromeIcon(\"chevrons-right\"),\n \"Evolve: drag to set the target maturity\",\n true,\n ),\n action: { click: startEvolve, dragstart: startEvolve },\n };\n }\n }\n }\n\n /** Row 2: settings, line style, colour, link. */\n private addPropertyEntries(shape: WardleyShape, entries: ContextPadEntries): void {\n if (shape.wardleyType === \"component\") {\n entries[\"settings\"] = {\n group: GROUP_PROPERTIES,\n title: \"Settings (type, sourcing, inertia)\",\n html: cpHtml(chromeIcon(\"sliders-horizontal\"), \"Settings (type, sourcing, inertia)\"),\n action: {\n click: (event: Event) => {\n const e = event as MouseEvent;\n this.popupMenu.open(shape as unknown as Element, POPUP_PROVIDER_ID, {\n x: e.clientX,\n y: e.clientY,\n });\n },\n },\n };\n }\n\n // Drawings: cycle the stroke style (solid -> dashed -> dotted).\n if (shape.wardleyType === \"drawing\") {\n const next =\n shape.strokeStyle === \"dashed\"\n ? \"dotted\"\n : shape.strokeStyle === \"dotted\"\n ? undefined\n : \"dashed\";\n const title = `Line style: ${shape.strokeStyle ?? \"solid\"} (click to change)`;\n entries[\"stroke-style\"] = {\n group: GROUP_PROPERTIES,\n title,\n html: cpHtml(chromeIcon(\"line-style\"), title),\n action: {\n click: this.focusingCanvas(() =>\n this.wardleyModeling.updateProperties(shape, { strokeStyle: next }),\n ),\n },\n };\n }\n\n // Color is available on EVERY element (model-wide `color`, DSL extension `(color ...)`).\n entries[\"color\"] = {\n group: GROUP_PROPERTIES,\n title: \"Color\",\n html: cpHtml(chromeIcon(\"palette\"), \"Color\"),\n action: {\n click: (event: Event) => {\n const e = event as MouseEvent;\n this.colorPicker.open(shape, e.clientX, e.clientY);\n },\n },\n };\n\n // OWM `url(...)`: set the address (submap drill-down / component link) and open it.\n const linkEditing = this.injector.get<WardleyLinkEditing>(\"wardleyLinkEditing\", false);\n const storedLink = linkOf(shape);\n if (linkEditing && canHaveLink(shape)) {\n const title = storedLink ? \"Edit link…\" : \"Set link…\";\n entries[\"link\"] = {\n group: GROUP_PROPERTIES,\n title,\n html: cpHtml(chromeIcon(\"link\"), title),\n action: { click: () => linkEditing.activate(shape) },\n };\n }\n // Shared maps can carry any address, so only allowlisted ones are ever opened.\n const openableLink = safeLinkUrl(storedLink);\n if (openableLink) {\n entries[\"open-link\"] = {\n group: GROUP_PROPERTIES,\n title: `Open link (${openableLink})`,\n html: cpHtml(chromeIcon(\"external-link\"), `Open link (${openableLink})`),\n action: {\n click: this.focusingCanvas(() =>\n window.open(openableLink, \"_blank\", \"noopener,noreferrer\"),\n ),\n },\n };\n }\n }\n\n /**\n * For an entry that opens no editor or popup: after a pointer click or drag it hands the focus to\n * the canvas (guide §5.8), whose keys act only while it has the focus. The clicked entry took the\n * focus and goes away when the pad re-renders or closes, which would leave it on `<body>`. Enter\n * and Space keep it in the pad (`onPadKeydown`).\n */\n private focusingCanvas(action: (event: Event) => void): (event: Event) => void {\n return (event) => {\n action(event);\n if (!this.keyboardEvents.has(event)) focusCanvasWithoutRing(this.canvas);\n };\n }\n\n /** Enter/Space on a focused entry = a click at the element's centre. */\n private onPadKeydown(event: KeyboardEvent, pad: HTMLElement): void {\n if (event.altKey || event.ctrlKey || event.metaKey || isKeyOnHiddenTarget(event)) return;\n const entry = (event.target as Element | null)?.closest?.(\".entry\");\n const action = entry?.getAttribute(\"data-action\");\n if (!entry || !action || !pad.contains(entry)) return;\n\n // Toolbar navigation, stopped here: no listener further up acts on these keys too.\n const entries = Array.from(pad.querySelectorAll<HTMLElement>(\".entry\"));\n const index = entries.indexOf(entry as HTMLElement);\n let next: HTMLElement | undefined;\n if (PAD_PREVIOUS_KEYS.has(event.key))\n next = entries[(index - 1 + entries.length) % entries.length];\n else if (PAD_NEXT_KEYS.has(event.key)) next = entries[(index + 1) % entries.length];\n else if (event.key === \"Home\") next = entries[0];\n else if (event.key === \"End\") next = entries[entries.length - 1];\n if (next || event.key === \"Escape\") {\n event.preventDefault();\n event.stopPropagation();\n if (next) next.focus();\n else this.canvas.focus();\n return;\n }\n\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n event.stopPropagation();\n\n const target = (this.contextPad as unknown as { _current?: { target?: unknown } })._current\n ?.target;\n const point = this.clientCenterOf(Array.isArray(target) ? target[0] : target);\n const click = new MouseEvent(\"click\", { bubbles: true, clientX: point.x, clientY: point.y });\n this.keyboardEvents.add(click);\n this.contextPad.triggerEntry(action, \"click\", click);\n\n // Actions that close the pad (delete, …) would otherwise drop focus onto <body>.\n const focused = document.activeElement;\n if (!pad.isConnected && (!focused || focused === document.body)) this.canvas.focus();\n }\n\n private clientCenterOf(element: unknown): { x: number; y: number } {\n const containerBounds = this.canvas.getContainer().getBoundingClientRect();\n const viewbox = this.canvas.viewbox();\n let center = { x: viewbox.x + viewbox.width / 2, y: viewbox.y + viewbox.height / 2 };\n if (isWardleyConnection(element)) {\n const first = element.waypoints[0];\n const last = element.waypoints[element.waypoints.length - 1];\n if (first && last) center = { x: (first.x + last.x) / 2, y: (first.y + last.y) / 2 };\n } else if (isWardleyShape(element)) {\n center = { x: element.x + element.width / 2, y: element.y + element.height / 2 };\n }\n return {\n x: containerBounds.left + (center.x - viewbox.x) * viewbox.scale,\n y: containerBounds.top + (center.y - viewbox.y) * viewbox.scale,\n };\n }\n\n /**\n * Keyboard append: there is no pointer to drag the new component to, so it is placed one step\n * further down the value chain, connected, selected and opened for naming.\n */\n private appendBelow(source: WardleyShape): void {\n const grid = this.injector.get<EvolutionGrid>(\"evolutionGrid\");\n const plotBottom = grid.toCanvas({ evolution: 0, visibility: 0 }).y;\n const next = this.factory.createNew(\"component\", \"Component\");\n const position = {\n x: source.x + source.width / 2,\n y: Math.min(\n source.y + source.height / 2 + KEYBOARD_APPEND_OFFSET,\n plotBottom - next.height / 2,\n ),\n };\n const created = this.modeling.appendShape(\n source as unknown as Shape,\n next as unknown as Shape,\n position,\n (source as unknown as Shape).parent!,\n { connection: { wardleyType: \"dependency\" } },\n );\n this.injector\n .get<{ select(element: unknown): void }>(\"selection\", false)\n ?.select(created ?? next);\n this.labelEditing.activate((created ?? next) as unknown as WardleyShape);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ContextPadModule from \"diagram-js/lib/features/context-pad\";\nimport WardleyContextPad from \"./WardleyContextPad.js\";\nimport WardleyContextPadProvider from \"./WardleyContextPadProvider.js\";\n\n/** Context actions per element. */\nexport const wardleyContextPadModule: ModuleDeclaration = {\n // Depending on the diagram-js module guarantees our 'contextPad' registration overrides its own.\n __depends__: [ContextPadModule],\n __init__: [\"wardleyContextPadProvider\"],\n contextPad: [\"type\", WardleyContextPad],\n wardleyContextPadProvider: [\"type\", WardleyContextPadProvider],\n};\n\nexport { default as WardleyContextPadProvider } from \"./WardleyContextPadProvider.js\";\nexport { default as WardleyContextPad } from \"./WardleyContextPad.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type LassoTool from \"diagram-js/lib/features/lasso-tool/LassoTool\";\nimport type Mouse from \"diagram-js/lib/features/mouse/Mouse\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type Rules from \"diagram-js/lib/features/rules/Rules\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Injector } from \"didi\";\nimport type WardleyCopyPaste from \"../modeling/WardleyCopyPaste.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyDrawTool from \"../draw-tool/WardleyDrawTool.js\";\nimport type WardleyDrawingHandles from \"../draw-tool/WardleyDrawingHandles.js\";\nimport type WardleyLabelEditing from \"../label-editing/WardleyLabelEditing.js\";\nimport type { FreeRect } from \"../free-rect/index.js\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport { isCanvasKey } from \"../a11y/index.js\";\nimport {\n isWardleyConnection,\n isWardleyShape,\n type WardleyShape,\n type WardleyShapeType,\n} from \"../model/di-types.js\";\n\n/** Diagram config `wardleyKeyboard` (viewer option `undoRedoKeys`). */\nexport interface WardleyKeyboardConfig {\n /**\n * Handle Cmd/Ctrl+Z, Cmd/Ctrl+Shift+Z and Cmd/Ctrl+Y on the canvas (default true). Hosts that own\n * undo themselves (VS Code custom editors) set this to false and receive the keys untouched.\n */\n undoRedo?: boolean;\n}\n\n/** Arrow-key nudge in diagram px (Shift = coarse). */\nconst NUDGE_STEP = 2;\nconst NUDGE_STEP_COARSE = 10;\n\nconst ARROW_DELTAS: Record<string, { x: number; y: number }> = {\n arrowleft: { x: -1, y: 0 },\n arrowright: { x: 1, y: 0 },\n arrowup: { x: 0, y: -1 },\n arrowdown: { x: 0, y: 1 },\n};\n\nconst QUICK_CREATE: Record<string, { type: WardleyShapeType; label: string }> = {\n c: { type: \"component\", label: \"Component\" },\n u: { type: \"anchor\", label: \"User\" },\n n: { type: \"note\", label: \"Note\" },\n p: { type: \"pipeline\", label: \"Pipeline\" },\n};\n\n/** The single-key tools C, U, N, P, A and L, pressed without Alt. */\nfunction isSingleKeyTool(e: KeyboardEvent, key: string): boolean {\n return !e.altKey && (key in QUICK_CREATE || key === \"a\" || key === \"l\");\n}\n\n/** Keyboard-created shapes stay this far inside the plot edge. */\nconst PLOT_INSET = 40;\n/**\n * Repeated keyboard creates step downwards so they do not stack on one spot; labels sit to the\n * right of nodes, so a vertical step keeps every name readable. At the plot bottom the next\n * column starts, leaving room for the labels.\n */\nconst STACK_STEP = 56;\nconst STACK_COLUMN_STEP = 160;\nconst STACK_CLEARANCE = { x: 48, y: 40 };\nconst STACK_ATTEMPTS = 40;\n\ninterface PlotBounds {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n/**\n * Keyboard binding: undo/redo, delete, copy/paste/duplicate, arrow-key nudge, Escape (deselect),\n * Cmd/Ctrl+A (select all), the single-key tools C (component), U (user), N (note), P (pipeline),\n * L (lasso) and A (connect from the selected node), all only while the canvas has the focus.\n * Deliberately a DOM listener (no diagram-js keyboard-service binding needed). While the draw tool\n * holds the points of a line, the single-key tools and paste do nothing, and the canvas takes them:\n * a paste attaches its copies to the pointer, where the next press belongs to the line. While a\n * point of a drawing is dragged, the arrow keys, paste, duplicate and the single-key tools do\n * nothing, and the canvas takes them; Escape ends that drag and Delete removes the drawing.\n */\nexport default class WardleyKeyboard {\n static $inject = [\n \"canvas\",\n \"commandStack\",\n \"selection\",\n \"modeling\",\n \"wardleyCopyPaste\",\n \"wardleyElementFactory\",\n \"create\",\n \"mouse\",\n \"lassoTool\",\n \"eventBus\",\n \"elementRegistry\",\n \"injector\",\n \"config.wardleyKeyboard\",\n ];\n\n private pointerOverCanvas = false;\n private readonly labelEditing: WardleyLabelEditing | null;\n private readonly grid: EvolutionGrid | null;\n private readonly freeRect: FreeRect | null;\n private readonly drawingHandles: WardleyDrawingHandles | null;\n private readonly drawTool: WardleyDrawTool | null;\n\n constructor(\n private readonly canvas: Canvas,\n commandStack: CommandStack,\n private readonly selection: Selection,\n private readonly modeling: Modeling,\n copyPaste: WardleyCopyPaste,\n private readonly factory: WardleyElementFactory,\n private readonly create: Create,\n private readonly mouse: Mouse,\n lassoTool: LassoTool,\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n injector: Injector,\n config: WardleyKeyboardConfig | undefined,\n ) {\n const container = canvas.getContainer();\n const undoRedoEnabled = config?.undoRedo !== false;\n const dragging = injector.get<Dragging | null>(\"dragging\", false);\n const connect = injector.get<Connect | null>(\"connect\", false);\n const rules = injector.get<Rules | null>(\"rules\", false);\n const popupMenu = injector.get<PopupMenu | null>(\"popupMenu\", false);\n this.drawTool = injector.get<WardleyDrawTool | null>(\"wardleyDrawTool\", false) ?? null;\n this.drawingHandles =\n injector.get<WardleyDrawingHandles | null>(\"wardleyDrawingHandles\", false) ?? null;\n this.labelEditing =\n injector.get<WardleyLabelEditing | null>(\"wardleyLabelEditing\", false) ?? null;\n this.grid = injector.get<EvolutionGrid | null>(\"evolutionGrid\", false) ?? null;\n this.freeRect = injector.get<FreeRect | null>(\"wardleyFreeRect\", false) ?? null;\n\n // getLastMoveEvent() never returns null (it fabricates an event at 0,0), so whether the\n // pointer really is over the canvas has to be tracked here.\n const onPointerMove = () => (this.pointerOverCanvas = true);\n const onPointerLeave = () => (this.pointerOverCanvas = false);\n container.addEventListener(\"mousemove\", onPointerMove);\n container.addEventListener(\"mouseleave\", onPointerLeave);\n\n // Escape is consumed by drags, the draw tool and popups, which react in the capture phase or\n // on keyup — their state is snapshotted before any of them runs.\n let escapeOwnedByOverlay = false;\n const onKeydownCapture = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\") return;\n escapeOwnedByOverlay =\n !!dragging?.context() ||\n !!this.drawTool?.isActive() ||\n this.pointDragged() ||\n !!popupMenu?.isOpen() ||\n !!container.querySelector(\".wardley-color-picker\");\n };\n\n const deleteSelection = (e: KeyboardEvent) => {\n const selected = selection.get() as Element[];\n if (!selected.length) return;\n e.preventDefault();\n modeling.removeElements(selected);\n };\n\n // The element clipboard lives in memory, so the browser cannot tell whether it or the system\n // clipboard is newer. After the page lost focus or saw a text copy, the system clipboard may\n // hold something newer (e.g. map text to import): let the browser's paste event reach the host\n // first and only paste the copied elements when nobody consumed it.\n let internalClipboardIsNewest = false;\n let deferredPaste: ReturnType<typeof setTimeout> | undefined;\n const markSystemClipboardNewer = () => (internalClipboardIsNewest = false);\n const pasteFromInternalClipboard = (e: KeyboardEvent) => {\n if (internalClipboardIsNewest) {\n if (copyPaste.paste()) e.preventDefault();\n return;\n }\n clearTimeout(deferredPaste);\n deferredPaste = setTimeout(() => {\n deferredPaste = undefined;\n copyPaste.paste();\n }, 0);\n };\n const onPaste = (e: ClipboardEvent) => {\n if (deferredPaste === undefined || !e.defaultPrevented) return;\n clearTimeout(deferredPaste);\n deferredPaste = undefined;\n };\n\n // A locked canvas (an invalid file in an IDE) keeps selection, copy and the lasso.\n const locked = () => isReadOnly(injector);\n const onModifierShortcut = (e: KeyboardEvent, key: string) => {\n if (locked() && ![\"a\", \"c\"].includes(key)) return;\n if (key === \"z\" || key === \"y\") {\n if (!undoRedoEnabled) return;\n e.preventDefault();\n if (key === \"z\" && !e.shiftKey) commandStack.undo();\n else commandStack.redo();\n } else if (key === \"a\") {\n e.preventDefault();\n selection.select(\n elementRegistry.filter((el) => isWardleyShape(el) || isWardleyConnection(el)),\n );\n } else if (key === \"c\") {\n if (copyPaste.copy()) {\n e.preventDefault();\n internalClipboardIsNewest = true;\n }\n } else if (key === \"v\") {\n if (this.pointDragged() || this.drawTool?.holdsLine()) e.preventDefault();\n else pasteFromInternalClipboard(e);\n } else if (key === \"d\") {\n e.preventDefault();\n if (!this.pointDragged() && copyPaste.duplicate()) internalClipboardIsNewest = true;\n } else if (key === \"delete\" || key === \"backspace\") {\n deleteSelection(e);\n }\n };\n\n const onPlainKey = (e: KeyboardEvent, key: string) => {\n if (locked() && key !== \"escape\" && key !== \"l\") return;\n // While the draw tool holds the points of a line or a point of a drawing is dragged, that\n // gesture owns the canvas keys as it owns the pointer: a tool started next to it would take\n // the next press or the release as well.\n if (this.takenByGesture(e, key)) return;\n const toolKey = isSingleKeyTool(e, key);\n if (key === \"escape\") {\n if (!escapeOwnedByOverlay && selection.get().length) selection.select(null);\n } else if (key === \"delete\" || key === \"backspace\") {\n deleteSelection(e);\n } else if (toolKey && key in QUICK_CREATE) {\n e.preventDefault();\n const { type, label } = QUICK_CREATE[key]!;\n this.quickCreate(type, label);\n } else if (toolKey && key === \"a\") {\n const source = this.singleSelectedShape();\n if (!source || !connect || !rules?.allowed(\"connection.start\", { source })) return;\n e.preventDefault();\n const center = { x: source.x + source.width / 2, y: source.y + source.height / 2 };\n connect.start(this.pointerEventOr(center), source as unknown as Element, center, true);\n } else if (toolKey && key === \"l\") {\n e.preventDefault();\n lassoTool.activateSelection(mouse.getLastMoveEvent(), true);\n } else if (key in ARROW_DELTAS) {\n const selected = selection.get() as Element[];\n if (!selected.length) return;\n e.preventDefault();\n if (this.pointDragged()) return;\n const step = e.shiftKey ? NUDGE_STEP_COARSE : NUDGE_STEP;\n const delta = ARROW_DELTAS[key]!;\n modeling.moveElements(selected, { x: delta.x * step, y: delta.y * step });\n }\n };\n\n // On the document, not the svg: a listener on the way up (a host's wrapper around the canvas)\n // runs first and can take a key (defaultPrevented) before the canvas acts on it.\n const onKeydown = (e: KeyboardEvent) => {\n if (!isCanvasKey(e, canvas)) return;\n const key = e.key.toLowerCase();\n if (e.ctrlKey || e.metaKey) onModifierShortcut(e, key);\n else onPlainKey(e, key);\n };\n\n window.addEventListener(\"keydown\", onKeydownCapture, true);\n document.addEventListener(\"keydown\", onKeydown);\n window.addEventListener(\"blur\", markSystemClipboardNewer);\n document.addEventListener(\"copy\", markSystemClipboardNewer);\n document.addEventListener(\"cut\", markSystemClipboardNewer);\n window.addEventListener(\"paste\", onPaste);\n eventBus.on(\"diagram.destroy\", () => {\n clearTimeout(deferredPaste);\n window.removeEventListener(\"keydown\", onKeydownCapture, true);\n document.removeEventListener(\"keydown\", onKeydown);\n window.removeEventListener(\"blur\", markSystemClipboardNewer);\n document.removeEventListener(\"copy\", markSystemClipboardNewer);\n document.removeEventListener(\"cut\", markSystemClipboardNewer);\n window.removeEventListener(\"paste\", onPaste);\n container.removeEventListener(\"mousemove\", onPointerMove);\n container.removeEventListener(\"mouseleave\", onPointerLeave);\n });\n }\n\n /**\n * With the pointer over the canvas the new node attaches to it (like palette create; placing it\n * opens the name editor). Without one — keyboard only — it lands in the centre of the free\n * rectangle (within the plot) and the name editor opens right away.\n */\n private quickCreate(type: WardleyShapeType, label: string): void {\n const shape = this.factory.createNew(type, label) as unknown as Shape;\n if (this.pointerOverCanvas) {\n this.create.start(this.mouse.getLastMoveEvent(), shape);\n return;\n }\n const bounds = this.insetPlotBounds();\n const created = this.modeling.createShape(\n shape,\n this.freeSpotNear(this.visiblePlotCenter(bounds), bounds),\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created);\n this.labelEditing?.activate(created as unknown as WardleyShape);\n }\n\n private insetPlotBounds(): PlotBounds | null {\n if (!this.grid) return null;\n const topLeft = this.grid.toCanvas({ visibility: 1, evolution: 0 });\n const bottomRight = this.grid.toCanvas({ visibility: 0, evolution: 1 });\n return {\n left: topLeft.x + PLOT_INSET,\n top: topLeft.y + PLOT_INSET,\n right: bottomRight.x - PLOT_INSET,\n bottom: bottomRight.y - PLOT_INSET,\n };\n }\n\n private visiblePlotCenter(bounds: PlotBounds | null): { x: number; y: number } {\n const viewbox = this.canvas.viewbox();\n const center = this.freeRect?.center() ?? {\n x: viewbox.x + viewbox.width / 2,\n y: viewbox.y + viewbox.height / 2,\n };\n if (!bounds) return center;\n return {\n x: clamp(center.x, bounds.left, bounds.right),\n y: clamp(center.y, bounds.top, bounds.bottom),\n };\n }\n\n private freeSpotNear(\n point: { x: number; y: number },\n bounds: PlotBounds | null,\n ): { x: number; y: number } {\n const occupied = (candidate: { x: number; y: number }) =>\n !!this.elementRegistry.find(\n (el) =>\n isWardleyShape(el) &&\n Math.abs(el.x + el.width / 2 - candidate.x) < STACK_CLEARANCE.x &&\n Math.abs(el.y + el.height / 2 - candidate.y) < STACK_CLEARANCE.y,\n );\n let candidate = point;\n for (let attempt = 0; attempt < STACK_ATTEMPTS && occupied(candidate); attempt++) {\n candidate = { x: candidate.x, y: candidate.y + STACK_STEP };\n if (bounds && candidate.y > bounds.bottom) {\n candidate = { x: candidate.x + STACK_COLUMN_STEP, y: point.y };\n if (candidate.x > bounds.right) return point;\n }\n }\n return candidate;\n }\n\n private singleSelectedShape(): WardleyShape | undefined {\n const selected = this.selection.get();\n return selected.length === 1 && isWardleyShape(selected[0]) ? selected[0] : undefined;\n }\n\n /**\n * A point drag owns Escape, and the keys that would act on its drawing or start a second gesture\n * (#375): a nudge or a duplicate is a command, which ends the drag, and a paste or a tool would\n * start a gesture that ends with the drag's release.\n */\n private pointDragged(): boolean {\n return !!this.drawingHandles?.isDraggingPoint();\n }\n\n /**\n * A line the draw tool holds and a point drag run on the canvas, which has the focus, so the\n * single-key tools pressed meanwhile are the canvas's and go no further, though they start\n * nothing (#404).\n */\n private takenByGesture(e: KeyboardEvent, key: string): boolean {\n if (!isSingleKeyTool(e, key)) return false;\n if (!this.pointDragged() && !this.drawTool?.holdsLine()) return false;\n e.preventDefault();\n return true;\n }\n\n /** The real pointer event, or a synthetic one at `canvasPoint` when the pointer is elsewhere. */\n private pointerEventOr(canvasPoint: { x: number; y: number }): MouseEvent {\n if (this.pointerOverCanvas) return this.mouse.getLastMoveEvent();\n const viewbox = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n const rect = this.canvas.getContainer().getBoundingClientRect();\n return new MouseEvent(\"mousemove\", {\n clientX: rect.left + (canvasPoint.x - viewbox.x) * scale,\n clientY: rect.top + (canvasPoint.y - viewbox.y) * scale,\n });\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return min > max ? (min + max) / 2 : Math.min(Math.max(value, min), max);\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyKeyboard from \"./WardleyKeyboard.js\";\n\n/** Undo/redo/delete and the single-key tools on the focused canvas. */\nexport const wardleyKeyboardModule: ModuleDeclaration = {\n __init__: [\"wardleyKeyboard\"],\n wardleyKeyboard: [\"type\", WardleyKeyboard],\n};\n\nexport { default as WardleyKeyboard } from \"./WardleyKeyboard.js\";\n","import type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Injector } from \"didi\";\n\ninterface ConnectionPreviewLike {\n drawPreview(context: object, canConnect: unknown, hints: object): void;\n cleanUp(context: object): void;\n}\n\ninterface LabelEditingLike {\n activate(element: object): void;\n}\n\ninterface SourceShape {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ninterface CreateEvent {\n x: number;\n y: number;\n context: {\n source?: SourceShape;\n shape?: { wardleyType?: unknown };\n elements?: readonly object[];\n canExecute?: { connect?: unknown } | false | null;\n /** Set by WardleyCopyPaste: pasted copies keep their names, no editor. */\n wardleyPaste?: boolean;\n };\n}\n\n/** Types that carry a visible name — placing one goes straight into naming it. */\nconst NAMED_TYPES: ReadonlySet<unknown> = new Set([\n \"component\",\n \"anchor\",\n \"submap\",\n \"pipeline\",\n \"accelerator\",\n \"note\",\n]);\n\n// diagram-js runs listeners in descending priority order; the default create.end handler (creation)\n// sits at 1000 -> with < 1000 we run AFTERWARDS, once the shape already exists.\nconst AFTER_CREATE = 500;\n\n/**\n * Create behavior for palette, keyboard and \"append component\" (`create.start`, the latter with\n * `context.source`):\n * 1. Append only: LIVE arrow preview from the source to the cursor (analogous to diagram-js\n * ConnectPreview, but in the create flow) — requires the `connectionPreview` service.\n * 2. After placing a single named element (component, user, submap, pipeline, accelerator, note)\n * the label editor opens with the placeholder selected, so typing names it right away.\n * Regions, drawings and pasted copies are left alone.\n */\nexport default class WardleyAppendBehavior {\n static $inject = [\"injector\", \"eventBus\"];\n\n constructor(injector: Injector, eventBus: EventBus) {\n const connectionPreview = injector.get(\n \"connectionPreview\",\n false,\n ) as ConnectionPreviewLike | null;\n const labelEditing = injector.get(\"wardleyLabelEditing\", false) as LabelEditingLike | null;\n\n // (1) arrow preview\n if (connectionPreview) {\n eventBus.on(\"create.move\", (event: CreateEvent) => {\n const { context } = event;\n const source = context.source;\n if (!source) return;\n const canConnect =\n context.canExecute && (context.canExecute as { connect?: unknown }).connect;\n connectionPreview.drawPreview(context, canConnect ?? false, {\n source,\n connectionStart: { x: source.x + source.width / 2, y: source.y + source.height / 2 },\n connectionEnd: { x: event.x, y: event.y },\n });\n });\n\n eventBus.on(\n [\"create.end\", \"create.cancel\", \"create.cleanup\"],\n (event: { context: object }) => {\n connectionPreview.cleanUp(event.context);\n },\n );\n }\n\n // (2) automatically open the label editor after placing a named element\n if (labelEditing) {\n // A host may destroy the modeler from the change listener of the drop (#380): the editor\n // then has no map left to open on.\n let destroyed = false;\n eventBus.on(\"diagram.destroy\", () => {\n destroyed = true;\n });\n eventBus.on(\"create.end\", AFTER_CREATE, (event: CreateEvent) => {\n const { context } = event;\n const shape = context.shape;\n if (!context.canExecute || !shape || context.wardleyPaste) return;\n if ((context.elements?.length ?? 1) !== 1 || !NAMED_TYPES.has(shape.wardleyType)) return;\n // Activate only after render/cleanup so the editor is positioned correctly.\n setTimeout(() => {\n if (!destroyed) labelEditing.activate(shape);\n }, 0);\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ConnectionPreviewModule from \"diagram-js/lib/features/connection-preview\";\nimport WardleyAppendBehavior from \"./WardleyAppendBehavior.js\";\n\n/**\n * \"Append component\": pulls in the `connectionPreview` service (thereby also enabling the connect\n * tool's arrow preview) and registers the append behavior (live arrow preview + automatically\n * opening the label editor after creation).\n */\nexport const wardleyAppendModule: ModuleDeclaration = {\n __depends__: [ConnectionPreviewModule],\n __init__: [\"wardleyAppendBehavior\"],\n wardleyAppendBehavior: [\"type\", WardleyAppendBehavior],\n};\n\nexport { default as WardleyAppendBehavior } from \"./WardleyAppendBehavior.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { NOTE_COLORS } from \"../draw/styles.js\";\nimport { isCanvasKey, isKeyAimedAt, isKeyOnHiddenTarget } from \"../a11y/index.js\";\n\n/** Must match `grid-template-columns` of `.wardley-color-picker` (arrow-key navigation). */\nconst GRID_COLUMNS = 3;\n\nconst GRID_STEPS: Record<string, number> = {\n ArrowLeft: -1,\n ArrowRight: 1,\n ArrowUp: -GRID_COLUMNS,\n ArrowDown: GRID_COLUMNS,\n};\n\n/**\n * Compact color picker (bpmn.io-style): a 3x3 grid of small color squares (no text), opened from a\n * note's context pad. Uses its own popover (instead of diagram-js PopupMenu) so the swatch grid can\n * be rendered exactly and without text. Sets the color via `wardleyModeling` (undo/redo). First\n * cell = \"no color\". Keyboard: focus starts on the active swatch, arrow keys move through the grid,\n * Enter/Space picks, Escape closes; focus then returns to the canvas.\n */\nexport default class WardleyColorPicker {\n static $inject = [\"canvas\", \"eventBus\", \"wardleyModeling\", \"injector\"];\n\n private popover: HTMLElement | undefined;\n\n private readonly onDocPointer = (e: MouseEvent): void => {\n if (this.popover && !this.popover.contains(e.target as Node)) this.close();\n };\n // A capture listener on the document: only an Escape aimed at the swatches or the canvas `<svg>`\n // is the picker's. The palette, the context pad, a label field and a host's overlay or menu sit\n // in the canvas container too, and Escape there belongs to that control.\n private readonly onKey = (e: KeyboardEvent): void => {\n if (e.key !== \"Escape\") return;\n if (!isKeyAimedAt(e, this.popover) && !isCanvasKey(e, this.canvas)) return;\n e.preventDefault();\n e.stopPropagation();\n this.close({ restoreFocus: true });\n };\n\n constructor(\n private readonly canvas: Canvas,\n eventBus: EventBus,\n private readonly modeling: WardleyModeling,\n private readonly injector: Injector,\n ) {\n // Close on pan/zoom, drag or re-import (otherwise the popover ends up misplaced), and with the\n // modeler, whose document listeners would otherwise outlive it.\n eventBus.on([\"canvas.viewbox.changing\", \"drag.init\", \"diagram.clear\", \"diagram.destroy\"], () =>\n this.close(),\n );\n }\n\n /** Opens the swatch grid for `shape` at the click position (viewport coordinates). */\n open(shape: WardleyShape, clientX: number, clientY: number): void {\n this.close();\n if (isReadOnly(this.injector)) return;\n const container = this.canvas.getContainer();\n const rect = container.getBoundingClientRect();\n\n const pop = document.createElement(\"div\");\n pop.className = \"wardley-color-picker\";\n pop.setAttribute(\"role\", \"dialog\");\n pop.setAttribute(\"aria-label\", \"Color\");\n\n const swatches: ReadonlyArray<{ value: string | undefined; title: string; cls: string }> = [\n { value: undefined, title: \"No color\", cls: \"wardley-cp-none\" },\n ...NOTE_COLORS.map((c) => ({ value: c.value as string, title: c.name, cls: \"\" })),\n ];\n const buttons: HTMLButtonElement[] = [];\n let activeButton: HTMLButtonElement | undefined;\n for (const s of swatches) {\n const btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.className = `wardley-cp-swatch ${s.cls}`.trim();\n btn.title = s.title;\n btn.setAttribute(\"aria-label\", s.title);\n if (s.value) btn.style.background = s.value;\n const isActive = (shape.color ?? undefined) === s.value;\n btn.setAttribute(\"aria-pressed\", String(isActive));\n if (isActive) {\n btn.classList.add(\"wardley-cp-active\");\n activeButton = btn;\n }\n btn.addEventListener(\"click\", (ev) => {\n if (isKeyOnHiddenTarget(ev)) return;\n ev.stopPropagation();\n this.modeling.setColor(shape, s.value);\n this.close({ restoreFocus: true });\n });\n buttons.push(btn);\n pop.append(btn);\n }\n pop.addEventListener(\"keydown\", (event) => this.onGridKeydown(event, buttons));\n\n container.appendChild(pop);\n\n // Keep it within the (overflow:hidden) container.\n const cw = container.clientWidth;\n const ch = container.clientHeight;\n const pw = pop.offsetWidth;\n const ph = pop.offsetHeight;\n const left = Math.max(4, Math.min(clientX - rect.left, cw - pw - 4));\n const top = Math.max(4, Math.min(clientY - rect.top, ch - ph - 4));\n pop.style.left = `${left}px`;\n pop.style.top = `${top}px`;\n\n this.popover = pop;\n (activeButton ?? buttons[0])?.focus({ preventScroll: true });\n // Attach listeners with a delay so the opening click does not immediately close the popover,\n // and not at all once it closed in the meantime.\n setTimeout(() => {\n if (this.popover !== pop) return;\n document.addEventListener(\"click\", this.onDocPointer, true);\n document.addEventListener(\"keydown\", this.onKey, true);\n }, 0);\n }\n\n isOpen(): boolean {\n return !!this.popover;\n }\n\n close(options: { restoreFocus?: boolean } = {}): void {\n if (!this.popover) return;\n const hadFocus = this.popover.contains(document.activeElement);\n this.popover.remove();\n this.popover = undefined;\n document.removeEventListener(\"click\", this.onDocPointer, true);\n document.removeEventListener(\"keydown\", this.onKey, true);\n if (options.restoreFocus || hadFocus) this.canvas.focus();\n }\n\n private onGridKeydown(event: KeyboardEvent, buttons: HTMLButtonElement[]): void {\n if (isKeyOnHiddenTarget(event)) return;\n const step = GRID_STEPS[event.key];\n const index = buttons.indexOf(document.activeElement as HTMLButtonElement);\n let next: number | undefined;\n if (step !== undefined) next = index < 0 ? 0 : index + step;\n else if (event.key === \"Home\") next = 0;\n else if (event.key === \"End\") next = buttons.length - 1;\n else if (event.key === \"Tab\") {\n // Keep focus inside the dialog while it is open.\n next = index + (event.shiftKey ? -1 : 1);\n next = (next + buttons.length) % buttons.length;\n }\n if (next === undefined) return;\n // The grid's own keys: no listener further up acts on them too.\n event.preventDefault();\n event.stopPropagation();\n buttons[Math.min(buttons.length - 1, Math.max(0, next))]?.focus();\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyColorPicker from \"./WardleyColorPicker.js\";\n\n/** Note color picker (3x3 swatch popover). */\nexport const wardleyColorPickerModule: ModuleDeclaration = {\n __init__: [\"wardleyColorPicker\"],\n wardleyColorPicker: [\"type\", WardleyColorPicker],\n};\n\nexport { default as WardleyColorPicker } from \"./WardleyColorPicker.js\";\n","import OrderingProvider from \"diagram-js/lib/features/ordering/OrderingProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ElementLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport { isWardleyConnection, isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\n/** Frame types sit at the very back (concept doc: frames -> connections -> nodes). */\nfunction isFrame(el: unknown): boolean {\n return (\n isWardleyShape(el) &&\n ((el as WardleyShape).wardleyType === \"attitude\" ||\n (el as WardleyShape).wardleyType === \"pipeline\")\n );\n}\n\n/**\n * Keeps the z-order stable for INTERACTIVELY created/moved elements, matching the import order:\n * frames (attitude/pipeline) at the back, then dependencies, then flows, nodes on top. Without this,\n * connections drawn in the editor would land above the nodes (unlike imported ones).\n */\nexport default class WardleyOrderingProvider extends OrderingProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override getOrdering(\n element: ElementLike,\n newParent: ShapeLike,\n ): { parent: ShapeLike; index?: number } {\n const siblings = (newParent.children ?? []) as ElementLike[];\n if (isWardleyConnection(element)) {\n // Behind the nodes. A flow goes on top of all connections; a dependency stays below the\n // flows, so it cannot strike through a flow value (matches the import order).\n const isFlow = element.wardleyType === \"flow\";\n const index = siblings.filter(\n (c) =>\n c !== element &&\n (isFrame(c) || (isWardleyConnection(c) && (isFlow || c.wardleyType !== \"flow\"))),\n ).length;\n return { parent: newParent, index };\n }\n if (isFrame(element)) {\n // All the way to the back (after the other frames).\n const index = siblings.filter((c) => c !== element && isFrame(c)).length;\n return { parent: newParent, index };\n }\n // Nodes: on top (append).\n return { parent: newParent };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport WardleyOrderingProvider from \"./WardleyOrderingProvider.js\";\n\n/** Z-order for interactive edits: frames -> connections -> nodes (like the import). */\nexport const wardleyOrderingModule: ModuleDeclaration = {\n __init__: [\"wardleyOrderingProvider\"],\n wardleyOrderingProvider: [\"type\", WardleyOrderingProvider],\n};\n\nexport { default as WardleyOrderingProvider } from \"./WardleyOrderingProvider.js\";\n","import type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport { COLORS } from \"../draw/styles.js\";\nimport type WardleyElementFactory from \"../model/WardleyElementFactory.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type { WardleyShape } from \"../model/di-types.js\";\nimport { focusCanvasWithoutRing, isCanvasKey, isKeyAimedAt } from \"../a11y/index.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\n/** Clicking this close (px, canvas coords) to the FIRST/LAST point finishes/closes. */\nconst CLOSE_RADIUS = 12;\n\nconst DRAW_TOOL_ENTRY = '.djs-palette .entry[data-action=\"draw-tool\"]';\n/** The tool's name on the tool manager's channel, which the palettes read its pressed state from. */\nconst DRAW_TOOL = \"draw\";\n\n/**\n * Excalidraw-style polyline tool: activate, click point by point (rubber-band preview).\n * Finishing (like Excalidraw): click the LAST point again, double-click, Enter or Escape\n * commits the open line, and so does Space on the tool's palette entry; clicking the FIRST point\n * closes the shape. Escape with fewer than two points cancels. The result is ONE undoable\n * `drawing` shape that moves as a whole. An import cancels a line in progress without committing\n * it and leaves a tool without points armed. Arming another tool (the lasso) puts it down and saves\n * a held line as Escape does, so one tool is armed at a time.\n */\nexport default class WardleyDrawTool {\n static $inject = [\n \"canvas\",\n \"eventBus\",\n \"modeling\",\n \"selection\",\n \"wardleyElementFactory\",\n \"evolutionGrid\",\n \"injector\",\n ];\n\n private active = false;\n private points: Point[] = [];\n private cursor: Point | null = null;\n private layer: SVGElement | null = null;\n\n constructor(\n private readonly canvas: Canvas,\n private readonly eventBus: EventBus,\n private readonly modeling: Modeling,\n private readonly selection: Selection,\n private readonly factory: WardleyElementFactory,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n ) {\n eventBus.on(\"diagram.destroy\", () => this.cancel());\n // The placed points are input the user has not committed yet, and the import replaces the map\n // they were drawn on: the import ends the line as an accepted import ends a running gesture,\n // with no change event from it (L1). A tool that only waits for its first press holds nothing\n // and stays armed, as the armed lasso does.\n eventBus.on([\"import.render.start\", \"diagram.clear\"], () => {\n if (this.holdsLine()) this.cancel();\n });\n // The tool arms itself outside diagram-js's tool manager, which puts down only the tools it\n // manages: without this, the lasso armed from its entry or its key would leave this tool armed\n // under it, shown released, and the next press on the canvas would place a point.\n eventBus.on(\"tool-manager.update\", (event: { tool?: string | null }) => {\n if (this.active && event.tool && event.tool !== DRAW_TOOL) this.giveWay();\n });\n }\n\n isActive(): boolean {\n return this.active;\n }\n\n /** True while the tool holds the points of a line it has not finished yet. */\n holdsLine(): boolean {\n return this.active && this.points.length > 0;\n }\n\n toggle(): void {\n if (this.active) this.cancel();\n else this.activate();\n }\n\n /**\n * The OUTER viewer container — getContainer() returns the inner .djs-container, but the\n * mode class must sit on .wardley-container for the crosshair/empty-state CSS to match.\n */\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n\n activate(): void {\n if (this.active || isReadOnly(this.injector)) return;\n this.active = true;\n this.points = [];\n this.cursor = null;\n const container = this.canvas.getContainer();\n this.outerContainer().classList.add(\"wardley-draw-mode\");\n // Capture phase: while drawing, clicks must NOT select/move elements underneath.\n container.addEventListener(\"mousedown\", this.onMouseDown, true);\n container.addEventListener(\"dblclick\", this.onDblClick, true);\n container.addEventListener(\"mousemove\", this.onMouseMove, true);\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n // Light up the palette entry (same channel the tool manager uses).\n this.eventBus.fire(\"tool-manager.update\", { tool: DRAW_TOOL });\n }\n\n /** Finishes the current polyline (>= 2 points) and deactivates the tool. */\n finish(): void {\n this.finishLine({ reportRelease: true });\n }\n\n /**\n * Another tool took the press: the line is saved as Escape saves it, and the release is not\n * reported, which would show that tool released while it is armed.\n */\n private giveWay(): void {\n this.finishLine({ reportRelease: false });\n }\n\n private finishLine({ reportRelease }: { reportRelease: boolean }): void {\n const pts = [...this.points];\n this.deactivate({ reportRelease });\n if (pts.length < 2) return;\n this.create(this.factory.drawingFromCanvasPoints(pts));\n }\n\n /** Closes the shape (polygon) using the collected points. */\n private finishClosed(): void {\n const pts = [...this.points];\n this.deactivate();\n if (pts.length < 3) return;\n this.create(this.factory.drawingFromCanvasPoints(pts, { closed: true }));\n }\n\n /**\n * Created at its exact bounds: a centre position would be rounded by diagram-js and could push\n * points that sit on the plot edge half a pixel outside.\n */\n private create(shape: WardleyShape): void {\n const { x, y, width, height } = shape;\n const bounds = { x, y, width, height };\n const created = this.modeling.createShape(\n shape as unknown as Shape,\n bounds,\n this.canvas.getRootElement() as Shape,\n );\n this.selection.select(created as unknown as Element);\n }\n\n cancel(): void {\n this.deactivate();\n }\n\n private deactivate({ reportRelease } = { reportRelease: true }): void {\n if (!this.active) return;\n this.active = false;\n const container = this.canvas.getContainer();\n this.outerContainer().classList.remove(\"wardley-draw-mode\");\n container.removeEventListener(\"mousedown\", this.onMouseDown, true);\n container.removeEventListener(\"dblclick\", this.onDblClick, true);\n container.removeEventListener(\"mousemove\", this.onMouseMove, true);\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.points = [];\n this.cursor = null;\n this.clearPreview();\n if (reportRelease) this.eventBus.fire(\"tool-manager.update\", { tool: null });\n }\n\n /**\n * Clamped into the plot: drawings are saved as normalized [0,1] points, so the preview must not\n * show anything the saved shape cannot hold.\n */\n private toCanvasPoint(e: MouseEvent): Point {\n const rect = this.canvas.getContainer().getBoundingClientRect();\n const vb = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n return this.grid.toCanvas(\n this.grid.fromCanvas({\n x: (e.clientX - rect.left) / scale + vb.x,\n y: (e.clientY - rect.top) / scale + vb.y,\n }),\n );\n }\n\n /** Palette/context-pad/menus live INSIDE the container — let their clicks through. */\n private isChromeTarget(e: MouseEvent): boolean {\n const target = e.target as HTMLElement | null;\n return !!target?.closest(\".djs-palette, .djs-context-pad, .wardley-color-picker\");\n }\n\n private readonly onMouseDown = (e: MouseEvent): void => {\n if (e.button !== 0 || this.isChromeTarget(e)) return;\n e.preventDefault();\n e.stopPropagation();\n // The prevented default also keeps the browser from focusing the canvas, whose Enter and\n // Escape end the drawing.\n focusCanvasWithoutRing(this.canvas);\n const p = this.toCanvasPoint(e);\n const first = this.points[0];\n if (first && this.points.length >= 3 && distance(p, first) <= CLOSE_RADIUS) {\n this.finishClosed();\n return;\n }\n // Clicking the LAST point again finishes the open line (Excalidraw behavior) — this is\n // the discoverable way out; double-click/Enter/Escape work as well.\n const last = this.points[this.points.length - 1];\n if (last && distance(p, last) <= CLOSE_RADIUS) {\n if (this.points.length >= 2) this.finish();\n return;\n }\n this.points.push(p);\n this.renderPreview();\n };\n\n private readonly onDblClick = (e: MouseEvent): void => {\n if (this.isChromeTarget(e)) return;\n e.preventDefault();\n e.stopPropagation();\n this.finish();\n };\n\n private readonly onMouseMove = (e: MouseEvent): void => {\n if (!this.points.length) return;\n this.cursor = this.toCanvasPoint(e);\n this.renderPreview();\n };\n\n /**\n * Enter and Escape end the drawing only when aimed at the canvas `<svg>`, or at the palette entry\n * that starts this tool, where a tool started with Enter leaves the focus (guide §5.5). Every\n * other target keeps them, inside the container too: a host's fields, buttons, menus and dialogs,\n * its zoom panel, a focusable element in an overlay next to the canvas, `<body>` and a canvas the\n * host made inert or hid. A capture listener on the document would otherwise take them from all\n * of these.\n */\n private ownsKey(e: KeyboardEvent): boolean {\n return isCanvasKey(e, this.canvas) || this.targetsOwnPaletteEntry(e);\n }\n\n private targetsOwnPaletteEntry(e: KeyboardEvent): boolean {\n const target = e.target;\n if (!(target instanceof globalThis.Element)) return false;\n // Scoped to this canvas's container: another modeler on the page has its own draw entry.\n const entry = target.closest(DRAW_TOOL_ENTRY);\n return !!entry && this.canvas.getContainer().contains(entry) && isKeyAimedAt(e, entry);\n }\n\n /**\n * Enter and Space act alike on a palette entry (guide §5.5), and Space on this tool's entry would\n * otherwise toggle the tool off and drop the line it holds, where Enter saves it. A Space with\n * Alt, Ctrl or Meta activates no entry and stays the page's here too.\n */\n private savesWithSpace(e: KeyboardEvent): boolean {\n return (\n e.key === \" \" &&\n !e.altKey &&\n !e.ctrlKey &&\n !e.metaKey &&\n this.holdsLine() &&\n this.targetsOwnPaletteEntry(e)\n );\n }\n\n private readonly onKeyDown = (e: KeyboardEvent): void => {\n if (!this.ownsKey(e)) return;\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n // Excalidraw semantics: Escape COMMITS what is there (undo removes it); it only\n // cancels while no line exists yet.\n if (this.points.length >= 2) this.finish();\n else this.cancel();\n } else if (e.key === \"Enter\" || this.savesWithSpace(e)) {\n e.preventDefault();\n e.stopPropagation();\n this.finish();\n }\n };\n\n private renderPreview(): void {\n this.clearPreview();\n if (!this.points.length) return;\n const layer = this.canvas.getLayer(\"wardley-draw-preview\", 1000);\n const group = svgCreate(\"g\");\n const pts = this.cursor ? [...this.points, this.cursor] : this.points;\n svgAppend(\n group,\n svgAttr(svgCreate(\"polyline\"), {\n points: pts.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: COLORS.ink,\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"stroke-dasharray\": \"5 4\",\n }),\n );\n // First point = \"close the shape here\", last point = \"finish the line here\".\n const first = this.points[0]!;\n svgAppend(\n group,\n svgAttr(svgCreate(\"circle\"), {\n cx: first.x,\n cy: first.y,\n r: this.points.length >= 3 ? 5 : 3,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n }),\n );\n if (this.points.length >= 2) {\n const last = this.points[this.points.length - 1]!;\n svgAppend(\n group,\n svgAttr(svgCreate(\"circle\"), {\n cx: last.x,\n cy: last.y,\n r: 5,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n }),\n );\n }\n svgAppend(layer, group);\n this.layer = group;\n }\n\n private clearPreview(): void {\n if (this.layer) {\n svgRemove(this.layer);\n this.layer = null;\n }\n }\n}\n\nfunction distance(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n","import type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport {\n append as svgAppend,\n attr as svgAttr,\n create as svgCreate,\n remove as svgRemove,\n} from \"tiny-svg\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { COLORS } from \"../draw/styles.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { focusCanvasWithoutRing, isCanvasKey } from \"../a11y/index.js\";\nimport { COMMAND_START_EVENTS, PUT_BACK_PRIORITY } from \"../live-preview/index.js\";\nimport type { WardleyInteraction } from \"../interaction/index.js\";\n\ninterface Point {\n x: number;\n y: number;\n}\n\ninterface PointDrag {\n shape: WardleyShape;\n unbind: () => void;\n}\n\n/**\n * Vertex handles for drawings: when exactly one drawing is selected, every point gets a small\n * draggable handle. Dragging shows a live preview; releasing commits the new geometry (points +\n * recomputed bbox) as ONE undoable command, and Escape ends the drag without one.\n */\nexport default class WardleyDrawingHandles {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"wardleyModeling\",\n \"evolutionGrid\",\n \"injector\",\n \"wardleyInteraction\",\n ];\n\n private shape: WardleyShape | null = null;\n private group: SVGElement | null = null;\n private dragPreview: SVGElement | null = null;\n private pointDrag: PointDrag | null = null;\n private unwatchRelease: (() => void) | null = null;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly modeling: WardleyModeling,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n private readonly interaction: WardleyInteraction,\n ) {\n eventBus.on(\"selection.changed\", (event: { newSelection?: unknown[] }) => {\n const sel = event.newSelection ?? [];\n const only = sel.length === 1 ? sel[0] : null;\n this.attach(\n isWardleyShape(only) && only.wardleyType === \"drawing\" ? (only as WardleyShape) : null,\n );\n });\n // Keep the handles glued to the shape while it is moved/changed.\n eventBus.on(\"element.changed\", (event: { element?: unknown }) => {\n if (this.shape && event.element === this.shape) this.render();\n });\n // An import, a delete or an undo removes the drawing mid-drag: the release must not commit\n // onto the removed shape.\n eventBus.on(\"shape.remove\", (event: { element?: unknown }) => {\n if (this.pointDrag?.shape === event.element) this.endPointDrag();\n });\n // The release writes back every point as it was when the handle was pressed, which would undo\n // a command in between (an undo pressed mid-drag, or a host's edit) and cost its redo step: the\n // drag ends first, without a commit. The release ends the drag before its own command. The\n // keys that would nudge or duplicate the drawing do nothing while it runs (`WardleyKeyboard`).\n // The button is still down, as after Escape; the watch comes first, so that a host that\n // destroys the map from the interaction listener the end calls drops it with the map (#346).\n eventBus.on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => {\n if (!this.pointDrag) return;\n this.swallowClickOfRelease();\n this.endPointDrag();\n });\n eventBus.on([\"diagram.clear\", \"diagram.destroy\"], () => {\n this.endPointDrag();\n this.attach(null);\n });\n eventBus.on(\"diagram.destroy\", () => this.stopWatchingRelease());\n }\n\n private attach(shape: WardleyShape | null): void {\n this.shape = shape;\n this.render();\n }\n\n private absolutePoints(): Point[] {\n const s = this.shape!;\n return (s.drawingPoints ?? []).map((p) => ({ x: s.x + p.x, y: s.y + p.y }));\n }\n\n private render(): void {\n this.clear();\n if (!this.shape) return;\n const layer = this.canvas.getLayer(\"wardley-drawing-handles\", 1100);\n const group = svgCreate(\"g\");\n this.absolutePoints().forEach((p, index) => {\n const handle = svgAttr(svgCreate(\"circle\"), {\n cx: p.x,\n cy: p.y,\n r: 5,\n fill: COLORS.paper,\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n class: \"wardley-drawing-handle\",\n });\n handle.addEventListener(\"mousedown\", (e) => this.startDrag(e as MouseEvent, index));\n svgAppend(group, handle);\n });\n svgAppend(layer, group);\n this.group = group;\n }\n\n private startDrag(e: MouseEvent, index: number): void {\n if (e.button !== 0 || !this.shape || isReadOnly(this.injector)) return;\n e.preventDefault();\n e.stopPropagation();\n // The prevented default keeps the browser from focusing the canvas, whose keys act only while\n // it has the focus.\n focusCanvasWithoutRing(this.canvas);\n this.endPointDrag();\n const shape = this.shape;\n const points = this.absolutePoints();\n const drag: PointDrag = { shape, unbind: () => undefined };\n\n const onMove = (ev: MouseEvent): void => {\n this.interaction.begin(drag);\n points[index] = this.toCanvasPoint(ev);\n this.renderDragPreview(points, !!shape.closed);\n };\n const onUp = (ev: MouseEvent): void => {\n points[index] = this.toCanvasPoint(ev);\n this.interaction.drop(drag, () => {\n this.stopPointDrag();\n this.commit(shape, points);\n });\n };\n // Escape ends the drag as it ends a diagram-js drag, and the drawing stays selected. Only an\n // Escape aimed at the canvas, which the press focused: a host's field, menu or dialog keeps its\n // own.\n const onKey = (ev: KeyboardEvent): void => {\n if (ev.key !== \"Escape\" || !isCanvasKey(ev, this.canvas)) return;\n ev.preventDefault();\n ev.stopPropagation();\n // The watch comes first: a host that destroys the modeler from the interaction listener the\n // end calls has it removed with the map, not left on the document without a canvas (#346).\n this.swallowClickOfRelease();\n this.endPointDrag();\n };\n document.addEventListener(\"mousemove\", onMove, true);\n document.addEventListener(\"mouseup\", onUp, true);\n document.addEventListener(\"keydown\", onKey, true);\n drag.unbind = () => {\n document.removeEventListener(\"mousemove\", onMove, true);\n document.removeEventListener(\"mouseup\", onUp, true);\n document.removeEventListener(\"keydown\", onKey, true);\n };\n this.pointDrag = drag;\n }\n\n /** True from the press on a handle until the drag's release or its end. */\n isDraggingPoint(): boolean {\n return this.pointDrag !== null;\n }\n\n /**\n * Ends a running point drag without committing it. The point drag is this renderer's own gesture,\n * outside diagram-js dragging, so the import's drag cancel does not reach it: the removal of its\n * drawing ends it, Escape does, and so does any command before the release.\n */\n private endPointDrag(): void {\n const drag = this.stopPointDrag();\n if (drag) this.interaction.end(drag);\n }\n\n /**\n * After Escape or a command the button is still down on a handle that stays drawn, so the\n * browser sends the release's click to the canvas, the element under both the press and the\n * release, and a click there clears the selection. A commit redraws the handles, and then no\n * click comes.\n */\n private swallowClickOfRelease(): void {\n this.stopWatchingRelease();\n const container = this.canvas.getContainer();\n const swallow = (event: MouseEvent): void => event.stopPropagation();\n const onRelease = (): void => {\n this.stopWatchingRelease();\n container.addEventListener(\"click\", swallow, { capture: true, once: true });\n setTimeout(() => container.removeEventListener(\"click\", swallow, true), 0);\n };\n // A press before a release: the page did not see the release, and the press's click is a real\n // one.\n const onPress = (): void => this.stopWatchingRelease();\n document.addEventListener(\"mouseup\", onRelease, true);\n document.addEventListener(\"mousedown\", onPress, true);\n this.unwatchRelease = () => {\n document.removeEventListener(\"mouseup\", onRelease, true);\n document.removeEventListener(\"mousedown\", onPress, true);\n };\n }\n\n private stopWatchingRelease(): void {\n this.unwatchRelease?.();\n this.unwatchRelease = null;\n }\n\n private stopPointDrag(): PointDrag | null {\n const drag = this.pointDrag;\n if (!drag) return null;\n this.pointDrag = null;\n drag.unbind();\n this.clearDragPreview();\n return drag;\n }\n\n /** New bbox + relative points + normalized anchor — ONE undoable updateProperties command. */\n private commit(shape: WardleyShape, points: Point[]): void {\n const xs = points.map((p) => p.x);\n const ys = points.map((p) => p.y);\n const x = Math.min(...xs);\n const y = Math.min(...ys);\n const firstNorm = this.grid.fromCanvas(points[0]!);\n this.modeling.updateProperties(shape, {\n x,\n y,\n width: Math.max(Math.max(...xs) - x, 4),\n height: Math.max(Math.max(...ys) - y, 4),\n drawingPoints: points.map((p) => ({ x: p.x - x, y: p.y - y })),\n evolution: firstNorm.evolution,\n visibility: firstNorm.visibility,\n });\n this.render();\n }\n\n private renderDragPreview(points: Point[], closed: boolean): void {\n this.clearDragPreview();\n const layer = this.canvas.getLayer(\"wardley-drawing-handles\", 1100);\n const preview = svgAttr(svgCreate(closed ? \"polygon\" : \"polyline\"), {\n points: points.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: COLORS.ink,\n \"stroke-width\": 1.5,\n \"stroke-dasharray\": \"5 4\",\n \"pointer-events\": \"none\",\n });\n svgAppend(layer, preview);\n this.dragPreview = preview;\n }\n\n private clearDragPreview(): void {\n if (this.dragPreview) {\n svgRemove(this.dragPreview);\n this.dragPreview = null;\n }\n }\n\n private clear(): void {\n this.clearDragPreview();\n if (this.group) {\n svgRemove(this.group);\n this.group = null;\n }\n }\n\n /** Clamped into the plot, like the draw tool: what the preview shows is what gets saved. */\n private toCanvasPoint(e: MouseEvent): Point {\n const rect = this.canvas.getContainer().getBoundingClientRect();\n const vb = this.canvas.viewbox();\n const scale = this.canvas.zoom();\n return this.grid.toCanvas(\n this.grid.fromCanvas({\n x: (e.clientX - rect.left) / scale + vb.x,\n y: (e.clientY - rect.top) / scale + vb.y,\n }),\n );\n }\n}\n","import { append as svgAppend, attr as svgAttr, create as svgCreate } from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type InteractionEvents from \"diagram-js/lib/features/interaction-events/InteractionEvents\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\n\nfunction isDrawing(el: unknown): el is WardleyShape {\n return isWardleyShape(el) && el.wardleyType === \"drawing\";\n}\n\n/**\n * Drawings get a hit zone along their STROKE only (generous 15px band, like the default\n * stroke hit) instead of the default full-bbox hit — a shape drawn AROUND elements must not\n * swallow the clicks for everything inside it. The interior stays click-through; the drawing\n * itself is selected/moved by grabbing its line.\n */\nexport default class WardleyDrawingHitProvider {\n static $inject = [\"eventBus\", \"interactionEvents\"];\n\n constructor(eventBus: EventBus, interactionEvents: InteractionEvents) {\n // The diagram-js default (box hit) listens on LOW_PRIORITY — returning false here\n // suppresses it (same pattern bpmn-js uses for its custom hits).\n eventBus.on(\"interactionEvents.createHit\", (event: { element?: unknown; gfx?: SVGElement }) => {\n if (!isDrawing(event.element) || !event.gfx) return;\n createStrokeHit(event.element, event.gfx);\n return false;\n });\n eventBus.on(\"interactionEvents.updateHit\", (event: { element?: unknown; gfx?: SVGElement }) => {\n if (!isDrawing(event.element) || !event.gfx) return;\n interactionEvents.removeHits(event.gfx);\n createStrokeHit(event.element, event.gfx);\n return false;\n });\n }\n}\n\nfunction createStrokeHit(shape: WardleyShape, gfx: SVGElement): void {\n const points = shape.drawingPoints ?? [];\n const hit = svgCreate(shape.closed ? \"polygon\" : \"polyline\");\n svgAttr(hit, {\n points: points.map((p) => `${p.x},${p.y}`).join(\" \"),\n class: \"djs-hit djs-hit-stroke\",\n fill: \"none\",\n stroke: \"white\",\n \"stroke-width\": 15,\n // diagram-js makes hits invisible via this INLINE attribute (its \"no-border\" trait),\n // not via CSS — without it the 15px white band is visible.\n \"stroke-opacity\": 0,\n });\n svgAppend(gfx, hit);\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport { wardleyInteractionModule } from \"../interaction/index.js\";\nimport WardleyDrawTool from \"./WardleyDrawTool.js\";\nimport WardleyDrawingHandles from \"./WardleyDrawingHandles.js\";\nimport WardleyDrawingHitProvider from \"./WardleyDrawingHitProvider.js\";\n\nexport const wardleyDrawToolModule: ModuleDeclaration = {\n __depends__: [wardleyInteractionModule],\n __init__: [\"wardleyDrawTool\", \"wardleyDrawingHandles\", \"wardleyDrawingHitProvider\"],\n wardleyDrawTool: [\"type\", WardleyDrawTool],\n wardleyDrawingHandles: [\"type\", WardleyDrawingHandles],\n wardleyDrawingHitProvider: [\"type\", WardleyDrawingHitProvider],\n};\n\nexport { default as WardleyDrawTool } from \"./WardleyDrawTool.js\";\nexport { default as WardleyDrawingHandles } from \"./WardleyDrawingHandles.js\";\nexport { default as WardleyDrawingHitProvider } from \"./WardleyDrawingHitProvider.js\";\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type { Injector } from \"didi\";\nimport { isReadOnly } from \"../read-only/index.js\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { LabelOffset, MapElement } from \"@miragon/wardley-schema-model\";\nimport type EvolutionGrid from \"../evolution-grid/EvolutionGrid.js\";\nimport type WardleyModeling from \"../modeling/WardleyModeling.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport { focusCanvasWithoutRing, isCanvasKey } from \"../a11y/index.js\";\nimport type { WardleyInteraction } from \"../interaction/index.js\";\nimport {\n COMMAND_START_EVENTS,\n PUT_BACK_PRIORITY,\n type LivePreview,\n} from \"../live-preview/index.js\";\nimport {\n LABEL_HANDLE_CLASS,\n LABEL_ROLE_ATTRIBUTE,\n componentLabelPlacement,\n componentLabelSlot,\n movementDeltaX,\n movementLabelPlacement,\n movementLabelSlot,\n normalizeLabelOffset,\n type LabelPlacement,\n} from \"../draw/index.js\";\n\n/** Which offset a label writes: the node's own `label [dx, dy]` or its evolve line's. */\nexport type LabelRole = \"name\" | \"movement\";\n\n/** Screen px the pointer must travel before a press on a label becomes a drag. */\nconst DRAG_THRESHOLD = 3;\n/** A label dropped this close to its default slot snaps back and clears the offset. */\nconst SNAP_HOME_DISTANCE = 4;\nconst ARMED_CLASS = \"wardley-labels-draggable\";\nconst DRAGGING_CLASS = \"wardley-label-dragging\";\n\ninterface LabelDrag {\n shape: WardleyShape;\n role: LabelRole;\n startClient: { x: number; y: number };\n startOffset: LabelOffset;\n homeOffset: LabelOffset;\n zoom: number;\n latest?: LabelOffset;\n dragging: boolean;\n}\n\n/**\n * OWM-style draggable labels: drag a component/anchor name or an evolve target name to store an\n * OWM `label [dx, dy]` offset (integers, clamped to ±200px) as ONE undoable command; the export holds\n * back the preview until then (`LivePreview`). A press without movement selects the owner;\n * double-click still edits the name.\n *\n * Reset paths: Alt+double-click on a label, dropping it back onto its default slot, or\n * `resetLabelOffset(shape, role)`.\n */\nexport default class WardleyLabelDragging {\n static $inject = [\n \"eventBus\",\n \"canvas\",\n \"elementRegistry\",\n \"wardleyModeling\",\n \"selection\",\n \"evolutionGrid\",\n \"injector\",\n \"wardleyInteraction\",\n \"wardleyLivePreview\",\n ];\n\n private active: LabelDrag | null = null;\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n private readonly modeling: WardleyModeling,\n private readonly selection: Selection,\n private readonly grid: EvolutionGrid,\n private readonly injector: Injector,\n private readonly interaction: WardleyInteraction,\n private readonly livePreview: LivePreview,\n ) {\n const container = canvas.getContainer();\n this.outerContainer().classList.add(ARMED_CLASS);\n // Capture phase: diagram-js must neither start a move/lasso/pan nor open the label editor.\n container.addEventListener(\"mousedown\", this.onMouseDown, true);\n container.addEventListener(\"dblclick\", this.onDoubleClick, true);\n // Deleting the owner mid-drag (Delete/Backspace, an external import) ends the gesture, or the\n // release would put an invisible offset change on the undo stack.\n eventBus.on(\"shape.remove\", ({ element }: { element: unknown }) => {\n if (this.active?.shape === element) this.cancel();\n });\n // The release puts back the offset the drag started from, which would undo a command in between\n // (an undo pressed mid-drag) and leave the history out of step with the document: a drag that\n // previews ends first, without a commit. The release puts back before its command.\n eventBus.on(COMMAND_START_EVENTS, PUT_BACK_PRIORITY, () => {\n if (this.active && livePreview.previewsShape(this.active.shape)) this.cancel();\n });\n eventBus.on(\"diagram.destroy\", () => {\n this.cancel();\n container.removeEventListener(\"mousedown\", this.onMouseDown, true);\n container.removeEventListener(\"dblclick\", this.onDoubleClick, true);\n });\n }\n\n /** Puts a label back into its default slot (undoable). */\n resetLabelOffset(shape: WardleyShape, role: LabelRole = \"name\"): void {\n if (role === \"movement\") {\n if (shape.movement?.labelOffset) this.commitMovementOffset(shape, undefined);\n return;\n }\n if (shape.labelOffset) this.commitNameOffset(shape, undefined);\n }\n\n private readonly onMouseDown = (event: MouseEvent): void => {\n if (event.button !== 0 || this.outerContainer().classList.contains(\"wardley-draw-mode\")) return;\n if (isReadOnly(this.injector)) return;\n const target = this.labelTarget(event);\n if (!target) return;\n event.stopPropagation();\n event.preventDefault();\n // A drag whose release never reached the document (the window lost focus mid-drag) would keep\n // its preview, and the export the offset it started from, after the next drag replaces it.\n this.cancel();\n // preventDefault keeps focus where it is; commit an open inline edit like any other click would,\n // and take focus to the canvas so Delete/Undo act on the map, not on a focused host input.\n const focused = document.activeElement;\n if (focused instanceof HTMLElement && this.outerContainer().contains(focused)) focused.blur();\n focusCanvasWithoutRing(this.canvas);\n\n const { shape, role, handle } = target;\n const startOffset = this.renderedOffset(shape, role, handle);\n this.active = {\n shape,\n role,\n startClient: { x: event.clientX, y: event.clientY },\n startOffset,\n homeOffset: this.defaultOffset(shape, role, handle),\n zoom: this.canvas.zoom(),\n dragging: false,\n };\n document.addEventListener(\"mousemove\", this.onMouseMove);\n document.addEventListener(\"mouseup\", this.onMouseUp);\n document.addEventListener(\"keydown\", this.onKeyDown, true);\n };\n\n private readonly onMouseMove = (event: MouseEvent): void => {\n const drag = this.active;\n if (!drag) return;\n const deltaX = event.clientX - drag.startClient.x;\n const deltaY = event.clientY - drag.startClient.y;\n if (!drag.dragging) {\n if (Math.hypot(deltaX, deltaY) < DRAG_THRESHOLD) return;\n drag.dragging = true;\n this.outerContainer().classList.add(DRAGGING_CLASS);\n this.interaction.begin(drag);\n }\n drag.latest = {\n dx: Math.round(drag.startOffset.dx + deltaX / drag.zoom),\n dy: Math.round(drag.startOffset.dy + deltaY / drag.zoom),\n };\n this.preview(drag, drag.latest);\n };\n\n private readonly onMouseUp = (): void => {\n const drag = this.active;\n if (!drag) return;\n // A plain press falls through to diagram-js's own click selection (incl. Shift to add).\n if (!drag.dragging) {\n this.finish();\n return;\n }\n this.interaction.drop(drag, () => this.dropLabel(drag));\n };\n\n private dropLabel(drag: LabelDrag): void {\n this.finish();\n if (!drag.latest || this.elementRegistry.get(drag.shape.id) !== drag.shape) return;\n const next = this.snapHome(drag.latest, drag.homeOffset);\n const previous =\n drag.role === \"name\" ? drag.shape.labelOffset : drag.shape.movement?.labelOffset;\n if (!sameOffset(next, previous)) {\n if (drag.role === \"name\") this.commitNameOffset(drag.shape, next);\n else this.commitMovementOffset(drag.shape, next);\n }\n this.suppressNextClick();\n this.selection.select(drag.shape);\n }\n\n /** The click that ends a drag would toggle the owner's selection off again. */\n private suppressNextClick(): void {\n const container = this.canvas.getContainer();\n const swallow = (event: MouseEvent) => event.stopPropagation();\n container.addEventListener(\"click\", swallow, { capture: true, once: true });\n setTimeout(() => container.removeEventListener(\"click\", swallow, true), 0);\n }\n\n // Only an Escape aimed at the canvas, which the press focused: a host's field, menu or dialog\n // keeps its own while a label is dragged.\n private readonly onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\" || !this.active || !isCanvasKey(event, this.canvas)) return;\n event.stopPropagation();\n this.cancel();\n };\n\n private readonly onDoubleClick = (event: MouseEvent): void => {\n if (!event.altKey || isReadOnly(this.injector)) return;\n const target = this.labelTarget(event);\n if (!target) return;\n event.stopPropagation();\n event.preventDefault();\n this.resetLabelOffset(target.shape, target.role);\n };\n\n private cancel(): void {\n const drag = this.active;\n if (!drag) return;\n this.finish();\n this.interaction.end(drag);\n }\n\n /** Ends the gesture and restores the pre-drag state (commits run through the command stack). */\n private finish(): void {\n const drag = this.active;\n if (!drag) return;\n this.active = null;\n document.removeEventListener(\"mousemove\", this.onMouseMove);\n document.removeEventListener(\"mouseup\", this.onMouseUp);\n document.removeEventListener(\"keydown\", this.onKeyDown, true);\n this.outerContainer().classList.remove(DRAGGING_CLASS);\n this.livePreview.putBackShape(drag.shape);\n }\n\n private preview(drag: LabelDrag, offset: LabelOffset): void {\n const { movement } = this.livePreview.beginShape(drag.shape);\n if (drag.role === \"name\") drag.shape.labelOffset = offset;\n else if (movement) drag.shape.movement = { ...movement, labelOffset: offset };\n this.eventBus.fire(\"element.changed\", { element: drag.shape });\n }\n\n private snapHome(offset: LabelOffset, home: LabelOffset): LabelOffset | undefined {\n const nearHome =\n Math.abs(offset.dx - home.dx) <= SNAP_HOME_DISTANCE &&\n Math.abs(offset.dy - home.dy) <= SNAP_HOME_DISTANCE;\n return nearHome ? undefined : normalizeLabelOffset(offset.dx, offset.dy);\n }\n\n private commitNameOffset(shape: WardleyShape, offset: LabelOffset | undefined): void {\n const properties: Record<string, unknown> = { labelOffset: offset };\n // The exporter falls back to the imported element's offset; clear it there too, or a reset\n // would come back on the next export.\n const imported = shape.businessObject as\n (MapElement & { labelOffset?: LabelOffset }) | undefined;\n if (!offset && imported?.labelOffset) {\n const { labelOffset: _clearedOffset, ...rest } = imported;\n properties[\"businessObject\"] = rest;\n }\n this.modeling.updateProperties(shape, properties);\n }\n\n private commitMovementOffset(shape: WardleyShape, offset: LabelOffset | undefined): void {\n const movement = shape.movement;\n if (!movement) return;\n const { labelOffset: _previousOffset, ...rest } = movement;\n this.modeling.updateProperties(shape, {\n movement: offset ? { ...rest, labelOffset: offset } : rest,\n });\n }\n\n /**\n * The offset that reproduces the label exactly where it is drawn now, in the OWM frame (relative to\n * the canonical slot). Automatic placements (left of the circle, inertia shift) are converted so\n * the first drag doesn't make the label jump.\n */\n private renderedOffset(\n shape: WardleyShape,\n role: LabelRole,\n handle: SVGTextElement,\n ): LabelOffset {\n if (role === \"movement\" && shape.movement?.labelOffset) return shape.movement.labelOffset;\n if (role === \"name\" && shape.labelOffset) return shape.labelOffset;\n return this.defaultOffset(shape, role, handle);\n }\n\n /** The offset (OWM frame) of the label's automatic, offset-free position. */\n private defaultOffset(shape: WardleyShape, role: LabelRole, handle: SVGTextElement): LabelOffset {\n if (shape.wardleyType === \"anchor\") return { dx: 0, dy: 0 };\n const deltaX = movementDeltaX(shape, this.grid);\n if (role === \"movement\") {\n if (deltaX === undefined) return { dx: 0, dy: 0 };\n const placement = movementLabelPlacement(undefined, deltaX);\n return offsetFromPlacement(placement, movementLabelSlot(deltaX), handle, shape);\n }\n const withoutOffset = { ...shape, labelOffset: undefined } as unknown as WardleyShape;\n const placement = componentLabelPlacement(withoutOffset, deltaX);\n return offsetFromPlacement(placement, componentLabelSlot(), handle, shape);\n }\n\n private labelTarget(\n event: MouseEvent,\n ): { shape: WardleyShape; role: LabelRole; handle: SVGTextElement } | null {\n const handle = (event.target as Element | null)?.closest?.(`.${LABEL_HANDLE_CLASS}`);\n if (!(handle instanceof SVGTextElement)) return null;\n const id = handle.closest(\"[data-element-id]\")?.getAttribute(\"data-element-id\");\n const shape = id ? this.elementRegistry.get(id) : undefined;\n if (!isWardleyShape(shape)) return null;\n const role: LabelRole =\n handle.getAttribute(LABEL_ROLE_ATTRIBUTE) === \"movement\" ? \"movement\" : \"name\";\n if (role === \"movement\" && !shape.movement) return null;\n if (role === \"name\" && shape.wardleyType !== \"component\" && shape.wardleyType !== \"anchor\") {\n return null;\n }\n return { shape, role, handle };\n }\n\n /** The `.wardley-container` the viewer mounts into (diagram-js renders into a child of it). */\n private outerContainer(): HTMLElement {\n const container = this.canvas.getContainer();\n return (container.closest(\".wardley-container\") as HTMLElement | null) ?? container;\n }\n}\n\n/**\n * Explicit offsets render start-anchored at `slot + offset`, so an end-anchored automatic label is\n * converted via its measured left edge (only possible in the browser, hence not in the renderer).\n */\nfunction offsetFromPlacement(\n placement: LabelPlacement,\n slot: { x: number; y: number },\n handle: SVGTextElement,\n shape: WardleyShape,\n): LabelOffset {\n const centerX = shape.width / 2;\n const left = placement.anchor === \"end\" ? handle.getBBox().x - centerX : placement.x;\n return { dx: Math.round(left - slot.x), dy: Math.round(placement.y - slot.y) };\n}\n\nfunction sameOffset(a: LabelOffset | undefined, b: LabelOffset | undefined): boolean {\n if (!a || !b) return !a && !b;\n return a.dx === b.dx && a.dy === b.dy;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport { wardleyInteractionModule } from \"../interaction/index.js\";\nimport { livePreviewModule } from \"../live-preview/index.js\";\nimport WardleyLabelDragging from \"./WardleyLabelDragging.js\";\n\n/** OWM-style draggable labels persisted as `label [dx, dy]` (undoable). */\nexport const wardleyLabelDragModule: ModuleDeclaration = {\n __depends__: [wardleyInteractionModule, livePreviewModule],\n __init__: [\"wardleyLabelDragging\"],\n wardleyLabelDragging: [\"type\", WardleyLabelDragging],\n};\n\nexport { default as WardleyLabelDragging, type LabelRole } from \"./WardleyLabelDragging.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type WardleyLabelEditing from \"./label-editing/WardleyLabelEditing.js\";\nimport type WardleyLinkEditing from \"./link-editing/WardleyLinkEditing.js\";\n\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport MoveModule from \"diagram-js/lib/features/move\";\nimport AutoScrollModule from \"diagram-js/lib/features/auto-scroll\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport ContextPadModule from \"diagram-js/lib/features/context-pad\";\nimport PaletteModule from \"diagram-js/lib/features/palette\";\nimport RulesModule from \"diagram-js/lib/features/rules\";\nimport OutlineModule from \"diagram-js/lib/features/outline\";\nimport ResizeModule from \"diagram-js/lib/features/resize\";\nimport PopupMenuModule from \"diagram-js/lib/features/popup-menu\";\n\nimport { NavigatedViewer } from \"./NavigatedViewer.js\";\nimport { wardleyModelingModule } from \"./modeling/index.js\";\nimport { wardleyLayoutModule } from \"./layout/index.js\";\nimport { wardleyLassoModule } from \"./lasso/index.js\";\nimport { wardleyRulesModule } from \"./rules/index.js\";\nimport { evolutionConstraintModule } from \"./evolution-grid/index.js\";\nimport { stageSnappingModule } from \"./snapping/index.js\";\nimport { wardleyPaletteModule } from \"./palette/index.js\";\nimport { wardleyContextPadModule } from \"./context-pad/index.js\";\nimport { labelEditingModule } from \"./label-editing/index.js\";\nimport { wardleyKeyboardModule } from \"./keyboard/index.js\";\nimport { wardleyEvolveModule } from \"./evolve/index.js\";\nimport { wardleyPopupModule } from \"./popup/index.js\";\nimport { wardleyAppendModule } from \"./append/index.js\";\nimport { wardleyColorPickerModule } from \"./color-picker/index.js\";\nimport { wardleyOrderingModule } from \"./ordering/index.js\";\nimport { wardleyDrawToolModule } from \"./draw-tool/index.js\";\nimport { pipelineGroupModule } from \"./pipeline/index.js\";\nimport { ResizeAwareAutoScroll, mapResizeModule } from \"./map-resize/index.js\";\nimport { linkEditingModule } from \"./link-editing/index.js\";\nimport { wardleyLabelDragModule } from \"./label-drag/index.js\";\nimport { canvasAccessibilityModule } from \"./a11y/index.js\";\nimport { readOnlyModule } from \"./read-only/index.js\";\nimport { wardleyInteractionModule } from \"./interaction/index.js\";\n\n/** Replaces diagram-js AutoScroll: no scrolling under a map-resize drag. */\nconst resizeAwareAutoScrollModule: ModuleDeclaration = {\n autoScroll: [\"type\", ResizeAwareAutoScroll],\n};\n\n/**\n * Full Wardley editor: palette/create, move with EvolutionConstraint + stage snapping, connect with\n * rules, context pad, inline label editing, undo/redo (concept doc §6.1, roadmap M3).\n */\nexport class Modeler extends NavigatedViewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n ModelingModule,\n wardleyLayoutModule,\n RulesModule,\n MoveModule,\n // Default 20px bands on every side; a larger top band would scroll as soon as an element is\n // dragged out of the top-centred palette.\n AutoScrollModule,\n resizeAwareAutoScrollModule,\n CreateModule,\n ConnectModule,\n ContextPadModule,\n PaletteModule,\n OutlineModule,\n ResizeModule,\n PopupMenuModule,\n wardleyModelingModule,\n wardleyRulesModule,\n evolutionConstraintModule,\n stageSnappingModule,\n wardleyPaletteModule,\n wardleyContextPadModule,\n labelEditingModule,\n wardleyKeyboardModule,\n wardleyEvolveModule,\n wardleyPopupModule,\n wardleyAppendModule,\n wardleyColorPickerModule,\n wardleyLassoModule,\n wardleyOrderingModule,\n wardleyDrawToolModule,\n pipelineGroupModule,\n mapResizeModule,\n linkEditingModule,\n canvasAccessibilityModule,\n wardleyLabelDragModule,\n readOnlyModule,\n wardleyInteractionModule,\n ];\n }\n\n /**\n * Saves any open inline editor (name, note, link annotation, flow value, link address). Call it\n * before saving or exporting from a keyboard shortcut, which does not take focus off the editor.\n */\n commitPendingEdits(): void {\n this.get<WardleyLabelEditing>(\"wardleyLabelEditing\").commitActiveEdit();\n this.get<WardleyLinkEditing>(\"wardleyLinkEditing\").commitActiveEdit();\n }\n\n undo(): void {\n this.get<CommandStack>(\"commandStack\").undo();\n }\n\n redo(): void {\n this.get<CommandStack>(\"commandStack\").redo();\n }\n\n canUndo(): boolean {\n return this.get<CommandStack>(\"commandStack\").canUndo();\n }\n\n canRedo(): boolean {\n return this.get<CommandStack>(\"commandStack\").canRedo();\n }\n}\n","import type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport type { Modeler } from \"./Modeler.js\";\nimport type WardleyLabelEditing from \"./label-editing/WardleyLabelEditing.js\";\nimport type { FieldSelection } from \"./label-editing/WardleyLabelEditing.js\";\nimport type WardleyLinkEditing from \"./link-editing/WardleyLinkEditing.js\";\nimport { isWardleyConnection, isWardleyShape, type WardleyConnection } from \"./model/di-types.js\";\nimport { focusCanvasWithoutRing } from \"./a11y/index.js\";\nimport { readBackIds } from \"@miragon/wardley-dsl\";\n\n/**\n * A connection by what it joins: dependency ids are positional (`dep_3`), so after a re-import the\n * same id may name a different link.\n */\ninterface ConnectionKey {\n sourceId: string;\n targetId: string;\n wardleyType: string;\n}\n\ntype OpenEdit =\n | { kind: \"name\"; elementId: string; value: string; selection?: FieldSelection }\n | { kind: \"connection\"; key: ConnectionKey; value: string; selection?: FieldSelection }\n | { kind: \"link\"; elementId: string; value: string; selection?: FieldSelection };\n\n/**\n * What the user had selected and was typing, put aside across a re-import. Element ids are the\n * ids the document gives the elements (`readBackIds`): an element created or renamed on the\n * canvas holds another id until the text is read again, and a re-import reads it.\n */\nexport interface EditorState {\n readonly shapeIds: readonly string[];\n readonly connections: readonly ConnectionKey[];\n readonly edit?: OpenEdit;\n /** The canvas's own id of each element above, by its document id, for an import that failed. */\n readonly canvasIds?: ReadonlyMap<string, string>;\n}\n\nexport interface RestoreOptions {\n /** The re-import was rejected: the canvas still holds the elements under their own ids. */\n importRejected?: boolean;\n}\n\n/** Document id by canvas id (identity where the map cannot be read). */\nfunction documentIdsOf(modeler: Modeler): (canvasId: string) => string {\n let ids: ReadonlyMap<string, string>;\n try {\n ids = readBackIds(modeler.exportMap());\n } catch {\n ids = new Map();\n }\n return (canvasId) => ids.get(canvasId) ?? canvasId;\n}\n\nfunction keyOf(\n connection: WardleyConnection,\n documentId: (canvasId: string) => string = (id) => id,\n): ConnectionKey {\n return {\n sourceId: documentId(connection.source?.id ?? \"\"),\n targetId: documentId(connection.target?.id ?? \"\"),\n wardleyType: connection.wardleyType,\n };\n}\n\nfunction findConnection(\n registry: ElementRegistry,\n key: ConnectionKey,\n): WardleyConnection | undefined {\n return registry.find(\n (element) =>\n isWardleyConnection(element) &&\n element.source?.id === key.sourceId &&\n element.target?.id === key.targetId &&\n element.wardleyType === key.wardleyType,\n ) as WardleyConnection | undefined;\n}\n\n/**\n * Captures the selection and any open inline editor, and closes the editor without saving (a save\n * would push a command onto a stack the import is about to clear). Call before re-importing a map\n * that changed outside the editor, then `restoreEditorState` afterwards.\n */\nexport function setAsideEditorState(modeler: Modeler): EditorState {\n const selected = modeler.get<Selection>(\"selection\").get() as unknown[];\n const registry = modeler.get<ElementRegistry>(\"elementRegistry\");\n const labelEditing = modeler.get<WardleyLabelEditing>(\"wardleyLabelEditing\");\n const linkEditing = modeler.get<WardleyLinkEditing>(\"wardleyLinkEditing\");\n const canvasIds = new Map<string, string>();\n const readBack = documentIdsOf(modeler);\n const documentId = (canvasId: string) => {\n const id = readBack(canvasId);\n canvasIds.set(id, canvasId);\n return id;\n };\n\n let edit: OpenEdit | undefined;\n const nameEdit = labelEditing.getActiveEdit();\n const linkEdit = linkEditing.getActiveEdit();\n if (nameEdit?.connection) {\n const connection = registry.get(nameEdit.elementId);\n if (isWardleyConnection(connection)) {\n edit = {\n kind: \"connection\",\n key: keyOf(connection, documentId),\n value: nameEdit.value,\n ...(nameEdit.selection ? { selection: nameEdit.selection } : {}),\n };\n }\n } else if (nameEdit) {\n edit = {\n kind: \"name\",\n elementId: documentId(nameEdit.elementId),\n value: nameEdit.value,\n ...(nameEdit.selection ? { selection: nameEdit.selection } : {}),\n };\n } else if (linkEdit) {\n edit = {\n kind: \"link\",\n elementId: documentId(linkEdit.elementId),\n value: linkEdit.value,\n selection: linkEdit.selection,\n };\n }\n labelEditing.cancel();\n linkEditing.cancel();\n\n return {\n shapeIds: selected.filter(isWardleyShape).map((shape) => documentId(shape.id)),\n connections: selected\n .filter(isWardleyConnection)\n .map((connection) => keyOf(connection, documentId)),\n ...(edit ? { edit } : {}),\n canvasIds,\n };\n}\n\n/**\n * Brings back what `setAsideEditorState` captured, for the elements that still exist: names are\n * stable ids (`cmp_tea`), connections are matched by their ends. An editor whose element is gone\n * leaves keyboard focus on the canvas rather than on the page.\n */\nexport function restoreEditorState(\n modeler: Modeler,\n state: EditorState,\n options: RestoreOptions = {},\n): void {\n const registry = modeler.get<ElementRegistry>(\"elementRegistry\");\n const canvasId = (id: string) => (options.importRejected ? (state.canvasIds?.get(id) ?? id) : id);\n const lookup = (id: string) => registry.get(canvasId(id));\n const connectionOf = (key: ConnectionKey) =>\n findConnection(registry, {\n ...key,\n sourceId: canvasId(key.sourceId),\n targetId: canvasId(key.targetId),\n });\n const shapes = state.shapeIds.map(lookup).filter(isWardleyShape);\n const connections = state.connections\n .map(connectionOf)\n .filter((connection): connection is WardleyConnection => connection !== undefined);\n const reselected = [...shapes, ...connections] as unknown as Element[];\n if (reselected.length) modeler.get<Selection>(\"selection\").select(reselected);\n\n const { edit } = state;\n if (!edit) return;\n const labelEditing = modeler.get<WardleyLabelEditing>(\"wardleyLabelEditing\");\n const restored = (() => {\n if (edit.kind === \"connection\") {\n const connection = connectionOf(edit.key);\n if (!connection) return false;\n labelEditing.activateConnection(connection, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n return true;\n }\n const shape = lookup(edit.elementId);\n if (!isWardleyShape(shape)) return false;\n if (edit.kind === \"link\") {\n modeler.get<WardleyLinkEditing>(\"wardleyLinkEditing\").activate(shape, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n } else {\n labelEditing.activate(shape, {\n value: edit.value,\n ...(edit.selection ? { selection: edit.selection } : {}),\n });\n }\n return true;\n })();\n if (!restored) focusCanvasWithoutRing(modeler.get<Canvas>(\"canvas\"));\n}\n","import {\n MODELER_API_VERSION,\n type AppearanceSurface,\n type CollaborativeModeler,\n type CollaborativeModelerOptions,\n type ElementBounds,\n type ElementInfo,\n type ElementsSurface,\n type ImportResult,\n type InteractionSurface,\n type ModelerMeta,\n} from \"@miragon/modeler-api\";\nimport { readBackIds, serializeDSL } from \"@miragon/wardley-dsl\";\nimport type { ModuleDeclaration } from \"didi\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { Modeler } from \"../Modeler.js\";\nimport { NavigatedViewer } from \"../NavigatedViewer.js\";\nimport type { WardleyViewerOptions } from \"../WardleyBaseViewer.js\";\nimport { WARDLEY_THEMES } from \"../appearance/index.js\";\nimport { restoreEditorState, setAsideEditorState } from \"../editor-state.js\";\nimport {\n INTERACTION_CHANGED,\n type InteractionChangedEvent,\n type WardleyInteraction,\n} from \"../interaction/index.js\";\nimport type { LivePreview } from \"../live-preview/index.js\";\nimport { isWardleyShape, type WardleyShape } from \"../model/di-types.js\";\nimport type { PanConstraint } from \"../pan-constraint/index.js\";\n\n/** Stable notation id in `meta.notation` of the collaborative-modeler contract. */\nexport const WARDLEY_NOTATION = \"wardley\";\n\n/**\n * The contract's factory options (`freeArea`, `fitOnImport`, `undoRedoKeys`, see\n * `WardleyViewerOptions`) plus the renderer's own. The viewer ignores `undoRedoKeys`.\n */\nexport interface CollaborativeWardleyOptions extends CollaborativeModelerOptions {\n /** Appended to the renderer's own modules (e.g. a host's chrome module). */\n additionalModules?: ModuleDeclaration[] | undefined;\n}\n\n/** The contract's element surface, with the optional `bounds` of contract 1.2 always present. */\nexport interface WardleyElementsSurface extends ElementsSurface {\n bounds(id: string): ElementBounds | undefined;\n}\n\n/**\n * The contract surface, with the optional `contentBounds` of contract 1.3 and `interaction` and\n * `appearance` of contract 1.5 always present, plus the wrapped diagram for host-specific wiring.\n */\nexport interface CollaborativeWardleyModeler extends CollaborativeModeler {\n readonly elements: WardleyElementsSurface;\n readonly interaction: InteractionSurface;\n readonly appearance: AppearanceSurface;\n readonly diagram: Modeler | NavigatedViewer;\n contentBounds(): ElementBounds | undefined;\n}\n\ninterface ViewState {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * The named elements: components, anchors, pipelines, submaps and accelerators. Their names are\n * unique on a map, so the id the document derives from a name survives edits to other elements.\n * Notes, annotations, regions and drawings may repeat their text, number or kind, and the parser\n * tells repeats apart by line order, so their ids would move to another element.\n */\nconst ADDRESSABLE_TYPES: ReadonlySet<string> = new Set([\n \"component\",\n \"anchor\",\n \"pipeline\",\n \"submap\",\n \"accelerator\",\n]);\n\nfunction isAddressable(element: unknown): element is WardleyShape {\n return isWardleyShape(element) && ADDRESSABLE_TYPES.has(element.wardleyType);\n}\n\n/** The editing mount (`meta.editable: true`) of the collaborative-modeler contract. */\nexport function createCollaborativeModeler(\n options: CollaborativeWardleyOptions = {},\n): CollaborativeWardleyModeler {\n return collaborative(\n new Modeler({\n ...diagramOptions(options),\n undoRedoKeys: options.undoRedoKeys,\n }),\n true,\n );\n}\n\n/** The read-only mount (`meta.editable: false`): imports, exports and reveals, never edits. */\nexport function createCollaborativeViewer(\n options: CollaborativeWardleyOptions = {},\n): CollaborativeWardleyModeler {\n return collaborative(new NavigatedViewer(diagramOptions(options)), false);\n}\n\nfunction diagramOptions(options: CollaborativeWardleyOptions): WardleyViewerOptions {\n return {\n width: \"100%\",\n height: \"100%\",\n additionalModules: options.additionalModules ?? [],\n freeArea: options.freeArea,\n fitOnImport: options.fitOnImport,\n };\n}\n\n/**\n * The document ids of the canvas's elements and back, read once per content change: an element\n * created or renamed on the canvas keeps its canvas id until the text is read again.\n */\nfunction documentIds(diagram: Modeler | NavigatedViewer, eventBus: EventBus) {\n let byCanvasId: Map<string, string> | undefined;\n let byDocumentId: Map<string, string> | undefined;\n eventBus.on(\n [\"elements.changed\", \"import.done\", \"diagram.clear\", \"commandStack.changed\"],\n () => (byCanvasId = byDocumentId = undefined),\n );\n const read = () => {\n if (!byCanvasId) {\n try {\n byCanvasId = readBackIds(diagram.exportMap());\n } catch {\n byCanvasId = new Map();\n }\n byDocumentId = new Map([...byCanvasId].map(([canvasId, id]) => [id, canvasId]));\n }\n return { byCanvasId, byDocumentId: byDocumentId! };\n };\n return {\n of: (canvasId: string) => read().byCanvasId.get(canvasId) ?? canvasId,\n canvasIdOf: (documentId: string) => read().byDocumentId.get(documentId) ?? documentId,\n };\n}\n\n/**\n * The contract's `interaction`, read from the Modeler's `wardleyInteraction`; a viewer has no\n * editing gesture and reports none. `afterUserAction` is the service's wait for the user's running\n * action.\n */\nfunction interactionOf(diagram: Modeler | NavigatedViewer, editable: boolean) {\n const service = editable ? diagram.get<WardleyInteraction>(\"wardleyInteraction\") : undefined;\n const listeners = new Set<(active: boolean) => void>();\n let destroyed = false;\n // The event fires inside diagram-js's drag handling: a host listener that throws there would\n // cancel the user's drag and keep the listeners after it from hearing of the change.\n diagram.get<EventBus>(\"eventBus\").on(INTERACTION_CHANGED, (event: InteractionChangedEvent) => {\n for (const listener of [...listeners]) {\n // An earlier listener may have destroyed the modeler, which drops every listener, or\n // unsubscribed this one during the same delivery.\n if (!listeners.has(listener)) continue;\n try {\n listener(event.active);\n } catch (error) {\n queueMicrotask(() => {\n throw error;\n });\n }\n }\n });\n const surface: InteractionSurface = {\n active: () => !destroyed && service?.isActive() === true,\n onChange(callback) {\n if (destroyed) return () => undefined;\n listeners.add(callback);\n return () => {\n listeners.delete(callback);\n };\n },\n };\n return {\n surface,\n afterUserAction: (): Promise<void> | undefined =>\n destroyed ? undefined : service?.afterUserAction(),\n /** Ends every delivery. */\n stop() {\n destroyed = true;\n listeners.clear();\n },\n /** Runs `teardown` at once, or after the handler of the user's input that runs. */\n tearDownAfterHandler(teardown: () => void) {\n if (service) service.tearDownAfterHandler(teardown);\n else teardown();\n },\n };\n}\n\n/**\n * The host's selection listeners. The code that calls them goes on with the map once they have\n * returned, also when it is the host's own call: `reveal` scrolls to the element it selected, and\n * an import draws the map after the clear that emptied the selection. A `destroy()` from one of\n * them waits for that code (`delivering`).\n */\nfunction selectionListeners(eventBus: EventBus, isDestroyed: () => boolean) {\n let deliveries = 0;\n return {\n delivering: (): boolean => deliveries > 0,\n subscribe(callback: (selected: unknown[]) => void): () => void {\n // The teardown cancels a running drag, which brings back the selection from before it.\n // diagram-js's event bus still calls a listener that an earlier one unsubscribed during the\n // same delivery after unsubscribing itself.\n let subscribed = true;\n const listener = (event: unknown) => {\n if (isDestroyed() || !subscribed) return;\n deliveries += 1;\n try {\n callback((event as { newSelection?: unknown[] }).newSelection ?? []);\n } finally {\n deliveries -= 1;\n }\n };\n eventBus.on(\"selection.changed\", listener);\n return () => {\n subscribed = false;\n eventBus.off(\"selection.changed\", listener);\n };\n },\n };\n}\n\n/**\n * The contract's `appearance`: written onto the container the map is drawn in, so the design tokens\n * resolve their roles there and not from the page around it. View state only: the map, its\n * exports, its history and the view are left as they are.\n */\nfunction appearanceOf(root: HTMLElement, isDestroyed: () => boolean): AppearanceSurface {\n return {\n themes: WARDLEY_THEMES,\n set(request) {\n if (isDestroyed()) return;\n // A host without the contract's types may send anything: it counts as an unlisted theme and\n // as normal contrast.\n const { theme, contrast } = (\n typeof request === \"object\" && request !== null ? request : {}\n ) as { theme?: unknown; contrast?: unknown };\n const drawn = WARDLEY_THEMES.find((listed) => listed === theme) ?? WARDLEY_THEMES[0];\n root.setAttribute(\"data-cd-theme\", drawn);\n if (contrast === \"high\") root.setAttribute(\"data-cd-kontrast\", \"hoch\");\n else root.removeAttribute(\"data-cd-kontrast\");\n },\n };\n}\n\n/**\n * The wait of each import: behind the imports that waited before it, then until each user action\n * still running by then has finished; `undefined` when there is nothing to wait for. A wait rejects\n * once the modeler has been destroyed meanwhile.\n */\nfunction importTurns(\n afterUserAction: () => Promise<void> | undefined,\n isDestroyed: () => boolean,\n): () => Promise<void> | undefined {\n let lastWaiting: Promise<void> | undefined;\n const wait = async (ahead: Promise<void> | undefined, action: Promise<void> | undefined) => {\n if (ahead) await ahead.catch(() => undefined);\n for (; ; action = afterUserAction()) {\n if (isDestroyed()) throw destroyedError();\n if (!action) return;\n await action;\n }\n };\n return () => {\n const ahead = lastWaiting;\n const action = afterUserAction();\n if (!ahead && !action) return undefined;\n const turn = wait(ahead, action);\n lastWaiting = turn;\n const taken = () => {\n if (lastWaiting === turn) lastWaiting = undefined;\n };\n turn.then(taken, taken);\n return turn;\n };\n}\n\nfunction collaborative(\n diagram: Modeler | NavigatedViewer,\n editable: boolean,\n): CollaborativeWardleyModeler {\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const canvas = diagram.get<Canvas>(\"canvas\");\n const elementRegistry = diagram.get<ElementRegistry>(\"elementRegistry\");\n const selection = diagram.get<Selection>(\"selection\");\n const panConstraint = diagram.get<PanConstraint>(\"panConstraint\");\n const ids = documentIds(diagram, eventBus);\n const livePreview = editable ? diagram.get<LivePreview>(\"wardleyLivePreview\") : undefined;\n const interaction = interactionOf(diagram, editable);\n const contentListeners = new Set<() => void>();\n let importsRunning = 0;\n let imported = false;\n let destroyed = false;\n let lastExport = \"\";\n const selections = selectionListeners(eventBus, () => destroyed);\n const untilItsTurn = importTurns(interaction.afterUserAction, () => destroyed);\n\n const meta: ModelerMeta = {\n notation: WARDLEY_NOTATION,\n apiVersion: MODELER_API_VERSION,\n editable,\n };\n\n // The command stack is the one channel of every user-visible change, config edits included;\n // an import clears it, which is housekeeping, not a change (L1, L3).\n if (editable) {\n eventBus.on(\"commandStack.changed\", () => {\n if (importsRunning > 0) return;\n // An earlier listener may destroy the modeler, which drops every listener, or unsubscribe a\n // later one during the same delivery.\n for (const listener of [...contentListeners]) {\n if (contentListeners.has(listener)) listener();\n }\n });\n }\n\n const documentIdsOf = (elements: readonly unknown[]): string[] =>\n elements.filter(isAddressable).map((element) => ids.of(element.id));\n\n const elementInfo = (element: WardleyShape): ElementInfo => {\n const id = ids.of(element.id);\n return element.wardleyLabel ? { id, name: element.wardleyLabel } : { id };\n };\n\n /** The element `list()` reports under `id`, read from the live canvas. */\n const listedElement = (id: string): WardleyShape | undefined => {\n if (destroyed) return undefined;\n const element: unknown = elementRegistry.get(ids.canvasIdOf(id));\n return isAddressable(element) && ids.of(element.id) === id ? element : undefined;\n };\n\n const elements: WardleyElementsSurface = {\n list: () =>\n destroyed\n ? []\n : (elementRegistry.getAll() as unknown[]).filter(isAddressable).map(elementInfo),\n reveal(id) {\n if (destroyed) return false;\n const element = elementRegistry.get(ids.canvasIdOf(id));\n if (!isAddressable(element)) return false;\n selection.select(element as unknown as Element);\n canvas.scrollToElement(element as unknown as Element);\n return true;\n },\n selection: () => (destroyed ? [] : documentIdsOf(selection.get())),\n onSelection: (callback) =>\n selections.subscribe((selected) => callback(documentIdsOf(selected))),\n bounds(id) {\n const element = listedElement(id);\n if (!element) return undefined;\n const { x, y, width, height } = element;\n return { x, y, width, height };\n },\n };\n\n // Never a live preview: a host saves the export at any moment, also while the user drags the plot\n // corner, an evolve target or a label.\n const committedText = (): string => {\n const committed = livePreview?.committedMap();\n return committed ? serializeDSL(committed) : diagram.exportDSL();\n };\n\n async function importText(text: string): Promise<ImportResult> {\n if (destroyed) throw destroyedError();\n // A host that echoes its own change back through its store imports from the change listener,\n // while the user's action still runs: a create goes on to select its element and open its name\n // editor, a press that saved a name goes on to start its drag, and a drop's later steps, also\n // those it defers by a task, hold the shapes the import would replace. So the import waits\n // until the action has finished, and after the imports that waited before it.\n const turn = untilItsTurn();\n if (turn) await turn;\n importsRunning += 1;\n // An open label editor neither commits during the import nor loses what was typed (L1): it\n // is taken down and reopened on the element with the same id.\n const editorState = editable && imported ? setAsideEditorState(diagram as Modeler) : undefined;\n try {\n const importing = diagram.importDSL(text);\n // The map is drawn by the time that call returns: a destroy after it comes from outside the\n // import and leaves it resolved, as in the other renderers.\n const destroyedWhenDrawn = destroyed;\n const { warnings } = await importing;\n imported = true;\n // Reading a destroyed map would build a new one on the detached container.\n const restoring = editorState !== undefined && !destroyed;\n if (restoring) restoreEditorState(diagram as Modeler, editorState);\n // A listener the import called (the end of a held gesture, the clear of the selection, the\n // selection it brings back) destroyed the modeler: the import rejects, as one that waits\n // does once the modeler is destroyed.\n if (restoring ? destroyed : destroyedWhenDrawn) throw destroyedError();\n return { warnings: warnings.map((warning) => warning.message) };\n } catch (error) {\n if (editorState && !destroyed)\n restoreEditorState(diagram as Modeler, editorState, { importRejected: true });\n throw error;\n } finally {\n importsRunning -= 1;\n }\n }\n\n return {\n meta,\n elements,\n interaction: interaction.surface,\n appearance: appearanceOf(diagram.container, () => destroyed),\n diagram,\n attachTo(host) {\n diagram.attachTo(host as HTMLElement);\n },\n importText,\n exportText() {\n // Asking a destroyed diagram would build a new one on the detached container.\n if (destroyed) return lastExport;\n return committedText();\n },\n onContentChanged(callback) {\n if (!editable) return () => undefined;\n contentListeners.add(callback);\n return () => contentListeners.delete(callback);\n },\n getViewState(): ViewState | undefined {\n if (destroyed) return undefined;\n try {\n const { x, y, width, height } = canvas.viewbox();\n const state = { x, y, width, height };\n return isViewState(state) ? state : undefined;\n } catch {\n return undefined;\n }\n },\n setViewState(state) {\n if (destroyed || !isViewState(state)) return;\n canvas.viewbox({ x: state.x, y: state.y, width: state.width, height: state.height });\n },\n // Every map draws its plot, also one without elements, so there is always a box to fit (before\n // the first import the default plot's). A host fits to the box the pan constraint keeps in view.\n contentBounds() {\n if (destroyed) return undefined;\n const { x, y, width, height } = panConstraint.contentBounds();\n return { x, y, width, height };\n },\n destroy() {\n if (destroyed) return;\n lastExport = textToKeep(committedText);\n destroyed = true;\n contentListeners.clear();\n interaction.stop();\n // An import whose listener destroyed the modeler goes on to draw its map before its Promise\n // rejects: the modeler keeps that map (#415). Whatever else runs on after the destroy\n // reaches no host, so the text read above stays.\n let imported = false;\n eventBus.on(\"import.done\", () => {\n imported = true;\n });\n const tearDown = () => {\n if (imported) lastExport = textToKeep(committedText);\n diagram.destroy();\n };\n if (selections.delivering()) queueMicrotask(tearDown);\n else interaction.tearDownAfterHandler(tearDown);\n },\n };\n}\n\nfunction destroyedError(): Error {\n return new Error(\"The modeler was destroyed.\");\n}\n\nfunction textToKeep(committedText: () => string): string {\n try {\n return committedText();\n } catch {\n return \"\";\n }\n}\n\nfunction isViewState(state: unknown): state is ViewState {\n if (typeof state !== \"object\" || state === null) return false;\n const { x, y, width, height } = state as Record<string, unknown>;\n return (\n isFiniteNumber(x) &&\n isFiniteNumber(y) &&\n isFiniteNumber(width) &&\n isFiniteNumber(height) &&\n width > 0 &&\n height > 0\n );\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n","/*\n * The map's entries of the chrome menu (guide §5.4), the same in every host. The types mirror\n * the menu groups of `@miragon/modeler-shell` structurally, so an app hands the result to the\n * shell as it is while the renderer never imports the shell.\n */\n\n/** The icons the guide gives these entries (guide §5.14, the shell's common set). */\nexport type MapMenuIcon = \"file-image\" | \"file-code-corner\" | \"keyboard\";\n\ninterface MapMenuItem {\n readonly id: string;\n readonly label: string;\n readonly icon?: MapMenuIcon;\n readonly keepEnabledWhenReadOnly?: boolean;\n}\n\nexport interface MapMenuAction extends MapMenuItem {\n readonly kind: \"action\";\n readonly shortcut?: string;\n onSelect(): void;\n}\n\nexport interface MapMenuDialog extends MapMenuItem {\n readonly kind: \"dialog\";\n /** The chip of a key that opens the dialog as well, e.g. \"?\". */\n readonly shortcut?: string;\n onSelect(): void;\n}\n\nexport type MapMenuEntry = MapMenuAction | MapMenuDialog;\n\nexport interface MapMenu {\n readonly model: readonly MapMenuEntry[];\n readonly export: readonly MapMenuEntry[];\n readonly help: readonly MapMenuEntry[];\n}\n\nexport interface MapExport {\n onSelect(): void;\n /** The chip of an app key that runs the same export, e.g. \"⌘S\". */\n readonly shortcut?: string | undefined;\n}\n\n/**\n * The exports a host offers, in the guide's order: PNG first (the more frequent target), then\n * SVG, then the variants, then further formats. Only the web app adds the map file itself, which\n * in VS Code is the document.\n */\nexport interface MapExports {\n readonly png: MapExport;\n readonly svg: MapExport;\n readonly transparentPng?: MapExport | undefined;\n readonly json?: MapExport | undefined;\n readonly wmap?: MapExport | undefined;\n}\n\nexport interface MapMenuActions {\n /** Opens the \"Map title…\" dialog; without it the Model group has no title entry. */\n mapTitle?: (() => void) | undefined;\n /** Opens the \"Map size…\" popover. */\n mapSize(): void;\n /** Opens the \"X-axis labels…\" popover. */\n axisLabels(): void;\n readonly exports: MapExports;\n showKeyboardShortcuts(): void;\n /** The chip of a key the host binds to the shortcuts dialog as well, e.g. \"?\" in the web app. */\n readonly shortcutsKey?: string | undefined;\n}\n\n/** The labels of the export entries, also used by the hosts' commands and notifications. */\nexport const EXPORT_LABELS = {\n png: \"Export as PNG\",\n svg: \"Export as SVG\",\n transparentPng: \"Export as PNG (4×, transparent)\",\n json: \"Export as JSON\",\n wmap: \"Export as .wmap\",\n} as const;\n\nfunction exportEntry(\n id: string,\n label: string,\n action: MapExport,\n icon?: MapMenuIcon,\n): MapMenuAction {\n return {\n kind: \"action\",\n id,\n label,\n ...(icon ? { icon } : {}),\n ...(action.shortcut ? { shortcut: action.shortcut } : {}),\n onSelect: () => action.onSelect(),\n };\n}\n\nfunction exportEntries(exports: MapExports): MapMenuAction[] {\n const entries = [\n exportEntry(\"export-png\", EXPORT_LABELS.png, exports.png, \"file-image\"),\n exportEntry(\"export-svg\", EXPORT_LABELS.svg, exports.svg, \"file-code-corner\"),\n ];\n if (exports.transparentPng) {\n entries.push(\n exportEntry(\"export-png-transparent\", EXPORT_LABELS.transparentPng, exports.transparentPng),\n );\n }\n if (exports.json) entries.push(exportEntry(\"export-json\", EXPORT_LABELS.json, exports.json));\n if (exports.wmap) entries.push(exportEntry(\"export-wmap\", EXPORT_LABELS.wmap, exports.wmap));\n return entries;\n}\n\n/**\n * The menu groups of a map (guide §5.4): Model with the title dialog where the host offers it and\n * the two popovers (all three change the document, so a read-only canvas disables them), Export\n * with PNG first, Help with the shortcuts dialog.\n */\nexport function mapMenu(actions: MapMenuActions): MapMenu {\n const { mapTitle, shortcutsKey } = actions;\n const titleEntries: MapMenuEntry[] = mapTitle\n ? [{ kind: \"dialog\", id: \"map-title\", label: \"Map title…\", onSelect: () => mapTitle() }]\n : [];\n return {\n model: [\n ...titleEntries,\n { kind: \"dialog\", id: \"map-size\", label: \"Map size…\", onSelect: () => actions.mapSize() },\n {\n kind: \"dialog\",\n id: \"x-axis-labels\",\n label: \"X-axis labels…\",\n onSelect: () => actions.axisLabels(),\n },\n ],\n export: exportEntries(actions.exports),\n help: [\n {\n kind: \"dialog\",\n id: \"keyboard-shortcuts\",\n label: \"Keyboard shortcuts…\",\n icon: \"keyboard\",\n ...(shortcutsKey ? { shortcut: shortcutsKey } : {}),\n onSelect: () => actions.showKeyboardShortcuts(),\n },\n ],\n };\n}\n","import { EXPORT_LABELS } from \"./menu.js\";\n\n/*\n * Every shortcut and gesture of a map for the \"Keyboard shortcuts…\" dialog (guide §5.4): one\n * table per group, the keys as chips like the chrome tooltip's (guide §5.6). The chrome's texts\n * and key names come in structurally (a `@miragon/modeler-shell` handle fits), so the View rows\n * say what the zoom panel's tooltips say.\n */\n\nexport type ShortcutPlatform = \"mac\" | \"other\";\n\nexport interface ShortcutKeyNames {\n readonly ctrl: string;\n readonly shift: string;\n readonly plus: string;\n readonly minus: string;\n}\n\n/** What the shortcuts need of the chrome around the map. */\nexport interface ShortcutsChrome {\n readonly platform: ShortcutPlatform;\n /** The tool's UI language, for the percentage in \"Zoom to 100%\". */\n readonly lang: string;\n readonly messages: {\n readonly zoomIn: string;\n readonly zoomOut: string;\n zoomToActual(percent: string): string;\n readonly fit: string;\n /** The File group's \"Open…\" (the shell's `messages.openFile`); default \"Open…\". */\n readonly openFile?: string | undefined;\n readonly keyNames: ShortcutKeyNames;\n };\n}\n\n/** Keys a web app binds itself, next to the canvas's and the chrome's. */\nexport interface MapShortcutOptions {\n /**\n * Cmd/Ctrl+O opens a file, Cmd/Ctrl+S exports the .wmap file and Cmd/Ctrl+V opens OWM text or a\n * share link pasted onto the canvas: a File group comes first.\n */\n readonly fileKeys?: boolean | undefined;\n /** The key that opens the dialog itself, e.g. \"?\", listed in the View group. */\n readonly shortcutsKey?: string | undefined;\n}\n\nexport interface ShortcutRow {\n readonly action: string;\n /** Alternative keys or gestures, each shown as its own chip. */\n readonly keys: readonly string[];\n}\n\nexport interface ShortcutGroup {\n readonly title: string;\n readonly rows: readonly ShortcutRow[];\n}\n\nconst ARROWS = \"←↑→↓\";\n\nfunction percentOfActualSize(lang: string): string {\n try {\n return new Intl.NumberFormat(lang, { style: \"percent\" }).format(1);\n } catch {\n return new Intl.NumberFormat(\"en\", { style: \"percent\" }).format(1);\n }\n}\n\n/** The chips of one platform: modifier symbols on macOS, names elsewhere. */\nfunction keysOf(platform: ShortcutPlatform, names: ShortcutKeyNames) {\n if (platform === \"mac\") {\n return {\n command: (key: string) => `⌘${key}`,\n shiftCommand: (key: string) => `⌘⇧${key}`,\n shift: (what: string) => `⇧ ${what}`,\n alt: (what: string) => `⌥ ${what}`,\n zoomIn: \"⌘+\",\n zoomOut: \"⌘−\",\n zoomToActual: \"⌘0\",\n fit: \"⇧1\",\n remove: [\"⌫\"],\n enter: \"↵\",\n breakLine: \"⇧↵\",\n };\n }\n const { ctrl, shift, plus, minus } = names;\n return {\n command: (key: string) => `${ctrl}+${key}`,\n shiftCommand: (key: string) => `${ctrl}+${shift}+${key}`,\n shift: (what: string) => `${shift}+${what}`,\n alt: (what: string) => `Alt+${what}`,\n zoomIn: `${ctrl}+${plus}`,\n zoomOut: `${ctrl}+${minus}`,\n zoomToActual: `${ctrl}+0`,\n fit: `${shift}+1`,\n remove: [\"Del\", \"Backspace\"],\n enter: \"Enter\",\n breakLine: `${shift}+Enter`,\n };\n}\n\nfunction fileGroup(chrome: ShortcutsChrome, command: (key: string) => string): ShortcutGroup {\n return {\n title: \"File\",\n rows: [\n { action: chrome.messages.openFile ?? \"Open…\", keys: [command(\"O\")] },\n { action: EXPORT_LABELS.wmap, keys: [command(\"S\")] },\n { action: \"Paste OWM text or a share link\", keys: [command(\"V\")] },\n ],\n };\n}\n\n/**\n * Every shortcut of a map, grouped as guide §5.4 asks: View (the chrome's zoom keys), Edit, the\n * notation's tools and the gestures on the map itself, after the web app's File keys where it\n * binds them.\n */\nexport function mapShortcuts(\n chrome: ShortcutsChrome,\n options: MapShortcutOptions = {},\n): ShortcutGroup[] {\n const { platform, messages } = chrome;\n const keys = keysOf(platform, messages.keyNames);\n return [\n ...(options.fileKeys ? [fileGroup(chrome, keys.command)] : []),\n {\n title: \"View\",\n rows: [\n { action: messages.zoomIn, keys: [keys.zoomIn] },\n { action: messages.zoomOut, keys: [keys.zoomOut] },\n {\n action: messages.zoomToActual(percentOfActualSize(chrome.lang)),\n keys: [keys.zoomToActual],\n },\n { action: messages.fit, keys: [keys.fit] },\n ...(options.shortcutsKey\n ? [{ action: \"Keyboard shortcuts\", keys: [options.shortcutsKey] }]\n : []),\n ],\n },\n {\n title: \"Edit\",\n rows: [\n { action: \"Undo\", keys: [keys.command(\"Z\")] },\n {\n action: \"Redo\",\n keys:\n platform === \"mac\"\n ? [keys.shiftCommand(\"Z\")]\n : [keys.shiftCommand(\"Z\"), keys.command(\"Y\")],\n },\n { action: \"Rename\", keys: [\"Double-click\"] },\n { action: \"Break the line in a name\", keys: [keys.breakLine] },\n { action: \"Save a note while editing\", keys: [keys.command(keys.enter)] },\n { action: \"Copy\", keys: [keys.command(\"C\")] },\n { action: \"Paste (a click places it, Esc cancels)\", keys: [keys.command(\"V\")] },\n { action: \"Duplicate\", keys: [keys.command(\"D\")] },\n { action: \"Delete\", keys: keys.remove },\n { action: \"Move the selection\", keys: [ARROWS] },\n { action: \"Move the selection further\", keys: [keys.shift(ARROWS)] },\n { action: \"Select all\", keys: [keys.command(\"A\")] },\n { action: \"Add to the selection\", keys: [keys.shift(\"Click\")] },\n { action: \"Deselect, cancel\", keys: [\"Esc\"] },\n ],\n },\n {\n title: \"Tools\",\n rows: [\n { action: \"Component\", keys: [\"C\"] },\n { action: \"User (anchor)\", keys: [\"U\"] },\n { action: \"Note\", keys: [\"N\"] },\n { action: \"Pipeline\", keys: [\"P\"] },\n { action: \"Connect from the selected node\", keys: [\"A\"] },\n { action: \"Lasso\", keys: [\"L\"] },\n { action: \"Lasso by dragging\", keys: [keys.shift(\"Drag\")] },\n { action: \"Draw: place a point\", keys: [\"Click\"] },\n { action: \"Finish a drawing\", keys: [keys.enter, \"Double-click\"] },\n { action: \"Close a drawing\", keys: [\"Click the first point\"] },\n ],\n },\n {\n title: \"Map\",\n rows: [\n { action: \"Move a label\", keys: [\"Drag the label\"] },\n { action: \"Reset a label’s position\", keys: [keys.alt(\"Double-click\")] },\n { action: \"Resize the map\", keys: [\"Drag the right or bottom edge\"] },\n { action: \"Resize, keeping the ratio\", keys: [keys.shift(\"Drag\")] },\n { action: \"Resize without snapping\", keys: [keys.alt(\"Drag\")] },\n { action: \"Reset the map size\", keys: [\"Double-click the corner\"] },\n ],\n },\n ];\n}\n","/*! @miragon/wardley-renderer icon geometry: x. Lucide (lucide-static 1.59.0) @license ISC\n * Copyright (c) 2026 Lucide Icons and Contributors\n * Derived from Feather @license MIT, Copyright (c) 2013-present Cole Bemis\n * Full notices: README.md of @miragon/wardley-renderer */\n/** Lucide `x` (lucide-static 1.59.0, ISC; derived from Feather, MIT) at the chrome size of §5.14. */\nexport const CLOSE_ICON =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>';\n\nexport function element<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n className: string,\n text?: string,\n): HTMLElementTagNameMap[K] {\n const created = document.createElement(tag);\n created.className = className;\n if (text !== undefined) created.textContent = text;\n return created;\n}\n\n/** Ids stay unique when two maps share a page (two webviews never do, a web page may). */\nlet nextId = 0;\nexport function uniqueId(prefix: string): string {\n nextId += 1;\n return `${prefix}-${nextId}`;\n}\n","import { CLOSE_ICON, element, uniqueId } from \"./dom.js\";\n\n/** What a dialog needs of the chrome around the map; a `@miragon/modeler-shell` handle fits. */\nexport interface DialogChrome {\n /** Where the dialog lives (the shell root), so it shares the chrome's mode and fonts. */\n readonly root: HTMLElement;\n readonly messages: { readonly close: string };\n /** The control the focus returns to once the dialog closes. */\n readonly menu: { readonly trigger: HTMLElement };\n}\n\nexport interface MapDialog {\n open(): void;\n isOpen(): boolean;\n close(): void;\n destroy(): void;\n}\n\nexport interface MapDialogParts {\n /** Class of the `<dialog>` next to `wardley-dialog`, for the dialog's own rules. */\n readonly className: string;\n readonly title: string;\n /** The parts below the header (body, footer), built once on the first open. */\n content(close: () => void): Node[];\n /** Runs before every open, while the dialog is still closed. */\n beforeOpen?(): void;\n /** Runs after every open, once the dialog shows and holds the focus. */\n afterOpen?(): void;\n /** Runs after every close, before the focus goes back. */\n afterClose?(): void;\n}\n\n/** A footer button of guide §8: primary (the confirming action), secondary or ghost. */\nexport function dialogButton(\n label: string,\n variant: \"primary\" | \"secondary\" | \"ghost\",\n): HTMLButtonElement {\n const created = element(\"button\", \"wardley-button\", label);\n created.type = \"button\";\n created.dataset[\"variant\"] = variant;\n return created;\n}\n\nfunction header(\n chrome: DialogChrome,\n title: string,\n titleId: string,\n onClose: () => void,\n): HTMLElement {\n const head = element(\"header\", \"wardley-dialog-header\");\n const heading = element(\"h3\", \"wardley-dialog-title\", title);\n heading.id = titleId;\n const close = element(\"button\", \"wardley-dialog-close\");\n close.type = \"button\";\n close.setAttribute(\"aria-label\", chrome.messages.close);\n close.innerHTML = CLOSE_ICON;\n close.addEventListener(\"click\", onClose);\n head.append(heading, close);\n return head;\n}\n\n/**\n * A dialog of the map's chrome (guide §8, \"Modeler dialogs\" of the shell's API): a native modal\n * <dialog> inside the chrome's root, so the browser keeps the focus inside it and closes it on\n * Escape. Built on the first open and kept (closed) afterwards; `destroy()` removes it. The host\n * calls it with the diagram's teardown, since the chrome removes only what it added itself.\n */\nexport function createMapDialog(chrome: DialogChrome, parts: MapDialogParts): MapDialog {\n let dialog: HTMLDialogElement | undefined;\n\n function build(): HTMLDialogElement {\n const titleId = uniqueId(`${parts.className}-title`);\n const created = element(\"dialog\", `wardley-dialog ${parts.className}`);\n created.setAttribute(\"aria-labelledby\", titleId);\n const close = () => created.close();\n const panel = element(\"div\", \"wardley-dialog-panel\");\n panel.append(header(chrome, parts.title, titleId, close), ...parts.content(close));\n created.append(panel);\n // A press that started on the panel (selecting text, then releasing outside) is no backdrop\n // click; the panel covers all of the dialog's own box, so the backdrop is the dialog itself.\n let pressedOnBackdrop = false;\n created.addEventListener(\"pointerdown\", (event) => {\n pressedOnBackdrop = event.target === created;\n });\n created.addEventListener(\"click\", (event) => {\n if (event.target === created && pressedOnBackdrop) created.close();\n pressedOnBackdrop = false;\n });\n created.addEventListener(\"close\", () => {\n parts.afterClose?.();\n if (!chrome.menu.trigger.hidden) chrome.menu.trigger.focus({ preventScroll: true });\n });\n chrome.root.append(created);\n return created;\n }\n\n return {\n open() {\n dialog ??= build();\n if (dialog.open) return;\n parts.beforeOpen?.();\n dialog.showModal();\n parts.afterOpen?.();\n },\n close() {\n dialog?.close();\n },\n isOpen: () => dialog?.open === true,\n destroy() {\n dialog?.remove();\n dialog = undefined;\n },\n };\n}\n","import { DEFAULT_MAP_TITLE } from \"@miragon/wardley-schema-model\";\nimport type { Modeler } from \"../Modeler.js\";\nimport { isImeCompositionKey } from \"../label-editing/index.js\";\nimport { READ_ONLY_CHANGED } from \"../read-only/index.js\";\nimport { createMapDialog, dialogButton, type DialogChrome, type MapDialog } from \"./dialog.js\";\nimport { element, uniqueId } from \"./dom.js\";\n\nexport type TitleDialogChrome = DialogChrome;\nexport type TitleDialog = MapDialog;\n\nfunction currentTitle(modeler: Modeler): string {\n return modeler.exportMap().config.title ?? DEFAULT_MAP_TITLE;\n}\n\n/**\n * The \"Map title…\" dialog of the Model group: guide §5.4 keeps form fields out of the menu, so the\n * entry opens a dialog (§8) with the title field, Cancel and Apply. Enter applies, Escape and\n * Cancel keep the title; an unchanged title writes nothing, so the map's history gets no empty\n * step. A canvas that turns read-only closes it without writing, as it locks the entry.\n */\nexport function createTitleDialog(chrome: TitleDialogChrome, modeler: Modeler): TitleDialog {\n const field = element(\"input\", \"wardley-field-input\");\n field.id = uniqueId(\"wardley-title-field\");\n field.type = \"text\";\n field.autocomplete = \"off\";\n field.spellcheck = false;\n field.maxLength = 120;\n // showModal() focuses the first focusable element, which would be the header's Close button.\n field.autofocus = true;\n // The form submits on the browser's Enter and the dialog closes on its Escape; while an input\n // method composes, these keys confirm or cancel its candidate instead.\n field.addEventListener(\"keydown\", (event) => {\n if ((event.key === \"Enter\" || event.key === \"Escape\") && isImeCompositionKey(event)) {\n event.preventDefault();\n }\n });\n\n const dialog = createMapDialog(chrome, {\n className: \"wardley-title-dialog\",\n title: \"Map title\",\n beforeOpen() {\n field.value = currentTitle(modeler);\n },\n afterOpen() {\n field.select();\n },\n content(close) {\n const form = element(\"form\", \"wardley-dialog-form\");\n form.noValidate = true;\n const body = element(\"div\", \"wardley-dialog-body\");\n const wrapper = element(\"div\", \"wardley-field\");\n const label = element(\"label\", \"wardley-field-label\", \"Title\");\n label.htmlFor = field.id;\n wrapper.append(label, field);\n body.append(wrapper);\n const footer = element(\"div\", \"wardley-dialog-footer\");\n const cancel = dialogButton(\"Cancel\", \"secondary\");\n cancel.addEventListener(\"click\", close);\n const apply = dialogButton(\"Apply\", \"primary\");\n apply.type = \"submit\";\n footer.append(cancel, apply);\n form.append(body, footer);\n form.addEventListener(\"submit\", (event) => {\n event.preventDefault();\n const title = field.value.replace(/\\s+/g, \" \").trim() || DEFAULT_MAP_TITLE;\n close();\n if (title !== currentTitle(modeler)) modeler.setTitle(title);\n });\n return [form];\n },\n });\n\n const onReadOnly = (event: unknown) => {\n if ((event as { readOnly?: boolean }).readOnly) dialog.close();\n };\n modeler.on(READ_ONLY_CHANGED, onReadOnly);\n return {\n open: () => dialog.open(),\n isOpen: () => dialog.isOpen(),\n close: () => dialog.close(),\n destroy() {\n modeler.off(READ_ONLY_CHANGED, onReadOnly);\n dialog.destroy();\n },\n };\n}\n","import type { Modeler } from \"../Modeler.js\";\nimport { isKeyOnHiddenTarget } from \"../a11y/index.js\";\nimport { isImeCompositionKey } from \"../label-editing/index.js\";\nimport { READ_ONLY_CHANGED } from \"../read-only/index.js\";\nimport { element, uniqueId } from \"./dom.js\";\n\n/** What a popover needs of the chrome around the map; a `@miragon/modeler-shell` handle fits. */\nexport interface PopoverChrome {\n /** Where the popover lives (the shell root): it anchors at the dropdown's place there. */\n readonly root: HTMLElement;\n /** The control the focus returns to after Escape or Done. */\n readonly menu: { readonly trigger: HTMLElement };\n}\n\n/** Why a popover closes: the user is done, an import replaced the map, or the canvas locked. */\nexport type PopoverEnd = \"done\" | \"import\" | \"cancel\";\n\nexport interface PopoverHandle {\n open(): void;\n isOpen(): boolean;\n /** Closes as if the user were done: the previewed change becomes one edit. */\n close(): void;\n destroy(): void;\n}\n\nexport interface PopoverParts {\n readonly className: string;\n readonly title: string;\n /** Fills the body (fields) and the footer (buttons) once; `done` closes like Done. */\n build(body: HTMLElement, footer: HTMLElement, done: () => void): void;\n /** Reads the map into the fields on every open; returns the field to focus. */\n opened(): HTMLElement | undefined;\n /** Commits the preview (`done`) or drops it (`import`: the map is gone, `cancel`: revert). */\n closed(end: PopoverEnd): void;\n}\n\n/**\n * Keeps the `keyup` of an Escape the popover took from the page: diagram-js's dragging cancels the\n * drag a tool armed from the palette waits with on any Escape `keyup` on the document, whatever its\n * target, and the popover stops the `keydown` before the shell's chrome could see it (#498). The next\n * press of Escape lets its own `keyup` through, in case the window lost the focus before this press\n * was released.\n */\nfunction stopEscapeKeyup(): void {\n const onKeyup = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n event.stopPropagation();\n release();\n };\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\" && !event.repeat) release();\n };\n function release(): void {\n document.removeEventListener(\"keyup\", onKeyup, true);\n document.removeEventListener(\"keydown\", onKeydown, true);\n }\n document.addEventListener(\"keyup\", onKeyup, true);\n document.addEventListener(\"keydown\", onKeydown, true);\n}\n\n/**\n * A popover of guide §5.4: a menu entry that needs the canvas preview opens it at the dropdown's\n * place, without a backdrop, as a non-modal `role=\"dialog\"` labelled by its title. Escape and a\n * click outside close it; the focus returns to the menu trigger after Escape and Done, while a\n * click outside leaves it on what was clicked.\n */\nexport function createPopover(\n chrome: PopoverChrome,\n parts: PopoverParts,\n): PopoverHandle & { end(end: PopoverEnd): void } {\n let panel: HTMLElement | undefined;\n\n const onPointerDown = (event: PointerEvent) => {\n if (panel && !panel.contains(event.target as Node)) end(\"done\");\n };\n // A click into the IDE's workbench or another frame takes the focus without a pointerdown here.\n const onWindowBlur = () => end(\"done\");\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || isImeCompositionKey(event) || isKeyOnHiddenTarget(event)) return;\n event.preventDefault();\n event.stopPropagation();\n end(\"done\", { returnFocus: true });\n stopEscapeKeyup();\n };\n\n function build(): HTMLElement {\n const titleId = uniqueId(`${parts.className}-title`);\n const created = element(\"div\", `wardley-popover ${parts.className}`);\n created.setAttribute(\"role\", \"dialog\");\n created.setAttribute(\"aria-labelledby\", titleId);\n created.hidden = true;\n const title = element(\"h2\", \"wardley-popover-title\", parts.title);\n title.id = titleId;\n const body = element(\"div\", \"wardley-popover-body\");\n const footer = element(\"div\", \"wardley-popover-footer\");\n parts.build(body, footer, () => end(\"done\", { returnFocus: true }));\n created.append(title, body, footer);\n created.addEventListener(\"keydown\", onKeyDown);\n chrome.root.append(created);\n return created;\n }\n\n function end(why: PopoverEnd, options: { returnFocus?: boolean } = {}): void {\n if (!panel || panel.hidden) return;\n panel.hidden = true;\n document.removeEventListener(\"pointerdown\", onPointerDown, true);\n window.removeEventListener(\"blur\", onWindowBlur);\n parts.closed(why);\n if (options.returnFocus && !chrome.menu.trigger.hidden) {\n chrome.menu.trigger.focus({ preventScroll: true });\n }\n }\n\n return {\n open() {\n panel ??= build();\n if (!panel.hidden) return;\n panel.hidden = false;\n const field = parts.opened();\n document.addEventListener(\"pointerdown\", onPointerDown, true);\n window.addEventListener(\"blur\", onWindowBlur);\n field?.focus();\n if (field instanceof HTMLInputElement) field.select();\n },\n isOpen: () => panel?.hidden === false,\n close: () => end(\"done\"),\n end: (why) => end(why),\n destroy() {\n end(\"cancel\");\n panel?.remove();\n panel = undefined;\n },\n };\n}\n\n/** A labelled field of guide §8: the label above, 4px apart, an error below it when refused. */\nexport function field(\n label: string,\n control: HTMLInputElement | HTMLSelectElement,\n): { wrapper: HTMLElement; showError(message: string): void; clearError(): void } {\n const wrapper = element(\"div\", \"wardley-field\");\n const id = uniqueId(\"wardley-field\");\n const caption = element(\"label\", \"wardley-field-label\", label);\n caption.htmlFor = id;\n control.id = id;\n control.classList.add(\"wardley-field-input\");\n wrapper.append(caption, control);\n let error: HTMLElement | undefined;\n return {\n wrapper,\n showError(message) {\n if (!error) {\n error = element(\"p\", \"wardley-field-error\");\n error.id = `${id}-error`;\n error.setAttribute(\"role\", \"alert\");\n wrapper.append(error);\n }\n error.textContent = message;\n control.setAttribute(\"aria-invalid\", \"true\");\n control.setAttribute(\"aria-describedby\", error.id);\n },\n clearError() {\n error?.remove();\n error = undefined;\n control.removeAttribute(\"aria-invalid\");\n control.removeAttribute(\"aria-describedby\");\n },\n };\n}\n\n/**\n * Closes `popover` without committing when the map is replaced (an import: the preview went with\n * the old map) or turns read-only (the preview is put back), and stops listening on destroy.\n */\nexport function withMapListeners(\n modeler: Modeler,\n popover: PopoverHandle & { end(end: PopoverEnd): void },\n): PopoverHandle {\n const onImport = () => popover.end(\"import\");\n const onReadOnly = (event: unknown) => {\n if ((event as { readOnly?: boolean }).readOnly) popover.end(\"cancel\");\n };\n modeler.on(\"import.done\", onImport);\n modeler.on(READ_ONLY_CHANGED, onReadOnly);\n return {\n open: () => popover.open(),\n isOpen: () => popover.isOpen(),\n close: () => popover.close(),\n destroy() {\n modeler.off(\"import.done\", onImport);\n modeler.off(READ_ONLY_CHANGED, onReadOnly);\n popover.destroy();\n },\n };\n}\n","import {\n MAP_SIZE_PRESETS,\n PLOT_MAX,\n PLOT_MIN,\n parsePlotLength,\n plotLengthMessage,\n} from \"@miragon/wardley-schema-model\";\nimport { isKeyOnHiddenTarget } from \"../a11y/index.js\";\nimport type { Modeler } from \"../Modeler.js\";\nimport type { MapSizeInfo } from \"../WardleyBaseViewer.js\";\nimport { element } from \"./dom.js\";\nimport { dialogButton } from \"./dialog.js\";\nimport {\n createPopover,\n field,\n withMapListeners,\n type PopoverChrome,\n type PopoverHandle,\n} from \"./popover.js\";\n\nconst CUSTOM = \"custom\";\n\n/** The size the popover last drew; `undefined` = the default size without a `size` line. */\ntype Target = { width: number; height: number } | undefined;\n\nfunction numberInput(min: number, max: number): HTMLInputElement {\n const input = element(\"input\", \"\");\n input.type = \"number\";\n input.inputMode = \"numeric\";\n input.min = String(min);\n input.max = String(max);\n input.step = \"10\";\n return input;\n}\n\n/**\n * \"Map size…\" (guide §5.4): presets, a custom width × height and a reset to the default size. Every\n * choice is drawn at once as a preview without an undo step; closing writes ONE edit (none when the\n * map ends at the size it had). An import while it is open closes it without writing, and so does\n * a canvas that turns read-only, after putting the previous size back.\n */\nexport function createMapSizePopover(chrome: PopoverChrome, modeler: Modeler): PopoverHandle {\n const preset = element(\"select\", \"\");\n for (const choice of MAP_SIZE_PRESETS) {\n const option = element(\"option\", \"\", `${choice.name} (${choice.width} × ${choice.height})`);\n option.value = choice.id;\n preset.append(option);\n }\n const custom = element(\"option\", \"\", \"Custom\");\n custom.value = CUSTOM;\n preset.append(custom);\n const width = numberInput(PLOT_MIN.width, PLOT_MAX.width);\n const height = numberInput(PLOT_MIN.height, PLOT_MAX.height);\n const reset = dialogButton(\"Reset to default\", \"ghost\");\n const sizeField = field(\"Size\", preset);\n const widthField = field(\"Width\", width);\n const heightField = field(\"Height\", height);\n\n let atOpen: MapSizeInfo | undefined;\n let target: { size: Target } | undefined;\n\n const show = (size: MapSizeInfo) => {\n preset.value = size.presetId ?? CUSTOM;\n width.value = String(size.width);\n height.value = String(size.height);\n reset.disabled = !size.isExplicit;\n widthField.clearError();\n heightField.clearError();\n };\n\n const preview = (size: Target) => {\n target = { size };\n const applied = size\n ? modeler.setMapSize(size.width, size.height, { transient: true })\n : modeler.resetMapSize({ transient: true });\n void applied.then(() => show(modeler.getMapSize()));\n };\n\n const applyLength = (input: HTMLInputElement, axis: \"width\" | \"height\") => {\n const fieldOf = axis === \"width\" ? widthField : heightField;\n const length = parsePlotLength(input.value, axis);\n if (length === undefined) {\n fieldOf.showError(plotLengthMessage(axis));\n return;\n }\n fieldOf.clearError();\n const current = modeler.getMapSize();\n if (length === current[axis]) return;\n preview({ width: current.width, height: current.height, [axis]: length });\n };\n\n const popover = createPopover(chrome, {\n className: \"wardley-map-size\",\n title: \"Map size\",\n build(body, footer, done) {\n const lengths = element(\"div\", \"wardley-field-row\");\n const times = element(\"span\", \"wardley-field-times\", \"×\");\n times.setAttribute(\"aria-hidden\", \"true\");\n lengths.append(widthField.wrapper, times, heightField.wrapper);\n const hint = element(\"p\", \"wardley-popover-hint\", \"Or drag the plot’s right or bottom edge.\");\n body.append(sizeField.wrapper, lengths, hint);\n const doneButton = dialogButton(\"Done\", \"secondary\");\n doneButton.addEventListener(\"click\", (event) => {\n if (!isKeyOnHiddenTarget(event)) done();\n });\n footer.append(reset, doneButton);\n\n preset.addEventListener(\"change\", () => {\n const choice = MAP_SIZE_PRESETS.find((candidate) => candidate.id === preset.value);\n if (choice) preview({ width: choice.width, height: choice.height });\n else width.focus();\n });\n width.addEventListener(\"change\", () => applyLength(width, \"width\"));\n height.addEventListener(\"change\", () => applyLength(height, \"height\"));\n reset.addEventListener(\"click\", (event) => {\n if (isKeyOnHiddenTarget(event)) return;\n // Reset disables itself, which would drop the focus out of the popover.\n preset.focus();\n preview(undefined);\n });\n },\n opened() {\n atOpen = modeler.getMapSize();\n target = undefined;\n show(atOpen);\n return preset;\n },\n closed(end) {\n const previewed = target;\n target = undefined;\n // An import already dropped the preview together with the map it was drawn on.\n if (!previewed || end === \"import\") return;\n // Committing the size at open puts it back without an undo step.\n const size = end === \"done\" ? previewed.size : sizeOf(atOpen);\n void (size ? modeler.setMapSize(size.width, size.height) : modeler.resetMapSize());\n },\n });\n\n return withMapListeners(modeler, popover);\n}\n\nfunction sizeOf(info: MapSizeInfo | undefined): Target {\n return info?.isExplicit ? { width: info.width, height: info.height } : undefined;\n}\n","import {\n DEFAULT_EVOLUTION_LABELS,\n EVOLUTION_PRESETS,\n normalizeEvolutionLabels,\n} from \"@miragon/wardley-schema-model\";\nimport { isKeyOnHiddenTarget } from \"../a11y/index.js\";\nimport { isImeCompositionKey } from \"../label-editing/index.js\";\nimport type { Modeler } from \"../Modeler.js\";\nimport { element } from \"./dom.js\";\nimport { dialogButton } from \"./dialog.js\";\nimport {\n createPopover,\n field,\n withMapListeners,\n type PopoverChrome,\n type PopoverHandle,\n} from \"./popover.js\";\n\nconst CUSTOM = \"custom\";\n\nfunction presetIdFor(labels: readonly string[]): string {\n return (\n EVOLUTION_PRESETS.find((preset) => preset.labels.every((label, i) => label === labels[i]))\n ?.id ?? CUSTOM\n );\n}\n\n/**\n * \"X-axis labels…\" (guide §5.4): a preset or four free stage names. Typing previews on the axis\n * without touching the document; closing commits ONE edit, so the document gets one change and\n * an IDE one undo step per session. An import while it is open closes it without committing, and\n * so does a canvas that turns read-only, after putting the previous labels back.\n */\nexport function createAxisLabelsPopover(chrome: PopoverChrome, modeler: Modeler): PopoverHandle {\n const preset = element(\"select\", \"\");\n for (const choice of EVOLUTION_PRESETS) {\n const option = element(\"option\", \"\", choice.name);\n option.value = choice.id;\n option.title = choice.labels.join(\" · \");\n preset.append(option);\n }\n const custom = element(\"option\", \"\", \"Custom\");\n custom.value = CUSTOM;\n preset.append(custom);\n const inputs = [1, 2, 3, 4].map(() => {\n const input = element(\"input\", \"\");\n input.type = \"text\";\n input.autocomplete = \"off\";\n input.spellcheck = false;\n return input;\n });\n\n let labelsAtOpen: readonly string[] = DEFAULT_EVOLUTION_LABELS;\n let previewed = false;\n\n const fill = (labels: readonly string[]) => {\n inputs.forEach((input, index) => (input.value = labels[index] ?? \"\"));\n preset.value = presetIdFor(labels);\n };\n const typedLabels = () => normalizeEvolutionLabels(inputs.map((input) => input.value));\n const preview = () => {\n previewed = true;\n const labels = typedLabels();\n modeler.setEvolutionLabels(labels, { transient: true });\n preset.value = presetIdFor(labels ?? DEFAULT_EVOLUTION_LABELS);\n };\n\n const popover = createPopover(chrome, {\n className: \"wardley-axis-labels\",\n title: \"X-axis labels\",\n build(body, footer, done) {\n const hint = element(\"p\", \"wardley-popover-hint\");\n const source = element(\"a\", \"wardley-popover-link\", \"Learn Wardley Mapping\");\n source.href = \"https://learnwardleymapping.com/landscape/\";\n source.target = \"_blank\";\n source.rel = \"noopener noreferrer\";\n hint.append(\"Label sets from \", source, \". Pick a set, or name each stage.\");\n body.append(field(\"Preset\", preset).wrapper, hint);\n inputs.forEach((input, index) => body.append(field(`Stage ${index + 1}`, input).wrapper));\n const reset = dialogButton(\"Reset to default\", \"ghost\");\n const doneButton = dialogButton(\"Done\", \"secondary\");\n footer.append(reset, doneButton);\n\n preset.addEventListener(\"change\", () => {\n const choice = EVOLUTION_PRESETS.find((candidate) => candidate.id === preset.value);\n if (!choice) return; // \"Custom\" keeps the fields as they are\n fill(choice.labels);\n preview();\n });\n for (const input of inputs) {\n input.addEventListener(\"input\", preview);\n input.addEventListener(\"keydown\", (event) => {\n if (event.key !== \"Enter\" || isImeCompositionKey(event) || isKeyOnHiddenTarget(event))\n return;\n event.preventDefault();\n done();\n });\n }\n reset.addEventListener(\"click\", (event) => {\n if (isKeyOnHiddenTarget(event)) return;\n fill(DEFAULT_EVOLUTION_LABELS);\n preview();\n });\n doneButton.addEventListener(\"click\", (event) => {\n if (!isKeyOnHiddenTarget(event)) done();\n });\n },\n opened() {\n labelsAtOpen = modeler.exportMap().config.evolutionLabels ?? DEFAULT_EVOLUTION_LABELS;\n previewed = false;\n fill(labelsAtOpen);\n return inputs[0];\n },\n closed(end) {\n if (!previewed || end === \"import\") return;\n previewed = false;\n // Committing the labels at open puts them back without an undo step.\n modeler.setEvolutionLabels(\n end === \"done\" ? typedLabels() : normalizeEvolutionLabels(labelsAtOpen),\n );\n },\n });\n\n return withMapListeners(modeler, popover);\n}\n"],"mappings":"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"}
|