xiaodao-spreader 0.1.3 → 0.1.5
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.ZH.md +459 -0
- package/README.md +409 -44
- package/dist/style.css +1 -1
- package/dist/types/components/spreader/{dropdown.vue.d.ts → components/dropdown.vue.d.ts} +11 -5
- package/dist/types/components/spreader/{borderPicker.vue.d.ts → components/pickers/borderPicker.vue.d.ts} +3 -0
- package/dist/types/components/spreader/{colorPicker.vue.d.ts → components/pickers/colorPicker.vue.d.ts} +6 -4
- package/dist/types/components/spreader/components/pickers/mergePicker.vue.d.ts +27 -0
- package/dist/types/components/spreader/{spreader.vue.d.ts → components/spreadsheet.vue.d.ts} +2 -8
- package/dist/types/components/spreader/{tabbar.vue.d.ts → components/tabbar.vue.d.ts} +11 -11
- package/dist/types/components/spreader/components/toolbar.vue.d.ts +111 -0
- package/dist/types/components/spreader/composables/borders-merge.d.ts +48 -0
- package/dist/types/components/spreader/composables/core-state.d.ts +98 -0
- package/dist/types/components/spreader/composables/interactions.d.ts +87 -0
- package/dist/types/components/spreader/composables/sheets-ops.d.ts +45 -0
- package/dist/types/components/spreader/composables/undo-styles.d.ts +86 -0
- package/dist/types/components/spreader/core/constants.d.ts +42 -0
- package/dist/types/components/spreader/{types.d.ts → core/types.d.ts} +2 -0
- package/dist/types/components/spreader/index.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/xiaodao-spreader.es.js +3507 -2442
- package/dist/xiaodao-spreader.umd.js +9 -4
- package/package.json +2 -1
- package/dist/types/components/spreader/constants.d.ts +0 -25
- package/dist/types/components/spreader/toolbar.vue.d.ts +0 -39
- /package/dist/types/components/spreader/{formula.d.ts → core/formula.d.ts} +0 -0
- /package/dist/types/components/spreader/{theme.d.ts → core/theme.d.ts} +0 -0
- /package/dist/types/components/spreader/{utils.d.ts → core/utils.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,31 +1,142 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Xiaodao Spreader
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
中文 | [English](./README.md)
|
|
4
|
+
|
|
5
|
+
A high-performance, canvas-based spreadsheet component for Vue 3 — bringing an Excel-like editing experience to the web.
|
|
6
|
+
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://vuejs.org/)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://vitejs.dev/)
|
|
4
11
|
|
|
5
12
|

|
|
6
13
|
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Table of Contents
|
|
17
|
+
|
|
18
|
+
- [Features](#features)
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Quick Start](#quick-start)
|
|
21
|
+
- [Basic Usage](#basic-usage)
|
|
22
|
+
- [Props](#props)
|
|
23
|
+
- [Data Model](#data-model)
|
|
24
|
+
- [Architecture](#architecture)
|
|
25
|
+
- [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
26
|
+
- [Formula Engine](#formula-engine)
|
|
27
|
+
- [Theming](#theming)
|
|
28
|
+
- [Development](#development)
|
|
29
|
+
- [Building](#building)
|
|
30
|
+
- [Roadmap](#roadmap)
|
|
31
|
+
- [Contributing](#contributing)
|
|
32
|
+
- [License](#license)
|
|
33
|
+
- [中文版](./README.ZH.md)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
### Core Spreadsheet
|
|
40
|
+
- **Canvas 2D Rendering** — High-DPI aware with DPR scaling, virtual viewport rendering for 200 × 26 sheets
|
|
41
|
+
- **Multi-Sheet Workbook** — Tab bar with add, rename, duplicate, delete, reorder
|
|
42
|
+
- **Formula Engine** — `=SUM()` range calculation with dependency tracking and circular-reference detection
|
|
43
|
+
- **Merge Cells** — Merge & Center, Merge Across, Unmerge with border synchronization
|
|
44
|
+
- **Rich Cell Formatting** — Font family, font size (5–72), bold, italic, underline, strikethrough, text color, fill color, horizontal & vertical alignment, wrap text
|
|
45
|
+
- **Borders** — Top / bottom / left / right / all / none with 5 predefined styles and custom color
|
|
46
|
+
- **Undo / Redo** — Full state snapshots for cells, column widths, and row heights (50 steps)
|
|
47
|
+
- **Format Painter** — Copy & apply cell formatting across ranges
|
|
48
|
+
|
|
49
|
+
### Interaction
|
|
50
|
+
- **Smart Selection** — Click, drag, Shift+Click, row/column header select, corner-cell select-all
|
|
51
|
+
- **Double-Click Editing** — Inline cell editor with `<textarea>` for multi-line input
|
|
52
|
+
- **Formula Bar** — Dedicated input bar with cell label and live formula display
|
|
53
|
+
- **Full Keyboard Navigation** — Arrow keys, Tab, Enter, Home, End, Ctrl+Home, Ctrl+End
|
|
54
|
+
- **Context Menus** — Context-aware menus for cells, rows, columns, sheet tabs, with nested submenus
|
|
55
|
+
- **Row / Column Operations** — Insert, delete, cut, copy, paste via right-click menu
|
|
56
|
+
- **Column Width / Row Height** — Drag-to-resize with live preview and double-click auto-fit
|
|
57
|
+
- **Touch Support** — Swipe scrolling, double-tap to edit
|
|
58
|
+
- **Responsive** — ResizeObserver for dynamic container sizing
|
|
59
|
+
|
|
60
|
+
### Visual
|
|
61
|
+
- **Light / Dark Theme** — Full color palette with 50+ CSS custom properties
|
|
62
|
+
- **Internationalization** — English & Chinese (zh-CN) out of the box
|
|
63
|
+
- **Overflow Toolbar** — Responsive toolbar that automatically collapses overflow buttons into a dropdown menu
|
|
64
|
+
- **Custom Scrollbars** — Native-styled scrollbars with arrow buttons and draggable thumbs
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# pnpm (recommended)
|
|
72
|
+
pnpm add xiaodao-spreader
|
|
73
|
+
|
|
74
|
+
# npm
|
|
75
|
+
npm install xiaodao-spreader
|
|
76
|
+
|
|
77
|
+
# yarn
|
|
78
|
+
yarn add xiaodao-spreader
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Peer Dependencies
|
|
82
|
+
|
|
83
|
+
- `vue` ^3.4.0
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
7
87
|
## Quick Start
|
|
8
88
|
|
|
9
89
|
```bash
|
|
90
|
+
# Clone the repository
|
|
91
|
+
git clone https://github.com/xiaodaozhi/xiaodao-spreader.git
|
|
92
|
+
cd xiaodao-spreader
|
|
93
|
+
|
|
94
|
+
# Install dependencies
|
|
10
95
|
pnpm install
|
|
96
|
+
|
|
97
|
+
# Start dev server
|
|
11
98
|
pnpm dev
|
|
12
99
|
```
|
|
13
100
|
|
|
101
|
+
Navigate to `http://localhost:5173` to see the demo application.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
14
105
|
## Basic Usage
|
|
15
106
|
|
|
16
107
|
```vue
|
|
17
108
|
<template>
|
|
18
|
-
<
|
|
109
|
+
<Spreader
|
|
110
|
+
v-model:data="myData"
|
|
111
|
+
:row-count="100"
|
|
112
|
+
:col-count="12"
|
|
113
|
+
theme="light"
|
|
114
|
+
locale="zh-CN"
|
|
115
|
+
/>
|
|
19
116
|
</template>
|
|
20
117
|
|
|
21
118
|
<script setup lang="ts">
|
|
22
|
-
import { ref } from 'vue'
|
|
23
|
-
import
|
|
119
|
+
import { ref } from 'vue';
|
|
120
|
+
import Spreader from 'xiaodao-spreader';
|
|
121
|
+
import type { SheetModelData } from 'xiaodao-spreader';
|
|
24
122
|
|
|
25
|
-
const myData = ref([
|
|
123
|
+
const myData = ref<SheetModelData[]>([
|
|
124
|
+
{
|
|
125
|
+
name: 'Sheet1',
|
|
126
|
+
cells: {
|
|
127
|
+
'0,0': { value: 'Name' },
|
|
128
|
+
'0,1': { value: 'Age' },
|
|
129
|
+
'1,0': { value: 'Alice', style: { fontSize: 14, fontWeight: 'bold' } },
|
|
130
|
+
'1,1': { value: '28' },
|
|
131
|
+
},
|
|
132
|
+
colWidths: { 0: 120, 1: 80 },
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
26
135
|
</script>
|
|
27
136
|
```
|
|
28
137
|
|
|
138
|
+
---
|
|
139
|
+
|
|
29
140
|
## Props
|
|
30
141
|
|
|
31
142
|
| Prop | Type | Default | Description |
|
|
@@ -33,59 +144,313 @@ const myData = ref([])
|
|
|
33
144
|
| `data` (v-model) | `SheetModelData[]` | `[]` | Multi-sheet data (two-way binding) |
|
|
34
145
|
| `rowCount` | `number` | `200` | Total rows per sheet |
|
|
35
146
|
| `colCount` | `number` | `26` | Total columns per sheet |
|
|
36
|
-
| `width` | `number \| string` | — | Component width (
|
|
37
|
-
| `height` | `number \| string` | — | Component height (
|
|
147
|
+
| `width` | `number \| string` | — | Component width (pixels; omit or pass `string` for responsive) |
|
|
148
|
+
| `height` | `number \| string` | — | Component height (pixels; omit or pass `string` for responsive) |
|
|
38
149
|
| `theme` | `'light' \| 'dark'` | `'light'` | Theme mode |
|
|
39
|
-
| `locale` | `string` | `'zh-CN'` | Language
|
|
150
|
+
| `locale` | `string` | `'zh-CN'` | Language — `'zh-CN'` \| `'en-US'` |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Data Model
|
|
155
|
+
|
|
156
|
+
### `SheetModelData`
|
|
40
157
|
|
|
41
|
-
|
|
158
|
+
The external data format used for v-model two-way binding:
|
|
42
159
|
|
|
43
160
|
```typescript
|
|
44
161
|
interface SheetModelData {
|
|
45
|
-
name: string
|
|
46
|
-
cells: Record<string, {
|
|
47
|
-
|
|
48
|
-
|
|
162
|
+
name: string;
|
|
163
|
+
cells: Record<string, {
|
|
164
|
+
value: string;
|
|
165
|
+
style?: Record<string, unknown>;
|
|
166
|
+
}>;
|
|
167
|
+
merges?: Record<string, SelectionRange>;
|
|
168
|
+
colWidths?: Record<number, number>;
|
|
169
|
+
rowHeights?: Record<number, number>;
|
|
49
170
|
}
|
|
50
171
|
```
|
|
51
172
|
|
|
52
|
-
|
|
173
|
+
- **`cells`**: Key is `"col,row"` (e.g., `"0,0"` for cell A1).
|
|
174
|
+
- **`style`**: Arbitrary CSS-like style properties (`fontSize`, `fontWeight`, `color`, `background`, etc.).
|
|
175
|
+
- **`merges`**: Merge cell definitions, keyed by merge anchor cell.
|
|
176
|
+
- **`colWidths` / `rowHeights`**: Sparse maps — only stores non-default values.
|
|
53
177
|
|
|
54
|
-
|
|
178
|
+
### Type Exports
|
|
55
179
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
180
|
+
```typescript
|
|
181
|
+
import type {
|
|
182
|
+
CellCoord, // { col: number; row: number }
|
|
183
|
+
SelectionRange, // { startCol; startRow; endCol; endRow }
|
|
184
|
+
CellData, // { value: string; style: Record<string, unknown> | null }
|
|
185
|
+
Range, // { start: number; end: number }
|
|
186
|
+
SpreadsheetOptions,
|
|
187
|
+
SpreadsheetData,
|
|
188
|
+
SheetModelData, // ← main data interface
|
|
189
|
+
SheetState, // internal runtime state
|
|
190
|
+
UndoSnapshot,
|
|
191
|
+
ContextMenuItem,
|
|
192
|
+
ThemeColors,
|
|
193
|
+
Point,
|
|
194
|
+
} from 'xiaodao-spreader';
|
|
195
|
+
```
|
|
72
196
|
|
|
73
|
-
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Architecture
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
src/
|
|
203
|
+
├── components/
|
|
204
|
+
│ └── spreader.ts # Barrel export (unified entry point)
|
|
205
|
+
│ └── spreader/
|
|
206
|
+
│ ├── components/
|
|
207
|
+
│ │ ├── spreadsheet.vue # Main component — template + style + composition
|
|
208
|
+
│ │ ├── toolbar.vue # Toolbar with overflow dropdown
|
|
209
|
+
│ │ ├── tabbar.vue # Sheet tab bar
|
|
210
|
+
│ │ ├── dropdown.vue # Generic dropdown component
|
|
211
|
+
│ │ └── pickers/
|
|
212
|
+
│ │ ├── colorPicker.vue
|
|
213
|
+
│ │ ├── borderPicker.vue
|
|
214
|
+
│ │ └── mergePicker.vue
|
|
215
|
+
│ ├── composables/
|
|
216
|
+
│ │ ├── core-state.ts # Props, cells/merges/selection, font metrics, navigation
|
|
217
|
+
│ │ ├── undo-styles.ts # Undo/redo, format painter, font/alignment/color
|
|
218
|
+
│ │ ├── borders-merge.ts # Border sync, merge ops, clipboard, sum
|
|
219
|
+
│ │ ├── sheets-ops.ts # Row/col ops, multi-sheet, v-model emit, theme, refs
|
|
220
|
+
│ │ └── interactions.ts # Renderer, formula bar, tab bar, context menu, scrollbar, events
|
|
221
|
+
│ └── core/
|
|
222
|
+
│ ├── constants.ts # Layout constants, i18n, theme palettes
|
|
223
|
+
│ ├── types.ts # All type definitions
|
|
224
|
+
│ ├── formula.ts # Formula engine (parse, evaluate, deps, cache)
|
|
225
|
+
│ ├── theme.ts # Theme CSS variable construction
|
|
226
|
+
│ └── utils.ts # Pure utilities (col label, hit test, resolve size)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Design Principles
|
|
230
|
+
|
|
231
|
+
- **Composition API**: All business logic extracted into `composables/`, maintaining single-responsibility modules
|
|
232
|
+
- **Canvas 2D Rendering**: Only visible cells are drawn (virtual rendering), ensuring smooth performance on large sheets
|
|
233
|
+
- **No Dirty Flags**: Manual `scheduleRender()` calls at interaction end-points; `requestAnimationFrame` automatically merges multiple calls within the same frame
|
|
234
|
+
- **Shared State**: A central `CoreState` object is injected into each composable, enabling cross-module communication without tight coupling
|
|
235
|
+
- **Reactive Wrap**: Composable return values are wrapped in `reactive()` for automatic ref/computed unwrapping in templates
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Keyboard Shortcuts
|
|
240
|
+
|
|
241
|
+
### Navigation
|
|
242
|
+
|
|
243
|
+
| Keys | Action |
|
|
244
|
+
|------|--------|
|
|
245
|
+
| `↑` `↓` `←` `→` | Move active cell |
|
|
246
|
+
| `Tab` / `Shift+Tab` | Move right / left |
|
|
247
|
+
| `Enter` / `Shift+Enter` | Move down / up |
|
|
248
|
+
| `Home` / `End` | Jump to first / last column |
|
|
249
|
+
| `Ctrl+Home` / `Ctrl+End` | Jump to A1 / bottom-right |
|
|
250
|
+
| `PageUp` / `PageDown` | Scroll one page up / down |
|
|
251
|
+
|
|
252
|
+
### Editing
|
|
253
|
+
|
|
254
|
+
| Keys | Action |
|
|
255
|
+
|------|--------|
|
|
256
|
+
| `F2` / `双击` / `直接输入` | Enter edit mode |
|
|
257
|
+
| `Enter` (in edit) | Commit and move down |
|
|
258
|
+
| `Tab` (in edit) | Commit and move right |
|
|
259
|
+
| `Escape` (in edit) | Cancel edit |
|
|
260
|
+
| `Ctrl+Enter` | Line break in multi-line cells |
|
|
261
|
+
| `Delete` / `Backspace` | Clear selection |
|
|
262
|
+
|
|
263
|
+
### Clipboard & History
|
|
264
|
+
|
|
265
|
+
| Keys | Action |
|
|
266
|
+
|------|--------|
|
|
267
|
+
| `Ctrl+C` / `Ctrl+X` / `Ctrl+V` | Copy / Cut / Paste |
|
|
268
|
+
| `Ctrl+Z` / `Ctrl+Y` | Undo / Redo |
|
|
269
|
+
| `Ctrl+A` | Select all |
|
|
270
|
+
|
|
271
|
+
### Formatting
|
|
272
|
+
|
|
273
|
+
| Keys | Action |
|
|
274
|
+
|------|--------|
|
|
275
|
+
| `Ctrl+B` | Bold |
|
|
276
|
+
| `Ctrl+I` | Italic |
|
|
277
|
+
| `Ctrl+U` | Underline |
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Formula Engine
|
|
282
|
+
|
|
283
|
+
### Supported Formulas
|
|
284
|
+
|
|
285
|
+
| Formula | Syntax | Description |
|
|
286
|
+
|---------|--------|-------------|
|
|
287
|
+
| `SUM` | `=SUM(A1:B5)` | Range summation |
|
|
288
|
+
| Absolute ref | `$A$1` | Lock column and row |
|
|
289
|
+
| Mixed ref | `$A1`, `A$1` | Lock column or row only |
|
|
290
|
+
|
|
291
|
+
### Dependency Tracking
|
|
292
|
+
|
|
293
|
+
The `FormulaDeps` class maintains a bidirectional dependency graph:
|
|
294
|
+
|
|
295
|
+
- **Forward**: `formulaKey` → `[depKey, ...]` — which cells a formula references
|
|
296
|
+
- **Reverse**: `depKey` → `Set<formulaKey>` — which formulas depend on a cell
|
|
297
|
+
|
|
298
|
+
When a cell changes, dirty flags propagate through the reverse graph. Circular references (depth > 20) return `#ERROR`.
|
|
299
|
+
|
|
300
|
+
### Reference Offsetting During Paste
|
|
74
301
|
|
|
75
|
-
|
|
76
|
-
- **Build**: Vite 5
|
|
77
|
-
- **Language**: TypeScript (strict)
|
|
78
|
-
- **Rendering**: Canvas 2D
|
|
79
|
-
- **Package Manager**: pnpm
|
|
302
|
+
`shiftFormulaRefs()` automatically adjusts cell references in formulas when pasting, with `$` absolute reference locking.
|
|
80
303
|
|
|
81
|
-
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Theming
|
|
307
|
+
|
|
308
|
+
### Built-in Themes
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import type { ThemeColors } from 'xiaodao-spreader';
|
|
312
|
+
|
|
313
|
+
const lightTheme: ThemeColors = { /* 50+ color fields */ };
|
|
314
|
+
const darkTheme: ThemeColors = { /* 50+ color fields */ };
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### CSS Variable Injection
|
|
318
|
+
|
|
319
|
+
Theme colors are injected via CSS custom properties (`--sp-*`):
|
|
320
|
+
|
|
321
|
+
```css
|
|
322
|
+
--sp-bg, --sp-gridBg, --sp-gridLine, --sp-selectionBg,
|
|
323
|
+
--sp-headerBg, --sp-headerBorder, --sp-headerText,
|
|
324
|
+
--sp-formulaBarBg, --sp-formulaBarInputBorder,
|
|
325
|
+
--sp-wrapperBg, --sp-cellEditorBorder,
|
|
326
|
+
/* ... and many more */
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Custom Theme
|
|
330
|
+
|
|
331
|
+
Pass `theme="dark"` for dark mode, or create a wrapper component that overrides CSS variables for full customization:
|
|
332
|
+
|
|
333
|
+
```vue
|
|
334
|
+
<template>
|
|
335
|
+
<div style="--sp-bg: #1a1a2e; --sp-cellText: #e0e0e0;">
|
|
336
|
+
<Spreader v-model:data="myData" theme="dark" />
|
|
337
|
+
</div>
|
|
338
|
+
</template>
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Internationalization
|
|
342
|
+
|
|
343
|
+
Built-in languages: `'zh-CN'`, `'en-US'`. Pass via `locale` prop. Right-click menus and toolbar labels are automatically localized.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Development
|
|
82
348
|
|
|
83
349
|
```bash
|
|
84
|
-
|
|
85
|
-
pnpm
|
|
86
|
-
|
|
350
|
+
# Install dependencies
|
|
351
|
+
pnpm install
|
|
352
|
+
|
|
353
|
+
# Start dev server (with auto-reload)
|
|
354
|
+
pnpm dev
|
|
355
|
+
|
|
356
|
+
# Type check only
|
|
357
|
+
pnpm type-check
|
|
87
358
|
```
|
|
88
359
|
|
|
89
|
-
|
|
360
|
+
The dev server runs on `http://localhost:5173` by default.
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Building
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
# Production build (type-check + vite build)
|
|
368
|
+
pnpm build
|
|
369
|
+
|
|
370
|
+
# Preview production build
|
|
371
|
+
pnpm preview
|
|
372
|
+
|
|
373
|
+
# Build for demo/testing purposes
|
|
374
|
+
pnpm build:demo
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Build Output
|
|
378
|
+
|
|
379
|
+
| File | Description |
|
|
380
|
+
|------|-------------|
|
|
381
|
+
| `dist/xiaodao-spreader.es.js` | ES module (for bundlers) |
|
|
382
|
+
| `dist/xiaodao-spreader.umd.js` | UMD bundle (for direct `<script>` usage) |
|
|
383
|
+
| `dist/xiaodao-spreader.css` | Extracted stylesheet |
|
|
384
|
+
| `dist/types/` | TypeScript declaration files |
|
|
385
|
+
|
|
386
|
+
### CI/CD
|
|
387
|
+
|
|
388
|
+
The project includes a GitHub Actions workflow (`.github/workflows/publish.yml`) for automated publishing to npm.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Roadmap
|
|
393
|
+
|
|
394
|
+
### Near-term
|
|
395
|
+
|
|
396
|
+
- [ ] More formulas: `AVERAGE`, `COUNT`, `IF`, `VLOOKUP`, `CONCATENATE`
|
|
397
|
+
- [ ] Cell background color picker
|
|
398
|
+
- [ ] Number format (currency, percentage, date, number of decimals)
|
|
399
|
+
- [ ] Conditional formatting rules
|
|
400
|
+
- [ ] Auto-fill drag handle
|
|
401
|
+
- [ ] Find & Replace
|
|
402
|
+
|
|
403
|
+
### Mid-term
|
|
404
|
+
|
|
405
|
+
- [ ] Frozen panes (freeze rows/columns)
|
|
406
|
+
- [ ] Data validation (dropdown lists, input constraints)
|
|
407
|
+
- [ ] Column / row grouping and collapsing
|
|
408
|
+
- [ ] Sort & filter
|
|
409
|
+
- [ ] Cell comments / notes
|
|
410
|
+
- [ ] Print layout
|
|
411
|
+
|
|
412
|
+
### Long-term
|
|
413
|
+
|
|
414
|
+
- [ ] OffscreenCanvas + Web Worker for multi-threaded rendering
|
|
415
|
+
- [ ] Shared worker for cross-tab collaboration
|
|
416
|
+
- [ ] Plugin system for custom cell renderers
|
|
417
|
+
- [ ] Excel / CSV import & export
|
|
418
|
+
- [ ] Chart engine (embedded mini-charts)
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Tech Stack
|
|
423
|
+
|
|
424
|
+
| Layer | Technology | Version |
|
|
425
|
+
|-------|-----------|---------|
|
|
426
|
+
| Framework | Vue 3 (Composition API + `<script setup>`) | ^3.4 |
|
|
427
|
+
| Build | Vite | ^5.0 |
|
|
428
|
+
| Language | TypeScript (strict) | ~5.4 |
|
|
429
|
+
| Rendering | Canvas 2D API | — |
|
|
430
|
+
| Type Checker | vue-tsc | ^2.2 |
|
|
431
|
+
| Package Manager | pnpm | — |
|
|
432
|
+
| CSS | Scoped CSS + CSS Custom Properties | — |
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Contributing
|
|
437
|
+
|
|
438
|
+
Contributions are welcome! Please feel free to:
|
|
439
|
+
|
|
440
|
+
1. Fork the repository
|
|
441
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
442
|
+
3. Commit your changes (`git commit -m 'feat: add amazing feature'`)
|
|
443
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
444
|
+
5. Open a Pull Request
|
|
445
|
+
|
|
446
|
+
Before submitting, please ensure the type check passes (`pnpm type-check`) and the build succeeds (`pnpm build`).
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## License
|
|
451
|
+
|
|
452
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|
|
453
|
+
|
|
454
|
+
---
|
|
90
455
|
|
|
91
|
-
|
|
456
|
+
**Crafted with care by [xiaodaozhi](https://github.com/xiaodaozhi)**
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.sp-dropdown[data-v-47e5c681]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-47e5c681]{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-47e5c681]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-47e5c681]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-47e5c681]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-47e5c681]{width:12px;height:12px;min-width:12px;opacity:.7}.sp-dropdown__menu[data-v-47e5c681]{position:fixed;z-index:20000;display:flex;flex-direction:column;background:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 2px 8px #00000026;padding:4px 0;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-47e5c681]{transform-origin:bottom center}.menu-pop-enter-active[data-v-47e5c681],.menu-pop-leave-active[data-v-47e5c681]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-47e5c681],.menu-pop-leave-to[data-v-47e5c681]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-47e5c681]{display:flex;align-items:center;justify-content:center;height:15px;min-height:15px;border:none;background:transparent;color:#666;cursor:pointer;padding:0}.sp-dropdown__nav[data-v-47e5c681]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-47e5c681]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-47e5c681]{width:10px;height:10px}.sp-dropdown__list[data-v-47e5c681]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__item[data-v-47e5c681]{display:block;width:100%;height:26px;min-height:26px;border:none;background:transparent;color:#333;font-size:13px;text-align:left;cursor:pointer;padding:0 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box}.sp-dropdown__item[data-v-47e5c681]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-47e5c681]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-c262a5e5]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-c262a5e5]{position:absolute;top:calc(100% + 4px);right:0;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-c262a5e5],.menu-pop-leave-active[data-v-c262a5e5]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-c262a5e5],.menu-pop-leave-to[data-v-c262a5e5]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-c262a5e5]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-c262a5e5]:last-child{margin-bottom:0}.color-picker__swatch[data-v-c262a5e5]{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-c262a5e5]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-c262a5e5]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-c9b0ba80]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-c9b0ba80]{position:absolute;top:calc(100% + 4px);right:0;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-c9b0ba80]{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-c9b0ba80]:hover{background:#eef3f9}.border-picker__icon[data-v-c9b0ba80]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-c9b0ba80]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-c9b0ba80],.menu-pop-leave-active[data-v-c9b0ba80]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-c9b0ba80],.menu-pop-leave-to[data-v-c9b0ba80]{opacity:0;transform:scale(.9)}.toolbar[data-v-69401a37]{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-69401a37]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-69401a37]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-69401a37]{flex:0 0 auto}.toolbar-font-size[data-v-69401a37]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-69401a37]{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:center;padding:0 2px;outline:none;box-sizing:border-box}.toolbar-font-size__input[data-v-69401a37]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-69401a37]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-69401a37]{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-69401a37]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-69401a37]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-69401a37]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-69401a37]{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-69401a37]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-69401a37]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-69401a37]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-69401a37]{width:26px;height:26px}.toolbar-btn--step svg[data-v-69401a37]{width:16px;height:16px}.toolbar-btn[data-v-69401a37]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-69401a37]{width:18px;height:18px}.toolbar-btn svg[data-v-69401a37]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-69401a37]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-69401a37]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-69401a37]{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-69401a37]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-69401a37]{width:10px!important;height:10px!important}.toolbar-more[data-v-69401a37]{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-69401a37]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-69401a37]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-69401a37]{width:18px;height:18px}.overflow-menu[data-v-69401a37]{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-69401a37]{transition:none!important}.overflow-menu .tb-item[data-v-69401a37]{width:100%}.overflow-menu .toolbar-sep[data-v-69401a37]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-69401a37]{width:100%}.overflow-menu .toolbar-split__main[data-v-69401a37]{flex:1 1 auto;justify-content:flex-start}.overflow-menu .toolbar-font-size[data-v-69401a37]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-69401a37]{width:100%}.menu-pop-enter-active[data-v-69401a37],.menu-pop-leave-active[data-v-69401a37]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-69401a37],.menu-pop-leave-to[data-v-69401a37]{opacity:0;transform:scale(.9)}.tab-bar[data-v-49f54625]{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-49f54625]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-49f54625]{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-49f54625]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-49f54625]{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-49f54625]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-49f54625]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-49f54625]{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__add-btn[data-v-49f54625]{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}.tab-bar__add-btn[data-v-49f54625]:hover{background:var(--sp-tab-add-btn-hover-bg)}.spreadsheet-outer[data-v-59bd8e5f]{flex:1;display:flex;flex-direction:column;overflow:hidden}.formula-bar[data-v-59bd8e5f]{display:flex;align-items:start;height:36px;min-height:36px;padding:0;gap:0}.formula-bar__cell-label[data-v-59bd8e5f]{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__input[data-v-59bd8e5f]{flex:1;height:28px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:0 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)}.formula-bar__input[data-v-59bd8e5f]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.spreadsheet-wrapper[data-v-59bd8e5f]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-59bd8e5f]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas[data-v-59bd8e5f]:focus{outline:none}.v-scrollbar[data-v-59bd8e5f]{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-59bd8e5f]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-59bd8e5f]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-59bd8e5f]{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-59bd8e5f]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-59bd8e5f]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-59bd8e5f]{display:block;width:0;height:0}.sb-arrow--up[data-v-59bd8e5f]{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-59bd8e5f]{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-59bd8e5f]{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-59bd8e5f]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-59bd8e5f]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-59bd8e5f]{width:11px}.sb-track--h[data-v-59bd8e5f]{height:11px}.sb-thumb[data-v-59bd8e5f]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-59bd8e5f]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-59bd8e5f]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-59bd8e5f]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-59bd8e5f]{position:absolute;border:2px solid var(--sp-cell-editor-border);outline:none;padding:0 4px;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}.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 20px;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:16px;margin-right:-5px;width:0;height:0;border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid #888}.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: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__unit{font-size:12px;color:#888}.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-8dc09f5d]{position:relative;display:inline-flex;min-width:0}.sp-dropdown__trigger[data-v-8dc09f5d]{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-8dc09f5d]:hover{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6)}.sp-dropdown__trigger--open[data-v-8dc09f5d]{background:var(--sp-toolbar-btn-hover-bg, #e6e6e6);border-color:var(--sp-toolbar-border, #d8d8d8)}.sp-dropdown__value[data-v-8dc09f5d]{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:left}.sp-dropdown__caret[data-v-8dc09f5d]{width:10px;height:10px;min-width:10px;opacity:.7}.sp-dropdown__menu[data-v-8dc09f5d]{position:fixed;z-index:20000;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-8dc09f5d]{transform-origin:bottom center}.menu-pop-enter-active[data-v-8dc09f5d],.menu-pop-leave-active[data-v-8dc09f5d]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-8dc09f5d],.menu-pop-leave-to[data-v-8dc09f5d]{opacity:0;transform:scaleY(.85)}.sp-dropdown__nav[data-v-8dc09f5d]{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-8dc09f5d]:hover:not(:disabled){background:#eef3f9}.sp-dropdown__nav[data-v-8dc09f5d]:disabled{color:#ccc;cursor:default}.sp-dropdown__nav svg[data-v-8dc09f5d]{width:10px;height:10px}.sp-dropdown__list[data-v-8dc09f5d]{display:flex;flex-direction:column;overflow:hidden;touch-action:none}.sp-dropdown__icon[data-v-8dc09f5d]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__icon[data-v-8dc09f5d] svg{width:18px;height:18px;display:block}.sp-dropdown__item-icon[data-v-8dc09f5d]{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.sp-dropdown__item-icon[data-v-8dc09f5d] svg{width:16px;height:16px;display:block}.sp-dropdown__item-label[data-v-8dc09f5d]{white-space:nowrap}.sp-dropdown__item[data-v-8dc09f5d]{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-8dc09f5d]:hover{background:#eef3f9}.sp-dropdown__item--active[data-v-8dc09f5d]{background:#e5f1fb;color:#0078d7}.color-picker[data-v-f00d0dae]{position:relative;display:inline-flex;height:26px}.color-picker__menu[data-v-f00d0dae]{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-f00d0dae],.menu-pop-leave-active[data-v-f00d0dae]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-f00d0dae],.menu-pop-leave-to[data-v-f00d0dae]{opacity:0;transform:scale(.9)}.color-picker__row[data-v-f00d0dae]{display:flex;gap:4px;margin-bottom:4px}.color-picker__row[data-v-f00d0dae]:last-child{margin-bottom:0}.color-picker__swatch[data-v-f00d0dae]{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-f00d0dae]:hover{transform:scale(1.18);box-shadow:0 0 0 1px #0003;z-index:1}.color-picker__swatch--selected[data-v-f00d0dae]{box-shadow:0 0 0 2px #0078d7}.border-picker[data-v-3721e5e4]{position:relative;display:inline-flex;height:26px}.border-picker__menu[data-v-3721e5e4]{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-3721e5e4]{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-3721e5e4]:hover{background:#eef3f9}.border-picker__icon[data-v-3721e5e4]{width:18px;height:18px;flex-shrink:0}.border-picker__label[data-v-3721e5e4]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-3721e5e4],.menu-pop-leave-active[data-v-3721e5e4]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-3721e5e4],.menu-pop-leave-to[data-v-3721e5e4]{opacity:0;transform:scale(.9)}.merge-picker[data-v-24e4dbe5]{position:relative;display:inline-flex;height:26px}.merge-picker__menu[data-v-24e4dbe5]{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-24e4dbe5]{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-24e4dbe5]:hover{background:#eef3f9}.merge-picker__icon[data-v-24e4dbe5]{width:18px;height:18px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.merge-picker__icon[data-v-24e4dbe5] svg{width:18px;height:18px}.merge-picker__label[data-v-24e4dbe5]{overflow:hidden;text-overflow:ellipsis}.menu-pop-enter-active[data-v-24e4dbe5],.menu-pop-leave-active[data-v-24e4dbe5]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-24e4dbe5],.menu-pop-leave-to[data-v-24e4dbe5]{opacity:0;transform:scale(.9)}.toolbar[data-v-c472a142]{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-c472a142]{display:flex;align-items:center;flex:0 0 auto}.toolbar-sep[data-v-c472a142]{width:1px;height:18px;margin:0 4px;background:var(--sp-toolbar-border)}.toolbar-font[data-v-c472a142],.toolbar-align[data-v-c472a142]{flex:0 0 auto}.toolbar-font-size[data-v-c472a142]{display:inline-flex;align-items:center;gap:0;height:26px;position:relative}.toolbar-font-size__input[data-v-c472a142]{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-c472a142]::-webkit-outer-spin-button,.toolbar-font-size__input[data-v-c472a142]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.toolbar-font-size__input[data-v-c472a142]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__input[data-v-c472a142]:focus{border-color:var(--sp-toolbar-border);background:#fff}.toolbar-font-size__btn[data-v-c472a142]{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-c472a142]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-font-size__btn svg[data-v-c472a142]{width:10px;height:10px}.toolbar-font-size__dropdown[data-v-c472a142]{position:absolute;width:56px;height:26px;pointer-events:none}.toolbar-btn[data-v-c472a142]{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-c472a142]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-btn[data-v-c472a142]:active:not(:disabled){opacity:.7}.toolbar-btn--active[data-v-c472a142]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-btn--step[data-v-c472a142]{width:26px;height:26px}.toolbar-btn--step svg[data-v-c472a142]{width:16px;height:16px}.toolbar-btn[data-v-c472a142]:disabled{color:var(--sp-toolbar-btn-disabled-color);cursor:default}.toolbar-btn__icon[data-v-c472a142]{width:18px;height:18px}.toolbar-btn svg[data-v-c472a142]:not(.toolbar-btn__icon){width:18px;height:18px}.toolbar-split[data-v-c472a142]{display:inline-flex;align-items:center;position:relative;height:26px}.toolbar-split__main[data-v-c472a142]{border:1px solid transparent;border-right:none;border-radius:3px 0 0 3px}.toolbar-split__arrow[data-v-c472a142]{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-c472a142]:hover:not(:disabled){background:var(--sp-toolbar-btn-hover-bg)}.toolbar-split__arrow svg[data-v-c472a142]{width:10px!important;height:10px!important}.toolbar-more[data-v-c472a142]{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-c472a142]:hover{background:var(--sp-toolbar-btn-hover-bg)}.toolbar-more--active[data-v-c472a142]{background:var(--sp-toolbar-btn-hover-bg);color:var(--sp-toolbar-btn-active-color)}.toolbar-more svg[data-v-c472a142]{width:18px;height:18px}.overflow-menu[data-v-c472a142]{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-c472a142]{transition:none!important}.overflow-menu .tb-item[data-v-c472a142]{width:100%}.overflow-menu .toolbar-sep[data-v-c472a142]{width:100%;height:1px;margin:2px 0}.overflow-menu .toolbar-split[data-v-c472a142]{width:100%}.overflow-menu .toolbar-split__main[data-v-c472a142]{flex:1 1 auto;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-font-size[data-v-c472a142]{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font[data-v-c472a142],.overflow-menu .toolbar-align[data-v-c472a142]{width:100%}.overflow-menu .toolbar-btn[data-v-c472a142]:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.overflow-menu .toolbar-color[data-v-c472a142]{width:100%}.overflow-menu .toolbar-wrap[data-v-c472a142]{width:100%;justify-content:flex-start}.menu-pop-enter-active[data-v-c472a142],.menu-pop-leave-active[data-v-c472a142]{transition:opacity .12s ease-out,transform .12s ease-out}.menu-pop-enter-from[data-v-c472a142],.menu-pop-leave-to[data-v-c472a142]{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{width:100%;justify-content:flex-start}.overflow-menu .toolbar-font,.overflow-menu .toolbar-align{width:100%}.overflow-menu .toolbar-btn:not(.toolbar-btn--step):not(.toolbar-split__arrow){width:100%;justify-content:flex-start;padding-left:6px}.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-454e1a12]{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-454e1a12]{display:flex;align-items:flex-start;flex:1;overflow:hidden;gap:1px;padding:0 1px}.tab-item[data-v-454e1a12]{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-454e1a12]:hover{background:var(--sp-tab-hover-bg)}.tab-item--active[data-v-454e1a12]{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-454e1a12]:hover{background:var(--sp-tab-active-bg)}.tab-item__name[data-v-454e1a12]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tab-rename-input[data-v-454e1a12]{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__add-btn[data-v-454e1a12]{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}.tab-bar__add-btn[data-v-454e1a12]:hover{background:var(--sp-tab-add-btn-hover-bg)}.spreadsheet-outer[data-v-a5861b41]{flex:1;display:flex;flex-direction:column;overflow:hidden}.formula-bar[data-v-a5861b41]{display:flex;align-items:start;height:36px;min-height:36px;padding:0;gap:0}.formula-bar__cell-label[data-v-a5861b41]{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__input[data-v-a5861b41]{flex:1;height:28px;margin-top:4px;border:1px solid var(--sp-formula-bar-input-border);border-radius:2px;outline:none;padding:0 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)}.formula-bar__input[data-v-a5861b41]:focus{border-color:var(--sp-formula-bar-input-focus-border);box-shadow:0 0 0 1px var(--sp-formula-bar-input-focus-shadow)}.spreadsheet-wrapper[data-v-a5861b41]{flex:1;position:relative;overflow:hidden;background:var(--sp-wrapper-bg)}.grid-canvas[data-v-a5861b41]{position:absolute;top:0;left:0;display:block;outline:none;cursor:cell}.grid-canvas[data-v-a5861b41]:focus{outline:none}.v-scrollbar[data-v-a5861b41]{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-a5861b41]{position:absolute;left:0;bottom:0;height:11px;width:calc(100% - 11px);display:flex;background:var(--sp-wrapper-bg)}.sb-corner[data-v-a5861b41]{position:absolute;right:0;bottom:0;width:11px;height:11px;background:var(--sp-wrapper-bg)}.sb-btn[data-v-a5861b41]{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-a5861b41]:hover{background:var(--sp-scroll-btn-hover-bg, #d0d0d0)}.sb-btn[data-v-a5861b41]:active{background:var(--sp-scroll-btn-active-bg, #c0c0c0)}.sb-arrow[data-v-a5861b41]{display:block;width:0;height:0}.sb-arrow--up[data-v-a5861b41]{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-a5861b41]{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-a5861b41]{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-a5861b41]{border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid var(--sp-scroll-btn-color, #666)}.sb-track[data-v-a5861b41]{flex:1;position:relative;background:var(--sp-scroll-track-bg, rgba(0,0,0,.06))}.sb-track--v[data-v-a5861b41]{width:11px}.sb-track--h[data-v-a5861b41]{height:11px}.sb-thumb[data-v-a5861b41]{position:absolute;border-radius:3px;background:var(--sp-scroll-thumb);cursor:default}.sb-thumb[data-v-a5861b41]:hover{background:var(--sp-scroll-thumb-hover)}.sb-thumb--v[data-v-a5861b41]{left:1px;right:1px;min-height:16px}.sb-thumb--h[data-v-a5861b41]{top:1px;bottom:1px;min-width:16px}.cell-editor[data-v-a5861b41]{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 20px;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:16px;margin-right:-5px;width:0;height:0;border-top:3px solid transparent;border-bottom:3px solid transparent;border-left:4px solid #888}.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: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__unit{font-size:12px;color:#888}.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,27 +1,33 @@
|
|
|
1
|
-
import type { FontOption } from '
|
|
1
|
+
import type { FontOption } from '../core/constants';
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
modelValue: string | number;
|
|
4
4
|
options: FontOption[];
|
|
5
5
|
width?: string | number;
|
|
6
|
+
menuWidth?: string | number;
|
|
6
7
|
visibleCount?: number;
|
|
7
8
|
title?: string;
|
|
8
9
|
modelOpen?: boolean;
|
|
9
10
|
hideTrigger?: boolean;
|
|
11
|
+
align?: 'left' | 'right';
|
|
12
|
+
triggerEl?: HTMLElement | null;
|
|
10
13
|
};
|
|
11
|
-
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
12
|
-
"update:modelValue": (v: string | number) =>
|
|
13
|
-
change: (v: string | number) =>
|
|
14
|
-
"update:modelOpen": (v: boolean) =>
|
|
14
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
15
|
+
"update:modelValue": (v: string | number) => void;
|
|
16
|
+
change: (v: string | number) => void;
|
|
17
|
+
"update:modelOpen": (v: boolean) => void;
|
|
15
18
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
16
19
|
"onUpdate:modelValue"?: ((v: string | number) => any) | undefined;
|
|
17
20
|
onChange?: ((v: string | number) => any) | undefined;
|
|
18
21
|
"onUpdate:modelOpen"?: ((v: boolean) => any) | undefined;
|
|
19
22
|
}>, {
|
|
20
23
|
width: string | number;
|
|
24
|
+
menuWidth: string | number;
|
|
21
25
|
visibleCount: number;
|
|
22
26
|
title: string;
|
|
23
27
|
modelOpen: boolean;
|
|
24
28
|
hideTrigger: boolean;
|
|
29
|
+
align: "left" | "right";
|
|
30
|
+
triggerEl: HTMLElement | null;
|
|
25
31
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
|
|
26
32
|
rootRef: HTMLDivElement;
|
|
27
33
|
menuRef: HTMLDivElement;
|
|
@@ -3,6 +3,7 @@ type __VLS_Props = {
|
|
|
3
3
|
modelOpen?: boolean;
|
|
4
4
|
locale?: string;
|
|
5
5
|
currentBorder?: BorderType;
|
|
6
|
+
triggerEl?: HTMLElement | null;
|
|
6
7
|
};
|
|
7
8
|
declare function openMenu(): void;
|
|
8
9
|
declare function close(): void;
|
|
@@ -18,9 +19,11 @@ declare const _default: import("vue").DefineComponent<__VLS_Props, {
|
|
|
18
19
|
"onUpdate:modelOpen"?: ((v: boolean) => any) | undefined;
|
|
19
20
|
}>, {
|
|
20
21
|
modelOpen: boolean;
|
|
22
|
+
triggerEl: HTMLElement | null;
|
|
21
23
|
locale: string;
|
|
22
24
|
currentBorder: BorderType;
|
|
23
25
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {
|
|
24
26
|
rootRef: HTMLDivElement;
|
|
27
|
+
menuRef: HTMLDivElement;
|
|
25
28
|
}, HTMLDivElement>;
|
|
26
29
|
export default _default;
|