@peter.prib/renderengine 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +203 -2
- package/REFERENCE.md +2198 -0
- package/dist/renderengine-workspace.umd.js +46905 -0
- package/dist/renderengine.umd.js +42223 -0
- package/examples/archimate.html +66 -0
- package/examples/diagram-editor.html +51 -0
- package/package.json +65 -4
- package/src/BaseRenderer.js +57 -0
- package/src/CanvasRenderer.js +194 -0
- package/src/Mat4.js +111 -0
- package/src/OrbitCamera.js +57 -0
- package/src/RendererFactory.js +50 -0
- package/src/SVGRenderer.js +439 -0
- package/src/archimate.js +723 -0
- package/src/archimateArchiFormat.js +1693 -0
- package/src/archimateArchiTypes.js +72 -0
- package/src/archimateArchive.js +140 -0
- package/src/archimateCSV.js +127 -0
- package/src/archimateDrawio.js +182 -0
- package/src/archimateExchangeFormat.js +546 -0
- package/src/archimateRelationshipTable.js +93 -0
- package/src/archimateSpecializations.js +161 -0
- package/src/chartCatalog.js +589 -0
- package/src/charting/ArchimateDiagramEditor.js +1624 -0
- package/src/charting/ArchimateSpecializationSelector.js +134 -0
- package/src/charting/Axis.js +68 -0
- package/src/charting/CameraSeeder.js +30 -0
- package/src/charting/CatalogDialog.js +92 -0
- package/src/charting/Chart.js +37 -0
- package/src/charting/Chart3D.js +99 -0
- package/src/charting/ChartBox.js +80 -0
- package/src/charting/ChartData.js +27 -0
- package/src/charting/ChartRegistry.js +76 -0
- package/src/charting/CheckboxTreeSelector.js +304 -0
- package/src/charting/ColorField.js +107 -0
- package/src/charting/ColorPalette.js +88 -0
- package/src/charting/CommandHistory.js +176 -0
- package/src/charting/DataFilter.js +52 -0
- package/src/charting/Diagram.js +36 -0
- package/src/charting/Diagram3D.js +29 -0
- package/src/charting/DiagramClipboard.js +31 -0
- package/src/charting/DiagramEditor.js +3330 -0
- package/src/charting/DiagramEditorCommand.js +110 -0
- package/src/charting/DiagramEditorCommands.js +237 -0
- package/src/charting/DiagramEditorEdgeCommands.js +142 -0
- package/src/charting/DiagramEditorState.js +98 -0
- package/src/charting/DiagramRegistry.js +86 -0
- package/src/charting/DiagramTypeRegistry.js +326 -0
- package/src/charting/DiagramViewPropertiesDialog.js +46 -0
- package/src/charting/Edge.js +113 -0
- package/src/charting/ErrorBars.js +37 -0
- package/src/charting/FilterSystem.js +285 -0
- package/src/charting/FindReplaceDialog.js +139 -0
- package/src/charting/FormDialog.js +385 -0
- package/src/charting/Gauge.js +58 -0
- package/src/charting/Hierarchy.js +175 -0
- package/src/charting/HintPanel.js +86 -0
- package/src/charting/ImageSelector.js +148 -0
- package/src/charting/InteractionManager.js +725 -0
- package/src/charting/Legend.js +58 -0
- package/src/charting/MenuBar.js +62 -0
- package/src/charting/ModelFileFormat.js +115 -0
- package/src/charting/OrbitControls.js +77 -0
- package/src/charting/Palette.js +119 -0
- package/src/charting/PopupMenu.js +117 -0
- package/src/charting/PropertiesPanel.js +155 -0
- package/src/charting/PropertyListEditor.js +96 -0
- package/src/charting/PropertyLog.js +92 -0
- package/src/charting/SettingsCascade.js +93 -0
- package/src/charting/SettingsDialog.js +53 -0
- package/src/charting/SettingsManager.js +179 -0
- package/src/charting/SettingsViewPropertiesDialog.js +58 -0
- package/src/charting/ShapePaths.js +27 -0
- package/src/charting/Statistics.js +134 -0
- package/src/charting/TemplateCatalog.js +59 -0
- package/src/charting/TemplateLibrary.js +103 -0
- package/src/charting/TextStyle.js +168 -0
- package/src/charting/ViewFit.js +55 -0
- package/src/charting/ViewMenu.js +70 -0
- package/src/charting/ViewPropertiesDialog.js +77 -0
- package/src/charting/ViewTabStrip.js +81 -0
- package/src/charting/archimate/ArchiFileFormat.js +32 -0
- package/src/charting/archimate/ArchimateCanvasEditor.js +815 -0
- package/src/charting/archimate/ArchimateCsvFileFormat.js +35 -0
- package/src/charting/archimate/ArchimateEdge.js +137 -0
- package/src/charting/archimate/ArchimateElementTemplate.js +195 -0
- package/src/charting/archimate/ArchimatePalette.js +102 -0
- package/src/charting/archimate/CsvImportDialog.js +105 -0
- package/src/charting/archimate/CustomViewpoints.js +74 -0
- package/src/charting/archimate/DerivedEdge.js +29 -0
- package/src/charting/archimate/DrawioFileFormat.js +24 -0
- package/src/charting/archimate/ElementFilterRule.js +21 -0
- package/src/charting/archimate/ExchangeFileFormat.js +28 -0
- package/src/charting/archimate/ViewGroupTemplate.js +137 -0
- package/src/charting/archimate/ViewLineEdge.js +84 -0
- package/src/charting/archimate/ViewpointRule.js +45 -0
- package/src/charting/archimate/archimateFileFormats.js +12 -0
- package/src/charting/archimate/archimateNames.js +5 -0
- package/src/charting/archimate/csvMapping.js +122 -0
- package/src/charting/archimate/elementMenuItems.js +32 -0
- package/src/charting/archimate/elementProperties.js +146 -0
- package/src/charting/archimate/elementTypeChoices.js +7 -0
- package/src/charting/archimate/elementTypeGroups.js +19 -0
- package/src/charting/archimate/index.js +17 -0
- package/src/charting/archimate/specializationCatalogDialog.js +64 -0
- package/src/charting/archimate/typeGlyph.js +29 -0
- package/src/charting/arrangement/Arrangement.js +112 -0
- package/src/charting/arrangement/ArrangementCommand.js +29 -0
- package/src/charting/arrangement/BackgroundCommand.js +41 -0
- package/src/charting/arrangement/BackgroundGroup.js +18 -0
- package/src/charting/arrangement/GroupCommand.js +46 -0
- package/src/charting/arrangement/ItemGroup.js +62 -0
- package/src/charting/arrangement/LockCommand.js +32 -0
- package/src/charting/arrangement/UngroupCommand.js +27 -0
- package/src/charting/arrangement/alignment.js +88 -0
- package/src/charting/arrangement/arrangeMenuItems.js +25 -0
- package/src/charting/arrangement/index.js +11 -0
- package/src/charting/arrangement/layouts.js +233 -0
- package/src/charting/canvas/ArchiHint.js +78 -0
- package/src/charting/canvas/CanvasBoxKind.js +39 -0
- package/src/charting/canvas/CanvasPalette.js +49 -0
- package/src/charting/canvas/CanvasTemplateLibrary.js +61 -0
- package/src/charting/canvas/CanvasTemplateMenu.js +151 -0
- package/src/charting/canvas/EditHintCommand.js +28 -0
- package/src/charting/canvas/canvasBoxKinds.js +27 -0
- package/src/charting/canvas/canvasBoxMenuItems.js +40 -0
- package/src/charting/canvas/defaultCanvasTemplates.js +186 -0
- package/src/charting/canvas/diagramBoxKinds.js +12 -0
- package/src/charting/canvas/hintMenuItems.js +49 -0
- package/src/charting/charts/ArcGauge.js +55 -0
- package/src/charting/charts/AreaChart.js +71 -0
- package/src/charting/charts/BarChart.js +80 -0
- package/src/charting/charts/BarChart3D.js +56 -0
- package/src/charting/charts/BarChart3DOrbit.js +53 -0
- package/src/charting/charts/BarChartBase.js +70 -0
- package/src/charting/charts/BarGauge.js +42 -0
- package/src/charting/charts/BoxPlotChart.js +41 -0
- package/src/charting/charts/BubbleChart.js +99 -0
- package/src/charting/charts/BubbleChart3D.js +78 -0
- package/src/charting/charts/BulletGauge.js +87 -0
- package/src/charting/charts/CalendarHeatmapChart.js +204 -0
- package/src/charting/charts/CandlestickChart.js +54 -0
- package/src/charting/charts/ChordDiagram.js +130 -0
- package/src/charting/charts/DensityChart.js +73 -0
- package/src/charting/charts/DialGauge.js +65 -0
- package/src/charting/charts/DonutChart.js +15 -0
- package/src/charting/charts/FunnelChart.js +47 -0
- package/src/charting/charts/GanttChart.js +201 -0
- package/src/charting/charts/GaugeChart.js +175 -0
- package/src/charting/charts/GeoMapChart.js +146 -0
- package/src/charting/charts/GroupedBarChart.js +88 -0
- package/src/charting/charts/GroupedDistributionChart.js +70 -0
- package/src/charting/charts/HeatmapChart.js +80 -0
- package/src/charting/charts/HierarchyChart.js +39 -0
- package/src/charting/charts/HistogramChart.js +45 -0
- package/src/charting/charts/KpiTile.js +72 -0
- package/src/charting/charts/LagPlotChart.js +41 -0
- package/src/charting/charts/LineChart.js +124 -0
- package/src/charting/charts/MultiRingGauge.js +54 -0
- package/src/charting/charts/OutlineChart.js +95 -0
- package/src/charting/charts/ParallelCoordinatesChart.js +130 -0
- package/src/charting/charts/PieChart.js +56 -0
- package/src/charting/charts/PipeChart.js +88 -0
- package/src/charting/charts/PopulationPyramidChart.js +106 -0
- package/src/charting/charts/QQPlotChart.js +64 -0
- package/src/charting/charts/RadarChart.js +76 -0
- package/src/charting/charts/RadialBarChart.js +96 -0
- package/src/charting/charts/RingGauge.js +23 -0
- package/src/charting/charts/SankeyDiagram.js +174 -0
- package/src/charting/charts/ScatterChart.js +104 -0
- package/src/charting/charts/StackedAreaChart.js +15 -0
- package/src/charting/charts/StackedBarChart.js +33 -0
- package/src/charting/charts/StackedBarChart3DOrbit.js +58 -0
- package/src/charting/charts/StreamGraphChart.js +131 -0
- package/src/charting/charts/SunburstChart.js +57 -0
- package/src/charting/charts/ThermometerGauge.js +43 -0
- package/src/charting/charts/TreemapChart.js +54 -0
- package/src/charting/charts/ViolinChart.js +37 -0
- package/src/charting/charts/WaterfallChart.js +66 -0
- package/src/charting/charts/WordCloudChart.js +104 -0
- package/src/charting/diagramModel/AddViewCommand.js +33 -0
- package/src/charting/diagramModel/DiagramModel.js +39 -0
- package/src/charting/diagramModel/DiagramModelSearch.js +22 -0
- package/src/charting/diagramModel/DiagramView.js +50 -0
- package/src/charting/diagramModel/ModelHistory.js +43 -0
- package/src/charting/diagramModel/ModelReport.js +153 -0
- package/src/charting/diagramModel/ModelSearch.js +223 -0
- package/src/charting/diagramModel/RemoveViewCommand.js +25 -0
- package/src/charting/diagramModel/RenameViewCommand.js +21 -0
- package/src/charting/diagramModel/ReplaceTextCommand.js +25 -0
- package/src/charting/diagramModel/ViewSetChecker.js +34 -0
- package/src/charting/diagramModel/ViewSetModel.js +243 -0
- package/src/charting/diagramModel/index.js +6 -0
- package/src/charting/diagramModel/nameTransforms.js +29 -0
- package/src/charting/diagrams/ArchimateCommands.js +141 -0
- package/src/charting/diagrams/ArchimateDiagram.js +263 -0
- package/src/charting/diagrams/ArchimateModel.js +1155 -0
- package/src/charting/diagrams/ArchimateModelChecker.js +125 -0
- package/src/charting/diagrams/ArchimateModelReport.js +128 -0
- package/src/charting/diagrams/ArchimateModelSearch.js +41 -0
- package/src/charting/diagrams/ArchimateValidator.js +357 -0
- package/src/charting/diagrams/CanvasView.js +112 -0
- package/src/charting/diagrams/ContextMenu.js +37 -0
- package/src/charting/diagrams/DataModelDiagram.js +86 -0
- package/src/charting/diagrams/DataModelRelationshipStrategy.js +38 -0
- package/src/charting/diagrams/DerivedRelationships.js +102 -0
- package/src/charting/diagrams/EbnfDiagram.js +39 -0
- package/src/charting/diagrams/EdgeGeometry.js +553 -0
- package/src/charting/diagrams/EditViewItemCommand.js +128 -0
- package/src/charting/diagrams/ElementInstance.js +157 -0
- package/src/charting/diagrams/GraphDiagram.js +1340 -0
- package/src/charting/diagrams/GraphDiagram3D.js +152 -0
- package/src/charting/diagrams/GraphMetrics.js +81 -0
- package/src/charting/diagrams/GridOverlay.js +137 -0
- package/src/charting/diagrams/ImportRowsCommand.js +62 -0
- package/src/charting/diagrams/LabelHelper.js +108 -0
- package/src/charting/diagrams/MergeElementsCommand.js +101 -0
- package/src/charting/diagrams/NestInstanceCommand.js +34 -0
- package/src/charting/diagrams/NodeGeometry.js +158 -0
- package/src/charting/diagrams/PlaceItemsCommand.js +77 -0
- package/src/charting/diagrams/RadialLayout.js +101 -0
- package/src/charting/diagrams/RelationshipInstance.js +93 -0
- package/src/charting/diagrams/RemoveGroupFromViewCommand.js +28 -0
- package/src/charting/diagrams/RemoveLineCommand.js +27 -0
- package/src/charting/diagrams/ShowElementCommand.js +43 -0
- package/src/charting/diagrams/SvgCoordinate.js +17 -0
- package/src/charting/diagrams/SvgZoom.js +127 -0
- package/src/charting/diagrams/Tooltip.js +62 -0
- package/src/charting/diagrams/ViewConnectionInstance.js +102 -0
- package/src/charting/diagrams/ViewObjectInstance.js +56 -0
- package/src/charting/diagrams/commands/AddEdgeCommand.js +34 -0
- package/src/charting/diagrams/commands/AddNodeCommand.js +28 -0
- package/src/charting/diagrams/commands/AddWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/CreateFolderCommand.js +27 -0
- package/src/charting/diagrams/commands/DeleteEdgeCommand.js +30 -0
- package/src/charting/diagrams/commands/DeleteFolderCommand.js +47 -0
- package/src/charting/diagrams/commands/DeleteNodeCommand.js +35 -0
- package/src/charting/diagrams/commands/DeleteWaypointCommand.js +24 -0
- package/src/charting/diagrams/commands/GraphCommand.js +65 -0
- package/src/charting/diagrams/commands/InvertEdgeCommand.js +24 -0
- package/src/charting/diagrams/commands/MoveNodeCommand.js +44 -0
- package/src/charting/diagrams/commands/MoveWaypointCommand.js +27 -0
- package/src/charting/diagrams/commands/RenameEdgeCommand.js +23 -0
- package/src/charting/diagrams/commands/RenameFolderCommand.js +31 -0
- package/src/charting/diagrams/commands/RenameNodeCommand.js +27 -0
- package/src/charting/diagrams/commands/ResizeNodeCommand.js +46 -0
- package/src/charting/diagrams/commands/UpdateEdgeSideCommand.js +40 -0
- package/src/charting/diagrams/commands/index.js +17 -0
- package/src/charting/diagrams/duplicates.js +49 -0
- package/src/charting/diagrams/nesting.js +30 -0
- package/src/charting/diagrams/roadmap.js +77 -0
- package/src/charting/edgeMarkers/ArrowMarker.js +15 -0
- package/src/charting/edgeMarkers/CircleMarker.js +13 -0
- package/src/charting/edgeMarkers/CrowsFootMarker.js +16 -0
- package/src/charting/edgeMarkers/DiamondMarker.js +15 -0
- package/src/charting/edgeMarkers/EdgeMarker.js +34 -0
- package/src/charting/edgeMarkers/HalfArrowMarker.js +8 -0
- package/src/charting/edgeMarkers/HollowDiamondMarker.js +18 -0
- package/src/charting/edgeMarkers/HollowTriangleMarker.js +18 -0
- package/src/charting/edgeMarkers/OpenArrowMarker.js +17 -0
- package/src/charting/edgeMarkers/index.js +27 -0
- package/src/charting/edgeStyle/EdgeStyleCascade.js +22 -0
- package/src/charting/edgeStyle/EdgeStyleDialog.js +51 -0
- package/src/charting/edgeStyle/EdgeStyleSchema.js +43 -0
- package/src/charting/edgeStyle/SetStyleCommand.js +12 -0
- package/src/charting/edgeStyle/index.js +4 -0
- package/src/charting/emphasis/EmphasisRule.js +42 -0
- package/src/charting/emphasis/HighlightRule.js +24 -0
- package/src/charting/gauges/ArcTrack.js +51 -0
- package/src/charting/gauges/GaugeAnimation.js +51 -0
- package/src/charting/gauges/GaugeBands.js +48 -0
- package/src/charting/gauges/GaugeScale.js +87 -0
- package/src/charting/gauges/GaugeTrack.js +44 -0
- package/src/charting/gauges/GaugeValue.js +61 -0
- package/src/charting/gauges/HorizontalTrack.js +14 -0
- package/src/charting/gauges/LinearTrack.js +29 -0
- package/src/charting/gauges/Sparkline.js +42 -0
- package/src/charting/gauges/VerticalTrack.js +17 -0
- package/src/charting/glyphs/ArrowGlyph.js +21 -0
- package/src/charting/glyphs/BatteryGlyph.js +18 -0
- package/src/charting/glyphs/ChevronGlyph.js +18 -0
- package/src/charting/glyphs/CircleGlyph.js +15 -0
- package/src/charting/glyphs/CloudGlyph.js +19 -0
- package/src/charting/glyphs/ComponentGlyph.js +18 -0
- package/src/charting/glyphs/ConstraintGlyph.js +24 -0
- package/src/charting/glyphs/ContractBoxGlyph.js +10 -0
- package/src/charting/glyphs/CubeGlyph.js +19 -0
- package/src/charting/glyphs/CylinderGlyph.js +19 -0
- package/src/charting/glyphs/DashedDoubleArrowGlyph.js +11 -0
- package/src/charting/glyphs/DeviceGlyph.js +17 -0
- package/src/charting/glyphs/DiamondGlyph.js +17 -0
- package/src/charting/glyphs/DocumentGlyph.js +17 -0
- package/src/charting/glyphs/DoubleArrowGlyph.js +23 -0
- package/src/charting/glyphs/DoubleCircleGlyph.js +24 -0
- package/src/charting/glyphs/EllipseGlyph.js +18 -0
- package/src/charting/glyphs/FactoryGlyph.js +20 -0
- package/src/charting/glyphs/FlagGlyph.js +16 -0
- package/src/charting/glyphs/GapCircleGlyph.js +17 -0
- package/src/charting/glyphs/GearGlyph.js +37 -0
- package/src/charting/glyphs/Glyph.js +98 -0
- package/src/charting/glyphs/GroupingBoxGlyph.js +13 -0
- package/src/charting/glyphs/HalfCircleGlyph.js +22 -0
- package/src/charting/glyphs/HexagonGlyph.js +28 -0
- package/src/charting/glyphs/IconGlyph.js +22 -0
- package/src/charting/glyphs/ImageGlyph.js +16 -0
- package/src/charting/glyphs/JunctionGlyph.js +17 -0
- package/src/charting/glyphs/LollipopGlyph.js +22 -0
- package/src/charting/glyphs/MagnifierGlyph.js +17 -0
- package/src/charting/glyphs/NoteGlyph.js +33 -0
- package/src/charting/glyphs/ObjectBoxGlyph.js +21 -0
- package/src/charting/glyphs/OrJunctionGlyph.js +17 -0
- package/src/charting/glyphs/ParallelogramGlyph.js +20 -0
- package/src/charting/glyphs/PersonGlyph.js +23 -0
- package/src/charting/glyphs/PillGlyph.js +23 -0
- package/src/charting/glyphs/PinGlyph.js +18 -0
- package/src/charting/glyphs/PrincipleGlyph.js +23 -0
- package/src/charting/glyphs/ProductBoxGlyph.js +16 -0
- package/src/charting/glyphs/RectGlyph.js +15 -0
- package/src/charting/glyphs/RoundedBoxGlyph.js +13 -0
- package/src/charting/glyphs/StackGlyph.js +14 -0
- package/src/charting/glyphs/StepsGlyph.js +20 -0
- package/src/charting/glyphs/StickFigureGlyph.js +32 -0
- package/src/charting/glyphs/SystemSoftwareBoxGlyph.js +16 -0
- package/src/charting/glyphs/TabbedBoxGlyph.js +37 -0
- package/src/charting/glyphs/TargetGlyph.js +23 -0
- package/src/charting/glyphs/WavyBoxGlyph.js +17 -0
- package/src/charting/glyphs/WheelGlyph.js +28 -0
- package/src/charting/glyphs/drawGlyph.js +28 -0
- package/src/charting/glyphs/glyphSvg.js +55 -0
- package/src/charting/glyphs/index.js +109 -0
- package/src/charting/modelTree/AnalysisPanel.js +159 -0
- package/src/charting/modelTree/DiagramTabs.js +217 -0
- package/src/charting/modelTree/ModelTree.js +164 -0
- package/src/charting/modelTree/ModelTreePanel.js +914 -0
- package/src/charting/modelTree/TreeBuilder.js +238 -0
- package/src/charting/modelTree/TreeModeRegistry.js +51 -0
- package/src/charting/modelTree/TreeViewMode.js +110 -0
- package/src/charting/modelTree/buildFilterTrees.js +138 -0
- package/src/charting/modelTree/modes/FlatTreeMode.js +46 -0
- package/src/charting/modelTree/modes/LayerGroupedTreeMode.js +62 -0
- package/src/charting/modelTree/modes/TypeGroupedTreeMode.js +60 -0
- package/src/charting/modelTree/treeLayers.js +11 -0
- package/src/charting/report/reportHtml.js +82 -0
- package/src/charting/report/reportViewer.js +118 -0
- package/src/charting/shapes/CircleShape.js +19 -0
- package/src/charting/shapes/PathShape.js +17 -0
- package/src/charting/shapes/RectShape.js +20 -0
- package/src/charting/shapes/Shape.js +20 -0
- package/src/charting/shapes/ShapeFactory.js +23 -0
- package/src/charting/storage/LocalJsonStore.js +43 -0
- package/src/charting/templates/ActorTemplate.js +36 -0
- package/src/charting/templates/BoxTemplate.js +27 -0
- package/src/charting/templates/CircleTemplate.js +18 -0
- package/src/charting/templates/ClassTemplate.js +20 -0
- package/src/charting/templates/CloudTemplate.js +43 -0
- package/src/charting/templates/ComponentTemplate.js +19 -0
- package/src/charting/templates/CylinderTemplate.js +30 -0
- package/src/charting/templates/DataStoreTemplate.js +16 -0
- package/src/charting/templates/DiamondTemplate.js +10 -0
- package/src/charting/templates/DocumentTemplate.js +32 -0
- package/src/charting/templates/EllipseTemplate.js +15 -0
- package/src/charting/templates/FinalStateTemplate.js +12 -0
- package/src/charting/templates/GlyphTemplate.js +47 -0
- package/src/charting/templates/HexagonTemplate.js +17 -0
- package/src/charting/templates/LifelineTemplate.js +20 -0
- package/src/charting/templates/ManualInputTemplate.js +12 -0
- package/src/charting/templates/NoteTemplate.js +23 -0
- package/src/charting/templates/OctagonTemplate.js +7 -0
- package/src/charting/templates/PackageTemplate.js +25 -0
- package/src/charting/templates/ParallelogramTemplate.js +11 -0
- package/src/charting/templates/PentagonTemplate.js +5 -0
- package/src/charting/templates/PolygonTemplate.js +18 -0
- package/src/charting/templates/PredefinedProcessTemplate.js +13 -0
- package/src/charting/templates/RectangleTemplate.js +28 -0
- package/src/charting/templates/RegularPolygonTemplate.js +21 -0
- package/src/charting/templates/RoundedRectangleTemplate.js +5 -0
- package/src/charting/templates/StadiumTemplate.js +8 -0
- package/src/charting/templates/StarTemplate.js +17 -0
- package/src/charting/templates/SwimlaneTemplate.js +18 -0
- package/src/charting/templates/Template.js +208 -0
- package/src/charting/templates/TrapezoidTemplate.js +11 -0
- package/src/charting/templates/TriangleTemplate.js +12 -0
- package/src/charting/templates/index.js +31 -0
- package/src/charting/templates/outline.js +59 -0
- package/src/charting/templates/svg.js +19 -0
- package/src/charting/textToShapes.js +61 -0
- package/src/charting/toolbar/ToolbarButton.js +38 -0
- package/src/charting/toolbar/ToolbarCheckbox.js +31 -0
- package/src/charting/toolbar/ToolbarItem.js +19 -0
- package/src/charting/toolbar/ToolbarMenu.js +36 -0
- package/src/charting/toolbar/ToolbarSelect.js +38 -0
- package/src/charting/toolbar/ToolbarSeparator.js +7 -0
- package/src/charting/toolbar/ToolbarText.js +22 -0
- package/src/charting/toolbar/index.js +8 -0
- package/src/charting/toolbar/pickFile.js +14 -0
- package/src/charting/viewDecorations.js +85 -0
- package/src/charting/zOrder.js +57 -0
- package/src/csvTable.js +61 -0
- package/src/datamodel.js +122 -0
- package/src/datawindow/BoundedWindow.js +36 -0
- package/src/datawindow/FlatDataWindow.js +34 -0
- package/src/datawindow/GraphDataWindow.js +40 -0
- package/src/datawindow/GroupedSampleDataWindow.js +16 -0
- package/src/datawindow/SeriesDataWindow.js +42 -0
- package/src/datawindow/index.js +31 -0
- package/src/diagramCatalog.js +30 -0
- package/src/ebnfDiagram.js +57 -0
- package/src/ebnfParser.js +129 -0
- package/src/exportImage.js +233 -0
- package/src/index.js +2636 -0
- package/src/itIcons.js +84 -0
- package/src/kernelExpr.js +243 -0
- package/src/propertiesDialog.js +463 -0
- package/src/railroadDiagram.js +571 -0
- package/src/treeModeCatalog.js +16 -0
- package/src/workspace/ContextBus.js +79 -0
- package/src/workspace/EditorShell.js +67 -0
- package/src/workspace/Part.js +163 -0
- package/src/workspace/PartFactory.js +49 -0
- package/src/workspace/PartRegistry.js +86 -0
- package/src/workspace/Workspace.js +321 -0
- package/src/workspace/archimateServices.js +33 -0
- package/src/workspace/dom.js +120 -0
- package/src/workspace/index.js +75 -0
- package/src/workspace/layout/GridNode.js +280 -0
- package/src/workspace/layout/LayoutNode.js +89 -0
- package/src/workspace/layout/PartNode.js +77 -0
- package/src/workspace/layout/SplitNode.js +114 -0
- package/src/workspace/layout/TabsNode.js +191 -0
- package/src/workspace/layout/index.js +24 -0
- package/src/workspace/parts/AdapterPart.js +33 -0
- package/src/workspace/parts/ArchimateCanvasPart.js +345 -0
- package/src/workspace/parts/ArchimateEditorPart.js +79 -0
- package/src/workspace/parts/ChartPart.js +115 -0
- package/src/workspace/parts/ContentPart.js +34 -0
- package/src/workspace/parts/DetailPart.js +46 -0
- package/src/workspace/parts/DiagramEditorPart.js +135 -0
- package/src/workspace/parts/EditorPart.js +388 -0
- package/src/workspace/parts/HtmlPart.js +25 -0
- package/src/workspace/parts/ListPart.js +57 -0
- package/src/workspace/parts/ModelFile.js +187 -0
- package/src/workspace/parts/ModelsPart.js +135 -0
- package/src/workspace/styles.js +258 -0
- package/src/workspace/themes.js +96 -0
- package/src/workspace/workArea.js +413 -0
- package/src/workspace/workAreaModel.js +197 -0
- package/src/workspace.js +16 -0
- package/src/zip/ZipArchive.js +160 -0
- package/src/zip/crc32.js +25 -0
- package/src/zip/inflate.js +159 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RenderEngine, ArchimateModel, ArchimateSpecializationSelector, DerivedRelationships, DiagramTabs, ModelTree,
|
|
3
|
+
SettingsManager, buildAnalysisPanel, buildModelTreePanel, fromArchimateView, parseArchiModel, toArchimateModel,
|
|
4
|
+
parseArchiFile, toArchiFile, toArchiExport, showGlobalSettingsDialog, showPropertiesDialog, showDiagramPropertiesDialog,
|
|
5
|
+
} from '../index.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* What ArchimateDiagramEditor takes as its `workspace` option: the classes and
|
|
9
|
+
* dialogs it builds its model tree, tabs, settings and import/export from,
|
|
10
|
+
* collected by direct import. A part hands this in rather than reading a
|
|
11
|
+
* bundle's global, so it works the same however the library was loaded.
|
|
12
|
+
*/
|
|
13
|
+
export const ARCHIMATE_SERVICES = Object.freeze({
|
|
14
|
+
RenderEngine,
|
|
15
|
+
ArchimateModel,
|
|
16
|
+
ArchimateSpecializationRegistry: RenderEngine.ArchimateSpecializationRegistry,
|
|
17
|
+
ArchimateSpecializationSelector,
|
|
18
|
+
DerivedRelationships,
|
|
19
|
+
DiagramTabs,
|
|
20
|
+
ModelTree,
|
|
21
|
+
SettingsManager,
|
|
22
|
+
buildAnalysisPanel,
|
|
23
|
+
buildModelTreePanel,
|
|
24
|
+
fromArchimateView,
|
|
25
|
+
parseArchiModel,
|
|
26
|
+
parseArchiFile,
|
|
27
|
+
toArchiFile,
|
|
28
|
+
toArchiExport,
|
|
29
|
+
toArchimateModel,
|
|
30
|
+
showGlobalSettingsDialog,
|
|
31
|
+
showPropertiesDialog,
|
|
32
|
+
showDiagramPropertiesDialog,
|
|
33
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* el() — build DOM from a plain-JSON element spec.
|
|
3
|
+
*
|
|
4
|
+
* The shell's structural guardrail: markup is generated from JavaScript and
|
|
5
|
+
* JSON objects, not written as HTML strings. Structure stays *data* — it can be
|
|
6
|
+
* inspected, composed, serialized and diffed the same way the layout tree is,
|
|
7
|
+
* and it never goes through an HTML parser, so text content cannot inject
|
|
8
|
+
* markup. Raw HTML injection is the deliberate escape hatch (`HtmlPart`), not
|
|
9
|
+
* the default (`ContentPart`).
|
|
10
|
+
*
|
|
11
|
+
* Spec shape — every field optional:
|
|
12
|
+
*
|
|
13
|
+
* {
|
|
14
|
+
* tag: 'div', // default 'div'
|
|
15
|
+
* cls: 'ws-toolbar' | ['a','b'], // class names
|
|
16
|
+
* text: 'label', // textContent (escaped by construction)
|
|
17
|
+
* attrs: { role: 'tablist' }, // setAttribute; null/false/undefined skipped
|
|
18
|
+
* dataset: { partId: 'nav' }, // data-* attributes
|
|
19
|
+
* style: { flex: '1 1 auto' }, // inline style properties
|
|
20
|
+
* on: { click: fn }, // addEventListener
|
|
21
|
+
* children: [spec | Node | string], // strings become text nodes
|
|
22
|
+
* ref: (element) => {}, // capture the node without querySelector
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* A bare string spec produces a text node, so `children: ['plain text']` works.
|
|
26
|
+
*/
|
|
27
|
+
export function el(spec, doc = document) {
|
|
28
|
+
if (spec == null) return doc.createTextNode('');
|
|
29
|
+
if (typeof spec === 'string' || typeof spec === 'number') return doc.createTextNode(String(spec));
|
|
30
|
+
// Duck-typed rather than `instanceof Node`: `Node` is a browser global, so
|
|
31
|
+
// that test throws a ReferenceError anywhere else — including under a
|
|
32
|
+
// substituted document. A spec object never carries either of these.
|
|
33
|
+
if (typeof spec.nodeType === 'number' || typeof spec.appendChild === 'function') return spec;
|
|
34
|
+
|
|
35
|
+
const node = doc.createElement(spec.tag ?? 'div');
|
|
36
|
+
|
|
37
|
+
if (spec.cls) {
|
|
38
|
+
const classes = Array.isArray(spec.cls) ? spec.cls : [spec.cls];
|
|
39
|
+
node.className = classes.filter(Boolean).join(' ');
|
|
40
|
+
}
|
|
41
|
+
if (spec.text != null) node.textContent = String(spec.text);
|
|
42
|
+
|
|
43
|
+
for (const [k, v] of Object.entries(spec.attrs ?? {})) {
|
|
44
|
+
if (v == null || v === false) continue;
|
|
45
|
+
node.setAttribute(k, v === true ? '' : String(v));
|
|
46
|
+
}
|
|
47
|
+
for (const [k, v] of Object.entries(spec.dataset ?? {})) {
|
|
48
|
+
if (v == null) continue;
|
|
49
|
+
node.dataset[k] = String(v);
|
|
50
|
+
}
|
|
51
|
+
for (const [k, v] of Object.entries(spec.style ?? {})) {
|
|
52
|
+
if (v == null) continue;
|
|
53
|
+
node.style.setProperty(cssProp(k), String(v));
|
|
54
|
+
}
|
|
55
|
+
for (const [event, handler] of Object.entries(spec.on ?? {})) {
|
|
56
|
+
if (typeof handler === 'function') node.addEventListener(event, handler);
|
|
57
|
+
}
|
|
58
|
+
for (const child of spec.children ?? []) {
|
|
59
|
+
node.appendChild(el(child, doc));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
spec.ref?.(node);
|
|
63
|
+
return node;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Build several specs into a DocumentFragment. */
|
|
67
|
+
export function frag(specs, doc = document) {
|
|
68
|
+
const f = doc.createDocumentFragment();
|
|
69
|
+
for (const spec of specs ?? []) f.appendChild(el(spec, doc));
|
|
70
|
+
return f;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Replace an element's contents with freshly built specs. */
|
|
74
|
+
export function render(host, specs, doc = document) {
|
|
75
|
+
host.textContent = '';
|
|
76
|
+
host.appendChild(frag(Array.isArray(specs) ? specs : [specs], doc));
|
|
77
|
+
return host;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** camelCase → kebab-case, so style keys can be written either way. */
|
|
81
|
+
function cssProp(key) {
|
|
82
|
+
return key.startsWith('--') ? key : key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const VOID_TAGS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr']);
|
|
86
|
+
const escapeHtml = (s) => String(s).replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[c]);
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The same spec as el(), written out as HTML text: for a page that is saved
|
|
90
|
+
* rather than shown (a report). Text and attribute values are escaped; `on`
|
|
91
|
+
* and `ref` have no meaning in text and are left out. `script` is the one
|
|
92
|
+
* extra field: the trusted contents of a <script> or <style> (not escaped,
|
|
93
|
+
* but `</` is, so it cannot close its element early).
|
|
94
|
+
*/
|
|
95
|
+
export function toHtml(spec) {
|
|
96
|
+
if (spec == null) return '';
|
|
97
|
+
if (typeof spec === 'string' || typeof spec === 'number') return escapeHtml(spec);
|
|
98
|
+
if (Array.isArray(spec)) return spec.map(toHtml).join('');
|
|
99
|
+
const tag = spec.tag ?? 'div';
|
|
100
|
+
const attrs = [];
|
|
101
|
+
if (spec.cls) {
|
|
102
|
+
const classes = (Array.isArray(spec.cls) ? spec.cls : [spec.cls]).filter(Boolean);
|
|
103
|
+
if (classes.length) attrs.push(['class', classes.join(' ')]);
|
|
104
|
+
}
|
|
105
|
+
for (const [k, v] of Object.entries(spec.attrs ?? {})) {
|
|
106
|
+
if (v == null || v === false) continue;
|
|
107
|
+
attrs.push([k, v === true ? '' : String(v)]);
|
|
108
|
+
}
|
|
109
|
+
for (const [k, v] of Object.entries(spec.dataset ?? {})) {
|
|
110
|
+
if (v != null) attrs.push([`data-${cssProp(k)}`, String(v)]);
|
|
111
|
+
}
|
|
112
|
+
const style = Object.entries(spec.style ?? {}).filter(([, v]) => v != null).map(([k, v]) => `${cssProp(k)}: ${v}`).join('; ');
|
|
113
|
+
if (style) attrs.push(['style', style]);
|
|
114
|
+
const open = `<${tag}${attrs.map(([k, v]) => ` ${k}="${escapeHtml(v)}"`).join('')}>`;
|
|
115
|
+
if (VOID_TAGS.has(tag)) return open;
|
|
116
|
+
const inner = spec.script != null
|
|
117
|
+
? String(spec.script).replace(/<\//g, '<\\/')
|
|
118
|
+
: (spec.text != null ? escapeHtml(spec.text) : '') + (spec.children ?? []).map(toHtml).join('');
|
|
119
|
+
return `${open}${inner}</${tag}>`;
|
|
120
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace — browser-only entry point for the application shell.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT re-exported from `src/index.js`: `Workspace` subclasses
|
|
5
|
+
* HTMLElement at module scope, so merely importing it throws under node — and
|
|
6
|
+
* `src/index.js` is the node entry the test suite loads. Import this module
|
|
7
|
+
* directly from a browser instead.
|
|
8
|
+
*
|
|
9
|
+
* Importing it registers the `<ws-workspace>` element. Built-in part types are
|
|
10
|
+
* NOT auto-registered: which parts exist is the consumer's decision, and
|
|
11
|
+
* pulling ChartPart in unconditionally would drag the whole RenderEngine into
|
|
12
|
+
* a shell that may only ever host adapted panels. Call
|
|
13
|
+
* `registerBuiltinParts(ws)` for the standard set, or register individually.
|
|
14
|
+
*
|
|
15
|
+
* See WORKSPACE_ARCHITECTURE.md for the design.
|
|
16
|
+
*/
|
|
17
|
+
import { Workspace, WORKSPACE_TAG, WORKSPACE_SCHEMA_VERSION, defineWorkspace } from './Workspace.js';
|
|
18
|
+
import { ContextBus } from './ContextBus.js';
|
|
19
|
+
import { Part } from './Part.js';
|
|
20
|
+
import { PartRegistry } from './PartRegistry.js';
|
|
21
|
+
import { PartFactory } from './PartFactory.js';
|
|
22
|
+
import { ContentPart } from './parts/ContentPart.js';
|
|
23
|
+
import { HtmlPart } from './parts/HtmlPart.js';
|
|
24
|
+
import { ListPart } from './parts/ListPart.js';
|
|
25
|
+
import { DetailPart } from './parts/DetailPart.js';
|
|
26
|
+
import { AdapterPart } from './parts/AdapterPart.js';
|
|
27
|
+
import { ModelsPart } from './parts/ModelsPart.js';
|
|
28
|
+
|
|
29
|
+
defineWorkspace();
|
|
30
|
+
|
|
31
|
+
/** The dependency-free part types — everything except ChartPart. */
|
|
32
|
+
export const BUILTIN_PARTS = [ContentPart, HtmlPart, ListPart, DetailPart, AdapterPart, ModelsPart];
|
|
33
|
+
|
|
34
|
+
/** Convenience: register the standard part types on a workspace element. */
|
|
35
|
+
export function registerBuiltinParts(ws) {
|
|
36
|
+
ws.registerParts(BUILTIN_PARTS);
|
|
37
|
+
return ws;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
Workspace, WORKSPACE_TAG, WORKSPACE_SCHEMA_VERSION, defineWorkspace,
|
|
42
|
+
ContextBus, Part, PartRegistry, PartFactory,
|
|
43
|
+
ContentPart, HtmlPart, ListPart, DetailPart, AdapterPart, ModelsPart,
|
|
44
|
+
};
|
|
45
|
+
export { el, frag, render } from './dom.js';
|
|
46
|
+
|
|
47
|
+
// The engine's whole public API, re-exported so the workspace UMD bundle is a
|
|
48
|
+
// superset of the main one: a page that loads renderengine-workspace.umd.js
|
|
49
|
+
// gets both the shell and RenderEngine from a single script tag, instead of
|
|
50
|
+
// having to load two bundles in the right order. A star export rather than a
|
|
51
|
+
// list, so nothing the engine adds can go missing here; this module's own
|
|
52
|
+
// exports take precedence over any of the same name.
|
|
53
|
+
export * from '../index.js';
|
|
54
|
+
export {
|
|
55
|
+
BUILTIN_THEMES, SYSTEM_THEME, THEME_VARS,
|
|
56
|
+
LIGHT_THEME, DARK_THEME, MIDNIGHT_THEME, SEPIA_THEME,
|
|
57
|
+
} from './themes.js';
|
|
58
|
+
export { ChartPart } from './parts/ChartPart.js';
|
|
59
|
+
export { EditorPart } from './parts/EditorPart.js';
|
|
60
|
+
export { DiagramEditorPart } from './parts/DiagramEditorPart.js';
|
|
61
|
+
export { ArchimateEditorPart } from './parts/ArchimateEditorPart.js';
|
|
62
|
+
export { ArchimateCanvasPart } from './parts/ArchimateCanvasPart.js';
|
|
63
|
+
export { ARCHIMATE_SERVICES } from './archimateServices.js';
|
|
64
|
+
export { EditorShell } from './EditorShell.js';
|
|
65
|
+
export {
|
|
66
|
+
createLayout, LayoutNode, PartNode, SplitNode, TabsNode, GridNode,
|
|
67
|
+
GRID_COLS, ROW_UNIT_PX, GRID_GAP_PX,
|
|
68
|
+
MIN_COL_SPAN, MIN_ROW_SPAN, DEFAULT_COL_SPAN, DEFAULT_ROW_SPAN,
|
|
69
|
+
} from './layout/index.js';
|
|
70
|
+
export { WORKSPACE_CSS, ensureStyles } from './styles.js';
|
|
71
|
+
export { WorkArea } from './workArea.js';
|
|
72
|
+
export {
|
|
73
|
+
emptyWorkArea, listGroups, listOpenParts, findPart, resolveGroup,
|
|
74
|
+
openPart, closePart, focusPart,
|
|
75
|
+
} from './workAreaModel.js';
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
import { LayoutNode } from './LayoutNode.js';
|
|
2
|
+
import { el, render } from '../dom.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GridNode — a 12-column grid of draggable, resizable panes.
|
|
6
|
+
*
|
|
7
|
+
* The geometry, snapping, collision-swap and "crystallize" behaviour here are
|
|
8
|
+
* lifted from sqlengine workbench's `dashboard.js`, which is where this model
|
|
9
|
+
* was proven in production. Keeping the numbers and the semantics identical is
|
|
10
|
+
* deliberate: it is what lets an existing dashboard document load into this
|
|
11
|
+
* shell unchanged, via `GridNode.migrateChildren()`.
|
|
12
|
+
*
|
|
13
|
+
* A child's placement lives in `child.spec.layout = {col, row, colSpan, rowSpan}`.
|
|
14
|
+
* `col`/`row` are 1-based and stay undefined until a pane is actually dragged,
|
|
15
|
+
* so an untouched grid flows left-to-right via native CSS grid auto-placement.
|
|
16
|
+
* The first drag or resize on ANY pane crystallizes the whole grid — every
|
|
17
|
+
* pane's currently rendered position is captured into explicit col/row — so
|
|
18
|
+
* pinned and auto-flowing panes are never mixed after that point.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const GRID_COLS = 12;
|
|
22
|
+
export const ROW_UNIT_PX = 20; // must match .ws-grid's grid-auto-rows
|
|
23
|
+
export const GRID_GAP_PX = 14; // must match .ws-grid's gap
|
|
24
|
+
export const MIN_COL_SPAN = 2;
|
|
25
|
+
export const MIN_ROW_SPAN = 4;
|
|
26
|
+
export const DEFAULT_COL_SPAN = 6;
|
|
27
|
+
export const DEFAULT_ROW_SPAN = 9;
|
|
28
|
+
|
|
29
|
+
/** Old dashboard shape `{span: 1-4, height: 'sm'|'md'|'lg'}` → `{colSpan,rowSpan}`. */
|
|
30
|
+
const OLD_HEIGHT_TO_ROWS = { sm: 6, md: 9, lg: 13 };
|
|
31
|
+
|
|
32
|
+
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
|
33
|
+
|
|
34
|
+
function rectsOverlap(a, b) {
|
|
35
|
+
if (a.col == null || b.col == null) return false;
|
|
36
|
+
return a.col < b.col + b.colSpan && a.col + a.colSpan > b.col &&
|
|
37
|
+
a.row < b.row + b.rowSpan && a.row + a.rowSpan > b.row;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class GridNode extends LayoutNode {
|
|
41
|
+
static type = 'grid';
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Convert legacy `{span, height}` child layouts in place. Returns true if
|
|
45
|
+
* anything was converted, so the caller knows to persist the migration
|
|
46
|
+
* rather than re-derive it on every load.
|
|
47
|
+
*/
|
|
48
|
+
static migrateChildren(children) {
|
|
49
|
+
let migrated = false;
|
|
50
|
+
for (const child of children ?? []) {
|
|
51
|
+
const old = child.layout ?? {};
|
|
52
|
+
if (old.colSpan != null) continue;
|
|
53
|
+
child.layout = {
|
|
54
|
+
colSpan: clamp((old.span ?? 2) * 3, MIN_COL_SPAN, GRID_COLS),
|
|
55
|
+
rowSpan: OLD_HEIGHT_TO_ROWS[old.height ?? 'md'] ?? DEFAULT_ROW_SPAN,
|
|
56
|
+
};
|
|
57
|
+
migrated = true;
|
|
58
|
+
}
|
|
59
|
+
return migrated;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
constructor(spec = {}) {
|
|
63
|
+
super(spec);
|
|
64
|
+
this.cols = spec.cols ?? GRID_COLS;
|
|
65
|
+
this.movable = spec.movable !== false;
|
|
66
|
+
this.resizable = spec.resizable !== false;
|
|
67
|
+
for (const child of this.children) {
|
|
68
|
+
const l = child.spec.layout ?? (child.spec.layout = {});
|
|
69
|
+
l.colSpan ??= DEFAULT_COL_SPAN;
|
|
70
|
+
l.rowSpan ??= DEFAULT_ROW_SPAN;
|
|
71
|
+
}
|
|
72
|
+
this._panes = [];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
build(ctx) {
|
|
76
|
+
this.el.classList.add('ws-grid');
|
|
77
|
+
this.el.style.gridTemplateColumns = `repeat(${this.cols}, minmax(0, 1fr))`;
|
|
78
|
+
this._panes = [];
|
|
79
|
+
|
|
80
|
+
this.children.forEach((child) => {
|
|
81
|
+
let header, body;
|
|
82
|
+
const paneEl = this.el.appendChild(el({
|
|
83
|
+
cls: 'ws-pane',
|
|
84
|
+
children: [
|
|
85
|
+
{ cls: 'ws-pane-header', attrs: { title: this.movable ? 'Drag to move' : null },
|
|
86
|
+
ref: n => { header = n; } },
|
|
87
|
+
{ cls: 'ws-pane-body', ref: n => { body = n; } },
|
|
88
|
+
],
|
|
89
|
+
}));
|
|
90
|
+
this._panes.push(paneEl);
|
|
91
|
+
this._applyPlacement(paneEl, child.spec.layout);
|
|
92
|
+
|
|
93
|
+
child.render(body, ctx);
|
|
94
|
+
child.activate?.();
|
|
95
|
+
// After render(): a PartNode only resolves its part — and therefore
|
|
96
|
+
// its title and actions — during render(), so building the header
|
|
97
|
+
// earlier would show the raw part id and no buttons.
|
|
98
|
+
this._buildPaneHeader(header, child);
|
|
99
|
+
|
|
100
|
+
if (this.movable) this._attachDragMove(paneEl, header, child);
|
|
101
|
+
if (this.resizable) this._attachResize(paneEl, child);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
activate() {
|
|
106
|
+
for (const child of this.children) child.activate?.();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Title plus the part's own pane actions (rename, refresh, close, …).
|
|
111
|
+
*
|
|
112
|
+
* Actions come from the mounted Part, not from the layout spec: they carry
|
|
113
|
+
* callbacks, and the layout tree has to stay serializable JSON. `_attachDragMove`
|
|
114
|
+
* already ignores pointerdowns inside `.ws-pane-controls`, so a button click
|
|
115
|
+
* never starts a pane drag.
|
|
116
|
+
*/
|
|
117
|
+
_buildPaneHeader(header, child) {
|
|
118
|
+
const actions = child.paneActions?.() ?? [];
|
|
119
|
+
render(header, [
|
|
120
|
+
{ tag: 'span', cls: 'ws-pane-title', text: child.label?.() ?? child.spec?.title ?? '',
|
|
121
|
+
attrs: { title: child.paneTooltip?.() ?? null } },
|
|
122
|
+
...(actions.length ? [{
|
|
123
|
+
tag: 'span', cls: 'ws-pane-controls',
|
|
124
|
+
children: actions.map(a => ({
|
|
125
|
+
tag: 'button',
|
|
126
|
+
cls: 'ws-pane-btn',
|
|
127
|
+
text: a.label,
|
|
128
|
+
attrs: { type: 'button', title: a.title ?? a.label },
|
|
129
|
+
on: { click: (e) => { e.stopPropagation(); a.onClick?.(e); } },
|
|
130
|
+
})),
|
|
131
|
+
}] : []),
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_applyPlacement(paneEl, l) {
|
|
136
|
+
paneEl.style.gridColumn = l.col != null ? `${l.col} / span ${l.colSpan}` : `span ${l.colSpan}`;
|
|
137
|
+
paneEl.style.gridRow = l.row != null ? `${l.row} / span ${l.rowSpan}` : `span ${l.rowSpan}`;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Re-apply every pane's placement after a move/resize commits. */
|
|
141
|
+
_restyleAll() {
|
|
142
|
+
this.children.forEach((child, i) => {
|
|
143
|
+
const paneEl = this._panes[i];
|
|
144
|
+
if (paneEl) this._applyPlacement(paneEl, child.spec.layout);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
_metrics() {
|
|
149
|
+
const rect = this.el.getBoundingClientRect();
|
|
150
|
+
const colWidth = (rect.width - GRID_GAP_PX * (this.cols - 1)) / this.cols;
|
|
151
|
+
return { rect, colWidth, rowHeight: ROW_UNIT_PX, gap: GRID_GAP_PX };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Capture every pane's currently rendered position into explicit col/row if
|
|
156
|
+
* any pane lacks one. Visually a no-op — see the class doc for why the
|
|
157
|
+
* whole grid is pinned at once rather than per pane.
|
|
158
|
+
*/
|
|
159
|
+
_crystallizeIfNeeded() {
|
|
160
|
+
if (!this.children.some(c => c.spec.layout.col == null || c.spec.layout.row == null)) return;
|
|
161
|
+
const { rect, colWidth, rowHeight, gap } = this._metrics();
|
|
162
|
+
this.children.forEach((child, i) => {
|
|
163
|
+
const l = child.spec.layout;
|
|
164
|
+
if (l.col != null && l.row != null) return;
|
|
165
|
+
const paneEl = this._panes[i];
|
|
166
|
+
if (!paneEl) return;
|
|
167
|
+
const r = paneEl.getBoundingClientRect();
|
|
168
|
+
l.col = Math.max(1, Math.round((r.left - rect.left) / (colWidth + gap)) + 1);
|
|
169
|
+
l.row = Math.max(1, Math.round((r.top - rect.top) / (rowHeight + gap)) + 1);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
_attachDragMove(paneEl, header, child) {
|
|
174
|
+
header.addEventListener('pointerdown', (e) => {
|
|
175
|
+
if (e.button !== 0 || e.target.closest('.ws-pane-controls')) return;
|
|
176
|
+
this._crystallizeIfNeeded();
|
|
177
|
+
const l = child.spec.layout;
|
|
178
|
+
const { colWidth, rowHeight, gap } = this._metrics();
|
|
179
|
+
const startX = e.clientX, startY = e.clientY;
|
|
180
|
+
const startCol = l.col, startRow = l.row;
|
|
181
|
+
header.setPointerCapture(e.pointerId);
|
|
182
|
+
paneEl.classList.add('ws-pane-dragging');
|
|
183
|
+
|
|
184
|
+
const onMove = (ev) => {
|
|
185
|
+
paneEl.style.transform = `translate(${ev.clientX - startX}px, ${ev.clientY - startY}px)`;
|
|
186
|
+
};
|
|
187
|
+
const onUp = (ev) => {
|
|
188
|
+
header.releasePointerCapture(e.pointerId);
|
|
189
|
+
header.removeEventListener('pointermove', onMove);
|
|
190
|
+
header.removeEventListener('pointerup', onUp);
|
|
191
|
+
header.removeEventListener('pointercancel', onUp);
|
|
192
|
+
paneEl.style.transform = '';
|
|
193
|
+
paneEl.classList.remove('ws-pane-dragging');
|
|
194
|
+
|
|
195
|
+
const colDelta = Math.round((ev.clientX - startX) / (colWidth + gap));
|
|
196
|
+
const rowDelta = Math.round((ev.clientY - startY) / (rowHeight + gap));
|
|
197
|
+
if (colDelta === 0 && rowDelta === 0) return; // a click, not a drag
|
|
198
|
+
|
|
199
|
+
const targetCol = clamp(startCol + colDelta, 1, this.cols - l.colSpan + 1);
|
|
200
|
+
const targetRow = Math.max(1, startRow + rowDelta);
|
|
201
|
+
const target = { col: targetCol, row: targetRow, colSpan: l.colSpan, rowSpan: l.rowSpan };
|
|
202
|
+
|
|
203
|
+
// Simple and predictable rather than a real bin-packer: landing
|
|
204
|
+
// on exactly one occupied pane swaps the two.
|
|
205
|
+
const occupant = this.children.find(c => c !== child && rectsOverlap(target, c.spec.layout));
|
|
206
|
+
if (occupant) {
|
|
207
|
+
const swapCol = occupant.spec.layout.col, swapRow = occupant.spec.layout.row;
|
|
208
|
+
occupant.spec.layout.col = l.col;
|
|
209
|
+
occupant.spec.layout.row = l.row;
|
|
210
|
+
l.col = swapCol;
|
|
211
|
+
l.row = swapRow;
|
|
212
|
+
} else {
|
|
213
|
+
l.col = targetCol;
|
|
214
|
+
l.row = targetRow;
|
|
215
|
+
}
|
|
216
|
+
this._restyleAll();
|
|
217
|
+
this._emitChange();
|
|
218
|
+
};
|
|
219
|
+
header.addEventListener('pointermove', onMove);
|
|
220
|
+
header.addEventListener('pointerup', onUp);
|
|
221
|
+
header.addEventListener('pointercancel', onUp);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
_attachResize(paneEl, child) {
|
|
226
|
+
const handle = paneEl.appendChild(el({
|
|
227
|
+
cls: 'ws-resize-handle',
|
|
228
|
+
text: '⤡',
|
|
229
|
+
attrs: { title: 'Drag to resize' },
|
|
230
|
+
}));
|
|
231
|
+
|
|
232
|
+
handle.addEventListener('pointerdown', (e) => {
|
|
233
|
+
if (e.button !== 0) return;
|
|
234
|
+
e.stopPropagation();
|
|
235
|
+
this._crystallizeIfNeeded();
|
|
236
|
+
const l = child.spec.layout;
|
|
237
|
+
const { colWidth, rowHeight, gap } = this._metrics();
|
|
238
|
+
const startX = e.clientX, startY = e.clientY;
|
|
239
|
+
const startColSpan = l.colSpan, startRowSpan = l.rowSpan;
|
|
240
|
+
const maxColSpan = this.cols - l.col + 1;
|
|
241
|
+
handle.setPointerCapture(e.pointerId);
|
|
242
|
+
paneEl.classList.add('ws-pane-dragging');
|
|
243
|
+
|
|
244
|
+
const computeSpans = (ev) => ({
|
|
245
|
+
colSpan: clamp(startColSpan + Math.round((ev.clientX - startX) / (colWidth + gap)), MIN_COL_SPAN, maxColSpan),
|
|
246
|
+
rowSpan: Math.max(MIN_ROW_SPAN, startRowSpan + Math.round((ev.clientY - startY) / (rowHeight + gap))),
|
|
247
|
+
});
|
|
248
|
+
const onMove = (ev) => {
|
|
249
|
+
const { colSpan, rowSpan } = computeSpans(ev);
|
|
250
|
+
paneEl.style.gridColumn = `${l.col} / span ${colSpan}`;
|
|
251
|
+
paneEl.style.gridRow = `${l.row} / span ${rowSpan}`;
|
|
252
|
+
};
|
|
253
|
+
const onUp = (ev) => {
|
|
254
|
+
handle.releasePointerCapture(e.pointerId);
|
|
255
|
+
handle.removeEventListener('pointermove', onMove);
|
|
256
|
+
handle.removeEventListener('pointerup', onUp);
|
|
257
|
+
handle.removeEventListener('pointercancel', onUp);
|
|
258
|
+
paneEl.classList.remove('ws-pane-dragging');
|
|
259
|
+
const { colSpan, rowSpan } = computeSpans(ev);
|
|
260
|
+
l.colSpan = colSpan;
|
|
261
|
+
l.rowSpan = rowSpan;
|
|
262
|
+
this._restyleAll();
|
|
263
|
+
this._emitChange();
|
|
264
|
+
};
|
|
265
|
+
handle.addEventListener('pointermove', onMove);
|
|
266
|
+
handle.addEventListener('pointerup', onUp);
|
|
267
|
+
handle.addEventListener('pointercancel', onUp);
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
serialize() {
|
|
272
|
+
return {
|
|
273
|
+
type: GridNode.type,
|
|
274
|
+
cols: this.cols,
|
|
275
|
+
...(this.movable ? {} : { movable: false }),
|
|
276
|
+
...(this.resizable ? {} : { resizable: false }),
|
|
277
|
+
children: this.children.map(c => c.serialize()),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayoutNode — base class for the layout tree.
|
|
3
|
+
*
|
|
4
|
+
* One subclass per node kind, one file each: SplitNode, TabsNode, GridNode,
|
|
5
|
+
* PartNode. The serialized form carries a `type` discriminator because JSON has
|
|
6
|
+
* no classes; `LayoutNode.create()` maps it back. Subclasses import only this
|
|
7
|
+
* base and call `LayoutNode.create()` for their children, so there is no import
|
|
8
|
+
* cycle with `layout/index.js` (which is what populates the type table).
|
|
9
|
+
*/
|
|
10
|
+
import { el } from '../dom.js';
|
|
11
|
+
|
|
12
|
+
export class LayoutNode {
|
|
13
|
+
/** Discriminator used in serialized form. Every subclass overrides this. */
|
|
14
|
+
static type = null;
|
|
15
|
+
|
|
16
|
+
/** @type {Map<string, typeof LayoutNode>} populated by layout/index.js */
|
|
17
|
+
static _types = new Map();
|
|
18
|
+
|
|
19
|
+
static registerType(NodeClass) {
|
|
20
|
+
if (!NodeClass?.type) throw new Error(`Layout node ${NodeClass?.name} has no static type`);
|
|
21
|
+
LayoutNode._types.set(NodeClass.type, NodeClass);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Build a node (and its subtree) from a plain-JSON descriptor. */
|
|
25
|
+
static create(json) {
|
|
26
|
+
if (json instanceof LayoutNode) return json;
|
|
27
|
+
const NodeClass = LayoutNode._types.get(json?.type);
|
|
28
|
+
if (!NodeClass) {
|
|
29
|
+
throw new Error(`Unknown layout node type "${json?.type}" (known: ${[...LayoutNode._types.keys()].join(', ') || 'none'})`);
|
|
30
|
+
}
|
|
31
|
+
return new NodeClass(json);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor(spec = {}) {
|
|
35
|
+
if (new.target === LayoutNode) throw new TypeError('LayoutNode is abstract — subclass it');
|
|
36
|
+
this.spec = spec;
|
|
37
|
+
/** @type {LayoutNode[]} */
|
|
38
|
+
this.children = (spec.children ?? []).map(c => LayoutNode.create(c));
|
|
39
|
+
/** @type {HTMLElement|null} this node's own root element */
|
|
40
|
+
this.el = null;
|
|
41
|
+
this.ctx = null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build DOM into `host`. Subclasses override `build()`, not this — this
|
|
46
|
+
* handles the common element/ctx bookkeeping.
|
|
47
|
+
*/
|
|
48
|
+
render(host, ctx) {
|
|
49
|
+
this.ctx = ctx;
|
|
50
|
+
// `ws-node-<type>`, not `ws-<type>` — the latter would give a PartNode
|
|
51
|
+
// the class `ws-part`, which is what a mounted Part names its own root.
|
|
52
|
+
this.el = host.appendChild(el({ cls: ['ws-node', `ws-node-${this.constructor.type}`] }));
|
|
53
|
+
this.build(ctx);
|
|
54
|
+
return this.el;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Subclasses implement. `this.el` is attached and empty. */
|
|
58
|
+
build() {
|
|
59
|
+
throw new Error(`${this.constructor.name} must implement build()`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Detach this node's DOM. Does NOT dispose parts — part lifetime belongs to
|
|
64
|
+
* the PartRegistry pool so instances survive a perspective switch (see
|
|
65
|
+
* PartRegistry.disposeExcept).
|
|
66
|
+
*/
|
|
67
|
+
dispose() {
|
|
68
|
+
for (const child of this.children) child.dispose();
|
|
69
|
+
if (this.el?.parentNode) this.el.parentNode.removeChild(this.el);
|
|
70
|
+
this.el = null;
|
|
71
|
+
this.ctx = null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Every part id referenced in this subtree. */
|
|
75
|
+
partIds() {
|
|
76
|
+
return this.children.flatMap(c => c.partIds());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
serialize() {
|
|
80
|
+
const out = { ...this.spec, type: this.constructor.type };
|
|
81
|
+
if (this.children.length) out.children = this.children.map(c => c.serialize());
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Notify the shell that geometry changed and should be persisted. */
|
|
86
|
+
_emitChange() {
|
|
87
|
+
this.ctx?.onLayoutChange?.();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LayoutNode } from './LayoutNode.js';
|
|
2
|
+
import { render } from '../dom.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PartNode — leaf of the layout tree. Resolves `partId` against the shell's
|
|
6
|
+
* PartRegistry pool and mounts that part into its own container.
|
|
7
|
+
*
|
|
8
|
+
* Mounting is lazy: `build()` only creates the container. `activate()` does the
|
|
9
|
+
* actual `part.mount()`, and TabsNode calls it when a tab is first shown. Once
|
|
10
|
+
* mounted the part stays mounted (see Part's class doc) — lazy-then-permanent,
|
|
11
|
+
* not mount/unmount per switch. Nodes outside a TabsNode are activated
|
|
12
|
+
* immediately by their parent.
|
|
13
|
+
*/
|
|
14
|
+
export class PartNode extends LayoutNode {
|
|
15
|
+
static type = 'part';
|
|
16
|
+
|
|
17
|
+
constructor(spec = {}) {
|
|
18
|
+
super(spec);
|
|
19
|
+
this.partId = spec.partId ?? spec.id;
|
|
20
|
+
if (!this.partId) throw new Error('PartNode requires a partId');
|
|
21
|
+
this.part = null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
build(ctx) {
|
|
25
|
+
this.el.classList.add('ws-part-host');
|
|
26
|
+
this.el.dataset.partId = this.partId;
|
|
27
|
+
this.part = ctx.registry.get(this.partId);
|
|
28
|
+
if (!this.part) {
|
|
29
|
+
render(this.el, { cls: 'ws-part-missing', text: `Unknown part: ${this.partId}` });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Mount the part, or re-parent it if it is already live (pooled across a
|
|
35
|
+
* perspective switch). Idempotent.
|
|
36
|
+
*/
|
|
37
|
+
activate() {
|
|
38
|
+
if (!this.part) return;
|
|
39
|
+
try {
|
|
40
|
+
this.part.mount(this.el, this.ctx);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
console.error(`PartNode: part "${this.partId}" failed to mount`, err);
|
|
43
|
+
render(this.el, { cls: 'ws-part-missing', text: `Part "${this.partId}" failed to mount — see console.` });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Title for a tab strip / pane header. */
|
|
48
|
+
label() {
|
|
49
|
+
return this.part?.title ?? this.spec.title ?? this.partId;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Pane-header buttons contributed by the mounted part. */
|
|
53
|
+
paneActions() {
|
|
54
|
+
return this.part?.actions ?? [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Hover text for the pane title. */
|
|
58
|
+
paneTooltip() {
|
|
59
|
+
return this.part?.paneTooltip ?? null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
dispose() {
|
|
63
|
+
// Detach the part's element without disposing the instance — the pool
|
|
64
|
+
// decides whether it survives the perspective switch, and detach()
|
|
65
|
+
// keeps its DOM (and therefore its state) intact either way.
|
|
66
|
+
this.part?.detach();
|
|
67
|
+
super.dispose();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
partIds() {
|
|
71
|
+
return [this.partId];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
serialize() {
|
|
75
|
+
return { type: PartNode.type, partId: this.partId, ...(this.spec.layout ? { layout: { ...this.spec.layout } } : {}) };
|
|
76
|
+
}
|
|
77
|
+
}
|