ooxml-ui 0.31.0 → 1.0.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/README.md +14 -0
- package/custom-elements.json +10 -0
- package/dist/{chunk-RAZAJMHK.js → chunk-4QQASR5A.js} +2 -2
- package/dist/{chunk-HZ422LTR.js → chunk-BOX43CZD.js} +1 -0
- package/dist/{chunk-3GE2NHNG.js → chunk-FLHM5Q4O.js} +119 -81
- package/dist/{chunk-2QW4QE56.js → chunk-T3HB5LMH.js} +103 -68
- package/dist/controls.js +2 -2
- package/dist/docx/hard-break-command.d.ts +1 -3
- package/dist/docx/link-commands.d.ts +4 -15
- package/dist/docx/note-editor.d.ts +3 -2
- package/dist/docx/run-styles.d.ts +1 -1
- package/dist/docx/schema.d.ts +1 -1
- package/dist/docx/toggle-commands.d.ts +2 -8
- package/dist/docx.js +109 -302
- package/dist/form/gradient-direction-gallery.d.ts +19 -0
- package/dist/form/gradient-gallery-preview.d.ts +3 -0
- package/dist/form/gradient-preset-gallery.d.ts +16 -0
- package/dist/form/gradient-stop-track.d.ts +20 -0
- package/dist/form/number-range.d.ts +12 -0
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.js +4 -4
- package/dist/menu/menu-button.d.ts +10 -0
- package/dist/menu/menu-button.d.ts.map +1 -1
- package/dist/pptx/{chart-3d-view-scene-IANLDFIE.mjs → chart-3d-view-scene-2KRQ5667.mjs} +2 -2
- package/dist/pptx/{chart-3d-view-scene-3DK5TUBZ.cjs → chart-3d-view-scene-36DMZWZ3.cjs} +37 -37
- package/dist/pptx/{chunk-C42ZL35K.mjs → chunk-ADOC5JLI.mjs} +1 -1
- package/dist/pptx/{chunk-QM4FGZG4.cjs → chunk-AIL3BNZS.cjs} +31 -131
- package/dist/pptx/{chunk-WLETAW3T.cjs → chunk-CJU4P5FT.cjs} +33 -13
- package/dist/pptx/{chunk-6SCK57RJ.cjs → chunk-FEFQTZDM.cjs} +158 -245
- package/dist/pptx/{chunk-EVGSFPUV.mjs → chunk-XWE5GSE7.mjs} +16 -109
- package/dist/pptx/{chunk-7JEMQW6R.mjs → chunk-YARCML7O.mjs} +11 -122
- package/dist/pptx/{chunk-OHE5UXST.cjs → chunk-YHA6XAB3.cjs} +1 -1
- package/dist/pptx/{chunk-X2F6PA2D.mjs → chunk-YOGDIDPB.mjs} +22 -3
- package/dist/pptx/dom/index.cjs +235 -235
- package/dist/pptx/dom/index.mjs +6 -6
- package/dist/pptx/export/html2canvas-clone.cjs +2 -2
- package/dist/pptx/export/html2canvas-clone.mjs +1 -1
- package/dist/pptx/index.cjs +2993 -2989
- package/dist/pptx/index.mjs +4 -4
- package/dist/pptx/render/chart-combo-stock.cjs +3 -3
- package/dist/pptx/render/chart-combo-stock.mjs +1 -1
- package/dist/pptx/render/chart-manual-layout.d.ts +2 -20
- package/dist/pptx/render/chart-manual-layout.d.ts.map +1 -1
- package/dist/pptx/render/chart-overlays.cjs +7 -7
- package/dist/pptx/render/chart-overlays.mjs +1 -1
- package/dist/pptx/render/chart-surface-treemap.cjs +4 -4
- package/dist/pptx/render/chart-surface-treemap.mjs +1 -1
- package/dist/pptx/render/chart-svg-def-types.d.ts +6 -1
- package/dist/pptx/render/chart-svg-def-types.d.ts.map +1 -1
- package/dist/pptx/render/chart-view-model-dom-helpers.d.ts +1 -1
- package/dist/pptx/render/chart-view-model-dom-helpers.d.ts.map +1 -1
- package/dist/pptx/render/chart-view-model.cjs +41 -41
- package/dist/pptx/render/chart-view-model.mjs +1 -1
- package/dist/pptx/render/chart-waterfall-map.cjs +6 -6
- package/dist/pptx/render/chart-waterfall-map.mjs +1 -1
- package/dist/pptx/render/element-interaction.d.ts +1 -1
- package/dist/pptx/render/element-interaction.d.ts.map +1 -1
- package/dist/pptx/render/gradient-picker.d.ts.map +1 -1
- package/dist/pptx/render/index.d.ts +1 -0
- package/dist/pptx/render/index.d.ts.map +1 -1
- package/dist/pptx/render/path-gradient-rect.d.ts +1 -75
- package/dist/pptx/render/path-gradient-rect.d.ts.map +1 -1
- package/dist/pptx/render/rotate-handle-placement.d.ts +1 -27
- package/dist/pptx/render/rotate-handle-placement.d.ts.map +1 -1
- package/dist/pptx/render/rotation-drag.d.ts +1 -7
- package/dist/pptx/render/rotation-drag.d.ts.map +1 -1
- package/dist/teams/app/files-panel.d.ts +8 -3
- package/dist/teams/app/teams-app.d.ts +1 -0
- package/dist/teams/app/teams-settings.d.ts +6 -0
- package/dist/teams.js +3 -3
- package/dist/visio/render-fill.d.ts +2 -1
- package/dist/visio/render-svg.d.ts +2 -0
- package/dist/visio/ribbon-action.d.ts +8 -1
- package/dist/visio/ribbon-parts.d.ts +2 -1
- package/dist/visio/ribbon-router.d.ts +4 -2
- package/dist/visio/viewer-commands.d.ts +3 -3
- package/dist/visio/viewer-draw-tool.d.ts +16 -6
- package/dist/visio/viewer-handle-events.d.ts +19 -0
- package/dist/visio/viewer-line-endpoints.d.ts +14 -0
- package/dist/visio/viewer-rotation-handle.d.ts +14 -0
- package/dist/visio/viewer-rotation-preview.d.ts +7 -0
- package/dist/visio.js +734 -88
- package/dist/xlsx/chart-area-pane.d.ts +9 -0
- package/dist/xlsx/chart-fill-binding.d.ts +23 -0
- package/dist/xlsx/chart-gradient-preview.d.ts +8 -0
- package/dist/xlsx/chart-series-fill.d.ts +2 -1
- package/dist/xlsx/chart-series-gradient-type.d.ts +9 -0
- package/dist/xlsx/chart-series-gradient.d.ts +8 -0
- package/dist/xlsx/chart-series-pane.d.ts +2 -1
- package/dist/xlsx/chart-series-range-preview.d.ts +7 -0
- package/dist/xlsx/chart-series-transparency.d.ts +2 -1
- package/dist/xlsx/grid/measure.d.ts +5 -0
- package/dist/xlsx/grid/styles.d.ts +1 -1
- package/dist/xlsx.js +962 -102
- package/package.json +2 -2
package/dist/xlsx.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import './chunk-
|
|
1
|
+
import './chunk-4QQASR5A.js';
|
|
2
2
|
import { defineSmartArt } from './chunk-XDUYS4KK.js';
|
|
3
|
-
import { withExtension, saveExtension, downloadBytes, emit, emitEvent, blobFor, announceFileCommand, pickFile } from './chunk-
|
|
4
|
-
export { XLSX_EDITOR_EVENTS } from './chunk-
|
|
3
|
+
import { withExtension, saveExtension, downloadBytes, emit, emitEvent, blobFor, announceFileCommand, pickFile } from './chunk-FLHM5Q4O.js';
|
|
4
|
+
export { XLSX_EDITOR_EVENTS } from './chunk-FLHM5Q4O.js';
|
|
5
5
|
import './chunk-SNV6YKPC.js';
|
|
6
6
|
import './chunk-X7RINDJQ.js';
|
|
7
|
-
import { range_control_default, createRibbonOverflow, defineBackstage, defineRibbon, defineTitleBar, defineStatusBar, defineZoomSlider, rangeControl, defineDialog, runKeyTips, assignKeyTips, defineCheckbox, defineGallery, defineContextMenu, parseSvgPreview } from './chunk-
|
|
8
|
-
import { getIcon, registerIcon } from './chunk-
|
|
7
|
+
import { range_control_default, createRibbonOverflow, defineBackstage, defineRibbon, defineTitleBar, defineStatusBar, defineZoomSlider, rangeControl, defineDialog, runKeyTips, assignKeyTips, defineCheckbox, defineGallery, defineContextMenu, parseSvgPreview } from './chunk-T3HB5LMH.js';
|
|
8
|
+
import { getIcon, registerIcon } from './chunk-BOX43CZD.js';
|
|
9
9
|
import './chunk-OXKWNNNJ.js';
|
|
10
10
|
import { withTokens } from './chunk-ZV2Z4IWH.js';
|
|
11
11
|
import './chunk-JFJXBYRD.js';
|
|
12
12
|
import { SPECIAL_CODES, FRACTION_CODES, AUTOSUM_FUNCTIONS, themeToCssVars, lightTheme, darkTheme, ICON_ACCENTS, ICON_PATHS, normalizeThemeMode, applyThemeColors, parseSelectionRef, selectionRef, normalizeEditorLocale, DirtyState, createCommandRegistry, createDialogRegistry, activeRef, createSelectionModel, SheetSelections, translator, initialSelection, sheetBaseName, onRibbonTabsChange, activeChart, editChart, ribbonTabs, isTabHidden, selectTab, setTabHidden, tabButton, searchCommands, formatNumber, TEMPLATES, createTemplateWorkbook, isMenuSeparator, registerRibbonTabs, installFormatPainter, SHEET_ICONS, clipboardCommands, fontCommands, alignmentCommands, numberCommands, cellCommands, editingCommands, pageLayoutCommands, formulaCommands, dataCommands, contextualCommands, reviewTab, viewTab, helpTab, editBridge, CellViewCache, QUADRANTS, columnHeaderHeight, rowHeaderWidth, GridGeometry, cellRange, scrollToReveal, buildItems, fitNumber, cssFont, clampAddress, selectCell, movingEnd, extendSelection, moveWithinSelection, rowsRange, colsRange, ALL_RANGE, tabMenu, editing, icon, DATA_BAR_COLORS, dataBarRule, COLOR_SCALES, colorScaleRule, iconSetRule, target, tableAt, viewing, activeTable, numberFormatOptions, FONT_NAMES, FONT_SIZES, BORDER_PRESETS, ORIENTATIONS, ACCOUNTING_FORMATS, themePaletteItems, MARGIN_PRESETS, PAPER_SIZES, FUNCTION_MENUS, MORE_FUNCTION_CATEGORIES, functionsIn, isSingleCell, spanRange, selectionCellCount, addRange, activeStyle, selectSpecial, insertFunctionCall, guessHeader, regionOf, HIGHLIGHT_STYLES, ICON_SETS, TABLE_STYLES, tableStylePreview, resolveNameBox, absoluteReference, nameForRange, fillPaint, iconSvg, colSelected, rowSelected, rowHeaderMenu, columnHeaderMenu, cellMenu, recentFunctions, evaluateRef, buildChart, detectCategory, CATEGORIES, TIME_CODES, DATE_CODES, DEFAULT_OPTIONS, cellStyleItems, textDecoration, justify, alignItems, textAlign, hasBorders, edgeCss, diagonalSvg, SYMBOLS, buildCode, UNSET, dxfCss, negativeCodes, iconCount, iconThresholds, rowsOf, colsOf } from 'ooxml-core/xlsx/ui';
|
|
13
13
|
export { EDITOR_LOCALES, THEME_KEYS, normalizeEditorLocale, registerRibbonTabs, themeToCssVars, darkTheme as xlsxDarkTheme, lightTheme as xlsxLightTheme } from 'ooxml-core/xlsx/ui';
|
|
14
|
-
import { createWorksheet, createEditSession, approximateMeasure, createWorkbook, MAX_ROW, MAX_COL, chartView, createRefEvaluator, chartBarSpacing, selectionStats, formatRange,
|
|
14
|
+
import { createWorksheet, createEditSession, approximateMeasure, createWorkbook, MAX_ROW, MAX_COL, chartView, createRefEvaluator, chartBarSpacing, CHART_FILL_PARTS, selectionStats, formatRange, chartSeriesTransparencyPatch, chartSeriesTransparency, chartSeriesGradientPatch, chartSeriesSolidFillPatch, chartSeriesFillPatch, chartWithElementFills, chartElementTransparencyPatch, chartElementTransparency, chartElementGradientPatch, chartElementSolidFillPatch, chartElementFillPatch, chartElementFill, usedRange, chartGradientStopTransparency, createGridMetrics, mergeView, cellView, DEFAULT_THEME, resolveColor, nextSheetName, FUNCTION_CATALOG, mergeAt, visibleCells, getCell, cellInputText, closeParens, isFormulaText, parseCellInput, referenceTarget, formatAddress, navigate, anchorToPixelBox, renderChartSvg, pixelBoxToAnchor, listValidationOptions, validationAt, getValue, resolvePasteOptions, DEFAULT_COL_WIDTH, nameAtCaret, functionMatches, callAtCaret, splice, acceptsReference, translateFormula, isCellError, parseHtmlTable, toggleAbsolute, rangeContains, formatValue, isDateFormat, pictureAnchorAt, validateDefinedName, parseAddress, styleAt, parseRange, rangesIntersect, chartColorScheme, coloredReferences, syntaxParams, activeParam, columnLabel, THEME_SLOTS, normalizeRange, currentRegion, autoFitColumnWidth, validateSheetName, dateToSerial, IMAGE_EXTENSIONS, verifySheetPassword, verifyWorkbookPassword, sheetByName, quoteSheetName, serialToDate, BUILTIN_NUMBER_FORMATS, pixelsToColumnWidth, validateTableName } from 'ooxml-core/xlsx';
|
|
15
15
|
import { hyperlinkPolicy } from 'ooxml-core/opc';
|
|
16
|
-
import { CHART_COLOR_PALETTES, chartPaletteColors } from 'ooxml-core/chart';
|
|
16
|
+
import { resolveChartGradient, sortGradientStops, withChartGradientDirection, buildChartGradientDef, chartGradientMarkup, CHART_COLOR_PALETTES, chartPaletteColors } from 'ooxml-core/chart';
|
|
17
17
|
import { render } from 'lit';
|
|
18
|
+
import { RECT_GRADIENT_DIRECTIONS, OFFICE_GRADIENT_PRESETS, officeGradientPresetId, officeGradientPresetFill, resolveDrawingColor, drawingColorBrightness, drawingColorCss, rectGradientDirection } from 'ooxml-core/diagram';
|
|
18
19
|
|
|
19
20
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/xlsx/theme/office-bridge.css?raw
|
|
20
21
|
var office_bridge_default = "/*\n * The shared ooxml-ui elements read only --office-* tokens. This feeds them from the editor's\n * --xve-* theme, declared on the host so a theme, a dark scheme or a host override of --xve-*\n * keeps working (the same approach as pptx-viewer's office-token-bridge and docx-viewer's).\n */\n:host {\n --office-font: 'Segoe UI', system-ui, -apple-system, sans-serif;\n --office-foreground: var(--xve-foreground);\n --office-muted-foreground: var(--xve-muted-foreground);\n --office-background: var(--xve-background);\n --office-surface: var(--xve-card);\n --office-selected: var(--xve-accent);\n --office-border: var(--xve-border);\n --office-accent: var(--xve-primary);\n --office-accent-foreground: var(--xve-primary-foreground);\n --office-ring: var(--xve-ring);\n --office-popover: var(--xve-popover);\n --office-popover-foreground: var(--xve-popover-foreground, var(--xve-foreground));\n --office-danger: var(--xve-destructive);\n --office-danger-foreground: var(--xve-destructive-foreground);\n}\n";
|
|
@@ -32,7 +33,7 @@ var popups_default = "/* Floating surfaces: ribbon popovers, menus, the colour g
|
|
|
32
33
|
var backstage_default = "/* File backstage: the shared office-ui-backstage draws the navigation; these style the page content.\n The nav colours come from its tokens. */\n.xve-backstage {\n z-index: 40;\n --office-background: var(--surface);\n --office-backstage-nav-background: var(--xl);\n --office-backstage-nav-foreground: var(--xve-primary-foreground);\n}\n.xve-backstage-content {\n overflow: auto;\n padding: 28px 40px;\n color: var(--ink);\n}\n.xve-backstage-content h2 {\n margin: 0 0 20px;\n font-size: 30px;\n font-weight: 300;\n}\n.xve-backstage-content h3 {\n margin: 24px 0 10px;\n font-size: 15px;\n font-weight: 600;\n}\n.xve-backstage-title {\n margin: 0 0 4px;\n font-size: 26px;\n font-weight: 400;\n overflow-wrap: anywhere;\n}\n.xve-backstage-muted {\n color: var(--muted);\n}\n.xve-backstage-facts {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: 6px 24px;\n margin: 0;\n}\n.xve-backstage-facts dt {\n color: var(--muted);\n}\n.xve-backstage-facts dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n.xve-compatibility-notes {\n display: grid;\n gap: 8px;\n max-width: 760px;\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.xve-compatibility-notes li {\n display: flex;\n gap: 8px;\n padding: 10px 12px;\n border: 1px solid var(--line);\n border-radius: 6px;\n line-height: 1.45;\n}\n.xve-compatibility-notes .xve-icon {\n margin-top: 2px;\n color: #b7791f;\n}\n.xve-backstage-columns {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 300px;\n gap: 40px;\n align-items: start;\n}\n.xve-backstage-properties {\n padding: 4px 0 0 24px;\n border-left: 1px solid var(--line);\n}\n.xve-backstage-properties h3 {\n margin-top: 0;\n}\n.xve-backstage-tiles {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n}\n.xve-backstage-tile {\n display: inline-flex;\n flex-direction: column;\n gap: 8px;\n padding: 8px;\n border: 1px solid transparent;\n border-radius: 6px;\n background: none;\n color: var(--ink);\n font: inherit;\n cursor: pointer;\n}\n.xve-backstage-tile:hover {\n border-color: var(--line);\n background: var(--xl-soft);\n}\n.xve-backstage-tile-preview {\n display: block;\n width: 150px;\n height: 112px;\n border: 1px solid var(--line);\n background-color: #fff;\n background-image:\n linear-gradient(#e1e1e1 1px, transparent 1px),\n linear-gradient(90deg, #e1e1e1 1px, transparent 1px);\n background-size: 30px 14px;\n box-shadow: 0 1px 3px #0002;\n}\n.xve-backstage-tile-preview[data-template]::before {\n display: block;\n height: 14px;\n background: var(--xl);\n content: '';\n opacity: 0.85;\n}\n.xve-backstage-card {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n max-width: 760px;\n margin-bottom: 12px;\n padding: 14px 18px;\n border: 1px solid var(--line);\n border-radius: 6px;\n}\n.xve-backstage-card h3 {\n margin: 0 0 4px;\n}\n.xve-backstage-card p {\n margin: 0;\n}\n.xve-backstage-primary {\n padding: 8px 18px;\n border: 0;\n border-radius: 4px;\n background: var(--xl);\n color: var(--xve-primary-foreground);\n font: inherit;\n cursor: pointer;\n white-space: nowrap;\n}\n.xve-backstage-field {\n display: grid;\n gap: 4px;\n max-width: 420px;\n margin-bottom: 14px;\n color: var(--muted);\n font-size: 12px;\n}\n.xve-backstage-field input,\n.xve-backstage-field select {\n height: 32px;\n padding: 0 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n background: var(--surface);\n color: var(--ink);\n font:\n 14px 'Segoe UI',\n Arial,\n sans-serif;\n}\n.xve-backstage-check {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 10px;\n}\n.xve-customize-group {\n margin: 0 0 8px;\n padding: 6px 10px 8px;\n border: 1px solid var(--line);\n border-radius: 4px;\n}\n.xve-customize-group legend {\n padding: 0 4px;\n color: var(--muted);\n font-size: 12px;\n}\n.xve-customize-row {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 180px;\n padding: 2px 8px 2px 0;\n font-size: 13px;\n}\n@media (max-width: 760px) {\n .xve-backstage-content {\n padding: 20px;\n }\n .xve-backstage-columns {\n grid-template-columns: minmax(0, 1fr);\n }\n .xve-backstage-properties {\n padding-left: 0;\n border-left: 0;\n }\n}\n";
|
|
33
34
|
|
|
34
35
|
// raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/xlsx/theme/chart-series.css?raw
|
|
35
|
-
var chart_series_default = ".xve-canvas-row {\n display: flex;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n.xve-chart-series-pane {\n box-sizing: border-box;\n width: 300px;\n max-width: 45%;\n flex: none;\n overflow: auto;\n border-left: 1px solid var(--line);\n background: var(--surface);\n}\n.xve-chart-series-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 12px 12px 18px;\n border-bottom: 1px solid var(--line);\n}\n.xve-chart-series-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 400;\n}\n.xve-chart-series-body,\n.xve-chart-series-pane > .xve-note {\n margin: 0;\n padding: 18px;\n}\n.xve-chart-series-body h3 {\n margin: 0 0 20px;\n font-size: 13px;\n font-weight: 600;\n}\n.xve-chart-series-body .xve-field {\n display: grid;\n grid-template-columns: 1fr 70px 12px;\n align-items: center;\n gap: 6px;\n margin: 14px 0;\n}\n.xve-chart-series-body .xve-input-number {\n box-sizing: border-box;\n width: 70px;\n min-width: 0;\n}\n.xve-chart-series-range .office-range-control {\n box-sizing: border-box;\n width: 100%;\n margin: 0 0 8px;\n}\n.xve-chart-series-fill {\n margin-top: 20px;\n padding-top: 18px;\n border-top: 1px solid var(--line);\n}\n.xve-chart-series-body .xve-field:has(select),\n.xve-chart-series-body .xve-field:has(.xve-chart-series-color) {\n grid-template-columns: 1fr minmax(100px, 1fr);\n}\n.xve-chart-series-color {\n height: 28px;\n background: var(--series-fill);\n border: 1px solid var(--line);\n cursor: pointer;\n}\n.xve-chart-series-color:disabled {\n opacity: 0.5;\n cursor: default;\n}\n";
|
|
36
|
+
var chart_series_default = ".xve-canvas-row {\n display: flex;\n flex: 1;\n min-width: 0;\n min-height: 0;\n}\n.xve-chart-series-pane {\n box-sizing: border-box;\n width: 300px;\n max-width: 45%;\n flex: none;\n overflow: auto;\n border-left: 1px solid var(--line);\n background: var(--surface);\n}\n.xve-chart-series-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 12px 12px 18px;\n border-bottom: 1px solid var(--line);\n}\n.xve-chart-series-header h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 400;\n}\n.xve-chart-series-body,\n.xve-chart-series-pane > .xve-note {\n margin: 0;\n padding: 18px;\n}\n.xve-chart-series-body h3 {\n margin: 0 0 20px;\n font-size: 13px;\n font-weight: 600;\n}\n.xve-chart-series-body .xve-field {\n display: grid;\n grid-template-columns: 1fr 70px 12px;\n align-items: center;\n gap: 6px;\n margin: 14px 0;\n}\n.xve-chart-series-body .xve-input-number {\n box-sizing: border-box;\n width: 70px;\n min-width: 0;\n}\n.xve-chart-series-range .office-range-control {\n box-sizing: border-box;\n width: 100%;\n margin: 0 0 8px;\n}\n.xve-chart-series-fill {\n margin-top: 20px;\n padding-top: 18px;\n border-top: 1px solid var(--line);\n}\n.xve-chart-series-body .xve-field:has(select),\n.xve-chart-series-body .xve-field:has(.xve-chart-series-color),\n.xve-chart-series-body .xve-field:has(office-ui-gallery) {\n grid-template-columns: 1fr minmax(100px, 1fr);\n}\n.xve-chart-series-body office-ui-gallery .trigger {\n box-sizing: border-box;\n width: 100%;\n white-space: normal;\n}\n.xve-chart-series-color {\n height: 28px;\n background: var(--series-fill);\n border: 1px solid var(--line);\n cursor: pointer;\n}\n.xve-chart-series-color:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.xve-chart-series-gradient {\n margin-top: 18px;\n}\n.xve-chart-gradient-buttons {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n}\n.xve-chart-gradient-selector {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n.xve-chart-gradient-selector .office-gradient-stop-track {\n flex: 1;\n min-width: 0;\n}\n.xve-chart-gradient-buttons .xve-button {\n width: 26px;\n height: 28px;\n padding: 0;\n font-size: 18px;\n}\n";
|
|
36
37
|
|
|
37
38
|
// src/xlsx/theme/styles.ts
|
|
38
39
|
var declarations = (theme, scheme) => Object.entries(themeToCssVars(theme)).map(([name, value]) => `${name}:${value};`).join("") + `color-scheme:${scheme};`;
|
|
@@ -1650,13 +1651,13 @@ var DISPLAY = {
|
|
|
1650
1651
|
function formatKeys(spec, mac) {
|
|
1651
1652
|
const parsed = parse(spec);
|
|
1652
1653
|
const key = parsed.code ?? (spec.endsWith("+") ? "+" : spec.split("+").pop() ?? "");
|
|
1653
|
-
const
|
|
1654
|
+
const names2 = [
|
|
1654
1655
|
parsed.mod ? mac ? "Cmd" : "Ctrl" : "",
|
|
1655
1656
|
parsed.alt ? mac ? "Option" : "Alt" : "",
|
|
1656
1657
|
parsed.shift ? "Shift" : "",
|
|
1657
1658
|
DISPLAY[key.toLowerCase()] ?? (key.length === 1 ? key.toUpperCase() : key)
|
|
1658
1659
|
];
|
|
1659
|
-
return
|
|
1660
|
+
return names2.filter(Boolean).join("+");
|
|
1660
1661
|
}
|
|
1661
1662
|
var displayKeys = (shortcut, mac) => shortcut.keys.filter((spec) => !spec.includes("code:")).map((spec) => formatKeys(spec, mac));
|
|
1662
1663
|
function findShortcut(event, mac) {
|
|
@@ -1921,12 +1922,12 @@ function openMenu(anchor, entries, label = "") {
|
|
|
1921
1922
|
item.setAttribute("role", entry.checked === void 0 ? "menuitem" : "menuitemcheckbox");
|
|
1922
1923
|
if (entry.checked !== void 0) item.setAttribute("aria-checked", String(entry.checked));
|
|
1923
1924
|
item.disabled = entry.disabled ?? false;
|
|
1924
|
-
const
|
|
1925
|
-
|
|
1926
|
-
if (entry.icon)
|
|
1925
|
+
const icon7 = doc.createElement("span");
|
|
1926
|
+
icon7.className = "ribbon-menu-icon";
|
|
1927
|
+
if (entry.icon) icon7.append(ribbonIcon(doc, entry.icon, 16));
|
|
1927
1928
|
const text3 = doc.createElement("span");
|
|
1928
1929
|
text3.textContent = entry.label;
|
|
1929
|
-
item.append(
|
|
1930
|
+
item.append(icon7, text3);
|
|
1930
1931
|
if (entry.shortcut) {
|
|
1931
1932
|
const keys = doc.createElement("span");
|
|
1932
1933
|
keys.className = "ribbon-menu-shortcut";
|
|
@@ -3002,10 +3003,10 @@ function openGoTo(ctx) {
|
|
|
3002
3003
|
(name) => reference.value = name,
|
|
3003
3004
|
() => confirm2?.()
|
|
3004
3005
|
);
|
|
3005
|
-
const
|
|
3006
|
+
const names2 = (workbook?.definedNames ?? []).filter(
|
|
3006
3007
|
(n) => !n.hidden && !n.name.startsWith("_xlnm.")
|
|
3007
3008
|
);
|
|
3008
|
-
list.setItems(
|
|
3009
|
+
list.setItems(names2.map((n) => [n.name, n.name]));
|
|
3009
3010
|
const special = button(ctx, "Special...");
|
|
3010
3011
|
return showDialog(
|
|
3011
3012
|
ctx,
|
|
@@ -3193,15 +3194,15 @@ function openCreateNames(ctx) {
|
|
|
3193
3194
|
opened: () => boxes[0]?.input.focus(),
|
|
3194
3195
|
submit: () => {
|
|
3195
3196
|
const chosen = boxes.filter((b) => b.input.checked).map((b) => b.edge);
|
|
3196
|
-
const
|
|
3197
|
-
if (!
|
|
3197
|
+
const names2 = namesFromSelection(ctx, chosen);
|
|
3198
|
+
if (!names2.length) {
|
|
3198
3199
|
ctx.toast(ctx.t("No names could be created from the selection."), "warning");
|
|
3199
3200
|
return void 0;
|
|
3200
3201
|
}
|
|
3201
3202
|
t.session.batch("Create names", () => {
|
|
3202
|
-
for (const name of
|
|
3203
|
+
for (const name of names2) t.session.setDefinedName(name);
|
|
3203
3204
|
});
|
|
3204
|
-
return
|
|
3205
|
+
return names2.length;
|
|
3205
3206
|
}
|
|
3206
3207
|
});
|
|
3207
3208
|
}
|
|
@@ -4225,7 +4226,7 @@ function nameValue(ctx, name) {
|
|
|
4225
4226
|
return { text: "#NAME?", error: true };
|
|
4226
4227
|
}
|
|
4227
4228
|
}
|
|
4228
|
-
var visibleNames = (
|
|
4229
|
+
var visibleNames = (names2) => names2.filter((n) => !n.hidden && !n.name.startsWith("_xlnm."));
|
|
4229
4230
|
function openNameManager(ctx) {
|
|
4230
4231
|
const doc = ctx.host.ownerDocument;
|
|
4231
4232
|
const filter = select(ctx, FILTERS, "all");
|
|
@@ -4253,9 +4254,9 @@ function openNameManager(ctx) {
|
|
|
4253
4254
|
head.append(th);
|
|
4254
4255
|
}
|
|
4255
4256
|
const body = table.createTBody();
|
|
4256
|
-
const
|
|
4257
|
-
if (selected && !
|
|
4258
|
-
for (const name of
|
|
4257
|
+
const names2 = visibleNames(workbook?.definedNames ?? []);
|
|
4258
|
+
if (selected && !names2.includes(selected)) selected = void 0;
|
|
4259
|
+
for (const name of names2) {
|
|
4259
4260
|
const value = nameValue(ctx, name);
|
|
4260
4261
|
const kind = filter.value;
|
|
4261
4262
|
if (kind === "worksheet" && name.localSheet === void 0) continue;
|
|
@@ -5711,12 +5712,12 @@ function hyperlinkDialog(ctx) {
|
|
|
5711
5712
|
const tooltip2 = textInput(ctx, existing?.tooltip ?? "");
|
|
5712
5713
|
const address = textInput(ctx, !mail ? existing?.target ?? "" : "");
|
|
5713
5714
|
const sheets = t.workbook.sheets.map((s) => [s.name, s.name]);
|
|
5714
|
-
const
|
|
5715
|
+
const names2 = t.workbook.definedNames.filter((n) => !n.hidden && !n.name.startsWith("_xlnm.")).map((n) => [`name:${n.name}`, n.name]);
|
|
5715
5716
|
const loc = existing?.location ? splitLocation(existing.location) : { sheet: t.ws.name, ref: "A1" };
|
|
5716
|
-
const isName = !loc.sheet &&
|
|
5717
|
+
const isName = !loc.sheet && names2.some(([, n]) => n === loc.ref);
|
|
5717
5718
|
const place2 = select(
|
|
5718
5719
|
ctx,
|
|
5719
|
-
[...sheets, ...
|
|
5720
|
+
[...sheets, ...names2],
|
|
5720
5721
|
isName ? `name:${loc.ref}` : loc.sheet ?? t.ws.name,
|
|
5721
5722
|
true
|
|
5722
5723
|
);
|
|
@@ -6166,14 +6167,14 @@ function registerSimpleDialogs(ctx) {
|
|
|
6166
6167
|
d.register("use-in-formula", (c) => {
|
|
6167
6168
|
const t = target(c);
|
|
6168
6169
|
if (!t) return Promise.resolve(void 0);
|
|
6169
|
-
const
|
|
6170
|
+
const names2 = t.workbook.definedNames.filter(
|
|
6170
6171
|
(n) => !n.hidden && !n.name.startsWith("_xlnm.") && (n.localSheet === void 0 || n.localSheet === t.sheet)
|
|
6171
6172
|
);
|
|
6172
6173
|
return pickDialog(c, {
|
|
6173
6174
|
name: "use-in-formula",
|
|
6174
6175
|
heading: "Paste Name",
|
|
6175
6176
|
label: "Paste name",
|
|
6176
|
-
items:
|
|
6177
|
+
items: names2.map((n) => [n.name, n.name]),
|
|
6177
6178
|
apply: (name) => {
|
|
6178
6179
|
const grid = c.grid();
|
|
6179
6180
|
const cell = getCell(t.ws, t.active.row, t.active.col);
|
|
@@ -7988,7 +7989,10 @@ function chartDesignTab() {
|
|
|
7988
7989
|
{
|
|
7989
7990
|
id: "series-options",
|
|
7990
7991
|
label: "Series Options",
|
|
7991
|
-
controls: [
|
|
7992
|
+
controls: [
|
|
7993
|
+
{ kind: "button", command: "chart.format-series", size: "large" },
|
|
7994
|
+
{ kind: "button", command: "chart.format-area", size: "large" }
|
|
7995
|
+
]
|
|
7992
7996
|
},
|
|
7993
7997
|
{
|
|
7994
7998
|
id: "chart-delete",
|
|
@@ -8731,44 +8735,122 @@ function reviewCommands() {
|
|
|
8731
8735
|
})
|
|
8732
8736
|
];
|
|
8733
8737
|
}
|
|
8734
|
-
function
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8738
|
+
function seriesFillBinding(selected) {
|
|
8739
|
+
return {
|
|
8740
|
+
commandId: "chart.format-series",
|
|
8741
|
+
key: selected,
|
|
8742
|
+
fill: (chart) => chart.series[selected()]?.fill,
|
|
8743
|
+
gradient: (view) => view.series[selected()]?.gradient,
|
|
8744
|
+
paint: (view) => view.series[selected()]?.color,
|
|
8745
|
+
rectangular: (chart) => chart.chartType === "bar" || chart.chartType === "column",
|
|
8746
|
+
color: (chart, color) => chartSeriesFillPatch(chart, selected(), color),
|
|
8747
|
+
solid: (chart) => chartSeriesSolidFillPatch(chart, selected()),
|
|
8748
|
+
edit: (chart, edit) => chartSeriesGradientPatch(chart, selected(), edit),
|
|
8749
|
+
transparency: (chart) => chartSeriesTransparency(chart, selected()),
|
|
8750
|
+
setTransparency: (chart, value) => chartSeriesTransparencyPatch(chart, selected(), value),
|
|
8751
|
+
preview: (chart, patch) => ({ ...chart, ...patch })
|
|
8752
|
+
};
|
|
8753
|
+
}
|
|
8754
|
+
function backgroundFillBinding(selected) {
|
|
8755
|
+
return {
|
|
8756
|
+
commandId: "chart.format-area",
|
|
8757
|
+
key: selected,
|
|
8758
|
+
fill: (chart) => chartElementFill(chart, selected()),
|
|
8759
|
+
gradient: (view) => view.appearance?.[selected()]?.gradient,
|
|
8760
|
+
paint: (view) => view.appearance?.[selected()]?.fillColor ?? (selected() === "chartArea" ? "#FFFFFF" : "none"),
|
|
8761
|
+
rectangular: () => true,
|
|
8762
|
+
color: (chart, color) => chartElementFillPatch(chart, selected(), color),
|
|
8763
|
+
solid: (chart) => chartElementSolidFillPatch(chart, selected()),
|
|
8764
|
+
edit: (chart, edit) => chartElementGradientPatch(chart, selected(), edit),
|
|
8765
|
+
transparency: (chart) => chartElementTransparency(chart, selected()),
|
|
8766
|
+
setTransparency: (chart, value) => chartElementTransparencyPatch(chart, selected(), value),
|
|
8767
|
+
preview: (chart, patch) => chartWithElementFills(chart, patch.elementFills ?? {})
|
|
8768
|
+
};
|
|
8769
|
+
}
|
|
8770
|
+
function createNumberRange(input, options) {
|
|
8771
|
+
const element = input.ownerDocument.createElement("div");
|
|
8772
|
+
let original;
|
|
8773
|
+
const enabled = () => !input.disabled && (options.enabled?.() ?? true);
|
|
8774
|
+
const cancel = () => {
|
|
8775
|
+
if (original === void 0) return;
|
|
8776
|
+
input.value = original;
|
|
8777
|
+
original = void 0;
|
|
8778
|
+
options.onPreview?.(void 0);
|
|
8779
|
+
paint();
|
|
8780
|
+
};
|
|
8744
8781
|
const paint = () => render(
|
|
8745
8782
|
rangeControl({
|
|
8746
|
-
label:
|
|
8783
|
+
label: options.label(),
|
|
8747
8784
|
value: input.valueAsNumber,
|
|
8748
|
-
valueText: `${input.value}
|
|
8749
|
-
min:
|
|
8750
|
-
max:
|
|
8751
|
-
|
|
8785
|
+
valueText: input.value ? `${input.value}%` : "",
|
|
8786
|
+
min: Number(input.min),
|
|
8787
|
+
max: Number(input.max),
|
|
8788
|
+
step: Number(input.step) || 1,
|
|
8789
|
+
disabled: !enabled(),
|
|
8752
8790
|
onInput: (value) => {
|
|
8753
|
-
if (!
|
|
8791
|
+
if (!enabled() || !Number.isFinite(value)) return;
|
|
8792
|
+
original ??= input.value;
|
|
8754
8793
|
input.value = String(value);
|
|
8794
|
+
options.onPreview?.(value);
|
|
8755
8795
|
paint();
|
|
8756
8796
|
},
|
|
8757
|
-
onChange: () =>
|
|
8797
|
+
onChange: () => {
|
|
8798
|
+
if (original === void 0) return;
|
|
8799
|
+
if (!enabled()) return cancel();
|
|
8800
|
+
const value = input.value;
|
|
8801
|
+
cancel();
|
|
8802
|
+
input.value = value;
|
|
8803
|
+
input.dispatchEvent(new Event("change"));
|
|
8804
|
+
paint();
|
|
8805
|
+
}
|
|
8758
8806
|
}),
|
|
8759
|
-
|
|
8807
|
+
element
|
|
8760
8808
|
);
|
|
8809
|
+
element.addEventListener("pointercancel", cancel);
|
|
8810
|
+
element.addEventListener("keydown", (event) => {
|
|
8811
|
+
if (event.key === "Escape" && original !== void 0) {
|
|
8812
|
+
event.preventDefault();
|
|
8813
|
+
event.stopPropagation();
|
|
8814
|
+
cancel();
|
|
8815
|
+
}
|
|
8816
|
+
});
|
|
8817
|
+
return {
|
|
8818
|
+
element,
|
|
8819
|
+
cancel,
|
|
8820
|
+
refresh: () => {
|
|
8821
|
+
cancel();
|
|
8822
|
+
paint();
|
|
8823
|
+
}
|
|
8824
|
+
};
|
|
8825
|
+
}
|
|
8826
|
+
|
|
8827
|
+
// src/xlsx/chart-series-transparency.ts
|
|
8828
|
+
function createSeriesTransparency(ctx, selected, binding = seriesFillBinding(selected)) {
|
|
8829
|
+
const element = el(ctx, "div");
|
|
8830
|
+
const input = numberInput(ctx, 0, 0, 100);
|
|
8831
|
+
const row2 = field(ctx, "Transparency", input);
|
|
8832
|
+
const unit = el(ctx, "span");
|
|
8833
|
+
unit.textContent = "%";
|
|
8834
|
+
row2.append(unit);
|
|
8835
|
+
const range2 = createNumberRange(input, {
|
|
8836
|
+
label: () => ctx.t("Transparency"),
|
|
8837
|
+
enabled: () => ctx.commands.isEnabled(binding.commandId)
|
|
8838
|
+
});
|
|
8839
|
+
range2.element.className = "xve-chart-series-range";
|
|
8840
|
+
element.append(row2, range2.element);
|
|
8841
|
+
let current;
|
|
8761
8842
|
const refresh = (chart) => {
|
|
8843
|
+
range2.cancel();
|
|
8762
8844
|
current = chart;
|
|
8763
|
-
const value = chart ?
|
|
8845
|
+
const value = chart ? binding.transparency(chart) : void 0;
|
|
8764
8846
|
input.value = String(value ?? 0);
|
|
8765
|
-
input.disabled = value === void 0 || !ctx.commands.isEnabled(
|
|
8847
|
+
input.disabled = value === void 0 || !ctx.commands.isEnabled(binding.commandId);
|
|
8766
8848
|
row2.querySelector("span").textContent = ctx.t("Transparency");
|
|
8767
8849
|
input.setAttribute("aria-label", ctx.t("Transparency"));
|
|
8768
|
-
|
|
8850
|
+
range2.refresh();
|
|
8769
8851
|
};
|
|
8770
8852
|
input.addEventListener("change", () => {
|
|
8771
|
-
if (!current || input.disabled || !ctx.commands.isEnabled(
|
|
8853
|
+
if (!current || input.disabled || !ctx.commands.isEnabled(binding.commandId))
|
|
8772
8854
|
return refresh(current);
|
|
8773
8855
|
if (!input.checkValidity() || !Number.isInteger(input.valueAsNumber)) {
|
|
8774
8856
|
ctx.toast(
|
|
@@ -8779,15 +8861,656 @@ function createSeriesTransparency(ctx, selected) {
|
|
|
8779
8861
|
}
|
|
8780
8862
|
const found = activeChart(ctx);
|
|
8781
8863
|
if (!found || found.chart !== current) return refresh(current);
|
|
8782
|
-
const patch =
|
|
8864
|
+
const patch = binding.setTransparency(current, input.valueAsNumber);
|
|
8783
8865
|
if (patch) ctx.session()?.updateChart(ctx.activeSheet(), found.index, patch);
|
|
8784
8866
|
refresh(found.chart);
|
|
8785
8867
|
});
|
|
8786
8868
|
return { element, refresh };
|
|
8787
8869
|
}
|
|
8870
|
+
function createGradientStopTrack(doc) {
|
|
8871
|
+
const element = doc.createElement("div");
|
|
8872
|
+
element.className = "office-gradient-stop-track";
|
|
8873
|
+
element.setAttribute("role", "group");
|
|
8874
|
+
const style = doc.createElement("style");
|
|
8875
|
+
style.textContent = `.office-gradient-stop-track{position:relative;height:40px;margin:12px 7px}
|
|
8876
|
+
.office-gradient-stop-paint{position:absolute;inset:3px 0 15px;border:1px solid var(--line,#aaa)}
|
|
8877
|
+
.office-gradient-stop{position:absolute;top:0;width:14px;height:30px;padding:0;border:1px solid var(--line,#888);border-radius:2px;cursor:pointer;touch-action:none}
|
|
8878
|
+
.office-gradient-stop[aria-pressed=true]{outline:2px solid var(--accent,#217346);outline-offset:2px}
|
|
8879
|
+
.office-gradient-stop:focus-visible{outline:2px solid var(--accent,#217346);outline-offset:3px}
|
|
8880
|
+
.office-gradient-stop:disabled{opacity:.5;cursor:default}`;
|
|
8881
|
+
const paint = doc.createElement("div");
|
|
8882
|
+
paint.className = "office-gradient-stop-paint";
|
|
8883
|
+
let current;
|
|
8884
|
+
let drag;
|
|
8885
|
+
const paintStops = (stops) => {
|
|
8886
|
+
paint.style.background = `linear-gradient(90deg,${sortGradientStops(stops).map((stop) => `${stop.color} ${stop.position}%`).join(",")})`;
|
|
8887
|
+
};
|
|
8888
|
+
const cancel = () => {
|
|
8889
|
+
if (!drag) return;
|
|
8890
|
+
const previous = drag;
|
|
8891
|
+
drag = void 0;
|
|
8892
|
+
paintStops(current.stops);
|
|
8893
|
+
element.querySelectorAll("button")[previous.index]?.style.setProperty("left", `calc(${previous.origin}% - 7px)`);
|
|
8894
|
+
current.onPreview?.(previous.index, void 0);
|
|
8895
|
+
if (element.hasPointerCapture?.(previous.pointer))
|
|
8896
|
+
element.releasePointerCapture(previous.pointer);
|
|
8897
|
+
};
|
|
8898
|
+
const update = (options) => {
|
|
8899
|
+
cancel();
|
|
8900
|
+
current = options;
|
|
8901
|
+
element.setAttribute("aria-label", options.label);
|
|
8902
|
+
paintStops(options.stops);
|
|
8903
|
+
element.replaceChildren(
|
|
8904
|
+
style,
|
|
8905
|
+
paint,
|
|
8906
|
+
...options.stops.map((stop, index) => {
|
|
8907
|
+
const button2 = doc.createElement("button");
|
|
8908
|
+
button2.type = "button";
|
|
8909
|
+
button2.className = "office-gradient-stop";
|
|
8910
|
+
button2.disabled = options.disabled;
|
|
8911
|
+
button2.setAttribute("aria-label", options.stopLabel(index));
|
|
8912
|
+
button2.setAttribute("aria-pressed", String(index === options.selected));
|
|
8913
|
+
button2.style.left = `calc(${stop.position}% - 7px)`;
|
|
8914
|
+
button2.style.background = stop.color;
|
|
8915
|
+
button2.addEventListener("click", () => {
|
|
8916
|
+
if (!current.disabled) current.onSelect(index);
|
|
8917
|
+
});
|
|
8918
|
+
button2.addEventListener("keydown", (event) => {
|
|
8919
|
+
const next = event.key === "ArrowRight" ? index + 1 : event.key === "ArrowLeft" ? index - 1 : void 0;
|
|
8920
|
+
if (next === void 0 || current.disabled) return;
|
|
8921
|
+
event.preventDefault();
|
|
8922
|
+
const selected = Math.max(0, Math.min(current.stops.length - 1, next));
|
|
8923
|
+
current.onSelect(selected);
|
|
8924
|
+
element.querySelectorAll("button")[selected]?.focus();
|
|
8925
|
+
});
|
|
8926
|
+
return button2;
|
|
8927
|
+
})
|
|
8928
|
+
);
|
|
8929
|
+
};
|
|
8930
|
+
element.addEventListener("pointerdown", (event) => {
|
|
8931
|
+
if (drag || !current || event.isPrimary === false || event.button !== 0 || current.disabled || !current.onMove)
|
|
8932
|
+
return;
|
|
8933
|
+
const button2 = event.target.closest("button");
|
|
8934
|
+
const index = Array.from(element.querySelectorAll("button")).indexOf(
|
|
8935
|
+
button2
|
|
8936
|
+
);
|
|
8937
|
+
if (index < 0) return;
|
|
8938
|
+
event.preventDefault();
|
|
8939
|
+
current.onSelect(index);
|
|
8940
|
+
const width = paint.getBoundingClientRect().width;
|
|
8941
|
+
const origin = current.stops[index]?.position;
|
|
8942
|
+
if (!width || origin === void 0) return;
|
|
8943
|
+
drag = { pointer: event.pointerId, index, x: event.clientX, width, origin, value: origin };
|
|
8944
|
+
try {
|
|
8945
|
+
element.setPointerCapture?.(event.pointerId);
|
|
8946
|
+
} catch {
|
|
8947
|
+
}
|
|
8948
|
+
element.querySelectorAll("button")[index]?.focus();
|
|
8949
|
+
});
|
|
8950
|
+
element.addEventListener("pointermove", (event) => {
|
|
8951
|
+
if (!drag || event.pointerId !== drag.pointer || current.disabled) return;
|
|
8952
|
+
const value = Math.max(
|
|
8953
|
+
0,
|
|
8954
|
+
Math.min(100, Math.round(drag.origin + (event.clientX - drag.x) / drag.width * 100))
|
|
8955
|
+
);
|
|
8956
|
+
if (value === drag.value) return;
|
|
8957
|
+
drag.value = value;
|
|
8958
|
+
element.querySelectorAll("button")[drag.index]?.style.setProperty("left", `calc(${value}% - 7px)`);
|
|
8959
|
+
paintStops(
|
|
8960
|
+
current.stops.map(
|
|
8961
|
+
(stop, index) => index === drag.index ? { ...stop, position: value } : stop
|
|
8962
|
+
)
|
|
8963
|
+
);
|
|
8964
|
+
current.onPreview?.(drag.index, value);
|
|
8965
|
+
});
|
|
8966
|
+
element.addEventListener("pointerup", (event) => {
|
|
8967
|
+
if (!drag || event.pointerId !== drag.pointer) return;
|
|
8968
|
+
const previous = drag;
|
|
8969
|
+
cancel();
|
|
8970
|
+
if (!current.disabled && element.isConnected && previous.value !== previous.origin)
|
|
8971
|
+
current.onMove?.(previous.index, previous.value);
|
|
8972
|
+
});
|
|
8973
|
+
for (const name of ["pointercancel", "lostpointercapture"])
|
|
8974
|
+
element.addEventListener(name, (event) => {
|
|
8975
|
+
if (drag?.pointer === event.pointerId) cancel();
|
|
8976
|
+
});
|
|
8977
|
+
element.addEventListener("keydown", (event) => {
|
|
8978
|
+
if (event.key === "Escape" && drag) {
|
|
8979
|
+
event.preventDefault();
|
|
8980
|
+
event.stopPropagation();
|
|
8981
|
+
cancel();
|
|
8982
|
+
}
|
|
8983
|
+
});
|
|
8984
|
+
return {
|
|
8985
|
+
element,
|
|
8986
|
+
update,
|
|
8987
|
+
cancel,
|
|
8988
|
+
preview: (stops) => {
|
|
8989
|
+
paintStops(stops);
|
|
8990
|
+
const buttons = element.querySelectorAll("button");
|
|
8991
|
+
stops.forEach((stop, index) => {
|
|
8992
|
+
const button2 = buttons[index];
|
|
8993
|
+
if (button2) {
|
|
8994
|
+
button2.style.left = `calc(${stop.position}% - 7px)`;
|
|
8995
|
+
button2.style.background = stop.color;
|
|
8996
|
+
}
|
|
8997
|
+
});
|
|
8998
|
+
}
|
|
8999
|
+
};
|
|
9000
|
+
}
|
|
9001
|
+
function gradientGalleryPreview(id, fill) {
|
|
9002
|
+
const def = buildChartGradientDef(id, fill, { width: 38, height: 38, shape: "rect" });
|
|
9003
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><defs>${chartGradientMarkup(def)}</defs><rect x="1" y="1" width="38" height="38" fill="url(#${def.id})" stroke="#999"/></svg>`;
|
|
9004
|
+
}
|
|
9005
|
+
|
|
9006
|
+
// src/form/gradient-direction-gallery.ts
|
|
9007
|
+
var DIRECTIONS2 = [
|
|
9008
|
+
[0, "Linear Right"],
|
|
9009
|
+
[45, "Linear Diagonal - Bottom Right"],
|
|
9010
|
+
[90, "Linear Down"],
|
|
9011
|
+
[135, "Linear Diagonal - Bottom Left"],
|
|
9012
|
+
[180, "Linear Left"],
|
|
9013
|
+
[225, "Linear Diagonal - Top Left"],
|
|
9014
|
+
[270, "Linear Up"],
|
|
9015
|
+
[315, "Linear Diagonal - Top Right"]
|
|
9016
|
+
];
|
|
9017
|
+
var sequence = 0;
|
|
9018
|
+
function createGradientDirectionGallery(doc) {
|
|
9019
|
+
const prefix = `office-gradient-direction-${++sequence}`;
|
|
9020
|
+
defineGallery(doc.defaultView?.customElements);
|
|
9021
|
+
const element = doc.createElement("office-ui-gallery");
|
|
9022
|
+
let current;
|
|
9023
|
+
element.addEventListener("office-gallery-pick", (event) => {
|
|
9024
|
+
const id = event.detail.itemId;
|
|
9025
|
+
if (["rect", "circle", "shape"].includes(current?.gradient.path ?? "")) {
|
|
9026
|
+
const direction2 = RECT_GRADIENT_DIRECTIONS.find((direction3) => direction3.id === id);
|
|
9027
|
+
if (direction2 && current && !current.disabled) {
|
|
9028
|
+
if (current.onPathPick) current.onPathPick(direction2.id);
|
|
9029
|
+
else if (current.gradient.path === "rect") current.onRectPick?.(direction2.id);
|
|
9030
|
+
}
|
|
9031
|
+
return;
|
|
9032
|
+
}
|
|
9033
|
+
const direction = DIRECTIONS2.find(([angle]) => String(angle) === id);
|
|
9034
|
+
if (direction && current && !current.disabled) current.onPick(direction[0]);
|
|
9035
|
+
});
|
|
9036
|
+
const update = (options) => {
|
|
9037
|
+
current = options;
|
|
9038
|
+
if (options.disabled) element.open = false;
|
|
9039
|
+
const rectangular = ["rect", "circle", "shape"].includes(options.gradient.path ?? "");
|
|
9040
|
+
const items2 = rectangular ? RECT_GRADIENT_DIRECTIONS.map(({ id, label }) => ({
|
|
9041
|
+
id,
|
|
9042
|
+
label: options.translate(label),
|
|
9043
|
+
applied: rectGradientDirection(options.gradient.fillToRect) === id,
|
|
9044
|
+
preview: gradientGalleryPreview(
|
|
9045
|
+
`${prefix}-${id}`,
|
|
9046
|
+
withChartGradientDirection(options.gradient, id)
|
|
9047
|
+
)
|
|
9048
|
+
})) : DIRECTIONS2.map(([angle, label]) => ({
|
|
9049
|
+
id: String(angle),
|
|
9050
|
+
label: options.translate(label),
|
|
9051
|
+
applied: options.gradient.angle === angle,
|
|
9052
|
+
preview: gradientGalleryPreview(`${prefix}-${angle}`, {
|
|
9053
|
+
...options.gradient,
|
|
9054
|
+
type: "linear",
|
|
9055
|
+
angle
|
|
9056
|
+
})
|
|
9057
|
+
}));
|
|
9058
|
+
element.state = {
|
|
9059
|
+
id: "gradient-direction",
|
|
9060
|
+
label: options.label,
|
|
9061
|
+
moreLabel: options.label,
|
|
9062
|
+
disabled: options.disabled,
|
|
9063
|
+
sections: [
|
|
9064
|
+
{
|
|
9065
|
+
columns: 4,
|
|
9066
|
+
tileWidth: 44,
|
|
9067
|
+
tileHeight: 44,
|
|
9068
|
+
items: items2
|
|
9069
|
+
}
|
|
9070
|
+
]
|
|
9071
|
+
};
|
|
9072
|
+
};
|
|
9073
|
+
return {
|
|
9074
|
+
element,
|
|
9075
|
+
update,
|
|
9076
|
+
close: () => {
|
|
9077
|
+
element.open = false;
|
|
9078
|
+
}
|
|
9079
|
+
};
|
|
9080
|
+
}
|
|
9081
|
+
var sequence2 = 0;
|
|
9082
|
+
function createGradientPresetGallery(doc) {
|
|
9083
|
+
const prefix = `office-gradient-preset-${++sequence2}`;
|
|
9084
|
+
defineGallery(doc.defaultView?.customElements);
|
|
9085
|
+
const element = doc.createElement("office-ui-gallery");
|
|
9086
|
+
let current;
|
|
9087
|
+
element.addEventListener("office-gallery-pick", (event) => {
|
|
9088
|
+
const id = event.detail.itemId;
|
|
9089
|
+
const preset = OFFICE_GRADIENT_PRESETS.find((preset2) => String(preset2.id) === id);
|
|
9090
|
+
if (preset && current && !current.disabled) current.onPick(preset.id);
|
|
9091
|
+
});
|
|
9092
|
+
return {
|
|
9093
|
+
element,
|
|
9094
|
+
close: () => {
|
|
9095
|
+
element.open = false;
|
|
9096
|
+
},
|
|
9097
|
+
update(options) {
|
|
9098
|
+
current = options;
|
|
9099
|
+
if (options.disabled) element.open = false;
|
|
9100
|
+
const selected = officeGradientPresetId(options.fill);
|
|
9101
|
+
element.state = {
|
|
9102
|
+
id: "gradient-presets",
|
|
9103
|
+
label: options.label,
|
|
9104
|
+
moreLabel: options.label,
|
|
9105
|
+
disabled: options.disabled,
|
|
9106
|
+
sections: [
|
|
9107
|
+
{
|
|
9108
|
+
columns: 6,
|
|
9109
|
+
tileWidth: 40,
|
|
9110
|
+
tileHeight: 40,
|
|
9111
|
+
items: OFFICE_GRADIENT_PRESETS.map((preset) => ({
|
|
9112
|
+
id: String(preset.id),
|
|
9113
|
+
label: options.translate(preset.label),
|
|
9114
|
+
applied: preset.id === selected,
|
|
9115
|
+
preview: gradientGalleryPreview(
|
|
9116
|
+
`${prefix}-${preset.id}`,
|
|
9117
|
+
resolveChartGradient(
|
|
9118
|
+
officeGradientPresetFill(preset.id),
|
|
9119
|
+
(color) => resolveDrawingColor(color)
|
|
9120
|
+
)
|
|
9121
|
+
)
|
|
9122
|
+
}))
|
|
9123
|
+
}
|
|
9124
|
+
]
|
|
9125
|
+
};
|
|
9126
|
+
}
|
|
9127
|
+
};
|
|
9128
|
+
}
|
|
9129
|
+
|
|
9130
|
+
// src/xlsx/chart-series-gradient-type.ts
|
|
9131
|
+
function createGradientTypeField(ctx, onPick) {
|
|
9132
|
+
const input = select(ctx, [
|
|
9133
|
+
["linear", "Linear"],
|
|
9134
|
+
["circle", "Radial"],
|
|
9135
|
+
["rect", "Rectangular"],
|
|
9136
|
+
["shape", "Path"]
|
|
9137
|
+
]);
|
|
9138
|
+
input.options[1].disabled = true;
|
|
9139
|
+
input.options[3].disabled = true;
|
|
9140
|
+
const other = el(ctx, "option");
|
|
9141
|
+
other.value = "unsupported";
|
|
9142
|
+
other.disabled = true;
|
|
9143
|
+
input.append(other);
|
|
9144
|
+
const element = field(ctx, "Type", input);
|
|
9145
|
+
input.addEventListener("change", () => {
|
|
9146
|
+
if (!input.disabled && !input.selectedOptions[0]?.disabled && ["linear", "rect", "circle", "shape"].includes(input.value))
|
|
9147
|
+
onPick(input.value);
|
|
9148
|
+
});
|
|
9149
|
+
return {
|
|
9150
|
+
element,
|
|
9151
|
+
refresh(fill, disabled, rectangularMarks = false) {
|
|
9152
|
+
input.options[1].disabled = input.options[3].disabled = !rectangularMarks;
|
|
9153
|
+
element.querySelector("span").textContent = ctx.t("Type");
|
|
9154
|
+
input.setAttribute("aria-label", ctx.t("Type"));
|
|
9155
|
+
const linearLabel = ctx.t("Linear gradient");
|
|
9156
|
+
input.options[0].textContent = linearLabel === "Linear gradient" ? "Linear" : linearLabel;
|
|
9157
|
+
input.options[1].textContent = ctx.t("Radial");
|
|
9158
|
+
input.options[2].textContent = ctx.t("Rectangular");
|
|
9159
|
+
input.options[3].textContent = ctx.t("Path");
|
|
9160
|
+
other.textContent = ctx.t("Imported gradient type");
|
|
9161
|
+
input.value = !fill.path ? "linear" : ["rect", "circle", "shape"].includes(fill.path) ? fill.path : "unsupported";
|
|
9162
|
+
other.hidden = input.value !== "unsupported";
|
|
9163
|
+
input.disabled = disabled;
|
|
9164
|
+
}
|
|
9165
|
+
};
|
|
9166
|
+
}
|
|
9167
|
+
function createChartGradientPreview(root, drawing, series, gradient) {
|
|
9168
|
+
const target24 = typeof series === "number" ? `s${series}` : series;
|
|
9169
|
+
const nodes = Array.from(
|
|
9170
|
+
root.querySelectorAll(
|
|
9171
|
+
`.xg-obj[data-index="${drawing}"] :is(linearGradient,radialGradient,pattern)[id$="-${target24}"]`
|
|
9172
|
+
)
|
|
9173
|
+
);
|
|
9174
|
+
const originals = nodes.map((node) => ({
|
|
9175
|
+
node,
|
|
9176
|
+
children: Array.from(node.childNodes).map((child) => child.cloneNode(true))
|
|
9177
|
+
}));
|
|
9178
|
+
const paint = (fill) => {
|
|
9179
|
+
const bounds = nodes.some((node) => node.localName === "pattern") ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
9180
|
+
const def = buildChartGradientDef("preview", fill, bounds);
|
|
9181
|
+
for (const node of nodes) {
|
|
9182
|
+
if (!node.isConnected) continue;
|
|
9183
|
+
if (def.kind === "rectPath") {
|
|
9184
|
+
const image = node.ownerDocument.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
9185
|
+
image.setAttribute("href", def.href);
|
|
9186
|
+
image.setAttribute("width", "1");
|
|
9187
|
+
image.setAttribute("height", "1");
|
|
9188
|
+
image.setAttribute("preserveAspectRatio", "none");
|
|
9189
|
+
node.replaceChildren(image);
|
|
9190
|
+
continue;
|
|
9191
|
+
}
|
|
9192
|
+
node.replaceChildren(
|
|
9193
|
+
...def.stops.map((stop) => {
|
|
9194
|
+
const element = node.ownerDocument.createElementNS("http://www.w3.org/2000/svg", "stop");
|
|
9195
|
+
element.setAttribute("offset", String(stop.offset));
|
|
9196
|
+
element.setAttribute("stop-color", stop.color);
|
|
9197
|
+
element.setAttribute("stop-opacity", String(stop.opacity ?? 1));
|
|
9198
|
+
return element;
|
|
9199
|
+
})
|
|
9200
|
+
);
|
|
9201
|
+
}
|
|
9202
|
+
};
|
|
9203
|
+
return {
|
|
9204
|
+
paint,
|
|
9205
|
+
position(index, position) {
|
|
9206
|
+
paint({
|
|
9207
|
+
...gradient,
|
|
9208
|
+
stops: gradient.stops.map((stop, i) => i === index ? { ...stop, position } : stop)
|
|
9209
|
+
});
|
|
9210
|
+
},
|
|
9211
|
+
restore() {
|
|
9212
|
+
for (const { node, children } of originals)
|
|
9213
|
+
if (node.isConnected) node.replaceChildren(...children);
|
|
9214
|
+
}
|
|
9215
|
+
};
|
|
9216
|
+
}
|
|
9217
|
+
function seriesRangePreview(ctx, chart, view, series, stop, drawing, track, color, valid, binding) {
|
|
9218
|
+
const gradient = binding.gradient(view);
|
|
9219
|
+
const book = ctx.workbook();
|
|
9220
|
+
const sheet = ctx.activeSheet();
|
|
9221
|
+
let preview;
|
|
9222
|
+
const strip = (fill) => {
|
|
9223
|
+
track.preview(
|
|
9224
|
+
fill.stops.map((item) => ({
|
|
9225
|
+
position: item.position,
|
|
9226
|
+
color: drawingColorCss({ hex: item.color, alpha: item.opacity ?? 1, unapplied: [] })
|
|
9227
|
+
}))
|
|
9228
|
+
);
|
|
9229
|
+
color.style.setProperty("--series-fill", fill.stops[stop]?.color ?? "transparent");
|
|
9230
|
+
};
|
|
9231
|
+
return (property, value) => {
|
|
9232
|
+
if (value === void 0) {
|
|
9233
|
+
preview?.restore();
|
|
9234
|
+
preview = void 0;
|
|
9235
|
+
if (valid() && gradient) strip(gradient);
|
|
9236
|
+
return;
|
|
9237
|
+
}
|
|
9238
|
+
if (!valid() || !book || !gradient || ctx.workbook() !== book || ctx.activeSheet() !== sheet || !ctx.commands.isEnabled(binding.commandId))
|
|
9239
|
+
return;
|
|
9240
|
+
const result = binding.edit(chart, {
|
|
9241
|
+
kind: "stop",
|
|
9242
|
+
index: stop,
|
|
9243
|
+
[property]: value
|
|
9244
|
+
});
|
|
9245
|
+
const paint = result ? binding.gradient(
|
|
9246
|
+
chartView(
|
|
9247
|
+
book,
|
|
9248
|
+
sheet,
|
|
9249
|
+
binding.preview(chart, result.patch),
|
|
9250
|
+
createRefEvaluator(book, ctx.session()?.calc, { sheet })
|
|
9251
|
+
)
|
|
9252
|
+
) : gradient;
|
|
9253
|
+
if (!paint) return;
|
|
9254
|
+
preview ??= createChartGradientPreview(ctx.root, drawing, series, gradient);
|
|
9255
|
+
preview.paint(paint);
|
|
9256
|
+
strip(paint);
|
|
9257
|
+
};
|
|
9258
|
+
}
|
|
9259
|
+
|
|
9260
|
+
// src/xlsx/chart-series-gradient.ts
|
|
9261
|
+
function createSeriesGradient(ctx, selected, binding = seriesFillBinding(selected)) {
|
|
9262
|
+
const element = el(ctx, "div", "xve-chart-series-gradient");
|
|
9263
|
+
const angle = numberInput(ctx, 90, 0, 360);
|
|
9264
|
+
const position = numberInput(ctx, 0, 0, 100);
|
|
9265
|
+
const transparency = numberInput(ctx, 0, 0, 100);
|
|
9266
|
+
const brightness = numberInput(ctx, 0, -100, 100);
|
|
9267
|
+
const color = el(ctx, "button", "xve-input xve-chart-series-color");
|
|
9268
|
+
color.type = "button";
|
|
9269
|
+
const track = createGradientStopTrack(element.ownerDocument);
|
|
9270
|
+
const direction = createGradientDirectionGallery(element.ownerDocument);
|
|
9271
|
+
const preset = createGradientPresetGallery(element.ownerDocument);
|
|
9272
|
+
const presetRow = field(ctx, "Preset gradients", preset.element);
|
|
9273
|
+
const type = createGradientTypeField(ctx, (type2) => {
|
|
9274
|
+
direction.close();
|
|
9275
|
+
apply({ kind: "geometry", type: type2 });
|
|
9276
|
+
});
|
|
9277
|
+
const rows = [
|
|
9278
|
+
[field(ctx, "Angle", angle), angle, "Angle"],
|
|
9279
|
+
[field(ctx, "Color", color), color, "Color"],
|
|
9280
|
+
[field(ctx, "Position", position), position, "Position"],
|
|
9281
|
+
[field(ctx, "Brightness", brightness), brightness, "Brightness"],
|
|
9282
|
+
[field(ctx, "Transparency", transparency), transparency, "Transparency"]
|
|
9283
|
+
];
|
|
9284
|
+
for (const [row2, , label] of rows.filter(([, input]) => input !== color)) {
|
|
9285
|
+
const unit = el(ctx, "span");
|
|
9286
|
+
unit.textContent = label === "Angle" ? "\xB0" : "%";
|
|
9287
|
+
row2.append(unit);
|
|
9288
|
+
}
|
|
9289
|
+
const buttons = el(ctx, "div", "xve-chart-gradient-buttons");
|
|
9290
|
+
const selector = el(ctx, "div", "xve-chart-gradient-selector");
|
|
9291
|
+
const add = el(ctx, "button", "xve-button");
|
|
9292
|
+
add.type = "button";
|
|
9293
|
+
const remove = el(ctx, "button", "xve-button");
|
|
9294
|
+
remove.type = "button";
|
|
9295
|
+
buttons.append(add, remove);
|
|
9296
|
+
selector.append(track.element, buttons);
|
|
9297
|
+
const directionRow = field(ctx, "Direction", direction.element);
|
|
9298
|
+
let previewRange;
|
|
9299
|
+
const ranges = /* @__PURE__ */ new Map();
|
|
9300
|
+
for (const [property, input] of [
|
|
9301
|
+
["position", position],
|
|
9302
|
+
["brightness", brightness],
|
|
9303
|
+
["transparency", transparency]
|
|
9304
|
+
]) {
|
|
9305
|
+
const range2 = createNumberRange(input, {
|
|
9306
|
+
label: () => input.getAttribute("aria-label") ?? "",
|
|
9307
|
+
enabled: () => {
|
|
9308
|
+
const fill = current && binding.fill(current);
|
|
9309
|
+
return ctx.commands.isEnabled(binding.commandId) && fill?.kind === "gradient" && fill.stops.length === (model && binding.gradient(model)?.stops.length);
|
|
9310
|
+
},
|
|
9311
|
+
onPreview: (value) => {
|
|
9312
|
+
if (value !== void 0) {
|
|
9313
|
+
for (const other of ranges.values()) if (other !== range2) other.cancel();
|
|
9314
|
+
}
|
|
9315
|
+
previewRange?.(property, value);
|
|
9316
|
+
}
|
|
9317
|
+
});
|
|
9318
|
+
range2.element.className = "xve-chart-series-range";
|
|
9319
|
+
ranges.set(input, range2);
|
|
9320
|
+
}
|
|
9321
|
+
element.append(
|
|
9322
|
+
presetRow,
|
|
9323
|
+
type.element,
|
|
9324
|
+
directionRow,
|
|
9325
|
+
rows[0][0],
|
|
9326
|
+
selector,
|
|
9327
|
+
...rows.slice(1).flatMap(([row2, input]) => {
|
|
9328
|
+
const range2 = ranges.get(input);
|
|
9329
|
+
return range2 ? [row2, range2.element] : [row2];
|
|
9330
|
+
})
|
|
9331
|
+
);
|
|
9332
|
+
let current;
|
|
9333
|
+
let model;
|
|
9334
|
+
let stopIndex = 0;
|
|
9335
|
+
let seriesIndex = -1;
|
|
9336
|
+
let drawingIndex = -1;
|
|
9337
|
+
let shownBook = ctx.workbook();
|
|
9338
|
+
let shownSheet = -1;
|
|
9339
|
+
let shownPath;
|
|
9340
|
+
const apply = (edit) => {
|
|
9341
|
+
if (!current || !ctx.commands.isEnabled(binding.commandId)) return;
|
|
9342
|
+
const found = activeChart(ctx);
|
|
9343
|
+
if (!found || found.chart !== current) return;
|
|
9344
|
+
const result = binding.edit(current, edit);
|
|
9345
|
+
if (!result) return;
|
|
9346
|
+
if (edit.kind !== "angle" && edit.kind !== "geometry") stopIndex = result.stopIndex;
|
|
9347
|
+
ctx.session()?.updateChart(ctx.activeSheet(), found.index, result.patch);
|
|
9348
|
+
};
|
|
9349
|
+
const refresh = (chart, view) => {
|
|
9350
|
+
track.cancel();
|
|
9351
|
+
for (const range2 of ranges.values()) range2.cancel();
|
|
9352
|
+
previewRange = void 0;
|
|
9353
|
+
const nextDrawing = activeChart(ctx)?.index ?? -1;
|
|
9354
|
+
if (seriesIndex !== binding.key() || drawingIndex !== nextDrawing || shownBook !== ctx.workbook() || shownSheet !== ctx.activeSheet()) {
|
|
9355
|
+
stopIndex = 0;
|
|
9356
|
+
direction.close();
|
|
9357
|
+
preset.close();
|
|
9358
|
+
}
|
|
9359
|
+
shownBook = ctx.workbook();
|
|
9360
|
+
shownSheet = ctx.activeSheet();
|
|
9361
|
+
seriesIndex = binding.key();
|
|
9362
|
+
drawingIndex = nextDrawing;
|
|
9363
|
+
current = chart;
|
|
9364
|
+
model = view;
|
|
9365
|
+
const fill = chart && binding.fill(chart);
|
|
9366
|
+
element.hidden = fill?.kind !== "gradient";
|
|
9367
|
+
if (fill?.kind !== "gradient") {
|
|
9368
|
+
direction.close();
|
|
9369
|
+
preset.close();
|
|
9370
|
+
return;
|
|
9371
|
+
}
|
|
9372
|
+
stopIndex = Math.max(0, Math.min(stopIndex, fill.stops.length - 1));
|
|
9373
|
+
const disabled = !ctx.commands.isEnabled(binding.commandId);
|
|
9374
|
+
presetRow.querySelector("span").textContent = ctx.t("Preset gradients");
|
|
9375
|
+
preset.update({
|
|
9376
|
+
fill,
|
|
9377
|
+
disabled,
|
|
9378
|
+
label: ctx.t("Preset gradients"),
|
|
9379
|
+
translate: ctx.t,
|
|
9380
|
+
onPick: (id) => apply({ kind: "preset", id })
|
|
9381
|
+
});
|
|
9382
|
+
const rectangularMarks = !!chart && binding.rectangular(chart);
|
|
9383
|
+
type.refresh(fill, disabled, rectangularMarks);
|
|
9384
|
+
if (shownPath !== fill.path) direction.close();
|
|
9385
|
+
shownPath = fill.path;
|
|
9386
|
+
angle.value = String(fill.angle ?? 90);
|
|
9387
|
+
angle.disabled = disabled || !!fill.path;
|
|
9388
|
+
position.value = String(fill.stops[stopIndex]?.position ?? 0);
|
|
9389
|
+
transparency.value = String(chartGradientStopTransparency(fill, stopIndex));
|
|
9390
|
+
const stopColor = fill.stops[stopIndex]?.color;
|
|
9391
|
+
const stopBrightness = stopColor && drawingColorBrightness(stopColor);
|
|
9392
|
+
brightness.value = stopBrightness === void 0 ? "" : String(stopBrightness);
|
|
9393
|
+
position.disabled = transparency.disabled = color.disabled = brightness.disabled = disabled || !fill.stops.length;
|
|
9394
|
+
const stops = (view && binding.gradient(view)?.stops) ?? [];
|
|
9395
|
+
directionRow.querySelector("span").textContent = ctx.t("Direction");
|
|
9396
|
+
direction.update({
|
|
9397
|
+
gradient: (view && binding.gradient(view)) ?? { type: "linear", stops: [] },
|
|
9398
|
+
disabled: disabled || !!fill.path && fill.path !== "rect" && !(rectangularMarks && ["circle", "shape"].includes(fill.path)),
|
|
9399
|
+
label: ctx.t("Direction"),
|
|
9400
|
+
translate: ctx.t,
|
|
9401
|
+
onPick: (value) => apply({ kind: "angle", value }),
|
|
9402
|
+
onRectPick: (direction2) => apply({ kind: "geometry", type: "rect", direction: direction2 }),
|
|
9403
|
+
onPathPick: (direction2) => {
|
|
9404
|
+
if (fill.path === "rect" || fill.path === "circle" || fill.path === "shape")
|
|
9405
|
+
apply({ kind: "geometry", type: fill.path, direction: direction2 });
|
|
9406
|
+
}
|
|
9407
|
+
});
|
|
9408
|
+
brightness.disabled ||= stopBrightness === void 0;
|
|
9409
|
+
const previewSeries = binding.key();
|
|
9410
|
+
const previewStop = stopIndex;
|
|
9411
|
+
if (chart && view)
|
|
9412
|
+
previewRange = seriesRangePreview(
|
|
9413
|
+
ctx,
|
|
9414
|
+
chart,
|
|
9415
|
+
view,
|
|
9416
|
+
previewSeries,
|
|
9417
|
+
previewStop,
|
|
9418
|
+
drawingIndex,
|
|
9419
|
+
track,
|
|
9420
|
+
color,
|
|
9421
|
+
() => current === chart && binding.key() === previewSeries && stopIndex === previewStop && binding.fill(chart) === fill,
|
|
9422
|
+
binding
|
|
9423
|
+
);
|
|
9424
|
+
color.style.setProperty("--series-fill", stops[stopIndex]?.color ?? "transparent");
|
|
9425
|
+
let preview;
|
|
9426
|
+
const gradient = view && binding.gradient(view);
|
|
9427
|
+
track.update({
|
|
9428
|
+
stops: stops.map((stop) => ({
|
|
9429
|
+
position: stop.position,
|
|
9430
|
+
color: drawingColorCss({ hex: stop.color, alpha: stop.opacity ?? 1, unapplied: [] })
|
|
9431
|
+
})),
|
|
9432
|
+
selected: stopIndex,
|
|
9433
|
+
disabled: disabled || stops.length !== fill.stops.length,
|
|
9434
|
+
label: ctx.t("Gradient stops"),
|
|
9435
|
+
stopLabel: (index) => ctx.t("Gradient stop {index}", { index: index + 1 }),
|
|
9436
|
+
onSelect: (index) => {
|
|
9437
|
+
stopIndex = index;
|
|
9438
|
+
refresh(current, model);
|
|
9439
|
+
},
|
|
9440
|
+
onMove: (index, position2) => apply({ kind: "stop", index, position: position2 }),
|
|
9441
|
+
onPreview: (index, value) => {
|
|
9442
|
+
if (value === void 0) {
|
|
9443
|
+
preview?.restore();
|
|
9444
|
+
preview = void 0;
|
|
9445
|
+
}
|
|
9446
|
+
if (current !== chart || chart && binding.fill(chart) !== fill) return;
|
|
9447
|
+
position.value = String(value ?? fill.stops[index]?.position ?? 0);
|
|
9448
|
+
if (value !== void 0 && gradient) {
|
|
9449
|
+
preview ??= createChartGradientPreview(ctx.root, drawingIndex, binding.key(), gradient);
|
|
9450
|
+
preview.position(index, value);
|
|
9451
|
+
}
|
|
9452
|
+
}
|
|
9453
|
+
});
|
|
9454
|
+
add.disabled = disabled || !fill.stops.length;
|
|
9455
|
+
remove.disabled = disabled || fill.stops.length <= 2;
|
|
9456
|
+
add.textContent = "+";
|
|
9457
|
+
remove.textContent = "\u2212";
|
|
9458
|
+
add.setAttribute("aria-label", ctx.t("Add gradient stop"));
|
|
9459
|
+
remove.setAttribute("aria-label", ctx.t("Remove gradient stop"));
|
|
9460
|
+
for (const [row2, input, label] of rows) {
|
|
9461
|
+
row2.querySelector("span").textContent = ctx.t(label);
|
|
9462
|
+
input.setAttribute("aria-label", ctx.t(label));
|
|
9463
|
+
}
|
|
9464
|
+
for (const range2 of ranges.values()) range2.refresh();
|
|
9465
|
+
};
|
|
9466
|
+
for (const [input, property] of [
|
|
9467
|
+
[angle, "angle"],
|
|
9468
|
+
[position, "position"],
|
|
9469
|
+
[transparency, "transparency"],
|
|
9470
|
+
[brightness, "brightness"]
|
|
9471
|
+
]) {
|
|
9472
|
+
input.addEventListener("change", () => {
|
|
9473
|
+
if (input.disabled || !ctx.commands.isEnabled(binding.commandId))
|
|
9474
|
+
return refresh(current, model);
|
|
9475
|
+
const value = input.valueAsNumber;
|
|
9476
|
+
if (!Number.isFinite(value) || !input.checkValidity()) {
|
|
9477
|
+
ctx.toast(
|
|
9478
|
+
ctx.t("Enter a whole number from {min} to {max}.", { min: input.min, max: input.max }),
|
|
9479
|
+
"warning"
|
|
9480
|
+
);
|
|
9481
|
+
return refresh(current, model);
|
|
9482
|
+
}
|
|
9483
|
+
apply(
|
|
9484
|
+
property === "angle" ? { kind: "angle", value } : { kind: "stop", index: stopIndex, [property]: value }
|
|
9485
|
+
);
|
|
9486
|
+
});
|
|
9487
|
+
}
|
|
9488
|
+
add.addEventListener("click", () => {
|
|
9489
|
+
if (!add.disabled) apply({ kind: "add", index: stopIndex });
|
|
9490
|
+
});
|
|
9491
|
+
remove.addEventListener("click", () => {
|
|
9492
|
+
if (!remove.disabled) apply({ kind: "remove", index: stopIndex });
|
|
9493
|
+
});
|
|
9494
|
+
color.addEventListener("click", () => {
|
|
9495
|
+
if (color.disabled || !ctx.commands.isEnabled(binding.commandId)) return;
|
|
9496
|
+
const chart = current;
|
|
9497
|
+
const series = binding.key();
|
|
9498
|
+
const index = stopIndex;
|
|
9499
|
+
const book = ctx.workbook();
|
|
9500
|
+
openColorGrid(
|
|
9501
|
+
color,
|
|
9502
|
+
(choice) => {
|
|
9503
|
+
if (choice && current === chart && binding.key() === series && stopIndex === index && ctx.workbook() === book)
|
|
9504
|
+
apply({ kind: "stop", index, color: choice });
|
|
9505
|
+
},
|
|
9506
|
+
{ t: ctx.t, ...book ? { theme: book.theme } : {} }
|
|
9507
|
+
);
|
|
9508
|
+
});
|
|
9509
|
+
return { element, refresh, create: () => apply({ kind: "create" }) };
|
|
9510
|
+
}
|
|
8788
9511
|
|
|
8789
9512
|
// src/xlsx/chart-series-fill.ts
|
|
8790
|
-
function createSeriesFill(ctx, selected) {
|
|
9513
|
+
function createSeriesFill(ctx, selected, binding = seriesFillBinding(selected)) {
|
|
8791
9514
|
const element = el(ctx, "div", "xve-chart-series-fill");
|
|
8792
9515
|
const heading2 = el(ctx, "h3");
|
|
8793
9516
|
const kind = select(ctx, []);
|
|
@@ -8795,35 +9518,37 @@ function createSeriesFill(ctx, selected) {
|
|
|
8795
9518
|
const color = el(ctx, "button", "xve-input xve-chart-series-color");
|
|
8796
9519
|
color.type = "button";
|
|
8797
9520
|
const colorField = field(ctx, "Color", color);
|
|
8798
|
-
const transparency = createSeriesTransparency(ctx, selected);
|
|
8799
|
-
|
|
9521
|
+
const transparency = createSeriesTransparency(ctx, selected, binding);
|
|
9522
|
+
const gradient = createSeriesGradient(ctx, selected, binding);
|
|
9523
|
+
element.append(heading2, kindField, colorField, transparency.element, gradient.element);
|
|
8800
9524
|
let current;
|
|
8801
9525
|
const apply = (value) => {
|
|
8802
|
-
if (!current || !ctx.commands.isEnabled(
|
|
9526
|
+
if (!current || !ctx.commands.isEnabled(binding.commandId)) return;
|
|
8803
9527
|
const found = activeChart(ctx);
|
|
8804
9528
|
if (!found || found.chart !== current) return;
|
|
8805
|
-
const patch =
|
|
9529
|
+
const patch = binding.color(current, value);
|
|
8806
9530
|
if (patch) ctx.session()?.updateChart(ctx.activeSheet(), found.index, patch);
|
|
8807
9531
|
};
|
|
8808
9532
|
kind.addEventListener("change", () => {
|
|
8809
9533
|
if (kind.value === "none") apply(null);
|
|
9534
|
+
else if (kind.value === "gradient") gradient.create();
|
|
8810
9535
|
else if (kind.value === "solid") {
|
|
8811
|
-
if (!current || !ctx.commands.isEnabled(
|
|
9536
|
+
if (!current || !ctx.commands.isEnabled(binding.commandId)) return;
|
|
8812
9537
|
const found = activeChart(ctx);
|
|
8813
9538
|
if (!found || found.chart !== current) return;
|
|
8814
|
-
const patch =
|
|
9539
|
+
const patch = binding.solid(current);
|
|
8815
9540
|
if (patch) ctx.session()?.updateChart(ctx.activeSheet(), found.index, patch);
|
|
8816
9541
|
}
|
|
8817
9542
|
});
|
|
8818
9543
|
color.addEventListener("click", () => {
|
|
8819
|
-
if (!current || !ctx.commands.isEnabled(
|
|
9544
|
+
if (!current || !ctx.commands.isEnabled(binding.commandId)) return;
|
|
8820
9545
|
const chart = current;
|
|
8821
|
-
const index =
|
|
9546
|
+
const index = binding.key();
|
|
8822
9547
|
const workbook = ctx.workbook();
|
|
8823
9548
|
openColorGrid(
|
|
8824
9549
|
color,
|
|
8825
9550
|
(choice) => {
|
|
8826
|
-
if (current === chart && ctx.workbook() === workbook &&
|
|
9551
|
+
if (current === chart && ctx.workbook() === workbook && binding.key() === index && choice)
|
|
8827
9552
|
apply(choice);
|
|
8828
9553
|
},
|
|
8829
9554
|
{ t: ctx.t, ...workbook ? { theme: workbook.theme } : {} }
|
|
@@ -8832,28 +9557,30 @@ function createSeriesFill(ctx, selected) {
|
|
|
8832
9557
|
const refresh = (chart, model) => {
|
|
8833
9558
|
current = chart;
|
|
8834
9559
|
transparency.refresh(chart);
|
|
8835
|
-
|
|
8836
|
-
const fill =
|
|
9560
|
+
gradient.refresh(chart, model);
|
|
9561
|
+
const fill = chart && binding.fill(chart);
|
|
8837
9562
|
const value = fill?.kind === "none" ? "none" : fill?.kind === "gradient" ? "gradient" : fill && fill.kind !== "solid" ? "imported" : "solid";
|
|
8838
9563
|
const entries = [
|
|
8839
9564
|
["none", "No fill"],
|
|
8840
|
-
["solid", "Solid fill"]
|
|
9565
|
+
["solid", "Solid fill"],
|
|
9566
|
+
["gradient", "Gradient fill"]
|
|
8841
9567
|
];
|
|
8842
|
-
if (value === "
|
|
8843
|
-
else if (value === "imported") entries.push(["imported", "Imported fill"]);
|
|
9568
|
+
if (value === "imported") entries.push(["imported", "Imported fill"]);
|
|
8844
9569
|
kind.replaceChildren(
|
|
8845
9570
|
...entries.map(([key, label]) => {
|
|
8846
9571
|
const option = el(ctx, "option");
|
|
8847
9572
|
option.value = key;
|
|
8848
9573
|
option.textContent = ctx.t(label);
|
|
8849
|
-
option.disabled = key === "
|
|
9574
|
+
option.disabled = key === "imported";
|
|
8850
9575
|
return option;
|
|
8851
9576
|
})
|
|
8852
9577
|
);
|
|
8853
9578
|
kind.value = value;
|
|
8854
|
-
|
|
9579
|
+
colorField.hidden = value !== "solid";
|
|
9580
|
+
transparency.element.hidden = value !== "solid";
|
|
9581
|
+
kind.disabled = !chart || !ctx.commands.isEnabled(binding.commandId);
|
|
8855
9582
|
color.disabled = kind.disabled || value !== "solid";
|
|
8856
|
-
const paint = model
|
|
9583
|
+
const paint = model && binding.paint(model);
|
|
8857
9584
|
color.style.setProperty("--series-fill", paint && paint !== "none" ? paint : "transparent");
|
|
8858
9585
|
heading2.textContent = ctx.t("Fill");
|
|
8859
9586
|
for (const [row2, control, label] of [
|
|
@@ -8881,7 +9608,7 @@ function chartSeriesCommand() {
|
|
|
8881
9608
|
run: (ctx, arg) => void ctx.dialogs.open("format-chart-series", arg)
|
|
8882
9609
|
});
|
|
8883
9610
|
}
|
|
8884
|
-
function createChartSeriesPane(ctx) {
|
|
9611
|
+
function createChartSeriesPane(ctx, onOpen) {
|
|
8885
9612
|
const element = el(ctx, "aside", "xve-chart-series-pane");
|
|
8886
9613
|
element.hidden = true;
|
|
8887
9614
|
element.setAttribute("role", "complementary");
|
|
@@ -8891,6 +9618,7 @@ function createChartSeriesPane(ctx) {
|
|
|
8891
9618
|
closeButton.type = "button";
|
|
8892
9619
|
closeButton.textContent = "\xD7";
|
|
8893
9620
|
const close = () => {
|
|
9621
|
+
fills.refresh(void 0, void 0);
|
|
8894
9622
|
element.hidden = true;
|
|
8895
9623
|
ctx.grid()?.focus();
|
|
8896
9624
|
};
|
|
@@ -9031,6 +9759,7 @@ function createChartSeriesPane(ctx) {
|
|
|
9031
9759
|
relocalize();
|
|
9032
9760
|
ctx.dialogs.register("format-chart-series", async (_ctx, props2) => {
|
|
9033
9761
|
if (!ctx.commands.isEnabled("chart.format-series")) return;
|
|
9762
|
+
onOpen?.();
|
|
9034
9763
|
element.hidden = false;
|
|
9035
9764
|
refresh();
|
|
9036
9765
|
if (typeof props2 === "number" && Number.isInteger(props2) && activeChart(ctx)?.chart.series[props2]) {
|
|
@@ -9039,7 +9768,112 @@ function createChartSeriesPane(ctx) {
|
|
|
9039
9768
|
}
|
|
9040
9769
|
overlap.focus();
|
|
9041
9770
|
});
|
|
9042
|
-
return { element, refresh, relocalize };
|
|
9771
|
+
return { element, refresh, relocalize, close };
|
|
9772
|
+
}
|
|
9773
|
+
var names = {
|
|
9774
|
+
chartArea: ["Chart Area", "Format Chart Area"],
|
|
9775
|
+
plotArea: ["Plot Area", "Format Plot Area"],
|
|
9776
|
+
title: ["Chart Title", "Format Chart Title"],
|
|
9777
|
+
legend: ["Legend", "Format Legend"]
|
|
9778
|
+
};
|
|
9779
|
+
function chartAreaCommand() {
|
|
9780
|
+
return editing({
|
|
9781
|
+
id: "chart.format-area",
|
|
9782
|
+
label: "Format Chart Area",
|
|
9783
|
+
icon: icon("chartColumn"),
|
|
9784
|
+
lock: "objects",
|
|
9785
|
+
enabled: (ctx) => !!activeChart(ctx),
|
|
9786
|
+
run: (ctx, arg) => void ctx.dialogs.open("format-chart-area", arg)
|
|
9787
|
+
});
|
|
9788
|
+
}
|
|
9789
|
+
function createChartAreaPane(ctx, onOpen) {
|
|
9790
|
+
const element = el(ctx, "aside", "xve-chart-series-pane");
|
|
9791
|
+
element.hidden = true;
|
|
9792
|
+
element.setAttribute("role", "complementary");
|
|
9793
|
+
const header = el(ctx, "div", "xve-chart-series-header");
|
|
9794
|
+
const title = el(ctx, "h2");
|
|
9795
|
+
const closeButton = el(ctx, "button", "xve-icon-button");
|
|
9796
|
+
closeButton.type = "button";
|
|
9797
|
+
closeButton.textContent = "\xD7";
|
|
9798
|
+
const body = el(ctx, "div", "xve-chart-series-body");
|
|
9799
|
+
let selected = "chartArea";
|
|
9800
|
+
const target24 = select(ctx, []);
|
|
9801
|
+
const targetField = field(ctx, "Chart element", target24);
|
|
9802
|
+
const fills = createSeriesFill(
|
|
9803
|
+
ctx,
|
|
9804
|
+
() => 0,
|
|
9805
|
+
backgroundFillBinding(() => selected)
|
|
9806
|
+
);
|
|
9807
|
+
const close = () => {
|
|
9808
|
+
fills.refresh(void 0, void 0);
|
|
9809
|
+
element.hidden = true;
|
|
9810
|
+
ctx.grid()?.focus();
|
|
9811
|
+
};
|
|
9812
|
+
closeButton.addEventListener("click", close);
|
|
9813
|
+
element.addEventListener("keydown", (event) => {
|
|
9814
|
+
if (event.key === "Escape") {
|
|
9815
|
+
event.preventDefault();
|
|
9816
|
+
event.stopPropagation();
|
|
9817
|
+
close();
|
|
9818
|
+
}
|
|
9819
|
+
});
|
|
9820
|
+
header.append(title, closeButton);
|
|
9821
|
+
body.append(targetField, fills.element);
|
|
9822
|
+
element.append(header, body);
|
|
9823
|
+
const refresh = () => {
|
|
9824
|
+
if (element.hidden) return;
|
|
9825
|
+
const found = activeChart(ctx), book = ctx.workbook();
|
|
9826
|
+
if (!found || !book) {
|
|
9827
|
+
close();
|
|
9828
|
+
return;
|
|
9829
|
+
}
|
|
9830
|
+
const available = (part) => part === "title" ? !!found.chart.title : part === "legend" ? found.chart.showLegend : true;
|
|
9831
|
+
for (const option of target24.options)
|
|
9832
|
+
option.disabled = !available(option.value);
|
|
9833
|
+
if (!available(selected)) selected = "chartArea";
|
|
9834
|
+
title.textContent = ctx.t(names[selected][1]);
|
|
9835
|
+
element.setAttribute("aria-label", title.textContent);
|
|
9836
|
+
target24.value = selected;
|
|
9837
|
+
target24.disabled = !ctx.commands.isEnabled("chart.format-area");
|
|
9838
|
+
fills.refresh(
|
|
9839
|
+
found.chart,
|
|
9840
|
+
chartView(
|
|
9841
|
+
book,
|
|
9842
|
+
ctx.activeSheet(),
|
|
9843
|
+
found.chart,
|
|
9844
|
+
createRefEvaluator(book, ctx.session()?.calc, { sheet: ctx.activeSheet() })
|
|
9845
|
+
)
|
|
9846
|
+
);
|
|
9847
|
+
};
|
|
9848
|
+
const relocalize = () => {
|
|
9849
|
+
closeButton.setAttribute("aria-label", ctx.t("Close"));
|
|
9850
|
+
targetField.querySelector("span").textContent = ctx.t("Chart element");
|
|
9851
|
+
target24.setAttribute("aria-label", ctx.t("Chart element"));
|
|
9852
|
+
target24.replaceChildren(
|
|
9853
|
+
...CHART_FILL_PARTS.map((part) => {
|
|
9854
|
+
const option = el(ctx, "option");
|
|
9855
|
+
option.value = part;
|
|
9856
|
+
option.textContent = ctx.t(names[part][0]);
|
|
9857
|
+
return option;
|
|
9858
|
+
})
|
|
9859
|
+
);
|
|
9860
|
+
refresh();
|
|
9861
|
+
};
|
|
9862
|
+
target24.addEventListener("change", () => {
|
|
9863
|
+
if (!target24.disabled && CHART_FILL_PARTS.includes(target24.value))
|
|
9864
|
+
selected = target24.value;
|
|
9865
|
+
refresh();
|
|
9866
|
+
});
|
|
9867
|
+
ctx.dialogs.register("format-chart-area", async (_ctx, part) => {
|
|
9868
|
+
if (!ctx.commands.isEnabled("chart.format-area")) return;
|
|
9869
|
+
onOpen();
|
|
9870
|
+
selected = CHART_FILL_PARTS.includes(part) ? part : "chartArea";
|
|
9871
|
+
element.hidden = false;
|
|
9872
|
+
refresh();
|
|
9873
|
+
target24.focus();
|
|
9874
|
+
});
|
|
9875
|
+
relocalize();
|
|
9876
|
+
return { element, refresh, relocalize, close };
|
|
9043
9877
|
}
|
|
9044
9878
|
|
|
9045
9879
|
// src/xlsx/commands/index.ts
|
|
@@ -9060,7 +9894,8 @@ function allCommands() {
|
|
|
9060
9894
|
...reviewCommands(),
|
|
9061
9895
|
...viewCommands(),
|
|
9062
9896
|
...contextualCommands(),
|
|
9063
|
-
chartSeriesCommand()
|
|
9897
|
+
chartSeriesCommand(),
|
|
9898
|
+
chartAreaCommand()
|
|
9064
9899
|
];
|
|
9065
9900
|
}
|
|
9066
9901
|
function installCommands(ctx) {
|
|
@@ -9953,10 +10788,12 @@ var DrawingLayer = class {
|
|
|
9953
10788
|
node.addEventListener("pointerdown", (event) => this.#press(event, index));
|
|
9954
10789
|
node.addEventListener("dblclick", (event) => {
|
|
9955
10790
|
const series = event.currentTarget.xgSeriesHit;
|
|
9956
|
-
|
|
10791
|
+
const part = event.currentTarget.xgChartPart;
|
|
10792
|
+
if (series === void 0 && part === void 0) return;
|
|
9957
10793
|
event.stopPropagation();
|
|
9958
10794
|
view.ctx.selection.set({ drawing: index });
|
|
9959
|
-
void view.ctx.commands.run("chart.format-series", series);
|
|
10795
|
+
if (series !== void 0) void view.ctx.commands.run("chart.format-series", series);
|
|
10796
|
+
else void view.ctx.commands.run("chart.format-area", part);
|
|
9960
10797
|
});
|
|
9961
10798
|
this.#nodes.set(key, node);
|
|
9962
10799
|
}
|
|
@@ -9965,7 +10802,7 @@ var DrawingLayer = class {
|
|
|
9965
10802
|
const sig = `${drawing.kind}:${Math.round(box.w)}x${Math.round(box.h)}:${this.#generation}`;
|
|
9966
10803
|
if (node.xgSig !== sig) {
|
|
9967
10804
|
node.xgSig = sig;
|
|
9968
|
-
this.#paint(node, drawing, box
|
|
10805
|
+
this.#paint(node, drawing, box);
|
|
9969
10806
|
}
|
|
9970
10807
|
this.#selection(node, index);
|
|
9971
10808
|
}
|
|
@@ -9976,7 +10813,7 @@ var DrawingLayer = class {
|
|
|
9976
10813
|
this.#nodes.delete(key);
|
|
9977
10814
|
}
|
|
9978
10815
|
}
|
|
9979
|
-
#paint(node, drawing, box
|
|
10816
|
+
#paint(node, drawing, box) {
|
|
9980
10817
|
const view = this.#view;
|
|
9981
10818
|
const doc = view.doc;
|
|
9982
10819
|
node.replaceChildren();
|
|
@@ -10002,11 +10839,10 @@ var DrawingLayer = class {
|
|
|
10002
10839
|
node.append(
|
|
10003
10840
|
svgNode(
|
|
10004
10841
|
doc,
|
|
10005
|
-
renderChartSvg(
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
)
|
|
10842
|
+
renderChartSvg(model, Math.max(10, box.w), Math.max(10, box.h), {
|
|
10843
|
+
measureText: (content, font) => view.measurer.measure(content, font),
|
|
10844
|
+
measureFont: (font) => view.measurer.fontMetrics(font)
|
|
10845
|
+
})
|
|
10010
10846
|
)
|
|
10011
10847
|
);
|
|
10012
10848
|
} catch {
|
|
@@ -10052,6 +10888,8 @@ var DrawingLayer = class {
|
|
|
10052
10888
|
const node = event.currentTarget;
|
|
10053
10889
|
const series = event.target.closest("[data-chart-series]")?.dataset.chartSeries;
|
|
10054
10890
|
node.xgSeriesHit = series === void 0 ? void 0 : Number(series);
|
|
10891
|
+
const part = event.target.closest("[data-chart-part]")?.dataset.chartPart;
|
|
10892
|
+
node.xgChartPart = CHART_FILL_PARTS.includes(part) ? part : void 0;
|
|
10055
10893
|
view.ctx.selection.set({ drawing: index });
|
|
10056
10894
|
view.ctx.grid()?.focus();
|
|
10057
10895
|
const session = view.ctx.session();
|
|
@@ -10142,9 +10980,9 @@ var GridA11y = class {
|
|
|
10142
10980
|
}
|
|
10143
10981
|
input;
|
|
10144
10982
|
/** Updates the sink label and announces (debounced) after a selection change. */
|
|
10145
|
-
update(selection,
|
|
10983
|
+
update(selection, editing7) {
|
|
10146
10984
|
const text3 = describeSelection(this.#view, selection);
|
|
10147
|
-
if (!
|
|
10985
|
+
if (!editing7) this.input.setAttribute("aria-label", text3);
|
|
10148
10986
|
if (this.#timer) clearTimeout(this.#timer);
|
|
10149
10987
|
this.#timer = setTimeout(() => {
|
|
10150
10988
|
this.live.textContent = text3;
|
|
@@ -11190,12 +12028,12 @@ function paintCell(doc, node, item, zoom) {
|
|
|
11190
12028
|
}
|
|
11191
12029
|
}
|
|
11192
12030
|
if (view.icon) {
|
|
11193
|
-
const
|
|
12031
|
+
const icon7 = svgNode(
|
|
11194
12032
|
doc,
|
|
11195
12033
|
iconSvg(view.icon.set, view.icon.index, Math.round(16 * (zoom / 100)))
|
|
11196
12034
|
);
|
|
11197
|
-
|
|
11198
|
-
node.append(
|
|
12035
|
+
icon7.setAttribute("class", "xg-ic");
|
|
12036
|
+
node.append(icon7);
|
|
11199
12037
|
}
|
|
11200
12038
|
if (item.text) {
|
|
11201
12039
|
const box = h(doc, "div", "xg-t");
|
|
@@ -11356,6 +12194,7 @@ function estimateWidth(text3, font) {
|
|
|
11356
12194
|
function createTextMeasurer(doc) {
|
|
11357
12195
|
let context;
|
|
11358
12196
|
const cache = /* @__PURE__ */ new Map();
|
|
12197
|
+
const metricsCache = /* @__PURE__ */ new Map();
|
|
11359
12198
|
const ctx = () => {
|
|
11360
12199
|
if (context !== void 0) return context;
|
|
11361
12200
|
try {
|
|
@@ -11383,7 +12222,24 @@ function createTextMeasurer(doc) {
|
|
|
11383
12222
|
};
|
|
11384
12223
|
return {
|
|
11385
12224
|
measure,
|
|
11386
|
-
measureFont: (text3, font) => measure(text3, cssFont(font, 100))
|
|
12225
|
+
measureFont: (text3, font) => measure(text3, cssFont(font, 100)),
|
|
12226
|
+
fontMetrics: (font) => {
|
|
12227
|
+
const hit = metricsCache.get(font);
|
|
12228
|
+
if (hit) return hit;
|
|
12229
|
+
const c = ctx();
|
|
12230
|
+
if (!c) return void 0;
|
|
12231
|
+
if (c.font !== font) c.font = font;
|
|
12232
|
+
const result = c.measureText("Mg");
|
|
12233
|
+
const metrics = {
|
|
12234
|
+
ascent: result.fontBoundingBoxAscent,
|
|
12235
|
+
descent: result.fontBoundingBoxDescent
|
|
12236
|
+
};
|
|
12237
|
+
if (!Number.isFinite(metrics.ascent) || !Number.isFinite(metrics.descent) || metrics.ascent + metrics.descent <= 0)
|
|
12238
|
+
return void 0;
|
|
12239
|
+
if (metricsCache.size > 1e4) metricsCache.clear();
|
|
12240
|
+
metricsCache.set(font, metrics);
|
|
12241
|
+
return metrics;
|
|
12242
|
+
}
|
|
11387
12243
|
};
|
|
11388
12244
|
}
|
|
11389
12245
|
function rectOf(metrics, range2, maxRow, maxCol) {
|
|
@@ -11976,9 +12832,9 @@ var GRID_CSS = `
|
|
|
11976
12832
|
.xg-drawings{z-index:4}
|
|
11977
12833
|
.xg-obj{position:absolute;box-sizing:border-box;pointer-events:auto;cursor:default}
|
|
11978
12834
|
.xg-obj img,.xg-obj svg{display:block;width:100%;height:100%;pointer-events:none}
|
|
11979
|
-
.xg-chart svg [data-chart-series]{pointer-events:auto}
|
|
11980
|
-
.xg-obj.xg-chart{background:#fff;
|
|
11981
|
-
.xg-obj.xg-obj-sel{outline:1px solid #8a8a8a}
|
|
12835
|
+
.xg-chart svg [data-chart-series],.xg-chart svg [data-chart-part]{pointer-events:auto}
|
|
12836
|
+
.xg-obj.xg-chart{background:#fff;outline:1px solid #d9d9d9;outline-offset:-1px}
|
|
12837
|
+
.xg-obj.xg-obj-sel{outline:1px solid #8a8a8a;outline-offset:0}
|
|
11982
12838
|
.xg-obj .xg-grip{position:absolute;width:8px;height:8px;background:#fff;border:1px solid #555;box-sizing:border-box;border-radius:50%}
|
|
11983
12839
|
.xg-obj-unsupported{background:repeating-linear-gradient(45deg,#f6f6f6,#f6f6f6 6px,#ececec 6px,#ececec 12px);border:1px dashed #aaa;
|
|
11984
12840
|
font-size:11px;color:#555;display:flex;align-items:center;justify-content:center;text-align:center}
|
|
@@ -12372,10 +13228,10 @@ function createFormulaInput(ctx, doc, bar) {
|
|
|
12372
13228
|
const onKey = (event) => {
|
|
12373
13229
|
event.stopPropagation();
|
|
12374
13230
|
if (assist.handleKey(event, field2)) return;
|
|
12375
|
-
const
|
|
13231
|
+
const editing7 = bridge.state().editing;
|
|
12376
13232
|
if (event.key === "Escape") {
|
|
12377
13233
|
event.preventDefault();
|
|
12378
|
-
if (
|
|
13234
|
+
if (editing7) bridge.cancel();
|
|
12379
13235
|
else showCell();
|
|
12380
13236
|
ctx.grid()?.focus();
|
|
12381
13237
|
return;
|
|
@@ -12388,7 +13244,7 @@ function createFormulaInput(ctx, doc, bar) {
|
|
|
12388
13244
|
onInput();
|
|
12389
13245
|
return;
|
|
12390
13246
|
}
|
|
12391
|
-
if (!
|
|
13247
|
+
if (!editing7) return;
|
|
12392
13248
|
if (event.key === "Enter") {
|
|
12393
13249
|
event.preventDefault();
|
|
12394
13250
|
if (event.ctrlKey || event.metaKey) bridge.commit("none", true);
|
|
@@ -12526,10 +13382,10 @@ function createNameBox(ctx, doc) {
|
|
|
12526
13382
|
const wb = ctx.workbook();
|
|
12527
13383
|
list.replaceChildren();
|
|
12528
13384
|
const sheet = ctx.activeSheet();
|
|
12529
|
-
const
|
|
13385
|
+
const names2 = (wb?.definedNames ?? []).filter(
|
|
12530
13386
|
(d) => !d.hidden && (d.localSheet === void 0 || d.localSheet === sheet)
|
|
12531
13387
|
);
|
|
12532
|
-
for (const named of
|
|
13388
|
+
for (const named of names2) {
|
|
12533
13389
|
const item = h(doc, "li", "xfb-name-item", { role: "option" });
|
|
12534
13390
|
item.textContent = named.name;
|
|
12535
13391
|
item.addEventListener("mousedown", (event) => {
|
|
@@ -12540,7 +13396,7 @@ function createNameBox(ctx, doc) {
|
|
|
12540
13396
|
});
|
|
12541
13397
|
list.append(item);
|
|
12542
13398
|
}
|
|
12543
|
-
if (!
|
|
13399
|
+
if (!names2.length) {
|
|
12544
13400
|
const empty = h(doc, "li", "xfb-name-empty", { "aria-disabled": "true" });
|
|
12545
13401
|
empty.textContent = t("No defined names");
|
|
12546
13402
|
list.append(empty);
|
|
@@ -13493,10 +14349,10 @@ function adjacentSheet(ctx, step2) {
|
|
|
13493
14349
|
return void 0;
|
|
13494
14350
|
}
|
|
13495
14351
|
function shellCommands(handlers) {
|
|
13496
|
-
const file = (id, label, command,
|
|
14352
|
+
const file = (id, label, command, icon7, shortcut) => ({
|
|
13497
14353
|
id,
|
|
13498
14354
|
label,
|
|
13499
|
-
icon:
|
|
14355
|
+
icon: icon7,
|
|
13500
14356
|
...shortcut ? { shortcut } : {},
|
|
13501
14357
|
enabled: (ctx) => command === "new" || command === "open" || hasWorkbook(ctx),
|
|
13502
14358
|
run: () => handlers.fileCommand(command)
|
|
@@ -14010,7 +14866,8 @@ function buildShell(core) {
|
|
|
14010
14866
|
});
|
|
14011
14867
|
const toaster = createToaster(doc, () => ctx.t("Close"));
|
|
14012
14868
|
const workspace = el2(doc, "div", "xve-workspace");
|
|
14013
|
-
const chartSeriesPane = createChartSeriesPane(ctx);
|
|
14869
|
+
const chartSeriesPane = createChartSeriesPane(ctx, () => chartAreaPane.close());
|
|
14870
|
+
const chartAreaPane = createChartAreaPane(ctx, () => chartSeriesPane.close());
|
|
14014
14871
|
const canvasRow = el2(doc, "div", "xve-canvas-row");
|
|
14015
14872
|
const formulaRow = el2(doc, "div", "xve-formula-row");
|
|
14016
14873
|
const gridHost = el2(doc, "div", "xve-grid-host");
|
|
@@ -14019,7 +14876,7 @@ function buildShell(core) {
|
|
|
14019
14876
|
const emptyText = el2(doc, "p");
|
|
14020
14877
|
empty.append(emptyText);
|
|
14021
14878
|
workspace.append(formulaRow, gridHost, tabsRow, empty);
|
|
14022
|
-
canvasRow.append(workspace, chartSeriesPane.element);
|
|
14879
|
+
canvasRow.append(workspace, chartSeriesPane.element, chartAreaPane.element);
|
|
14023
14880
|
frame.append(
|
|
14024
14881
|
titleBar.element,
|
|
14025
14882
|
ribbon.element,
|
|
@@ -14044,6 +14901,7 @@ function buildShell(core) {
|
|
|
14044
14901
|
gridHost,
|
|
14045
14902
|
tabsRow,
|
|
14046
14903
|
chartSeriesPane.element,
|
|
14904
|
+
chartAreaPane.element,
|
|
14047
14905
|
statusBar.element
|
|
14048
14906
|
].filter((region) => region.getClientRects().length);
|
|
14049
14907
|
const focusRegion = (region) => {
|
|
@@ -14083,6 +14941,7 @@ function buildShell(core) {
|
|
|
14083
14941
|
titleBar.refresh();
|
|
14084
14942
|
statusBar.refresh();
|
|
14085
14943
|
chartSeriesPane.refresh();
|
|
14944
|
+
chartAreaPane.refresh();
|
|
14086
14945
|
titleBar.setFileName(core.fileName);
|
|
14087
14946
|
if (core.dirty.dirty && saveState !== "dirty" && saveState !== "saving")
|
|
14088
14947
|
chrome.setSaveState("dirty");
|
|
@@ -14098,6 +14957,7 @@ function buildShell(core) {
|
|
|
14098
14957
|
statusBar.relocalize();
|
|
14099
14958
|
backstage.relocalize();
|
|
14100
14959
|
chartSeriesPane.relocalize();
|
|
14960
|
+
chartAreaPane.relocalize();
|
|
14101
14961
|
core.requestRender();
|
|
14102
14962
|
}
|
|
14103
14963
|
};
|