xiaodao-spreader 0.1.28 → 0.1.30

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 CHANGED
@@ -8,7 +8,7 @@
8
8
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-3178C6.svg)](https://www.typescriptlang.org/)
9
9
  [![Vite](https://img.shields.io/badge/Vite-5.0+-646CFF.svg)](https://vitejs.dev/)
10
10
 
11
- A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an Excel-like editing experience to the web.
11
+ A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. It supports full cell editing, formula evaluation with relative/absolute/mixed references, clipboard cut/copy/paste, merge cells, frozen panes, number formatting, borders, find & replace, sorting, and auto-fill: all rendered on a single virtualized canvas with smooth scrolling across hundreds of thousands of rows. The pure-logic core (formula engine, sort, find-replace, auto-fill) is fully decoupled from Vue/Canvas and unit-tested, making it easy to embed or reuse across projects.
12
12
 
13
13
  ![Preview](./img/preview.png)
14
14
 
@@ -17,37 +17,39 @@ A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an
17
17
  ## Features
18
18
 
19
19
  ### Core Spreadsheet
20
- - **Dynamic Sheet Expansion** — Excel-like dynamic row/column expansion; default 26 columns (A-Z) × 200 rows, automatically expands when scrolling near boundaries, inputting at edges, pasting beyond current range, or inserting rows/columns that would push data out of bounds
21
- - **Canvas 2D Rendering** — High-DPI aware with DPR scaling, virtual viewport rendering for dynamically-sized sheets
22
- - **Multi-Sheet Workbook** — Tab bar with add, rename, duplicate, delete, reorder
23
- - **Formula Engine** — `=SUM()`, `=AVERAGE()`, `=COUNT()`, `=IF()`, `=VLOOKUP()`, `=CONCATENATE()` with dependency tracking and circular-reference detection; toolbar and context menu provide one-click sum/average/count
24
- - **Merge Cells** — Merge & Center, Merge Across, Unmerge; merged-region borders stored at the anchor, shared borders resolved at render time
25
- - **Freeze Panes** — Pin frozen top rows / left columns so they keep visible while the body scrolls. The toolbar "Freeze Panes" dropdown exposes *Freeze Panes* (freezes at the top-left corner of the current selection / active cell — Excel's "Freeze Panes" behavior), *Freeze First Row*, *Freeze First Column*, and *Unfreeze* (shown only when a pane is already frozen, replacing the "Freeze Panes" entry). Per-sheet view state (`freeze: { rows, cols }`) persisted through v-model; merged cells straddling the freeze line are handled correctly — only the frozen portion stays pinned, the rest scrolls away
26
- - **Rich Cell Formatting** — Font family, font size (5–72), bold, italic, underline, strikethrough, text color, fill color, horizontal & vertical alignment, wrap text
27
- - **Borders** — Top / bottom / left / right / outside / all / none with 5 predefined styles and custom color; stored in a dedicated border pool, shared borders resolved at render time
28
- - **Undo / Redo** — Full state snapshots for cells, column widths, and row heights (50 steps)
29
- - **Format Painter** — Copy & apply cell formatting across ranges
30
- - **Number Format** — Excel-style number formatting (General / Text / Number / Currency / Accounting / Percent / Scientific / Date / Time / DateTime / Duration) with a custom format dialog; display-only, never mutates the stored cell value
31
- - **Smart Data Recognition** — Typing `100%`, `1,234`, `¥1,234.56` auto-converts the text to a number and applies the matching format; common date/time text auto-converts to dates — matching Excel input behavior
32
- - **Sorting & Sort Warning** — Sort any column by its **displayed content** (numbers / dates / text); sorting moves data only, never cell styles; ranges containing merged cells or formulas are auto-disabled; when adjacent data sits outside the selection, an Excel-style **Sort Warning** dialog lets you choose "Expand the selection" or "Sort the current selection only"
33
- - **Find & Replace** — Open via the toolbar find button or `Ctrl/Cmd+F` (also `Ctrl/Cmd+H`); three scopes — current sheet / entire workbook / current selection; match case and match entire cell; highlights all matches and locates the active one with wrap-around navigation; single and replace-all both integrate with undo/redo, mutating only the raw `value` (always kept a string), never format / border / merge
20
+ - **Dynamic Sheet Expansion**: Excel-like dynamic row/column expansion; default 26 columns (A-Z) × 200 rows, automatically expands when scrolling near boundaries, inputting at edges, pasting beyond current range, or inserting rows/columns that would push data out of bounds
21
+ - **Canvas 2D Rendering**: High-DPI aware with DPR scaling, virtual viewport rendering for dynamically-sized sheets
22
+ - **Multi-Sheet Workbook**: Tab bar with add, rename, duplicate, delete, reorder
23
+ - **Formula Engine**: `=SUM()`, `=AVERAGE()`, `=COUNT()`, `=IF()`, `=VLOOKUP()`, `=CONCATENATE()` with dependency tracking and circular-reference detection; toolbar and context menu provide one-click sum/average/count
24
+ - **Merge Cells**: Merge & Center, Merge Across, Unmerge; merged-region borders stored at the anchor, shared borders resolved at render time
25
+ - **Freeze Panes**: Pin frozen top rows / left columns so they keep visible while the body scrolls. The toolbar "Freeze Panes" dropdown exposes *Freeze Panes* (freezes at the top-left corner of the current selection / active cell: Excel's "Freeze Panes" behavior), *Freeze First Row*, *Freeze First Column*, and *Unfreeze* (shown only when a pane is already frozen, replacing the "Freeze Panes" entry). Per-sheet view state (`freeze: { rows, cols }`) persisted through v-model; merged cells straddling the freeze line are handled correctly: only the frozen portion stays pinned, the rest scrolls away
26
+ - **Rich Cell Formatting**: Font family, font size (5–72), bold, italic, underline, strikethrough, text color, fill color, horizontal & vertical alignment, wrap text
27
+ - **Borders**: Top / bottom / left / right / outside / all / none with 5 predefined styles and custom color; stored in a dedicated border pool, shared borders resolved at render time
28
+ - **Undo / Redo**: Full state snapshots for cells, column widths, and row heights (50 steps)
29
+ - **Format Painter**: Copy & apply cell formatting across ranges
30
+ - **Number Format**: Excel-style number formatting (General / Text / Number / Currency / Accounting / Percent / Scientific / Date / Time / DateTime / Duration) with a custom format dialog; display-only, never mutates the stored cell value
31
+ - **Smart Data Recognition**: Typing `100%`, `1,234`, `¥1,234.56` auto-converts the text to a number and applies the matching format; common date/time text auto-converts to dates: matching Excel input behavior
32
+ - **Sorting & Sort Warning**: Sort any column by its **displayed content** (numbers / dates / text); sorting moves data only, never cell styles; ranges containing merged cells or formulas are auto-disabled; when adjacent data sits outside the selection, an Excel-style **Sort Warning** dialog lets you choose "Expand the selection" or "Sort the current selection only"
33
+ - **Auto Filter (AutoFilter)**: Excel-style auto filter on a normal range. Enable via the toolbar **Data → Filter** or `Ctrl+Shift+L`; select a data cell (or a single-row multi-column range) and the filter is created by intelligently probing the contiguous data region **downward** from that header row. Each column header shows a filter drop-down arrow; opening it reveals the filter panel (values / text / number / date / search / blanks / multi-column AND). Clearing one column's criteria clears only that column; removing the AutoFilter clears everything. Only columns inside the Filter Range get an arrow; selecting a single merged cell with no active filter disables the filter button — *see [Auto Filter (AutoFilter)](#auto-filter-autofilter)*
34
+ - **Find & Replace**: Open via the toolbar find button or `Ctrl/Cmd+F` (also `Ctrl/Cmd+H`); three scopes: current sheet / entire workbook / current selection; match case and match entire cell; highlights all matches and locates the active one with wrap-around navigation; single and replace-all both integrate with undo/redo, mutating only the raw `value` (always kept a string), never format / border / merge
35
+ - **Auto Fill (Fill Handle)**: Excel-style fill handle at the bottom-right corner of the active selection. Drag it up/down/left/right to fill cells: single values copy, number/date/text-number sequences auto-continue (e.g. `1,2 → 3,4,5`), formula references adjust per relative/absolute/mixed rules (e.g. `=A1*2` → `=A2*2`), and source `styleId` is reused via the style pool. Live preview during drag, edge auto-scroll, dynamic sheet expansion, freeze-pane compatibility, and a single undo step per operation: *see [Auto Fill](#auto-fill)*
34
36
 
35
37
  ### Interaction
36
- - **Smart Selection** — Click, drag, Shift+Click, row/column header select, corner-cell select-all
37
- - **Double-Click Editing** — Inline cell editor with `<textarea>` for multi-line input
38
- - **Formula Bar** — Dedicated input bar with cell label and live formula display
39
- - **Full Keyboard Navigation** — Arrow keys, Tab, Enter, Home, End, Ctrl+Home, Ctrl+End
40
- - **Context Menus** — Context-aware menus for cells, rows, columns, sheet tabs, with nested submenus
41
- - **Row / Column Operations** — Insert, delete, cut, copy, paste via right-click menu
42
- - **Column Width / Row Height** — Drag-to-resize with live preview and double-click auto-fit
43
- - **Touch Support** — Swipe scrolling, double-tap to edit
44
- - **Responsive** — ResizeObserver for dynamic container sizing
38
+ - **Smart Selection**: Click, drag, Shift+Click, row/column header select, corner-cell select-all
39
+ - **Double-Click Editing**: Inline cell editor with `<textarea>` for multi-line input
40
+ - **Formula Bar**: Dedicated input bar with cell label and live formula display
41
+ - **Full Keyboard Navigation**: Arrow keys, Tab, Enter, Home, End, Ctrl+Home, Ctrl+End
42
+ - **Context Menus**: Context-aware menus for cells, rows, columns, sheet tabs, with nested submenus
43
+ - **Row / Column Operations**: Insert, delete, cut, copy, paste via right-click menu
44
+ - **Column Width / Row Height**: Drag-to-resize with live preview and double-click auto-fit
45
+ - **Touch Support**: Swipe scrolling, double-tap to edit
46
+ - **Responsive**: ResizeObserver for dynamic container sizing
45
47
 
46
48
  ### Visual
47
- - **Light / Dark Theme** — Full color palette with 50+ CSS custom properties
48
- - **Internationalization** — English & Chinese (zh-CN) out of the box
49
- - **Overflow Toolbar** — Responsive toolbar that automatically collapses overflow buttons into a dropdown menu
50
- - **Custom Scrollbars** — Native-styled scrollbars with arrow buttons and draggable thumbs
49
+ - **Light / Dark Theme**: Full color palette with 50+ CSS custom properties
50
+ - **Internationalization**: English & Chinese (zh-CN) out of the box
51
+ - **Overflow Toolbar**: Responsive toolbar that automatically collapses overflow buttons into a dropdown menu
52
+ - **Custom Scrollbars**: Native-styled scrollbars with arrow buttons and draggable thumbs
51
53
 
52
54
  ---
53
55
 
@@ -131,10 +133,10 @@ const myData = ref<SheetModelData[]>([
131
133
  | `data` (v-model) | `SheetModelData[]` | `[]` | Multi-sheet data (two-way binding) |
132
134
  | `rowCount` | `number` | `200` | Initial rows per sheet (can be exceeded dynamically) |
133
135
  | `colCount` | `number` | `26` | Initial columns per sheet (can be exceeded dynamically) |
134
- | `width` | `number \| string` | — | Component width (pixels; omit or pass `string` for responsive) |
135
- | `height` | `number \| string` | — | Component height (pixels; omit or pass `string` for responsive) |
136
+ | `width` | `number \| string` | - | Component width (pixels; omit or pass `string` for responsive) |
137
+ | `height` | `number \| string` | - | Component height (pixels; omit or pass `string` for responsive) |
136
138
  | `theme` | `'light' \| 'dark'` | `'light'` | Theme mode |
137
- | `locale` | `string` | `'zh-CN'` | Language — `'zh-CN'` \| `'en-US'` |
139
+ | `locale` | `string` | `'zh-CN'` | Language: `'zh-CN'` \| `'en-US'` |
138
140
 
139
141
  ---
140
142
 
@@ -164,12 +166,12 @@ interface SheetModelData {
164
166
  }
165
167
  ```
166
168
 
167
- - **`styles`**: Style pool — `styles[0]` is always the default empty style `{}`. Cells reference styles by index (`styleId`).
168
- - **`borders`**: Border pool — `borders[0]` is always the default empty border `{}`. Styles reference borders by index (`borderId`); auto-migrated from legacy inline border props when omitted.
169
+ - **`styles`**: Style pool: `styles[0]` is always the default empty style `{}`. Cells reference styles by index (`styleId`).
170
+ - **`borders`**: Border pool: `borders[0]` is always the default empty border `{}`. Styles reference borders by index (`borderId`); auto-migrated from legacy inline border props when omitted.
169
171
  - **`cells`**: Key is `"col,row"` (e.g., `"0,0"` for cell A1). `styleId` references into the `styles` array; `styleId=0` or omitted means default style.
170
172
  - **`merges`**: Merge cell definitions, keyed by merge anchor cell.
171
- - **`freeze`**: View state for frozen panes — `{ rows, cols }` freezes the top `rows` rows and the left `cols` columns; `{ rows: 0, cols: 0 }` means no freeze. Persisted per sheet and restored on sheet switch.
172
- - **`colWidths` / `rowHeights`**: Sparse maps — only stores non-default values.
173
+ - **`freeze`**: View state for frozen panes: `{ rows, cols }` freezes the top `rows` rows and the left `cols` columns; `{ rows: 0, cols: 0 }` means no freeze. Persisted per sheet and restored on sheet switch.
174
+ - **`colWidths` / `rowHeights`**: Sparse maps: only stores non-default values.
173
175
 
174
176
  ### Type Exports
175
177
 
@@ -203,21 +205,26 @@ import { StylePool, resolveStyle, migrateCells, cloneCells } from 'xiaodao-sprea
203
205
 
204
206
  ```
205
207
  src/
206
- ├── index.ts # Library entry — re-exports from spreader/
208
+ ├── index.ts # Library entry: re-exports from spreader/
207
209
  ├── App.vue # Demo application
208
210
  └── components/
209
211
  └── spreader/
210
- ├── index.ts # Unified export — component + types (barrel)
212
+ ├── index.ts # Unified export: component + types (barrel)
211
213
  ├── components/
212
- │ ├── spreader.vue # Entry component — template + style + composition
214
+ │ ├── spreader.vue # Entry component: template + style + composition
213
215
  │ ├── toolbar.vue # Toolbar with overflow dropdown
214
216
  │ ├── tabbar.vue # Sheet tab bar
215
217
  │ ├── dropdown.vue # Generic dropdown component
218
+ │ ├── find-replace-bar.vue # Find/replace bar UI
216
219
  │ └── pickers/
217
- │ ├── colorPicker.vue
218
- │ ├── borderPicker.vue
219
- │ ├── mergePicker.vue
220
- │ └── numberFormatDialog.vue
220
+ │ ├── colorPicker.vue # Text & fill color picker
221
+ │ ├── borderPicker.vue # Border picker
222
+ │ ├── mergePicker.vue # Merge cell picker
223
+ │ ├── numberFormatDialog.vue # Number format custom dialog
224
+ │ ├── sortPicker.vue # Sort dropdown
225
+ │ ├── sortConfirmDialog.vue # Excel-style sort warning dialog
226
+ │ ├── calcPicker.vue # Sum / average / count picker
227
+ │ └── insertFunctionDialog.vue # Insert function dialog
221
228
  ├── composables/
222
229
  │ ├── core-state.ts # Props, cells/merges/selection, font metrics, navigation
223
230
  │ ├── undo-styles.ts # Undo/redo, format painter, font/alignment/color
@@ -233,6 +240,8 @@ src/
233
240
  ├── border-resolve.ts # Shared-border conflict resolution (resolveSharedBorder)
234
241
  ├── formula.ts # Formula engine (parse, evaluate, deps, cache)
235
242
  ├── find-replace-core.ts # Find/replace pure algorithms (zero Vue deps, unit-testable)
243
+ ├── sort-core.ts # Sort pure algorithms (zero Vue deps, unit-testable)
244
+ ├── autofill.ts # Auto-fill pure engine (pattern inference, fill handle logic, zero Vue deps)
236
245
  ├── number-format.ts # Number format engine (Excel-style display formatting)
237
246
  ├── theme.ts # Theme CSS variable construction
238
247
  └── utils.ts # Pure utilities (col label, hit test, resolve size)
@@ -284,6 +293,7 @@ src/
284
293
  | `Ctrl+C` / `Ctrl+X` / `Ctrl+V` | Copy / Cut / Paste |
285
294
  | `Ctrl+Z` / `Ctrl+Y` | Undo / Redo |
286
295
  | `Ctrl+A` | Select all |
296
+ | `Ctrl+Shift+L` | Toggle Auto Filter |
287
297
 
288
298
  ### Formatting
289
299
 
@@ -314,8 +324,8 @@ src/
314
324
 
315
325
  The `FormulaDeps` class maintains a bidirectional dependency graph:
316
326
 
317
- - **Forward**: `formulaKey` → `[depKey, ...]` — which cells a formula references
318
- - **Reverse**: `depKey` → `Set<formulaKey>` — which formulas depend on a cell
327
+ - **Forward**: `formulaKey` → `[depKey, ...]`: which cells a formula references
328
+ - **Reverse**: `depKey` → `Set<formulaKey>`: which formulas depend on a cell
319
329
 
320
330
  When a cell changes, dirty flags propagate through the reverse graph. Circular references are detected via a separate `inProgress` set and return `#ERROR`.
321
331
 
@@ -327,7 +337,7 @@ When a cell changes, dirty flags propagate through the reverse graph. Circular r
327
337
 
328
338
  ## Number Format
329
339
 
330
- An Excel-style number formatting engine (`spreader/core/number-format.ts`) that controls **how a cell value is displayed** — it never mutates the stored `value` (which always remains a raw string).
340
+ An Excel-style number formatting engine (`spreader/core/number-format.ts`) that controls **how a cell value is displayed**: it never mutates the stored `value` (which always remains a raw string).
331
341
 
332
342
  ### Categories
333
343
 
@@ -346,24 +356,123 @@ An Excel-style number formatting engine (`spreader/core/number-format.ts`) that
346
356
  | Time | `13:45:30` | `h:mm:ss` |
347
357
  | Date & Time | `2026年8月24日 13:45:30` | `yyyy"年"m"月"d"日" h:mm:ss` |
348
358
  | Duration | `26:30:00` | `[h]:mm:ss` |
349
- | Custom | User-defined Excel-style code | — |
359
+ | Custom | User-defined Excel-style code | - |
350
360
 
351
361
  ### How it works
352
362
 
353
363
  - **Storage**: the format code is stored per-cell in the resolved style's `numberFormat` property (a string). Omitting the property (or empty string) means General.
354
364
  - **UI**: the toolbar number-format dropdown applies presets to the current selection; the **「Format…」(格式…)** item opens `numberFormatDialog.vue` for a custom code, decimals, and thousands separator.
355
365
  - **Display**: `formatNumber(value, format, locale)` parses the code (cached), applies thousands separators / decimals / percent scaling / date-serial conversion, and returns the display string. Invalid date/duration serials render as `###`.
356
- - **Alignment**: numeric formats default to right-aligned; Text and General-with-non-numeric keep left alignment — matching Excel semantics.
366
+ - **Alignment**: numeric formats default to right-aligned; Text and General-with-non-numeric keep left alignment: matching Excel semantics.
357
367
  - **i18n**: currency symbol (`¥` / `$`), month and weekday names follow the `locale` prop.
358
368
 
359
369
  ---
360
370
 
371
+ ## Auto Fill
372
+
373
+ An Excel-style fill-handle mechanism (`spreader/core/autofill.ts` pure engine + `composables/interactions.ts` canvas/interaction layer). Drag the small square at the bottom-right corner of the active selection to fill cells: no DOM handles, all drawn on Canvas.
374
+
375
+ ### Fill Patterns
376
+
377
+ | Source values | Fill behavior | Example |
378
+ |---------------|---------------|---------|
379
+ | Single number | Copy | `42 → 42, 42, 42` |
380
+ | Single text | Copy | `foo → foo, foo, foo` |
381
+ | Single date | +1 day | `2026-01-01 → 2026-01-02, 2026-01-03` |
382
+ | Two+ numbers, constant diff | Linear series | `1,2 → 3,4,5` · `2,4 → 6,8,10` |
383
+ | Two+ dates, constant diff | Date series | `2026-01-01, 2026-01-03 → 2026-01-05, 2026-01-07` |
384
+ | Text + number, same prefix | Text-number series | `Item1,Item2 → Item3,Item4` |
385
+ | Two single letters | Alpha series | `A,B → C,D,E` |
386
+ | Formula | Reference translation | `=A1*2` → `=A2*2, =A3*2` |
387
+ | Multi-column / multi-row block | Per-column pattern inference | `A1:B2=[[1,10],[2,20]] → [[3,30],[4,40]]` |
388
+
389
+ ### Formula Reference Rules
390
+
391
+ Fill-handle translation reuses the existing `shiftFormulaRefs()`: no second formula engine:
392
+
393
+ | Reference type | Syntax | Fill behavior |
394
+ |----------------|--------|---------------|
395
+ | Relative | `=A1` | Row/col offset with the target cell |
396
+ | Absolute | `=$A$1` | Stays unchanged |
397
+ | Mixed (col absolute) | `=$A1` | Row adjusts, column locked |
398
+ | Mixed (row absolute) | `=A$1` | Column adjusts, row locked |
399
+ | Composite | `=B1*$F$1` | `B1` adjusts, `$F$1` locked |
400
+
401
+ ### Interaction
402
+
403
+ - **Fill handle**: 6px square at the selection's bottom-right corner, theme primary color; turns grey when the selection partially intersects a merge (fill disabled).
404
+ - **Hit-test**: independent `isFillHandleHit()` runs after resize handles and before cell click; hover shows `crosshair` cursor.
405
+ - **State machine**: a dedicated `autofilling` state prevents selection drag / editor / resize from starting; ESC cancels mid-drag.
406
+ - **Live preview**: the target range renders as a semi-transparent dashed rectangle during drag; the source selection stays put; no cell data is mutated until `mouseup`.
407
+ - **Edge auto-scroll**: dragging within 30px of the viewport edge starts a single `requestAnimationFrame` loop that scrolls and updates the target range; stopped on `mouseup` / ESC / pointercancel.
408
+ - **Dynamic expansion**: fills beyond the current `rowCount`/`colCount` trigger `ensureCapacity()` first, folded into the same undo step.
409
+ - **Selection after fill**: the selection updates to the union of source + target range.
410
+ - **Freeze panes**: all coordinates flow through `cellToScreenRect` / `screenToCell`, so the handle, hit-test, preview, and final fill work across frozen and body regions alike.
411
+ - **Merge compatibility**: partially intersecting merges disable the fill handle (conservative first version); whole-block merges fill correctly.
412
+ - **Touch**: shares the same `autoFillState` and `applyAutoFill` path as mouse: no separate implementation.
413
+
414
+ ### Architecture
415
+
416
+ ```
417
+ Fill Handle UI (drawFillHandle)
418
+ ↓
419
+ Unified Hit-Test (isFillHandleHit)
420
+ ↓
421
+ AutoFill Drag State (autoFillState)
422
+ ↓
423
+ Target Range Calculation (computeTargetRange)
424
+ ↓
425
+ Pure AutoFill Pattern Engine (core/autofill.ts)
426
+ ↓
427
+ Formula Translation (shiftFormulaRefs)
428
+ ↓
429
+ Style / Border / Cell Mutation (applyAutoFill)
430
+ ↓
431
+ Undo Snapshot (saveUndo, one step per drag)
432
+ ↓
433
+ scheduleRender()
434
+ ```
435
+
436
+ The pure engine (`core/autofill.ts`) has zero Vue/Canvas dependencies and is fully unit-tested in `test/autofill.test.ts` (54 cases), making it reusable for `Ctrl+D`/`Ctrl+R`, paste-fill, right-click fill, and programmatic auto-fill.
437
+
438
+ ---
439
+
440
+ ## Auto Filter (AutoFilter)
441
+
442
+ An Excel-style auto filter on a normal range: filtering is a **Sheet-level feature bound to a data Range**, not a per-column-header filter. The header arrows are drawn on the Canvas (no DOM); the filter panel uses Vue DOM.
443
+
444
+ ### Enable & toggle
445
+
446
+ - Toolbar **Data → Filter** or `Ctrl+Shift+L` invokes `toggleAutoFilter()`.
447
+ - **Not enabled → create**: select a data cell or a single-row multi-column range, then the filter is created by probing the contiguous data region **downward** from that header row; a completely empty sheet creates no invalid filter.
448
+ - **Enabled → remove entirely**: restores hidden rows, clears all column criteria, and removes header arrows. The toolbar button's highlighted state exactly matches its click behavior (highlight = enabled, click = turn off).
449
+ - Selecting a single merged cell (a multi-cell merge) with no active filter disables the filter button (a merged cell cannot serve as a valid data-region header).
450
+
451
+ ### Header arrow
452
+
453
+ - Shown only on the header row of the Filter Range and only for columns inside the range; not shown when disabled or outside the range.
454
+ - Styled as a "drop-down button with background on the right border": grey background + dark arrow when not filtered, blue background + white arrow when filtered (distinguishes "enabled" from "this column filtered").
455
+ - Clicking the arrow opens only the filter panel, never a normal selection; with frozen panes the arrow renders correctly on the frozen header.
456
+
457
+ ### Filter panel
458
+
459
+ Reuses the existing engine: the title shows the column's header text (not the column letter); unchecking items takes effect only on **OK**, never immediately. Supports value / text / number / date filters, search, blanks, and multi-column AND; candidate values come from the corresponding column inside the Filter Range, generated from already-filtered rows when other columns are filtered (Excel cascading behavior).
460
+
461
+ ### Compatibility
462
+
463
+ - Hidden rows use the existing `filteredOutRows` + visible-row mapping; rows are **never deleted or copied**.
464
+ - Row/column insert/delete adjust the range via `adjustFilterRows` / `adjustFilterCols`; deleting the entire filter region auto-cancels the filter.
465
+ - After sorting, filtered rows are recomputed; original row indices are preserved.
466
+ - Persisted through v-model, fully retaining range, arrows, criteria, and hidden rows.
467
+
468
+ ---
469
+
361
470
  ## Border System
362
471
 
363
472
  A dedicated border storage & rendering mechanism (`spreader/core/border-pool.ts` + `border-resolve.ts`).
364
473
 
365
474
  - **Dedicated border pool**: each sheet maintains a `borders: BorderStyle[]` pool (`borders[0]` is always the empty border `{}`); styles reference borders by index (`borderId`), and identical borders are deduplicated.
366
- - **Shared-border resolution**: adjacent cells' shared border is resolved at render time via `resolveSharedBorder()` — wider wins, then the first side on equal width; setting a border no longer mutates neighboring cells.
475
+ - **Shared-border resolution**: adjacent cells' shared border is resolved at render time via `resolveSharedBorder()`: wider wins, then the first side on equal width; setting a border no longer mutates neighboring cells.
367
476
  - **Merged cells**: merged-region borders are stored at the anchor (top-left); internal borders are masked, outer boundaries are resolved segment-wise against neighbors, and the four corners fill in corner blocks.
368
477
  - **Legacy compatibility**: legacy inline border props (`borderTopWidth`, etc., deprecated) are auto-migrated via `migrateBordersInStyles()` on load.
369
478
 
@@ -460,18 +569,19 @@ The project includes a GitHub Actions workflow (`.github/workflows/publish.yml`)
460
569
  ### Near-term
461
570
 
462
571
  - [x] More formulas: `COUNT`, `IF`, `VLOOKUP`, `CONCATENATE`
463
- - [ ] Cell background color picker
464
- - [x] Number format (currency, percentage, date, number of decimals) — *see [Number Format](#number-format)*
572
+ - [x] Cell background color picker
573
+ - [x] Number format (currency, percentage, date, number of decimals): *see [Number Format](#number-format)*
465
574
  - [ ] Conditional formatting rules
466
- - [ ] Auto-fill drag handle
467
- - [x] Find & Replace — *see [Find & Replace](#find--replace)*
575
+ - [x] Auto-fill drag handle: *see [Auto Fill](#auto-fill)*
576
+ - [x] Find & Replace: *see [Find & Replace](#find--replace)*
468
577
 
469
578
  ### Mid-term
470
579
 
471
- - [x] Frozen panes (freeze rows/columns) — *see [Freeze Panes](#features)*
580
+ - [x] Frozen panes (freeze rows/columns): *see [Freeze Panes](#features)*
472
581
  - [ ] Data validation (dropdown lists, input constraints)
473
582
  - [ ] Column / row grouping and collapsing
474
- - [x] Sort & filter — sort by displayed content with Excel-style Sort Warning dialog (expand selection / current selection only); see [Sorting & Sort Warning](#features)
583
+ - [x] Sort & filter: sort by displayed content with Excel-style Sort Warning dialog (expand selection / current selection only); see [Sorting & Sort Warning](#features)
584
+ - [x] Auto Filter (AutoFilter): toolbar "Filter" / `Ctrl+Shift+L` to enable, header drop-down arrows, intelligent downward data probing, value/text/number/date multi-type filters, separate clear-column vs remove-all; see [Auto Filter (AutoFilter)](#auto-filter-autofilter)
475
585
  - [ ] Cell comments / notes
476
586
  - [ ] Print layout
477
587
 
@@ -492,13 +602,13 @@ The project includes a GitHub Actions workflow (`.github/workflows/publish.yml`)
492
602
  | Framework | Vue 3 (Composition API + `<script setup>`) | ^3.4 |
493
603
  | Build | Vite | ^5.0 |
494
604
  | Language | TypeScript (strict) | ~5.4 |
495
- | Rendering | Canvas 2D API | — |
605
+ | Rendering | Canvas 2D API | - |
496
606
  | Type Checker | vue-tsc | ^2.2 |
497
- | Package Manager | pnpm | — |
498
- | CSS | Scoped CSS + CSS Custom Properties | — |
607
+ | Package Manager | pnpm | - |
608
+ | CSS | Scoped CSS + CSS Custom Properties | - |
499
609
 
500
610
  ---
501
611
 
502
612
  ## License
503
613
 
504
- This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
614
+ This project is licensed under the MIT License: see the [LICENSE](LICENSE) file for details.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .sp-dropdown[data-v-804e629f]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-804e629f]{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;height:26px;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;padding:0 5px;box-sizing:border-box}.sp-dropdown__trigger[data-v-804e629f]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-804e629f]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-804e629f]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-804e629f]{width:10px;height:10px;min-width:10px;opacity:.7}.sp-dropdown__menu[data-v-804e629f]{position:fixed;z-index:40000;display:flex;flex-direction:column;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;transform-origin:top center}.sp-dropdown__menu--up[data-v-804e629f]{transform-origin:bottom center}.menu-pop-enter-active[data-v-804e629f],.menu-pop-leave-active[data-v-804e629f]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-804e629f],.menu-pop-leave-to[data-v-804e629f]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-804e629f]{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.sp-dropdown__nav[data-v-804e629f]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-804e629f]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-804e629f]{width:10px;height:10px}.sp-dropdown__list[data-v-804e629f]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__search[data-v-804e629f]{flex:0 0 auto;height:26px;margin-bottom:4px;padding:0 8px;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:3px;font-size:12px;font-family:inherit;color:#1a1a1a;outline:none;box-sizing:border-box}.sp-dropdown__search[data-v-804e629f]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.sp-dropdown__empty[data-v-804e629f]{padding:6px 8px;font-size:12px;color:#999;text-align:center}.sp-dropdown__icon[data-v-804e629f]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__icon[data-v-804e629f] svg{width:18px;height:18px;display:block}.sp-dropdown__item-icon[data-v-804e629f]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__item-icon[data-v-804e629f] svg{width:16px;height:16px;display:block}.sp-dropdown__item-label[data-v-804e629f]{white-space:nowrap}.sp-dropdown__item[data-v-804e629f]{display:flex;align-items:center;gap:6px;width:100%;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;cursor:pointer;padding:4px 8px;box-sizing:border-box;border-radius:3px}.sp-dropdown__item[data-v-804e629f]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-804e629f]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-70f3dfdc]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-70f3dfdc]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;padding:6px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;transform-origin:top right}.menu-pop-enter-active[data-v-70f3dfdc],.menu-pop-leave-active[data-v-70f3dfdc]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-70f3dfdc],.menu-pop-leave-to[data-v-70f3dfdc]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-70f3dfdc]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-70f3dfdc]:last-child{margin-bottom:0}.color-picker__swatch[data-v-70f3dfdc]{width:20px;height:20px;padding:0;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .08s,box-shadow .08s;position:relative}.color-picker__swatch[data-v-70f3dfdc]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-70f3dfdc]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-551c0ffe]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-551c0ffe]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.border-picker__item[data-v-551c0ffe]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.border-picker__item[data-v-551c0ffe]:hover{background:#eef3f9}.border-picker__icon[data-v-551c0ffe]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-551c0ffe]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-551c0ffe],.menu-pop-leave-active[data-v-551c0ffe]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-551c0ffe],.menu-pop-leave-to[data-v-551c0ffe]{opacity:0;transform:scale(.9)}.sort-picker[data-v-45929b74]{position:relative;display:inline-flex;height:26px}.sort-picker__menu[data-v-45929b74]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.sort-picker__item[data-v-45929b74]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.sort-picker__item[data-v-45929b74]:hover{background:#eef3f9}.sort-picker__icon[data-v-45929b74]{width:18px;height:18px;flex-shrink:0}.sort-picker__label[data-v-45929b74]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-45929b74],.menu-pop-leave-active[data-v-45929b74]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-45929b74],.menu-pop-leave-to[data-v-45929b74]{opacity:0;transform:scale(.9)}.merge-picker[data-v-edd36208]{position:relative;display:inline-flex;height:26px}.merge-picker__menu[data-v-edd36208]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.merge-picker__item[data-v-edd36208]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.merge-picker__item[data-v-edd36208]:hover{background:#eef3f9}.merge-picker__icon[data-v-edd36208]{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.merge-picker__icon[data-v-edd36208] svg{width:18px;height:18px}.merge-picker__label[data-v-edd36208]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-edd36208],.menu-pop-leave-active[data-v-edd36208]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-edd36208],.menu-pop-leave-to[data-v-edd36208]{opacity:0;transform:scale(.9)}.calc-picker[data-v-01a18e00]{position:relative;display:inline-flex;height:26px}.calc-picker__menu[data-v-01a18e00]{position:fixed;z-index:9999;min-width:120px;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.calc-picker__item[data-v-01a18e00]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.calc-picker__item[data-v-01a18e00]:hover:not(.calc-picker__item--disabled){background:#eef3f9}.calc-picker__item--disabled[data-v-01a18e00]{color:var(--sp-toolbar-btn-disabled-color, #bbb);cursor:default}.calc-picker__label[data-v-01a18e00]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-01a18e00],.menu-pop-leave-active[data-v-01a18e00]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-01a18e00],.menu-pop-leave-to[data-v-01a18e00]{opacity:0;transform:scale(.9)}.toolbar[data-v-a97a071a]{position:relative;display:flex;align-items:center;height:32px;min-height:32px;gap:2px;padding:0 6px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none}.tb-item[data-v-a97a071a]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-a97a071a]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-a97a071a],.toolbar-number-format[data-v-a97a071a],.toolbar-align[data-v-a97a071a],.toolbar-freeze[data-v-a97a071a]{flex:0 0 auto}.toolbar-font-size[data-v-a97a071a],.toolbar-number-format-group[data-v-a97a071a]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-a97a071a]{width:36px;height:26px;border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px;background:transparent;color:var(--sp-toolbar-btn-color);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;text-align:left;padding:0 5px;outline:none;box-sizing:border-box;-webkit-appearance:none;appearance:none;-moz-appearance:textfield}.toolbar-font-size__input[data-v-a97a071a]::-webkit-outer-spin-button,.toolbar-font-size__input[data-v-a97a071a]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.toolbar-font-size__input[data-v-a97a071a]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-a97a071a]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-a97a071a]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-left:none;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-font-size__btn[data-v-a97a071a]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-a97a071a]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-a97a071a]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-a97a071a]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-btn[data-v-a97a071a]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-a97a071a]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-a97a071a]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-a97a071a]{width:26px;height:26px}.toolbar-btn--step svg[data-v-a97a071a]{width:16px;height:16px}.toolbar-btn[data-v-a97a071a]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-a97a071a]{width:18px;height:18px}.toolbar-btn svg[data-v-a97a071a]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-a97a071a]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-a97a071a]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-a97a071a]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-split__arrow[data-v-a97a071a]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-a97a071a]{width:10px!important;height:10px!important}.toolbar-more[data-v-a97a071a]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0;flex:0 0 auto;margin-left:auto}.toolbar-more[data-v-a97a071a]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-a97a071a]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-a97a071a]{width:18px;height:18px}.overflow-menu[data-v-a97a071a]{min-width:180px;max-width:260px;max-height:calc(100vh - 40px);overflow-y:auto;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px 6px;display:flex;flex-direction:column;gap:2px;z-index:1000;transform-origin:top right}.overflow-menu.no-anim[data-v-a97a071a]{transition:none!important}.overflow-menu .tb-item[data-v-a97a071a]{width:100%}.overflow-menu .toolbar-sep[data-v-a97a071a]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-a97a071a]{width:100%}.overflow-menu .toolbar-split__main[data-v-a97a071a]{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size[data-v-a97a071a],.overflow-menu .toolbar-number-format-group[data-v-a97a071a]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-a97a071a]{width:100%}.overflow-menu .toolbar-number-format[data-v-a97a071a]{flex:1 1 auto;width:auto!important;min-width:0}.overflow-menu .toolbar-align[data-v-a97a071a],.overflow-menu .toolbar-freeze[data-v-a97a071a]{width:100%}.overflow-menu .toolbar-btn[data-v-a97a071a]:not(.toolbar-btn--step):not(.toolbar-split__arrow):not(.toolbar-number-format__btn){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-number-format__btn[data-v-a97a071a]{flex:0 0 auto;width:30px}.overflow-menu .toolbar-color[data-v-a97a071a]{width:100%}.overflow-menu .toolbar-wrap[data-v-a97a071a]{width:100%;justify-content:flex-start}.menu-pop-enter-active[data-v-a97a071a],.menu-pop-leave-active[data-v-a97a071a]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-a97a071a],.menu-pop-leave-to[data-v-a97a071a]{opacity:0;transform:scale(.9)}.overflow-menu .tb-item{width:100%}.overflow-menu .toolbar-sep{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split{width:100%}.overflow-menu .toolbar-split__main{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size,.overflow-menu .toolbar-number-format-group{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font{width:100%}.overflow-menu .toolbar-number-format{flex:1 1 auto;width:auto!important;min-width:0}.overflow-menu .toolbar-align,.overflow-menu .toolbar-freeze{width:100%}.overflow-menu .toolbar-btn:not(.toolbar-btn--step):not(.toolbar-split__arrow):not(.toolbar-number-format__btn){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-number-format__btn{flex:0 0 auto;width:30px}.overflow-menu .toolbar-color{width:100%}.overflow-menu .toolbar-wrap{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font-size__input{flex:1 1 auto;width:auto;min-width:40px}.overflow-menu .toolbar-btn:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-btn:active:not(:disabled){opacity:.7}.overflow-menu .toolbar-btn--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.overflow-menu .toolbar-btn:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.overflow-menu .toolbar-split__main:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-split__arrow:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:focus{border-color:var(--sp-toolbar-border);background:#fff}.overflow-menu .toolbar-font-size__btn:hover,.overflow-menu .toolbar-more:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-more--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.tab-bar[data-v-ec10bade]{display:flex;align-items:stretch;height:30px;min-height:30px;background:var(--sp-tab-bar-bg);border-top:1px solid var(--sp-tab-bar-border);-webkit-user-select:none;user-select:none;margin-top:4px}.tab-list[data-v-ec10bade]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-ec10bade]{display:flex;align-items:center;height:28px;min-width:0;max-width:120px;padding:0 10px;cursor:pointer;border:1px solid var(--sp-tab-inactive-border);background:var(--sp-tab-inactive-bg);color:var(--sp-tab-inactive-color);font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap;transition:background .1s}.tab-item[data-v-ec10bade]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-ec10bade]{height:28px;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);border-color:var(--sp-tab-active-bg) var(--sp-tab-bar-border) var(--sp-tab-bar-border);border-top:2px solid var(--sp-tab-active-border);font-size:16px}.tab-item--active[data-v-ec10bade]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-ec10bade]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-ec10bade]{width:100%;height:18px;border:none;border-radius:0;outline:none;padding:0;font-size:16px;font-family:inherit;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);box-sizing:border-box}.tab-bar__list-btn[data-v-ec10bade]{display:flex;align-items:center;justify-content:center;width:24px;min-width:24px;height:24px;margin:0 2px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);cursor:pointer;padding:0;align-self:flex-end}.tab-bar__list-btn[data-v-ec10bade]:hover,.tab-bar__list-btn--active[data-v-ec10bade]{background:var(--sp-tab-add-btn-hover-bg)}.tab-bar__list-btn svg[data-v-ec10bade]{width:14px;height:14px}.tab-bar__add-btn[data-v-ec10bade]{display:flex;align-items:center;justify-content:center;width:24px;min-width:24px;height:24px;margin:0 4px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);font-size:16px;line-height:22px;text-align:center;cursor:pointer;padding:0;align-self:flex-end}.tab-bar__add-btn[data-v-ec10bade]:hover{background:var(--sp-tab-add-btn-hover-bg)}.tab-list-menu{position:fixed;display:flex;flex-direction:column;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border, #d8d8d8);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;z-index:1000;transform-origin:bottom left;min-width:140px;max-width:260px;box-sizing:border-box}.tab-list-menu__nav{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.tab-list-menu__nav:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg, #eef3f9)}.tab-list-menu__nav:disabled{color:#ccc;cursor:default}.tab-list-menu__nav svg{width:10px;height:10px}.tab-list-menu__list{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.tab-list-menu__item{display:flex;align-items:center;gap:4px;width:100%;height:28px;padding:0 6px 0 10px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;white-space:nowrap;border-radius:3px;box-sizing:border-box}.tab-list-menu__item:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.tab-list-menu__item--active{color:var(--sp-tab-active-border, #0078d7);font-weight:500}.tab-list-menu__name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-list-menu__del{display:flex;align-items:center;justify-content:center;width:18px;height:18px;flex:0 0 auto;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #999);cursor:pointer;padding:0;border-radius:3px;opacity:.55}.tab-list-menu__item:hover .tab-list-menu__del{opacity:1}.tab-list-menu__del:hover:not(:disabled){background:rgba(0,0,0,.08);color:#d9534f}.tab-list-menu__del:disabled{cursor:default;opacity:.25}.tab-list-menu__del svg{width:12px;height:12px}.find-bar[data-v-3120909b]{display:flex;align-items:center;gap:6px;padding:4px 8px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none;flex-wrap:nowrap;overflow-x:auto}.find-bar__input[data-v-3120909b]{height:24px;width:160px;flex:0 0 auto;border:1px solid var(--sp-toolbar-border);border-radius:3px;padding:0 6px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color, #1a1a1a);background:#fff;outline:none;box-sizing:border-box}.find-bar__input[data-v-3120909b]:focus{border-color:var(--sp-toolbar-btn-active-color)}.find-bar__dropdown[data-v-3120909b]{flex:0 0 auto}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger{height:24px;border:1px solid var(--sp-toolbar-border);background:#fff;color:var(--sp-formula-bar-input-color, #1a1a1a);font-size:12px;padding:0 4px}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger:hover{background:#f5f5f5}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger--open{border-color:var(--sp-toolbar-btn-active-color)}.find-bar__chk[data-v-3120909b]{display:flex;align-items:center;gap:5px;flex:0 0 auto;font-size:12px;color:var(--sp-toolbar-btn-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.find-bar__chk-input[data-v-3120909b]{position:absolute;width:0;height:0;margin:0;padding:0;opacity:0;pointer-events:none}.find-bar__chk-box[data-v-3120909b]{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;flex:0 0 auto;box-sizing:border-box;border:1px solid var(--sp-toolbar-border);border-radius:3px;background:#fff;transition:background .12s ease,border-color .12s ease}.find-bar__chk-tick[data-v-3120909b]{width:12px;height:12px;color:#fff;opacity:0;transform:scale(.5);transition:opacity .12s ease,transform .12s ease}.find-bar__chk-input:checked+.find-bar__chk-box[data-v-3120909b]{background:#0078d7;border-color:#0078d7}.find-bar__chk-input:checked+.find-bar__chk-box .find-bar__chk-tick[data-v-3120909b]{opacity:1;transform:scale(1)}.find-bar__chk-input:focus-visible+.find-bar__chk-box[data-v-3120909b]{outline:2px solid rgba(0,120,215,.4);outline-offset:1px}.find-bar__count[data-v-3120909b]{flex:0 0 auto;font-size:12px;color:var(--sp-toolbar-btn-color);min-width:44px;text-align:center;white-space:nowrap}.find-bar__btn[data-v-3120909b]{height:24px;flex:0 0 auto;border:1px solid var(--sp-toolbar-border);border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;font-size:12px;padding:0 8px;display:inline-flex;align-items:center;justify-content:center}.find-bar__btn[data-v-3120909b]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.find-bar__btn[data-v-3120909b]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.find-bar__btn--icon[data-v-3120909b]{width:26px;padding:0}.find-bar__btn--icon svg[data-v-3120909b]{width:14px;height:14px}.find-bar__btn--close[data-v-3120909b]{width:26px;padding:0;margin-left:auto;border:none}.find-bar__btn--close svg[data-v-3120909b]{width:14px;height:14px}.nf-dialog__mask[data-v-39792a0b]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.nf-dialog[data-v-39792a0b]{width:380px;max-width:calc(100vw - 32px);max-height:calc(100vh - 48px);overflow-y:auto;background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.nf-dialog__header[data-v-39792a0b]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.nf-dialog__title[data-v-39792a0b]{font-size:13px;font-weight:600}.nf-dialog__close[data-v-39792a0b]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.nf-dialog__close[data-v-39792a0b]:hover{background:#f0f0f0;color:#444}.nf-dialog__close svg[data-v-39792a0b]{width:14px;height:14px}.nf-dialog__body[data-v-39792a0b]{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.nf-field[data-v-39792a0b]{display:flex;align-items:center;gap:8px}.nf-field--inline[data-v-39792a0b]{min-height:26px}.nf-field__label[data-v-39792a0b]{width:88px;min-width:88px;font-size:12px;color:#555}.nf-field__input[data-v-39792a0b]{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:0 6px;outline:none;box-sizing:border-box;font-family:inherit}.nf-field__input[data-v-39792a0b]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-field__dropdown[data-v-39792a0b]{flex:1}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger{border:1px solid #c0c0c0;background:#fff;color:#1a1a1a;padding:0 6px}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger:hover{background:#f5f5f5}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger--open{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-field__textarea[data-v-39792a0b]{flex:1;min-height:44px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:4px 6px;outline:none;box-sizing:border-box;resize:none;font-family:Consolas,Courier New,monospace}.nf-field__textarea[data-v-39792a0b]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-checkbox[data-v-39792a0b]{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#333;cursor:pointer}.nf-checkbox input[data-v-39792a0b]{margin:0;cursor:pointer}.nf-dialog__footer[data-v-39792a0b]{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.nf-preview[data-v-39792a0b]{display:flex;flex-direction:column;gap:2px;min-width:0}.nf-preview__label[data-v-39792a0b]{font-size:11px;color:#888}.nf-preview__value[data-v-39792a0b]{font-size:13px;color:#1a1a1a;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.nf-dialog__actions[data-v-39792a0b]{display:flex;gap:8px}.nf-btn[data-v-39792a0b]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.nf-btn[data-v-39792a0b]:hover{background:#f0f0f0}.nf-btn--primary[data-v-39792a0b]{border-color:#0078d7;background:#0078d7;color:#fff}.nf-btn--primary[data-v-39792a0b]:hover{background:#0069c0}.nf-dialog-enter-active[data-v-39792a0b],.nf-dialog-leave-active[data-v-39792a0b]{transition:opacity .14s ease-out}.nf-dialog-enter-from[data-v-39792a0b],.nf-dialog-leave-to[data-v-39792a0b]{opacity:0}.nf-dialog-enter-active .nf-dialog[data-v-39792a0b],.nf-dialog-leave-active .nf-dialog[data-v-39792a0b]{transition:transform .14s ease-out}.nf-dialog-enter-from .nf-dialog[data-v-39792a0b],.nf-dialog-leave-to .nf-dialog[data-v-39792a0b]{transform:scale(.96)}.sort-confirm__mask[data-v-d26d5917]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.sort-confirm[data-v-d26d5917]{width:360px;max-width:calc(100vw - 32px);background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.sort-confirm__header[data-v-d26d5917]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.sort-confirm__title[data-v-d26d5917]{font-size:13px;font-weight:600}.sort-confirm__close[data-v-d26d5917]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.sort-confirm__close[data-v-d26d5917]:hover{background:#f0f0f0;color:#444}.sort-confirm__close svg[data-v-d26d5917]{width:14px;height:14px}.sort-confirm__body[data-v-d26d5917]{padding:14px}.sort-confirm__message[data-v-d26d5917]{margin:0 0 12px;font-size:12px;line-height:1.5;color:#333}.sort-confirm__options[data-v-d26d5917]{display:flex;flex-direction:column;gap:8px}.sort-confirm__option[data-v-d26d5917]{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#333;cursor:pointer}.sort-confirm__option input[data-v-d26d5917]{margin:0;cursor:pointer}.sort-confirm__footer[data-v-d26d5917]{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.sort-confirm__btn[data-v-d26d5917]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.sort-confirm__btn[data-v-d26d5917]:hover{background:#f0f0f0}.sort-confirm__btn--primary[data-v-d26d5917]{border-color:#0078d7;background:#0078d7;color:#fff}.sort-confirm__btn--primary[data-v-d26d5917]:hover{background:#0069c0}.sort-confirm-enter-active[data-v-d26d5917],.sort-confirm-leave-active[data-v-d26d5917]{transition:opacity .14s ease-out}.sort-confirm-enter-from[data-v-d26d5917],.sort-confirm-leave-to[data-v-d26d5917]{opacity:0}.sort-confirm-enter-active .sort-confirm[data-v-d26d5917],.sort-confirm-leave-active .sort-confirm[data-v-d26d5917]{transition:transform .14s ease-out}.sort-confirm-enter-from .sort-confirm[data-v-d26d5917],.sort-confirm-leave-to .sort-confirm[data-v-d26d5917]{transform:scale(.96)}.ifn-dialog__mask[data-v-f4e459b6]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.ifn-dialog[data-v-f4e459b6]{width:440px;max-width:calc(100vw - 32px);background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.ifn-dialog__header[data-v-f4e459b6]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.ifn-dialog__title[data-v-f4e459b6]{font-size:13px;font-weight:600}.ifn-dialog__close[data-v-f4e459b6]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.ifn-dialog__close[data-v-f4e459b6]:hover{background:#f0f0f0;color:#444}.ifn-dialog__close svg[data-v-f4e459b6]{width:14px;height:14px}.ifn-dialog__body[data-v-f4e459b6]{padding:14px;display:flex;flex-direction:column;gap:12px}.ifn-dialog__field[data-v-f4e459b6]{display:flex;flex-direction:column;gap:6px}.ifn-dialog__label[data-v-f4e459b6]{font-size:12px;color:#333}.ifn-dialog__dropdown[data-v-f4e459b6]{width:100%}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger{border:1px solid #c0c0c0;background:#fff;color:#1a1a1a;padding:0 6px}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger:hover{background:#f5f5f5}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger--open{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.ifn-dialog__desc[data-v-f4e459b6]{font-size:12px;line-height:1.5;color:#666;-webkit-user-select:text;user-select:text}.ifn-dialog__textarea[data-v-f4e459b6]{width:100%;height:84px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;line-height:1.5;color:#1a1a1a;padding:5px 6px;outline:none;box-sizing:border-box;font-family:Consolas,Menlo,monospace;resize:none;-webkit-user-select:text;user-select:text}.ifn-dialog__textarea[data-v-f4e459b6]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.ifn-dialog__footer[data-v-f4e459b6]{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.ifn-dialog__btn[data-v-f4e459b6]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.ifn-dialog__btn[data-v-f4e459b6]:hover{background:#f0f0f0}.ifn-dialog__btn--primary[data-v-f4e459b6]{border-color:#0078d7;background:#0078d7;color:#fff}.ifn-dialog__btn--primary[data-v-f4e459b6]:hover{background:#0069c0}.ifn-dialog__btn--primary[data-v-f4e459b6]:disabled,.ifn-dialog__btn--primary[data-v-f4e459b6]:disabled:hover{border-color:#ccc;background:#f0f0f0;color:#a8a8a8;cursor:not-allowed}.ifn-dialog-enter-active[data-v-f4e459b6],.ifn-dialog-leave-active[data-v-f4e459b6]{transition:opacity .14s ease-out}.ifn-dialog-enter-from[data-v-f4e459b6],.ifn-dialog-leave-to[data-v-f4e459b6]{opacity:0}.ifn-dialog-enter-active .ifn-dialog[data-v-f4e459b6],.ifn-dialog-leave-active .ifn-dialog[data-v-f4e459b6]{transition:transform .14s ease-out}.ifn-dialog-enter-from .ifn-dialog[data-v-f4e459b6],.ifn-dialog-leave-to .ifn-dialog[data-v-f4e459b6]{transform:scale(.96)}.spreadsheet-outer[data-v-a7c5466d]{flex:1;display:flex;flex-direction:column;overflow:hidden;height:100%;min-height:400px;width:100%}.formula-bar[data-v-a7c5466d]{display:flex;align-items:flex-start;min-height:36px;padding:0;gap:0}.formula-bar--expanded[data-v-a7c5466d]{min-height:72px}.formula-bar__cell-label[data-v-a7c5466d]{width:48px;min-width:48px;height:28px;line-height:28px;margin-top:4px;text-align:center;font-size:12px;font-weight:600;color:var(--sp-formula-bar-label-color);background:var(--sp-formula-bar-label-bg);border:1px solid var(--sp-formula-bar-label-border);border-radius:2px;-webkit-user-select:none;user-select:none}.formula-bar__buttons[data-v-a7c5466d]{display:inline-flex;align-items:stretch;margin-top:4px;margin-left:6px;height:28px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;overflow:hidden;background:var(--sp-formula-bar-input-bg)}.formula-bar__btn[data-v-a7c5466d]{width:22px;height:28px;border:none;border-radius:0;background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none;color:inherit}.formula-bar__btn+.formula-bar__btn[data-v-a7c5466d]{border-left:1px solid var(--sp-formula-bar-input-border)}.formula-bar__btn[data-v-a7c5466d]:hover{background:var(--sp-scroll-btn-hover-bg, #f0f0f0)}.formula-bar__btn--cancel[data-v-a7c5466d]:hover{color:#e53935;background:#fdecea}.formula-bar__btn--accept[data-v-a7c5466d]:hover{color:#2e7d32;background:#e8f5e9}.formula-bar__fx-label[data-v-a7c5466d]{font-family:Georgia,Times New Roman,serif;font-style:italic;font-weight:600;font-size:13px;line-height:1;-webkit-user-select:none;user-select:none}.formula-bar__btn--fx[data-v-a7c5466d]:hover{background:var(--sp-scroll-btn-hover-bg, #f0f0f0)}.formula-bar__input[data-v-a7c5466d]{flex:1;min-height:28px;height:28px;line-height:20px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:3px 6px;margin-left:4px;font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color);background:var(--sp-formula-bar-input-bg);resize:none;overflow:hidden;box-sizing:border-box}.formula-bar__input--expanded[data-v-a7c5466d]{height:68px;overflow:auto}.formula-bar__input[data-v-a7c5466d]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.formula-bar__toggle[data-v-a7c5466d]{width:22px;min-width:22px;height:28px;margin-top:4px;margin-left:2px;margin-right:2px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;background:var(--sp-formula-bar-input-bg);color:var(--sp-formula-bar-input-color);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none}.formula-bar__toggle[data-v-a7c5466d]:hover{background:var(--sp-scroll-btn-hover-bg, #e8e8e8)}.spreadsheet-wrapper[data-v-a7c5466d]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-a7c5466d]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas--freeze[data-v-a7c5466d]{pointer-events:none;z-index:1}.grid-canvas[data-v-a7c5466d]:not(.grid-canvas--freeze){z-index:0}.grid-canvas[data-v-a7c5466d]:focus{outline:none}.v-scrollbar[data-v-a7c5466d]{position:absolute;right:0;top:0;width:11px;height:calc(100% - 11px);display:flex;flex-direction:column;background:var(--sp-wrapper-bg)}.h-scrollbar[data-v-a7c5466d]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-a7c5466d]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-a7c5466d]{width:11px;height:11px;min-width:11px;min-height:11px;border:none;background:var(--sp-scroll-btn-bg, #e8e8e8);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;-webkit-user-select:none;user-select:none}.sb-btn[data-v-a7c5466d]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-a7c5466d]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-a7c5466d]{display:block;width:0;height:0}.sb-arrow--up[data-v-a7c5466d]{border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--down[data-v-a7c5466d]{border-left:3px solid transparent;border-right:3px solid transparent;border-top:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--left[data-v-a7c5466d]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-right:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--right[data-v-a7c5466d]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-a7c5466d]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-a7c5466d]{width:11px}.sb-track--h[data-v-a7c5466d]{height:11px}.sb-thumb[data-v-a7c5466d]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-a7c5466d]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-a7c5466d]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-a7c5466d]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-a7c5466d]{position:absolute;border:2px solid var(--sp-cell-editor-border);outline:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;color:var(--sp-cell-editor-color);background:var(--sp-cell-editor-bg);box-shadow:0 0 0 1px var(--sp-cell-editor-shadow);z-index:10;box-sizing:border-box;min-width:0;overflow:hidden;padding:0;margin:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;resize:none;white-space:pre-wrap;word-break:break-all}.context-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:120px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;transform-origin:top left}.context-menu__item{padding:6px 12px;cursor:pointer;color:#333;white-space:nowrap;position:relative;display:flex;align-items:center;justify-content:space-between}.context-menu__item:hover{background:#e8f0fe}.context-menu__item--disabled{color:#bbb;cursor:default}.context-menu__item--disabled:hover{background:transparent}.context-menu__arrow{margin-left:8px;margin-right:-2px;width:12px;height:12px;fill:#888;flex:none}.context-submenu{display:none;position:absolute;left:100%;top:-4px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:100px;z-index:10001}.context-submenu--left{left:auto;right:100%}.context-menu__item:not(.context-menu__item--disabled):hover>.context-submenu{display:block}.context-submenu .context-menu__item{justify-content:flex-start}.menu-pop-enter-active,.menu-pop-leave-active{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from,.menu-pop-leave-to{opacity:0;transform:scale(.9)}.dim-panel{position:fixed;z-index:10002;width:220px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:10px 12px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none;transform-origin:top left}.dim-panel__title{font-size:13px;font-weight:600;color:#333;margin-bottom:8px}.dim-panel__body{display:flex;align-items:center;gap:6px}.dim-panel__input{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;outline:none;padding:0 6px;font-size:13px;color:#1a1a1a;background:#fff;box-sizing:border-box}.dim-panel__input:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.dim-panel__input--error{border-color:#d93025;box-shadow:0 0 0 1px #d930254d}.dim-panel__error{margin-top:6px;font-size:12px;color:#d93025;line-height:1.4}.dim-panel__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.dim-panel__btn{height:26px;padding:0 14px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:13px;cursor:pointer}.dim-panel__btn:hover{background:#f0f0f0}.dim-panel__btn--primary{border-color:#0078d7;background:#0078d7;color:#fff}.dim-panel__btn--primary:hover{background:#0069c0}
1
+ .sp-dropdown[data-v-804e629f]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-804e629f]{display:flex;align-items:center;justify-content:space-between;gap:4px;width:100%;height:26px;border:1px solid transparent;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;padding:0 5px;box-sizing:border-box}.sp-dropdown__trigger[data-v-804e629f]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-804e629f]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-804e629f]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-804e629f]{width:10px;height:10px;min-width:10px;opacity:.7}.sp-dropdown__menu[data-v-804e629f]{position:fixed;z-index:40000;display:flex;flex-direction:column;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;transform-origin:top center}.sp-dropdown__menu--up[data-v-804e629f]{transform-origin:bottom center}.menu-pop-enter-active[data-v-804e629f],.menu-pop-leave-active[data-v-804e629f]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-804e629f],.menu-pop-leave-to[data-v-804e629f]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-804e629f]{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.sp-dropdown__nav[data-v-804e629f]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-804e629f]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-804e629f]{width:10px;height:10px}.sp-dropdown__list[data-v-804e629f]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__search[data-v-804e629f]{flex:0 0 auto;height:26px;margin-bottom:4px;padding:0 8px;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:3px;font-size:12px;font-family:inherit;color:#1a1a1a;outline:none;box-sizing:border-box}.sp-dropdown__search[data-v-804e629f]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.sp-dropdown__empty[data-v-804e629f]{padding:6px 8px;font-size:12px;color:#999;text-align:center}.sp-dropdown__icon[data-v-804e629f]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__icon[data-v-804e629f] svg{width:18px;height:18px;display:block}.sp-dropdown__item-icon[data-v-804e629f]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__item-icon[data-v-804e629f] svg{width:16px;height:16px;display:block}.sp-dropdown__item-label[data-v-804e629f]{white-space:nowrap}.sp-dropdown__item[data-v-804e629f]{display:flex;align-items:center;gap:6px;width:100%;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:12px;cursor:pointer;padding:4px 8px;box-sizing:border-box;border-radius:3px}.sp-dropdown__item[data-v-804e629f]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-804e629f]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-70f3dfdc]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-70f3dfdc]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;padding:6px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;transform-origin:top right}.menu-pop-enter-active[data-v-70f3dfdc],.menu-pop-leave-active[data-v-70f3dfdc]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-70f3dfdc],.menu-pop-leave-to[data-v-70f3dfdc]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-70f3dfdc]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-70f3dfdc]:last-child{margin-bottom:0}.color-picker__swatch[data-v-70f3dfdc]{width:20px;height:20px;padding:0;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform .08s,box-shadow .08s;position:relative}.color-picker__swatch[data-v-70f3dfdc]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-70f3dfdc]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-551c0ffe]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-551c0ffe]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.border-picker__item[data-v-551c0ffe]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.border-picker__item[data-v-551c0ffe]:hover{background:#eef3f9}.border-picker__icon[data-v-551c0ffe]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-551c0ffe]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-551c0ffe],.menu-pop-leave-active[data-v-551c0ffe]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-551c0ffe],.menu-pop-leave-to[data-v-551c0ffe]{opacity:0;transform:scale(.9)}.sort-picker[data-v-45929b74]{position:relative;display:inline-flex;height:26px}.sort-picker__menu[data-v-45929b74]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.sort-picker__item[data-v-45929b74]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.sort-picker__item[data-v-45929b74]:hover{background:#eef3f9}.sort-picker__icon[data-v-45929b74]{width:18px;height:18px;flex-shrink:0}.sort-picker__label[data-v-45929b74]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-45929b74],.menu-pop-leave-active[data-v-45929b74]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-45929b74],.menu-pop-leave-to[data-v-45929b74]{opacity:0;transform:scale(.9)}.merge-picker[data-v-edd36208]{position:relative;display:inline-flex;height:26px}.merge-picker__menu[data-v-edd36208]{position:fixed;z-index:9999;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.merge-picker__item[data-v-edd36208]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.merge-picker__item[data-v-edd36208]:hover{background:#eef3f9}.merge-picker__icon[data-v-edd36208]{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.merge-picker__icon[data-v-edd36208] svg{width:18px;height:18px}.merge-picker__label[data-v-edd36208]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-edd36208],.menu-pop-leave-active[data-v-edd36208]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-edd36208],.menu-pop-leave-to[data-v-edd36208]{opacity:0;transform:scale(.9)}.calc-picker[data-v-01a18e00]{position:relative;display:inline-flex;height:26px}.calc-picker__menu[data-v-01a18e00]{position:fixed;z-index:9999;min-width:120px;background:#fff;border:1px solid var(--sp-toolbar-border, #d0d0d0);border-radius:4px;box-shadow:0 4px 12px #0000001f;-webkit-user-select:none;user-select:none;padding:4px;transform-origin:top right}.calc-picker__item[data-v-01a18e00]{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);cursor:pointer;border-radius:3px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap}.calc-picker__item[data-v-01a18e00]:hover:not(.calc-picker__item--disabled){background:#eef3f9}.calc-picker__item--disabled[data-v-01a18e00]{color:var(--sp-toolbar-btn-disabled-color, #bbb);cursor:default}.calc-picker__label[data-v-01a18e00]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-01a18e00],.menu-pop-leave-active[data-v-01a18e00]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-01a18e00],.menu-pop-leave-to[data-v-01a18e00]{opacity:0;transform:scale(.9)}.toolbar[data-v-0d0b0e86]{position:relative;display:flex;align-items:center;height:32px;min-height:32px;gap:2px;padding:0 6px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none}.tb-item[data-v-0d0b0e86]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-0d0b0e86]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-0d0b0e86],.toolbar-number-format[data-v-0d0b0e86],.toolbar-align[data-v-0d0b0e86],.toolbar-freeze[data-v-0d0b0e86]{flex:0 0 auto}.toolbar-font-size[data-v-0d0b0e86],.toolbar-number-format-group[data-v-0d0b0e86]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-0d0b0e86]{width:36px;height:26px;border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px;background:transparent;color:var(--sp-toolbar-btn-color);font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;text-align:left;padding:0 5px;outline:none;box-sizing:border-box;-webkit-appearance:none;appearance:none;-moz-appearance:textfield}.toolbar-font-size__input[data-v-0d0b0e86]::-webkit-outer-spin-button,.toolbar-font-size__input[data-v-0d0b0e86]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.toolbar-font-size__input[data-v-0d0b0e86]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-0d0b0e86]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-0d0b0e86]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-left:none;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-font-size__btn[data-v-0d0b0e86]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-0d0b0e86]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-0d0b0e86]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-0d0b0e86]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-btn[data-v-0d0b0e86]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-0d0b0e86]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-0d0b0e86]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-0d0b0e86]{width:26px;height:26px}.toolbar-btn--step svg[data-v-0d0b0e86]{width:16px;height:16px}.toolbar-btn[data-v-0d0b0e86]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-0d0b0e86]{width:18px;height:18px}.toolbar-btn svg[data-v-0d0b0e86]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-0d0b0e86]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-0d0b0e86]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-0d0b0e86]{display:flex;align-items:center;justify-content:center;width:16px;height:26px;border:1px solid transparent;border-radius:0 3px 3px 0;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0}.toolbar-split__arrow[data-v-0d0b0e86]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-0d0b0e86]{width:10px!important;height:10px!important}.toolbar-more[data-v-0d0b0e86]{display:flex;align-items:center;justify-content:center;width:30px;height:26px;border:none;border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;padding:0;flex:0 0 auto;margin-left:auto}.toolbar-more[data-v-0d0b0e86]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-0d0b0e86]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-0d0b0e86]{width:18px;height:18px}.overflow-menu[data-v-0d0b0e86]{min-width:180px;max-width:260px;max-height:calc(100vh - 40px);overflow-y:auto;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px 6px;display:flex;flex-direction:column;gap:2px;z-index:1000;transform-origin:top right}.overflow-menu.no-anim[data-v-0d0b0e86]{transition:none!important}.overflow-menu .tb-item[data-v-0d0b0e86]{width:100%}.overflow-menu .toolbar-sep[data-v-0d0b0e86]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-0d0b0e86]{width:100%}.overflow-menu .toolbar-split__main[data-v-0d0b0e86]{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size[data-v-0d0b0e86],.overflow-menu .toolbar-number-format-group[data-v-0d0b0e86]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-0d0b0e86]{width:100%}.overflow-menu .toolbar-number-format[data-v-0d0b0e86]{flex:1 1 auto;width:auto!important;min-width:0}.overflow-menu .toolbar-align[data-v-0d0b0e86],.overflow-menu .toolbar-freeze[data-v-0d0b0e86]{width:100%}.overflow-menu .toolbar-btn[data-v-0d0b0e86]:not(.toolbar-btn--step):not(.toolbar-split__arrow):not(.toolbar-number-format__btn){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-number-format__btn[data-v-0d0b0e86]{flex:0 0 auto;width:30px}.overflow-menu .toolbar-color[data-v-0d0b0e86]{width:100%}.overflow-menu .toolbar-wrap[data-v-0d0b0e86]{width:100%;justify-content:flex-start}.menu-pop-enter-active[data-v-0d0b0e86],.menu-pop-leave-active[data-v-0d0b0e86]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-0d0b0e86],.menu-pop-leave-to[data-v-0d0b0e86]{opacity:0;transform:scale(.9)}.overflow-menu .tb-item{width:100%}.overflow-menu .toolbar-sep{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split{width:100%}.overflow-menu .toolbar-split__main{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size,.overflow-menu .toolbar-number-format-group{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font{width:100%}.overflow-menu .toolbar-number-format{flex:1 1 auto;width:auto!important;min-width:0}.overflow-menu .toolbar-align,.overflow-menu .toolbar-freeze{width:100%}.overflow-menu .toolbar-btn:not(.toolbar-btn--step):not(.toolbar-split__arrow):not(.toolbar-number-format__btn){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-number-format__btn{flex:0 0 auto;width:30px}.overflow-menu .toolbar-color{width:100%}.overflow-menu .toolbar-wrap{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font-size__input{flex:1 1 auto;width:auto;min-width:40px}.overflow-menu .toolbar-btn:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-btn:active:not(:disabled){opacity:.7}.overflow-menu .toolbar-btn--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.overflow-menu .toolbar-btn:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.overflow-menu .toolbar-split__main:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-split__arrow:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-font-size__input:focus{border-color:var(--sp-toolbar-border);background:#fff}.overflow-menu .toolbar-font-size__btn:hover,.overflow-menu .toolbar-more:hover{background:var(--sp-toolbar-btn-hover-bg)}.overflow-menu .toolbar-more--active{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.tab-bar[data-v-e00401ad]{display:flex;align-items:stretch;height:30px;min-height:30px;background:var(--sp-tab-bar-bg);border-top:1px solid var(--sp-tab-bar-border);-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;margin-top:4px}.tab-list[data-v-e00401ad]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-e00401ad]{display:flex;align-items:center;height:28px;min-width:0;max-width:120px;padding:0 10px;cursor:pointer;border:1px solid var(--sp-tab-inactive-border);background:var(--sp-tab-inactive-bg);color:var(--sp-tab-inactive-color);font-size:14px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;white-space:nowrap;transition:background .1s;-webkit-touch-callout:none}.tab-item[data-v-e00401ad]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-e00401ad]{height:28px;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);border-color:var(--sp-tab-active-bg) var(--sp-tab-bar-border) var(--sp-tab-bar-border);border-top:2px solid var(--sp-tab-active-border)}.tab-item--active[data-v-e00401ad]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-e00401ad]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-e00401ad]{width:100%;height:18px;border:none;border-radius:0;outline:none;padding:0;font-size:14px;font-family:inherit;background:var(--sp-tab-active-bg);color:var(--sp-tab-active-color);box-sizing:border-box}.tab-bar__list-btn[data-v-e00401ad]{display:flex;align-items:center;justify-content:center;width:24px;min-width:24px;height:24px;margin:0 2px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);cursor:pointer;padding:0;align-self:flex-end}.tab-bar__list-btn[data-v-e00401ad]:hover,.tab-bar__list-btn--active[data-v-e00401ad]{background:var(--sp-tab-add-btn-hover-bg)}.tab-bar__list-btn svg[data-v-e00401ad]{width:14px;height:14px}.tab-bar__add-btn[data-v-e00401ad]{display:flex;align-items:center;justify-content:center;width:24px;min-width:24px;height:24px;margin:0 4px 3px 3px;border:none;background:transparent;color:var(--sp-tab-add-btn-color);font-size:16px;line-height:22px;text-align:center;cursor:pointer;padding:0;align-self:flex-end}.tab-bar__add-btn[data-v-e00401ad]:hover{background:var(--sp-tab-add-btn-hover-bg)}.tab-list-menu{position:fixed;display:flex;flex-direction:column;background:var(--sp-toolbar-bg, #fff);border:1px solid var(--sp-toolbar-border, #d8d8d8);border-radius:4px;box-shadow:0 4px 12px #0000001f;padding:4px;z-index:1000;transform-origin:bottom left;min-width:140px;max-width:260px;box-sizing:border-box}.tab-list-menu__nav{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #666);cursor:pointer;padding:0;border-radius:3px}.tab-list-menu__nav:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg, #eef3f9)}.tab-list-menu__nav:disabled{color:#ccc;cursor:default}.tab-list-menu__nav svg{width:10px;height:10px}.tab-list-menu__list{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.tab-list-menu__item{display:flex;align-items:center;gap:4px;width:100%;height:28px;padding:0 6px 0 10px;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #444);font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;cursor:pointer;white-space:nowrap;border-radius:3px;box-sizing:border-box}.tab-list-menu__item:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.tab-list-menu__item--active{color:var(--sp-tab-active-border, #0078d7);font-weight:500}.tab-list-menu__name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-list-menu__del{display:flex;align-items:center;justify-content:center;width:18px;height:18px;flex:0 0 auto;border:none;background:transparent;color:var(--sp-toolbar-btn-color, #999);cursor:pointer;padding:0;border-radius:3px;opacity:.55}.tab-list-menu__item:hover .tab-list-menu__del{opacity:1}.tab-list-menu__del:hover:not(:disabled){background:rgba(0,0,0,.08);color:#d9534f}.tab-list-menu__del:disabled{cursor:default;opacity:.25}.tab-list-menu__del svg{width:12px;height:12px}.find-bar[data-v-3120909b]{display:flex;align-items:center;gap:6px;padding:4px 8px;background:var(--sp-toolbar-bg);border-bottom:1px solid var(--sp-toolbar-border);-webkit-user-select:none;user-select:none;flex-wrap:nowrap;overflow-x:auto}.find-bar__input[data-v-3120909b]{height:24px;width:160px;flex:0 0 auto;border:1px solid var(--sp-toolbar-border);border-radius:3px;padding:0 6px;font-size:12px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color, #1a1a1a);background:#fff;outline:none;box-sizing:border-box}.find-bar__input[data-v-3120909b]:focus{border-color:var(--sp-toolbar-btn-active-color)}.find-bar__dropdown[data-v-3120909b]{flex:0 0 auto}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger{height:24px;border:1px solid var(--sp-toolbar-border);background:#fff;color:var(--sp-formula-bar-input-color, #1a1a1a);font-size:12px;padding:0 4px}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger:hover{background:#f5f5f5}.find-bar__dropdown[data-v-3120909b] .sp-dropdown__trigger--open{border-color:var(--sp-toolbar-btn-active-color)}.find-bar__chk[data-v-3120909b]{display:flex;align-items:center;gap:5px;flex:0 0 auto;font-size:12px;color:var(--sp-toolbar-btn-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.find-bar__chk-input[data-v-3120909b]{position:absolute;width:0;height:0;margin:0;padding:0;opacity:0;pointer-events:none}.find-bar__chk-box[data-v-3120909b]{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;flex:0 0 auto;box-sizing:border-box;border:1px solid var(--sp-toolbar-border);border-radius:3px;background:#fff;transition:background .12s ease,border-color .12s ease}.find-bar__chk-tick[data-v-3120909b]{width:12px;height:12px;color:#fff;opacity:0;transform:scale(.5);transition:opacity .12s ease,transform .12s ease}.find-bar__chk-input:checked+.find-bar__chk-box[data-v-3120909b]{background:#0078d7;border-color:#0078d7}.find-bar__chk-input:checked+.find-bar__chk-box .find-bar__chk-tick[data-v-3120909b]{opacity:1;transform:scale(1)}.find-bar__chk-input:focus-visible+.find-bar__chk-box[data-v-3120909b]{outline:2px solid rgba(0,120,215,.4);outline-offset:1px}.find-bar__count[data-v-3120909b]{flex:0 0 auto;font-size:12px;color:var(--sp-toolbar-btn-color);min-width:44px;text-align:center;white-space:nowrap}.find-bar__btn[data-v-3120909b]{height:24px;flex:0 0 auto;border:1px solid var(--sp-toolbar-border);border-radius:3px;background:transparent;color:var(--sp-toolbar-btn-color);cursor:pointer;font-size:12px;padding:0 8px;display:inline-flex;align-items:center;justify-content:center}.find-bar__btn[data-v-3120909b]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.find-bar__btn[data-v-3120909b]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.find-bar__btn--icon[data-v-3120909b]{width:26px;padding:0}.find-bar__btn--icon svg[data-v-3120909b]{width:14px;height:14px}.find-bar__btn--close[data-v-3120909b]{width:26px;padding:0;margin-left:auto;border:none}.find-bar__btn--close svg[data-v-3120909b]{width:14px;height:14px}.nf-dialog__mask[data-v-39792a0b]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.nf-dialog[data-v-39792a0b]{width:380px;max-width:calc(100vw - 32px);max-height:calc(100vh - 48px);overflow-y:auto;background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.nf-dialog__header[data-v-39792a0b]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.nf-dialog__title[data-v-39792a0b]{font-size:13px;font-weight:600}.nf-dialog__close[data-v-39792a0b]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.nf-dialog__close[data-v-39792a0b]:hover{background:#f0f0f0;color:#444}.nf-dialog__close svg[data-v-39792a0b]{width:14px;height:14px}.nf-dialog__body[data-v-39792a0b]{padding:12px 14px;display:flex;flex-direction:column;gap:10px}.nf-field[data-v-39792a0b]{display:flex;align-items:center;gap:8px}.nf-field--inline[data-v-39792a0b]{min-height:26px}.nf-field__label[data-v-39792a0b]{width:88px;min-width:88px;font-size:12px;color:#555}.nf-field__input[data-v-39792a0b]{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:0 6px;outline:none;box-sizing:border-box;font-family:inherit}.nf-field__input[data-v-39792a0b]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-field__dropdown[data-v-39792a0b]{flex:1}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger{border:1px solid #c0c0c0;background:#fff;color:#1a1a1a;padding:0 6px}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger:hover{background:#f5f5f5}.nf-field__dropdown[data-v-39792a0b] .sp-dropdown__trigger--open{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-field__textarea[data-v-39792a0b]{flex:1;min-height:44px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;color:#1a1a1a;padding:4px 6px;outline:none;box-sizing:border-box;resize:none;font-family:Consolas,Courier New,monospace}.nf-field__textarea[data-v-39792a0b]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.nf-checkbox[data-v-39792a0b]{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#333;cursor:pointer}.nf-checkbox input[data-v-39792a0b]{margin:0;cursor:pointer}.nf-dialog__footer[data-v-39792a0b]{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.nf-preview[data-v-39792a0b]{display:flex;flex-direction:column;gap:2px;min-width:0}.nf-preview__label[data-v-39792a0b]{font-size:11px;color:#888}.nf-preview__value[data-v-39792a0b]{font-size:13px;color:#1a1a1a;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.nf-dialog__actions[data-v-39792a0b]{display:flex;gap:8px}.nf-btn[data-v-39792a0b]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.nf-btn[data-v-39792a0b]:hover{background:#f0f0f0}.nf-btn--primary[data-v-39792a0b]{border-color:#0078d7;background:#0078d7;color:#fff}.nf-btn--primary[data-v-39792a0b]:hover{background:#0069c0}.nf-dialog-enter-active[data-v-39792a0b],.nf-dialog-leave-active[data-v-39792a0b]{transition:opacity .14s ease-out}.nf-dialog-enter-from[data-v-39792a0b],.nf-dialog-leave-to[data-v-39792a0b]{opacity:0}.nf-dialog-enter-active .nf-dialog[data-v-39792a0b],.nf-dialog-leave-active .nf-dialog[data-v-39792a0b]{transition:transform .14s ease-out}.nf-dialog-enter-from .nf-dialog[data-v-39792a0b],.nf-dialog-leave-to .nf-dialog[data-v-39792a0b]{transform:scale(.96)}.sort-confirm__mask[data-v-d26d5917]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.sort-confirm[data-v-d26d5917]{width:360px;max-width:calc(100vw - 32px);background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.sort-confirm__header[data-v-d26d5917]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.sort-confirm__title[data-v-d26d5917]{font-size:13px;font-weight:600}.sort-confirm__close[data-v-d26d5917]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.sort-confirm__close[data-v-d26d5917]:hover{background:#f0f0f0;color:#444}.sort-confirm__close svg[data-v-d26d5917]{width:14px;height:14px}.sort-confirm__body[data-v-d26d5917]{padding:14px}.sort-confirm__message[data-v-d26d5917]{margin:0 0 12px;font-size:12px;line-height:1.5;color:#333}.sort-confirm__options[data-v-d26d5917]{display:flex;flex-direction:column;gap:8px}.sort-confirm__option[data-v-d26d5917]{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#333;cursor:pointer}.sort-confirm__option input[data-v-d26d5917]{margin:0;cursor:pointer}.sort-confirm__footer[data-v-d26d5917]{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.sort-confirm__btn[data-v-d26d5917]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.sort-confirm__btn[data-v-d26d5917]:hover{background:#f0f0f0}.sort-confirm__btn--primary[data-v-d26d5917]{border-color:#0078d7;background:#0078d7;color:#fff}.sort-confirm__btn--primary[data-v-d26d5917]:hover{background:#0069c0}.sort-confirm-enter-active[data-v-d26d5917],.sort-confirm-leave-active[data-v-d26d5917]{transition:opacity .14s ease-out}.sort-confirm-enter-from[data-v-d26d5917],.sort-confirm-leave-to[data-v-d26d5917]{opacity:0}.sort-confirm-enter-active .sort-confirm[data-v-d26d5917],.sort-confirm-leave-active .sort-confirm[data-v-d26d5917]{transition:transform .14s ease-out}.sort-confirm-enter-from .sort-confirm[data-v-d26d5917],.sort-confirm-leave-to .sort-confirm[data-v-d26d5917]{transform:scale(.96)}.ifn-dialog__mask[data-v-f4e459b6]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:30000;background:rgba(0,0,0,.25);display:flex;align-items:center;justify-content:center}.ifn-dialog[data-v-f4e459b6]{width:440px;max-width:calc(100vw - 32px);background:#fff;border:1px solid #d0d0d0;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:#1a1a1a;-webkit-user-select:none;user-select:none}.ifn-dialog__header[data-v-f4e459b6]{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid #ececec}.ifn-dialog__title[data-v-f4e459b6]{font-size:13px;font-weight:600}.ifn-dialog__close[data-v-f4e459b6]{display:flex;align-items:center;justify-content:center;width:22px;height:22px;border:none;background:transparent;color:#888;cursor:pointer;border-radius:3px;padding:0}.ifn-dialog__close[data-v-f4e459b6]:hover{background:#f0f0f0;color:#444}.ifn-dialog__close svg[data-v-f4e459b6]{width:14px;height:14px}.ifn-dialog__body[data-v-f4e459b6]{padding:14px;display:flex;flex-direction:column;gap:12px}.ifn-dialog__field[data-v-f4e459b6]{display:flex;flex-direction:column;gap:6px}.ifn-dialog__label[data-v-f4e459b6]{font-size:12px;color:#333}.ifn-dialog__dropdown[data-v-f4e459b6]{width:100%}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger{border:1px solid #c0c0c0;background:#fff;color:#1a1a1a;padding:0 6px}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger:hover{background:#f5f5f5}.ifn-dialog__dropdown[data-v-f4e459b6] .sp-dropdown__trigger--open{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.ifn-dialog__desc[data-v-f4e459b6]{font-size:12px;line-height:1.5;color:#666;-webkit-user-select:text;user-select:text}.ifn-dialog__textarea[data-v-f4e459b6]{width:100%;height:84px;border:1px solid #c0c0c0;border-radius:3px;background:#fff;font-size:12px;line-height:1.5;color:#1a1a1a;padding:5px 6px;outline:none;box-sizing:border-box;font-family:Consolas,Menlo,monospace;resize:none;-webkit-user-select:text;user-select:text}.ifn-dialog__textarea[data-v-f4e459b6]:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.ifn-dialog__footer[data-v-f4e459b6]{display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;border-top:1px solid #ececec}.ifn-dialog__btn[data-v-f4e459b6]{height:28px;padding:0 16px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:12px;cursor:pointer;font-family:inherit}.ifn-dialog__btn[data-v-f4e459b6]:hover{background:#f0f0f0}.ifn-dialog__btn--primary[data-v-f4e459b6]{border-color:#0078d7;background:#0078d7;color:#fff}.ifn-dialog__btn--primary[data-v-f4e459b6]:hover{background:#0069c0}.ifn-dialog__btn--primary[data-v-f4e459b6]:disabled,.ifn-dialog__btn--primary[data-v-f4e459b6]:disabled:hover{border-color:#ccc;background:#f0f0f0;color:#a8a8a8;cursor:not-allowed}.ifn-dialog-enter-active[data-v-f4e459b6],.ifn-dialog-leave-active[data-v-f4e459b6]{transition:opacity .14s ease-out}.ifn-dialog-enter-from[data-v-f4e459b6],.ifn-dialog-leave-to[data-v-f4e459b6]{opacity:0}.ifn-dialog-enter-active .ifn-dialog[data-v-f4e459b6],.ifn-dialog-leave-active .ifn-dialog[data-v-f4e459b6]{transition:transform .14s ease-out}.ifn-dialog-enter-from .ifn-dialog[data-v-f4e459b6],.ifn-dialog-leave-to .ifn-dialog[data-v-f4e459b6]{transform:scale(.96)}.filter-popup[data-v-ec90eb74]{position:fixed;z-index:10005;width:248px;background:#fff;border:1px solid #d0d0d0;border-radius:4px;box-shadow:0 4px 14px #00000029;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;color:#333;-webkit-user-select:none;user-select:none;overflow:hidden;transform-origin:top right}.filter-popup__head[data-v-ec90eb74]{display:flex;align-items:center;gap:6px;padding:8px 10px 6px;border-bottom:1px solid #eee}.filter-popup__head-label[data-v-ec90eb74]{font-weight:600;font-size:13px}.filter-popup__head-badge[data-v-ec90eb74]{font-size:11px;color:#0078d7;background:rgba(0,120,215,.1);border-radius:8px;padding:1px 6px}.filter-popup__search[data-v-ec90eb74]{padding:8px 10px 4px}.filter-popup__search-input[data-v-ec90eb74]{width:100%;box-sizing:border-box;height:26px;border:1px solid #ccc;border-radius:3px;padding:0 8px;font-size:12px;outline:none}.filter-popup__search-input[data-v-ec90eb74]:focus{border-color:#0078d7}.filter-popup__tools[data-v-ec90eb74]{display:flex;align-items:center;gap:4px;padding:4px 10px 6px}.filter-popup__tool[data-v-ec90eb74]{border:none;background:transparent;color:#0078d7;font-size:12px;cursor:pointer;padding:2px 4px}.filter-popup__tool[data-v-ec90eb74]:hover{text-decoration:underline}.filter-popup__count[data-v-ec90eb74]{margin-left:auto;font-size:11px;color:#999}.filter-popup__list[data-v-ec90eb74]{height:252px;overflow-y:auto;border-top:1px solid #f0f0f0;border-bottom:1px solid #f0f0f0}.filter-popup__item[data-v-ec90eb74]{display:flex;align-items:center;gap:6px;height:28px;padding:0 10px;box-sizing:border-box;cursor:pointer;white-space:nowrap}.filter-popup__item[data-v-ec90eb74]:hover{background:#eef3f9}.filter-popup__item input[data-v-ec90eb74]{margin:0;flex-shrink:0}.filter-popup__item-label[data-v-ec90eb74]{overflow:hidden;text-overflow:ellipsis;font-size:12px}.filter-popup__item-note[data-v-ec90eb74]{font-size:11px;color:#999;flex-shrink:0}.filter-popup__empty[data-v-ec90eb74]{padding:16px 10px;text-align:center;color:#999;font-size:12px}.filter-popup__modes[data-v-ec90eb74]{display:flex;gap:2px;padding:6px 10px}.filter-popup__mode[data-v-ec90eb74]{flex:1;border:1px solid #e0e0e0;background:#f7f7f7;border-radius:3px;font-size:12px;color:#444;padding:5px 0;cursor:pointer}.filter-popup__mode[data-v-ec90eb74]:hover{background:#eef3f9;border-color:#c8d8f0}.filter-popup__cond[data-v-ec90eb74]{padding:8px 10px}.filter-popup__cond-back[data-v-ec90eb74]{border:none;background:transparent;color:#0078d7;font-size:12px;cursor:pointer;padding:0;margin-bottom:8px}.filter-popup__cond-row[data-v-ec90eb74]{display:flex;align-items:center;gap:6px;margin-bottom:6px}.filter-popup__cond-select[data-v-ec90eb74]{width:100%;height:26px;border:1px solid #ccc;border-radius:3px;font-size:12px;background:#fff;outline:none}.filter-popup__cond-input[data-v-ec90eb74]{flex:1;min-width:0;height:26px;border:1px solid #ccc;border-radius:3px;padding:0 6px;font-size:12px;box-sizing:border-box;outline:none}.filter-popup__cond-input[data-v-ec90eb74]:focus{border-color:#0078d7}.filter-popup__cond-and[data-v-ec90eb74]{font-size:12px;color:#666}.filter-popup__footer[data-v-ec90eb74]{display:flex;align-items:center;gap:6px;padding:8px 10px;border-top:1px solid #eee}.filter-popup__btn[data-v-ec90eb74]{height:26px;padding:0 12px;border:1px solid #d0d0d0;border-radius:3px;background:#f7f7f7;color:#333;font-size:12px;cursor:pointer}.filter-popup__btn[data-v-ec90eb74]:hover{background:#eef3f9}.filter-popup__btn--primary[data-v-ec90eb74]{background:#0078d7;border-color:#0078d7;color:#fff}.filter-popup__btn--primary[data-v-ec90eb74]:hover{background:#006cbe}.filter-popup__btn--clear[data-v-ec90eb74]{color:#c62828;border-color:#e0c0c0}.filter-popup__btn--clear[data-v-ec90eb74]:hover{background:#fdf0f0}.filter-popup__footer-spacer[data-v-ec90eb74]{flex:1}.spreadsheet-outer[data-v-17b333fa]{flex:1;display:flex;flex-direction:column;overflow:hidden;height:100%;min-height:400px;width:100%}.formula-bar[data-v-17b333fa]{display:flex;align-items:flex-start;min-height:36px;padding:0;gap:0}.formula-bar--expanded[data-v-17b333fa]{min-height:72px}.formula-bar__cell-label[data-v-17b333fa]{width:48px;min-width:48px;height:28px;line-height:28px;margin-top:4px;text-align:center;font-size:12px;font-weight:600;color:var(--sp-formula-bar-label-color);background:var(--sp-formula-bar-label-bg);border:1px solid var(--sp-formula-bar-label-border);border-radius:2px;-webkit-user-select:none;user-select:none}.formula-bar__buttons[data-v-17b333fa]{display:inline-flex;align-items:stretch;margin-top:4px;margin-left:6px;height:28px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;overflow:hidden;background:var(--sp-formula-bar-input-bg)}.formula-bar__btn[data-v-17b333fa]{width:22px;height:28px;border:none;border-radius:0;background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none;color:inherit}.formula-bar__btn+.formula-bar__btn[data-v-17b333fa]{border-left:1px solid var(--sp-formula-bar-input-border)}.formula-bar__btn[data-v-17b333fa]:hover{background:var(--sp-scroll-btn-hover-bg, #f0f0f0)}.formula-bar__btn--cancel[data-v-17b333fa]:hover{color:#e53935;background:#fdecea}.formula-bar__btn--accept[data-v-17b333fa]:hover{color:#2e7d32;background:#e8f5e9}.formula-bar__fx-label[data-v-17b333fa]{font-family:Georgia,Times New Roman,serif;font-style:italic;font-weight:600;font-size:13px;line-height:1;-webkit-user-select:none;user-select:none}.formula-bar__btn--fx[data-v-17b333fa]:hover{background:var(--sp-scroll-btn-hover-bg, #f0f0f0)}.formula-bar__input[data-v-17b333fa]{flex:1;min-height:28px;height:28px;line-height:20px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:3px 6px;margin-left:4px;font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;color:var(--sp-formula-bar-input-color);background:var(--sp-formula-bar-input-bg);resize:none;overflow:hidden;box-sizing:border-box}.formula-bar__input--expanded[data-v-17b333fa]{height:68px;overflow:auto}.formula-bar__input[data-v-17b333fa]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.formula-bar__toggle[data-v-17b333fa]{width:22px;min-width:22px;height:28px;margin-top:4px;margin-left:2px;margin-right:2px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;background:var(--sp-formula-bar-input-bg);color:var(--sp-formula-bar-input-color);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;padding:0;-webkit-user-select:none;user-select:none}.formula-bar__toggle[data-v-17b333fa]:hover{background:var(--sp-scroll-btn-hover-bg, #e8e8e8)}.spreadsheet-wrapper[data-v-17b333fa]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-17b333fa]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas--freeze[data-v-17b333fa]{pointer-events:none;z-index:1}.grid-canvas[data-v-17b333fa]:not(.grid-canvas--freeze){z-index:0}.grid-canvas[data-v-17b333fa]:focus{outline:none}.v-scrollbar[data-v-17b333fa]{position:absolute;right:0;top:0;width:11px;height:calc(100% - 11px);display:flex;flex-direction:column;background:var(--sp-wrapper-bg)}.h-scrollbar[data-v-17b333fa]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-17b333fa]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-17b333fa]{width:11px;height:11px;min-width:11px;min-height:11px;border:none;background:var(--sp-scroll-btn-bg, #e8e8e8);display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;-webkit-user-select:none;user-select:none}.sb-btn[data-v-17b333fa]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-17b333fa]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-17b333fa]{display:block;width:0;height:0}.sb-arrow--up[data-v-17b333fa]{border-left:3px solid transparent;border-right:3px solid transparent;border-bottom:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--down[data-v-17b333fa]{border-left:3px solid transparent;border-right:3px solid transparent;border-top:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--left[data-v-17b333fa]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-right:4px solid var(--sp-scroll-btn-color, #666)}.sb-arrow--right[data-v-17b333fa]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-17b333fa]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-17b333fa]{width:11px}.sb-track--h[data-v-17b333fa]{height:11px}.sb-thumb[data-v-17b333fa]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-17b333fa]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-17b333fa]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-17b333fa]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-17b333fa]{position:absolute;border:2px solid var(--sp-cell-editor-border);outline:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;color:var(--sp-cell-editor-color);background:var(--sp-cell-editor-bg);box-shadow:0 0 0 1px var(--sp-cell-editor-shadow);z-index:10;box-sizing:border-box;min-width:0;overflow:hidden;padding:0;margin:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;resize:none;white-space:pre-wrap;word-break:break-all}.context-menu{position:fixed;z-index:10000;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:120px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;font-size:13px;transform-origin:top left}.context-menu__item{padding:6px 12px;cursor:pointer;color:#333;white-space:nowrap;position:relative;display:flex;align-items:center;justify-content:space-between}.context-menu__item:hover{background:#e8f0fe}.context-menu__item--disabled{color:#bbb;cursor:default}.context-menu__item--disabled:hover{background:transparent}.context-menu__arrow{margin-left:8px;margin-right:-2px;width:12px;height:12px;fill:#888;flex:none}.context-submenu{display:none;position:absolute;left:100%;top:-4px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;min-width:100px;z-index:10001}.context-submenu--left{left:auto;right:100%}.context-menu__item:not(.context-menu__item--disabled):hover>.context-submenu{display:block}.context-submenu .context-menu__item{justify-content:flex-start}.menu-pop-enter-active,.menu-pop-leave-active{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from,.menu-pop-leave-to{opacity:0;transform:scale(.9)}.dim-panel{position:fixed;z-index:10002;width:220px;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:10px 12px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Microsoft YaHei,sans-serif;-webkit-user-select:none;user-select:none;transform-origin:top left}.dim-panel__title{font-size:13px;font-weight:600;color:#333;margin-bottom:8px}.dim-panel__body{display:flex;align-items:center;gap:6px}.dim-panel__input{flex:1;height:26px;border:1px solid #c0c0c0;border-radius:3px;outline:none;padding:0 6px;font-size:13px;color:#1a1a1a;background:#fff;box-sizing:border-box}.dim-panel__input:focus{border-color:#0078d7;box-shadow:0 0 0 1px #0078d74d}.dim-panel__input--error{border-color:#d93025;box-shadow:0 0 0 1px #d930254d}.dim-panel__error{margin-top:6px;font-size:12px;color:#d93025;line-height:1.4}.dim-panel__footer{display:flex;justify-content:flex-end;gap:8px;margin-top:10px}.dim-panel__btn{height:26px;padding:0 14px;border:1px solid #ccc;border-radius:3px;background:#fff;color:#333;font-size:13px;cursor:pointer}.dim-panel__btn:hover{background:#f0f0f0}.dim-panel__btn--primary{border-color:#0078d7;background:#0078d7;color:#fff}.dim-panel__btn--primary:hover{background:#0069c0}
@@ -0,0 +1,30 @@
1
+ import type { SheetFilter, FilterColumn } from '../core/types';
2
+ type __VLS_Props = {
3
+ /** 正在筛选的列(0-based) */
4
+ col: number;
5
+ /** 锚点:筛选按钮左上角(屏幕坐标) */
6
+ anchor: {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ locale?: string;
11
+ /** 当前列 Header 单元格的值(如「班级」),缺省回退到列字母 */
12
+ headerLabel?: string;
13
+ getFilter: () => SheetFilter | null;
14
+ setFilter: (f: SheetFilter | null) => void;
15
+ setFilterColumn: (col: number, fc: FilterColumn | null) => void;
16
+ clearFilterColumn: (col: number) => void;
17
+ getColumnCandidates: (col: number) => {
18
+ values: string[];
19
+ hasBlank: boolean;
20
+ };
21
+ close: () => void;
22
+ };
23
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
24
+ locale: string;
25
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
26
+ rootRef: HTMLDivElement;
27
+ searchInputRef: HTMLInputElement;
28
+ listRef: HTMLDivElement;
29
+ }, any>;
30
+ export default _default;