@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,201 @@
|
|
|
1
|
+
import { Chart } from '../Chart.js';
|
|
2
|
+
import { ColorPalette } from '../ColorPalette.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GanttChart — horizontal bars on a time axis, one row per task.
|
|
6
|
+
*
|
|
7
|
+
* Data: Array<{
|
|
8
|
+
* label: string,
|
|
9
|
+
* start: string|Date|number,
|
|
10
|
+
* end: string|Date|number,
|
|
11
|
+
* progress?: number, // 0-100 percentage of bar to fill
|
|
12
|
+
* category?: string, // optional grouping / color key
|
|
13
|
+
* color?: string, // explicit bar color
|
|
14
|
+
* }>
|
|
15
|
+
*
|
|
16
|
+
* Options:
|
|
17
|
+
* - title
|
|
18
|
+
* - barHeight, barGap
|
|
19
|
+
* - colors: string[] palette (used per category)
|
|
20
|
+
* - axisLabel: label for the time axis
|
|
21
|
+
* - dateFormat: 'auto' | 'date' | 'datetime' | 'iso'
|
|
22
|
+
* - showProgress: boolean (default true when any task has progress)
|
|
23
|
+
* - showToday: boolean (default true) — draw a vertical marker at the current time
|
|
24
|
+
*/
|
|
25
|
+
export class GanttChart extends Chart {
|
|
26
|
+
static chartType = 'gantt';
|
|
27
|
+
|
|
28
|
+
static parseTime(v) {
|
|
29
|
+
if (v instanceof Date) return v.getTime();
|
|
30
|
+
if (typeof v === 'number') return v;
|
|
31
|
+
if (typeof v === 'string') {
|
|
32
|
+
// Try ISO / date string first.
|
|
33
|
+
const d = new Date(v);
|
|
34
|
+
if (!Number.isNaN(d.getTime())) return d.getTime();
|
|
35
|
+
}
|
|
36
|
+
return NaN;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static formatDate(ts, mode) {
|
|
40
|
+
const d = new Date(ts);
|
|
41
|
+
if (mode === 'iso') return d.toISOString().slice(0, 10);
|
|
42
|
+
if (mode === 'datetime') return d.toISOString().replace('T', ' ').slice(0, 16);
|
|
43
|
+
if (mode === 'date') return d.toLocaleDateString('en-US', { timeZone: 'UTC' });
|
|
44
|
+
// Auto: full date if span > 1 day, otherwise include hour.
|
|
45
|
+
return d.toLocaleDateString('en-US', { timeZone: 'UTC' });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_render() {
|
|
49
|
+
const data = this.data || [];
|
|
50
|
+
const options = this.options || {};
|
|
51
|
+
const w = this.renderer?.width ?? 800;
|
|
52
|
+
const h = this.renderer?.height ?? 400;
|
|
53
|
+
|
|
54
|
+
const {
|
|
55
|
+
x = 60, y = 40,
|
|
56
|
+
width = w - x - 40,
|
|
57
|
+
height = h - y - 60,
|
|
58
|
+
title,
|
|
59
|
+
barHeight = 24,
|
|
60
|
+
barGap = 12,
|
|
61
|
+
colors,
|
|
62
|
+
axisLabel,
|
|
63
|
+
dateFormat = 'auto',
|
|
64
|
+
showProgress,
|
|
65
|
+
showToday = true,
|
|
66
|
+
} = options;
|
|
67
|
+
|
|
68
|
+
const palette = new ColorPalette(colors);
|
|
69
|
+
const categories = [...new Set(data.map(d => d.category).filter(Boolean))];
|
|
70
|
+
const categoryIndex = new Map(categories.map((c, i) => [c, i]));
|
|
71
|
+
|
|
72
|
+
const items = data.map(d => {
|
|
73
|
+
const start = GanttChart.parseTime(d.start);
|
|
74
|
+
const end = GanttChart.parseTime(d.end);
|
|
75
|
+
return {
|
|
76
|
+
label: d.label ?? '',
|
|
77
|
+
start,
|
|
78
|
+
end,
|
|
79
|
+
progress: typeof d.progress === 'number' ? Math.max(0, Math.min(100, d.progress)) : undefined,
|
|
80
|
+
category: d.category,
|
|
81
|
+
color: d.color,
|
|
82
|
+
duration: end - start,
|
|
83
|
+
};
|
|
84
|
+
}).filter(d => !Number.isNaN(d.start) && !Number.isNaN(d.end) && d.end >= d.start);
|
|
85
|
+
|
|
86
|
+
const allTimes = items.flatMap(d => [d.start, d.end]);
|
|
87
|
+
if (showToday) allTimes.push(Date.now());
|
|
88
|
+
const tMin = allTimes.length ? Math.min(...allTimes) : Date.now();
|
|
89
|
+
const tMax = allTimes.length ? Math.max(...allTimes) : tMin + 86400000;
|
|
90
|
+
const tRange = Math.max(1, tMax - tMin);
|
|
91
|
+
|
|
92
|
+
const textAnchor = this.renderer.centerTextAnchor;
|
|
93
|
+
const labelColW = Math.min(180, width * 0.22);
|
|
94
|
+
const plotX = x + labelColW;
|
|
95
|
+
const plotW = width - labelColW;
|
|
96
|
+
const plotY = y + (title ? 30 : 0);
|
|
97
|
+
const plotH = height - (title ? 30 : 0);
|
|
98
|
+
|
|
99
|
+
if (title) {
|
|
100
|
+
this.renderer.text(title, x, y + 12, { textAnchor: 'start', fontSize: '16px', fill: '#333' });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const showProg = showProgress ?? items.some(d => d.progress != null);
|
|
104
|
+
|
|
105
|
+
const toX = (t) => plotX + ((t - tMin) / tRange) * plotW;
|
|
106
|
+
|
|
107
|
+
// Grid lines & time-axis ticks.
|
|
108
|
+
const ticks = this._ticks(tMin, tMax, 5);
|
|
109
|
+
ticks.forEach(t => {
|
|
110
|
+
const tx = toX(t);
|
|
111
|
+
this.renderer.path(`M${tx},${plotY} L${tx},${plotY + plotH}`, 'none', { color: '#e0e0e0', width: 1 });
|
|
112
|
+
this.renderer.text(GanttChart.formatDate(t, dateFormat), tx, plotY + plotH + 18, {
|
|
113
|
+
textAnchor, fontSize: '10px', fill: '#666',
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (axisLabel) {
|
|
118
|
+
this.renderer.text(axisLabel, plotX + plotW / 2, plotY + plotH + 38, {
|
|
119
|
+
textAnchor: 'middle', fontSize: '11px', fill: '#666',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Today marker.
|
|
124
|
+
if (showToday) {
|
|
125
|
+
const now = Date.now();
|
|
126
|
+
if (now >= tMin && now <= tMax) {
|
|
127
|
+
const tx = toX(now);
|
|
128
|
+
this.renderer.path(`M${tx},${plotY} L${tx},${plotY + plotH}`, 'none', { color: '#e74c3c', width: 1.5, dasharray: '4 3' });
|
|
129
|
+
this.renderer.text('Today', tx, plotY - 6, { textAnchor, fontSize: '10px', fill: '#e74c3c' });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Bars.
|
|
134
|
+
const contentH = items.length * barHeight + Math.max(0, items.length - 1) * barGap;
|
|
135
|
+
const startY = plotY + (plotH - contentH) / 2;
|
|
136
|
+
|
|
137
|
+
items.forEach((d, i) => {
|
|
138
|
+
const yRow = startY + i * (barHeight + barGap);
|
|
139
|
+
const x1 = toX(d.start);
|
|
140
|
+
const x2 = toX(d.end);
|
|
141
|
+
const barW = Math.max(2, x2 - x1);
|
|
142
|
+
const baseColor = d.color ?? (d.category ? palette.colorAt(categoryIndex.get(d.category)) : '#4f8ef7');
|
|
143
|
+
|
|
144
|
+
// Background track.
|
|
145
|
+
this.renderer.rect(x1, yRow, barW, barHeight, '#eef2f7', null, {
|
|
146
|
+
tooltip: `${d.label}: ${GanttChart.formatDate(d.start, dateFormat)} → ${GanttChart.formatDate(d.end, dateFormat)}`,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Progress fill.
|
|
150
|
+
if (showProg && d.progress != null) {
|
|
151
|
+
const progW = barW * (d.progress / 100);
|
|
152
|
+
this.renderer.rect(x1, yRow, progW, barHeight, baseColor, null, {
|
|
153
|
+
tooltip: `${d.label}: ${d.progress}%`,
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
this.renderer.rect(x1, yRow, barW, barHeight, baseColor, null, {
|
|
157
|
+
tooltip: `${d.label}: ${GanttChart.formatDate(d.start, dateFormat)} → ${GanttChart.formatDate(d.end, dateFormat)}`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Label in the label column.
|
|
162
|
+
this.renderer.text(d.label, x + labelColW - 8, yRow + barHeight / 2 + 4, {
|
|
163
|
+
textAnchor: 'end', fontSize: '11px', fill: '#333',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Duration label inside/near the bar if space permits.
|
|
167
|
+
if (barW > 40) {
|
|
168
|
+
const durationDays = Math.round(d.duration / 86400000);
|
|
169
|
+
const label = durationDays >= 1 ? `${durationDays}d` : `${Math.round(d.duration / 3600000)}h`;
|
|
170
|
+
this.renderer.text(label, x1 + barW - 6, yRow + barHeight / 2 + 4, {
|
|
171
|
+
textAnchor: 'end', fontSize: '9px', fill: ColorPalette.isDark(baseColor) ? '#fff' : '#333',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Baseline axis.
|
|
177
|
+
this.renderer.path(`M${plotX},${plotY + plotH} L${plotX + plotW},${plotY + plotH}`, 'none', { color: '#999', width: 1 });
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
_ticks(tMin, tMax, count) {
|
|
181
|
+
const span = tMax - tMin;
|
|
182
|
+
if (span <= 0) return [tMin];
|
|
183
|
+
// Round to a nice interval.
|
|
184
|
+
const rough = span / count;
|
|
185
|
+
const exp = Math.floor(Math.log10(rough));
|
|
186
|
+
const frac = rough / Math.pow(10, exp);
|
|
187
|
+
let step;
|
|
188
|
+
if (frac <= 1) step = Math.pow(10, exp);
|
|
189
|
+
else if (frac <= 2) step = 2 * Math.pow(10, exp);
|
|
190
|
+
else if (frac <= 5) step = 5 * Math.pow(10, exp);
|
|
191
|
+
else step = 10 * Math.pow(10, exp);
|
|
192
|
+
|
|
193
|
+
const start = Math.ceil(tMin / step) * step;
|
|
194
|
+
const ticks = [];
|
|
195
|
+
for (let t = start; t <= tMax; t += step) {
|
|
196
|
+
ticks.push(t);
|
|
197
|
+
}
|
|
198
|
+
if (ticks.length === 0) ticks.push(tMin);
|
|
199
|
+
return ticks;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { Chart } from '../Chart.js';
|
|
2
|
+
import { Gauge } from '../Gauge.js';
|
|
3
|
+
import { GaugeScale } from '../gauges/GaugeScale.js';
|
|
4
|
+
import { GaugeBands } from '../gauges/GaugeBands.js';
|
|
5
|
+
import { GaugeValue } from '../gauges/GaugeValue.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* GaugeChart — abstract base for gauges: one value shown along a track.
|
|
9
|
+
*
|
|
10
|
+
* It reads what every gauge has in common from its data and options (a
|
|
11
|
+
* `GaugeScale`, `GaugeBands`, a `GaugeValue`) and draws the parts every gauge
|
|
12
|
+
* has on the subclass's `track()`: the background or the bands, the value, a
|
|
13
|
+
* target marker, ticks and the labels. A subclass picks the track and its
|
|
14
|
+
* layout, and adds its own parts (the dial's needle).
|
|
15
|
+
*
|
|
16
|
+
* Options every gauge takes:
|
|
17
|
+
* min, max (0, 100), format, units — the scale (see GaugeScale)
|
|
18
|
+
* bands: [{to, color?, label?}] — ranges drawn behind the value; the value takes its band's colour
|
|
19
|
+
* bandColors: string[] — colours for bands without their own
|
|
20
|
+
* color — the value's colour: one, a gradient array, or (percent) => colour
|
|
21
|
+
* target — a marker at a value (or data.target)
|
|
22
|
+
* targetColor ('#333')
|
|
23
|
+
* ticks: number — that many equal steps, marked and labelled
|
|
24
|
+
* segments: number, segmentGap (2) — the track as that many blocks (LED style), lit up to the value;
|
|
25
|
+
* with bands, each lit block takes its own band's colour
|
|
26
|
+
* title
|
|
27
|
+
*/
|
|
28
|
+
export class GaugeChart extends Chart {
|
|
29
|
+
/** The value's colour when neither `color` nor a band gives one. */
|
|
30
|
+
static defaultColor = '#5352ed';
|
|
31
|
+
|
|
32
|
+
/** The track behind the value when there are no bands. */
|
|
33
|
+
static trackColor = '#f1f2f6';
|
|
34
|
+
|
|
35
|
+
/** Where and how big this type draws when the options don't say (cx, cy, r, ...). */
|
|
36
|
+
static LAYOUT = {};
|
|
37
|
+
|
|
38
|
+
/** The layout: the options' values for this type's LAYOUT keys, over its own. */
|
|
39
|
+
get layout() {
|
|
40
|
+
const layout = { ...this.constructor.LAYOUT };
|
|
41
|
+
for (const key of Object.keys(layout)) if (this.options[key] != null) layout[key] = this.options[key];
|
|
42
|
+
return layout;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get scale() {
|
|
46
|
+
const { min, max, format, units } = this.options;
|
|
47
|
+
return (this._scale ??= new GaugeScale({ min, max, format: format ?? this.defaultFormat(), units }));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get bands() {
|
|
51
|
+
// `ranges` and `rangeColors`: the bullet graph's older names for them.
|
|
52
|
+
const { bands, ranges, bandColors = this.options.rangeColors } = this.options;
|
|
53
|
+
return (this._bands ??= new GaugeBands(bands ?? ranges ?? this.defaultBands(), this.scale, bandColors ? { colors: bandColors } : {}));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get gaugeValue() { return (this._value ??= GaugeValue.from(this.data, this.options)); }
|
|
57
|
+
|
|
58
|
+
/** The value, held to the scale. */
|
|
59
|
+
get value() { return this.scale.clamp(this.gaugeValue.value); }
|
|
60
|
+
|
|
61
|
+
/** A format this gauge type reads its numbers with when none is given (null: the scale's). */
|
|
62
|
+
defaultFormat() { return null; }
|
|
63
|
+
|
|
64
|
+
/** Bands this gauge type draws when none are given. */
|
|
65
|
+
defaultBands() { return []; }
|
|
66
|
+
|
|
67
|
+
/** The track the value moves along. Subclasses implement. @returns {import('../gauges/GaugeTrack.js').GaugeTrack} */
|
|
68
|
+
track() { throw new Error(`${this.constructor.name} must implement track()`); }
|
|
69
|
+
|
|
70
|
+
/** The value's colour: the `color` option, else its band's, else the type's own. */
|
|
71
|
+
valueColor(value = this.value) {
|
|
72
|
+
const { color } = this.options;
|
|
73
|
+
if (color != null) return Gauge.resolveColor(color, this.scale.fraction(value) * 100);
|
|
74
|
+
return this.bands.at(value)?.color ?? this.constructor.defaultColor;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* With `segments`, the track as that many blocks a `segmentGap` (pixels)
|
|
79
|
+
* apart: [{from, to, mid}] as fractions; null without (fewer than 2).
|
|
80
|
+
*/
|
|
81
|
+
segmentsOf(track) {
|
|
82
|
+
const n = Math.round(this.options.segments ?? 0);
|
|
83
|
+
if (n < 2) return null;
|
|
84
|
+
const gap = Math.min((this.options.segmentGap ?? 2) / (track.length || 1), 0.5 / n);
|
|
85
|
+
return Array.from({ length: n }, (_, i) => ({ from: i / n + gap / 2, to: (i + 1) / n - gap / 2, mid: (i + 0.5) / n }));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** The bands, lighter, along the whole track; or the plain track without any. */
|
|
89
|
+
drawBackground(track, options = {}) {
|
|
90
|
+
const blocks = this.segmentsOf(track);
|
|
91
|
+
if (blocks) {
|
|
92
|
+
for (const block of blocks) {
|
|
93
|
+
const band = this.bands.at(this.scale.valueAt(block.mid));
|
|
94
|
+
track.draw(this.renderer, block.from, block.to, band ? GaugeBands.tint(band.color) : this.constructor.trackColor, { ...options, cap: undefined });
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (!this.bands.length) {
|
|
99
|
+
track.draw(this.renderer, 0, 1, this.constructor.trackColor, options);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
for (const band of this.bands.list) {
|
|
103
|
+
track.draw(this.renderer, this.scale.fraction(band.from), this.scale.fraction(band.to), GaugeBands.tint(band.color), { ...options, cap: undefined });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A value: the track from the scale's start to it. This gauge's value and
|
|
109
|
+
* scale unless given (a gauge of several values draws each on its own).
|
|
110
|
+
*/
|
|
111
|
+
drawValue(track, { value = this.value, scale = this.scale, color, ...options } = {}) {
|
|
112
|
+
const blocks = this.segmentsOf(track);
|
|
113
|
+
if (!blocks) {
|
|
114
|
+
track.draw(this.renderer, 0, scale.fraction(value), color ?? this.valueColor(value), options);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// The blocks up to the value are lit: each in its band's colour (a level meter), unless a colour is given.
|
|
118
|
+
const lit = Math.round(scale.fraction(value) * blocks.length);
|
|
119
|
+
const own = color ?? (this.options.color != null || !this.bands.length ? this.valueColor(value) : null);
|
|
120
|
+
for (const block of blocks.slice(0, lit)) {
|
|
121
|
+
const blockColor = own ?? this.bands.at(scale.valueAt(block.mid))?.color ?? this.constructor.defaultColor;
|
|
122
|
+
track.draw(this.renderer, block.from, block.to, blockColor, { ...options, cap: undefined });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** A line across the track at the target, a little past both edges. */
|
|
127
|
+
drawTarget(track, { overhang = 3, width = 2 } = {}) {
|
|
128
|
+
const { target } = this.gaugeValue;
|
|
129
|
+
if (target == null) return;
|
|
130
|
+
const half = track.thickness / 2 + overhang;
|
|
131
|
+
track.line(this.renderer, this.scale.fraction(target), -half, half, { color: this.options.targetColor ?? '#333', width });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** `ticks` marks outside the track, each labelled with its value. */
|
|
135
|
+
drawTicks(track) {
|
|
136
|
+
const { ticks } = this.options;
|
|
137
|
+
if (!ticks) return;
|
|
138
|
+
const count = Math.max(1, Math.round(ticks));
|
|
139
|
+
const edge = track.thickness / 2;
|
|
140
|
+
for (const value of this.scale.ticks(count)) {
|
|
141
|
+
const f = this.scale.fraction(value);
|
|
142
|
+
track.line(this.renderer, f, edge + 2, edge + 6, { color: '#999', width: 1 });
|
|
143
|
+
const at = track.point(f, edge + 14);
|
|
144
|
+
this.renderer.text(this.scale.tickLabel(value, count), at.x, at.y, {
|
|
145
|
+
textAnchor: track.anchorAt(f), verticalAlign: 'middle', fontSize: '10px', fill: '#747d8c',
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Draw a gauge title. */
|
|
151
|
+
_renderTitle(title, x, y, options = {}) {
|
|
152
|
+
if (!title) return;
|
|
153
|
+
this.renderer.text(title, x, y, {
|
|
154
|
+
textAnchor: options.textAnchor || 'start',
|
|
155
|
+
fontSize: options.fontSize || '10px',
|
|
156
|
+
fill: options.fill || '#333',
|
|
157
|
+
...options,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Draw the value's label, centred at a point. */
|
|
162
|
+
_renderValueLabel(x, y, options = {}) {
|
|
163
|
+
this.renderer.text(this.scale.label(this.value), x, y, {
|
|
164
|
+
textAnchor: options.textAnchor || 'middle',
|
|
165
|
+
verticalAlign: options.verticalAlign || 'middle',
|
|
166
|
+
fontSize: options.fontSize || '12px',
|
|
167
|
+
fill: options.fill || '#fff',
|
|
168
|
+
...options,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
_render() {
|
|
173
|
+
throw new Error(`${this.constructor.name} must implement _render()`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Chart } from '../Chart.js';
|
|
2
|
+
import { ChartBox, ChartLabels } from '../ChartBox.js';
|
|
3
|
+
import { ColorPalette } from '../ColorPalette.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GeoMapChart — simple equirectangular-projection map for choropleth fills
|
|
7
|
+
* and bubble markers. No external dependencies; the caller supplies the
|
|
8
|
+
* GeoJSON-like feature collection.
|
|
9
|
+
*
|
|
10
|
+
* Data:
|
|
11
|
+
* {
|
|
12
|
+
* features: Array<{
|
|
13
|
+
* id, name, value?, color?,
|
|
14
|
+
* geometry: { type: 'Polygon'|'MultiPolygon', coordinates: number[][][][] }
|
|
15
|
+
* }>,
|
|
16
|
+
* bubbles?: Array<{ lat, lon, value, label?, color?, radius? }>
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* Options:
|
|
20
|
+
* - center: [lon, lat] — default [0, 20]
|
|
21
|
+
* - scale: number — pixels per degree; auto-fitted if omitted
|
|
22
|
+
* - colorScale: string[] — gradient stops for choropleth values
|
|
23
|
+
* - bubbleMaxRadius: number — max bubble radius (default 20)
|
|
24
|
+
* - bubbleColor: string — default bubble fill
|
|
25
|
+
* - title
|
|
26
|
+
*/
|
|
27
|
+
export class GeoMapChart extends Chart {
|
|
28
|
+
static chartType = 'geoMap';
|
|
29
|
+
|
|
30
|
+
static DEFAULT_COLOR_SCALE = ['#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'];
|
|
31
|
+
|
|
32
|
+
_render() {
|
|
33
|
+
const data = this.data || {};
|
|
34
|
+
const options = this.options || {};
|
|
35
|
+
const box = ChartBox.fromRenderer(this.renderer, { left: 40, top: 50, right: 40, bottom: 50 });
|
|
36
|
+
const {
|
|
37
|
+
x = box.x, y = box.y, width = box.width, height = box.height,
|
|
38
|
+
title,
|
|
39
|
+
center: [centerLon = 0, centerLat = 20] = [],
|
|
40
|
+
scale: explicitScale,
|
|
41
|
+
colorScale = GeoMapChart.DEFAULT_COLOR_SCALE,
|
|
42
|
+
bubbleMaxRadius = 20,
|
|
43
|
+
bubbleColor = '#e74c3c',
|
|
44
|
+
} = options;
|
|
45
|
+
const features = data.features || [];
|
|
46
|
+
const bubbles = data.bubbles || [];
|
|
47
|
+
|
|
48
|
+
new ChartLabels({ title }).draw(this.renderer, { x, y, width, height });
|
|
49
|
+
|
|
50
|
+
const scale = explicitScale || this._fitScale(features, width, height, centerLon, centerLat);
|
|
51
|
+
const cx = x + width / 2;
|
|
52
|
+
const cy = y + height / 2;
|
|
53
|
+
const project = (lon, lat) => ({
|
|
54
|
+
x: cx + (lon - centerLon) * scale,
|
|
55
|
+
y: cy - (lat - centerLat) * scale,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const valueRange = this._valueRange(features);
|
|
59
|
+
const palette = new ColorPalette(colorScale);
|
|
60
|
+
|
|
61
|
+
features.forEach(f => {
|
|
62
|
+
const pathData = this._featurePath(f.geometry, project);
|
|
63
|
+
if (!pathData) return;
|
|
64
|
+
const fill = f.color || this._choroplethColor(f.value, valueRange, palette);
|
|
65
|
+
this.renderer.path(pathData, fill, { color: '#fff', width: 1 }, {
|
|
66
|
+
tooltip: f.name || f.id || '',
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (bubbles.length) {
|
|
71
|
+
const bubbleValues = bubbles.map(b => b.value).filter(v => v != null && !Number.isNaN(v));
|
|
72
|
+
const maxBubbleValue = bubbleValues.length ? Math.max(...bubbleValues) : 1;
|
|
73
|
+
bubbles.forEach(b => {
|
|
74
|
+
const p = project(b.lon, b.lat);
|
|
75
|
+
const r = b.radius || (b.value != null ? Math.max(3, (b.value / maxBubbleValue) * bubbleMaxRadius) : 5);
|
|
76
|
+
this.renderer.circle(p.x, p.y, r, b.color || bubbleColor, { color: '#fff', width: 1 }, {
|
|
77
|
+
tooltip: b.label ? `${b.label}: ${b.value ?? ''}` : String(b.value ?? ''),
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_featurePath(geometry, project) {
|
|
84
|
+
if (!geometry) return '';
|
|
85
|
+
const rings = geometry.type === 'Polygon'
|
|
86
|
+
? [geometry.coordinates]
|
|
87
|
+
: geometry.type === 'MultiPolygon'
|
|
88
|
+
? geometry.coordinates
|
|
89
|
+
: [];
|
|
90
|
+
if (!rings.length) return '';
|
|
91
|
+
|
|
92
|
+
let d = '';
|
|
93
|
+
rings.forEach(polygon => {
|
|
94
|
+
polygon.forEach(ring => {
|
|
95
|
+
ring.forEach(([lon, lat], i) => {
|
|
96
|
+
const p = project(lon, lat);
|
|
97
|
+
d += `${i === 0 ? 'M' : 'L'}${p.x},${p.y} `;
|
|
98
|
+
});
|
|
99
|
+
d += 'Z ';
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
return d.trim();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_fitScale(features, width, height, centerLon, centerLat) {
|
|
106
|
+
const lons = [];
|
|
107
|
+
const lats = [];
|
|
108
|
+
features.forEach(f => this._walkCoordinates(f.geometry, (lon, lat) => {
|
|
109
|
+
lons.push(lon);
|
|
110
|
+
lats.push(lat);
|
|
111
|
+
}));
|
|
112
|
+
if (!lons.length) return 4;
|
|
113
|
+
const lonRange = Math.max(1, Math.max(...lons) - Math.min(...lons));
|
|
114
|
+
const latRange = Math.max(1, Math.max(...lats) - Math.min(...lats));
|
|
115
|
+
return Math.min(width / lonRange, height / latRange) * 0.9;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
_walkCoordinates(geometry, cb) {
|
|
119
|
+
if (!geometry) return;
|
|
120
|
+
const rings = geometry.type === 'Polygon'
|
|
121
|
+
? [geometry.coordinates]
|
|
122
|
+
: geometry.type === 'MultiPolygon'
|
|
123
|
+
? geometry.coordinates
|
|
124
|
+
: [];
|
|
125
|
+
rings.forEach(polygon => {
|
|
126
|
+
polygon.forEach(ring => {
|
|
127
|
+
ring.forEach(([lon, lat]) => cb(lon, lat));
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
_valueRange(features) {
|
|
133
|
+
const values = features.map(f => f.value).filter(v => v != null && !Number.isNaN(v));
|
|
134
|
+
return {
|
|
135
|
+
min: values.length ? Math.min(...values) : 0,
|
|
136
|
+
max: values.length ? Math.max(...values) : 1,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_choroplethColor(value, range, palette) {
|
|
141
|
+
if (value == null || range.max === range.min) return palette.colorAt(0);
|
|
142
|
+
const t = (value - range.min) / (range.max - range.min);
|
|
143
|
+
const index = Math.min(palette.colors.length - 1, Math.floor(t * palette.colors.length));
|
|
144
|
+
return palette.colorAt(index);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Legend } from '../Legend.js';
|
|
2
|
+
import { BarChartBase } from './BarChartBase.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GroupedBarChart — vertical grouped (multi-set) bar chart.
|
|
6
|
+
*
|
|
7
|
+
* Data shape:
|
|
8
|
+
* Array<{name: string, values: Array<{label: string, value: number}>}>
|
|
9
|
+
*
|
|
10
|
+
* Each category (`label`) gets a cluster of bars side-by-side, one per series.
|
|
11
|
+
*/
|
|
12
|
+
export class GroupedBarChart extends BarChartBase {
|
|
13
|
+
static chartType = 'groupedBar';
|
|
14
|
+
|
|
15
|
+
_computeMaxValue() {
|
|
16
|
+
const series = this.data;
|
|
17
|
+
const rawMax = Math.max(
|
|
18
|
+
...series.flatMap(s => s.values.map(v => v.value)),
|
|
19
|
+
1,
|
|
20
|
+
);
|
|
21
|
+
return this._drawYAxis(rawMax);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_renderBars(maxValue) {
|
|
25
|
+
const series = this.data;
|
|
26
|
+
const options = this.options;
|
|
27
|
+
const { x, y, width, height } = this._plotBox;
|
|
28
|
+
const {
|
|
29
|
+
groupPadding = 0.2, barPadding = 0.05,
|
|
30
|
+
} = options;
|
|
31
|
+
const seriesCount = series.length;
|
|
32
|
+
const labels = [...new Set(series.flatMap(s => s.values.map(v => v.label)))];
|
|
33
|
+
const categoryCount = labels.length;
|
|
34
|
+
|
|
35
|
+
// Build a value lookup so missing labels per series render as 0.
|
|
36
|
+
const valueBySeriesLabel = series.map(s => {
|
|
37
|
+
const map = new Map();
|
|
38
|
+
for (const v of s.values) map.set(v.label, v.value);
|
|
39
|
+
return map;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const clusterWidth = width / categoryCount;
|
|
43
|
+
const groupGap = clusterWidth * groupPadding;
|
|
44
|
+
const availableWidth = clusterWidth - groupGap;
|
|
45
|
+
const barWidth = availableWidth / seriesCount;
|
|
46
|
+
const barGap = barWidth * barPadding;
|
|
47
|
+
const finalBarWidth = barWidth - barGap;
|
|
48
|
+
|
|
49
|
+
const textAnchor = this.renderer.centerTextAnchor;
|
|
50
|
+
|
|
51
|
+
labels.forEach((label, categoryIndex) => {
|
|
52
|
+
const clusterX = x + categoryIndex * clusterWidth + groupGap / 2;
|
|
53
|
+
|
|
54
|
+
series.forEach((seriesData, seriesIndex) => {
|
|
55
|
+
const value = valueBySeriesLabel[seriesIndex].get(label) ?? 0;
|
|
56
|
+
const barHeight = (value / maxValue) * height;
|
|
57
|
+
const barX = clusterX + seriesIndex * barWidth + barGap / 2;
|
|
58
|
+
const barY = y + height - barHeight;
|
|
59
|
+
const color = this._palette.colorAt(seriesIndex);
|
|
60
|
+
|
|
61
|
+
this.renderer.rect(barX, barY, finalBarWidth, barHeight, color, null, {
|
|
62
|
+
tooltip: `${seriesData.name} — ${label}: ${value}`,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.renderer.text(label, clusterX + availableWidth / 2, y + height + 20, { textAnchor });
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_afterBars() {
|
|
71
|
+
const series = this.data;
|
|
72
|
+
const options = this.options;
|
|
73
|
+
const { x, y, width } = this._plotBox;
|
|
74
|
+
const { legend: showLegend = false } = options;
|
|
75
|
+
|
|
76
|
+
if (showLegend) {
|
|
77
|
+
const legendItems = series.map((s, i) => ({
|
|
78
|
+
label: s.name,
|
|
79
|
+
color: this._palette.colorAt(i),
|
|
80
|
+
dataIndex: i,
|
|
81
|
+
}));
|
|
82
|
+
new Legend({
|
|
83
|
+
items: legendItems, x: x + width + 20, y,
|
|
84
|
+
itemHeight: 20, markerSize: 10,
|
|
85
|
+
}).draw(this.renderer);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Chart } from '../Chart.js';
|
|
2
|
+
import { ChartBox, ChartLabels } from '../ChartBox.js';
|
|
3
|
+
import { ColorPalette } from '../ColorPalette.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GroupedDistributionChart — abstract base for charts that draw one glyph per
|
|
7
|
+
* grouped numeric sample (`{label, values: number[]}`).
|
|
8
|
+
*
|
|
9
|
+
* Owns the cartesian setup, shared value-domain computation, slot layout, and
|
|
10
|
+
* x-axis label drawing. Subclasses implement `_renderGlyph(cx, slotWidth, i, d)`.
|
|
11
|
+
*/
|
|
12
|
+
export class GroupedDistributionChart extends Chart {
|
|
13
|
+
_setup() {
|
|
14
|
+
const box = ChartBox.fromRenderer(this.renderer);
|
|
15
|
+
const options = this.options;
|
|
16
|
+
const {
|
|
17
|
+
x = box.x, y = box.y, width = box.width, height = box.height,
|
|
18
|
+
colors, title, xAxisLabel, yAxisLabel,
|
|
19
|
+
} = options;
|
|
20
|
+
this._plotBox = { x, y, width, height };
|
|
21
|
+
this._palette = new ColorPalette(colors);
|
|
22
|
+
new ChartLabels({ title, xAxisLabel, yAxisLabel }).draw(this.renderer, this._plotBox);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_computeDomain() {
|
|
26
|
+
const data = this.data;
|
|
27
|
+
const allVals = data.flatMap(d => d.values);
|
|
28
|
+
const vMax = Math.max(...allVals);
|
|
29
|
+
const vMin = Math.min(...allVals);
|
|
30
|
+
const range = (vMax - vMin) || 1;
|
|
31
|
+
return { vMin, vMax, range };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_toY(v) {
|
|
35
|
+
const { y, height } = this._plotBox;
|
|
36
|
+
return y + height - ((v - this._domain.vMin) / this._domain.range) * height;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_slotWidth() {
|
|
40
|
+
return this._plotBox.width / this.data.length;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_drawBaseAxis() {
|
|
44
|
+
const { x, y, width, height } = this._plotBox;
|
|
45
|
+
this.renderer.path(`M${x},${y} L${x},${y + height} L${x + width},${y + height}`, 'none', { color: 'black', width: 1 });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
_drawXAxisLabel(cx, label) {
|
|
49
|
+
const { y, height } = this._plotBox;
|
|
50
|
+
this.renderer.text(label, cx, y + height + 20, { textAnchor: this.renderer.centerTextAnchor, fontSize: '10px' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_render() {
|
|
54
|
+
this._setup();
|
|
55
|
+
this._domain = this._computeDomain();
|
|
56
|
+
this._drawBaseAxis();
|
|
57
|
+
const slotWidth = this._slotWidth();
|
|
58
|
+
const data = this.data;
|
|
59
|
+
data.forEach((d, i) => {
|
|
60
|
+
const cx = this._plotBox.x + i * slotWidth + slotWidth / 2;
|
|
61
|
+
this._renderGlyph(cx, slotWidth, i, d);
|
|
62
|
+
this._drawXAxisLabel(cx, d.label);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** @abstract */
|
|
67
|
+
_renderGlyph(cx, slotWidth, i, d) {
|
|
68
|
+
throw new Error(`${this.constructor.name} must implement _renderGlyph()`);
|
|
69
|
+
}
|
|
70
|
+
}
|