@a3s-lab/office 0.13.0 → 0.13.1

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.
Files changed (25) hide show
  1. package/README.md +13 -1
  2. package/dist/0~6090.js +63 -4
  3. package/dist/0~spreadsheet-editor.js +2940 -2164
  4. package/dist/4104.js +1094 -18
  5. package/dist/internal/features/work/editors/office-menu-keyboard.d.ts +1 -0
  6. package/dist/internal/features/work/editors/spreadsheet-cell-border-per-cell.d.ts +5 -0
  7. package/dist/internal/features/work/editors/spreadsheet-cell-border.d.ts +15 -1
  8. package/dist/internal/features/work/editors/spreadsheet-cell-style-command.d.ts +3 -0
  9. package/dist/internal/features/work/editors/spreadsheet-cell-style-ribbon.d.ts +9 -0
  10. package/dist/internal/features/work/editors/spreadsheet-cell-style.d.ts +41 -0
  11. package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +134 -0
  12. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +2 -0
  13. package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +3 -1
  14. package/dist/internal/features/work/editors/spreadsheet-number-format.d.ts +15 -3
  15. package/dist/internal/features/work/work-xlsx-cell-borders.d.ts +25 -0
  16. package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +21 -0
  17. package/dist/internal/features/work/work-xlsx-cell-style-xml.d.ts +17 -0
  18. package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +13 -0
  19. package/dist/internal/features/work/work-xlsx-colors.d.ts +6 -0
  20. package/dist/internal/features/work/work-xlsx-interop.d.ts +3 -1
  21. package/dist/internal/features/work/work-xlsx-worksheet-scan.d.ts +1 -0
  22. package/dist/office-kernel.wasm +0 -0
  23. package/dist/styles.css +117 -0
  24. package/dist/work-spreadsheet-package-scan.worker.js +7 -3
  25. package/package.json +5 -3
@@ -1,2 +1,3 @@
1
1
  import type { KeyboardEvent } from 'react';
2
2
  export declare function moveOfficeMenuFocus(event: KeyboardEvent<HTMLElement>): boolean;
3
+ export declare function moveOfficeGridMenuFocus(event: KeyboardEvent<HTMLElement>, columns: number): boolean;
@@ -0,0 +1,5 @@
1
+ import type { WorkSpreadsheetContent } from '../work-types';
2
+ import { type SpreadsheetCellBorderFormat } from './spreadsheet-cell-border';
3
+ import { type SpreadsheetCellRangeInput } from './spreadsheet-cell-range';
4
+ export declare const MAX_SPREADSHEET_PER_CELL_BORDER_CELLS = 10000;
5
+ export declare function setSpreadsheetCellBordersPerCell(content: WorkSpreadsheetContent, sheetId: string, range: SpreadsheetCellRangeInput, formats: readonly SpreadsheetCellBorderFormat[]): WorkSpreadsheetContent | null;
@@ -1,4 +1,4 @@
1
- import type { WorkSpreadsheetContent } from '../work-types';
1
+ import type { WorkSpreadsheetContent, WorkSpreadsheetSheet } from '../work-types';
2
2
  import { type SpreadsheetCellRangeInput } from './spreadsheet-cell-range';
3
3
  export declare const spreadsheetCellBorderTargets: readonly ["top", "bottom", "left", "right", "none", "all", "outside", "inside", "horizontal", "vertical", "diagonal"];
4
4
  export type SpreadsheetCellBorderTarget = (typeof spreadsheetCellBorderTargets)[number];
@@ -9,6 +9,20 @@ export interface SpreadsheetCellBorderFormat {
9
9
  color: string;
10
10
  style: SpreadsheetCellBorderStyle;
11
11
  }
12
+ export interface SpreadsheetResolvedCellBorderLine {
13
+ color: string;
14
+ style: string;
15
+ }
16
+ export interface SpreadsheetResolvedCellBorders {
17
+ bottom?: SpreadsheetResolvedCellBorderLine;
18
+ diagonal?: SpreadsheetResolvedCellBorderLine;
19
+ left?: SpreadsheetResolvedCellBorderLine;
20
+ right?: SpreadsheetResolvedCellBorderLine;
21
+ top?: SpreadsheetResolvedCellBorderLine;
22
+ }
12
23
  export declare const MAX_SPREADSHEET_DIAGONAL_BORDER_CELLS = 4096;
24
+ export declare function spreadsheetNativeBorderStyle(style: SpreadsheetCellBorderStyle): string;
13
25
  export declare function canSetSpreadsheetCellBorders(content: WorkSpreadsheetContent, sheetId: string, range: SpreadsheetCellRangeInput, format: SpreadsheetCellBorderFormat): boolean;
14
26
  export declare function setSpreadsheetCellBorders(content: WorkSpreadsheetContent, sheetId: string, range: SpreadsheetCellRangeInput, format: SpreadsheetCellBorderFormat): WorkSpreadsheetContent | null;
27
+ export declare function spreadsheetCellBordersAt(sheet: WorkSpreadsheetSheet | undefined, row: number, column: number): SpreadsheetResolvedCellBorders;
28
+ export declare function normalizeSpreadsheetBorderFormat(format: SpreadsheetCellBorderFormat): SpreadsheetCellBorderFormat | null;
@@ -0,0 +1,3 @@
1
+ import type { SpreadsheetCommandContext, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
2
+ import { type OfficeEditorExtension } from './office-editor-extension';
3
+ export declare function createSpreadsheetCellStyleExtension(): OfficeEditorExtension<SpreadsheetCommandContext, SpreadsheetEditorCommands>;
@@ -0,0 +1,9 @@
1
+ import type { Cell } from '@fortune-sheet/core';
2
+ import type { SpreadsheetResolvedCellBorders } from './spreadsheet-cell-border';
3
+ import type { SpreadsheetEditorCanCommands, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
4
+ export declare function SpreadsheetCellStyleRibbon({ can, commands, toolbarCell, toolbarCellBorders, }: {
5
+ can: SpreadsheetEditorCanCommands;
6
+ commands: SpreadsheetEditorCommands;
7
+ toolbarCell: Cell | null | undefined;
8
+ toolbarCellBorders?: SpreadsheetResolvedCellBorders;
9
+ }): import("react").JSX.Element;
@@ -0,0 +1,41 @@
1
+ import type { Cell } from '@fortune-sheet/core';
2
+ import type { WorkSpreadsheetContent } from '../work-types';
3
+ import { type SpreadsheetCellBorderFormat, type SpreadsheetResolvedCellBorders } from './spreadsheet-cell-border';
4
+ import { type SpreadsheetCellRangeInput } from './spreadsheet-cell-range';
5
+ export declare const spreadsheetCellStylePresetIds: readonly ["normal", "good", "bad", "neutral", "calculation", "checkCell", "explanatoryText", "input", "linkedCell", "note", "output", "warningText", "heading1", "heading2", "heading3", "heading4", "total"];
6
+ export type SpreadsheetCellStyleChoice = (typeof spreadsheetCellStylePresetIds)[number];
7
+ export type SpreadsheetCellStylePreset = SpreadsheetCellStyleChoice | 'custom';
8
+ export declare const MAX_SPREADSHEET_CELL_STYLE_CELLS = 10000;
9
+ interface SpreadsheetCellStyleFormat {
10
+ bg: string;
11
+ bl: 0 | 1;
12
+ cl: 0 | 1;
13
+ fc: string;
14
+ ff: string;
15
+ fs: number;
16
+ it: 0 | 1;
17
+ un: 0 | 1;
18
+ }
19
+ export interface SpreadsheetCellStylePreview {
20
+ backgroundColor: string;
21
+ color: string;
22
+ fontSize?: string;
23
+ fontStyle?: 'italic' | 'normal';
24
+ fontWeight?: number;
25
+ textDecoration?: 'none' | 'underline';
26
+ }
27
+ export interface SpreadsheetCellStyleDefinition {
28
+ id: SpreadsheetCellStyleChoice;
29
+ label: string;
30
+ group: '常用' | '数据和模型' | '标题和汇总';
31
+ description: string;
32
+ format: SpreadsheetCellStyleFormat;
33
+ borders?: readonly SpreadsheetCellBorderFormat[];
34
+ preview: SpreadsheetCellStylePreview;
35
+ }
36
+ export declare const spreadsheetCellStyleDefinitions: readonly [SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition, SpreadsheetCellStyleDefinition];
37
+ export declare function spreadsheetCellStyleDefinition(preset: SpreadsheetCellStyleChoice): SpreadsheetCellStyleDefinition;
38
+ export declare function spreadsheetCellStylePreset(cell: Cell | null | undefined, borders?: SpreadsheetResolvedCellBorders): SpreadsheetCellStylePreset;
39
+ export declare function canApplySpreadsheetCellStyle(content: WorkSpreadsheetContent, sheetId: string, range: SpreadsheetCellRangeInput, preset: SpreadsheetCellStyleChoice): boolean;
40
+ export declare function applySpreadsheetCellStyle(content: WorkSpreadsheetContent, sheetId: string, range: SpreadsheetCellRangeInput, preset: SpreadsheetCellStyleChoice): WorkSpreadsheetContent | null;
41
+ export {};
@@ -173,6 +173,131 @@ export declare const spreadsheetCommandCatalog: {
173
173
  readonly editor: readonly ["Mod-5"];
174
174
  };
175
175
  };
176
+ readonly numberFormatGeneral: {
177
+ readonly id: "number.general";
178
+ readonly label: "常规";
179
+ readonly location: {
180
+ readonly area: "ribbon";
181
+ readonly tab: "home";
182
+ readonly group: "number";
183
+ };
184
+ readonly shortcut: {
185
+ readonly label: "Cmd/Ctrl+Shift+~";
186
+ readonly aria: "Control+Shift+~ Meta+Shift+~";
187
+ readonly editor: readonly ["Mod-Shift-~"];
188
+ };
189
+ };
190
+ readonly numberFormatNumber: {
191
+ readonly id: "number.number";
192
+ readonly label: "数字";
193
+ readonly location: {
194
+ readonly area: "ribbon";
195
+ readonly tab: "home";
196
+ readonly group: "number";
197
+ };
198
+ readonly shortcut: {
199
+ readonly label: "Cmd/Ctrl+Shift+!";
200
+ readonly aria: "Control+Shift+! Meta+Shift+!";
201
+ readonly editor: readonly ["Mod-Shift-!"];
202
+ };
203
+ };
204
+ readonly numberFormatCurrency: {
205
+ readonly id: "number.currency";
206
+ readonly label: "货币";
207
+ readonly location: {
208
+ readonly area: "ribbon";
209
+ readonly tab: "home";
210
+ readonly group: "number";
211
+ };
212
+ readonly shortcut: {
213
+ readonly label: "Cmd/Ctrl+Shift+$";
214
+ readonly aria: "Control+Shift+$ Meta+Shift+$";
215
+ readonly editor: readonly ["Mod-Shift-$"];
216
+ };
217
+ };
218
+ readonly numberFormatAccounting: {
219
+ readonly id: "number.accounting";
220
+ readonly label: "会计专用";
221
+ readonly location: {
222
+ readonly area: "ribbon";
223
+ readonly tab: "home";
224
+ readonly group: "number";
225
+ };
226
+ };
227
+ readonly numberFormatPercent: {
228
+ readonly id: "number.percent";
229
+ readonly label: "百分比";
230
+ readonly location: {
231
+ readonly area: "ribbon";
232
+ readonly tab: "home";
233
+ readonly group: "number";
234
+ };
235
+ readonly shortcut: {
236
+ readonly label: "Cmd/Ctrl+Shift+%";
237
+ readonly aria: "Control+Shift+% Meta+Shift+%";
238
+ readonly editor: readonly ["Mod-Shift-%"];
239
+ };
240
+ };
241
+ readonly numberFormatDate: {
242
+ readonly id: "number.date";
243
+ readonly label: "短日期";
244
+ readonly location: {
245
+ readonly area: "ribbon";
246
+ readonly tab: "home";
247
+ readonly group: "number";
248
+ };
249
+ readonly shortcut: {
250
+ readonly label: "Cmd/Ctrl+Shift+#";
251
+ readonly aria: "Control+Shift+# Meta+Shift+#";
252
+ readonly editor: readonly ["Mod-Shift-#"];
253
+ };
254
+ };
255
+ readonly numberFormatTime: {
256
+ readonly id: "number.time";
257
+ readonly label: "时间";
258
+ readonly location: {
259
+ readonly area: "ribbon";
260
+ readonly tab: "home";
261
+ readonly group: "number";
262
+ };
263
+ readonly shortcut: {
264
+ readonly label: "Cmd/Ctrl+Shift+@";
265
+ readonly aria: "Control+Shift+@ Meta+Shift+@";
266
+ readonly editor: readonly ["Mod-Shift-@"];
267
+ };
268
+ };
269
+ readonly numberFormatScientific: {
270
+ readonly id: "number.scientific";
271
+ readonly label: "科学计数";
272
+ readonly location: {
273
+ readonly area: "ribbon";
274
+ readonly tab: "home";
275
+ readonly group: "number";
276
+ };
277
+ readonly shortcut: {
278
+ readonly label: "Cmd/Ctrl+Shift+^";
279
+ readonly aria: "Control+Shift+^ Meta+Shift+^";
280
+ readonly editor: readonly ["Mod-Shift-^"];
281
+ };
282
+ };
283
+ readonly numberFormatFraction: {
284
+ readonly id: "number.fraction";
285
+ readonly label: "分数";
286
+ readonly location: {
287
+ readonly area: "ribbon";
288
+ readonly tab: "home";
289
+ readonly group: "number";
290
+ };
291
+ };
292
+ readonly numberFormatText: {
293
+ readonly id: "number.text";
294
+ readonly label: "文本";
295
+ readonly location: {
296
+ readonly area: "ribbon";
297
+ readonly tab: "home";
298
+ readonly group: "number";
299
+ };
300
+ };
176
301
  readonly borderTop: {
177
302
  readonly id: "font.borderTop";
178
303
  readonly label: "上框线";
@@ -331,6 +456,15 @@ export declare const spreadsheetCommandCatalog: {
331
456
  readonly group: "styles";
332
457
  };
333
458
  };
459
+ readonly cellStyles: {
460
+ readonly id: "styles.cellStyles";
461
+ readonly label: "单元格样式";
462
+ readonly location: {
463
+ readonly area: "ribbon";
464
+ readonly tab: "home";
465
+ readonly group: "styles";
466
+ };
467
+ };
334
468
  readonly insertRowsAbove: {
335
469
  readonly id: "cells.insertRowsAbove";
336
470
  readonly label: "在上方插入行";
@@ -4,6 +4,7 @@ import type { WorkSpreadsheetContent } from '../work-types';
4
4
  import { type OfficeEditorCanCommands, type OfficeEditorExtension } from './office-editor-extension';
5
5
  import { type SpreadsheetCellClearMode } from './spreadsheet-cell-clear';
6
6
  import type { SpreadsheetCellBorderFormat } from './spreadsheet-cell-border';
7
+ import type { SpreadsheetCellStyleChoice } from './spreadsheet-cell-style';
7
8
  import type { SpreadsheetCellFillDirection } from './spreadsheet-cell-fill';
8
9
  import { type SpreadsheetCellMergeCommand } from './spreadsheet-cell-merge';
9
10
  import type { SpreadsheetFormatPainterMode } from './spreadsheet-format-painter';
@@ -104,6 +105,7 @@ export interface SpreadsheetEditorCommands {
104
105
  activateSheet: (sheetId: string) => boolean;
105
106
  activateFormatPainter: (mode: SpreadsheetFormatPainterMode) => boolean;
106
107
  addSheet: () => boolean;
108
+ applyCellStyle: (preset: SpreadsheetCellStyleChoice) => boolean;
107
109
  applyFormatPainter: (target: SpreadsheetCommandSelection) => boolean;
108
110
  cancelFormatPainter: () => boolean;
109
111
  clearSelectedCells: (mode?: SpreadsheetCellClearMode) => boolean;
@@ -1,12 +1,13 @@
1
1
  import type { Cell, Selection } from '@fortune-sheet/core';
2
2
  import type { WorkSpreadsheetContent } from '../work-types';
3
+ import type { SpreadsheetResolvedCellBorders } from './spreadsheet-cell-border';
3
4
  import { type SpreadsheetRibbonTabId } from './spreadsheet-command-catalog';
4
5
  import type { SpreadsheetEditorCanCommands, SpreadsheetEditorCommands } from './spreadsheet-command-controller';
5
6
  import type { SpreadsheetFormatPainterMode } from './spreadsheet-format-painter';
6
7
  import type { SpreadsheetWorkbookPanelView } from './spreadsheet-workbook-panel';
7
8
  import { type WorkOfficeFileAction } from './work-office-chrome';
8
9
  export type { SpreadsheetRibbonTabId } from './spreadsheet-command-catalog';
9
- export declare function SpreadsheetEditorRibbon({ activeTab, autoFilterActive, can, commands, content, fileActions, findOpen, formatPainterMode, freezePanesActive, freezePanesSelection, gridLinesVisible, panelId, onOpenFind, onTabChange, onTogglePanel, panel, toolbarCell, }: {
10
+ export declare function SpreadsheetEditorRibbon({ activeTab, autoFilterActive, can, commands, content, fileActions, findOpen, formatPainterMode, freezePanesActive, freezePanesSelection, gridLinesVisible, panelId, onOpenFind, onTabChange, onTogglePanel, panel, toolbarCell, toolbarCellBorders, }: {
10
11
  activeTab: SpreadsheetRibbonTabId;
11
12
  autoFilterActive?: boolean;
12
13
  can: SpreadsheetEditorCanCommands;
@@ -24,4 +25,5 @@ export declare function SpreadsheetEditorRibbon({ activeTab, autoFilterActive, c
24
25
  onTogglePanel: (panel: SpreadsheetWorkbookPanelView, trigger: HTMLButtonElement) => void;
25
26
  panel: SpreadsheetWorkbookPanelView | null;
26
27
  toolbarCell: Cell | null | undefined;
28
+ toolbarCellBorders?: SpreadsheetResolvedCellBorders;
27
29
  }): import("react").JSX.Element;
@@ -1,6 +1,19 @@
1
1
  import type { Cell } from '@fortune-sheet/core';
2
- export type SpreadsheetNumberFormatPreset = 'general' | 'number' | 'percent' | 'custom';
3
- type SpreadsheetNumberFormatChoice = Exclude<SpreadsheetNumberFormatPreset, 'custom'>;
2
+ export type SpreadsheetNumberFormatPreset = 'general' | 'number' | 'currency' | 'accounting' | 'percent' | 'date' | 'time' | 'scientific' | 'fraction' | 'text' | 'custom';
3
+ export type SpreadsheetNumberFormatChoice = Exclude<SpreadsheetNumberFormatPreset, 'custom'>;
4
+ export declare const spreadsheetNumberFormatPresetLabels: {
5
+ readonly general: "常规";
6
+ readonly number: "数字";
7
+ readonly currency: "货币";
8
+ readonly accounting: "会计专用";
9
+ readonly percent: "百分比";
10
+ readonly date: "短日期";
11
+ readonly time: "时间";
12
+ readonly scientific: "科学计数";
13
+ readonly fraction: "分数";
14
+ readonly text: "文本";
15
+ readonly custom: "自定义";
16
+ };
4
17
  export declare function spreadsheetNumberFormatPreset(formatCode?: string): SpreadsheetNumberFormatPreset;
5
18
  export declare function spreadsheetNumberFormatCode(preset: SpreadsheetNumberFormatChoice): string;
6
19
  export declare function spreadsheetNumberFormatValue(formatCode: string, cell?: Cell | null): NonNullable<Cell['ct']> & {
@@ -8,4 +21,3 @@ export declare function spreadsheetNumberFormatValue(formatCode: string, cell?:
8
21
  t: string;
9
22
  };
10
23
  export declare function adjustSpreadsheetNumberFormat(formatCode: string | undefined, direction: -1 | 1): string;
11
- export {};
@@ -0,0 +1,25 @@
1
+ import type { Sheet } from '@fortune-sheet/core';
2
+ export type XlsxCellBorderStyle = 'dashDot' | 'dashDotDot' | 'dashed' | 'dotted' | 'double' | 'hair' | 'medium' | 'mediumDashDot' | 'mediumDashDotDot' | 'mediumDashed' | 'slantDashDot' | 'thick' | 'thin';
3
+ export interface XlsxCellBorderLine {
4
+ color: string;
5
+ style: XlsxCellBorderStyle;
6
+ }
7
+ export interface XlsxCellBorder {
8
+ bottom?: XlsxCellBorderLine | null;
9
+ diagonal?: XlsxCellBorderLine | null;
10
+ diagonalDown?: boolean;
11
+ diagonalUp?: boolean;
12
+ left?: XlsxCellBorderLine | null;
13
+ right?: XlsxCellBorderLine | null;
14
+ top?: XlsxCellBorderLine | null;
15
+ }
16
+ export interface XlsxPositionedCellBorder {
17
+ border?: XlsxCellBorder;
18
+ column: number;
19
+ row: number;
20
+ }
21
+ export declare function collectXlsxCellBorders(sheet: Sheet): ReadonlyMap<string, XlsxCellBorder>;
22
+ export declare function fortuneBorderInfoFromXlsxCells(entries: readonly XlsxPositionedCellBorder[]): unknown[];
23
+ export declare function xlsxCellBorderKey(row: number, column: number): string;
24
+ export declare function xlsxCellBorderLineFromFortune(value: unknown): XlsxCellBorderLine | null | undefined;
25
+ export declare function fortuneBorderStyle(style: XlsxCellBorderStyle): string;
@@ -0,0 +1,21 @@
1
+ import type { Cell } from '@fortune-sheet/core';
2
+ import type { XlsxCellBorder } from './work-xlsx-cell-borders';
3
+ export declare class XlsxDirectCellStyleWriter {
4
+ private readonly styles;
5
+ private readonly fonts;
6
+ private readonly fills;
7
+ private readonly borders;
8
+ private readonly cellXfs;
9
+ private readonly generatedFonts;
10
+ private readonly generatedFills;
11
+ private readonly generatedBorders;
12
+ private readonly generatedStyles;
13
+ changed: boolean;
14
+ constructor(styles: Document);
15
+ styleId(baseStyleId: number, cell: Cell, border?: XlsxCellBorder): number;
16
+ private fontId;
17
+ private fillId;
18
+ private borderId;
19
+ private updateCounts;
20
+ }
21
+ export declare function hasXlsxDirectCellStyle(cell: Cell): boolean;
@@ -0,0 +1,17 @@
1
+ import type { XlsxCellBorderLine } from './work-xlsx-cell-borders';
2
+ export interface XlsxDirectAlignmentStyle {
3
+ horizontal?: 'center' | 'left' | 'right';
4
+ textRotation?: number;
5
+ vertical?: 'bottom' | 'center' | 'top';
6
+ wrapText?: boolean;
7
+ }
8
+ export declare function ensureXlsxStyleCollection(document: Document, name: string, anchors: readonly string[]): Element;
9
+ export declare function defaultXlsxFill(document: Document, patternType: string): Element;
10
+ export declare function defaultXlsxBorder(document: Document): Element;
11
+ export declare function setXlsxBorderLine(document: Document, border: Element, name: 'bottom' | 'diagonal' | 'left' | 'right' | 'top', line: XlsxCellBorderLine | null): void;
12
+ export declare function writeXlsxAlignment(document: Document, xf: Element, style: XlsxDirectAlignmentStyle): void;
13
+ export declare function setXlsxValueChild(document: Document, parent: Element, name: string, value: string, order: readonly string[]): void;
14
+ export declare function setXlsxColorChild(document: Document, parent: Element, color: string, order: readonly string[]): void;
15
+ export declare function setXlsxToggleChild(document: Document, parent: Element, name: string, enabled: boolean, order: readonly string[]): void;
16
+ export declare function setXlsxUnderlineChild(document: Document, parent: Element, enabled: boolean, order: readonly string[]): void;
17
+ export declare function xlsxRgbColor(value: unknown): string | null;
@@ -0,0 +1,13 @@
1
+ import type { Cell, Sheet } from '@fortune-sheet/core';
2
+ import { type XlsxCellBorder } from './work-xlsx-cell-borders';
3
+ import { type XlsxDirectCellStyleWriter } from './work-xlsx-cell-style-writer';
4
+ export { XlsxDirectCellStyleWriter } from './work-xlsx-cell-style-writer';
5
+ export interface XlsxDirectCellStyle {
6
+ border?: XlsxCellBorder;
7
+ column: number;
8
+ row: number;
9
+ style: Partial<Cell>;
10
+ }
11
+ export declare function readXlsxDirectCellStyles(worksheet: Document, styles: Document | null, theme?: Document | null): XlsxDirectCellStyle[];
12
+ export declare function sheetHasDirectCellStyles(sheet: Sheet): boolean;
13
+ export declare function writeXlsxDirectCellStyles(worksheet: Document, sheet: Sheet, styles: XlsxDirectCellStyleWriter): void;
@@ -0,0 +1,6 @@
1
+ export interface XlsxColorResolver {
2
+ indexed: readonly string[];
3
+ theme: readonly string[];
4
+ }
5
+ export declare function createXlsxColorResolver(styles: Document, theme: Document | null): XlsxColorResolver;
6
+ export declare function resolveXlsxColor(element: Element | undefined, resolver: XlsxColorResolver): string | undefined;
@@ -2,18 +2,20 @@ import type { Sheet } from '@fortune-sheet/core';
2
2
  import { OoxmlPackage } from './work-ooxml-package';
3
3
  import type { WorkSpreadsheetContent, WorkSpreadsheetDataValidationItem } from './work-types';
4
4
  import { type XlsxWorksheetChart } from './work-xlsx-charts';
5
+ import { type XlsxDirectCellStyle } from './work-xlsx-cell-styles';
5
6
  import { type FortuneConditionalFormatRule } from './work-xlsx-conditional-format';
6
7
  import { type XlsxWorksheetImage } from './work-xlsx-images';
7
8
  import { type XlsxManualPageBreaks } from './work-xlsx-page-breaks';
8
9
  import { type XlsxPageSetup } from './work-xlsx-page-setup';
9
10
  import { type XlsxProtectionFeatures } from './work-xlsx-protection';
10
- import type { XlsxWorksheetXmlScan } from './work-xlsx-worksheet-scan';
11
+ import { type XlsxWorksheetXmlScan } from './work-xlsx-worksheet-scan';
11
12
  type FrozenPane = NonNullable<Sheet['frozen']>;
12
13
  export interface XlsxDataValidation {
13
14
  references: string[];
14
15
  item: FortuneDataValidationItem;
15
16
  }
16
17
  export interface XlsxSheetFeatures {
18
+ directCellStyles: XlsxDirectCellStyle[];
17
19
  frozen?: FrozenPane;
18
20
  validations: XlsxDataValidation[];
19
21
  conditionalFormats: FortuneConditionalFormatRule[];
@@ -1,4 +1,5 @@
1
1
  export interface XlsxWorksheetXmlScan {
2
+ hasDirectCellStyles: boolean;
2
3
  hasDiagnosticFeatures: boolean;
3
4
  hasFormulaFeatures: boolean;
4
5
  hasImportedFeatures: boolean;
Binary file
package/dist/styles.css CHANGED
@@ -15010,6 +15010,123 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
15010
15010
  color: currentColor;
15011
15011
  }
15012
15012
 
15013
+ .work-spreadsheet-cell-style-panel {
15014
+ gap: 10px;
15015
+ width: min(440px, 100vw - 32px);
15016
+ padding: 9px;
15017
+ display: grid;
15018
+ }
15019
+
15020
+ .work-spreadsheet-cell-style-group {
15021
+ border: 0;
15022
+ gap: 4px;
15023
+ min-width: 0;
15024
+ margin: 0;
15025
+ padding: 0;
15026
+ display: grid;
15027
+ }
15028
+
15029
+ .work-spreadsheet-cell-style-group + .work-spreadsheet-cell-style-group {
15030
+ border-top: 1px solid var(--a3s-line);
15031
+ padding-top: 8px;
15032
+ }
15033
+
15034
+ .work-spreadsheet-cell-style-group-label {
15035
+ color: var(--a3s-faint);
15036
+ padding-inline: 2px;
15037
+ font-size: 11px;
15038
+ font-weight: 650;
15039
+ line-height: 16px;
15040
+ }
15041
+
15042
+ .work-spreadsheet-cell-style-grid {
15043
+ grid-template-columns: repeat(3, minmax(0, 1fr));
15044
+ gap: 4px;
15045
+ display: grid;
15046
+ }
15047
+
15048
+ .work-spreadsheet-cell-style-grid > button {
15049
+ min-width: 0;
15050
+ min-height: 64px;
15051
+ color: var(--a3s-muted);
15052
+ font: inherit;
15053
+ text-align: left;
15054
+ cursor: pointer;
15055
+ background: none;
15056
+ border: 1px solid #0000;
15057
+ border-radius: 7px;
15058
+ outline: 0;
15059
+ align-content: start;
15060
+ gap: 4px;
15061
+ padding: 4px;
15062
+ display: grid;
15063
+ }
15064
+
15065
+ .work-spreadsheet-cell-style-preview {
15066
+ border: 1px solid color-mix(in srgb, currentcolor 28%, var(--a3s-line));
15067
+ text-overflow: ellipsis;
15068
+ white-space: nowrap;
15069
+ border-radius: 4px;
15070
+ align-items: center;
15071
+ min-width: 0;
15072
+ height: 29px;
15073
+ padding-inline: 7px;
15074
+ line-height: 1;
15075
+ display: flex;
15076
+ overflow: hidden;
15077
+ }
15078
+
15079
+ .work-spreadsheet-cell-style-description {
15080
+ min-width: 0;
15081
+ color: var(--a3s-faint);
15082
+ -webkit-line-clamp: 2;
15083
+ -webkit-box-orient: vertical;
15084
+ font-size: 10px;
15085
+ line-height: 13px;
15086
+ display: -webkit-box;
15087
+ overflow: hidden;
15088
+ }
15089
+
15090
+ .work-spreadsheet-cell-style-grid > button:hover:not(:disabled), .work-spreadsheet-cell-style-grid > button:focus-visible {
15091
+ border-color: color-mix(in srgb,
15092
+ var(--work-office-control-accent, #159469) 38%,
15093
+ var(--a3s-line));
15094
+ background: var(--a3s-panel-soft);
15095
+ }
15096
+
15097
+ .work-spreadsheet-cell-style-grid > button:focus-visible {
15098
+ box-shadow: 0 0 0 2px
15099
+ color-mix(in srgb,
15100
+ var(--work-office-control-accent, #159469) 18%,
15101
+ transparent);
15102
+ }
15103
+
15104
+ .work-spreadsheet-cell-style-grid > button[aria-checked="true"] {
15105
+ border-color: color-mix(in srgb,
15106
+ var(--work-office-control-accent, #159469) 58%,
15107
+ var(--a3s-line));
15108
+ background: color-mix(in srgb,
15109
+ var(--work-office-control-accent, #159469) 7%,
15110
+ var(--a3s-panel));
15111
+ }
15112
+
15113
+ .work-spreadsheet-cell-style-grid > button:disabled {
15114
+ cursor: not-allowed;
15115
+ opacity: .42;
15116
+ }
15117
+
15118
+ @media (width <= 520px) {
15119
+ .work-spreadsheet-cell-style-panel {
15120
+ width: min(328px, 100vw - 24px);
15121
+ max-height: calc(100dvh - 24px);
15122
+ padding: 8px;
15123
+ }
15124
+
15125
+ .work-spreadsheet-cell-style-grid {
15126
+ grid-template-columns: repeat(2, minmax(0, 1fr));
15127
+ }
15128
+ }
15129
+
15013
15130
  .work-spreadsheet-border-split-root {
15014
15131
  border-radius: 6px;
15015
15132
  flex: none;
@@ -4011,8 +4011,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
4011
4011
  'rowBreaks',
4012
4012
  'colBreaks'
4013
4013
  ]);
4014
- const WORKSHEET_SCAN_PATTERN = /<(?:[A-Za-z_][\w.-]*:)?(?:(cols|f|pane|dataValidation|conditionalFormatting|sheetProtection|protectedRange|rowBreaks|colBreaks|pageSetup|pageMargins|printOptions|headerFooter|pageSetUpPr|drawing)(?=[\s/>])|(row)(?=[\s/>])[^>]*\s(?:collapsed|customFormat|customHeight|hidden|ht|outlineLevel|thickBot|thickTop)\s*=)/g;
4014
+ const WORKSHEET_SCAN_PATTERN = /<(?:[A-Za-z_][\w.-]*:)?(?:(cols|f|pane|dataValidation|conditionalFormatting|sheetProtection|protectedRange|rowBreaks|colBreaks|pageSetup|pageMargins|printOptions|headerFooter|pageSetUpPr|drawing)(?=[\s/>])|(row)(?=[\s/>])[^>]*\s(?:collapsed|customFormat|customHeight|hidden|ht|outlineLevel|thickBot|thickTop)\s*=|(c)(?=[\s/>])[^>]*\ss\s*=)/g;
4015
4015
  function scanXlsxWorksheetXml(source) {
4016
+ let hasDirectCellStyles = false;
4016
4017
  let hasDiagnosticFeatures = false;
4017
4018
  let hasFormulaFeatures = false;
4018
4019
  let hasImportedFeatures = false;
@@ -4020,15 +4021,17 @@ https://github.com/nodeca/pako/blob/main/LICENSE
4020
4021
  WORKSHEET_SCAN_PATTERN.lastIndex = 0;
4021
4022
  for(let match = WORKSHEET_SCAN_PATTERN.exec(source); match;){
4022
4023
  const element = match[1];
4023
- if (match[2] || 'cols' === element) requiresSheetJsCellStyles = true;
4024
+ if (match[3]) hasDirectCellStyles = true;
4025
+ if (match[2] || match[3] || 'cols' === element) requiresSheetJsCellStyles = true;
4024
4026
  if ('f' === element) hasFormulaFeatures = true;
4025
4027
  if (element && IMPORTED_WORKSHEET_ELEMENTS.has(element)) hasImportedFeatures = true;
4026
4028
  if (element && DIAGNOSTIC_WORKSHEET_ELEMENTS.has(element)) hasDiagnosticFeatures = true;
4027
- if (hasDiagnosticFeatures && hasFormulaFeatures && hasImportedFeatures && requiresSheetJsCellStyles) break;
4029
+ if (hasDirectCellStyles && hasDiagnosticFeatures && hasFormulaFeatures && hasImportedFeatures && requiresSheetJsCellStyles) break;
4028
4030
  match = WORKSHEET_SCAN_PATTERN.exec(source);
4029
4031
  }
4030
4032
  WORKSHEET_SCAN_PATTERN.lastIndex = 0;
4031
4033
  return {
4034
+ hasDirectCellStyles,
4032
4035
  hasDiagnosticFeatures,
4033
4036
  hasFormulaFeatures,
4034
4037
  hasImportedFeatures,
@@ -4123,6 +4126,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
4123
4126
  }
4124
4127
  };
4125
4128
  const PLAIN_WORKSHEET_SCAN = {
4129
+ hasDirectCellStyles: false,
4126
4130
  hasDiagnosticFeatures: false,
4127
4131
  hasFormulaFeatures: false,
4128
4132
  hasImportedFeatures: false,