@miragon/context-maps-renderer 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +23 -21
  2. package/dist/CmBaseViewer.d.ts.map +1 -1
  3. package/dist/Modeler.d.ts +3 -2
  4. package/dist/Modeler.d.ts.map +1 -1
  5. package/dist/behaviors/CmFlatModelBehavior.d.ts.map +1 -1
  6. package/dist/context-maps.css +1 -1
  7. package/dist/context-pad/CmContextPadProvider.d.ts +96 -0
  8. package/dist/context-pad/CmContextPadProvider.d.ts.map +1 -0
  9. package/dist/context-pad/index.d.ts +4 -0
  10. package/dist/context-pad/index.d.ts.map +1 -0
  11. package/dist/draw/ContextMapsRenderer.d.ts +4 -0
  12. package/dist/draw/ContextMapsRenderer.d.ts.map +1 -1
  13. package/dist/draw/icons.d.ts +6 -0
  14. package/dist/draw/icons.d.ts.map +1 -1
  15. package/dist/draw/palette-icons.d.ts +8 -3
  16. package/dist/draw/palette-icons.d.ts.map +1 -1
  17. package/dist/draw/styles.d.ts +11 -0
  18. package/dist/draw/styles.d.ts.map +1 -1
  19. package/dist/index.d.ts +3 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1017 -447
  22. package/dist/index.js.map +1 -1
  23. package/dist/label-editing/CmLabelEditing.d.ts +39 -3
  24. package/dist/label-editing/CmLabelEditing.d.ts.map +1 -1
  25. package/dist/label-editing/index.d.ts +1 -1
  26. package/dist/label-editing/index.d.ts.map +1 -1
  27. package/dist/legend/CmLegend.d.ts +15 -0
  28. package/dist/legend/CmLegend.d.ts.map +1 -0
  29. package/dist/legend/index.d.ts +4 -0
  30. package/dist/legend/index.d.ts.map +1 -0
  31. package/dist/model/CmElementFactory.d.ts +2 -1
  32. package/dist/model/CmElementFactory.d.ts.map +1 -1
  33. package/dist/palette/CmPaletteProvider.d.ts +3 -1
  34. package/dist/palette/CmPaletteProvider.d.ts.map +1 -1
  35. package/dist/palette/index.d.ts +1 -1
  36. package/dist/palette/index.d.ts.map +1 -1
  37. package/dist/rules/CmRules.d.ts.map +1 -1
  38. package/dist/rules/index.d.ts +1 -1
  39. package/dist/rules/index.d.ts.map +1 -1
  40. package/package.json +4 -3
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/model/di-types.ts","../src/io/saveSvg.ts","../src/io/types.ts","../src/CmBaseViewer.ts","../src/model/CmElementFactory.ts","../src/model/CmDiagramElementFactory.ts","../src/model/CmLayouter.ts","../src/model/index.ts","../src/theme/palette.ts","../src/draw/styles.ts","../src/draw/endRoleChips.ts","../src/draw/ContextMapsRenderer.ts","../src/draw/index.ts","../src/io/CmImporter.ts","../src/io/CmExporter.ts","../src/io/index.ts","../src/Viewer.ts","../src/NavigatedViewer.ts","../src/modeling/cmd/UpdatePropertiesHandler.ts","../src/modeling/cmd/SwapEndsHandler.ts","../src/modeling/CmModeling.ts","../src/modeling/index.ts","../src/rules/CmRules.ts","../src/rules/index.ts","../src/behaviors/CmFlatModelBehavior.ts","../src/behaviors/CmDragBehavior.ts","../src/behaviors/CmClickSelectionBehavior.ts","../src/behaviors/index.ts","../src/draw/palette-icons.ts","../src/palette/CmPaletteProvider.ts","../src/palette/index.ts","../src/draw/icons.ts","../src/connect-handles/CmConnectHandles.ts","../src/connect-handles/index.ts","../src/label-editing/CmLabelEditing.ts","../src/label-editing/index.ts","../src/keyboard/CmKeyboard.ts","../src/keyboard/index.ts","../src/validation/CmValidationMarkers.ts","../src/validation/index.ts","../src/zorder/CmZOrder.ts","../src/zorder/index.ts","../src/Modeler.ts"],"sourcesContent":["/**\n * diagram-js runtime model for the Context Maps notation.\n *\n * - `context` — a bounded context: a placed, resizable SHAPE (box) with a\n * label, optional owning team and subdomain classification.\n * - `relationship` — a context-mapping pattern: a CONNECTION (edge) between two\n * contexts, carrying a pattern plus upstream/downstream roles.\n *\n * These runtime properties are the source of truth while editing; the exporter\n * rebuilds the canonical `CmDocument` from them.\n */\n\nimport type { Connection, Shape } from \"diagram-js/lib/model/Types\";\nimport type {\n DownstreamRole,\n RelationshipPattern,\n SubdomainType,\n UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\n\nexport type CmKind = \"context\" | \"relationship\";\n\nexport interface CmContext extends Shape {\n cmKind: \"context\";\n subdomainType?: SubdomainType;\n /** Display name (separate from diagram-js `label`). */\n cmLabel?: string;\n team?: string;\n description?: string;\n fill?: string;\n stroke?: string;\n}\n\nexport interface CmRelationship extends Connection {\n cmKind: \"relationship\";\n pattern: RelationshipPattern;\n upstreamRoles?: UpstreamRole[];\n downstreamRoles?: DownstreamRole[];\n cmLabel?: string;\n description?: string;\n implementationTechnology?: string;\n}\n\nexport type CmElement = CmContext | CmRelationship;\n\nfunction kindOf(el: unknown): string | undefined {\n return typeof el === \"object\" && el !== null\n ? ((el as { cmKind?: unknown }).cmKind as string | undefined)\n : undefined;\n}\n\nexport function isCmElement(el: unknown): el is CmElement {\n return typeof kindOf(el) === \"string\";\n}\n\nexport function isCmContext(el: unknown): el is CmContext {\n return kindOf(el) === \"context\";\n}\n\nexport function isCmRelationship(el: unknown): el is CmRelationship {\n return kindOf(el) === \"relationship\";\n}\n","/**\n * Serialises the current canvas into a standalone SVG (snapshot / export),\n * fitted to the content bounds and independent of the current zoom / scroll.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport { isCmContext } from \"../model/di-types.js\";\n\nconst MARGIN = 40;\n\nexport function saveSVG(canvas: Canvas, elementRegistry: ElementRegistry): { svg: string } {\n const container = canvas.getContainer();\n const source = container.querySelector(\"svg\");\n if (!source) throw new Error(\"No SVG found in the canvas container.\");\n\n // Content bounds from the context boxes (relationship lines stay within them).\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const el of elementRegistry.getAll()) {\n if (!isCmContext(el)) continue;\n const s = el as unknown as { x: number; y: number; width: number; height: number };\n minX = Math.min(minX, s.x);\n minY = Math.min(minY, s.y);\n maxX = Math.max(maxX, s.x + s.width);\n maxY = Math.max(maxY, s.y + s.height);\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 100;\n maxY = 100;\n }\n\n const x = minX - MARGIN;\n const y = minY - MARGIN;\n const width = maxX - minX + MARGIN * 2;\n const height = maxY - minY + MARGIN * 2;\n\n const clone = source.cloneNode(true) as SVGSVGElement;\n clone.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n clone.setAttribute(\"viewBox\", `${x} ${y} ${width} ${height}`);\n clone.setAttribute(\"width\", String(Math.round(width)));\n clone.setAttribute(\"height\", String(Math.round(height)));\n\n // Neutralise pan/zoom: let the viewBox (above) drive 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","/** ID of the diagram-js root element holding the Context Maps diagram. */\nexport const ROOT_ID = \"cm-root\";\n\nexport interface ImportWarning {\n readonly message: string;\n readonly elementId?: string;\n}\n\n/** Diagram-level metadata stashed on the root element. */\nexport interface RootBusinessObject {\n title: string;\n}\n","/**\n * Shared lifecycle & DI bootstrap for every Context Maps viewer. Subclasses\n * only override `_getModules()`. The renderer\n * is framework-agnostic — mount it into any element (e.g. a VS Code webview).\n */\n\nimport Diagram from \"diagram-js/lib/Diagram\";\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 { Root } from \"diagram-js/lib/model/Types\";\nimport type { CmDocument } from \"@miragon/context-maps-schema-model\";\nimport { saveSVG } from \"./io/saveSvg.js\";\nimport type CmImporter from \"./io/CmImporter.js\";\nimport type CmExporter from \"./io/CmExporter.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./io/types.js\";\n\nexport interface CmViewerOptions {\n /** Host element. When absent, a detached <div> is created (attach later). */\n container?: HTMLElement;\n width?: number | string;\n height?: number | string;\n /** Appended to the module list (extension point). */\n additionalModules?: ModuleDeclaration[];\n}\n\nexport type EventCallback<T = unknown> = (event: T) => void;\n\ntype RootWithMeta = Root & { businessObject?: RootBusinessObject };\n\nfunction sizeToCss(value: number | string): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\nexport abstract class CmBaseViewer {\n protected abstract _getModules(): ModuleDeclaration[];\n\n private _diagram: Diagram | undefined;\n private readonly _container: HTMLElement;\n private readonly _options: CmViewerOptions;\n\n constructor(options: CmViewerOptions = {}) {\n this._options = options;\n this._container = this._createContainer(options);\n }\n\n private _createContainer(options: CmViewerOptions): HTMLElement {\n const container = options.container ?? document.createElement(\"div\");\n container.classList.add(\"cm-djs-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({ canvas: { container: this._container }, modules });\n }\n return this._diagram;\n }\n\n /** Resolve a diagram-js service from the didi injector. */\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 /** Load a document into the canvas (replaces existing content). */\n importDocument(doc: CmDocument): { warnings: ImportWarning[] } {\n const diagram = this._ensureDiagram();\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const importer = diagram.get<CmImporter>(\"cmImporter\");\n importer.clear();\n const warnings = importer.import(doc);\n this._fit();\n eventBus.fire(\"import.done\", { warnings });\n return { warnings };\n }\n\n /** Current canvas state as a canonical document. */\n exportDocument(): CmDocument {\n return this.get<CmExporter>(\"cmExporter\").export();\n }\n\n /** Update diagram-level metadata (title / flow-of-change) on the root. */\n setMeta(partial: Partial<RootBusinessObject>): void {\n const canvas = this.get<Canvas>(\"canvas\");\n let root: RootWithMeta | undefined;\n try {\n root = canvas.getRootElement() as RootWithMeta;\n } catch {\n return;\n }\n if (!root || root.id !== ROOT_ID) return;\n const current = root.businessObject ?? { title: \"Untitled context map\" };\n root.businessObject = { ...current, ...partial };\n }\n\n /** Read diagram-level metadata (title / flow-of-change) from the root. */\n getMeta(): RootBusinessObject | undefined {\n try {\n const root = this.get<Canvas>(\"canvas\").getRootElement() as RootWithMeta;\n return root.businessObject;\n } catch {\n return undefined;\n }\n }\n\n /** Standalone, self-contained SVG snapshot. */\n saveSVG(): { svg: string } {\n return saveSVG(this.get<Canvas>(\"canvas\"), this.get<ElementRegistry>(\"elementRegistry\"));\n }\n\n /** Fit the content into the viewport, leaving room at the top for the palette. */\n private _fit(topInset = 84, pad = 56): void {\n const canvas = this.get<Canvas>(\"canvas\");\n const registry = this.get<ElementRegistry>(\"elementRegistry\");\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const el of registry.getAll()) {\n const e = el as { x?: number; y?: number; width?: number; height?: number };\n if (\n typeof e.x !== \"number\" ||\n typeof e.y !== \"number\" ||\n typeof e.width !== \"number\" ||\n typeof e.height !== \"number\"\n ) {\n continue;\n }\n minX = Math.min(minX, e.x);\n minY = Math.min(minY, e.y);\n maxX = Math.max(maxX, e.x + e.width);\n maxY = Math.max(maxY, e.y + e.height);\n }\n if (!Number.isFinite(minX)) return;\n\n const rect = this._container.getBoundingClientRect();\n const W = rect.width;\n const H = rect.height;\n const cw = Math.max(maxX - minX, 1);\n const ch = Math.max(maxY - minY, 1);\n if (!W || !H) {\n canvas.zoom(\"fit-viewport\");\n return;\n }\n const s = Math.min((W - 2 * pad) / cw, (H - topInset - pad) / ch, 1.25);\n canvas.viewbox({\n x: minX + cw / 2 - W / 2 / s,\n y: minY - topInset / s,\n width: W / s,\n height: H / s,\n });\n }\n\n /** Attach the container into `target`. */\n attachTo(target: HTMLElement): void {\n target.appendChild(this._container);\n this.get<Canvas>(\"canvas\").resized();\n }\n\n /** Detach the container from the DOM, preserving 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","/**\n * Creates diagram-js runtime elements carrying Context Maps markers: bounded\n * contexts (shapes) and relationships (connections), from canonical document\n * elements (import) or from scratch (palette / context-pad create).\n */\n\nimport type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { SUBDOMAIN_TYPE_SPECS } from \"@miragon/context-maps-schema-model\";\nimport type {\n BoundedContext,\n Relationship,\n SubdomainType,\n} from \"@miragon/context-maps-schema-model\";\nimport type { CmContext, CmRelationship } from \"./di-types.js\";\n\nexport default class CmElementFactory {\n static $inject = [\"elementFactory\"];\n\n constructor(private readonly elementFactory: ElementFactory) {}\n\n // --- from canonical document elements (import) -------------------------\n\n createContext(ctx: BoundedContext): CmContext {\n return this.elementFactory.createShape({\n id: ctx.id,\n x: ctx.position.x,\n y: ctx.position.y,\n width: ctx.size.width,\n height: ctx.size.height,\n cmKind: \"context\",\n cmLabel: ctx.label,\n ...(ctx.subdomainType ? { subdomainType: ctx.subdomainType } : {}),\n ...(ctx.team ? { team: ctx.team } : {}),\n ...(ctx.description ? { description: ctx.description } : {}),\n ...(ctx.fill ? { fill: ctx.fill } : {}),\n ...(ctx.stroke ? { stroke: ctx.stroke } : {}),\n } as Partial<CmContext>) as unknown as CmContext;\n }\n\n createRelationship(\n rel: Relationship,\n source: CmContext,\n target: CmContext,\n waypoints: Point[],\n ): CmRelationship {\n return this.elementFactory.createConnection({\n id: rel.id,\n source,\n target,\n waypoints,\n cmKind: \"relationship\",\n pattern: rel.pattern,\n ...(rel.upstreamRoles?.length ? { upstreamRoles: [...rel.upstreamRoles] } : {}),\n ...(rel.downstreamRoles?.length ? { downstreamRoles: [...rel.downstreamRoles] } : {}),\n ...(rel.label ? { cmLabel: rel.label } : {}),\n ...(rel.description ? { description: rel.description } : {}),\n ...(rel.implementationTechnology\n ? { implementationTechnology: rel.implementationTechnology }\n : {}),\n } as unknown as Partial<CmRelationship>) as unknown as CmRelationship;\n }\n\n // --- fresh, not-yet-placed elements (palette / context-pad create) -----\n //\n // No explicit id: the element factory (CmDiagramElementFactory) assigns a\n // collision-free model-style id (`ctx_…`).\n\n createNewContext(subdomainType: SubdomainType, label?: string): CmContext {\n const spec = SUBDOMAIN_TYPE_SPECS[subdomainType];\n return this.elementFactory.createShape({\n width: spec.defaultSize.width,\n height: spec.defaultSize.height,\n cmKind: \"context\",\n subdomainType,\n cmLabel: label ?? \"New Context\",\n } as Partial<CmContext>) as unknown as CmContext;\n }\n}\n","/**\n * Element factory that assigns model-style random ids (`ctx_…`, `rel_…`) when\n * none is provided. diagram-js' stock factory numbers elements with a session\n * counter that restarts on every page load and is never advanced past ids\n * arriving via import — after a reload, drawing a connection would re-generate\n * an id already taken by an imported relationship (e.g. `connection_13`) and\n * the create command would die with \"element already exists\", silently\n * dropping the just-drawn line.\n */\n\nimport ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type { Connection, Label, Root, Shape } from \"diagram-js/lib/model/Types\";\nimport { newId } from \"@miragon/context-maps-schema-model\";\n\nexport default class CmDiagramElementFactory extends ElementFactory {\n override create(type: \"root\", attrs?: Partial<Root>): Root;\n override create(type: \"shape\", attrs?: Partial<Shape>): Shape;\n override create(type: \"connection\", attrs?: Partial<Connection>): Connection;\n override create(type: \"label\", attrs?: Partial<Label>): Label;\n override create(\n type: \"root\" | \"shape\" | \"connection\" | \"label\",\n attrs?: Partial<Root | Shape | Connection | Label>,\n ): Root | Shape | Connection | Label {\n if (!attrs?.id && (type === \"shape\" || type === \"connection\")) {\n attrs = { ...attrs, id: newId(type === \"shape\" ? \"ctx\" : \"rel\") };\n }\n return super.create(type as \"shape\", attrs as Partial<Shape>);\n }\n}\n","/**\n * Straight-line connection layouter that crops the waypoints to the context box\n * borders via the cropping docking. diagram-js' stock BaseLayouter only returns\n * mid(source)→mid(target), so without this the relationship line would run from\n * box centre to box centre (visibly starting inside the boxes).\n */\n\nimport { getMid } from \"diagram-js/lib/layout/LayoutUtil\";\nimport type CroppingConnectionDocking from \"diagram-js/lib/layout/CroppingConnectionDocking\";\nimport type { ConnectionLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\n\ninterface LayoutHints {\n /**\n * diagram-js may pass a Point (drag anchor) or `false` (end did not move,\n * e.g. MoveHelper's `connectionStart: sourceMoved && anchor`) here.\n */\n connectionStart?: Point | false;\n connectionEnd?: Point | false;\n source?: ShapeLike;\n target?: ShapeLike;\n}\n\nexport default class CmLayouter {\n static $inject = [\"connectionDocking\"];\n\n constructor(private readonly docking: CroppingConnectionDocking) {}\n\n layoutConnection(connection: ConnectionLike, hints: LayoutHints = {}): Point[] {\n const source = hints.source ?? connection.source;\n const target = hints.target ?? connection.target;\n // A relationship line always aims at the CENTRE of its contexts (then gets\n // cropped to the borders below). Anchor hints are deliberately ignored when\n // the shape is known: diagram-js' move helpers pass stale/shifted anchors\n // (the box may already have been relaid out), which would detach the line.\n // Hints only matter while an end has no shape yet (connect rubber band).\n const start = source ? getMid(source) : hints.connectionStart || undefined;\n const end = target ? getMid(target) : hints.connectionEnd || undefined;\n\n const provisional: Point[] = [start, end].filter(Boolean) as Point[];\n // Give the connection a straight line so the docking can crop it to the\n // shape borders. Falls back to the raw line if either end is missing.\n connection.waypoints = provisional;\n if (source && target && provisional.length === 2) {\n return this.docking.getCroppedWaypoints(connection, source, target);\n }\n return provisional;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CroppingConnectionDocking from \"diagram-js/lib/layout/CroppingConnectionDocking\";\nimport CmElementFactory from \"./CmElementFactory.js\";\nimport CmDiagramElementFactory from \"./CmDiagramElementFactory.js\";\n\n/**\n * Element factory with Context Maps defaults, plus the cropping docking so\n * relationship lines dock to the context box borders. The layouter itself is\n * bound in the modeling module (see there) because diagram-js' ModelingModule\n * binds a default `layouter` and loads after this one. The stock\n * `elementFactory` is replaced so every element gets a collision-free id\n * (see CmDiagramElementFactory).\n */\nexport const cmModelModule: ModuleDeclaration = {\n elementFactory: [\"type\", CmDiagramElementFactory],\n cmElementFactory: [\"type\", CmElementFactory],\n connectionDocking: [\"type\", CroppingConnectionDocking],\n};\n\nexport { default as CmElementFactory } from \"./CmElementFactory.js\";\nexport { default as CmDiagramElementFactory } from \"./CmDiagramElementFactory.js\";\nexport { default as CmLayouter } from \"./CmLayouter.js\";\nexport * from \"./di-types.js\";\n","/**\n * Miragon design tokens — the single source of truth for every non-notation colour in the renderer.\n *\n * Values mirror the Miragon corporate identity: the `miragon-brand:corporate-design` skill in\n * `Miragon/corporate-identity`, whose vendored `cd-tokens.generated.css` (next to this file) defines\n * the `--cd-*` custom properties, generated from the brand's `tokens.json`. Re-copy that CSS from the\n * corporate-identity repo to update; never fork the hex values by hand. `theme.sync.test.ts` fails if\n * this mirror drifts from the vendored CSS.\n *\n * Pure data — no DOM, no imports — so it can be consumed by the SVG-drawing constants in\n * `draw/styles.ts`.\n *\n * Brand rule: blue leads (`blau` — surfaces, buttons, links, selection), green accents (`gruen` — key\n * visual, highlights; a fill, never body text on white). The subdomain-type fills and\n * relationship-pattern strokes are the official Context Maps notation and live in\n * `schema-model/notation.ts` — they are NOT part of this brand ramp.\n */\n\n/** Raw Miragon brand ramp + functional layer — exact `--cd-*` values. */\nexport const MIRAGON = {\n /** Primary: surfaces, buttons, links, selection, 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 accents on dark surfaces (unused here — the canvas is light-only). */\n blauHell: \"#6B8AFF\",\n /** Accent: key visual, highlights, the brand gradient. Bright — a fill, never text on white. */\n gruen: \"#00E676\",\n /** Calm neutral surface (warm off-white) — the paper surround. */\n grau: \"#F9F7F7\",\n /** Text on light; not pure black. */\n schwarz: \"#1D1D1D\",\n weiss: \"#FFFFFF\",\n /** Functional / status layer (own layer beside the brand palette; AA as text on white). */\n success: \"#0B7A55\",\n warning: \"#92610A\",\n danger: \"#C92A2A\",\n info: \"#2B50D4\",\n /** Signature brand gradient — brand moments only. Use verbatim. */\n gradientBrand: \"linear-gradient(120deg, #335DE5 30%, #00E676)\",\n} as const;\n\n/**\n * Every `--cd-*` token this repo depends on, mapped to the value it MUST hold. The drift test parses\n * `cd-tokens.generated.css` and asserts each entry matches, so re-copying the vendored CSS with a\n * changed value fails CI until this mirror (and `MIRAGON`) is updated too.\n */\nexport const CD_TOKENS: Record<string, string> = {\n \"--cd-blau\": MIRAGON.blau,\n \"--cd-gruen\": MIRAGON.gruen,\n \"--cd-grau\": MIRAGON.grau,\n \"--cd-schwarz\": MIRAGON.schwarz,\n \"--cd-weiss\": MIRAGON.weiss,\n \"--cd-blau-link\": MIRAGON.blauLink,\n \"--cd-blau-hell\": MIRAGON.blauHell,\n \"--cd-success\": MIRAGON.success,\n \"--cd-success-soft\": \"rgba(11, 122, 85, 0.12)\",\n \"--cd-warning\": MIRAGON.warning,\n \"--cd-warning-soft\": \"rgba(146, 97, 10, 0.12)\",\n \"--cd-danger\": MIRAGON.danger,\n \"--cd-danger-soft\": \"rgba(201, 42, 42, 0.12)\",\n \"--cd-info\": MIRAGON.info,\n \"--cd-info-soft\": \"rgba(43, 80, 212, 0.12)\",\n \"--cd-gradient-brand\": MIRAGON.gradientBrand,\n};\n","/** Shared rendering constants (typography, accent, priorities) — Miragon corporate identity.\n * Colours are derived from the single source of truth in `theme/palette.ts` (`MIRAGON`), which\n * mirrors the vendored `--cd-*` brand tokens. */\n\nimport { MIRAGON } from \"../theme/index.js\";\n\n/** BaseRenderer default priority is 1000; 1500 wins the render.shape/connection event. */\nexport const TT_RENDER_PRIORITY = 1500;\n\n/** Selection / hover accent (Miragon blue — kept in sync with the app theme via the shared palette). */\nexport const ACCENT = MIRAGON.blau;\n\nexport const INK = MIRAGON.schwarz;\nexport const INK_SOFT = \"#5B5B5B\";\n\nexport const FONT = {\n /**\n * Set directly as the `font-family` attribute on every SVG <text> (canvas\n * labels and therefore the SVG export too) — not inherited from a CSS\n * container. Prefers the self-hosted Miragon typeface Geist (registered as\n * 'Geist Variable' by @fontsource-variable/geist, with 'Geist' as a fallback\n * name), and falls back to a system sans when the host hasn't loaded it (e.g.\n * an exported SVG opened standalone).\n */\n family:\n \"'Geist Variable', 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif\",\n label: 13.5,\n small: 11,\n} as const;\n\n/** Paper colour used for the label halo so text stays legible over lines. */\nexport const PAPER = MIRAGON.weiss;\n","/**\n * Geometry of the role-chip group at a relationship end (the OHS/PL/ACL/CF\n * badges next to the direction letter). Kept in one place so the renderer\n * (which draws the chips) and the validation markers (which anchor to the\n * chips' bottom-right corner) can never drift apart.\n */\n\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { FONT } from \"./styles.js\";\n\nexport interface EndRoleChipLayout {\n /** The parent box around all chips of this end. */\n box: { x: number; y: number; width: number; height: number };\n center: Point;\n chipWidths: number[];\n chipHeight: number;\n innerWidth: number;\n gap: number;\n}\n\nexport function endRoleChipLayout(\n endpoint: Point,\n toward: Point,\n direction: string,\n roles: string[],\n): EndRoleChipLayout | null {\n if (roles.length === 0) return null;\n\n const dx = toward.x - endpoint.x;\n const dy = toward.y - endpoint.y;\n const length = Math.hypot(dx, dy) || 1;\n const ux = dx / length;\n const uy = dy / length;\n const charW = FONT.small * 0.64;\n const letterDist = 11;\n\n const chipHeight = FONT.small + 6;\n const gap = 3;\n const pad = 4;\n const chipWidths = roles.map((role) => role.length * charW + 12);\n const innerWidth = chipWidths.reduce((a, b) => a + b, 0) + gap * (roles.length - 1);\n const width = innerWidth + pad * 2;\n const height = chipHeight + pad * 2;\n\n const dist = letterDist + (direction.length * charW) / 2 + 8 + width / 2;\n const center = { x: endpoint.x + ux * dist, y: endpoint.y + uy * dist };\n\n return {\n box: { x: center.x - width / 2, y: center.y - height / 2, width, height },\n center,\n chipWidths,\n chipHeight,\n innerWidth,\n gap,\n };\n}\n","/**\n * SVG rendering of the Context Maps notation (BaseRenderer subclass).\n *\n * - bounded contexts: solid resizable boxes, coloured by subdomain type, with a\n * wrapped name and an optional owning-team caption;\n * - relationships: lines between contexts carrying the pattern abbreviation\n * (e.g. \"SK\", \"C/S\"), U/D end markers for asymmetric patterns, and the\n * integration roles (OHS/PL upstream, ACL/CF downstream).\n *\n * Colours/labels come from the single notation source (`@miragon/context-maps-schema-model`).\n */\n\nimport BaseRenderer from \"diagram-js/lib/draw/BaseRenderer\";\nimport {\n append as svgAppend,\n create as svgCreate,\n attr as svgAttr,\n clear as svgClear,\n} from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ConnectionLike, ElementLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport {\n MARK_COLORS,\n MARK_TEXT_COLOR,\n RELATIONSHIP_PATTERN_SPECS,\n SUBDOMAIN_TYPE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport type { SubdomainType } from \"@miragon/context-maps-schema-model\";\nimport { FONT, INK, INK_SOFT, PAPER, TT_RENDER_PRIORITY } from \"./styles.js\";\nimport { endRoleChipLayout } from \"./endRoleChips.js\";\nimport {\n isCmContext,\n isCmElement,\n isCmRelationship,\n type CmContext,\n type CmRelationship,\n} from \"../model/di-types.js\";\n\ntype Attrs = Record<string, string | number>;\n\nconst NEUTRAL_FILL = \"#F1F1EE\";\nconst NEUTRAL_STROKE = \"#8A8577\";\n\nexport default class ContextMapsRenderer extends BaseRenderer {\n static $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus, TT_RENDER_PRIORITY);\n }\n\n override canRender(element: ElementLike): boolean {\n return isCmElement(element);\n }\n\n override drawShape(visuals: SVGElement, element: ShapeLike): SVGElement {\n // diagram-js does not always clear our visual group before re-rendering on\n // update; clear it ourselves so re-draws never leave stale duplicates behind.\n svgClear(visuals);\n if (isCmContext(element)) return this.drawContext(visuals, element);\n const rect = svgAttr(svgCreate(\"rect\"), {\n width: element.width,\n height: element.height,\n fill: \"#eee\",\n });\n svgAppend(visuals, rect);\n return rect;\n }\n\n override drawConnection(visuals: SVGElement, connection: ConnectionLike): SVGElement {\n svgClear(visuals);\n if (isCmRelationship(connection)) return this.drawRelationship(visuals, connection);\n const line = svgAttr(svgCreate(\"polyline\"), {\n points: (connection.waypoints ?? []).map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: INK,\n });\n svgAppend(visuals, line);\n return line;\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 wp = (connection.waypoints ?? []) as Point[];\n if (wp.length === 0) return \"\";\n return wp.map((p, idx) => `${idx === 0 ? \"M\" : \"L\"}${p.x},${p.y}`).join(\"\");\n }\n\n // --- bounded context -----------------------------------------------------\n\n private drawContext(visuals: SVGElement, ctx: CmContext): SVGElement {\n const spec = ctx.subdomainType ? SUBDOMAIN_TYPE_SPECS[ctx.subdomainType] : undefined;\n const w = Math.max(ctx.width, 1);\n const h = Math.max(ctx.height, 1);\n const sw = 2;\n const i = sw / 2;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: i,\n y: i,\n width: w - sw,\n height: h - sw,\n rx: 8,\n ry: 8,\n fill: ctx.fill ?? spec?.fill ?? NEUTRAL_FILL,\n stroke: ctx.stroke ?? spec?.stroke ?? NEUTRAL_STROKE,\n \"stroke-width\": sw,\n \"stroke-linejoin\": \"round\",\n });\n svgAppend(visuals, box);\n\n const hasTeam = Boolean(ctx.team);\n this.appendLabel(visuals, ctx.cmLabel ?? \"\", w, hasTeam ? h - 18 : h, {\n \"font-weight\": \"650\",\n });\n if (ctx.subdomainType && spec) {\n // Kaiser subdomain icon at the top-left corner (star / open hand / dotted\n // circle) plus the domain-type label next to it.\n svgAppend(visuals, subdomainIcon(ctx.subdomainType, 15, 15, 18, spec.stroke));\n const badge = svgAttr(svgCreate(\"text\"), {\n x: 28,\n y: 15,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: spec.stroke,\n \"text-anchor\": \"start\",\n \"dominant-baseline\": \"central\",\n \"letter-spacing\": \"0.03em\",\n });\n badge.textContent = spec.label;\n svgAppend(visuals, badge);\n }\n if (ctx.team) {\n // People icon + team name, centred as a unit at the bottom of the box.\n const textWidth = ctx.team.length * FONT.small * 0.55;\n const iconSize = 14;\n const gap = 5;\n const totalWidth = iconSize + gap + textWidth;\n const startX = w / 2 - totalWidth / 2;\n const cy = h - 12;\n\n svgAppend(visuals, peopleIcon(startX + iconSize / 2, cy, iconSize, INK_SOFT));\n\n const team = svgAttr(svgCreate(\"text\"), {\n x: startX + iconSize + gap,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n fill: INK_SOFT,\n \"text-anchor\": \"start\",\n \"dominant-baseline\": \"central\",\n });\n team.textContent = ctx.team;\n svgAppend(visuals, team);\n }\n return box;\n }\n\n // --- relationship --------------------------------------------------------\n\n private drawRelationship(visuals: SVGElement, rel: CmRelationship): SVGElement {\n const spec =\n RELATIONSHIP_PATTERN_SPECS[rel.pattern] ?? RELATIONSHIP_PATTERN_SPECS[\"upstream-downstream\"];\n const wp = (rel.waypoints ?? []) as Point[];\n const dash = spec.dash;\n const line = svgAttr(svgCreate(\"polyline\"), {\n points: wp.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: spec.stroke,\n \"stroke-width\": spec.strokeWidth,\n \"stroke-linejoin\": \"round\",\n \"stroke-linecap\": \"round\",\n ...(dash ? { \"stroke-dasharray\": dash } : {}),\n });\n svgAppend(visuals, line);\n\n if (wp.length >= 2) {\n const src = wp[0];\n const tgt = wp[wp.length - 1];\n const upRoles = rel.upstreamRoles ?? [];\n const downRoles = rel.downstreamRoles ?? [];\n\n if (spec.symmetric) {\n // No direction (SK / P / SW): a single neutral pattern chip in the MIDDLE.\n const mx = (src.x + tgt.x) / 2;\n const my = (src.y + tgt.y) / 2;\n this.chip(visuals, mx, my, spec.abbreviation, PAPER, spec.stroke, spec.stroke);\n } else {\n // Direction letter sits AT the domain as a plain letter (no box); the\n // integration roles follow as their own coloured boxes. Customer-supplier\n // uses S (supplier, upstream) and C (customer, downstream) instead of U/D.\n const cs = rel.pattern === \"customer-supplier\";\n this.endMarkers(visuals, src, tgt, cs ? \"S\" : \"U\", upRoles);\n this.endMarkers(visuals, tgt, src, cs ? \"C\" : \"D\", downRoles);\n }\n }\n return line;\n }\n\n /**\n * Draws the markers at one relationship end: the direction letter (U/D/S/C) as\n * a plain letter right at the domain (no box), then the integration roles side\n * by side inside a single axis-aligned parent box.\n */\n private endMarkers(\n visuals: SVGElement,\n endpoint: Point,\n toward: Point,\n direction: string,\n roles: string[],\n ): void {\n const dx = toward.x - endpoint.x;\n const dy = toward.y - endpoint.y;\n const len = Math.hypot(dx, dy) || 1;\n const ux = dx / len;\n const uy = dy / len;\n\n // Direction letter: plain bold letter at the domain, white halo for legibility.\n const letterDist = 11;\n const dirColor = MARK_COLORS[direction] ?? INK;\n const letter = svgAttr(svgCreate(\"text\"), {\n x: endpoint.x + ux * letterDist,\n y: endpoint.y + uy * letterDist,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small + 1,\n \"font-weight\": \"800\",\n fill: dirColor,\n stroke: PAPER,\n \"stroke-width\": 3,\n \"paint-order\": \"stroke\",\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n letter.textContent = direction;\n svgAppend(visuals, letter);\n\n // Integration roles: horizontal chips inside one axis-aligned parent box\n // (geometry shared with the validation markers via endRoleChipLayout).\n const layout = endRoleChipLayout(endpoint, toward, direction, roles);\n if (!layout) return;\n const { box, center, chipWidths: widths, chipHeight: chipH, innerWidth: innerW, gap } = layout;\n const cy = center.y;\n\n const parent = svgAttr(svgCreate(\"rect\"), {\n x: box.x,\n y: box.y,\n width: box.width,\n height: box.height,\n rx: 6,\n ry: 6,\n fill: PAPER,\n \"fill-opacity\": 0.96,\n stroke: \"#d9d5cc\",\n \"stroke-width\": 1,\n });\n svgAppend(visuals, parent);\n\n let x = center.x - innerW / 2;\n roles.forEach((role, i) => {\n const w = widths[i];\n const fill = MARK_COLORS[role] ?? NEUTRAL_STROKE;\n this.miniChip(visuals, x + w / 2, cy, w, chipH, role, fill);\n x += w + gap;\n });\n }\n\n /** A fixed-size coloured sub-label (own colour + border) inside a parent box. */\n private miniChip(\n visuals: SVGElement,\n cx: number,\n cy: number,\n w: number,\n h: number,\n text: string,\n fill: string,\n ): void {\n const bg = svgAttr(svgCreate(\"rect\"), {\n x: cx - w / 2,\n y: cy - h / 2,\n width: w,\n height: h,\n rx: 3,\n ry: 3,\n fill,\n stroke: darken(fill),\n \"stroke-width\": 1,\n });\n svgAppend(visuals, bg);\n const t = svgAttr(svgCreate(\"text\"), {\n x: cx,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: MARK_TEXT_COLOR,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n t.textContent = text;\n svgAppend(visuals, t);\n }\n\n /** A single small filled, bordered box (background, text colour, border colour). */\n private chip(\n visuals: SVGElement,\n cx: number,\n cy: number,\n text: string,\n bgFill: string,\n textFill: string,\n border: string,\n ): void {\n if (!text) return;\n const padX = 6;\n const charW = FONT.small * 0.64;\n const w = text.length * charW + padX * 2;\n const h = FONT.small + 8;\n const bg = svgAttr(svgCreate(\"rect\"), {\n x: cx - w / 2,\n y: cy - h / 2,\n width: w,\n height: h,\n rx: 4,\n ry: 4,\n fill: bgFill,\n stroke: border,\n \"stroke-width\": 1,\n ...(bgFill === PAPER ? { \"fill-opacity\": 0.95 } : {}),\n });\n svgAppend(visuals, bg);\n const t = svgAttr(svgCreate(\"text\"), {\n x: cx,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: textFill,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n t.textContent = text;\n svgAppend(visuals, t);\n }\n\n // --- shared label rendering (wrapped, centred) ---------------------------\n\n private appendLabel(visuals: SVGElement, text: string, w: number, h: number, attrs: Attrs): void {\n const fontSize =\n typeof attrs[\"font-size\"] === \"number\" ? (attrs[\"font-size\"] as number) : FONT.label;\n const lines = wrapLabel(text, w - 20, fontSize);\n const lineHeight = fontSize * 1.2;\n const startY = h / 2 - ((lines.length - 1) * lineHeight) / 2;\n lines.forEach((ln, idx) => {\n const t = svgAttr(svgCreate(\"text\"), {\n x: w / 2,\n y: startY + idx * lineHeight,\n \"font-family\": FONT.family,\n \"font-size\": fontSize,\n fill: INK,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n ...attrs,\n });\n t.textContent = ln;\n svgAppend(visuals, t);\n });\n }\n}\n\n// --- helpers ---------------------------------------------------------------\n\n/** Darkens a #rrggbb colour toward black by factor `f` (0..1) for chip borders. */\nfunction darken(hex: string, f = 0.7): string {\n const m = /^#([0-9a-f]{6})$/i.exec(hex);\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const r = Math.round(((n >> 16) & 255) * f);\n const g = Math.round(((n >> 8) & 255) * f);\n const b = Math.round((n & 255) * f);\n return `rgb(${r},${g},${b})`;\n}\n\n// Material star + pan_tool (open hand) paths (Apache-2.0), 24×24 viewBox.\nconst STAR_PATH =\n \"M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 7.1-1.01z\";\nconst HAND_PATH =\n \"M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31 2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z\";\n\n/**\n * Kaiser subdomain icon centred on (cx, cy) at `size` px: a filled star for a\n * core domain, an open hand for a supporting subdomain, a dotted circle for a\n * generic subdomain.\n */\nfunction subdomainIcon(\n type: SubdomainType,\n cx: number,\n cy: number,\n size: number,\n color: string,\n): SVGElement {\n if (type === \"generic\") {\n const g = svgCreate(\"g\");\n const c = svgAttr(svgCreate(\"circle\"), {\n cx,\n cy,\n r: size / 2 - 1,\n fill: \"none\",\n stroke: color,\n \"stroke-width\": 1.6,\n \"stroke-dasharray\": \"2.2 2.2\",\n });\n svgAppend(g, c);\n return g;\n }\n const scale = size / 24;\n // The open hand is drawn upright by Material; rotate it to lie sideways.\n const rot = type === \"supporting\" ? \" rotate(90 12 12)\" : \"\";\n const g = svgCreate(\"g\");\n svgAttr(g, {\n transform: `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})${rot}`,\n });\n const path = svgAttr(svgCreate(\"path\"), {\n d: type === \"core\" ? STAR_PATH : HAND_PATH,\n fill: color,\n });\n svgAppend(g, path);\n return g;\n}\n\n// Material \"people\" icon (Apache-2.0), 24×24 viewBox.\nconst PEOPLE_PATH =\n \"M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z\";\n\n/** A people glyph centred on (cx, cy), rendered at `size` px in the given colour. */\nfunction peopleIcon(cx: number, cy: number, size: number, color: string): SVGElement {\n const scale = size / 24;\n const g = svgCreate(\"g\");\n svgAttr(g, { transform: `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})` });\n const path = svgAttr(svgCreate(\"path\"), { d: PEOPLE_PATH, fill: color });\n svgAppend(g, path);\n return g;\n}\n\n/** Greedy word-wrap into lines that roughly fit `maxWidth` at the font size. */\nfunction wrapLabel(text: string, maxWidth: number, fontSize: number): string[] {\n const maxChars = Math.max(4, Math.floor(maxWidth / (fontSize * 0.58)));\n const words = text.split(/\\s+/).filter(Boolean);\n if (words.length === 0) return [];\n const lines: string[] = [];\n let cur = \"\";\n for (const word of words) {\n const candidate = cur ? `${cur} ${word}` : word;\n if (candidate.length > maxChars && cur) {\n lines.push(cur);\n cur = word;\n } else {\n cur = candidate;\n }\n }\n if (cur) lines.push(cur);\n return lines;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ContextMapsRenderer from \"./ContextMapsRenderer.js\";\n\n/** SVG rendering of all Context Maps element types (BaseRenderer, priority 1500). */\nexport const cmDrawModule: ModuleDeclaration = {\n __init__: [\"cmRenderer\"],\n cmRenderer: [\"type\", ContextMapsRenderer],\n};\n\nexport { default as ContextMapsRenderer } from \"./ContextMapsRenderer.js\";\n","/**\n * Bridges the canonical `CmDocument` into the diagram-js canvas. Contexts become\n * shapes; relationships become connections whose waypoints are cropped to the\n * context box borders. Connections are added first so they sit behind the boxes.\n */\n\nimport 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 { Point } from \"diagram-js/lib/util/Types\";\nimport type { CmDocument } from \"@miragon/context-maps-schema-model\";\nimport type CmElementFactory from \"../model/CmElementFactory.js\";\nimport type { CmContext } from \"../model/di-types.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./types.js\";\n\ntype RootWithMeta = Root & { businessObject?: RootBusinessObject };\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** The point where the ray from a rect's centre toward `toward` crosses its border. */\nfunction borderPoint(rect: Rect, toward: Point): Point {\n const cx = rect.x + rect.width / 2;\n const cy = rect.y + rect.height / 2;\n const dx = toward.x - cx;\n const dy = toward.y - cy;\n if (dx === 0 && dy === 0) return { x: cx, y: cy };\n const sx = dx !== 0 ? rect.width / 2 / Math.abs(dx) : Infinity;\n const sy = dy !== 0 ? rect.height / 2 / Math.abs(dy) : Infinity;\n const s = Math.min(sx, sy);\n return { x: cx + dx * s, y: cy + dy * s };\n}\n\nfunction centre(rect: Rect): Point {\n return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };\n}\n\nexport default class CmImporter {\n static $inject = [\"canvas\", \"elementFactory\", \"cmElementFactory\", \"eventBus\", \"elementRegistry\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementFactory: ElementFactory,\n private readonly factory: CmElementFactory,\n private readonly eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n ) {}\n\n import(doc: CmDocument): ImportWarning[] {\n const warnings: ImportWarning[] = [];\n this.eventBus.fire(\"import.render.start\", { document: doc });\n\n let existing: RootWithMeta | undefined;\n try {\n existing = this.canvas.getRootElement() as RootWithMeta;\n } catch {\n existing = undefined;\n }\n let root: RootWithMeta;\n if (existing && existing.id === ROOT_ID) {\n root = existing;\n } else {\n root = this.elementFactory.createRoot({ id: ROOT_ID }) as RootWithMeta;\n this.canvas.setRootElement(root);\n }\n root.businessObject = { title: doc.title };\n\n const byId = new Map<string, CmContext>();\n for (const ctx of doc.contexts) {\n const shape = this.factory.createContext(ctx);\n byId.set(ctx.id, shape);\n }\n\n // Connections first (back), then contexts (front).\n for (const rel of doc.relationships) {\n const source = byId.get(rel.from);\n const target = byId.get(rel.to);\n if (!source || !target) {\n warnings.push({\n message: `Relationship \"${rel.id}\" references a missing context; skipped.`,\n elementId: rel.id,\n });\n continue;\n }\n const waypoints: Point[] = [\n borderPoint(source as unknown as Rect, centre(target as unknown as Rect)),\n borderPoint(target as unknown as Rect, centre(source as unknown as Rect)),\n ];\n const connection = this.factory.createRelationship(rel, source, target, waypoints);\n this.canvas.addConnection(connection, root);\n }\n for (const shape of byId.values()) {\n this.canvas.addShape(shape, root);\n }\n\n this.eventBus.fire(\"import.render.done\", { warnings });\n return warnings;\n }\n\n /** Removes every element (for re-import). */\n clear(): void {\n for (const el of [...this.elementRegistry.getAll()]) {\n if (el.id === ROOT_ID) continue;\n try {\n if (\"waypoints\" in el) this.canvas.removeConnection(el.id);\n else this.canvas.removeShape(el.id);\n } catch {\n // already removed — ignore\n }\n }\n }\n}\n","/**\n * Rebuilds a canonical `CmDocument` from the diagram-js runtime model. Position\n * and size truth are the live `x/y/width/height`; editable fields (label,\n * subdomain, team, pattern, roles, colours) are read from runtime properties.\n */\n\nimport 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 { DOCUMENT_VERSION } from \"@miragon/context-maps-schema-model\";\nimport type { BoundedContext, Relationship, CmDocument } from \"@miragon/context-maps-schema-model\";\nimport { isCmContext, isCmRelationship } from \"../model/di-types.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"./types.js\";\n\nexport default class CmExporter {\n static $inject = [\"elementRegistry\", \"canvas\"];\n\n constructor(\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n ) {}\n\n export(): CmDocument {\n let meta: RootBusinessObject | undefined;\n try {\n const root = this.canvas.getRootElement() as Root & {\n businessObject?: RootBusinessObject;\n };\n meta = root.businessObject;\n } catch {\n meta = undefined;\n }\n\n const contexts: BoundedContext[] = [];\n const relationships: Relationship[] = [];\n\n for (const el of this.elementRegistry.getAll()) {\n if (el.id === ROOT_ID) continue;\n\n if (isCmContext(el)) {\n const geom = el as unknown as { x: number; y: number; width: number; height: number };\n contexts.push({\n id: el.id,\n label: el.cmLabel ?? \"\",\n position: { x: geom.x, y: geom.y },\n size: { width: geom.width, height: geom.height },\n ...(el.subdomainType ? { subdomainType: el.subdomainType } : {}),\n ...(el.team ? { team: el.team } : {}),\n ...(el.description ? { description: el.description } : {}),\n ...(el.fill ? { fill: el.fill } : {}),\n ...(el.stroke ? { stroke: el.stroke } : {}),\n });\n } else if (isCmRelationship(el)) {\n const source = el.source as { id?: string } | undefined;\n const target = el.target as { id?: string } | undefined;\n if (!source?.id || !target?.id) continue;\n relationships.push({\n id: el.id,\n from: source.id,\n to: target.id,\n pattern: el.pattern,\n ...(el.upstreamRoles?.length ? { upstreamRoles: [...el.upstreamRoles] } : {}),\n ...(el.downstreamRoles?.length ? { downstreamRoles: [...el.downstreamRoles] } : {}),\n ...(el.cmLabel ? { label: el.cmLabel } : {}),\n ...(el.description ? { description: el.description } : {}),\n ...(el.implementationTechnology\n ? { implementationTechnology: el.implementationTechnology }\n : {}),\n });\n }\n }\n\n return {\n version: DOCUMENT_VERSION,\n title: meta?.title ?? \"Untitled context map\",\n contexts,\n relationships,\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmImporter from \"./CmImporter.js\";\nimport CmExporter from \"./CmExporter.js\";\n\n/** Document <-> diagram-js bridge (import / export). */\nexport const ioModule: ModuleDeclaration = {\n cmImporter: [\"type\", CmImporter],\n cmExporter: [\"type\", CmExporter],\n};\n\nexport { default as CmImporter } from \"./CmImporter.js\";\nexport { default as CmExporter } from \"./CmExporter.js\";\nexport { saveSVG } from \"./saveSvg.js\";\nexport { ROOT_ID } from \"./types.js\";\nexport type { ImportWarning, RootBusinessObject } from \"./types.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport { CmBaseViewer } from \"./CmBaseViewer.js\";\nimport { cmModelModule } from \"./model/index.js\";\nimport { cmDrawModule } from \"./draw/index.js\";\nimport { ioModule } from \"./io/index.js\";\n\n/** Read-only renderer: draws a Context Maps diagram with no interaction. */\nexport class Viewer extends CmBaseViewer {\n protected _getModules(): ModuleDeclaration[] {\n return [cmModelModule, cmDrawModule, ioModule];\n }\n}\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 { Viewer } from \"./Viewer.js\";\n\n/** Read-only + navigation: zoom (scroll), pan (drag), selection. */\nexport class NavigatedViewer extends Viewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [...super._getModules(), SelectionModule, ZoomScrollModule, MoveCanvasModule];\n }\n}\n","/**\n * Generic, undo-able command that sets arbitrary Context Maps properties\n * (cmLabel, teamType, mode, fill, stroke, description). Returns the changed\n * element so the CommandStack fires `elements.changed` → re-render.\n */\n\nimport 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\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","/**\n * Swaps a relationship's two ends: source ⇄ target (and reverses the waypoints).\n * This flips the direction — what was upstream/supplier becomes downstream/\n * customer and vice versa. The integration roles stay bound to their SIDE, not\n * to a context: upstreamRoles (OHS/PL) always describe whichever context is\n * upstream after the swap, downstreamRoles (ACL/CF) the downstream one — the\n * role types are side-specific, so they cannot travel with a context.\n * Undoable (revert simply swaps back).\n */\n\nimport type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type { Connection, Element } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\n\nexport interface SwapEndsContext {\n connection: Connection & { source: Element; target: Element; waypoints: Point[] };\n}\n\nfunction swap(connection: SwapEndsContext[\"connection\"]): Element[] {\n const oldSource = connection.source;\n connection.source = connection.target;\n connection.target = oldSource;\n if (Array.isArray(connection.waypoints)) {\n connection.waypoints = [...connection.waypoints].reverse();\n }\n return [connection];\n}\n\nexport default class SwapEndsHandler implements CommandHandler {\n execute(context: SwapEndsContext): Element[] {\n return swap(context.connection);\n }\n\n revert(context: SwapEndsContext): Element[] {\n return swap(context.connection);\n }\n}\n","/**\n * High-level Context Maps mutations that go through the command stack\n * (undo/redo). Registers the generic property command handler.\n */\n\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type GraphicsFactory from \"diagram-js/lib/core/GraphicsFactory\";\nimport {\n isSymmetricPattern,\n type DownstreamRole,\n type RelationshipPattern,\n type SubdomainType,\n type UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\nimport type { CmContext, CmElement, CmRelationship } from \"../model/di-types.js\";\nimport { isCmRelationship } from \"../model/di-types.js\";\nimport UpdatePropertiesHandler from \"./cmd/UpdatePropertiesHandler.js\";\nimport SwapEndsHandler, { type SwapEndsContext } from \"./cmd/SwapEndsHandler.js\";\n\nconst UPDATE_PROPERTIES = \"element.updateProperties\";\nconst SWAP_ENDS = \"relationship.swapEnds\";\n\nexport default class CmModeling {\n static $inject = [\"commandStack\", \"elementRegistry\", \"graphicsFactory\"];\n\n constructor(\n private readonly commandStack: CommandStack,\n private readonly elementRegistry: ElementRegistry,\n private readonly graphicsFactory: GraphicsFactory,\n ) {\n commandStack.registerHandler(UPDATE_PROPERTIES, UpdatePropertiesHandler);\n commandStack.registerHandler(SWAP_ENDS, SwapEndsHandler);\n }\n\n /**\n * Force an immediate re-render of an element's graphics. diagram-js'\n * ChangeSupport only redraws on `elements.changed` when `element.parent` is\n * set; this guarantees the visual reflects a property/swap change regardless\n * (a redundant redraw is harmless — the visual layer is cleared first).\n */\n private redraw(element: CmElement): void {\n const gfx = this.elementRegistry.getGraphics(element);\n if (!gfx) return;\n this.graphicsFactory.update(isCmRelationship(element) ? \"connection\" : \"shape\", element, gfx);\n }\n\n /** Swap the two ends of a relationship (reverse upstream/downstream). */\n swapEnds(relationship: CmRelationship): void {\n this.commandStack.execute(SWAP_ENDS, {\n connection: relationship,\n } as unknown as SwapEndsContext);\n this.redraw(relationship);\n }\n\n updateProperties(element: CmElement, properties: Record<string, unknown>): void {\n this.commandStack.execute(UPDATE_PROPERTIES, { element, properties });\n this.redraw(element);\n }\n\n /** Rename / relabel any element. */\n updateLabel(element: CmElement, label: string): void {\n this.updateProperties(element, { cmLabel: label || undefined });\n }\n\n // --- context ------------------------------------------------------------\n\n setSubdomainType(context: CmContext, subdomainType: SubdomainType | undefined): void {\n this.updateProperties(context, { subdomainType });\n }\n\n setTeam(context: CmContext, team: string | undefined): void {\n this.updateProperties(context, { team: team || undefined });\n }\n\n setDescription(element: CmElement, description: string | undefined): void {\n this.updateProperties(element, { description: description || undefined });\n }\n\n /** Set or clear per-element colour overrides (`undefined` reverts to default). */\n setColors(context: CmContext, fill: string | undefined, stroke: string | undefined): void {\n this.updateProperties(context, { fill, stroke });\n }\n\n // --- relationship -------------------------------------------------------\n\n /**\n * Switch the pattern and sanitise the roles so the result is always valid:\n * symmetric patterns carry no roles; customer-supplier drops the inapplicable\n * OHS (upstream) and CF (downstream).\n */\n setPattern(relationship: CmRelationship, pattern: RelationshipPattern): void {\n const props: Record<string, unknown> = { pattern };\n if (isSymmetricPattern(pattern)) {\n props.upstreamRoles = undefined;\n props.downstreamRoles = undefined;\n } else if (pattern === \"customer-supplier\") {\n const up = (relationship.upstreamRoles ?? []).filter((r) => r !== \"OHS\");\n const down = (relationship.downstreamRoles ?? []).filter((r) => r !== \"CF\");\n props.upstreamRoles = up.length ? up : undefined;\n props.downstreamRoles = down.length ? down : undefined;\n }\n this.updateProperties(relationship, props);\n }\n\n setUpstreamRoles(relationship: CmRelationship, roles: UpstreamRole[]): void {\n this.updateProperties(relationship, { upstreamRoles: roles.length ? roles : undefined });\n }\n\n setDownstreamRoles(relationship: CmRelationship, roles: DownstreamRole[]): void {\n this.updateProperties(relationship, { downstreamRoles: roles.length ? roles : undefined });\n }\n\n setImplementationTechnology(relationship: CmRelationship, tech: string | undefined): void {\n this.updateProperties(relationship, { implementationTechnology: tech || undefined });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmModeling from \"./CmModeling.js\";\nimport CmLayouter from \"../model/CmLayouter.js\";\n\n/**\n * High-level Context Maps mutations + command handlers. Also (re)binds the\n * cropping `layouter`: diagram-js' ModelingModule binds a default BaseLayouter,\n * and this module loads after it, so binding here wins and relationship lines\n * dock to the context box borders.\n */\nexport const cmModelingModule: ModuleDeclaration = {\n __init__: [\"cmModeling\"],\n cmModeling: [\"type\", CmModeling],\n layouter: [\"type\", CmLayouter],\n};\n\nexport { default as CmModeling } from \"./CmModeling.js\";\n","/**\n * Allowed editing operations.\n *\n * - Contexts are free, placed, resizable shapes that overlap but never nest.\n * - Relationships are connections between two distinct contexts (no\n * self-loops), at most ONE per pair of contexts — a second, overlapping\n * line between the same two contexts is impossible to tell apart visually.\n */\n\nimport RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { isCmContext } from \"../model/di-types.js\";\n\ninterface MoveContext {\n target?: { parent?: unknown } | null;\n}\n\ninterface ConnectContext {\n source?: unknown;\n target?: unknown;\n}\n\ninterface ReconnectContext {\n source?: unknown;\n target?: unknown;\n connection?: unknown;\n}\n\nexport default class CmRules extends RuleProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override init(): void {\n // Don't re-parent a dragged shape into whatever it is dropped on: contexts\n // are independent and only overlap. Dropping on the root (no parent) is fine.\n this.addRule([\"shape.move\", \"elements.move\"], (context: MoveContext) =>\n context.target && context.target.parent ? null : true,\n );\n this.addRule(\"shape.create\", () => true);\n this.addRule(\"shape.resize\", () => true);\n\n // A relationship connects two distinct contexts. Returning an attributes\n // object (not just `true`) makes diagram-js stamp the new connection as a\n // relationship with a default pattern, so it renders correctly.\n this.addRule(\"connection.create\", (context: ConnectContext) =>\n canConnect(context.source, context.target),\n );\n this.addRule(\"connection.reconnect\", (context: ReconnectContext) =>\n canConnect(context.source, context.target, context.connection) ? true : false,\n );\n this.addRule(\"connection.updateWaypoints\", () => true);\n }\n}\n\ninterface ConnectedElement {\n incoming?: Array<{ source?: unknown; target?: unknown }>;\n outgoing?: Array<{ source?: unknown; target?: unknown }>;\n}\n\n/** True if any relationship (other than `ignore`) already links the two contexts, either way. */\nfunction alreadyConnected(source: unknown, target: unknown, ignore?: unknown): boolean {\n const { incoming = [], outgoing = [] } = source as ConnectedElement;\n return [...incoming, ...outgoing].some(\n (connection) =>\n connection !== ignore &&\n ((connection.source === source && connection.target === target) ||\n (connection.source === target && connection.target === source)),\n );\n}\n\n/** Returns default relationship attributes if the connection is allowed, else false. */\nfunction canConnect(\n source: unknown,\n target: unknown,\n ignore?: unknown,\n): false | { cmKind: \"relationship\"; pattern: \"upstream-downstream\" } {\n if (!isCmContext(source) || !isCmContext(target)) return false;\n if (source === target) return false;\n if (alreadyConnected(source, target, ignore)) return false;\n return { cmKind: \"relationship\", pattern: \"upstream-downstream\" };\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport RulesModule from \"diagram-js/lib/features/rules\";\nimport CmRules from \"./CmRules.js\";\n\n/** Context Maps editing rules (connect, move, create, resize). */\nexport const cmRulesModule: ModuleDeclaration = {\n __depends__: [RulesModule],\n __init__: [\"cmRules\"],\n cmRules: [\"type\", CmRules],\n};\n\nexport { default as CmRules } from \"./CmRules.js\";\n","/**\n * Two model-keeping behaviours:\n *\n * 1. Flat model — diagram-js parents a newly created shape to whatever element\n * it is dropped on, which would nest overlapping contexts and glue them\n * together. Force every created shape onto the diagram root instead.\n * (Re-parenting on *move* is prevented separately in CmRules.)\n *\n * 2. Connection relayout — when a context moves or resizes, re-crop the\n * waypoints of its attached relationships to the new box borders, so lines\n * stay docked to the edges.\n */\n\nimport CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Connection, Shape } from \"diagram-js/lib/model/Types\";\n\ninterface MovedContext {\n shape?: Shape;\n shapes?: Shape[];\n}\n\nexport default class CmFlatModelBehavior extends CommandInterceptor {\n static override $inject = [\"eventBus\", \"canvas\", \"modeling\"];\n\n constructor(eventBus: EventBus, canvas: Canvas, modeling: Modeling) {\n super(eventBus);\n\n this.preExecute(\n [\"shape.create\", \"elements.create\"],\n (context: { parent?: unknown }) => {\n context.parent = canvas.getRootElement();\n },\n true,\n );\n\n const relayout = (context: MovedContext): void => {\n const shapes = context.shapes ?? (context.shape ? [context.shape] : []);\n const seen = new Set<string>();\n for (const shape of shapes) {\n const attached: Connection[] = [\n ...((shape.incoming as Connection[]) ?? []),\n ...((shape.outgoing as Connection[]) ?? []),\n ];\n for (const connection of attached) {\n if (seen.has(connection.id)) continue;\n seen.add(connection.id);\n modeling.layoutConnection(connection);\n }\n }\n };\n\n this.postExecute([\"shape.move\", \"elements.move\", \"shape.resize\"], relayout, true);\n }\n}\n","/**\n * Marks the canvas container with `cm-dragging` while any drag operation\n * (connect, move, create) is in flight. The CSS keyed on it makes the HTML\n * overlays (connect handles, validation markers, tooltips) click-transparent,\n * so releasing a drag on top of one still reaches the element underneath —\n * otherwise a connect drag dropped on a warning triangle would silently die.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\n\nconst DRAGGING_CLS = \"cm-dragging\";\n\nexport default class CmDragBehavior {\n static $inject = [\"eventBus\", \"canvas\"];\n\n constructor(eventBus: EventBus, canvas: Canvas) {\n eventBus.on(\"drag.init\", () => {\n canvas.getContainer().classList.add(DRAGGING_CLS);\n });\n eventBus.on(\"drag.cleanup\", () => {\n canvas.getContainer().classList.remove(DRAGGING_CLS);\n });\n }\n}\n","/**\n * Clicking an already-selected element KEEPS it selected. diagram-js' stock\n * SelectionBehavior toggles instead (click on selected = deselect), which\n * reads as \"the editor lost my selection\" — especially since the connect\n * handles and the inspector vanish with it. Deselecting is done by clicking\n * the empty canvas. Ctrl/Cmd-click still toggles for multi-select workflows.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport { hasPrimaryModifier } from \"diagram-js/lib/util/Mouse\";\nimport { isCmElement } from \"../model/di-types.js\";\n\n/** Above SelectionBehavior's element.click listener (default priority 500). */\nconst BEFORE_SELECTION_BEHAVIOR = 2000;\n\nexport default class CmClickSelectionBehavior {\n static $inject = [\"eventBus\", \"selection\"];\n\n constructor(eventBus: EventBus, selection: Selection) {\n eventBus.on(\n \"element.click\",\n BEFORE_SELECTION_BEHAVIOR,\n (event: { element?: unknown } & Parameters<typeof hasPrimaryModifier>[0]) => {\n const element = event.element;\n if (!isCmElement(element)) return;\n if (hasPrimaryModifier(event)) return;\n if (selection.isSelected(element)) return false;\n },\n );\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmFlatModelBehavior from \"./CmFlatModelBehavior.js\";\nimport CmDragBehavior from \"./CmDragBehavior.js\";\nimport CmClickSelectionBehavior from \"./CmClickSelectionBehavior.js\";\n\n/** Editing behaviors: keep the model flat (no nesting), drag-state CSS marker. */\nexport const cmBehaviorsModule: ModuleDeclaration = {\n __init__: [\"cmFlatModelBehavior\", \"cmDragBehavior\", \"cmClickSelectionBehavior\"],\n cmFlatModelBehavior: [\"type\", CmFlatModelBehavior],\n cmDragBehavior: [\"type\", CmDragBehavior],\n cmClickSelectionBehavior: [\"type\", CmClickSelectionBehavior],\n};\n\nexport { default as CmFlatModelBehavior } from \"./CmFlatModelBehavior.js\";\nexport { default as CmDragBehavior } from \"./CmDragBehavior.js\";\nexport { default as CmClickSelectionBehavior } from \"./CmClickSelectionBehavior.js\";\n","/**\n * Tiny inline-SVG glyphs for the palette / legend — the same shapes the canvas\n * draws (contexts coloured by subdomain, plus a relationship line). Returned as\n * HTML strings for diagram-js palette `html`.\n */\n\nimport {\n RELATIONSHIP_PATTERN_SPECS,\n SUBDOMAIN_TYPE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport type { RelationshipPattern, SubdomainType } from \"@miragon/context-maps-schema-model\";\n\nfunction svg(inner: string): string {\n return `<svg class=\"cm-palette-svg\" width=\"24\" height=\"24\" viewBox=\"0 0 26 26\" aria-hidden=\"true\">${inner}</svg>`;\n}\n\n// Kaiser subdomain glyphs (Material star / pan_tool), 24×24 viewBox.\nconst STAR = \"M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 7.1-1.01z\";\nconst HAND =\n \"M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31 2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z\";\n\n/** The subdomain glyph centred at (cx, cy) at `size` px: star / hand / dotted circle. */\nfunction subdomainGlyph(\n type: SubdomainType,\n cx: number,\n cy: number,\n size: number,\n color: string,\n): string {\n if (type === \"generic\") {\n return `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${size / 2 - 0.5}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.4\" stroke-dasharray=\"1.8 1.8\"/>`;\n }\n const scale = size / 24;\n const rot = type === \"supporting\" ? ` rotate(90 12 12)` : \"\";\n const t = `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})${rot}`;\n return `<path d=\"${type === \"core\" ? STAR : HAND}\" fill=\"${color}\" transform=\"${t}\"/>`;\n}\n\nexport function contextIconSvg(type: SubdomainType): string {\n const s = SUBDOMAIN_TYPE_SPECS[type];\n return svg(\n `<rect x=\"2\" y=\"4\" width=\"22\" height=\"18\" rx=\"3.5\" fill=\"${s.fill}\" stroke=\"${s.stroke}\" stroke-width=\"1.5\"/>` +\n subdomainGlyph(type, 13, 13, 12, s.stroke),\n );\n}\n\nexport function relationshipIconSvg(pattern: RelationshipPattern = \"upstream-downstream\"): string {\n const s = RELATIONSHIP_PATTERN_SPECS[pattern];\n const dash = s.dash ? ` stroke-dasharray=\"${s.dash}\"` : \"\";\n const w = Math.min(s.strokeWidth, 2.6);\n return svg(\n `<g stroke=\"${s.stroke}\" stroke-width=\"${w}\" stroke-linecap=\"round\">` +\n `<circle cx=\"5\" cy=\"13\" r=\"2.5\" fill=\"${s.stroke}\" stroke=\"none\"/>` +\n `<line x1=\"7\" y1=\"13\" x2=\"19\" y2=\"13\"${dash}/>` +\n `<circle cx=\"21\" cy=\"13\" r=\"2.5\" fill=\"${s.stroke}\" stroke=\"none\"/></g>`,\n );\n}\n","/**\n * The floating tool palette (styled top-centre, Excalidraw style):\n * drag-to-create the three subdomain types of bounded context. Relationships\n * are drawn via the context pad's connect arrow, not from the palette.\n */\n\nimport type Palette from \"diagram-js/lib/features/palette/Palette\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type {\n PaletteEntries,\n default as PaletteProvider,\n} from \"diagram-js/lib/features/palette/PaletteProvider\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { ALL_SUBDOMAIN_SPECS } from \"@miragon/context-maps-schema-model\";\nimport { contextIconSvg } from \"../draw/palette-icons.js\";\nimport type CmElementFactory from \"../model/CmElementFactory.js\";\n\nconst GROUP_CONTEXTS = \"cm-1-contexts\";\n\nfunction entryHtml(icon: string, title: string): string {\n return `<div class=\"entry cm-palette-entry\" draggable=\"true\" title=\"${title}\">${icon}</div>`;\n}\n\nexport default class CmPaletteProvider implements PaletteProvider {\n static $inject = [\"palette\", \"create\", \"cmElementFactory\"];\n\n constructor(\n palette: Palette,\n private readonly create: Create,\n private readonly factory: CmElementFactory,\n ) {\n palette.registerProvider(this);\n }\n\n getPaletteEntries(): PaletteEntries {\n const entries: PaletteEntries = {};\n\n for (const spec of ALL_SUBDOMAIN_SPECS) {\n const start = (event: Event) =>\n this.create.start(\n event as MouseEvent,\n this.factory.createNewContext(spec.type, spec.label) as unknown as Element,\n );\n entries[`context.${spec.type}`] = {\n group: GROUP_CONTEXTS,\n title: `${spec.label} — ${spec.description}`,\n html: entryHtml(contextIconSvg(spec.type), `${spec.label} — ${spec.description}`),\n action: { dragstart: start, click: start },\n };\n }\n\n return entries;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PaletteModule from \"diagram-js/lib/features/palette\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport CmPaletteProvider from \"./CmPaletteProvider.js\";\n\n/** Tool palette: drag-to-create contexts. */\nexport const cmPaletteModule: ModuleDeclaration = {\n __depends__: [PaletteModule, CreateModule, ConnectModule],\n __init__: [\"cmPaletteProvider\"],\n cmPaletteProvider: [\"type\", CmPaletteProvider],\n};\n\nexport { default as CmPaletteProvider } from \"./CmPaletteProvider.js\";\n","/**\n * A handful of Material-style icon paths (Apache-2.0) used by the context pad,\n * exposed as HTML markup. Reusable by host chrome too.\n */\n\nexport const ICON_ARROW_FORWARD = \"M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z\";\nexport const ICON_EDIT =\n \"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z\";\nexport const ICON_DELETE =\n \"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\";\nexport const ICON_SWAP = \"M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z\";\n\nexport function iconMarkup(path: string, size = 18): string {\n return `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"${path}\"/></svg>`;\n}\n","/**\n * Four connect handles around a selected bounded context — one arrow at the\n * middle of each side (top, right, bottom, left), each pointing outward.\n * Press a handle, drag, release over another context to draw the relationship\n * (press-drag-release ONLY: a click listener would restart the tool after the\n * mouseup and leave the preview line chasing the cursor). Implemented as\n * diagram-js overlays so the handles float outside the shape, follow it, and\n * never collide with the resize handles on the selection outline.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Overlays from \"diagram-js/lib/features/overlays/Overlays\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { getMid } from \"diagram-js/lib/layout/LayoutUtil\";\nimport { isCmContext } from \"../model/di-types.js\";\nimport { ICON_ARROW_FORWARD, iconMarkup } from \"../draw/icons.js\";\n\nconst OVERLAY_TYPE = \"cm-connect-handle\";\nconst HANDLE_SIZE = 28;\n/** Clear of the selection outline and its mid-side resize handles. */\nconst HANDLE_GAP = 12;\n\nconst SIDES = [\n { side: \"top\", rotationDeg: -90 },\n { side: \"right\", rotationDeg: 0 },\n { side: \"bottom\", rotationDeg: 90 },\n { side: \"left\", rotationDeg: 180 },\n] as const;\n\ntype Side = (typeof SIDES)[number][\"side\"];\n\nfunction handlePosition(\n side: Side,\n shape: { width: number; height: number },\n): { top: number; left: number } {\n const centeredLeft = shape.width / 2 - HANDLE_SIZE / 2;\n const centeredTop = shape.height / 2 - HANDLE_SIZE / 2;\n const outside = HANDLE_SIZE + HANDLE_GAP;\n switch (side) {\n case \"top\":\n return { top: -outside, left: centeredLeft };\n case \"bottom\":\n return { top: shape.height + HANDLE_GAP, left: centeredLeft };\n case \"left\":\n return { top: centeredTop, left: -outside };\n case \"right\":\n return { top: centeredTop, left: shape.width + HANDLE_GAP };\n }\n}\n\nexport default class CmConnectHandles {\n static $inject = [\"eventBus\", \"selection\", \"overlays\", \"connect\", \"dragging\"];\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly selection: Selection,\n private readonly overlays: Overlays,\n connect: Connect,\n private readonly dragging: Dragging,\n ) {\n // Not used to start the drag, but injecting Connect instantiates it so its\n // connect.* event handlers (hover/end → modeling.connect) are registered —\n // the connect module does not eagerly initialize it.\n void connect;\n const refresh = (): void => this.refresh();\n eventBus.on(\"selection.changed\", refresh);\n // Re-anchor after resize/undo/redo (handle offsets depend on width/height).\n eventBus.on(\"commandStack.changed\", refresh);\n }\n\n private refresh(): void {\n this.overlays.remove({ type: OVERLAY_TYPE });\n\n const selected = this.selection.get() as Element[];\n if (selected.length !== 1) return;\n const element = selected[0];\n if (!isCmContext(element)) return;\n const shape = element as unknown as { width: number; height: number };\n\n for (const { side, rotationDeg } of SIDES) {\n const handle = document.createElement(\"div\");\n handle.className = \"cm-connect-handle\";\n handle.dataset.side = side;\n handle.title = \"Connect to another context\";\n handle.innerHTML = `<span style=\"display:flex;transform:rotate(${rotationDeg}deg)\">${iconMarkup(ICON_ARROW_FORWARD)}</span>`;\n handle.addEventListener(\"mousedown\", (event: MouseEvent) => {\n if (event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n // Same payload as Connect#start, but with trapClick OFF: the ghost-\n // click trap Dragging arms after a drag is only consumed by a click\n // that reaches the canvas — a drag started on this HTML handle never\n // produces one, so the trap would instead swallow the user's NEXT\n // click on a context (no selection, seemingly broken editor).\n this.dragging.init(event, \"connect\", {\n autoActivate: false,\n trapClick: false,\n data: {\n shape: element,\n context: { start: element, connectionStart: getMid(element) },\n },\n });\n // Keep the source context marked after the drag: the drag lifecycle\n // clears the selection, but the user is still \"at\" this context. Low\n // priority so this runs after the stock cleanup listeners.\n this.eventBus.once(\"connect.cleanup\", 250, () => {\n if (this.selection.get().length === 0) this.selection.select(element);\n });\n });\n\n this.overlays.add(element, OVERLAY_TYPE, {\n position: handlePosition(side, shape),\n html: handle,\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport OverlaysModule from \"diagram-js/lib/features/overlays\";\nimport SelectionModule from \"diagram-js/lib/features/selection\";\nimport CmConnectHandles from \"./CmConnectHandles.js\";\n\n/** Four outward connect arrows around a selected context (top/right/bottom/left). */\nexport const cmConnectHandlesModule: ModuleDeclaration = {\n __depends__: [ConnectModule, OverlaysModule, SelectionModule],\n __init__: [\"cmConnectHandles\"],\n cmConnectHandles: [\"type\", CmConnectHandles],\n};\n\nexport { default as CmConnectHandles } from \"./CmConnectHandles.js\";\n","/**\n * Inline label editing as an HTML overlay (an <input> centred over the element).\n * Commit goes through `cmModeling.updateLabel` → command stack (undoable).\n * Double-click any element (context or relationship) to (re)label it.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { isCmElement, isCmRelationship, type CmElement } from \"../model/di-types.js\";\nimport type CmModeling from \"../modeling/CmModeling.js\";\n\ninterface ActiveEdit {\n commit: () => void;\n cleanup: () => void;\n}\n\nexport default class CmLabelEditing {\n static $inject = [\"eventBus\", \"canvas\", \"cmModeling\"];\n\n private active: ActiveEdit | null = null;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly modeling: CmModeling,\n ) {\n eventBus.on(\"element.dblclick\", (event: { element?: unknown }) => {\n if (isCmElement(event.element)) this.activate(event.element);\n });\n // Any click/drag/pan outside the input commits (only Escape discards).\n eventBus.on([\"element.mousedown\", \"drag.init\", \"canvas.viewbox.changing\"], () =>\n this.active?.commit(),\n );\n }\n\n activate(element: CmElement): void {\n this.active?.commit();\n\n const container = this.canvas.getContainer();\n const scale = this.canvas.zoom();\n const vb = this.canvas.viewbox();\n const { x: cx, y: cy } = centreOf(element);\n const width = 170;\n const left = (cx - vb.x) * scale - width / 2;\n const top = (cy - vb.y) * scale - 14;\n\n const input = document.createElement(\"input\");\n input.type = \"text\";\n input.className = \"cm-label-input\";\n input.value = element.cmLabel ?? \"\";\n input.style.position = \"absolute\";\n input.style.left = `${left}px`;\n input.style.top = `${top}px`;\n input.style.width = `${width}px`;\n container.appendChild(input);\n input.focus();\n input.select();\n\n let done = false;\n const cleanup = () => {\n if (done) return;\n done = true;\n input.removeEventListener(\"keydown\", onKey);\n input.removeEventListener(\"blur\", onBlur);\n input.remove();\n this.active = null;\n };\n const commit = () => {\n if (done) return;\n const value = input.value.trim();\n const changed = value !== (element.cmLabel ?? \"\");\n cleanup();\n if (changed) this.modeling.updateLabel(element, value);\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n commit();\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n cleanup();\n }\n };\n const onBlur = () => commit();\n input.addEventListener(\"keydown\", onKey);\n input.addEventListener(\"blur\", onBlur);\n\n this.active = { commit, cleanup };\n }\n\n cancel(): void {\n this.active?.cleanup();\n }\n}\n\n/** The canvas-space centre of a context (box centre) or relationship (mid-waypoint). */\nfunction centreOf(element: CmElement): Point {\n if (isCmRelationship(element)) {\n const wp = (element.waypoints ?? []) as Point[];\n if (wp.length >= 2) {\n const a = wp[0];\n const b = wp[wp.length - 1];\n return { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };\n }\n if (wp.length === 1) return { x: wp[0].x, y: wp[0].y };\n return { x: 0, y: 0 };\n }\n const shape = element as unknown as { x: number; y: number; width: number; height: number };\n return { x: shape.x + shape.width / 2, y: shape.y + shape.height / 2 };\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmLabelEditing from \"./CmLabelEditing.js\";\n\n/** Inline label editing (double-click a team to rename). */\nexport const cmLabelEditingModule: ModuleDeclaration = {\n __init__: [\"cmLabelEditing\"],\n cmLabelEditing: [\"type\", CmLabelEditing],\n};\n\nexport { default as CmLabelEditing } from \"./CmLabelEditing.js\";\n","/**\n * Keyboard shortcuts: undo / redo / delete-selection. Bound to the document so\n * they work without first clicking (focusing) the canvas — typing inside form\n * fields is left untouched. No container `tabindex`, so the canvas never shows a\n * focus ring.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\n\nfunction isTypingTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el) return false;\n return (\n el.tagName === \"INPUT\" ||\n el.tagName === \"TEXTAREA\" ||\n el.tagName === \"SELECT\" ||\n el.isContentEditable\n );\n}\n\nexport default class CmKeyboard {\n static $inject = [\"canvas\", \"commandStack\", \"selection\", \"modeling\"];\n\n constructor(\n canvas: Canvas,\n commandStack: CommandStack,\n selection: Selection,\n modeling: Modeling,\n ) {\n const doc = canvas.getContainer().ownerDocument ?? document;\n\n doc.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (isTypingTarget(e.target)) return;\n const cmd = e.ctrlKey || e.metaKey;\n const key = e.key.toLowerCase();\n\n if (cmd && key === \"z\" && !e.shiftKey) {\n e.preventDefault();\n if (commandStack.canUndo()) commandStack.undo();\n } else if ((cmd && key === \"z\" && e.shiftKey) || (cmd && key === \"y\")) {\n e.preventDefault();\n if (commandStack.canRedo()) commandStack.redo();\n } else if (key === \"delete\" || key === \"backspace\") {\n const sel = selection.get() as Element[];\n if (sel.length) {\n e.preventDefault();\n modeling.removeElements([...sel]);\n }\n }\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmKeyboard from \"./CmKeyboard.js\";\n\n/** Undo/redo + delete-selection on the canvas container. */\nexport const cmKeyboardModule: ModuleDeclaration = {\n __init__: [\"cmKeyboard\"],\n cmKeyboard: [\"type\", CmKeyboard],\n};\n\nexport { default as CmKeyboard } from \"./CmKeyboard.js\";\n","/**\n * Live semantic-rule markers on the canvas: a relationship with validation\n * findings gets a small warning triangle next to the issue — amber for\n * warnings, red if any finding is an error. Sided findings (e.g. an ACL issue\n * is a downstream concern) anchor at the BOTTOM-RIGHT corner of that end's\n * role-chip box (geometry shared with the renderer via endRoleChipLayout);\n * findings about the relationship as a whole sit at the middle of the line.\n * Hovering shows the message(s) instantly via a CSS tooltip (a native `title`\n * would only appear after the OS hover delay). Implemented as diagram-js\n * overlays (HTML above the SVG), so hover is not swallowed by the connection\n * hit layer and the marker follows its element. Recomputed on every change.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Overlays from \"diagram-js/lib/features/overlays/Overlays\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { validateDocument, type SemanticFinding } from \"@miragon/context-maps-schema-model\";\nimport type CmExporter from \"../io/CmExporter.js\";\nimport { isCmRelationship, type CmRelationship } from \"../model/di-types.js\";\nimport { endRoleChipLayout } from \"../draw/endRoleChips.js\";\n\nconst OVERLAY_TYPE = \"cm-validation\";\nconst MARKER_SIZE = 20;\nconst LINE_OFFSET = 16;\n/** Fallback distance from the endpoint when the end has no role chips. */\nconst END_DISTANCE = 44;\n\ntype MarkerSide = \"upstream\" | \"downstream\" | \"middle\";\n\nconst AMBER = \"#d97706\";\nconst RED = \"#dc2626\";\n\ninterface RankedFinding extends SemanticFinding {\n kind: \"error\" | \"warning\";\n}\n\nfunction markerHtml(findings: RankedFinding[]): HTMLElement {\n const hasError = findings.some((finding) => finding.kind === \"error\");\n const fill = hasError ? RED : AMBER;\n const marker = document.createElement(\"div\");\n marker.className = \"cm-validation-marker\";\n marker.innerHTML =\n `<svg width=\"${MARKER_SIZE}\" height=\"${MARKER_SIZE}\" viewBox=\"0 0 24 24\">` +\n `<path d=\"M12 2.5 23 21.5H1Z\" fill=\"${fill}\" stroke=\"#fff\" stroke-width=\"1.6\" stroke-linejoin=\"round\"/>` +\n `<text x=\"12\" y=\"18.5\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"800\" fill=\"#fff\" font-family=\"system-ui, sans-serif\">!</text>` +\n `</svg>`;\n\n const tooltip = document.createElement(\"div\");\n tooltip.className = \"cm-validation-tooltip\";\n for (const finding of findings) {\n const message = document.createElement(\"div\");\n message.className = \"cm-validation-tooltip__message\";\n message.textContent = finding.message;\n tooltip.appendChild(message);\n }\n marker.appendChild(tooltip);\n return marker;\n}\n\n/**\n * Where the marker sits. Sided findings anchor at the bottom-right corner of\n * the role-chip box of that end (that is where the offending OHS/PL/ACL/CF\n * badge is drawn); without chips they fall back to a point near the endpoint.\n * Whole-relationship findings sit at the middle of the line, nudged off it.\n */\nfunction anchorPoint(relationship: CmRelationship, waypoints: Point[], side: MarkerSide): Point {\n const start = waypoints[0];\n const end = waypoints[waypoints.length - 1];\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const length = Math.hypot(dx, dy) || 1;\n const ux = dx / length;\n const uy = dy / length;\n\n if (side === \"middle\") {\n return {\n x: (start.x + end.x) / 2 + -uy * LINE_OFFSET,\n y: (start.y + end.y) / 2 + ux * LINE_OFFSET,\n };\n }\n\n const customerSupplier = relationship.pattern === \"customer-supplier\";\n const layout =\n side === \"upstream\"\n ? endRoleChipLayout(\n start,\n end,\n customerSupplier ? \"S\" : \"U\",\n relationship.upstreamRoles ?? [],\n )\n : endRoleChipLayout(\n end,\n start,\n customerSupplier ? \"C\" : \"D\",\n relationship.downstreamRoles ?? [],\n );\n if (layout) {\n // Centred (almost) on the chip box corner: the triangle's visible body is\n // bottom-heavy, so half the marker overlapping the corner reads as sitting\n // right AT the corner instead of floating next to it.\n const corner = { x: layout.box.x + layout.box.width, y: layout.box.y + layout.box.height };\n return { x: corner.x + 1, y: corner.y + 1 };\n }\n\n const along = Math.min(END_DISTANCE, length * 0.35);\n const baseX = side === \"upstream\" ? start.x + ux * along : end.x - ux * along;\n const baseY = side === \"upstream\" ? start.y + uy * along : end.y - uy * along;\n return { x: baseX + -uy * LINE_OFFSET, y: baseY + ux * LINE_OFFSET };\n}\n\nexport default class CmValidationMarkers {\n static $inject = [\"eventBus\", \"elementRegistry\", \"overlays\", \"cmExporter\"];\n\n constructor(\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n private readonly overlays: Overlays,\n private readonly exporter: CmExporter,\n ) {\n const refresh = (): void => this.refresh();\n eventBus.on(\"import.render.done\", refresh);\n eventBus.on(\"commandStack.changed\", refresh);\n }\n\n private refresh(): void {\n this.overlays.remove({ type: OVERLAY_TYPE });\n\n const report = validateDocument(this.exporter.export());\n // One marker per relationship END the findings point at (or the middle for\n // whole-relationship findings), so the triangle sits next to the issue.\n const byAnchor = new Map<string, { relationshipId: string; findings: RankedFinding[] }>();\n const collect = (findings: SemanticFinding[], kind: RankedFinding[\"kind\"]): void => {\n for (const finding of findings) {\n if (!finding.relationshipId) continue;\n const key = `${finding.relationshipId} ${finding.side ?? \"middle\"}`;\n const group = byAnchor.get(key) ?? { relationshipId: finding.relationshipId, findings: [] };\n group.findings.push({ ...finding, kind });\n byAnchor.set(key, group);\n }\n };\n collect(report.errors, \"error\");\n collect(report.warnings, \"warning\");\n\n for (const [key, group] of byAnchor) {\n const element = this.elementRegistry.get(group.relationshipId);\n if (!isCmRelationship(element)) continue;\n const waypoints = (element.waypoints ?? []) as Point[];\n if (waypoints.length < 2) continue;\n const side = key.split(\" \")[1] as MarkerSide;\n const { x: markerX, y: markerY } = anchorPoint(element, waypoints, side);\n\n // Overlay positions on a connection are relative to its waypoint bbox.\n const bboxX = Math.min(...waypoints.map((p) => p.x));\n const bboxY = Math.min(...waypoints.map((p) => p.y));\n this.overlays.add(element, OVERLAY_TYPE, {\n position: {\n left: markerX - bboxX - MARKER_SIZE / 2,\n top: markerY - bboxY - MARKER_SIZE / 2,\n },\n html: markerHtml(group.findings),\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport OverlaysModule from \"diagram-js/lib/features/overlays\";\nimport CmValidationMarkers from \"./CmValidationMarkers.js\";\n\n/** Live semantic-rule markers (warning triangles with tooltips) on the canvas. */\nexport const cmValidationModule: ModuleDeclaration = {\n __depends__: [OverlaysModule],\n __init__: [\"cmValidationMarkers\"],\n cmValidationMarkers: [\"type\", CmValidationMarkers],\n};\n\nexport { default as CmValidationMarkers } from \"./CmValidationMarkers.js\";\n","/**\n * Enforces a fixed stacking order regardless of creation order, by reordering\n * the element graphics within the canvas layer. Back → front:\n *\n * relationships < contexts\n *\n * So the relationship lines always read behind the context boxes and appear to\n * dock to the box borders (the segment inside a box is covered by the box).\n */\n\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 { isCmElement, isCmRelationship, type CmElement } from \"../model/di-types.js\";\n\n/** Lower = further back. */\nfunction tier(el: CmElement): number {\n return isCmRelationship(el) ? 0 : 1;\n}\n\nexport default class CmZOrder {\n static $inject = [\"eventBus\", \"canvas\", \"elementRegistry\"];\n\n private importing = false;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n ) {\n eventBus.on(\"import.render.start\", () => {\n this.importing = true;\n });\n eventBus.on(\"import.render.done\", () => {\n this.importing = false;\n this.reorder();\n });\n eventBus.on(\"commandStack.changed\", () => {\n if (!this.importing) this.reorder();\n });\n }\n\n /** Re-append each element's graphics group in ascending tier order (back → front). */\n reorder(): void {\n const ordered = (this.elementRegistry.getAll().filter(isCmElement) as CmElement[]).sort(\n (a, b) => tier(a) - tier(b),\n );\n for (const el of ordered) {\n const gfx = this.canvas.getGraphics(el) as SVGElement | undefined;\n const wrapper = gfx?.parentNode as (Node & ChildNode) | null;\n const layer = wrapper?.parentNode as (Node & { appendChild(n: Node): Node }) | null;\n if (wrapper && layer) layer.appendChild(wrapper);\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmZOrder from \"./CmZOrder.js\";\n\n/** Keeps the fixed stacking order (interactions on top, base teams at the back). */\nexport const cmZOrderModule: ModuleDeclaration = {\n __init__: [\"cmZOrder\"],\n cmZOrder: [\"type\", CmZOrder],\n};\n\nexport { default as CmZOrder } from \"./CmZOrder.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\n\nimport ConnectionPreviewModule from \"diagram-js/lib/features/connection-preview\";\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport MoveModule from \"diagram-js/lib/features/move\";\nimport OutlineModule from \"diagram-js/lib/features/outline\";\nimport ResizeModule from \"diagram-js/lib/features/resize\";\n\nimport { NavigatedViewer } from \"./NavigatedViewer.js\";\nimport { cmModelingModule } from \"./modeling/index.js\";\nimport { cmRulesModule } from \"./rules/index.js\";\nimport { cmBehaviorsModule } from \"./behaviors/index.js\";\nimport { cmPaletteModule } from \"./palette/index.js\";\nimport { cmConnectHandlesModule } from \"./connect-handles/index.js\";\nimport { cmLabelEditingModule } from \"./label-editing/index.js\";\nimport { cmKeyboardModule } from \"./keyboard/index.js\";\nimport { cmValidationModule } from \"./validation/index.js\";\nimport { cmZOrderModule } from \"./zorder/index.js\";\n\n/**\n * Full Context Maps editor: palette/create, move, resize, connect with\n * rules, context pad, inline label editing, undo/redo.\n */\nexport class Modeler extends NavigatedViewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n // diagram-js stock\n ConnectionPreviewModule,\n ModelingModule,\n MoveModule,\n OutlineModule,\n ResizeModule,\n // Context Maps editor\n cmModelingModule,\n cmRulesModule,\n cmBehaviorsModule,\n cmPaletteModule,\n cmConnectHandlesModule,\n cmLabelEditingModule,\n cmKeyboardModule,\n cmValidationModule,\n cmZOrderModule,\n ];\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"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/model/di-types.ts","../src/io/saveSvg.ts","../src/io/types.ts","../src/CmBaseViewer.ts","../src/model/CmElementFactory.ts","../src/model/CmDiagramElementFactory.ts","../src/model/CmLayouter.ts","../src/model/index.ts","../src/theme/palette.ts","../src/draw/styles.ts","../src/draw/endRoleChips.ts","../src/draw/ContextMapsRenderer.ts","../src/draw/index.ts","../src/io/CmImporter.ts","../src/io/CmExporter.ts","../src/io/index.ts","../src/Viewer.ts","../src/NavigatedViewer.ts","../src/modeling/cmd/UpdatePropertiesHandler.ts","../src/modeling/cmd/SwapEndsHandler.ts","../src/modeling/CmModeling.ts","../src/modeling/index.ts","../src/rules/CmRules.ts","../src/rules/index.ts","../src/behaviors/CmFlatModelBehavior.ts","../src/behaviors/CmDragBehavior.ts","../src/behaviors/CmClickSelectionBehavior.ts","../src/behaviors/index.ts","../src/draw/palette-icons.ts","../src/draw/icons.ts","../src/palette/CmPaletteProvider.ts","../src/palette/index.ts","../src/label-editing/CmLabelEditing.ts","../src/label-editing/index.ts","../src/context-pad/CmContextPadProvider.ts","../src/context-pad/index.ts","../src/legend/CmLegend.ts","../src/legend/index.ts","../src/keyboard/CmKeyboard.ts","../src/keyboard/index.ts","../src/validation/CmValidationMarkers.ts","../src/validation/index.ts","../src/zorder/CmZOrder.ts","../src/zorder/index.ts","../src/Modeler.ts","../src/connect-handles/CmConnectHandles.ts","../src/connect-handles/index.ts"],"sourcesContent":["/**\n * diagram-js runtime model for the Context Maps notation.\n *\n * - `context` — a bounded context: a placed, resizable SHAPE (box) with a\n * label, optional owning team and subdomain classification.\n * - `relationship` — a context-mapping pattern: a CONNECTION (edge) between two\n * contexts, carrying a pattern plus upstream/downstream roles.\n *\n * These runtime properties are the source of truth while editing; the exporter\n * rebuilds the canonical `CmDocument` from them.\n */\n\nimport type { Connection, Shape } from \"diagram-js/lib/model/Types\";\nimport type {\n DownstreamRole,\n RelationshipPattern,\n SubdomainType,\n UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\n\nexport type CmKind = \"context\" | \"relationship\";\n\nexport interface CmContext extends Shape {\n cmKind: \"context\";\n subdomainType?: SubdomainType;\n /** Display name (separate from diagram-js `label`). */\n cmLabel?: string;\n team?: string;\n description?: string;\n fill?: string;\n stroke?: string;\n}\n\nexport interface CmRelationship extends Connection {\n cmKind: \"relationship\";\n pattern: RelationshipPattern;\n upstreamRoles?: UpstreamRole[];\n downstreamRoles?: DownstreamRole[];\n cmLabel?: string;\n description?: string;\n implementationTechnology?: string;\n}\n\nexport type CmElement = CmContext | CmRelationship;\n\nfunction kindOf(el: unknown): string | undefined {\n return typeof el === \"object\" && el !== null\n ? ((el as { cmKind?: unknown }).cmKind as string | undefined)\n : undefined;\n}\n\nexport function isCmElement(el: unknown): el is CmElement {\n return typeof kindOf(el) === \"string\";\n}\n\nexport function isCmContext(el: unknown): el is CmContext {\n return kindOf(el) === \"context\";\n}\n\nexport function isCmRelationship(el: unknown): el is CmRelationship {\n return kindOf(el) === \"relationship\";\n}\n","/**\n * Serialises the current canvas into a standalone SVG (snapshot / export),\n * fitted to the content bounds and independent of the current zoom / scroll.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport { isCmContext } from \"../model/di-types.js\";\n\nconst MARGIN = 40;\n\nexport function saveSVG(canvas: Canvas, elementRegistry: ElementRegistry): { svg: string } {\n const container = canvas.getContainer();\n const source = container.querySelector(\"svg\");\n if (!source) throw new Error(\"No SVG found in the canvas container.\");\n\n // Content bounds from the context boxes (relationship lines stay within them).\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const el of elementRegistry.getAll()) {\n if (!isCmContext(el)) continue;\n const s = el as unknown as { x: number; y: number; width: number; height: number };\n minX = Math.min(minX, s.x);\n minY = Math.min(minY, s.y);\n maxX = Math.max(maxX, s.x + s.width);\n maxY = Math.max(maxY, s.y + s.height);\n }\n if (!Number.isFinite(minX)) {\n minX = 0;\n minY = 0;\n maxX = 100;\n maxY = 100;\n }\n\n const x = minX - MARGIN;\n const y = minY - MARGIN;\n const width = maxX - minX + MARGIN * 2;\n const height = maxY - minY + MARGIN * 2;\n\n const clone = source.cloneNode(true) as SVGSVGElement;\n clone.setAttribute(\"xmlns\", \"http://www.w3.org/2000/svg\");\n clone.setAttribute(\"viewBox\", `${x} ${y} ${width} ${height}`);\n clone.setAttribute(\"width\", String(Math.round(width)));\n clone.setAttribute(\"height\", String(Math.round(height)));\n\n // Neutralise pan/zoom: let the viewBox (above) drive 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","/** ID of the diagram-js root element holding the Context Maps diagram. */\nexport const ROOT_ID = \"cm-root\";\n\nexport interface ImportWarning {\n readonly message: string;\n readonly elementId?: string;\n}\n\n/** Diagram-level metadata stashed on the root element. */\nexport interface RootBusinessObject {\n title: string;\n}\n","/**\n * Shared lifecycle & DI bootstrap for every Context Maps viewer. Subclasses\n * only override `_getModules()`. The renderer\n * is framework-agnostic — mount it into any element (e.g. a VS Code webview).\n */\n\nimport Diagram from \"diagram-js/lib/Diagram\";\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 { Root } from \"diagram-js/lib/model/Types\";\nimport type { CmDocument } from \"@miragon/context-maps-schema-model\";\nimport { saveSVG } from \"./io/saveSvg.js\";\nimport type CmImporter from \"./io/CmImporter.js\";\nimport type CmExporter from \"./io/CmExporter.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./io/types.js\";\n\nexport interface CmViewerOptions {\n /** Host element. When absent, a detached <div> is created (attach later). */\n container?: HTMLElement;\n width?: number | string;\n height?: number | string;\n /** Appended to the module list (extension point). */\n additionalModules?: ModuleDeclaration[];\n}\n\nexport type EventCallback<T = unknown> = (event: T) => void;\n\ntype RootWithMeta = Root & { businessObject?: RootBusinessObject };\n\nfunction sizeToCss(value: number | string): string {\n return typeof value === \"number\" ? `${value}px` : value;\n}\n\nexport abstract class CmBaseViewer {\n protected abstract _getModules(): ModuleDeclaration[];\n\n private _diagram: Diagram | undefined;\n private readonly _container: HTMLElement;\n private readonly _options: CmViewerOptions;\n\n constructor(options: CmViewerOptions = {}) {\n this._options = options;\n this._container = this._createContainer(options);\n }\n\n private _createContainer(options: CmViewerOptions): HTMLElement {\n const container = options.container ?? document.createElement(\"div\");\n container.classList.add(\"cm-djs-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({ canvas: { container: this._container }, modules });\n }\n return this._diagram;\n }\n\n /** Resolve a diagram-js service from the didi injector. */\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 /** Load a document into the canvas (replaces existing content). */\n importDocument(doc: CmDocument): { warnings: ImportWarning[] } {\n const diagram = this._ensureDiagram();\n const eventBus = diagram.get<EventBus>(\"eventBus\");\n const importer = diagram.get<CmImporter>(\"cmImporter\");\n importer.clear();\n const warnings = importer.import(doc);\n this._fit();\n eventBus.fire(\"import.done\", { warnings });\n return { warnings };\n }\n\n /** Current canvas state as a canonical document. */\n exportDocument(): CmDocument {\n return this.get<CmExporter>(\"cmExporter\").export();\n }\n\n /** Update diagram-level metadata (title / flow-of-change) on the root. */\n setMeta(partial: Partial<RootBusinessObject>): void {\n const canvas = this.get<Canvas>(\"canvas\");\n let root: RootWithMeta | undefined;\n try {\n root = canvas.getRootElement() as RootWithMeta;\n } catch {\n return;\n }\n if (!root || root.id !== ROOT_ID) return;\n const current = root.businessObject ?? { title: \"Untitled context map\" };\n root.businessObject = { ...current, ...partial };\n }\n\n /** Read diagram-level metadata (title / flow-of-change) from the root. */\n getMeta(): RootBusinessObject | undefined {\n try {\n const root = this.get<Canvas>(\"canvas\").getRootElement() as RootWithMeta;\n return root.businessObject;\n } catch {\n return undefined;\n }\n }\n\n /** Standalone, self-contained SVG snapshot. */\n saveSVG(): { svg: string } {\n return saveSVG(this.get<Canvas>(\"canvas\"), this.get<ElementRegistry>(\"elementRegistry\"));\n }\n\n /** Fit the content into the viewport, leaving room at the top for the palette. */\n private _fit(topInset = 84, pad = 56, leftInset = pad): void {\n const canvas = this.get<Canvas>(\"canvas\");\n const registry = this.get<ElementRegistry>(\"elementRegistry\");\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const el of registry.getAll()) {\n const e = el as { x?: number; y?: number; width?: number; height?: number };\n if (\n typeof e.x !== \"number\" ||\n typeof e.y !== \"number\" ||\n typeof e.width !== \"number\" ||\n typeof e.height !== \"number\"\n ) {\n continue;\n }\n minX = Math.min(minX, e.x);\n minY = Math.min(minY, e.y);\n maxX = Math.max(maxX, e.x + e.width);\n maxY = Math.max(maxY, e.y + e.height);\n }\n if (!Number.isFinite(minX)) return;\n\n const rect = this._container.getBoundingClientRect();\n const W = rect.width;\n const H = rect.height;\n const cw = Math.max(maxX - minX, 1);\n const ch = Math.max(maxY - minY, 1);\n if (!W || !H) {\n canvas.zoom(\"fit-viewport\");\n return;\n }\n const s = Math.min((W - leftInset - pad) / cw, (H - topInset - pad) / ch, 1.25);\n // Centre the content in the region right of the palette column.\n const offsetX = leftInset + (W - leftInset - pad - s * cw) / 2;\n canvas.viewbox({\n x: minX - offsetX / s,\n y: minY - topInset / s,\n width: W / s,\n height: H / s,\n });\n }\n\n /** Attach the container into `target`. */\n attachTo(target: HTMLElement): void {\n target.appendChild(this._container);\n this.get<Canvas>(\"canvas\").resized();\n }\n\n /** Detach the container from the DOM, preserving 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","/**\n * Creates diagram-js runtime elements carrying Context Maps markers: bounded\n * contexts (shapes) and relationships (connections), from canonical document\n * elements (import) or from scratch (palette / context-pad create).\n */\n\nimport type ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { SUBDOMAIN_TYPE_SPECS } from \"@miragon/context-maps-schema-model\";\nimport type {\n BoundedContext,\n Relationship,\n SubdomainType,\n} from \"@miragon/context-maps-schema-model\";\nimport type { CmContext, CmRelationship } from \"./di-types.js\";\n\nexport default class CmElementFactory {\n static $inject = [\"elementFactory\"];\n\n constructor(private readonly elementFactory: ElementFactory) {}\n\n // --- from canonical document elements (import) -------------------------\n\n createContext(ctx: BoundedContext): CmContext {\n // Boxes are fixed-size on the canvas (no resize feature) — clamp legacy or\n // hand-edited imports up to the notation minimum so the fixed name/team\n // layout always fits inside the box.\n const spec = ctx.subdomainType ? SUBDOMAIN_TYPE_SPECS[ctx.subdomainType] : undefined;\n const minSize = spec?.minSize ?? { width: 120, height: 72 };\n return this.elementFactory.createShape({\n id: ctx.id,\n x: ctx.position.x,\n y: ctx.position.y,\n width: Math.max(ctx.size.width, minSize.width),\n height: Math.max(ctx.size.height, minSize.height),\n cmKind: \"context\",\n cmLabel: ctx.label,\n ...(ctx.subdomainType ? { subdomainType: ctx.subdomainType } : {}),\n ...(ctx.team ? { team: ctx.team } : {}),\n ...(ctx.description ? { description: ctx.description } : {}),\n ...(ctx.fill ? { fill: ctx.fill } : {}),\n ...(ctx.stroke ? { stroke: ctx.stroke } : {}),\n } as Partial<CmContext>) as unknown as CmContext;\n }\n\n createRelationship(\n rel: Relationship,\n source: CmContext,\n target: CmContext,\n waypoints: Point[],\n ): CmRelationship {\n return this.elementFactory.createConnection({\n id: rel.id,\n source,\n target,\n waypoints,\n cmKind: \"relationship\",\n pattern: rel.pattern,\n ...(rel.upstreamRoles?.length ? { upstreamRoles: [...rel.upstreamRoles] } : {}),\n ...(rel.downstreamRoles?.length ? { downstreamRoles: [...rel.downstreamRoles] } : {}),\n ...(rel.label ? { cmLabel: rel.label } : {}),\n ...(rel.description ? { description: rel.description } : {}),\n ...(rel.implementationTechnology\n ? { implementationTechnology: rel.implementationTechnology }\n : {}),\n } as unknown as Partial<CmRelationship>) as unknown as CmRelationship;\n }\n\n // --- fresh, not-yet-placed elements (palette / context-pad create) -----\n //\n // No explicit id: the element factory (CmDiagramElementFactory) assigns a\n // collision-free model-style id (`ctx_…`).\n\n /** No type → an unclassified context (the pad's append action starts blank). */\n createNewContext(subdomainType?: SubdomainType, label?: string): CmContext {\n // Every type shares one default size; generic serves as the neutral fallback.\n const size =\n (subdomainType ? SUBDOMAIN_TYPE_SPECS[subdomainType] : undefined)?.defaultSize ??\n SUBDOMAIN_TYPE_SPECS.generic.defaultSize;\n return this.elementFactory.createShape({\n width: size.width,\n height: size.height,\n cmKind: \"context\",\n ...(subdomainType ? { subdomainType } : {}),\n cmLabel: label ?? \"New Context\",\n } as Partial<CmContext>) as unknown as CmContext;\n }\n}\n","/**\n * Element factory that assigns model-style random ids (`ctx_…`, `rel_…`) when\n * none is provided. diagram-js' stock factory numbers elements with a session\n * counter that restarts on every page load and is never advanced past ids\n * arriving via import — after a reload, drawing a connection would re-generate\n * an id already taken by an imported relationship (e.g. `connection_13`) and\n * the create command would die with \"element already exists\", silently\n * dropping the just-drawn line.\n */\n\nimport ElementFactory from \"diagram-js/lib/core/ElementFactory\";\nimport type { Connection, Label, Root, Shape } from \"diagram-js/lib/model/Types\";\nimport { newId } from \"@miragon/context-maps-schema-model\";\n\nexport default class CmDiagramElementFactory extends ElementFactory {\n override create(type: \"root\", attrs?: Partial<Root>): Root;\n override create(type: \"shape\", attrs?: Partial<Shape>): Shape;\n override create(type: \"connection\", attrs?: Partial<Connection>): Connection;\n override create(type: \"label\", attrs?: Partial<Label>): Label;\n override create(\n type: \"root\" | \"shape\" | \"connection\" | \"label\",\n attrs?: Partial<Root | Shape | Connection | Label>,\n ): Root | Shape | Connection | Label {\n if (!attrs?.id && (type === \"shape\" || type === \"connection\")) {\n attrs = { ...attrs, id: newId(type === \"shape\" ? \"ctx\" : \"rel\") };\n }\n return super.create(type as \"shape\", attrs as Partial<Shape>);\n }\n}\n","/**\n * Straight-line connection layouter that crops the waypoints to the context box\n * borders via the cropping docking. diagram-js' stock BaseLayouter only returns\n * mid(source)→mid(target), so without this the relationship line would run from\n * box centre to box centre (visibly starting inside the boxes).\n */\n\nimport { getMid } from \"diagram-js/lib/layout/LayoutUtil\";\nimport type CroppingConnectionDocking from \"diagram-js/lib/layout/CroppingConnectionDocking\";\nimport type { ConnectionLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\n\ninterface LayoutHints {\n /**\n * diagram-js may pass a Point (drag anchor) or `false` (end did not move,\n * e.g. MoveHelper's `connectionStart: sourceMoved && anchor`) here.\n */\n connectionStart?: Point | false;\n connectionEnd?: Point | false;\n source?: ShapeLike;\n target?: ShapeLike;\n}\n\nexport default class CmLayouter {\n static $inject = [\"connectionDocking\"];\n\n constructor(private readonly docking: CroppingConnectionDocking) {}\n\n layoutConnection(connection: ConnectionLike, hints: LayoutHints = {}): Point[] {\n const source = hints.source ?? connection.source;\n const target = hints.target ?? connection.target;\n // A relationship line always aims at the CENTRE of its contexts (then gets\n // cropped to the borders below). Anchor hints are deliberately ignored when\n // the shape is known: diagram-js' move helpers pass stale/shifted anchors\n // (the box may already have been relaid out), which would detach the line.\n // Hints only matter while an end has no shape yet (connect rubber band).\n const start = source ? getMid(source) : hints.connectionStart || undefined;\n const end = target ? getMid(target) : hints.connectionEnd || undefined;\n\n const provisional: Point[] = [start, end].filter(Boolean) as Point[];\n // Give the connection a straight line so the docking can crop it to the\n // shape borders. Falls back to the raw line if either end is missing.\n connection.waypoints = provisional;\n if (source && target && provisional.length === 2) {\n return this.docking.getCroppedWaypoints(connection, source, target);\n }\n return provisional;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CroppingConnectionDocking from \"diagram-js/lib/layout/CroppingConnectionDocking\";\nimport CmElementFactory from \"./CmElementFactory.js\";\nimport CmDiagramElementFactory from \"./CmDiagramElementFactory.js\";\n\n/**\n * Element factory with Context Maps defaults, plus the cropping docking so\n * relationship lines dock to the context box borders. The layouter itself is\n * bound in the modeling module (see there) because diagram-js' ModelingModule\n * binds a default `layouter` and loads after this one. The stock\n * `elementFactory` is replaced so every element gets a collision-free id\n * (see CmDiagramElementFactory).\n */\nexport const cmModelModule: ModuleDeclaration = {\n elementFactory: [\"type\", CmDiagramElementFactory],\n cmElementFactory: [\"type\", CmElementFactory],\n connectionDocking: [\"type\", CroppingConnectionDocking],\n};\n\nexport { default as CmElementFactory } from \"./CmElementFactory.js\";\nexport { default as CmDiagramElementFactory } from \"./CmDiagramElementFactory.js\";\nexport { default as CmLayouter } from \"./CmLayouter.js\";\nexport * from \"./di-types.js\";\n","/**\n * Miragon design tokens — the single source of truth for every non-notation colour in the renderer.\n *\n * Values mirror the Miragon corporate identity: the `miragon-brand:corporate-design` skill in\n * `Miragon/corporate-identity`, whose vendored `cd-tokens.generated.css` (next to this file) defines\n * the `--cd-*` custom properties, generated from the brand's `tokens.json`. Re-copy that CSS from the\n * corporate-identity repo to update; never fork the hex values by hand. `theme.sync.test.ts` fails if\n * this mirror drifts from the vendored CSS.\n *\n * Pure data — no DOM, no imports — so it can be consumed by the SVG-drawing constants in\n * `draw/styles.ts`.\n *\n * Brand rule: blue leads (`blau` — surfaces, buttons, links, selection), green accents (`gruen` — key\n * visual, highlights; a fill, never body text on white). The subdomain-type fills and\n * relationship-pattern strokes are the official Context Maps notation and live in\n * `schema-model/notation.ts` — they are NOT part of this brand ramp.\n */\n\n/** Raw Miragon brand ramp + functional layer — exact `--cd-*` values. */\nexport const MIRAGON = {\n /** Primary: surfaces, buttons, links, selection, 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 accents on dark surfaces (unused here — the canvas is light-only). */\n blauHell: \"#6B8AFF\",\n /** Accent: key visual, highlights, the brand gradient. Bright — a fill, never text on white. */\n gruen: \"#00E676\",\n /** Calm neutral surface (warm off-white) — the paper surround. */\n grau: \"#F9F7F7\",\n /** Text on light; not pure black. */\n schwarz: \"#1D1D1D\",\n weiss: \"#FFFFFF\",\n /** Functional / status layer (own layer beside the brand palette; AA as text on white). */\n success: \"#0B7A55\",\n warning: \"#92610A\",\n danger: \"#C92A2A\",\n info: \"#2B50D4\",\n /** Signature brand gradient — brand moments only. Use verbatim. */\n gradientBrand: \"linear-gradient(120deg, #335DE5 30%, #00E676)\",\n} as const;\n\n/**\n * Every `--cd-*` token this repo depends on, mapped to the value it MUST hold. The drift test parses\n * `cd-tokens.generated.css` and asserts each entry matches, so re-copying the vendored CSS with a\n * changed value fails CI until this mirror (and `MIRAGON`) is updated too.\n */\nexport const CD_TOKENS: Record<string, string> = {\n \"--cd-blau\": MIRAGON.blau,\n \"--cd-gruen\": MIRAGON.gruen,\n \"--cd-grau\": MIRAGON.grau,\n \"--cd-schwarz\": MIRAGON.schwarz,\n \"--cd-weiss\": MIRAGON.weiss,\n \"--cd-blau-link\": MIRAGON.blauLink,\n \"--cd-blau-hell\": MIRAGON.blauHell,\n \"--cd-success\": MIRAGON.success,\n \"--cd-success-soft\": \"rgba(11, 122, 85, 0.12)\",\n \"--cd-warning\": MIRAGON.warning,\n \"--cd-warning-soft\": \"rgba(146, 97, 10, 0.12)\",\n \"--cd-danger\": MIRAGON.danger,\n \"--cd-danger-soft\": \"rgba(201, 42, 42, 0.12)\",\n \"--cd-info\": MIRAGON.info,\n \"--cd-info-soft\": \"rgba(43, 80, 212, 0.12)\",\n \"--cd-gradient-brand\": MIRAGON.gradientBrand,\n};\n","/** Shared rendering constants (typography, accent, priorities) — Miragon corporate identity.\n * Colours are derived from the single source of truth in `theme/palette.ts` (`MIRAGON`), which\n * mirrors the vendored `--cd-*` brand tokens. */\n\nimport { MIRAGON } from \"../theme/index.js\";\n\n/** BaseRenderer default priority is 1000; 1500 wins the render.shape/connection event. */\nexport const TT_RENDER_PRIORITY = 1500;\n\n/** Selection / hover accent (Miragon blue — kept in sync with the app theme via the shared palette). */\nexport const ACCENT = MIRAGON.blau;\n\nexport const INK = MIRAGON.schwarz;\nexport const INK_SOFT = \"#5B5B5B\";\n\nexport const FONT = {\n /**\n * Set directly as the `font-family` attribute on every SVG <text> (canvas\n * labels and therefore the SVG export too) — not inherited from a CSS\n * container. Prefers the self-hosted Miragon typeface Geist (registered as\n * 'Geist Variable' by @fontsource-variable/geist, with 'Geist' as a fallback\n * name), and falls back to a system sans when the host hasn't loaded it (e.g.\n * an exported SVG opened standalone).\n */\n family:\n \"'Geist Variable', 'Geist', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif\",\n label: 13.5,\n small: 11,\n} as const;\n\n/**\n * Fixed top offset (px at zoom 1) of a context's name inside its box: the\n * first line starts here, right below the subdomain-type header, so the gap\n * between header and name never varies with box size or line count.\n */\nexport const CONTEXT_NAME_TOP = 36;\n\n/** Height (px at zoom 1) reserved at the box bottom for the team caption. */\nexport const CONTEXT_TEAM_RESERVE = 18;\n\n/** Paper colour used for the label halo so text stays legible over lines. */\nexport const PAPER = MIRAGON.weiss;\n\n/** Box colours for contexts without a subdomain classification (canvas + icons). */\nexport const NEUTRAL_FILL = \"#F1F1EE\";\nexport const NEUTRAL_STROKE = \"#8A8577\";\n","/**\n * Geometry of the role-chip group at a relationship end (the OHS/PL/ACL/CF\n * badges next to the direction letter). Kept in one place so the renderer\n * (which draws the chips) and the validation markers (which anchor to the\n * chips' bottom-right corner) can never drift apart.\n */\n\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { FONT } from \"./styles.js\";\n\nexport interface EndRoleChipLayout {\n /** The parent box around all chips of this end. */\n box: { x: number; y: number; width: number; height: number };\n center: Point;\n chipWidths: number[];\n chipHeight: number;\n innerWidth: number;\n gap: number;\n}\n\nexport function endRoleChipLayout(\n endpoint: Point,\n toward: Point,\n direction: string,\n roles: string[],\n): EndRoleChipLayout | null {\n if (roles.length === 0) return null;\n\n const dx = toward.x - endpoint.x;\n const dy = toward.y - endpoint.y;\n const length = Math.hypot(dx, dy) || 1;\n const ux = dx / length;\n const uy = dy / length;\n const charW = FONT.small * 0.64;\n const letterDist = 11;\n\n const chipHeight = FONT.small + 6;\n const gap = 3;\n const pad = 4;\n const chipWidths = roles.map((role) => role.length * charW + 12);\n const innerWidth = chipWidths.reduce((a, b) => a + b, 0) + gap * (roles.length - 1);\n const width = innerWidth + pad * 2;\n const height = chipHeight + pad * 2;\n\n const dist = letterDist + (direction.length * charW) / 2 + 8 + width / 2;\n const center = { x: endpoint.x + ux * dist, y: endpoint.y + uy * dist };\n\n return {\n box: { x: center.x - width / 2, y: center.y - height / 2, width, height },\n center,\n chipWidths,\n chipHeight,\n innerWidth,\n gap,\n };\n}\n","/**\n * SVG rendering of the Context Maps notation (BaseRenderer subclass).\n *\n * - bounded contexts: solid fixed-size boxes, coloured by subdomain type, with\n * a wrapped name and an optional owning-team caption;\n * - relationships: lines between contexts carrying the pattern abbreviation\n * (e.g. \"SK\", \"C/S\"), U/D end markers for asymmetric patterns, and the\n * integration roles (OHS/PL upstream, ACL/CF downstream).\n *\n * Colours/labels come from the single notation source (`@miragon/context-maps-schema-model`).\n */\n\nimport BaseRenderer from \"diagram-js/lib/draw/BaseRenderer\";\nimport {\n append as svgAppend,\n create as svgCreate,\n attr as svgAttr,\n clear as svgClear,\n} from \"tiny-svg\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { ConnectionLike, ElementLike, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport {\n MARK_COLORS,\n MARK_TEXT_COLOR,\n RELATIONSHIP_PATTERN_SPECS,\n SUBDOMAIN_TYPE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport type { SubdomainType } from \"@miragon/context-maps-schema-model\";\nimport {\n CONTEXT_NAME_TOP,\n CONTEXT_TEAM_RESERVE,\n FONT,\n INK,\n INK_SOFT,\n NEUTRAL_FILL,\n NEUTRAL_STROKE,\n PAPER,\n TT_RENDER_PRIORITY,\n} from \"./styles.js\";\nimport { endRoleChipLayout } from \"./endRoleChips.js\";\nimport {\n isCmContext,\n isCmElement,\n isCmRelationship,\n type CmContext,\n type CmRelationship,\n} from \"../model/di-types.js\";\n\ntype Attrs = Record<string, string | number>;\n\nexport default class ContextMapsRenderer extends BaseRenderer {\n static $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus, TT_RENDER_PRIORITY);\n }\n\n override canRender(element: ElementLike): boolean {\n return isCmElement(element);\n }\n\n override drawShape(visuals: SVGElement, element: ShapeLike): SVGElement {\n // diagram-js does not always clear our visual group before re-rendering on\n // update; clear it ourselves so re-draws never leave stale duplicates behind.\n svgClear(visuals);\n if (isCmContext(element)) return this.drawContext(visuals, element);\n const rect = svgAttr(svgCreate(\"rect\"), {\n width: element.width,\n height: element.height,\n fill: \"#eee\",\n });\n svgAppend(visuals, rect);\n return rect;\n }\n\n override drawConnection(visuals: SVGElement, connection: ConnectionLike): SVGElement {\n svgClear(visuals);\n if (isCmRelationship(connection)) return this.drawRelationship(visuals, connection);\n const line = svgAttr(svgCreate(\"polyline\"), {\n points: (connection.waypoints ?? []).map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: INK,\n });\n svgAppend(visuals, line);\n return line;\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 wp = (connection.waypoints ?? []) as Point[];\n if (wp.length === 0) return \"\";\n return wp.map((p, idx) => `${idx === 0 ? \"M\" : \"L\"}${p.x},${p.y}`).join(\"\");\n }\n\n // --- bounded context -----------------------------------------------------\n\n private drawContext(visuals: SVGElement, ctx: CmContext): SVGElement {\n const spec = ctx.subdomainType ? SUBDOMAIN_TYPE_SPECS[ctx.subdomainType] : undefined;\n const w = Math.max(ctx.width, 1);\n const h = Math.max(ctx.height, 1);\n const sw = 2;\n const i = sw / 2;\n const box = svgAttr(svgCreate(\"rect\"), {\n x: i,\n y: i,\n width: w - sw,\n height: h - sw,\n rx: 8,\n ry: 8,\n fill: ctx.fill ?? spec?.fill ?? NEUTRAL_FILL,\n stroke: ctx.stroke ?? spec?.stroke ?? NEUTRAL_STROKE,\n \"stroke-width\": sw,\n \"stroke-linejoin\": \"round\",\n });\n svgAppend(visuals, box);\n\n this.appendLabel(visuals, ctx.cmLabel ?? \"\", w, h, Boolean(ctx.team), {\n \"font-weight\": \"650\",\n });\n if (ctx.subdomainType && spec) {\n // Kaiser subdomain icon at the top-left corner (star / open hand / dotted\n // circle) plus the domain-type label next to it.\n svgAppend(visuals, subdomainIcon(ctx.subdomainType, 15, 15, 18, spec.stroke));\n const badge = svgAttr(svgCreate(\"text\"), {\n x: 28,\n y: 15,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: spec.stroke,\n \"text-anchor\": \"start\",\n \"dominant-baseline\": \"central\",\n \"letter-spacing\": \"0.03em\",\n });\n badge.textContent = spec.label;\n svgAppend(visuals, badge);\n }\n if (ctx.team) {\n // People icon + team name, centred as a unit at the bottom of the box.\n const textWidth = ctx.team.length * FONT.small * 0.55;\n const iconSize = 14;\n const gap = 5;\n const totalWidth = iconSize + gap + textWidth;\n const startX = w / 2 - totalWidth / 2;\n const cy = h - 12;\n\n const icon = peopleIcon(startX + iconSize / 2, cy, iconSize, INK_SOFT);\n svgAttr(icon, { class: \"cm-team\" });\n svgAppend(visuals, icon);\n\n const team = svgAttr(svgCreate(\"text\"), {\n class: \"cm-team\",\n x: startX + iconSize + gap,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n fill: INK_SOFT,\n \"text-anchor\": \"start\",\n \"dominant-baseline\": \"central\",\n });\n team.textContent = ctx.team;\n svgAppend(visuals, team);\n }\n return box;\n }\n\n // --- relationship --------------------------------------------------------\n\n private drawRelationship(visuals: SVGElement, rel: CmRelationship): SVGElement {\n const spec =\n RELATIONSHIP_PATTERN_SPECS[rel.pattern] ?? RELATIONSHIP_PATTERN_SPECS[\"upstream-downstream\"];\n const wp = (rel.waypoints ?? []) as Point[];\n const dash = spec.dash;\n const line = svgAttr(svgCreate(\"polyline\"), {\n points: wp.map((p) => `${p.x},${p.y}`).join(\" \"),\n fill: \"none\",\n stroke: spec.stroke,\n \"stroke-width\": spec.strokeWidth,\n \"stroke-linejoin\": \"round\",\n \"stroke-linecap\": \"round\",\n ...(dash ? { \"stroke-dasharray\": dash } : {}),\n });\n svgAppend(visuals, line);\n\n if (wp.length >= 2) {\n const src = wp[0];\n const tgt = wp[wp.length - 1];\n const upRoles = rel.upstreamRoles ?? [];\n const downRoles = rel.downstreamRoles ?? [];\n\n if (spec.symmetric) {\n // No direction (SK / P / SW): a single neutral pattern chip in the MIDDLE.\n const mx = (src.x + tgt.x) / 2;\n const my = (src.y + tgt.y) / 2;\n this.chip(visuals, mx, my, spec.abbreviation, PAPER, spec.stroke, spec.stroke);\n } else {\n // Direction letter sits AT the domain as a plain letter (no box); the\n // integration roles follow as their own coloured boxes. Customer-supplier\n // uses S (supplier, upstream) and C (customer, downstream) instead of U/D.\n const cs = rel.pattern === \"customer-supplier\";\n this.endMarkers(visuals, src, tgt, cs ? \"S\" : \"U\", upRoles);\n this.endMarkers(visuals, tgt, src, cs ? \"C\" : \"D\", downRoles);\n }\n }\n return line;\n }\n\n /**\n * Draws the markers at one relationship end: the direction letter (U/D/S/C) as\n * a plain letter right at the domain (no box), then the integration roles side\n * by side inside a single axis-aligned parent box.\n */\n private endMarkers(\n visuals: SVGElement,\n endpoint: Point,\n toward: Point,\n direction: string,\n roles: string[],\n ): void {\n const dx = toward.x - endpoint.x;\n const dy = toward.y - endpoint.y;\n const len = Math.hypot(dx, dy) || 1;\n const ux = dx / len;\n const uy = dy / len;\n\n // Direction letter: plain bold letter at the domain, white halo for legibility.\n const letterDist = 11;\n const dirColor = MARK_COLORS[direction] ?? INK;\n const letter = svgAttr(svgCreate(\"text\"), {\n x: endpoint.x + ux * letterDist,\n y: endpoint.y + uy * letterDist,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small + 1,\n \"font-weight\": \"800\",\n fill: dirColor,\n stroke: PAPER,\n \"stroke-width\": 3,\n \"paint-order\": \"stroke\",\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n letter.textContent = direction;\n svgAppend(visuals, letter);\n\n // Integration roles: horizontal chips inside one axis-aligned parent box\n // (geometry shared with the validation markers via endRoleChipLayout).\n const layout = endRoleChipLayout(endpoint, toward, direction, roles);\n if (!layout) return;\n const { box, center, chipWidths: widths, chipHeight: chipH, innerWidth: innerW, gap } = layout;\n const cy = center.y;\n\n const parent = svgAttr(svgCreate(\"rect\"), {\n x: box.x,\n y: box.y,\n width: box.width,\n height: box.height,\n rx: 6,\n ry: 6,\n fill: PAPER,\n \"fill-opacity\": 0.96,\n stroke: \"#d9d5cc\",\n \"stroke-width\": 1,\n });\n svgAppend(visuals, parent);\n\n let x = center.x - innerW / 2;\n roles.forEach((role, i) => {\n const w = widths[i];\n const fill = MARK_COLORS[role] ?? NEUTRAL_STROKE;\n this.miniChip(visuals, x + w / 2, cy, w, chipH, role, fill);\n x += w + gap;\n });\n }\n\n /** A fixed-size coloured sub-label (own colour + border) inside a parent box. */\n private miniChip(\n visuals: SVGElement,\n cx: number,\n cy: number,\n w: number,\n h: number,\n text: string,\n fill: string,\n ): void {\n const bg = svgAttr(svgCreate(\"rect\"), {\n x: cx - w / 2,\n y: cy - h / 2,\n width: w,\n height: h,\n rx: 3,\n ry: 3,\n fill,\n stroke: darken(fill),\n \"stroke-width\": 1,\n });\n svgAppend(visuals, bg);\n const t = svgAttr(svgCreate(\"text\"), {\n x: cx,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: MARK_TEXT_COLOR,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n t.textContent = text;\n svgAppend(visuals, t);\n }\n\n /** A single small filled, bordered box (background, text colour, border colour). */\n private chip(\n visuals: SVGElement,\n cx: number,\n cy: number,\n text: string,\n bgFill: string,\n textFill: string,\n border: string,\n ): void {\n if (!text) return;\n const padX = 6;\n const charW = FONT.small * 0.64;\n const w = text.length * charW + padX * 2;\n const h = FONT.small + 8;\n const bg = svgAttr(svgCreate(\"rect\"), {\n x: cx - w / 2,\n y: cy - h / 2,\n width: w,\n height: h,\n rx: 4,\n ry: 4,\n fill: bgFill,\n stroke: border,\n \"stroke-width\": 1,\n ...(bgFill === PAPER ? { \"fill-opacity\": 0.95 } : {}),\n });\n svgAppend(visuals, bg);\n const t = svgAttr(svgCreate(\"text\"), {\n x: cx,\n y: cy,\n \"font-family\": FONT.family,\n \"font-size\": FONT.small,\n \"font-weight\": \"700\",\n fill: textFill,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n });\n t.textContent = text;\n svgAppend(visuals, t);\n }\n\n // --- shared label rendering (wrapped, top-anchored) ----------------------\n\n /** The name starts at the FIXED offset below the type header — the gap\n * between header and name never varies with box size or line count. Lines\n * that would run past the (fixed-size) box are dropped, the last kept line\n * gets an ellipsis. */\n private appendLabel(\n visuals: SVGElement,\n text: string,\n w: number,\n h: number,\n hasTeam: boolean,\n attrs: Attrs,\n ): void {\n const fontSize =\n typeof attrs[\"font-size\"] === \"number\" ? (attrs[\"font-size\"] as number) : FONT.label;\n const fontWeight = String(attrs[\"font-weight\"] ?? \"400\");\n const maxWidth = w - 20;\n let lines = wrapLabel(text, maxWidth, fontSize, fontWeight);\n const lineHeight = fontSize * 1.2;\n const available = h - CONTEXT_NAME_TOP - (hasTeam ? CONTEXT_TEAM_RESERVE : 8);\n const maxLines = Math.max(1, Math.floor(available / lineHeight));\n if (lines.length > maxLines) {\n lines = lines.slice(0, maxLines);\n lines[maxLines - 1] = ellipsize(lines[maxLines - 1], maxWidth, fontSize, fontWeight);\n }\n const startY = CONTEXT_NAME_TOP + lineHeight / 2;\n lines.forEach((ln, idx) => {\n const t = svgAttr(svgCreate(\"text\"), {\n // `cm-name` lets the direct-editing marker hide the rendered name.\n class: \"cm-name\",\n x: w / 2,\n y: startY + idx * lineHeight,\n \"font-family\": FONT.family,\n \"font-size\": fontSize,\n fill: INK,\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n ...attrs,\n });\n t.textContent = ln;\n svgAppend(visuals, t);\n });\n }\n}\n\n// --- helpers ---------------------------------------------------------------\n\n/** Darkens a #rrggbb colour toward black by factor `f` (0..1) for chip borders. */\nfunction darken(hex: string, f = 0.7): string {\n const m = /^#([0-9a-f]{6})$/i.exec(hex);\n if (!m) return hex;\n const n = parseInt(m[1], 16);\n const r = Math.round(((n >> 16) & 255) * f);\n const g = Math.round(((n >> 8) & 255) * f);\n const b = Math.round((n & 255) * f);\n return `rgb(${r},${g},${b})`;\n}\n\n// Material star + pan_tool (open hand) paths (Apache-2.0), 24×24 viewBox.\nconst STAR_PATH =\n \"M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 7.1-1.01z\";\nconst HAND_PATH =\n \"M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31 2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z\";\n\n/**\n * Kaiser subdomain icon centred on (cx, cy) at `size` px: a filled star for a\n * core domain, an open hand for a supporting subdomain, a dotted circle for a\n * generic subdomain.\n */\nfunction subdomainIcon(\n type: SubdomainType,\n cx: number,\n cy: number,\n size: number,\n color: string,\n): SVGElement {\n if (type === \"generic\") {\n const g = svgCreate(\"g\");\n const c = svgAttr(svgCreate(\"circle\"), {\n cx,\n cy,\n r: size / 2 - 1,\n fill: \"none\",\n stroke: color,\n \"stroke-width\": 1.6,\n \"stroke-dasharray\": \"2.2 2.2\",\n });\n svgAppend(g, c);\n return g;\n }\n const scale = size / 24;\n // The open hand is drawn upright by Material; rotate it to lie sideways.\n const rot = type === \"supporting\" ? \" rotate(90 12 12)\" : \"\";\n const g = svgCreate(\"g\");\n svgAttr(g, {\n transform: `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})${rot}`,\n });\n const path = svgAttr(svgCreate(\"path\"), {\n d: type === \"core\" ? STAR_PATH : HAND_PATH,\n fill: color,\n });\n svgAppend(g, path);\n return g;\n}\n\n// Material \"people\" icon (Apache-2.0), 24×24 viewBox.\nconst PEOPLE_PATH =\n \"M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z\";\n\n/** A people glyph centred on (cx, cy), rendered at `size` px in the given colour. */\nfunction peopleIcon(cx: number, cy: number, size: number, color: string): SVGElement {\n const scale = size / 24;\n const g = svgCreate(\"g\");\n svgAttr(g, { transform: `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})` });\n const path = svgAttr(svgCreate(\"path\"), { d: PEOPLE_PATH, fill: color });\n svgAppend(g, path);\n return g;\n}\n\n/**\n * Real text measurement so the rendered wrap matches the browser's own wrap\n * in the direct-editing box (same font, same width): a shared 2D context\n * measures actual glyph widths; the character-count heuristic remains only\n * as a fallback for environments without canvas support.\n */\nlet measureContext: CanvasRenderingContext2D | null | undefined;\n\nfunction textWidth(text: string, fontSize: number, fontWeight: string): number {\n if (measureContext === undefined) {\n measureContext =\n typeof document === \"undefined\" ? null : document.createElement(\"canvas\").getContext(\"2d\");\n }\n if (!measureContext) return text.length * fontSize * 0.58;\n measureContext.font = `${fontWeight} ${fontSize}px ${FONT.family}`;\n return measureContext.measureText(text).width;\n}\n\nfunction ellipsize(line: string, maxWidth: number, fontSize: number, fontWeight: string): string {\n let kept = line;\n while (kept && textWidth(`${kept}…`, fontSize, fontWeight) > maxWidth) {\n kept = kept.slice(0, -1).trimEnd();\n }\n return `${kept}…`;\n}\n\n/** Greedy word-wrap into lines that fit `maxWidth` at the font size. */\n/** Explicit line breaks are the author's — wrap only within each of them. */\nfunction wrapLabel(text: string, maxWidth: number, fontSize: number, fontWeight: string): string[] {\n const paragraphs = text.split(\"\\n\");\n if (paragraphs.every((paragraph) => paragraph.trim() === \"\")) return [];\n return paragraphs.flatMap((paragraph) => {\n const lines = wrapParagraph(paragraph, maxWidth, fontSize, fontWeight);\n // An intentionally blank line keeps its vertical space.\n return lines.length ? lines : [\"\"];\n });\n}\n\nfunction wrapParagraph(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontWeight: string,\n): string[] {\n const words = text.split(/\\s+/).filter(Boolean);\n if (words.length === 0) return [];\n const fits = (candidate: string) => textWidth(candidate, fontSize, fontWeight) <= maxWidth;\n const lines: string[] = [];\n let current = \"\";\n for (const word of words) {\n const candidate = current ? `${current} ${word}` : word;\n if (fits(candidate)) {\n current = candidate;\n continue;\n }\n if (current) lines.push(current);\n // A word longer than the line hard-breaks mid-word (the editor's\n // break-word behaviour), so nothing ever overflows the box.\n let rest = word;\n while (rest && !fits(rest)) {\n let low = 1;\n let high = rest.length - 1;\n while (low < high) {\n const mid = Math.ceil((low + high) / 2);\n if (fits(rest.slice(0, mid))) low = mid;\n else high = mid - 1;\n }\n lines.push(rest.slice(0, low));\n rest = rest.slice(low);\n }\n current = rest;\n }\n if (current) lines.push(current);\n return lines;\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ContextMapsRenderer from \"./ContextMapsRenderer.js\";\n\n/** SVG rendering of all Context Maps element types (BaseRenderer, priority 1500). */\nexport const cmDrawModule: ModuleDeclaration = {\n __init__: [\"cmRenderer\"],\n cmRenderer: [\"type\", ContextMapsRenderer],\n};\n\nexport { default as ContextMapsRenderer } from \"./ContextMapsRenderer.js\";\n","/**\n * Bridges the canonical `CmDocument` into the diagram-js canvas. Contexts become\n * shapes; relationships become connections whose waypoints are cropped to the\n * context box borders. Connections are added first so they sit behind the boxes.\n */\n\nimport 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 { Point } from \"diagram-js/lib/util/Types\";\nimport type { CmDocument } from \"@miragon/context-maps-schema-model\";\nimport type CmElementFactory from \"../model/CmElementFactory.js\";\nimport type { CmContext } from \"../model/di-types.js\";\nimport { ROOT_ID, type ImportWarning, type RootBusinessObject } from \"./types.js\";\n\ntype RootWithMeta = Root & { businessObject?: RootBusinessObject };\n\ninterface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** The point where the ray from a rect's centre toward `toward` crosses its border. */\nfunction borderPoint(rect: Rect, toward: Point): Point {\n const cx = rect.x + rect.width / 2;\n const cy = rect.y + rect.height / 2;\n const dx = toward.x - cx;\n const dy = toward.y - cy;\n if (dx === 0 && dy === 0) return { x: cx, y: cy };\n const sx = dx !== 0 ? rect.width / 2 / Math.abs(dx) : Infinity;\n const sy = dy !== 0 ? rect.height / 2 / Math.abs(dy) : Infinity;\n const s = Math.min(sx, sy);\n return { x: cx + dx * s, y: cy + dy * s };\n}\n\nfunction centre(rect: Rect): Point {\n return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };\n}\n\nexport default class CmImporter {\n static $inject = [\"canvas\", \"elementFactory\", \"cmElementFactory\", \"eventBus\", \"elementRegistry\"];\n\n constructor(\n private readonly canvas: Canvas,\n private readonly elementFactory: ElementFactory,\n private readonly factory: CmElementFactory,\n private readonly eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n ) {}\n\n import(doc: CmDocument): ImportWarning[] {\n const warnings: ImportWarning[] = [];\n this.eventBus.fire(\"import.render.start\", { document: doc });\n\n let existing: RootWithMeta | undefined;\n try {\n existing = this.canvas.getRootElement() as RootWithMeta;\n } catch {\n existing = undefined;\n }\n let root: RootWithMeta;\n if (existing && existing.id === ROOT_ID) {\n root = existing;\n } else {\n root = this.elementFactory.createRoot({ id: ROOT_ID }) as RootWithMeta;\n this.canvas.setRootElement(root);\n }\n root.businessObject = { title: doc.title };\n\n const byId = new Map<string, CmContext>();\n for (const ctx of doc.contexts) {\n const shape = this.factory.createContext(ctx);\n byId.set(ctx.id, shape);\n }\n\n // Connections first (back), then contexts (front).\n for (const rel of doc.relationships) {\n const source = byId.get(rel.from);\n const target = byId.get(rel.to);\n if (!source || !target) {\n warnings.push({\n message: `Relationship \"${rel.id}\" references a missing context; skipped.`,\n elementId: rel.id,\n });\n continue;\n }\n const waypoints: Point[] = [\n borderPoint(source as unknown as Rect, centre(target as unknown as Rect)),\n borderPoint(target as unknown as Rect, centre(source as unknown as Rect)),\n ];\n const connection = this.factory.createRelationship(rel, source, target, waypoints);\n this.canvas.addConnection(connection, root);\n }\n for (const shape of byId.values()) {\n this.canvas.addShape(shape, root);\n }\n\n this.eventBus.fire(\"import.render.done\", { warnings });\n return warnings;\n }\n\n /** Removes every element (for re-import). */\n clear(): void {\n for (const el of [...this.elementRegistry.getAll()]) {\n if (el.id === ROOT_ID) continue;\n try {\n if (\"waypoints\" in el) this.canvas.removeConnection(el.id);\n else this.canvas.removeShape(el.id);\n } catch {\n // already removed — ignore\n }\n }\n }\n}\n","/**\n * Rebuilds a canonical `CmDocument` from the diagram-js runtime model. Position\n * and size truth are the live `x/y/width/height`; editable fields (label,\n * subdomain, team, pattern, roles, colours) are read from runtime properties.\n */\n\nimport 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 { DOCUMENT_VERSION } from \"@miragon/context-maps-schema-model\";\nimport type { BoundedContext, Relationship, CmDocument } from \"@miragon/context-maps-schema-model\";\nimport { isCmContext, isCmRelationship } from \"../model/di-types.js\";\nimport { ROOT_ID, type RootBusinessObject } from \"./types.js\";\n\nexport default class CmExporter {\n static $inject = [\"elementRegistry\", \"canvas\"];\n\n constructor(\n private readonly elementRegistry: ElementRegistry,\n private readonly canvas: Canvas,\n ) {}\n\n export(): CmDocument {\n let meta: RootBusinessObject | undefined;\n try {\n const root = this.canvas.getRootElement() as Root & {\n businessObject?: RootBusinessObject;\n };\n meta = root.businessObject;\n } catch {\n meta = undefined;\n }\n\n const contexts: BoundedContext[] = [];\n const relationships: Relationship[] = [];\n\n for (const el of this.elementRegistry.getAll()) {\n if (el.id === ROOT_ID) continue;\n\n if (isCmContext(el)) {\n const geom = el as unknown as { x: number; y: number; width: number; height: number };\n contexts.push({\n id: el.id,\n label: el.cmLabel ?? \"\",\n position: { x: geom.x, y: geom.y },\n size: { width: geom.width, height: geom.height },\n ...(el.subdomainType ? { subdomainType: el.subdomainType } : {}),\n ...(el.team ? { team: el.team } : {}),\n ...(el.description ? { description: el.description } : {}),\n ...(el.fill ? { fill: el.fill } : {}),\n ...(el.stroke ? { stroke: el.stroke } : {}),\n });\n } else if (isCmRelationship(el)) {\n const source = el.source as { id?: string } | undefined;\n const target = el.target as { id?: string } | undefined;\n if (!source?.id || !target?.id) continue;\n relationships.push({\n id: el.id,\n from: source.id,\n to: target.id,\n pattern: el.pattern,\n ...(el.upstreamRoles?.length ? { upstreamRoles: [...el.upstreamRoles] } : {}),\n ...(el.downstreamRoles?.length ? { downstreamRoles: [...el.downstreamRoles] } : {}),\n ...(el.cmLabel ? { label: el.cmLabel } : {}),\n ...(el.description ? { description: el.description } : {}),\n ...(el.implementationTechnology\n ? { implementationTechnology: el.implementationTechnology }\n : {}),\n });\n }\n }\n\n return {\n version: DOCUMENT_VERSION,\n title: meta?.title ?? \"Untitled context map\",\n contexts,\n relationships,\n };\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmImporter from \"./CmImporter.js\";\nimport CmExporter from \"./CmExporter.js\";\n\n/** Document <-> diagram-js bridge (import / export). */\nexport const ioModule: ModuleDeclaration = {\n cmImporter: [\"type\", CmImporter],\n cmExporter: [\"type\", CmExporter],\n};\n\nexport { default as CmImporter } from \"./CmImporter.js\";\nexport { default as CmExporter } from \"./CmExporter.js\";\nexport { saveSVG } from \"./saveSvg.js\";\nexport { ROOT_ID } from \"./types.js\";\nexport type { ImportWarning, RootBusinessObject } from \"./types.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport { CmBaseViewer } from \"./CmBaseViewer.js\";\nimport { cmModelModule } from \"./model/index.js\";\nimport { cmDrawModule } from \"./draw/index.js\";\nimport { ioModule } from \"./io/index.js\";\n\n/** Read-only renderer: draws a Context Maps diagram with no interaction. */\nexport class Viewer extends CmBaseViewer {\n protected _getModules(): ModuleDeclaration[] {\n return [cmModelModule, cmDrawModule, ioModule];\n }\n}\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 { Viewer } from \"./Viewer.js\";\n\n/** Read-only + navigation: zoom (scroll), pan (drag), selection. */\nexport class NavigatedViewer extends Viewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [...super._getModules(), SelectionModule, ZoomScrollModule, MoveCanvasModule];\n }\n}\n","/**\n * Generic, undo-able command that sets arbitrary Context Maps properties\n * (cmLabel, teamType, mode, fill, stroke, description). Returns the changed\n * element so the CommandStack fires `elements.changed` → re-render.\n */\n\nimport 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\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","/**\n * Swaps a relationship's two ends: source ⇄ target (and reverses the waypoints).\n * This flips the direction — what was upstream/supplier becomes downstream/\n * customer and vice versa. The integration roles stay bound to their SIDE, not\n * to a context: upstreamRoles (OHS/PL) always describe whichever context is\n * upstream after the swap, downstreamRoles (ACL/CF) the downstream one — the\n * role types are side-specific, so they cannot travel with a context.\n * Undoable (revert simply swaps back).\n */\n\nimport type CommandHandler from \"diagram-js/lib/command/CommandHandler\";\nimport type { Connection, Element } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\n\nexport interface SwapEndsContext {\n connection: Connection & { source: Element; target: Element; waypoints: Point[] };\n}\n\nfunction swap(connection: SwapEndsContext[\"connection\"]): Element[] {\n const oldSource = connection.source;\n connection.source = connection.target;\n connection.target = oldSource;\n if (Array.isArray(connection.waypoints)) {\n connection.waypoints = [...connection.waypoints].reverse();\n }\n return [connection];\n}\n\nexport default class SwapEndsHandler implements CommandHandler {\n execute(context: SwapEndsContext): Element[] {\n return swap(context.connection);\n }\n\n revert(context: SwapEndsContext): Element[] {\n return swap(context.connection);\n }\n}\n","/**\n * High-level Context Maps mutations that go through the command stack\n * (undo/redo). Registers the generic property command handler.\n */\n\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type GraphicsFactory from \"diagram-js/lib/core/GraphicsFactory\";\nimport {\n isSymmetricPattern,\n type DownstreamRole,\n type RelationshipPattern,\n type SubdomainType,\n type UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\nimport type { CmContext, CmElement, CmRelationship } from \"../model/di-types.js\";\nimport { isCmRelationship } from \"../model/di-types.js\";\nimport UpdatePropertiesHandler from \"./cmd/UpdatePropertiesHandler.js\";\nimport SwapEndsHandler, { type SwapEndsContext } from \"./cmd/SwapEndsHandler.js\";\n\nconst UPDATE_PROPERTIES = \"element.updateProperties\";\nconst SWAP_ENDS = \"relationship.swapEnds\";\n\nexport default class CmModeling {\n static $inject = [\"commandStack\", \"elementRegistry\", \"graphicsFactory\"];\n\n constructor(\n private readonly commandStack: CommandStack,\n private readonly elementRegistry: ElementRegistry,\n private readonly graphicsFactory: GraphicsFactory,\n ) {\n commandStack.registerHandler(UPDATE_PROPERTIES, UpdatePropertiesHandler);\n commandStack.registerHandler(SWAP_ENDS, SwapEndsHandler);\n }\n\n /**\n * Force an immediate re-render of an element's graphics. diagram-js'\n * ChangeSupport only redraws on `elements.changed` when `element.parent` is\n * set; this guarantees the visual reflects a property/swap change regardless\n * (a redundant redraw is harmless — the visual layer is cleared first).\n */\n private redraw(element: CmElement): void {\n const gfx = this.elementRegistry.getGraphics(element);\n if (!gfx) return;\n this.graphicsFactory.update(isCmRelationship(element) ? \"connection\" : \"shape\", element, gfx);\n }\n\n /** Swap the two ends of a relationship (reverse upstream/downstream). */\n swapEnds(relationship: CmRelationship): void {\n this.commandStack.execute(SWAP_ENDS, {\n connection: relationship,\n } as unknown as SwapEndsContext);\n this.redraw(relationship);\n }\n\n updateProperties(element: CmElement, properties: Record<string, unknown>): void {\n this.commandStack.execute(UPDATE_PROPERTIES, { element, properties });\n this.redraw(element);\n }\n\n /** Rename / relabel any element. */\n updateLabel(element: CmElement, label: string): void {\n this.updateProperties(element, { cmLabel: label || undefined });\n }\n\n // --- context ------------------------------------------------------------\n\n setSubdomainType(context: CmContext, subdomainType: SubdomainType | undefined): void {\n this.updateProperties(context, { subdomainType });\n }\n\n setTeam(context: CmContext, team: string | undefined): void {\n this.updateProperties(context, { team: team || undefined });\n }\n\n setDescription(element: CmElement, description: string | undefined): void {\n this.updateProperties(element, { description: description || undefined });\n }\n\n /** Set or clear per-element colour overrides (`undefined` reverts to default). */\n setColors(context: CmContext, fill: string | undefined, stroke: string | undefined): void {\n this.updateProperties(context, { fill, stroke });\n }\n\n // --- relationship -------------------------------------------------------\n\n /**\n * Switch the pattern and sanitise the roles so the result is always valid:\n * symmetric patterns carry no roles; customer-supplier drops the inapplicable\n * OHS (upstream) and CF (downstream).\n */\n setPattern(relationship: CmRelationship, pattern: RelationshipPattern): void {\n const props: Record<string, unknown> = { pattern };\n if (isSymmetricPattern(pattern)) {\n props.upstreamRoles = undefined;\n props.downstreamRoles = undefined;\n } else if (pattern === \"customer-supplier\") {\n const up = (relationship.upstreamRoles ?? []).filter((r) => r !== \"OHS\");\n const down = (relationship.downstreamRoles ?? []).filter((r) => r !== \"CF\");\n props.upstreamRoles = up.length ? up : undefined;\n props.downstreamRoles = down.length ? down : undefined;\n }\n this.updateProperties(relationship, props);\n }\n\n setUpstreamRoles(relationship: CmRelationship, roles: UpstreamRole[]): void {\n this.updateProperties(relationship, { upstreamRoles: roles.length ? roles : undefined });\n }\n\n setDownstreamRoles(relationship: CmRelationship, roles: DownstreamRole[]): void {\n this.updateProperties(relationship, { downstreamRoles: roles.length ? roles : undefined });\n }\n\n setImplementationTechnology(relationship: CmRelationship, tech: string | undefined): void {\n this.updateProperties(relationship, { implementationTechnology: tech || undefined });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmModeling from \"./CmModeling.js\";\nimport CmLayouter from \"../model/CmLayouter.js\";\n\n/**\n * High-level Context Maps mutations + command handlers. Also (re)binds the\n * cropping `layouter`: diagram-js' ModelingModule binds a default BaseLayouter,\n * and this module loads after it, so binding here wins and relationship lines\n * dock to the context box borders.\n */\nexport const cmModelingModule: ModuleDeclaration = {\n __init__: [\"cmModeling\"],\n cmModeling: [\"type\", CmModeling],\n layouter: [\"type\", CmLayouter],\n};\n\nexport { default as CmModeling } from \"./CmModeling.js\";\n","/**\n * Allowed editing operations.\n *\n * - Contexts are free, placed, fixed-size shapes that overlap but never nest.\n * - Relationships are connections between two distinct contexts (no\n * self-loops), at most ONE per pair of contexts — a second, overlapping\n * line between the same two contexts is impossible to tell apart visually.\n */\n\nimport RuleProvider from \"diagram-js/lib/features/rules/RuleProvider\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport { isCmContext } from \"../model/di-types.js\";\n\ninterface MoveContext {\n target?: { parent?: unknown } | null;\n}\n\ninterface ConnectContext {\n source?: unknown;\n target?: unknown;\n}\n\ninterface ReconnectContext {\n source?: unknown;\n target?: unknown;\n connection?: unknown;\n}\n\nexport default class CmRules extends RuleProvider {\n static override $inject = [\"eventBus\"];\n\n constructor(eventBus: EventBus) {\n super(eventBus);\n }\n\n override init(): void {\n // Don't re-parent a dragged shape into whatever it is dropped on: contexts\n // are independent and only overlap. Dropping on the root (no parent) is fine.\n this.addRule([\"shape.move\", \"elements.move\"], (context: MoveContext) =>\n context.target && context.target.parent ? null : true,\n );\n this.addRule(\"shape.create\", () => true);\n // Boxes have a fixed size — the uniform card look is part of the notation.\n this.addRule(\"shape.resize\", () => false);\n\n // A relationship connects two distinct contexts. Returning an attributes\n // object (not just `true`) makes diagram-js stamp the new connection as a\n // relationship with a default pattern, so it renders correctly.\n this.addRule(\"connection.create\", (context: ConnectContext) =>\n canConnect(context.source, context.target),\n );\n this.addRule(\"connection.reconnect\", (context: ReconnectContext) =>\n canConnect(context.source, context.target, context.connection) ? true : false,\n );\n this.addRule(\"connection.updateWaypoints\", () => true);\n }\n}\n\ninterface ConnectedElement {\n incoming?: Array<{ source?: unknown; target?: unknown }>;\n outgoing?: Array<{ source?: unknown; target?: unknown }>;\n}\n\n/** True if any relationship (other than `ignore`) already links the two contexts, either way. */\nfunction alreadyConnected(source: unknown, target: unknown, ignore?: unknown): boolean {\n const { incoming = [], outgoing = [] } = source as ConnectedElement;\n return [...incoming, ...outgoing].some(\n (connection) =>\n connection !== ignore &&\n ((connection.source === source && connection.target === target) ||\n (connection.source === target && connection.target === source)),\n );\n}\n\n/** Returns default relationship attributes if the connection is allowed, else false. */\nfunction canConnect(\n source: unknown,\n target: unknown,\n ignore?: unknown,\n): false | { cmKind: \"relationship\"; pattern: \"upstream-downstream\" } {\n if (!isCmContext(source) || !isCmContext(target)) return false;\n if (source === target) return false;\n if (alreadyConnected(source, target, ignore)) return false;\n return { cmKind: \"relationship\", pattern: \"upstream-downstream\" };\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport RulesModule from \"diagram-js/lib/features/rules\";\nimport CmRules from \"./CmRules.js\";\n\n/** Context Maps editing rules (connect, move, create — no resize). */\nexport const cmRulesModule: ModuleDeclaration = {\n __depends__: [RulesModule],\n __init__: [\"cmRules\"],\n cmRules: [\"type\", CmRules],\n};\n\nexport { default as CmRules } from \"./CmRules.js\";\n","/**\n * Two model-keeping behaviours:\n *\n * 1. Flat model — diagram-js parents a newly created shape to whatever element\n * it is dropped on, which would nest overlapping contexts and glue them\n * together. Force every created shape onto the diagram root instead.\n * (Re-parenting on *move* is prevented separately in CmRules.)\n *\n * 2. Connection relayout — when a context moves or resizes, re-crop the\n * waypoints of its attached relationships to the new box borders, so lines\n * stay docked to the edges.\n */\n\nimport CommandInterceptor from \"diagram-js/lib/command/CommandInterceptor\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Connection, Shape } from \"diagram-js/lib/model/Types\";\n\ninterface MovedContext {\n shape?: Shape;\n shapes?: Shape[];\n}\n\nexport default class CmFlatModelBehavior extends CommandInterceptor {\n static override $inject = [\"eventBus\", \"canvas\", \"modeling\"];\n\n constructor(eventBus: EventBus, canvas: Canvas, modeling: Modeling) {\n super(eventBus);\n\n this.preExecute(\n [\"shape.create\", \"elements.create\"],\n (context: { parent?: unknown }) => {\n context.parent = canvas.getRootElement();\n },\n true,\n );\n\n // During a multi-element move, diagram-js' MoveHelper translates every\n // fully-enclosed connection (both ends moved) by the drag delta AFTER the\n // per-shape child commands ran. Re-cropping those connections here as well\n // would apply the delta twice — and a straight line whose two ends move by\n // the same delta is already correct after the plain translation. Track the\n // moved set so relayout only touches half-attached connections.\n let multiMove: Set<string> | null = null;\n this.preExecute(\n \"elements.move\",\n (context: MovedContext) => {\n multiMove = new Set((context.shapes ?? []).map((shape) => shape.id));\n },\n true,\n );\n this.postExecuted(\n \"elements.move\",\n () => {\n multiMove = null;\n },\n true,\n );\n\n const relayout = (context: MovedContext): void => {\n const shapes = context.shapes ?? (context.shape ? [context.shape] : []);\n const seen = new Set<string>();\n for (const shape of shapes) {\n const attached: Connection[] = [\n ...((shape.incoming as Connection[]) ?? []),\n ...((shape.outgoing as Connection[]) ?? []),\n ];\n for (const connection of attached) {\n if (seen.has(connection.id)) continue;\n seen.add(connection.id);\n const sourceId = connection.source?.id;\n const targetId = connection.target?.id;\n if (sourceId && targetId && multiMove?.has(sourceId) && multiMove.has(targetId)) {\n continue;\n }\n modeling.layoutConnection(connection);\n }\n }\n };\n\n this.postExecute([\"shape.move\", \"shape.resize\"], relayout, true);\n }\n}\n","/**\n * Marks the canvas container with `cm-dragging` while any drag operation\n * (connect, move, create) is in flight. The CSS keyed on it makes the HTML\n * overlays (connect handles, validation markers, tooltips) click-transparent,\n * so releasing a drag on top of one still reaches the element underneath —\n * otherwise a connect drag dropped on a warning triangle would silently die.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\n\nconst DRAGGING_CLS = \"cm-dragging\";\n\nexport default class CmDragBehavior {\n static $inject = [\"eventBus\", \"canvas\"];\n\n constructor(eventBus: EventBus, canvas: Canvas) {\n eventBus.on(\"drag.init\", () => {\n canvas.getContainer().classList.add(DRAGGING_CLS);\n });\n eventBus.on(\"drag.cleanup\", () => {\n canvas.getContainer().classList.remove(DRAGGING_CLS);\n });\n }\n}\n","/**\n * Clicking an already-selected element KEEPS it selected. diagram-js' stock\n * SelectionBehavior toggles instead (click on selected = deselect), which\n * reads as \"the editor lost my selection\" — especially since the connect\n * handles and the inspector vanish with it. Deselecting is done by clicking\n * the empty canvas. Ctrl/Cmd-click still toggles for multi-select workflows.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport { hasPrimaryModifier } from \"diagram-js/lib/util/Mouse\";\nimport { isCmElement } from \"../model/di-types.js\";\n\n/** Above SelectionBehavior's element.click listener (default priority 500). */\nconst BEFORE_SELECTION_BEHAVIOR = 2000;\n\nexport default class CmClickSelectionBehavior {\n static $inject = [\"eventBus\", \"selection\"];\n\n constructor(eventBus: EventBus, selection: Selection) {\n eventBus.on(\n \"element.click\",\n BEFORE_SELECTION_BEHAVIOR,\n (event: { element?: unknown } & Parameters<typeof hasPrimaryModifier>[0]) => {\n const element = event.element;\n if (!isCmElement(element)) return;\n if (hasPrimaryModifier(event)) return;\n if (selection.isSelected(element)) return false;\n },\n );\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmFlatModelBehavior from \"./CmFlatModelBehavior.js\";\nimport CmDragBehavior from \"./CmDragBehavior.js\";\nimport CmClickSelectionBehavior from \"./CmClickSelectionBehavior.js\";\n\n/** Editing behaviors: keep the model flat (no nesting), drag-state CSS marker. */\nexport const cmBehaviorsModule: ModuleDeclaration = {\n __init__: [\"cmFlatModelBehavior\", \"cmDragBehavior\", \"cmClickSelectionBehavior\"],\n cmFlatModelBehavior: [\"type\", CmFlatModelBehavior],\n cmDragBehavior: [\"type\", CmDragBehavior],\n cmClickSelectionBehavior: [\"type\", CmClickSelectionBehavior],\n};\n\nexport { default as CmFlatModelBehavior } from \"./CmFlatModelBehavior.js\";\nexport { default as CmDragBehavior } from \"./CmDragBehavior.js\";\nexport { default as CmClickSelectionBehavior } from \"./CmClickSelectionBehavior.js\";\n","/**\n * Tiny inline-SVG glyphs for the palette / legend — the same shapes the canvas\n * draws (contexts coloured by subdomain, plus a relationship line). Returned as\n * HTML strings for diagram-js palette `html`.\n */\n\nimport {\n MARK_COLORS,\n MARK_TEXT_COLOR,\n RELATIONSHIP_PATTERN_SPECS,\n SUBDOMAIN_TYPE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport type {\n DownstreamRole,\n RelationshipPattern,\n SubdomainType,\n SubdomainTypeSpec,\n UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\nimport { FONT, NEUTRAL_FILL, NEUTRAL_STROKE } from \"./styles.js\";\n\nfunction svg(inner: string, size = 24): string {\n return `<svg class=\"cm-palette-svg\" width=\"${size}\" height=\"${size}\" viewBox=\"0 0 26 26\" aria-hidden=\"true\">${inner}</svg>`;\n}\n\n// Kaiser subdomain glyphs (Material star / pan_tool), 24×24 viewBox.\nconst STAR = \"M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 22 12 18.56 5.82 22 7 14.14l-5-4.87 7.1-1.01z\";\nconst HAND =\n \"M23 5.5V20c0 2.2-1.8 4-4 4h-7.3c-1.08 0-2.1-.43-2.85-1.19L1 14.83s1.26-1.23 1.3-1.25c.22-.19.49-.29.79-.29.22 0 .42.06.6.16.04.01 4.31 2.46 4.31 2.46V4c0-.83.67-1.5 1.5-1.5S11 3.17 11 4v7h1V1.5c0-.83.67-1.5 1.5-1.5S15 .67 15 1.5V11h1V2.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V11h1V5.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5z\";\n\n/** The subdomain glyph centred at (cx, cy) at `size` px: star / hand / dotted circle. */\nfunction subdomainGlyph(\n type: SubdomainType,\n cx: number,\n cy: number,\n size: number,\n color: string,\n): string {\n if (type === \"generic\") {\n return `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${size / 2 - 0.5}\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.4\" stroke-dasharray=\"1.8 1.8\"/>`;\n }\n const scale = size / 24;\n const rot = type === \"supporting\" ? ` rotate(90 12 12)` : \"\";\n const t = `translate(${cx - 12 * scale} ${cy - 12 * scale}) scale(${scale})${rot}`;\n return `<path d=\"${type === \"core\" ? STAR : HAND}\" fill=\"${color}\" transform=\"${t}\"/>`;\n}\n\n/** No (or unknown) type → the neutral box an unclassified context gets on the canvas. */\nexport function contextIconSvg(type?: SubdomainType): string {\n const s = type ? SUBDOMAIN_TYPE_SPECS[type] : undefined;\n if (!type || !s) {\n return svg(\n `<rect x=\"2\" y=\"4\" width=\"22\" height=\"18\" rx=\"3.5\" fill=\"${NEUTRAL_FILL}\" stroke=\"${NEUTRAL_STROKE}\" stroke-width=\"1.5\"/>`,\n );\n }\n return svg(\n `<rect x=\"2\" y=\"4\" width=\"22\" height=\"18\" rx=\"3.5\" fill=\"${s.fill}\" stroke=\"${s.stroke}\" stroke-width=\"1.5\"/>` +\n subdomainGlyph(type, 13, 13, 12, s.stroke),\n );\n}\n\n/** The bare subdomain glyph (star / hand / dotted circle) without the box — legend rows. */\nexport function subdomainIconSvg(type: SubdomainType, size = 18): string {\n const s = SUBDOMAIN_TYPE_SPECS[type] as SubdomainTypeSpec | undefined;\n const color = s?.stroke ?? NEUTRAL_STROKE;\n const inner =\n !s || type === \"generic\"\n ? `<circle cx=\"12\" cy=\"12\" r=\"9\" fill=\"none\" stroke=\"${color}\" stroke-width=\"1.8\" stroke-dasharray=\"2.4 2.4\"/>`\n : `<path d=\"${type === \"core\" ? STAR : HAND}\" fill=\"${color}\"/>`;\n return `<svg class=\"cm-palette-svg\" width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">${inner}</svg>`;\n}\n\n/** The same coloured role chip (OHS/PL/ACL/CF) the canvas draws at relationship ends. */\nexport function roleChipSvg(role: UpstreamRole | DownstreamRole): string {\n return svg(\n `<rect x=\"1\" y=\"6.5\" width=\"24\" height=\"13\" rx=\"3\" fill=\"${MARK_COLORS[role] ?? NEUTRAL_STROKE}\"/>` +\n `<text x=\"13\" y=\"16.4\" text-anchor=\"middle\" font-size=\"9.5\" font-weight=\"700\" fill=\"${MARK_TEXT_COLOR}\" font-family=\"${FONT.family}\">${role}</text>`,\n );\n}\n\nexport function relationshipIconSvg(\n pattern: RelationshipPattern = \"upstream-downstream\",\n size = 24,\n): string {\n const s =\n RELATIONSHIP_PATTERN_SPECS[pattern] ?? RELATIONSHIP_PATTERN_SPECS[\"upstream-downstream\"];\n const dash = s.dash ? ` stroke-dasharray=\"${s.dash}\"` : \"\";\n const w = Math.min(s.strokeWidth, 2.6);\n return svg(\n `<g stroke=\"${s.stroke}\" stroke-width=\"${w}\" stroke-linecap=\"round\">` +\n `<circle cx=\"5\" cy=\"13\" r=\"2.5\" fill=\"${s.stroke}\" stroke=\"none\"/>` +\n `<line x1=\"7\" y1=\"13\" x2=\"19\" y2=\"13\"${dash}/>` +\n `<circle cx=\"21\" cy=\"13\" r=\"2.5\" fill=\"${s.stroke}\" stroke=\"none\"/></g>`,\n size,\n );\n}\n","/**\n * A handful of Material-style icon paths (Apache-2.0) used by the context pad,\n * exposed as HTML markup. Reusable by host chrome too.\n */\n\nexport const ICON_ARROW_FORWARD = \"M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z\";\nexport const ICON_EDIT =\n \"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z\";\nexport const ICON_DELETE =\n \"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\";\nexport const ICON_SWAP = \"M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z\";\nexport const ICON_TUNE =\n \"M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z\";\nexport const ICON_ADD_BOX =\n \"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z\";\n\nexport const ICON_NOTES = \"M3 18h12v-2H3v2zM3 6v2h18V6H3zm0 7h18v-2H3v2z\";\nexport const ICON_TEAM =\n \"M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z\";\n\nexport function iconMarkup(path: string, size = 18): string {\n return `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"${path}\"/></svg>`;\n}\n\n/** A dashed marquee box — the lasso (rubber-band multi-select) glyph. */\nexport function lassoIconMarkup(size = 18): string {\n return `<svg width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" aria-hidden=\"true\"><rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" stroke-dasharray=\"3.2 2.6\"/></svg>`;\n}\n","/**\n * The floating tool palette (horizontal pill, top-centre): the lasso tool\n * first, then drag-to-create for the three subdomain types of bounded\n * context. Relationships are drawn via the context pad's connect arrow, not\n * from the palette.\n */\n\nimport 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 {\n PaletteEntries,\n default as PaletteProvider,\n} from \"diagram-js/lib/features/palette/PaletteProvider\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { ALL_SUBDOMAIN_SPECS } from \"@miragon/context-maps-schema-model\";\nimport { contextIconSvg } from \"../draw/palette-icons.js\";\nimport { lassoIconMarkup } from \"../draw/icons.js\";\nimport type CmElementFactory from \"../model/CmElementFactory.js\";\n\n/** diagram-js highlights tools only inside the group named exactly `tools`. */\nconst GROUP_TOOLS = \"tools\";\nconst GROUP_CONTEXTS = \"cm-1-contexts\";\n\nfunction entryHtml(icon: string, title: string, draggable = true): string {\n const drag = draggable ? ` draggable=\"true\"` : \"\";\n return `<div class=\"entry cm-palette-entry\"${drag} title=\"${title}\">${icon}</div>`;\n}\n\nexport default class CmPaletteProvider implements PaletteProvider {\n static $inject = [\"palette\", \"create\", \"lassoTool\", \"cmElementFactory\"];\n\n constructor(\n palette: Palette,\n private readonly create: Create,\n private readonly lassoTool: LassoTool,\n private readonly factory: CmElementFactory,\n ) {\n palette.registerProvider(this);\n }\n\n getPaletteEntries(): PaletteEntries {\n const entries: PaletteEntries = {};\n\n // Entry keys must end in `-tool` (\"lasso-tool\" ↔ tool \"lasso\") for\n // diagram-js' tool-manager highlight to find them; Esc cancels any tool.\n const lassoTitle = \"Lasso tool — drag a box to select multiple elements\";\n entries[\"lasso-tool\"] = {\n group: GROUP_TOOLS,\n title: lassoTitle,\n html: entryHtml(lassoIconMarkup(), lassoTitle, false),\n action: {\n click: (event: Event) => this.lassoTool.activateSelection(event as MouseEvent),\n },\n };\n\n for (const spec of ALL_SUBDOMAIN_SPECS) {\n const start = (event: Event) =>\n this.create.start(\n event as MouseEvent,\n this.factory.createNewContext(spec.type, spec.label) as unknown as Element,\n );\n entries[`context.${spec.type}`] = {\n group: GROUP_CONTEXTS,\n title: `${spec.label} — ${spec.description}`,\n html: entryHtml(contextIconSvg(spec.type), `${spec.label} — ${spec.description}`),\n action: { dragstart: start, click: start },\n };\n }\n\n return entries;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport PaletteModule from \"diagram-js/lib/features/palette\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport LassoToolModule from \"diagram-js/lib/features/lasso-tool\";\nimport CmPaletteProvider from \"./CmPaletteProvider.js\";\n\n/** Tool palette: lasso tool + drag-to-create contexts. */\nexport const cmPaletteModule: ModuleDeclaration = {\n __depends__: [PaletteModule, CreateModule, ConnectModule, LassoToolModule],\n __init__: [\"cmPaletteProvider\"],\n cmPaletteProvider: [\"type\", CmPaletteProvider],\n};\n\nexport { default as CmPaletteProvider } from \"./CmPaletteProvider.js\";\n","/**\n * In-place editing via diagram-js-direct-editing (the bpmn.io mechanism):\n * double-click a context or relationship — or use the context pad's rename\n * action — and the name becomes editable directly inside the element, at the\n * spot and size it is rendered (Shift+Enter inserts a line break the renderer\n * preserves). The owning-team caption edits the same way: the pad's team\n * action (or a double-click on the caption) opens the box right over it.\n * Enter/blur commits through `cmModeling` (undoable), Escape cancels;\n * panning/zooming or starting a drag completes the edit. The edited text is\n * hidden behind an element marker while the box is open so nothing doubles up.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Element, ShapeLike } from \"diagram-js/lib/model/Types\";\nimport { CONTEXT_NAME_TOP, CONTEXT_TEAM_RESERVE, FONT } from \"../draw/styles.js\";\nimport { isCmContext, isCmElement, type CmContext, type CmElement } from \"../model/di-types.js\";\nimport type CmModeling from \"../modeling/CmModeling.js\";\n\ntype EditMode = \"name\" | \"team\";\n\n/** Hide the rendered text being edited: `.cm-name` resp. `.cm-team` (CSS). */\nconst MARKERS: Record<EditMode, string> = {\n name: \"cm-direct-editing\",\n team: \"cm-direct-editing-team\",\n};\n\n/** Mirrors the renderer: label wrap inset (10px each side). */\nconst LABEL_INSET_X = 10;\n/** The team caption band at the bottom of the box (renderer: centre at h-12). */\nconst TEAM_BAND_HEIGHT = 20;\nconst TEAM_BAND_BOTTOM_GAP = 2;\n\n// The service surface of the (untyped, plain-JS) diagram-js-direct-editing\n// package — typed locally so nothing untyped leaks into the published d.ts.\ninterface DirectEditingContext {\n bounds: { x: number; y: number; width: number; height: number };\n text: string;\n style?: Record<string, string | number>;\n options?: { centerVertically?: boolean; autoResize?: boolean; resizable?: boolean };\n}\n\ninterface DirectEditingService {\n registerProvider(provider: {\n activate(element: Element): DirectEditingContext | undefined;\n update(element: Element, newText: string): void;\n }): void;\n activate(element: Element): boolean;\n isActive(element?: Element): boolean;\n cancel(): void;\n complete(): void;\n}\n\nexport default class CmLabelEditing {\n static $inject = [\"eventBus\", \"canvas\", \"directEditing\", \"cmModeling\"];\n\n /** Which property the CURRENT activation edits (set right before activate). */\n private mode: EditMode = \"name\";\n private activeMarker?: { element: Element; marker: string };\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly directEditing: DirectEditingService,\n private readonly modeling: CmModeling,\n ) {\n // Registered as a plain object: the provider contract claims the method\n // name `activate` for context creation, while this service keeps\n // `activate(element)` as the public \"start editing\" API.\n directEditing.registerProvider({\n activate: (element) => this.activationContext(element),\n update: (element, newText) => this.commit(element, newText),\n });\n\n eventBus.on(\n \"element.dblclick\",\n (event: { element?: unknown; originalEvent?: { clientY?: number } }) => {\n const element = event.element;\n if (!isCmElement(element)) return;\n // A double-click on the team caption band edits the team, not the name.\n this.mode =\n isCmContext(element) && element.team && this.isInTeamBand(element, event.originalEvent)\n ? \"team\"\n : \"name\";\n directEditing.activate(element as Element);\n },\n );\n\n // The edit box is viewport-anchored — complete before the canvas moves\n // away underneath it (complete() is a no-op while inactive).\n eventBus.on([\"canvas.viewbox.changing\", \"drag.init\"], () => directEditing.complete());\n\n eventBus.on(\"directEditing.activate\", (event: { active?: { element?: Element } }) => {\n const element = event.active?.element;\n if (!element) return;\n const marker = MARKERS[this.mode];\n canvas.addMarker(element as unknown as ShapeLike, marker);\n this.activeMarker = { element, marker };\n });\n eventBus.on([\"directEditing.complete\", \"directEditing.cancel\"], () => {\n const active = this.activeMarker;\n if (active) canvas.removeMarker(active.element as unknown as ShapeLike, active.marker);\n this.activeMarker = undefined;\n });\n }\n\n /** Start in-place editing of the element's name (context pad, hosts). */\n activate(element: CmElement): void {\n this.mode = \"name\";\n this.directEditing.activate(element as Element);\n }\n\n /** Start in-place editing of the owning-team caption at the box bottom. */\n activateTeam(context: CmContext): void {\n this.mode = \"team\";\n this.directEditing.activate(context as unknown as Element);\n }\n\n cancel(): void {\n this.directEditing.cancel();\n }\n\n private isInTeamBand(context: CmContext, originalEvent?: { clientY?: number }): boolean {\n if (typeof originalEvent?.clientY !== \"number\") return false;\n const zoom = this.canvas.zoom();\n const bbox = this.canvas.getAbsoluteBBox(context as unknown as ShapeLike);\n const containerTop = this.canvas.getContainer().getBoundingClientRect().top;\n const y = originalEvent.clientY - containerTop;\n return y >= bbox.y + bbox.height - (TEAM_BAND_HEIGHT + TEAM_BAND_BOTTOM_GAP) * zoom;\n }\n\n private activationContext(element: Element): DirectEditingContext | undefined {\n if (!isCmElement(element)) return undefined;\n if (this.mode === \"team\" && !isCmContext(element)) this.mode = \"name\";\n const zoom = this.canvas.zoom();\n const bbox = this.canvas.getAbsoluteBBox(element as unknown as ShapeLike);\n\n if (this.mode === \"team\") {\n const context = element as CmContext;\n // Right over the caption at the box bottom, in the caption's type size.\n return {\n bounds: {\n x: bbox.x + LABEL_INSET_X * zoom,\n y: bbox.y + bbox.height - (TEAM_BAND_HEIGHT + TEAM_BAND_BOTTOM_GAP) * zoom,\n width: bbox.width - 2 * LABEL_INSET_X * zoom,\n height: TEAM_BAND_HEIGHT * zoom,\n },\n text: context.team ?? \"\",\n style: {\n fontFamily: FONT.family,\n fontSize: `${FONT.small * zoom}px`,\n fontWeight: 400,\n lineHeight: 1.2,\n backgroundColor: \"transparent\",\n border: \"1px dashed rgba(51, 93, 229, 0.65)\",\n textAlign: \"center\",\n },\n options: { centerVertically: true },\n };\n }\n\n const style: Record<string, string | number> = {\n fontFamily: FONT.family,\n fontSize: `${FONT.label * zoom}px`,\n fontWeight: 650,\n lineHeight: 1.2,\n // In-place illusion: the element's own fill stays visible, a dashed\n // accent frame signals the edit state (the rendered name is hidden).\n backgroundColor: \"transparent\",\n border: \"1px dashed rgba(51, 93, 229, 0.65)\",\n textAlign: \"center\",\n };\n\n if (isCmContext(element)) {\n // The renderer anchors the name at the fixed top offset below the type\n // header — mirror that band exactly so the text does not jump. The 1px\n // dashed border (box-sizing: border-box) pushes the text down — offset\n // the box up by it.\n const reserve = element.team ? CONTEXT_TEAM_RESERVE * zoom : 0;\n return {\n bounds: {\n x: bbox.x + LABEL_INSET_X * zoom,\n y: bbox.y + CONTEXT_NAME_TOP * zoom - 1,\n width: bbox.width - 2 * LABEL_INSET_X * zoom,\n height: bbox.height - CONTEXT_NAME_TOP * zoom - reserve,\n },\n text: element.cmLabel ?? \"\",\n style,\n };\n }\n\n // Relationship: a compact box centred on the line (the canvas shows the\n // label only in the hover tooltip, so the box needs its own paper).\n const width = 160 * zoom;\n const height = 44 * zoom;\n return {\n bounds: {\n x: bbox.x + bbox.width / 2 - width / 2,\n y: bbox.y + bbox.height / 2 - height / 2,\n width,\n height,\n },\n text: (element as CmElement).cmLabel ?? \"\",\n style: { ...style, backgroundColor: \"rgba(255, 255, 255, 0.95)\" },\n options: { centerVertically: true },\n };\n }\n\n private commit(element: Element, newText: string): void {\n const value = newText.trim();\n // DirectEditing also calls update() on pure bounds jitter — don't push a\n // no-op command (an empty undo step) when nothing changed.\n if (this.mode === \"team\") {\n const context = element as unknown as CmContext;\n if (value === (context.team ?? \"\")) return;\n this.modeling.setTeam(context, value || undefined);\n return;\n }\n if (value === ((element as CmElement).cmLabel ?? \"\")) return;\n this.modeling.updateLabel(element as CmElement, value);\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport DirectEditingModule from \"diagram-js-direct-editing\";\nimport { cmModelingModule } from \"../modeling/index.js\";\nimport CmLabelEditing from \"./CmLabelEditing.js\";\n\n/** In-place name editing (double-click / context pad), bpmn.io style. */\nexport const cmLabelEditingModule: ModuleDeclaration = {\n __depends__: [DirectEditingModule, cmModelingModule],\n __init__: [\"cmLabelEditing\"],\n cmLabelEditing: [\"type\", CmLabelEditing],\n};\n\nexport { default as CmLabelEditing } from \"./CmLabelEditing.js\";\n","/**\n * Per-element quick actions (diagram-js context pad + popup menus), so every\n * embedder of the Modeler gets element-level editing out of the box — not just\n * hosts that build their own inspector.\n *\n * - Bounded context: append a connected context, connect, subdomain type\n * (menu), owning team (in-place over its caption), rename (in-place direct\n * editing), description (anchored prompt), delete.\n * - Relationship: pattern (menu); integration roles (menu) and swap ends\n * while the pattern is asymmetric; rename, description, delete.\n * - Multi-selection: delete.\n *\n * Every mutation goes through `cmModeling`/`modeling`, so it is undoable and\n * lands in `exportDocument()`. Role/pattern constraints mirror the reference\n * inspector: upstream roles combine, downstream roles exclude each other, and\n * customer-supplier blocks OHS (upstream) and CF (downstream).\n */\n\nimport type ContextPad from \"diagram-js/lib/features/context-pad/ContextPad\";\nimport type {\n ContextPadEntries,\n ContextPadEntry,\n default as ContextPadProvider,\n} from \"diagram-js/lib/features/context-pad/ContextPadProvider\";\nimport type PopupMenu from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type { PopupMenuTarget } from \"diagram-js/lib/features/popup-menu/PopupMenu\";\nimport type { PopupMenuEntries } from \"diagram-js/lib/features/popup-menu/PopupMenuProvider\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Create from \"diagram-js/lib/features/create/Create\";\nimport type AutoPlace from \"diagram-js/lib/features/auto-place/AutoPlace\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type Rules from \"diagram-js/lib/features/rules/Rules\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Scheduler from \"diagram-js/lib/features/scheduler/Scheduler\";\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type { Element, Shape } from \"diagram-js/lib/model/Types\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { asTRBL, getMid } from \"diagram-js/lib/layout/LayoutUtil\";\nimport {\n DEFAULT_DISTANCE,\n findFreePosition,\n generateGetNextPosition,\n} from \"diagram-js/lib/features/auto-place/AutoPlaceUtil\";\nimport {\n ALL_PATTERN_SPECS,\n ALL_SUBDOMAIN_SPECS,\n DOWNSTREAM_ROLES,\n DOWNSTREAM_ROLE_SPECS,\n RELATIONSHIP_PATTERN_SPECS,\n SUBDOMAIN_TYPE_SPECS,\n UPSTREAM_ROLES,\n UPSTREAM_ROLE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport type {\n DownstreamRole,\n RelationshipPatternSpec,\n UpstreamRole,\n} from \"@miragon/context-maps-schema-model\";\nimport {\n isCmContext,\n isCmElement,\n isCmRelationship,\n type CmContext,\n type CmElement,\n type CmRelationship,\n} from \"../model/di-types.js\";\nimport type CmModeling from \"../modeling/CmModeling.js\";\nimport type CmLabelEditing from \"../label-editing/CmLabelEditing.js\";\nimport type CmElementFactory from \"../model/CmElementFactory.js\";\nimport { contextIconSvg, relationshipIconSvg, roleChipSvg } from \"../draw/palette-icons.js\";\nimport {\n ICON_ADD_BOX,\n ICON_ARROW_FORWARD,\n ICON_DELETE,\n ICON_EDIT,\n ICON_NOTES,\n ICON_SWAP,\n ICON_TEAM,\n ICON_TUNE,\n iconMarkup,\n} from \"../draw/icons.js\";\n\nconst SUBDOMAIN_MENU = \"cm-subdomain-menu\";\nconst PATTERN_MENU = \"cm-pattern-menu\";\nconst ROLES_MENU = \"cm-roles-menu\";\n\n/** Marks the entry matching the element's current state (check + accent, CSS). */\nconst ACTIVE_CLASS = \"cm-popup-active\";\nconst MENU_GAP = 8;\n\n/** Why OHS / CF are unavailable while the pattern is customer-supplier. */\nconst CUSTOMER_SUPPLIER_BLOCKERS: Partial<Record<UpstreamRole | DownstreamRole, string>> = {\n OHS: \"Open Host Service is one-size-fits-all and not applicable in a customer-supplier relationship.\",\n CF: \"Conformist is not applicable in a customer-supplier relationship — a customer can negotiate.\",\n};\n\nfunction padEntryHtml(\n icon: string,\n title: string,\n options: { draggable?: boolean; danger?: boolean } = {},\n): string {\n const draggable = options.draggable ? ` draggable=\"true\"` : \"\";\n const danger = options.danger ? \" cm-pad-entry--danger\" : \"\";\n return `<div class=\"entry cm-pad-entry${danger}\"${draggable} title=\"${title}\">${icon}</div>`;\n}\n\nexport default class CmContextPadProvider implements ContextPadProvider {\n static $inject = [\n \"contextPad\",\n \"popupMenu\",\n \"eventBus\",\n \"connect\",\n \"create\",\n \"autoPlace\",\n \"rules\",\n \"dragging\",\n \"modeling\",\n \"cmModeling\",\n \"cmLabelEditing\",\n \"cmElementFactory\",\n \"selection\",\n \"canvas\",\n \"scheduler\",\n ];\n\n /** The last pad-opened menu, so a roles toggle can re-open it in place. */\n private currentMenu?: { element: CmElement; menuId: string; title: string; position: Point };\n\n constructor(\n private readonly contextPad: ContextPad,\n private readonly popupMenu: PopupMenu,\n private readonly eventBus: EventBus,\n connect: Connect,\n private readonly create: Create,\n private readonly autoPlace: AutoPlace,\n private readonly rules: Rules,\n private readonly dragging: Dragging,\n private readonly modeling: Modeling,\n private readonly cmModeling: CmModeling,\n private readonly labelEditing: CmLabelEditing,\n private readonly elementFactory: CmElementFactory,\n private readonly selection: Selection,\n private readonly canvas: Canvas,\n private readonly scheduler: Scheduler,\n ) {\n // Injecting Connect instantiates it so its connect.* drag handlers exist\n // (same reason as CmConnectHandles — the module does not eagerly init it).\n void connect;\n contextPad.registerProvider(this);\n popupMenu.registerProvider(SUBDOMAIN_MENU, {\n getPopupMenuEntries: (target: PopupMenuTarget) => this.subdomainMenuEntries(target),\n });\n popupMenu.registerProvider(PATTERN_MENU, {\n getPopupMenuEntries: (target: PopupMenuTarget) => this.patternMenuEntries(target),\n });\n popupMenu.registerProvider(ROLES_MENU, {\n getPopupMenuEntries: (target: PopupMenuTarget) => this.rolesMenuEntries(target),\n });\n // Deconflict auto-placed appends: diagram-js' stock position (right of the\n // source) ignores occupied slots — step downwards until the slot is free.\n // Registered at default priority, beating the stock low-priority listener.\n eventBus.on(\"autoPlace\", (event: { source: Shape; shape: Shape }) => {\n const { source, shape } = event;\n const position = {\n x: asTRBL(source).right + DEFAULT_DISTANCE + shape.width / 2,\n y: getMid(source).y,\n };\n return findFreePosition(\n source,\n shape,\n position,\n generateGetNextPosition({ y: { margin: 30, minDistance: 30 } }),\n );\n });\n // The pad's placement is corrected purely via CSS classes: connections\n // flip it away from the target context their last segment points into.\n eventBus.on(\"contextPad.create\", (event: { target?: unknown; pad?: HTMLElement }) => {\n const { pad, target } = event;\n if (!pad) return;\n let flipX = false;\n let flipY = false;\n if (isCmRelationship(target)) {\n const waypoints = (target.waypoints ?? []) as Point[];\n const last = waypoints[waypoints.length - 1];\n const previous = waypoints[waypoints.length - 2];\n if (last && previous) {\n const dx = last.x - previous.x;\n const dy = last.y - previous.y;\n flipX = Math.abs(dx) >= Math.abs(dy) && dx > 0;\n flipY = Math.abs(dy) > Math.abs(dx) && dy > 0;\n }\n }\n pad.classList.toggle(\"cm-pad-flip-x\", flipX);\n pad.classList.toggle(\"cm-pad-flip-y\", flipY);\n });\n // diagram-js positions the pad without any viewport clamping, and the\n // canvas container clips (overflow: hidden) — pull an overflowing pad back\n // in so its actions stay reachable for shapes at the canvas edge. Runs\n // after diagram-js' own scheduled position update (lower listener priority\n // → later schedule() call → later task).\n eventBus.on([\"contextPad.open\", \"contextPad.show\", \"canvas.viewbox.changed\"], 250, () =>\n this.clampPadIntoView(),\n );\n }\n\n private clampPadIntoView(): void {\n void this.scheduler.schedule(() => {\n const container = this.canvas.getContainer();\n const pad = container.querySelector<HTMLElement>(\".djs-context-pad.open\");\n if (!pad) return;\n const containerBounds = container.getBoundingClientRect();\n const padBounds = pad.getBoundingClientRect();\n const margin = 4;\n const overflowRight = padBounds.right - (containerBounds.right - margin);\n if (overflowRight > 0) {\n pad.style.left = `${parseFloat(pad.style.left || \"0\") - overflowRight}px`;\n }\n // The cm-pad-flip-x transform can carry a connection's pad past the\n // LEFT border (its anchor is the unclamped last waypoint).\n const overflowLeft = containerBounds.left + margin - padBounds.left;\n if (overflowLeft > 0) {\n pad.style.left = `${parseFloat(pad.style.left || \"0\") + overflowLeft}px`;\n }\n // Vertically pull an overflowing pad up — but never past the top\n // border: when the stack is taller than the canvas, the top actions\n // stay reachable rather than none of them.\n let shiftY = 0;\n const overflowBottom = padBounds.bottom - (containerBounds.bottom - margin);\n if (overflowBottom > 0) shiftY = -overflowBottom;\n const overflowTop = containerBounds.top + margin - (padBounds.top + shiftY);\n if (overflowTop > 0) shiftY += overflowTop;\n if (shiftY !== 0) {\n pad.style.top = `${parseFloat(pad.style.top || \"0\") + shiftY}px`;\n }\n }, \"cmContextPad#clampIntoView\");\n }\n\n getContextPadEntries(element: Element): ContextPadEntries {\n if (isCmContext(element)) return this.contextEntries(element);\n if (isCmRelationship(element)) return this.relationshipEntries(element);\n return {};\n }\n\n getMultiElementContextPadEntries(elements: Element[]): ContextPadEntries {\n const cmElements = elements.filter(isCmElement);\n if (cmElements.length !== elements.length) return {};\n return { delete: this.deleteEntry(cmElements, \"Delete selection\") };\n }\n\n // --- bounded context ------------------------------------------------------\n\n private contextEntries(context: CmContext): ContextPadEntries {\n const spec = context.subdomainType ? SUBDOMAIN_TYPE_SPECS[context.subdomainType] : undefined;\n return {\n \"append-context\": {\n group: \"edit\",\n html: padEntryHtml(\n iconMarkup(ICON_ADD_BOX),\n \"Append a connected context — click to place automatically, drag to position\",\n { draggable: true },\n ),\n action: {\n click: () => this.appendContext(context),\n dragstart: (event: Event) => this.startAppend(event, context),\n },\n },\n connect: {\n group: \"edit\",\n html: padEntryHtml(iconMarkup(ICON_ARROW_FORWARD), \"Connect to another context\", {\n draggable: true,\n }),\n action: {\n click: (event: Event) => this.startConnect(event, context, true),\n dragstart: (event: Event) => this.startConnect(event, context, false),\n },\n },\n \"subdomain-type\": {\n group: \"edit\",\n html: padEntryHtml(\n contextIconSvg(context.subdomainType),\n `Change subdomain type — currently ${spec?.label ?? \"unclassified\"}`,\n ),\n action: {\n click: (event: Event) => this.openMenu(event, context, SUBDOMAIN_MENU, \"Subdomain type\"),\n },\n },\n team: {\n group: \"edit\",\n html: padEntryHtml(\n iconMarkup(ICON_TEAM),\n `Set owning team — currently ${context.team ?? \"none\"}`,\n ),\n action: { click: () => this.labelEditing.activateTeam(context) },\n },\n \"edit-label\": this.editLabelEntry(context, \"Rename context\"),\n description: this.descriptionEntry(context, \"Purpose, ubiquitous language, notes…\"),\n delete: this.deleteEntry([context], \"Delete context\"),\n };\n }\n\n /**\n * Same payload as Connect#start, mirroring CmConnectHandles, but with\n * diagram-js' ghost-click trap OFF for both variants: the trap relies on the\n * gesture-ending canvas click, which Chromium suppresses whenever the\n * mousedown target was re-rendered by the connect command — the unconsumed\n * trap would then swallow the user's NEXT click. The click variant instead\n * blocks exactly one immediately-following element.click itself (when it\n * does fire, it must not re-select the target over the fresh relationship).\n */\n private startConnect(event: Event, source: CmContext, viaClick: boolean): void {\n this.dragging.init(event as MouseEvent, \"connect\", {\n autoActivate: viaClick,\n trapClick: false,\n data: {\n shape: source,\n context: { start: source, connectionStart: getMid(source) },\n },\n });\n if (viaClick) {\n const swallowGestureClick = () => false;\n this.eventBus.once(\"connect.cleanup\", 250, () => {\n this.eventBus.once(\"element.click\", 10000, swallowGestureClick);\n const disarm = (): void => this.eventBus.off(\"element.click\", swallowGestureClick);\n // Dragging binds endDrag to mousedown AND mouseup — the gesture already\n // ends in the *mousedown* of the finishing click, whose click event is\n // only delivered after the following mouseup. Hold the blocker until\n // then: the capture-mouseup runs before the click, the 0ms task after.\n document.addEventListener(\"mouseup\", () => setTimeout(disarm, 0), {\n capture: true,\n once: true,\n });\n // Safety net (same window as diagram-js' ClickTrap): if the click never\n // arrives, the blocker must not eat a later real one.\n setTimeout(disarm, 400);\n });\n }\n // The drag lifecycle clears the selection; the user is still \"at\" the source.\n this.eventBus.once(\"connect.cleanup\", 250, () => {\n if (this.selection.get().length === 0) this.selection.select(source);\n });\n }\n\n /**\n * Append a fresh, unclassified context connected to the source. The click\n * variant auto-places it (diagram-js auto-place, which also selects it), the\n * drag variant hands placement to the create tool with a `source` hint —\n * both stamp the connection through the `connection.create` rule. After\n * placement the subdomain-type menu opens so classifying is one click away.\n */\n private appendContext(source: CmContext): void {\n const shape = this.elementFactory.createNewContext();\n // CmRules returns the relationship attrs (cmKind + default pattern), not\n // just a boolean — pass them on so the connection is stamped correctly.\n const connection = this.rules.allowed(\"connection.create\", {\n source,\n target: shape,\n }) as unknown as false | null | Record<string, unknown>;\n const appended = this.autoPlace.append(\n source,\n shape,\n connection && typeof connection === \"object\" ? { connection } : {},\n ) as unknown as CmContext;\n this.openTypeMenu(appended);\n }\n\n private startAppend(event: Event, source: CmContext): void {\n const shape = this.elementFactory.createNewContext();\n const onCreated = () => this.openTypeMenu(shape);\n this.eventBus.once(\"create.end\", 250, onCreated);\n // A cancelled create must not leave the armed listener behind — it would\n // fire on the next palette create otherwise.\n this.eventBus.once(\"create.cleanup\", () => this.eventBus.off(\"create.end\", onCreated));\n this.create.start(event as MouseEvent, shape, { source });\n }\n\n /** Open the subdomain-type menu for a freshly appended context, anchored to\n * its pad entry — deferred one task so the pad has been positioned first. */\n private openTypeMenu(context: CmContext): void {\n void this.scheduler.schedule(() => {\n if (!this.contextPad.isOpen(context)) return;\n const entry = this.canvas\n .getContainer()\n .querySelector<HTMLElement>('.djs-context-pad.open [data-action=\"subdomain-type\"]');\n if (!entry) return;\n this.openMenuBeside(entry.getBoundingClientRect(), context, SUBDOMAIN_MENU, \"Subdomain type\");\n }, \"cmContextPad#openTypeMenu\");\n }\n\n // --- relationship ---------------------------------------------------------\n\n private relationshipEntries(relationship: CmRelationship): ContextPadEntries {\n // Tolerate unknown patterns (unvalidated imports), like the renderer does:\n // the pad must still open so the pattern menu can repair the element.\n const spec = RELATIONSHIP_PATTERN_SPECS[relationship.pattern] as\n RelationshipPatternSpec | undefined;\n const entries: ContextPadEntries = {\n pattern: {\n group: \"edit\",\n html: padEntryHtml(\n relationshipIconSvg(spec?.pattern),\n `Change pattern — currently ${spec?.label ?? relationship.pattern}`,\n ),\n action: {\n click: (event: Event) =>\n this.openMenu(event, relationship, PATTERN_MENU, \"Relationship pattern\"),\n },\n },\n };\n if (spec && !spec.symmetric) {\n entries.roles = {\n group: \"edit\",\n html: padEntryHtml(\n iconMarkup(ICON_TUNE),\n \"Edit integration roles — OHS/PL upstream, ACL/CF downstream\",\n ),\n action: {\n click: (event: Event) =>\n this.openMenu(event, relationship, ROLES_MENU, \"Integration roles\"),\n },\n };\n entries[\"swap-ends\"] = {\n group: \"edit\",\n html: padEntryHtml(iconMarkup(ICON_SWAP), \"Swap ends — reverse upstream/downstream\"),\n action: { click: () => this.cmModeling.swapEnds(relationship) },\n };\n }\n entries[\"edit-label\"] = this.editLabelEntry(relationship, \"Edit label\");\n entries.description = this.descriptionEntry(relationship, \"What flows here, contracts, notes…\");\n entries.delete = this.deleteEntry([relationship], \"Delete relationship\");\n return entries;\n }\n\n // --- shared entries -------------------------------------------------------\n\n private editLabelEntry(element: CmElement, title: string): ContextPadEntry {\n return {\n group: \"edit\",\n html: padEntryHtml(iconMarkup(ICON_EDIT), `${title} — edit the name in place`),\n action: { click: () => this.labelEditing.activate(element) },\n };\n }\n\n private descriptionEntry(element: CmElement, placeholder: string): ContextPadEntry {\n return {\n group: \"edit\",\n html: padEntryHtml(iconMarkup(ICON_NOTES), \"Edit description\"),\n action: {\n click: (event: Event) =>\n this.openPrompt(event, {\n value: element.description ?? \"\",\n placeholder,\n label: \"Description\",\n multiline: true,\n onCommit: (value) => this.cmModeling.setDescription(element, value || undefined),\n }),\n },\n };\n }\n\n /**\n * A small input card anchored beside the clicked pad entry (like the popup\n * menus — below would cover the rest of the vertical stack) — for the\n * free-text properties, which should not open centred over the element.\n * Enter (Ctrl/Cmd+Enter in the multiline variant) and blur commit, Escape\n * cancels.\n */\n private activePrompt?: { cancel(): void };\n\n private openPrompt(\n event: Event,\n config: {\n value: string;\n placeholder: string;\n label: string;\n multiline?: boolean;\n onCommit(value: string): void;\n },\n ): void {\n this.activePrompt?.cancel();\n const anchor = ((event as { delegateTarget?: EventTarget }).delegateTarget ??\n event.target) as HTMLElement;\n const bounds = anchor.getBoundingClientRect();\n\n const card = document.createElement(\"div\");\n card.className = \"cm-pad-prompt\";\n card.style.left = `${bounds.right + MENU_GAP}px`;\n card.style.top = `${bounds.top}px`;\n\n const field = document.createElement(config.multiline ? \"textarea\" : \"input\") as\n HTMLInputElement | HTMLTextAreaElement;\n field.className = \"cm-pad-prompt__field\";\n field.value = config.value;\n field.placeholder = config.placeholder;\n field.setAttribute(\"aria-label\", config.label);\n if (field instanceof HTMLTextAreaElement) field.rows = 4;\n card.appendChild(field);\n\n if (config.multiline) {\n const hint = document.createElement(\"div\");\n hint.className = \"cm-pad-prompt__hint\";\n hint.textContent = \"Esc to cancel · ⌘/Ctrl+Enter to save\";\n card.appendChild(hint);\n }\n\n this.canvas.getContainer().appendChild(card);\n // Keep the card on screen when the pad entry sits at a viewport edge:\n // no room on the right → flip to the entry's left, bottom → shift up.\n const cardBounds = card.getBoundingClientRect();\n const margin = 8;\n if (cardBounds.right > window.innerWidth - margin) {\n card.style.left = `${Math.max(margin, bounds.left - cardBounds.width - MENU_GAP)}px`;\n }\n if (cardBounds.bottom > window.innerHeight - margin) {\n card.style.top = `${Math.max(margin, window.innerHeight - margin - cardBounds.height)}px`;\n }\n field.focus();\n if (field instanceof HTMLTextAreaElement) {\n // Select-all in a filled textarea makes the first keystroke wipe the\n // text — park the caret at the end instead.\n field.setSelectionRange(field.value.length, field.value.length);\n } else {\n field.select();\n }\n\n // The card is viewport-anchored — commit before the canvas moves away\n // underneath it (mirrors the direct-editing guard).\n const onViewboxChanging = (): void => commit();\n this.eventBus.on(\"canvas.viewbox.changing\", onViewboxChanging);\n\n let done = false;\n const cleanup = (): void => {\n if (done) return;\n done = true;\n this.eventBus.off(\"canvas.viewbox.changing\", onViewboxChanging);\n card.remove();\n this.activePrompt = undefined;\n (this.canvas as { restoreFocus?: () => void }).restoreFocus?.();\n };\n const commit = (): void => {\n if (done) return;\n const value = field.value.trim();\n const changed = value !== config.value.trim();\n cleanup();\n if (changed) config.onCommit(value);\n };\n field.addEventListener(\"keydown\", (event: Event) => {\n const keyEvent = event as KeyboardEvent;\n if (keyEvent.key === \"Escape\") {\n keyEvent.preventDefault();\n keyEvent.stopPropagation();\n cleanup();\n } else if (\n keyEvent.key === \"Enter\" &&\n (!config.multiline || keyEvent.ctrlKey || keyEvent.metaKey)\n ) {\n keyEvent.preventDefault();\n commit();\n }\n });\n field.addEventListener(\"blur\", commit);\n this.activePrompt = { cancel: cleanup };\n }\n\n private deleteEntry(elements: CmElement[], title: string): ContextPadEntry {\n return {\n group: \"delete\",\n html: padEntryHtml(iconMarkup(ICON_DELETE), title, { danger: true }),\n action: { click: () => this.modeling.removeElements(elements as Element[]) },\n };\n }\n\n private openMenu(event: Event, element: CmElement, menuId: string, title: string): void {\n const anchor = ((event as { delegateTarget?: EventTarget }).delegateTarget ??\n event.target) as HTMLElement;\n this.openMenuBeside(anchor.getBoundingClientRect(), element, menuId, title);\n }\n\n /**\n * Menus open beside the clicked entry — beneath it they would cover the\n * rest of the vertical stack. At the viewport's right edge PopupMenu flips\n * an overflowing menu back across its anchor (and the whole pad column), so\n * a flipped menu is pushed fully left of the pad instead; the popup applies\n * its initial position only once, so the correction sticks (and is saved\n * for `reopenMenu`).\n */\n private openMenuBeside(\n entryBounds: DOMRect,\n element: CmElement,\n menuId: string,\n title: string,\n ): void {\n const position = { x: entryBounds.right + MENU_GAP, y: entryBounds.top };\n this.popupMenu.open(element, menuId, position, { title });\n const popup = document.querySelector<HTMLElement>(\".djs-popup\");\n const popupBounds = popup?.getBoundingClientRect();\n if (popup && popupBounds && popupBounds.left < entryBounds.right) {\n position.x = Math.max(MENU_GAP, entryBounds.left - MENU_GAP - popupBounds.width);\n popup.style.left = `${position.x}px`;\n }\n this.currentMenu = { element, menuId, title, position };\n }\n\n /**\n * Re-open a menu after a command: the command stack's `commandStack.changed`\n * auto-closes any popup, but a multi-select menu (integration roles) should\n * survive a toggle so combinations don't require re-opening the pad entry.\n */\n private reopenMenu(element: CmElement, menuId: string): void {\n const menu = this.currentMenu;\n if (!menu || menu.menuId !== menuId || menu.element !== element) return;\n this.popupMenu.open(element, menuId, menu.position, { title: menu.title });\n }\n\n // --- popup menus ----------------------------------------------------------\n\n private subdomainMenuEntries(target: PopupMenuTarget): PopupMenuEntries {\n if (!isCmContext(target)) return {};\n const current = target.subdomainType;\n const entries: PopupMenuEntries = {};\n for (const spec of ALL_SUBDOMAIN_SPECS) {\n entries[`type-${spec.type}`] = {\n label: spec.label,\n description: spec.description,\n imageHtml: contextIconSvg(spec.type),\n ...(spec.type === current ? { className: ACTIVE_CLASS } : {}),\n action: () => {\n if (spec.type !== current) this.cmModeling.setSubdomainType(target, spec.type);\n },\n };\n }\n entries[\"type-none\"] = {\n label: \"Unclassified\",\n description: \"No subdomain classification.\",\n imageHtml: contextIconSvg(),\n ...(current === undefined ? { className: ACTIVE_CLASS } : {}),\n action: () => {\n if (current !== undefined) this.cmModeling.setSubdomainType(target, undefined);\n },\n };\n return entries;\n }\n\n private patternMenuEntries(target: PopupMenuTarget): PopupMenuEntries {\n if (!isCmRelationship(target)) return {};\n const current = target.pattern;\n const entries: PopupMenuEntries = {};\n for (const spec of ALL_PATTERN_SPECS) {\n entries[`pattern-${spec.pattern}`] = {\n label: spec.label,\n description: spec.description,\n imageHtml: relationshipIconSvg(spec.pattern),\n ...(spec.pattern === current ? { className: ACTIVE_CLASS } : {}),\n action: () => {\n if (spec.pattern !== current) this.cmModeling.setPattern(target, spec.pattern);\n },\n };\n }\n return entries;\n }\n\n private rolesMenuEntries(target: PopupMenuTarget): PopupMenuEntries {\n if (!isCmRelationship(target)) return {};\n const spec = RELATIONSHIP_PATTERN_SPECS[target.pattern] as RelationshipPatternSpec | undefined;\n if (!spec || spec.symmetric) return {};\n const customerSupplier = target.pattern === \"customer-supplier\";\n const upstream = target.upstreamRoles ?? [];\n const downstream = target.downstreamRoles ?? [];\n const entries: PopupMenuEntries = {};\n\n for (const role of UPSTREAM_ROLES) {\n const active = upstream.includes(role);\n const blocker = customerSupplier ? CUSTOMER_SUPPLIER_BLOCKERS[role] : undefined;\n // A blocked role that is already set (unvalidated import, CML) stays\n // clickable — deselecting it is the repair, not the violation.\n const blocked = blocker !== undefined && !active;\n entries[`upstream-${role}`] = {\n label: UPSTREAM_ROLE_SPECS[role].label,\n description: blocker\n ? active\n ? `${blocker} Click to remove it.`\n : blocker\n : UPSTREAM_ROLE_SPECS[role].description,\n imageHtml: roleChipSvg(role),\n group: { id: \"upstream\", name: \"Upstream (from) — OHS and/or PL\" },\n ...(blocked ? { disabled: true } : {}),\n ...(active ? { className: ACTIVE_CLASS } : {}),\n action: () => {\n if (blocked) return;\n this.cmModeling.setUpstreamRoles(\n target,\n active ? upstream.filter((existing) => existing !== role) : [...upstream, role],\n );\n this.reopenMenu(target, ROLES_MENU);\n },\n };\n }\n for (const role of DOWNSTREAM_ROLES) {\n const active = downstream.includes(role);\n const blocker = customerSupplier ? CUSTOMER_SUPPLIER_BLOCKERS[role] : undefined;\n const blocked = blocker !== undefined && !active;\n entries[`downstream-${role}`] = {\n label: DOWNSTREAM_ROLE_SPECS[role].label,\n description: blocker\n ? active\n ? `${blocker} Click to remove it.`\n : blocker\n : DOWNSTREAM_ROLE_SPECS[role].description,\n imageHtml: roleChipSvg(role),\n group: { id: \"downstream\", name: \"Downstream (to) — ACL or CF, not both\" },\n ...(blocked ? { disabled: true } : {}),\n ...(active ? { className: ACTIVE_CLASS } : {}),\n action: () => {\n if (blocked) return;\n this.cmModeling.setDownstreamRoles(target, active ? [] : [role]);\n this.reopenMenu(target, ROLES_MENU);\n },\n };\n }\n return entries;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ContextPadModule from \"diagram-js/lib/features/context-pad\";\nimport PopupMenuModule from \"diagram-js/lib/features/popup-menu\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport CreateModule from \"diagram-js/lib/features/create\";\nimport AutoPlaceModule from \"diagram-js/lib/features/auto-place\";\nimport SelectionModule from \"diagram-js/lib/features/selection\";\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport { cmModelingModule } from \"../modeling/index.js\";\nimport { cmRulesModule } from \"../rules/index.js\";\nimport { cmLabelEditingModule } from \"../label-editing/index.js\";\nimport CmContextPadProvider from \"./CmContextPadProvider.js\";\n\nexport const cmContextPadModule: ModuleDeclaration = {\n __depends__: [\n ContextPadModule,\n PopupMenuModule,\n ConnectModule,\n CreateModule,\n AutoPlaceModule,\n SelectionModule,\n ModelingModule,\n cmModelingModule,\n // The connect action needs CmRules: only its connection.create rule stamps\n // the new connection as a relationship (cmKind + default pattern).\n cmRulesModule,\n cmLabelEditingModule,\n ],\n __init__: [\"cmContextPadProvider\"],\n cmContextPadProvider: [\"type\", CmContextPadProvider],\n};\n\nexport { default as CmContextPadProvider } from \"./CmContextPadProvider.js\";\n","/**\n * Consolidated, collapsible notation legend (single card, bottom-left of the\n * canvas): subdomain types, integration roles (OHS/PL/ACL/CF) and the\n * relationship patterns — driven entirely by the notation spec, so it can\n * never drift from what the canvas draws. Shipped by the renderer so every\n * embedder gets it, replacing the per-host copies the reference apps carried.\n * Hovering a row shows the spelled-out explanation instantly (custom CSS\n * tooltip — a native `title` only appears after the OS hover delay).\n * Collapsed it shrinks to a button in the same corner, never disappearing.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport {\n ALL_PATTERN_SPECS,\n ALL_SUBDOMAIN_SPECS,\n DOWNSTREAM_ROLE_SPECS,\n MARK_COLORS,\n UPSTREAM_ROLE_SPECS,\n} from \"@miragon/context-maps-schema-model\";\nimport { relationshipIconSvg, subdomainIconSvg } from \"../draw/palette-icons.js\";\n\nconst ROLES: ReadonlyArray<{ token: string; label: string; description: string }> = [\n { token: \"OHS\", ...UPSTREAM_ROLE_SPECS.OHS },\n { token: \"PL\", ...UPSTREAM_ROLE_SPECS.PL },\n { token: \"ACL\", ...DOWNSTREAM_ROLE_SPECS.ACL },\n { token: \"CF\", ...DOWNSTREAM_ROLE_SPECS.CF },\n];\n\nfunction legendRow(icon: HTMLElement, label: string, explanation: string): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"cm-legend__row cm-legend-item\";\n const text = document.createElement(\"span\");\n text.textContent = label;\n const tip = document.createElement(\"span\");\n tip.className = \"cm-legend-tip\";\n tip.textContent = explanation;\n // The tip is position: fixed (anchored here) so it escapes the card's\n // scroll clipping when a small canvas forces the legend body to scroll.\n row.addEventListener(\"mouseenter\", () => {\n const bounds = row.getBoundingClientRect();\n tip.style.left = `${bounds.right + 10}px`;\n tip.style.top = `${bounds.top + bounds.height / 2}px`;\n });\n row.append(icon, text, tip);\n return row;\n}\n\nfunction iconNode(svg: string): HTMLElement {\n const span = document.createElement(\"span\");\n span.className = \"cm-legend__icon\";\n span.innerHTML = svg;\n return span;\n}\n\nfunction markNode(token: string): HTMLElement {\n const span = document.createElement(\"span\");\n span.className = \"cm-legend__mark\";\n span.style.background = MARK_COLORS[token];\n span.textContent = token;\n return span;\n}\n\nfunction group(label: string, rows: HTMLElement[]): HTMLElement {\n const el = document.createElement(\"div\");\n el.className = \"cm-legend__group\";\n el.setAttribute(\"aria-label\", label);\n el.append(...rows);\n return el;\n}\n\nfunction divider(): HTMLElement {\n const el = document.createElement(\"div\");\n el.className = \"cm-legend__divider\";\n return el;\n}\n\nexport default class CmLegend {\n static $inject = [\"canvas\", \"eventBus\"];\n\n private openState = true;\n private readonly host: HTMLElement;\n\n constructor(canvas: Canvas, eventBus: EventBus) {\n this.host = document.createElement(\"div\");\n canvas.getContainer().appendChild(this.host);\n this.render();\n eventBus.on(\"diagram.destroy\", () => this.host.remove());\n }\n\n isOpen(): boolean {\n return this.openState;\n }\n\n setOpen(open: boolean): void {\n if (this.openState === open) return;\n this.openState = open;\n this.render();\n }\n\n toggle(): void {\n this.setOpen(!this.openState);\n }\n\n private render(): void {\n // The activated toggle removes itself with the re-render — hand the focus\n // to its counterpart so the keyboard path survives, but only when the\n // focus actually was inside (the initial render must not steal it).\n const hadFocus = this.host.contains(this.host.ownerDocument.activeElement);\n this.host.replaceChildren(this.openState ? this.panel() : this.collapsedButton());\n if (hadFocus) {\n this.host.querySelector<HTMLButtonElement>(\".cm-legend__close, .cm-legend-toggle\")?.focus();\n }\n }\n\n private panel(): HTMLElement {\n const box = document.createElement(\"div\");\n box.className = \"cm-legend\";\n box.setAttribute(\"aria-label\", \"Legend\");\n\n const head = document.createElement(\"div\");\n head.className = \"cm-legend__head\";\n const title = document.createElement(\"strong\");\n title.textContent = \"Legend\";\n const close = document.createElement(\"button\");\n close.type = \"button\";\n close.className = \"cm-legend__close\";\n close.setAttribute(\"aria-expanded\", \"true\");\n close.setAttribute(\"aria-label\", \"Collapse legend\");\n close.textContent = \"–\";\n close.addEventListener(\"click\", () => this.toggle());\n head.append(title, close);\n\n const subdomains = group(\n \"Subdomain types\",\n ALL_SUBDOMAIN_SPECS.map((s) =>\n legendRow(iconNode(subdomainIconSvg(s.type)), s.label, s.description),\n ),\n );\n const roles = group(\n \"Integration roles\",\n ROLES.map((r) => legendRow(markNode(r.token), r.label, `${r.label} — ${r.description}`)),\n );\n const patterns = group(\n \"Relationship patterns\",\n ALL_PATTERN_SPECS.map((p) =>\n legendRow(\n iconNode(relationshipIconSvg(p.pattern, 18)),\n `${p.abbreviation} · ${p.label}`,\n p.description,\n ),\n ),\n );\n\n // Groups live in a scrollable body so a small canvas never clips the head\n // (and with it the collapse button) away.\n const body = document.createElement(\"div\");\n body.className = \"cm-legend__body\";\n body.append(subdomains, divider(), roles, divider(), patterns);\n box.append(head, body);\n return box;\n }\n\n private collapsedButton(): HTMLElement {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"cm-legend-toggle\";\n button.setAttribute(\"aria-expanded\", \"false\");\n button.setAttribute(\"aria-label\", \"Show legend\");\n const glyph = document.createElement(\"span\");\n glyph.setAttribute(\"aria-hidden\", \"true\");\n glyph.textContent = \"▤\";\n const label = document.createElement(\"span\");\n label.textContent = \"Legend\";\n button.append(glyph, label);\n button.addEventListener(\"click\", () => this.toggle());\n return button;\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmLegend from \"./CmLegend.js\";\n\nexport const cmLegendModule: ModuleDeclaration = {\n __init__: [\"cmLegend\"],\n cmLegend: [\"type\", CmLegend],\n};\n\nexport { default as CmLegend } from \"./CmLegend.js\";\n","/**\n * Keyboard shortcuts: undo / redo / delete-selection. Bound to the document so\n * they work without first clicking (focusing) the canvas — typing inside form\n * fields is left untouched. No container `tabindex`, so the canvas never shows a\n * focus ring.\n */\n\nimport type Canvas from \"diagram-js/lib/core/Canvas\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Modeling from \"diagram-js/lib/features/modeling/Modeling\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\n\nfunction isTypingTarget(target: EventTarget | null): boolean {\n const el = target as HTMLElement | null;\n if (!el) return false;\n return (\n el.tagName === \"INPUT\" ||\n el.tagName === \"TEXTAREA\" ||\n el.tagName === \"SELECT\" ||\n el.isContentEditable\n );\n}\n\nexport default class CmKeyboard {\n static $inject = [\"canvas\", \"commandStack\", \"selection\", \"modeling\"];\n\n constructor(\n canvas: Canvas,\n commandStack: CommandStack,\n selection: Selection,\n modeling: Modeling,\n ) {\n const doc = canvas.getContainer().ownerDocument ?? document;\n\n doc.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (isTypingTarget(e.target)) return;\n const cmd = e.ctrlKey || e.metaKey;\n const key = e.key.toLowerCase();\n\n if (cmd && key === \"z\" && !e.shiftKey) {\n e.preventDefault();\n if (commandStack.canUndo()) commandStack.undo();\n } else if ((cmd && key === \"z\" && e.shiftKey) || (cmd && key === \"y\")) {\n e.preventDefault();\n if (commandStack.canRedo()) commandStack.redo();\n } else if (key === \"delete\" || key === \"backspace\") {\n const sel = selection.get() as Element[];\n if (sel.length) {\n e.preventDefault();\n modeling.removeElements([...sel]);\n }\n }\n });\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmKeyboard from \"./CmKeyboard.js\";\n\n/** Undo/redo + delete-selection on the canvas container. */\nexport const cmKeyboardModule: ModuleDeclaration = {\n __init__: [\"cmKeyboard\"],\n cmKeyboard: [\"type\", CmKeyboard],\n};\n\nexport { default as CmKeyboard } from \"./CmKeyboard.js\";\n","/**\n * Live semantic-rule markers on the canvas: a relationship with validation\n * findings gets a small warning triangle next to the issue — amber for\n * warnings, red if any finding is an error. Sided findings (e.g. an ACL issue\n * is a downstream concern) anchor at the BOTTOM-RIGHT corner of that end's\n * role-chip box (geometry shared with the renderer via endRoleChipLayout);\n * findings about the relationship as a whole sit at the middle of the line.\n * Hovering shows the message(s) instantly via a CSS tooltip (a native `title`\n * would only appear after the OS hover delay). Implemented as diagram-js\n * overlays (HTML above the SVG), so hover is not swallowed by the connection\n * hit layer and the marker follows its element. Recomputed on every change.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type ElementRegistry from \"diagram-js/lib/core/ElementRegistry\";\nimport type Overlays from \"diagram-js/lib/features/overlays/Overlays\";\nimport type { Point } from \"diagram-js/lib/util/Types\";\nimport { validateDocument, type SemanticFinding } from \"@miragon/context-maps-schema-model\";\nimport type CmExporter from \"../io/CmExporter.js\";\nimport { isCmRelationship, type CmRelationship } from \"../model/di-types.js\";\nimport { endRoleChipLayout } from \"../draw/endRoleChips.js\";\n\nconst OVERLAY_TYPE = \"cm-validation\";\nconst MARKER_SIZE = 20;\nconst LINE_OFFSET = 16;\n/** Fallback distance from the endpoint when the end has no role chips. */\nconst END_DISTANCE = 44;\n\ntype MarkerSide = \"upstream\" | \"downstream\" | \"middle\";\n\nconst AMBER = \"#d97706\";\nconst RED = \"#dc2626\";\n\ninterface RankedFinding extends SemanticFinding {\n kind: \"error\" | \"warning\";\n}\n\nfunction markerHtml(findings: RankedFinding[]): HTMLElement {\n const hasError = findings.some((finding) => finding.kind === \"error\");\n const fill = hasError ? RED : AMBER;\n const marker = document.createElement(\"div\");\n marker.className = \"cm-validation-marker\";\n marker.innerHTML =\n `<svg width=\"${MARKER_SIZE}\" height=\"${MARKER_SIZE}\" viewBox=\"0 0 24 24\">` +\n `<path d=\"M12 2.5 23 21.5H1Z\" fill=\"${fill}\" stroke=\"#fff\" stroke-width=\"1.6\" stroke-linejoin=\"round\"/>` +\n `<text x=\"12\" y=\"18.5\" text-anchor=\"middle\" font-size=\"12\" font-weight=\"800\" fill=\"#fff\" font-family=\"system-ui, sans-serif\">!</text>` +\n `</svg>`;\n\n const tooltip = document.createElement(\"div\");\n tooltip.className = \"cm-validation-tooltip\";\n for (const finding of findings) {\n const message = document.createElement(\"div\");\n message.className = \"cm-validation-tooltip__message\";\n message.textContent = finding.message;\n tooltip.appendChild(message);\n }\n marker.appendChild(tooltip);\n return marker;\n}\n\n/**\n * Where the marker sits. Sided findings anchor at the bottom-right corner of\n * the role-chip box of that end (that is where the offending OHS/PL/ACL/CF\n * badge is drawn); without chips they fall back to a point near the endpoint.\n * Whole-relationship findings sit at the middle of the line, nudged off it.\n */\nfunction anchorPoint(relationship: CmRelationship, waypoints: Point[], side: MarkerSide): Point {\n const start = waypoints[0];\n const end = waypoints[waypoints.length - 1];\n const dx = end.x - start.x;\n const dy = end.y - start.y;\n const length = Math.hypot(dx, dy) || 1;\n const ux = dx / length;\n const uy = dy / length;\n\n if (side === \"middle\") {\n return {\n x: (start.x + end.x) / 2 + -uy * LINE_OFFSET,\n y: (start.y + end.y) / 2 + ux * LINE_OFFSET,\n };\n }\n\n const customerSupplier = relationship.pattern === \"customer-supplier\";\n const layout =\n side === \"upstream\"\n ? endRoleChipLayout(\n start,\n end,\n customerSupplier ? \"S\" : \"U\",\n relationship.upstreamRoles ?? [],\n )\n : endRoleChipLayout(\n end,\n start,\n customerSupplier ? \"C\" : \"D\",\n relationship.downstreamRoles ?? [],\n );\n if (layout) {\n // Centred (almost) on the chip box corner: the triangle's visible body is\n // bottom-heavy, so half the marker overlapping the corner reads as sitting\n // right AT the corner instead of floating next to it.\n const corner = { x: layout.box.x + layout.box.width, y: layout.box.y + layout.box.height };\n return { x: corner.x + 1, y: corner.y + 1 };\n }\n\n const along = Math.min(END_DISTANCE, length * 0.35);\n const baseX = side === \"upstream\" ? start.x + ux * along : end.x - ux * along;\n const baseY = side === \"upstream\" ? start.y + uy * along : end.y - uy * along;\n return { x: baseX + -uy * LINE_OFFSET, y: baseY + ux * LINE_OFFSET };\n}\n\nexport default class CmValidationMarkers {\n static $inject = [\"eventBus\", \"elementRegistry\", \"overlays\", \"cmExporter\"];\n\n constructor(\n eventBus: EventBus,\n private readonly elementRegistry: ElementRegistry,\n private readonly overlays: Overlays,\n private readonly exporter: CmExporter,\n ) {\n const refresh = (): void => this.refresh();\n eventBus.on(\"import.render.done\", refresh);\n eventBus.on(\"commandStack.changed\", refresh);\n }\n\n private refresh(): void {\n this.overlays.remove({ type: OVERLAY_TYPE });\n\n const report = validateDocument(this.exporter.export());\n // One marker per relationship END the findings point at (or the middle for\n // whole-relationship findings), so the triangle sits next to the issue.\n const byAnchor = new Map<string, { relationshipId: string; findings: RankedFinding[] }>();\n const collect = (findings: SemanticFinding[], kind: RankedFinding[\"kind\"]): void => {\n for (const finding of findings) {\n if (!finding.relationshipId) continue;\n const key = `${finding.relationshipId} ${finding.side ?? \"middle\"}`;\n const group = byAnchor.get(key) ?? { relationshipId: finding.relationshipId, findings: [] };\n group.findings.push({ ...finding, kind });\n byAnchor.set(key, group);\n }\n };\n collect(report.errors, \"error\");\n collect(report.warnings, \"warning\");\n\n for (const [key, group] of byAnchor) {\n const element = this.elementRegistry.get(group.relationshipId);\n if (!isCmRelationship(element)) continue;\n const waypoints = (element.waypoints ?? []) as Point[];\n if (waypoints.length < 2) continue;\n const side = key.split(\" \")[1] as MarkerSide;\n const { x: markerX, y: markerY } = anchorPoint(element, waypoints, side);\n\n // Overlay positions on a connection are relative to its waypoint bbox.\n const bboxX = Math.min(...waypoints.map((p) => p.x));\n const bboxY = Math.min(...waypoints.map((p) => p.y));\n this.overlays.add(element, OVERLAY_TYPE, {\n position: {\n left: markerX - bboxX - MARKER_SIZE / 2,\n top: markerY - bboxY - MARKER_SIZE / 2,\n },\n html: markerHtml(group.findings),\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport OverlaysModule from \"diagram-js/lib/features/overlays\";\nimport CmValidationMarkers from \"./CmValidationMarkers.js\";\n\n/** Live semantic-rule markers (warning triangles with tooltips) on the canvas. */\nexport const cmValidationModule: ModuleDeclaration = {\n __depends__: [OverlaysModule],\n __init__: [\"cmValidationMarkers\"],\n cmValidationMarkers: [\"type\", CmValidationMarkers],\n};\n\nexport { default as CmValidationMarkers } from \"./CmValidationMarkers.js\";\n","/**\n * Enforces a fixed stacking order regardless of creation order, by reordering\n * the element graphics within the canvas layer. Back → front:\n *\n * relationships < contexts\n *\n * So the relationship lines always read behind the context boxes and appear to\n * dock to the box borders (the segment inside a box is covered by the box).\n */\n\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 { isCmElement, isCmRelationship, type CmElement } from \"../model/di-types.js\";\n\n/** Lower = further back. */\nfunction tier(el: CmElement): number {\n return isCmRelationship(el) ? 0 : 1;\n}\n\nexport default class CmZOrder {\n static $inject = [\"eventBus\", \"canvas\", \"elementRegistry\"];\n\n private importing = false;\n\n constructor(\n eventBus: EventBus,\n private readonly canvas: Canvas,\n private readonly elementRegistry: ElementRegistry,\n ) {\n eventBus.on(\"import.render.start\", () => {\n this.importing = true;\n });\n eventBus.on(\"import.render.done\", () => {\n this.importing = false;\n this.reorder();\n });\n eventBus.on(\"commandStack.changed\", () => {\n if (!this.importing) this.reorder();\n });\n }\n\n /** Re-append each element's graphics group in ascending tier order (back → front). */\n reorder(): void {\n const ordered = (this.elementRegistry.getAll().filter(isCmElement) as CmElement[]).sort(\n (a, b) => tier(a) - tier(b),\n );\n for (const el of ordered) {\n const gfx = this.canvas.getGraphics(el) as SVGElement | undefined;\n const wrapper = gfx?.parentNode as (Node & ChildNode) | null;\n const layer = wrapper?.parentNode as (Node & { appendChild(n: Node): Node }) | null;\n if (wrapper && layer) layer.appendChild(wrapper);\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport CmZOrder from \"./CmZOrder.js\";\n\n/** Keeps the fixed stacking order (interactions on top, base teams at the back). */\nexport const cmZOrderModule: ModuleDeclaration = {\n __init__: [\"cmZOrder\"],\n cmZOrder: [\"type\", CmZOrder],\n};\n\nexport { default as CmZOrder } from \"./CmZOrder.js\";\n","import type { ModuleDeclaration } from \"didi\";\nimport type CommandStack from \"diagram-js/lib/command/CommandStack\";\n\nimport ConnectionPreviewModule from \"diagram-js/lib/features/connection-preview\";\nimport ModelingModule from \"diagram-js/lib/features/modeling\";\nimport MoveModule from \"diagram-js/lib/features/move\";\nimport OutlineModule from \"diagram-js/lib/features/outline\";\n\nimport { NavigatedViewer } from \"./NavigatedViewer.js\";\nimport { cmModelingModule } from \"./modeling/index.js\";\nimport { cmRulesModule } from \"./rules/index.js\";\nimport { cmBehaviorsModule } from \"./behaviors/index.js\";\nimport { cmPaletteModule } from \"./palette/index.js\";\nimport { cmContextPadModule } from \"./context-pad/index.js\";\nimport { cmLegendModule } from \"./legend/index.js\";\nimport { cmLabelEditingModule } from \"./label-editing/index.js\";\nimport { cmKeyboardModule } from \"./keyboard/index.js\";\nimport { cmValidationModule } from \"./validation/index.js\";\nimport { cmZOrderModule } from \"./zorder/index.js\";\n\n/**\n * Full Context Maps editor: palette/create, move, connect with rules,\n * context pad, inline label editing, undo/redo. Boxes are fixed-size —\n * no resize feature.\n */\nexport class Modeler extends NavigatedViewer {\n protected override _getModules(): ModuleDeclaration[] {\n return [\n ...super._getModules(),\n // diagram-js stock\n ConnectionPreviewModule,\n ModelingModule,\n MoveModule,\n OutlineModule,\n // Context Maps editor\n cmModelingModule,\n cmRulesModule,\n cmBehaviorsModule,\n cmPaletteModule,\n cmContextPadModule,\n cmLegendModule,\n cmLabelEditingModule,\n cmKeyboardModule,\n cmValidationModule,\n cmZOrderModule,\n ];\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","/**\n * Four connect handles around a selected bounded context — one arrow at the\n * middle of each side (top, right, bottom, left), each pointing outward.\n * Press a handle, drag, release over another context to draw the relationship\n * (press-drag-release ONLY: a click listener would restart the tool after the\n * mouseup and leave the preview line chasing the cursor). Implemented as\n * diagram-js overlays so the handles float outside the shape, follow it, and\n * never collide with the resize handles on the selection outline.\n */\n\nimport type EventBus from \"diagram-js/lib/core/EventBus\";\nimport type Overlays from \"diagram-js/lib/features/overlays/Overlays\";\nimport type Selection from \"diagram-js/lib/features/selection/Selection\";\nimport type Connect from \"diagram-js/lib/features/connect/Connect\";\nimport type Dragging from \"diagram-js/lib/features/dragging/Dragging\";\nimport type { Element } from \"diagram-js/lib/model/Types\";\nimport { getMid } from \"diagram-js/lib/layout/LayoutUtil\";\nimport { isCmContext } from \"../model/di-types.js\";\nimport { ICON_ARROW_FORWARD, iconMarkup } from \"../draw/icons.js\";\n\nconst OVERLAY_TYPE = \"cm-connect-handle\";\nconst HANDLE_SIZE = 28;\n/** Clear of the selection outline and its mid-side resize handles. */\nconst HANDLE_GAP = 12;\n\nconst SIDES = [\n { side: \"top\", rotationDeg: -90 },\n { side: \"right\", rotationDeg: 0 },\n { side: \"bottom\", rotationDeg: 90 },\n { side: \"left\", rotationDeg: 180 },\n] as const;\n\ntype Side = (typeof SIDES)[number][\"side\"];\n\nfunction handlePosition(\n side: Side,\n shape: { width: number; height: number },\n): { top: number; left: number } {\n const centeredLeft = shape.width / 2 - HANDLE_SIZE / 2;\n const centeredTop = shape.height / 2 - HANDLE_SIZE / 2;\n const outside = HANDLE_SIZE + HANDLE_GAP;\n switch (side) {\n case \"top\":\n return { top: -outside, left: centeredLeft };\n case \"bottom\":\n return { top: shape.height + HANDLE_GAP, left: centeredLeft };\n case \"left\":\n return { top: centeredTop, left: -outside };\n case \"right\":\n return { top: centeredTop, left: shape.width + HANDLE_GAP };\n }\n}\n\nexport default class CmConnectHandles {\n static $inject = [\"eventBus\", \"selection\", \"overlays\", \"connect\", \"dragging\"];\n\n constructor(\n private readonly eventBus: EventBus,\n private readonly selection: Selection,\n private readonly overlays: Overlays,\n connect: Connect,\n private readonly dragging: Dragging,\n ) {\n // Not used to start the drag, but injecting Connect instantiates it so its\n // connect.* event handlers (hover/end → modeling.connect) are registered —\n // the connect module does not eagerly initialize it.\n void connect;\n const refresh = (): void => this.refresh();\n eventBus.on(\"selection.changed\", refresh);\n // Re-anchor after resize/undo/redo (handle offsets depend on width/height).\n eventBus.on(\"commandStack.changed\", refresh);\n }\n\n private refresh(): void {\n this.overlays.remove({ type: OVERLAY_TYPE });\n\n const selected = this.selection.get() as Element[];\n if (selected.length !== 1) return;\n const element = selected[0];\n if (!isCmContext(element)) return;\n const shape = element as unknown as { width: number; height: number };\n\n for (const { side, rotationDeg } of SIDES) {\n const handle = document.createElement(\"div\");\n handle.className = \"cm-connect-handle\";\n handle.dataset.side = side;\n handle.title = \"Connect to another context\";\n handle.innerHTML = `<span style=\"display:flex;transform:rotate(${rotationDeg}deg)\">${iconMarkup(ICON_ARROW_FORWARD)}</span>`;\n handle.addEventListener(\"mousedown\", (event: MouseEvent) => {\n if (event.button !== 0) return;\n event.preventDefault();\n event.stopPropagation();\n // Same payload as Connect#start, but with trapClick OFF: the ghost-\n // click trap Dragging arms after a drag is only consumed by a click\n // that reaches the canvas — a drag started on this HTML handle never\n // produces one, so the trap would instead swallow the user's NEXT\n // click on a context (no selection, seemingly broken editor).\n this.dragging.init(event, \"connect\", {\n autoActivate: false,\n trapClick: false,\n data: {\n shape: element,\n context: { start: element, connectionStart: getMid(element) },\n },\n });\n // Keep the source context marked after the drag: the drag lifecycle\n // clears the selection, but the user is still \"at\" this context. Low\n // priority so this runs after the stock cleanup listeners.\n this.eventBus.once(\"connect.cleanup\", 250, () => {\n if (this.selection.get().length === 0) this.selection.select(element);\n });\n });\n\n this.overlays.add(element, OVERLAY_TYPE, {\n position: handlePosition(side, shape),\n html: handle,\n });\n }\n }\n}\n","import type { ModuleDeclaration } from \"didi\";\nimport ConnectModule from \"diagram-js/lib/features/connect\";\nimport OverlaysModule from \"diagram-js/lib/features/overlays\";\nimport SelectionModule from \"diagram-js/lib/features/selection\";\nimport CmConnectHandles from \"./CmConnectHandles.js\";\n\n/** Four outward connect arrows around a selected context (top/right/bottom/left). */\nexport const cmConnectHandlesModule: ModuleDeclaration = {\n __depends__: [ConnectModule, OverlaysModule, SelectionModule],\n __init__: [\"cmConnectHandles\"],\n cmConnectHandles: [\"type\", CmConnectHandles],\n};\n\nexport { default as CmConnectHandles } from \"./CmConnectHandles.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAS,EAAO,GAAiC;CAC/C,OAAO,OAAO,KAAO,YAAY,IAC3B,EAA4B,SAC9B,KAAA;AACN;AAEA,SAAgB,EAAY,GAA8B;CACxD,OAAO,OAAO,EAAO,CAAE,KAAM;AAC/B;AAEA,SAAgB,EAAY,GAA8B;CACxD,OAAO,EAAO,CAAE,MAAM;AACxB;AAEA,SAAgB,EAAiB,GAAmC;CAClE,OAAO,EAAO,CAAE,MAAM;AACxB;;;ACpDA,IAAM,KAAS;AAEf,SAAgB,GAAQ,GAAgB,GAAmD;CAEzF,IAAM,IADY,EAAO,aACV,CAAA,CAAU,cAAc,KAAK;CAC5C,IAAI,CAAC,GAAQ,MAAU,MAAM,uCAAuC;CAGpE,IAAI,IAAO,UACP,IAAO,UACP,IAAO,WACP,IAAO;CACX,KAAK,IAAM,KAAM,EAAgB,OAAO,GAAG;EACzC,IAAI,CAAC,EAAY,CAAE,GAAG;EACtB,IAAM,IAAI;EAIV,AAHA,IAAO,KAAK,IAAI,GAAM,EAAE,CAAC,GACzB,IAAO,KAAK,IAAI,GAAM,EAAE,CAAC,GACzB,IAAO,KAAK,IAAI,GAAM,EAAE,IAAI,EAAE,KAAK,GACnC,IAAO,KAAK,IAAI,GAAM,EAAE,IAAI,EAAE,MAAM;CACtC;CACA,AAAK,OAAO,SAAS,CAAI,MACvB,IAAO,GACP,IAAO,GACP,IAAO,KACP,IAAO;CAGT,IAAM,IAAI,IAAO,IACX,IAAI,IAAO,IACX,IAAQ,IAAO,IAAO,IACtB,IAAS,IAAO,IAAO,IAEvB,IAAQ,EAAO,UAAU,EAAI;CAInC,AAHA,EAAM,aAAa,SAAS,4BAA4B,GACxD,EAAM,aAAa,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAM,GAAG,GAAQ,GAC5D,EAAM,aAAa,SAAS,OAAO,KAAK,MAAM,CAAK,CAAC,CAAC,GACrD,EAAM,aAAa,UAAU,OAAO,KAAK,MAAM,CAAM,CAAC,CAAC;CAGvD,IAAM,IAAW,EAAM,cAA2B,WAAW;CAI7D,OAHI,KAAU,EAAS,gBAAgB,WAAW,GAG3C,EAAE,KAAK,iDADF,IAAI,cAAc,CAAC,CAAC,kBAAkB,CACS,EAAI;AACjE;;;ACpDA,IAAa,KAAU;;;AC8BvB,SAAS,GAAU,GAAgC;CACjD,OAAO,OAAO,KAAU,WAAW,GAAG,EAAM,MAAM;AACpD;AAEA,IAAsB,IAAtB,MAAmC;CAGjC;CACA;CACA;CAEA,YAAY,IAA2B,CAAC,GAAG;EAEzC,AADA,KAAK,WAAW,GAChB,KAAK,aAAa,KAAK,iBAAiB,CAAO;CACjD;CAEA,iBAAyB,GAAuC;EAC9D,IAAM,IAAY,EAAQ,aAAa,SAAS,cAAc,KAAK;EAInE,OAHA,EAAU,UAAU,IAAI,kBAAkB,GAC1C,EAAU,MAAM,QAAQ,GAAU,EAAQ,SAAS,MAAM,GACzD,EAAU,MAAM,SAAS,GAAU,EAAQ,WAAW,EAAQ,YAAY,SAAS,QAAQ,GACpF;CACT;CAEA,iBAAkC;EAChC,IAAI,CAAC,KAAK,UAAU;GAClB,IAAM,IAAU,CAAC,GAAG,KAAK,YAAY,GAAG,GAAI,KAAK,SAAS,qBAAqB,CAAC,CAAE;GAClF,KAAK,WAAW,IAAI,EAAQ;IAAE,QAAQ,EAAE,WAAW,KAAK,WAAW;IAAG;GAAQ,CAAC;EACjF;EACA,OAAO,KAAK;CACd;CAGA,IAAO,GAAiB;EACtB,OAAO,KAAK,eAAe,CAAC,CAAC,IAAO,CAAI;CAC1C;CAEA,GAAgB,GAAe,GAA4B,IAAW,KAAY;EAChF,KAAK,IAAc,UAAU,CAAC,CAAC,GAAG,GAAO,GAAU,CAAyB;CAC9E;CAEA,IAAI,GAAe,GAA+B;EAChD,KAAK,IAAc,UAAU,CAAC,CAAC,IAAI,GAAO,CAAQ;CACpD;CAGA,eAAe,GAAgD;EAC7D,IAAM,IAAU,KAAK,eAAe,GAC9B,IAAW,EAAQ,IAAc,UAAU,GAC3C,IAAW,EAAQ,IAAgB,YAAY;EACrD,EAAS,MAAM;EACf,IAAM,IAAW,EAAS,OAAO,CAAG;EAGpC,OAFA,KAAK,KAAK,GACV,EAAS,KAAK,eAAe,EAAE,YAAS,CAAC,GAClC,EAAE,YAAS;CACpB;CAGA,iBAA6B;EAC3B,OAAO,KAAK,IAAgB,YAAY,CAAC,CAAC,OAAO;CACnD;CAGA,QAAQ,GAA4C;EAClD,IAAM,IAAS,KAAK,IAAY,QAAQ,GACpC;EACJ,IAAI;GACF,IAAO,EAAO,eAAe;EAC/B,QAAQ;GACN;EACF;EACA,IAAI,CAAC,KAAQ,EAAK,OAAA,WAAgB;EAClC,IAAM,IAAU,EAAK,kBAAkB,EAAE,OAAO,uBAAuB;EACvE,EAAK,iBAAiB;GAAE,GAAG;GAAS,GAAG;EAAQ;CACjD;CAGA,UAA0C;EACxC,IAAI;GAEF,OADa,KAAK,IAAY,QAAQ,CAAC,CAAC,eACjC,CAAA,CAAK;EACd,QAAQ;GACN;EACF;CACF;CAGA,UAA2B;EACzB,OAAO,GAAQ,KAAK,IAAY,QAAQ,GAAG,KAAK,IAAqB,iBAAiB,CAAC;CACzF;CAGA,KAAa,IAAW,IAAI,IAAM,IAAI,IAAY,GAAW;EAC3D,IAAM,IAAS,KAAK,IAAY,QAAQ,GAClC,IAAW,KAAK,IAAqB,iBAAiB,GACxD,IAAO,UACP,IAAO,UACP,IAAO,WACP,IAAO;EACX,KAAK,IAAM,KAAM,EAAS,OAAO,GAAG;GAClC,IAAM,IAAI;GAER,OAAO,EAAE,KAAM,YACf,OAAO,EAAE,KAAM,YACf,OAAO,EAAE,SAAU,YACnB,OAAO,EAAE,UAAW,aAItB,IAAO,KAAK,IAAI,GAAM,EAAE,CAAC,GACzB,IAAO,KAAK,IAAI,GAAM,EAAE,CAAC,GACzB,IAAO,KAAK,IAAI,GAAM,EAAE,IAAI,EAAE,KAAK,GACnC,IAAO,KAAK,IAAI,GAAM,EAAE,IAAI,EAAE,MAAM;EACtC;EACA,IAAI,CAAC,OAAO,SAAS,CAAI,GAAG;EAE5B,IAAM,IAAO,KAAK,WAAW,sBAAsB,GAC7C,IAAI,EAAK,OACT,IAAI,EAAK,QACT,IAAK,KAAK,IAAI,IAAO,GAAM,CAAC,GAC5B,IAAK,KAAK,IAAI,IAAO,GAAM,CAAC;EAClC,IAAI,CAAC,KAAK,CAAC,GAAG;GACZ,EAAO,KAAK,cAAc;GAC1B;EACF;EACA,IAAM,IAAI,KAAK,KAAK,IAAI,IAAY,KAAO,IAAK,IAAI,IAAW,KAAO,GAAI,IAAI,GAExE,IAAU,KAAa,IAAI,IAAY,IAAM,IAAI,KAAM;EAC7D,EAAO,QAAQ;GACb,GAAG,IAAO,IAAU;GACpB,GAAG,IAAO,IAAW;GACrB,OAAO,IAAI;GACX,QAAQ,IAAI;EACd,CAAC;CACH;CAGA,SAAS,GAA2B;EAElC,AADA,EAAO,YAAY,KAAK,UAAU,GAClC,KAAK,IAAY,QAAQ,CAAC,CAAC,QAAQ;CACrC;CAGA,SAAe;EACb,KAAK,WAAW,OAAO;CACzB;CAEA,QAAc;EACZ,KAAK,eAAe,CAAC,CAAC,MAAM;CAC9B;CAEA,UAAgB;EAKd,AAJA,AAEE,KAAK,cADL,KAAK,SAAS,QAAQ,GACN,KAAA,IAElB,KAAK,WAAW,OAAO;CACzB;CAEA,IAAI,YAAyB;EAC3B,OAAO,KAAK;CACd;AACF,GCjLqB,KAArB,MAAsC;CAGP;CAF7B,OAAO,UAAU,CAAC,gBAAgB;CAElC,YAAY,GAAiD;EAAhC,KAAA,iBAAA;CAAiC;CAI9D,cAAc,GAAgC;EAK5C,IAAM,KADO,EAAI,gBAAgB,EAAqB,EAAI,iBAAiB,KAAA,EAAA,EACrD,WAAW;GAAE,OAAO;GAAK,QAAQ;EAAG;EAC1D,OAAO,KAAK,eAAe,YAAY;GACrC,IAAI,EAAI;GACR,GAAG,EAAI,SAAS;GAChB,GAAG,EAAI,SAAS;GAChB,OAAO,KAAK,IAAI,EAAI,KAAK,OAAO,EAAQ,KAAK;GAC7C,QAAQ,KAAK,IAAI,EAAI,KAAK,QAAQ,EAAQ,MAAM;GAChD,QAAQ;GACR,SAAS,EAAI;GACb,GAAI,EAAI,gBAAgB,EAAE,eAAe,EAAI,cAAc,IAAI,CAAC;GAChE,GAAI,EAAI,OAAO,EAAE,MAAM,EAAI,KAAK,IAAI,CAAC;GACrC,GAAI,EAAI,cAAc,EAAE,aAAa,EAAI,YAAY,IAAI,CAAC;GAC1D,GAAI,EAAI,OAAO,EAAE,MAAM,EAAI,KAAK,IAAI,CAAC;GACrC,GAAI,EAAI,SAAS,EAAE,QAAQ,EAAI,OAAO,IAAI,CAAC;EAC7C,CAAuB;CACzB;CAEA,mBACE,GACA,GACA,GACA,GACgB;EAChB,OAAO,KAAK,eAAe,iBAAiB;GAC1C,IAAI,EAAI;GACR;GACA;GACA;GACA,QAAQ;GACR,SAAS,EAAI;GACb,GAAI,EAAI,eAAe,SAAS,EAAE,eAAe,CAAC,GAAG,EAAI,aAAa,EAAE,IAAI,CAAC;GAC7E,GAAI,EAAI,iBAAiB,SAAS,EAAE,iBAAiB,CAAC,GAAG,EAAI,eAAe,EAAE,IAAI,CAAC;GACnF,GAAI,EAAI,QAAQ,EAAE,SAAS,EAAI,MAAM,IAAI,CAAC;GAC1C,GAAI,EAAI,cAAc,EAAE,aAAa,EAAI,YAAY,IAAI,CAAC;GAC1D,GAAI,EAAI,2BACJ,EAAE,0BAA0B,EAAI,yBAAyB,IACzD,CAAC;EACP,CAAuC;CACzC;CAQA,iBAAiB,GAA+B,GAA2B;EAEzE,IAAM,KACH,IAAgB,EAAqB,KAAiB,KAAA,EAAA,EAAY,eACnE,EAAqB,QAAQ;EAC/B,OAAO,KAAK,eAAe,YAAY;GACrC,OAAO,EAAK;GACZ,QAAQ,EAAK;GACb,QAAQ;GACR,GAAI,IAAgB,EAAE,iBAAc,IAAI,CAAC;GACzC,SAAS,KAAS;EACpB,CAAuB;CACzB;AACF,GCzEqB,KAArB,cAAqD,EAAe;CAKlE,OACE,GACA,GACmC;EAInC,OAHI,CAAC,GAAO,OAAO,MAAS,WAAW,MAAS,kBAC9C,IAAQ;GAAE,GAAG;GAAO,IAAI,EAAM,MAAS,UAAU,QAAQ,KAAK;EAAE,IAE3D,MAAM,OAAO,GAAiB,CAAuB;CAC9D;AACF,GCLqB,KAArB,MAAgC;CAGD;CAF7B,OAAO,UAAU,CAAC,mBAAmB;CAErC,YAAY,GAAqD;EAApC,KAAA,UAAA;CAAqC;CAElE,iBAAiB,GAA4B,IAAqB,CAAC,GAAY;EAC7E,IAAM,IAAS,EAAM,UAAU,EAAW,QACpC,IAAS,EAAM,UAAU,EAAW,QASpC,IAAuB,CAHf,IAAS,EAAO,CAAM,IAAI,EAAM,mBAAmB,KAAA,GACrD,IAAS,EAAO,CAAM,IAAI,EAAM,iBAAiB,KAAA,CAErB,CAAC,CAAC,OAAO,OAAO;EAOxD,OAJA,EAAW,YAAY,GACnB,KAAU,KAAU,EAAY,WAAW,IACtC,KAAK,QAAQ,oBAAoB,GAAY,GAAQ,CAAM,IAE7D;CACT;AACF,GCnCa,KAAmC;CAC9C,gBAAgB,CAAC,QAAQ,EAAuB;CAChD,kBAAkB,CAAC,QAAQ,EAAgB;CAC3C,mBAAmB,CAAC,QAAQ,CAAyB;AACvD,GCEa,IAAU;CAErB,MAAM;CAEN,UAAU;CAEV,UAAU;CAEV,OAAO;CAEP,MAAM;CAEN,SAAS;CACT,OAAO;CAEP,SAAS;CACT,SAAS;CACT,QAAQ;CACR,MAAM;CAEN,eAAe;AACjB,GAOa,KAAoC;CAC/C,aAAa,EAAQ;CACrB,cAAc,EAAQ;CACtB,aAAa,EAAQ;CACrB,gBAAgB,EAAQ;CACxB,cAAc,EAAQ;CACtB,kBAAkB,EAAQ;CAC1B,kBAAkB,EAAQ;CAC1B,gBAAgB,EAAQ;CACxB,qBAAqB;CACrB,gBAAgB,EAAQ;CACxB,qBAAqB;CACrB,eAAe,EAAQ;CACvB,oBAAoB;CACpB,aAAa,EAAQ;CACrB,kBAAkB;CAClB,uBAAuB,EAAQ;AACjC,GCzDa,KAAqB;AAGZ,EAAQ;AAE9B,IAAa,IAAM,EAAQ,SACd,KAAW,WAEX,IAAO;CASlB,QACE;CACF,OAAO;CACP,OAAO;AACT,GAaa,IAAQ,EAAQ,OAGhB,KAAe,WACf,KAAiB;;;ACzB9B,SAAgB,EACd,GACA,GACA,GACA,GAC0B;CAC1B,IAAI,EAAM,WAAW,GAAG,OAAO;CAE/B,IAAM,IAAK,EAAO,IAAI,EAAS,GACzB,IAAK,EAAO,IAAI,EAAS,GACzB,IAAS,KAAK,MAAM,GAAI,CAAE,KAAK,GAC/B,IAAK,IAAK,GACV,IAAK,IAAK,GACV,IAAQ,EAAK,QAAQ,KAGrB,IAAa,EAAK,QAAQ,GAG1B,IAAa,EAAM,KAAK,MAAS,EAAK,SAAS,IAAQ,EAAE,GACzD,IAAa,EAAW,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,KAAO,EAAM,SAAS,IAC3E,IAAQ,IAAa,GACrB,IAAS,IAAa,GAEtB,IAAO,KAAc,EAAU,SAAS,IAAS,IAAI,IAAI,IAAQ,GACjE,IAAS;EAAE,GAAG,EAAS,IAAI,IAAK;EAAM,GAAG,EAAS,IAAI,IAAK;CAAK;CAEtE,OAAO;EACL,KAAK;GAAE,GAAG,EAAO,IAAI,IAAQ;GAAG,GAAG,EAAO,IAAI,IAAS;GAAG;GAAO;EAAO;EACxE;EACA;EACA;EACA;EACA;CACF;AACF;;;ACJA,IAAqB,KAArB,cAAiD,GAAa;CAC5D,OAAO,UAAU,CAAC,UAAU;CAE5B,YAAY,GAAoB;EAC9B,MAAM,GAAU,EAAkB;CACpC;CAEA,UAAmB,GAA+B;EAChD,OAAO,EAAY,CAAO;CAC5B;CAEA,UAAmB,GAAqB,GAAgC;EAItE,IADA,EAAS,CAAO,GACZ,EAAY,CAAO,GAAG,OAAO,KAAK,YAAY,GAAS,CAAO;EAClE,IAAM,IAAO,EAAQ,EAAU,MAAM,GAAG;GACtC,OAAO,EAAQ;GACf,QAAQ,EAAQ;GAChB,MAAM;EACR,CAAC;EAED,OADA,EAAU,GAAS,CAAI,GAChB;CACT;CAEA,eAAwB,GAAqB,GAAwC;EAEnF,IADA,EAAS,CAAO,GACZ,EAAiB,CAAU,GAAG,OAAO,KAAK,iBAAiB,GAAS,CAAU;EAClF,IAAM,IAAO,EAAQ,EAAU,UAAU,GAAG;GAC1C,SAAS,EAAW,aAAa,CAAC,EAAA,CAAG,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG;GACzE,MAAM;GACN,QAAQ;EACV,CAAC;EAED,OADA,EAAU,GAAS,CAAI,GAChB;CACT;CAEA,aAAsB,GAA0B;EAC9C,IAAM,EAAE,MAAG,MAAG,UAAO,cAAW;EAChC,OAAO,IAAI,EAAE,GAAG,EAAE,GAAG,EAAM,OAAO,EAAO,GAAG,CAAC,EAAM;CACrD;CAEA,kBAA2B,GAAoC;EAC7D,IAAM,IAAM,EAAW,aAAa,CAAC;EAErC,OADI,EAAG,WAAW,IAAU,KACrB,EAAG,KAAK,GAAG,MAAQ,GAAG,MAAQ,IAAI,MAAM,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE;CAC5E;CAIA,YAAoB,GAAqB,GAA4B;EACnE,IAAM,IAAO,EAAI,gBAAgB,EAAqB,EAAI,iBAAiB,KAAA,GACrE,IAAI,KAAK,IAAI,EAAI,OAAO,CAAC,GACzB,IAAI,KAAK,IAAI,EAAI,QAAQ,CAAC,GAG1B,IAAM,EAAQ,EAAU,MAAM,GAAG;GACrC,GAAG;GACH,GAAG;GACH,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,IAAI;GACJ,IAAI;GACJ,MAAM,EAAI,QAAQ,GAAM,QAAA;GACxB,QAAQ,EAAI,UAAU,GAAM,UAAA;GAC5B,gBAAgB;GAChB,mBAAmB;EACrB,CAAC;EAMD,IALA,EAAU,GAAS,CAAG,GAEtB,KAAK,YAAY,GAAS,EAAI,WAAW,IAAI,GAAG,GAAG,EAAQ,EAAI,MAAO,EACpE,eAAe,MACjB,CAAC,GACG,EAAI,iBAAiB,GAAM;GAG7B,EAAU,GAAS,GAAc,EAAI,eAAe,IAAI,IAAI,IAAI,EAAK,MAAM,CAAC;GAC5E,IAAM,IAAQ,EAAQ,EAAU,MAAM,GAAG;IACvC,GAAG;IACH,GAAG;IACH,eAAe,EAAK;IACpB,aAAa,EAAK;IAClB,eAAe;IACf,MAAM,EAAK;IACX,eAAe;IACf,qBAAqB;IACrB,kBAAkB;GACpB,CAAC;GAED,AADA,EAAM,cAAc,EAAK,OACzB,EAAU,GAAS,CAAK;EAC1B;EACA,IAAI,EAAI,MAAM;GAEZ,IAGM,IAAa,KAHD,EAAI,KAAK,SAAS,EAAK,QAAQ,KAI3C,IAAS,IAAI,IAAI,IAAa,GAC9B,IAAK,IAAI,IAET,IAAO,GAAW,IAAS,GAAc,GAAI,IAAU,EAAQ;GAErE,AADA,EAAQ,GAAM,EAAE,OAAO,UAAU,CAAC,GAClC,EAAU,GAAS,CAAI;GAEvB,IAAM,IAAO,EAAQ,EAAU,MAAM,GAAG;IACtC,OAAO;IACP,GAAG,IAAS,KAAW;IACvB,GAAG;IACH,eAAe,EAAK;IACpB,aAAa,EAAK;IAClB,MAAM;IACN,eAAe;IACf,qBAAqB;GACvB,CAAC;GAED,AADA,EAAK,cAAc,EAAI,MACvB,EAAU,GAAS,CAAI;EACzB;EACA,OAAO;CACT;CAIA,iBAAyB,GAAqB,GAAiC;EAC7E,IAAM,IACJ,EAA2B,EAAI,YAAY,EAA2B,wBAClE,IAAM,EAAI,aAAa,CAAC,GACxB,IAAO,EAAK,MACZ,IAAO,EAAQ,EAAU,UAAU,GAAG;GAC1C,QAAQ,EAAG,KAAK,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG;GAC/C,MAAM;GACN,QAAQ,EAAK;GACb,gBAAgB,EAAK;GACrB,mBAAmB;GACnB,kBAAkB;GAClB,GAAI,IAAO,EAAE,oBAAoB,EAAK,IAAI,CAAC;EAC7C,CAAC;EAGD,IAFA,EAAU,GAAS,CAAI,GAEnB,EAAG,UAAU,GAAG;GAClB,IAAM,IAAM,EAAG,IACT,IAAM,EAAG,EAAG,SAAS,IACrB,IAAU,EAAI,iBAAiB,CAAC,GAChC,IAAY,EAAI,mBAAmB,CAAC;GAE1C,IAAI,EAAK,WAAW;IAElB,IAAM,KAAM,EAAI,IAAI,EAAI,KAAK,GACvB,KAAM,EAAI,IAAI,EAAI,KAAK;IAC7B,KAAK,KAAK,GAAS,GAAI,GAAI,EAAK,cAAc,GAAO,EAAK,QAAQ,EAAK,MAAM;GAC/E,OAAO;IAIL,IAAM,IAAK,EAAI,YAAY;IAE3B,AADA,KAAK,WAAW,GAAS,GAAK,GAAK,IAAK,MAAM,KAAK,CAAO,GAC1D,KAAK,WAAW,GAAS,GAAK,GAAK,IAAK,MAAM,KAAK,CAAS;GAC9D;EACF;EACA,OAAO;CACT;CAOA,WACE,GACA,GACA,GACA,GACA,GACM;EACN,IAAM,IAAK,EAAO,IAAI,EAAS,GACzB,IAAK,EAAO,IAAI,EAAS,GACzB,IAAM,KAAK,MAAM,GAAI,CAAE,KAAK,GAC5B,IAAK,IAAK,GACV,IAAK,IAAK,GAIV,IAAW,EAAY,MAAc,GACrC,IAAS,EAAQ,EAAU,MAAM,GAAG;GACxC,GAAG,EAAS,IAAI,IAAK;GACrB,GAAG,EAAS,IAAI,IAAK;GACrB,eAAe,EAAK;GACpB,aAAa,EAAK,QAAQ;GAC1B,eAAe;GACf,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,eAAe;GACf,eAAe;GACf,qBAAqB;EACvB,CAAC;EAED,AADA,EAAO,cAAc,GACrB,EAAU,GAAS,CAAM;EAIzB,IAAM,IAAS,EAAkB,GAAU,GAAQ,GAAW,CAAK;EACnE,IAAI,CAAC,GAAQ;EACb,IAAM,EAAE,QAAK,WAAQ,YAAY,GAAQ,YAAY,IAAO,YAAY,GAAQ,YAAQ,GAClF,IAAK,EAAO,GAEZ,IAAS,EAAQ,EAAU,MAAM,GAAG;GACxC,GAAG,EAAI;GACP,GAAG,EAAI;GACP,OAAO,EAAI;GACX,QAAQ,EAAI;GACZ,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,gBAAgB;GAChB,QAAQ;GACR,gBAAgB;EAClB,CAAC;EACD,EAAU,GAAS,CAAM;EAEzB,IAAI,IAAI,EAAO,IAAI,IAAS;EAC5B,EAAM,SAAS,GAAM,MAAM;GACzB,IAAM,IAAI,EAAO,IACX,IAAO,EAAY,MAAA;GAEzB,AADA,KAAK,SAAS,GAAS,IAAI,IAAI,GAAG,GAAI,GAAG,IAAO,GAAM,CAAI,GAC1D,KAAK,IAAI;EACX,CAAC;CACH;CAGA,SACE,GACA,GACA,GACA,GACA,GACA,GACA,GACM;EACN,IAAM,IAAK,EAAQ,EAAU,MAAM,GAAG;GACpC,GAAG,IAAK,IAAI;GACZ,GAAG,IAAK,IAAI;GACZ,OAAO;GACP,QAAQ;GACR,IAAI;GACJ,IAAI;GACJ;GACA,QAAQ,GAAO,CAAI;GACnB,gBAAgB;EAClB,CAAC;EACD,EAAU,GAAS,CAAE;EACrB,IAAM,IAAI,EAAQ,EAAU,MAAM,GAAG;GACnC,GAAG;GACH,GAAG;GACH,eAAe,EAAK;GACpB,aAAa,EAAK;GAClB,eAAe;GACf,MAAM;GACN,eAAe;GACf,qBAAqB;EACvB,CAAC;EAED,AADA,EAAE,cAAc,GAChB,EAAU,GAAS,CAAC;CACtB;CAGA,KACE,GACA,GACA,GACA,GACA,GACA,GACA,GACM;EACN,IAAI,CAAC,GAAM;EAEX,IAAM,IAAQ,EAAK,QAAQ,KACrB,IAAI,EAAK,SAAS,IAAQ,IAC1B,IAAI,EAAK,QAAQ,GACjB,IAAK,EAAQ,EAAU,MAAM,GAAG;GACpC,GAAG,IAAK,IAAI;GACZ,GAAG,IAAK,IAAI;GACZ,OAAO;GACP,QAAQ;GACR,IAAI;GACJ,IAAI;GACJ,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,GAAI,MAAW,IAAQ,EAAE,gBAAgB,IAAK,IAAI,CAAC;EACrD,CAAC;EACD,EAAU,GAAS,CAAE;EACrB,IAAM,IAAI,EAAQ,EAAU,MAAM,GAAG;GACnC,GAAG;GACH,GAAG;GACH,eAAe,EAAK;GACpB,aAAa,EAAK;GAClB,eAAe;GACf,MAAM;GACN,eAAe;GACf,qBAAqB;EACvB,CAAC;EAED,AADA,EAAE,cAAc,GAChB,EAAU,GAAS,CAAC;CACtB;CAQA,YACE,GACA,GACA,GACA,GACA,GACA,GACM;EACN,IAAM,IACJ,OAAO,EAAM,gBAAiB,WAAY,EAAM,eAA0B,EAAK,OAC3E,IAAa,OAAO,EAAM,kBAAkB,KAAK,GACjD,IAAW,IAAI,IACjB,IAAQ,GAAU,GAAM,GAAU,GAAU,CAAU,GACpD,IAAa,IAAW,KACxB,IAAY,IAAA,MAAwB,IAAA,KAAiC,IACrE,IAAW,KAAK,IAAI,GAAG,KAAK,MAAM,IAAY,CAAU,CAAC;EAC/D,AAAI,EAAM,SAAS,MACjB,IAAQ,EAAM,MAAM,GAAG,CAAQ,GAC/B,EAAM,IAAW,KAAK,GAAU,EAAM,IAAW,IAAI,GAAU,GAAU,CAAU;EAErF,IAAM,IAAA,KAA4B,IAAa;EAC/C,EAAM,SAAS,GAAI,MAAQ;GACzB,IAAM,IAAI,EAAQ,EAAU,MAAM,GAAG;IAEnC,OAAO;IACP,GAAG,IAAI;IACP,GAAG,IAAS,IAAM;IAClB,eAAe,EAAK;IACpB,aAAa;IACb,MAAM;IACN,eAAe;IACf,qBAAqB;IACrB,GAAG;GACL,CAAC;GAED,AADA,EAAE,cAAc,GAChB,EAAU,GAAS,CAAC;EACtB,CAAC;CACH;AACF;AAKA,SAAS,GAAO,GAAa,IAAI,IAAa;CAC5C,IAAM,IAAI,oBAAoB,KAAK,CAAG;CACtC,IAAI,CAAC,GAAG,OAAO;CACf,IAAM,IAAI,SAAS,EAAE,IAAI,EAAE;CAI3B,OAAO,OAHG,KAAK,OAAQ,KAAK,KAAM,OAAO,CAG3B,EAAE,GAFN,KAAK,OAAQ,KAAK,IAAK,OAAO,CAErB,EAAE,GADX,KAAK,OAAO,IAAI,OAAO,CACT,EAAE;AAC5B;AAGA,IAAM,KACJ,sFACI,KACJ;AAOF,SAAS,GACP,GACA,GACA,GACA,GACA,GACY;CACZ,IAAI,MAAS,WAAW;EACtB,IAAM,IAAI,EAAU,GAAG,GACjB,IAAI,EAAQ,EAAU,QAAQ,GAAG;GACrC;GACA;GACA,GAAG,IAAO,IAAI;GACd,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,oBAAoB;EACtB,CAAC;EAED,OADA,EAAU,GAAG,CAAC,GACP;CACT;CACA,IAAM,IAAQ,IAAO,IAEf,IAAM,MAAS,eAAe,sBAAsB,IACpD,IAAI,EAAU,GAAG;CACvB,EAAQ,GAAG,EACT,WAAW,aAAa,IAAK,KAAK,EAAM,GAAG,IAAK,KAAK,EAAM,UAAU,EAAM,GAAG,IAChF,CAAC;CACD,IAAM,IAAO,EAAQ,EAAU,MAAM,GAAG;EACtC,GAAG,MAAS,SAAS,KAAY;EACjC,MAAM;CACR,CAAC;CAED,OADA,EAAU,GAAG,CAAI,GACV;AACT;AAGA,IAAM,KACJ;AAGF,SAAS,GAAW,GAAY,GAAY,GAAc,GAA2B;CACnF,IAAM,IAAQ,IAAO,IACf,IAAI,EAAU,GAAG;CACvB,EAAQ,GAAG,EAAE,WAAW,aAAa,IAAK,KAAK,EAAM,GAAG,IAAK,KAAK,EAAM,UAAU,EAAM,GAAG,CAAC;CAC5F,IAAM,IAAO,EAAQ,EAAU,MAAM,GAAG;EAAE,GAAG;EAAa,MAAM;CAAM,CAAC;CAEvE,OADA,EAAU,GAAG,CAAI,GACV;AACT;AAQA,IAAI;AAEJ,SAAS,GAAU,GAAc,GAAkB,GAA4B;CAO7E,OANI,MAAmB,KAAA,MACrB,IACE,OAAO,WAAa,MAAc,OAAO,SAAS,cAAc,QAAQ,CAAC,CAAC,WAAW,IAAI,IAExF,KACL,EAAe,OAAO,GAAG,EAAW,GAAG,EAAS,KAAK,EAAK,UACnD,EAAe,YAAY,CAAI,CAAC,CAAC,SAFZ,EAAK,SAAS,IAAW;AAGvD;AAEA,SAAS,GAAU,GAAc,GAAkB,GAAkB,GAA4B;CAC/F,IAAI,IAAO;CACX,OAAO,KAAQ,GAAU,GAAG,EAAK,IAAI,GAAU,CAAU,IAAI,IAC3D,IAAO,EAAK,MAAM,GAAG,EAAE,CAAC,CAAC,QAAQ;CAEnC,OAAO,GAAG,EAAK;AACjB;AAIA,SAAS,GAAU,GAAc,GAAkB,GAAkB,GAA8B;CACjG,IAAM,IAAa,EAAK,MAAM,IAAI;CAElC,OADI,EAAW,OAAO,MAAc,EAAU,KAAK,MAAM,EAAE,IAAU,CAAC,IAC/D,EAAW,SAAS,MAAc;EACvC,IAAM,IAAQ,GAAc,GAAW,GAAU,GAAU,CAAU;EAErE,OAAO,EAAM,SAAS,IAAQ,CAAC,EAAE;CACnC,CAAC;AACH;AAEA,SAAS,GACP,GACA,GACA,GACA,GACU;CACV,IAAM,IAAQ,EAAK,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CAC9C,IAAI,EAAM,WAAW,GAAG,OAAO,CAAC;CAChC,IAAM,KAAQ,MAAsB,GAAU,GAAW,GAAU,CAAU,KAAK,GAC5E,IAAkB,CAAC,GACrB,IAAU;CACd,KAAK,IAAM,KAAQ,GAAO;EACxB,IAAM,IAAY,IAAU,GAAG,EAAQ,GAAG,MAAS;EACnD,IAAI,EAAK,CAAS,GAAG;GACnB,IAAU;GACV;EACF;EACA,AAAI,KAAS,EAAM,KAAK,CAAO;EAG/B,IAAI,IAAO;EACX,OAAO,KAAQ,CAAC,EAAK,CAAI,IAAG;GAC1B,IAAI,IAAM,GACN,IAAO,EAAK,SAAS;GACzB,OAAO,IAAM,IAAM;IACjB,IAAM,IAAM,KAAK,MAAM,IAAM,KAAQ,CAAC;IACtC,AAAI,EAAK,EAAK,MAAM,GAAG,CAAG,CAAC,IAAG,IAAM,IAC/B,IAAO,IAAM;GACpB;GAEA,AADA,EAAM,KAAK,EAAK,MAAM,GAAG,CAAG,CAAC,GAC7B,IAAO,EAAK,MAAM,CAAG;EACvB;EACA,IAAU;CACZ;CAEA,OADI,KAAS,EAAM,KAAK,CAAO,GACxB;AACT;;;ACniBA,IAAa,KAAkC;CAC7C,UAAU,CAAC,YAAY;CACvB,YAAY,CAAC,QAAQ,EAAmB;AAC1C;;;ACoBA,SAAS,GAAY,GAAY,GAAsB;CACrD,IAAM,IAAK,EAAK,IAAI,EAAK,QAAQ,GAC3B,IAAK,EAAK,IAAI,EAAK,SAAS,GAC5B,IAAK,EAAO,IAAI,GAChB,IAAK,EAAO,IAAI;CACtB,IAAI,MAAO,KAAK,MAAO,GAAG,OAAO;EAAE,GAAG;EAAI,GAAG;CAAG;CAChD,IAAM,IAAK,MAAO,IAAoC,WAAhC,EAAK,QAAQ,IAAI,KAAK,IAAI,CAAE,GAC5C,IAAK,MAAO,IAAqC,WAAjC,EAAK,SAAS,IAAI,KAAK,IAAI,CAAE,GAC7C,IAAI,KAAK,IAAI,GAAI,CAAE;CACzB,OAAO;EAAE,GAAG,IAAK,IAAK;EAAG,GAAG,IAAK,IAAK;CAAE;AAC1C;AAEA,SAAS,GAAO,GAAmB;CACjC,OAAO;EAAE,GAAG,EAAK,IAAI,EAAK,QAAQ;EAAG,GAAG,EAAK,IAAI,EAAK,SAAS;CAAE;AACnE;AAEA,IAAqB,KAArB,MAAgC;CAIX;CACA;CACA;CACA;CACA;CAPnB,OAAO,UAAU;EAAC;EAAU;EAAkB;EAAoB;EAAY;CAAiB;CAE/F,YACE,GACA,GACA,GACA,GACA,GACA;EADiB,AAJA,KAAA,SAAA,GACA,KAAA,iBAAA,GACA,KAAA,UAAA,GACA,KAAA,WAAA,GACA,KAAA,kBAAA;CAChB;CAEH,OAAO,GAAkC;EACvC,IAAM,IAA4B,CAAC;EACnC,KAAK,SAAS,KAAK,uBAAuB,EAAE,UAAU,EAAI,CAAC;EAE3D,IAAI;EACJ,IAAI;GACF,IAAW,KAAK,OAAO,eAAe;EACxC,QAAQ;GACN,IAAW,KAAA;EACb;EACA,IAAI;EAOJ,AANI,KAAY,EAAS,OAAA,YACvB,IAAO,KAEP,IAAO,KAAK,eAAe,WAAW,EAAE,IAAI,GAAQ,CAAC,GACrD,KAAK,OAAO,eAAe,CAAI,IAEjC,EAAK,iBAAiB,EAAE,OAAO,EAAI,MAAM;EAEzC,IAAM,oBAAO,IAAI,IAAuB;EACxC,KAAK,IAAM,KAAO,EAAI,UAAU;GAC9B,IAAM,IAAQ,KAAK,QAAQ,cAAc,CAAG;GAC5C,EAAK,IAAI,EAAI,IAAI,CAAK;EACxB;EAGA,KAAK,IAAM,KAAO,EAAI,eAAe;GACnC,IAAM,IAAS,EAAK,IAAI,EAAI,IAAI,GAC1B,IAAS,EAAK,IAAI,EAAI,EAAE;GAC9B,IAAI,CAAC,KAAU,CAAC,GAAQ;IACtB,EAAS,KAAK;KACZ,SAAS,iBAAiB,EAAI,GAAG;KACjC,WAAW,EAAI;IACjB,CAAC;IACD;GACF;GACA,IAAM,IAAqB,CACzB,GAAY,GAA2B,GAAO,CAAyB,CAAC,GACxE,GAAY,GAA2B,GAAO,CAAyB,CAAC,CAC1E,GACM,IAAa,KAAK,QAAQ,mBAAmB,GAAK,GAAQ,GAAQ,CAAS;GACjF,KAAK,OAAO,cAAc,GAAY,CAAI;EAC5C;EACA,KAAK,IAAM,KAAS,EAAK,OAAO,GAC9B,KAAK,OAAO,SAAS,GAAO,CAAI;EAIlC,OADA,KAAK,SAAS,KAAK,sBAAsB,EAAE,YAAS,CAAC,GAC9C;CACT;CAGA,QAAc;EACZ,KAAK,IAAM,KAAM,CAAC,GAAG,KAAK,gBAAgB,OAAO,CAAC,GAC5C,MAAG,OAAA,WACP,IAAI;GACF,AAAI,eAAe,IAAI,KAAK,OAAO,iBAAiB,EAAG,EAAE,IACpD,KAAK,OAAO,YAAY,EAAG,EAAE;EACpC,QAAQ,CAER;CAEJ;AACF,GCvGqB,KAArB,MAAgC;CAIX;CACA;CAJnB,OAAO,UAAU,CAAC,mBAAmB,QAAQ;CAE7C,YACE,GACA,GACA;EADiB,AADA,KAAA,kBAAA,GACA,KAAA,SAAA;CAChB;CAEH,SAAqB;EACnB,IAAI;EACJ,IAAI;GAIF,IAHa,KAAK,OAAO,eAGlB,CAAA,CAAK;EACd,QAAQ;GACN,IAAO,KAAA;EACT;EAEA,IAAM,IAA6B,CAAC,GAC9B,IAAgC,CAAC;EAEvC,KAAK,IAAM,KAAM,KAAK,gBAAgB,OAAO,GACvC,MAAG,OAAA,WAEP;OAAI,EAAY,CAAE,GAAG;IACnB,IAAM,IAAO;IACb,EAAS,KAAK;KACZ,IAAI,EAAG;KACP,OAAO,EAAG,WAAW;KACrB,UAAU;MAAE,GAAG,EAAK;MAAG,GAAG,EAAK;KAAE;KACjC,MAAM;MAAE,OAAO,EAAK;MAAO,QAAQ,EAAK;KAAO;KAC/C,GAAI,EAAG,gBAAgB,EAAE,eAAe,EAAG,cAAc,IAAI,CAAC;KAC9D,GAAI,EAAG,OAAO,EAAE,MAAM,EAAG,KAAK,IAAI,CAAC;KACnC,GAAI,EAAG,cAAc,EAAE,aAAa,EAAG,YAAY,IAAI,CAAC;KACxD,GAAI,EAAG,OAAO,EAAE,MAAM,EAAG,KAAK,IAAI,CAAC;KACnC,GAAI,EAAG,SAAS,EAAE,QAAQ,EAAG,OAAO,IAAI,CAAC;IAC3C,CAAC;GACH,OAAO,IAAI,EAAiB,CAAE,GAAG;IAC/B,IAAM,IAAS,EAAG,QACZ,IAAS,EAAG;IAClB,IAAI,CAAC,GAAQ,MAAM,CAAC,GAAQ,IAAI;IAChC,EAAc,KAAK;KACjB,IAAI,EAAG;KACP,MAAM,EAAO;KACb,IAAI,EAAO;KACX,SAAS,EAAG;KACZ,GAAI,EAAG,eAAe,SAAS,EAAE,eAAe,CAAC,GAAG,EAAG,aAAa,EAAE,IAAI,CAAC;KAC3E,GAAI,EAAG,iBAAiB,SAAS,EAAE,iBAAiB,CAAC,GAAG,EAAG,eAAe,EAAE,IAAI,CAAC;KACjF,GAAI,EAAG,UAAU,EAAE,OAAO,EAAG,QAAQ,IAAI,CAAC;KAC1C,GAAI,EAAG,cAAc,EAAE,aAAa,EAAG,YAAY,IAAI,CAAC;KACxD,GAAI,EAAG,2BACH,EAAE,0BAA0B,EAAG,yBAAyB,IACxD,CAAC;IACP,CAAC;GACH;;EAGF,OAAO;GACL,SAAS;GACT,OAAO,GAAM,SAAS;GACtB;GACA;EACF;CACF;AACF,GC1Ea,KAA8B;CACzC,YAAY,CAAC,QAAQ,EAAU;CAC/B,YAAY,CAAC,QAAQ,EAAU;AACjC,GCDa,KAAb,cAA4B,EAAa;CACvC,cAA6C;EAC3C,OAAO;GAAC;GAAe;GAAc;EAAQ;CAC/C;AACF,GCJa,KAAb,cAAqC,GAAO;CAC1C,cAAsD;EACpD,OAAO;GAAC,GAAG,MAAM,YAAY;GAAG;GAAiB;GAAkB;EAAgB;CACrF;AACF;;;ACKA,SAAS,GAAY,GAA8B,GAAa,GAAsB;CACpF,AAAI,MAAU,KAAA,IAAW,OAAO,EAAI,KAC/B,EAAI,KAAO;AAClB;AAEA,IAAqB,KAArB,MAAuE;CACrE,QAAQ,GAAiD;EACvD,IAAM,EAAE,YAAS,kBAAe,GAC1B,IAAS,GACT,IAA+B,CAAC;EACtC,KAAK,IAAM,KAAO,OAAO,KAAK,CAAU,GAEtC,AADA,EAAI,KAAO,EAAO,IAClB,GAAY,GAAQ,GAAK,EAAW,EAAI;EAG1C,OADA,EAAQ,gBAAgB,GACjB,CAAC,CAAO;CACjB;CAEA,OAAO,GAAiD;EACtD,IAAM,EAAE,YAAS,qBAAkB,GAC7B,IAAS;EACf,IAAI,GACF,KAAK,IAAM,KAAO,OAAO,KAAK,CAAa,GAAG,GAAY,GAAQ,GAAK,EAAc,EAAI;EAE3F,OAAO,CAAC,CAAO;CACjB;AACF;;;ACxBA,SAAS,EAAK,GAAsD;CAClE,IAAM,IAAY,EAAW;CAM7B,OALA,EAAW,SAAS,EAAW,QAC/B,EAAW,SAAS,GAChB,MAAM,QAAQ,EAAW,SAAS,MACpC,EAAW,YAAY,CAAC,GAAG,EAAW,SAAS,CAAC,CAAC,QAAQ,IAEpD,CAAC,CAAU;AACpB;AAEA,IAAqB,KAArB,MAA+D;CAC7D,QAAQ,GAAqC;EAC3C,OAAO,EAAK,EAAQ,UAAU;CAChC;CAEA,OAAO,GAAqC;EAC1C,OAAO,EAAK,EAAQ,UAAU;CAChC;AACF,GChBM,KAAoB,4BACpB,KAAY,yBAEG,KAArB,MAAgC;CAIX;CACA;CACA;CALnB,OAAO,UAAU;EAAC;EAAgB;EAAmB;CAAiB;CAEtE,YACE,GACA,GACA,GACA;EAEA,AALiB,KAAA,eAAA,GACA,KAAA,kBAAA,GACA,KAAA,kBAAA,GAEjB,EAAa,gBAAgB,IAAmB,EAAuB,GACvE,EAAa,gBAAgB,IAAW,EAAe;CACzD;CAQA,OAAe,GAA0B;EACvC,IAAM,IAAM,KAAK,gBAAgB,YAAY,CAAO;EAC/C,KACL,KAAK,gBAAgB,OAAO,EAAiB,CAAO,IAAI,eAAe,SAAS,GAAS,CAAG;CAC9F;CAGA,SAAS,GAAoC;EAI3C,AAHA,KAAK,aAAa,QAAQ,IAAW,EACnC,YAAY,EACd,CAA+B,GAC/B,KAAK,OAAO,CAAY;CAC1B;CAEA,iBAAiB,GAAoB,GAA2C;EAE9E,AADA,KAAK,aAAa,QAAQ,IAAmB;GAAE;GAAS;EAAW,CAAC,GACpE,KAAK,OAAO,CAAO;CACrB;CAGA,YAAY,GAAoB,GAAqB;EACnD,KAAK,iBAAiB,GAAS,EAAE,SAAS,KAAS,KAAA,EAAU,CAAC;CAChE;CAIA,iBAAiB,GAAoB,GAAgD;EACnF,KAAK,iBAAiB,GAAS,EAAE,iBAAc,CAAC;CAClD;CAEA,QAAQ,GAAoB,GAAgC;EAC1D,KAAK,iBAAiB,GAAS,EAAE,MAAM,KAAQ,KAAA,EAAU,CAAC;CAC5D;CAEA,eAAe,GAAoB,GAAuC;EACxE,KAAK,iBAAiB,GAAS,EAAE,aAAa,KAAe,KAAA,EAAU,CAAC;CAC1E;CAGA,UAAU,GAAoB,GAA0B,GAAkC;EACxF,KAAK,iBAAiB,GAAS;GAAE;GAAM;EAAO,CAAC;CACjD;CASA,WAAW,GAA8B,GAAoC;EAC3E,IAAM,IAAiC,EAAE,WAAQ;EACjD,IAAI,EAAmB,CAAO,GAE5B,AADA,EAAM,gBAAgB,KAAA,GACtB,EAAM,kBAAkB,KAAA;OACnB,IAAI,MAAY,qBAAqB;GAC1C,IAAM,KAAM,EAAa,iBAAiB,CAAC,EAAA,CAAG,QAAQ,MAAM,MAAM,KAAK,GACjE,KAAQ,EAAa,mBAAmB,CAAC,EAAA,CAAG,QAAQ,MAAM,MAAM,IAAI;GAE1E,AADA,EAAM,gBAAgB,EAAG,SAAS,IAAK,KAAA,GACvC,EAAM,kBAAkB,EAAK,SAAS,IAAO,KAAA;EAC/C;EACA,KAAK,iBAAiB,GAAc,CAAK;CAC3C;CAEA,iBAAiB,GAA8B,GAA6B;EAC1E,KAAK,iBAAiB,GAAc,EAAE,eAAe,EAAM,SAAS,IAAQ,KAAA,EAAU,CAAC;CACzF;CAEA,mBAAmB,GAA8B,GAA+B;EAC9E,KAAK,iBAAiB,GAAc,EAAE,iBAAiB,EAAM,SAAS,IAAQ,KAAA,EAAU,CAAC;CAC3F;CAEA,4BAA4B,GAA8B,GAAgC;EACxF,KAAK,iBAAiB,GAAc,EAAE,0BAA0B,KAAQ,KAAA,EAAU,CAAC;CACrF;AACF,GC1Ga,IAAsC;CACjD,UAAU,CAAC,YAAY;CACvB,YAAY,CAAC,QAAQ,EAAU;CAC/B,UAAU,CAAC,QAAQ,EAAU;AAC/B,GCcqB,KAArB,cAAqC,GAAa;CAChD,OAAgB,UAAU,CAAC,UAAU;CAErC,YAAY,GAAoB;EAC9B,MAAM,CAAQ;CAChB;CAEA,OAAsB;EAmBpB,AAhBA,KAAK,QAAQ,CAAC,cAAc,eAAe,IAAI,MAC7C,EAAQ,UAAU,EAAQ,OAAO,SAAS,OAAO,EACnD,GACA,KAAK,QAAQ,sBAAsB,EAAI,GAEvC,KAAK,QAAQ,sBAAsB,EAAK,GAKxC,KAAK,QAAQ,sBAAsB,MACjC,GAAW,EAAQ,QAAQ,EAAQ,MAAM,CAC3C,GACA,KAAK,QAAQ,yBAAyB,MACpC,KAAW,EAAQ,QAAQ,EAAQ,QAAQ,EAAQ,UAAU,CAC/D,GACA,KAAK,QAAQ,oCAAoC,EAAI;CACvD;AACF;AAQA,SAAS,GAAiB,GAAiB,GAAiB,GAA2B;CACrF,IAAM,EAAE,cAAW,CAAC,GAAG,cAAW,CAAC,MAAM;CACzC,OAAO,CAAC,GAAG,GAAU,GAAG,CAAQ,CAAC,CAAC,MAC/B,MACC,MAAe,MACb,EAAW,WAAW,KAAU,EAAW,WAAW,KACrD,EAAW,WAAW,KAAU,EAAW,WAAW,EAC7D;AACF;AAGA,SAAS,GACP,GACA,GACA,GACoE;CAIpE,OAHI,CAAC,EAAY,CAAM,KAAK,CAAC,EAAY,CAAM,KAC3C,MAAW,KACX,GAAiB,GAAQ,GAAQ,CAAM,IAAU,KAC9C;EAAE,QAAQ;EAAgB,SAAS;CAAsB;AAClE;;;AC/EA,IAAa,IAAmC;CAC9C,aAAa,CAAC,EAAW;CACzB,UAAU,CAAC,SAAS;CACpB,SAAS,CAAC,QAAQ,EAAO;AAC3B,GCeqB,KAArB,cAAiD,GAAmB;CAClE,OAAgB,UAAU;EAAC;EAAY;EAAU;CAAU;CAE3D,YAAY,GAAoB,GAAgB,GAAoB;EAGlE,AAFA,MAAM,CAAQ,GAEd,KAAK,WACH,CAAC,gBAAgB,iBAAiB,IACjC,MAAkC;GACjC,EAAQ,SAAS,EAAO,eAAe;EACzC,GACA,EACF;EAQA,IAAI,IAAgC;EAqCpC,AApCA,KAAK,WACH,kBACC,MAA0B;GACzB,IAAY,IAAI,KAAK,EAAQ,UAAU,CAAC,EAAA,CAAG,KAAK,MAAU,EAAM,EAAE,CAAC;EACrE,GACA,EACF,GACA,KAAK,aACH,uBACM;GACJ,IAAY;EACd,GACA,EACF,GAuBA,KAAK,YAAY,CAAC,cAAc,cAAc,IArB5B,MAAgC;GAChD,IAAM,IAAS,EAAQ,WAAW,EAAQ,QAAQ,CAAC,EAAQ,KAAK,IAAI,CAAC,IAC/D,oBAAO,IAAI,IAAY;GAC7B,KAAK,IAAM,KAAS,GAAQ;IAC1B,IAAM,IAAyB,CAC7B,GAAK,EAAM,YAA6B,CAAC,GACzC,GAAK,EAAM,YAA6B,CAAC,CAC3C;IACA,KAAK,IAAM,KAAc,GAAU;KACjC,IAAI,EAAK,IAAI,EAAW,EAAE,GAAG;KAC7B,EAAK,IAAI,EAAW,EAAE;KACtB,IAAM,IAAW,EAAW,QAAQ,IAC9B,IAAW,EAAW,QAAQ;KAChC,KAAY,KAAY,GAAW,IAAI,CAAQ,KAAK,EAAU,IAAI,CAAQ,KAG9E,EAAS,iBAAiB,CAAU;IACtC;GACF;EACF,GAE2D,EAAI;CACjE;AACF,GCxEM,KAAe,eAEA,KAArB,MAAoC;CAClC,OAAO,UAAU,CAAC,YAAY,QAAQ;CAEtC,YAAY,GAAoB,GAAgB;EAI9C,AAHA,EAAS,GAAG,mBAAmB;GAC7B,EAAO,aAAa,CAAC,CAAC,UAAU,IAAI,EAAY;EAClD,CAAC,GACD,EAAS,GAAG,sBAAsB;GAChC,EAAO,aAAa,CAAC,CAAC,UAAU,OAAO,EAAY;EACrD,CAAC;CACH;AACF,GCVM,KAA4B,KCRrB,KAAuC;CAClD,UAAU;EAAC;EAAuB;EAAkB;CAA0B;CAC9E,qBAAqB,CAAC,QAAQ,EAAmB;CACjD,gBAAgB,CAAC,QAAQ,EAAc;CACvC,0BAA0B,CAAC,QAAQ,MDMS;EAC5C,OAAO,UAAU,CAAC,YAAY,WAAW;EAEzC,YAAY,GAAoB,GAAsB;GACpD,EAAS,GACP,iBACA,KACC,MAA4E;IAC3E,IAAM,IAAU,EAAM;IACjB,MAAY,CAAO,KACpB,IAAmB,CAAK,KACxB,EAAU,WAAW,CAAO,GAAG,OAAO;GAC5C,CACF;EACF;CACF,CCrB6D;AAC7D;;;ACUA,SAAS,EAAI,GAAe,IAAO,IAAY;CAC7C,OAAO,sCAAsC,EAAK,YAAY,EAAK,2CAA2C,EAAM;AACtH;AAGA,IAAM,KAAO,sFACP,KACJ;AAGF,SAAS,GACP,GACA,GACA,GACA,GACA,GACQ;CACR,IAAI,MAAS,WACX,OAAO,eAAe,EAAG,QAAQ,EAAG,OAAO,IAAO,IAAI,GAAI,wBAAwB,EAAM;CAE1F,IAAM,IAAQ,IAAO,IACf,IAAM,MAAS,eAAe,sBAAsB,IACpD,IAAI,aAAa,IAAK,KAAK,EAAM,GAAG,IAAK,KAAK,EAAM,UAAU,EAAM,GAAG;CAC7E,OAAO,YAAY,MAAS,SAAS,KAAO,GAAK,UAAU,EAAM,eAAe,EAAE;AACpF;AAGA,SAAgB,EAAe,GAA8B;CAC3D,IAAM,IAAI,IAAO,EAAqB,KAAQ,KAAA;CAM9C,OAJS,EADL,CAAC,KAAQ,CAAC,IAEV,2DAA2D,GAAa,YAAY,GAAe,0BAIrG,2DAA2D,EAAE,KAAK,YAAY,EAAE,OAAO,0BACrF,GAAe,GAAM,IAAI,IAAI,IAAI,EAAE,MAAM,CAJ3C;AAMJ;AAGA,SAAgB,GAAiB,GAAqB,IAAO,IAAY;CACvE,IAAM,IAAI,EAAqB,IACzB,IAAQ,GAAG,UAAA;CAKjB,OAAO,sCAAsC,EAAK,YAAY,EAAK,2CAHjE,CAAC,KAAK,MAAS,YACX,qDAAqD,EAAM,qDAC3D,YAAY,MAAS,SAAS,KAAO,GAAK,UAAU,EAAM,KACoD;AACtH;AAGA,SAAgB,EAAY,GAA6C;CACvE,OAAO,EACL,2DAA2D,EAAY,MAAA,UAAwB,wFACP,EAAgB,iBAAiB,EAAK,OAAO,IAAI,EAAK,QAChJ;AACF;AAEA,SAAgB,EACd,IAA+B,uBAC/B,IAAO,IACC;CACR,IAAM,IACJ,EAA2B,MAAY,EAA2B,wBAC9D,IAAO,EAAE,OAAO,sBAAsB,EAAE,KAAK,KAAK,IAClD,IAAI,KAAK,IAAI,EAAE,aAAa,GAAG;CACrC,OAAO,EACL,cAAc,EAAE,OAAO,kBAAkB,EAAE,gEACD,EAAE,OAAO,uDACV,EAAK,0CACH,EAAE,OAAO,wBACpD,CACF;AACF;;;AC1FA,IAAa,KAAqB,6DACrB,KACX,wJACW,KACX,iFACW,KAAY,2EACZ,KACX,2HACW,KACX,mHAEW,KAAa,iDACb,KACX;AAEF,SAAgB,EAAW,GAAc,IAAO,IAAY;CAC1D,OAAO,eAAe,EAAK,YAAY,EAAK,wEAAwE,EAAK;AAC3H;AAGA,SAAgB,GAAgB,IAAO,IAAY;CACjD,OAAO,eAAe,EAAK,YAAY,EAAK;AAC9C;;;ACNA,IAAM,KAAc,SACd,KAAiB;AAEvB,SAAS,GAAU,GAAc,GAAe,IAAY,IAAc;CAExE,OAAO,sCADM,IAAY,wBAAsB,GACG,UAAU,EAAM,IAAI,EAAK;AAC7E;AAEA,IAAqB,KAArB,MAAkE;CAK7C;CACA;CACA;CANnB,OAAO,UAAU;EAAC;EAAW;EAAU;EAAa;CAAkB;CAEtE,YACE,GACA,GACA,GACA,GACA;EACA,AAJiB,KAAA,SAAA,GACA,KAAA,YAAA,GACA,KAAA,UAAA,GAEjB,EAAQ,iBAAiB,IAAI;CAC/B;CAEA,oBAAoC;EAClC,IAAM,IAA0B,CAAC,GAI3B,IAAa;EACnB,EAAQ,gBAAgB;GACtB,OAAO;GACP,OAAO;GACP,MAAM,GAAU,GAAgB,GAAG,GAAY,EAAK;GACpD,QAAQ,EACN,QAAQ,MAAiB,KAAK,UAAU,kBAAkB,CAAmB,EAC/E;EACF;EAEA,KAAK,IAAM,KAAQ,GAAqB;GACtC,IAAM,KAAS,MACb,KAAK,OAAO,MACV,GACA,KAAK,QAAQ,iBAAiB,EAAK,MAAM,EAAK,KAAK,CACrD;GACF,EAAQ,WAAW,EAAK,UAAU;IAChC,OAAO;IACP,OAAO,GAAG,EAAK,MAAM,KAAK,EAAK;IAC/B,MAAM,GAAU,EAAe,EAAK,IAAI,GAAG,GAAG,EAAK,MAAM,KAAK,EAAK,aAAa;IAChF,QAAQ;KAAE,WAAW;KAAO,OAAO;IAAM;GAC3C;EACF;EAEA,OAAO;CACT;AACF,GChEa,KAAqC;CAChD,aAAa;EAAC;EAAe;EAAc;EAAe;CAAe;CACzE,UAAU,CAAC,mBAAmB;CAC9B,mBAAmB,CAAC,QAAQ,EAAiB;AAC/C,GCUM,KAAoC;CACxC,MAAM;CACN,MAAM;AACR,GAGM,KAAgB,IAEhB,KAAmB,IAuBJ,KAArB,MAAoC;CASf;CACA;CACA;CAVnB,OAAO,UAAU;EAAC;EAAY;EAAU;EAAiB;CAAY;CAGrE,OAAyB;CACzB;CAEA,YACE,GACA,GACA,GACA,GACA;EAkCA,AArCiB,KAAA,SAAA,GACA,KAAA,gBAAA,GACA,KAAA,WAAA,GAKjB,EAAc,iBAAiB;GAC7B,WAAW,MAAY,KAAK,kBAAkB,CAAO;GACrD,SAAS,GAAS,MAAY,KAAK,OAAO,GAAS,CAAO;EAC5D,CAAC,GAED,EAAS,GACP,qBACC,MAAuE;GACtE,IAAM,IAAU,EAAM;GACjB,EAAY,CAAO,MAExB,KAAK,OACH,EAAY,CAAO,KAAK,EAAQ,QAAQ,KAAK,aAAa,GAAS,EAAM,aAAa,IAClF,SACA,QACN,EAAc,SAAS,CAAkB;EAC3C,CACF,GAIA,EAAS,GAAG,CAAC,2BAA2B,WAAW,SAAS,EAAc,SAAS,CAAC,GAEpF,EAAS,GAAG,2BAA2B,MAA8C;GACnF,IAAM,IAAU,EAAM,QAAQ;GAC9B,IAAI,CAAC,GAAS;GACd,IAAM,IAAS,GAAQ,KAAK;GAE5B,AADA,EAAO,UAAU,GAAiC,CAAM,GACxD,KAAK,eAAe;IAAE;IAAS;GAAO;EACxC,CAAC,GACD,EAAS,GAAG,CAAC,0BAA0B,sBAAsB,SAAS;GACpE,IAAM,IAAS,KAAK;GAEpB,AADI,KAAQ,EAAO,aAAa,EAAO,SAAiC,EAAO,MAAM,GACrF,KAAK,eAAe,KAAA;EACtB,CAAC;CACH;CAGA,SAAS,GAA0B;EAEjC,AADA,KAAK,OAAO,QACZ,KAAK,cAAc,SAAS,CAAkB;CAChD;CAGA,aAAa,GAA0B;EAErC,AADA,KAAK,OAAO,QACZ,KAAK,cAAc,SAAS,CAA6B;CAC3D;CAEA,SAAe;EACb,KAAK,cAAc,OAAO;CAC5B;CAEA,aAAqB,GAAoB,GAA+C;EACtF,IAAI,OAAO,GAAe,WAAY,UAAU,OAAO;EACvD,IAAM,IAAO,KAAK,OAAO,KAAK,GACxB,IAAO,KAAK,OAAO,gBAAgB,CAA+B,GAClE,IAAe,KAAK,OAAO,aAAa,CAAC,CAAC,sBAAsB,CAAC,CAAC;EAExE,OADU,EAAc,UAAU,KACtB,EAAK,IAAI,EAAK,SAAU,KAA2C;CACjF;CAEA,kBAA0B,GAAoD;EAC5E,IAAI,CAAC,EAAY,CAAO,GAAG;EAC3B,AAAI,KAAK,SAAS,UAAU,CAAC,EAAY,CAAO,MAAG,KAAK,OAAO;EAC/D,IAAM,IAAO,KAAK,OAAO,KAAK,GACxB,IAAO,KAAK,OAAO,gBAAgB,CAA+B;EAExE,IAAI,KAAK,SAAS,QAAQ;GACxB,IAAM,IAAU;GAEhB,OAAO;IACL,QAAQ;KACN,GAAG,EAAK,IAAI,KAAgB;KAC5B,GAAG,EAAK,IAAI,EAAK,SAAU,KAA2C;KACtE,OAAO,EAAK,QAAQ,KAAoB;KACxC,QAAQ,KAAmB;IAC7B;IACA,MAAM,EAAQ,QAAQ;IACtB,OAAO;KACL,YAAY,EAAK;KACjB,UAAU,GAAG,EAAK,QAAQ,EAAK;KAC/B,YAAY;KACZ,YAAY;KACZ,iBAAiB;KACjB,QAAQ;KACR,WAAW;IACb;IACA,SAAS,EAAE,kBAAkB,GAAK;GACpC;EACF;EAEA,IAAM,IAAyC;GAC7C,YAAY,EAAK;GACjB,UAAU,GAAG,EAAK,QAAQ,EAAK;GAC/B,YAAY;GACZ,YAAY;GAGZ,iBAAiB;GACjB,QAAQ;GACR,WAAW;EACb;EAEA,IAAI,EAAY,CAAO,GAAG;GAKxB,IAAM,IAAU,EAAQ,OAAA,KAA8B,IAAO;GAC7D,OAAO;IACL,QAAQ;KACN,GAAG,EAAK,IAAI,KAAgB;KAC5B,GAAG,EAAK,IAAA,KAAuB,IAAO;KACtC,OAAO,EAAK,QAAQ,KAAoB;KACxC,QAAQ,EAAK,SAAA,KAA4B,IAAO;IAClD;IACA,MAAM,EAAQ,WAAW;IACzB;GACF;EACF;EAIA,IAAM,IAAQ,MAAM,GACd,IAAS,KAAK;EACpB,OAAO;GACL,QAAQ;IACN,GAAG,EAAK,IAAI,EAAK,QAAQ,IAAI,IAAQ;IACrC,GAAG,EAAK,IAAI,EAAK,SAAS,IAAI,IAAS;IACvC;IACA;GACF;GACA,MAAO,EAAsB,WAAW;GACxC,OAAO;IAAE,GAAG;IAAO,iBAAiB;GAA4B;GAChE,SAAS,EAAE,kBAAkB,GAAK;EACpC;CACF;CAEA,OAAe,GAAkB,GAAuB;EACtD,IAAM,IAAQ,EAAQ,KAAK;EAG3B,IAAI,KAAK,SAAS,QAAQ;GACxB,IAAM,IAAU;GAChB,IAAI,OAAW,EAAQ,QAAQ,KAAK;GACpC,KAAK,SAAS,QAAQ,GAAS,KAAS,KAAA,CAAS;GACjD;EACF;EACI,OAAY,EAAsB,WAAW,OACjD,KAAK,SAAS,YAAY,GAAsB,CAAK;CACvD;AACF,GCvNa,IAA0C;CACrD,aAAa,CAAC,IAAqB,CAAgB;CACnD,UAAU,CAAC,gBAAgB;CAC3B,gBAAgB,CAAC,QAAQ,EAAc;AACzC,GC0EM,IAAiB,qBACjB,KAAe,mBACf,IAAa,iBAGb,IAAe,mBACf,IAAW,GAGX,KAAqF;CACzF,KAAK;CACL,IAAI;AACN;AAEA,SAAS,EACP,GACA,GACA,IAAqD,CAAC,GAC9C;CACR,IAAM,IAAY,EAAQ,YAAY,wBAAsB;CAE5D,OAAO,iCADQ,EAAQ,SAAS,0BAA0B,GACX,GAAG,EAAU,UAAU,EAAM,IAAI,EAAK;AACvF;AAEA,IAAqB,KAArB,MAAwE;CAuBnD;CACA;CACA;CAEA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CApCnB,OAAO,UAAU;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CAGA;CAEA,YACE,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA;EAwDA,AAvEiB,KAAA,aAAA,GACA,KAAA,YAAA,GACA,KAAA,WAAA,GAEA,KAAA,SAAA,GACA,KAAA,YAAA,GACA,KAAA,QAAA,GACA,KAAA,WAAA,GACA,KAAA,WAAA,GACA,KAAA,aAAA,GACA,KAAA,eAAA,GACA,KAAA,iBAAA,GACA,KAAA,YAAA,GACA,KAAA,SAAA,GACA,KAAA,YAAA,GAKjB,EAAW,iBAAiB,IAAI,GAChC,EAAU,iBAAiB,GAAgB,EACzC,sBAAsB,MAA4B,KAAK,qBAAqB,CAAM,EACpF,CAAC,GACD,EAAU,iBAAiB,IAAc,EACvC,sBAAsB,MAA4B,KAAK,mBAAmB,CAAM,EAClF,CAAC,GACD,EAAU,iBAAiB,GAAY,EACrC,sBAAsB,MAA4B,KAAK,iBAAiB,CAAM,EAChF,CAAC,GAID,EAAS,GAAG,cAAc,MAA2C;GACnE,IAAM,EAAE,WAAQ,aAAU,GACpB,IAAW;IACf,GAAG,GAAO,CAAM,CAAC,CAAC,QAAQ,KAAmB,EAAM,QAAQ;IAC3D,GAAG,EAAO,CAAM,CAAC,CAAC;GACpB;GACA,OAAO,GACL,GACA,GACA,GACA,GAAwB,EAAE,GAAG;IAAE,QAAQ;IAAI,aAAa;GAAG,EAAE,CAAC,CAChE;EACF,CAAC,GAGD,EAAS,GAAG,sBAAsB,MAAmD;GACnF,IAAM,EAAE,QAAK,cAAW;GACxB,IAAI,CAAC,GAAK;GACV,IAAI,IAAQ,IACR,IAAQ;GACZ,IAAI,EAAiB,CAAM,GAAG;IAC5B,IAAM,IAAa,EAAO,aAAa,CAAC,GAClC,IAAO,EAAU,EAAU,SAAS,IACpC,IAAW,EAAU,EAAU,SAAS;IAC9C,IAAI,KAAQ,GAAU;KACpB,IAAM,IAAK,EAAK,IAAI,EAAS,GACvB,IAAK,EAAK,IAAI,EAAS;KAE7B,AADA,IAAQ,KAAK,IAAI,CAAE,KAAK,KAAK,IAAI,CAAE,KAAK,IAAK,GAC7C,IAAQ,KAAK,IAAI,CAAE,IAAI,KAAK,IAAI,CAAE,KAAK,IAAK;IAC9C;GACF;GAEA,AADA,EAAI,UAAU,OAAO,iBAAiB,CAAK,GAC3C,EAAI,UAAU,OAAO,iBAAiB,CAAK;EAC7C,CAAC,GAMD,EAAS,GAAG;GAAC;GAAmB;GAAmB;EAAwB,GAAG,WAC5E,KAAK,iBAAiB,CACxB;CACF;CAEA,mBAAiC;EAC/B,KAAU,UAAU,eAAe;GACjC,IAAM,IAAY,KAAK,OAAO,aAAa,GACrC,IAAM,EAAU,cAA2B,uBAAuB;GACxE,IAAI,CAAC,GAAK;GACV,IAAM,IAAkB,EAAU,sBAAsB,GAClD,IAAY,EAAI,sBAAsB,GAEtC,IAAgB,EAAU,SAAS,EAAgB,QAAQ;GACjE,AAAI,IAAgB,MAClB,EAAI,MAAM,OAAO,GAAG,WAAW,EAAI,MAAM,QAAQ,GAAG,IAAI,EAAc;GAIxE,IAAM,IAAe,EAAgB,OAAO,IAAS,EAAU;GAC/D,AAAI,IAAe,MACjB,EAAI,MAAM,OAAO,GAAG,WAAW,EAAI,MAAM,QAAQ,GAAG,IAAI,EAAa;GAKvE,IAAI,IAAS,GACP,IAAiB,EAAU,UAAU,EAAgB,SAAS;GACpE,AAAI,IAAiB,MAAG,IAAS,CAAC;GAClC,IAAM,IAAc,EAAgB,MAAM,KAAU,EAAU,MAAM;GAEpE,AADI,IAAc,MAAG,KAAU,IAC3B,MAAW,MACb,EAAI,MAAM,MAAM,GAAG,WAAW,EAAI,MAAM,OAAO,GAAG,IAAI,EAAO;EAEjE,GAAG,4BAA4B;CACjC;CAEA,qBAAqB,GAAqC;EAGxD,OAFI,EAAY,CAAO,IAAU,KAAK,eAAe,CAAO,IACxD,EAAiB,CAAO,IAAU,KAAK,oBAAoB,CAAO,IAC/D,CAAC;CACV;CAEA,iCAAiC,GAAwC;EACvE,IAAM,IAAa,EAAS,OAAO,CAAW;EAE9C,OADI,EAAW,WAAW,EAAS,SAC5B,EAAE,QAAQ,KAAK,YAAY,GAAY,kBAAkB,EAAE,IADhB,CAAC;CAErD;CAIA,eAAuB,GAAuC;EAC5D,IAAM,IAAO,EAAQ,gBAAgB,EAAqB,EAAQ,iBAAiB,KAAA;EACnF,OAAO;GACL,kBAAkB;IAChB,OAAO;IACP,MAAM,EACJ,EAAW,EAAY,GACvB,+EACA,EAAE,WAAW,GAAK,CACpB;IACA,QAAQ;KACN,aAAa,KAAK,cAAc,CAAO;KACvC,YAAY,MAAiB,KAAK,YAAY,GAAO,CAAO;IAC9D;GACF;GACA,SAAS;IACP,OAAO;IACP,MAAM,EAAa,EAAW,EAAkB,GAAG,8BAA8B,EAC/E,WAAW,GACb,CAAC;IACD,QAAQ;KACN,QAAQ,MAAiB,KAAK,aAAa,GAAO,GAAS,EAAI;KAC/D,YAAY,MAAiB,KAAK,aAAa,GAAO,GAAS,EAAK;IACtE;GACF;GACA,kBAAkB;IAChB,OAAO;IACP,MAAM,EACJ,EAAe,EAAQ,aAAa,GACpC,qCAAqC,GAAM,SAAS,gBACtD;IACA,QAAQ,EACN,QAAQ,MAAiB,KAAK,SAAS,GAAO,GAAS,GAAgB,gBAAgB,EACzF;GACF;GACA,MAAM;IACJ,OAAO;IACP,MAAM,EACJ,EAAW,EAAS,GACpB,+BAA+B,EAAQ,QAAQ,QACjD;IACA,QAAQ,EAAE,aAAa,KAAK,aAAa,aAAa,CAAO,EAAE;GACjE;GACA,cAAc,KAAK,eAAe,GAAS,gBAAgB;GAC3D,aAAa,KAAK,iBAAiB,GAAS,sCAAsC;GAClF,QAAQ,KAAK,YAAY,CAAC,CAAO,GAAG,gBAAgB;EACtD;CACF;CAWA,aAAqB,GAAc,GAAmB,GAAyB;EAS7E,IARA,KAAK,SAAS,KAAK,GAAqB,WAAW;GACjD,cAAc;GACd,WAAW;GACX,MAAM;IACJ,OAAO;IACP,SAAS;KAAE,OAAO;KAAQ,iBAAiB,EAAO,CAAM;IAAE;GAC5D;EACF,CAAC,GACG,GAAU;GACZ,IAAM,UAA4B;GAClC,KAAK,SAAS,KAAK,mBAAmB,WAAW;IAC/C,KAAK,SAAS,KAAK,iBAAiB,KAAO,CAAmB;IAC9D,IAAM,UAAqB,KAAK,SAAS,IAAI,iBAAiB,CAAmB;IAWjF,AANA,SAAS,iBAAiB,iBAAiB,WAAW,GAAQ,CAAC,GAAG;KAChE,SAAS;KACT,MAAM;IACR,CAAC,GAGD,WAAW,GAAQ,GAAG;GACxB,CAAC;EACH;EAEA,KAAK,SAAS,KAAK,mBAAmB,WAAW;GAC/C,AAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAG,KAAK,UAAU,OAAO,CAAM;EACrE,CAAC;CACH;CASA,cAAsB,GAAyB;EAC7C,IAAM,IAAQ,KAAK,eAAe,iBAAiB,GAG7C,IAAa,KAAK,MAAM,QAAQ,qBAAqB;GACzD;GACA,QAAQ;EACV,CAAC,GACK,IAAW,KAAK,UAAU,OAC9B,GACA,GACA,KAAc,OAAO,KAAe,WAAW,EAAE,cAAW,IAAI,CAAC,CACnE;EACA,KAAK,aAAa,CAAQ;CAC5B;CAEA,YAAoB,GAAc,GAAyB;EACzD,IAAM,IAAQ,KAAK,eAAe,iBAAiB,GAC7C,UAAkB,KAAK,aAAa,CAAK;EAK/C,AAJA,KAAK,SAAS,KAAK,cAAc,KAAK,CAAS,GAG/C,KAAK,SAAS,KAAK,wBAAwB,KAAK,SAAS,IAAI,cAAc,CAAS,CAAC,GACrF,KAAK,OAAO,MAAM,GAAqB,GAAO,EAAE,UAAO,CAAC;CAC1D;CAIA,aAAqB,GAA0B;EAC7C,KAAU,UAAU,eAAe;GACjC,IAAI,CAAC,KAAK,WAAW,OAAO,CAAO,GAAG;GACtC,IAAM,IAAQ,KAAK,OAChB,aAAa,CAAC,CACd,cAA2B,wDAAsD;GAC/E,KACL,KAAK,eAAe,EAAM,sBAAsB,GAAG,GAAS,GAAgB,gBAAgB;EAC9F,GAAG,2BAA2B;CAChC;CAIA,oBAA4B,GAAiD;EAG3E,IAAM,IAAO,EAA2B,EAAa,UAE/C,IAA6B,EACjC,SAAS;GACP,OAAO;GACP,MAAM,EACJ,EAAoB,GAAM,OAAO,GACjC,8BAA8B,GAAM,SAAS,EAAa,SAC5D;GACA,QAAQ,EACN,QAAQ,MACN,KAAK,SAAS,GAAO,GAAc,IAAc,sBAAsB,EAC3E;EACF,EACF;EAsBA,OArBI,KAAQ,CAAC,EAAK,cAChB,EAAQ,QAAQ;GACd,OAAO;GACP,MAAM,EACJ,EAAW,EAAS,GACpB,6DACF;GACA,QAAQ,EACN,QAAQ,MACN,KAAK,SAAS,GAAO,GAAc,GAAY,mBAAmB,EACtE;EACF,GACA,EAAQ,eAAe;GACrB,OAAO;GACP,MAAM,EAAa,EAAW,EAAS,GAAG,yCAAyC;GACnF,QAAQ,EAAE,aAAa,KAAK,WAAW,SAAS,CAAY,EAAE;EAChE,IAEF,EAAQ,gBAAgB,KAAK,eAAe,GAAc,YAAY,GACtE,EAAQ,cAAc,KAAK,iBAAiB,GAAc,oCAAoC,GAC9F,EAAQ,SAAS,KAAK,YAAY,CAAC,CAAY,GAAG,qBAAqB,GAChE;CACT;CAIA,eAAuB,GAAoB,GAAgC;EACzE,OAAO;GACL,OAAO;GACP,MAAM,EAAa,EAAW,EAAS,GAAG,GAAG,EAAM,0BAA0B;GAC7E,QAAQ,EAAE,aAAa,KAAK,aAAa,SAAS,CAAO,EAAE;EAC7D;CACF;CAEA,iBAAyB,GAAoB,GAAsC;EACjF,OAAO;GACL,OAAO;GACP,MAAM,EAAa,EAAW,EAAU,GAAG,kBAAkB;GAC7D,QAAQ,EACN,QAAQ,MACN,KAAK,WAAW,GAAO;IACrB,OAAO,EAAQ,eAAe;IAC9B;IACA,OAAO;IACP,WAAW;IACX,WAAW,MAAU,KAAK,WAAW,eAAe,GAAS,KAAS,KAAA,CAAS;GACjF,CAAC,EACL;EACF;CACF;CASA;CAEA,WACE,GACA,GAOM;EACN,KAAK,cAAc,OAAO;EAG1B,IAAM,KAFW,EAA2C,kBAC1D,EAAM,OAAA,CACc,sBAAsB,GAEtC,IAAO,SAAS,cAAc,KAAK;EAGzC,AAFA,EAAK,YAAY,iBACjB,EAAK,MAAM,OAAO,GAAG,EAAO,QAAQ,EAAS,KAC7C,EAAK,MAAM,MAAM,GAAG,EAAO,IAAI;EAE/B,IAAM,IAAQ,SAAS,cAAc,EAAO,YAAY,aAAa,OAAO;EAS5E,IAPA,EAAM,YAAY,wBAClB,EAAM,QAAQ,EAAO,OACrB,EAAM,cAAc,EAAO,aAC3B,EAAM,aAAa,cAAc,EAAO,KAAK,GACzC,aAAiB,wBAAqB,EAAM,OAAO,IACvD,EAAK,YAAY,CAAK,GAElB,EAAO,WAAW;GACpB,IAAM,IAAO,SAAS,cAAc,KAAK;GAGzC,AAFA,EAAK,YAAY,uBACjB,EAAK,cAAc,wCACnB,EAAK,YAAY,CAAI;EACvB;EAEA,KAAK,OAAO,aAAa,CAAC,CAAC,YAAY,CAAI;EAG3C,IAAM,IAAa,EAAK,sBAAsB;EAS9C,AAPI,EAAW,QAAQ,OAAO,aAAa,MACzC,EAAK,MAAM,OAAO,GAAG,KAAK,IAAI,GAAQ,EAAO,OAAO,EAAW,QAAQ,CAAQ,EAAE,MAE/E,EAAW,SAAS,OAAO,cAAc,MAC3C,EAAK,MAAM,MAAM,GAAG,KAAK,IAAI,GAAQ,OAAO,cAAc,IAAS,EAAW,MAAM,EAAE,MAExF,EAAM,MAAM,GACR,aAAiB,sBAGnB,EAAM,kBAAkB,EAAM,MAAM,QAAQ,EAAM,MAAM,MAAM,IAE9D,EAAM,OAAO;EAKf,IAAM,UAAgC,EAAO;EAC7C,KAAK,SAAS,GAAG,2BAA2B,CAAiB;EAE7D,IAAI,IAAO,IACL,UAAsB;GACtB,MACJ,IAAO,IACP,KAAK,SAAS,IAAI,2BAA2B,CAAiB,GAC9D,EAAK,OAAO,GACZ,KAAK,eAAe,KAAA,GACpB,KAAM,OAAyC,eAAe;EAChE,GACM,UAAqB;GACzB,IAAI,GAAM;GACV,IAAM,IAAQ,EAAM,MAAM,KAAK,GACzB,IAAU,MAAU,EAAO,MAAM,KAAK;GAE5C,AADA,EAAQ,GACJ,KAAS,EAAO,SAAS,CAAK;EACpC;EAgBA,AAfA,EAAM,iBAAiB,YAAY,MAAiB;GAClD,IAAM,IAAW;GACjB,AAAI,EAAS,QAAQ,YACnB,EAAS,eAAe,GACxB,EAAS,gBAAgB,GACzB,EAAQ,KAER,EAAS,QAAQ,YAChB,CAAC,EAAO,aAAa,EAAS,WAAW,EAAS,aAEnD,EAAS,eAAe,GACxB,EAAO;EAEX,CAAC,GACD,EAAM,iBAAiB,QAAQ,CAAM,GACrC,KAAK,eAAe,EAAE,QAAQ,EAAQ;CACxC;CAEA,YAAoB,GAAuB,GAAgC;EACzE,OAAO;GACL,OAAO;GACP,MAAM,EAAa,EAAW,EAAW,GAAG,GAAO,EAAE,QAAQ,GAAK,CAAC;GACnE,QAAQ,EAAE,aAAa,KAAK,SAAS,eAAe,CAAqB,EAAE;EAC7E;CACF;CAEA,SAAiB,GAAc,GAAoB,GAAgB,GAAqB;EACtF,IAAM,IAAW,EAA2C,kBAC1D,EAAM;EACR,KAAK,eAAe,EAAO,sBAAsB,GAAG,GAAS,GAAQ,CAAK;CAC5E;CAUA,eACE,GACA,GACA,GACA,GACM;EACN,IAAM,IAAW;GAAE,GAAG,EAAY,QAAQ;GAAU,GAAG,EAAY;EAAI;EACvE,KAAK,UAAU,KAAK,GAAS,GAAQ,GAAU,EAAE,SAAM,CAAC;EACxD,IAAM,IAAQ,SAAS,cAA2B,YAAY,GACxD,IAAc,GAAO,sBAAsB;EAKjD,AAJI,KAAS,KAAe,EAAY,OAAO,EAAY,UACzD,EAAS,IAAI,KAAK,IAAI,GAAU,EAAY,OAAO,IAAW,EAAY,KAAK,GAC/E,EAAM,MAAM,OAAO,GAAG,EAAS,EAAE,MAEnC,KAAK,cAAc;GAAE;GAAS;GAAQ;GAAO;EAAS;CACxD;CAOA,WAAmB,GAAoB,GAAsB;EAC3D,IAAM,IAAO,KAAK;EACd,CAAC,KAAQ,EAAK,WAAW,KAAU,EAAK,YAAY,KACxD,KAAK,UAAU,KAAK,GAAS,GAAQ,EAAK,UAAU,EAAE,OAAO,EAAK,MAAM,CAAC;CAC3E;CAIA,qBAA6B,GAA2C;EACtE,IAAI,CAAC,EAAY,CAAM,GAAG,OAAO,CAAC;EAClC,IAAM,IAAU,EAAO,eACjB,IAA4B,CAAC;EACnC,KAAK,IAAM,KAAQ,GACjB,EAAQ,QAAQ,EAAK,UAAU;GAC7B,OAAO,EAAK;GACZ,aAAa,EAAK;GAClB,WAAW,EAAe,EAAK,IAAI;GACnC,GAAI,EAAK,SAAS,IAAU,EAAE,WAAW,EAAa,IAAI,CAAC;GAC3D,cAAc;IACZ,AAAI,EAAK,SAAS,KAAS,KAAK,WAAW,iBAAiB,GAAQ,EAAK,IAAI;GAC/E;EACF;EAWF,OATA,EAAQ,eAAe;GACrB,OAAO;GACP,aAAa;GACb,WAAW,EAAe;GAC1B,GAAI,MAAY,KAAA,IAAY,EAAE,WAAW,EAAa,IAAI,CAAC;GAC3D,cAAc;IACZ,AAAI,MAAY,KAAA,KAAW,KAAK,WAAW,iBAAiB,GAAQ,KAAA,CAAS;GAC/E;EACF,GACO;CACT;CAEA,mBAA2B,GAA2C;EACpE,IAAI,CAAC,EAAiB,CAAM,GAAG,OAAO,CAAC;EACvC,IAAM,IAAU,EAAO,SACjB,IAA4B,CAAC;EACnC,KAAK,IAAM,KAAQ,GACjB,EAAQ,WAAW,EAAK,aAAa;GACnC,OAAO,EAAK;GACZ,aAAa,EAAK;GAClB,WAAW,EAAoB,EAAK,OAAO;GAC3C,GAAI,EAAK,YAAY,IAAU,EAAE,WAAW,EAAa,IAAI,CAAC;GAC9D,cAAc;IACZ,AAAI,EAAK,YAAY,KAAS,KAAK,WAAW,WAAW,GAAQ,EAAK,OAAO;GAC/E;EACF;EAEF,OAAO;CACT;CAEA,iBAAyB,GAA2C;EAClE,IAAI,CAAC,EAAiB,CAAM,GAAG,OAAO,CAAC;EACvC,IAAM,IAAO,EAA2B,EAAO;EAC/C,IAAI,CAAC,KAAQ,EAAK,WAAW,OAAO,CAAC;EACrC,IAAM,IAAmB,EAAO,YAAY,qBACtC,IAAW,EAAO,iBAAiB,CAAC,GACpC,IAAa,EAAO,mBAAmB,CAAC,GACxC,IAA4B,CAAC;EAEnC,KAAK,IAAM,KAAQ,GAAgB;GACjC,IAAM,IAAS,EAAS,SAAS,CAAI,GAC/B,IAAU,IAAmB,GAA2B,KAAQ,KAAA,GAGhE,IAAU,MAAY,KAAA,KAAa,CAAC;GAC1C,EAAQ,YAAY,OAAU;IAC5B,OAAO,EAAoB,EAAK,CAAC;IACjC,aAAa,IACT,IACE,GAAG,EAAQ,wBACX,IACF,EAAoB,EAAK,CAAC;IAC9B,WAAW,EAAY,CAAI;IAC3B,OAAO;KAAE,IAAI;KAAY,MAAM;IAAkC;IACjE,GAAI,IAAU,EAAE,UAAU,GAAK,IAAI,CAAC;IACpC,GAAI,IAAS,EAAE,WAAW,EAAa,IAAI,CAAC;IAC5C,cAAc;KACR,MACJ,KAAK,WAAW,iBACd,GACA,IAAS,EAAS,QAAQ,MAAa,MAAa,CAAI,IAAI,CAAC,GAAG,GAAU,CAAI,CAChF,GACA,KAAK,WAAW,GAAQ,CAAU;IACpC;GACF;EACF;EACA,KAAK,IAAM,KAAQ,GAAkB;GACnC,IAAM,IAAS,EAAW,SAAS,CAAI,GACjC,IAAU,IAAmB,GAA2B,KAAQ,KAAA,GAChE,IAAU,MAAY,KAAA,KAAa,CAAC;GAC1C,EAAQ,cAAc,OAAU;IAC9B,OAAO,EAAsB,EAAK,CAAC;IACnC,aAAa,IACT,IACE,GAAG,EAAQ,wBACX,IACF,EAAsB,EAAK,CAAC;IAChC,WAAW,EAAY,CAAI;IAC3B,OAAO;KAAE,IAAI;KAAc,MAAM;IAAwC;IACzE,GAAI,IAAU,EAAE,UAAU,GAAK,IAAI,CAAC;IACpC,GAAI,IAAS,EAAE,WAAW,EAAa,IAAI,CAAC;IAC5C,cAAc;KACR,MACJ,KAAK,WAAW,mBAAmB,GAAQ,IAAS,CAAC,IAAI,CAAC,CAAI,CAAC,GAC/D,KAAK,WAAW,GAAQ,CAAU;IACpC;GACF;EACF;EACA,OAAO;CACT;AACF,GCrsBa,KAAwC;CACnD,aAAa;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;CACF;CACA,UAAU,CAAC,sBAAsB;CACjC,sBAAsB,CAAC,QAAQ,EAAoB;AACrD,GCRM,KAA8E;CAClF;EAAE,OAAO;EAAO,GAAG,EAAoB;CAAI;CAC3C;EAAE,OAAO;EAAM,GAAG,EAAoB;CAAG;CACzC;EAAE,OAAO;EAAO,GAAG,EAAsB;CAAI;CAC7C;EAAE,OAAO;EAAM,GAAG,EAAsB;CAAG;AAC7C;AAEA,SAAS,EAAU,GAAmB,GAAe,GAAkC;CACrF,IAAM,IAAM,SAAS,cAAc,KAAK;CACxC,EAAI,YAAY;CAChB,IAAM,IAAO,SAAS,cAAc,MAAM;CAC1C,EAAK,cAAc;CACnB,IAAM,IAAM,SAAS,cAAc,MAAM;CAWzC,OAVA,EAAI,YAAY,iBAChB,EAAI,cAAc,GAGlB,EAAI,iBAAiB,oBAAoB;EACvC,IAAM,IAAS,EAAI,sBAAsB;EAEzC,AADA,EAAI,MAAM,OAAO,GAAG,EAAO,QAAQ,GAAG,KACtC,EAAI,MAAM,MAAM,GAAG,EAAO,MAAM,EAAO,SAAS,EAAE;CACpD,CAAC,GACD,EAAI,OAAO,GAAM,GAAM,CAAG,GACnB;AACT;AAEA,SAAS,GAAS,GAA0B;CAC1C,IAAM,IAAO,SAAS,cAAc,MAAM;CAG1C,OAFA,EAAK,YAAY,mBACjB,EAAK,YAAY,GACV;AACT;AAEA,SAAS,GAAS,GAA4B;CAC5C,IAAM,IAAO,SAAS,cAAc,MAAM;CAI1C,OAHA,EAAK,YAAY,mBACjB,EAAK,MAAM,aAAa,EAAY,IACpC,EAAK,cAAc,GACZ;AACT;AAEA,SAAS,EAAM,GAAe,GAAkC;CAC9D,IAAM,IAAK,SAAS,cAAc,KAAK;CAIvC,OAHA,EAAG,YAAY,oBACf,EAAG,aAAa,cAAc,CAAK,GACnC,EAAG,OAAO,GAAG,CAAI,GACV;AACT;AAEA,SAAS,KAAuB;CAC9B,IAAM,IAAK,SAAS,cAAc,KAAK;CAEvC,OADA,EAAG,YAAY,sBACR;AACT;AAEA,IAAqB,KAArB,MAA8B;CAC5B,OAAO,UAAU,CAAC,UAAU,UAAU;CAEtC,YAAoB;CACpB;CAEA,YAAY,GAAgB,GAAoB;EAI9C,AAHA,KAAK,OAAO,SAAS,cAAc,KAAK,GACxC,EAAO,aAAa,CAAC,CAAC,YAAY,KAAK,IAAI,GAC3C,KAAK,OAAO,GACZ,EAAS,GAAG,yBAAyB,KAAK,KAAK,OAAO,CAAC;CACzD;CAEA,SAAkB;EAChB,OAAO,KAAK;CACd;CAEA,QAAQ,GAAqB;EACvB,KAAK,cAAc,MACvB,KAAK,YAAY,GACjB,KAAK,OAAO;CACd;CAEA,SAAe;EACb,KAAK,QAAQ,CAAC,KAAK,SAAS;CAC9B;CAEA,SAAuB;EAIrB,IAAM,IAAW,KAAK,KAAK,SAAS,KAAK,KAAK,cAAc,aAAa;EAEzE,AADA,KAAK,KAAK,gBAAgB,KAAK,YAAY,KAAK,MAAM,IAAI,KAAK,gBAAgB,CAAC,GAC5E,KACF,KAAK,KAAK,cAAiC,sCAAsC,CAAC,EAAE,MAAM;CAE9F;CAEA,QAA6B;EAC3B,IAAM,IAAM,SAAS,cAAc,KAAK;EAExC,AADA,EAAI,YAAY,aAChB,EAAI,aAAa,cAAc,QAAQ;EAEvC,IAAM,IAAO,SAAS,cAAc,KAAK;EACzC,EAAK,YAAY;EACjB,IAAM,IAAQ,SAAS,cAAc,QAAQ;EAC7C,EAAM,cAAc;EACpB,IAAM,IAAQ,SAAS,cAAc,QAAQ;EAO7C,AANA,EAAM,OAAO,UACb,EAAM,YAAY,oBAClB,EAAM,aAAa,iBAAiB,MAAM,GAC1C,EAAM,aAAa,cAAc,iBAAiB,GAClD,EAAM,cAAc,KACpB,EAAM,iBAAiB,eAAe,KAAK,OAAO,CAAC,GACnD,EAAK,OAAO,GAAO,CAAK;EAExB,IAAM,IAAa,EACjB,mBACA,EAAoB,KAAK,MACvB,EAAU,GAAS,GAAiB,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,CACtE,CACF,GACM,IAAQ,EACZ,qBACA,GAAM,KAAK,MAAM,EAAU,GAAS,EAAE,KAAK,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,KAAK,EAAE,aAAa,CAAC,CACzF,GACM,IAAW,EACf,yBACA,EAAkB,KAAK,MACrB,EACE,GAAS,EAAoB,EAAE,SAAS,EAAE,CAAC,GAC3C,GAAG,EAAE,aAAa,KAAK,EAAE,SACzB,EAAE,WACJ,CACF,CACF,GAIM,IAAO,SAAS,cAAc,KAAK;EAIzC,OAHA,EAAK,YAAY,mBACjB,EAAK,OAAO,GAAY,GAAQ,GAAG,GAAO,GAAQ,GAAG,CAAQ,GAC7D,EAAI,OAAO,GAAM,CAAI,GACd;CACT;CAEA,kBAAuC;EACrC,IAAM,IAAS,SAAS,cAAc,QAAQ;EAI9C,AAHA,EAAO,OAAO,UACd,EAAO,YAAY,oBACnB,EAAO,aAAa,iBAAiB,OAAO,GAC5C,EAAO,aAAa,cAAc,aAAa;EAC/C,IAAM,IAAQ,SAAS,cAAc,MAAM;EAE3C,AADA,EAAM,aAAa,eAAe,MAAM,GACxC,EAAM,cAAc;EACpB,IAAM,IAAQ,SAAS,cAAc,MAAM;EAI3C,OAHA,EAAM,cAAc,UACpB,EAAO,OAAO,GAAO,CAAK,GAC1B,EAAO,iBAAiB,eAAe,KAAK,OAAO,CAAC,GAC7C;CACT;AACF,GC/Ka,KAAoC;CAC/C,UAAU,CAAC,UAAU;CACrB,UAAU,CAAC,QAAQ,EAAQ;AAC7B;;;ACOA,SAAS,GAAe,GAAqC;CAC3D,IAAM,IAAK;CAEX,OADK,IAEH,EAAG,YAAY,WACf,EAAG,YAAY,cACf,EAAG,YAAY,YACf,EAAG,oBALW;AAOlB;AAEA,IAAqB,KAArB,MAAgC;CAC9B,OAAO,UAAU;EAAC;EAAU;EAAgB;EAAa;CAAU;CAEnE,YACE,GACA,GACA,GACA,GACA;EAGA,CAFY,EAAO,aAAa,CAAC,CAAC,iBAAiB,SAAA,CAE/C,iBAAiB,YAAY,MAAqB;GACpD,IAAI,GAAe,EAAE,MAAM,GAAG;GAC9B,IAAM,IAAM,EAAE,WAAW,EAAE,SACrB,IAAM,EAAE,IAAI,YAAY;GAE9B,IAAI,KAAO,MAAQ,OAAO,CAAC,EAAE,UAE3B,AADA,EAAE,eAAe,GACb,EAAa,QAAQ,KAAG,EAAa,KAAK;QACzC,IAAK,KAAO,MAAQ,OAAO,EAAE,YAAc,KAAO,MAAQ,KAE/D,AADA,EAAE,eAAe,GACb,EAAa,QAAQ,KAAG,EAAa,KAAK;QACzC,IAAI,MAAQ,YAAY,MAAQ,aAAa;IAClD,IAAM,IAAM,EAAU,IAAI;IAC1B,AAAI,EAAI,WACN,EAAE,eAAe,GACjB,EAAS,eAAe,CAAC,GAAG,CAAG,CAAC;GAEpC;EACF,CAAC;CACH;AACF,GCnDa,KAAsC;CACjD,UAAU,CAAC,YAAY;CACvB,YAAY,CAAC,QAAQ,EAAU;AACjC,GCeM,KAAe,iBACf,IAAc,IACd,IAAc,IAEd,KAAe,IAIf,KAAQ,WACR,KAAM;AAMZ,SAAS,GAAW,GAAwC;CAE1D,IAAM,IADW,EAAS,MAAM,MAAY,EAAQ,SAAS,OAChD,IAAW,KAAM,IACxB,IAAS,SAAS,cAAc,KAAK;CAE3C,AADA,EAAO,YAAY,wBACnB,EAAO,YACL,eAAe,EAAY,YAAY,EAAY,2DACb,EAAK;CAI7C,IAAM,IAAU,SAAS,cAAc,KAAK;CAC5C,EAAQ,YAAY;CACpB,KAAK,IAAM,KAAW,GAAU;EAC9B,IAAM,IAAU,SAAS,cAAc,KAAK;EAG5C,AAFA,EAAQ,YAAY,kCACpB,EAAQ,cAAc,EAAQ,SAC9B,EAAQ,YAAY,CAAO;CAC7B;CAEA,OADA,EAAO,YAAY,CAAO,GACnB;AACT;AAQA,SAAS,GAAY,GAA8B,GAAoB,GAAyB;CAC9F,IAAM,IAAQ,EAAU,IAClB,IAAM,EAAU,EAAU,SAAS,IACnC,IAAK,EAAI,IAAI,EAAM,GACnB,IAAK,EAAI,IAAI,EAAM,GACnB,IAAS,KAAK,MAAM,GAAI,CAAE,KAAK,GAC/B,IAAK,IAAK,GACV,IAAK,IAAK;CAEhB,IAAI,MAAS,UACX,OAAO;EACL,IAAI,EAAM,IAAI,EAAI,KAAK,IAAI,CAAC,IAAK;EACjC,IAAI,EAAM,IAAI,EAAI,KAAK,IAAI,IAAK;CAClC;CAGF,IAAM,IAAmB,EAAa,YAAY,qBAC5C,IACJ,MAAS,aACL,EACE,GACA,GACA,IAAmB,MAAM,KACzB,EAAa,iBAAiB,CAAC,CACjC,IACA,EACE,GACA,GACA,IAAmB,MAAM,KACzB,EAAa,mBAAmB,CAAC,CACnC;CACN,IAAI,GAAQ;EAIV,IAAM,IAAS;GAAE,GAAG,EAAO,IAAI,IAAI,EAAO,IAAI;GAAO,GAAG,EAAO,IAAI,IAAI,EAAO,IAAI;EAAO;EACzF,OAAO;GAAE,GAAG,EAAO,IAAI;GAAG,GAAG,EAAO,IAAI;EAAE;CAC5C;CAEA,IAAM,IAAQ,KAAK,IAAI,IAAc,IAAS,GAAI,GAC5C,IAAQ,MAAS,aAAa,EAAM,IAAI,IAAK,IAAQ,EAAI,IAAI,IAAK,GAClE,IAAQ,MAAS,aAAa,EAAM,IAAI,IAAK,IAAQ,EAAI,IAAI,IAAK;CACxE,OAAO;EAAE,GAAG,IAAQ,CAAC,IAAK;EAAa,GAAG,IAAQ,IAAK;CAAY;AACrE;;;ACxGA,IAAa,KAAwC;CACnD,aAAa,CAAC,EAAc;CAC5B,UAAU,CAAC,qBAAqB;CAChC,qBAAqB,CAAC,QAAQ,MDuGS;EAKpB;EACA;EACA;EANnB,OAAO,UAAU;GAAC;GAAY;GAAmB;GAAY;EAAY;EAEzE,YACE,GACA,GACA,GACA,GACA;GADiB,AAFA,KAAA,kBAAA,GACA,KAAA,WAAA,GACA,KAAA,WAAA;GAEjB,IAAM,UAAsB,KAAK,QAAQ;GAEzC,AADA,EAAS,GAAG,sBAAsB,CAAO,GACzC,EAAS,GAAG,wBAAwB,CAAO;EAC7C;EAEA,UAAwB;GACtB,KAAK,SAAS,OAAO,EAAE,MAAM,GAAa,CAAC;GAE3C,IAAM,IAAS,EAAiB,KAAK,SAAS,OAAO,CAAC,GAGhD,oBAAW,IAAI,IAAmE,GAClF,KAAW,GAA6B,MAAsC;IAClF,KAAK,IAAM,KAAW,GAAU;KAC9B,IAAI,CAAC,EAAQ,gBAAgB;KAC7B,IAAM,IAAM,GAAG,EAAQ,eAAe,GAAG,EAAQ,QAAQ,YACnD,IAAQ,EAAS,IAAI,CAAG,KAAK;MAAE,gBAAgB,EAAQ;MAAgB,UAAU,CAAC;KAAE;KAE1F,AADA,EAAM,SAAS,KAAK;MAAE,GAAG;MAAS;KAAK,CAAC,GACxC,EAAS,IAAI,GAAK,CAAK;IACzB;GACF;GAEA,AADA,EAAQ,EAAO,QAAQ,OAAO,GAC9B,EAAQ,EAAO,UAAU,SAAS;GAElC,KAAK,IAAM,CAAC,GAAK,MAAU,GAAU;IACnC,IAAM,IAAU,KAAK,gBAAgB,IAAI,EAAM,cAAc;IAC7D,IAAI,CAAC,EAAiB,CAAO,GAAG;IAChC,IAAM,IAAa,EAAQ,aAAa,CAAC;IACzC,IAAI,EAAU,SAAS,GAAG;IAC1B,IAAM,IAAO,EAAI,MAAM,GAAG,CAAC,CAAC,IACtB,EAAE,GAAG,GAAS,GAAG,MAAY,GAAY,GAAS,GAAW,CAAI,GAGjE,IAAQ,KAAK,IAAI,GAAG,EAAU,KAAK,MAAM,EAAE,CAAC,CAAC,GAC7C,IAAQ,KAAK,IAAI,GAAG,EAAU,KAAK,MAAM,EAAE,CAAC,CAAC;IACnD,KAAK,SAAS,IAAI,GAAS,IAAc;KACvC,UAAU;MACR,MAAM,IAAU,IAAQ,IAAc;MACtC,KAAK,IAAU,IAAQ,IAAc;KACvC;KACA,MAAM,GAAW,EAAM,QAAQ;IACjC,CAAC;GACH;EACF;CACF,CC5JmD;AACnD;;;ACOA,SAAS,GAAK,GAAuB;CACnC,OAAO,IAAiB,CAAE;AAC5B;AAEA,IAAqB,KAArB,MAA8B;CAOT;CACA;CAPnB,OAAO,UAAU;EAAC;EAAY;EAAU;CAAiB;CAEzD,YAAoB;CAEpB,YACE,GACA,GACA,GACA;EAQA,AAViB,KAAA,SAAA,GACA,KAAA,kBAAA,GAEjB,EAAS,GAAG,6BAA6B;GACvC,KAAK,YAAY;EACnB,CAAC,GACD,EAAS,GAAG,4BAA4B;GAEtC,AADA,KAAK,YAAY,IACjB,KAAK,QAAQ;EACf,CAAC,GACD,EAAS,GAAG,8BAA8B;GACxC,AAAK,KAAK,aAAW,KAAK,QAAQ;EACpC,CAAC;CACH;CAGA,UAAgB;EACd,IAAM,IAAW,KAAK,gBAAgB,OAAO,CAAC,CAAC,OAAO,CAAW,CAAC,CAAiB,MAChF,GAAG,MAAM,GAAK,CAAC,IAAI,GAAK,CAAC,CAC5B;EACA,KAAK,IAAM,KAAM,GAAS;GAExB,IAAM,IADM,KAAK,OAAO,YAAY,CACpB,CAAA,EAAK,YACf,IAAQ,GAAS;GACvB,AAAI,KAAW,KAAO,EAAM,YAAY,CAAO;EACjD;CACF;AACF,GClDa,KAAoC;CAC/C,UAAU,CAAC,UAAU;CACrB,UAAU,CAAC,QAAQ,EAAQ;AAC7B,GCkBa,KAAb,cAA6B,GAAgB;CAC3C,cAAsD;EACpD,OAAO;GACL,GAAG,MAAM,YAAY;GAErB;GACA;GACA;GACA;GAEA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF;CACF;CAEA,OAAa;EACX,KAAK,IAAkB,cAAc,CAAC,CAAC,KAAK;CAC9C;CAEA,OAAa;EACX,KAAK,IAAkB,cAAc,CAAC,CAAC,KAAK;CAC9C;CAEA,UAAmB;EACjB,OAAO,KAAK,IAAkB,cAAc,CAAC,CAAC,QAAQ;CACxD;CAEA,UAAmB;EACjB,OAAO,KAAK,IAAkB,cAAc,CAAC,CAAC,QAAQ;CACxD;AACF,GC3CM,KAAe,qBACf,KAAc,IAEd,KAAa,IAEb,KAAQ;CACZ;EAAE,MAAM;EAAO,aAAa;CAAI;CAChC;EAAE,MAAM;EAAS,aAAa;CAAE;CAChC;EAAE,MAAM;EAAU,aAAa;CAAG;CAClC;EAAE,MAAM;EAAQ,aAAa;CAAI;AACnC;AAIA,SAAS,GACP,GACA,GAC+B;CAC/B,IAAM,IAAe,EAAM,QAAQ,IAAI,KAAc,GAC/C,IAAc,EAAM,SAAS,IAAI,KAAc;CAErD,QAAQ,GAAR;EACE,KAAK,OACH,OAAO;GAAE,KAAK;GAAU,MAAM;EAAa;EAC7C,KAAK,UACH,OAAO;GAAE,KAAK,EAAM,SAAS;GAAY,MAAM;EAAa;EAC9D,KAAK,QACH,OAAO;GAAE,KAAK;GAAa,MAAM;EAAS;EAC5C,KAAK,SACH,OAAO;GAAE,KAAK;GAAa,MAAM,EAAM,QAAQ;EAAW;CAC9D;AACF;AAEA,IAAqB,KAArB,MAAsC;CAIjB;CACA;CACA;CAEA;CAPnB,OAAO,UAAU;EAAC;EAAY;EAAa;EAAY;EAAW;CAAU;CAE5E,YACE,GACA,GACA,GACA,GACA,GACA;EADiB,AAJA,KAAA,WAAA,GACA,KAAA,YAAA,GACA,KAAA,WAAA,GAEA,KAAA,WAAA;EAMjB,IAAM,UAAsB,KAAK,QAAQ;EAGzC,AAFA,EAAS,GAAG,qBAAqB,CAAO,GAExC,EAAS,GAAG,wBAAwB,CAAO;CAC7C;CAEA,UAAwB;EACtB,KAAK,SAAS,OAAO,EAAE,MAAM,GAAa,CAAC;EAE3C,IAAM,IAAW,KAAK,UAAU,IAAI;EACpC,IAAI,EAAS,WAAW,GAAG;EAC3B,IAAM,IAAU,EAAS;EACzB,IAAI,CAAC,EAAY,CAAO,GAAG;EAC3B,IAAM,IAAQ;EAEd,KAAK,IAAM,EAAE,SAAM,oBAAiB,IAAO;GACzC,IAAM,IAAS,SAAS,cAAc,KAAK;GA8B3C,AA7BA,EAAO,YAAY,qBACnB,EAAO,QAAQ,OAAO,GACtB,EAAO,QAAQ,8BACf,EAAO,YAAY,8CAA8C,EAAY,QAAQ,EAAW,EAAkB,EAAE,UACpH,EAAO,iBAAiB,cAAc,MAAsB;IACtD,EAAM,WAAW,MACrB,EAAM,eAAe,GACrB,EAAM,gBAAgB,GAMtB,KAAK,SAAS,KAAK,GAAO,WAAW;KACnC,cAAc;KACd,WAAW;KACX,MAAM;MACJ,OAAO;MACP,SAAS;OAAE,OAAO;OAAS,iBAAiB,EAAO,CAAO;MAAE;KAC9D;IACF,CAAC,GAID,KAAK,SAAS,KAAK,mBAAmB,WAAW;KAC/C,AAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAG,KAAK,UAAU,OAAO,CAAO;IACtE,CAAC;GACH,CAAC,GAED,KAAK,SAAS,IAAI,GAAS,IAAc;IACvC,UAAU,GAAe,GAAM,CAAK;IACpC,MAAM;GACR,CAAC;EACH;CACF;AACF,GChHa,KAA4C;CACvD,aAAa;EAAC;EAAe;EAAgB;CAAe;CAC5D,UAAU,CAAC,kBAAkB;CAC7B,kBAAkB,CAAC,QAAQ,EAAgB;AAC7C"}