ooxml-core 1.13.0 → 1.14.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/dist/PptxHandler-5YP75BPO.cjs +12 -0
- package/dist/PptxHandler-GT5Q66TG.mjs +3 -0
- package/dist/{PptxHandler-FIN6XDTI.mjs → PptxHandler-KNBFECUE.mjs} +3 -3
- package/dist/PresentationBuilder-5DCCFHWJ.mjs +7 -0
- package/dist/PresentationBuilder-CVM6LJ7L.mjs +3 -0
- package/dist/PresentationBuilder-II7C4A3R.cjs +20 -0
- package/dist/automation/docx.d.ts +18 -0
- package/dist/automation/docx.d.ts.map +1 -1
- package/dist/automation/index.cjs +21278 -8022
- package/dist/automation/index.d.ts +1 -0
- package/dist/automation/index.d.ts.map +1 -1
- package/dist/automation/index.mjs +21275 -8023
- package/dist/automation/node.cjs +66 -6
- package/dist/automation/node.d.ts +10 -0
- package/dist/automation/node.d.ts.map +1 -1
- package/dist/automation/node.mjs +67 -7
- package/dist/automation/outline.d.ts +29 -0
- package/dist/automation/outline.d.ts.map +1 -0
- package/dist/automation/xlsx.d.ts +21 -0
- package/dist/automation/xlsx.d.ts.map +1 -1
- package/dist/chart/auto-title.d.ts +31 -0
- package/dist/chart/auto-title.d.ts.map +1 -0
- package/dist/chart/axis-format.d.ts +13 -0
- package/dist/chart/axis-format.d.ts.map +1 -0
- package/dist/chart/bubble-radius.d.ts +30 -0
- package/dist/chart/bubble-radius.d.ts.map +1 -0
- package/dist/chart/error-bar-amount.d.ts +22 -0
- package/dist/chart/error-bar-amount.d.ts.map +1 -0
- package/dist/chart/hierarchy.d.ts +69 -0
- package/dist/chart/hierarchy.d.ts.map +1 -0
- package/dist/chart/index.cjs +2377 -527
- package/dist/chart/index.d.ts +12 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +2338 -528
- package/dist/chart/model-analysis.d.ts +66 -0
- package/dist/chart/model-analysis.d.ts.map +1 -0
- package/dist/chart/model-series.d.ts +5 -0
- package/dist/chart/model-series.d.ts.map +1 -1
- package/dist/chart/number-format-pattern.d.ts +35 -0
- package/dist/chart/number-format-pattern.d.ts.map +1 -0
- package/dist/chart/number-format.d.ts +21 -0
- package/dist/chart/number-format.d.ts.map +1 -0
- package/dist/chart/parse-analysis.d.ts +13 -0
- package/dist/chart/parse-analysis.d.ts.map +1 -0
- package/dist/chart/parse-series.d.ts +1 -1
- package/dist/chart/parse-series.d.ts.map +1 -1
- package/dist/chart/parse-util.d.ts +2 -0
- package/dist/chart/parse-util.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-analysis.d.ts +7 -0
- package/dist/chart/render/chart-svg-analysis.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-bars.d.ts +5 -0
- package/dist/chart/render/chart-svg-bars.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-cartesian.d.ts +7 -2
- package/dist/chart/render/chart-svg-cartesian.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-hierarchy.d.ts +5 -0
- package/dist/chart/render/chart-svg-hierarchy.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-plots.d.ts +5 -0
- package/dist/chart/render/chart-svg-plots.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-stock.d.ts +4 -0
- package/dist/chart/render/chart-svg-stock.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-waterfall.d.ts +4 -0
- package/dist/chart/render/chart-svg-waterfall.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-xy.d.ts +4 -0
- package/dist/chart/render/chart-svg-xy.d.ts.map +1 -0
- package/dist/chart/render/chart-svg.d.ts +1 -1
- package/dist/chart/render/chart-svg.d.ts.map +1 -1
- package/dist/chart/render/chart-value-axis.d.ts +6 -1
- package/dist/chart/render/chart-value-axis.d.ts.map +1 -1
- package/dist/chart/render/chart-view-analysis.d.ts +30 -0
- package/dist/chart/render/chart-view-analysis.d.ts.map +1 -0
- package/dist/chart/render/chart-view-ex.d.ts +24 -0
- package/dist/chart/render/chart-view-ex.d.ts.map +1 -0
- package/dist/chart/render/chart-view-families.d.ts +10 -0
- package/dist/chart/render/chart-view-families.d.ts.map +1 -0
- package/dist/chart/render/chart-view-series.d.ts +36 -0
- package/dist/chart/render/chart-view-series.d.ts.map +1 -0
- package/dist/chart/render/chart-view-stock.d.ts +23 -0
- package/dist/chart/render/chart-view-stock.d.ts.map +1 -0
- package/dist/chart/render/chart-view.d.ts +49 -18
- package/dist/chart/render/chart-view.d.ts.map +1 -1
- package/dist/chart/render/index.d.ts +2 -0
- package/dist/chart/render/index.d.ts.map +1 -1
- package/dist/chart/render/render-space.d.ts +6 -1
- package/dist/chart/render/render-space.d.ts.map +1 -1
- package/dist/chart/render/summary-analysis.d.ts +11 -0
- package/dist/chart/render/summary-analysis.d.ts.map +1 -0
- package/dist/chart/render/summary-from-chartex.d.ts +11 -0
- package/dist/chart/render/summary-from-chartex.d.ts.map +1 -0
- package/dist/chart/render/summary-from-space.d.ts.map +1 -1
- package/dist/chart/render/summary.d.ts +86 -3
- package/dist/chart/render/summary.d.ts.map +1 -1
- package/dist/chart/stock-candles.d.ts +72 -0
- package/dist/chart/stock-candles.d.ts.map +1 -0
- package/dist/chart/style-palette.d.ts +29 -0
- package/dist/chart/style-palette.d.ts.map +1 -0
- package/dist/chart/sunburst-arcs.d.ts +41 -0
- package/dist/chart/sunburst-arcs.d.ts.map +1 -0
- package/dist/chart/trendline-fit.d.ts +39 -0
- package/dist/chart/trendline-fit.d.ts.map +1 -0
- package/dist/chart/waterfall.d.ts +31 -0
- package/dist/chart/waterfall.d.ts.map +1 -0
- package/dist/chart/write-analysis.d.ts +12 -0
- package/dist/chart/write-analysis.d.ts.map +1 -0
- package/dist/chart/write-series.d.ts.map +1 -1
- package/dist/{chunk-G5PQKHCG.mjs → chunk-2D4IFQ5M.mjs} +1 -1
- package/dist/{chunk-UAY26XOI.mjs → chunk-2EBMHIGJ.mjs} +1303 -994
- package/dist/{chunk-TVE6UIJF.mjs → chunk-4WZLFUUA.mjs} +54 -13
- package/dist/{chunk-H2FRDUNV.mjs → chunk-54ASP65T.mjs} +868 -585
- package/dist/chunk-M4XLF4R7.mjs +387 -0
- package/dist/{chunk-O6NIA4NG.mjs → chunk-ORH32TO3.mjs} +5798 -5742
- package/dist/{chunk-B2JBBAEQ.mjs → chunk-TNNXOW2O.mjs} +1 -1
- package/dist/{chunk-IT3U6QD6.cjs → chunk-TQE7FFNT.cjs} +6754 -6695
- package/dist/{chunk-7QZGRB3T.cjs → chunk-X7MGZQ6C.cjs} +1321 -995
- package/dist/{chunk-6DELVMYB.mjs → chunk-XGXIS4PN.mjs} +12316 -12260
- package/dist/crypto/decrypt.d.ts +17 -3
- package/dist/crypto/decrypt.d.ts.map +1 -1
- package/dist/crypto/encryption-info.d.ts.map +1 -1
- package/dist/crypto/index.cjs +252 -78
- package/dist/crypto/index.d.ts +19 -4
- package/dist/crypto/index.d.ts.map +1 -1
- package/dist/crypto/index.mjs +252 -79
- package/dist/crypto/key-derivation.d.ts +2 -3
- package/dist/crypto/key-derivation.d.ts.map +1 -1
- package/dist/crypto/validate.d.ts +22 -0
- package/dist/crypto/validate.d.ts.map +1 -0
- package/dist/diagram/engine/layout-def-parse.d.ts.map +1 -1
- package/dist/diagram/engine/pres-tree.d.ts.map +1 -1
- package/dist/diagram/index.cjs +102 -52
- package/dist/diagram/index.mjs +102 -52
- package/dist/digest/index.cjs +23 -11
- package/dist/digest/index.d.ts +2 -1
- package/dist/digest/index.d.ts.map +1 -1
- package/dist/digest/index.mjs +21 -12
- package/dist/digest/password-hash.d.ts +19 -5
- package/dist/digest/password-hash.d.ts.map +1 -1
- package/dist/digest/timing-safe.d.ts +7 -0
- package/dist/digest/timing-safe.d.ts.map +1 -0
- package/dist/docx/block-parser.d.ts.map +1 -1
- package/dist/docx/chart-paint.d.ts.map +1 -1
- package/dist/docx/chart.d.ts +10 -2
- package/dist/docx/chart.d.ts.map +1 -1
- package/dist/docx/content-control-edit.d.ts +26 -0
- package/dist/docx/content-control-edit.d.ts.map +1 -0
- package/dist/docx/content-control-model.d.ts +51 -0
- package/dist/docx/content-control-model.d.ts.map +1 -0
- package/dist/docx/content-control.d.ts +9 -0
- package/dist/docx/content-control.d.ts.map +1 -0
- package/dist/docx/default-styles.d.ts.map +1 -1
- package/dist/docx/drawing.d.ts.map +1 -1
- package/dist/docx/embedded.cjs +9932 -935
- package/dist/docx/embedded.mjs +9932 -935
- package/dist/docx/equation.d.ts +7 -3
- package/dist/docx/equation.d.ts.map +1 -1
- package/dist/docx/index.cjs +14117 -1513
- package/dist/docx/index.d.ts +6 -0
- package/dist/docx/index.d.ts.map +1 -1
- package/dist/docx/index.mjs +14093 -1514
- package/dist/docx/inline-model.d.ts +3 -0
- package/dist/docx/inline-model.d.ts.map +1 -1
- package/dist/docx/layout/adapt-floats.d.ts +3 -3
- package/dist/docx/layout/adapt-floats.d.ts.map +1 -1
- package/dist/docx/layout/adapter.d.ts.map +1 -1
- package/dist/docx/layout/equation-object.d.ts +7 -0
- package/dist/docx/layout/equation-object.d.ts.map +1 -0
- package/dist/docx/layout/floats.d.ts +8 -0
- package/dist/docx/layout/floats.d.ts.map +1 -1
- package/dist/docx/layout/incremental-layout.d.ts +39 -0
- package/dist/docx/layout/incremental-layout.d.ts.map +1 -0
- package/dist/docx/layout/index.cjs +14177 -1707
- package/dist/docx/layout/index.d.ts +2 -2
- package/dist/docx/layout/index.d.ts.map +1 -1
- package/dist/docx/layout/index.mjs +14176 -1708
- package/dist/docx/layout/input.d.ts +4 -0
- package/dist/docx/layout/input.d.ts.map +1 -1
- package/dist/docx/layout/layout-session.d.ts +13 -2
- package/dist/docx/layout/layout-session.d.ts.map +1 -1
- package/dist/docx/layout/layout.d.ts +1 -1
- package/dist/docx/layout/layout.d.ts.map +1 -1
- package/dist/docx/layout/line-metrics.d.ts.map +1 -1
- package/dist/docx/layout/page-cursor.d.ts +1 -1
- package/dist/docx/layout/page-cursor.d.ts.map +1 -1
- package/dist/docx/layout/page-fields.d.ts +3 -1
- package/dist/docx/layout/page-fields.d.ts.map +1 -1
- package/dist/docx/layout/result.d.ts +14 -1
- package/dist/docx/layout/result.d.ts.map +1 -1
- package/dist/docx/layout/section-flow.d.ts +11 -1
- package/dist/docx/layout/section-flow.d.ts.map +1 -1
- package/dist/docx/ligatures.d.ts +2 -0
- package/dist/docx/ligatures.d.ts.map +1 -1
- package/dist/docx/load/index.cjs +12709 -3590
- package/dist/docx/load/index.mjs +12709 -3590
- package/dist/docx/model-paragraph.d.ts +3 -0
- package/dist/docx/model-paragraph.d.ts.map +1 -1
- package/dist/docx/model-run.d.ts +3 -0
- package/dist/docx/model-run.d.ts.map +1 -1
- package/dist/docx/model.d.ts +3 -0
- package/dist/docx/model.d.ts.map +1 -1
- package/dist/docx/numbering-parse.d.ts.map +1 -1
- package/dist/docx/numbering-text.d.ts.map +1 -1
- package/dist/docx/package-limits.d.ts +6 -0
- package/dist/docx/package-limits.d.ts.map +1 -0
- package/dist/docx/parse-content-control.d.ts +28 -0
- package/dist/docx/parse-content-control.d.ts.map +1 -0
- package/dist/docx/parse-table.d.ts.map +1 -1
- package/dist/docx/parse.d.ts.map +1 -1
- package/dist/docx/save.d.ts.map +1 -1
- package/dist/docx/shape-model.d.ts +31 -0
- package/dist/docx/shape-model.d.ts.map +1 -0
- package/dist/docx/shape-palette.d.ts +19 -0
- package/dist/docx/shape-palette.d.ts.map +1 -0
- package/dist/docx/shape-parse.d.ts +16 -0
- package/dist/docx/shape-parse.d.ts.map +1 -0
- package/dist/docx/shape-svg.d.ts +20 -0
- package/dist/docx/shape-svg.d.ts.map +1 -0
- package/dist/docx/table-model.d.ts +4 -0
- package/dist/docx/table-model.d.ts.map +1 -1
- package/dist/docx/ui/content-control-commands.d.ts +37 -0
- package/dist/docx/ui/content-control-commands.d.ts.map +1 -0
- package/dist/docx/ui/content-control-guard.d.ts +8 -0
- package/dist/docx/ui/content-control-guard.d.ts.map +1 -0
- package/dist/docx/ui/content-control-spans.d.ts +19 -0
- package/dist/docx/ui/content-control-spans.d.ts.map +1 -0
- package/dist/docx/ui/index.cjs +3132 -506
- package/dist/docx/ui/index.d.ts +3 -0
- package/dist/docx/ui/index.d.ts.map +1 -1
- package/dist/docx/ui/index.mjs +3117 -507
- package/dist/docx/ui/inline-content-schema.d.ts.map +1 -1
- package/dist/docx/ui/paragraph-attributes.d.ts.map +1 -1
- package/dist/docx/ui/ribbon-action-ids.d.ts +1 -1
- package/dist/docx/ui/ribbon-action-ids.d.ts.map +1 -1
- package/dist/docx/ui/run-adapter.d.ts.map +1 -1
- package/dist/docx/ui/run-compare.d.ts.map +1 -1
- package/dist/docx/ui/run-mark-properties.d.ts.map +1 -1
- package/dist/docx/ui/run-marks.d.ts.map +1 -1
- package/dist/docx/ui/schema-marks.d.ts +16 -1
- package/dist/docx/ui/schema-marks.d.ts.map +1 -1
- package/dist/docx/ui/table-structure-guard.d.ts.map +1 -1
- package/dist/docx/write-block-placement.d.ts +9 -0
- package/dist/docx/write-block-placement.d.ts.map +1 -0
- package/dist/docx/write-content-control.d.ts +12 -0
- package/dist/docx/write-content-control.d.ts.map +1 -0
- package/dist/docx/write-drawing.d.ts +2 -0
- package/dist/docx/write-drawing.d.ts.map +1 -1
- package/dist/docx/write-inline.d.ts.map +1 -1
- package/dist/docx/write-paragraph.d.ts.map +1 -1
- package/dist/docx/write-shape.d.ts +16 -0
- package/dist/docx/write-shape.d.ts.map +1 -0
- package/dist/docx/write-table.d.ts.map +1 -1
- package/dist/docx/write.d.ts.map +1 -1
- package/dist/drawingml/index.cjs +24 -0
- package/dist/drawingml/index.mjs +24 -0
- package/dist/geometry/index.cjs +63 -48
- package/dist/geometry/index.mjs +63 -48
- package/dist/geometry/preset-shape-definitions-table.d.ts.map +1 -1
- package/dist/index.cjs +4291 -1578
- package/dist/index.mjs +4291 -1578
- package/dist/math/equation-gallery.d.ts +10 -0
- package/dist/math/equation-gallery.d.ts.map +1 -0
- package/dist/math/index.cjs +777 -139
- package/dist/math/index.d.ts +3 -0
- package/dist/math/index.d.ts.map +1 -1
- package/dist/math/index.mjs +772 -140
- package/dist/math/latex-omml-siblings.d.ts.map +1 -1
- package/dist/math/latex-to-omml.d.ts.map +1 -1
- package/dist/math/omml-box-grouped.d.ts +9 -0
- package/dist/math/omml-box-grouped.d.ts.map +1 -0
- package/dist/math/omml-box-layout.d.ts +15 -0
- package/dist/math/omml-box-layout.d.ts.map +1 -0
- package/dist/math/omml-box-structures.d.ts +7 -0
- package/dist/math/omml-box-structures.d.ts.map +1 -0
- package/dist/math/omml-box.d.ts +85 -0
- package/dist/math/omml-box.d.ts.map +1 -0
- package/dist/math/omml-dom.d.ts.map +1 -1
- package/dist/math/omml-mathml-converters.d.ts.map +1 -1
- package/dist/math/omml-svg.d.ts +14 -0
- package/dist/math/omml-svg.d.ts.map +1 -0
- package/dist/math/omml-to-xml.d.ts +10 -0
- package/dist/math/omml-to-xml.d.ts.map +1 -0
- package/dist/opc/embedded-packages.d.ts.map +1 -1
- package/dist/opc/index.cjs +257 -22
- package/dist/opc/index.d.ts +1 -0
- package/dist/opc/index.d.ts.map +1 -1
- package/dist/opc/index.mjs +251 -23
- package/dist/opc/package.d.ts.map +1 -1
- package/dist/opc/signature/detection.d.ts +22 -6
- package/dist/opc/signature/detection.d.ts.map +1 -1
- package/dist/opc/signature/index.d.ts +1 -1
- package/dist/opc/signature/index.d.ts.map +1 -1
- package/dist/opc/signature/xml-utils.d.ts.map +1 -1
- package/dist/opc/zip-limits.d.ts +52 -0
- package/dist/opc/zip-limits.d.ts.map +1 -0
- package/dist/pptx/automation/index.cjs +1848 -1320
- package/dist/pptx/automation/index.d.ts +4 -4
- package/dist/pptx/automation/index.mjs +6 -6
- package/dist/pptx/chunks/{elements-DmbzOhFu.d.ts → elements-tK7xnWeS.d.ts} +20 -9
- package/dist/pptx/chunks/elements-tK7xnWeS.d.ts.map +1 -0
- package/dist/pptx/chunks/{index-Cija6Dih.d.ts → index-BSpNQuvz.d.ts} +30 -5
- package/dist/pptx/chunks/{index-Cija6Dih.d.ts.map → index-BSpNQuvz.d.ts.map} +1 -1
- package/dist/pptx/chunks/{index-BmvOxbsh.d.ts → index-DS9Y4Ne3.d.ts} +25 -9
- package/dist/pptx/chunks/index-DS9Y4Ne3.d.ts.map +1 -0
- package/dist/pptx/chunks/inspection-status-DjiWd_Aa.d.ts.map +1 -1
- package/dist/pptx/chunks/{text-operations-sXxhsKDd.d.ts → text-operations-BdD_UQ11.d.ts} +2 -2
- package/dist/pptx/chunks/{text-operations-sXxhsKDd.d.ts.map → text-operations-BdD_UQ11.d.ts.map} +1 -1
- package/dist/pptx/cli/index.cjs +1795 -1275
- package/dist/pptx/cli/index.d.ts +1 -1
- package/dist/pptx/cli/index.mjs +5 -5
- package/dist/pptx/converter/index.cjs +80 -54
- package/dist/pptx/converter/index.d.ts +1 -1
- package/dist/pptx/converter/index.mjs +3 -3
- package/dist/pptx/editor/render/find-replace.cjs +14 -14
- package/dist/pptx/editor/render/find-replace.d.ts +2 -2
- package/dist/pptx/editor/render/find-replace.mjs +1 -1
- package/dist/pptx/editor/render/slide-operations.cjs +8 -8
- package/dist/pptx/editor/render/slide-operations.mjs +2 -2
- package/dist/pptx/editor/render/text-runs-style-patch.d.ts +1 -1
- package/dist/pptx/editor/render/text-style-scope.d.ts +1 -1
- package/dist/pptx/index.cjs +1117 -351
- package/dist/pptx/index.d.ts +5 -5
- package/dist/pptx/index.mjs +6 -6
- package/dist/pptx/signature-node/index.cjs +342 -65
- package/dist/pptx/signature-node/index.d.ts +12 -1
- package/dist/pptx/signature-node/index.d.ts.map +1 -1
- package/dist/pptx/signature-node/index.mjs +112 -52
- package/dist/teams/activity-feed.d.ts +19 -0
- package/dist/teams/activity-feed.d.ts.map +1 -0
- package/dist/teams/activity-state.d.ts +12 -0
- package/dist/teams/activity-state.d.ts.map +1 -0
- package/dist/teams/activity.d.ts +52 -0
- package/dist/teams/activity.d.ts.map +1 -0
- package/dist/teams/calendar.d.ts +57 -0
- package/dist/teams/calendar.d.ts.map +1 -0
- package/dist/teams/chat-actions.d.ts +20 -0
- package/dist/teams/chat-actions.d.ts.map +1 -0
- package/dist/teams/chat-rooms.d.ts +42 -0
- package/dist/teams/chat-rooms.d.ts.map +1 -0
- package/dist/teams/chat-view.d.ts +56 -0
- package/dist/teams/chat-view.d.ts.map +1 -0
- package/dist/teams/chat.d.ts +19 -3
- package/dist/teams/chat.d.ts.map +1 -1
- package/dist/teams/chats.d.ts +52 -0
- package/dist/teams/chats.d.ts.map +1 -0
- package/dist/teams/ics-timezone.d.ts +17 -0
- package/dist/teams/ics-timezone.d.ts.map +1 -0
- package/dist/teams/ics.d.ts +20 -0
- package/dist/teams/ics.d.ts.map +1 -0
- package/dist/teams/index.cjs +7252 -2926
- package/dist/teams/index.d.ts +22 -0
- package/dist/teams/index.d.ts.map +1 -1
- package/dist/teams/index.mjs +7162 -2927
- package/dist/teams/meeting-actions.d.ts +31 -0
- package/dist/teams/meeting-actions.d.ts.map +1 -0
- package/dist/teams/meeting-exceptions.d.ts +28 -0
- package/dist/teams/meeting-exceptions.d.ts.map +1 -0
- package/dist/teams/meeting-reminders.d.ts +13 -0
- package/dist/teams/meeting-reminders.d.ts.map +1 -0
- package/dist/teams/meetings.d.ts +71 -0
- package/dist/teams/meetings.d.ts.map +1 -0
- package/dist/teams/mention-text.d.ts +11 -0
- package/dist/teams/mention-text.d.ts.map +1 -0
- package/dist/teams/mentions.d.ts +68 -0
- package/dist/teams/mentions.d.ts.map +1 -0
- package/dist/teams/model.d.ts +7 -0
- package/dist/teams/model.d.ts.map +1 -1
- package/dist/teams/notifications.d.ts +21 -0
- package/dist/teams/notifications.d.ts.map +1 -0
- package/dist/teams/recurrence.d.ts +18 -0
- package/dist/teams/recurrence.d.ts.map +1 -0
- package/dist/teams/roster.d.ts +12 -0
- package/dist/teams/roster.d.ts.map +1 -0
- package/dist/teams/server-config.d.ts +23 -2
- package/dist/teams/server-config.d.ts.map +1 -1
- package/dist/teams/server-session.d.ts +19 -0
- package/dist/teams/server-session.d.ts.map +1 -0
- package/dist/teams/shared-chat.d.ts +83 -0
- package/dist/teams/shared-chat.d.ts.map +1 -0
- package/dist/teams/store.d.ts +58 -4
- package/dist/teams/store.d.ts.map +1 -1
- package/dist/teams/sync-transport.d.ts +12 -0
- package/dist/teams/sync-transport.d.ts.map +1 -0
- package/dist/teams/time-zone.d.ts +32 -0
- package/dist/teams/time-zone.d.ts.map +1 -0
- package/dist/teams/view.d.ts +3 -0
- package/dist/teams/view.d.ts.map +1 -1
- package/dist/teams/workspace.d.ts +13 -2
- package/dist/teams/workspace.d.ts.map +1 -1
- package/dist/visio/edit-connector-follow.d.ts +15 -0
- package/dist/visio/edit-connector-follow.d.ts.map +1 -0
- package/dist/visio/edit-connector-obstacles.d.ts +9 -3
- package/dist/visio/edit-connector-obstacles.d.ts.map +1 -1
- package/dist/visio/edit-connector-reroute.d.ts.map +1 -1
- package/dist/visio/edit-connector.d.ts.map +1 -1
- package/dist/visio/edit-master-add.d.ts +37 -0
- package/dist/visio/edit-master-add.d.ts.map +1 -0
- package/dist/visio/edit-master-drop.d.ts +6 -0
- package/dist/visio/edit-master-drop.d.ts.map +1 -1
- package/dist/visio/edit-recalculate-index.d.ts +5 -0
- package/dist/visio/edit-recalculate-index.d.ts.map +1 -1
- package/dist/visio/edit-recalculate-values.d.ts.map +1 -1
- package/dist/visio/edit-stencil-connector-layout.d.ts +2 -0
- package/dist/visio/edit-stencil-connector-layout.d.ts.map +1 -1
- package/dist/visio/edit-stencil-connector.d.ts +1 -0
- package/dist/visio/edit-stencil-connector.d.ts.map +1 -1
- package/dist/visio/edit-stencil-import.d.ts +10 -0
- package/dist/visio/edit-stencil-import.d.ts.map +1 -0
- package/dist/visio/edit-stencil-line.d.ts +29 -0
- package/dist/visio/edit-stencil-line.d.ts.map +1 -0
- package/dist/visio/edit-stencil-master.d.ts +3 -8
- package/dist/visio/edit-stencil-master.d.ts.map +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/formula-evaluate.d.ts.map +1 -1
- package/dist/visio/formula-math-functions.d.ts +11 -0
- package/dist/visio/formula-math-functions.d.ts.map +1 -0
- package/dist/visio/formula-text-functions.d.ts +23 -0
- package/dist/visio/formula-text-functions.d.ts.map +1 -0
- package/dist/visio/formula.d.ts.map +1 -1
- package/dist/visio/index.cjs +2552 -1833
- package/dist/visio/index.d.ts +1 -0
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +2552 -1834
- package/dist/visio/parser.d.ts +6 -0
- package/dist/visio/parser.d.ts.map +1 -1
- package/dist/visio/stencil-file.d.ts +14 -0
- package/dist/visio/stencil-file.d.ts.map +1 -0
- package/dist/visio/ui/index.cjs +2398 -1679
- package/dist/visio/ui/index.mjs +2398 -1680
- package/dist/visio/ui/master-drop.d.ts +10 -0
- package/dist/visio/ui/master-drop.d.ts.map +1 -1
- package/dist/xlsx/edit/cell-values.d.ts.map +1 -1
- package/dist/xlsx/edit/clipboard-html-parse.d.ts +4 -0
- package/dist/xlsx/edit/clipboard-html-parse.d.ts.map +1 -1
- package/dist/xlsx/edit/data-table.d.ts +38 -0
- package/dist/xlsx/edit/data-table.d.ts.map +1 -0
- package/dist/xlsx/edit/drawings.d.ts.map +1 -1
- package/dist/xlsx/edit/goal-seek.d.ts +30 -0
- package/dist/xlsx/edit/goal-seek.d.ts.map +1 -0
- package/dist/xlsx/edit/goal-solver.d.ts +20 -0
- package/dist/xlsx/edit/goal-solver.d.ts.map +1 -0
- package/dist/xlsx/edit/history.d.ts +1 -1
- package/dist/xlsx/edit/history.d.ts.map +1 -1
- package/dist/xlsx/edit/index.d.ts +5 -0
- package/dist/xlsx/edit/index.d.ts.map +1 -1
- package/dist/xlsx/edit/input-text.d.ts.map +1 -1
- package/dist/xlsx/edit/pivots.d.ts +2 -1
- package/dist/xlsx/edit/pivots.d.ts.map +1 -1
- package/dist/xlsx/edit/scenarios.d.ts +41 -0
- package/dist/xlsx/edit/scenarios.d.ts.map +1 -0
- package/dist/xlsx/edit/session.d.ts.map +1 -1
- package/dist/xlsx/edit/slicers.d.ts +34 -0
- package/dist/xlsx/edit/slicers.d.ts.map +1 -0
- package/dist/xlsx/edit/table-edits.d.ts.map +1 -1
- package/dist/xlsx/edit/timelines.d.ts +26 -0
- package/dist/xlsx/edit/timelines.d.ts.map +1 -0
- package/dist/xlsx/edit/types.d.ts +39 -0
- package/dist/xlsx/edit/types.d.ts.map +1 -1
- package/dist/xlsx/formula/context.d.ts +13 -0
- package/dist/xlsx/formula/context.d.ts.map +1 -1
- package/dist/xlsx/formula/engine.d.ts.map +1 -1
- package/dist/xlsx/formula/evaluator.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/helpers.d.ts +3 -2
- package/dist/xlsx/formula/functions/helpers.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/text-regex.d.ts +8 -0
- package/dist/xlsx/formula/functions/text-regex.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/text.d.ts.map +1 -1
- package/dist/xlsx/formula/functions/wildcard.d.ts +8 -0
- package/dist/xlsx/formula/functions/wildcard.d.ts.map +1 -0
- package/dist/xlsx/formula/values.d.ts +9 -0
- package/dist/xlsx/formula/values.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +9230 -3233
- package/dist/xlsx/index.d.ts +1 -0
- package/dist/xlsx/index.d.ts.map +1 -1
- package/dist/xlsx/index.mjs +9146 -3233
- package/dist/xlsx/layout/chart-view.d.ts.map +1 -1
- package/dist/xlsx/layout/header-footer-edit.d.ts +16 -0
- package/dist/xlsx/layout/header-footer-edit.d.ts.map +1 -0
- package/dist/xlsx/layout/index.d.ts +3 -0
- package/dist/xlsx/layout/index.d.ts.map +1 -1
- package/dist/xlsx/layout/page-break-view.d.ts +39 -0
- package/dist/xlsx/layout/page-break-view.d.ts.map +1 -0
- package/dist/xlsx/layout/page-view.d.ts +69 -0
- package/dist/xlsx/layout/page-view.d.ts.map +1 -0
- package/dist/xlsx/layout/ref-evaluator.d.ts.map +1 -1
- package/dist/xlsx/load/index.cjs +4528 -1707
- package/dist/xlsx/load/index.mjs +4527 -1706
- package/dist/xlsx/model-pivots.d.ts +88 -2
- package/dist/xlsx/model-pivots.d.ts.map +1 -1
- package/dist/xlsx/model-slicers.d.ts +146 -0
- package/dist/xlsx/model-slicers.d.ts.map +1 -0
- package/dist/xlsx/model-whatif.d.ts +51 -0
- package/dist/xlsx/model-whatif.d.ts.map +1 -0
- package/dist/xlsx/model.d.ts +26 -1
- package/dist/xlsx/model.d.ts.map +1 -1
- package/dist/xlsx/pivot/admission.d.ts.map +1 -1
- package/dist/xlsx/pivot/aggregate.d.ts +15 -6
- package/dist/xlsx/pivot/aggregate.d.ts.map +1 -1
- package/dist/xlsx/pivot/axes.d.ts +6 -0
- package/dist/xlsx/pivot/axes.d.ts.map +1 -0
- package/dist/xlsx/pivot/cache-xml.d.ts.map +1 -1
- package/dist/xlsx/pivot/columns.d.ts +48 -0
- package/dist/xlsx/pivot/columns.d.ts.map +1 -0
- package/dist/xlsx/pivot/data.d.ts +9 -3
- package/dist/xlsx/pivot/data.d.ts.map +1 -1
- package/dist/xlsx/pivot/date-axes.d.ts +12 -0
- package/dist/xlsx/pivot/date-axes.d.ts.map +1 -0
- package/dist/xlsx/pivot/date-group-read.d.ts +11 -0
- package/dist/xlsx/pivot/date-group-read.d.ts.map +1 -0
- package/dist/xlsx/pivot/date-groups.d.ts +60 -0
- package/dist/xlsx/pivot/date-groups.d.ts.map +1 -0
- package/dist/xlsx/pivot/date-read.d.ts +10 -0
- package/dist/xlsx/pivot/date-read.d.ts.map +1 -0
- package/dist/xlsx/pivot/dates.d.ts +17 -0
- package/dist/xlsx/pivot/dates.d.ts.map +1 -0
- package/dist/xlsx/pivot/group-read.d.ts +9 -0
- package/dist/xlsx/pivot/group-read.d.ts.map +1 -0
- package/dist/xlsx/pivot/groups.d.ts +31 -0
- package/dist/xlsx/pivot/groups.d.ts.map +1 -0
- package/dist/xlsx/pivot/hierarchy.d.ts +4 -1
- package/dist/xlsx/pivot/hierarchy.d.ts.map +1 -1
- package/dist/xlsx/pivot/index.d.ts +7 -0
- package/dist/xlsx/pivot/index.d.ts.map +1 -1
- package/dist/xlsx/pivot/item-filters-read.d.ts +7 -0
- package/dist/xlsx/pivot/item-filters-read.d.ts.map +1 -0
- package/dist/xlsx/pivot/item-filters.d.ts +23 -0
- package/dist/xlsx/pivot/item-filters.d.ts.map +1 -0
- package/dist/xlsx/pivot/measures.d.ts +6 -4
- package/dist/xlsx/pivot/measures.d.ts.map +1 -1
- package/dist/xlsx/pivot/nested.d.ts +8 -0
- package/dist/xlsx/pivot/nested.d.ts.map +1 -0
- package/dist/xlsx/pivot/page-filter-admission.d.ts.map +1 -1
- package/dist/xlsx/pivot/page-filter.d.ts.map +1 -1
- package/dist/xlsx/pivot/read.d.ts +2 -1
- package/dist/xlsx/pivot/read.d.ts.map +1 -1
- package/dist/xlsx/pivot/subtotal-read.d.ts +9 -0
- package/dist/xlsx/pivot/subtotal-read.d.ts.map +1 -0
- package/dist/xlsx/pivot/subtotals.d.ts +23 -0
- package/dist/xlsx/pivot/subtotals.d.ts.map +1 -0
- package/dist/xlsx/pivot/table-xml.d.ts +1 -1
- package/dist/xlsx/pivot/table-xml.d.ts.map +1 -1
- package/dist/xlsx/pivot/values-axis.d.ts +2 -2
- package/dist/xlsx/pivot/values-axis.d.ts.map +1 -1
- package/dist/xlsx/read/chart-ex.d.ts +9 -0
- package/dist/xlsx/read/chart-ex.d.ts.map +1 -0
- package/dist/xlsx/read/chart.d.ts.map +1 -1
- package/dist/xlsx/read/drawing.d.ts.map +1 -1
- package/dist/xlsx/read/load.d.ts.map +1 -1
- package/dist/xlsx/read/package.d.ts +2 -1
- package/dist/xlsx/read/package.d.ts.map +1 -1
- package/dist/xlsx/read/scenarios.d.ts +4 -0
- package/dist/xlsx/read/scenarios.d.ts.map +1 -0
- package/dist/xlsx/read/sheet-data.d.ts.map +1 -1
- package/dist/xlsx/read/sheet-props.d.ts.map +1 -1
- package/dist/xlsx/read/tables.d.ts +3 -0
- package/dist/xlsx/read/tables.d.ts.map +1 -1
- package/dist/xlsx/read/worksheet.d.ts.map +1 -1
- package/dist/xlsx/slicer/book.d.ts +16 -0
- package/dist/xlsx/slicer/book.d.ts.map +1 -0
- package/dist/xlsx/slicer/frame.d.ts +14 -0
- package/dist/xlsx/slicer/frame.d.ts.map +1 -0
- package/dist/xlsx/slicer/index.d.ts +10 -0
- package/dist/xlsx/slicer/index.d.ts.map +1 -0
- package/dist/xlsx/slicer/items.d.ts +30 -0
- package/dist/xlsx/slicer/items.d.ts.map +1 -0
- package/dist/xlsx/slicer/layout.d.ts +67 -0
- package/dist/xlsx/slicer/layout.d.ts.map +1 -0
- package/dist/xlsx/slicer/read-slicers.d.ts +11 -0
- package/dist/xlsx/slicer/read-slicers.d.ts.map +1 -0
- package/dist/xlsx/slicer/read-timelines.d.ts +5 -0
- package/dist/xlsx/slicer/read-timelines.d.ts.map +1 -0
- package/dist/xlsx/slicer/read.d.ts +26 -0
- package/dist/xlsx/slicer/read.d.ts.map +1 -0
- package/dist/xlsx/slicer/select.d.ts +10 -0
- package/dist/xlsx/slicer/select.d.ts.map +1 -0
- package/dist/xlsx/slicer/styles.d.ts +36 -0
- package/dist/xlsx/slicer/styles.d.ts.map +1 -0
- package/dist/xlsx/slicer/table-filter.d.ts +28 -0
- package/dist/xlsx/slicer/table-filter.d.ts.map +1 -0
- package/dist/xlsx/slicer/timeline-periods.d.ts +35 -0
- package/dist/xlsx/slicer/timeline-periods.d.ts.map +1 -0
- package/dist/xlsx/slicer/timeline-view.d.ts +60 -0
- package/dist/xlsx/slicer/timeline-view.d.ts.map +1 -0
- package/dist/xlsx/slicer/write-plan.d.ts +31 -0
- package/dist/xlsx/slicer/write-plan.d.ts.map +1 -0
- package/dist/xlsx/slicer/write-timeline.d.ts +7 -0
- package/dist/xlsx/slicer/write-timeline.d.ts.map +1 -0
- package/dist/xlsx/slicer/write-xml.d.ts +17 -0
- package/dist/xlsx/slicer/write-xml.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/i18n/index.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/pivots.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/print-layout.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/i18n/slicers.d.ts +3 -0
- package/dist/xlsx/ui/commands/i18n/slicers.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/i18n/what-if.d.ts +3 -0
- package/dist/xlsx/ui/commands/i18n/what-if.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/icons.d.ts.map +1 -1
- package/dist/xlsx/ui/commands/slicers.d.ts +37 -0
- package/dist/xlsx/ui/commands/slicers.d.ts.map +1 -0
- package/dist/xlsx/ui/commands/what-if.d.ts +4 -0
- package/dist/xlsx/ui/commands/what-if.d.ts.map +1 -0
- package/dist/xlsx/ui/commands.d.ts +2 -0
- package/dist/xlsx/ui/commands.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +4201 -1316
- package/dist/xlsx/ui/index.d.ts +2 -0
- package/dist/xlsx/ui/index.d.ts.map +1 -1
- package/dist/xlsx/ui/index.mjs +4196 -1317
- package/dist/xlsx/ui/locales/de/shell.d.ts.map +1 -1
- package/dist/xlsx/ui/locales/en/shell.d.ts.map +1 -1
- package/dist/xlsx/ui/locales/es/shell.d.ts.map +1 -1
- package/dist/xlsx/ui/locales/fr/shell.d.ts.map +1 -1
- package/dist/xlsx/ui/locales/zh-CN/shell.d.ts.map +1 -1
- package/dist/xlsx/ui/ribbon/tabs/review-view.d.ts.map +1 -1
- package/dist/xlsx/write/carried-refs.d.ts.map +1 -1
- package/dist/xlsx/write/drawing.d.ts.map +1 -1
- package/dist/xlsx/write/package-writer.d.ts +2 -0
- package/dist/xlsx/write/package-writer.d.ts.map +1 -1
- package/dist/xlsx/write/save.d.ts.map +1 -1
- package/dist/xlsx/write/scenarios.d.ts +4 -0
- package/dist/xlsx/write/scenarios.d.ts.map +1 -0
- package/dist/xlsx/write/sheet-data.d.ts.map +1 -1
- package/dist/xlsx/write/sheet-parts.d.ts +1 -0
- package/dist/xlsx/write/sheet-parts.d.ts.map +1 -1
- package/dist/xlsx/write/sheet-props.d.ts.map +1 -1
- package/dist/xlsx/write/table-patch.d.ts.map +1 -1
- package/dist/xlsx/write/tables.d.ts.map +1 -1
- package/dist/xlsx/write/worksheet.d.ts.map +1 -1
- package/dist/xml/index.cjs +28 -0
- package/dist/xml/index.mjs +27 -1
- package/dist/xml/namespaces.d.ts +2 -0
- package/dist/xml/namespaces.d.ts.map +1 -1
- package/dist/xml/xml.d.ts +15 -0
- package/dist/xml/xml.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/PptxHandler-RWTOUCLC.mjs +0 -3
- package/dist/PptxHandler-UU4ZCT6H.cjs +0 -12
- package/dist/chunk-KBIJI6P5.mjs +0 -166
- package/dist/pptx/chunks/elements-DmbzOhFu.d.ts.map +0 -1
- package/dist/pptx/chunks/index-BmvOxbsh.d.ts.map +0 -1
package/dist/chart/index.mjs
CHANGED
|
@@ -288,6 +288,669 @@ function niceValueAxisBounds(dataMin, dataMax, targetIntervals = DEFAULT_TARGET_
|
|
|
288
288
|
return { min, max, majorUnit: unit };
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
// chart/number-format-pattern.ts
|
|
292
|
+
var NAMED_FORMAT_COLORS = {
|
|
293
|
+
black: "#000000",
|
|
294
|
+
blue: "#0000FF",
|
|
295
|
+
cyan: "#00FFFF",
|
|
296
|
+
green: "#00FF00",
|
|
297
|
+
magenta: "#FF00FF",
|
|
298
|
+
red: "#FF0000",
|
|
299
|
+
white: "#FFFFFF",
|
|
300
|
+
yellow: "#FFFF00"
|
|
301
|
+
};
|
|
302
|
+
var PLACEHOLDER = /[0#?]/u;
|
|
303
|
+
function parsePattern(code) {
|
|
304
|
+
let scale = 1;
|
|
305
|
+
let scientific = false;
|
|
306
|
+
let color;
|
|
307
|
+
const chars = [];
|
|
308
|
+
let inQuotes = false;
|
|
309
|
+
for (let i = 0; i < code.length; i += 1) {
|
|
310
|
+
const ch = code[i] ?? "";
|
|
311
|
+
if (ch === '"') {
|
|
312
|
+
inQuotes = !inQuotes;
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
315
|
+
if (inQuotes) {
|
|
316
|
+
chars.push({ ch, literal: true });
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (ch === "\\" || ch === "*" || ch === "_") {
|
|
320
|
+
const next = code[i + 1];
|
|
321
|
+
i += 1;
|
|
322
|
+
if (ch === "\\" && next !== void 0) {
|
|
323
|
+
chars.push({ ch: next, literal: true });
|
|
324
|
+
}
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
if (ch === "%") {
|
|
328
|
+
scale *= 100;
|
|
329
|
+
chars.push({ ch, literal: true });
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (ch === "E" && (code[i + 1] === "+" || code[i + 1] === "-")) {
|
|
333
|
+
scientific = true;
|
|
334
|
+
chars.push({ ch: "E", literal: false });
|
|
335
|
+
i += 1;
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (ch === "[") {
|
|
339
|
+
const close = code.indexOf("]", i);
|
|
340
|
+
const token = code.slice(i + 1, close === -1 ? code.length : close);
|
|
341
|
+
const named2 = NAMED_FORMAT_COLORS[token.trim().toLowerCase()];
|
|
342
|
+
if (named2 && color === void 0) {
|
|
343
|
+
color = named2;
|
|
344
|
+
}
|
|
345
|
+
i = close === -1 ? code.length : close;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
chars.push({ ch, literal: false });
|
|
349
|
+
}
|
|
350
|
+
const firstDigit = chars.findIndex((c2) => !c2.literal && PLACEHOLDER.test(c2.ch));
|
|
351
|
+
if (firstDigit === -1) {
|
|
352
|
+
return void 0;
|
|
353
|
+
}
|
|
354
|
+
let lastDigit = firstDigit;
|
|
355
|
+
for (let i = chars.length - 1; i >= firstDigit; i -= 1) {
|
|
356
|
+
const c2 = chars[i];
|
|
357
|
+
if (c2 && !c2.literal && (PLACEHOLDER.test(c2.ch) || c2.ch === "." || c2.ch === "," || c2.ch === "E")) {
|
|
358
|
+
lastDigit = i;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const numeric = chars.slice(firstDigit, lastDigit + 1);
|
|
363
|
+
const prefix = chars.slice(0, firstDigit).map((c2) => c2.ch).join("");
|
|
364
|
+
const suffix = chars.slice(lastDigit + 1).map((c2) => c2.ch).join("");
|
|
365
|
+
let grouped = false;
|
|
366
|
+
let intDigits = 0;
|
|
367
|
+
let required = 0;
|
|
368
|
+
let optional = 0;
|
|
369
|
+
let afterPoint = false;
|
|
370
|
+
let inExponent = false;
|
|
371
|
+
for (let i = 0; i < numeric.length; i += 1) {
|
|
372
|
+
const { ch, literal } = numeric[i] ?? { ch: "", literal: true };
|
|
373
|
+
if (literal) {
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (ch === "E") {
|
|
377
|
+
inExponent = true;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
if (inExponent) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (ch === ".") {
|
|
384
|
+
afterPoint = true;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
if (ch === ",") {
|
|
388
|
+
const next = numeric.slice(i + 1).find((c2) => !c2.literal);
|
|
389
|
+
if (!next || next.ch === "." || !PLACEHOLDER.test(next.ch)) {
|
|
390
|
+
scale /= 1e3;
|
|
391
|
+
} else {
|
|
392
|
+
grouped = true;
|
|
393
|
+
}
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (!PLACEHOLDER.test(ch)) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (afterPoint) {
|
|
400
|
+
if (ch === "0") {
|
|
401
|
+
required += 1;
|
|
402
|
+
} else {
|
|
403
|
+
optional += 1;
|
|
404
|
+
}
|
|
405
|
+
} else if (ch === "0") {
|
|
406
|
+
intDigits += 1;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
prefix,
|
|
411
|
+
suffix,
|
|
412
|
+
intDigits,
|
|
413
|
+
decimals: { required, optional },
|
|
414
|
+
grouped,
|
|
415
|
+
scale,
|
|
416
|
+
scientific,
|
|
417
|
+
color
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function group(intPart) {
|
|
421
|
+
return intPart.replace(/\B(?=(\d{3})+(?!\d))/gu, ",");
|
|
422
|
+
}
|
|
423
|
+
function applyPattern(value, pattern, forcePositive) {
|
|
424
|
+
const scaled = value * pattern.scale;
|
|
425
|
+
const magnitude = forcePositive ? Math.abs(scaled) : scaled;
|
|
426
|
+
if (pattern.scientific) {
|
|
427
|
+
const digits = pattern.decimals.required + pattern.decimals.optional;
|
|
428
|
+
const exponential = magnitude.toExponential(digits);
|
|
429
|
+
const [mantissa = "", exponent = "0"] = exponential.split("e");
|
|
430
|
+
const sign = exponent.startsWith("-") ? "-" : "+";
|
|
431
|
+
const power = Math.abs(Number(exponent)).toString().padStart(2, "0");
|
|
432
|
+
return `${pattern.prefix}${mantissa}E${sign}${power}${pattern.suffix}`;
|
|
433
|
+
}
|
|
434
|
+
const maxDecimals = pattern.decimals.required + pattern.decimals.optional;
|
|
435
|
+
let body = magnitude.toFixed(maxDecimals);
|
|
436
|
+
if (pattern.decimals.optional > 0) {
|
|
437
|
+
body = body.replace(/(\.\d*?)0+$/u, "$1").replace(/\.$/u, "");
|
|
438
|
+
const [, frac = ""] = body.split(".");
|
|
439
|
+
if (frac.length < pattern.decimals.required) {
|
|
440
|
+
body = Number(body).toFixed(pattern.decimals.required);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
const [rawIntPart = "", fracPart] = body.split(".");
|
|
444
|
+
let intPart = rawIntPart;
|
|
445
|
+
const hasMinusChar = intPart.startsWith("-");
|
|
446
|
+
const negative = hasMinusChar && Number(body) !== 0;
|
|
447
|
+
if (hasMinusChar) {
|
|
448
|
+
intPart = intPart.slice(1);
|
|
449
|
+
}
|
|
450
|
+
if (intPart.length < pattern.intDigits) {
|
|
451
|
+
intPart = intPart.padStart(pattern.intDigits, "0");
|
|
452
|
+
}
|
|
453
|
+
if (pattern.intDigits === 0 && intPart === "0" && fracPart !== void 0) {
|
|
454
|
+
intPart = "";
|
|
455
|
+
}
|
|
456
|
+
if (pattern.grouped) {
|
|
457
|
+
intPart = group(intPart);
|
|
458
|
+
}
|
|
459
|
+
const number = fracPart === void 0 ? intPart : `${intPart}.${fracPart}`;
|
|
460
|
+
return `${negative ? "-" : ""}${pattern.prefix}${number}${pattern.suffix}`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// chart/number-format.ts
|
|
464
|
+
var GENERAL = /* @__PURE__ */ new Set(["", "general", "@"]);
|
|
465
|
+
function sections(code) {
|
|
466
|
+
const out = [];
|
|
467
|
+
let current = "";
|
|
468
|
+
let inQuotes = false;
|
|
469
|
+
for (let i = 0; i < code.length; i += 1) {
|
|
470
|
+
const ch = code[i];
|
|
471
|
+
if (ch === '"') {
|
|
472
|
+
inQuotes = !inQuotes;
|
|
473
|
+
current += ch;
|
|
474
|
+
continue;
|
|
475
|
+
}
|
|
476
|
+
if (ch === "\\") {
|
|
477
|
+
current += ch + (code[i + 1] ?? "");
|
|
478
|
+
i += 1;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (ch === ";" && !inQuotes) {
|
|
482
|
+
out.push(current);
|
|
483
|
+
current = "";
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
current += ch;
|
|
487
|
+
}
|
|
488
|
+
out.push(current);
|
|
489
|
+
return out;
|
|
490
|
+
}
|
|
491
|
+
function sectionFor(value, parts) {
|
|
492
|
+
if (parts.length === 1) {
|
|
493
|
+
return { code: parts[0] ?? "", forcePositive: false };
|
|
494
|
+
}
|
|
495
|
+
if (value < 0 && parts[1] !== void 0) {
|
|
496
|
+
return { code: parts[1] ?? "", forcePositive: true };
|
|
497
|
+
}
|
|
498
|
+
if (value === 0 && parts[2] !== void 0) {
|
|
499
|
+
return { code: parts[2] ?? "", forcePositive: false };
|
|
500
|
+
}
|
|
501
|
+
return { code: parts[0] ?? "", forcePositive: false };
|
|
502
|
+
}
|
|
503
|
+
function formatChartNumberWithColor(value, formatCode) {
|
|
504
|
+
if (!Number.isFinite(value)) {
|
|
505
|
+
return void 0;
|
|
506
|
+
}
|
|
507
|
+
const code = (formatCode ?? "").trim();
|
|
508
|
+
if (GENERAL.has(code.toLowerCase())) {
|
|
509
|
+
return void 0;
|
|
510
|
+
}
|
|
511
|
+
if (/(?:^|[^\\"])(?:yy|mm?m|dd?|hh|ss)/iu.test(code) && !/[0#?]/u.test(code)) {
|
|
512
|
+
return void 0;
|
|
513
|
+
}
|
|
514
|
+
const { code: section, forcePositive } = sectionFor(value, sections(code));
|
|
515
|
+
const pattern = parsePattern(section);
|
|
516
|
+
if (!pattern) {
|
|
517
|
+
return void 0;
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
return { text: applyPattern(value, pattern, forcePositive), color: pattern.color };
|
|
521
|
+
} catch {
|
|
522
|
+
return void 0;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function formatChartNumber(value, formatCode) {
|
|
526
|
+
return formatChartNumberWithColor(value, formatCode)?.text;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// chart/auto-title.ts
|
|
530
|
+
var CHART_AUTO_TITLE = "Chart Title";
|
|
531
|
+
var CHARTEX_ONLY_TYPES = /* @__PURE__ */ new Set([
|
|
532
|
+
"waterfall",
|
|
533
|
+
"funnel",
|
|
534
|
+
"treemap",
|
|
535
|
+
"sunburst",
|
|
536
|
+
"boxWhisker",
|
|
537
|
+
"histogram",
|
|
538
|
+
"regionMap"
|
|
539
|
+
]);
|
|
540
|
+
function isChartexOnlyType(chartType) {
|
|
541
|
+
return CHARTEX_ONLY_TYPES.has(chartType);
|
|
542
|
+
}
|
|
543
|
+
function impliesAutoTitle(input) {
|
|
544
|
+
return !(input.hasTitle !== void 0 || input.autoTitleDeleted === true || isChartexOnlyType(input.chartType) || input.seriesNames.length !== 1 || !input.seriesNames[0]);
|
|
545
|
+
}
|
|
546
|
+
function resolveAutoTitleText(input) {
|
|
547
|
+
if (!input.hasTitle) return void 0;
|
|
548
|
+
if (input.title) return input.title;
|
|
549
|
+
if (!isChartexOnlyType(input.chartType) && input.seriesNames.length === 1)
|
|
550
|
+
return input.seriesNames[0] || void 0;
|
|
551
|
+
return input.seriesNames.length > 0 ? CHART_AUTO_TITLE : void 0;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// chart/axis-format.ts
|
|
555
|
+
function formatCompactAxisValue(value, formatCode) {
|
|
556
|
+
const formatted = formatChartNumber(value, formatCode);
|
|
557
|
+
if (formatted !== void 0) return formatted;
|
|
558
|
+
if (Math.abs(value) >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
|
|
559
|
+
if (Math.abs(value) >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
|
|
560
|
+
if (Number.isInteger(value)) return String(value);
|
|
561
|
+
return value.toFixed(1);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// chart/bubble-radius.ts
|
|
565
|
+
function computeBubbleRadius(sizeVal, maxBubble, medianRadius, options) {
|
|
566
|
+
const scale = (options?.bubbleScale ?? 100) / 100;
|
|
567
|
+
if (sizeVal === void 0) return medianRadius * scale;
|
|
568
|
+
const denom = maxBubble > 0 ? maxBubble : 1;
|
|
569
|
+
const magnitude = Math.abs(sizeVal);
|
|
570
|
+
const ratio = (options?.sizeRepresents ?? "w") === "area" ? Math.sqrt(magnitude) / Math.sqrt(denom) : magnitude / denom;
|
|
571
|
+
return medianRadius * scale * 0.5 + ratio * medianRadius * scale * 1.5;
|
|
572
|
+
}
|
|
573
|
+
function maxBubbleSize(sizes) {
|
|
574
|
+
return sizes.length > 0 ? Math.max(1, ...sizes.map(Math.abs)) : 1;
|
|
575
|
+
}
|
|
576
|
+
function medianBubbleRadius(plotWidth, plotHeight) {
|
|
577
|
+
return Math.min(plotWidth, plotHeight) * 0.04;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// chart/stock-candles.ts
|
|
581
|
+
var STOCK_DEFAULT_UP_FILL = "#FFFFFF";
|
|
582
|
+
var STOCK_DEFAULT_DOWN_FILL = "#404040";
|
|
583
|
+
var STOCK_DEFAULT_WICK_COLOR = "#334155";
|
|
584
|
+
var STOCK_TICK_WIDTH = 1.5;
|
|
585
|
+
function stockSlots(count, closeLast = false) {
|
|
586
|
+
if (count < 3) return void 0;
|
|
587
|
+
const four = count >= 4;
|
|
588
|
+
return {
|
|
589
|
+
...four ? { open: 0 } : {},
|
|
590
|
+
high: four ? 1 : 0,
|
|
591
|
+
low: four ? 2 : 1,
|
|
592
|
+
close: closeLast ? count - 1 : four ? 3 : 2
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
var present = (v) => v !== null && v !== void 0;
|
|
596
|
+
function stockCandle(input) {
|
|
597
|
+
const { high, low, close, open, x, band, y } = input;
|
|
598
|
+
if (!present(high) || !present(low)) return void 0;
|
|
599
|
+
const candleWidth = band * (input.bodyShare ?? 0.5);
|
|
600
|
+
const candle = { wick: { x, y1: y(high), y2: y(low) } };
|
|
601
|
+
if (input.hasOpen && present(open) && present(close)) {
|
|
602
|
+
const openY = y(open);
|
|
603
|
+
const closeY = y(close);
|
|
604
|
+
candle.body = {
|
|
605
|
+
x: x - candleWidth / 2,
|
|
606
|
+
y: Math.min(openY, closeY),
|
|
607
|
+
w: candleWidth,
|
|
608
|
+
h: Math.max(Math.abs(openY - closeY), 1),
|
|
609
|
+
up: close >= open
|
|
610
|
+
};
|
|
611
|
+
} else if (present(close)) {
|
|
612
|
+
candle.tick = {
|
|
613
|
+
x1: x,
|
|
614
|
+
x2: x + Math.max(candleWidth * 0.4, 4),
|
|
615
|
+
y: y(close)
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return candle;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// chart/treemap-squarify.ts
|
|
622
|
+
function worstAspectRatio(areas, side) {
|
|
623
|
+
const sum = areas.reduce((total, area) => total + area, 0);
|
|
624
|
+
const max = Math.max(...areas);
|
|
625
|
+
const min = Math.min(...areas);
|
|
626
|
+
const sideSq = side * side;
|
|
627
|
+
const sumSq = sum * sum;
|
|
628
|
+
return Math.max(sideSq * max / sumSq, sumSq / (sideSq * min));
|
|
629
|
+
}
|
|
630
|
+
function squarify(nodes, box) {
|
|
631
|
+
const sorted = [...nodes].sort((a2, b) => b.weight - a2.weight);
|
|
632
|
+
const total = sorted.reduce((sum, node) => sum + node.weight, 0);
|
|
633
|
+
const scale = total > 0 ? box.w * box.h / total : box.w * box.h / sorted.length;
|
|
634
|
+
const items = sorted.map((node) => ({ node, area: (total > 0 ? node.weight : 1) * scale }));
|
|
635
|
+
const result = [];
|
|
636
|
+
let rect2 = { ...box };
|
|
637
|
+
let remaining = items;
|
|
638
|
+
for (let first2 = remaining[0]; first2 !== void 0; first2 = remaining[0]) {
|
|
639
|
+
const side = Math.min(rect2.w, rect2.h);
|
|
640
|
+
let row = [first2];
|
|
641
|
+
let rowAreas = [first2.area];
|
|
642
|
+
let worst = worstAspectRatio(rowAreas, side);
|
|
643
|
+
let cursor = 1;
|
|
644
|
+
for (let next = remaining[cursor]; next !== void 0; next = remaining[cursor]) {
|
|
645
|
+
const candidateAreas = [...rowAreas, next.area];
|
|
646
|
+
const candidateWorst = worstAspectRatio(candidateAreas, side);
|
|
647
|
+
if (candidateWorst > worst) {
|
|
648
|
+
break;
|
|
649
|
+
}
|
|
650
|
+
row = [...row, next];
|
|
651
|
+
rowAreas = candidateAreas;
|
|
652
|
+
worst = candidateWorst;
|
|
653
|
+
cursor++;
|
|
654
|
+
}
|
|
655
|
+
const rowTotalArea = rowAreas.reduce((sum, area) => sum + area, 0);
|
|
656
|
+
const thickness = side > 0 ? rowTotalArea / side : 0;
|
|
657
|
+
const layoutVertically = rect2.w >= rect2.h;
|
|
658
|
+
let offset = layoutVertically ? rect2.y : rect2.x;
|
|
659
|
+
for (const item of row) {
|
|
660
|
+
const length = thickness > 0 ? item.area / thickness : 0;
|
|
661
|
+
if (layoutVertically) {
|
|
662
|
+
result.push([item.node, { x: rect2.x, y: offset, w: thickness, h: length }]);
|
|
663
|
+
} else {
|
|
664
|
+
result.push([item.node, { x: offset, y: rect2.y, w: length, h: thickness }]);
|
|
665
|
+
}
|
|
666
|
+
offset += length;
|
|
667
|
+
}
|
|
668
|
+
rect2 = layoutVertically ? { ...rect2, x: rect2.x + thickness, w: rect2.w - thickness } : { ...rect2, y: rect2.y + thickness, h: rect2.h - thickness };
|
|
669
|
+
remaining = remaining.slice(row.length);
|
|
670
|
+
}
|
|
671
|
+
return result;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// chart/hierarchy.ts
|
|
675
|
+
function normalizeLevels(levels, pointCount) {
|
|
676
|
+
return levels.map((level) => {
|
|
677
|
+
let previous = "";
|
|
678
|
+
return Array.from({ length: pointCount }, (_, index) => {
|
|
679
|
+
const label = level[index]?.trim() ?? "";
|
|
680
|
+
if (label) previous = label;
|
|
681
|
+
return label || previous;
|
|
682
|
+
});
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
function findOrAddParent(children2, label, colorIndex, parentLabelLayout) {
|
|
686
|
+
const existing = children2.find((child2) => child2.children && child2.label === label);
|
|
687
|
+
if (existing?.children) return existing;
|
|
688
|
+
const parent = { label, weight: 0, children: [], colorIndex, parentLabelLayout };
|
|
689
|
+
children2.push(parent);
|
|
690
|
+
return parent;
|
|
691
|
+
}
|
|
692
|
+
function buildSeriesHierarchy(series, seriesIndex, categoryLabels, categoryLevels2, colorStride) {
|
|
693
|
+
const pointCount = series.values.length;
|
|
694
|
+
const levels = normalizeLevels(categoryLevels2 ?? [], pointCount);
|
|
695
|
+
const layout = series.parentLabelLayout ?? "banner";
|
|
696
|
+
const roots = [];
|
|
697
|
+
for (let pointIndex = 0; pointIndex < pointCount; pointIndex++) {
|
|
698
|
+
let children2 = roots;
|
|
699
|
+
for (let levelIndex = levels.length - 1; levelIndex >= 1; levelIndex--) {
|
|
700
|
+
const label = levels[levelIndex]?.[pointIndex] || `Group ${levelIndex}`;
|
|
701
|
+
children2 = findOrAddParent(children2, label, pointIndex, layout).children;
|
|
702
|
+
}
|
|
703
|
+
children2.push({
|
|
704
|
+
label: levels[0]?.[pointIndex] || categoryLabels[pointIndex] || String(pointIndex + 1),
|
|
705
|
+
weight: Math.abs(series.values[pointIndex] ?? 0),
|
|
706
|
+
seriesIndex,
|
|
707
|
+
pointIndex,
|
|
708
|
+
colorIndex: seriesIndex * colorStride + pointIndex,
|
|
709
|
+
parentLabelLayout: layout
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
return roots;
|
|
713
|
+
}
|
|
714
|
+
function aggregate(node) {
|
|
715
|
+
if (node.children) node.weight = node.children.reduce((sum, child2) => sum + aggregate(child2), 0);
|
|
716
|
+
return node.weight;
|
|
717
|
+
}
|
|
718
|
+
function propagateColor(node, colorIndex) {
|
|
719
|
+
node.colorIndex = colorIndex;
|
|
720
|
+
for (const child2 of node.children ?? []) propagateColor(child2, colorIndex);
|
|
721
|
+
}
|
|
722
|
+
function buildHierarchyRoots(series, categoryLabels, categoryLevels2) {
|
|
723
|
+
const colorStride = Math.max(categoryLabels.length, ...series.map((s) => s.values.length), 1);
|
|
724
|
+
let roots = series.flatMap(
|
|
725
|
+
(s, index) => buildSeriesHierarchy(s, index, categoryLabels, categoryLevels2, colorStride)
|
|
726
|
+
);
|
|
727
|
+
if (series.length > 1)
|
|
728
|
+
roots = series.map((s, index) => ({
|
|
729
|
+
label: s.name,
|
|
730
|
+
weight: 0,
|
|
731
|
+
children: buildSeriesHierarchy(s, index, categoryLabels, categoryLevels2, colorStride),
|
|
732
|
+
colorIndex: index * colorStride,
|
|
733
|
+
parentLabelLayout: s.parentLabelLayout ?? "banner"
|
|
734
|
+
}));
|
|
735
|
+
for (const root of roots) aggregate(root);
|
|
736
|
+
roots.forEach((root, index) => propagateColor(root, index));
|
|
737
|
+
return roots;
|
|
738
|
+
}
|
|
739
|
+
function hierarchyBranchLabels(series, categoryLabels, categoryLevels2) {
|
|
740
|
+
if (series.length > 1) return series.map((s) => s.name);
|
|
741
|
+
if (categoryLevels2 && categoryLevels2.length > 1) {
|
|
742
|
+
const pointCount = series[0]?.values.length ?? categoryLabels.length;
|
|
743
|
+
const topLevel = normalizeLevels(categoryLevels2, pointCount).at(-1) ?? [];
|
|
744
|
+
const seen = [];
|
|
745
|
+
for (const label of topLevel) if (!seen.includes(label)) seen.push(label);
|
|
746
|
+
return seen;
|
|
747
|
+
}
|
|
748
|
+
return [...categoryLabels];
|
|
749
|
+
}
|
|
750
|
+
var BANNER_HEIGHT = 16;
|
|
751
|
+
function layoutTreemap(nodes, box) {
|
|
752
|
+
const cells = [];
|
|
753
|
+
for (const [node, allocation] of squarify(nodes, box)) {
|
|
754
|
+
const cell = {
|
|
755
|
+
x: allocation.x + 1,
|
|
756
|
+
y: allocation.y + 1,
|
|
757
|
+
w: Math.max(allocation.w - 2, 1),
|
|
758
|
+
h: Math.max(allocation.h - 2, 1)
|
|
759
|
+
};
|
|
760
|
+
if (node.children) {
|
|
761
|
+
const showParent = node.parentLabelLayout !== "none" && cell.w > 28 && cell.h > 16;
|
|
762
|
+
if (showParent)
|
|
763
|
+
cells.push({ kind: "parent", label: node.label, x: cell.x + 4, y: cell.y + 11 });
|
|
764
|
+
const banner = showParent && node.parentLabelLayout === "banner" ? BANNER_HEIGHT : 0;
|
|
765
|
+
cells.push(
|
|
766
|
+
...layoutTreemap(node.children, {
|
|
767
|
+
...cell,
|
|
768
|
+
y: cell.y + banner,
|
|
769
|
+
h: Math.max(cell.h - banner, 1)
|
|
770
|
+
})
|
|
771
|
+
);
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
cells.push({
|
|
775
|
+
kind: "leaf",
|
|
776
|
+
...cell,
|
|
777
|
+
label: node.label,
|
|
778
|
+
colorIndex: node.colorIndex,
|
|
779
|
+
seriesIndex: node.seriesIndex ?? 0,
|
|
780
|
+
pointIndex: node.pointIndex ?? 0,
|
|
781
|
+
labelFits: cell.w > 30 && cell.h > 14,
|
|
782
|
+
labelSize: Math.min(10, cell.h * 0.3)
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
return cells;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// chart/sunburst-arcs.ts
|
|
789
|
+
function arcLabelPlacement(cx2, cy, radius, startAngle, endAngle) {
|
|
790
|
+
const midAngle = (startAngle + endAngle) / 2;
|
|
791
|
+
let rotation = midAngle * 180 / Math.PI + 90;
|
|
792
|
+
if (rotation > 90 && rotation < 270) rotation -= 180;
|
|
793
|
+
return {
|
|
794
|
+
labelX: cx2 + radius * Math.cos(midAngle),
|
|
795
|
+
labelY: cy + radius * Math.sin(midAngle),
|
|
796
|
+
labelRotation: rotation
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
function sunburstArcPath(cx2, cy, innerRadius, outerRadius, startAngle, endAngle) {
|
|
800
|
+
const sweep = endAngle - startAngle;
|
|
801
|
+
const largeArc = sweep > Math.PI ? 1 : 0;
|
|
802
|
+
const x1 = cx2 + outerRadius * Math.cos(startAngle);
|
|
803
|
+
const y1 = cy + outerRadius * Math.sin(startAngle);
|
|
804
|
+
const x2 = cx2 + outerRadius * Math.cos(endAngle);
|
|
805
|
+
const y2 = cy + outerRadius * Math.sin(endAngle);
|
|
806
|
+
const x3 = cx2 + innerRadius * Math.cos(endAngle);
|
|
807
|
+
const y3 = cy + innerRadius * Math.sin(endAngle);
|
|
808
|
+
const x4 = cx2 + innerRadius * Math.cos(startAngle);
|
|
809
|
+
const y4 = cy + innerRadius * Math.sin(startAngle);
|
|
810
|
+
return `M ${x1} ${y1} A ${outerRadius} ${outerRadius} 0 ${largeArc} 1 ${x2} ${y2} L ${x3} ${y3} A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${x4} ${y4} Z`;
|
|
811
|
+
}
|
|
812
|
+
function computeSunburstArcs(series, cx2, cy, maxR) {
|
|
813
|
+
const seriesCount = Math.max(series.length, 1);
|
|
814
|
+
const ringWidth = maxR / (seriesCount + 0.5);
|
|
815
|
+
const out = [];
|
|
816
|
+
series.forEach((s, si) => {
|
|
817
|
+
const values = s.values;
|
|
818
|
+
const innerRadius = ringWidth * (si + 0.5);
|
|
819
|
+
const outerRadius = ringWidth * (si + 1.5);
|
|
820
|
+
const total = values.reduce((acc, value) => acc + Math.abs(value), 0) || 1;
|
|
821
|
+
let startAngle = -Math.PI / 2;
|
|
822
|
+
for (let pointIndex = 0; pointIndex < values.length; pointIndex++) {
|
|
823
|
+
const endAngle = startAngle + Math.abs(values[pointIndex] ?? 0) / total * Math.PI * 2;
|
|
824
|
+
out.push({
|
|
825
|
+
d: sunburstArcPath(cx2, cy, innerRadius, outerRadius, startAngle, endAngle),
|
|
826
|
+
colorIndex: pointIndex,
|
|
827
|
+
opacity: Math.max(0.1, 0.9 - si * 0.1),
|
|
828
|
+
pointIndex,
|
|
829
|
+
level: si,
|
|
830
|
+
...arcLabelPlacement(cx2, cy, (innerRadius + outerRadius) / 2, startAngle, endAngle)
|
|
831
|
+
});
|
|
832
|
+
startAngle = endAngle;
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
return out;
|
|
836
|
+
}
|
|
837
|
+
function hierarchyKey(levels, level, index) {
|
|
838
|
+
return levels.slice(level).map((labels) => labels[index] ?? "").join("\0");
|
|
839
|
+
}
|
|
840
|
+
function computeHierarchicalSunburstArcs(categoryLevels2, values, cx2, cy, maxR) {
|
|
841
|
+
const levels = categoryLevels2.filter((level) => level.length > 0);
|
|
842
|
+
const leafCount = Math.max(values.length, ...levels.map((level) => level.length), 0);
|
|
843
|
+
if (levels.length === 0 || leafCount === 0) return [];
|
|
844
|
+
const rawWeights = Array.from({ length: leafCount }, (_, index) => Math.abs(values[index] ?? 0));
|
|
845
|
+
const weights = rawWeights.some((value) => value !== 0) ? rawWeights : rawWeights.map(() => 1);
|
|
846
|
+
const total = weights.reduce((sum, value) => sum + value, 0);
|
|
847
|
+
const prefix = [0];
|
|
848
|
+
for (const weight of weights) prefix.push((prefix[prefix.length - 1] ?? 0) + weight);
|
|
849
|
+
const ringWidth = maxR / (levels.length + 0.5);
|
|
850
|
+
const rootLabels = levels[levels.length - 1] ?? [];
|
|
851
|
+
const rootColors = /* @__PURE__ */ new Map();
|
|
852
|
+
const out = [];
|
|
853
|
+
for (let level = levels.length - 1; level >= 0; level--) {
|
|
854
|
+
const ringIndex = levels.length - 1 - level;
|
|
855
|
+
const innerRadius = ringWidth * (ringIndex + 0.5);
|
|
856
|
+
const outerRadius = ringWidth * (ringIndex + 1.5);
|
|
857
|
+
let start = 0;
|
|
858
|
+
while (start < leafCount) {
|
|
859
|
+
const key = hierarchyKey(levels, level, start);
|
|
860
|
+
let end = start + 1;
|
|
861
|
+
while (end < leafCount && hierarchyKey(levels, level, end) === key) end++;
|
|
862
|
+
const startAngle = -Math.PI / 2 + (prefix[start] ?? 0) / total * Math.PI * 2;
|
|
863
|
+
const endAngle = -Math.PI / 2 + (prefix[end] ?? 0) / total * Math.PI * 2;
|
|
864
|
+
const rootLabel = rootLabels[start] ?? "";
|
|
865
|
+
if (!rootColors.has(rootLabel)) rootColors.set(rootLabel, rootColors.size);
|
|
866
|
+
out.push({
|
|
867
|
+
d: sunburstArcPath(cx2, cy, innerRadius, outerRadius, startAngle, endAngle),
|
|
868
|
+
colorIndex: rootColors.get(rootLabel) ?? start,
|
|
869
|
+
opacity: Math.max(0.1, 0.9 - ringIndex * 0.1),
|
|
870
|
+
level: ringIndex,
|
|
871
|
+
label: levels[level]?.[start] ?? "",
|
|
872
|
+
...level === 0 && end === start + 1 ? { pointIndex: start } : {},
|
|
873
|
+
...arcLabelPlacement(cx2, cy, (innerRadius + outerRadius) / 2, startAngle, endAngle)
|
|
874
|
+
});
|
|
875
|
+
start = end;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return out;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// chart/style-palette.ts
|
|
882
|
+
function hexToRgb(hex) {
|
|
883
|
+
const h = hex.replace("#", "");
|
|
884
|
+
return [
|
|
885
|
+
parseInt(h.substring(0, 2), 16),
|
|
886
|
+
parseInt(h.substring(2, 4), 16),
|
|
887
|
+
parseInt(h.substring(4, 6), 16)
|
|
888
|
+
];
|
|
889
|
+
}
|
|
890
|
+
function rgbToHex(r, g, b) {
|
|
891
|
+
const clamp = (v) => Math.max(0, Math.min(255, Math.round(v)));
|
|
892
|
+
return `#${clamp(r).toString(16).padStart(2, "0")}${clamp(g).toString(16).padStart(2, "0")}${clamp(b).toString(16).padStart(2, "0")}`;
|
|
893
|
+
}
|
|
894
|
+
function tint(hex, amount) {
|
|
895
|
+
const [r, g, b] = hexToRgb(hex);
|
|
896
|
+
return rgbToHex(r + (255 - r) * amount, g + (255 - g) * amount, b + (255 - b) * amount);
|
|
897
|
+
}
|
|
898
|
+
function shade(hex, amount) {
|
|
899
|
+
const [r, g, b] = hexToRgb(hex);
|
|
900
|
+
return rgbToHex(r * (1 - amount), g * (1 - amount), b * (1 - amount));
|
|
901
|
+
}
|
|
902
|
+
var OFFICE_ACCENTS = [
|
|
903
|
+
"#4472C4",
|
|
904
|
+
"#ED7D31",
|
|
905
|
+
"#A5A5A5",
|
|
906
|
+
"#FFC000",
|
|
907
|
+
"#5B9BD5",
|
|
908
|
+
"#70AD47"
|
|
909
|
+
];
|
|
910
|
+
var DEFAULT_EXTRAS = ["#FF0000", "#00B0F0"];
|
|
911
|
+
var DEFAULT_CHART_PALETTE = [...OFFICE_ACCENTS, ...DEFAULT_EXTRAS];
|
|
912
|
+
function monochromaticRamp(base) {
|
|
913
|
+
return [
|
|
914
|
+
shade(base, 0.5),
|
|
915
|
+
shade(base, 0.35),
|
|
916
|
+
shade(base, 0.15),
|
|
917
|
+
base,
|
|
918
|
+
tint(base, 0.2),
|
|
919
|
+
tint(base, 0.4),
|
|
920
|
+
tint(base, 0.6),
|
|
921
|
+
tint(base, 0.8)
|
|
922
|
+
];
|
|
923
|
+
}
|
|
924
|
+
var GREY = "#7F7F7F";
|
|
925
|
+
function buildPalette(column, accents) {
|
|
926
|
+
if (column === 0) {
|
|
927
|
+
return monochromaticRamp(GREY);
|
|
928
|
+
}
|
|
929
|
+
if (column === 1) {
|
|
930
|
+
return [...accents, ...accents.map((accent) => shade(accent, 0.4))];
|
|
931
|
+
}
|
|
932
|
+
return monochromaticRamp(accents[column - 2]);
|
|
933
|
+
}
|
|
934
|
+
function usableAccents(accents) {
|
|
935
|
+
return accents?.length === 6 && accents.every((accent) => /^#[0-9a-f]{6}$/iu.test(accent)) ? accents : OFFICE_ACCENTS;
|
|
936
|
+
}
|
|
937
|
+
var paletteCache = /* @__PURE__ */ new Map();
|
|
938
|
+
function getChartStylePalette(styleId, themeAccents) {
|
|
939
|
+
const accents = usableAccents(themeAccents);
|
|
940
|
+
const valid = styleId !== void 0 && styleId >= 1 && styleId <= 48;
|
|
941
|
+
if (!valid && accents === OFFICE_ACCENTS) {
|
|
942
|
+
return DEFAULT_CHART_PALETTE;
|
|
943
|
+
}
|
|
944
|
+
const column = valid ? (Math.trunc(styleId) - 1) % 8 : -1;
|
|
945
|
+
const key = `${column}:${accents.join(",")}`;
|
|
946
|
+
let palette = paletteCache.get(key);
|
|
947
|
+
if (!palette) {
|
|
948
|
+
palette = column < 0 ? [...accents, ...DEFAULT_EXTRAS] : buildPalette(column, accents);
|
|
949
|
+
paletteCache.set(key, palette);
|
|
950
|
+
}
|
|
951
|
+
return palette;
|
|
952
|
+
}
|
|
953
|
+
|
|
291
954
|
// chart/histogram-binning.ts
|
|
292
955
|
function binLabel(lower, upper, closed, format) {
|
|
293
956
|
return closed === "r" ? `(${format(lower)}, ${format(upper)}]` : `[${format(lower)}, ${format(upper)})`;
|
|
@@ -380,57 +1043,38 @@ function aggregateByCategory(values, rawCategories) {
|
|
|
380
1043
|
});
|
|
381
1044
|
}
|
|
382
1045
|
|
|
383
|
-
// chart/
|
|
384
|
-
function
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const candidateAreas = [...rowAreas, next.area];
|
|
408
|
-
const candidateWorst = worstAspectRatio(candidateAreas, side);
|
|
409
|
-
if (candidateWorst > worst) {
|
|
410
|
-
break;
|
|
411
|
-
}
|
|
412
|
-
row = [...row, next];
|
|
413
|
-
rowAreas = candidateAreas;
|
|
414
|
-
worst = candidateWorst;
|
|
415
|
-
cursor++;
|
|
416
|
-
}
|
|
417
|
-
const rowTotalArea = rowAreas.reduce((sum, area) => sum + area, 0);
|
|
418
|
-
const thickness = side > 0 ? rowTotalArea / side : 0;
|
|
419
|
-
const layoutVertically = rect2.w >= rect2.h;
|
|
420
|
-
let offset = layoutVertically ? rect2.y : rect2.x;
|
|
421
|
-
for (const item of row) {
|
|
422
|
-
const length = thickness > 0 ? item.area / thickness : 0;
|
|
423
|
-
if (layoutVertically) {
|
|
424
|
-
result.push([item.node, { x: rect2.x, y: offset, w: thickness, h: length }]);
|
|
425
|
-
} else {
|
|
426
|
-
result.push([item.node, { x: offset, y: rect2.y, w: length, h: thickness }]);
|
|
427
|
-
}
|
|
428
|
-
offset += length;
|
|
1046
|
+
// chart/waterfall.ts
|
|
1047
|
+
function buildWaterfallSteps(values, options) {
|
|
1048
|
+
const subtotalIndices = new Set(
|
|
1049
|
+
options?.subtotalIndices ?? (values.length > 0 ? [values.length - 1] : [])
|
|
1050
|
+
);
|
|
1051
|
+
const steps = [];
|
|
1052
|
+
let runningTotal = 0;
|
|
1053
|
+
for (let sourceIndex = 0; sourceIndex < values.length; sourceIndex++) {
|
|
1054
|
+
const value = values[sourceIndex] ?? 0;
|
|
1055
|
+
const isSubtotal = subtotalIndices.has(sourceIndex);
|
|
1056
|
+
const startValue = isSubtotal ? 0 : runningTotal;
|
|
1057
|
+
const endValue = isSubtotal ? value : runningTotal + value;
|
|
1058
|
+
steps.push({ sourceIndex, value, startValue, endValue, isSubtotal });
|
|
1059
|
+
runningTotal = endValue;
|
|
1060
|
+
}
|
|
1061
|
+
return steps;
|
|
1062
|
+
}
|
|
1063
|
+
function computeWaterfallRange(steps, plotHeightPx) {
|
|
1064
|
+
let dataMin = Number.POSITIVE_INFINITY;
|
|
1065
|
+
let dataMax = Number.NEGATIVE_INFINITY;
|
|
1066
|
+
for (const step of steps)
|
|
1067
|
+
for (const value of [step.startValue, step.endValue]) {
|
|
1068
|
+
if (value < dataMin) dataMin = value;
|
|
1069
|
+
if (value > dataMax) dataMax = value;
|
|
429
1070
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
1071
|
+
if (dataMin === Number.POSITIVE_INFINITY) return { min: 0, max: 1, span: 1 };
|
|
1072
|
+
const { min, max, majorUnit } = niceValueAxisBounds(
|
|
1073
|
+
dataMin,
|
|
1074
|
+
dataMax,
|
|
1075
|
+
plotHeightPx !== void 0 ? axisTargetIntervals(plotHeightPx) : void 0
|
|
1076
|
+
);
|
|
1077
|
+
return { min, max, span: Math.max(max - min, Number.EPSILON), majorUnit };
|
|
434
1078
|
}
|
|
435
1079
|
|
|
436
1080
|
// chart/trendline-equation.ts
|
|
@@ -459,16 +1103,147 @@ function formatLogarithmicEquation(slope, intercept) {
|
|
|
459
1103
|
function formatPowerEquation(a2, b) {
|
|
460
1104
|
return `y = ${formatTrendlineCoefficient(a2)}x^${formatTrendlineCoefficient(b)}`;
|
|
461
1105
|
}
|
|
462
|
-
function formatPolynomialEquation(coeffsAscending) {
|
|
463
|
-
const order = coeffsAscending.length - 1;
|
|
464
|
-
let out = "y = ";
|
|
465
|
-
for (let power = order; power >= 0; power--) {
|
|
466
|
-
const coeff = coeffsAscending[power] ?? 0;
|
|
467
|
-
const { sign, abs } = signedTerm(coeff);
|
|
468
|
-
const variable = power === 0 ? "" : power === 1 ? "x" : `x^${power}`;
|
|
469
|
-
out += power === order ? `${sign === "-" ? "-" : ""}${abs}${variable}` : ` ${sign} ${abs}${variable}`;
|
|
1106
|
+
function formatPolynomialEquation(coeffsAscending) {
|
|
1107
|
+
const order = coeffsAscending.length - 1;
|
|
1108
|
+
let out = "y = ";
|
|
1109
|
+
for (let power = order; power >= 0; power--) {
|
|
1110
|
+
const coeff = coeffsAscending[power] ?? 0;
|
|
1111
|
+
const { sign, abs } = signedTerm(coeff);
|
|
1112
|
+
const variable = power === 0 ? "" : power === 1 ? "x" : `x^${power}`;
|
|
1113
|
+
out += power === order ? `${sign === "-" ? "-" : ""}${abs}${variable}` : ` ${sign} ${abs}${variable}`;
|
|
1114
|
+
}
|
|
1115
|
+
return out;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// chart/trendline-fit.ts
|
|
1119
|
+
var noFit = () => ({
|
|
1120
|
+
points: [],
|
|
1121
|
+
equation: "",
|
|
1122
|
+
rSquared: 0,
|
|
1123
|
+
coefficients: []
|
|
1124
|
+
});
|
|
1125
|
+
function fitModel(options, xVals, yVals) {
|
|
1126
|
+
const xs = [...xVals];
|
|
1127
|
+
const ys = [...yVals];
|
|
1128
|
+
switch (options.kind) {
|
|
1129
|
+
case "linear": {
|
|
1130
|
+
const reg = computeLinearRegression(xs, ys);
|
|
1131
|
+
const fixed = options.intercept;
|
|
1132
|
+
const slope = fixed !== void 0 ? ys.reduce((s, y, i) => s + (y - fixed) * xs[i], 0) / xs.reduce((s, x) => s + x * x, 0) : reg.slope;
|
|
1133
|
+
const b = fixed ?? reg.intercept;
|
|
1134
|
+
return {
|
|
1135
|
+
evaluate: (x) => slope * x + b,
|
|
1136
|
+
equation: formatLinearEquation(slope, b),
|
|
1137
|
+
rSquared: reg.rSquared,
|
|
1138
|
+
coefficients: [b, slope]
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
case "exponential": {
|
|
1142
|
+
const logY = ys.filter((y) => y > 0).map((y) => Math.log(y));
|
|
1143
|
+
const posX = xs.filter((_x, i) => ys[i] > 0);
|
|
1144
|
+
if (logY.length < 2) return void 0;
|
|
1145
|
+
const reg = computeLinearRegression(posX, logY);
|
|
1146
|
+
const a2 = Math.exp(reg.intercept);
|
|
1147
|
+
const b = reg.slope;
|
|
1148
|
+
return {
|
|
1149
|
+
evaluate: (x) => a2 * Math.exp(b * x),
|
|
1150
|
+
equation: formatExponentialEquation(a2, b),
|
|
1151
|
+
rSquared: reg.rSquared,
|
|
1152
|
+
coefficients: [a2, b]
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
case "logarithmic": {
|
|
1156
|
+
const lnX = xs.filter((x) => x > 0).map((x) => Math.log(x));
|
|
1157
|
+
const posY = ys.filter((_y, i) => xs[i] > 0);
|
|
1158
|
+
if (lnX.length < 2) return void 0;
|
|
1159
|
+
const reg = computeLinearRegression(lnX, posY);
|
|
1160
|
+
return {
|
|
1161
|
+
evaluate: (x) => x > 0 ? reg.slope * Math.log(x) + reg.intercept : 0,
|
|
1162
|
+
equation: formatLogarithmicEquation(reg.slope, reg.intercept),
|
|
1163
|
+
rSquared: reg.rSquared,
|
|
1164
|
+
coefficients: [reg.intercept, reg.slope]
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
case "power": {
|
|
1168
|
+
const logX = xs.filter((x, i) => x > 0 && ys[i] > 0).map((x) => Math.log(x));
|
|
1169
|
+
const logY = ys.filter((y, i) => y > 0 && xs[i] > 0).map((y) => Math.log(y));
|
|
1170
|
+
if (logX.length < 2) return void 0;
|
|
1171
|
+
const reg = computeLinearRegression(logX, logY);
|
|
1172
|
+
const a2 = Math.exp(reg.intercept);
|
|
1173
|
+
return {
|
|
1174
|
+
evaluate: (x) => x > 0 ? a2 * x ** reg.slope : 0,
|
|
1175
|
+
equation: formatPowerEquation(a2, reg.slope),
|
|
1176
|
+
rSquared: reg.rSquared,
|
|
1177
|
+
coefficients: [a2, reg.slope]
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
case "polynomial": {
|
|
1181
|
+
const order = Math.min(options.order ?? 2, 6);
|
|
1182
|
+
const coeffs = fitPolynomial(xs, ys, order);
|
|
1183
|
+
const evaluate = (x) => coeffs.reduce((s, c2, i) => s + c2 * x ** i, 0);
|
|
1184
|
+
return {
|
|
1185
|
+
evaluate,
|
|
1186
|
+
equation: formatPolynomialEquation(coeffs),
|
|
1187
|
+
rSquared: computeRSquared(xs, ys, evaluate),
|
|
1188
|
+
coefficients: coeffs
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
default:
|
|
1192
|
+
return void 0;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function fitChartTrendline(options, xVals, yVals) {
|
|
1196
|
+
const count = yVals.length;
|
|
1197
|
+
if (count < 2) return noFit();
|
|
1198
|
+
if (options.kind === "movingAvg") {
|
|
1199
|
+
const period = options.period ?? 2;
|
|
1200
|
+
const points2 = [];
|
|
1201
|
+
for (let i = period - 1; i < count; i++) {
|
|
1202
|
+
let sum = 0;
|
|
1203
|
+
for (let j = i - period + 1; j <= i; j++) sum += yVals[j];
|
|
1204
|
+
points2.push({ x: xVals[i], y: sum / period });
|
|
1205
|
+
}
|
|
1206
|
+
return { points: points2, equation: `${period}-period moving average`, rSquared: 0, coefficients: [] };
|
|
1207
|
+
}
|
|
1208
|
+
const model = fitModel(options, xVals, yVals);
|
|
1209
|
+
if (!model) return noFit();
|
|
1210
|
+
const startX = Math.min(...xVals) - (options.backward ?? 0);
|
|
1211
|
+
const endX = Math.max(...xVals) + (options.forward ?? 0);
|
|
1212
|
+
const steps = Math.max(Math.ceil((endX - startX) * 4), 20);
|
|
1213
|
+
const points = [];
|
|
1214
|
+
for (let step = 0; step <= steps; step++) {
|
|
1215
|
+
const x = startX + (endX - startX) * step / steps;
|
|
1216
|
+
const y = model.evaluate(x);
|
|
1217
|
+
if (Number.isFinite(y)) points.push({ x, y });
|
|
1218
|
+
}
|
|
1219
|
+
return {
|
|
1220
|
+
points,
|
|
1221
|
+
equation: model.equation,
|
|
1222
|
+
rSquared: model.rSquared,
|
|
1223
|
+
coefficients: model.coefficients
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// chart/error-bar-amount.ts
|
|
1228
|
+
function chartSampleVariance(values) {
|
|
1229
|
+
const count = values.length;
|
|
1230
|
+
if (count === 0) return 0;
|
|
1231
|
+
const mean = values.reduce((sum, value) => sum + value, 0) / count;
|
|
1232
|
+
return values.reduce((sum, value) => sum + (value - mean) ** 2, 0) / Math.max(count - 1, 1);
|
|
1233
|
+
}
|
|
1234
|
+
function chartErrorBarAmount(options, values, displayIndex, sourceIndex, side) {
|
|
1235
|
+
switch (options.valueType) {
|
|
1236
|
+
case "fixedVal":
|
|
1237
|
+
return options.value ?? 0;
|
|
1238
|
+
case "percentage":
|
|
1239
|
+
return Math.abs(values[displayIndex] ?? 0) * ((options.value ?? 0) / 100);
|
|
1240
|
+
case "stdDev":
|
|
1241
|
+
return Math.sqrt(chartSampleVariance(values)) * (options.value ?? 1);
|
|
1242
|
+
case "stdErr":
|
|
1243
|
+
return Math.sqrt(chartSampleVariance(values) / Math.max(values.length, 1));
|
|
1244
|
+
case "cust":
|
|
1245
|
+
return side === "plus" ? options.customPlus?.[sourceIndex] ?? 0 : options.customMinus?.[sourceIndex] ?? 0;
|
|
470
1246
|
}
|
|
471
|
-
return out;
|
|
472
1247
|
}
|
|
473
1248
|
|
|
474
1249
|
// chart/radar-geometry.ts
|
|
@@ -476,18 +1251,18 @@ function radarAngle(index, catCount) {
|
|
|
476
1251
|
const n2 = Math.max(catCount, 1);
|
|
477
1252
|
return Math.PI * 2 * index / n2 - Math.PI / 2;
|
|
478
1253
|
}
|
|
479
|
-
function computeRadarPoints(values, maxVal, radius,
|
|
1254
|
+
function computeRadarPoints(values, maxVal, radius, cx2, cy, catCount) {
|
|
480
1255
|
const denom = maxVal > 0 ? maxVal : 1;
|
|
481
1256
|
return values.slice(0, Math.max(catCount, 1)).map((val, i) => {
|
|
482
1257
|
const angle = radarAngle(i, catCount), r = Math.abs(val) / denom * radius;
|
|
483
|
-
return { x:
|
|
1258
|
+
return { x: cx2 + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
|
|
484
1259
|
});
|
|
485
1260
|
}
|
|
486
|
-
function radarRingPoints(
|
|
1261
|
+
function radarRingPoints(cx2, cy, rr, catCount) {
|
|
487
1262
|
const n2 = Math.max(catCount, 1);
|
|
488
1263
|
return Array.from({ length: n2 }, (_, i) => {
|
|
489
1264
|
const angle = radarAngle(i, n2);
|
|
490
|
-
return `${(
|
|
1265
|
+
return `${(cx2 + rr * Math.cos(angle)).toFixed(2)},${(cy + rr * Math.sin(angle)).toFixed(2)}`;
|
|
491
1266
|
}).join(" ");
|
|
492
1267
|
}
|
|
493
1268
|
|
|
@@ -621,13 +1396,13 @@ function hexToRgbChannels(color) {
|
|
|
621
1396
|
b: Number.parseInt(normalized.slice(4, 6), 16)
|
|
622
1397
|
};
|
|
623
1398
|
}
|
|
624
|
-
function percentDivisorFor(
|
|
625
|
-
return
|
|
1399
|
+
function percentDivisorFor(text3) {
|
|
1400
|
+
return text3.endsWith("%") ? 100 : 1e5;
|
|
626
1401
|
}
|
|
627
1402
|
function parseOoxmlPercent(value) {
|
|
628
|
-
const
|
|
629
|
-
const divisor = percentDivisorFor(
|
|
630
|
-
const magnitude = Number.parseFloat(divisor === 100 ?
|
|
1403
|
+
const text3 = String(value ?? "").trim();
|
|
1404
|
+
const divisor = percentDivisorFor(text3);
|
|
1405
|
+
const magnitude = Number.parseFloat(divisor === 100 ? text3.slice(0, -1) : text3);
|
|
631
1406
|
if (!Number.isFinite(magnitude)) {
|
|
632
1407
|
return void 0;
|
|
633
1408
|
}
|
|
@@ -1028,16 +1803,42 @@ var NS = {
|
|
|
1028
1803
|
a: "http://schemas.openxmlformats.org/drawingml/2006/main",
|
|
1029
1804
|
/** DrawingML chart. */
|
|
1030
1805
|
c: "http://schemas.openxmlformats.org/drawingml/2006/chart",
|
|
1806
|
+
/** Office 2016 extended charts (waterfall, histogram, funnel...; `cx:chartSpace`). */
|
|
1807
|
+
cx: "http://schemas.microsoft.com/office/drawing/2014/chartex",
|
|
1031
1808
|
/** Office 2010 chart extensions, including built-in modern chart styles. */
|
|
1032
1809
|
c14: "http://schemas.microsoft.com/office/drawing/2007/8/2/chart",
|
|
1033
1810
|
/** Relationships (`r:id`, `r:embed`). */
|
|
1034
1811
|
r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
|
|
1035
1812
|
/** Markup compatibility (`mc:AlternateContent`). */
|
|
1036
1813
|
mc: "http://schemas.openxmlformats.org/markup-compatibility/2006"};
|
|
1814
|
+
var DEFAULT_XML_LIMITS = {
|
|
1815
|
+
maxDepth: 512,
|
|
1816
|
+
maxNodes: 5e6
|
|
1817
|
+
};
|
|
1818
|
+
var MARKUP_RE = /<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>|<\?[\s\S]*?\?>|<(\/?)([^\s\/>]+)(?:\s+[^\s=\/>]+\s*=\s*(?:"[^"]*"|'[^']*'))*\s*(\/?)>/g;
|
|
1819
|
+
function checkXmlLimits(xml, label, limits = {}) {
|
|
1820
|
+
const maxDepth = limits.maxDepth ?? DEFAULT_XML_LIMITS.maxDepth;
|
|
1821
|
+
const maxNodes = limits.maxNodes ?? DEFAULT_XML_LIMITS.maxNodes;
|
|
1822
|
+
let depth = 0;
|
|
1823
|
+
let nodes = 0;
|
|
1824
|
+
for (const match of xml.matchAll(MARKUP_RE)) {
|
|
1825
|
+
const [, closing, name, selfClosing] = match;
|
|
1826
|
+
if (name === void 0) continue;
|
|
1827
|
+
if (closing) {
|
|
1828
|
+
depth--;
|
|
1829
|
+
continue;
|
|
1830
|
+
}
|
|
1831
|
+
nodes++;
|
|
1832
|
+
if (nodes > maxNodes) throw new Error(`${label} XML exceeds the limit of ${maxNodes} elements`);
|
|
1833
|
+
if (!selfClosing && ++depth > maxDepth)
|
|
1834
|
+
throw new Error(`${label} XML exceeds the nesting depth limit of ${maxDepth}`);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1037
1837
|
function parseXml(xml, options = {}) {
|
|
1038
1838
|
const label = options.label ?? "OOXML";
|
|
1039
1839
|
if (/<!DOCTYPE|<!ENTITY/i.test(xml))
|
|
1040
1840
|
throw new Error(`${label} XML with DTD or entity declarations is not supported`);
|
|
1841
|
+
checkXmlLimits(xml, label, options.limits);
|
|
1041
1842
|
let parseError = "";
|
|
1042
1843
|
let parsed;
|
|
1043
1844
|
try {
|
|
@@ -1257,17 +2058,17 @@ function resolveDrawingColor(color, theme, options) {
|
|
|
1257
2058
|
}
|
|
1258
2059
|
if (has("inv")) [r, g, b] = [255 - r, 255 - g, 255 - b];
|
|
1259
2060
|
if (has("gray")) r = g = b = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
|
|
1260
|
-
const
|
|
1261
|
-
if (
|
|
1262
|
-
r = linearToSrgb255(srgb255ToLinear(r) *
|
|
1263
|
-
g = linearToSrgb255(srgb255ToLinear(g) *
|
|
1264
|
-
b = linearToSrgb255(srgb255ToLinear(b) *
|
|
1265
|
-
}
|
|
1266
|
-
const
|
|
1267
|
-
if (
|
|
1268
|
-
r = linearToSrgb255(1 - (1 - srgb255ToLinear(r)) *
|
|
1269
|
-
g = linearToSrgb255(1 - (1 - srgb255ToLinear(g)) *
|
|
1270
|
-
b = linearToSrgb255(1 - (1 - srgb255ToLinear(b)) *
|
|
2061
|
+
const shade2 = parseDrawingPercent(find("shade"));
|
|
2062
|
+
if (shade2 !== void 0) {
|
|
2063
|
+
r = linearToSrgb255(srgb255ToLinear(r) * shade2);
|
|
2064
|
+
g = linearToSrgb255(srgb255ToLinear(g) * shade2);
|
|
2065
|
+
b = linearToSrgb255(srgb255ToLinear(b) * shade2);
|
|
2066
|
+
}
|
|
2067
|
+
const tint2 = parseDrawingPercent(find("tint"));
|
|
2068
|
+
if (tint2 !== void 0) {
|
|
2069
|
+
r = linearToSrgb255(1 - (1 - srgb255ToLinear(r)) * tint2);
|
|
2070
|
+
g = linearToSrgb255(1 - (1 - srgb255ToLinear(g)) * tint2);
|
|
2071
|
+
b = linearToSrgb255(1 - (1 - srgb255ToLinear(b)) * tint2);
|
|
1271
2072
|
}
|
|
1272
2073
|
if (["hue", "hueMod", "hueOff", "sat", "satMod", "satOff", "lum", "lumMod", "lumOff"].some(has)) {
|
|
1273
2074
|
const hsl = rgbToHsl(r, g, b);
|
|
@@ -1619,28 +2420,28 @@ function parseDrawingLine(ln) {
|
|
|
1619
2420
|
}
|
|
1620
2421
|
|
|
1621
2422
|
// chart/read-appearance.ts
|
|
1622
|
-
function readChartAppearance(
|
|
2423
|
+
function readChartAppearance(text3, properties2) {
|
|
1623
2424
|
const out = {};
|
|
1624
|
-
const size = Number(
|
|
2425
|
+
const size = Number(text3?.getAttribute("sz") ?? NaN);
|
|
1625
2426
|
if (Number.isFinite(size) && size > 0) out.fontSize = size / 100;
|
|
1626
2427
|
for (const [attribute2, key] of [
|
|
1627
2428
|
["b", "bold"],
|
|
1628
2429
|
["i", "italic"]
|
|
1629
2430
|
]) {
|
|
1630
|
-
const value =
|
|
2431
|
+
const value = text3?.getAttribute(attribute2);
|
|
1631
2432
|
if (value !== null && value !== void 0) out[key] = value === "1" || value === "true";
|
|
1632
2433
|
}
|
|
1633
|
-
const typeface2 = first(
|
|
1634
|
-
const underline =
|
|
2434
|
+
const typeface2 = first(text3, "latin", NS.a)?.getAttribute("typeface");
|
|
2435
|
+
const underline = text3?.getAttribute("u");
|
|
1635
2436
|
if (underline) out.underline = underline !== "none";
|
|
1636
2437
|
if (typeface2) out.typeface = typeface2;
|
|
1637
|
-
const color = parseDrawingColorIn(first(
|
|
2438
|
+
const color = parseDrawingColorIn(first(text3, "solidFill", NS.a));
|
|
1638
2439
|
if (color) out.textColor = color;
|
|
1639
2440
|
const fill = parseDrawingFill(properties2);
|
|
1640
2441
|
const line2 = parseDrawingLine(first(properties2, "ln", NS.a));
|
|
1641
2442
|
if (fill) out.fill = fill;
|
|
1642
2443
|
if (line2) out.line = line2;
|
|
1643
|
-
const effects = first(
|
|
2444
|
+
const effects = first(text3, "effectLst", NS.a);
|
|
1644
2445
|
if (effects) out.textEffectsXml = buildXml(effects);
|
|
1645
2446
|
return out;
|
|
1646
2447
|
}
|
|
@@ -2156,7 +2957,7 @@ function rectGradientFocus(id) {
|
|
|
2156
2957
|
if (!direction) throw new RangeError(`Unknown rectangular gradient direction ${id}`);
|
|
2157
2958
|
return { l: direction.x, t: direction.y, r: 1 - direction.x, b: 1 - direction.y };
|
|
2158
2959
|
}
|
|
2159
|
-
function
|
|
2960
|
+
function hexToRgb2(color) {
|
|
2160
2961
|
const parsed = hexToRgbChannels(color);
|
|
2161
2962
|
if (parsed) return parsed;
|
|
2162
2963
|
const hex = color.replace("#", "");
|
|
@@ -2170,8 +2971,8 @@ function toHexChannel(value) {
|
|
|
2170
2971
|
return toHex(value).toLowerCase();
|
|
2171
2972
|
}
|
|
2172
2973
|
function lerpStops(a2, b, t) {
|
|
2173
|
-
const ca =
|
|
2174
|
-
const cb =
|
|
2974
|
+
const ca = hexToRgb2(a2.color);
|
|
2975
|
+
const cb = hexToRgb2(b.color);
|
|
2175
2976
|
const oa = a2.opacity ?? 1;
|
|
2176
2977
|
const ob = b.opacity ?? 1;
|
|
2177
2978
|
return {
|
|
@@ -2250,8 +3051,8 @@ function buildRectPathGradientSvg(stops, focalPoint, fillToRect, options) {
|
|
|
2250
3051
|
);
|
|
2251
3052
|
}
|
|
2252
3053
|
}
|
|
2253
|
-
const
|
|
2254
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="none">${
|
|
3054
|
+
const paint2 = masked ? `<defs><mask id="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100" mask-type="luminance" color-interpolation="sRGB">${alphaRects.join("")}</mask></defs><g mask="url(#alpha)">${rects.join("")}</g>` : rects.join("");
|
|
3055
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="none">${paint2}</svg>`;
|
|
2255
3056
|
}
|
|
2256
3057
|
|
|
2257
3058
|
// chart/gradient-definition.ts
|
|
@@ -2303,16 +3104,16 @@ function buildChartGradientDef(id, fill, bounds) {
|
|
|
2303
3104
|
};
|
|
2304
3105
|
}
|
|
2305
3106
|
if (fill.type === "radial") {
|
|
2306
|
-
const
|
|
3107
|
+
const cx2 = fill.focalPoint?.x ?? 0.5;
|
|
2307
3108
|
const cy = fill.focalPoint?.y ?? 0.5;
|
|
2308
3109
|
const aspect = fill.path === "circle" && bounds && Number.isFinite(bounds.width) && Number.isFinite(bounds.height) && bounds.width > 0 && bounds.height > 0 ? bounds.height / bounds.width : 1;
|
|
2309
3110
|
return {
|
|
2310
3111
|
kind: "radialGradient",
|
|
2311
3112
|
id,
|
|
2312
|
-
cx,
|
|
3113
|
+
cx: cx2,
|
|
2313
3114
|
cy,
|
|
2314
3115
|
r: Math.max(
|
|
2315
|
-
...[0, 1].flatMap((x) => [0, 1].map((y) => Math.hypot(x -
|
|
3116
|
+
...[0, 1].flatMap((x) => [0, 1].map((y) => Math.hypot(x - cx2, (y - cy) * aspect)))
|
|
2316
3117
|
),
|
|
2317
3118
|
...aspect === 1 ? {} : { gradientTransform: `matrix(1 0 0 ${1 / aspect} 0 ${cy * (1 - 1 / aspect)})` },
|
|
2318
3119
|
stops
|
|
@@ -2405,14 +3206,43 @@ function writeChartLayoutFormatting(root, formatting) {
|
|
|
2405
3206
|
return changed;
|
|
2406
3207
|
}
|
|
2407
3208
|
|
|
3209
|
+
// chart/model-analysis.ts
|
|
3210
|
+
var KIND_OF_TYPE = {
|
|
3211
|
+
linear: "linear",
|
|
3212
|
+
exp: "exponential",
|
|
3213
|
+
log: "logarithmic",
|
|
3214
|
+
poly: "polynomial",
|
|
3215
|
+
power: "power",
|
|
3216
|
+
movingAvg: "movingAvg"
|
|
3217
|
+
};
|
|
3218
|
+
var TYPE_OF_KIND = {
|
|
3219
|
+
linear: "linear",
|
|
3220
|
+
exponential: "exp",
|
|
3221
|
+
logarithmic: "log",
|
|
3222
|
+
polynomial: "poly",
|
|
3223
|
+
power: "power",
|
|
3224
|
+
movingAvg: "movingAvg"
|
|
3225
|
+
};
|
|
3226
|
+
var chartTrendlineKind = (type) => type !== void 0 && Object.hasOwn(KIND_OF_TYPE, type) ? KIND_OF_TYPE[type] : void 0;
|
|
3227
|
+
var chartTrendlineType = (kind) => TYPE_OF_KIND[kind];
|
|
3228
|
+
var CHART_ERROR_BAR_DIRECTIONS = ["x", "y"];
|
|
3229
|
+
var CHART_ERROR_BAR_TYPES = ["both", "minus", "plus"];
|
|
3230
|
+
var CHART_ERROR_VALUE_TYPES = [
|
|
3231
|
+
"cust",
|
|
3232
|
+
"fixedVal",
|
|
3233
|
+
"percentage",
|
|
3234
|
+
"stdDev",
|
|
3235
|
+
"stdErr"
|
|
3236
|
+
];
|
|
3237
|
+
|
|
2408
3238
|
// chart/data-cache.ts
|
|
2409
3239
|
function chartCacheValues(cache) {
|
|
2410
3240
|
if (!cache) return [];
|
|
2411
3241
|
const numeric = cache.type === "number";
|
|
2412
3242
|
const out = [];
|
|
2413
3243
|
for (const point of cache.points) {
|
|
2414
|
-
const
|
|
2415
|
-
out[point.index ?? out.length] = numeric &&
|
|
3244
|
+
const text3 = point.value;
|
|
3245
|
+
out[point.index ?? out.length] = numeric && text3.trim() !== "" && Number.isFinite(Number(text3)) ? Number(text3) : text3;
|
|
2416
3246
|
}
|
|
2417
3247
|
const size = Math.max(cache.pointCount ?? 0, out.length);
|
|
2418
3248
|
for (let index = 0; index < size; index++) if (out[index] === void 0) out[index] = "";
|
|
@@ -2470,6 +3300,14 @@ function cNumber(context, parent, local) {
|
|
|
2470
3300
|
malformed(context, element, raw2);
|
|
2471
3301
|
return void 0;
|
|
2472
3302
|
}
|
|
3303
|
+
function cEnum(context, parent, local, allowed) {
|
|
3304
|
+
const element = cChild(parent, local);
|
|
3305
|
+
const raw2 = attribute(element, "val");
|
|
3306
|
+
if (!element || raw2 === void 0) return void 0;
|
|
3307
|
+
if (allowed.includes(raw2)) return raw2;
|
|
3308
|
+
malformed(context, element, raw2);
|
|
3309
|
+
return void 0;
|
|
3310
|
+
}
|
|
2473
3311
|
function reportUnmodelled(context, element, handled) {
|
|
2474
3312
|
for (const child2 of elements(element)) {
|
|
2475
3313
|
if (handled.has(child2.localName)) continue;
|
|
@@ -2590,20 +3428,20 @@ function parseDataSource(element) {
|
|
|
2590
3428
|
}
|
|
2591
3429
|
function parseChartText(context, tx, allowValue) {
|
|
2592
3430
|
if (!tx) return void 0;
|
|
2593
|
-
const
|
|
3431
|
+
const text3 = {};
|
|
2594
3432
|
const rich = chartTextBody(cChild(tx, "rich"));
|
|
2595
|
-
if (rich)
|
|
3433
|
+
if (rich) text3.rich = rich;
|
|
2596
3434
|
if (cChild(tx, "strRef")) {
|
|
2597
3435
|
const reference2 = parseDataSource(tx);
|
|
2598
|
-
if (reference2)
|
|
3436
|
+
if (reference2) text3.reference = reference2;
|
|
2599
3437
|
}
|
|
2600
3438
|
const value = allowValue ? cChild(tx, "v")?.textContent : void 0;
|
|
2601
|
-
if (value !== void 0 && value !== null)
|
|
2602
|
-
const cached = chartCacheValues(
|
|
2603
|
-
const flat =
|
|
2604
|
-
if (flat !== void 0)
|
|
3439
|
+
if (value !== void 0 && value !== null) text3.value = value;
|
|
3440
|
+
const cached = chartCacheValues(text3.reference?.cache)[0];
|
|
3441
|
+
const flat = text3.value ?? (rich ? rich.text : cached === void 0 ? void 0 : String(cached));
|
|
3442
|
+
if (flat !== void 0) text3.text = flat;
|
|
2605
3443
|
reportUnmodelled(context, tx, new Set(allowValue ? ["strRef", "v"] : ["rich", "strRef"]));
|
|
2606
|
-
return
|
|
3444
|
+
return text3;
|
|
2607
3445
|
}
|
|
2608
3446
|
var TITLE = /* @__PURE__ */ new Set(["tx", "layout", "overlay", "spPr", "txPr", "extLst"]);
|
|
2609
3447
|
function parseTitle(context, element) {
|
|
@@ -2770,6 +3608,105 @@ function readDisplayNaAsBlank(chartExtLst) {
|
|
|
2770
3608
|
return void 0;
|
|
2771
3609
|
}
|
|
2772
3610
|
|
|
3611
|
+
// chart/parse-analysis.ts
|
|
3612
|
+
var TRENDLINE_TYPES = [
|
|
3613
|
+
"exp",
|
|
3614
|
+
"linear",
|
|
3615
|
+
"log",
|
|
3616
|
+
"movingAvg",
|
|
3617
|
+
"poly",
|
|
3618
|
+
"power"
|
|
3619
|
+
];
|
|
3620
|
+
var LABEL2 = /* @__PURE__ */ new Set(["layout", "tx", "numFmt", "spPr", "txPr", "extLst"]);
|
|
3621
|
+
function parseTrendlineLabel(context, element) {
|
|
3622
|
+
if (!element) return void 0;
|
|
3623
|
+
reportUnmodelled(context, element, LABEL2);
|
|
3624
|
+
return assignDefined(
|
|
3625
|
+
{},
|
|
3626
|
+
{
|
|
3627
|
+
layout: manualLayout(element),
|
|
3628
|
+
tx: parseChartText(context, cChild(element, "tx"), false),
|
|
3629
|
+
numberFormat: numberFormat(element),
|
|
3630
|
+
spPr: shapeProperties(element),
|
|
3631
|
+
txPr: textProperties(element),
|
|
3632
|
+
extLst: extensionList(element)
|
|
3633
|
+
}
|
|
3634
|
+
);
|
|
3635
|
+
}
|
|
3636
|
+
var TRENDLINE = /* @__PURE__ */ new Set([
|
|
3637
|
+
"name",
|
|
3638
|
+
"spPr",
|
|
3639
|
+
"trendlineType",
|
|
3640
|
+
"order",
|
|
3641
|
+
"period",
|
|
3642
|
+
"forward",
|
|
3643
|
+
"backward",
|
|
3644
|
+
"intercept",
|
|
3645
|
+
"dispRSqr",
|
|
3646
|
+
"dispEq",
|
|
3647
|
+
"trendlineLbl",
|
|
3648
|
+
"extLst"
|
|
3649
|
+
]);
|
|
3650
|
+
function parseTrendline(context, element) {
|
|
3651
|
+
reportUnmodelled(context, element, TRENDLINE);
|
|
3652
|
+
const name = cChild(element, "name");
|
|
3653
|
+
return assignDefined(
|
|
3654
|
+
{},
|
|
3655
|
+
{
|
|
3656
|
+
name: name ? name.textContent ?? "" : void 0,
|
|
3657
|
+
spPr: shapeProperties(element),
|
|
3658
|
+
trendlineType: cEnum(context, element, "trendlineType", TRENDLINE_TYPES),
|
|
3659
|
+
order: cNumber(context, element, "order"),
|
|
3660
|
+
period: cNumber(context, element, "period"),
|
|
3661
|
+
forward: cNumber(context, element, "forward"),
|
|
3662
|
+
backward: cNumber(context, element, "backward"),
|
|
3663
|
+
intercept: cNumber(context, element, "intercept"),
|
|
3664
|
+
displayRSquared: cBool(context, element, "dispRSqr"),
|
|
3665
|
+
displayEquation: cBool(context, element, "dispEq"),
|
|
3666
|
+
label: parseTrendlineLabel(context, cChild(element, "trendlineLbl")),
|
|
3667
|
+
extLst: extensionList(element)
|
|
3668
|
+
}
|
|
3669
|
+
);
|
|
3670
|
+
}
|
|
3671
|
+
var ERROR_BARS = /* @__PURE__ */ new Set([
|
|
3672
|
+
"errDir",
|
|
3673
|
+
"errBarType",
|
|
3674
|
+
"errValType",
|
|
3675
|
+
"noEndCap",
|
|
3676
|
+
"plus",
|
|
3677
|
+
"minus",
|
|
3678
|
+
"val",
|
|
3679
|
+
"spPr",
|
|
3680
|
+
"extLst"
|
|
3681
|
+
]);
|
|
3682
|
+
function parseErrorBars(context, element) {
|
|
3683
|
+
reportUnmodelled(context, element, ERROR_BARS);
|
|
3684
|
+
return assignDefined(
|
|
3685
|
+
{},
|
|
3686
|
+
{
|
|
3687
|
+
direction: cEnum(context, element, "errDir", CHART_ERROR_BAR_DIRECTIONS),
|
|
3688
|
+
barType: cEnum(context, element, "errBarType", CHART_ERROR_BAR_TYPES),
|
|
3689
|
+
valueType: cEnum(context, element, "errValType", CHART_ERROR_VALUE_TYPES),
|
|
3690
|
+
noEndCap: cBool(context, element, "noEndCap"),
|
|
3691
|
+
plus: parseDataSource(cChild(element, "plus")),
|
|
3692
|
+
minus: parseDataSource(cChild(element, "minus")),
|
|
3693
|
+
value: cNumber(context, element, "val"),
|
|
3694
|
+
spPr: shapeProperties(element),
|
|
3695
|
+
extLst: extensionList(element)
|
|
3696
|
+
}
|
|
3697
|
+
);
|
|
3698
|
+
}
|
|
3699
|
+
function parseSeriesAnalysis(context, series) {
|
|
3700
|
+
const trendlines2 = children(series, "trendline", NS.c).map(
|
|
3701
|
+
(node) => parseTrendline(context, node)
|
|
3702
|
+
);
|
|
3703
|
+
const errorBars = children(series, "errBars", NS.c).map((node) => parseErrorBars(context, node));
|
|
3704
|
+
return {
|
|
3705
|
+
...trendlines2.length ? { trendlines: trendlines2 } : {},
|
|
3706
|
+
...errorBars.length ? { errorBars } : {}
|
|
3707
|
+
};
|
|
3708
|
+
}
|
|
3709
|
+
|
|
2773
3710
|
// chart/parse-series.ts
|
|
2774
3711
|
var MARKER = /* @__PURE__ */ new Set(["symbol", "size", "spPr", "extLst"]);
|
|
2775
3712
|
function parseMarker(context, element) {
|
|
@@ -2818,6 +3755,8 @@ var SERIES = /* @__PURE__ */ new Set([
|
|
|
2818
3755
|
"invertIfNegative",
|
|
2819
3756
|
"dPt",
|
|
2820
3757
|
"dLbls",
|
|
3758
|
+
"trendline",
|
|
3759
|
+
"errBars",
|
|
2821
3760
|
"cat",
|
|
2822
3761
|
"val",
|
|
2823
3762
|
"xVal",
|
|
@@ -2833,7 +3772,10 @@ var SERIES = /* @__PURE__ */ new Set([
|
|
|
2833
3772
|
function parseSeries(context, element) {
|
|
2834
3773
|
reportUnmodelled(context, element, SERIES);
|
|
2835
3774
|
return assignDefined(
|
|
2836
|
-
{
|
|
3775
|
+
{
|
|
3776
|
+
dataPoints: children(element, "dPt", NS.c).map((point) => parseDataPoint(context, point)),
|
|
3777
|
+
...parseSeriesAnalysis(context, element)
|
|
3778
|
+
},
|
|
2837
3779
|
{
|
|
2838
3780
|
index: cNumber(context, element, "idx"),
|
|
2839
3781
|
order: cNumber(context, element, "order"),
|
|
@@ -2916,7 +3858,7 @@ function parseGroup(context, element) {
|
|
|
2916
3858
|
const number = (local) => cNumber(context, element, local);
|
|
2917
3859
|
const flag = (local) => cBool(context, element, local);
|
|
2918
3860
|
const barDir = cVal(element, "barDir");
|
|
2919
|
-
const
|
|
3861
|
+
const present2 = (local) => cChild(element, local) ? true : void 0;
|
|
2920
3862
|
const linesShape = (local) => chartLines(element, local)?.spPr;
|
|
2921
3863
|
const bars2 = cChild(element, "upDownBars");
|
|
2922
3864
|
return assignDefined(
|
|
@@ -2942,10 +3884,10 @@ function parseGroup(context, element) {
|
|
|
2942
3884
|
shape: cVal(element, "shape"),
|
|
2943
3885
|
marker: flag("marker"),
|
|
2944
3886
|
smooth: flag("smooth"),
|
|
2945
|
-
dropLines:
|
|
2946
|
-
hiLowLines:
|
|
2947
|
-
upDownBars:
|
|
2948
|
-
seriesLines:
|
|
3887
|
+
dropLines: present2("dropLines"),
|
|
3888
|
+
hiLowLines: present2("hiLowLines"),
|
|
3889
|
+
upDownBars: present2("upDownBars"),
|
|
3890
|
+
seriesLines: present2("serLines"),
|
|
2949
3891
|
dropLinesSpPr: linesShape("dropLines"),
|
|
2950
3892
|
hiLowLinesSpPr: linesShape("hiLowLines"),
|
|
2951
3893
|
seriesLinesSpPr: linesShape("serLines"),
|
|
@@ -3277,9 +4219,9 @@ var escapeText = (value) => value.replace(INVALID_XML, "").replace(/&/g, "&"
|
|
|
3277
4219
|
var escapeAttribute = (value) => escapeText(value).replace(/"/g, """).replace(/\r/g, " ").replace(/\n/g, " ").replace(/\t/g, "	");
|
|
3278
4220
|
function chartNumber(value) {
|
|
3279
4221
|
if (!Number.isFinite(value)) throw new Error(`Chart number ${value} is not finite`);
|
|
3280
|
-
const
|
|
3281
|
-
const match = /^(-?)(\d+)(?:\.(\d+))?e([+-]\d+)$/i.exec(
|
|
3282
|
-
if (!match) return
|
|
4222
|
+
const text3 = String(value);
|
|
4223
|
+
const match = /^(-?)(\d+)(?:\.(\d+))?e([+-]\d+)$/i.exec(text3);
|
|
4224
|
+
if (!match) return text3;
|
|
3283
4225
|
const [, sign = "", whole = "", fraction = "", exponent = "0"] = match;
|
|
3284
4226
|
const digits = whole + fraction;
|
|
3285
4227
|
const point = whole.length + Number(exponent);
|
|
@@ -3288,8 +4230,8 @@ function chartNumber(value) {
|
|
|
3288
4230
|
}
|
|
3289
4231
|
function valXml(local, value) {
|
|
3290
4232
|
if (value === void 0) return "";
|
|
3291
|
-
const
|
|
3292
|
-
return `<c:${local} val="${
|
|
4233
|
+
const text3 = typeof value === "boolean" ? value ? "1" : "0" : typeof value === "number" ? chartNumber(value) : escapeAttribute(value);
|
|
4234
|
+
return `<c:${local} val="${text3}"/>`;
|
|
3293
4235
|
}
|
|
3294
4236
|
var elementXml = (local, content, attributes = "") => content ? `<c:${local}${attributes}>${content}</c:${local}>` : `<c:${local}${attributes}/>`;
|
|
3295
4237
|
var raw = (context, xml) => xml ? stripDeclarations(xml, context.bindings) : "";
|
|
@@ -3321,11 +4263,11 @@ function spacing(local, value) {
|
|
|
3321
4263
|
return `<a:${local}>${inner}</a:${local}>`;
|
|
3322
4264
|
}
|
|
3323
4265
|
function run(value) {
|
|
3324
|
-
const { text:
|
|
4266
|
+
const { text: text3, ...properties2 } = value;
|
|
3325
4267
|
const hasProperties = Object.keys(properties2).length > 0;
|
|
3326
|
-
if (
|
|
4268
|
+
if (text3 === "\n")
|
|
3327
4269
|
return hasProperties ? `<a:br>${runProperties("rPr", properties2)}</a:br>` : "<a:br/>";
|
|
3328
|
-
return `<a:r>${hasProperties ? runProperties("rPr", properties2) : ""}<a:t>${escapeText(
|
|
4270
|
+
return `<a:r>${hasProperties ? runProperties("rPr", properties2) : ""}<a:t>${escapeText(text3)}</a:t></a:r>`;
|
|
3329
4271
|
}
|
|
3330
4272
|
function paragraph(value) {
|
|
3331
4273
|
const align = value.align ? ` algn="${escapeAttribute(value.align)}"` : "";
|
|
@@ -3436,8 +4378,8 @@ function layoutXml(context, value) {
|
|
|
3436
4378
|
const manual = LAYOUT_FIELDS.map(([local, key]) => {
|
|
3437
4379
|
const value2 = layout[key];
|
|
3438
4380
|
if (value2 === void 0) return "";
|
|
3439
|
-
const
|
|
3440
|
-
return `<c:${local} val="${
|
|
4381
|
+
const text3 = typeof value2 === "number" ? chartNumber(value2) : value2;
|
|
4382
|
+
return `<c:${local} val="${text3}"/>`;
|
|
3441
4383
|
}).join("");
|
|
3442
4384
|
return elementXml("layout", manual ? `<c:manualLayout>${manual}</c:manualLayout>` : "");
|
|
3443
4385
|
}
|
|
@@ -3483,16 +4425,16 @@ function dataSourceInner(source) {
|
|
|
3483
4425
|
}
|
|
3484
4426
|
}
|
|
3485
4427
|
var dataSourceXml = (local, source) => source ? elementXml(local, dataSourceInner(source)) : "";
|
|
3486
|
-
function chartTextXml(context,
|
|
3487
|
-
if (!
|
|
3488
|
-
if (
|
|
4428
|
+
function chartTextXml(context, text3, seriesName2) {
|
|
4429
|
+
if (!text3) return "";
|
|
4430
|
+
if (text3.reference) return elementXml("tx", dataSourceInner(text3.reference));
|
|
3489
4431
|
if (seriesName2) {
|
|
3490
|
-
const value =
|
|
4432
|
+
const value = text3.value ?? text3.text;
|
|
3491
4433
|
return elementXml("tx", value === void 0 ? "" : textElement("v", value));
|
|
3492
4434
|
}
|
|
3493
|
-
if (
|
|
3494
|
-
if (
|
|
3495
|
-
const paragraphs =
|
|
4435
|
+
if (text3.rich) return elementXml("tx", textBodyXml(context, text3.rich, "rich"));
|
|
4436
|
+
if (text3.text === void 0) return "<c:tx/>";
|
|
4437
|
+
const paragraphs = text3.text.split("\n").map((line2) => ({ runs: [{ text: line2 }] }));
|
|
3496
4438
|
return `<c:tx><c:rich>${writeTextBody({ paragraphs })}</c:rich></c:tx>`;
|
|
3497
4439
|
}
|
|
3498
4440
|
function titleXml(context, title) {
|
|
@@ -3555,7 +4497,7 @@ var AXIS_ELEMENTS2 = {
|
|
|
3555
4497
|
date: "dateAx",
|
|
3556
4498
|
ser: "serAx"
|
|
3557
4499
|
};
|
|
3558
|
-
var gridlinesXml = (context, local,
|
|
4500
|
+
var gridlinesXml = (context, local, present2, shape) => present2 ? elementXml(local, shapePropertiesXml(context, shape)) : "";
|
|
3559
4501
|
function axisXml(context, axis) {
|
|
3560
4502
|
const { scaling } = axis;
|
|
3561
4503
|
return elementXml(
|
|
@@ -3567,6 +4509,28 @@ function axisXml(context, axis) {
|
|
|
3567
4509
|
);
|
|
3568
4510
|
}
|
|
3569
4511
|
|
|
4512
|
+
// chart/write-analysis.ts
|
|
4513
|
+
function trendlineLabelXml(context, label) {
|
|
4514
|
+
if (!label) return "";
|
|
4515
|
+
return elementXml(
|
|
4516
|
+
"trendlineLbl",
|
|
4517
|
+
layoutXml(context, label.layout) + chartTextXml(context, label.tx, false) + numberFormatXml(label.numberFormat) + shapePropertiesXml(context, label.spPr) + textBodyXml(context, label.txPr) + raw(context, label.extLst)
|
|
4518
|
+
);
|
|
4519
|
+
}
|
|
4520
|
+
function trendlineXml(context, trendline) {
|
|
4521
|
+
return elementXml(
|
|
4522
|
+
"trendline",
|
|
4523
|
+
(trendline.name === void 0 ? "" : `<c:name>${escapeText(trendline.name)}</c:name>`) + shapePropertiesXml(context, trendline.spPr) + valXml("trendlineType", trendline.trendlineType ?? "linear") + valXml("order", trendline.order) + valXml("period", trendline.period) + valXml("forward", trendline.forward) + valXml("backward", trendline.backward) + valXml("intercept", trendline.intercept) + valXml("dispRSqr", trendline.displayRSquared) + valXml("dispEq", trendline.displayEquation) + trendlineLabelXml(context, trendline.label) + raw(context, trendline.extLst)
|
|
4524
|
+
);
|
|
4525
|
+
}
|
|
4526
|
+
function errorBarsXml(context, bars2) {
|
|
4527
|
+
return elementXml(
|
|
4528
|
+
"errBars",
|
|
4529
|
+
valXml("errDir", bars2.direction) + valXml("errBarType", bars2.barType ?? "both") + valXml("errValType", bars2.valueType ?? "fixedVal") + valXml("noEndCap", bars2.noEndCap) + dataSourceXml("plus", bars2.plus) + dataSourceXml("minus", bars2.minus) + valXml("val", bars2.value) + shapePropertiesXml(context, bars2.spPr) + raw(context, bars2.extLst)
|
|
4530
|
+
);
|
|
4531
|
+
}
|
|
4532
|
+
var seriesAnalysisXml = (context, series) => (series.trendlines ?? []).map((trendline) => trendlineXml(context, trendline)).join("") + (series.errorBars ?? []).map((bars2) => errorBarsXml(context, bars2)).join("");
|
|
4533
|
+
|
|
3570
4534
|
// chart/write-series.ts
|
|
3571
4535
|
function markerXml(context, marker) {
|
|
3572
4536
|
if (!marker) return "";
|
|
@@ -3584,38 +4548,38 @@ function dataPointXml(context, point) {
|
|
|
3584
4548
|
function seriesXml(context, series, position) {
|
|
3585
4549
|
return elementXml(
|
|
3586
4550
|
"ser",
|
|
3587
|
-
valXml("idx", series.index ?? position) + valXml("order", series.order ?? position) + chartTextXml(context, series.tx, true) + shapePropertiesXml(context, series.spPr) + valXml("invertIfNegative", series.invertIfNegative) + markerXml(context, series.marker) + valXml("explosion", series.explosion) + series.dataPoints.map((point) => dataPointXml(context, point)).join("") + dataLabelsXml(context, series.dataLabels) + dataSourceXml("cat", series.categories) + dataSourceXml("val", series.values) + dataSourceXml("xVal", series.xValues) + dataSourceXml("yVal", series.yValues) + dataSourceXml("bubbleSize", series.bubbleSizes) + valXml("smooth", series.smooth) + valXml("shape", series.shape) + valXml("bubble3D", series.bubble3D) + raw(context, series.extLst)
|
|
4551
|
+
valXml("idx", series.index ?? position) + valXml("order", series.order ?? position) + chartTextXml(context, series.tx, true) + shapePropertiesXml(context, series.spPr) + valXml("invertIfNegative", series.invertIfNegative) + markerXml(context, series.marker) + valXml("explosion", series.explosion) + series.dataPoints.map((point) => dataPointXml(context, point)).join("") + dataLabelsXml(context, series.dataLabels) + seriesAnalysisXml(context, series) + dataSourceXml("cat", series.categories) + dataSourceXml("val", series.values) + dataSourceXml("xVal", series.xValues) + dataSourceXml("yVal", series.yValues) + dataSourceXml("bubbleSize", series.bubbleSizes) + valXml("smooth", series.smooth) + valXml("shape", series.shape) + valXml("bubble3D", series.bubble3D) + raw(context, series.extLst)
|
|
3588
4552
|
);
|
|
3589
4553
|
}
|
|
3590
4554
|
|
|
3591
4555
|
// chart/write-plot.ts
|
|
3592
|
-
var linesXml = (context, local,
|
|
4556
|
+
var linesXml = (context, local, present2, shape) => present2 ? elementXml(local, shapePropertiesXml(context, shape)) : "";
|
|
3593
4557
|
var barsXml = (context, local, bars2) => bars2 ? elementXml(local, shapePropertiesXml(context, bars2.spPr)) : "";
|
|
3594
|
-
function upDownBarsXml(context,
|
|
3595
|
-
if (!
|
|
4558
|
+
function upDownBarsXml(context, group2) {
|
|
4559
|
+
if (!group2.upDownBars) return "";
|
|
3596
4560
|
return elementXml(
|
|
3597
4561
|
"upDownBars",
|
|
3598
|
-
valXml("gapWidth",
|
|
4562
|
+
valXml("gapWidth", group2.upDownBarsGapWidth) + barsXml(context, "upBars", group2.upBars) + barsXml(context, "downBars", group2.downBars)
|
|
3599
4563
|
);
|
|
3600
4564
|
}
|
|
3601
|
-
function groupElement(
|
|
3602
|
-
if (Object.hasOwn(CHART_GROUP_ELEMENTS,
|
|
4565
|
+
function groupElement(group2) {
|
|
4566
|
+
if (Object.hasOwn(CHART_GROUP_ELEMENTS, group2.element)) return group2.element;
|
|
3603
4567
|
const match = Object.entries(CHART_GROUP_ELEMENTS).find(
|
|
3604
|
-
([, value]) => value.kind ===
|
|
4568
|
+
([, value]) => value.kind === group2.kind && value.is3D === group2.is3D
|
|
3605
4569
|
);
|
|
3606
|
-
if (!match) throw new Error(`No chart group element for ${
|
|
4570
|
+
if (!match) throw new Error(`No chart group element for ${group2.kind}`);
|
|
3607
4571
|
return match[0];
|
|
3608
4572
|
}
|
|
3609
|
-
function groupXml(context,
|
|
4573
|
+
function groupXml(context, group2) {
|
|
3610
4574
|
return elementXml(
|
|
3611
|
-
groupElement(
|
|
3612
|
-
valXml("ofPieType",
|
|
4575
|
+
groupElement(group2),
|
|
4576
|
+
valXml("ofPieType", group2.ofPieType) + valXml("scatterStyle", group2.scatterStyle) + valXml("radarStyle", group2.radarStyle) + valXml("wireframe", group2.wireframe) + valXml("barDir", group2.barDirection) + valXml("grouping", group2.grouping) + valXml("varyColors", group2.varyColors) + group2.series.map((series, position) => seriesXml(context, series, position)).join("") + dataLabelsXml(context, group2.dataLabels) + valXml("gapWidth", group2.gapWidth) + valXml("overlap", group2.overlap) + linesXml(context, "dropLines", group2.dropLines, group2.dropLinesSpPr) + linesXml(context, "hiLowLines", group2.hiLowLines, group2.hiLowLinesSpPr) + upDownBarsXml(context, group2) + valXml("marker", group2.marker) + valXml("smooth", group2.smooth) + valXml("gapDepth", group2.gapDepth) + valXml("shape", group2.shape) + valXml("firstSliceAng", group2.firstSliceAngle) + valXml("holeSize", group2.holeSize) + valXml("bubble3D", group2.bubble3D) + valXml("bubbleScale", group2.bubbleScale) + valXml("showNegBubbles", group2.showNegativeBubbles) + valXml("sizeRepresents", group2.sizeRepresents) + linesXml(context, "serLines", group2.seriesLines, group2.seriesLinesSpPr) + group2.axisIds.map((id) => valXml("axId", id)).join("") + raw(context, group2.extLst)
|
|
3613
4577
|
);
|
|
3614
4578
|
}
|
|
3615
4579
|
function plotAreaXml(context, plotArea) {
|
|
3616
4580
|
return elementXml(
|
|
3617
4581
|
"plotArea",
|
|
3618
|
-
layoutXml(context, plotArea.layout) + plotArea.groups.map((
|
|
4582
|
+
layoutXml(context, plotArea.layout) + plotArea.groups.map((group2) => groupXml(context, group2)).join("") + plotArea.axes.map((axis) => axisXml(context, axis)).join("") + dataTableXml(context, plotArea.dataTable) + shapePropertiesXml(context, plotArea.spPr) + raw(context, plotArea.extLst)
|
|
3619
4583
|
);
|
|
3620
4584
|
}
|
|
3621
4585
|
|
|
@@ -3671,6 +4635,46 @@ function writeChartSpace(space, options = {}) {
|
|
|
3671
4635
|
return `${DECLARATION2}${breakAfter}<c:chartSpace${declarations}>${body}</c:chartSpace>`;
|
|
3672
4636
|
}
|
|
3673
4637
|
|
|
4638
|
+
// chart/render/summary-analysis.ts
|
|
4639
|
+
function summaryTrendline(source) {
|
|
4640
|
+
const kind = chartTrendlineKind(source.trendlineType);
|
|
4641
|
+
if (!kind) return void 0;
|
|
4642
|
+
const out = { kind };
|
|
4643
|
+
if (source.order !== void 0) out.order = source.order;
|
|
4644
|
+
if (source.period !== void 0) out.period = source.period;
|
|
4645
|
+
if (source.forward !== void 0) out.forward = source.forward;
|
|
4646
|
+
if (source.backward !== void 0) out.backward = source.backward;
|
|
4647
|
+
if (source.intercept !== void 0) out.intercept = source.intercept;
|
|
4648
|
+
if (source.name !== void 0) out.name = source.name;
|
|
4649
|
+
if (source.spPr?.line) out.line = source.spPr.line;
|
|
4650
|
+
return out;
|
|
4651
|
+
}
|
|
4652
|
+
var amounts = (source) => chartSourceValues(source).map((value) => typeof value === "number" ? value : 0);
|
|
4653
|
+
function summaryErrorBars(source) {
|
|
4654
|
+
if (!source.valueType) return void 0;
|
|
4655
|
+
const out = {
|
|
4656
|
+
direction: source.direction ?? "y",
|
|
4657
|
+
barType: source.barType ?? "both",
|
|
4658
|
+
valueType: source.valueType
|
|
4659
|
+
};
|
|
4660
|
+
if (source.value !== void 0) out.value = source.value;
|
|
4661
|
+
if (source.valueType === "cust") {
|
|
4662
|
+
out.customPlus = amounts(source.plus);
|
|
4663
|
+
out.customMinus = amounts(source.minus);
|
|
4664
|
+
}
|
|
4665
|
+
if (source.noEndCap !== void 0) out.noEndCap = source.noEndCap;
|
|
4666
|
+
if (source.spPr?.line) out.line = source.spPr.line;
|
|
4667
|
+
return out;
|
|
4668
|
+
}
|
|
4669
|
+
function summaryAnalysis(series) {
|
|
4670
|
+
const trendlines2 = (series.trendlines ?? []).map(summaryTrendline).filter((entry3) => entry3 !== void 0);
|
|
4671
|
+
const errorBars = (series.errorBars ?? []).map(summaryErrorBars).filter((entry3) => entry3 !== void 0);
|
|
4672
|
+
return {
|
|
4673
|
+
...trendlines2.length ? { trendlines: trendlines2 } : {},
|
|
4674
|
+
...errorBars.length ? { errorBars } : {}
|
|
4675
|
+
};
|
|
4676
|
+
}
|
|
4677
|
+
|
|
3674
4678
|
// chart/render/summary-from-space.ts
|
|
3675
4679
|
var solidColor = (fill) => fill?.kind === "solid" ? fill.color : void 0;
|
|
3676
4680
|
var isSolidFill = (fill) => fill?.kind === "solid" || fill?.kind === "unsupported" && fill.element === "solidFill";
|
|
@@ -3691,12 +4695,15 @@ var GROUPINGS = /* @__PURE__ */ new Set(["clustered", "stacked", "percentStacked
|
|
|
3691
4695
|
function chartSummarySeries(source, chartType) {
|
|
3692
4696
|
const categories = source.categories ?? source.xValues;
|
|
3693
4697
|
const values = source.values ?? source.yValues;
|
|
4698
|
+
const numeric = (v) => typeof v === "number" ? v : v === "" ? null : Number.isFinite(Number(v)) ? Number(v) : null;
|
|
3694
4699
|
const out = {
|
|
3695
4700
|
categories: chartSourceValues(categories),
|
|
3696
|
-
values: chartSourceValues(values).map(
|
|
3697
|
-
(v) => typeof v === "number" ? v : v === "" ? null : Number.isFinite(Number(v)) ? Number(v) : null
|
|
3698
|
-
)
|
|
4701
|
+
values: chartSourceValues(values).map(numeric)
|
|
3699
4702
|
};
|
|
4703
|
+
if (source.bubbleSizes) {
|
|
4704
|
+
out.bubbleSizes = chartSourceValues(source.bubbleSizes).map(numeric);
|
|
4705
|
+
if (source.bubbleSizes.formula) out.bubbleSizesRef = source.bubbleSizes.formula;
|
|
4706
|
+
}
|
|
3700
4707
|
if (source.tx?.text !== void 0) out.name = source.tx.text;
|
|
3701
4708
|
const nameRef = source.tx?.reference?.formula;
|
|
3702
4709
|
if (nameRef) out.nameRef = nameRef;
|
|
@@ -3721,50 +4728,446 @@ function chartSummarySeries(source, chartType) {
|
|
|
3721
4728
|
}
|
|
3722
4729
|
if (Object.keys(points).length) out.pointColors = points;
|
|
3723
4730
|
if (Object.keys(pointFills).length) out.pointFills = pointFills;
|
|
4731
|
+
Object.assign(out, summaryAnalysis(source));
|
|
4732
|
+
return out;
|
|
4733
|
+
}
|
|
4734
|
+
function valueAxisId(chartSpace, axisIds) {
|
|
4735
|
+
return axisIds.find(
|
|
4736
|
+
(id) => chartSpace.plotArea.axes.some((a2) => a2.id === id && a2.kind === "val")
|
|
4737
|
+
);
|
|
4738
|
+
}
|
|
4739
|
+
function stockStyle(group2) {
|
|
4740
|
+
return {
|
|
4741
|
+
...group2.hiLowLinesSpPr ? { hiLowLines: group2.hiLowLinesSpPr } : {},
|
|
4742
|
+
...group2.upBars?.spPr ? { upBars: group2.upBars.spPr } : {},
|
|
4743
|
+
...group2.downBars?.spPr ? { downBars: group2.downBars.spPr } : {},
|
|
4744
|
+
...group2.upDownBarsGapWidth === void 0 ? {} : { gapWidth: group2.upDownBarsGapWidth }
|
|
4745
|
+
};
|
|
4746
|
+
}
|
|
4747
|
+
function extraGroups(chartSpace, firstType) {
|
|
4748
|
+
const [first2, ...rest] = chartSpace.plotArea.groups;
|
|
4749
|
+
if (!first2 || !["column", "line", "area"].includes(firstType)) return [];
|
|
4750
|
+
const primary = valueAxisId(chartSpace, first2.axisIds);
|
|
4751
|
+
const out = [];
|
|
4752
|
+
for (const group2 of rest) {
|
|
4753
|
+
const stockOverColumns = group2.kind === "stock" && firstType === "column";
|
|
4754
|
+
if (group2.is3D || !(["bar", "line", "area"].includes(group2.kind) || stockOverColumns)) continue;
|
|
4755
|
+
const type = group2.kind === "bar" ? "column" : group2.kind;
|
|
4756
|
+
const entry3 = {
|
|
4757
|
+
chartType: type,
|
|
4758
|
+
series: group2.series.map((source) => chartSummarySeries(source, type)),
|
|
4759
|
+
secondary: valueAxisId(chartSpace, group2.axisIds) !== primary
|
|
4760
|
+
};
|
|
4761
|
+
if (group2.grouping && GROUPINGS.has(group2.grouping))
|
|
4762
|
+
entry3.grouping = group2.grouping;
|
|
4763
|
+
if (type === "stock") entry3.stock = stockStyle(group2);
|
|
4764
|
+
if (type === "column") {
|
|
4765
|
+
if (group2.gapWidth !== void 0) entry3.barGapWidth = group2.gapWidth;
|
|
4766
|
+
if (group2.overlap !== void 0) entry3.barOverlap = group2.overlap;
|
|
4767
|
+
}
|
|
4768
|
+
if (entry3.series.length) out.push(entry3);
|
|
4769
|
+
}
|
|
4770
|
+
return out;
|
|
4771
|
+
}
|
|
4772
|
+
function chartSummaryFromSpace(chartSpace, extras = {}) {
|
|
4773
|
+
const group2 = chartSpace.plotArea.groups[0];
|
|
4774
|
+
let chartType = group2 ? GROUP_TYPES[group2.kind] : "column";
|
|
4775
|
+
if (chartType === "bar" && group2?.barDirection !== "bar") chartType = "column";
|
|
4776
|
+
const series = (group2?.series ?? []).map((source) => chartSummarySeries(source, chartType));
|
|
4777
|
+
const summary = {
|
|
4778
|
+
chartType,
|
|
4779
|
+
series,
|
|
4780
|
+
showLegend: chartSpace.legend !== void 0
|
|
4781
|
+
};
|
|
4782
|
+
const combined = extraGroups(chartSpace, chartType);
|
|
4783
|
+
if (combined.length) summary.extraGroups = combined;
|
|
4784
|
+
if (chartType === "stock" && group2) summary.stock = stockStyle(group2);
|
|
4785
|
+
if (chartType === "bubble" && group2) {
|
|
4786
|
+
const sizeRepresents = group2.sizeRepresents === "w" ? "w" : "area";
|
|
4787
|
+
summary.bubble = {
|
|
4788
|
+
sizeRepresents,
|
|
4789
|
+
...group2.bubbleScale === void 0 ? {} : { bubbleScale: group2.bubbleScale },
|
|
4790
|
+
showNegativeBubbles: group2.showNegativeBubbles === true
|
|
4791
|
+
};
|
|
4792
|
+
}
|
|
4793
|
+
const grouping = group2?.grouping;
|
|
4794
|
+
if (grouping && GROUPINGS.has(grouping))
|
|
4795
|
+
summary.grouping = grouping;
|
|
4796
|
+
if (chartType === "bar" || chartType === "column") {
|
|
4797
|
+
for (const [value, field, fallback, min, max] of [
|
|
4798
|
+
[group2?.gapWidth, "barGapWidth", 150, 0, 500],
|
|
4799
|
+
[group2?.overlap, "barOverlap", 0, -100, 100]
|
|
4800
|
+
]) {
|
|
4801
|
+
const resolved = value ?? fallback;
|
|
4802
|
+
if (Number.isInteger(resolved) && resolved >= min && resolved <= max)
|
|
4803
|
+
summary[field] = resolved;
|
|
4804
|
+
}
|
|
4805
|
+
}
|
|
4806
|
+
if (chartSpace.title && chartSpace.autoTitleDeleted !== true) {
|
|
4807
|
+
const title = chartSpace.title.text;
|
|
4808
|
+
if (title !== void 0) summary.title = title;
|
|
4809
|
+
else if (series.length === 1 && series[0]?.name) summary.title = series[0].name;
|
|
4810
|
+
}
|
|
4811
|
+
const legendPos = chartSpace.legend?.position;
|
|
4812
|
+
if (legendPos && ["r", "l", "t", "b", "tr"].includes(legendPos))
|
|
4813
|
+
summary.legendPosition = legendPos;
|
|
4814
|
+
if (extras.formatting) summary.formatting = extras.formatting;
|
|
4815
|
+
if (extras.colorPalette !== void 0) summary.colorPalette = extras.colorPalette;
|
|
4816
|
+
if (extras.styleDefinition) summary.styleDefinition = extras.styleDefinition;
|
|
4817
|
+
return summary;
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4820
|
+
// chart/render/summary-from-chartex.ts
|
|
4821
|
+
var cx = (parent, local) => first(parent, local, NS.cx);
|
|
4822
|
+
var text = (element) => (element?.textContent ?? "").trim();
|
|
4823
|
+
function scalar(parent, local) {
|
|
4824
|
+
const element = cx(parent, local);
|
|
4825
|
+
if (!element) return void 0;
|
|
4826
|
+
return element.hasAttribute("val") ? element.getAttribute("val") ?? "" : text(element);
|
|
4827
|
+
}
|
|
4828
|
+
function seriesData(root, series) {
|
|
4829
|
+
const inline = cx(series, "data");
|
|
4830
|
+
if (inline) return inline;
|
|
4831
|
+
const id = cx(series, "dataId")?.getAttribute("val");
|
|
4832
|
+
const shared = children(cx(root, "chartData") ?? root, "data", NS.cx);
|
|
4833
|
+
return id === null || id === void 0 ? shared[0] : shared.find((d) => d.getAttribute("id") === id);
|
|
4834
|
+
}
|
|
4835
|
+
function dimension(data, kind, type) {
|
|
4836
|
+
const all = data ? children(data, kind, NS.cx) : [];
|
|
4837
|
+
const element = all.find((d) => (d.getAttribute("type") ?? "") === type) ?? void 0;
|
|
4838
|
+
if (!element) return void 0;
|
|
4839
|
+
const out = { points: [] };
|
|
4840
|
+
const formula = text(cx(element, "f"));
|
|
4841
|
+
if (formula) out.formula = formula;
|
|
4842
|
+
const level = cx(element, "lvl");
|
|
4843
|
+
const count = Number(level?.getAttribute("ptCount") ?? 0);
|
|
4844
|
+
for (const point of level ? children(level, "pt", NS.cx) : []) {
|
|
4845
|
+
const index = Number(point.getAttribute("idx") ?? out.points.length);
|
|
4846
|
+
if (Number.isInteger(index) && index >= 0) out.points[index] = text(point);
|
|
4847
|
+
}
|
|
4848
|
+
for (let i = 0; i < Math.max(count, out.points.length); i++) out.points[i] ??= "";
|
|
4849
|
+
return out;
|
|
4850
|
+
}
|
|
4851
|
+
function categoryLevels(data) {
|
|
4852
|
+
const element = data ? children(data, "strDim", NS.cx).find((d) => (d.getAttribute("type") ?? "") === "cat") : void 0;
|
|
4853
|
+
return (element ? children(element, "lvl", NS.cx) : []).map((level) => {
|
|
4854
|
+
const points = [];
|
|
4855
|
+
const count = Number(level.getAttribute("ptCount") ?? 0);
|
|
4856
|
+
for (const point of children(level, "pt", NS.cx)) {
|
|
4857
|
+
const index = Number(point.getAttribute("idx") ?? points.length);
|
|
4858
|
+
if (Number.isInteger(index) && index >= 0) points[index] = text(point);
|
|
4859
|
+
}
|
|
4860
|
+
for (let i = 0; i < Math.max(count, points.length); i++) points[i] ??= "";
|
|
4861
|
+
return points;
|
|
4862
|
+
});
|
|
4863
|
+
}
|
|
4864
|
+
function titleOf(chart) {
|
|
4865
|
+
const tx = cx(cx(chart, "title"), "tx");
|
|
4866
|
+
const data = text(cx(cx(tx, "txData"), "v"));
|
|
4867
|
+
if (data) return data;
|
|
4868
|
+
const rich = cx(tx, "rich");
|
|
4869
|
+
if (!rich) return void 0;
|
|
4870
|
+
const runs = Array.from(rich.getElementsByTagNameNS(NS.a, "t")).map((t) => t.textContent ?? "");
|
|
4871
|
+
return runs.join("") || void 0;
|
|
4872
|
+
}
|
|
4873
|
+
function seriesFill(series) {
|
|
4874
|
+
const fill = parseDrawingFill(cx(series, "spPr"));
|
|
4875
|
+
const color = fill?.kind === "solid" ? fill.color : void 0;
|
|
4876
|
+
return color ? { drawingColor: color } : {};
|
|
4877
|
+
}
|
|
4878
|
+
function numberOf(value) {
|
|
4879
|
+
const parsed = Number.parseFloat(value ?? "");
|
|
4880
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
4881
|
+
}
|
|
4882
|
+
function histogramOptions(layoutPr) {
|
|
4883
|
+
const binning = cx(layoutPr, "binning");
|
|
4884
|
+
const out = {};
|
|
4885
|
+
const size = numberOf(scalar(binning, "binSize"));
|
|
4886
|
+
const count = numberOf(scalar(binning, "binCount"));
|
|
4887
|
+
if (size !== void 0) out.binSize = size;
|
|
4888
|
+
if (count !== void 0 && count >= 0) out.binCount = Math.trunc(count);
|
|
4889
|
+
const closed = binning?.getAttribute("intervalClosed");
|
|
4890
|
+
if (closed === "l" || closed === "r") out.intervalClosed = closed;
|
|
4891
|
+
for (const key of ["underflow", "overflow"]) {
|
|
4892
|
+
const raw2 = binning?.getAttribute(key);
|
|
4893
|
+
if (raw2 === "auto") out[key] = "auto";
|
|
4894
|
+
else if (raw2 !== null && raw2 !== void 0 && numberOf(raw2) !== void 0)
|
|
4895
|
+
out[key] = numberOf(raw2);
|
|
4896
|
+
}
|
|
4897
|
+
if (cx(layoutPr, "aggregation")) out.aggregateByCategory = true;
|
|
3724
4898
|
return out;
|
|
3725
4899
|
}
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
if (
|
|
3730
|
-
const
|
|
3731
|
-
const
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
4900
|
+
var LEGEND_POSITIONS = ["r", "l", "t", "b", "tr"];
|
|
4901
|
+
function chartExSummary(source) {
|
|
4902
|
+
const root = typeof source === "string" ? parseXml(source, { label: "Chart part" }).documentElement : source;
|
|
4903
|
+
if (root.localName !== "chartSpace" || root.namespaceURI !== NS.cx) return void 0;
|
|
4904
|
+
const chart = cx(root, "chart");
|
|
4905
|
+
const region = cx(cx(chart, "plotArea"), "plotAreaRegion");
|
|
4906
|
+
const all = region ? children(region, "series", NS.cx) : [];
|
|
4907
|
+
const primary = all.find((s) => s.getAttribute("layoutId") !== "paretoLine") ?? all[0];
|
|
4908
|
+
const layoutId = primary?.getAttribute("layoutId") ?? "";
|
|
4909
|
+
const chartType = layoutId === "waterfall" ? "waterfall" : layoutId === "clusteredColumn" ? "histogram" : layoutId === "treemap" || layoutId === "sunburst" ? layoutId : void 0;
|
|
4910
|
+
if (!primary || !chartType) return { layoutId };
|
|
4911
|
+
const data = seriesData(root, primary);
|
|
4912
|
+
const categories = dimension(data, "strDim", "cat");
|
|
4913
|
+
const values = dimension(
|
|
4914
|
+
data,
|
|
4915
|
+
"numDim",
|
|
4916
|
+
chartType === "treemap" || chartType === "sunburst" ? "size" : "val"
|
|
4917
|
+
);
|
|
4918
|
+
const txData = cx(cx(primary, "tx"), "txData");
|
|
4919
|
+
const series = {
|
|
4920
|
+
categories: categories?.points ?? [],
|
|
4921
|
+
values: (values?.points ?? []).map(
|
|
4922
|
+
(p) => p !== "" && Number.isFinite(Number(p)) ? Number(p) : null
|
|
4923
|
+
),
|
|
4924
|
+
...seriesFill(primary)
|
|
4925
|
+
};
|
|
4926
|
+
const name = text(cx(txData, "v"));
|
|
4927
|
+
if (name) series.name = name;
|
|
4928
|
+
const nameRef = text(cx(txData, "f"));
|
|
4929
|
+
if (nameRef) series.nameRef = nameRef;
|
|
4930
|
+
if (categories?.formula) series.categoriesRef = categories.formula;
|
|
4931
|
+
if (values?.formula) series.valuesRef = values.formula;
|
|
4932
|
+
const layoutPr = cx(primary, "layoutPr");
|
|
4933
|
+
const legend = cx(chart, "legend");
|
|
4934
|
+
const summary = { chartType, series: [series], showLegend: legend !== void 0 };
|
|
4935
|
+
summary.formatting = {
|
|
4936
|
+
builtInStyle: 2,
|
|
4937
|
+
sourceXml: "",
|
|
4938
|
+
entries: {
|
|
4939
|
+
title: {
|
|
4940
|
+
fontSize: 14,
|
|
4941
|
+
bold: false,
|
|
4942
|
+
textColor: {
|
|
4943
|
+
kind: "scheme",
|
|
4944
|
+
value: "tx1",
|
|
4945
|
+
transforms: [
|
|
4946
|
+
{ name: "lumMod", value: "65000" },
|
|
4947
|
+
{ name: "lumOff", value: "35000" }
|
|
4948
|
+
]
|
|
4949
|
+
},
|
|
4950
|
+
sourceXml: ""
|
|
4951
|
+
}
|
|
4952
|
+
}
|
|
4953
|
+
};
|
|
4954
|
+
const title = titleOf(chart);
|
|
4955
|
+
if (title) summary.title = title;
|
|
4956
|
+
const position = legend?.getAttribute("pos");
|
|
4957
|
+
if (position && LEGEND_POSITIONS.includes(position))
|
|
4958
|
+
summary.legendPosition = position;
|
|
4959
|
+
if (chartType === "waterfall") {
|
|
4960
|
+
const subtotals = cx(layoutPr, "subtotals");
|
|
4961
|
+
const connectors = cx(layoutPr, "visibility")?.getAttribute("connectorLines");
|
|
4962
|
+
summary.waterfall = {
|
|
4963
|
+
...subtotals ? {
|
|
4964
|
+
subtotalIndices: children(subtotals, "idx", NS.cx).map((idx) => Number.parseInt(idx.getAttribute("val") ?? "", 10)).filter((idx) => Number.isInteger(idx) && idx >= 0)
|
|
4965
|
+
} : {},
|
|
4966
|
+
...connectors === "0" || connectors === "false" ? { connectorLines: false } : {}
|
|
4967
|
+
};
|
|
4968
|
+
} else if (chartType === "treemap" || chartType === "sunburst") {
|
|
4969
|
+
const layout = cx(layoutPr, "parentLabelLayout")?.getAttribute("val");
|
|
4970
|
+
summary.hierarchy = {
|
|
4971
|
+
levels: categoryLevels(data),
|
|
4972
|
+
dataLabels: cx(primary, "dataLabels") !== void 0,
|
|
4973
|
+
...layout === "none" || layout === "banner" || layout === "overlapping" ? { parentLabelLayout: layout } : {}
|
|
4974
|
+
};
|
|
4975
|
+
} else summary.histogram = histogramOptions(layoutPr);
|
|
4976
|
+
return { layoutId, summary };
|
|
4977
|
+
}
|
|
4978
|
+
|
|
4979
|
+
// drawingml/theme-color.ts
|
|
4980
|
+
function themeSlotHex(color) {
|
|
4981
|
+
if (!color) return void 0;
|
|
4982
|
+
const value = color.kind === "srgb" ? color.value : color.kind === "system" ? color.fallback : void 0;
|
|
4983
|
+
return value ? value.toUpperCase() : void 0;
|
|
4984
|
+
}
|
|
4985
|
+
|
|
4986
|
+
// chart/render/chart-svg-util.ts
|
|
4987
|
+
var TEXT_COLOR = "#595959";
|
|
4988
|
+
var GRID_COLOR = "#D9D9D9";
|
|
4989
|
+
var AXIS_COLOR = "#BFBFBF";
|
|
4990
|
+
var FONT_SIZE = 10;
|
|
4991
|
+
function esc(text3) {
|
|
4992
|
+
return text3.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4993
|
+
}
|
|
4994
|
+
var n = (value) => String(Math.round(value * 100) / 100);
|
|
4995
|
+
var textWidth = (text3, size = FONT_SIZE) => text3.length * size * 0.55;
|
|
4996
|
+
function text2(x, y, content, attrs = {}) {
|
|
4997
|
+
const parts = [`x="${n(x)}"`, `y="${n(y)}"`];
|
|
4998
|
+
parts.push(`font-size="${attrs.size ?? FONT_SIZE}"`);
|
|
4999
|
+
parts.push(`fill="${esc(attrs.fill ?? TEXT_COLOR)}"`);
|
|
5000
|
+
if (attrs.anchor && attrs.anchor !== "start") parts.push(`text-anchor="${attrs.anchor}"`);
|
|
5001
|
+
if (attrs.weight) parts.push(`font-weight="${attrs.weight}"`);
|
|
5002
|
+
if (attrs.baseline) parts.push(`dominant-baseline="${attrs.baseline}"`);
|
|
5003
|
+
if (attrs.family) parts.push(`font-family="${esc(attrs.family)}"`);
|
|
5004
|
+
if (attrs.filter) parts.push(`filter="${esc(attrs.filter)}"`);
|
|
5005
|
+
if (attrs.italic !== void 0) parts.push(`font-style="${attrs.italic ? "italic" : "normal"}"`);
|
|
5006
|
+
if (attrs.underline !== void 0)
|
|
5007
|
+
parts.push(`text-decoration="${attrs.underline ? "underline" : "none"}"`);
|
|
5008
|
+
return `<text ${parts.join(" ")}>${esc(content)}</text>`;
|
|
5009
|
+
}
|
|
5010
|
+
var line = (x1, y1, x2, y2, stroke, width = 1) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" stroke="${stroke}" stroke-width="${width}"/>`;
|
|
5011
|
+
var rect = (x, y, w, h, fill, filter) => `<rect x="${n(x)}" y="${n(y)}" width="${n(Math.max(0, w))}" height="${n(Math.max(0, h))}" fill="${fill}"${filter ? ` filter="${esc(filter)}"` : ""}/>`;
|
|
5012
|
+
function fit(content, maxWidth, size = FONT_SIZE) {
|
|
5013
|
+
if (textWidth(content, size) <= maxWidth) return content;
|
|
5014
|
+
const chars = Math.max(1, Math.floor(maxWidth / (size * 0.55)) - 1);
|
|
5015
|
+
return `${content.slice(0, chars)}\u2026`;
|
|
5016
|
+
}
|
|
5017
|
+
|
|
5018
|
+
// chart/render/chart-spacing.ts
|
|
5019
|
+
function chartBarSpacing(chart) {
|
|
5020
|
+
const stacked = chart.grouping === "stacked" || chart.grouping === "percentStacked";
|
|
5021
|
+
return {
|
|
5022
|
+
barGapWidth: chart.barGapWidth ?? DEFAULT_BAR_GAP_WIDTH,
|
|
5023
|
+
barOverlap: chart.barOverlap ?? (stacked ? 100 : 0)
|
|
5024
|
+
};
|
|
5025
|
+
}
|
|
5026
|
+
|
|
5027
|
+
// chart/render/chart-svg-bars.ts
|
|
5028
|
+
function barLayout(model, frame) {
|
|
5029
|
+
const count = Math.max(1, model.series.length);
|
|
5030
|
+
const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
|
|
5031
|
+
const barSize = geometry.singleBarWidth;
|
|
5032
|
+
const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
|
|
5033
|
+
return { barSize, offset };
|
|
5034
|
+
}
|
|
5035
|
+
function bars(model, frame, out, values) {
|
|
5036
|
+
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
5037
|
+
const { barSize, offset: barOffset } = barLayout(model, frame);
|
|
5038
|
+
const base = frame.value(0);
|
|
5039
|
+
const pos = new Array(model.categories.length).fill(0);
|
|
5040
|
+
const neg = new Array(model.categories.length).fill(0);
|
|
5041
|
+
model.series.forEach((s, si) => {
|
|
5042
|
+
values[si]?.forEach((v, i) => {
|
|
5043
|
+
if (v === null || i >= model.categories.length) return;
|
|
5044
|
+
let from = 0;
|
|
5045
|
+
let to = v;
|
|
5046
|
+
if (stacked) {
|
|
5047
|
+
const acc = v >= 0 ? pos : neg;
|
|
5048
|
+
from = acc[i] ?? 0;
|
|
5049
|
+
to = from + v;
|
|
5050
|
+
acc[i] = to;
|
|
5051
|
+
}
|
|
5052
|
+
const a2 = stacked ? frame.value(from) : base;
|
|
5053
|
+
const b = frame.value(to);
|
|
5054
|
+
const offset = barOffset(si);
|
|
5055
|
+
const center = frame.band(i);
|
|
5056
|
+
const width = model.horizontal ? Math.abs(b - a2) : barSize;
|
|
5057
|
+
const height = model.horizontal ? barSize : Math.abs(b - a2);
|
|
5058
|
+
let color = s.pointColors?.[i] ?? s.color;
|
|
5059
|
+
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
5060
|
+
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
5061
|
+
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
5062
|
+
if (baseId) {
|
|
5063
|
+
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
5064
|
+
const def = buildChartGradientDef(id, gradient, {
|
|
5065
|
+
width: Number(n(width)),
|
|
5066
|
+
height: Number(n(height)),
|
|
5067
|
+
shape: "rect"
|
|
5068
|
+
});
|
|
5069
|
+
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
5070
|
+
color = `url(#${id})`;
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
5074
|
+
if (model.horizontal)
|
|
5075
|
+
out.push(
|
|
5076
|
+
rect(Math.min(a2, b), center + offset, Math.abs(b - a2), barSize, color, s.shadowFilter)
|
|
5077
|
+
);
|
|
5078
|
+
else
|
|
5079
|
+
out.push(
|
|
5080
|
+
rect(center + offset, Math.min(a2, b), barSize, Math.abs(b - a2), color, s.shadowFilter)
|
|
5081
|
+
);
|
|
5082
|
+
out.push("</g>");
|
|
5083
|
+
});
|
|
5084
|
+
});
|
|
5085
|
+
}
|
|
5086
|
+
|
|
5087
|
+
// chart/render/chart-svg-analysis.ts
|
|
5088
|
+
var DASHES = {
|
|
5089
|
+
dot: [1, 3],
|
|
5090
|
+
dash: [4, 3],
|
|
5091
|
+
lgDash: [8, 3],
|
|
5092
|
+
dashDot: [4, 3, 1, 3],
|
|
5093
|
+
lgDashDot: [8, 3, 1, 3],
|
|
5094
|
+
lgDashDotDot: [8, 3, 1, 3, 1, 3],
|
|
5095
|
+
sysDash: [3, 1],
|
|
5096
|
+
sysDot: [1, 1],
|
|
5097
|
+
sysDashDot: [3, 1, 1, 1],
|
|
5098
|
+
sysDashDotDot: [3, 1, 1, 1, 1, 1]
|
|
5099
|
+
};
|
|
5100
|
+
var CAP = 4;
|
|
5101
|
+
function strokeAttributes(stroke) {
|
|
5102
|
+
const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
|
|
5103
|
+
const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
|
|
5104
|
+
return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
|
|
5105
|
+
}
|
|
5106
|
+
var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
|
|
5107
|
+
function trendlines(series, si, xs, ys, plane, out) {
|
|
5108
|
+
for (const trendline of series.trendlines ?? []) {
|
|
5109
|
+
const fit2 = fitChartTrendline(trendline.fit, xs, ys);
|
|
5110
|
+
if (fit2.points.length < 2) continue;
|
|
5111
|
+
const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
|
|
5112
|
+
out.push(
|
|
5113
|
+
`<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
|
|
5114
|
+
);
|
|
3748
5115
|
}
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
5116
|
+
}
|
|
5117
|
+
function errorBar(bars2, at, values, plane, out) {
|
|
5118
|
+
const stroke = strokeAttributes(bars2.stroke);
|
|
5119
|
+
for (const side of ["plus", "minus"]) {
|
|
5120
|
+
if (bars2.barType !== side && bars2.barType !== "both") continue;
|
|
5121
|
+
const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
|
|
5122
|
+
const sign = side === "plus" ? 1 : -1;
|
|
5123
|
+
const [x1, y1] = plane(at.x, at.y);
|
|
5124
|
+
const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
|
|
5125
|
+
out.push(segment(x1, y1, x2, y2, stroke));
|
|
5126
|
+
if (!bars2.endCap) continue;
|
|
5127
|
+
if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
|
|
5128
|
+
else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
5131
|
+
function plottedPoints(series, xOf) {
|
|
5132
|
+
return series.values.flatMap((y, index) => {
|
|
5133
|
+
const x = xOf(index);
|
|
5134
|
+
return y === null || x === null ? [] : [{ x, y, index }];
|
|
5135
|
+
});
|
|
5136
|
+
}
|
|
5137
|
+
function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
|
|
5138
|
+
const points = plottedPoints(series, xOf);
|
|
5139
|
+
const xs = points.map((p) => p.x);
|
|
5140
|
+
const ys = points.map((p) => p.y);
|
|
5141
|
+
trendlines(series, si, xs, ys, plane, out);
|
|
5142
|
+
for (const bars2 of series.errorBars ?? []) {
|
|
5143
|
+
if (categoryAxis && bars2.direction === "x") continue;
|
|
5144
|
+
const values = bars2.direction === "x" ? xs : ys;
|
|
5145
|
+
points.forEach(
|
|
5146
|
+
(p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
|
|
5147
|
+
);
|
|
3753
5148
|
}
|
|
3754
|
-
const legendPos = chartSpace.legend?.position;
|
|
3755
|
-
if (legendPos && ["r", "l", "t", "b", "tr"].includes(legendPos))
|
|
3756
|
-
summary.legendPosition = legendPos;
|
|
3757
|
-
if (extras.formatting) summary.formatting = extras.formatting;
|
|
3758
|
-
if (extras.colorPalette !== void 0) summary.colorPalette = extras.colorPalette;
|
|
3759
|
-
if (extras.styleDefinition) summary.styleDefinition = extras.styleDefinition;
|
|
3760
|
-
return summary;
|
|
3761
5149
|
}
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
const
|
|
3767
|
-
|
|
5150
|
+
function categoryAnalysis(model, frame, out) {
|
|
5151
|
+
if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
|
|
5152
|
+
const plane = (x, y) => model.horizontal ? [frame.value(y), frame.band(x - 1)] : [frame.band(x - 1), frame.value(y)];
|
|
5153
|
+
const barred = model.type === "bar" || model.type === "column";
|
|
5154
|
+
const layout = barred ? barLayout(model, frame) : void 0;
|
|
5155
|
+
model.series.forEach((series, si) => {
|
|
5156
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
5157
|
+
const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
|
|
5158
|
+
const barPlane = (x, y) => {
|
|
5159
|
+
const [px, py] = plane(x, y);
|
|
5160
|
+
return model.horizontal ? [px, py + shift] : [px + shift, py];
|
|
5161
|
+
};
|
|
5162
|
+
seriesAnalysis(series, si, (i) => i + 1, plane, barPlane, true, out);
|
|
5163
|
+
});
|
|
5164
|
+
}
|
|
5165
|
+
function scatterAnalysis(model, px, py, out) {
|
|
5166
|
+
const plane = (x, y) => [px(x), py(y)];
|
|
5167
|
+
model.series.forEach((series, si) => {
|
|
5168
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
5169
|
+
seriesAnalysis(series, si, (i) => series.xValues?.[i] ?? null, plane, plane, false, out);
|
|
5170
|
+
});
|
|
3768
5171
|
}
|
|
3769
5172
|
|
|
3770
5173
|
// chart/render/chart-scale.ts
|
|
@@ -3833,36 +5236,47 @@ function formatAxisValue(value, percent = false) {
|
|
|
3833
5236
|
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
3834
5237
|
}
|
|
3835
5238
|
|
|
3836
|
-
//
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
return
|
|
5239
|
+
// drawingml/drawing-color-css.ts
|
|
5240
|
+
function drawingColorCss(value) {
|
|
5241
|
+
if (!value || value.alpha === 1) return value?.hex;
|
|
5242
|
+
const channels = [1, 3, 5].map(
|
|
5243
|
+
(offset) => Number.parseInt(value.hex.slice(offset, offset + 2), 16)
|
|
5244
|
+
);
|
|
5245
|
+
return `rgba(${channels.join(",")},${value.alpha})`;
|
|
3843
5246
|
}
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
if (
|
|
3853
|
-
|
|
3854
|
-
if (
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
5247
|
+
|
|
5248
|
+
// units/constants.ts
|
|
5249
|
+
var EMU_PER_PIXEL = 9525;
|
|
5250
|
+
var EMU_PER_POINT = 12700;
|
|
5251
|
+
|
|
5252
|
+
// drawingml/drawing-shadow.ts
|
|
5253
|
+
function resolveDrawingShadow(effects, theme) {
|
|
5254
|
+
const node = first(effects, "outerShdw", NS.a);
|
|
5255
|
+
if (!node) return void 0;
|
|
5256
|
+
const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
|
|
5257
|
+
if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
|
|
5258
|
+
return void 0;
|
|
5259
|
+
const color = parseDrawingColorIn(node);
|
|
5260
|
+
const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
|
|
5261
|
+
const blur = value("blurRad", 0) / EMU_PER_PIXEL;
|
|
5262
|
+
const distance = value("dist", 0) / EMU_PER_PIXEL;
|
|
5263
|
+
const angle = value("dir", 0) / 6e4 * Math.PI / 180;
|
|
5264
|
+
if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
|
|
5265
|
+
return void 0;
|
|
5266
|
+
return {
|
|
5267
|
+
color: resolved.hex,
|
|
5268
|
+
opacity: resolved.alpha,
|
|
5269
|
+
blur,
|
|
5270
|
+
dx: Math.cos(angle) * distance,
|
|
5271
|
+
dy: Math.sin(angle) * distance
|
|
5272
|
+
};
|
|
3859
5273
|
}
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
const
|
|
3865
|
-
return
|
|
5274
|
+
function resolveDrawingShadowXml(xml, theme) {
|
|
5275
|
+
return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
|
|
5276
|
+
}
|
|
5277
|
+
function svgDropShadowElement(s, format) {
|
|
5278
|
+
const num = format.number;
|
|
5279
|
+
return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
|
|
3866
5280
|
}
|
|
3867
5281
|
|
|
3868
5282
|
// chart/render/theme-palette.ts
|
|
@@ -3926,88 +5340,6 @@ function autoSeriesColor(theme, index) {
|
|
|
3926
5340
|
return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
|
|
3927
5341
|
}
|
|
3928
5342
|
|
|
3929
|
-
// drawingml/drawing-color-css.ts
|
|
3930
|
-
function drawingColorCss(value) {
|
|
3931
|
-
if (!value || value.alpha === 1) return value?.hex;
|
|
3932
|
-
const channels = [1, 3, 5].map(
|
|
3933
|
-
(offset) => Number.parseInt(value.hex.slice(offset, offset + 2), 16)
|
|
3934
|
-
);
|
|
3935
|
-
return `rgba(${channels.join(",")},${value.alpha})`;
|
|
3936
|
-
}
|
|
3937
|
-
|
|
3938
|
-
// chart/render/chart-value-axis.ts
|
|
3939
|
-
function valueAxis(model) {
|
|
3940
|
-
const stackable = model.type === "bar" || model.type === "column" || model.type === "line" || model.type === "area";
|
|
3941
|
-
if (stackable && model.grouping === "percentStacked")
|
|
3942
|
-
return { ...PERCENT_SCALE, ticks: [...PERCENT_SCALE.ticks], percent: true };
|
|
3943
|
-
let min = Infinity;
|
|
3944
|
-
let max = -Infinity;
|
|
3945
|
-
if (stackable && model.grouping === "stacked") {
|
|
3946
|
-
for (let i = 0; i < model.categories.length; i++) {
|
|
3947
|
-
let pos = 0;
|
|
3948
|
-
let neg = 0;
|
|
3949
|
-
for (const s of model.series) {
|
|
3950
|
-
const v = s.values[i] ?? 0;
|
|
3951
|
-
if (v >= 0) pos += v;
|
|
3952
|
-
else neg += v;
|
|
3953
|
-
}
|
|
3954
|
-
min = Math.min(min, neg);
|
|
3955
|
-
max = Math.max(max, pos);
|
|
3956
|
-
}
|
|
3957
|
-
} else {
|
|
3958
|
-
for (const s of model.series)
|
|
3959
|
-
for (const v of s.values)
|
|
3960
|
-
if (v !== null) {
|
|
3961
|
-
min = Math.min(min, v);
|
|
3962
|
-
max = Math.max(max, v);
|
|
3963
|
-
}
|
|
3964
|
-
}
|
|
3965
|
-
if (min === Infinity) {
|
|
3966
|
-
min = 0;
|
|
3967
|
-
max = 1;
|
|
3968
|
-
}
|
|
3969
|
-
return { ...niceScale(min, max), percent: false };
|
|
3970
|
-
}
|
|
3971
|
-
function categoryTotals(model) {
|
|
3972
|
-
return model.categories.map(
|
|
3973
|
-
(_, i) => model.series.reduce((sum, s) => sum + Math.abs(s.values[i] ?? 0), 0)
|
|
3974
|
-
);
|
|
3975
|
-
}
|
|
3976
|
-
|
|
3977
|
-
// units/constants.ts
|
|
3978
|
-
var EMU_PER_PIXEL = 9525;
|
|
3979
|
-
var EMU_PER_POINT = 12700;
|
|
3980
|
-
|
|
3981
|
-
// drawingml/drawing-shadow.ts
|
|
3982
|
-
function resolveDrawingShadow(effects, theme) {
|
|
3983
|
-
const node = first(effects, "outerShdw", NS.a);
|
|
3984
|
-
if (!node) return void 0;
|
|
3985
|
-
const value = (key, fallback) => Number(node.getAttribute(key) ?? fallback);
|
|
3986
|
-
if (value("sx", 1e5) !== 1e5 || value("sy", 1e5) !== 1e5 || value("kx", 0) !== 0 || value("ky", 0) !== 0)
|
|
3987
|
-
return void 0;
|
|
3988
|
-
const color = parseDrawingColorIn(node);
|
|
3989
|
-
const resolved = color && resolveDrawingColor(color, theme, { transformOrder: "document" });
|
|
3990
|
-
const blur = value("blurRad", 0) / EMU_PER_PIXEL;
|
|
3991
|
-
const distance = value("dist", 0) / EMU_PER_PIXEL;
|
|
3992
|
-
const angle = value("dir", 0) / 6e4 * Math.PI / 180;
|
|
3993
|
-
if (!resolved || ![blur, distance, angle].every(Number.isFinite) || blur < 0 || distance < 0)
|
|
3994
|
-
return void 0;
|
|
3995
|
-
return {
|
|
3996
|
-
color: resolved.hex,
|
|
3997
|
-
opacity: resolved.alpha,
|
|
3998
|
-
blur,
|
|
3999
|
-
dx: Math.cos(angle) * distance,
|
|
4000
|
-
dy: Math.sin(angle) * distance
|
|
4001
|
-
};
|
|
4002
|
-
}
|
|
4003
|
-
function resolveDrawingShadowXml(xml, theme) {
|
|
4004
|
-
return xml ? resolveDrawingShadow(parseXml(xml).documentElement, theme) : void 0;
|
|
4005
|
-
}
|
|
4006
|
-
function svgDropShadowElement(s, format) {
|
|
4007
|
-
const num = format.number;
|
|
4008
|
-
return `<feDropShadow dx="${num(s.dx)}" dy="${num(s.dy)}" stdDeviation="${num(s.blur / 2)}" flood-color="${format.color(s.color, "#000000")}" flood-opacity="${num(s.opacity)}" result="shadow"/>`;
|
|
4009
|
-
}
|
|
4010
|
-
|
|
4011
5343
|
// chart/text-inheritance.ts
|
|
4012
5344
|
var TEXT_KEYS = [
|
|
4013
5345
|
"fontSize",
|
|
@@ -4073,27 +5405,239 @@ function chartAppearance(chart, theme) {
|
|
|
4073
5405
|
{ scheme: (name) => scheme[name] },
|
|
4074
5406
|
{ hslRounding: "halfDown", transformOrder: "document" }
|
|
4075
5407
|
);
|
|
4076
|
-
const out = resolveChartStyleDefinition(
|
|
4077
|
-
{ entries},
|
|
4078
|
-
(color) => drawingColorCss(resolve(color))
|
|
4079
|
-
) ?? {};
|
|
4080
|
-
for (const part of CHART_STYLE_PARTS) {
|
|
4081
|
-
const entry3 = entries[part];
|
|
4082
|
-
if (!entry3) continue;
|
|
4083
|
-
const family = typeface(entry3, theme);
|
|
4084
|
-
const shadow = resolveDrawingShadowXml(entry3.textEffectsXml, {
|
|
4085
|
-
scheme: (name) => scheme[name]
|
|
4086
|
-
});
|
|
4087
|
-
if (shadow) (out[part] ??= {}).textShadow = shadow;
|
|
4088
|
-
if (family) (out[part] ??= {}).typeface = family;
|
|
4089
|
-
if (entry3.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry3.axisVisible;
|
|
4090
|
-
if (entry3.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry3.labelsVisible;
|
|
4091
|
-
if (entry3.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
|
|
4092
|
-
if (entry3.fill?.kind === "gradient") {
|
|
4093
|
-
(out[part] ??= {}).gradient = resolveChartGradient(entry3.fill, resolve);
|
|
5408
|
+
const out = resolveChartStyleDefinition(
|
|
5409
|
+
{ entries},
|
|
5410
|
+
(color) => drawingColorCss(resolve(color))
|
|
5411
|
+
) ?? {};
|
|
5412
|
+
for (const part of CHART_STYLE_PARTS) {
|
|
5413
|
+
const entry3 = entries[part];
|
|
5414
|
+
if (!entry3) continue;
|
|
5415
|
+
const family = typeface(entry3, theme);
|
|
5416
|
+
const shadow = resolveDrawingShadowXml(entry3.textEffectsXml, {
|
|
5417
|
+
scheme: (name) => scheme[name]
|
|
5418
|
+
});
|
|
5419
|
+
if (shadow) (out[part] ??= {}).textShadow = shadow;
|
|
5420
|
+
if (family) (out[part] ??= {}).typeface = family;
|
|
5421
|
+
if (entry3.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry3.axisVisible;
|
|
5422
|
+
if (entry3.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry3.labelsVisible;
|
|
5423
|
+
if (entry3.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
|
|
5424
|
+
if (entry3.fill?.kind === "gradient") {
|
|
5425
|
+
(out[part] ??= {}).gradient = resolveChartGradient(entry3.fill, resolve);
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
return out;
|
|
5429
|
+
}
|
|
5430
|
+
|
|
5431
|
+
// chart/render/chart-view-analysis.ts
|
|
5432
|
+
function strokeOf(line2, fallback, resolve) {
|
|
5433
|
+
if (line2?.fill?.kind === "none") return void 0;
|
|
5434
|
+
const color = (line2?.fill?.kind === "solid" ? resolve(line2.fill.color) : void 0) ?? fallback.color;
|
|
5435
|
+
const width = line2?.widthEmu === void 0 ? fallback.width : chartPointsToPixels(line2.widthEmu / 12700);
|
|
5436
|
+
const dash = line2?.dash ?? fallback.dash;
|
|
5437
|
+
return { color, width, ...dash && dash !== "solid" ? { dash } : {} };
|
|
5438
|
+
}
|
|
5439
|
+
function analysisView(source, seriesColor, resolve) {
|
|
5440
|
+
const plain = seriesColor === "none" || seriesColor.startsWith("url(") ? TEXT_COLOR : seriesColor;
|
|
5441
|
+
const trendlines2 = (source.trendlines ?? []).flatMap((entry3) => {
|
|
5442
|
+
const { name: _name, line: line2, ...fit2 } = entry3;
|
|
5443
|
+
const fallback = { color: plain, width: chartPointsToPixels(1.5), dash: "sysDot" };
|
|
5444
|
+
const stroke = strokeOf(line2, fallback, resolve);
|
|
5445
|
+
return stroke ? [{ fit: fit2, stroke }] : [];
|
|
5446
|
+
});
|
|
5447
|
+
const errorBars = (source.errorBars ?? []).flatMap((entry3) => {
|
|
5448
|
+
const { direction, barType, noEndCap, line: line2, ...amount } = entry3;
|
|
5449
|
+
const stroke = strokeOf(line2, { color: TEXT_COLOR, width: chartPointsToPixels(0.75) }, resolve);
|
|
5450
|
+
return stroke ? [{ direction, barType, amount, endCap: noEndCap !== true, stroke }] : [];
|
|
5451
|
+
});
|
|
5452
|
+
return {
|
|
5453
|
+
...trendlines2.length ? { trendlines: trendlines2 } : {},
|
|
5454
|
+
...errorBars.length ? { errorBars } : {}
|
|
5455
|
+
};
|
|
5456
|
+
}
|
|
5457
|
+
|
|
5458
|
+
// chart/render/chart-view-series.ts
|
|
5459
|
+
var isRefError = (value) => typeof value === "object" && value !== null && "error" in value;
|
|
5460
|
+
function toText(value) {
|
|
5461
|
+
if (value === null) return "";
|
|
5462
|
+
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
5463
|
+
if (isRefError(value)) return value.error;
|
|
5464
|
+
return String(value);
|
|
5465
|
+
}
|
|
5466
|
+
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
5467
|
+
function resolveRef(ref, evaluateRef) {
|
|
5468
|
+
if (!ref) return void 0;
|
|
5469
|
+
try {
|
|
5470
|
+
const values = evaluateRef(ref);
|
|
5471
|
+
return values.length ? values : void 0;
|
|
5472
|
+
} catch {
|
|
5473
|
+
return void 0;
|
|
5474
|
+
}
|
|
5475
|
+
}
|
|
5476
|
+
function seriesName(series, index, evaluateRef) {
|
|
5477
|
+
const fromRef = resolveRef(series.nameRef, evaluateRef)?.map(toText).filter((t) => t !== "").join(" ");
|
|
5478
|
+
return fromRef || series.name || `Series${index + 1}`;
|
|
5479
|
+
}
|
|
5480
|
+
function seriesContext(chart, theme, options) {
|
|
5481
|
+
const scheme = chartColorScheme(theme);
|
|
5482
|
+
const resolver = { scheme: (name) => scheme[name] };
|
|
5483
|
+
return {
|
|
5484
|
+
theme,
|
|
5485
|
+
scheme,
|
|
5486
|
+
palette: chart.colorPalette === void 0 ? void 0 : findChartColorPalette(chart.colorPalette),
|
|
5487
|
+
evaluateRef: options.evaluateRef ?? (() => []),
|
|
5488
|
+
seriesColor: options.seriesColor,
|
|
5489
|
+
drawingColor: (color) => color && drawingColorCss(resolveDrawingColor(color, resolver, { transformOrder: "document" })),
|
|
5490
|
+
gradient: (fill) => fill?.kind === "gradient" ? resolveChartGradient(
|
|
5491
|
+
fill,
|
|
5492
|
+
(color) => resolveDrawingColor(color, resolver, { transformOrder: "document" })
|
|
5493
|
+
) : void 0
|
|
5494
|
+
};
|
|
5495
|
+
}
|
|
5496
|
+
function seriesView(ctx, s, index, total, categoriesOf) {
|
|
5497
|
+
const { theme, scheme, palette, evaluateRef } = ctx;
|
|
5498
|
+
const values = resolveRef(s.valuesRef, evaluateRef)?.map(toNumber) ?? s.values.map(toNumber);
|
|
5499
|
+
categoriesOf(resolveRef(s.categoriesRef, evaluateRef) ?? s.categories);
|
|
5500
|
+
const paletteColor = palette && chartPaletteSeriesColor(palette, index, total, scheme);
|
|
5501
|
+
const color = s.fill?.kind === "none" ? "none" : ctx.drawingColor(s.fill?.kind === "solid" ? s.fill.color : s.drawingColor) ?? ctx.seriesColor?.(s, index) ?? paletteColor ?? autoSeriesColor(theme, index);
|
|
5502
|
+
const view = { name: seriesName(s, index, evaluateRef), values, color };
|
|
5503
|
+
const shadow = resolveDrawingShadowXml(s.effectsXml, { scheme: (name) => scheme[name] });
|
|
5504
|
+
if (shadow) view.shadow = shadow;
|
|
5505
|
+
const resolvedGradient = ctx.gradient(s.fill);
|
|
5506
|
+
if (resolvedGradient) view.gradient = resolvedGradient;
|
|
5507
|
+
const points = Object.fromEntries(
|
|
5508
|
+
Object.entries(s.pointFills ?? {}).flatMap(([key, fill]) => {
|
|
5509
|
+
const value = ctx.gradient(fill);
|
|
5510
|
+
return value ? [[key, value]] : [];
|
|
5511
|
+
})
|
|
5512
|
+
);
|
|
5513
|
+
if (Object.keys(points).length) view.pointGradients = points;
|
|
5514
|
+
Object.assign(view, analysisView(s, color, ctx.drawingColor));
|
|
5515
|
+
return view;
|
|
5516
|
+
}
|
|
5517
|
+
|
|
5518
|
+
// chart/render/chart-view-families.ts
|
|
5519
|
+
function bubbleView(chart, model, evaluateRef) {
|
|
5520
|
+
chart.series.forEach((source, i) => {
|
|
5521
|
+
const view = model.series[i];
|
|
5522
|
+
if (!view) return;
|
|
5523
|
+
const live = resolveRef(source.bubbleSizesRef, evaluateRef)?.map(toNumber);
|
|
5524
|
+
const sizes = live ?? source.bubbleSizes;
|
|
5525
|
+
if (sizes) view.sizes = sizes;
|
|
5526
|
+
});
|
|
5527
|
+
model.bubble = {
|
|
5528
|
+
sizeRepresents: chart.bubble?.sizeRepresents ?? "area",
|
|
5529
|
+
...chart.bubble?.bubbleScale === void 0 ? {} : { bubbleScale: chart.bubble.bubbleScale },
|
|
5530
|
+
showNegativeBubbles: chart.bubble?.showNegativeBubbles === true
|
|
5531
|
+
};
|
|
5532
|
+
}
|
|
5533
|
+
var columnNumber = (letters) => [...letters].reduce((n2, ch) => n2 * 26 + ch.charCodeAt(0) - 64, 0);
|
|
5534
|
+
function refColumns(ref) {
|
|
5535
|
+
const match = /\$?([A-Z]{1,3})\$?\d+:\$?([A-Z]{1,3})\$?\d+\s*$/i.exec(ref);
|
|
5536
|
+
if (!match) return 1;
|
|
5537
|
+
return Math.max(
|
|
5538
|
+
1,
|
|
5539
|
+
columnNumber((match[2] ?? "").toUpperCase()) - columnNumber((match[1] ?? "").toUpperCase()) + 1
|
|
5540
|
+
);
|
|
5541
|
+
}
|
|
5542
|
+
function liveLevels(ref, evaluateRef) {
|
|
5543
|
+
const columns = ref ? refColumns(ref) : 1;
|
|
5544
|
+
const flat = columns > 1 ? resolveRef(ref, evaluateRef)?.map(toText) : void 0;
|
|
5545
|
+
if (!flat || flat.length % columns !== 0) return void 0;
|
|
5546
|
+
const levels = Array.from({ length: columns }, () => []);
|
|
5547
|
+
flat.forEach((label, i) => levels[columns - 1 - i % columns]?.push(label));
|
|
5548
|
+
return levels;
|
|
5549
|
+
}
|
|
5550
|
+
function hierarchyView(chart, model, evaluateRef) {
|
|
5551
|
+
const first2 = model.series[0];
|
|
5552
|
+
const live = liveLevels(chart.series[0]?.categoriesRef, evaluateRef);
|
|
5553
|
+
if (live?.[0]) model.categories = live[0];
|
|
5554
|
+
const count = Math.max(first2?.values.length ?? 0, model.categories.length);
|
|
5555
|
+
const supplied = live ?? chart.hierarchy?.levels ?? [];
|
|
5556
|
+
const levels = supplied.length > 1 ? normalizeLevels(supplied, count) : [];
|
|
5557
|
+
model.hierarchy = {
|
|
5558
|
+
levels,
|
|
5559
|
+
parentLabelLayout: chart.hierarchy?.parentLabelLayout ?? "banner",
|
|
5560
|
+
labels: chart.hierarchy?.dataLabels !== false,
|
|
5561
|
+
branches: hierarchyBranchLabels(
|
|
5562
|
+
model.series.map((s) => ({ name: s.name, values: s.values.map((v) => v ?? 0) })),
|
|
5563
|
+
model.categories,
|
|
5564
|
+
levels.length > 1 ? levels : void 0
|
|
5565
|
+
)
|
|
5566
|
+
};
|
|
5567
|
+
}
|
|
5568
|
+
|
|
5569
|
+
// chart/render/chart-view-stock.ts
|
|
5570
|
+
var EMU_PER_PX = 9525;
|
|
5571
|
+
function paintOf(fill, ctx) {
|
|
5572
|
+
if (fill?.kind === "none") return "none";
|
|
5573
|
+
return fill?.kind === "solid" ? ctx.drawingColor(fill.color) : void 0;
|
|
5574
|
+
}
|
|
5575
|
+
function lineOf(shape, ctx, color) {
|
|
5576
|
+
const line2 = shape?.line;
|
|
5577
|
+
return {
|
|
5578
|
+
color: paintOf(line2?.fill, ctx) ?? color,
|
|
5579
|
+
width: line2?.widthEmu === void 0 ? 1 : Math.max(0.5, line2.widthEmu / EMU_PER_PX)
|
|
5580
|
+
};
|
|
5581
|
+
}
|
|
5582
|
+
function barOf(shape, ctx, fallback) {
|
|
5583
|
+
const stroke = lineOf(shape, ctx, "#404040");
|
|
5584
|
+
return {
|
|
5585
|
+
fill: paintOf(shape?.fill, ctx) ?? fallback,
|
|
5586
|
+
stroke: stroke.color,
|
|
5587
|
+
strokeWidth: stroke.width
|
|
5588
|
+
};
|
|
5589
|
+
}
|
|
5590
|
+
function stockView(style, ctx) {
|
|
5591
|
+
return {
|
|
5592
|
+
wick: lineOf(style?.hiLowLines, ctx, STOCK_DEFAULT_WICK_COLOR),
|
|
5593
|
+
up: barOf(style?.upBars, ctx, STOCK_DEFAULT_UP_FILL),
|
|
5594
|
+
down: barOf(style?.downBars, ctx, STOCK_DEFAULT_DOWN_FILL),
|
|
5595
|
+
bodyShare: 1 / (1 + Math.max(0, style?.gapWidth ?? 150) / 100)
|
|
5596
|
+
};
|
|
5597
|
+
}
|
|
5598
|
+
|
|
5599
|
+
// chart/render/chart-value-axis.ts
|
|
5600
|
+
function valueExtent(type, grouping, series, categories) {
|
|
5601
|
+
const stackable = type === "bar" || type === "column" || type === "line" || type === "area";
|
|
5602
|
+
let min = Infinity;
|
|
5603
|
+
let max = -Infinity;
|
|
5604
|
+
if (stackable && grouping === "stacked") {
|
|
5605
|
+
for (let i = 0; i < categories; i++) {
|
|
5606
|
+
let pos = 0;
|
|
5607
|
+
let neg = 0;
|
|
5608
|
+
for (const s of series) {
|
|
5609
|
+
const v = s.values[i] ?? 0;
|
|
5610
|
+
if (v >= 0) pos += v;
|
|
5611
|
+
else neg += v;
|
|
5612
|
+
}
|
|
5613
|
+
min = Math.min(min, neg);
|
|
5614
|
+
max = Math.max(max, pos);
|
|
4094
5615
|
}
|
|
5616
|
+
} else {
|
|
5617
|
+
for (const s of series)
|
|
5618
|
+
for (const v of s.values)
|
|
5619
|
+
if (v !== null) {
|
|
5620
|
+
min = Math.min(min, v);
|
|
5621
|
+
max = Math.max(max, v);
|
|
5622
|
+
}
|
|
4095
5623
|
}
|
|
4096
|
-
return
|
|
5624
|
+
return { min, max };
|
|
5625
|
+
}
|
|
5626
|
+
function valueAxis(model) {
|
|
5627
|
+
const stackable = model.type === "bar" || model.type === "column" || model.type === "line" || model.type === "area";
|
|
5628
|
+
if (stackable && model.grouping === "percentStacked")
|
|
5629
|
+
return { ...PERCENT_SCALE, ticks: [...PERCENT_SCALE.ticks], percent: true };
|
|
5630
|
+
let { min, max } = valueExtent(model.type, model.grouping, model.series, model.categories.length);
|
|
5631
|
+
if (min === Infinity) {
|
|
5632
|
+
min = 0;
|
|
5633
|
+
max = 1;
|
|
5634
|
+
}
|
|
5635
|
+
return { ...niceScale(min, max), percent: false };
|
|
5636
|
+
}
|
|
5637
|
+
function categoryTotals(model) {
|
|
5638
|
+
return model.categories.map(
|
|
5639
|
+
(_, i) => model.series.reduce((sum, s) => sum + Math.abs(s.values[i] ?? 0), 0)
|
|
5640
|
+
);
|
|
4097
5641
|
}
|
|
4098
5642
|
|
|
4099
5643
|
// chart/render/chart-title-text.ts
|
|
@@ -4140,8 +5684,87 @@ function chartTitleText(chart, theme) {
|
|
|
4140
5684
|
};
|
|
4141
5685
|
}
|
|
4142
5686
|
|
|
5687
|
+
// chart/render/chart-view-ex.ts
|
|
5688
|
+
function groupsAxis(groups, categories) {
|
|
5689
|
+
let min = Infinity;
|
|
5690
|
+
let max = -Infinity;
|
|
5691
|
+
for (const group2 of groups) {
|
|
5692
|
+
const extent = valueExtent(group2.type, group2.grouping, group2.series, categories);
|
|
5693
|
+
min = Math.min(min, extent.min);
|
|
5694
|
+
max = Math.max(max, extent.max);
|
|
5695
|
+
}
|
|
5696
|
+
return min === Infinity ? { ...niceScale(0, 1), percent: false } : { ...niceScale(min, max), percent: false };
|
|
5697
|
+
}
|
|
5698
|
+
function chartExtraView(chart, model, ctx, total, categoriesOf) {
|
|
5699
|
+
let index = chart.series.length;
|
|
5700
|
+
const groups = [];
|
|
5701
|
+
for (const group2 of chart.extraGroups ?? []) {
|
|
5702
|
+
const series = group2.series.map((s) => seriesView(ctx, s, index++, total, categoriesOf));
|
|
5703
|
+
const view = {
|
|
5704
|
+
type: group2.chartType,
|
|
5705
|
+
grouping: group2.grouping ?? (group2.chartType === "column" ? "clustered" : "standard"),
|
|
5706
|
+
series,
|
|
5707
|
+
secondary: group2.secondary
|
|
5708
|
+
};
|
|
5709
|
+
if (group2.chartType === "stock") view.stock = stockView(group2.stock, ctx);
|
|
5710
|
+
if (group2.barGapWidth !== void 0) view.barGapWidth = group2.barGapWidth;
|
|
5711
|
+
if (group2.barOverlap !== void 0) view.barOverlap = group2.barOverlap;
|
|
5712
|
+
groups.push(view);
|
|
5713
|
+
}
|
|
5714
|
+
if (!groups.length) return;
|
|
5715
|
+
model.extraGroups = groups;
|
|
5716
|
+
}
|
|
5717
|
+
function chartExtraAxes(model) {
|
|
5718
|
+
const groups = model.extraGroups;
|
|
5719
|
+
if (!groups || !model.valueAxis) return;
|
|
5720
|
+
const count = model.categories.length;
|
|
5721
|
+
const secondary = groups.filter((g) => g.secondary);
|
|
5722
|
+
if (secondary.length) model.secondaryAxis = groupsAxis(secondary, count);
|
|
5723
|
+
const shared = groups.filter((g) => !g.secondary);
|
|
5724
|
+
if (!shared.length || model.valueAxis.percent) return;
|
|
5725
|
+
const own = valueExtent(model.type, model.grouping, model.series, count);
|
|
5726
|
+
let min = own.min;
|
|
5727
|
+
let max = own.max;
|
|
5728
|
+
for (const group2 of shared) {
|
|
5729
|
+
const extent = valueExtent(group2.type, group2.grouping, group2.series, count);
|
|
5730
|
+
min = Math.min(min, extent.min);
|
|
5731
|
+
max = Math.max(max, extent.max);
|
|
5732
|
+
}
|
|
5733
|
+
model.valueAxis = { ...niceScale(min, max), percent: false };
|
|
5734
|
+
}
|
|
5735
|
+
function waterfallView(chart, model, ctx) {
|
|
5736
|
+
const values = (model.series[0]?.values ?? []).map((v) => v ?? 0);
|
|
5737
|
+
const steps = buildWaterfallSteps(values, chart.waterfall);
|
|
5738
|
+
const role = (i) => ctx.palette && chartPaletteSeriesColor(ctx.palette, i, 3, ctx.scheme) || autoSeriesColor(ctx.theme, i);
|
|
5739
|
+
model.waterfall = {
|
|
5740
|
+
steps,
|
|
5741
|
+
connectors: chart.waterfall?.connectorLines !== false,
|
|
5742
|
+
colors: { increase: role(0), decrease: role(1), total: role(2) }
|
|
5743
|
+
};
|
|
5744
|
+
const ends = steps.flatMap((step) => [step.startValue, step.endValue]);
|
|
5745
|
+
model.valueAxis = {
|
|
5746
|
+
...ends.length ? niceScale(Math.min(...ends), Math.max(...ends)) : niceScale(0, 1),
|
|
5747
|
+
percent: false
|
|
5748
|
+
};
|
|
5749
|
+
const labels = model.categories;
|
|
5750
|
+
model.categories = steps.map((_, i) => labels[i] ?? String(i + 1));
|
|
5751
|
+
}
|
|
5752
|
+
function histogramView(chart, model) {
|
|
5753
|
+
const first2 = model.series[0];
|
|
5754
|
+
if (!first2) return;
|
|
5755
|
+
const raw2 = first2.values.map((v) => v ?? Number.NaN);
|
|
5756
|
+
const options = chart.histogram ?? {};
|
|
5757
|
+
const bins = options.aggregateByCategory ? aggregateByCategory(
|
|
5758
|
+
first2.values.map((v) => v ?? 0),
|
|
5759
|
+
model.categories
|
|
5760
|
+
) : computeHistogramBins(raw2, options, formatAxisValue);
|
|
5761
|
+
model.categories = bins.map((bin) => bin.label);
|
|
5762
|
+
first2.values = bins.map((bin) => bin.value);
|
|
5763
|
+
model.barGapWidth = 0;
|
|
5764
|
+
model.barOverlap = 0;
|
|
5765
|
+
}
|
|
5766
|
+
|
|
4143
5767
|
// chart/render/chart-view.ts
|
|
4144
|
-
var isRefError = (value) => typeof value === "object" && value !== null && "error" in value;
|
|
4145
5768
|
var SUPPORTED = /* @__PURE__ */ new Set([
|
|
4146
5769
|
"bar",
|
|
4147
5770
|
"column",
|
|
@@ -4150,85 +5773,37 @@ var SUPPORTED = /* @__PURE__ */ new Set([
|
|
|
4150
5773
|
"pie",
|
|
4151
5774
|
"doughnut",
|
|
4152
5775
|
"scatter",
|
|
4153
|
-
"radar"
|
|
5776
|
+
"radar",
|
|
5777
|
+
"waterfall",
|
|
5778
|
+
"histogram",
|
|
5779
|
+
"bubble",
|
|
5780
|
+
"stock",
|
|
5781
|
+
"treemap",
|
|
5782
|
+
"sunburst"
|
|
4154
5783
|
]);
|
|
4155
|
-
function toText(value) {
|
|
4156
|
-
if (value === null) return "";
|
|
4157
|
-
if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
|
|
4158
|
-
if (isRefError(value)) return value.error;
|
|
4159
|
-
return String(value);
|
|
4160
|
-
}
|
|
4161
|
-
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
4162
|
-
function resolveRef(ref, evaluateRef) {
|
|
4163
|
-
if (!ref) return void 0;
|
|
4164
|
-
try {
|
|
4165
|
-
const values = evaluateRef(ref);
|
|
4166
|
-
return values.length ? values : void 0;
|
|
4167
|
-
} catch {
|
|
4168
|
-
return void 0;
|
|
4169
|
-
}
|
|
4170
|
-
}
|
|
4171
|
-
function seriesName(series, index, evaluateRef) {
|
|
4172
|
-
const fromRef = resolveRef(series.nameRef, evaluateRef)?.map(toText).filter((t) => t !== "").join(" ");
|
|
4173
|
-
return fromRef || series.name || `Series${index + 1}`;
|
|
4174
|
-
}
|
|
4175
5784
|
function chartSummaryView(chart, theme, options = {}) {
|
|
4176
|
-
const evaluateRef = options.evaluateRef ?? (() => []);
|
|
4177
5785
|
const type = chart.chartType;
|
|
4178
5786
|
const radial = type === "pie" || type === "doughnut";
|
|
4179
|
-
const
|
|
4180
|
-
const
|
|
4181
|
-
const
|
|
4182
|
-
resolveDrawingColor(
|
|
4183
|
-
color,
|
|
4184
|
-
{
|
|
4185
|
-
scheme: (name) => scheme[name]
|
|
4186
|
-
},
|
|
4187
|
-
{ transformOrder: "document" }
|
|
4188
|
-
)
|
|
4189
|
-
);
|
|
4190
|
-
const gradient = (fill) => fill?.kind === "gradient" ? resolveChartGradient(
|
|
4191
|
-
fill,
|
|
4192
|
-
(color) => resolveDrawingColor(
|
|
4193
|
-
color,
|
|
4194
|
-
{
|
|
4195
|
-
scheme: (name) => scheme[name]
|
|
4196
|
-
},
|
|
4197
|
-
{ transformOrder: "document" }
|
|
4198
|
-
)
|
|
4199
|
-
) : void 0;
|
|
5787
|
+
const byPoint = radial || type === "treemap" || type === "sunburst";
|
|
5788
|
+
const ctx = seriesContext(chart, theme, options);
|
|
5789
|
+
const { palette, scheme, drawingColor } = ctx;
|
|
4200
5790
|
const grouping = chart.grouping ?? (type === "bar" || type === "column" ? "clustered" : "standard");
|
|
4201
|
-
let categories = [];
|
|
4202
5791
|
const rawCategories = [];
|
|
4203
|
-
const
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
});
|
|
4213
|
-
if (shadow) view.shadow = shadow;
|
|
4214
|
-
const resolvedGradient = gradient(s.fill);
|
|
4215
|
-
if (resolvedGradient) view.gradient = resolvedGradient;
|
|
4216
|
-
const points = Object.fromEntries(
|
|
4217
|
-
Object.entries(s.pointFills ?? {}).flatMap(([key, fill]) => {
|
|
4218
|
-
const value = gradient(fill);
|
|
4219
|
-
return value ? [[key, value]] : [];
|
|
4220
|
-
})
|
|
4221
|
-
);
|
|
4222
|
-
if (Object.keys(points).length) view.pointGradients = points;
|
|
4223
|
-
return view;
|
|
4224
|
-
});
|
|
4225
|
-
const longest = Math.max(0, ...series.map((s) => s.values.length));
|
|
5792
|
+
const collect = (cats) => void rawCategories.push(cats);
|
|
5793
|
+
const extra = chart.extraGroups ?? [];
|
|
5794
|
+
const total = chart.series.length + extra.reduce((n2, g) => n2 + g.series.length, 0);
|
|
5795
|
+
const series = chart.series.map((s, i) => seriesView(ctx, s, i, total, collect));
|
|
5796
|
+
const longest = Math.max(
|
|
5797
|
+
0,
|
|
5798
|
+
...series.map((s) => s.values.length),
|
|
5799
|
+
...extra.flatMap((g) => g.series.map((s) => s.values.length))
|
|
5800
|
+
);
|
|
4226
5801
|
const firstCats = rawCategories.find((c2) => c2.length > 0) ?? [];
|
|
4227
|
-
categories = Array.from(
|
|
5802
|
+
const categories = Array.from(
|
|
4228
5803
|
{ length: Math.max(longest, firstCats.length) },
|
|
4229
5804
|
(_, i) => firstCats[i] !== void 0 ? toText(firstCats[i] ?? null) : String(i + 1)
|
|
4230
5805
|
);
|
|
4231
|
-
if (
|
|
5806
|
+
if (byPoint) {
|
|
4232
5807
|
series.forEach((s, seriesIndex) => {
|
|
4233
5808
|
s.pointColors = s.values.map((_, i) => {
|
|
4234
5809
|
const explicit = drawingColor(chart.series[seriesIndex]?.pointColors?.[i]);
|
|
@@ -4249,8 +5824,8 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
4249
5824
|
for (const [key, fill] of Object.entries(source.pointFills ?? {})) {
|
|
4250
5825
|
if (fill.kind === "none") (s.pointColors ??= [])[Number(key)] = "none";
|
|
4251
5826
|
else if (fill.kind === "solid") {
|
|
4252
|
-
const
|
|
4253
|
-
if (
|
|
5827
|
+
const paint2 = drawingColor(fill.color);
|
|
5828
|
+
if (paint2) (s.pointColors ??= [])[Number(key)] = paint2;
|
|
4254
5829
|
}
|
|
4255
5830
|
}
|
|
4256
5831
|
});
|
|
@@ -4277,7 +5852,7 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
4277
5852
|
if (titleText) model.titleText = titleText;
|
|
4278
5853
|
const appearance = chartAppearance(chart, theme);
|
|
4279
5854
|
if (appearance) model.appearance = appearance;
|
|
4280
|
-
if (type === "scatter") {
|
|
5855
|
+
if (type === "scatter" || type === "bubble") {
|
|
4281
5856
|
series.forEach((s, i) => {
|
|
4282
5857
|
const cats = rawCategories[i] ?? [];
|
|
4283
5858
|
const numeric = cats.length > 0 && cats.every((c2) => typeof c2 === "number");
|
|
@@ -4286,7 +5861,15 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
4286
5861
|
const xs = series.flatMap((s) => s.xValues ?? []).filter((x) => x !== null);
|
|
4287
5862
|
model.xAxis = xs.length ? niceScale(Math.min(...xs), Math.max(...xs)) : niceScale(0, 1);
|
|
4288
5863
|
}
|
|
4289
|
-
if (
|
|
5864
|
+
if (type === "stock") model.stock = stockView(chart.stock, ctx);
|
|
5865
|
+
if (type === "bubble") bubbleView(chart, model, ctx.evaluateRef);
|
|
5866
|
+
if (type === "treemap" || type === "sunburst") hierarchyView(chart, model, ctx.evaluateRef);
|
|
5867
|
+
if (type === "histogram") histogramView(chart, model);
|
|
5868
|
+
if (extra.length && (type === "column" || type === "line" || type === "area"))
|
|
5869
|
+
chartExtraView(chart, model, ctx, total, collect);
|
|
5870
|
+
if (type === "waterfall") waterfallView(chart, model, ctx);
|
|
5871
|
+
else if (!byPoint) model.valueAxis = valueAxis(model);
|
|
5872
|
+
chartExtraAxes(model);
|
|
4290
5873
|
return model;
|
|
4291
5874
|
}
|
|
4292
5875
|
|
|
@@ -4328,7 +5911,7 @@ function chartGradientPaint(model, width = 1024, height = 768) {
|
|
|
4328
5911
|
textShadowFilter: shadowPaint(entry3.textShadow, `${part}-text-shadow`)
|
|
4329
5912
|
};
|
|
4330
5913
|
}
|
|
4331
|
-
const
|
|
5914
|
+
const paint2 = (gradient, suffix, bounds) => {
|
|
4332
5915
|
const def = buildChartGradientDef(`${prefix}-${suffix}`, gradient, bounds);
|
|
4333
5916
|
defs.push(chartGradientMarkup(def));
|
|
4334
5917
|
return `url(#${def.id})`;
|
|
@@ -4339,18 +5922,18 @@ function chartGradientPaint(model, width = 1024, height = 768) {
|
|
|
4339
5922
|
if (part === "plotArea" && ["circle", "shape"].includes(entry3.gradient.path ?? "")) continue;
|
|
4340
5923
|
appearance[part] = {
|
|
4341
5924
|
...entry3,
|
|
4342
|
-
fillColor:
|
|
5925
|
+
fillColor: paint2(entry3.gradient, part, { width, height, shape: "rect" })
|
|
4343
5926
|
};
|
|
4344
5927
|
}
|
|
4345
5928
|
const series = model.series.map((source, index) => {
|
|
4346
5929
|
const view = { ...source };
|
|
4347
5930
|
if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
|
|
4348
5931
|
const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
4349
|
-
if (source.gradient) view.color =
|
|
5932
|
+
if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
|
|
4350
5933
|
if (source.pointGradients) {
|
|
4351
5934
|
view.pointColors = [...source.pointColors ?? []];
|
|
4352
5935
|
for (const [key, gradient] of Object.entries(source.pointGradients))
|
|
4353
|
-
view.pointColors[Number(key)] =
|
|
5936
|
+
view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
|
|
4354
5937
|
}
|
|
4355
5938
|
return view;
|
|
4356
5939
|
});
|
|
@@ -4395,72 +5978,8 @@ function chartAreaRect(model, part, area) {
|
|
|
4395
5978
|
return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
|
|
4396
5979
|
}
|
|
4397
5980
|
|
|
4398
|
-
// chart/render/chart-spacing.ts
|
|
4399
|
-
function chartBarSpacing(chart) {
|
|
4400
|
-
const stacked = chart.grouping === "stacked" || chart.grouping === "percentStacked";
|
|
4401
|
-
return {
|
|
4402
|
-
barGapWidth: chart.barGapWidth ?? DEFAULT_BAR_GAP_WIDTH,
|
|
4403
|
-
barOverlap: chart.barOverlap ?? (stacked ? 100 : 0)
|
|
4404
|
-
};
|
|
4405
|
-
}
|
|
4406
|
-
|
|
4407
|
-
// chart/render/chart-svg-bars.ts
|
|
4408
|
-
function bars(model, frame, out, values) {
|
|
4409
|
-
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
4410
|
-
const count = Math.max(1, model.series.length);
|
|
4411
|
-
const geometry = clusteredBarGeometry(frame.bandSize, count, chartBarSpacing(model));
|
|
4412
|
-
const barSize = geometry.singleBarWidth;
|
|
4413
|
-
const base = frame.value(0);
|
|
4414
|
-
const pos = new Array(model.categories.length).fill(0);
|
|
4415
|
-
const neg = new Array(model.categories.length).fill(0);
|
|
4416
|
-
model.series.forEach((s, si) => {
|
|
4417
|
-
values[si]?.forEach((v, i) => {
|
|
4418
|
-
if (v === null || i >= model.categories.length) return;
|
|
4419
|
-
let from = 0;
|
|
4420
|
-
let to = v;
|
|
4421
|
-
if (stacked) {
|
|
4422
|
-
const acc = v >= 0 ? pos : neg;
|
|
4423
|
-
from = acc[i] ?? 0;
|
|
4424
|
-
to = from + v;
|
|
4425
|
-
acc[i] = to;
|
|
4426
|
-
}
|
|
4427
|
-
const a2 = stacked ? frame.value(from) : base;
|
|
4428
|
-
const b = frame.value(to);
|
|
4429
|
-
const offset = model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
|
|
4430
|
-
const center = frame.band(i);
|
|
4431
|
-
const width = model.horizontal ? Math.abs(b - a2) : barSize;
|
|
4432
|
-
const height = model.horizontal ? barSize : Math.abs(b - a2);
|
|
4433
|
-
let color = s.pointColors?.[i] ?? s.color;
|
|
4434
|
-
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
4435
|
-
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
4436
|
-
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
4437
|
-
if (baseId) {
|
|
4438
|
-
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
4439
|
-
const def = buildChartGradientDef(id, gradient, {
|
|
4440
|
-
width: Number(n(width)),
|
|
4441
|
-
height: Number(n(height)),
|
|
4442
|
-
shape: "rect"
|
|
4443
|
-
});
|
|
4444
|
-
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
4445
|
-
color = `url(#${id})`;
|
|
4446
|
-
}
|
|
4447
|
-
}
|
|
4448
|
-
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
4449
|
-
if (model.horizontal)
|
|
4450
|
-
out.push(
|
|
4451
|
-
rect(Math.min(a2, b), center + offset, Math.abs(b - a2), barSize, color, s.shadowFilter)
|
|
4452
|
-
);
|
|
4453
|
-
else
|
|
4454
|
-
out.push(
|
|
4455
|
-
rect(center + offset, Math.min(a2, b), barSize, Math.abs(b - a2), color, s.shadowFilter)
|
|
4456
|
-
);
|
|
4457
|
-
out.push("</g>");
|
|
4458
|
-
});
|
|
4459
|
-
});
|
|
4460
|
-
}
|
|
4461
|
-
|
|
4462
5981
|
// chart/render/chart-svg-cartesian.ts
|
|
4463
|
-
function
|
|
5982
|
+
function cartesianAxes(model, area, out) {
|
|
4464
5983
|
const scale = model.valueAxis;
|
|
4465
5984
|
if (!scale) return void 0;
|
|
4466
5985
|
const labels = scale.ticks.map((t) => formatAxisValue(t, scale.percent));
|
|
@@ -4479,6 +5998,9 @@ function axes(model, area, out) {
|
|
|
4479
5998
|
area.w * 0.3,
|
|
4480
5999
|
Math.max(...model.categories.map((c2) => textWidth(c2, categorySize)), 8) + 6
|
|
4481
6000
|
);
|
|
6001
|
+
const second = horizontal ? void 0 : model.secondaryAxis;
|
|
6002
|
+
const secondLabels = second?.ticks.map((t) => formatAxisValue(t, second.percent)) ?? [];
|
|
6003
|
+
const secondW = second ? valueLabels ? Math.max(...secondLabels.map((l) => textWidth(l, valueSize)), 8) + 8 : 4 : 0;
|
|
4482
6004
|
const plot = horizontal ? {
|
|
4483
6005
|
x: area.x + catW,
|
|
4484
6006
|
y: area.y,
|
|
@@ -4487,7 +6009,7 @@ function axes(model, area, out) {
|
|
|
4487
6009
|
} : {
|
|
4488
6010
|
x: area.x + labelW,
|
|
4489
6011
|
y: area.y + 4,
|
|
4490
|
-
w: Math.max(1, area.w - labelW - 4),
|
|
6012
|
+
w: Math.max(1, area.w - labelW - 4 - secondW),
|
|
4491
6013
|
h: Math.max(1, area.h - Math.max(20, categorySize * 1.5))
|
|
4492
6014
|
};
|
|
4493
6015
|
const span = scale.max - scale.min || 1;
|
|
@@ -4502,12 +6024,12 @@ function axes(model, area, out) {
|
|
|
4502
6024
|
out.push(line(p, plot.y, p, plot.y + plot.h, grid.color, grid.width));
|
|
4503
6025
|
if (valueLabels)
|
|
4504
6026
|
out.push(
|
|
4505
|
-
|
|
6027
|
+
text2(p, plot.y + plot.h + valueSize + 2, label, { anchor: "middle", ...valueAttrs })
|
|
4506
6028
|
);
|
|
4507
6029
|
} else {
|
|
4508
6030
|
out.push(line(plot.x, p, plot.x + plot.w, p, grid.color, grid.width));
|
|
4509
6031
|
if (valueLabels)
|
|
4510
|
-
out.push(
|
|
6032
|
+
out.push(text2(plot.x - 4, p + valueSize * 0.3, label, { anchor: "end", ...valueAttrs }));
|
|
4511
6033
|
}
|
|
4512
6034
|
});
|
|
4513
6035
|
const zero = value(Math.min(Math.max(0, scale.min), scale.max));
|
|
@@ -4522,20 +6044,45 @@ function axes(model, area, out) {
|
|
|
4522
6044
|
const p = band(i);
|
|
4523
6045
|
if (horizontal)
|
|
4524
6046
|
out.push(
|
|
4525
|
-
|
|
6047
|
+
text2(plot.x - 4, p + categorySize * 0.3, fit(c2, catW - 6, categorySize), {
|
|
4526
6048
|
anchor: "end",
|
|
4527
6049
|
...categoryAttrs
|
|
4528
6050
|
})
|
|
4529
6051
|
);
|
|
4530
6052
|
else
|
|
4531
6053
|
out.push(
|
|
4532
|
-
|
|
6054
|
+
text2(p, plot.y + plot.h + categorySize + 3, fit(c2, bandSize * step, categorySize), {
|
|
4533
6055
|
anchor: "middle",
|
|
4534
6056
|
...categoryAttrs
|
|
4535
6057
|
})
|
|
4536
6058
|
);
|
|
4537
6059
|
});
|
|
4538
|
-
|
|
6060
|
+
const frame = { plot, value, band, bandSize };
|
|
6061
|
+
if (second) {
|
|
6062
|
+
const secondSpan = second.max - second.min || 1;
|
|
6063
|
+
frame.secondary = (v) => plot.y + plot.h - (v - second.min) / secondSpan * plot.h;
|
|
6064
|
+
const secondAxis = chartStroke(model, "valueAxis");
|
|
6065
|
+
out.push(
|
|
6066
|
+
line(
|
|
6067
|
+
plot.x + plot.w,
|
|
6068
|
+
plot.y,
|
|
6069
|
+
plot.x + plot.w,
|
|
6070
|
+
plot.y + plot.h,
|
|
6071
|
+
secondAxis.color,
|
|
6072
|
+
secondAxis.width
|
|
6073
|
+
)
|
|
6074
|
+
);
|
|
6075
|
+
if (valueLabels)
|
|
6076
|
+
second.ticks.forEach(
|
|
6077
|
+
(t, i) => out.push(
|
|
6078
|
+
text2(plot.x + plot.w + 4, frame.secondary(t) + valueSize * 0.3, secondLabels[i] ?? "", {
|
|
6079
|
+
anchor: "start",
|
|
6080
|
+
...valueAttrs
|
|
6081
|
+
})
|
|
6082
|
+
)
|
|
6083
|
+
);
|
|
6084
|
+
}
|
|
6085
|
+
return frame;
|
|
4539
6086
|
}
|
|
4540
6087
|
function plotted(model) {
|
|
4541
6088
|
if (model.grouping !== "percentStacked") return model.series.map((s) => s.values);
|
|
@@ -4578,17 +6125,17 @@ function linesAndAreas(model, frame, out) {
|
|
|
4578
6125
|
out.push(`<polygon points="${poly}" fill="${color}" fill-opacity="0.85"${filter}/>`);
|
|
4579
6126
|
continue;
|
|
4580
6127
|
}
|
|
4581
|
-
let
|
|
6128
|
+
let segment2 = [];
|
|
4582
6129
|
const flush = () => {
|
|
4583
|
-
if (
|
|
6130
|
+
if (segment2.length > 1)
|
|
4584
6131
|
out.push(
|
|
4585
|
-
`<polyline points="${
|
|
6132
|
+
`<polyline points="${segment2.join(" ")}" fill="none" stroke="${color}" stroke-width="2.25" stroke-linejoin="round"${filter}/>`
|
|
4586
6133
|
);
|
|
4587
|
-
|
|
6134
|
+
segment2 = [];
|
|
4588
6135
|
};
|
|
4589
6136
|
for (const [x, y] of points) {
|
|
4590
6137
|
if (Number.isNaN(x)) flush();
|
|
4591
|
-
else
|
|
6138
|
+
else segment2.push(`${n(x)},${n(y)}`);
|
|
4592
6139
|
}
|
|
4593
6140
|
flush();
|
|
4594
6141
|
for (const [x, y] of points)
|
|
@@ -4596,6 +6143,8 @@ function linesAndAreas(model, frame, out) {
|
|
|
4596
6143
|
out.push(`<circle cx="${n(x)}" cy="${n(y)}" r="2.5" fill="${color}"${filter}/>`);
|
|
4597
6144
|
}
|
|
4598
6145
|
}
|
|
6146
|
+
|
|
6147
|
+
// chart/render/chart-svg-xy.ts
|
|
4599
6148
|
function scatter(model, area, out) {
|
|
4600
6149
|
const ys = model.valueAxis;
|
|
4601
6150
|
const xs = model.xAxis;
|
|
@@ -4617,26 +6166,42 @@ function scatter(model, area, out) {
|
|
|
4617
6166
|
w: Math.max(1, area.w - labelW - 8),
|
|
4618
6167
|
h: Math.max(1, area.h - Math.max(20, categorySize * 1.5))
|
|
4619
6168
|
};
|
|
4620
|
-
const
|
|
4621
|
-
const
|
|
6169
|
+
const bubble = model.type === "bubble" ? model.bubble : void 0;
|
|
6170
|
+
const biggest = maxBubbleSize(
|
|
6171
|
+
model.series.flatMap((s) => (s.sizes ?? []).filter((v) => v !== null))
|
|
6172
|
+
);
|
|
6173
|
+
const median = medianBubbleRadius(plot.w, plot.h);
|
|
6174
|
+
const radiusOf = (size) => bubble && !(size !== void 0 && size < 0 && !bubble.showNegativeBubbles) ? computeBubbleRadius(size, biggest, median, bubble) : void 0;
|
|
6175
|
+
let reach = 0;
|
|
6176
|
+
if (bubble)
|
|
6177
|
+
for (const s of model.series)
|
|
6178
|
+
s.values.forEach((_, i) => {
|
|
6179
|
+
reach = Math.max(reach, radiusOf(s.sizes?.[i] ?? void 0) ?? 0);
|
|
6180
|
+
});
|
|
6181
|
+
const widen = (s, length) => {
|
|
6182
|
+
const pad = reach * (s.max - s.min || 1) / Math.max(1, length - 2 * reach);
|
|
6183
|
+
return { ...s, min: s.min - pad, max: s.max + pad };
|
|
6184
|
+
};
|
|
6185
|
+
const xView = widen(xs, plot.w);
|
|
6186
|
+
const yView = widen(ys, plot.h);
|
|
6187
|
+
const px = (v) => plot.x + (v - xView.min) / (xView.max - xView.min || 1) * plot.w;
|
|
6188
|
+
const py = (v) => plot.y + plot.h - (v - yView.min) / (yView.max - yView.min || 1) * plot.h;
|
|
4622
6189
|
out.push(chartAreaRect(model, "plotArea", plot));
|
|
4623
6190
|
ys.ticks.forEach((t, i) => {
|
|
4624
|
-
out.push(line(plot.x, py(t
|
|
6191
|
+
out.push(line(plot.x, py(t), plot.x + plot.w, py(t), grid.color, grid.width));
|
|
4625
6192
|
if (valueLabels)
|
|
4626
6193
|
out.push(
|
|
4627
|
-
|
|
6194
|
+
text2(plot.x - 4, py(t) + valueSize * 0.3, yLabels[i] ?? "", {
|
|
4628
6195
|
anchor: "end",
|
|
4629
6196
|
...valueAttrs
|
|
4630
6197
|
})
|
|
4631
6198
|
);
|
|
4632
6199
|
});
|
|
4633
6200
|
for (const t of xs.ticks) {
|
|
4634
|
-
out.push(
|
|
4635
|
-
line(px(t, xs), plot.y + plot.h, px(t, xs), plot.y + plot.h + 3, xAxis.color, xAxis.width)
|
|
4636
|
-
);
|
|
6201
|
+
out.push(line(px(t), plot.y + plot.h, px(t), plot.y + plot.h + 3, xAxis.color, xAxis.width));
|
|
4637
6202
|
if (categoryLabels)
|
|
4638
6203
|
out.push(
|
|
4639
|
-
|
|
6204
|
+
text2(px(t), plot.y + plot.h + categorySize + 3, formatAxisValue(t), {
|
|
4640
6205
|
anchor: "middle",
|
|
4641
6206
|
...categoryAttrs
|
|
4642
6207
|
})
|
|
@@ -4646,51 +6211,185 @@ function scatter(model, area, out) {
|
|
|
4646
6211
|
line(plot.x, plot.y + plot.h, plot.x + plot.w, plot.y + plot.h, xAxis.color, xAxis.width)
|
|
4647
6212
|
);
|
|
4648
6213
|
out.push(line(plot.x, plot.y, plot.x, plot.y + plot.h, yAxis.color, yAxis.width));
|
|
4649
|
-
for (const s of model.series)
|
|
6214
|
+
for (const [si, s] of model.series.entries())
|
|
4650
6215
|
s.values.forEach((v, i) => {
|
|
4651
6216
|
const x = s.xValues?.[i] ?? null;
|
|
4652
6217
|
if (v === null || x === null) return;
|
|
6218
|
+
const filter = s.shadowFilter ? ` filter="${s.shadowFilter}"` : "";
|
|
6219
|
+
const fill = s.pointColors?.[i] ?? s.color;
|
|
6220
|
+
if (!bubble) {
|
|
6221
|
+
out.push(`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="3" fill="${fill}"${filter}/>`);
|
|
6222
|
+
return;
|
|
6223
|
+
}
|
|
6224
|
+
const r = radiusOf(s.sizes?.[i] ?? void 0);
|
|
6225
|
+
if (r === void 0) return;
|
|
4653
6226
|
out.push(
|
|
4654
|
-
`<circle cx="${n(px(x
|
|
6227
|
+
`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="${n(r)}" fill="${fill}" fill-opacity="0.6" data-chart-series="${si}" data-chart-point="${i}"${filter}/>`
|
|
4655
6228
|
);
|
|
4656
6229
|
});
|
|
6230
|
+
scatterAnalysis(model, px, py, out);
|
|
6231
|
+
}
|
|
6232
|
+
|
|
6233
|
+
// chart/render/chart-svg-stock.ts
|
|
6234
|
+
function stockBars(model, frame, out) {
|
|
6235
|
+
const slots = stockSlots(model.series.length);
|
|
6236
|
+
if (!slots) return;
|
|
6237
|
+
const style = model.stock ?? stockView(void 0, { drawingColor: () => void 0 });
|
|
6238
|
+
const at = (role, i) => role === void 0 ? void 0 : model.series[role]?.values[i];
|
|
6239
|
+
const closeColor = model.series[slots.close]?.color ?? style.wick.color;
|
|
6240
|
+
model.categories.forEach((_, i) => {
|
|
6241
|
+
const candle = stockCandle({
|
|
6242
|
+
x: frame.band(i),
|
|
6243
|
+
band: frame.bandSize,
|
|
6244
|
+
high: at(slots.high, i),
|
|
6245
|
+
low: at(slots.low, i),
|
|
6246
|
+
close: at(slots.close, i),
|
|
6247
|
+
open: at(slots.open, i),
|
|
6248
|
+
hasOpen: slots.open !== void 0,
|
|
6249
|
+
bodyShare: style.bodyShare,
|
|
6250
|
+
y: frame.value
|
|
6251
|
+
});
|
|
6252
|
+
if (!candle) return;
|
|
6253
|
+
out.push(`<g data-chart-series="${slots.close}" data-chart-point="${i}">`);
|
|
6254
|
+
out.push(
|
|
6255
|
+
line(
|
|
6256
|
+
candle.wick.x,
|
|
6257
|
+
candle.wick.y1,
|
|
6258
|
+
candle.wick.x,
|
|
6259
|
+
candle.wick.y2,
|
|
6260
|
+
style.wick.color,
|
|
6261
|
+
style.wick.width
|
|
6262
|
+
)
|
|
6263
|
+
);
|
|
6264
|
+
if (candle.body) {
|
|
6265
|
+
const { x, y, w, h, up } = candle.body;
|
|
6266
|
+
const bar = up ? style.up : style.down;
|
|
6267
|
+
const stroke = bar.stroke === "none" ? "" : ` stroke="${esc(bar.stroke)}" stroke-width="${n(bar.strokeWidth)}"`;
|
|
6268
|
+
out.push(rect(x, y, w, h, bar.fill).replace("/>", `${stroke}/>`));
|
|
6269
|
+
} else if (candle.tick) {
|
|
6270
|
+
out.push(
|
|
6271
|
+
line(
|
|
6272
|
+
candle.tick.x1,
|
|
6273
|
+
candle.tick.y,
|
|
6274
|
+
candle.tick.x2,
|
|
6275
|
+
candle.tick.y,
|
|
6276
|
+
closeColor,
|
|
6277
|
+
STOCK_TICK_WIDTH
|
|
6278
|
+
)
|
|
6279
|
+
);
|
|
6280
|
+
}
|
|
6281
|
+
out.push("</g>");
|
|
6282
|
+
});
|
|
6283
|
+
}
|
|
6284
|
+
|
|
6285
|
+
// chart/render/chart-svg-waterfall.ts
|
|
6286
|
+
var CONNECTOR_COLOR = "#7F7F7F";
|
|
6287
|
+
var BAR_SHARE = 2 / 3;
|
|
6288
|
+
function waterfallBars(model, frame, out) {
|
|
6289
|
+
const view = model.waterfall;
|
|
6290
|
+
if (!view) return;
|
|
6291
|
+
const width = frame.bandSize * BAR_SHARE;
|
|
6292
|
+
view.steps.forEach((step, i) => {
|
|
6293
|
+
const a2 = frame.value(step.startValue);
|
|
6294
|
+
const b = frame.value(step.endValue);
|
|
6295
|
+
const color = step.isSubtotal ? view.colors.total : step.value >= 0 ? view.colors.increase : view.colors.decrease;
|
|
6296
|
+
const x = frame.band(i) - width / 2;
|
|
6297
|
+
out.push(`<g data-chart-series="0" data-chart-point="${step.sourceIndex}">`);
|
|
6298
|
+
out.push(rect(x, Math.min(a2, b), width, Math.max(Math.abs(b - a2), 1), color));
|
|
6299
|
+
out.push("</g>");
|
|
6300
|
+
const next = view.steps[i + 1];
|
|
6301
|
+
if (view.connectors && next) {
|
|
6302
|
+
const xNext = frame.band(i + 1) - width / 2;
|
|
6303
|
+
out.push(
|
|
6304
|
+
line(x + width, b, xNext, b, CONNECTOR_COLOR, 0.75).replace(
|
|
6305
|
+
"/>",
|
|
6306
|
+
` stroke-dasharray="${n(3)} ${n(2)}"/>`
|
|
6307
|
+
)
|
|
6308
|
+
);
|
|
6309
|
+
}
|
|
6310
|
+
});
|
|
6311
|
+
}
|
|
6312
|
+
|
|
6313
|
+
// chart/render/chart-svg-plots.ts
|
|
6314
|
+
var RANK = {
|
|
6315
|
+
area: 0,
|
|
6316
|
+
bar: 1,
|
|
6317
|
+
column: 1,
|
|
6318
|
+
histogram: 1,
|
|
6319
|
+
line: 2,
|
|
6320
|
+
stock: 2
|
|
6321
|
+
};
|
|
6322
|
+
function paint(layer, out) {
|
|
6323
|
+
const { model, frame } = layer;
|
|
6324
|
+
if (model.type === "stock") stockBars(model, frame, out);
|
|
6325
|
+
else if (model.type === "bar" || model.type === "column" || model.type === "histogram")
|
|
6326
|
+
bars(model, frame, out, plotted(model));
|
|
6327
|
+
else linesAndAreas(model, frame, out);
|
|
4657
6328
|
}
|
|
4658
6329
|
function cartesianSvg(model, area) {
|
|
4659
6330
|
const out = [];
|
|
4660
|
-
if (model.type === "scatter") {
|
|
6331
|
+
if (model.type === "scatter" || model.type === "bubble") {
|
|
4661
6332
|
scatter(model, area, out);
|
|
4662
6333
|
return out.join("");
|
|
4663
6334
|
}
|
|
4664
|
-
const frame =
|
|
6335
|
+
const frame = cartesianAxes(model, area, out);
|
|
4665
6336
|
if (!frame) return "";
|
|
4666
|
-
if (model.type === "
|
|
4667
|
-
|
|
6337
|
+
if (model.type === "waterfall") {
|
|
6338
|
+
waterfallBars(model, frame, out);
|
|
6339
|
+
return out.join("");
|
|
6340
|
+
}
|
|
6341
|
+
if (model.type === "stock") {
|
|
6342
|
+
stockBars(model, frame, out);
|
|
6343
|
+
return out.join("");
|
|
6344
|
+
}
|
|
6345
|
+
const layers = [{ model, frame }];
|
|
6346
|
+
for (const group2 of model.extraGroups ?? []) {
|
|
6347
|
+
const grouped = {
|
|
6348
|
+
...model,
|
|
6349
|
+
type: group2.type,
|
|
6350
|
+
grouping: group2.grouping,
|
|
6351
|
+
series: group2.series,
|
|
6352
|
+
horizontal: false
|
|
6353
|
+
};
|
|
6354
|
+
if (group2.stock) grouped.stock = group2.stock;
|
|
6355
|
+
else delete grouped.stock;
|
|
6356
|
+
if (group2.barGapWidth !== void 0) grouped.barGapWidth = group2.barGapWidth;
|
|
6357
|
+
else delete grouped.barGapWidth;
|
|
6358
|
+
if (group2.barOverlap !== void 0) grouped.barOverlap = group2.barOverlap;
|
|
6359
|
+
else delete grouped.barOverlap;
|
|
6360
|
+
const value = group2.secondary && frame.secondary ? frame.secondary : frame.value;
|
|
6361
|
+
layers.push({ model: grouped, frame: { ...frame, value } });
|
|
6362
|
+
}
|
|
6363
|
+
layers.map((layer, order) => ({ layer, order })).sort(
|
|
6364
|
+
(a2, b) => (RANK[a2.layer.model.type] ?? 1) - (RANK[b.layer.model.type] ?? 1) || a2.order - b.order
|
|
6365
|
+
).forEach(({ layer }) => paint(layer, out));
|
|
6366
|
+
categoryAnalysis(model, frame, out);
|
|
4668
6367
|
return out.join("");
|
|
4669
6368
|
}
|
|
4670
6369
|
|
|
4671
6370
|
// chart/render/chart-svg-radial.ts
|
|
4672
|
-
var polar = (
|
|
4673
|
-
|
|
6371
|
+
var polar = (cx2, cy, r, angle) => [
|
|
6372
|
+
cx2 + r * Math.sin(angle),
|
|
4674
6373
|
cy - r * Math.cos(angle)
|
|
4675
6374
|
];
|
|
4676
|
-
function slicePath(
|
|
6375
|
+
function slicePath(cx2, cy, r, inner, a0, a1) {
|
|
4677
6376
|
const sweep = a1 - a0;
|
|
4678
6377
|
if (sweep >= Math.PI * 2 - 1e-9) {
|
|
4679
6378
|
const mid = a0 + Math.PI;
|
|
4680
|
-
return slicePath(
|
|
6379
|
+
return slicePath(cx2, cy, r, inner, a0, mid) + slicePath(cx2, cy, r, inner, mid, a1);
|
|
4681
6380
|
}
|
|
4682
6381
|
const large = sweep > Math.PI ? 1 : 0;
|
|
4683
|
-
const [x0, y0] = polar(
|
|
4684
|
-
const [x1, y1] = polar(
|
|
6382
|
+
const [x0, y0] = polar(cx2, cy, r, a0);
|
|
6383
|
+
const [x1, y1] = polar(cx2, cy, r, a1);
|
|
4685
6384
|
if (inner <= 0)
|
|
4686
|
-
return `M${n(
|
|
4687
|
-
const [ix1, iy1] = polar(
|
|
4688
|
-
const [ix0, iy0] = polar(
|
|
6385
|
+
return `M${n(cx2)},${n(cy)} L${n(x0)},${n(y0)} A${n(r)},${n(r)} 0 ${large} 1 ${n(x1)},${n(y1)} Z`;
|
|
6386
|
+
const [ix1, iy1] = polar(cx2, cy, inner, a1);
|
|
6387
|
+
const [ix0, iy0] = polar(cx2, cy, inner, a0);
|
|
4689
6388
|
return `M${n(x0)},${n(y0)} A${n(r)},${n(r)} 0 ${large} 1 ${n(x1)},${n(y1)} L${n(ix1)},${n(iy1)} A${n(inner)},${n(inner)} 0 ${large} 0 ${n(ix0)},${n(iy0)} Z`;
|
|
4690
6389
|
}
|
|
4691
6390
|
function pieSvg(model, area) {
|
|
4692
6391
|
const out = [chartAreaRect(model, "plotArea", area)];
|
|
4693
|
-
const
|
|
6392
|
+
const cx2 = area.x + area.w / 2;
|
|
4694
6393
|
const cy = area.y + area.h / 2;
|
|
4695
6394
|
const radius = Math.max(1, Math.min(area.w, area.h) / 2 - 4);
|
|
4696
6395
|
const rings = model.type === "doughnut" ? model.series : model.series.slice(0, 1);
|
|
@@ -4707,7 +6406,7 @@ function pieSvg(model, area) {
|
|
|
4707
6406
|
const sweep = v / total * Math.PI * 2;
|
|
4708
6407
|
const color = s.pointColors?.[i] ?? s.color;
|
|
4709
6408
|
out.push(
|
|
4710
|
-
`<path d="${slicePath(
|
|
6409
|
+
`<path d="${slicePath(cx2, cy, outer, inner, angle, angle + sweep)}" fill="${color}" stroke="#FFFFFF" stroke-width="1"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
4711
6410
|
);
|
|
4712
6411
|
angle += sweep;
|
|
4713
6412
|
});
|
|
@@ -4725,7 +6424,7 @@ function radarSvg(model, area) {
|
|
|
4725
6424
|
const categorySize = categoryAttrs.size ?? 10;
|
|
4726
6425
|
const grid = chartStroke(model, "gridlineMajor");
|
|
4727
6426
|
const axis = chartStroke(model, "categoryAxis");
|
|
4728
|
-
const
|
|
6427
|
+
const cx2 = area.x + area.w / 2;
|
|
4729
6428
|
const cy = area.y + area.h / 2 + 4;
|
|
4730
6429
|
const radius = Math.max(1, Math.min(area.w, area.h) / 2 - Math.max(18, categorySize * 1.8));
|
|
4731
6430
|
const angle = (i) => i / count * Math.PI * 2;
|
|
@@ -4735,30 +6434,30 @@ function radarSvg(model, area) {
|
|
|
4735
6434
|
Math.ceil(12 / Math.max(1, radius / Math.max(1, scale.ticks.length - 1)))
|
|
4736
6435
|
);
|
|
4737
6436
|
for (const [k, t] of scale.ticks.entries()) {
|
|
4738
|
-
const ring = Array.from({ length: count }, (_, i) => polar(
|
|
6437
|
+
const ring = Array.from({ length: count }, (_, i) => polar(cx2, cy, r(t), angle(i))).map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
4739
6438
|
out.push(
|
|
4740
6439
|
`<polygon points="${ring}" fill="none" stroke="${grid.color}" stroke-width="${n(grid.width)}"/>`
|
|
4741
6440
|
);
|
|
4742
6441
|
if (model.appearance?.valueAxis?.labelsVisible !== false && k % labelEvery === 0)
|
|
4743
6442
|
out.push(
|
|
4744
|
-
|
|
6443
|
+
text2(cx2 + 3, cy - r(t) + valueSize * 0.3, formatAxisValue(t, scale.percent), valueAttrs)
|
|
4745
6444
|
);
|
|
4746
6445
|
}
|
|
4747
6446
|
model.categories.forEach((c2, i) => {
|
|
4748
|
-
const [x, y] = polar(
|
|
4749
|
-
out.push(line(
|
|
4750
|
-
const [lx, ly] = polar(
|
|
4751
|
-
const anchor = Math.abs(lx -
|
|
6447
|
+
const [x, y] = polar(cx2, cy, radius, angle(i));
|
|
6448
|
+
out.push(line(cx2, cy, x, y, axis.color, axis.width));
|
|
6449
|
+
const [lx, ly] = polar(cx2, cy, radius + 10, angle(i));
|
|
6450
|
+
const anchor = Math.abs(lx - cx2) < 2 ? "middle" : lx > cx2 ? "start" : "end";
|
|
4752
6451
|
if (model.appearance?.categoryAxis?.labelsVisible !== false)
|
|
4753
6452
|
out.push(
|
|
4754
|
-
|
|
6453
|
+
text2(lx, ly + categorySize * 0.3, fit(c2, area.w / 4, categorySize), {
|
|
4755
6454
|
anchor,
|
|
4756
6455
|
...categoryAttrs
|
|
4757
6456
|
})
|
|
4758
6457
|
);
|
|
4759
6458
|
});
|
|
4760
6459
|
for (const s of model.series) {
|
|
4761
|
-
const points = s.values.slice(0, count).map((v, i) => polar(
|
|
6460
|
+
const points = s.values.slice(0, count).map((v, i) => polar(cx2, cy, r(v ?? scale.min), angle(i))).map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
4762
6461
|
out.push(
|
|
4763
6462
|
`<polygon points="${points}" fill="none" stroke="${s.color}" stroke-width="2"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
4764
6463
|
);
|
|
@@ -4766,6 +6465,88 @@ function radarSvg(model, area) {
|
|
|
4766
6465
|
return out.join("");
|
|
4767
6466
|
}
|
|
4768
6467
|
|
|
6468
|
+
// chart/render/chart-svg-hierarchy.ts
|
|
6469
|
+
var colorAt2 = (model, index) => {
|
|
6470
|
+
const first2 = model.series[0];
|
|
6471
|
+
const colors = first2?.pointColors;
|
|
6472
|
+
return (colors && colors.length > 0 ? colors[index % colors.length] : void 0) ?? first2?.color ?? "#4472C4";
|
|
6473
|
+
};
|
|
6474
|
+
var leafValues = (model) => (model.series[0]?.values ?? []).map((v) => v ?? 0);
|
|
6475
|
+
function treemapSvg(model, area) {
|
|
6476
|
+
const out = [chartAreaRect(model, "plotArea", area)];
|
|
6477
|
+
const hierarchy = model.hierarchy;
|
|
6478
|
+
const series = model.series.map((s) => ({
|
|
6479
|
+
name: s.name,
|
|
6480
|
+
values: s.values.map((v) => v ?? 0),
|
|
6481
|
+
// Without data labels Office draws no parent banners either, so no space is reserved.
|
|
6482
|
+
parentLabelLayout: hierarchy?.labels === false ? "none" : hierarchy?.parentLabelLayout
|
|
6483
|
+
}));
|
|
6484
|
+
const roots = buildHierarchyRoots(
|
|
6485
|
+
series,
|
|
6486
|
+
model.categories,
|
|
6487
|
+
hierarchy && hierarchy.levels.length > 1 ? hierarchy.levels : void 0
|
|
6488
|
+
);
|
|
6489
|
+
const cells = layoutTreemap(roots, { x: area.x, y: area.y, w: area.w, h: area.h });
|
|
6490
|
+
for (const cell of cells) {
|
|
6491
|
+
if (cell.kind === "parent") {
|
|
6492
|
+
if (hierarchy?.labels !== false)
|
|
6493
|
+
out.push(text2(cell.x, cell.y, cell.label, { size: 10, weight: "bold", fill: "#303030" }));
|
|
6494
|
+
continue;
|
|
6495
|
+
}
|
|
6496
|
+
out.push(`<g data-chart-series="${cell.seriesIndex}" data-chart-point="${cell.pointIndex}">`);
|
|
6497
|
+
out.push(
|
|
6498
|
+
rect(cell.x, cell.y, cell.w, cell.h, colorAt2(model, cell.colorIndex)).replace(
|
|
6499
|
+
"/>",
|
|
6500
|
+
' rx="2"/>'
|
|
6501
|
+
)
|
|
6502
|
+
);
|
|
6503
|
+
if (cell.labelFits && hierarchy?.labels !== false)
|
|
6504
|
+
out.push(
|
|
6505
|
+
text2(
|
|
6506
|
+
cell.x + cell.w / 2,
|
|
6507
|
+
cell.y + cell.h / 2,
|
|
6508
|
+
fit(cell.label, cell.w - 4, cell.labelSize),
|
|
6509
|
+
{
|
|
6510
|
+
anchor: "middle",
|
|
6511
|
+
size: cell.labelSize,
|
|
6512
|
+
weight: "bold",
|
|
6513
|
+
fill: "#FFFFFF",
|
|
6514
|
+
baseline: "central"
|
|
6515
|
+
}
|
|
6516
|
+
)
|
|
6517
|
+
);
|
|
6518
|
+
out.push("</g>");
|
|
6519
|
+
}
|
|
6520
|
+
return out.join("");
|
|
6521
|
+
}
|
|
6522
|
+
function sunburstSvg(model, area) {
|
|
6523
|
+
const out = [chartAreaRect(model, "plotArea", area)];
|
|
6524
|
+
const cx2 = area.x + area.w / 2;
|
|
6525
|
+
const cy = area.y + area.h / 2;
|
|
6526
|
+
const maxR = Math.min(area.w, area.h) / 2 - 4;
|
|
6527
|
+
if (maxR <= 0) return out.join("");
|
|
6528
|
+
const levels = model.hierarchy?.levels ?? [];
|
|
6529
|
+
const arcs = levels.length > 1 ? computeHierarchicalSunburstArcs(levels, leafValues(model), cx2, cy, maxR) : computeSunburstArcs(
|
|
6530
|
+
model.series.map((s) => ({ values: s.values.map((v) => v ?? 0) })),
|
|
6531
|
+
cx2,
|
|
6532
|
+
cy,
|
|
6533
|
+
maxR
|
|
6534
|
+
);
|
|
6535
|
+
for (const arc of arcs)
|
|
6536
|
+
out.push(
|
|
6537
|
+
`<path d="${arc.d}" fill="${colorAt2(model, arc.colorIndex)}" stroke="#FFFFFF" stroke-width="1.5"${arc.pointIndex === void 0 ? "" : ` data-chart-series="0" data-chart-point="${arc.pointIndex}"`}/>`
|
|
6538
|
+
);
|
|
6539
|
+
const flatLabels = levels.length > 1 || model.series.length !== 1 ? void 0 : model.categories;
|
|
6540
|
+
for (const arc of model.hierarchy?.labels === false ? [] : arcs) {
|
|
6541
|
+
const label = arc.label ?? (arc.pointIndex === void 0 ? void 0 : flatLabels?.[arc.pointIndex]);
|
|
6542
|
+
if (!label) continue;
|
|
6543
|
+
out.push(
|
|
6544
|
+
`<text x="${n(arc.labelX)}" y="${n(arc.labelY)}" font-size="10" fill="#FFFFFF" text-anchor="middle" dominant-baseline="central" transform="rotate(${n(arc.labelRotation)}, ${n(arc.labelX)}, ${n(arc.labelY)})">${esc(label)}</text>`
|
|
6545
|
+
);
|
|
6546
|
+
}
|
|
6547
|
+
return out.join("");
|
|
6548
|
+
}
|
|
6549
|
+
|
|
4769
6550
|
// chart/render/chart-svg-text-metrics.ts
|
|
4770
6551
|
var CHART_FONT_FAMILY = "Calibri, Carlito, Arial, sans-serif";
|
|
4771
6552
|
function cssFont(attrs) {
|
|
@@ -4839,7 +6620,7 @@ function chartLegendSvg(model, area, frame, options) {
|
|
|
4839
6620
|
const x = horizontal ? horizontalX : manual.x + Math.max(size / 4, (rowWidth - contentWidth) / 2);
|
|
4840
6621
|
const centerY = manual.y + (horizontal ? 0 : i * rowHeight) + rowHeight / 2;
|
|
4841
6622
|
markup.push(rect(x, centerY - keySize / 2, keySize, keySize, entry3.color));
|
|
4842
|
-
markup.push(
|
|
6623
|
+
markup.push(text2(x + keySize + keyGap, centerY + baselineOffset, label, attrs));
|
|
4843
6624
|
if (horizontal) horizontalX += (widths[i] ?? 0) + horizontalGap;
|
|
4844
6625
|
});
|
|
4845
6626
|
return {
|
|
@@ -4856,7 +6637,23 @@ function legendEntries(model) {
|
|
|
4856
6637
|
color: first2?.pointColors?.[i] ?? first2?.color ?? "#4472C4"
|
|
4857
6638
|
}));
|
|
4858
6639
|
}
|
|
4859
|
-
|
|
6640
|
+
if ((model.type === "treemap" || model.type === "sunburst") && model.hierarchy) {
|
|
6641
|
+
const first2 = model.series[0];
|
|
6642
|
+
return model.hierarchy.branches.map((label, i) => ({
|
|
6643
|
+
label,
|
|
6644
|
+
color: first2?.pointColors?.[i % Math.max(1, first2.pointColors.length)] ?? first2?.color ?? "#4472C4"
|
|
6645
|
+
}));
|
|
6646
|
+
}
|
|
6647
|
+
if (model.type === "waterfall" && model.waterfall)
|
|
6648
|
+
return [
|
|
6649
|
+
{ label: "Increase", color: model.waterfall.colors.increase },
|
|
6650
|
+
{ label: "Decrease", color: model.waterfall.colors.decrease },
|
|
6651
|
+
{ label: "Total", color: model.waterfall.colors.total }
|
|
6652
|
+
];
|
|
6653
|
+
return [...model.series, ...(model.extraGroups ?? []).flatMap((g) => g.series)].map((s) => ({
|
|
6654
|
+
label: s.name,
|
|
6655
|
+
color: s.color
|
|
6656
|
+
}));
|
|
4860
6657
|
}
|
|
4861
6658
|
function automaticLegend(model, area, out, options, bounds) {
|
|
4862
6659
|
const entries = legendEntries(model);
|
|
@@ -4884,7 +6681,7 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
4884
6681
|
entries.forEach((e, i) => {
|
|
4885
6682
|
const w = widths[i] ?? 0;
|
|
4886
6683
|
out.push(rect(x2, y, 8, 8, e.color));
|
|
4887
|
-
out.push(
|
|
6684
|
+
out.push(text2(x2 + 12, y + 8, fitChartText(e.label, w - 16, attrs, options), attrs));
|
|
4888
6685
|
x2 += w;
|
|
4889
6686
|
});
|
|
4890
6687
|
return pos === "t" ? { x: area.x, y: area.y + rowH + 4, w: area.w, h: area.h - rowH - 4 } : { x: area.x, y: area.y, w: area.w, h: area.h - rowH - 4 };
|
|
@@ -4909,7 +6706,7 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
4909
6706
|
const y = y0 + i * rowH;
|
|
4910
6707
|
if (y + rowH > area.y + area.h + 2) return;
|
|
4911
6708
|
out.push(rect(x, y + 3, 8, 8, e.color));
|
|
4912
|
-
out.push(
|
|
6709
|
+
out.push(text2(x + 12, y + 11, fitChartText(e.label, width - 16, attrs, options), attrs));
|
|
4913
6710
|
});
|
|
4914
6711
|
return pos === "l" ? { x: area.x + width + 8, y: area.y, w: area.w - width - 8, h: area.h } : { x: area.x, y: area.y, w: area.w - width - 8, h: area.h };
|
|
4915
6712
|
}
|
|
@@ -4921,12 +6718,12 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
|
|
|
4921
6718
|
for (const [source, run2] of runs.entries()) {
|
|
4922
6719
|
for (const token of run2.text.split(/(\r\n|[\r\n]|[ \t]+)/u).filter(Boolean)) {
|
|
4923
6720
|
const kind = /^[\r\n]+$/u.test(token) ? "break" : /^[ \t]+$/u.test(token) ? "space" : "word";
|
|
4924
|
-
let
|
|
4925
|
-
if (!
|
|
4926
|
-
|
|
4927
|
-
groups.push(
|
|
6721
|
+
let group2 = groups.at(-1);
|
|
6722
|
+
if (!group2 || group2.kind !== kind || kind === "break") {
|
|
6723
|
+
group2 = { kind, pieces: [] };
|
|
6724
|
+
groups.push(group2);
|
|
4928
6725
|
}
|
|
4929
|
-
if (kind !== "break")
|
|
6726
|
+
if (kind !== "break") group2.pieces.push({ run: run2, source, text: token });
|
|
4930
6727
|
}
|
|
4931
6728
|
}
|
|
4932
6729
|
const merged = (left, right) => {
|
|
@@ -4950,29 +6747,29 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
|
|
|
4950
6747
|
line2 = [];
|
|
4951
6748
|
spaces = [];
|
|
4952
6749
|
};
|
|
4953
|
-
for (const
|
|
4954
|
-
if (
|
|
6750
|
+
for (const group2 of groups) {
|
|
6751
|
+
if (group2.kind === "break") {
|
|
4955
6752
|
flush();
|
|
4956
6753
|
continue;
|
|
4957
6754
|
}
|
|
4958
|
-
if (
|
|
4959
|
-
spaces =
|
|
6755
|
+
if (group2.kind === "space") {
|
|
6756
|
+
spaces = group2.pieces;
|
|
4960
6757
|
continue;
|
|
4961
6758
|
}
|
|
4962
6759
|
const separator = line2.length ? spaces : [];
|
|
4963
|
-
const wordWidth = width(
|
|
4964
|
-
if (line2.length && width(merged(line2, [...separator, ...
|
|
6760
|
+
const wordWidth = width(group2.pieces);
|
|
6761
|
+
if (line2.length && width(merged(line2, [...separator, ...group2.pieces])) > maxWidth) flush();
|
|
4965
6762
|
else line2 = merged(line2, separator);
|
|
4966
6763
|
spaces = [];
|
|
4967
6764
|
if (options.breakWords && wordWidth > maxWidth) {
|
|
4968
|
-
for (const piece of
|
|
4969
|
-
for (const { segment } of graphemes.segment(piece.text)) {
|
|
4970
|
-
const next = { ...piece, text:
|
|
6765
|
+
for (const piece of group2.pieces) {
|
|
6766
|
+
for (const { segment: segment2 } of graphemes.segment(piece.text)) {
|
|
6767
|
+
const next = { ...piece, text: segment2 };
|
|
4971
6768
|
if (line2.length && width(merged(line2, [next])) > maxWidth) flush();
|
|
4972
6769
|
line2 = merged(line2, [next]);
|
|
4973
6770
|
}
|
|
4974
6771
|
}
|
|
4975
|
-
} else line2 = merged(line2,
|
|
6772
|
+
} else line2 = merged(line2, group2.pieces);
|
|
4976
6773
|
}
|
|
4977
6774
|
flush();
|
|
4978
6775
|
return result;
|
|
@@ -5082,7 +6879,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
5082
6879
|
let x = line2.align === "l" ? (width - boxWidth) / 2 + 4 : line2.align === "r" ? (width + boxWidth) / 2 - 4 - line2.width : (width - line2.width) / 2;
|
|
5083
6880
|
for (const run2 of line2.runs) {
|
|
5084
6881
|
spans.push(
|
|
5085
|
-
|
|
6882
|
+
text2(x, baseline, run2.text, {
|
|
5086
6883
|
...run2.attrs,
|
|
5087
6884
|
anchor: "start"
|
|
5088
6885
|
}).replace("<text ", '<tspan data-chart-title-run="true" ').replace("</text>", "</tspan>")
|
|
@@ -5090,7 +6887,7 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
5090
6887
|
x += chartTextWidth(run2.text, run2.attrs, options);
|
|
5091
6888
|
}
|
|
5092
6889
|
}
|
|
5093
|
-
const parent =
|
|
6890
|
+
const parent = text2(0, 0, "", { ...base, underline: false }).replace(
|
|
5094
6891
|
"</text>",
|
|
5095
6892
|
`${spans.join("")}</text>`
|
|
5096
6893
|
);
|
|
@@ -5114,8 +6911,8 @@ function chartRichTitleSvg(model, width, options = {}, frameHeight = 400) {
|
|
|
5114
6911
|
|
|
5115
6912
|
// chart/render/chart-svg.ts
|
|
5116
6913
|
function renderChartSvg(model, width, height, options = {}) {
|
|
5117
|
-
const
|
|
5118
|
-
model =
|
|
6914
|
+
const paint2 = chartGradientPaint(model, Math.max(1, width), Math.max(1, height));
|
|
6915
|
+
model = paint2.model;
|
|
5119
6916
|
const w = Math.max(1, width);
|
|
5120
6917
|
const h = Math.max(1, height);
|
|
5121
6918
|
const out = [];
|
|
@@ -5124,7 +6921,7 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
5124
6921
|
`<svg xmlns="http://www.w3.org/2000/svg" width="${n(w)}" height="${n(h)}" viewBox="0 0 ${n(w)} ${n(h)}" font-family="${esc(CHART_FONT_FAMILY)}" role="img">`
|
|
5125
6922
|
);
|
|
5126
6923
|
if (model.title) out.push(`<title>${esc(model.title)}</title>`);
|
|
5127
|
-
if (
|
|
6924
|
+
if (paint2.defs) out.push(paint2.defs);
|
|
5128
6925
|
out.push(chartAreaRect(model, "chartArea", { x: 0, y: 0, w, h }));
|
|
5129
6926
|
let area = { x: 8, y: 8, w: w - 16, h: h - 16 };
|
|
5130
6927
|
const richTitle = chartRichTitleSvg(model, w, options, h);
|
|
@@ -5149,7 +6946,7 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
5149
6946
|
})
|
|
5150
6947
|
);
|
|
5151
6948
|
out.push(
|
|
5152
|
-
|
|
6949
|
+
text2(w / 2, 8 + size, label, {
|
|
5153
6950
|
anchor: "middle",
|
|
5154
6951
|
fill: "#404040",
|
|
5155
6952
|
...attrs
|
|
@@ -5160,7 +6957,7 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
5160
6957
|
}
|
|
5161
6958
|
if (!model.supported) {
|
|
5162
6959
|
out.push(
|
|
5163
|
-
|
|
6960
|
+
text2(w / 2, area.y + area.h / 2, `${model.type} charts are not drawn`, { anchor: "middle" })
|
|
5164
6961
|
);
|
|
5165
6962
|
if (foregroundTitle) out.push(foregroundTitle);
|
|
5166
6963
|
out.push("</svg>");
|
|
@@ -5172,6 +6969,8 @@ function renderChartSvg(model, width, height, options = {}) {
|
|
|
5172
6969
|
if (area.w > 4 && area.h > 4) {
|
|
5173
6970
|
if (model.type === "pie" || model.type === "doughnut") out.push(pieSvg(model, area));
|
|
5174
6971
|
else if (model.type === "radar") out.push(radarSvg(model, area));
|
|
6972
|
+
else if (model.type === "treemap") out.push(treemapSvg(model, area));
|
|
6973
|
+
else if (model.type === "sunburst") out.push(sunburstSvg(model, area));
|
|
5175
6974
|
else out.push(cartesianSvg(model, area));
|
|
5176
6975
|
}
|
|
5177
6976
|
if (legend.foreground) out.push(legend.markup);
|
|
@@ -5189,7 +6988,13 @@ var DRAWN_CHART_TYPES = /* @__PURE__ */ new Set([
|
|
|
5189
6988
|
"pie",
|
|
5190
6989
|
"doughnut",
|
|
5191
6990
|
"scatter",
|
|
5192
|
-
"radar"
|
|
6991
|
+
"radar",
|
|
6992
|
+
"waterfall",
|
|
6993
|
+
"histogram",
|
|
6994
|
+
"bubble",
|
|
6995
|
+
"stock",
|
|
6996
|
+
"treemap",
|
|
6997
|
+
"sunburst"
|
|
5193
6998
|
]);
|
|
5194
6999
|
function chartThemePalette(theme, fonts = {}) {
|
|
5195
7000
|
return {
|
|
@@ -5215,5 +7020,10 @@ function renderChartSpaceSvg(space, options) {
|
|
|
5215
7020
|
const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
|
|
5216
7021
|
return renderChartSvg(view, width, height, svg);
|
|
5217
7022
|
}
|
|
7023
|
+
function renderChartSummarySvg(summary, options) {
|
|
7024
|
+
const { width, height, theme, fonts, ...svg } = options;
|
|
7025
|
+
const view = chartSummaryView(summary, chartThemePalette(theme, fonts));
|
|
7026
|
+
return renderChartSvg(view, width, height, svg);
|
|
7027
|
+
}
|
|
5218
7028
|
|
|
5219
|
-
export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DEFAULT_BAR_GAP_WIDTH, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, THEME_SLOTS, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, axisTargetIntervals, buildChartGradientDef, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartGradientMarkup, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, clusteredBarGeometry, computeBoxStats, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, effectiveBuiltInChartStyle, findChartColorPalette, fitPolynomial, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, groupRowsByCategory, hasManualLayoutFields, modulateLuminance, niceAxisStep, niceValueAxisBounds, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSvg, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveManualLayoutRect, scottBinCount, sortGradientStops, squarify, themeColor, updateGradientStop, visibleRuns, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };
|
|
7029
|
+
export { BEST_FIT_EDGE_TOLERANCE, BEST_FIT_OUTSIDE_GAP, BEST_FIT_RIM_INSET, CHART_AUTO_TITLE, CHART_COLOR_PALETTES, CHART_COLOR_STYLE_CONTENT_TYPE, CHART_COLOR_STYLE_NS, CHART_COLOR_STYLE_REL, CHART_ERROR_BAR_DIRECTIONS, CHART_ERROR_BAR_TYPES, CHART_ERROR_VALUE_TYPES, CHART_GROUP_ELEMENTS, CHART_STYLE_PARTS, DEFAULT_BAR_GAP_WIDTH, DEFAULT_CHART_PALETTE, DEFAULT_THEME_COLORS, DRAWN_CHART_TYPES, LABEL_COLLISION_GAP, STOCK_DEFAULT_DOWN_FILL, STOCK_DEFAULT_UP_FILL, STOCK_DEFAULT_WICK_COLOR, STOCK_TICK_WIDTH, THEME_SLOTS, aggregate, aggregateByCategory, assertBarClusterOptions, autoSeriesColor, axisTargetIntervals, buildChartGradientDef, buildHierarchyRoots, buildWaterfallSteps, builtInChartStyleXml, builtInChartTextStyle, categoryTotals, chartCacheValues, chartColorScheme, chartColorStyleId, chartColorStyleXml, chartErrorBarAmount, chartExSummary, chartGradientMarkup, chartPaletteColors, chartPaletteSeriesColor, chartPaletteSeriesColorChoice, chartSampleVariance, chartSourceValues, chartSpaceKind, chartSummaryFromSpace, chartSummarySeries, chartSummaryView, chartThemePalette, chartTrendlineKind, chartTrendlineType, clusteredBarGeometry, computeBoxStats, computeBubbleRadius, computeHierarchicalSunburstArcs, computeHistogramBins, computeLinearRegression, computeRSquared, computeRadarPoints, computeStackedSeriesPlots, computeSunburstArcs, computeWaterfallRange, effectiveBuiltInChartStyle, findChartColorPalette, fitChartTrendline, fitPolynomial, formatChartNumber, formatChartNumberWithColor, formatCompactAxisValue, formatExponentialEquation, formatLinearEquation, formatLogarithmicEquation, formatPolynomialEquation, formatPowerEquation, formatTrendlineCoefficient, getChartStylePalette, groupRowsByCategory, hasManualLayoutFields, hierarchyBranchLabels, impliesAutoTitle, isChartexOnlyType, layoutTreemap, maxBubbleSize, medianBubbleRadius, modulateLuminance, niceAxisStep, niceValueAxisBounds, normalizeLevels, nudgeOutsideLabels, parseChartSpace, placeBestFitLabel, radarAngle, radarRingPoints, readBuiltInChartStyle, readChartFormatting, readChartManualLayoutValues, readChartStyle, readDisplayNaAsBlank, removeGradientStop, renderChartSpaceSvg, renderChartSummarySvg, renderChartSvg, resolveAutoTitleText, resolveBlankDisplay, resolveChartGradient, resolveChartStyleDefinition, resolveManualLayoutRect, scottBinCount, shade, sortGradientStops, squarify, stockCandle, stockSlots, sunburstArcPath, themeColor, tint, updateGradientStop, visibleRuns, withChartGradientDirection, withinLinearTransform, writeChartAxisFormatting, writeChartFillFormatting, writeChartLayoutFormatting, writeChartSpace };
|