@invana/canvas-react 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2291 -0
- package/dist/index.js +2251 -0
- package/dist/index.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/CanvasContext.ts","../src/Canvas.tsx","../src/HistoryContext.ts","../src/ClipboardContext.ts","../src/ToolContext.ts","../src/hooks/useResolvedCanvas.ts","../src/providers/GraphHistoryProvider.tsx","../src/providers/GraphClipboardProvider.tsx","../src/providers/GraphToolProvider.tsx","../src/layers/GraphLayer.tsx","../src/layers/BackgroundLayer.tsx","../src/layers/MiniMapLayer.tsx","../src/behaviours/useBehaviourRegistration.ts","../src/behaviours/DragPanBehaviour.tsx","../src/behaviours/WheelZoomBehaviour.tsx","../src/behaviours/PinchZoomBehaviour.tsx","../src/behaviours/KeyboardCameraInputBehaviour.tsx","../src/behaviours/DragNodeBehaviour.tsx","../src/behaviours/ContextMenuBehaviour.tsx","../src/behaviours/CreateNodeBehaviour.tsx","../src/behaviours/DrawEdgeBehaviour.tsx","../src/behaviours/EraseBehaviour.tsx","../src/behaviours/HoverActivateBehaviour.tsx","../src/behaviours/ClickSelectBehaviour.tsx","../src/behaviours/ClickInspectBehaviour.tsx","../src/behaviours/BrushSelectBehaviour.tsx","../src/behaviours/LassoSelectBehaviour.tsx","../src/behaviours/CollapseExpandBehaviour.tsx","../src/behaviours/NodeResizeBehaviour.tsx","../src/behaviours/LabelCollisionBehaviour.tsx","../src/behaviours/LabelResolutionLODBehaviour.tsx","../src/behaviours/NodeSizeLODBehaviour.tsx","../src/behaviours/EdgeSizeLODBehaviour.tsx","../src/behaviours/ParallelEdgeBehaviour.tsx","../src/behaviours/DegreeSizeBehaviour.tsx","../src/behaviours/ResponsiveThemeBehaviour.tsx","../src/layouts/D3ForceLayout.tsx","../src/hooks/useCamera.ts","../src/hooks/useZoom.ts","../src/hooks/useFitContent.ts","../src/hooks/useCanvasEvent.ts","../src/hooks/useClearGraph.ts","../src/hooks/useSelection.ts","../src/hooks/useInspectTarget.ts","../src/hooks/useHistory.ts","../src/hooks/useClipboard.ts","../src/hooks/useGrid.ts","../src/hooks/useTheme.ts","../src/hooks/useLayout.ts","../src/hooks/useSelectMode.ts","../src/hooks/useEdgeType.ts","../src/hooks/useLock.ts","../src/hooks/useTool.ts","../src/hooks/useDrawHistory.ts","../src/hooks/useEntityEditor.ts","../src/hooks/useContextMenu.ts","../src/components/Panel.tsx","../src/components/Tooltipped.tsx","../src/components/ControlButton.tsx","../src/components/PropertiesEditor.tsx","../src/components/OptionPicker.tsx","../src/components/ZoomControls.tsx","../src/components/LockToggle.tsx","../src/components/ClearButton.tsx","../src/components/FitContentButton.tsx","../src/components/ZoomPicker.tsx","../src/components/UndoButton.tsx","../src/components/RedoButton.tsx","../src/components/RedrawButton.tsx","../src/components/CutButton.tsx","../src/components/CopyButton.tsx","../src/components/PasteButton.tsx","../src/components/DeleteSelectionButton.tsx","../src/components/GridToggle.tsx","../src/components/ThemeToggle.tsx","../src/components/LockButton.tsx","../src/components/LayoutPicker.tsx","../src/components/SelectModePicker.tsx","../src/components/EdgeTypePicker.tsx","../src/components/ContextMenuOverlay.tsx","../src/toolbars/CanvasControlsToolbar.tsx","../src/toolbars/GraphToolbar.tsx","../src/toolbars/HistoryToolbar.tsx","../src/toolbars/EditToolbar.tsx","../src/toolbars/ViewToolbar.tsx","../src/toolbars/GridToolbar.tsx","../src/toolbars/GraphLayoutToolbar.tsx","../src/toolbars/ModellerToolbar.tsx","../src/toolbars/InspectorPanel.tsx","../src/menus/GraphContextMenuBase.tsx","../src/menus/GraphNodeContextMenu.tsx","../src/menus/GraphEdgeContextMenu.tsx","../src/menus/GraphBackgroundContextMenu.tsx"],"names":["Canvas","EngineCanvas","createContext","useContext","useState","useEffect","jsx","useRef","EngineGraphLayer","EngineBackgroundLayer","useMemo","EngineMiniMapLayer","EngineDragPanBehaviour","EngineWheelZoomBehaviour","EnginePinchZoomBehaviour","EngineKeyboardCameraInputBehaviour","EngineDragNodeBehaviour","EngineContextMenuBehaviour","EngineCreateNodeBehaviour","EngineDrawEdgeBehaviour","EngineEraseBehaviour","EngineHoverActivateBehaviour","EngineClickSelectBehaviour","EngineClickInspectBehaviour","EngineBrushSelectBehaviour","EngineLassoSelectBehaviour","EngineCollapseExpandBehaviour","EngineNodeResizeBehaviour","EngineLabelCollisionBehaviour","EngineLabelResolutionLODBehaviour","EngineNodeSizeLODBehaviour","EngineEdgeSizeLODBehaviour","EngineParallelEdgeBehaviour","EngineDegreeSizeBehaviour","EngineResponsiveThemeBehaviour","EngineD3ForceLayout","useCallback","type","commit","jsxs","Button","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","Fragment","DropdownMenuRadioGroup","DropdownMenuRadioItem","NavHorizontal","NavVertical"],"mappings":";;;;;;;;AAQO,IAAM,aAAA,GAAgB,cAAmC,IAAI;AAO7D,SAAS,SAAA,GAA0B;AACxC,EAAA,MAAM,MAAA,GAAS,WAAW,aAAa,CAAA;AACvC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAAA,EAC1E;AACA,EAAA,OAAO,MAAA;AACT;AC8BO,IAAM,MAAA,GAAS,UAAA,CAAsC,SAASA,OAAAA,CACnE,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,GAAG,UAAA,EAAW,EAC5C,GAAA,EACA;AACA,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAA8B,IAAI,CAAA;AAI9D,EAAA,MAAM,OAAA,GAAU,OAAO,UAAU,CAAA;AACjC,EAAA,OAAA,CAAQ,OAAA,GAAU,UAAA;AAElB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,YAAY,OAAA,CAAQ,OAAA;AAC1B,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,MAAM,MAAA,GAAS,IAAIC,QAAA,EAAa;AAEhC,IAAA,KAAK,MAAA,CACF,IAAA,CAAK,EAAE,SAAA,EAAW,GAAG,QAAQ,OAAA,EAAS,CAAA,CACtC,IAAA,CAAK,MAAM;AACV,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAA,CAAO,OAAA,EAAQ;AACf,QAAA;AAAA,MACF;AACA,MAAA,SAAA,CAAU,MAAM,CAAA;AAAA,IAClB,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAiB;AACvB,MAAA,IAAI,CAAC,SAAA,EAAW;AAId,QAAA,OAAA,CAAQ,KAAA,CAAM,wCAAwC,GAAG,CAAA;AAAA,MAC3D;AAAA,IACF,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,SAAA,CAAU,IAAI,CAAA;AACd,MAAA,IAAI,MAAA,CAAO,aAAA,EAAe,MAAA,CAAO,OAAA,EAAQ;AAAA,IAC3C,CAAA;AAAA,EAIF,CAAA,EAAG,EAAE,CAAA;AAML,EAAA,mBAAA,CAAoB,GAAA,EAAK,MAAM,MAAA,EAAwB,CAAC,MAAM,CAAC,CAAA;AAE/D,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,OAAA;AAAA,MACL,SAAA;AAAA,MAGA,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,QAAQ,MAAA,EAAQ,QAAA,EAAU,UAAA,EAAY,GAAG,KAAA,EAAM;AAAA,MAEtE,oCAAU,GAAA,CAAC,aAAA,CAAc,UAAd,EAAuB,KAAA,EAAO,QAAS,QAAA,EAAS;AAAA;AAAA,GAC9D;AAEJ,CAAC;AC1GM,IAAM,cAAA,GAAiBC,cAAmC,IAAI;ACA9D,IAAM,gBAAA,GAAmBA,cAAqC,IAAI;ACuBlE,IAAM,WAAA,GAAcA,cAAuC,IAAI;AChB/D,SAAS,kBAAkB,QAAA,EAA8C;AAC9E,EAAA,MAAM,WAAA,GAAcC,WAAW,aAAa,CAAA;AAC5C,EAAA,MAAM,SAAS,QAAA,IAAY,WAAA;AAC3B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;ACWO,SAAS,oBAAA,CAAqB;AAAA,EACnC,OAAA,GAAU,OAAA;AAAA,EACV,KAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIC,SAA8B,IAAI,CAAA;AAEhE,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAsB,OAAO,CAAA;AAC3D,IAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AACrB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,QAAA,GAAW,IAAI,YAAA,CAAa,KAAA,EAAO,KAAA,KAAU,SAAY,EAAE,KAAA,EAAM,GAAI,EAAE,CAAA;AAC7E,IAAA,UAAA,CAAW,QAAQ,CAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA,IACjB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,OAAA,EAAS,KAAK,CAAC,CAAA;AAO7B,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAsB,OAAO,CAAA;AAC3D,IAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AACrB,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,EAAO;AAEtB,IAAA,IAAI,MAAA,GAAmC,IAAA;AACvC,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,EAAA,CAAG,mBAAmB,CAAC,EAAE,MAAA,EAAQ,OAAA,EAAQ,KAAM;AAC3E,MAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,MAAA,KAAA,MAAW,OAAA,IAAW,OAAA,IAAW,CAAC,MAAM,CAAA,EAAG;AACzC,QAAA,GAAA,CAAI,IAAI,OAAO,CAAA;AACf,QAAA,KAAA,MAAW,QAAQ,KAAA,CAAM,aAAA,CAAc,OAAO,CAAA,EAAG,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,MAC/D;AACA,MAAA,MAAA,uBAAa,GAAA,EAAI;AACjB,MAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,QAAA,MAAM,CAAA,GAAI,KAAA,CAAM,WAAA,CAAY,EAAE,CAAA;AAC9B,QAAA,IAAI,CAAA,EAAG,MAAA,CAAO,GAAA,CAAI,EAAA,EAAI,EAAE,CAAA,EAAG,CAAA,CAAE,CAAA,EAAG,CAAA,EAAG,CAAA,CAAE,CAAA,EAAG,CAAA;AAAA,MAC1C;AAAA,IACF,CAAC,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,iBAAiB,MAAM;AACpD,MAAA,MAAM,IAAA,GAAO,MAAA;AACb,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,IAAI,CAAC,IAAA,EAAM;AACX,MAAA,MAAM,MAAmB,EAAC;AAC1B,MAAA,KAAA,MAAW,CAAC,EAAA,EAAI,IAAI,CAAA,IAAK,IAAA,EAAM;AAC7B,QAAA,MAAM,EAAA,GAAK,KAAA,CAAM,WAAA,CAAY,EAAE,CAAA;AAC/B,QAAA,IAAI,EAAA,KAAO,GAAG,CAAA,KAAM,IAAA,CAAK,KAAK,EAAA,CAAG,CAAA,KAAM,KAAK,CAAA,CAAA,EAAI;AAC9C,UAAA,GAAA,CAAI,KAAK,EAAE,IAAA,EAAM,UAAA,EAAY,EAAA,EAAI,QAAQ,IAAA,EAAM,KAAA,EAAO,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,EAAA,CAAG,CAAA,IAAK,CAAA;AAAA,QAC9E;AAAA,MACF;AACA,MAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG,OAAA,CAAQ,KAAK,EAAE,GAAA,EAAK,KAAA,EAAO,MAAA,EAAQ,CAAA;AAAA,IACzD,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,EAAS;AACT,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,OAAA,EAAS,OAAO,CAAC,CAAA;AAE/B,EAAA,uBAAOC,GAAAA,CAAC,cAAA,CAAe,UAAf,EAAwB,KAAA,EAAO,SAAU,QAAA,EAAS,CAAA;AAC5D;ACzEO,SAAS,sBAAA,CAAuB;AAAA,EACrC,OAAA,GAAU,OAAA;AAAA,EACV,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIF,SAAgC,IAAI,CAAA;AAEtE,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAsB,OAAO,CAAA;AAC3D,IAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AACrB,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,QAAA,GAAW,IAAI,cAAA,CAAe,KAAA,EAAO,cAAc,EAAE,WAAA,EAAY,GAAI,EAAE,CAAA;AAC7E,IAAA,YAAA,CAAa,QAAQ,CAAA;AACrB,IAAA,OAAO,MAAM,aAAa,IAAI,CAAA;AAAA,EAChC,CAAA,EAAG,CAAC,QAAA,EAAU,OAAA,EAAS,WAAW,CAAC,CAAA;AAEnC,EAAA,uBAAOC,GAAAA,CAAC,gBAAA,CAAiB,UAAjB,EAA0B,KAAA,EAAO,WAAY,QAAA,EAAS,CAAA;AAChE;ACrBO,SAAS,iBAAA,CAAkB;AAAA,EAChC,WAAA,GAAc,QAAA;AAAA,EACd,eAAA,GAAkB,QAAA;AAAA,EAClB,cAAA,GAAiB,IAAA;AAAA,EACjB;AACF,CAAA,EAA2B;AACzB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIF,SAAoB,WAAW,CAAA;AACvD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,SAAiB,eAAe,CAAA;AAIhE,EAAA,MAAM,QAAQ,WAAA,CAAY,MAAM,QAAQ,QAAQ,CAAA,EAAG,EAAE,CAAA;AACrD,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,cAAA,EAAgB;AACrB,IAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAA2B;AACxC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,QAAA,EAAU,KAAA,EAAM;AAAA,IAChC,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,KAAK,CAAA;AACxC,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,KAAK,CAAA;AAAA,EAC1D,CAAA,EAAG,CAAC,cAAA,EAAgB,KAAK,CAAC,CAAA;AAE1B,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,UAAU,WAAA,EAAY,CAAA;AAAA,IAC9C,CAAC,MAAM,QAAQ;AAAA,GACjB;AAEA,EAAA,uBAAOC,GAAAA,CAAC,WAAA,CAAY,QAAA,EAAZ,EAAqB,OAAe,QAAA,EAAS,CAAA;AACvD;ACnBO,SAAS,UAAA,CAAW,EAAE,EAAA,GAAK,OAAA,EAAS,MAAM,KAAA,EAAO,GAAG,MAAK,EAAoB;AAClF,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,QAAA,GAAWC,OAAgC,IAAI,CAAA;AAErD,EAAAF,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,IAAIG,YAAA,CAAiB;AAAA,MACjC,EAAA;AAAA,MACA,OAAA,EAAS,EAAE,GAAI,IAAA,EAA4B,GAAI,QAAQ,EAAE,KAAA,EAAM,GAAI,EAAC;AAAG,KACxE,CAAA;AACD,IAAA,MAAA,CAAO,MAAA,CAAO,IAAI,KAAK,CAAA;AACvB,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,MAAA,CAAO,OAAO,EAAE,CAAA;AACvB,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EAGF,CAAA,EAAG,CAAC,MAAA,EAAQ,EAAE,CAAC,CAAA;AAEf,EAAAH,UAAU,MAAM;AACd,IAAA,IAAI,IAAA,IAAQ,SAAS,OAAA,EAAS;AAC5B,MAAA,QAAA,CAAS,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,OAAO,IAAA;AACT;ACvCO,SAAS,gBAAgB,EAAE,EAAA,GAAK,YAAA,EAAc,GAAG,SAAQ,EAAyB;AACvF,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,QAAA,GAAWE,OAAqC,IAAI,CAAA;AAE1D,EAAAF,UAAU,MAAM;AACd,IAAA,MAAM,QAAQ,IAAII,iBAAA,CAAsB,EAAE,EAAA,EAAI,SAAS,CAAA;AACvD,IAAA,MAAA,CAAO,MAAA,CAAO,IAAI,KAAK,CAAA;AACvB,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,MAAA,CAAO,OAAO,EAAE,CAAA;AACvB,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EAGF,CAAA,EAAG,CAAC,MAAA,EAAQ,EAAE,CAAC,CAAA;AAIf,EAAA,MAAM,UAAA,GAAaC,QAAQ,MAAM,IAAA,CAAK,UAAU,OAAO,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACnE,EAAAL,UAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,WAAW,OAAO,CAAA;AAAA,EAEtC,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,OAAO,IAAA;AACT;ACxBO,SAAS,YAAA,CAAa;AAAA,EAC3B,EAAA,GAAK,SAAA;AAAA,EACL,YAAA,GAAe,OAAA;AAAA,EACf,GAAG;AACL,CAAA,EAAsB;AACpB,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,QAAA,GAAWE,OAAkC,IAAI,CAAA;AAEvD,EAAAF,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,IAAIM,cAAA,CAAmB,EAAE,EAAA,EAAI,OAAA,EAAS,EAAE,YAAA,EAAc,GAAG,OAAA,EAAQ,EAAG,CAAA;AAClF,IAAA,MAAA,CAAO,MAAA,CAAO,IAAI,KAAK,CAAA;AACvB,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,MAAA,CAAO,OAAO,EAAE,CAAA;AACvB,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EAGF,CAAA,EAAG,CAAC,MAAA,EAAQ,EAAA,EAAI,YAAY,CAAC,CAAA;AAE7B,EAAA,MAAM,UAAA,GAAaD,QAAQ,MAAM,IAAA,CAAK,UAAU,OAAO,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AACnE,EAAAL,UAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,WAAW,OAAO,CAAA;AAAA,EAEtC,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,OAAO,IAAA;AACT;ACxBO,SAAS,wBAAA,CACd,MAAA,EACA,EAAA,EACA,OAAA,EACA,QAAA,EACM;AACN,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,YAAY,MAAA,EAAO;AACzB,IAAA,MAAA,CAAO,UAAA,CAAW,SAAS,SAAS,CAAA;AACpC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,UAAA,CAAW,WAAW,EAAE,CAAA;AAAA,IACjC,CAAA;AAAA,EAGF,CAAA,EAAG,CAAC,MAAA,EAAQ,GAAG,QAAQ,CAAC,CAAA;AAExB,EAAAA,UAAU,MAAM;AACd,IAAA,MAAA,CAAO,UAAA,CAAW,UAAA,CAAW,EAAA,EAAI,OAAO,CAAA;AAAA,EAE1C,GAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,GAAG,QAAQ,CAAC,CAAA;AACnC;;;AC7BO,SAAS,gBAAA,CAAiB,EAAE,EAAA,GAAK,KAAA,EAAO,UAAU,IAAA,EAAM,GAAG,MAAK,EAA0B;AAC/F,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIO,kBAAA,CAAuB,EAAE,IAAI,OAAA,EAAS,GAAG,MAAM,CAAA;AAAA,IACzD,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AACA,EAAA,OAAO,IAAA;AACT;ACRO,SAAS,kBAAA,CAAmB;AAAA,EACjC,EAAA,GAAK,MAAA;AAAA,EACL,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA4B;AAC1B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,oBAAA,CAAyB,EAAE,IAAI,OAAA,EAAS,GAAG,MAAM,CAAA;AAAA,IAC3D,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AACA,EAAA,OAAO,IAAA;AACT;ACZO,SAAS,kBAAA,CAAmB;AAAA,EACjC,EAAA,GAAK,OAAA;AAAA,EACL,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA4B;AAC1B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,oBAAA,CAAyB,EAAE,IAAI,OAAA,EAAS,GAAG,MAAM,CAAA;AAAA,IAC3D,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AACA,EAAA,OAAO,IAAA;AACT;ACXO,SAAS,4BAAA,CAA6B;AAAA,EAC3C,EAAA,GAAK,iBAAA;AAAA,EACL,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAsC;AACpC,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,8BAAA,CAAmC,EAAE,IAAI,OAAA,EAAS,GAAG,MAAM,CAAA;AAAA,IACrE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AACA,EAAA,OAAO,IAAA;AACT;ACXO,SAAS,iBAAA,CAAkB;AAAA,EAChC,EAAA,GAAK,WAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA2B;AACzB,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,mBAAA,CAAwB,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACnE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACVO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,cAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACdO,SAAS,mBAAA,CAAoB;AAAA,EAClC,EAAA,GAAK,aAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA6B;AAC3B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,qBAAA,CAA0B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACrE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,iBAAA,CAAkB;AAAA,EAChC,EAAA,GAAK,WAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA2B;AACzB,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,mBAAA,CAAwB,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACnE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,cAAA,CAAe;AAAA,EAC7B,EAAA,GAAK,OAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAwB;AACtB,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,gBAAA,CAAqB,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IAChE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACfO,SAAS,sBAAA,CAAuB;AAAA,EACrC,EAAA,GAAK,OAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAgC;AAC9B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,wBAAA,CAA6B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACxE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,cAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACXO,SAAS,qBAAA,CAAsB;AAAA,EACpC,EAAA,GAAK,eAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA+B;AAC7B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,uBAAA,CAA4B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACvE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACdO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,cAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,cAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,uBAAA,CAAwB;AAAA,EACtC,EAAA,GAAK,iBAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAiC;AAC/B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,yBAAA,CAA8B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACzE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,mBAAA,CAAoB;AAAA,EAClC,EAAA,GAAK,aAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA6B;AAC3B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,qBAAA,CAA0B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACrE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,uBAAA,CAAwB;AAAA,EACtC,EAAA,GAAK,iBAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAiC;AAC/B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,yBAAA,CAA8B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACzE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,2BAAA,CAA4B;AAAA,EAC1C,EAAA,GAAK,WAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAqC;AACnC,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,6BAAA,CAAkC,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IAC7E,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,eAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,oBAAA,CAAqB;AAAA,EACnC,EAAA,GAAK,eAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,sBAAA,CAA2B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACtE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,qBAAA,CAAsB;AAAA,EACpC,EAAA,GAAK,eAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA+B;AAC7B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,uBAAA,CAA4B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACvE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACbO,SAAS,mBAAA,CAAoB;AAAA,EAClC,EAAA,GAAK,aAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAA6B;AAC3B,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,qBAAA,CAA0B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IACrE,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACXO,SAAS,wBAAA,CAAyB;AAAA,EACvC,EAAA,GAAK,kBAAA;AAAA,EACL,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,GAAG;AACL,CAAA,EAAkC;AAChC,EAAA,wBAAA;AAAA,IACE,MAAM,IAAIC,0BAAA,CAA+B,EAAE,IAAI,OAAA,EAAS,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IAC1E,EAAA;AAAA,IACA,OAAA;AAAA,IACA,CAAC,IAAI,OAAO;AAAA,GACd;AACA,EAAA,OAAO,IAAA;AACT;ACCO,SAAS,aAAA,CAAc;AAAA,EAC5B,aAAA,GAAgB,OAAA;AAAA,EAChB,UAAA,GAAa,EAAA;AAAA,EACb;AACF,CAAA,EAAuB;AACrB,EAAA,MAAM,SAAS,SAAA,EAAU;AAEzB,EAAA7B,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,GAAA,CAAsB,aAAa,CAAA;AAC/D,IAAA,IAAI,CAAC,KAAA,EAAO;AAEV,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,wDAAwD,aAAa,CAAA,+EAAA;AAAA,OACvE;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAI8B,eAAA,CAAoB,OAAO,CAAA;AAC9C,IAAA,IAAI,cAAc,IAAA,EAAM;AACtB,MAAA,MAAA,CAAO,MAAA,CAAO,EAAA,CAAG,KAAA,EAAO,MAAM;AAC5B,QAAA,MAAA,CAAO,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,SAAA,IAAa,UAAU,CAAA;AAAA,MACxD,CAAC,CAAA;AAAA,IACH;AACA,IAAA,KAAK,MAAA,CAAO,MAAM,KAAK,CAAA;AAEvB,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,IAAA,EAAK;AAAA,IACd,CAAA;AAAA,EAIF,CAAA,EAAG,CAAC,MAAA,EAAQ,aAAa,CAAC,CAAA;AAE1B,EAAA,OAAO,IAAA;AACT;ACjEA,IAAM,iBAAA,GAAoB,GAAA;AA4BnB,SAAS,UAAU,MAAA,EAA+C;AACvE,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AAEzC,EAAA,OAAOzB,QAAyB,MAAM;AACpC,IAAA,MAAM,SAAS,QAAA,CAAS,MAAA;AACxB,IAAA,OAAO;AAAA,MACL,QAAQ,CAAC,MAAA,GAAS,iBAAA,KAAsB,MAAA,CAAO,OAAO,MAAM,CAAA;AAAA,MAC5D,SAAS,CAAC,MAAA,GAAS,sBAAsB,MAAA,CAAO,MAAA,CAAO,IAAI,MAAM,CAAA;AAAA,MACjE,OAAA,EAAS,CAAC,KAAA,KAAU,MAAA,CAAO,QAAQ,KAAK,CAAA;AAAA,MACxC,MAAA,EAAQ,CAAC,KAAA,EAAO,OAAA,EAAS,OAAA,KACvB,MAAA,CAAO,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAAA,MACtD,KAAK,CAAC,EAAA,EAAI,OAAO,MAAA,CAAO,GAAA,CAAI,IAAI,EAAE,CAAA;AAAA,MAClC,YAAY,CAAC,SAAA,EAAW,YAAY,MAAA,CAAO,UAAA,CAAW,WAAW,OAAO,CAAA;AAAA,MACxE,OAAA,EAAS,MAAM,MAAA,CAAO;AAAA,KACxB;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AACf;ACzBO,SAAS,QAAQ,MAAA,EAA6C;AACnE,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAS,MAAA,EAAO,GAAI,UAAU,QAAQ,CAAA;AAC/D,EAAA,MAAM,CAAC,MAAM,YAAY,CAAA,GAAIN,SAAS,MAAM,QAAA,CAAS,OAAO,KAAK,CAAA;AAEjE,EAAAC,UAAU,MAAM;AAEd,IAAA,YAAA,CAAa,QAAA,CAAS,OAAO,KAAK,CAAA;AAClC,IAAA,OAAO,QAAA,CAAS,MAAA,CAAO,EAAA,CAAG,aAAA,EAAe,CAAC,EAAE,KAAA,EAAM,KAAM,YAAA,CAAa,KAAK,CAAC,CAAA;AAAA,EAC7E,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,SAAS,MAAA,EAAO;AAClD;AC/BA,IAAM,mBAAA,GAAsB,EAAA;AAO5B,SAAS,aAAa,KAAA,EAAuC;AAC3D,EAAA,OAAO,OAAQ,OAAoC,SAAA,KAAc,UAAA;AACnE;AAmBO,SAAS,aAAA,CACd,SACA,MAAA,EACqB;AACrB,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAID,QAAAA,CAAS,MAAM,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAC,CAAA;AAE/E,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,OAAO,MAAM,aAAA,CAAc,SAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAC,CAAA;AAC7D,IAAA,IAAA,EAAK;AACL,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,MAAA,CAAO,EAAA,CAAG,eAAe,IAAI,CAAA;AACvD,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,MAAA,CAAO,EAAA,CAAG,iBAAiB,IAAI,CAAA;AAC3D,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,EAAS;AACT,MAAA,UAAA,EAAW;AAAA,IACb,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,OAAO,CAAC,CAAA;AAEtB,EAAA,MAAM,UAAA,GAAa+B,WAAAA;AAAA,IACjB,CAAC,UAAU,mBAAA,KAAwB;AACjC,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA;AACzC,MAAA,IAAI,YAAA,CAAa,KAAK,CAAA,EAAG;AACvB,QAAA,QAAA,CAAS,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,SAAA,IAAa,OAAO,CAAA;AAAA,MACvD;AAAA,IACF,CAAA;AAAA,IACA,CAAC,UAAU,OAAO;AAAA,GACpB;AAEA,EAAA,OAAO,EAAE,YAAY,UAAA,EAAW;AAClC;AC5CO,SAAS,cAAA,CACd,KAAA,EACA,OAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa7B,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAErB,EAAAF,UAAU,MAAM;AAEd,IAAA,OAAO,QAAA,CAAS,OAAO,EAAA,CAAG,KAAA,EAAO,CAAC,OAAA,KAAY,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAC,CAAA;AAAA,EAC3E,CAAA,EAAG,CAAC,QAAA,EAAU,KAAK,CAAC,CAAA;AACtB;AChBA,SAAS,SAAS,KAAA,EAAyC;AACzD,EAAA,OAAO,OAAQ,OAAsC,KAAA,KAAU,UAAA;AACjE;AAqBO,SAAS,aAAA,CACd,SACA,MAAA,EACqB;AACrB,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,OAAA,GAAUF,WAAW,cAAc,CAAA;AAEzC,EAAA,MAAM,KAAA,GAAQiC,YAAY,MAAM;AAC9B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AAEtB,IAAA,MAAM,QAAS,KAAA,CAAwB,KAAA;AACvC,IAAA,IAAI,WAAW,KAAA,EAAO;AAIpB,MAAA,MAAM,GAAA,GAAM,CAAC,GAAG,KAAA,CAAM,KAAA,EAAO,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA;AAC9C,MAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AAClB,QAAA,OAAA,CAAQ,WAAA,CAAY,OAAA,EAAS,CAAC,GAAA,KAAQ;AACpC,UAAA,KAAA,MAAW,EAAA,IAAM,GAAA,EAAK,GAAA,CAAI,UAAA,CAAW,EAAE,CAAA;AAAA,QACzC,CAAC,CAAA;AACD,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,KAAA,CAAM,KAAA,EAAM;AAAA,EACd,CAAA,EAAG,CAAC,QAAA,EAAU,OAAA,EAAS,OAAO,CAAC,CAAA;AAE/B,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;ACtCO,SAAS,YAAA,CACd,OAAA,GAA+B,EAAC,EAChC,MAAA,EACoB;AACpB,EAAA,MAAM,EAAE,aAAA,GAAgB,cAAA,EAAe,GAAI,OAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,eAAA,EAAiB,UAAU,CAAA,GAAIhC,QAAAA,CAAmB,EAAE,CAAA;AAC3D,EAAA,MAAM,CAAC,eAAA,EAAiB,UAAU,CAAA,GAAIA,QAAAA,CAAmB,EAAE,CAAA;AAE3D,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,CAAW,GAAA,CAA0B,aAAa,CAAA;AAC7E,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,UAAA,CAAW,EAAE,CAAA;AACb,MAAA,UAAA,CAAW,EAAE,CAAA;AACb,MAAA;AAAA,IACF;AACA,IAAA,UAAA,CAAW,SAAA,CAAU,qBAAqB,CAAA;AAC1C,IAAA,UAAA,CAAW,SAAA,CAAU,yBAAyB,CAAA;AAC9C,IAAA,OAAO,SAAA,CAAU,MAAA,CAAO,EAAA,CAAG,kBAAA,EAAoB,CAAC,QAAA,KAAa;AAC3D,MAAA,UAAA,CAAW,SAAS,QAAQ,CAAA;AAC5B,MAAA,UAAA,CAAW,SAAS,YAAY,CAAA;AAAA,IAClC,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAE5B,EAAA,MAAM,KAAA,GAAQ+B,YAAY,MAAM;AAC9B,IAAA,QAAA,CAAS,UAAA,CAAW,GAAA,CAA0B,aAAa,CAAA,EAAG,cAAA,EAAe;AAAA,EAC/E,CAAA,EAAG,CAAC,QAAA,EAAU,aAAa,CAAC,CAAA;AAE5B,EAAA,OAAO;AAAA,IACL,eAAA;AAAA,IACA,eAAA;AAAA,IACA,KAAA,EAAO,eAAA,CAAgB,MAAA,GAAS,eAAA,CAAgB,MAAA;AAAA,IAChD;AAAA,GACF;AACF;AC5CO,SAAS,gBAAA,CACd,OAAA,GAAmC,EAAC,EACpC,MAAA,EACsB;AACtB,EAAA,MAAM,EAAE,SAAA,GAAY,eAAA,EAAgB,GAAI,OAAA;AACxC,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIhC,SAA+B,IAAI,CAAA;AAE/D,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,CAAW,GAAA,CAA2B,SAAS,CAAA;AAC1E,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,SAAA,CAAU,IAAI,CAAA;AACd,MAAA;AAAA,IACF;AACA,IAAA,SAAA,CAAU,SAAA,CAAU,WAAW,CAAA;AAC/B,IAAA,OAAO,SAAA,CAAU,MAAA,CAAO,EAAA,CAAG,gBAAA,EAAkB,SAAS,CAAA;AAAA,EACxD,CAAA,EAAG,CAAC,QAAA,EAAU,SAAS,CAAC,CAAA;AAExB,EAAA,OAAO,MAAA;AACT;ACbA,SAAS,UAAU,KAAA,EAA0C;AAC3D,EAAA,OAAO,OAAQ,OAAuC,MAAA,KAAW,UAAA;AACnE;AAQO,SAAS,UAAA,CACd,OAAA,GAA6B,EAAC,EAC9B,MAAA,EACkB;AAClB,EAAA,MAAM,EAAE,OAAA,GAAU,OAAA,EAAQ,GAAI,OAAA;AAC9B,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,OAAA,GAAUF,WAAW,cAAc,CAAA;AACzC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,QAAAA,CAAS,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,CAAA;AAErE,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,QAAA,CAAS,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAC3C,MAAA;AAAA,IACF;AACA,IAAA,QAAA,CAAS,EAAE,OAAA,EAAS,OAAA,CAAQ,SAAS,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAC/D,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,EAAA,CAAG,QAAA,EAAU,CAAC,EAAE,OAAA,EAAS,OAAA,EAAQ,KAAM,QAAA,CAAS,EAAE,OAAA,EAAS,OAAA,EAAS,CAAC,CAAA;AAAA,EAC7F,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,IAAA,GAAO+B,YAAY,MAAM,OAAA,EAAS,MAAK,EAAG,CAAC,OAAO,CAAC,CAAA;AACzD,EAAA,MAAM,IAAA,GAAOA,YAAY,MAAM,OAAA,EAAS,MAAK,EAAG,CAAC,OAAO,CAAC,CAAA;AACzD,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,IAAI,SAAA,CAAU,KAAK,CAAA,EAAG,KAAA,CAAM,MAAA,EAAO;AAAA,EACrC,CAAA,EAAG,CAAC,QAAA,EAAU,OAAO,CAAC,CAAA;AAEtB,EAAA,OAAO,EAAE,MAAM,IAAA,EAAM,MAAA,EAAQ,SAAS,KAAA,CAAM,OAAA,EAAS,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ;AAC9E;ACvBO,SAAS,YAAA,CACd,OAAA,GAA+B,EAAC,EAChC,MAAA,EACoB;AACpB,EAAA,MAAM,EAAE,aAAA,GAAgB,cAAA,EAAe,GAAI,OAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,SAAA,GAAYjC,WAAW,gBAAgB,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAUA,WAAW,cAAc,CAAA;AACzC,EAAA,MAAM,EAAE,iBAAiB,eAAA,EAAiB,KAAA,KAAU,YAAA,CAAa,EAAE,aAAA,EAAc,EAAG,QAAQ,CAAA;AAC5F,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIC,SAAS,KAAK,CAAA;AAK9C,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,WAAA,CAAY,KAAK,CAAA;AACjB,MAAA;AAAA,IACF;AACA,IAAA,WAAA,CAAY,UAAU,UAAU,CAAA;AAChC,IAAA,OAAO,SAAA,CAAU,MAAA,CAAO,EAAA,CAAG,QAAA,EAAU,CAAC,EAAE,UAAA,EAAW,KAAM,WAAA,CAAY,UAAU,CAAC,CAAA;AAAA,EAClF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,MAAM,IAAA,GAAO+B,YAAY,MAAM;AAC7B,IAAA,SAAA,EAAW,IAAA,CAAK,iBAAiB,eAAe,CAAA;AAAA,EAClD,CAAA,EAAG,CAAC,SAAA,EAAW,eAAA,EAAiB,eAAe,CAAC,CAAA;AAEhD,EAAA,MAAM,GAAA,GAAMA,YAAY,MAAM;AAC5B,IAAA,SAAA,EAAW,GAAA,CAAI,eAAA,EAAiB,eAAA,EAAiB,OAAA,IAAW,MAAS,CAAA;AAAA,EACvE,GAAG,CAAC,SAAA,EAAW,OAAA,EAAS,eAAA,EAAiB,eAAe,CAAC,CAAA;AAEzD,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,SAAA,EAAW,MAAA,CAAO,eAAA,EAAiB,eAAA,EAAiB,OAAA,IAAW,MAAS,CAAA;AAAA,EAC1E,GAAG,CAAC,SAAA,EAAW,OAAA,EAAS,eAAA,EAAiB,eAAe,CAAC,CAAA;AAEzD,EAAA,MAAM,KAAA,GAAQA,YAAY,MAAM;AAC9B,IAAA,IAAI,CAAC,SAAA,EAAW;AAChB,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,KAAY,SAAA,CAAU,KAAA,CAAM,WAAW,MAAS,CAAA;AACjE,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,CAAW,GAAA,CAA0B,aAAa,CAAA;AAC7E,IAAA,SAAA,EAAW,cAAA,CAAe;AAAA,MACxB,GAAG,QAAQ,GAAA,CAAI,CAAC,QAAQ,EAAE,EAAA,EAAI,IAAA,EAAM,OAAA,EAAiB,CAAE,CAAA;AAAA,MACvD,GAAG,QAAQ,GAAA,CAAI,CAAC,QAAQ,EAAE,EAAA,EAAI,IAAA,EAAM,WAAA,EAAqB,CAAE;AAAA,KAC5D,CAAA;AAAA,EACH,GAAG,CAAC,SAAA,EAAW,OAAA,EAAS,QAAA,EAAU,aAAa,CAAC,CAAA;AAEhD,EAAA,OAAO,EAAE,KAAK,IAAA,EAAM,KAAA,EAAO,QAAQ,QAAA,EAAU,YAAA,EAAc,QAAQ,CAAA,EAAE;AACvE;AClDO,SAAS,OAAA,CACd,OAAA,GAA0B,EAAC,EAC3B,MAAA,EACe;AACf,EAAA,MAAM,EAAE,iBAAA,GAAoB,YAAA,EAAc,WAAA,EAAY,GAAI,OAAA;AAC1D,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIhC,SAAS,KAAK,CAAA;AAE9C,EAAAC,UAAU,MAAM;AACd,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAqB,iBAAiB,CAAA;AACpE,IAAA,IAAI,OAAO,WAAA,CAAY,KAAA,CAAM,UAAA,EAAW,CAAE,SAAS,SAAS,CAAA;AAAA,EAC9D,CAAA,EAAG,CAAC,QAAA,EAAU,iBAAiB,CAAC,CAAA;AAEhC,EAAA,MAAM,OAAA,GAAU+B,WAAAA;AAAA,IACd,CAAC,EAAA,KAAgB;AACf,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAqB,iBAAiB,CAAA;AACpE,MAAA,IAAI,CAAC,KAAA,EAAO;AACZ,MAAA,MAAM,IAAA,GAAwC,EAAE,IAAA,EAAM,EAAA,GAAK,YAAY,OAAA,EAAQ;AAC/E,MAAA,IAAI,EAAA,IAAM,WAAA,EAAa,IAAA,CAAK,WAAA,GAAc,WAAA;AAC1C,MAAA,KAAA,CAAM,WAAW,IAAI,CAAA;AACrB,MAAA,WAAA,CAAY,EAAE,CAAA;AAAA,IAChB,CAAA;AAAA,IACA,CAAC,QAAA,EAAU,iBAAA,EAAmB,WAAW;AAAA,GAC3C;AAEA,EAAA,MAAM,UAAA,GAAaA,WAAAA,CAAY,MAAM,OAAA,CAAQ,CAAC,QAAQ,CAAA,EAAG,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAE5E,EAAA,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,OAAA,EAAQ;AACzC;ACVO,SAAS,QAAA,CACd,OAAA,GAA2B,EAAC,EAC5B,MAAA,EACgB;AAChB,EAAA,MAAM,EAAE,WAAA,GAAc,kBAAA,EAAoB,iBAAA,EAAmB,UAAS,GAAI,OAAA;AAC1E,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,IAAA,EAAM,YAAY,CAAA,GAAIhC,SAAoB,MAAM,CAAA;AACvD,EAAA,MAAM,CAAC,IAAA,EAAM,YAAY,CAAA,GAAIA,SAAoB,OAAO,CAAA;AAExD,EAAA,MAAM,YAAA,GAAegC,WAAAA;AAAA,IACnB,MAAM,QAAA,CAAS,UAAA,CAAW,GAAA,CAA8B,WAAW,CAAA;AAAA,IACnE,CAAC,UAAU,WAAW;AAAA,GACxB;AACA,EAAA,MAAM,aAAA,GAAgBA,WAAAA;AAAA,IACpB,MACE,iBAAA,GAAoB,QAAA,CAAS,MAAA,CAAO,GAAA,CAAqB,iBAAiB,CAAA,GAAI,MAAA;AAAA,IAChF,CAAC,UAAU,iBAAiB;AAAA,GAC9B;AAGA,EAAA,MAAM,IAAA,GAAOA,YAAY,MAA4C;AACnE,IAAA,MAAM,MAAA,GAAS,YAAA,EAAa,IAAK,aAAA,EAAc;AAC/C,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ,IAAK,MAAA;AAAA,MAC3B,IAAA,EAAM,MAAA,EAAQ,eAAA,EAAgB,IAAK;AAAA,KACrC;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,aAAa,CAAC,CAAA;AAEhC,EAAA/B,UAAU,MAAM;AACd,IAAA,MAAM,EAAE,IAAA,EAAM,CAAA,EAAG,IAAA,EAAM,CAAA,KAAM,IAAA,EAAK;AAClC,IAAA,YAAA,CAAa,CAAC,CAAA;AACd,IAAA,YAAA,CAAa,CAAC,CAAA;AAAA,EAChB,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,MAAM,SAAA,GAAY+B,WAAAA;AAAA,IAChB,CAAC,IAAA,KAAoB;AACnB,MAAA,YAAA,EAAa,EAAG,QAAQ,IAAI,CAAA;AAC5B,MAAA,aAAA,EAAc,EAAG,QAAQ,IAAI,CAAA;AAC7B,MAAA,MAAM,EAAE,IAAA,EAAM,CAAA,EAAG,IAAA,EAAM,CAAA,KAAM,IAAA,EAAK;AAClC,MAAA,YAAA,CAAa,CAAC,CAAA;AACd,MAAA,YAAA,CAAa,CAAC,CAAA;AACd,MAAA,QAAA,GAAW,GAAG,CAAC,CAAA;AAAA,IACjB,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,aAAA,EAAe,IAAA,EAAM,QAAQ;AAAA,GAC9C;AAEA,EAAA,MAAM,OAAA,GAAUA,YAAY,CAAC,IAAA,KAAoB,UAAU,IAAI,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAE7E,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,SAAA,CAAU,IAAA,EAAK,CAAE,IAAA,KAAS,MAAA,GAAS,UAAU,MAAM,CAAA;AAAA,EACrD,CAAA,EAAG,CAAC,SAAA,EAAW,IAAI,CAAC,CAAA;AAEpB,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,MAAA,EAAO;AACvC;AC1DO,SAAS,SAAA,CACd,OAAA,EACA,OAAA,GAA4B,IAC5B,MAAA,EACiB;AACjB,EAAA,MAAM,EAAE,OAAA,GAAU,OAAA,EAAS,UAAA,GAAa,IAAG,GAAI,OAAA;AAC/C,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAChC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIhC,QAAAA,CAAS,QAAQ,OAAA,IAAW,IAAA,CAAK,CAAC,CAAA,IAAK,EAAE,CAAA;AACrE,EAAA,MAAM,CAAC,SAAA,EAAW,UAAU,CAAA,GAAIA,SAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,SAAA,GAAYG,OAAgC,IAAI,CAAA;AAEtD,EAAA,MAAM,WAAA,GAAc6B,WAAAA;AAAA,IAClB,CAAC,GAAA,KAAgB;AACf,MAAA,MAAM,OAAA,GAAU,QAAQ,GAAG,CAAA;AAC3B,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAsB,OAAO,CAAA;AAC3D,MAAA,IAAI,CAAC,OAAA,IAAW,CAAC,KAAA,EAAO;AACxB,MAAA,SAAA,CAAU,SAAS,IAAA,IAAO;AAC1B,MAAA,MAAM,WAAW,OAAA,EAAQ;AACzB,MAAA,SAAA,CAAU,OAAA,GAAU,QAAA;AACpB,MAAA,SAAA,CAAU,GAAG,CAAA;AACb,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,OAAA,CAAQ,QAAQ,QAAA,CAAS,KAAA,CAAM,KAAK,CAAC,CAAA,CAClC,KAAK,MAAM;AACV,QAAA,IAAI,SAAA,CAAU,YAAY,QAAA,EAAU;AACpC,QAAA,QAAA,CAAS,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,SAAA,IAAa,UAAU,CAAA;AACxD,QAAA,UAAA,CAAW,KAAK,CAAA;AAAA,MAClB,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,QAAA,IAAI,SAAA,CAAU,OAAA,KAAY,QAAA,EAAU,UAAA,CAAW,KAAK,CAAA;AAAA,MACtD,CAAC,CAAA;AAAA,IACL,CAAA;AAAA,IACA,CAAC,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,UAAU;AAAA,GACzC;AAGA,EAAA,MAAM,OAAA,GAAU7B,OAAO,KAAK,CAAA;AAC5B,EAAA,MAAM,YAAA,GAAe,QAAQ,YAAA,IAAgB,IAAA;AAC7C,EAAAF,UAAU,MAAM;AACd,IAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,CAAC,YAAA,IAAgB,CAAC,MAAA,EAAQ;AACjD,IAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA,EAAG;AACnC,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,IAAA,WAAA,CAAY,MAAM,CAAA;AAAA,EACpB,GAAG,CAAC,QAAA,EAAU,SAAS,MAAA,EAAQ,WAAA,EAAa,YAAY,CAAC,CAAA;AAEzD,EAAA,MAAM,aAAA,GACJ,OAAA,CAAQ,MAAA,IAAU,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AAE9D,EAAA,OAAO,EAAE,MAAA,EAAQ,aAAA,EAAe,WAAA,EAAa,SAAA,EAAU;AACzD;ACnEO,SAAS,aAAA,CACd,YAAA,EACA,OAAA,GAAgC,IAChC,MAAA,EACqB;AACrB,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA;AACrC,EAAA,MAAM,CAAC,IAAA,EAAM,YAAY,CAAA,GAAID,QAAAA,CAAS,QAAQ,OAAA,IAAW,IAAA,CAAK,CAAC,CAAA,IAAK,EAAE,CAAA;AACtE,EAAA,MAAM,OAAA,GAAUG,OAAO,IAAI,CAAA;AAC3B,EAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAElB,EAAA,MAAM,OAAA,GAAU6B,WAAAA;AAAA,IACd,CAAC,IAAA,KAAiB;AAChB,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,EAAE,KAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG;AACpD,QAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,CAAW,GAAA,CAAI,EAAE,CAAA;AAC5C,QAAA,IAAI,CAAC,SAAA,EAAW;AAChB,QAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,SAAA,CAAU,MAAA,EAAO;AAAA,uBACpB,OAAA,EAAQ;AAAA,MACzB;AACA,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,IACnB,CAAA;AAAA,IACA,CAAC,UAAU,YAAY;AAAA,GACzB;AAGA,EAAA/B,UAAU,MAAM;AACd,IAAA,OAAA,CAAQ,QAAQ,OAAO,CAAA;AAAA,EAIzB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,IAAU,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AAEhF,EAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAQ;AACtC;ACtDO,IAAM,kBAAA,GAA8C;AAAA,EACzD,UAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF;AAGO,IAAM,wBAAA,GAAmD;AAAA,EAC9D,QAAA,EAAU,UAAA;AAAA,EACV,IAAA,EAAM,YAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,OAAA,EAAS,SAAA;AAAA,EACT,MAAA,EAAQ,QAAA;AAAA,EACR,SAAA,EAAW,WAAA;AAAA,EACX,aAAA,EAAe,eAAA;AAAA,EACf,iBAAA,EAAmB,mBAAA;AAAA,EACnB,aAAA,EAAe,eAAA;AAAA,EACf,MAAA,EAAQ;AACV;AAwCO,SAAS,WAAA,CACd,OAAA,GAA8B,EAAC,EAC/B,MAAA,EACmB;AACnB,EAAA,MAAM,EAAE,OAAA,GAAU,OAAA,EAAS,SAAS,KAAA,GAAQ,kBAAA,EAAoB,QAAO,GAAI,OAAA;AAC3E,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,UAAU,gBAAgB,CAAA,GAAID,SAAiB,OAAA,IAAW,KAAA,CAAM,CAAC,CAAA,IAAK,UAAU,CAAA;AAKvF,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,OAAA,EAAS;AACb,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAgB,OAAO,CAAA;AACrD,IAAA,MAAM,UAAU,KAAA,EAAO,YAAA;AACvB,IAAA,MAAM,QAAQ,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,GAAY,QAAgC,KAAA,GAAQ,MAAA;AAChG,IAAA,MAAM,WACJ,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,GAAY,MAAgC,QAAA,GAAW,MAAA;AACnF,IAAA,IAAI,QAAA,mBAA2B,QAAQ,CAAA;AAAA,EACzC,CAAA,EAAG,CAAC,QAAA,EAAU,OAAA,EAAS,OAAO,CAAC,CAAA;AAE/B,EAAA,MAAM,WAAA,GAAc+B,WAAAA;AAAA,IAClB,CAAC,IAAA,KAAiB;AAChB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAgB,OAAO,CAAA;AACrD,MAAA,IAAI,CAAC,KAAA,EAAO;AAGZ,MAAA,MAAM,SAAA,GAAY,MAAM,YAAA,EAAc,KAAA;AACtC,MAAA,MAAM,YAAa,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,GAAW,YAAY,EAAC;AAC7E,MAAA,MAAM,KAAA,GAA0B,EAAE,GAAG,SAAA,EAAW,UAAU,IAAA,EAAqB;AAC/E,MAAA,KAAA,CAAM,eAAA,CAAgB,EAAE,KAAA,EAAO,CAAA;AAC/B,MAAA,gBAAA,CAAiB,IAAI,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,CAAC,UAAU,OAAO;AAAA,GACpB;AAEA,EAAA,MAAM,eAAA,GACJ,MAAA,IAAU,MAAA,CAAO,WAAA,CAAY,MAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,GAAG,wBAAA,CAAyB,CAAC,CAAA,IAAK,CAAC,CAAC,CAAC,CAAA;AAEtF,EAAA,OAAO,EAAE,QAAA,EAAU,eAAA,EAAiB,WAAA,EAAY;AAClD;AC3GA,IAAM,gBAAA,GAAmB,CAAC,KAAA,EAAO,WAAW,CAAA;AAwBrC,SAAS,OAAA,CACd,OAAA,GAA0B,EAAC,EAC3B,MAAA,EACe;AACf,EAAA,MAAM,EAAE,YAAA,GAAe,gBAAA,EAAkB,aAAA,GAAgB,OAAM,GAAI,OAAA;AACnE,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIhC,SAAS,aAAa,CAAA;AAElD,EAAA,MAAM,OAAA,GAAUgC,WAAAA;AAAA,IACd,CAAC,IAAA,KAAkB;AACjB,MAAA,KAAA,MAAW,MAAM,YAAA,EAAc;AAC7B,QAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,CAAW,GAAA,CAAI,EAAE,CAAA;AAC5C,QAAA,IAAI,CAAC,SAAA,EAAW;AAChB,QAAA,IAAI,IAAA,YAAgB,OAAA,EAAQ;AAAA,uBACb,MAAA,EAAO;AAAA,MACxB;AACA,MAAA,SAAA,CAAU,IAAI,CAAA;AAAA,IAChB,CAAA;AAAA,IACA,CAAC,UAAU,YAAY;AAAA,GACzB;AAEA,EAAA,MAAM,UAAA,GAAaA,WAAAA,CAAY,MAAM,OAAA,CAAQ,CAAC,MAAM,CAAA,EAAG,CAAC,OAAA,EAAS,MAAM,CAAC,CAAA;AAExE,EAAA,OAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAQ;AACvC;ACvCO,SAAS,OAAA,GAA4B;AAC1C,EAAA,MAAM,GAAA,GAAMjC,WAAW,WAAW,CAAA;AAClC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,GAAA;AACT;ACSO,SAAS,cAAA,GAAuC;AACrD,EAAA,MAAM,OAAA,GAAUA,WAAW,cAAc,CAAA;AAKzC,EAAA,MAAM,GAAA,GAAMI,OAAO,OAAO,CAAA;AAC1B,EAAA,GAAA,CAAI,OAAA,GAAU,OAAA;AAEd,EAAA,MAAM,IAAA,GAAO6B,WAAAA,CAAY,CAAC,EAAA,EAAe,KAAA,KAAwB;AAC/D,IAAA,GAAA,CAAI,OAAA,EAAS,KAAK,EAAE,GAAA,EAAK,CAAC,EAAE,CAAA,EAAG,OAAO,CAAA;AAAA,EACxC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,YAAA,GAAeA,WAAAA;AAAA,IACnB,CAAC,SAAoB,IAAA,CAAK,EAAE,MAAM,SAAA,EAAW,IAAA,IAAQ,UAAU,CAAA;AAAA,IAC/D,CAAC,IAAI;AAAA,GACP;AACA,EAAA,MAAM,YAAA,GAAeA,WAAAA;AAAA,IACnB,CAAC,SAAoB,IAAA,CAAK,EAAE,MAAM,SAAA,EAAW,IAAA,IAAQ,SAAS,CAAA;AAAA,IAC9D,CAAC,IAAI;AAAA,GACP;AACA,EAAA,MAAM,OAAA,GAAUA,WAAAA;AAAA,IACd,CAAC,OAAA,KAA2B;AAC1B,MAAA,MAAM,KACJ,OAAA,CAAQ,IAAA,KAAS,SACb,EAAE,IAAA,EAAM,cAAc,IAAA,EAAM,OAAA,CAAQ,MAAM,KAAA,EAAO,OAAA,CAAQ,OAAM,GAC/D,EAAE,MAAM,YAAA,EAAc,IAAA,EAAM,QAAQ,IAAA,EAAK;AAC/C,MAAA,IAAA,CAAK,IAAI,QAAQ,CAAA;AAAA,IACnB,CAAA;AAAA,IACA,CAAC,IAAI;AAAA,GACP;AAEA,EAAA,OAAO,EAAE,YAAA,EAAc,YAAA,EAAc,OAAA,EAAQ;AAC/C;ACPA,SAAS,YAAY,IAAA,EAAuC;AAC1D,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,SAAiB,EAAC;AAC/C,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,IAA+B,CAAA,EAAG;AACpE,IAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM,MAAA,EAAW;AACnC,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,OAAO,CAAA,KAAM,WAAW,CAAA,GAAI,OAAO,CAAA,KAAM,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AAAA,EAC3F;AACA,EAAA,OAAO,GAAA;AACT;AAaO,SAAS,eAAA,CACd,OAAA,GAAkC,EAAC,EACnC,MAAA,EAC2B;AAC3B,EAAA,MAAM,EAAE,OAAA,GAAU,OAAA,EAAS,YAAY,eAAA,EAAiB,WAAA,GAAc,OAAM,GAAI,OAAA;AAChF,EAAA,MAAM,QAAA,GAAW,kBAAkB,MAAM,CAAA;AACzC,EAAA,MAAM,OAAA,GAAUjC,WAAW,cAAc,CAAA;AACzC,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,EAAE,SAAA,IAAa,MAAM,CAAA;AACrD,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,GAAA,CAAsB,OAAO,CAAA;AAC3D,EAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AACrB,EAAA,IAAI,CAAC,KAAA,IAAS,CAAC,KAAA,EAAO,OAAO,IAAA;AAE7B,EAAA,IAAI,MAAA,CAAO,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAA;AACpC,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,IAAA,MAAM,KAAA,GAAS,KAAA,CAAM,gBAAA,CAAiB,IAAI,EAAE,SAAA,IAAoC,EAAA;AAEhF,IAAA,IAAI,WAAA,EAAa;AAGf,MAAA,MAAMkC,KAAAA,GAAQ,KAAK,IAAA,IAA+B,KAAA;AAClD,MAAA,MAAMC,UAAS,CAAC,EAAE,IAAA,EAAM,QAAA,EAAU,MAAK,KAAoC;AACzE,QAAA,MAAM,QAAQ,QAAA,IAAY,EAAA;AAC1B,QAAA,MAAM,KAAA,GAAS,IAAA,CAAK,KAAA,IAAS,EAAC;AAC9B,QAAA,MAAM,KAAA,GAA4B,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,SAAA,EAAW,KAAA,EAAM,EAAG,IAAA,EAAK;AAC7F,QAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,WAAA,EAAa,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAC,CAAA;AAAA,aAClF,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAA;AAAA,MACxC,CAAA;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,EAAA,EAAI,MAAA,CAAO,IAAI,KAAA,EAAO,EAAA,EAAI,IAAA,EAAAD,KAAAA,EAAM,MAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA,EAAG,QAAAC,OAAAA,EAAO;AAAA,IAC9F;AAEA,IAAA,MAAMA,UAAS,CAAC,EAAE,KAAA,EAAO,SAAA,EAAW,MAAK,KAAoC;AAC3E,MAAA,MAAM,KAAA,GAAS,IAAA,CAAK,KAAA,IAAS,EAAC;AAC9B,MAAA,MAAM,KAAA,GAA4B,EAAE,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,SAAA,EAAW,SAAA,EAAU,EAAG,IAAA,EAAK;AACpF,MAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,WAAA,EAAa,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAC,CAAA;AAAA,WAClF,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAA;AAAA,IACxC,CAAA;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,KAAA,EAAO,IAAA,EAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA,EAAG,QAAAA,OAAAA,EAAO;AAAA,EACpF;AAEA,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAA;AACpC,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAIlB,EAAA,MAAM,SAAA,GAAa,KAAA,CAAM,gBAAA,CAAiB,IAAI,EAAE,SAAA,IAAoC,EAAA;AACpF,EAAA,MAAM,IAAA,GAAQ,IAAA,CAAK,IAAA,KAAgC,WAAA,GAAc,SAAA,GAAY,EAAA,CAAA;AAC7E,EAAA,MAAM,SAAS,CAAC,EAAE,IAAA,EAAM,QAAA,EAAU,MAAK,KAAoC;AACzE,IAAA,MAAM,QAAQ,QAAA,IAAY,EAAA;AAC1B,IAAA,MAAM,KAAA,GAA4B,EAAE,IAAA,EAAK;AACzC,IAAA,IAAI,QAAA,KAAa,MAAA,EAAW,KAAA,CAAM,IAAA,GAAO,KAAA;AACzC,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAM,KAAA,GAAS,IAAA,CAAK,KAAA,IAAS,EAAC;AAC9B,MAAA,KAAA,CAAM,KAAA,GAAQ,EAAE,GAAG,KAAA,EAAO,WAAW,KAAA,EAAM;AAAA,IAC7C;AACA,IAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,WAAA,EAAa,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAC,CAAA;AAAA,SAClF,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,KAAK,CAAA;AAAA,EACxC,CAAA;AACA,EAAA,MAAM,UAAU,MAAY;AAC1B,IAAA,MAAM,OAA2B,EAAE,MAAA,EAAQ,KAAK,MAAA,EAAQ,MAAA,EAAQ,KAAK,MAAA,EAAO;AAC5E,IAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,WAAA,CAAY,cAAA,EAAgB,CAAC,GAAA,KAAQ,GAAA,CAAI,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,IAAI,CAAC,CAAA;AAAA,SACpF,KAAA,CAAM,UAAA,CAAW,MAAA,CAAO,EAAA,EAAI,IAAI,CAAA;AAAA,EACvC,CAAA;AACA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA;AAAA,IACN,IAAI,MAAA,CAAO,EAAA;AAAA,IACX,KAAA,EAAO,EAAA;AAAA,IACP,IAAA;AAAA,IACA,IAAA,EAAM,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA;AAAA,IAC3B,MAAA;AAAA,IACA;AAAA,GACF;AACF;ACpGO,SAAS,cAAA,GAA6C;AAC3D,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIlC,SAAqC,IAAI,CAAA;AAEjE,EAAA,MAAM,QAAQgC,WAAAA,CAAY,MAAM,QAAQ,IAAI,CAAA,EAAG,EAAE,CAAA;AACjD,EAAA,MAAM,IAAA,GAAOA,WAAAA,CAAY,CAAC,CAAA,EAAW,GAAW,KAAA,KAAa;AAC3D,IAAA,OAAA,CAAQ,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA/B,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,KAA4B;AACzC,MAAA,IAAI,EAAA,CAAG,GAAA,KAAQ,QAAA,EAAU,KAAA,EAAM;AAAA,IACjC,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,eAAe,KAAK,CAAA;AAC5C,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,KAAK,CAAA;AACxC,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,eAAe,KAAK,CAAA;AAC/C,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,KAAK,CAAA;AAAA,IAC7C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,KAAK,CAAC,CAAA;AAEhB,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,EAAM;AAC7B;AClDA,SAAS,QAAA,CAAS,UAAyB,MAAA,EAA+B;AACxE,EAAA,MAAM,CAAC,QAAA,EAAU,UAAU,CAAA,GAAI,QAAA,CAAS,MAAM,GAAG,CAAA;AAIjD,EAAA,MAAM,QAAuB,EAAE,QAAA,EAAU,YAAY,CAAC,QAAQ,GAAG,MAAA,EAAO;AACxE,EAAA,IAAI,eAAe,QAAA,EAAU;AAC3B,IAAA,KAAA,CAAM,IAAA,GAAO,KAAA;AACb,IAAA,KAAA,CAAM,SAAA,GAAY,kBAAA;AAAA,EACpB,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,UAAU,CAAA,GAAI,MAAA;AAAA,EACtB;AACA,EAAA,OAAO,KAAA;AACT;AAkBO,SAAS,KAAA,CAAM;AAAA,EACpB,QAAA,GAAW,UAAA;AAAA,EACX,WAAA,GAAc,UAAA;AAAA,EACd,MAAA,GAAS,CAAA;AAAA,EACT,GAAA,GAAM,CAAA;AAAA,EACN,MAAA,GAAS,CAAA;AAAA,EACT,SAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAAe;AACb,EAAA,uBACEC,GAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,GAAG,QAAA,CAAS,QAAA,EAAU,MAAM,CAAA,EAAG,MAAA,EAAQ,aAAA,EAAe,MAAA,IAClE,QAAA,kBAAAA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,MAAA;AAAA,QACT,aAAA,EAAe,WAAA,KAAgB,UAAA,GAAa,QAAA,GAAW,KAAA;AAAA,QACvD,GAAA;AAAA,QACA,aAAA,EAAe,MAAA;AAAA,QACf,GAAG;AAAA,OACL;AAAA,MAEC;AAAA;AAAA,GACH,EACF,CAAA;AAEJ;AC1CO,SAAS,WAAW,EAAE,KAAA,EAAO,MAAM,aAAA,GAAgB,CAAA,EAAG,UAAS,EAAoB;AACxF,EAAA,IAAI,KAAA,IAAS,IAAA,IAAQ,KAAA,KAAU,EAAA,EAAI,OAAO,QAAA;AAC1C,EAAA,uBACEA,GAAAA,CAAC,eAAA,EAAA,EAAgB,aAAA,EACf,+BAAC,OAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAA,GAAAA,CAAC,cAAA,EAAA,EAAe,OAAA,EAAO,IAAA,EAAE,QAAA,EAAS,CAAA;AAAA,oBAClCA,IAAC,cAAA,EAAA,EAAe,IAAA,EAAY,OAAO,EAAE,eAAA,EAAiB,sBAAA,EAAuB,EAC1E,QAAA,EAAA,KAAA,EACH;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;ACpBO,SAAS,aAAA,CAAc;AAAA,EAC5B,IAAA,EAAM,IAAA;AAAA,EACN,OAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,EAAuB;AACrB,EAAA,uBACEA,GAAAA,CAAC,UAAA,EAAA,EAAW,OAAO,KAAA,EAAO,IAAA,EAAM,aAC9B,QAAA,kBAAAA,GAAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,SAAS,SAAA,GAAY,OAAA;AAAA,MAC9B,IAAA,EAAK,MAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MACZ,QAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MAEA,QAAA,kBAAAA,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,GAClB,EACF,CAAA;AAEJ;ACSO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc,OAAA;AAAA,EACd,SAAA,GAAY,IAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA,EACX,SAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAIF,QAAAA,CAAS,QAAA,EAAU,SAAS,EAAE,CAAA;AACxD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,IAAIA,QAAAA,CAAS,QAAA,EAAU,QAAQ,EAAE,CAAA;AACrD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIA,QAAAA;AAAA,IAAgB,MACtC,MAAA,CAAO,OAAA,CAAQ,QAAA,EAAU,IAAA,IAAQ,EAAE,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,CAAC,OAAO,EAAE,CAAA,EAAG,GAAE,CAAE;AAAA,GACjE;AAEA,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,EAAW,KAAA,KACzB,QAAQ,CAAC,EAAA,KAAO,GAAG,GAAA,CAAI,CAAC,GAAG,CAAA,KAAO,CAAA,KAAM,IAAI,EAAE,GAAG,GAAG,GAAG,KAAA,EAAM,GAAI,CAAE,CAAC,CAAA;AACtE,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAoB,OAAA,CAAQ,CAAC,EAAA,KAAO,EAAA,CAAG,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,KAAM,CAAC,CAAC,CAAA;AACnF,EAAA,MAAM,MAAA,GAAS,MAAY,OAAA,CAAQ,CAAC,OAAO,CAAC,GAAG,EAAA,EAAI,EAAE,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,CAAC,CAAA;AAEpE,EAAA,MAAM,QAAQ,MAAY;AACxB,IAAA,MAAM,OAA+B,EAAC;AACtC,IAAA,KAAA,MAAW,EAAE,CAAA,EAAG,CAAA,EAAE,IAAK,IAAA,EAAM;AAC3B,MAAA,MAAM,GAAA,GAAM,EAAE,IAAA,EAAK;AACnB,MAAA,IAAI,GAAA,EAAK,IAAA,CAAK,GAAG,CAAA,GAAI,CAAA;AAAA,IACvB;AACA,IAAA,QAAA,CAAS,QAAA,GAAW,EAAE,KAAA,EAAO,IAAA,EAAM,MAAK,GAAI,EAAE,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,EAC7D,CAAA;AAEA,EAAA,uBACEmC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,OAAO,SAAA,EAC/B,QAAA,EAAA;AAAA,IAAA,KAAA,oBAASjC,GAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,YAAa,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IAExC,SAAA,oBACCiC,IAAAA,CAAC,OAAA,EAAA,EAAM,OAAO,UAAA,EACZ,QAAA,EAAA;AAAA,sBAAAjC,GAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,YAAA,EAAc,QAAA,EAAA,OAAA,EAAK,CAAA;AAAA,sBAChCA,GAAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,UAAA;AAAA,UACP,KAAA,EAAO,KAAA;AAAA,UACP,WAAA,EAAY,YAAA;AAAA,UACZ,UAAU,CAAC,CAAA,KAAqC,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK;AAAA;AAAA;AACzE,KAAA,EACF,CAAA;AAAA,IAGD,QAAA,oBACCiC,IAAAA,CAAC,OAAA,EAAA,EAAM,OAAO,UAAA,EACZ,QAAA,EAAA;AAAA,sBAAAjC,GAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,YAAA,EAAc,QAAA,EAAA,MAAA,EAAI,CAAA;AAAA,sBAC/BA,GAAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,UAAA;AAAA,UACP,KAAA,EAAO,IAAA;AAAA,UACP,WAAA,EAAY,UAAA;AAAA,UACZ,UAAU,CAAC,CAAA,KAAqC,OAAA,CAAQ,CAAA,CAAE,OAAO,KAAK;AAAA;AAAA;AACxE,KAAA,EACF,CAAA;AAAA,oBAGFiC,IAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,UAAA,EACV,QAAA,EAAA;AAAA,sBAAAjC,GAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,YAAA,EAAc,QAAA,EAAA,YAAA,EAAU,CAAA;AAAA,MACpC,IAAA,CAAK,WAAW,CAAA,oBAAKA,IAAC,MAAA,EAAA,EAAK,KAAA,EAAO,YAAY,QAAA,EAAA,oBAAA,EAAkB,CAAA;AAAA,MAChE,IAAA,CAAK,IAAI,CAAC,GAAA,EAAK,sBACdiC,IAAAA,CAAC,KAAA,EAAA,EAAY,KAAA,EAAO,QAAA,EAClB,QAAA,EAAA;AAAA,wBAAAjC,GAAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,UAAA;AAAA,YACP,OAAO,GAAA,CAAI,CAAA;AAAA,YACX,WAAA,EAAY,KAAA;AAAA,YACZ,QAAA,EAAU,CAAC,CAAA,KAAqC,MAAA,CAAO,CAAA,EAAG,EAAE,CAAA,EAAG,CAAA,CAAE,MAAA,CAAO,KAAA,EAAO;AAAA;AAAA,SACjF;AAAA,wBACAA,GAAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO,UAAA;AAAA,YACP,OAAO,GAAA,CAAI,CAAA;AAAA,YACX,WAAA,EAAY,OAAA;AAAA,YACZ,QAAA,EAAU,CAAC,CAAA,KAAqC,MAAA,CAAO,CAAA,EAAG,EAAE,CAAA,EAAG,CAAA,CAAE,MAAA,CAAO,KAAA,EAAO;AAAA;AAAA,SACjF;AAAA,wBACAA,GAAAA;AAAA,UAACkC,MAAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,OAAA;AAAA,YACR,IAAA,EAAK,MAAA;AAAA,YACL,YAAA,EAAW,cAAA;AAAA,YACX,OAAA,EAAS,MAAM,SAAA,CAAU,CAAC,CAAA;AAAA,YAC3B,QAAA,EAAA;AAAA;AAAA;AAED,OAAA,EAAA,EApBQ,CAqBV,CACD,CAAA;AAAA,sBACDlC,GAAAA,CAAC,KAAA,EAAA,EACC,QAAA,kBAAAA,IAACkC,MAAAA,EAAA,EAAO,OAAA,EAAQ,SAAA,EAAU,IAAA,EAAK,IAAA,EAAK,OAAA,EAAS,MAAA,EAAQ,uBAErD,CAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,oBAEAD,IAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO;AAAA,UACL,OAAA,EAAS,MAAA;AAAA,UACT,cAAA,EAAgB,YAAY,eAAA,GAAkB,UAAA;AAAA,UAC9C,UAAA,EAAY;AAAA,SACd;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,SAAA,oBACCjC,GAAAA,CAACkC,MAAAA,EAAA,EAAO,OAAA,EAAQ,WAAU,IAAA,EAAK,IAAA,EAAK,OAAA,EAAS,SAAA,EAAW,QAAA,EAAA,mBAAA,EAExD,CAAA;AAAA,0BAEFlC,GAAAA,CAACkC,MAAAA,EAAA,EAAO,OAAA,EAAS,OAAQ,QAAA,EAAA,WAAA,EAAY;AAAA;AAAA;AAAA;AACvC,GAAA,EACF,CAAA;AAEJ;AAEA,IAAM,SAAA,GAA2B;AAAA,EAC/B,OAAA,EAAS,MAAA;AAAA,EACT,aAAA,EAAe,QAAA;AAAA,EACf,GAAA,EAAK,EAAA;AAAA,EACL,OAAA,EAAS,EAAA;AAAA,EACT,QAAA,EAAU,GAAA;AAAA,EACV,UAAA,EAAY,sBAAA;AAAA,EACZ,KAAA,EAAO,iCAAA;AAAA,EACP,MAAA,EAAQ,+BAAA;AAAA,EACR,YAAA,EAAc,CAAA;AAAA,EACd,SAAA,EAAW;AACb,CAAA;AACA,IAAM,aAA4B,EAAE,QAAA,EAAU,IAAI,UAAA,EAAY,GAAA,EAAK,SAAS,IAAA,EAAK;AACjF,IAAM,aAA4B,EAAE,OAAA,EAAS,QAAQ,aAAA,EAAe,QAAA,EAAU,KAAK,CAAA,EAAE;AACrF,IAAM,eAA8B,EAAE,QAAA,EAAU,IAAI,UAAA,EAAY,GAAA,EAAK,SAAS,GAAA,EAAI;AAClF,IAAM,WAA0B,EAAE,OAAA,EAAS,QAAQ,GAAA,EAAK,CAAA,EAAG,YAAY,QAAA,EAAS;AAChF,IAAM,UAAA,GAA4B,EAAE,QAAA,EAAU,EAAA,EAAI,SAAS,GAAA,EAAI;AAC/D,IAAM,UAAA,GAA4B;AAAA,EAChC,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO,MAAA;AAAA,EACP,MAAA,EAAQ,EAAA;AAAA,EACR,OAAA,EAAS,OAAA;AAAA,EACT,QAAA,EAAU,EAAA;AAAA,EACV,KAAA,EAAO,yBAAA;AAAA,EACP,UAAA,EAAY,yBAAA;AAAA,EACZ,MAAA,EAAQ,+BAAA;AAAA,EACR,YAAA,EAAc,CAAA;AAAA,EACd,OAAA,EAAS;AACX,CAAA;AC1JO,SAAS,YAAA,CAAa;AAAA,EAC3B,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,GAAQ,OAAA;AAAA,EACR,OAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,UAAA,GAAa,QAAQ,KAAK,CAAA;AAChC,EAAA,uBACED,KAAC,YAAA,EAAA,EAIC,QAAA,EAAA;AAAA,oBAAAjC,GAAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAO,OAAA,IAAW,KAAA,EAAO,IAAA,EAAM,WAAA,EACzC,QAAA,kBAAAA,GAAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,IAAA,EAK1B,QAAA,kBAAAA,GAAAA;AAAA,MAACkC,MAAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,SAAA;AAAA,QACR,IAAA,EAAK,IAAA;AAAA,QACL,SAAA,EAAW,CAAC,wBAAA,EAA0B,SAAS,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,QAEzE,QAAA,kBAAAD,IAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,CAAA,EAAE,EAC1D,QAAA,EAAA;AAAA,UAAA,UAAA,oBAAcjC,GAAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,UACpC,KAAA;AAAA,UAAM,IAAA;AAAA,UAAG,OAAA,CAAQ,KAAK,CAAA,IAAK;AAAA,SAAA,EAC9B;AAAA;AAAA,OAEJ,CAAA,EACF,CAAA;AAAA,oBAIAiC,KAAC,mBAAA,EAAA,EAAoB,KAAA,EAAc,OAAO,EAAE,eAAA,EAAiB,wBAAuB,EAClF,QAAA,EAAA;AAAA,sBAAAjC,GAAAA,CAAC,qBAAmB,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBAC1BA,GAAAA,CAAC,sBAAA,EAAA,EAAuB,KAAA,EAAc,aAAA,EAAe,QAAA,EAClD,QAAA,EAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,KAAQ;AACjC,QAAA,MAAM,IAAA,GAAO,QAAQ,GAAG,CAAA;AACxB,QAAA,uBACEA,GAAAA,CAAC,qBAAA,EAAA,EAAgC,KAAA,EAAO,GAAA,EACtC,0BAAAiC,IAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,GAAE,EAC1D,QAAA,EAAA;AAAA,UAAA,IAAA,oBAAQjC,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,UACxB,OAAA,CAAQ,GAAG,CAAA,IAAK;AAAA,SAAA,EACnB,KAJ0B,GAK5B,CAAA;AAAA,MAEJ,CAAC,CAAA,EACH;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;AChEO,SAAS,YAAA,CAAa;AAAA,EAC3B,MAAA;AAAA,EACA,UAAA,EAAY,UAAA;AAAA,EACZ,WAAA,EAAa,WAAA;AAAA,EACb,SAAA,GAAY,KAAA;AAAA,EACZ,WAAA,GAAc,YAAA;AAAA,EACd,SAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ,GAAI,QAAQ,MAAM,CAAA;AAChD,EAAA,MAAM,aAAA,GAAgB,SAAA,IAAa,IAAA,GAAO,SAAA,GAAY,SAAA,GAAY,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,GAAG,CAAC,CAAA,CAAA,CAAA,GAAM,MAAA;AACjG,EAAA,MAAM,SAAA,mBACJA,GAAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,SAAA,EAAU,IAAA,EAAM,WAAA,EAChC,QAAA,kBAAAA,GAAAA,CAACkC,MAAAA,EAAA,EAAO,OAAA,EAAQ,OAAA,EAAQ,IAAA,EAAK,MAAA,EAAO,YAAA,EAAW,SAAA,EAAU,OAAA,EAAS,MAAM,MAAA,EAAO,EAC7E,QAAA,kBAAAlC,GAAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAM,EAAA,EAAI,CAAA,EACxB,CAAA,EACF,CAAA;AAEF,EAAA,MAAM,UAAA,mBACJA,GAAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,UAAA,EAAW,IAAA,EAAM,WAAA,EACjC,QAAA,kBAAAA,GAAAA,CAACkC,MAAAA,EAAA,EAAO,OAAA,EAAQ,OAAA,EAAQ,IAAA,EAAK,MAAA,EAAO,YAAA,EAAW,UAAA,EAAW,OAAA,EAAS,MAAM,OAAA,EAAQ,EAC/E,QAAA,kBAAAlC,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI,CAAA,EACzB,CAAA,EACF,CAAA;AAEF,EAAA,MAAM,KAAA,GACJ,aAAA,IAAiB,IAAA,mBACfA,GAAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL,QAAA,EAAU,EAAA;AAAA,QACV,kBAAA,EAAoB,cAAA;AAAA,QACpB,OAAA,EAAS,GAAA;AAAA,QACT,SAAA,EAAW,QAAA;AAAA,QACX,QAAA,EAAU;AAAA,OACZ;AAAA,MAEC,QAAA,EAAA;AAAA;AAAA,GACH,GACE,IAAA;AAEN,EAAA,uBACEA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,MAAA;AAAA,QACT,aAAA,EAAe,WAAA,KAAgB,UAAA,GAAa,QAAA,GAAW,KAAA;AAAA,QACvD,UAAA,EAAY,QAAA;AAAA,QACZ,GAAA,EAAK;AAAA,OACP;AAAA,MAGC,QAAA,EAAA,WAAA,KAAgB,YAAA,mBACfiC,IAAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,QAAA,UAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OAAA,EACH,CAAA,mBAEAA,IAAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,QAAA,SAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA,OAAA,EACH;AAAA;AAAA,GAEJ;AAEJ;AClFO,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA,EAAY,UAAA;AAAA,EACZ,YAAA,EAAc,YAAA;AAAA,EACd,WAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,IAAA,GAAO,SAAS,UAAA,GAAa,YAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,SAAS,aAAA,GAAgB,WAAA;AACvC,EAAA,uBACEjC,GAAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAc,IAAA,EAAM,aAC9B,QAAA,kBAAAA,GAAAA;AAAA,IAACkC,MAAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,SAAS,SAAA,GAAY,OAAA;AAAA,MAC9B,IAAA,EAAK,MAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MACZ,OAAA,EAAS,QAAA;AAAA,MACT,SAAA;AAAA,MAEA,QAAA,kBAAAlC,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,GAClB,EACF,CAAA;AAEJ;ACjBO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA,EAAM,IAAA;AAAA,EACN,MAAA;AAAA,EACA,OAAA,GAAU,OAAA;AAAA,EACV,KAAA,GAAQ,OAAA;AAAA,EACR,WAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,CAAc,SAAS,MAAM,CAAA;AAC/C,EAAA,uBACEA,GAAAA,CAAC,UAAA,EAAA,EAAW,OAAc,IAAA,EAAM,WAAA,EAC9B,0BAAAiC,IAAAA,CAACC,MAAAA,EAAA,EAAO,OAAA,EAAQ,WAAU,IAAA,EAAK,IAAA,EAAK,SAAS,MAAM,KAAA,IAAS,SAAA,EACzD,QAAA,EAAA;AAAA,IAAA,IAAA,mBAAOlC,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,IAAI,CAAA,GAAK,IAAA;AAAA,IAC5B;AAAA,GAAA,EACH,CAAA,EACF,CAAA;AAEJ;AChBO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,IAAA,EAAM,IAAA;AAAA,EACN,MAAA;AAAA,EACA,OAAA,GAAU,OAAA;AAAA,EACV,KAAA,GAAQ,gBAAA;AAAA,EACR,WAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,aAAA,CAAc,SAAS,MAAM,CAAA;AACpD,EAAA,uBACEA,GAAAA,CAAC,UAAA,EAAA,EAAW,OAAO,KAAA,EAAO,IAAA,EAAM,aAC9B,QAAA,kBAAAA,GAAAA;AAAA,IAACkC,MAAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,OAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,YAAA,EAAY,KAAA;AAAA,MACZ,OAAA,EAAS,MAAM,UAAA,EAAW;AAAA,MAC1B,SAAA;AAAA,MAEA,QAAA,kBAAAlC,GAAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,GAClB,EACF,CAAA;AAEJ;AClCA,IAAM,eAAA,GAAkB,CAAC,EAAA,EAAI,EAAA,EAAI,EAAA,EAAI,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AA4C1D,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,eAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,QAAA,GAAW,kBAAA;AAAA,EACX,KAAA,GAAQ,YAAA;AAAA,EACR,WAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAQ,GAAI,QAAQ,MAAM,CAAA;AACxC,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,aAAA,CAAc,SAAS,MAAM,CAAA;AACpD,EAAA,MAAM,aAAa,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,GAAG,CAAC,CAAA;AAEhD,EAAA,uBACEiC,IAAAA,CAACE,YAAAA,EAAA,EAEC,QAAA,EAAA;AAAA,oBAAAnC,GAAAA,CAAC,cAAW,KAAA,EAAO,KAAA,EAAO,MAAM,WAAA,EAC9B,QAAA,kBAAAA,GAAAA,CAACoC,mBAAAA,EAAA,EAAoB,OAAA,EAAO,MAC1B,QAAA,kBAAAH,IAAAA,CAACC,QAAA,EAAO,OAAA,EAAQ,WAAU,IAAA,EAAK,IAAA,EAAK,YAAA,EAAY,KAAA,EAAO,SAAA,EACpD,QAAA,EAAA;AAAA,MAAA,UAAA;AAAA,MAAW;AAAA,KAAA,EACd,GACF,CAAA,EACF,CAAA;AAAA,oBAEAD,KAACI,mBAAAA,EAAA,EAAoB,OAAO,EAAE,eAAA,EAAiB,wBAAuB,EACnE,QAAA,EAAA;AAAA,MAAA,OAAA,oBACCJ,IAAAA,CAAAK,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,wBAAAtC,IAAC,gBAAA,EAAA,EAAiB,QAAA,EAAU,MAAM,UAAA,IAC/B,QAAA,EAAA,QAAA,EACH,CAAA;AAAA,wBACAA,IAAC,qBAAA,EAAA,EAAsB;AAAA,OAAA,EACzB,CAAA;AAAA,sBAEFA,GAAAA;AAAA,QAACuC,sBAAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,UAAA;AAAA,UACP,eAAe,CAAC,CAAA,KAAM,QAAQ,MAAA,CAAO,CAAC,IAAI,GAAG,CAAA;AAAA,UAE5C,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAA,qBACZN,IAAAA,CAACO,qBAAAA,EAAA,EAAgC,KAAA,EAAO,MAAA,CAAO,GAAG,CAAA,EAC/C,QAAA,EAAA;AAAA,YAAA,GAAA;AAAA,YAAI;AAAA,WAAA,EAAA,EADqB,GAE5B,CACD;AAAA;AAAA;AACH,KAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;ACvFO,SAAS,UAAA,CAAW,EAAE,IAAA,EAAM,KAAA,GAAQ,QAAQ,WAAA,EAAa,MAAA,EAAQ,WAAU,EAAoB;AACpG,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,KAAY,UAAA,CAAW,IAAI,MAAM,CAAA;AAC/C,EAAA,uBACExC,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,IAAA;AAAA,MACT,UAAU,CAAC,OAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACZO,SAAS,UAAA,CAAW,EAAE,IAAA,EAAM,KAAA,GAAQ,QAAQ,WAAA,EAAa,MAAA,EAAQ,WAAU,EAAoB;AACpG,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,KAAY,UAAA,CAAW,IAAI,MAAM,CAAA;AAC/C,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,IAAA;AAAA,MACT,UAAU,CAAC,OAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACVO,SAAS,YAAA,CAAa;AAAA,EAC3B,IAAA;AAAA,EACA,KAAA,GAAQ,QAAA;AAAA,EACR,WAAA;AAAA,EACA,OAAA,GAAU,OAAA;AAAA,EACV,MAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,WAAW,EAAE,OAAA,IAAW,MAAM,CAAA;AACjD,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,MAAA;AAAA,MACT;AAAA;AAAA,GACF;AAEJ;AChBO,SAAS,SAAA,CAAU;AAAA,EACxB,IAAA;AAAA,EACA,KAAA,GAAQ,KAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,EAAE,GAAA,EAAK,YAAA,EAAa,GAAI,YAAA;AAAA,IAC5B,aAAA,GAAgB,EAAE,aAAA,EAAc,GAAI,EAAC;AAAA,IACrC;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,GAAA;AAAA,MACT,UAAU,CAAC,YAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACvBO,SAAS,UAAA,CAAW;AAAA,EACzB,IAAA;AAAA,EACA,KAAA,GAAQ,MAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAa,GAAI,YAAA;AAAA,IAC7B,aAAA,GAAgB,EAAE,aAAA,EAAc,GAAI,EAAC;AAAA,IACrC;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,IAAA;AAAA,MACT,UAAU,CAAC,YAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACtBO,SAAS,WAAA,CAAY;AAAA,EAC1B,IAAA;AAAA,EACA,KAAA,GAAQ,OAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,YAAA;AAAA,IAC1B,aAAA,GAAgB,EAAE,aAAA,EAAc,GAAI,EAAC;AAAA,IACrC;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,KAAA;AAAA,MACT,UAAU,CAAC,QAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACtBO,SAAS,qBAAA,CAAsB;AAAA,EACpC,IAAA;AAAA,EACA,KAAA,GAAQ,kBAAA;AAAA,EACR,WAAA;AAAA,EACA,aAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAA+B;AAC7B,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAa,GAAI,YAAA;AAAA,IAC/B,aAAA,GAAgB,EAAE,aAAA,EAAc,GAAI,EAAC;AAAA,IACrC;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,MAAA;AAAA,MACT,UAAU,CAAC,YAAA;AAAA,MACX;AAAA;AAAA,GACF;AAEJ;ACnBO,SAAS,UAAA,CAAW;AAAA,EACzB,IAAA;AAAA,EACA,KAAA,GAAQ,aAAA;AAAA,EACR,WAAA;AAAA,EACA,iBAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAW,GAAI,OAAA;AAAA,IAC/B,EAAE,GAAI,iBAAA,GAAoB,EAAE,mBAAkB,GAAI,EAAC,EAAI,GAAI,WAAA,GAAc,EAAE,WAAA,EAAY,GAAI,EAAC,EAAG;AAAA,IAC/F;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,UAAA;AAAA,MACT,MAAA,EAAQ,QAAA;AAAA,MACR;AAAA;AAAA,GACF;AAEJ;ACXO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,iBAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAO,GAAI,QAAA;AAAA,IACvB;AAAA,MACE,GAAI,WAAA,GAAc,EAAE,WAAA,KAAgB,EAAC;AAAA,MACrC,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB,EAAC;AAAA,MACjD,GAAI,QAAA,GAAW,EAAE,QAAA,KAAa;AAAC,KACjC;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,OAAO,IAAA,KAAS,MAAA;AACtB,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,OAAO,QAAA,GAAW,SAAA;AAAA,MACxB,KAAA,EAAO,KAAA,KAAU,IAAA,GAAO,uBAAA,GAA0B,sBAAA,CAAA;AAAA,MAClD,WAAA;AAAA,MACA,OAAA,EAAS,MAAA;AAAA,MACT,MAAA,EAAQ,IAAA;AAAA,MACR;AAAA;AAAA,GACF;AAEJ;AC7CO,SAAS,UAAA,CAAW;AAAA,EACzB,UAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,EAAE,MAAA,EAAQ,UAAA,EAAW,GAAI,OAAA;AAAA,IAC7B;AAAA,MACE,GAAI,YAAA,GAAe,EAAE,YAAA,KAAiB,EAAC;AAAA,MACvC,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB;AAAC,KACzD;AAAA,IACA;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,QAAA,EAAU,UAAA;AAAA,MACV,UAAA;AAAA,MACA,YAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AAAA,GACF;AAEJ;ACjBO,SAAS,YAAA,CAAa;AAAA,EAC3B,OAAA;AAAA,EACA,KAAA,GAAQ,QAAA;AAAA,EACR,OAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,EAAe,WAAA,EAAY,GAAI,SAAA;AAAA,IAC7C,OAAA;AAAA,IACA;AAAA,MACE,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY,EAAC;AAAA,MAC7B,GAAI,UAAA,KAAe,MAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,MACjD,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY,EAAC;AAAA,MAC7B,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW;AAAC,KAC7B;AAAA,IACA;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,KAAA,EAAO,MAAA;AAAA,MACP,OAAA,EAAS,aAAA;AAAA,MACT,QAAA,EAAU,WAAA;AAAA,MACV,KAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AAAA,GACF;AAEJ;ACnCO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,YAAA;AAAA,EACA,KAAA,GAAQ,QAAA;AAAA,EACR,OAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAQ,GAAI,aAAA;AAAA,IACrC,YAAA;AAAA,IACA,EAAE,GAAI,OAAA,GAAU,EAAE,SAAQ,GAAI,EAAC,EAAI,GAAI,MAAA,GAAS,EAAE,MAAA,EAAO,GAAI,EAAC,EAAG;AAAA,IACjE;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,KAAA,EAAO,IAAA;AAAA,MACP,OAAA,EAAS,WAAA;AAAA,MACT,KAAA;AAAA,MACA,QAAA,EAAU,OAAA;AAAA,MACV,KAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AAAA,GACF;AAEJ;ACxBO,SAAS,cAAA,CAAe;AAAA,EAC7B,OAAA;AAAA,EACA,KAAA,GAAQ,MAAA;AAAA,EACR,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,EAAE,QAAA,EAAU,eAAA,EAAiB,WAAA,EAAY,GAAI,WAAA;AAAA,IACjD;AAAA,MACE,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY,EAAC;AAAA,MAC7B,GAAI,OAAA,GAAU,EAAE,OAAA,KAAY,EAAC;AAAA,MAC7B,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU,EAAC;AAAA,MACzB,GAAI,MAAA,GAAS,EAAE,MAAA,KAAW;AAAC,KAC7B;AAAA,IACA;AAAA,GACF;AACA,EAAA,uBACEA,GAAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,KAAA;AAAA,MACA,KAAA,EAAO,QAAA;AAAA,MACP,OAAA,EAAS,eAAA;AAAA,MACT,KAAA;AAAA,MACA,QAAA,EAAU,WAAA;AAAA,MACV,KAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AAAA,GACF;AAEJ;ACtCO,SAAS,kBAAA,CAAmB,EAAE,CAAA,EAAG,CAAA,EAAG,OAAO,MAAA,GAAS,GAAA,EAAM,OAAM,EAA4B;AACjG,EAAA,uBACEA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,EAAE,QAAA,EAAU,UAAA,EAAY,IAAA,EAAM,GAAG,GAAA,EAAK,CAAA,EAAG,MAAA,EAAQ,GAAG,KAAA,EAAM;AAAA,MACjE,aAAA,EAAe,CAAC,EAAA,KAAO,EAAA,CAAG,eAAA,EAAgB;AAAA,MAC1C,aAAA,EAAe,CAAC,EAAA,KAAO,EAAA,CAAG,cAAA,EAAe;AAAA,MAEzC,QAAA,kBAAAA,GAAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,KAAA,EAAO;AAAA;AAAA,GAChC;AAEJ;ACmCO,SAAS,qBAAA,CAAsB;AAAA,EACpC,QAAA,GAAW,aAAA;AAAA,EACX,WAAA,GAAc,UAAA;AAAA,EACd,UAAA,GAAa,OAAA;AAAA,EACb,QAAA,GAAW,IAAA;AAAA,EACX,aAAA,GAAgB,KAAA;AAAA,EAChB,OAAA,GAAU,IAAA;AAAA,EACV,KAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA+B;AAC7B,EAAA,MAAM,WACJ,MAAA,KAAW,MAAA,IAAa,YAAA,IAAgB,KAAA,CAAM,UAAU,KAAA,CAAM,QAAA;AAEhE,EAAA,MAAM,QAAA,mBACJiC,IAAAA,CAAAK,QAAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA,oBACCtC,GAAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,WAAA;AAAA,QACA,MAAA;AAAA,QACA,YAAY,KAAA,CAAM,MAAA;AAAA,QAClB,aAAa,KAAA,CAAM,OAAA;AAAA,QACnB,SAAA,EAAW;AAAA;AAAA,KACb;AAAA,IAED,OAAA,oBACCA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,MAAM,KAAA,CAAM,GAAA,EAAK,MAAA,EAAgB,OAAA,EAAS,UAAA,EAAY,CAAA;AAAA,IAEzE,4BACCA,GAAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,QAAA,EAAU,YAAA;AAAA,QACV,YAAY,KAAA,CAAM,MAAA;AAAA,QAClB,cAAc,KAAA,CAAM;AAAA;AAAA,KACtB;AAAA,IAED;AAAA,GAAA,EACH,CAAA;AAGF,EAAA,MAAM,GAAA,GACJ,WAAA,KAAgB,UAAA,mBACdA,IAAC,WAAA,EAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElDA,GAAAA,CAAC,aAAA,EAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AAEjB,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;AC9EO,SAAS,YAAA,CAAa;AAAA,EAC3B,MAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAA;AAAA,EACA,iBAAA;AAAA,EACA,kBAAA;AAAA,EACA,eAAA,GAAkB,OAAA;AAAA,EAClB,SAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA,GAAe,OAAA;AAAA,EACf,SAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,GAAW,YAAA;AAAA,EACX;AACF,CAAA,EAAsB;AACpB,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,WAAA,EAAY,cACrC,QAAA,kBAAAA,GAAAA;AAAA,IAACyC,aAAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,MAAA,kBACER,IAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,GAAA,EAAK,CAAA,EAAG,UAAA,EAAY,QAAA,EAAS,EAC1D,QAAA,EAAA;AAAA,wBAAAjC,GAAAA;AAAA,UAAC,YAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,QAAA;AAAA,YACN,KAAA,EAAO,MAAA;AAAA,YACP,OAAA,EAAS,aAAA;AAAA,YACT,QAAA,EAAU;AAAA;AAAA,SACZ;AAAA,wBACAA,GAAAA;AAAA,UAAC,YAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,QAAA;AAAA,YACN,KAAA,EAAO,UAAA;AAAA,YACP,OAAA,EAAS,iBAAA;AAAA,YACT,QAAA,EAAU;AAAA;AAAA,SACZ;AAAA,QACC,eAAA,IAAmB,wBAClBA,GAAAA;AAAA,UAAC,cAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAS,eAAA;AAAA,YACR,GAAI,SAAA,GAAY,EAAE,KAAA,EAAO,SAAA,KAAc,EAAC;AAAA,YACxC,GAAI,cAAA,GAAiB,EAAE,MAAA,EAAQ,cAAA,KAAmB,EAAC;AAAA,YACnD,GAAI,aAAA,GAAgB,EAAE,KAAA,EAAO,aAAA,KAAkB,EAAC;AAAA,YACjD;AAAA;AAAA,SACF;AAAA,wBAEFA,GAAAA,CAAC,WAAA,EAAA,EAAY,MAAM,SAAA,EAAW,OAAA,EAAS,cAAc,MAAA,EAAgB;AAAA,OAAA,EACvE;AAAA;AAAA,GAEJ,EACF,CAAA;AAEJ;ACvEO,SAAS,cAAA,CAAe;AAAA,EAC7B,KAAA;AAAA,EACA,QAAA,GAAW,UAAA;AAAA,EACX,WAAA,GAAc,YAAA;AAAA,EACd,UAAA,GAAa,IAAA;AAAA,EACb,OAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,QAAA,mBACJiC,IAAAA,CAAAK,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAtC,GAAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAM,KAAA,CAAM,MAAM,MAAA,EAAgB,CAAA;AAAA,oBAC9CA,GAAAA,CAAC,UAAA,EAAA,EAAW,IAAA,EAAM,KAAA,CAAM,MAAM,MAAA,EAAgB,CAAA;AAAA,IAC7C,UAAA,IAAc,KAAA,CAAM,MAAA,oBACnBA,GAAAA,CAAC,gBAAa,IAAA,EAAM,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAkB,MAAA,EAAgB;AAAA,GAAA,EAExE,CAAA;AAGF,EAAA,MAAM,MACJ,WAAA,KAAgB,UAAA,mBACdA,GAAAA,CAAC0C,aAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElD1C,GAAAA,CAACyC,eAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEzC,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;ACnBO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,QAAA,GAAW,UAAA;AAAA,EACX,WAAA,GAAc,YAAA;AAAA,EACd,SAAA,GAAY,IAAA;AAAA,EACZ,aAAA;AAAA,EACA,OAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,QAAA,mBACJiC,IAAAA,CAAAK,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAtC,IAAC,SAAA,EAAA,EAAU,IAAA,EAAM,KAAA,CAAM,GAAA,EAAK,eAA8B,MAAA,EAAgB,CAAA;AAAA,oBAC1EA,GAAAA,CAAC,UAAA,EAAA,EAAW,MAAM,KAAA,CAAM,IAAA,EAAM,eAA8B,MAAA,EAAgB,CAAA;AAAA,oBAC5EA,GAAAA,CAAC,WAAA,EAAA,EAAY,MAAM,KAAA,CAAM,KAAA,EAAO,eAA8B,MAAA,EAAgB,CAAA;AAAA,oBAC9EA,GAAAA;AAAA,MAAC,qBAAA;AAAA,MAAA;AAAA,QACC,MAAM,KAAA,CAAM,MAAA;AAAA,QACZ,aAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,IACC,SAAA,oBAAaA,GAAAA,CAAC,WAAA,EAAA,EAAY,MAAM,KAAA,CAAM,KAAA,EAAO,SAAkB,MAAA,EAAgB;AAAA,GAAA,EAClF,CAAA;AAGF,EAAA,MAAM,MACJ,WAAA,KAAgB,UAAA,mBACdA,GAAAA,CAAC0C,aAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElD1C,GAAAA,CAACyC,eAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEzC,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;ACjCO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,QAAA,GAAW,aAAA;AAAA,EACX,WAAA,GAAc,UAAA;AAAA,EACd,QAAA,GAAW,IAAA;AAAA,EACX,aAAA,GAAgB,KAAA;AAAA,EAChB,cAAA,GAAiB,IAAA;AAAA,EACjB,OAAA,GAAU,IAAA;AAAA,EACV,QAAA,GAAW,IAAA;AAAA,EACX,OAAA,GAAU,OAAA;AAAA,EACV,gBAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,SAAA,GAAY,QAAA,IAAY,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM,QAAA;AACpD,EAAA,MAAM,QAAA,mBACJiC,IAAAA,CAAAK,QAAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA,oBACCtC,GAAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,WAAA;AAAA,QACA,MAAA;AAAA,QACA,YAAY,KAAA,CAAM,MAAA;AAAA,QAClB,aAAa,KAAA,CAAM,OAAA;AAAA,QACnB,SAAA,EAAW;AAAA;AAAA,KACb;AAAA,IAED,cAAA,oBAAkBA,GAAAA,CAAC,UAAA,EAAA,EAAW,QAAgB,OAAA,EAAkB,CAAA;AAAA,IAChE,OAAA,oBAAWA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,MAAM,KAAA,CAAM,GAAA,EAAK,QAAgB,OAAA,EAAkB,CAAA;AAAA,IAChF,6BACCA,GAAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,YAAY,KAAA,CAAM,MAAA;AAAA,QAClB,cAAc,KAAA,CAAM,QAAA;AAAA,QACpB,YAAA,EAAc,gBAAA;AAAA,QACd;AAAA;AAAA;AACF,GAAA,EAEJ,CAAA;AAGF,EAAA,MAAM,MACJ,WAAA,KAAgB,UAAA,mBACdA,GAAAA,CAAC0C,aAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElD1C,GAAAA,CAACyC,eAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEzC,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;ACzEO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,QAAA,GAAW,cAAA;AAAA,EACX,WAAA,GAAc,YAAA;AAAA,EACd,iBAAA;AAAA,EACA,WAAA;AAAA,EACA,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,2BACJA,GAAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,iBAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AAAA,GACF;AAGF,EAAA,MAAM,MACJ,WAAA,KAAgB,UAAA,mBACdA,GAAAA,CAAC0C,aAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElD1C,GAAAA,CAACyC,eAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEzC,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;AC1BO,SAAS,kBAAA,CAAmB;AAAA,EACjC,OAAA;AAAA,EACA,sBAAA;AAAA,EACA,YAAA;AAAA,EACA,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,aAAA;AAAA,EACA,iBAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW,YAAA;AAAA,EACX,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,sBACJA,GAAAA;AAAA,IAACyC,aAAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,MAAA,kBACER,IAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,GAAA,EAAK,CAAA,EAAG,UAAA,EAAY,QAAA,EAAS,EAC1D,QAAA,EAAA;AAAA,wBAAAjC,GAAAA;AAAA,UAAC,YAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,MAAA,EAAQ,YAAA;AAAA,YACR,OAAA,EAAS,aAAA;AAAA,YACT,OAAA;AAAA,YACA;AAAA;AAAA,SACF;AAAA,wBACAA,GAAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,UAAA,EAAW,KAAA,EAAO,EAAE,SAAA,EAAW,QAAA,EAAU,MAAA,EAAQ,EAAA,EAAG,EAAG,CAAA;AAAA,wBAC9EA,GAAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YACC,YAAA,EAAc,sBAAA;AAAA,YACd,MAAA,EAAQ,gBAAA;AAAA,YACR,KAAA,EAAO,eAAA;AAAA,YACP,OAAA,EAAS,iBAAA;AAAA,YACT;AAAA;AAAA;AACF,OAAA,EACF;AAAA;AAAA,GAEJ;AAGF,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,WAAA,EAAY,cACpC,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;ACzBA,IAAM,aAAA,GAAsC,CAAC,QAAA,EAAU,KAAA,EAAO,WAAW,QAAQ,CAAA;AACjF,IAAM,cAAA,GAA4C;AAAA,EAChD,MAAA,EAAQ,QAAA;AAAA,EACR,GAAA,EAAK,UAAA;AAAA,EACL,OAAA,EAAS,SAAA;AAAA,EACT,MAAA,EAAQ;AACV,CAAA;AAaO,SAAS,eAAA,CAAgB;AAAA,EAC9B,KAAA;AAAA,EACA,KAAA,GAAQ,aAAA;AAAA,EACR,MAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA,GAAc,IAAA;AAAA,EACd,SAAA,GAAY,IAAA;AAAA,EACZ,OAAA;AAAA,EACA,QAAA,GAAW,YAAA;AAAA,EACX,WAAA,GAAc,YAAA;AAAA,EACd,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAyB;AACvB,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,QAAA,EAAU,WAAA,KAAgB,OAAA,EAAQ;AACzD,EAAA,MAAM,OAAA,GAAuB,WAAA,KAAgB,UAAA,GAAa,OAAA,GAAU,QAAA;AACpE,EAAA,MAAM,QAAQ,CAAC,CAAA,KAAyB,SAAS,CAAC,CAAA,IAAK,eAAe,CAAC,CAAA;AAEvE,EAAA,MAAM,QAAA,mBACJiC,IAAAA,CAAAK,QAAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,qBACVtC,GAAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QAEC,IAAA,EAAM,MAAM,CAAC,CAAA;AAAA,QACb,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,QACd,WAAA,EAAa,OAAA;AAAA,QACb,QAAQ,IAAA,KAAS,CAAA;AAAA,QACjB,OAAA,EAAS,MAAM,OAAA,CAAQ,CAAC;AAAA,OAAA;AAAA,MALnB;AAAA,KAOR,CAAA;AAAA,IACA,IAAA,KAAS,SAAS,SAAA,IAAa,MAAA,CAAO,KAAK,SAAS,CAAA,CAAE,MAAA,GAAS,CAAA,oBAC9DA,GAAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAM,OAAA;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,OAAA,EAAS,SAAA;AAAA,QACR,GAAI,aAAA,GAAgB,EAAE,KAAA,EAAO,aAAA,KAAkB,EAAC;AAAA,QACjD,QAAA,EAAU,WAAA;AAAA,QACV,WAAA,EAAa;AAAA;AAAA,KACf;AAAA,IAED,WAAA,IAAe,MAAM,IAAA,IAAQ,KAAA,CAAM,wBAClCiC,IAAAA,CAAAK,UAAA,EACE,QAAA,EAAA;AAAA,sBAAAtC,IAAC,UAAA,EAAA,EAAW,IAAA,EAAM,MAAM,IAAA,EAAM,WAAA,EAAa,SAAS,MAAA,EAAgB,CAAA;AAAA,sBACpEA,IAAC,UAAA,EAAA,EAAW,IAAA,EAAM,MAAM,IAAA,EAAM,WAAA,EAAa,SAAS,MAAA,EAAgB;AAAA,KAAA,EACtE,CAAA;AAAA,IAED,SAAA,oBACCA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,MAAM,KAAA,EAAO,OAAA,EAAkB,WAAA,EAAa,OAAA,EAAS,MAAA,EAAgB;AAAA,GAAA,EAE5F,CAAA;AAGF,EAAA,MAAM,MACJ,WAAA,KAAgB,UAAA,mBACdA,GAAAA,CAAC0C,aAAA,EAAY,GAAA,EAAK,QAAA,EAAU,SAAA,EAAsB,oBAElD1C,GAAAA,CAACyC,eAAA,EAAc,IAAA,EAAM,UAAU,SAAA,EAAsB,CAAA;AAGzD,EAAA,IAAI,MAAM,OAAO,GAAA;AACjB,EAAA,uBACEzC,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,aACxB,QAAA,EAAA,GAAA,EACH,CAAA;AAEJ;ACtGO,SAAS,cAAA,CAAe;AAAA,EAC7B,OAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,GAAW,WAAA;AAAA,EACX,SAAA;AAAA,EACA,WAAA,GAAc,KAAA;AAAA,EACd,SAAA,GAAY,MAAA;AAAA,EACZ,SAAA,GAAY,MAAA;AAAA,EACZ,IAAA,GAAO,KAAA;AAAA,EACP,MAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,OAAwE,EAAC;AAC/E,EAAA,IAAI,OAAA,KAAY,MAAA,EAAW,IAAA,CAAK,OAAA,GAAU,OAAA;AAC1C,EAAA,IAAI,SAAA,KAAc,MAAA,EAAW,IAAA,CAAK,SAAA,GAAY,SAAA;AAC9C,EAAA,IAAI,WAAA,OAAkB,WAAA,GAAc,IAAA;AAEpC,EAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,EAAM,MAAM,CAAA;AAC3C,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,MAAM,MAAA,GAAS,OAAO,IAAA,KAAS,MAAA;AAG/B,EAAA,MAAM,gBAAgB,WAAA,IAAe,MAAA;AACrC,EAAA,MAAM,cAAA,GAAiB,CAAC,aAAA,KAAkB,SAAA,IAAa,IAAA,CAAA;AACvD,EAAA,MAAM,yBACJA,GAAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MAEC,KAAA,EAAO,SAAS,SAAA,GAAY,SAAA;AAAA,MAC5B,QAAA,EAAU,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,MAAM,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,IAAA,EAAK;AAAA,MACtE,UAAU,MAAA,CAAO,MAAA;AAAA,MACjB,SAAA,EAAW,cAAA;AAAA,MACV,GAAI,aAAA,GAAgB,EAAE,QAAA,EAAU,IAAA,KAAS,EAAC;AAAA,MAC1C,GAAI,UAAU,MAAA,CAAO,OAAA,GAAU,EAAE,SAAA,EAAW,MAAA,CAAO,OAAA,EAAQ,GAAI,EAAC;AAAA,MAChE,GAAI,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,KAAc;AAAC,KAAA;AAAA,IAP3C,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,OAAO,EAAE,CAAA;AAAA,GAQlC;AAGF,EAAA,IAAI,MAAM,OAAO,MAAA;AACjB,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAoB,WAAA,EAAY,YACpC,QAAA,EAAA,MAAA,EACH,CAAA;AAEJ;ACxBA,SAAS,aAAA,CAAc,OAAmB,KAAA,EAA+B;AACvE,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACzB,IAAA,MAAM,IAAA,GAAiB,EAAE,GAAG,IAAA,EAAK;AACjC,IAAA,IAAI,KAAK,QAAA,EAAU,IAAA,CAAK,WAAW,aAAA,CAAc,IAAA,CAAK,UAAU,KAAK,CAAA;AACrE,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,WAAW,IAAA,CAAK,OAAA;AACtB,MAAA,IAAA,CAAK,UAAU,MAAY;AACzB,QAAA,QAAA,EAAS;AACT,QAAA,KAAA,EAAM;AAAA,MACR,CAAA;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA;AACH;AAuBO,SAAS,oBAAA,CAAqB;AAAA,EACnC,MAAA;AAAA,EACA,EAAA;AAAA,EACA,OAAA,GAAU,OAAA;AAAA,EACV,OAAA,GAAU,IAAA;AAAA,EACV,MAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA,GAAY,IAAA;AAAA,EACZ,KAAA,GAAQ,IAAA;AAAA,EACR;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAM,KAAA,KAAU,cAAA,EAA2B;AAEzD,EAAA,MAAM,aAAA,GAAgB8B,WAAAA;AAAA,IACpB,CAAC,KAAA,KAAkC;AACjC,MAAA,MAAM,IAAA,GAAgC;AAAA,QACpC,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,MAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,EAAO,IAAI,CAAA;AAC/B,MAAA,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,CAAA,EAAG,KAAA,CAAM,MAAA,CAAO,CAAA,EAAG,SAAA,GAAY,aAAA,CAAc,KAAA,EAAO,KAAK,CAAA,GAAI,KAAK,CAAA;AAAA,IACtF,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,MAAM,KAAK;AAAA,GACxC;AAEA,EAAA,uBACEG,IAAAA,CAAAK,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAtC,GAAAA;AAAA,MAAC,oBAAA;AAAA,MAAA;AAAA,QACC,EAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA;AAAA,QACA,OAAA,EAAS,CAAC,MAAM,CAAA;AAAA,QAChB,KAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,IACC,IAAA,oBACCA,GAAAA,CAAC,kBAAA,EAAA,EAAmB,GAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,QAAgB,KAAA,EAAc;AAAA,GAAA,EAE/F,CAAA;AAEJ;AC1FO,SAAS,oBAAA,CAAqB;AAAA,EACnC,KAAA;AAAA,EACA,EAAA,GAAK,mBAAA;AAAA,EACL,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,MAAM,KAAA,GAAQ8B,WAAAA;AAAA,IACZ,CAAC,KAAA,EAAyB,IAAA,KACxB,KAAA,CAAM,EAAE,GAAG,IAAA,EAAM,EAAA,EAAI,KAAA,CAAM,EAAA,EAAc,IAAA,EAAM,KAAA,CAAM,MAAM,CAAA;AAAA,IAC7D,CAAC,KAAK;AAAA,GACR;AACA,EAAA,uBAAO9B,IAAC,oBAAA,EAAA,EAAqB,MAAA,EAAO,QAAO,EAAA,EAAQ,KAAA,EAAe,GAAG,MAAA,EAAQ,CAAA;AAC/E;ACXO,SAAS,oBAAA,CAAqB;AAAA,EACnC,KAAA;AAAA,EACA,EAAA,GAAK,mBAAA;AAAA,EACL,GAAG;AACL,CAAA,EAA8B;AAC5B,EAAA,MAAM,KAAA,GAAQ8B,WAAAA;AAAA,IACZ,CAAC,KAAA,EAAyB,IAAA,KACxB,KAAA,CAAM,EAAE,GAAG,IAAA,EAAM,EAAA,EAAI,KAAA,CAAM,EAAA,EAAc,IAAA,EAAM,KAAA,CAAM,MAAM,CAAA;AAAA,IAC7D,CAAC,KAAK;AAAA,GACR;AACA,EAAA,uBAAO9B,IAAC,oBAAA,EAAA,EAAqB,MAAA,EAAO,QAAO,EAAA,EAAQ,KAAA,EAAe,GAAG,MAAA,EAAQ,CAAA;AAC/E;ACjBO,SAAS,0BAAA,CAA2B;AAAA,EACzC,KAAA;AAAA,EACA,EAAA,GAAK,yBAAA;AAAA,EACL,GAAG;AACL,CAAA,EAAoC;AAClC,EAAA,MAAM,KAAA,GAAQ8B,WAAAA;AAAA,IACZ,CAAC,MAAA,EAA0B,IAAA,KAA8C,KAAA,CAAM,IAAI,CAAA;AAAA,IACnF,CAAC,KAAK;AAAA,GACR;AACA,EAAA,uBAAO9B,IAAC,oBAAA,EAAA,EAAqB,MAAA,EAAO,UAAS,EAAA,EAAQ,KAAA,EAAe,GAAG,MAAA,EAAQ,CAAA;AACjF","file":"index.js","sourcesContent":["import { createContext, useContext } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\n/**\n * Holds the initialised engine `Canvas` for all descendant child wrappers.\n * `<Canvas>` only renders children once the engine is ready, so the context\n * value inside a wrapper is always non-null.\n */\nexport const CanvasContext = createContext<EngineCanvas | null>(null);\n\n/**\n * Read the engine `Canvas` from context. Throws when used outside a\n * `<Canvas>` so misuse fails loudly during render instead of silently\n * skipping the effect that would have registered a layer or behaviour.\n */\nexport function useCanvas(): EngineCanvas {\n const canvas = useContext(CanvasContext);\n if (!canvas) {\n throw new Error('useCanvas() must be called inside a <Canvas> component');\n }\n return canvas;\n}\n","import {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { Canvas as EngineCanvas, type CanvasOptions } from '@invana/canvas';\n\nimport { CanvasContext } from './CanvasContext';\n\nexport interface CanvasProps extends Omit<CanvasOptions, 'container'> {\n /**\n * JSX children — layer / behaviour / layout wrappers. They aren't mounted\n * until the engine has finished initialising, so child effects can assume\n * `useCanvas()` returns a live, initialised engine.\n */\n children?: ReactNode;\n /** Inline style on the host `<div>`. Defaults to `width: '100%', height: '100%'`. */\n style?: CSSProperties;\n /** Class name on the host `<div>`. */\n className?: string;\n}\n\n/**\n * React root for the canvas engine. Renders a sized host `<div>`, creates an\n * `EngineCanvas` once on mount, calls `init({ container, ...opts })`, and\n * provides the initialised instance to descendants via {@link CanvasContext}.\n *\n * The component is `forwardRef`'d — `ref.current` is the underlying\n * `EngineCanvas` (or `null` until init resolves). Use it as the imperative\n * escape hatch: `ref.current?.layers.get(...)`, `ref.current?.events.tap(...)`,\n * `ref.current?.camera.fitContent(...)`.\n *\n * StrictMode-safe: the init promise is guarded by a cancelled flag so a\n * double-mount cleans up the partially-initialised engine.\n *\n * @example\n * ```tsx\n * const canvasRef = useRef<EngineCanvas>(null);\n *\n * <Canvas ref={canvasRef} autoResize>\n * <DragPanBehaviour />\n * <WheelZoomBehaviour />\n * <GraphLayer id=\"graph\" data={data} />\n * <D3ForceLayout targetLayerId=\"graph\" />\n * </Canvas>\n * ```\n */\nexport const Canvas = forwardRef<EngineCanvas, CanvasProps>(function Canvas(\n { children, style, className, ...engineOpts },\n ref,\n) {\n const hostRef = useRef<HTMLDivElement>(null);\n const [canvas, setCanvas] = useState<EngineCanvas | null>(null);\n\n // Engine options change rarely; we only read them on first init. Capture\n // them in a ref so the init effect runs exactly once (StrictMode aside).\n const optsRef = useRef(engineOpts);\n optsRef.current = engineOpts;\n\n useEffect(() => {\n const container = hostRef.current;\n if (!container) return;\n\n let cancelled = false;\n const engine = new EngineCanvas();\n\n void engine\n .init({ container, ...optsRef.current })\n .then(() => {\n if (cancelled) {\n engine.destroy();\n return;\n }\n setCanvas(engine);\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n // Surface init failures to the console — there's no React-idiomatic\n // way to throw from a useEffect promise.\n // eslint-disable-next-line no-console\n console.error('[canvas-react] Canvas.init() failed:', err);\n }\n });\n\n return () => {\n cancelled = true;\n setCanvas(null);\n if (engine.isInitialised) engine.destroy();\n };\n // Init is intentionally one-shot. Reactive props (other than `children`)\n // are not supported in v0 — recreate the <Canvas> with a key to re-init.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // `ref.current` is typed as `EngineCanvas | null` because React's `Ref<T>`\n // already permits null on `.current`; we surface the live value (null until\n // init resolves, then the initialised engine) with a cast that satisfies\n // useImperativeHandle's `R extends T` constraint.\n useImperativeHandle(ref, () => canvas as EngineCanvas, [canvas]);\n\n return (\n <div\n ref={hostRef}\n className={className}\n // `position: relative` makes the host the positioned ancestor that child\n // overlays (`<Panel>`, `<CanvasControlsToolbar>`, the turnkey toolbars) pin to.\n style={{ width: '100%', height: '100%', position: 'relative', ...style }}\n >\n {canvas && <CanvasContext.Provider value={canvas}>{children}</CanvasContext.Provider>}\n </div>\n );\n});\n","import { createContext } from 'react';\nimport type { GraphHistory } from '@invana/graph';\n\n/**\n * Holds the `GraphHistory` constructed by a `<GraphHistoryProvider>` for all\n * descendant hooks (`useHistory`) and self-wiring buttons (Undo/Redo/Redraw).\n * `null` until the provider's effect has built the instance, or when no provider\n * is present — consumers must guard.\n */\nexport const HistoryContext = createContext<GraphHistory | null>(null);\n","import { createContext } from 'react';\nimport type { GraphClipboard } from '@invana/graph';\n\n/**\n * Holds the `GraphClipboard` constructed by a `<GraphClipboardProvider>` for all\n * descendant hooks (`useClipboard`) and self-wiring buttons (Cut/Copy/Paste/\n * Delete). `null` until the provider's effect has built the instance, or when no\n * provider is present — consumers must guard.\n */\nexport const ClipboardContext = createContext<GraphClipboard | null>(null);\n","import { createContext } from 'react';\n\n/**\n * The active modelling tool. `'select'` is the neutral pointer (drag / select);\n * `'add'` drops nodes; `'connect'` draws edges; `'delete'` erases on click.\n * A string-literal union, but consumers may treat it opaquely — the\n * {@link ModellerToolbar} only renders the tools it's told to.\n */\nexport type GraphTool = 'select' | 'add' | 'connect' | 'delete';\n\n/** Shared modeller state surfaced by {@link GraphToolProvider}. */\nexport interface ToolContextValue {\n /** The currently active tool. */\n tool: GraphTool;\n /** Switch the active tool. */\n setTool: (tool: GraphTool) => void;\n /**\n * The node \"kind\" the **Add** tool drops next (an opaque key like `'circle'`\n * / `'rect'`). The consumer maps it to a concrete `NodeStyle` in its\n * `CreateNodeBehaviour` `createNode` factory.\n */\n nodeKind: string;\n /** Choose the node kind the Add tool drops next. */\n setNodeKind: (kind: string) => void;\n}\n\n/**\n * Holds the active {@link GraphTool} + node kind for a modeller, set by a\n * `<GraphToolProvider>` and read by `useTool` / `<ModellerToolbar>`. `null` when\n * no provider is present — `useTool` throws in that case (a modeller toolbar\n * without a provider is a wiring bug, not a graceful-degrade case).\n */\nexport const ToolContext = createContext<ToolContextValue | null>(null);\n","import { useContext } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { CanvasContext } from '../CanvasContext';\n\n/**\n * Resolve the engine `Canvas` a hook should act on. Prefers an explicit\n * instance (for the out-of-`<Canvas>` / multi-canvas-orchestration case), and\n * otherwise reads the instance-scoped {@link CanvasContext}. Throws only when\n * neither is available — so calling a canvas hook outside any `<Canvas>` and\n * without an explicit instance fails loudly instead of silently no-op'ing.\n *\n * This is what keeps every hook multi-canvas-safe: inside a `<Canvas>` tree the\n * context yields *that* instance; passing an explicit `canvas` targets a\n * specific one. There is no global fallback.\n */\nexport function useResolvedCanvas(explicit?: EngineCanvas | null): EngineCanvas {\n const fromContext = useContext(CanvasContext);\n const canvas = explicit ?? fromContext;\n if (!canvas) {\n throw new Error(\n 'Canvas hooks need a <Canvas> ancestor, or an explicit `canvas` argument.',\n );\n }\n return canvas;\n}\n","import { useEffect, useState, type ReactNode } from 'react';\nimport {\n GraphHistory,\n type GraphLayer as EngineGraphLayer,\n type HistoryOp,\n type Vec2,\n} from '@invana/graph';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from '../hooks/useResolvedCanvas';\nimport { HistoryContext } from '../HistoryContext';\n\nexport interface GraphHistoryProviderProps {\n /** Id of the `GraphLayer` whose store the history journals. Default `'graph'`. */\n layerId?: string;\n /** Maximum undo depth. Forwarded to `GraphHistory`. Default `100`. */\n limit?: number;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n children?: ReactNode;\n}\n\n/**\n * Constructs a `GraphHistory` over the target layer's store and provides it via\n * {@link HistoryContext}. Place it **inside** `<Canvas>` and **after** the\n * `<GraphLayer>` it targets, so the layer (and its store) exist when the effect\n * runs. Descendant `useHistory` / Undo-Redo-Redraw buttons resolve the history\n * from here.\n *\n * Node **drags** are captured as one undoable \"move\" entry per gesture (snapshot\n * at `node:drag-start`, net change pushed at `node:drag-end`) — reusing\n * `history.push`, so per-frame writes and layout sim ticks never enter the stack.\n *\n * The history is rebuilt (and its stacks cleared) if `layerId`, `limit`, or the\n * resolved canvas change.\n */\nexport function GraphHistoryProvider({\n layerId = 'graph',\n limit,\n canvas,\n children,\n}: GraphHistoryProviderProps) {\n const resolved = useResolvedCanvas(canvas);\n const [history, setHistory] = useState<GraphHistory | null>(null);\n\n useEffect(() => {\n const layer = resolved.layers.get<EngineGraphLayer>(layerId);\n const store = layer?.store;\n if (!store) return;\n const instance = new GraphHistory(store, limit !== undefined ? { limit } : {});\n setHistory(instance);\n return () => {\n instance.clear();\n setHistory(null);\n };\n }, [resolved, layerId, limit]);\n\n // Capture node drags as one \"move\" entry per gesture. Every dragged primary\n // (a multi-selection drag moves them all) plus each one's descendants (group\n // drag) is snapshot at drag-start; the net position change is pushed at\n // drag-end. No per-frame recording → layout sim writes and programmatic\n // moves stay out of history.\n useEffect(() => {\n if (!history) return;\n const layer = resolved.layers.get<EngineGraphLayer>(layerId);\n const store = layer?.store;\n if (!layer || !store) return;\n\n let before: Map<string, Vec2> | null = null;\n const offStart = layer.events.on('node:drag-start', ({ nodeId, nodeIds }) => {\n const ids = new Set<string>();\n for (const primary of nodeIds ?? [nodeId]) {\n ids.add(primary);\n for (const desc of store.descendantsOf(primary)) ids.add(desc);\n }\n before = new Map();\n for (const id of ids) {\n const p = store.getPosition(id);\n if (p) before.set(id, { x: p.x, y: p.y });\n }\n });\n const offEnd = layer.events.on('node:drag-end', () => {\n const snap = before;\n before = null;\n if (!snap) return;\n const ops: HistoryOp[] = [];\n for (const [id, from] of snap) {\n const to = store.getPosition(id);\n if (to && (to.x !== from.x || to.y !== from.y)) {\n ops.push({ kind: 'moveNode', id, before: from, after: { x: to.x, y: to.y } });\n }\n }\n if (ops.length > 0) history.push({ ops, label: 'move' });\n });\n return () => {\n offStart();\n offEnd();\n };\n }, [resolved, layerId, history]);\n\n return <HistoryContext.Provider value={history}>{children}</HistoryContext.Provider>;\n}\n","import { useEffect, useState, type ReactNode } from 'react';\nimport {\n GraphClipboard,\n type GraphLayer as EngineGraphLayer,\n type Vec2,\n} from '@invana/graph';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from '../hooks/useResolvedCanvas';\nimport { ClipboardContext } from '../ClipboardContext';\n\nexport interface GraphClipboardProviderProps {\n /** Id of the `GraphLayer` whose store the clipboard reads/writes. Default `'graph'`. */\n layerId?: string;\n /** Offset applied to pasted node positions. Forwarded to `GraphClipboard`. */\n pasteOffset?: Vec2;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n children?: ReactNode;\n}\n\n/**\n * Constructs a `GraphClipboard` over the target layer's store and provides it\n * via {@link ClipboardContext}. Place it **inside** `<Canvas>` and **after** the\n * `<GraphLayer>` it targets. Descendant `useClipboard` / Cut-Copy-Paste-Delete\n * buttons resolve the clipboard from here. Pair with a `<GraphHistoryProvider>`\n * to make cut/paste/delete undoable.\n */\nexport function GraphClipboardProvider({\n layerId = 'graph',\n pasteOffset,\n canvas,\n children,\n}: GraphClipboardProviderProps) {\n const resolved = useResolvedCanvas(canvas);\n const [clipboard, setClipboard] = useState<GraphClipboard | null>(null);\n\n useEffect(() => {\n const layer = resolved.layers.get<EngineGraphLayer>(layerId);\n const store = layer?.store;\n if (!store) return;\n const instance = new GraphClipboard(store, pasteOffset ? { pasteOffset } : {});\n setClipboard(instance);\n return () => setClipboard(null);\n }, [resolved, layerId, pasteOffset]);\n\n return <ClipboardContext.Provider value={clipboard}>{children}</ClipboardContext.Provider>;\n}\n","import { useCallback, useEffect, useMemo, useState, type ReactNode } from 'react';\n\nimport { ToolContext, type GraphTool, type ToolContextValue } from '../ToolContext';\n\nexport interface GraphToolProviderProps {\n /** Tool active on mount. Default `'select'`. */\n defaultTool?: GraphTool;\n /** Node kind the Add tool drops first. Default `'circle'`. */\n defaultNodeKind?: string;\n /**\n * Pressing <kbd>Esc</kbd> returns to the `'select'` tool (cancelling any\n * in-progress draw). Default `true`. Set `false` to handle Esc yourself.\n */\n escapeToSelect?: boolean;\n children?: ReactNode;\n}\n\n/**\n * Holds the active modelling {@link GraphTool} + node kind and provides them via\n * {@link ToolContext}. The modeller equivalent of `<GraphHistoryProvider>`:\n * descendant `useTool` / `<ModellerToolbar>` read and switch the tool; the\n * consumer gates its drawing behaviours' `enabled` on `useTool().tool`.\n *\n * Place it anywhere above both the toolbar and the `<Canvas>` (it owns no engine\n * reference — it's pure React state), typically wrapping the whole modeller.\n */\nexport function GraphToolProvider({\n defaultTool = 'select',\n defaultNodeKind = 'circle',\n escapeToSelect = true,\n children,\n}: GraphToolProviderProps) {\n const [tool, setTool] = useState<GraphTool>(defaultTool);\n const [nodeKind, setNodeKind] = useState<string>(defaultNodeKind);\n\n // Esc → back to the neutral Select tool (the draw behaviours' onDisable\n // cancels any in-flight gesture when their `enabled` flips off).\n const reset = useCallback(() => setTool('select'), []);\n useEffect(() => {\n if (!escapeToSelect) return;\n const onKey = (e: KeyboardEvent): void => {\n if (e.key === 'Escape') reset();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [escapeToSelect, reset]);\n\n const value = useMemo<ToolContextValue>(\n () => ({ tool, setTool, nodeKind, setNodeKind }),\n [tool, nodeKind],\n );\n\n return <ToolContext.Provider value={value}>{children}</ToolContext.Provider>;\n}\n","import { useEffect, useRef } from 'react';\nimport {\n GraphLayer as EngineGraphLayer,\n type GraphData,\n type GraphLayerOptions,\n} from '@invana/graph';\n\nimport { useCanvas } from '../CanvasContext';\n\nexport interface GraphLayerProps extends Omit<GraphLayerOptions, 'store'> {\n /** Layer id; default `'graph'`. Changing this remounts the layer. */\n id?: string;\n /**\n * Graph data — nodes + edges. Reactive: when this prop changes the wrapper\n * calls `layer.setData(data)`, which clears and refills the store in one\n * batch. Pass `undefined` to skip the initial data load.\n */\n data?: GraphData;\n /**\n * Pre-built `GraphStore`. Forwarded to the engine layer. Init-only.\n */\n store?: GraphLayerOptions['store'];\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `GraphLayer`.\n *\n * Init-only: `id`, `node`, `edge`, `useDefaultStates`, `store`, etc. — change\n * the `id` (or the component's `key`) to recreate with new options.\n *\n * Reactive: `data`. The wrapper calls `layer.setData(data)` whenever the\n * referenced `GraphData` object changes — make sure the prop is a stable\n * reference between renders unless you actually want a re-load.\n */\nexport function GraphLayer({ id = 'graph', data, store, ...rest }: GraphLayerProps) {\n const canvas = useCanvas();\n const layerRef = useRef<EngineGraphLayer | null>(null);\n\n useEffect(() => {\n const layer = new EngineGraphLayer({\n id,\n options: { ...(rest as GraphLayerOptions), ...(store ? { store } : {}) },\n });\n canvas.layers.add(layer);\n layerRef.current = layer;\n return () => {\n canvas.layers.remove(id);\n layerRef.current = null;\n };\n // Other options are init-only; remount via `id` / `key` to change them.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, id]);\n\n useEffect(() => {\n if (data && layerRef.current) {\n layerRef.current.setData(data);\n }\n }, [data]);\n\n return null;\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport {\n BackgroundLayer as EngineBackgroundLayer,\n type BackgroundLayerOptions,\n} from '@invana/canvas';\n\nimport { useCanvas } from '../CanvasContext';\n\nexport interface BackgroundLayerProps extends BackgroundLayerOptions {\n /** Layer id; default `'background'`. Changing this remounts the layer. */\n id?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/canvas` `BackgroundLayer`.\n *\n * Reactive: all style options (`type`, `patternType`, `color`,\n * `backgroundColor`, `size`, `spacing`, `alpha`, `followCamera`, `mode`) — a\n * change calls `layer.setOptions(...)` and re-renders in place (no remount).\n * Only `id` forces a remount.\n */\nexport function BackgroundLayer({ id = 'background', ...options }: BackgroundLayerProps) {\n const canvas = useCanvas();\n const layerRef = useRef<EngineBackgroundLayer | null>(null);\n\n useEffect(() => {\n const layer = new EngineBackgroundLayer({ id, options });\n canvas.layers.add(layer);\n layerRef.current = layer;\n return () => {\n canvas.layers.remove(id);\n layerRef.current = null;\n };\n // Options are applied reactively below; only `id` recreates the layer.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, id]);\n\n // Re-apply options whenever any value changes. Keyed on a serialised\n // snapshot so a new-but-equal `options` object doesn't trigger a re-render.\n const optionsKey = useMemo(() => JSON.stringify(options), [options]);\n useEffect(() => {\n layerRef.current?.setOptions(options);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n return null;\n}\n","import { useEffect, useMemo, useRef } from 'react';\nimport { MiniMapLayer as EngineMiniMapLayer, type MiniMapLayerOptions } from '@invana/graph';\n\nimport { useCanvas } from '../CanvasContext';\n\nexport interface MiniMapLayerProps extends Omit<MiniMapLayerOptions, 'graphLayerId'> {\n /** Layer id; default `'minimap'`. Changing this remounts the layer. */\n id?: string;\n /** Source `GraphLayer` id this minimap mirrors; default `'graph'`. */\n graphLayerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `MiniMapLayer`.\n *\n * Mount/unmount toggles visibility — conditionally render this component\n * (`{showMinimap && <MiniMapLayer/>}`) to show/hide the minimap.\n *\n * Reactive: appearance options (size, colours, viewport indicator, position,\n * margin) via `layer.setOptions(...)`. `id` and `graphLayerId` are identity —\n * changing either remounts.\n */\nexport function MiniMapLayer({\n id = 'minimap',\n graphLayerId = 'graph',\n ...options\n}: MiniMapLayerProps) {\n const canvas = useCanvas();\n const layerRef = useRef<EngineMiniMapLayer | null>(null);\n\n useEffect(() => {\n const layer = new EngineMiniMapLayer({ id, options: { graphLayerId, ...options } });\n canvas.layers.add(layer);\n layerRef.current = layer;\n return () => {\n canvas.layers.remove(id);\n layerRef.current = null;\n };\n // Appearance options are applied reactively below; identity recreates.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, id, graphLayerId]);\n\n const optionsKey = useMemo(() => JSON.stringify(options), [options]);\n useEffect(() => {\n layerRef.current?.setOptions(options);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optionsKey]);\n\n return null;\n}\n","import { useEffect } from 'react';\nimport type { IBehaviour } from '@invana/canvas';\n\nimport { useCanvas } from '../CanvasContext';\n\n/**\n * Shared registration lifecycle for behaviour wrappers. One place owns the two\n * effects every wrapper needs:\n *\n * 1. **Register / unregister** keyed on `identity` (the behaviour `id`, plus\n * `layerId` for layer-scoped behaviours). Construction options are read once\n * via `create()` — change an identity value (or the component `key`) to\n * recreate with new options.\n * 2. **Reactive `enabled`** — toggles via `canvas.behaviours.setEnabled(id, …)`\n * whenever the `enabled` prop changes, *without* re-registering. This is\n * what lets a toolbar flip a behaviour on/off declaratively.\n *\n * `setEnabled` no-ops on an unknown id and on a no-op state change, and effects\n * run top-down, so the register effect has always run before the enable effect.\n *\n * @param create Factory that constructs the engine behaviour from current props.\n * @param id Behaviour id (used for unregister + setEnabled).\n * @param enabled Desired enabled state; reconciled on every change.\n * @param identity Values that force a recreate when changed (e.g. `[id]` or `[id, layerId]`).\n */\nexport function useBehaviourRegistration(\n create: () => IBehaviour,\n id: string,\n enabled: boolean,\n identity: readonly unknown[],\n): void {\n const canvas = useCanvas();\n\n useEffect(() => {\n const behaviour = create();\n canvas.behaviours.register(behaviour);\n return () => {\n canvas.behaviours.unregister(id);\n };\n // `create` closes over init-only options; recreate only on identity change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, ...identity]);\n\n useEffect(() => {\n canvas.behaviours.setEnabled(id, enabled);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, enabled, ...identity]);\n}\n","import {\n DragPanBehaviour as EngineDragPanBehaviour,\n type DragPanBehaviourOptions,\n} from '@invana/canvas';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface DragPanBehaviourProps extends Omit<DragPanBehaviourOptions, 'id'> {\n /** Behaviour id; default `'pan'`. Changing this remounts the behaviour. */\n id?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/canvas` `DragPanBehaviour`.\n *\n * `enabled` is reactive (toggles in place). Other options are init-only —\n * change `id` or the component `key` to recreate with new options.\n */\nexport function DragPanBehaviour({ id = 'pan', enabled = true, ...rest }: DragPanBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineDragPanBehaviour({ id, enabled, ...rest }),\n id,\n enabled,\n [id],\n );\n return null;\n}\n","import {\n WheelZoomBehaviour as EngineWheelZoomBehaviour,\n type WheelZoomBehaviourOptions,\n} from '@invana/canvas';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface WheelZoomBehaviourProps extends Omit<WheelZoomBehaviourOptions, 'id'> {\n /** Behaviour id; default `'zoom'`. Changing this remounts the behaviour. */\n id?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/canvas` `WheelZoomBehaviour`.\n *\n * `enabled` is reactive (toggles in place). Other options are init-only —\n * change `id` or the component `key` to recreate.\n */\nexport function WheelZoomBehaviour({\n id = 'zoom',\n enabled = true,\n ...rest\n}: WheelZoomBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineWheelZoomBehaviour({ id, enabled, ...rest }),\n id,\n enabled,\n [id],\n );\n return null;\n}\n","import {\n PinchZoomBehaviour as EnginePinchZoomBehaviour,\n type PinchZoomBehaviourOptions,\n} from '@invana/canvas';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface PinchZoomBehaviourProps extends Omit<PinchZoomBehaviourOptions, 'id'> {\n /** Behaviour id; default `'pinch'`. Changing this remounts the behaviour. */\n id?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/canvas` `PinchZoomBehaviour`\n * (two-finger / trackpad pinch zoom).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `key`.\n */\nexport function PinchZoomBehaviour({\n id = 'pinch',\n enabled = true,\n ...rest\n}: PinchZoomBehaviourProps) {\n useBehaviourRegistration(\n () => new EnginePinchZoomBehaviour({ id, enabled, ...rest }),\n id,\n enabled,\n [id],\n );\n return null;\n}\n","import {\n KeyboardCameraInputBehaviour as EngineKeyboardCameraInputBehaviour,\n type KeyboardCameraInputBehaviourOptions,\n} from '@invana/canvas';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface KeyboardCameraInputBehaviourProps\n extends Omit<KeyboardCameraInputBehaviourOptions, 'id'> {\n /** Behaviour id; default `'keyboard-camera'`. Changing this remounts the behaviour. */\n id?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/canvas` `KeyboardCameraInputBehaviour`\n * (arrow-key pan, +/- zoom, 0 reset).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `key`.\n */\nexport function KeyboardCameraInputBehaviour({\n id = 'keyboard-camera',\n enabled = true,\n ...rest\n}: KeyboardCameraInputBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineKeyboardCameraInputBehaviour({ id, enabled, ...rest }),\n id,\n enabled,\n [id],\n );\n return null;\n}\n","import {\n DragNodeBehaviour as EngineDragNodeBehaviour,\n type DragNodeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface DragNodeBehaviourProps extends Omit<DragNodeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'drag-node'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id whose nodes this behaviour drags; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `DragNodeBehaviour`.\n *\n * `enabled` is reactive (toggles in place). Other options are init-only —\n * change `id` / `layerId` (or the `key`) to recreate.\n */\nexport function DragNodeBehaviour({\n id = 'drag-node',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: DragNodeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineDragNodeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n ContextMenuBehaviour as EngineContextMenuBehaviour,\n type ContextMenuBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface ContextMenuBehaviourProps\n extends Omit<ContextMenuBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'context-menu'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id whose nodes/edges this behaviour watches; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `ContextMenuBehaviour`.\n *\n * Headless — pass `onContextMenu` to receive node/edge/canvas right-click\n * events and render your own menu. `enabled` is reactive (toggles in place);\n * other options are init-only — change `id` / `layerId` (or the `key`) to\n * recreate.\n */\nexport function ContextMenuBehaviour({\n id = 'context-menu',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: ContextMenuBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineContextMenuBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n CreateNodeBehaviour as EngineCreateNodeBehaviour,\n type CreateNodeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface CreateNodeBehaviourProps\n extends Omit<CreateNodeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'create-node'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour adds nodes to; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `CreateNodeBehaviour` — click empty\n * canvas to add a node.\n *\n * `enabled` is reactive (toggle it from a tool-mode switch); other options are\n * init-only — change `id` / `layerId` (or the `key`) to recreate.\n */\nexport function CreateNodeBehaviour({\n id = 'create-node',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: CreateNodeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineCreateNodeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n DrawEdgeBehaviour as EngineDrawEdgeBehaviour,\n type DrawEdgeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface DrawEdgeBehaviourProps extends Omit<DrawEdgeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'draw-edge'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour draws edges in; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `DrawEdgeBehaviour` — drag from a\n * source node to a target node to create an edge (rubber-band preview).\n *\n * `enabled` is reactive (toggle it from a tool-mode switch). Don't enable this\n * and `DragNodeBehaviour` at once — both start on node pointer-down. Other\n * options are init-only — change `id` / `layerId` (or the `key`) to recreate.\n */\nexport function DrawEdgeBehaviour({\n id = 'draw-edge',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: DrawEdgeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineDrawEdgeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n EraseBehaviour as EngineEraseBehaviour,\n type EraseBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface EraseBehaviourProps extends Omit<EraseBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'erase'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour erases from; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `EraseBehaviour` — click a node\n * (cascades its edges) or an edge to delete it.\n *\n * `enabled` is reactive (toggle it from a tool-mode switch); other options are\n * init-only — change `id` / `layerId` (or the `key`) to recreate. Pair `onErase`\n * with `useDrawHistory().onErase` to make deletes undoable.\n */\nexport function EraseBehaviour({\n id = 'erase',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: EraseBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineEraseBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n HoverActivateBehaviour as EngineHoverActivateBehaviour,\n type HoverActivateBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface HoverActivateBehaviourProps\n extends Omit<HoverActivateBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'hover'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `HoverActivateBehaviour`.\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function HoverActivateBehaviour({\n id = 'hover',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: HoverActivateBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineHoverActivateBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n ClickSelectBehaviour as EngineClickSelectBehaviour,\n type ClickSelectBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface ClickSelectBehaviourProps\n extends Omit<ClickSelectBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'click-select'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `ClickSelectBehaviour`.\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function ClickSelectBehaviour({\n id = 'click-select',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: ClickSelectBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineClickSelectBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n ClickInspectBehaviour as EngineClickInspectBehaviour,\n type ClickInspectBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface ClickInspectBehaviourProps\n extends Omit<ClickInspectBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'click-inspect'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour reads clicks from; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `ClickInspectBehaviour` — tracks the\n * single node/edge clicked for editing, decoupled from selection. Pair with\n * `<InspectorPanel>` (which reads this behaviour's target by id).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function ClickInspectBehaviour({\n id = 'click-inspect',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: ClickInspectBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineClickInspectBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n BrushSelectBehaviour as EngineBrushSelectBehaviour,\n type BrushSelectBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface BrushSelectBehaviourProps\n extends Omit<BrushSelectBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'brush-select'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `BrushSelectBehaviour`\n * (rectangular rubber-band selection).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function BrushSelectBehaviour({\n id = 'brush-select',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: BrushSelectBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineBrushSelectBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n LassoSelectBehaviour as EngineLassoSelectBehaviour,\n type LassoSelectBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface LassoSelectBehaviourProps\n extends Omit<LassoSelectBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'lasso-select'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `LassoSelectBehaviour`\n * (freeform polygon selection).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function LassoSelectBehaviour({\n id = 'lasso-select',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: LassoSelectBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineLassoSelectBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n CollapseExpandBehaviour as EngineCollapseExpandBehaviour,\n type CollapseExpandBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface CollapseExpandBehaviourProps\n extends Omit<CollapseExpandBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'collapse-expand'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `CollapseExpandBehaviour`\n * (click a group's +/- toggle to collapse/expand).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function CollapseExpandBehaviour({\n id = 'collapse-expand',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: CollapseExpandBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineCollapseExpandBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n NodeResizeBehaviour as EngineNodeResizeBehaviour,\n type NodeResizeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface NodeResizeBehaviourProps\n extends Omit<NodeResizeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'node-resize'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `NodeResizeBehaviour`\n * (drag corner handles to resize a node).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function NodeResizeBehaviour({\n id = 'node-resize',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: NodeResizeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineNodeResizeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n LabelCollisionBehaviour as EngineLabelCollisionBehaviour,\n type LabelCollisionBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface LabelCollisionBehaviourProps\n extends Omit<LabelCollisionBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'label-collision'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `LabelCollisionBehaviour`\n * (hide/show overlapping labels by priority).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function LabelCollisionBehaviour({\n id = 'label-collision',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: LabelCollisionBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineLabelCollisionBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n LabelResolutionLODBehaviour as EngineLabelResolutionLODBehaviour,\n type LabelResolutionLODBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface LabelResolutionLODBehaviourProps\n extends Omit<LabelResolutionLODBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'label-lod'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `LabelResolutionLODBehaviour`\n * (show/hide labels by camera zoom tier).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function LabelResolutionLODBehaviour({\n id = 'label-lod',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: LabelResolutionLODBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineLabelResolutionLODBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n NodeSizeLODBehaviour as EngineNodeSizeLODBehaviour,\n type NodeSizeLODBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface NodeSizeLODBehaviourProps\n extends Omit<NodeSizeLODBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'node-size-lod'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `NodeSizeLODBehaviour`\n * (rescale node sizes per camera zoom).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function NodeSizeLODBehaviour({\n id = 'node-size-lod',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: NodeSizeLODBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineNodeSizeLODBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n EdgeSizeLODBehaviour as EngineEdgeSizeLODBehaviour,\n type EdgeSizeLODBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface EdgeSizeLODBehaviourProps\n extends Omit<EdgeSizeLODBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'edge-size-lod'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `EdgeSizeLODBehaviour`\n * (rescale edge stroke widths per camera zoom).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function EdgeSizeLODBehaviour({\n id = 'edge-size-lod',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: EdgeSizeLODBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineEdgeSizeLODBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n ParallelEdgeBehaviour as EngineParallelEdgeBehaviour,\n type ParallelEdgeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface ParallelEdgeBehaviourProps\n extends Omit<ParallelEdgeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'parallel-edge'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `ParallelEdgeBehaviour`\n * (fan out edges that share the same source/target pair).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function ParallelEdgeBehaviour({\n id = 'parallel-edge',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: ParallelEdgeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineParallelEdgeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n DegreeSizeBehaviour as EngineDegreeSizeBehaviour,\n type DegreeSizeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface DegreeSizeBehaviourProps\n extends Omit<DegreeSizeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'degree-size'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour drives; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `DegreeSizeBehaviour`\n * (size nodes by in/out degree).\n *\n * `enabled` is reactive; other options are init-only — change `id` / `layerId`.\n */\nexport function DegreeSizeBehaviour({\n id = 'degree-size',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: DegreeSizeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineDegreeSizeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import {\n ResponsiveThemeBehaviour as EngineResponsiveThemeBehaviour,\n type ResponsiveThemeBehaviourOptions,\n} from '@invana/graph';\n\nimport { useBehaviourRegistration } from './useBehaviourRegistration';\n\nexport interface ResponsiveThemeBehaviourProps\n extends Omit<ResponsiveThemeBehaviourOptions, 'id' | 'layerId'> {\n /** Behaviour id; default `'responsive-theme'`. Changing this remounts the behaviour. */\n id?: string;\n /** GraphLayer id this behaviour themes; default `'graph'`. */\n layerId?: string;\n}\n\n/**\n * Declarative wrapper for `@invana/graph` `ResponsiveThemeBehaviour`.\n *\n * Keeps the graph's theme-dependent node / edge styling in sync with the host's\n * `prefers-color-scheme` (or a pinned `mode`). `enabled` is reactive; the\n * `node` / `edge` / `mode` options are init-only — change `id` / `layerId` (or\n * the component `key`) to recreate with new variants.\n */\nexport function ResponsiveThemeBehaviour({\n id = 'responsive-theme',\n layerId = 'graph',\n enabled = true,\n ...rest\n}: ResponsiveThemeBehaviourProps) {\n useBehaviourRegistration(\n () => new EngineResponsiveThemeBehaviour({ id, layerId, enabled, ...rest }),\n id,\n enabled,\n [id, layerId],\n );\n return null;\n}\n","import { useEffect } from 'react';\nimport { D3ForceLayout as EngineD3ForceLayout } from '@invana/graph-layout-d3-force';\nimport type { GraphLayer as EngineGraphLayer } from '@invana/graph';\n\nimport { useCanvas } from '../CanvasContext';\n\n// The layout package's option type isn't re-exported as a value, so we mirror\n// its shape via the constructor parameter to stay decoupled.\ntype D3ForceLayoutCtorOptions = ConstructorParameters<typeof EngineD3ForceLayout>[0];\n\nexport interface D3ForceLayoutProps {\n /**\n * Id of the `<GraphLayer>` this layout drives. Default `'graph'`. The\n * wrapper looks the layer up at mount time; if it isn't registered yet,\n * mount the layout *after* the layer in JSX order.\n */\n targetLayerId?: string;\n /**\n * Padding in screen pixels for the auto-fit that runs when the simulation\n * settles. `null` disables auto-fit. Default `80`.\n */\n fitPadding?: number | null;\n /** D3ForceLayout constructor options (`charge`, `link`, `center`, …). */\n options?: D3ForceLayoutCtorOptions;\n}\n\n/**\n * Declarative wrapper for `@invana/graph-layout-d3-force` `D3ForceLayout`.\n *\n * Mount: builds a new layout, wires `end → camera.fitContent(...)` (unless\n * `fitPadding` is `null`), then calls `layout.apply(layer)`.\n *\n * Unmount: `layout.stop()`. The simulation cancels and emits its final\n * `end` event with `reason: 'stopped'`.\n *\n * All inputs are init-only — remount with a new `key` to reseed the sim.\n */\nexport function D3ForceLayout({\n targetLayerId = 'graph',\n fitPadding = 80,\n options,\n}: D3ForceLayoutProps) {\n const canvas = useCanvas();\n\n useEffect(() => {\n const layer = canvas.layers.get<EngineGraphLayer>(targetLayerId);\n if (!layer) {\n // eslint-disable-next-line no-console\n console.warn(\n `[canvas-react] <D3ForceLayout> could not find layer \"${targetLayerId}\". Make sure the corresponding <GraphLayer> is mounted earlier in the JSX tree.`,\n );\n return;\n }\n\n const layout = new EngineD3ForceLayout(options);\n if (fitPadding != null) {\n layout.events.on('end', () => {\n canvas.camera.fitContent(layer.getBounds(), fitPadding);\n });\n }\n void layout.apply(layer);\n\n return () => {\n layout.stop();\n };\n // Re-run when the target layer id changes; option object changes do not\n // re-seed (remount via key for that).\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [canvas, targetLayerId]);\n\n return null;\n}\n","import { useMemo } from 'react';\nimport type { Canvas as EngineCanvas, Rect } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\n/** Default multiplicative step for one zoom-in / zoom-out tick. */\nconst DEFAULT_ZOOM_STEP = 1.2;\n\nexport interface UseCameraResult {\n /** Multiply scale by `factor` (default 1.2), anchored at the viewport centre. */\n zoomIn: (factor?: number) => void;\n /** Divide scale by `factor` (default 1.2), anchored at the viewport centre. */\n zoomOut: (factor?: number) => void;\n /** Set an absolute scale, anchored at the viewport centre. */\n setZoom: (scale: number) => void;\n /** Set an absolute scale around an arbitrary screen point (defaults to centre). */\n zoomTo: (scale: number, centerX?: number, centerY?: number) => void;\n /** Pan by `(dx, dy)` screen pixels. */\n pan: (dx: number, dy: number) => void;\n /** Fit a world-space rectangle into the viewport. */\n fitContent: (worldRect: Rect, padding?: number) => void;\n /** Read the current uniform scale (does not subscribe — use `useZoom` for live state). */\n getZoom: () => number;\n}\n\n/**\n * Imperative camera actions for the resolved canvas — the wiring the\n * GraphVisualiser story used to hand-write inline (`camera.zoomAt(1.2)` etc.),\n * promoted to a reusable, multi-canvas-safe hook. Pure actions, no\n * subscriptions; callbacks are stable per resolved `canvas`. For a live zoom\n * value that re-renders, use {@link useZoom}.\n *\n * @param canvas Optional explicit instance; defaults to the context canvas.\n */\nexport function useCamera(canvas?: EngineCanvas | null): UseCameraResult {\n const resolved = useResolvedCanvas(canvas);\n\n return useMemo<UseCameraResult>(() => {\n const camera = resolved.camera;\n return {\n zoomIn: (factor = DEFAULT_ZOOM_STEP) => camera.zoomAt(factor),\n zoomOut: (factor = DEFAULT_ZOOM_STEP) => camera.zoomAt(1 / factor),\n setZoom: (scale) => camera.setZoom(scale),\n zoomTo: (scale, centerX, centerY) =>\n camera.zoomAt(scale / camera.scale, centerX, centerY),\n pan: (dx, dy) => camera.pan(dx, dy),\n fitContent: (worldRect, padding) => camera.fitContent(worldRect, padding),\n getZoom: () => camera.scale,\n };\n }, [resolved]);\n}\n","import { useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useCamera } from './useCamera';\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nexport interface UseZoomResult {\n /** Live uniform scale — re-renders whenever the camera zooms (interactively or programmatically). */\n zoom: number;\n zoomIn: (factor?: number) => void;\n zoomOut: (factor?: number) => void;\n setZoom: (scale: number) => void;\n zoomTo: (scale: number, centerX?: number, centerY?: number) => void;\n}\n\n/**\n * Live zoom state + zoom actions for the resolved canvas. Subscribes to\n * `camera:zoom`, so the returned `zoom` tracks wheel / pinch / programmatic\n * zoom and re-renders the component.\n *\n * Multi-canvas-safe: the subscription effect is keyed on the resolved instance,\n * so two `<Canvas>` trees (or two explicit instances) never share zoom state.\n *\n * @param canvas Optional explicit instance; defaults to the context canvas.\n */\nexport function useZoom(canvas?: EngineCanvas | null): UseZoomResult {\n const resolved = useResolvedCanvas(canvas);\n const { zoomIn, zoomOut, setZoom, zoomTo } = useCamera(resolved);\n const [zoom, setZoomState] = useState(() => resolved.camera.scale);\n\n useEffect(() => {\n // Resync immediately in case the resolved instance changed under us.\n setZoomState(resolved.camera.scale);\n return resolved.events.on('camera:zoom', ({ scale }) => setZoomState(scale));\n }, [resolved]);\n\n return { zoom, zoomIn, zoomOut, setZoom, zoomTo };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas, Rect } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\n/** Default padding (screen px) around the fitted content. */\nconst DEFAULT_FIT_PADDING = 80;\n\n/** Structural shape of a world layer that can report its content bounds. */\ninterface BoundedLayer {\n getBounds(): Rect;\n}\n\nfunction hasGetBounds(layer: unknown): layer is BoundedLayer {\n return typeof (layer as BoundedLayer | undefined)?.getBounds === 'function';\n}\n\nexport interface UseFitContentResult {\n /** Fit the viewport to the target layer's content bounds. No-op until the layer exists. */\n fitContent: (padding?: number) => void;\n /** Whether the target layer is currently mounted (drives e.g. button disabled state). */\n hasContent: boolean;\n}\n\n/**\n * Fit-to-content (zoom-to-extent) for a specific layer on the resolved canvas.\n * The layer is resolved lazily *inside* the returned callback, so the hook\n * tolerates the layer mounting after the hook runs (common, since layer\n * wrappers register in effects). `hasContent` tracks layer mount/unmount via\n * the `layer:added` / `layer:removed` canvas events.\n *\n * @param layerId Target layer id (e.g. `'graph'`).\n * @param canvas Optional explicit instance; defaults to the context canvas.\n */\nexport function useFitContent(\n layerId: string,\n canvas?: EngineCanvas | null,\n): UseFitContentResult {\n const resolved = useResolvedCanvas(canvas);\n const [hasContent, setHasContent] = useState(() => resolved.layers.has(layerId));\n\n useEffect(() => {\n const sync = () => setHasContent(resolved.layers.has(layerId));\n sync();\n const offAdded = resolved.events.on('layer:added', sync);\n const offRemoved = resolved.events.on('layer:removed', sync);\n return () => {\n offAdded();\n offRemoved();\n };\n }, [resolved, layerId]);\n\n const fitContent = useCallback(\n (padding = DEFAULT_FIT_PADDING) => {\n const layer = resolved.layers.get(layerId);\n if (hasGetBounds(layer)) {\n resolved.camera.fitContent(layer.getBounds(), padding);\n }\n },\n [resolved, layerId],\n );\n\n return { fitContent, hasContent };\n}\n","import { useEffect, useRef } from 'react';\nimport type { Canvas as EngineCanvas, CanvasGlobalEvents } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\n/**\n * Subscribe to a typed canvas-wide event (`camera:zoom`, `camera:pan`,\n * `layer:added`, …) for the lifetime of the calling component. Fully typed off\n * the engine's exported {@link CanvasGlobalEvents} map.\n *\n * The handler is held in a ref so changing it between renders does **not** tear\n * down and re-create the subscription; only a change of the resolved `canvas`\n * (or the `event` name) does. That keeps subscriptions stable and — because the\n * effect is keyed on the resolved instance — correct across multiple canvases.\n *\n * @param event Event name from {@link CanvasGlobalEvents}.\n * @param handler Fired with the event payload.\n * @param canvas Optional explicit instance; defaults to the context canvas.\n */\nexport function useCanvasEvent<E extends keyof CanvasGlobalEvents>(\n event: E,\n handler: (payload: CanvasGlobalEvents[E]) => void,\n canvas?: EngineCanvas | null,\n): void {\n const resolved = useResolvedCanvas(canvas);\n const handlerRef = useRef(handler);\n handlerRef.current = handler;\n\n useEffect(() => {\n // `on` returns an unsubscribe fn — return it straight as the cleanup.\n return resolved.events.on(event, (payload) => handlerRef.current(payload));\n }, [resolved, event]);\n}\n","import { useCallback, useContext } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\nimport { HistoryContext } from '../HistoryContext';\n\n/** Structural guard — any layer that exposes a `clear()` method. */\ninterface ClearableLayer {\n clear(): void;\n}\n\n/** Structural shape of the store we read node ids off for an undoable clear. */\ninterface StorefulLayer {\n store?: { nodes(): IterableIterator<{ id: string }> };\n}\n\nfunction hasClear(layer: unknown): layer is ClearableLayer {\n return typeof (layer as ClearableLayer | undefined)?.clear === 'function';\n}\n\nexport interface UseClearGraphResult {\n /** Remove every node and edge from the target layer. No-op if the layer doesn't exist yet. */\n clear: () => void;\n}\n\n/**\n * Clear-graph action for a specific layer on the resolved canvas.\n *\n * When a `<GraphHistoryProvider>` is present, the clear runs as a single\n * undoable `history.transaction('clear', …)` — removing every node (edges\n * cascade) so Undo restores the whole graph and Redo clears it again. Without a\n * history provider it falls back to the layer's fast `clear()`.\n *\n * Uses structural duck-types (`clear()` / `store.nodes()`) so it works with any\n * compatible layer without a hard `@invana/graph` import.\n *\n * @param layerId Target layer id (e.g. `'graph'`).\n * @param canvas Optional explicit instance; defaults to the context canvas.\n */\nexport function useClearGraph(\n layerId: string,\n canvas?: EngineCanvas | null,\n): UseClearGraphResult {\n const resolved = useResolvedCanvas(canvas);\n const history = useContext(HistoryContext);\n\n const clear = useCallback(() => {\n const layer = resolved.layers.get(layerId);\n if (!hasClear(layer)) return;\n\n const store = (layer as StorefulLayer).store;\n if (history && store) {\n // Snapshot ids first — removing mutates the store mid-iteration. Removing\n // every node cascades all incident edges, captured in each removeNode op,\n // so Undo re-adds nodes + edges as one entry.\n const ids = [...store.nodes()].map((n) => n.id);\n if (ids.length > 0) {\n history.transaction('clear', (rec) => {\n for (const id of ids) rec.removeNode(id);\n });\n return;\n }\n }\n\n layer.clear();\n }, [resolved, layerId, history]);\n\n return { clear };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { ClickSelectBehaviour } from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nexport interface UseSelectionOptions {\n /** Id of the `ClickSelectBehaviour` to read selection from. Default `'click-select'`. */\n clickSelectId?: string;\n}\n\nexport interface UseSelectionResult {\n /** Currently selected node ids. */\n selectedNodeIds: string[];\n /** Currently selected edge ids. */\n selectedEdgeIds: string[];\n /** Total selected (nodes + edges). */\n count: number;\n /** Clear the selection. */\n clear: () => void;\n}\n\n/**\n * Reactive view of the current graph selection, driven by a\n * `ClickSelectBehaviour`'s `selection:change` event (brush/lasso flow through it\n * by delegation, so all three selection modes are covered by this one hook).\n *\n * Requires a registered `ClickSelectBehaviour`; if absent, the selection is\n * empty and `clear` is a no-op.\n */\nexport function useSelection(\n options: UseSelectionOptions = {},\n canvas?: EngineCanvas | null,\n): UseSelectionResult {\n const { clickSelectId = 'click-select' } = options;\n const resolved = useResolvedCanvas(canvas);\n const [selectedNodeIds, setNodeIds] = useState<string[]>([]);\n const [selectedEdgeIds, setEdgeIds] = useState<string[]>([]);\n\n useEffect(() => {\n const behaviour = resolved.behaviours.get<ClickSelectBehaviour>(clickSelectId);\n if (!behaviour) {\n setNodeIds([]);\n setEdgeIds([]);\n return;\n }\n setNodeIds(behaviour.getSelectedShapeIds());\n setEdgeIds(behaviour.getSelectedConnectorIds());\n return behaviour.events.on('selection:change', (snapshot) => {\n setNodeIds(snapshot.shapeIds);\n setEdgeIds(snapshot.connectorIds);\n });\n }, [resolved, clickSelectId]);\n\n const clear = useCallback(() => {\n resolved.behaviours.get<ClickSelectBehaviour>(clickSelectId)?.clearSelection();\n }, [resolved, clickSelectId]);\n\n return {\n selectedNodeIds,\n selectedEdgeIds,\n count: selectedNodeIds.length + selectedEdgeIds.length,\n clear,\n };\n}\n","import { useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { ClickInspectBehaviour, InspectTarget } from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nexport interface UseInspectTargetOptions {\n /** Id of the `ClickInspectBehaviour` to read the target from. Default `'click-inspect'`. */\n inspectId?: string;\n}\n\n/**\n * Reactive view of the single node/edge currently targeted for editing, driven\n * by a `ClickInspectBehaviour`'s `inspect:change` event. Returns `null` when no\n * element is targeted (or the behaviour isn't registered).\n *\n * Distinct from {@link useSelection}: selection can hold many elements (for\n * highlighting / multi-drag), whereas this is always the *one* element a\n * property editor should edit.\n */\nexport function useInspectTarget(\n options: UseInspectTargetOptions = {},\n canvas?: EngineCanvas | null,\n): InspectTarget | null {\n const { inspectId = 'click-inspect' } = options;\n const resolved = useResolvedCanvas(canvas);\n const [target, setTarget] = useState<InspectTarget | null>(null);\n\n useEffect(() => {\n const behaviour = resolved.behaviours.get<ClickInspectBehaviour>(inspectId);\n if (!behaviour) {\n setTarget(null);\n return;\n }\n setTarget(behaviour.getTarget());\n return behaviour.events.on('inspect:change', setTarget);\n }, [resolved, inspectId]);\n\n return target;\n}\n","import { useCallback, useContext, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\nimport { HistoryContext } from '../HistoryContext';\n\nexport interface UseHistoryOptions {\n /** Layer id whose `redraw()` the `redraw` action targets. Default `'graph'`. */\n layerId?: string;\n}\n\nexport interface UseHistoryResult {\n /** Revert the most recent change. No-op when `!canUndo`. */\n undo: () => void;\n /** Re-apply the most recently undone change. No-op when `!canRedo`. */\n redo: () => void;\n /** Force a full re-render of the target layer (render pass; not undoable). */\n redraw: () => void;\n canUndo: boolean;\n canRedo: boolean;\n}\n\ninterface RedrawableLayer {\n redraw(): void;\n}\n\nfunction hasRedraw(layer: unknown): layer is RedrawableLayer {\n return typeof (layer as RedrawableLayer | undefined)?.redraw === 'function';\n}\n\n/**\n * Undo/redo + redraw, wired to the `GraphHistory` from a\n * `<GraphHistoryProvider>` ancestor. `canUndo`/`canRedo` stay reactive via the\n * history's `change` event. Without a provider, undo/redo are no-ops and the\n * flags are `false` (redraw still works — it goes straight to the layer).\n */\nexport function useHistory(\n options: UseHistoryOptions = {},\n canvas?: EngineCanvas | null,\n): UseHistoryResult {\n const { layerId = 'graph' } = options;\n const resolved = useResolvedCanvas(canvas);\n const history = useContext(HistoryContext);\n const [state, setState] = useState({ canUndo: false, canRedo: false });\n\n useEffect(() => {\n if (!history) {\n setState({ canUndo: false, canRedo: false });\n return;\n }\n setState({ canUndo: history.canUndo, canRedo: history.canRedo });\n return history.events.on('change', ({ canUndo, canRedo }) => setState({ canUndo, canRedo }));\n }, [history]);\n\n const undo = useCallback(() => history?.undo(), [history]);\n const redo = useCallback(() => history?.redo(), [history]);\n const redraw = useCallback(() => {\n const layer = resolved.layers.get(layerId);\n if (hasRedraw(layer)) layer.redraw();\n }, [resolved, layerId]);\n\n return { undo, redo, redraw, canUndo: state.canUndo, canRedo: state.canRedo };\n}\n","import { useCallback, useContext, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { ClickSelectBehaviour } from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\nimport { useSelection } from './useSelection';\nimport { ClipboardContext } from '../ClipboardContext';\nimport { HistoryContext } from '../HistoryContext';\n\nexport interface UseClipboardOptions {\n /** Id of the `ClickSelectBehaviour` selection is read from / re-applied to. Default `'click-select'`. */\n clickSelectId?: string;\n}\n\nexport interface UseClipboardResult {\n /** Copy the selection to the buffer, then delete it (one undoable step). */\n cut: () => void;\n /** Copy the selection to the buffer. */\n copy: () => void;\n /** Paste the buffer (offset + re-id'd) and select the pasted items. */\n paste: () => void;\n /** Delete the selection (one undoable step). */\n remove: () => void;\n /** True iff the buffer has content to paste. */\n canPaste: boolean;\n /** True iff something is selected. */\n hasSelection: boolean;\n}\n\n/**\n * Cut / copy / paste / delete for the current selection, wired to the\n * `GraphClipboard` from a `<GraphClipboardProvider>` ancestor. Operations route\n * through the `<GraphHistoryProvider>`'s history when present, so they're\n * undoable. Reads the selection (and re-selects pasted items) via a\n * `ClickSelectBehaviour`.\n *\n * `canPaste` tracks the buffer (recomputed after each op); `hasSelection` is\n * reactive via {@link useSelection}.\n */\nexport function useClipboard(\n options: UseClipboardOptions = {},\n canvas?: EngineCanvas | null,\n): UseClipboardResult {\n const { clickSelectId = 'click-select' } = options;\n const resolved = useResolvedCanvas(canvas);\n const clipboard = useContext(ClipboardContext);\n const history = useContext(HistoryContext);\n const { selectedNodeIds, selectedEdgeIds, count } = useSelection({ clickSelectId }, resolved);\n const [canPaste, setCanPaste] = useState(false);\n\n // Subscribe to the clipboard's buffer-change event so every `useClipboard`\n // instance stays in sync — e.g. the Paste button reacts to a Copy that\n // happened in a different button's hook instance.\n useEffect(() => {\n if (!clipboard) {\n setCanPaste(false);\n return;\n }\n setCanPaste(clipboard.hasContent);\n return clipboard.events.on('change', ({ hasContent }) => setCanPaste(hasContent));\n }, [clipboard]);\n\n const copy = useCallback(() => {\n clipboard?.copy(selectedNodeIds, selectedEdgeIds);\n }, [clipboard, selectedNodeIds, selectedEdgeIds]);\n\n const cut = useCallback(() => {\n clipboard?.cut(selectedNodeIds, selectedEdgeIds, history ?? undefined);\n }, [clipboard, history, selectedNodeIds, selectedEdgeIds]);\n\n const remove = useCallback(() => {\n clipboard?.delete(selectedNodeIds, selectedEdgeIds, history ?? undefined);\n }, [clipboard, history, selectedNodeIds, selectedEdgeIds]);\n\n const paste = useCallback(() => {\n if (!clipboard) return;\n const { nodeIds, edgeIds } = clipboard.paste(history ?? undefined);\n const behaviour = resolved.behaviours.get<ClickSelectBehaviour>(clickSelectId);\n behaviour?.selectMultiple([\n ...nodeIds.map((id) => ({ id, type: 'shape' as const })),\n ...edgeIds.map((id) => ({ id, type: 'connector' as const })),\n ]);\n }, [clipboard, history, resolved, clickSelectId]);\n\n return { cut, copy, paste, remove, canPaste, hasSelection: count > 0 };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas, BackgroundLayer, BackgroundLayerOptions } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\ntype PatternType = NonNullable<BackgroundLayerOptions['patternType']>;\n\nexport interface UseGridOptions {\n /** Id of the `BackgroundLayer` to toggle. Default `'background'`. */\n backgroundLayerId?: string;\n /**\n * Pattern to switch to when the grid is shown. When omitted, the layer's\n * existing `patternType` is preserved (only `type` is toggled).\n */\n patternType?: PatternType;\n}\n\nexport interface UseGridResult {\n /** Whether the background pattern (grid/dots/lines) is currently shown. */\n showGrid: boolean;\n /** Toggle the grid on/off. */\n toggleGrid: () => void;\n /** Set the grid on/off explicitly. */\n setGrid: (on: boolean) => void;\n}\n\n/**\n * Toggle a `BackgroundLayer`'s pattern on/off. \"Grid shown\" maps to\n * `type: 'pattern'`, \"hidden\" to `type: 'solid'`. Pass `patternType` to force a\n * specific pattern (e.g. `'grid'`) when turning it on; otherwise the layer's\n * configured pattern is kept.\n *\n * State is owned by the hook (the background layer emits no option-change event)\n * and seeded from `getOptions()` on mount.\n */\nexport function useGrid(\n options: UseGridOptions = {},\n canvas?: EngineCanvas | null,\n): UseGridResult {\n const { backgroundLayerId = 'background', patternType } = options;\n const resolved = useResolvedCanvas(canvas);\n const [showGrid, setShowGrid] = useState(false);\n\n useEffect(() => {\n const layer = resolved.layers.get<BackgroundLayer>(backgroundLayerId);\n if (layer) setShowGrid(layer.getOptions().type === 'pattern');\n }, [resolved, backgroundLayerId]);\n\n const setGrid = useCallback(\n (on: boolean) => {\n const layer = resolved.layers.get<BackgroundLayer>(backgroundLayerId);\n if (!layer) return;\n const next: Partial<BackgroundLayerOptions> = { type: on ? 'pattern' : 'solid' };\n if (on && patternType) next.patternType = patternType;\n layer.setOptions(next);\n setShowGrid(on);\n },\n [resolved, backgroundLayerId, patternType],\n );\n\n const toggleGrid = useCallback(() => setGrid(!showGrid), [setGrid, showGrid]);\n\n return { showGrid, toggleGrid, setGrid };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas, BackgroundLayer } from '@invana/canvas';\nimport type {\n ResponsiveThemeBehaviour,\n ThemeKind,\n ThemeMode,\n} from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nexport interface UseThemeOptions {\n /** Id of the `ResponsiveThemeBehaviour` to drive. Default `'responsive-theme'`. */\n behaviourId?: string;\n /**\n * Optional id of a `BackgroundLayer` to flip in lockstep. When set, switching\n * the theme also switches the background's `mode`, so the whole canvas changes\n * appearance together instead of the background staying on its own\n * `prefers-color-scheme`. Omit to leave the background alone.\n */\n backgroundLayerId?: string;\n /**\n * Called after the theme switches, with the new resolved kind + mode. Use it\n * to flip *app chrome* that lives outside the canvas (e.g. a design-system\n * `data-theme` attribute) so floating controls stay legible against the\n * canvas. The hook never touches chrome itself — that's app policy.\n */\n onChange?: (kind: ThemeKind, mode: ThemeMode) => void;\n}\n\nexport interface UseThemeResult {\n /** Current mode setting (`'auto' | 'light' | 'dark'`). */\n mode: ThemeMode;\n /** Concrete kind currently resolved (`'light' | 'dark'`). */\n kind: ThemeKind;\n /** Set the mode explicitly. `'auto'` re-follows `prefers-color-scheme`. */\n setMode: (mode: ThemeMode) => void;\n /** Flip between pinned light and dark, based on the current resolved kind. */\n toggle: () => void;\n}\n\n/**\n * Drive a registered `ResponsiveThemeBehaviour` (from `@invana/graph`) — read its\n * mode / resolved kind and switch it. Useful for a theme-toggle control.\n *\n * Pass `backgroundLayerId` to also flip a `BackgroundLayer`'s mode in lockstep so\n * the background switches with the graph content (otherwise the background keeps\n * following the OS `prefers-color-scheme` and dark-theme content can land on a\n * light background). Pass `onChange` to switch app chrome to match.\n *\n * State is owned by the hook (neither the behaviour nor the layer emits a\n * mode-change event) and seeded once they are registered. Each action looks the\n * targets up fresh, so it tolerates them mounting after this hook.\n */\nexport function useTheme(\n options: UseThemeOptions = {},\n canvas?: EngineCanvas | null,\n): UseThemeResult {\n const { behaviourId = 'responsive-theme', backgroundLayerId, onChange } = options;\n const resolved = useResolvedCanvas(canvas);\n const [mode, setModeState] = useState<ThemeMode>('auto');\n const [kind, setKindState] = useState<ThemeKind>('light');\n\n const getBehaviour = useCallback(\n () => resolved.behaviours.get<ResponsiveThemeBehaviour>(behaviourId),\n [resolved, behaviourId],\n );\n const getBackground = useCallback(\n () =>\n backgroundLayerId ? resolved.layers.get<BackgroundLayer>(backgroundLayerId) : undefined,\n [resolved, backgroundLayerId],\n );\n\n /** Read the live state of whichever target is present. */\n const read = useCallback((): { mode: ThemeMode; kind: ThemeKind } => {\n const source = getBehaviour() ?? getBackground();\n return {\n mode: source?.getMode() ?? 'auto',\n kind: source?.getResolvedKind() ?? 'light',\n };\n }, [getBehaviour, getBackground]);\n\n useEffect(() => {\n const { mode: m, kind: k } = read();\n setModeState(m);\n setKindState(k);\n }, [read]);\n\n const applyMode = useCallback(\n (next: ThemeMode) => {\n getBehaviour()?.setMode(next);\n getBackground()?.setMode(next);\n const { mode: m, kind: k } = read();\n setModeState(m);\n setKindState(k);\n onChange?.(k, m);\n },\n [getBehaviour, getBackground, read, onChange],\n );\n\n const setMode = useCallback((next: ThemeMode) => applyMode(next), [applyMode]);\n\n const toggle = useCallback(() => {\n applyMode(read().kind === 'dark' ? 'light' : 'dark');\n }, [applyMode, read]);\n\n return { mode, kind, setMode, toggle };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { GraphLayer as EngineGraphLayer } from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\n/** Minimal structural shape of a layout instance the hook can apply + stop. */\nexport interface ApplicableLayout {\n apply(layer: unknown): Promise<void> | void;\n stop?: () => void;\n}\n\n/** Factory producing a fresh layout instance per application. */\nexport type LayoutFactory = () => ApplicableLayout;\n\nexport interface UseLayoutOptions {\n /** Target `GraphLayer` id. Default `'graph'`. */\n layerId?: string;\n /** Padding for the post-layout `camera.fitContent`. Default `80`. */\n fitPadding?: number;\n /** Initially-selected key. Default: first key of `layouts`. */\n initial?: string;\n /** Optional key → human label map for the picker. Default: identity. */\n labels?: Record<string, string>;\n /** Apply the initial layout once the target layer is mounted. Default `true`. */\n applyInitial?: boolean;\n}\n\nexport interface UseLayoutResult {\n /** Currently-applied layout key. */\n layout: string;\n /** Key → label map for a picker. */\n layoutOptions: Record<string, string>;\n /** Apply the layout registered under `key`, then fit the view. */\n applyLayout: (key: string) => void;\n /** True while a layout's `apply` promise is in flight. */\n isRunning: boolean;\n}\n\n/**\n * Imperative layout switching, lifting the common \"instantiate → `apply(layer)`\n * → `camera.fitContent`\" pattern into a hook. Layouts live in separate packages\n * (`@invana/graph-layout-*`) with no registry, so the consumer supplies a map of\n * **factories**; this hook can't be turnkey.\n *\n * Memoize the `layouts` map (module scope or `useMemo`) so `applyLayout` stays\n * stable across renders.\n */\nexport function useLayout(\n layouts: Record<string, LayoutFactory>,\n options: UseLayoutOptions = {},\n canvas?: EngineCanvas | null,\n): UseLayoutResult {\n const { layerId = 'graph', fitPadding = 80 } = options;\n const resolved = useResolvedCanvas(canvas);\n const keys = Object.keys(layouts);\n const [layout, setLayout] = useState(options.initial ?? keys[0] ?? '');\n const [isRunning, setRunning] = useState(false);\n const activeRef = useRef<ApplicableLayout | null>(null);\n\n const applyLayout = useCallback(\n (key: string) => {\n const factory = layouts[key];\n const layer = resolved.layers.get<EngineGraphLayer>(layerId);\n if (!factory || !layer) return;\n activeRef.current?.stop?.();\n const instance = factory();\n activeRef.current = instance;\n setLayout(key);\n setRunning(true);\n Promise.resolve(instance.apply(layer))\n .then(() => {\n if (activeRef.current !== instance) return; // superseded by a newer apply\n resolved.camera.fitContent(layer.getBounds(), fitPadding);\n setRunning(false);\n })\n .catch(() => {\n if (activeRef.current === instance) setRunning(false);\n });\n },\n [layouts, resolved, layerId, fitPadding],\n );\n\n // Apply the initial layout once, as soon as the target layer is mounted.\n const didInit = useRef(false);\n const applyInitial = options.applyInitial ?? true;\n useEffect(() => {\n if (didInit.current || !applyInitial || !layout) return;\n if (!resolved.layers.has(layerId)) return; // retry on a later render\n didInit.current = true;\n applyLayout(layout);\n }, [resolved, layerId, layout, applyLayout, applyInitial]);\n\n const layoutOptions =\n options.labels ?? Object.fromEntries(keys.map((k) => [k, k]));\n\n return { layout, layoutOptions, applyLayout, isRunning };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nexport interface UseSelectModeOptions {\n /** Initially-active mode key. Default: first key of `behaviourIds`. */\n initial?: string;\n /** Optional key → human label map for a picker. Default: identity. */\n labels?: Record<string, string>;\n}\n\nexport interface UseSelectModeResult {\n /** Currently-active mode key. */\n mode: string;\n /** Key → label map for a picker. */\n modeOptions: Record<string, string>;\n /** Switch mode: enables that mode's behaviour, disables the others. */\n setMode: (mode: string) => void;\n}\n\n/**\n * Mutually-exclusive selection-mode switch. Maps mode keys to behaviour ids\n * (e.g. `{ click: 'click-select', brush: 'brush-select', lasso: 'lasso-select' }`)\n * and toggles their `enabled` so exactly one is active. The consumer must have\n * registered those behaviours; this hook can't be turnkey.\n *\n * The initial mode is enabled on mount. Memoize `behaviourIds` (module scope or\n * `useMemo`) so `setMode` stays stable.\n */\nexport function useSelectMode(\n behaviourIds: Record<string, string>,\n options: UseSelectModeOptions = {},\n canvas?: EngineCanvas | null,\n): UseSelectModeResult {\n const resolved = useResolvedCanvas(canvas);\n const keys = Object.keys(behaviourIds);\n const [mode, setModeState] = useState(options.initial ?? keys[0] ?? '');\n const modeRef = useRef(mode);\n modeRef.current = mode;\n\n const setMode = useCallback(\n (next: string) => {\n for (const [key, id] of Object.entries(behaviourIds)) {\n const behaviour = resolved.behaviours.get(id);\n if (!behaviour) continue;\n if (key === next) behaviour.enable();\n else behaviour.disable();\n }\n setModeState(next);\n },\n [resolved, behaviourIds],\n );\n\n // Enable the initial mode (and disable the rest) once the canvas is resolved.\n useEffect(() => {\n setMode(modeRef.current);\n // setMode is recreated when behaviourIds identity changes; re-syncing then\n // is harmless. Intentionally not depending on `mode`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [setMode]);\n\n const modeOptions = options.labels ?? Object.fromEntries(keys.map((k) => [k, k]));\n\n return { mode, modeOptions, setMode };\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { GraphLayer, EdgePathType, EdgeShapeOptions } from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\n/**\n * Default path types surfaced by an edge-type picker, in display order. A\n * curated subset of {@link EdgePathType} that maps cleanly to the three common\n * routing styles plus their rounded/smooth orthogonal variants.\n */\nexport const DEFAULT_EDGE_TYPES: readonly EdgePathType[] = [\n 'straight',\n 'orth',\n 'bezier',\n 'rounded',\n 'smooth',\n];\n\n/** Human labels for the built-in {@link EdgePathType} values (picker display). */\nexport const DEFAULT_EDGE_TYPE_LABELS: Record<string, string> = {\n straight: 'Straight',\n orth: 'Orthogonal',\n bezier: 'Curved',\n quadratic: 'Quadratic',\n rounded: 'Rounded',\n smooth: 'Smooth',\n manhattan: 'Manhattan',\n 'bump-radial': 'Bump (radial)',\n 'bump-horizontal': 'Bump (horizontal)',\n 'step-radial': 'Step (radial)',\n bundle: 'Bundled',\n};\n\nexport interface UseEdgeTypeOptions {\n /** Target `GraphLayer` id. Default `'graph'`. */\n layerId?: string;\n /**\n * Initially-selected path type. When omitted, the hook seeds from the layer's\n * current `edgeDefaults.shape.pathType` on mount, falling back to the first\n * entry of `types`.\n */\n initial?: EdgePathType;\n /** Path types to expose, in order. Default {@link DEFAULT_EDGE_TYPES}. */\n types?: readonly EdgePathType[];\n /** Optional key → human label map. Default {@link DEFAULT_EDGE_TYPE_LABELS}. */\n labels?: Record<string, string>;\n}\n\nexport interface UseEdgeTypeResult {\n /** Currently-selected path type key. */\n edgeType: string;\n /** Key → label map for a picker. */\n edgeTypeOptions: Record<string, string>;\n /**\n * Switch the path type for **every** edge in the layer and make it the\n * default for future edges (via `GraphLayer.setEdgeDefaults`).\n */\n setEdgeType: (type: string) => void;\n}\n\n/**\n * Layer-wide edge routing switch. Patches the `GraphLayer` edge template\n * (`options.edge.style.shape.pathType`) via {@link GraphLayer.setEdgeDefaults},\n * which re-renders every edge and becomes the default for edges added later —\n * the engine-side `pathType` shorthand resolves to the right router + pathStyle\n * pair (e.g. `'orth'`, `'bezier'`, `'rounded'`).\n *\n * The prior `shape` is spread before patching so anchors / waypoints survive\n * (`setEdgeDefaults` replaces structured fields wholesale). State is owned by\n * the hook and seeded from `layer.edgeDefaults` on mount.\n */\nexport function useEdgeType(\n options: UseEdgeTypeOptions = {},\n canvas?: EngineCanvas | null,\n): UseEdgeTypeResult {\n const { layerId = 'graph', initial, types = DEFAULT_EDGE_TYPES, labels } = options;\n const resolved = useResolvedCanvas(canvas);\n const [edgeType, setEdgeTypeState] = useState<string>(initial ?? types[0] ?? 'straight');\n\n // Seed from the layer's current default once the canvas is resolved, unless an\n // explicit `initial` was given (the background layer emits no option event, so\n // the hook owns this state).\n useEffect(() => {\n if (initial) return;\n const layer = resolved.layers.get<GraphLayer>(layerId);\n const current = layer?.edgeDefaults;\n const shape = current && typeof current === 'object' ? (current as { shape?: unknown }).shape : undefined;\n const pathType =\n shape && typeof shape === 'object' ? (shape as { pathType?: string }).pathType : undefined;\n if (pathType) setEdgeTypeState(pathType);\n }, [resolved, layerId, initial]);\n\n const setEdgeType = useCallback(\n (next: string) => {\n const layer = resolved.layers.get<GraphLayer>(layerId);\n if (!layer) return;\n // `setEdgeDefaults` replaces `shape` wholesale — spread the prior shape so\n // anchors / waypoints aren't dropped when only `pathType` changes.\n const prevShape = layer.edgeDefaults?.shape;\n const baseShape = (prevShape && typeof prevShape === 'object' ? prevShape : {}) as EdgeShapeOptions;\n const shape: EdgeShapeOptions = { ...baseShape, pathType: next as EdgePathType };\n layer.setEdgeDefaults({ shape });\n setEdgeTypeState(next);\n },\n [resolved, layerId],\n );\n\n const edgeTypeOptions =\n labels ?? Object.fromEntries(types.map((t) => [t, DEFAULT_EDGE_TYPE_LABELS[t] ?? t]));\n\n return { edgeType, edgeTypeOptions, setEdgeType };\n}\n","import { useCallback, useState } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\n\nconst DEFAULT_LOCK_IDS = ['pan', 'drag-node'];\n\nexport interface UseLockOptions {\n /**\n * Behaviour ids disabled while locked (re-enabled on unlock). Default\n * `['pan', 'drag-node']` — pan + node drag, leaving zoom available.\n */\n behaviourIds?: string[];\n /** Initial locked state. Default `false`. */\n initialLocked?: boolean;\n}\n\nexport interface UseLockResult {\n locked: boolean;\n toggleLock: () => void;\n setLock: (locked: boolean) => void;\n}\n\n/**\n * View lock — disables a configurable set of behaviours (pan + node drag by\n * default) while keeping zoom available. \"Lock\" is app policy, not an engine\n * concept, so which behaviours it disables is configurable. State is owned by\n * the hook.\n */\nexport function useLock(\n options: UseLockOptions = {},\n canvas?: EngineCanvas | null,\n): UseLockResult {\n const { behaviourIds = DEFAULT_LOCK_IDS, initialLocked = false } = options;\n const resolved = useResolvedCanvas(canvas);\n const [locked, setLocked] = useState(initialLocked);\n\n const setLock = useCallback(\n (next: boolean) => {\n for (const id of behaviourIds) {\n const behaviour = resolved.behaviours.get(id);\n if (!behaviour) continue;\n if (next) behaviour.disable();\n else behaviour.enable();\n }\n setLocked(next);\n },\n [resolved, behaviourIds],\n );\n\n const toggleLock = useCallback(() => setLock(!locked), [setLock, locked]);\n\n return { locked, toggleLock, setLock };\n}\n","import { useContext } from 'react';\n\nimport { ToolContext, type ToolContextValue } from '../ToolContext';\n\n/**\n * Read + switch the active modelling tool (and Add-tool node kind) from a\n * `<GraphToolProvider>` ancestor.\n *\n * Gate your drawing behaviours on the result, e.g.\n * `<CreateNodeBehaviour enabled={useTool().tool === 'add'} />`.\n *\n * @throws if no `<GraphToolProvider>` is above — a modeller without one is a\n * wiring bug, so this fails loudly rather than silently doing nothing.\n */\nexport function useTool(): ToolContextValue {\n const ctx = useContext(ToolContext);\n if (!ctx) {\n throw new Error('useTool must be used within a <GraphToolProvider>.');\n }\n return ctx;\n}\n","import { useCallback, useContext, useRef } from 'react';\nimport type { ErasedElement, GraphEdge, GraphNode, HistoryOp } from '@invana/graph';\n\nimport { HistoryContext } from '../HistoryContext';\n\nexport interface UseDrawHistoryResult {\n /** Journal a just-created node as an undoable `add node` entry. */\n onNodeCreate: (node: GraphNode) => void;\n /** Journal a just-created edge as an undoable `connect` entry. */\n onEdgeCreate: (edge: GraphEdge) => void;\n /** Journal a just-erased node/edge as an undoable `delete` entry. */\n onErase: (removed: ErasedElement) => void;\n}\n\n/**\n * Ready-made callbacks that make `CreateNodeBehaviour` / `DrawEdgeBehaviour` /\n * `EraseBehaviour` **undoable**. Wire them to the behaviours' `onNodeCreate` /\n * `onEdgeCreate` / `onErase` props — each pushes the already-applied mutation as\n * one entry on the `GraphHistory` from a `<GraphHistoryProvider>` ancestor\n * (mirroring how the provider records drags via `history.push`).\n *\n * The behaviours mutate the store themselves; these only *journal* the change,\n * so they pair with — they don't replace — the behaviour's own mutation.\n *\n * Without a history provider the callbacks are harmless no-ops (drawing still\n * works; it just isn't undoable). The returned functions are referentially\n * stable, so they're safe to capture once in a behaviour that reads its\n * callbacks at construction.\n */\nexport function useDrawHistory(): UseDrawHistoryResult {\n const history = useContext(HistoryContext);\n\n // The draw behaviours capture their callbacks once (at construction), but the\n // history instance is built in an effect *after* first render. Read it through\n // a ref so the stable callbacks always see the current (possibly-late) history.\n const ref = useRef(history);\n ref.current = history;\n\n const push = useCallback((op: HistoryOp, label: string): void => {\n ref.current?.push({ ops: [op], label });\n }, []);\n\n const onNodeCreate = useCallback(\n (node: GraphNode) => push({ kind: 'addNode', node }, 'add node'),\n [push],\n );\n const onEdgeCreate = useCallback(\n (edge: GraphEdge) => push({ kind: 'addEdge', edge }, 'connect'),\n [push],\n );\n const onErase = useCallback(\n (removed: ErasedElement) => {\n const op: HistoryOp =\n removed.kind === 'node'\n ? { kind: 'removeNode', node: removed.node, edges: removed.edges }\n : { kind: 'removeEdge', edge: removed.edge };\n push(op, 'delete');\n },\n [push],\n );\n\n return { onNodeCreate, onEdgeCreate, onErase };\n}\n","import { useContext } from 'react';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type {\n GraphLayer as EngineGraphLayer,\n GraphEdge,\n GraphNode,\n EdgeStyle,\n NodeStyle,\n} from '@invana/graph';\n\nimport { useResolvedCanvas } from './useResolvedCanvas';\nimport { useInspectTarget } from './useInspectTarget';\nimport { HistoryContext } from '../HistoryContext';\nimport type { PropertiesEditorValues } from '../components/PropertiesEditor';\n\nexport interface UseEntityEditorOptions {\n /** GraphLayer to read/write. Default `'graph'`. */\n layerId?: string;\n /** Id of the `ClickInspectBehaviour` the edit target is read from. Default `'click-inspect'`. */\n inspectId?: string;\n /**\n * Modeller mode: edit a single `type` field on **both** nodes and edges whose\n * value also drives the displayed label (mirrored to `style.labelText`) — in a\n * modeller the type *is* what's drawn on the element. Off by default, in which\n * case nodes edit their `label` (`style.labelText`) and edges edit their `type`,\n * each as a separate field.\n */\n typeAsLabel?: boolean;\n}\n\n/** The single selected node/edge, its current label + data, and a commit action. */\nexport interface EntityEditorTarget {\n kind: 'node' | 'edge';\n id: string;\n /** Effective (resolved) label text. Empty for edges (they have no label field). */\n label: string;\n /** The element's free-form `type` tag. Present for edges (`'' ` when unset). */\n type?: string;\n /** Current `data` as a flat string map (non-string values are stringified). */\n data: Record<string, string>;\n /**\n * Write the editor's values back to the store, undoable as one entry when a\n * `<GraphHistoryProvider>` is present (a direct mutation otherwise). Replaces\n * `data` wholesale. A **node** also overwrites `style.labelText` (spreading the\n * prior style); an **edge** writes its `type` instead — edges have no label.\n */\n commit: (values: PropertiesEditorValues) => void;\n /**\n * Swap an edge's `source`/`target` (reverse its direction). Present only for\n * edges; undoable as one entry when a `<GraphHistoryProvider>` is present.\n */\n reverse?: () => void;\n}\n\n/** Coerce an opaque `data` payload into the flat string map the editor edits. */\nfunction toStringMap(data: unknown): Record<string, string> {\n if (!data || typeof data !== 'object') return {};\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(data as Record<string, unknown>)) {\n if (v === null || v === undefined) continue;\n out[k] = typeof v === 'string' ? v : typeof v === 'object' ? JSON.stringify(v) : String(v);\n }\n return out;\n}\n\n/**\n * Click-driven property editing for an inspector. Returns the **single** node or\n * edge the user clicked to edit — its effective label + `data` and a `commit`\n * that writes edits back undoably — or `null` when nothing is targeted (so a\n * panel can render nothing). Reads the target via {@link useInspectTarget}\n * (needs a `ClickInspectBehaviour`, independent of selection); commits via the\n * `GraphHistory` from a `<GraphHistoryProvider>` ancestor when present.\n *\n * The view (`<PropertiesEditor>`) and placement (`<Panel>`) are the consumer's —\n * see {@link InspectorPanel} for the turnkey wiring.\n */\nexport function useEntityEditor(\n options: UseEntityEditorOptions = {},\n canvas?: EngineCanvas | null,\n): EntityEditorTarget | null {\n const { layerId = 'graph', inspectId = 'click-inspect', typeAsLabel = false } = options;\n const resolved = useResolvedCanvas(canvas);\n const history = useContext(HistoryContext);\n const single = useInspectTarget({ inspectId }, canvas);\n if (!single) return null;\n\n const layer = resolved.layers.get<EngineGraphLayer>(layerId);\n const store = layer?.store;\n if (!layer || !store) return null;\n\n if (single.kind === 'node') {\n const node = store.getNode(single.id);\n if (!node) return null;\n const label = (layer.resolveNodeStyle(node).labelText as string | undefined) ?? '';\n\n if (typeAsLabel) {\n // One `type` field, mirrored to the displayed `labelText`. Seed it from the\n // node's `type`, falling back to its current label so existing text shows.\n const type = (node.type as string | undefined) ?? label;\n const commit = ({ type: nextType, data }: PropertiesEditorValues): void => {\n const value = nextType ?? '';\n const prior = (node.style ?? {}) as Partial<NodeStyle>;\n const patch: Partial<GraphNode> = { type: value, style: { ...prior, labelText: value }, data };\n if (history) history.transaction('edit node', (rec) => rec.updateNode(single.id, patch));\n else store.updateNode(single.id, patch);\n };\n return { kind: 'node', id: single.id, label: '', type, data: toStringMap(node.data), commit };\n }\n\n const commit = ({ label: nextLabel, data }: PropertiesEditorValues): void => {\n const prior = (node.style ?? {}) as Partial<NodeStyle>;\n const patch: Partial<GraphNode> = { style: { ...prior, labelText: nextLabel }, data };\n if (history) history.transaction('edit node', (rec) => rec.updateNode(single.id, patch));\n else store.updateNode(single.id, patch);\n };\n return { kind: 'node', id: single.id, label, data: toStringMap(node.data), commit };\n }\n\n const edge = store.getEdge(single.id);\n if (!edge) return null;\n // Edges are identified by their `type` (predicate), not a `label`. In\n // `typeAsLabel` mode the type also drives the drawn label (`style.labelText`);\n // otherwise the edge inspector edits `type` + `data` only.\n const edgeLabel = (layer.resolveEdgeStyle(edge).labelText as string | undefined) ?? '';\n const type = (edge.type as string | undefined) ?? (typeAsLabel ? edgeLabel : '');\n const commit = ({ type: nextType, data }: PropertiesEditorValues): void => {\n const value = nextType ?? '';\n const patch: Partial<GraphEdge> = { data };\n if (nextType !== undefined) patch.type = value;\n if (typeAsLabel) {\n const prior = (edge.style ?? {}) as Partial<EdgeStyle>;\n patch.style = { ...prior, labelText: value };\n }\n if (history) history.transaction('edit edge', (rec) => rec.updateEdge(single.id, patch));\n else store.updateEdge(single.id, patch);\n };\n const reverse = (): void => {\n const swap: Partial<GraphEdge> = { source: edge.target, target: edge.source };\n if (history) history.transaction('reverse edge', (rec) => rec.updateEdge(single.id, swap));\n else store.updateEdge(single.id, swap);\n };\n return {\n kind: 'edge',\n id: single.id,\n label: '',\n type,\n data: toStringMap(edge.data),\n commit,\n reverse,\n };\n}\n","import { useCallback, useEffect, useState } from 'react';\n\n/** Open menu: where it sits (screen / canvas-relative px) + what it carries. */\nexport interface ContextMenuState<T> {\n /** Left offset in px, relative to the positioned ancestor (the `<Canvas>` host). */\n x: number;\n /** Top offset in px, relative to the positioned ancestor. */\n y: number;\n /** Caller-defined payload — typically the per-target menu items to render. */\n items: T;\n}\n\nexport interface UseContextMenuResult<T> {\n /** Current open menu, or `null` when closed. */\n menu: ContextMenuState<T> | null;\n /** Open (or move) the menu at `(x, y)` carrying `items`. */\n open: (x: number, y: number, items: T) => void;\n /** Close the menu. */\n close: () => void;\n}\n\n/**\n * Headless open/close + position state for a right-click context menu, with the\n * dismissal lifecycle baked in: while a menu is open, an outside `pointerdown`\n * or `Escape` closes it.\n *\n * Pairs with `<ContextMenuBehaviour onContextMenu={…}>` (which supplies the\n * target + `screen` position) and `<ContextMenuOverlay>` (which renders the\n * menu). Feed `e.screen.x / e.screen.y` straight into {@link open}; because the\n * `<Canvas>` host is `position: relative`, those coordinates place the overlay\n * correctly when it's rendered as a `<Canvas>` descendant.\n *\n * The opening right-click's `pointerdown` fires *before* this effect's listener\n * attaches, so the menu never self-closes. `<ContextMenuOverlay>` stops\n * `pointerdown` propagation, so clicks *inside* the menu don't dismiss it —\n * leaf `onClick`s call {@link close} explicitly.\n *\n * Generic over the payload `T` so it stays UI-kit-agnostic; the graph stories\n * parameterise it as `MenuItem[]` (from `@invana/ui`).\n *\n * @example\n * ```tsx\n * const { menu, open, close } = useContextMenu<MenuItem[]>();\n * const onContextMenu = (e: ContextMenuEvent) =>\n * open(e.screen.x, e.screen.y, buildItems(e, close));\n * // …\n * <ContextMenuBehaviour layerId=\"graph\" onContextMenu={onContextMenu} />\n * {menu && <ContextMenuOverlay x={menu.x} y={menu.y} items={menu.items} />}\n * ```\n */\nexport function useContextMenu<T>(): UseContextMenuResult<T> {\n const [menu, setMenu] = useState<ContextMenuState<T> | null>(null);\n\n const close = useCallback(() => setMenu(null), []);\n const open = useCallback((x: number, y: number, items: T) => {\n setMenu({ x, y, items });\n }, []);\n\n useEffect(() => {\n if (!menu) return;\n const onKey = (ev: KeyboardEvent): void => {\n if (ev.key === 'Escape') close();\n };\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', onKey);\n return () => {\n window.removeEventListener('pointerdown', close);\n window.removeEventListener('keydown', onKey);\n };\n }, [menu, close]);\n\n return { menu, open, close };\n}\n","import type { CSSProperties, ReactNode } from 'react';\n\nimport type { PanelPosition } from './types';\n\nexport interface PanelProps {\n /** Corner / edge of the nearest positioned ancestor to pin to. Default `'top-left'`. */\n position?: PanelPosition;\n /** Stack direction for children. Default `'vertical'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Distance from the pinned edges, in px. Default `8`. */\n offset?: number;\n /** Gap between children, in px. Default `4`. */\n gap?: number;\n /** Stacking order, so the overlay sits above canvas content. Default `5`. */\n zIndex?: number;\n className?: string;\n /** Extra inline styles, merged onto the content wrapper (not the positioner). */\n style?: CSSProperties;\n children?: ReactNode;\n}\n\n/** Translate a {@link PanelPosition} + offset into absolute-positioning styles. */\nfunction pinStyle(position: PanelPosition, offset: number): CSSProperties {\n const [vertical, horizontal] = position.split('-') as [\n 'top' | 'bottom',\n 'left' | 'center' | 'right',\n ];\n const style: CSSProperties = { position: 'absolute', [vertical]: offset };\n if (horizontal === 'center') {\n style.left = '50%';\n style.transform = 'translateX(-50%)';\n } else {\n style[horizontal] = offset;\n }\n return style;\n}\n\n/**\n * A positioned overlay container — the canvas equivalent of React Flow's\n * `<Panel>`. Pins itself to a corner / edge-centre of its **nearest positioned\n * ancestor** (e.g. the `<Canvas>` host, which is `position: relative`), and\n * stacks its children horizontally or vertically.\n *\n * Engine-agnostic and reference-free: it needs no `Canvas` instance — with\n * multiple canvases on one page you simply render one `<Panel>` inside each\n * `<Canvas>` and each pins to its own host.\n *\n * **Pointer events:** the absolutely-positioned root is `pointerEvents: 'none'`\n * so it never creates a dead zone over the canvas (a wide `top-center` panel\n * would otherwise block pan/zoom along that strip). Only the inner content\n * wrapper re-enables `pointerEvents: 'auto'`, so drags that miss the actual\n * controls still reach the canvas underneath.\n */\nexport function Panel({\n position = 'top-left',\n orientation = 'vertical',\n offset = 8,\n gap = 4,\n zIndex = 5,\n className,\n style,\n children,\n}: PanelProps) {\n return (\n <div style={{ ...pinStyle(position, offset), zIndex, pointerEvents: 'none' }}>\n <div\n className={className}\n style={{\n display: 'flex',\n flexDirection: orientation === 'vertical' ? 'column' : 'row',\n gap,\n pointerEvents: 'auto',\n ...style,\n }}\n >\n {children}\n </div>\n </div>\n );\n}\n","import type { ReactElement, ReactNode } from 'react';\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@invana/ui';\n\nimport type { TooltipSide } from './types';\n\nexport interface TooltippedProps {\n /**\n * Tooltip content (typically the host control's `title` / `label`). When\n * `null` / `undefined` / `''` the child renders **unwrapped** — no tooltip,\n * no extra DOM — so callers can pass an optional label without branching.\n */\n label?: ReactNode;\n /** Side the tooltip is placed on relative to the trigger. Default `'top'`. */\n side?: TooltipSide;\n /** Hover-open delay in ms. Default `0` (instant — matches a toolbar feel). */\n delayDuration?: number;\n /** The single trigger element (a `Button`, a dropdown trigger, …). */\n children: ReactElement;\n}\n\n/**\n * Wraps a single interactive element with an `@invana/ui` (Radix) tooltip\n * driven by `label`. The building-block that lets the dumb control components\n * surface their `title` / `label` as a real hover tooltip — readable when the\n * controls are dropped into a compact `NavHorizontal` / `NavVertical` slot,\n * where the native `title` attribute is easy to miss.\n *\n * Self-contained: bundles its own `TooltipProvider` (like `@invana/ui`'s\n * `ButtonWithTooltip`), so a control works standalone without the host wiring a\n * provider. `asChild` forwards the trigger props onto the child, preserving its\n * variant / size / active styling.\n *\n * The content background is pinned to `--color-popover` (opaque): the design\n * kit's default tooltip is translucent (`bg-popover/85` + backdrop-blur), which\n * reads as see-through over a busy canvas — same reasoning as the dropdown\n * surfaces in {@link OptionPicker} / {@link ZoomPicker}.\n */\nexport function Tooltipped({ label, side, delayDuration = 0, children }: TooltippedProps) {\n if (label == null || label === '') return children;\n return (\n <TooltipProvider delayDuration={delayDuration}>\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent side={side} style={{ backgroundColor: 'var(--color-popover)' }}>\n {label}\n </TooltipContent>\n </Tooltip>\n </TooltipProvider>\n );\n}\n","import { Button } from '@invana/ui';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\n\nexport interface ControlButtonProps {\n /** Icon component (e.g. a `lucide-react` glyph). Consumer-supplied — icon-agnostic. */\n icon: ToolbarIcon;\n onClick: () => void;\n /** Tooltip content + accessible label. */\n title: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Active styling — `'default'` (filled) vs `'ghost'` Button variant. Default `false`. */\n active?: boolean;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * A single icon control button — the building block to drop into a {@link Panel}\n * (the canvas equivalent of React Flow's `<ControlButton>`). Thin wrapper over\n * the `@invana/ui` `Button`; active state uses Button variants, not Tailwind, so\n * it works without the host running Tailwind.\n *\n * `title` drives both a real hover tooltip (via {@link Tooltipped}) and the\n * `aria-label`, so the icon-only button stays usable and accessible inside a\n * compact `NavHorizontal` / `NavVertical`.\n */\nexport function ControlButton({\n icon: Icon,\n onClick,\n title,\n tooltipSide,\n active = false,\n disabled = false,\n className,\n}: ControlButtonProps) {\n return (\n <Tooltipped label={title} side={tooltipSide}>\n <Button\n variant={active ? 'default' : 'ghost'}\n size=\"icon\"\n aria-label={title}\n disabled={disabled}\n onClick={onClick}\n className={className}\n >\n <Icon size={16} />\n </Button>\n </Tooltipped>\n );\n}\n","import { useState, type ChangeEvent, type CSSProperties } from 'react';\nimport { Button } from '@invana/ui';\n\n/** The values a {@link PropertiesEditor} edits: a label + a flat string→string data map. */\nexport interface PropertiesEditorValues {\n /** The element's label text. */\n label: string;\n /** The element's free-form type tag (maps to `node.type` / `edge.type`). Only edited when `showType`. */\n type?: string;\n /** Arbitrary key/value metadata (maps to `node.data` / `edge.data`). */\n data: Record<string, string>;\n}\n\n/** One editable key/value row. Kept as an array (not a map) so blank/duplicate keys are editable mid-typing. */\ninterface Row {\n k: string;\n v: string;\n}\n\nexport interface PropertiesEditorProps {\n /** Heading shown above the form, e.g. `'Node'` / `'Edge'`. */\n title?: string;\n /**\n * Initial values, loaded into local state **once** on mount (same as\n * `NodeStyleEditor`). To reload for a different element, remount via `key`.\n */\n defaults?: Partial<PropertiesEditorValues>;\n /** Called with the edited values when the user clicks Apply. */\n onSubmit: (values: PropertiesEditorValues) => void;\n /** Submit button label. Default `'Apply'`. */\n submitLabel?: string;\n /** Show the label field. Default `true`. */\n showLabel?: boolean;\n /** Show an editable `type` field above the properties list. Default `false`. */\n showType?: boolean;\n /**\n * When provided, render a \"Reverse direction\" button in the footer that\n * invokes this callback immediately (i.e. not on Apply). Used for edges to\n * swap source/target. Omit for elements that have no direction.\n */\n onReverse?: () => void;\n className?: string;\n}\n\n/**\n * Dumb, engine-agnostic editor for an element's **label + key/value\n * properties** — the canvas counterpart of `@invana/canvas-ui`'s\n * `NodeStyleEditor`, but for arbitrary `data` rather than visual style (which\n * `@invana/forms`' fixed field types can't express as a dynamic list).\n *\n * Props in / `onSubmit` out: it owns the row state, lets the user add / remove /\n * rename fields, and on Apply emits `{ label, data }`. It holds **no** engine /\n * layer / commit logic — the consumer (see {@link InspectorPanel}) wires\n * `onSubmit` to the store. Blank-keyed rows are dropped on submit; on duplicate\n * keys the last row wins.\n *\n * The text fields are styled native `<input>`s: the `@invana/ui` build this\n * package resolves doesn't export a plain `Input`, and the dynamic key/value\n * list isn't expressible via the `@invana/forms` schema generator. `Button`\n * still comes from `@invana/ui` (no raw `<button>`).\n */\nexport function PropertiesEditor({\n title,\n defaults,\n onSubmit,\n submitLabel = 'Apply',\n showLabel = true,\n showType = false,\n onReverse,\n className,\n}: PropertiesEditorProps) {\n const [label, setLabel] = useState(defaults?.label ?? '');\n const [type, setType] = useState(defaults?.type ?? '');\n const [rows, setRows] = useState<Row[]>(() =>\n Object.entries(defaults?.data ?? {}).map(([k, v]) => ({ k, v })),\n );\n\n const setRow = (i: number, patch: Partial<Row>): void =>\n setRows((rs) => rs.map((r, j) => (j === i ? { ...r, ...patch } : r)));\n const removeRow = (i: number): void => setRows((rs) => rs.filter((_, j) => j !== i));\n const addRow = (): void => setRows((rs) => [...rs, { k: '', v: '' }]);\n\n const apply = (): void => {\n const data: Record<string, string> = {};\n for (const { k, v } of rows) {\n const key = k.trim();\n if (key) data[key] = v;\n }\n onSubmit(showType ? { label, type, data } : { label, data });\n };\n\n return (\n <div className={className} style={cardStyle}>\n {title && <div style={titleStyle}>{title}</div>}\n\n {showLabel && (\n <label style={fieldStyle}>\n <span style={captionStyle}>Label</span>\n <input\n style={inputStyle}\n value={label}\n placeholder=\"Label text\"\n onChange={(e: ChangeEvent<HTMLInputElement>) => setLabel(e.target.value)}\n />\n </label>\n )}\n\n {showType && (\n <label style={fieldStyle}>\n <span style={captionStyle}>Type</span>\n <input\n style={inputStyle}\n value={type}\n placeholder=\"Type tag\"\n onChange={(e: ChangeEvent<HTMLInputElement>) => setType(e.target.value)}\n />\n </label>\n )}\n\n <div style={fieldStyle}>\n <span style={captionStyle}>Properties</span>\n {rows.length === 0 && <span style={emptyStyle}>No properties yet.</span>}\n {rows.map((row, i) => (\n <div key={i} style={rowStyle}>\n <input\n style={inputStyle}\n value={row.k}\n placeholder=\"key\"\n onChange={(e: ChangeEvent<HTMLInputElement>) => setRow(i, { k: e.target.value })}\n />\n <input\n style={inputStyle}\n value={row.v}\n placeholder=\"value\"\n onChange={(e: ChangeEvent<HTMLInputElement>) => setRow(i, { v: e.target.value })}\n />\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label=\"Remove field\"\n onClick={() => removeRow(i)}\n >\n ✕\n </Button>\n </div>\n ))}\n <div>\n <Button variant=\"outline\" size=\"sm\" onClick={addRow}>\n Add field\n </Button>\n </div>\n </div>\n\n <div\n style={{\n display: 'flex',\n justifyContent: onReverse ? 'space-between' : 'flex-end',\n alignItems: 'center',\n }}\n >\n {onReverse && (\n <Button variant=\"outline\" size=\"sm\" onClick={onReverse}>\n Reverse direction\n </Button>\n )}\n <Button onClick={apply}>{submitLabel}</Button>\n </div>\n </div>\n );\n}\n\nconst cardStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n padding: 12,\n minWidth: 240,\n background: 'var(--color-popover)',\n color: 'var(--color-popover-foreground)',\n border: '1px solid var(--color-border)',\n borderRadius: 8,\n boxShadow: '0 4px 16px rgba(0,0,0,0.18)',\n};\nconst titleStyle: CSSProperties = { fontSize: 13, fontWeight: 600, opacity: 0.85 };\nconst fieldStyle: CSSProperties = { display: 'flex', flexDirection: 'column', gap: 6 };\nconst captionStyle: CSSProperties = { fontSize: 12, fontWeight: 500, opacity: 0.8 };\nconst rowStyle: CSSProperties = { display: 'flex', gap: 6, alignItems: 'center' };\nconst emptyStyle: CSSProperties = { fontSize: 12, opacity: 0.6 };\nconst inputStyle: CSSProperties = {\n flex: 1,\n width: '100%',\n height: 28,\n padding: '0 8px',\n fontSize: 13,\n color: 'var(--color-foreground)',\n background: 'var(--color-background)',\n border: '1px solid var(--color-border)',\n borderRadius: 6,\n outline: 'none',\n};\n","import {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from '@invana/ui';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\n\nexport interface OptionPickerProps {\n /**\n * Label shown on the trigger and as the menu heading (e.g. `'Layout'`). Also\n * the trigger tooltip content unless {@link OptionPickerProps.tooltip} overrides it.\n */\n label: string;\n /** Currently selected option key. */\n value: string;\n /** Option key → human label. */\n options: Record<string, string>;\n /**\n * Optional option key → icon. When present, the active option's icon shows on\n * the trigger and each option's icon shows beside its label in the menu.\n * Icon-agnostic — pass a {@link ToolbarIcon} (e.g. a `lucide-react` glyph).\n */\n icons?: Record<string, ToolbarIcon>;\n /** Fired with the newly selected key. */\n onChange: (value: string) => void;\n /** Menu alignment relative to the trigger. Default `'start'`. */\n align?: 'start' | 'center' | 'end';\n /** Trigger tooltip content. Defaults to {@link OptionPickerProps.label}. */\n tooltip?: string;\n /** Side the trigger tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n className?: string;\n}\n\n/**\n * A single-select dropdown (radio group). Engine-agnostic — drives a `value` +\n * `onChange`. Used as the **layout switcher** and **selection-mode** picker in\n * {@link GraphToolbar}, and standalone for any single-choice control.\n */\nexport function OptionPicker({\n label,\n value,\n options,\n icons,\n onChange,\n align = 'start',\n tooltip,\n tooltipSide,\n className,\n}: OptionPickerProps) {\n const ActiveIcon = icons?.[value];\n return (\n <DropdownMenu>\n {/* Tooltip wraps the trigger: `TooltipTrigger asChild` → `DropdownMenuTrigger\n asChild` → `Button`, all merging onto the one Button. The DropdownMenu\n context still resolves the trigger regardless of the tooltip wrapper. */}\n <Tooltipped label={tooltip ?? label} side={tooltipSide}>\n <DropdownMenuTrigger asChild>\n {/* `ring-offset-background`: the design-kit Button sets `ring-offset-2`\n but no offset colour, so the focus ring's 2px offset falls back to\n Tailwind's default white — a light halo around the open trigger in\n dark mode. Pin it to the `--color-background` token instead. */}\n <Button\n variant=\"outline\"\n size=\"sm\"\n className={['ring-offset-background', className].filter(Boolean).join(' ')}\n >\n <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n {ActiveIcon && <ActiveIcon size={16} />}\n {label}: {options[value] ?? value}\n </span>\n </Button>\n </DropdownMenuTrigger>\n </Tooltipped>\n {/* Force a solid token-driven background: the design-kit's default\n popover styling is a translucent frosted glass (`bg-popover/80` +\n backdrop-blur), which reads as transparent over a busy canvas. */}\n <DropdownMenuContent align={align} style={{ backgroundColor: 'var(--color-popover)' }}>\n <DropdownMenuLabel>{label}</DropdownMenuLabel>\n <DropdownMenuRadioGroup value={value} onValueChange={onChange}>\n {Object.keys(options).map((key) => {\n const Icon = icons?.[key];\n return (\n <DropdownMenuRadioItem key={key} value={key}>\n <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>\n {Icon && <Icon size={14} />}\n {options[key] ?? key}\n </span>\n </DropdownMenuRadioItem>\n );\n })}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import type { ReactNode } from 'react';\nimport { Button } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { useZoom } from '../hooks/useZoom';\n\nexport interface ZoomControlsProps {\n zoomInIcon: ToolbarIcon;\n zoomOutIcon: ToolbarIcon;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n /** Side the \"Zoom in\" / \"Zoom out\" tooltips are placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /**\n * Show a live `NN%` zoom readout between the two buttons, sourced from the\n * canvas via {@link useZoom}. Ignored when `zoomLevel` is also provided.\n * Default `false`.\n */\n showLevel?: boolean;\n /** Stack direction. Default `'horizontal'`. */\n orientation?: 'horizontal' | 'vertical';\n /**\n * Manual zoom readout override rendered **between** the two buttons (e.g.\n * `'46%'`). Takes precedence over `showLevel`. Omit for a plain button pair.\n */\n zoomLevel?: ReactNode;\n className?: string;\n}\n\n/**\n * A pair of zoom-in / zoom-out icon buttons, optionally with a live zoom\n * readout between them. Self-wiring: hooks into the canvas via {@link useZoom}\n * — drop inside a `<Canvas>` and it works without any callback wiring.\n * Pass `onZoomIn` / `onZoomOut` to override the default hook-driven actions.\n */\nexport function ZoomControls({\n canvas,\n zoomInIcon: ZoomInIcon,\n zoomOutIcon: ZoomOutIcon,\n showLevel = false,\n orientation = 'horizontal',\n zoomLevel,\n tooltipSide,\n className,\n}: ZoomControlsProps) {\n const { zoom, zoomIn, zoomOut } = useZoom(canvas);\n const resolvedLevel = zoomLevel != null ? zoomLevel : showLevel ? `${Math.round(zoom * 100)}%` : undefined;\n const zoomInBtn = (\n <Tooltipped label=\"Zoom in\" side={tooltipSide}>\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Zoom in\" onClick={() => zoomIn()}>\n <ZoomInIcon size={16} />\n </Button>\n </Tooltipped>\n );\n const zoomOutBtn = (\n <Tooltipped label=\"Zoom out\" side={tooltipSide}>\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Zoom out\" onClick={() => zoomOut()}>\n <ZoomOutIcon size={16} />\n </Button>\n </Tooltipped>\n );\n const level =\n resolvedLevel != null ? (\n <span\n style={{\n fontSize: 12,\n fontVariantNumeric: 'tabular-nums',\n opacity: 0.8,\n textAlign: 'center',\n minWidth: 36,\n }}\n >\n {resolvedLevel}\n </span>\n ) : null;\n\n return (\n <div\n className={className}\n style={{\n display: 'flex',\n flexDirection: orientation === 'vertical' ? 'column' : 'row',\n alignItems: 'center',\n gap: 4,\n }}\n >\n {/* Horizontal: − level + · Vertical: + level − (zoom-in leads). */}\n {orientation === 'horizontal' ? (\n <>\n {zoomOutBtn}\n {level}\n {zoomInBtn}\n </>\n ) : (\n <>\n {zoomInBtn}\n {level}\n {zoomOutBtn}\n </>\n )}\n </div>\n );\n}\n","import { Button } from '@invana/ui';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\n\nexport interface LockToggleProps {\n /** Whether the view is locked (drives icon + active styling). */\n locked: boolean;\n onToggle: () => void;\n lockedIcon: ToolbarIcon;\n unlockedIcon: ToolbarIcon;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n className?: string;\n}\n\n/**\n * Toggle button for a \"lock view\" action (the consumer decides what locking\n * disables — e.g. pan + drag). Shows the locked icon and active styling while\n * locked. The tooltip + accessible label flips with state\n * (\"Lock view\" / \"Unlock view\").\n */\nexport function LockToggle({\n locked,\n onToggle,\n lockedIcon: LockedIcon,\n unlockedIcon: UnlockedIcon,\n tooltipSide,\n className,\n}: LockToggleProps) {\n const Icon = locked ? LockedIcon : UnlockedIcon;\n const label = locked ? 'Unlock view' : 'Lock view';\n return (\n <Tooltipped label={label} side={tooltipSide}>\n <Button\n variant={locked ? 'default' : 'ghost'}\n size=\"icon\"\n aria-label={label}\n onClick={onToggle}\n className={className}\n >\n <Icon size={16} />\n </Button>\n </Tooltipped>\n );\n}\n","import { Button } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { useClearGraph } from '../hooks/useClearGraph';\n\nexport interface ClearButtonProps {\n /** Optional leading icon (e.g. a trash glyph). */\n icon?: ToolbarIcon;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n /**\n * Layer id to clear. Default `'graph'`. Forwarded to {@link useClearGraph}.\n */\n layerId?: string;\n /** Button text + tooltip content. Default `'Clear'`. */\n label?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n className?: string;\n}\n\n/**\n * Labelled action button that clears all nodes and edges from the target layer.\n * Self-wiring: hooks into the canvas via {@link useClearGraph} — drop inside a\n * `<Canvas>` and it works without any callback wiring.\n */\nexport function ClearButton({\n icon: Icon,\n canvas,\n layerId = 'graph',\n label = 'Clear',\n tooltipSide,\n className,\n}: ClearButtonProps) {\n const { clear } = useClearGraph(layerId, canvas);\n return (\n <Tooltipped label={label} side={tooltipSide}>\n <Button variant=\"outline\" size=\"sm\" onClick={() => clear()} className={className}>\n {Icon ? <Icon size={16} /> : null}\n {label}\n </Button>\n </Tooltipped>\n );\n}\n","import { Button } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { useFitContent } from '../hooks/useFitContent';\n\nexport interface FitContentButtonProps {\n /** Leading icon (e.g. a maximize / frame glyph). */\n icon: ToolbarIcon;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n /**\n * Layer id to fit to. Default `'graph'`. Forwarded to {@link useFitContent}.\n */\n layerId?: string;\n /** Tooltip text + accessible label. Default `'Fit to content'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n className?: string;\n}\n\n/**\n * Icon button that fits the viewport to the graph's content (zoom-to-extent).\n * Self-wiring: hooks into the canvas via {@link useFitContent} — drop inside a\n * `<Canvas>` and it works without any callback wiring. Pass `onFitContent` to\n * override the default hook-driven action.\n */\nexport function FitContentButton({\n icon: Icon,\n canvas,\n layerId = 'graph',\n title = 'Fit to content',\n tooltipSide,\n className,\n}: FitContentButtonProps) {\n const { fitContent } = useFitContent(layerId, canvas);\n return (\n <Tooltipped label={title} side={tooltipSide}>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={title}\n onClick={() => fitContent()}\n className={className}\n >\n <Icon size={16} />\n </Button>\n </Tooltipped>\n );\n}\n","import {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Tooltipped } from './Tooltipped';\nimport type { TooltipSide } from './types';\nimport { useZoom } from '../hooks/useZoom';\nimport { useFitContent } from '../hooks/useFitContent';\n\nconst DEFAULT_PRESETS = [25, 50, 75, 100, 125, 150, 200, 300, 400];\n\nexport interface ZoomPickerProps {\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n /**\n * Layer id used for the fit-to-content action. Default `'graph'`.\n */\n layerId?: string;\n /**\n * Preset zoom percentages shown in the dropdown. Default\n * `[25, 50, 75, 100, 125, 150, 200, 300, 400]`.\n */\n presets?: number[];\n /**\n * Show the \"Fit / Reset View\" action at the top of the dropdown.\n * Default `true`.\n */\n showFit?: boolean;\n /** Label for the fit action. Default `'Fit / Reset View'`. */\n fitLabel?: string;\n /** Trigger tooltip content + accessible label. Default `'Zoom level'`. */\n title?: string;\n /** Side the trigger tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n className?: string;\n}\n\n/**\n * A zoom-level picker: a trigger button showing the current zoom percentage\n * that opens a dropdown with preset zoom levels and an optional fit-to-content\n * action. Self-wiring via {@link useZoom} and {@link useFitContent} — drop\n * inside a `<Canvas>` and it works without any callback wiring.\n *\n * The active preset is highlighted automatically based on the live zoom state.\n *\n * @example\n * // In any toolbar — vertical or horizontal:\n * <ZoomPicker layerId=\"graph\" />\n *\n * @example\n * // Custom presets, no fit action:\n * <ZoomPicker presets={[50, 100, 200]} showFit={false} />\n */\nexport function ZoomPicker({\n canvas,\n layerId = 'graph',\n presets = DEFAULT_PRESETS,\n showFit = true,\n fitLabel = 'Fit / Reset View',\n title = 'Zoom level',\n tooltipSide,\n className,\n}: ZoomPickerProps) {\n const { zoom, setZoom } = useZoom(canvas);\n const { fitContent } = useFitContent(layerId, canvas);\n const currentPct = String(Math.round(zoom * 100));\n\n return (\n <DropdownMenu>\n {/* Tooltip wraps the trigger — see OptionPicker for the asChild nesting. */}\n <Tooltipped label={title} side={tooltipSide}>\n <DropdownMenuTrigger asChild>\n <Button variant=\"outline\" size=\"sm\" aria-label={title} className={className}>\n {currentPct}% ▾\n </Button>\n </DropdownMenuTrigger>\n </Tooltipped>\n {/* Force a solid token-driven background: same reasoning as OptionPicker. */}\n <DropdownMenuContent style={{ backgroundColor: 'var(--color-popover)' }}>\n {showFit && (\n <>\n <DropdownMenuItem onSelect={() => fitContent()}>\n {fitLabel}\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n </>\n )}\n <DropdownMenuRadioGroup\n value={currentPct}\n onValueChange={(v) => setZoom(Number(v) / 100)}\n >\n {presets.map((pct) => (\n <DropdownMenuRadioItem key={pct} value={String(pct)}>\n {pct}%\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useHistory } from '../hooks/useHistory';\n\nexport interface UndoButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Undo'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring undo button. Disabled when there is nothing to undo. Requires a\n * `<GraphHistoryProvider>` ancestor (see {@link useHistory}).\n */\nexport function UndoButton({ icon, title = 'Undo', tooltipSide, canvas, className }: UndoButtonProps) {\n const { undo, canUndo } = useHistory({}, canvas);\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={undo}\n disabled={!canUndo}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useHistory } from '../hooks/useHistory';\n\nexport interface RedoButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Redo'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring redo button. Disabled when there is nothing to redo. Requires a\n * `<GraphHistoryProvider>` ancestor (see {@link useHistory}).\n */\nexport function RedoButton({ icon, title = 'Redo', tooltipSide, canvas, className }: RedoButtonProps) {\n const { redo, canRedo } = useHistory({}, canvas);\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={redo}\n disabled={!canRedo}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useHistory } from '../hooks/useHistory';\n\nexport interface RedrawButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Redraw'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Layer to redraw. Default `'graph'`. */\n layerId?: string;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring redraw button — forces a full re-render of the target layer. A\n * pure render pass (not undoable); works without a history provider.\n */\nexport function RedrawButton({\n icon,\n title = 'Redraw',\n tooltipSide,\n layerId = 'graph',\n canvas,\n className,\n}: RedrawButtonProps) {\n const { redraw } = useHistory({ layerId }, canvas);\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={redraw}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useClipboard } from '../hooks/useClipboard';\n\nexport interface CutButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Cut'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `ClickSelectBehaviour` to read selection from. Default `'click-select'`. */\n clickSelectId?: string;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring cut button — copies the selection to the clipboard, then deletes\n * it (undoable when a `<GraphHistoryProvider>` is present). Disabled when\n * nothing is selected. Requires a `<GraphClipboardProvider>` + a\n * `ClickSelectBehaviour`.\n */\nexport function CutButton({\n icon,\n title = 'Cut',\n tooltipSide,\n clickSelectId,\n canvas,\n className,\n}: CutButtonProps) {\n const { cut, hasSelection } = useClipboard(\n clickSelectId ? { clickSelectId } : {},\n canvas,\n );\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={cut}\n disabled={!hasSelection}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useClipboard } from '../hooks/useClipboard';\n\nexport interface CopyButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Copy'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `ClickSelectBehaviour` to read selection from. Default `'click-select'`. */\n clickSelectId?: string;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring copy button — copies the selection to the clipboard. Disabled when\n * nothing is selected. Requires a `<GraphClipboardProvider>` + a\n * `ClickSelectBehaviour`.\n */\nexport function CopyButton({\n icon,\n title = 'Copy',\n tooltipSide,\n clickSelectId,\n canvas,\n className,\n}: CopyButtonProps) {\n const { copy, hasSelection } = useClipboard(\n clickSelectId ? { clickSelectId } : {},\n canvas,\n );\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={copy}\n disabled={!hasSelection}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useClipboard } from '../hooks/useClipboard';\n\nexport interface PasteButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Paste'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `ClickSelectBehaviour` the pasted items are re-selected on. Default `'click-select'`. */\n clickSelectId?: string;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring paste button — inserts the clipboard buffer (offset + re-id'd) and\n * selects the pasted items. Disabled when the buffer is empty. Requires a\n * `<GraphClipboardProvider>`; undoable when a `<GraphHistoryProvider>` is present.\n */\nexport function PasteButton({\n icon,\n title = 'Paste',\n tooltipSide,\n clickSelectId,\n canvas,\n className,\n}: PasteButtonProps) {\n const { paste, canPaste } = useClipboard(\n clickSelectId ? { clickSelectId } : {},\n canvas,\n );\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={paste}\n disabled={!canPaste}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useClipboard } from '../hooks/useClipboard';\n\nexport interface DeleteSelectionButtonProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Delete selection'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `ClickSelectBehaviour` to read selection from. Default `'click-select'`. */\n clickSelectId?: string;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring delete button — removes the selected nodes/edges (undoable when a\n * `<GraphHistoryProvider>` is present). Disabled when nothing is selected.\n * Requires a `<GraphClipboardProvider>` + a `ClickSelectBehaviour`.\n */\nexport function DeleteSelectionButton({\n icon,\n title = 'Delete selection',\n tooltipSide,\n clickSelectId,\n canvas,\n className,\n}: DeleteSelectionButtonProps) {\n const { remove, hasSelection } = useClipboard(\n clickSelectId ? { clickSelectId } : {},\n canvas,\n );\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={remove}\n disabled={!hasSelection}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas, BackgroundLayerOptions } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useGrid } from '../hooks/useGrid';\n\ntype PatternType = NonNullable<BackgroundLayerOptions['patternType']>;\n\nexport interface GridToggleProps {\n icon: ToolbarIcon;\n /** Tooltip / accessible label. Default `'Toggle grid'`. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `BackgroundLayer` to toggle. Default `'background'`. */\n backgroundLayerId?: string;\n /** Pattern to switch to when shown (e.g. `'grid'`); preserves existing if omitted. */\n patternType?: PatternType;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring grid toggle. Shows the button as active while the background\n * pattern is visible. Wraps {@link useGrid}.\n */\nexport function GridToggle({\n icon,\n title = 'Toggle grid',\n tooltipSide,\n backgroundLayerId,\n patternType,\n canvas,\n className,\n}: GridToggleProps) {\n const { showGrid, toggleGrid } = useGrid(\n { ...(backgroundLayerId ? { backgroundLayerId } : {}), ...(patternType ? { patternType } : {}) },\n canvas,\n );\n return (\n <ControlButton\n icon={icon}\n title={title}\n tooltipSide={tooltipSide}\n onClick={toggleGrid}\n active={showGrid}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { ThemeKind, ThemeMode } from '@invana/graph';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { ControlButton } from './ControlButton';\nimport { useTheme } from '../hooks/useTheme';\n\nexport interface ThemeToggleProps {\n /** Icon shown while the resolved theme is light. */\n lightIcon: ToolbarIcon;\n /** Icon shown while the resolved theme is dark. */\n darkIcon: ToolbarIcon;\n /** Tooltip / accessible label. Defaults describe the switch target. */\n title?: string;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Id of the `ResponsiveThemeBehaviour` to drive. Default `'responsive-theme'`. */\n behaviourId?: string;\n /**\n * Optional id of a `BackgroundLayer` to flip in lockstep, so the background\n * switches with the graph content instead of following the OS independently.\n */\n backgroundLayerId?: string;\n /**\n * Called after the theme switches. Use it to flip app chrome that lives\n * outside the canvas (e.g. a design-system `data-theme` attribute) so the\n * floating controls stay legible against the canvas.\n */\n onChange?: (kind: ThemeKind, mode: ThemeMode) => void;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring theme toggle. Flips a registered `ResponsiveThemeBehaviour` between\n * pinned light and dark, showing the current theme's icon and active styling\n * while dark. Wraps {@link useTheme}.\n */\nexport function ThemeToggle({\n lightIcon,\n darkIcon,\n title,\n tooltipSide,\n behaviourId,\n backgroundLayerId,\n onChange,\n canvas,\n className,\n}: ThemeToggleProps) {\n const { kind, toggle } = useTheme(\n {\n ...(behaviourId ? { behaviourId } : {}),\n ...(backgroundLayerId ? { backgroundLayerId } : {}),\n ...(onChange ? { onChange } : {}),\n },\n canvas,\n );\n const dark = kind === 'dark';\n return (\n <ControlButton\n icon={dark ? darkIcon : lightIcon}\n title={title ?? (dark ? 'Switch to light theme' : 'Switch to dark theme')}\n tooltipSide={tooltipSide}\n onClick={toggle}\n active={dark}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { LockToggle } from './LockToggle';\nimport { useLock } from '../hooks/useLock';\n\nexport interface LockButtonProps {\n lockedIcon: ToolbarIcon;\n unlockedIcon: ToolbarIcon;\n /** Behaviour ids disabled while locked. Default `['pan', 'drag-node']`. */\n behaviourIds?: string[];\n /** Initial locked state. Default `false`. */\n initialLocked?: boolean;\n /** Side the tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring lock toggle — disables pan + node drag (by default) while locked,\n * leaving zoom available. Wraps the dumb {@link LockToggle} with {@link useLock}.\n */\nexport function LockButton({\n lockedIcon,\n unlockedIcon,\n behaviourIds,\n initialLocked,\n tooltipSide,\n canvas,\n className,\n}: LockButtonProps) {\n const { locked, toggleLock } = useLock(\n {\n ...(behaviourIds ? { behaviourIds } : {}),\n ...(initialLocked !== undefined ? { initialLocked } : {}),\n },\n canvas,\n );\n return (\n <LockToggle\n locked={locked}\n onToggle={toggleLock}\n lockedIcon={lockedIcon}\n unlockedIcon={unlockedIcon}\n tooltipSide={tooltipSide}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { OptionPicker } from './OptionPicker';\nimport type { TooltipSide } from './types';\nimport { useLayout, type LayoutFactory } from '../hooks/useLayout';\n\nexport interface LayoutPickerProps {\n /** Map of layout key → factory producing a fresh layout instance. Memoize it. */\n layouts: Record<string, LayoutFactory>;\n /** Trigger label. Default `'Layout'`. */\n label?: string;\n /** Target `GraphLayer` id. Default `'graph'`. */\n layerId?: string;\n /** Padding for the post-layout fit. Default `80`. */\n fitPadding?: number;\n /** Initially-selected key. Default: first key. */\n initial?: string;\n /** Optional key → human label map. Default: identity. */\n labels?: Record<string, string>;\n /** Dropdown alignment. */\n align?: 'start' | 'center' | 'end';\n /** Side the trigger tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring layout selector: a dropdown that applies the chosen layout via\n * {@link useLayout}. Layouts come from separate packages, so the consumer\n * supplies the factory map.\n */\nexport function LayoutPicker({\n layouts,\n label = 'Layout',\n layerId,\n fitPadding,\n initial,\n labels,\n align,\n tooltipSide,\n canvas,\n className,\n}: LayoutPickerProps) {\n const { layout, layoutOptions, applyLayout } = useLayout(\n layouts,\n {\n ...(layerId ? { layerId } : {}),\n ...(fitPadding !== undefined ? { fitPadding } : {}),\n ...(initial ? { initial } : {}),\n ...(labels ? { labels } : {}),\n },\n canvas,\n );\n return (\n <OptionPicker\n label={label}\n value={layout}\n options={layoutOptions}\n onChange={applyLayout}\n align={align}\n tooltipSide={tooltipSide}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { OptionPicker } from './OptionPicker';\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { useSelectMode } from '../hooks/useSelectMode';\n\nexport interface SelectModePickerProps {\n /** Map of mode key → behaviour id (e.g. `{ click: 'click-select', ... }`). Memoize it. */\n behaviourIds: Record<string, string>;\n /** Trigger label. Default `'Select'`. */\n label?: string;\n /** Initially-active mode key. Default: first key. */\n initial?: string;\n /** Optional key → human label map. Default: identity. */\n labels?: Record<string, string>;\n /** Optional mode key → icon map. Shown on the trigger and beside each option. */\n icons?: Record<string, ToolbarIcon>;\n /** Dropdown alignment. */\n align?: 'start' | 'center' | 'end';\n /** Side the trigger tooltip is placed on. Default `'top'`. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring selection-mode selector: a dropdown that enables exactly one of\n * the mapped behaviours via {@link useSelectMode}. The consumer must have\n * registered those behaviours.\n */\nexport function SelectModePicker({\n behaviourIds,\n label = 'Select',\n initial,\n labels,\n icons,\n align,\n tooltipSide,\n canvas,\n className,\n}: SelectModePickerProps) {\n const { mode, modeOptions, setMode } = useSelectMode(\n behaviourIds,\n { ...(initial ? { initial } : {}), ...(labels ? { labels } : {}) },\n canvas,\n );\n return (\n <OptionPicker\n label={label}\n value={mode}\n options={modeOptions}\n icons={icons}\n onChange={setMode}\n align={align}\n tooltipSide={tooltipSide}\n className={className}\n />\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { EdgePathType } from '@invana/graph';\n\nimport { OptionPicker } from './OptionPicker';\nimport type { ToolbarIcon, TooltipSide } from './types';\nimport { useEdgeType } from '../hooks/useEdgeType';\n\nexport interface EdgeTypePickerProps {\n /** Target `GraphLayer` id. Default `'graph'`. */\n layerId?: string;\n /** Trigger label. Default `'Edge'`. */\n label?: string;\n /** Initially-selected path type. Default: the layer's current edge default. */\n initial?: EdgePathType;\n /** Path types to expose, in order. Default: straight / orth / bezier / rounded / smooth. */\n types?: readonly EdgePathType[];\n /** Optional key → human label map. Default: the built-in path-type labels. */\n labels?: Record<string, string>;\n /** Per-option icons (key → icon component), surfaced on the trigger + items. */\n icons?: Record<string, ToolbarIcon>;\n /** Dropdown alignment. */\n align?: 'start' | 'center' | 'end';\n /** Side the trigger tooltip is placed on. */\n tooltipSide?: TooltipSide;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring edge-routing selector: a dropdown that re-routes **every** edge in\n * the layer via {@link useEdgeType} (`GraphLayer.setEdgeDefaults`). Mirrors\n * {@link SelectModePicker} / {@link LayoutPicker} — consume the hook, render an\n * {@link OptionPicker}. Per-option icons are supported via `icons`.\n */\nexport function EdgeTypePicker({\n layerId,\n label = 'Edge',\n initial,\n types,\n labels,\n icons,\n align,\n tooltipSide,\n canvas,\n className,\n}: EdgeTypePickerProps) {\n const { edgeType, edgeTypeOptions, setEdgeType } = useEdgeType(\n {\n ...(layerId ? { layerId } : {}),\n ...(initial ? { initial } : {}),\n ...(types ? { types } : {}),\n ...(labels ? { labels } : {}),\n },\n canvas,\n );\n return (\n <OptionPicker\n label={label}\n value={edgeType}\n options={edgeTypeOptions}\n icons={icons}\n onChange={setEdgeType}\n align={align}\n tooltipSide={tooltipSide}\n className={className}\n />\n );\n}\n","import type { CSSProperties } from 'react';\nimport { NestedMenu, type MenuItem } from '@invana/ui';\n\nexport interface ContextMenuOverlayProps {\n /** Left offset in px, relative to the positioned ancestor (the `<Canvas>` host). */\n x: number;\n /** Top offset in px, relative to the positioned ancestor. */\n y: number;\n /** Menu tree to render (per-target; leaves carry their own `onClick`). */\n items: MenuItem[];\n /** Stacking order; default `1000` so the menu floats over canvas chrome. */\n zIndex?: number;\n /** Extra inline style merged onto the positioned wrapper. */\n style?: CSSProperties;\n}\n\n/**\n * Dumb overlay for a right-click context menu: an absolutely-positioned\n * `@invana/ui` `<NestedMenu>` anchored at `(x, y)` within its positioned\n * ancestor. Engine-agnostic, props-in only — the open/close state and the\n * action wiring live in the consumer (`useContextMenu` + the menu items).\n *\n * Render it as a `<Canvas>` descendant: the host `<div>` is `position: relative`,\n * so `(x, y)` taken from `ContextMenuEvent.screen` lands the menu at the cursor.\n *\n * It **stops `pointerdown` propagation** so a click *inside* the menu doesn't\n * reach the window-level dismiss listener `useContextMenu` attaches, and\n * **prevents the native context menu** on a right-click over itself. Leaf items\n * close the menu via their own `onClick`.\n */\nexport function ContextMenuOverlay({ x, y, items, zIndex = 1000, style }: ContextMenuOverlayProps) {\n return (\n <div\n style={{ position: 'absolute', left: x, top: y, zIndex, ...style }}\n onPointerDown={(ev) => ev.stopPropagation()}\n onContextMenu={(ev) => ev.preventDefault()}\n >\n <NestedMenu menuItems={items} />\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport { NavHorizontal, NavVertical } from '@invana/ui';\nimport { Panel, ZoomControls, FitContentButton, LockToggle } from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nexport interface CanvasControlsToolbarIconSet {\n zoomIn: ToolbarIcon;\n zoomOut: ToolbarIcon;\n fit: ToolbarIcon;\n /** Required only when using the controlled `locked` toggle. */\n locked?: ToolbarIcon;\n unlocked?: ToolbarIcon;\n}\n\nexport interface CanvasControlsToolbarProps {\n /** Where the controls pin within the canvas host. Default `'bottom-left'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'vertical'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Layer id the fit-to-content button targets. Default `'graph'`. */\n fitLayerId?: string;\n /** Show zoom +/- buttons. Default `true`. */\n showZoom?: boolean;\n /**\n * Show a live `NN%` zoom readout between the +/- buttons. Sourced from the\n * canvas via the self-wired {@link ZoomControls}. Default `false`.\n */\n showZoomLevel?: boolean;\n /** Show the fit-to-content button. Default `true`. */\n showFit?: boolean;\n /** Icon components (consumer-supplied — the package stays icon-agnostic). */\n icons: CanvasControlsToolbarIconSet;\n /**\n * Controlled lock state. Lock is **not** auto-wired (what \"locked\" disables —\n * pan, node-drag, … — is app policy). Provide both `locked` and\n * `onToggleLock` (plus `icons.locked`/`icons.unlocked`) to render the toggle.\n */\n locked?: boolean;\n onToggleLock?: () => void;\n /**\n * Render **without** the self-positioning `<Panel>` — just the bare nav\n * component — so it composes into consumer chrome. Default `false`.\n */\n bare?: boolean;\n /** Explicit canvas instance; forwarded to each smart component. Defaults to context canvas. */\n canvas?: EngineCanvas | null;\n /** Extra controls appended after the presets — e.g. `<ControlButton>`s. */\n children?: ReactNode;\n className?: string;\n}\n\n/**\n * Turnkey controls overlay — the canvas equivalent of React Flow's `<Controls>`.\n * Assembled from self-wiring smart components ({@link ZoomControls},\n * {@link FitContentButton}) arranged in a {@link NavVertical} or\n * {@link NavHorizontal} from `@invana/ui`. No hook wiring needed — drop inside\n * a `<Canvas>` with an `icons` prop and it works.\n *\n * Lock stays **controlled** — pass `locked` + `onToggleLock` to surface it.\n * Append extra controls as `children`.\n *\n * @example\n * // Pattern A — drop inside a <Canvas>, self-wires via context:\n * <Canvas>\n * <GraphLayer id=\"graph\" data={data} />\n * <CanvasControlsToolbar icons={{ zoomIn: ZoomIn, zoomOut: ZoomOut, fit: Maximize }} />\n * </Canvas>\n *\n * @example\n * // Pattern B — one external controller driving the active canvas:\n * <div className=\"my-toolbar\">\n * <CanvasControlsToolbar bare canvas={activeCanvas} icons={…} />\n * </div>\n */\nexport function CanvasControlsToolbar({\n position = 'bottom-left',\n orientation = 'vertical',\n fitLayerId = 'graph',\n showZoom = true,\n showZoomLevel = false,\n showFit = true,\n icons,\n locked,\n onToggleLock,\n bare = false,\n canvas,\n children,\n className,\n}: CanvasControlsToolbarProps) {\n const showLock =\n locked !== undefined && onToggleLock && icons.locked && icons.unlocked;\n\n const controls = (\n <>\n {showZoom && (\n <ZoomControls\n orientation={orientation}\n canvas={canvas}\n zoomInIcon={icons.zoomIn}\n zoomOutIcon={icons.zoomOut}\n showLevel={showZoomLevel}\n />\n )}\n {showFit && (\n <FitContentButton icon={icons.fit} canvas={canvas} layerId={fitLayerId} />\n )}\n {showLock && (\n <LockToggle\n locked={locked}\n onToggle={onToggleLock}\n lockedIcon={icons.locked!}\n unlockedIcon={icons.unlocked!}\n />\n )}\n {children}\n </>\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n\n","import { NavHorizontal } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\nimport type { EdgePathType } from '@invana/graph';\n\nimport { ClearButton, EdgeTypePicker, OptionPicker, Panel } from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\n\nexport interface GraphToolbarProps {\n /** Layout switcher. */\n layout: string;\n layoutOptions: Record<string, string>;\n onLayoutChange: (value: string) => void;\n\n /** Selection-mode switcher (e.g. click / brush / lasso). */\n selectMode: string;\n selectModeOptions: Record<string, string>;\n onSelectModeChange: (value: string) => void;\n\n /**\n * Self-wiring edge-routing picker (straight / orthogonal / curved …) targeting\n * this `GraphLayer` id. Default `'graph'`; pass `null` to hide the picker.\n */\n edgeTypeLayerId?: string | null;\n /** Path types the edge picker exposes, in order. Default: straight / orth / bezier / rounded / smooth. */\n edgeTypes?: readonly EdgePathType[];\n /** Optional key → label map for the edge picker. */\n edgeTypeLabels?: Record<string, string>;\n /** Per-option icons for the edge picker (key → icon component). */\n edgeTypeIcons?: Record<string, ToolbarIcon>;\n\n /** Clear button — layer to clear. Default `'graph'`. */\n clearLayerId?: string;\n clearIcon?: ToolbarIcon;\n /** Explicit canvas instance; forwarded to the self-wiring {@link ClearButton}. Defaults to context canvas. */\n canvas?: EngineCanvas | null;\n\n /** Where the toolbar pins within the canvas host. Default `'top-center'`. */\n position?: PanelPosition;\n className?: string;\n}\n\n/**\n * Turnkey **horizontal** graph toolbar: a layout picker + selection-mode picker\n * + a self-wiring {@link EdgeTypePicker} (edge routing) + clear action, grouped\n * in a `@invana/ui` `NavHorizontal`. The layout / select pickers are\n * callback-driven (the consumer wires them to the engine); the edge-type and\n * clear actions self-wire from their layer id. Compose the underlying\n * {@link OptionPicker} / {@link EdgeTypePicker} / {@link ClearButton} primitives\n * directly for a custom arrangement.\n *\n * Self-positioning: it wraps itself in a {@link Panel}, so it overlays the\n * canvas host directly — render it as a child of `<Canvas>` (no hand-rolled\n * absolute wrapper needed). Positioning is the Panel's job (`position`); there\n * is no internal `align` knob.\n */\nexport function GraphToolbar({\n layout,\n layoutOptions,\n onLayoutChange,\n selectMode,\n selectModeOptions,\n onSelectModeChange,\n edgeTypeLayerId = 'graph',\n edgeTypes,\n edgeTypeLabels,\n edgeTypeIcons,\n clearLayerId = 'graph',\n clearIcon,\n canvas,\n position = 'top-center',\n className,\n}: GraphToolbarProps) {\n return (\n <Panel position={position} orientation=\"horizontal\">\n <NavHorizontal\n className={className}\n center={\n <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>\n <OptionPicker\n label=\"Layout\"\n value={layout}\n options={layoutOptions}\n onChange={onLayoutChange}\n />\n <OptionPicker\n label=\"Select\"\n value={selectMode}\n options={selectModeOptions}\n onChange={onSelectModeChange}\n />\n {edgeTypeLayerId != null && (\n <EdgeTypePicker\n layerId={edgeTypeLayerId}\n {...(edgeTypes ? { types: edgeTypes } : {})}\n {...(edgeTypeLabels ? { labels: edgeTypeLabels } : {})}\n {...(edgeTypeIcons ? { icons: edgeTypeIcons } : {})}\n canvas={canvas}\n />\n )}\n <ClearButton icon={clearIcon} layerId={clearLayerId} canvas={canvas} />\n </div>\n }\n />\n </Panel>\n );\n}\n","import { NavHorizontal, NavVertical } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Panel, UndoButton, RedoButton, RedrawButton } from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\n\nexport interface HistoryToolbarIconSet {\n undo: ToolbarIcon;\n redo: ToolbarIcon;\n /** Required only when `showRedraw` is left on. */\n redraw?: ToolbarIcon;\n}\n\nexport interface HistoryToolbarProps {\n icons: HistoryToolbarIconSet;\n /** Where the toolbar pins. Default `'top-left'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'horizontal'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Show the redraw button (needs `icons.redraw`). Default `true`. */\n showRedraw?: boolean;\n /** Layer the redraw button targets. Default `'graph'`. */\n layerId?: string;\n /** Render without the `<Panel>` wrapper (embed in external chrome). Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Undo / redo / redraw bar. Self-wires through {@link useHistory}; requires a\n * `<GraphHistoryProvider>` ancestor for undo/redo (redraw works regardless).\n */\nexport function HistoryToolbar({\n icons,\n position = 'top-left',\n orientation = 'horizontal',\n showRedraw = true,\n layerId,\n bare = false,\n canvas,\n className,\n}: HistoryToolbarProps) {\n const controls = (\n <>\n <UndoButton icon={icons.undo} canvas={canvas} />\n <RedoButton icon={icons.redo} canvas={canvas} />\n {showRedraw && icons.redraw && (\n <RedrawButton icon={icons.redraw} layerId={layerId} canvas={canvas} />\n )}\n </>\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n","import { NavHorizontal, NavVertical } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport {\n Panel,\n CutButton,\n CopyButton,\n PasteButton,\n DeleteSelectionButton,\n ClearButton,\n} from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\n\nexport interface EditToolbarIconSet {\n cut: ToolbarIcon;\n copy: ToolbarIcon;\n paste: ToolbarIcon;\n delete: ToolbarIcon;\n /** Optional leading icon for the (labelled) Clear button. */\n clear?: ToolbarIcon;\n}\n\nexport interface EditToolbarProps {\n icons: EditToolbarIconSet;\n /** Where the toolbar pins. Default `'top-left'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'horizontal'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Show the clear-canvas button. Default `true`. */\n showClear?: boolean;\n /** Id of the `ClickSelectBehaviour` selection is read from. Default `'click-select'`. */\n clickSelectId?: string;\n /** Layer that clear / clipboard target. Default `'graph'`. */\n layerId?: string;\n /** Render without the `<Panel>` wrapper. Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Clipboard / edit bar — cut, copy, paste, delete selection, clear canvas. The\n * clipboard actions self-wire through {@link useClipboard} (require a\n * `<GraphClipboardProvider>` + a `ClickSelectBehaviour`); clear self-wires\n * through {@link useClearGraph}. All edits are undoable when a\n * `<GraphHistoryProvider>` is present.\n */\nexport function EditToolbar({\n icons,\n position = 'top-left',\n orientation = 'horizontal',\n showClear = true,\n clickSelectId,\n layerId,\n bare = false,\n canvas,\n className,\n}: EditToolbarProps) {\n const controls = (\n <>\n <CutButton icon={icons.cut} clickSelectId={clickSelectId} canvas={canvas} />\n <CopyButton icon={icons.copy} clickSelectId={clickSelectId} canvas={canvas} />\n <PasteButton icon={icons.paste} clickSelectId={clickSelectId} canvas={canvas} />\n <DeleteSelectionButton\n icon={icons.delete}\n clickSelectId={clickSelectId}\n canvas={canvas}\n />\n {showClear && <ClearButton icon={icons.clear} layerId={layerId} canvas={canvas} />}\n </>\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n","import { NavHorizontal, NavVertical } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport {\n Panel,\n ZoomControls,\n ZoomPicker,\n FitContentButton,\n LockButton,\n} from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\n\nexport interface ViewToolbarIconSet {\n zoomIn: ToolbarIcon;\n zoomOut: ToolbarIcon;\n fit: ToolbarIcon;\n /** Required only when the lock toggle is shown. */\n locked?: ToolbarIcon;\n unlocked?: ToolbarIcon;\n}\n\nexport interface ViewToolbarProps {\n icons: ViewToolbarIconSet;\n /** Where the toolbar pins. Default `'bottom-left'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'vertical'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Show zoom in/out buttons. Default `true`. */\n showZoom?: boolean;\n /** Show the live NN% readout between the zoom buttons. Default `false`. */\n showZoomLevel?: boolean;\n /** Show the zoom-level preset picker. Default `true`. */\n showZoomPicker?: boolean;\n /** Show the fit-to-content button. Default `true`. */\n showFit?: boolean;\n /** Show the lock toggle (needs `icons.locked` + `icons.unlocked`). Default `true`. */\n showLock?: boolean;\n /** Layer that fit + zoom-picker target. Default `'graph'`. */\n layerId?: string;\n /** Behaviour ids disabled while locked. Default `['pan', 'drag-node']`. */\n lockBehaviourIds?: string[];\n /** Render without the `<Panel>` wrapper. Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * View controls — zoom in/out, zoom-level picker, fit-to-content, lock view.\n * Zoom + fit self-wire through the camera hooks; lock self-wires through\n * {@link useLock} (disables pan + node drag by default, leaving zoom available).\n */\nexport function ViewToolbar({\n icons,\n position = 'bottom-left',\n orientation = 'vertical',\n showZoom = true,\n showZoomLevel = false,\n showZoomPicker = true,\n showFit = true,\n showLock = true,\n layerId = 'graph',\n lockBehaviourIds,\n bare = false,\n canvas,\n className,\n}: ViewToolbarProps) {\n const lockReady = showLock && icons.locked && icons.unlocked;\n const controls = (\n <>\n {showZoom && (\n <ZoomControls\n orientation={orientation}\n canvas={canvas}\n zoomInIcon={icons.zoomIn}\n zoomOutIcon={icons.zoomOut}\n showLevel={showZoomLevel}\n />\n )}\n {showZoomPicker && <ZoomPicker canvas={canvas} layerId={layerId} />}\n {showFit && <FitContentButton icon={icons.fit} canvas={canvas} layerId={layerId} />}\n {lockReady && (\n <LockButton\n lockedIcon={icons.locked!}\n unlockedIcon={icons.unlocked!}\n behaviourIds={lockBehaviourIds}\n canvas={canvas}\n />\n )}\n </>\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n","import { NavHorizontal, NavVertical } from '@invana/ui';\nimport type { Canvas as EngineCanvas, BackgroundLayerOptions } from '@invana/canvas';\n\nimport { Panel, GridToggle } from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\n\ntype PatternType = NonNullable<BackgroundLayerOptions['patternType']>;\n\nexport interface GridToolbarIconSet {\n grid: ToolbarIcon;\n}\n\nexport interface GridToolbarProps {\n icons: GridToolbarIconSet;\n /** Where the toolbar pins. Default `'bottom-right'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'horizontal'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Id of the `BackgroundLayer` to toggle. Default `'background'`. */\n backgroundLayerId?: string;\n /** Pattern to switch to when shown (e.g. `'grid'`); preserves existing if omitted. */\n patternType?: PatternType;\n /** Render without the `<Panel>` wrapper. Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Grid toggle bar — shows/hides a `BackgroundLayer`'s pattern. Self-wires\n * through {@link useGrid}.\n */\nexport function GridToolbar({\n icons,\n position = 'bottom-right',\n orientation = 'horizontal',\n backgroundLayerId,\n patternType,\n bare = false,\n canvas,\n className,\n}: GridToolbarProps) {\n const controls = (\n <GridToggle\n icon={icons.grid}\n backgroundLayerId={backgroundLayerId}\n patternType={patternType}\n canvas={canvas}\n />\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n","import { NavHorizontal, Separator } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Panel, LayoutPicker, SelectModePicker } from '../components';\nimport type { PanelPosition, ToolbarIcon } from '../components';\nimport type { LayoutFactory } from '../hooks/useLayout';\n\nexport interface GraphLayoutToolbarProps {\n /** Map of layout key → factory producing a fresh layout instance. Memoize it. */\n layouts: Record<string, LayoutFactory>;\n /** Map of select-mode key → behaviour id (e.g. `{ click: 'click-select', ... }`). Memoize it. */\n selectModeBehaviourIds: Record<string, string>;\n /** Optional layout key → label map. Default: identity. */\n layoutLabels?: Record<string, string>;\n /** Optional select-mode key → label map. Default: identity. */\n selectModeLabels?: Record<string, string>;\n /** Optional select-mode key → icon map. Shown on the trigger and beside each option. */\n selectModeIcons?: Record<string, ToolbarIcon>;\n /** Initially-selected layout key. */\n initialLayout?: string;\n /** Initially-active select mode key. */\n initialSelectMode?: string;\n /** Target `GraphLayer` id. Default `'graph'`. */\n layerId?: string;\n /** Where the toolbar pins. Default `'top-center'`. */\n position?: PanelPosition;\n /** Render without the `<Panel>` wrapper (embed in external chrome). Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Graph controls — layout selector + selection-mode selector. Both self-wire\n * ({@link useLayout} / {@link useSelectMode}), but since layouts live in\n * separate packages and mode-switching toggles consumer-registered behaviours,\n * the consumer supplies the layout factory map and the mode→behaviour-id map.\n */\nexport function GraphLayoutToolbar({\n layouts,\n selectModeBehaviourIds,\n layoutLabels,\n selectModeLabels,\n selectModeIcons,\n initialLayout,\n initialSelectMode,\n layerId,\n position = 'top-center',\n bare = false,\n canvas,\n className,\n}: GraphLayoutToolbarProps) {\n const nav = (\n <NavHorizontal\n className={className}\n center={\n <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>\n <LayoutPicker\n layouts={layouts}\n labels={layoutLabels}\n initial={initialLayout}\n layerId={layerId}\n canvas={canvas}\n />\n <Separator orientation=\"vertical\" style={{ alignSelf: 'center', height: 24 }} />\n <SelectModePicker\n behaviourIds={selectModeBehaviourIds}\n labels={selectModeLabels}\n icons={selectModeIcons}\n initial={initialSelectMode}\n canvas={canvas}\n />\n </div>\n }\n />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation=\"horizontal\">\n {nav}\n </Panel>\n );\n}\n","import { NavHorizontal, NavVertical } from '@invana/ui';\nimport type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport {\n Panel,\n ControlButton,\n OptionPicker,\n UndoButton,\n RedoButton,\n ClearButton,\n} from '../components';\nimport type { PanelPosition, ToolbarIcon, TooltipSide } from '../components';\nimport { useTool } from '../hooks/useTool';\nimport type { GraphTool } from '../ToolContext';\n\n/** Icons for the modeller toolbar. The four tool icons are required; the rest gate their controls. */\nexport interface ModellerToolbarIconSet {\n select: ToolbarIcon;\n add: ToolbarIcon;\n connect: ToolbarIcon;\n delete: ToolbarIcon;\n /** Required when `showHistory` is on (the default). */\n undo?: ToolbarIcon;\n redo?: ToolbarIcon;\n /** Optional leading icon for the Clear button. */\n clear?: ToolbarIcon;\n}\n\nexport interface ModellerToolbarProps {\n icons: ModellerToolbarIconSet;\n /** Which tool toggles to show, in order. Default `['select','add','connect','delete']`. */\n tools?: readonly GraphTool[];\n /** Override the tool tooltips / accessible labels. */\n labels?: Partial<Record<GraphTool, string>>;\n /**\n * Node-kind options for the **Add** tool's shape picker (key → label). The\n * picker shows only while the Add tool is active. Omit / leave empty to hide\n * it (e.g. when your `createNode` factory is fixed-shape).\n */\n nodeKinds?: Record<string, string>;\n /** Per-kind icons for the shape picker. */\n nodeKindIcons?: Record<string, ToolbarIcon>;\n /** Show undo / redo (needs `icons.undo` + `icons.redo`). Default `true`. */\n showHistory?: boolean;\n /** Show the clear-canvas button. Default `true`. */\n showClear?: boolean;\n /** Layer the clear button targets. Default `'graph'`. */\n layerId?: string;\n /** Where the toolbar pins. Default `'top-center'`. */\n position?: PanelPosition;\n /** Stack direction. Default `'horizontal'`. */\n orientation?: 'horizontal' | 'vertical';\n /** Render without the `<Panel>` wrapper (embed in external chrome). Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\nconst DEFAULT_TOOLS: readonly GraphTool[] = ['select', 'add', 'connect', 'delete'];\nconst DEFAULT_LABELS: Record<GraphTool, string> = {\n select: 'Select',\n add: 'Add node',\n connect: 'Connect',\n delete: 'Delete',\n};\n\n/**\n * Turnkey **drawing / modeller** toolbar — tool toggles (Select / Add / Connect\n * / Delete) plus an optional Add-tool shape picker, undo/redo, and clear. The\n * canvas equivalent of a drawing app's tool palette.\n *\n * Self-wires the tool toggles through {@link useTool} (requires a\n * `<GraphToolProvider>` ancestor) and the undo/redo/clear actions through their\n * own hooks (a `<GraphHistoryProvider>` makes them live). The consumer still\n * declares the drawing behaviours, gating each one's `enabled` on the active\n * tool — this toolbar owns the *tool state*, not the behaviours.\n */\nexport function ModellerToolbar({\n icons,\n tools = DEFAULT_TOOLS,\n labels,\n nodeKinds,\n nodeKindIcons,\n showHistory = true,\n showClear = true,\n layerId,\n position = 'top-center',\n orientation = 'horizontal',\n bare = false,\n canvas,\n className,\n}: ModellerToolbarProps) {\n const { tool, setTool, nodeKind, setNodeKind } = useTool();\n const tipSide: TooltipSide = orientation === 'vertical' ? 'right' : 'bottom';\n const label = (t: GraphTool): string => labels?.[t] ?? DEFAULT_LABELS[t];\n\n const controls = (\n <>\n {tools.map((t) => (\n <ControlButton\n key={t}\n icon={icons[t]}\n title={label(t)}\n tooltipSide={tipSide}\n active={tool === t}\n onClick={() => setTool(t)}\n />\n ))}\n {tool === 'add' && nodeKinds && Object.keys(nodeKinds).length > 0 && (\n <OptionPicker\n label=\"Shape\"\n value={nodeKind}\n options={nodeKinds}\n {...(nodeKindIcons ? { icons: nodeKindIcons } : {})}\n onChange={setNodeKind}\n tooltipSide={tipSide}\n />\n )}\n {showHistory && icons.undo && icons.redo && (\n <>\n <UndoButton icon={icons.undo} tooltipSide={tipSide} canvas={canvas} />\n <RedoButton icon={icons.redo} tooltipSide={tipSide} canvas={canvas} />\n </>\n )}\n {showClear && (\n <ClearButton icon={icons.clear} layerId={layerId} tooltipSide={tipSide} canvas={canvas} />\n )}\n </>\n );\n\n const nav =\n orientation === 'vertical' ? (\n <NavVertical top={controls} className={className} />\n ) : (\n <NavHorizontal left={controls} className={className} />\n );\n\n if (bare) return nav;\n return (\n <Panel position={position} orientation={orientation}>\n {nav}\n </Panel>\n );\n}\n","import type { Canvas as EngineCanvas } from '@invana/canvas';\n\nimport { Panel, PropertiesEditor } from '../components';\nimport type { PanelPosition } from '../components';\nimport { useEntityEditor } from '../hooks/useEntityEditor';\n\nexport interface InspectorPanelProps {\n /** GraphLayer to read/write. Default `'graph'`. */\n layerId?: string;\n /** Id of the `ClickInspectBehaviour` the edit target is read from. Default `'click-inspect'`. */\n inspectId?: string;\n /** Where the panel pins. Default `'top-right'`. */\n position?: PanelPosition;\n /** Show the label field (nodes, non-`typeAsLabel` mode only). Default `true`. */\n showLabel?: boolean;\n /**\n * Modeller mode — edit a single `type` field on both nodes and edges that also\n * drives the drawn label. Hides the label field for both. Default `false`.\n */\n typeAsLabel?: boolean;\n /** Heading when a node is selected. Default `'Node'`. */\n nodeTitle?: string;\n /** Heading when an edge is selected. Default `'Edge'`. */\n edgeTitle?: string;\n /** Render the bare editor without the `<Panel>` wrapper. Default `false`. */\n bare?: boolean;\n /** Explicit canvas instance; defaults to the context canvas. */\n canvas?: EngineCanvas | null;\n className?: string;\n}\n\n/**\n * Self-wiring **inspector** — shows a {@link PropertiesEditor} for the single\n * node/edge the user clicked to edit and commits edits (label + `data`, plus\n * `type` + reverse for edges) back to the store undoably. The property-editing\n * analogue of `CanvasControlsToolbar`: drop it inside `<Canvas>` and it appears\n * whenever an element is clicked for editing, and renders nothing otherwise.\n *\n * Needs a `ClickInspectBehaviour` (for the click-to-edit target) and, for\n * undoable commits, a `<GraphHistoryProvider>` ancestor. Remounts the editor\n * (via `key`) when the targeted element changes, so the form reloads from it.\n */\nexport function InspectorPanel({\n layerId,\n inspectId,\n position = 'top-right',\n showLabel,\n typeAsLabel = false,\n nodeTitle = 'Node',\n edgeTitle = 'Edge',\n bare = false,\n canvas,\n className,\n}: InspectorPanelProps) {\n const opts: { layerId?: string; inspectId?: string; typeAsLabel?: boolean } = {};\n if (layerId !== undefined) opts.layerId = layerId;\n if (inspectId !== undefined) opts.inspectId = inspectId;\n if (typeAsLabel) opts.typeAsLabel = true;\n\n const target = useEntityEditor(opts, canvas);\n if (!target) return null;\n\n const isEdge = target.kind === 'edge';\n // The `type` field shows for edges always, and for nodes too in `typeAsLabel`\n // mode; the `label` field shows only for nodes when NOT in `typeAsLabel` mode.\n const showTypeField = typeAsLabel || isEdge;\n const showLabelField = !showTypeField && (showLabel ?? true);\n const editor = (\n <PropertiesEditor\n key={`${target.kind}:${target.id}`}\n title={isEdge ? edgeTitle : nodeTitle}\n defaults={{ label: target.label, type: target.type, data: target.data }}\n onSubmit={target.commit}\n showLabel={showLabelField}\n {...(showTypeField ? { showType: true } : {})}\n {...(isEdge && target.reverse ? { onReverse: target.reverse } : {})}\n {...(className !== undefined ? { className } : {})}\n />\n );\n\n if (bare) return editor;\n return (\n <Panel position={position} orientation=\"vertical\">\n {editor}\n </Panel>\n );\n}\n","import { useCallback, type CSSProperties } from 'react';\nimport type { Canvas } from '@invana/canvas';\nimport type { ContextMenuEvent, ContextMenuTargetType } from '@invana/graph';\nimport type { MenuItem } from '@invana/ui';\n\nimport { useCanvas } from '../CanvasContext';\nimport { ContextMenuBehaviour } from '../behaviours/ContextMenuBehaviour';\nimport { ContextMenuOverlay } from '../components/ContextMenuOverlay';\nimport { useContextMenu } from '../hooks/useContextMenu';\n\n/**\n * Context handed to a context-menu `items` builder for an empty-canvas\n * (background) right-click. Carries the pointer position, the live `Canvas`,\n * and a `close` callback for items that need to dismiss the menu explicitly\n * (auto-close already fires `close` after every leaf `onClick`).\n */\nexport interface GraphContextMenuContext {\n /** Pointer position in world (scene) coordinates — e.g. to place a new node. */\n readonly world: { readonly x: number; readonly y: number };\n /** Pointer position in canvas-relative screen px (where the overlay sits). */\n readonly screen: { readonly x: number; readonly y: number };\n /** The live engine instance, for reaching layers / behaviours / camera. */\n readonly canvas: Canvas;\n /** Dismiss the menu. Available for manual control; auto-close uses it too. */\n readonly close: () => void;\n}\n\n/**\n * Context handed to a node/edge context-menu `items` builder. Extends\n * {@link GraphContextMenuContext} with the right-clicked element's `id` and its\n * arbitrary `data` payload (`node.data` / `edge.data`).\n */\nexport interface GraphTargetMenuContext extends GraphContextMenuContext {\n /** Id of the right-clicked node / edge. */\n readonly id: string;\n /** Arbitrary user payload from `node.data` / `edge.data` (`undefined` if none). */\n readonly data: unknown;\n}\n\n/** Options shared by all three `Graph*ContextMenu` components. */\nexport interface GraphContextMenuCommonProps {\n /** GraphLayer id whose nodes/edges this menu watches; default `'graph'`. */\n layerId?: string;\n /** Whether the menu is active; reactive. Default `true`. */\n enabled?: boolean;\n /** Stacking order of the overlay; default `1000`. */\n zIndex?: number;\n /** Extra inline style merged onto the overlay wrapper. */\n style?: CSSProperties;\n /**\n * Auto-close the menu after any leaf item's `onClick`. Default `true`.\n * Set `false` to manage dismissal yourself via `ctx.close`.\n */\n autoClose?: boolean;\n}\n\n/**\n * Recursively wrap every leaf `onClick` so it also closes the menu. Items that\n * only open a submenu (no `onClick`) are left untouched; their `children` are\n * wrapped in turn. `close` is idempotent, so an `onClick` that already calls it\n * is harmless.\n */\nfunction withAutoClose(items: MenuItem[], close: () => void): MenuItem[] {\n return items.map((item) => {\n const next: MenuItem = { ...item };\n if (item.children) next.children = withAutoClose(item.children, close);\n if (item.onClick) {\n const original = item.onClick;\n next.onClick = (): void => {\n original();\n close();\n };\n }\n return next;\n });\n}\n\n/** Props for the internal single-target root the public components delegate to. */\ninterface GraphContextMenuRootProps extends GraphContextMenuCommonProps {\n /** The one target type this menu responds to. */\n target: ContextMenuTargetType;\n /** Behaviour id — unique per target so the three menus coexist. */\n id: string;\n /** Transient state to mark the right-clicked node/edge while open (node/edge only). */\n state?: string | null;\n /** Build the menu tree from the right-click event + shared context. */\n build: (event: ContextMenuEvent, base: GraphContextMenuContext) => MenuItem[];\n}\n\n/**\n * Shared engine for the three target-scoped context menus. Owns one\n * single-target `ContextMenuBehaviour`, the open/close state (via\n * `useContextMenu`), and the overlay. The public components are thin wrappers\n * that fix `target` / `id` and adapt the event into their typed `items` builder.\n *\n * Not exported from the package — use `GraphNodeContextMenu`,\n * `GraphEdgeContextMenu`, or `GraphBackgroundContextMenu`.\n */\nexport function GraphContextMenuRoot({\n target,\n id,\n layerId = 'graph',\n enabled = true,\n zIndex,\n style,\n autoClose = true,\n state = null,\n build,\n}: GraphContextMenuRootProps) {\n const canvas = useCanvas();\n const { menu, open, close } = useContextMenu<MenuItem[]>();\n\n const onContextMenu = useCallback(\n (event: ContextMenuEvent): void => {\n const base: GraphContextMenuContext = {\n world: event.world,\n screen: event.screen,\n canvas,\n close,\n };\n const items = build(event, base);\n open(event.screen.x, event.screen.y, autoClose ? withAutoClose(items, close) : items);\n },\n [canvas, build, autoClose, open, close],\n );\n\n return (\n <>\n <ContextMenuBehaviour\n id={id}\n layerId={layerId}\n enabled={enabled}\n targets={[target]}\n state={state}\n onContextMenu={onContextMenu}\n />\n {menu && (\n <ContextMenuOverlay x={menu.x} y={menu.y} items={menu.items} zIndex={zIndex} style={style} />\n )}\n </>\n );\n}\n","import { useCallback } from 'react';\nimport type { ContextMenuEvent } from '@invana/graph';\nimport type { MenuItem } from '@invana/ui';\n\nimport {\n GraphContextMenuRoot,\n type GraphContextMenuCommonProps,\n type GraphContextMenuContext,\n type GraphTargetMenuContext,\n} from './GraphContextMenuBase';\n\n/** Context handed to {@link GraphNodeContextMenuProps.items}. */\nexport type GraphNodeMenuContext = GraphTargetMenuContext;\n\nexport interface GraphNodeContextMenuProps extends GraphContextMenuCommonProps {\n /**\n * Build the menu shown when a **node** is right-clicked. Receives the node's\n * `id`, its `data`, the pointer position, the live `canvas`, and `close`.\n * Return the `@invana/ui` `MenuItem[]` to render.\n */\n items: (ctx: GraphNodeMenuContext) => MenuItem[];\n /** Behaviour id; default `'node-context-menu'`. */\n id?: string;\n /**\n * Transient state name applied to the right-clicked node while the menu is\n * open (e.g. `'context-open'`), cleared on the next open / dismiss. Default\n * `null` (no marker).\n */\n state?: string | null;\n}\n\n/**\n * Node-scoped right-click menu for a `GraphLayer`. Drop it inside `<Canvas>`\n * (alongside the layer) and pass an `items` builder — the behaviour wiring,\n * positioning, dismissal (outside-click / Escape), and auto-close are handled\n * internally.\n *\n * Pairs with {@link GraphEdgeContextMenu} and {@link GraphBackgroundContextMenu};\n * each owns a distinct behaviour scoped to its own target, so the three compose\n * without conflict.\n *\n * @example\n * ```tsx\n * <GraphNodeContextMenu\n * items={({ id, canvas, close }) => [\n * { id: 'edit', label: 'Edit', onClick: () => editNode(id) },\n * { id: 'delete', label: 'Delete', onClick: () => deleteNode(id) },\n * ]}\n * />\n * ```\n */\nexport function GraphNodeContextMenu({\n items,\n id = 'node-context-menu',\n ...common\n}: GraphNodeContextMenuProps) {\n const build = useCallback(\n (event: ContextMenuEvent, base: GraphContextMenuContext): MenuItem[] =>\n items({ ...base, id: event.id as string, data: event.data }),\n [items],\n );\n return <GraphContextMenuRoot target=\"node\" id={id} build={build} {...common} />;\n}\n","import { useCallback } from 'react';\nimport type { ContextMenuEvent } from '@invana/graph';\nimport type { MenuItem } from '@invana/ui';\n\nimport {\n GraphContextMenuRoot,\n type GraphContextMenuCommonProps,\n type GraphContextMenuContext,\n type GraphTargetMenuContext,\n} from './GraphContextMenuBase';\n\n/** Context handed to {@link GraphEdgeContextMenuProps.items}. */\nexport type GraphEdgeMenuContext = GraphTargetMenuContext;\n\nexport interface GraphEdgeContextMenuProps extends GraphContextMenuCommonProps {\n /**\n * Build the menu shown when an **edge** is right-clicked. Receives the edge's\n * `id`, its `data`, the pointer position, the live `canvas`, and `close`.\n * Return the `@invana/ui` `MenuItem[]` to render.\n */\n items: (ctx: GraphEdgeMenuContext) => MenuItem[];\n /** Behaviour id; default `'edge-context-menu'`. */\n id?: string;\n /**\n * Transient state name applied to the right-clicked edge while the menu is\n * open (e.g. `'context-open'`), cleared on the next open / dismiss. Default\n * `null` (no marker).\n */\n state?: string | null;\n}\n\n/**\n * Edge-scoped right-click menu for a `GraphLayer`. Drop it inside `<Canvas>`\n * (alongside the layer) and pass an `items` builder — the behaviour wiring,\n * positioning, dismissal (outside-click / Escape), and auto-close are handled\n * internally.\n *\n * Pairs with {@link GraphNodeContextMenu} and {@link GraphBackgroundContextMenu};\n * each owns a distinct behaviour scoped to its own target, so the three compose\n * without conflict.\n *\n * @example\n * ```tsx\n * <GraphEdgeContextMenu\n * items={({ id, close }) => [\n * { id: 'reverse', label: 'Reverse direction', onClick: () => reverseEdge(id) },\n * { id: 'delete', label: 'Delete', onClick: () => deleteEdge(id) },\n * ]}\n * />\n * ```\n */\nexport function GraphEdgeContextMenu({\n items,\n id = 'edge-context-menu',\n ...common\n}: GraphEdgeContextMenuProps) {\n const build = useCallback(\n (event: ContextMenuEvent, base: GraphContextMenuContext): MenuItem[] =>\n items({ ...base, id: event.id as string, data: event.data }),\n [items],\n );\n return <GraphContextMenuRoot target=\"edge\" id={id} build={build} {...common} />;\n}\n","import { useCallback } from 'react';\nimport type { ContextMenuEvent } from '@invana/graph';\nimport type { MenuItem } from '@invana/ui';\n\nimport {\n GraphContextMenuRoot,\n type GraphContextMenuCommonProps,\n type GraphContextMenuContext,\n} from './GraphContextMenuBase';\n\n/** Context handed to {@link GraphBackgroundContextMenuProps.items}. */\nexport type GraphBackgroundMenuContext = GraphContextMenuContext;\n\nexport interface GraphBackgroundContextMenuProps extends GraphContextMenuCommonProps {\n /**\n * Build the menu shown when the **empty canvas** is right-clicked. Receives\n * the pointer position (`world` is handy for \"add node here\"), the live\n * `canvas`, and `close`. Return the `@invana/ui` `MenuItem[]` to render.\n */\n items: (ctx: GraphBackgroundMenuContext) => MenuItem[];\n /** Behaviour id; default `'background-context-menu'`. */\n id?: string;\n}\n\n/**\n * Background-scoped right-click menu for a `GraphLayer` — fires on a right-click\n * over the empty canvas (not on any node or edge). Drop it inside `<Canvas>`\n * (alongside the layer) and pass an `items` builder — the behaviour wiring,\n * positioning, dismissal (outside-click / Escape), and auto-close are handled\n * internally.\n *\n * Pairs with {@link GraphNodeContextMenu} and {@link GraphEdgeContextMenu}; each\n * owns a distinct behaviour scoped to its own target, so the three compose\n * without conflict.\n *\n * @example\n * ```tsx\n * <GraphBackgroundContextMenu\n * items={({ world, canvas }) => [\n * { id: 'add', label: 'Add node here', onClick: () => addNodeAt(world) },\n * { id: 'fit', label: 'Fit to content', onClick: () => fit(canvas) },\n * ]}\n * />\n * ```\n */\nexport function GraphBackgroundContextMenu({\n items,\n id = 'background-context-menu',\n ...common\n}: GraphBackgroundContextMenuProps) {\n const build = useCallback(\n (_event: ContextMenuEvent, base: GraphContextMenuContext): MenuItem[] => items(base),\n [items],\n );\n return <GraphContextMenuRoot target=\"canvas\" id={id} build={build} {...common} />;\n}\n"]}
|