@tita-agent/dsh-data-table 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -2
  3. package/cordis.patch.yml +7 -0
  4. package/lib/client.js +16766 -0
  5. package/lib/contract-envelope.d.ts +91 -0
  6. package/lib/contract-envelope.js +106 -0
  7. package/lib/contract-layout.d.ts +130 -0
  8. package/lib/contract-layout.js +138 -0
  9. package/lib/contract-refs.d.ts +39 -0
  10. package/lib/contract-refs.js +9 -0
  11. package/lib/contract-version.d.ts +311 -0
  12. package/lib/contract-version.js +270 -0
  13. package/lib/contract-wire.d.ts +147 -0
  14. package/lib/contract-wire.js +99 -0
  15. package/lib/contracts.d.ts +12 -0
  16. package/lib/contracts.js +12 -0
  17. package/lib/types/audit.d.ts +42 -0
  18. package/lib/types/audit.js +39 -0
  19. package/lib/types/client/ProjectImportMenu.d.ts +30 -0
  20. package/lib/types/client/ProjectImportMenu.js +70 -0
  21. package/lib/types/client/SheetPanel.d.ts +33 -0
  22. package/lib/types/client/SheetPanel.js +1766 -0
  23. package/lib/types/client/SheetToggle.d.ts +18 -0
  24. package/lib/types/client/SheetToggle.js +26 -0
  25. package/lib/types/client/index.d.ts +15 -0
  26. package/lib/types/client/index.js +110 -0
  27. package/lib/types/client/persistence/changes.d.ts +15 -0
  28. package/lib/types/client/persistence/changes.js +51 -0
  29. package/lib/types/client/persistence/ids.d.ts +34 -0
  30. package/lib/types/client/persistence/ids.js +48 -0
  31. package/lib/types/client/persistence/merge.d.ts +35 -0
  32. package/lib/types/client/persistence/merge.js +362 -0
  33. package/lib/types/client/store.d.ts +61 -0
  34. package/lib/types/client/store.js +152 -0
  35. package/lib/types/client/surface-context.d.ts +27 -0
  36. package/lib/types/client/surface-context.js +104 -0
  37. package/lib/types/client/surface-control.d.ts +2 -0
  38. package/lib/types/client/surface-control.js +12 -0
  39. package/lib/types/client/transport/workbookApi.d.ts +159 -0
  40. package/lib/types/client/transport/workbookApi.js +246 -0
  41. package/lib/types/client/univer/StandaloneWorkbookPage.d.ts +5 -0
  42. package/lib/types/client/univer/StandaloneWorkbookPage.js +7 -0
  43. package/lib/types/client/univer/WorkbookCanvas.d.ts +40 -0
  44. package/lib/types/client/univer/WorkbookCanvas.js +87 -0
  45. package/lib/types/client/univer/WorkbookView.d.ts +3 -0
  46. package/lib/types/client/univer/WorkbookView.js +2 -0
  47. package/lib/types/client/univer/loader.d.ts +18 -0
  48. package/lib/types/client/univer/loader.js +81 -0
  49. package/lib/types/client/univer/standalone-entry.d.ts +1 -0
  50. package/lib/types/client/univer/standalone-entry.js +19 -0
  51. package/lib/types/client/versions/VersionChrome.d.ts +33 -0
  52. package/lib/types/client/versions/VersionChrome.js +21 -0
  53. package/lib/types/client/versions/inspect.d.ts +70 -0
  54. package/lib/types/client/versions/inspect.js +88 -0
  55. package/lib/types/client/versions/preview-decoration.d.ts +11 -0
  56. package/lib/types/client/versions/preview-decoration.js +54 -0
  57. package/lib/types/client/versions/records.d.ts +19 -0
  58. package/lib/types/client/versions/records.js +70 -0
  59. package/lib/types/client/workspace-host.d.ts +61 -0
  60. package/lib/types/client/workspace-host.js +124 -0
  61. package/lib/types/collaboration-hub.d.ts +31 -0
  62. package/lib/types/collaboration-hub.js +69 -0
  63. package/lib/types/contract/ids.d.ts +24 -0
  64. package/lib/types/contract/ids.js +46 -0
  65. package/lib/types/contract/mutations.d.ts +25 -0
  66. package/lib/types/contract/mutations.js +782 -0
  67. package/lib/types/contract/operations.d.ts +54 -0
  68. package/lib/types/contract/operations.js +203 -0
  69. package/lib/types/contract/snapshots.d.ts +176 -0
  70. package/lib/types/contract/snapshots.js +351 -0
  71. package/lib/types/contract/univer-api-catalog.d.ts +29 -0
  72. package/lib/types/contract/univer-api-catalog.js +264 -0
  73. package/lib/types/errors.d.ts +8 -0
  74. package/lib/types/errors.js +12 -0
  75. package/lib/types/http/assets-routes.d.ts +3 -0
  76. package/lib/types/http/assets-routes.js +169 -0
  77. package/lib/types/http/collaboration.d.ts +10 -0
  78. package/lib/types/http/collaboration.js +154 -0
  79. package/lib/types/http/history.d.ts +15 -0
  80. package/lib/types/http/history.js +134 -0
  81. package/lib/types/http/project-files.d.ts +79 -0
  82. package/lib/types/http/project-files.js +206 -0
  83. package/lib/types/http/project-scope.d.ts +50 -0
  84. package/lib/types/http/project-scope.js +52 -0
  85. package/lib/types/http/routes.d.ts +98 -0
  86. package/lib/types/http/routes.js +323 -0
  87. package/lib/types/http/standalone.d.ts +9 -0
  88. package/lib/types/http/standalone.js +31 -0
  89. package/lib/types/http/trunk.d.ts +10 -0
  90. package/lib/types/http/trunk.js +322 -0
  91. package/lib/types/http/worktree.d.ts +9 -0
  92. package/lib/types/http/worktree.js +145 -0
  93. package/lib/types/index.d.ts +18 -0
  94. package/lib/types/index.js +156 -0
  95. package/lib/types/invariant.d.ts +15 -0
  96. package/lib/types/invariant.js +15 -0
  97. package/lib/types/request-params.d.ts +21 -0
  98. package/lib/types/request-params.js +76 -0
  99. package/lib/types/store/paths.d.ts +68 -0
  100. package/lib/types/store/paths.js +148 -0
  101. package/lib/types/store/project.d.ts +88 -0
  102. package/lib/types/store/project.js +120 -0
  103. package/lib/types/store/read.d.ts +110 -0
  104. package/lib/types/store/read.js +404 -0
  105. package/lib/types/store/retention.d.ts +27 -0
  106. package/lib/types/store/retention.js +111 -0
  107. package/lib/types/store/write.d.ts +22 -0
  108. package/lib/types/store/write.js +210 -0
  109. package/lib/types/tools/arguments.d.ts +40 -0
  110. package/lib/types/tools/arguments.js +130 -0
  111. package/lib/types/tools/cells.d.ts +50 -0
  112. package/lib/types/tools/cells.js +298 -0
  113. package/lib/types/tools/index.d.ts +2 -0
  114. package/lib/types/tools/index.js +250 -0
  115. package/lib/types/tools/render.d.ts +47 -0
  116. package/lib/types/tools/render.js +290 -0
  117. package/lib/types/tools/univer-api.d.ts +18 -0
  118. package/lib/types/tools/univer-api.js +198 -0
  119. package/lib/types/tools/workbook-catalog.d.ts +3 -0
  120. package/lib/types/tools/workbook-catalog.js +83 -0
  121. package/lib/types/tools/workbook-edit.d.ts +192 -0
  122. package/lib/types/tools/workbook-edit.js +912 -0
  123. package/lib/types/tools/workbook-find.d.ts +11 -0
  124. package/lib/types/tools/workbook-find.js +89 -0
  125. package/lib/types/tools/workbook-history.d.ts +2 -0
  126. package/lib/types/tools/workbook-history.js +59 -0
  127. package/lib/types/tools/workbook-read.d.ts +21 -0
  128. package/lib/types/tools/workbook-read.js +204 -0
  129. package/lib/types/types.d.ts +377 -0
  130. package/lib/types/types.js +34 -0
  131. package/lib/types/univer/apply-operation.d.ts +14 -0
  132. package/lib/types/univer/apply-operation.js +398 -0
  133. package/lib/types/univer/chunk.d.ts +68 -0
  134. package/lib/types/univer/chunk.js +16 -0
  135. package/lib/types/univer/decoration.d.ts +34 -0
  136. package/lib/types/univer/decoration.js +88 -0
  137. package/lib/types/univer/diagnostics.d.ts +31 -0
  138. package/lib/types/univer/diagnostics.js +141 -0
  139. package/lib/types/univer/engine.d.ts +33 -0
  140. package/lib/types/univer/engine.js +338 -0
  141. package/lib/types/univer/entry.d.ts +8 -0
  142. package/lib/types/univer/entry.js +11 -0
  143. package/lib/types/univer/facade.d.ts +107 -0
  144. package/lib/types/univer/facade.js +1 -0
  145. package/lib/types/univer/fonts.d.ts +202 -0
  146. package/lib/types/univer/fonts.js +140 -0
  147. package/lib/types/univer/plugins/collaboration.d.ts +23 -0
  148. package/lib/types/univer/plugins/collaboration.js +47 -0
  149. package/lib/types/univer/plugins/export.d.ts +39 -0
  150. package/lib/types/univer/plugins/export.js +246 -0
  151. package/lib/types/univer/plugins/history.d.ts +24 -0
  152. package/lib/types/univer/plugins/history.js +50 -0
  153. package/lib/types/univer/plugins/version.d.ts +13 -0
  154. package/lib/types/univer/plugins/version.js +13 -0
  155. package/lib/types/version/diff.d.ts +36 -0
  156. package/lib/types/version/diff.js +156 -0
  157. package/lib/types/version/grouping.d.ts +7 -0
  158. package/lib/types/version/grouping.js +94 -0
  159. package/lib/types/version/records.d.ts +17 -0
  160. package/lib/types/version/records.js +102 -0
  161. package/lib/types/version/session.d.ts +36 -0
  162. package/lib/types/version/session.js +89 -0
  163. package/lib/types/version/summary.d.ts +24 -0
  164. package/lib/types/version/summary.js +111 -0
  165. package/lib/types/workbook-manager.d.ts +191 -0
  166. package/lib/types/workbook-manager.js +935 -0
  167. package/lib/types/xlsx-export-worker.d.ts +5 -0
  168. package/lib/types/xlsx-export-worker.js +24 -0
  169. package/lib/types/xlsx-export.d.ts +21 -0
  170. package/lib/types/xlsx-export.js +371 -0
  171. package/lib/types/xlsx-import-worker.d.ts +1 -0
  172. package/lib/types/xlsx-import-worker.js +19 -0
  173. package/lib/univer-client.js +690 -0
  174. package/lib/workbook-page.js +23826 -0
  175. package/lib/xlsx-export-worker.js +104 -0
  176. package/lib/xlsx-import-worker.js +46 -0
  177. package/package.json +106 -3
  178. package/src/audit.ts +58 -0
  179. package/src/client/ProjectImportMenu.tsx +100 -0
  180. package/src/client/SheetPanel.module.css +1578 -0
  181. package/src/client/SheetPanel.tsx +1934 -0
  182. package/src/client/SheetToggle.module.css +73 -0
  183. package/src/client/SheetToggle.tsx +65 -0
  184. package/src/client/contract.d.ts +19 -0
  185. package/src/client/index.ts +131 -0
  186. package/src/client/persistence/changes.ts +58 -0
  187. package/src/client/persistence/ids.ts +60 -0
  188. package/src/client/persistence/merge.ts +392 -0
  189. package/src/client/store.ts +188 -0
  190. package/src/client/surface-context.ts +123 -0
  191. package/src/client/surface-control.ts +13 -0
  192. package/src/client/transport/workbookApi.ts +355 -0
  193. package/src/client/univer/SheetView.module.css +110 -0
  194. package/src/client/univer/StandaloneWorkbookPage.module.css +8 -0
  195. package/src/client/univer/StandaloneWorkbookPage.tsx +15 -0
  196. package/src/client/univer/WorkbookCanvas.tsx +128 -0
  197. package/src/client/univer/WorkbookView.module.css +30 -0
  198. package/src/client/univer/WorkbookView.tsx +3 -0
  199. package/src/client/univer/loader.ts +90 -0
  200. package/src/client/univer/react-dom-client.d.ts +10 -0
  201. package/src/client/univer/standalone-entry.tsx +19 -0
  202. package/src/client/univer/standalone.css +12 -0
  203. package/src/client/univer/univer-locales.d.ts +89 -0
  204. package/src/client/univer/univer-modules.d.ts +26 -0
  205. package/src/client/versions/VersionChrome.tsx +114 -0
  206. package/src/client/versions/inspect.ts +138 -0
  207. package/src/client/versions/preview-decoration.ts +54 -0
  208. package/src/client/versions/records.ts +78 -0
  209. package/src/client/workspace-host.ts +147 -0
  210. package/src/collaboration-hub.ts +83 -0
  211. package/src/contract/ids.ts +50 -0
  212. package/src/contract/mutations.ts +791 -0
  213. package/src/contract/operations.ts +221 -0
  214. package/src/contract/snapshots.ts +383 -0
  215. package/src/contract/univer-api-catalog.ts +289 -0
  216. package/src/css-modules.d.ts +6 -0
  217. package/src/errors.ts +25 -0
  218. package/src/http/assets-routes.ts +177 -0
  219. package/src/http/collaboration.ts +144 -0
  220. package/src/http/history.ts +151 -0
  221. package/src/http/project-files.ts +227 -0
  222. package/src/http/project-scope.ts +77 -0
  223. package/src/http/routes.ts +364 -0
  224. package/src/http/standalone.ts +32 -0
  225. package/src/http/trunk.ts +322 -0
  226. package/src/http/worktree.ts +119 -0
  227. package/src/index.ts +165 -0
  228. package/src/invariant.ts +17 -0
  229. package/src/request-params.ts +92 -0
  230. package/src/store/paths.ts +165 -0
  231. package/src/store/project.ts +137 -0
  232. package/src/store/read.ts +454 -0
  233. package/src/store/retention.ts +106 -0
  234. package/src/store/write.ts +230 -0
  235. package/src/tools/arguments.ts +128 -0
  236. package/src/tools/cells.ts +298 -0
  237. package/src/tools/index.ts +274 -0
  238. package/src/tools/render.ts +301 -0
  239. package/src/tools/univer-api.ts +243 -0
  240. package/src/tools/workbook-catalog.ts +94 -0
  241. package/src/tools/workbook-edit.ts +987 -0
  242. package/src/tools/workbook-find.ts +80 -0
  243. package/src/tools/workbook-history.ts +63 -0
  244. package/src/tools/workbook-read.ts +210 -0
  245. package/src/types.ts +432 -0
  246. package/src/univer/apply-operation.ts +369 -0
  247. package/src/univer/chunk.ts +77 -0
  248. package/src/univer/decoration.ts +111 -0
  249. package/src/univer/diagnostics.ts +136 -0
  250. package/src/univer/engine.ts +370 -0
  251. package/src/univer/entry.ts +14 -0
  252. package/src/univer/facade.ts +91 -0
  253. package/src/univer/fonts.ts +148 -0
  254. package/src/univer/overrides.css +33 -0
  255. package/src/univer/plugins/collaboration.ts +47 -0
  256. package/src/univer/plugins/export.ts +236 -0
  257. package/src/univer/plugins/history.ts +49 -0
  258. package/src/univer/plugins/version.ts +13 -0
  259. package/src/version/diff.ts +169 -0
  260. package/src/version/grouping.ts +96 -0
  261. package/src/version/records.ts +113 -0
  262. package/src/version/session.ts +90 -0
  263. package/src/version/summary.ts +117 -0
  264. package/src/workbook-manager.ts +1111 -0
  265. package/src/xlsx-export-worker.ts +34 -0
  266. package/src/xlsx-export.ts +373 -0
  267. package/src/xlsx-import-worker.ts +30 -0
@@ -0,0 +1,148 @@
1
+ import { DEFAULT_SHEET_FONT_FAMILY } from '../contract/snapshots.ts'
2
+
3
+ export interface DataSheetFontConfig {
4
+ value: string
5
+ label: string
6
+ category: 'sans-serif' | 'serif'
7
+ }
8
+
9
+ /**
10
+ * Additional font families exposed by the Datasheet Univer residency.
11
+ *
12
+ * This is intentionally a candidate list, not a bundled-font list. The
13
+ * browser-side probe below removes entries that are not installed on the
14
+ * current machine, while keeping the dropdown useful across macOS, Windows,
15
+ * Linux and common Chinese-font setups.
16
+ */
17
+ export const DATA_SHEET_CUSTOM_FONT_CONFIGS = [
18
+ {
19
+ // macOS family name for Simplified Chinese PingFang.
20
+ value: 'PingFang SC',
21
+ label: '苹方(简体中文)',
22
+ category: 'sans-serif' as const,
23
+ },
24
+ {
25
+ // Keep the Traditional Chinese family available on macOS as well.
26
+ value: 'PingFang TC',
27
+ label: '苹方(繁体中文)',
28
+ category: 'sans-serif' as const,
29
+ },
30
+ {
31
+ // The CSS family name used by the JD Lang Zhengti font files.
32
+ value: 'JingDongLangZhengTi',
33
+ label: '京东朗正体',
34
+ category: 'sans-serif' as const,
35
+ },
36
+ { value: 'Helvetica', label: 'Helvetica', category: 'sans-serif' as const },
37
+ { value: 'Helvetica Neue', label: 'Helvetica Neue', category: 'sans-serif' as const },
38
+ { value: 'Segoe UI', label: 'Segoe UI', category: 'sans-serif' as const },
39
+ { value: 'Calibri', label: 'Calibri', category: 'sans-serif' as const },
40
+ { value: 'Cambria', label: 'Cambria', category: 'serif' as const },
41
+ { value: 'Georgia', label: 'Georgia', category: 'serif' as const },
42
+ { value: 'Consolas', label: 'Consolas', category: 'sans-serif' as const },
43
+ { value: 'Courier New', label: 'Courier New', category: 'serif' as const },
44
+ { value: 'Trebuchet MS', label: 'Trebuchet MS', category: 'sans-serif' as const },
45
+ { value: 'Gill Sans', label: 'Gill Sans', category: 'sans-serif' as const },
46
+ { value: 'Avenir Next', label: 'Avenir Next', category: 'sans-serif' as const },
47
+ { value: 'Menlo', label: 'Menlo', category: 'sans-serif' as const },
48
+ { value: 'Roboto', label: 'Roboto', category: 'sans-serif' as const },
49
+ { value: 'Noto Sans', label: 'Noto Sans', category: 'sans-serif' as const },
50
+ { value: 'Noto Sans CJK SC', label: 'Noto Sans CJK SC', category: 'sans-serif' as const },
51
+ { value: 'Noto Sans CJK TC', label: 'Noto Sans CJK TC', category: 'sans-serif' as const },
52
+ { value: 'Noto Serif CJK SC', label: 'Noto Serif CJK SC', category: 'serif' as const },
53
+ { value: 'Noto Serif CJK TC', label: 'Noto Serif CJK TC', category: 'serif' as const },
54
+ { value: 'Source Han Sans SC', label: '思源黑体(简体中文)', category: 'sans-serif' as const },
55
+ { value: 'Source Han Sans TC', label: '思源黑体(繁体中文)', category: 'sans-serif' as const },
56
+ { value: 'Source Han Serif SC', label: '思源宋体(简体中文)', category: 'serif' as const },
57
+ { value: 'Source Han Serif TC', label: '思源宋体(繁体中文)', category: 'serif' as const },
58
+ { value: 'WenQuanYi Zen Hei', label: '文泉驿正黑', category: 'sans-serif' as const },
59
+ { value: 'Microsoft JhengHei', label: '微软正黑', category: 'sans-serif' as const },
60
+ { value: 'Microsoft JhengHei UI', label: '微软正黑 UI', category: 'sans-serif' as const },
61
+ { value: 'DengXian', label: '等线', category: 'sans-serif' as const },
62
+ { value: 'STHeiti', label: '华文黑体', category: 'sans-serif' as const },
63
+ { value: 'STSong', label: '华文宋体', category: 'serif' as const },
64
+ { value: 'STKaiti', label: '华文楷体', category: 'serif' as const },
65
+ { value: 'STFangsong', label: '华文仿宋', category: 'serif' as const },
66
+ { value: 'Songti SC', label: '宋体 SC', category: 'serif' as const },
67
+ { value: 'Songti TC', label: '宋体 TC', category: 'serif' as const },
68
+ { value: 'Heiti SC', label: '黑体 SC', category: 'sans-serif' as const },
69
+ { value: 'Hiragino Sans GB', label: '冬青黑体简', category: 'sans-serif' as const },
70
+ { value: 'Hiragino Mincho ProN', label: '冬青明朝体', category: 'serif' as const },
71
+ { value: 'MingLiU', label: '细明体', category: 'serif' as const },
72
+ { value: 'PMingLiU', label: '新细明体', category: 'serif' as const },
73
+ { value: 'Alibaba PuHuiTi 3.0', label: '阿里巴巴普惠体 3.0', category: 'sans-serif' as const },
74
+ { value: 'Alibaba PuHuiTi 2.0', label: '阿里巴巴普惠体 2.0', category: 'sans-serif' as const },
75
+ ] as const
76
+
77
+ /**
78
+ * Univer's built-in list is repeated here so it can be filtered before
79
+ * Univer creates its FontService. Browsers cannot enumerate every system
80
+ * font, so this is a candidate list rather than a system-font API.
81
+ */
82
+ export const DATA_SHEET_FONT_CANDIDATE_CONFIGS: readonly DataSheetFontConfig[] = [
83
+ { value: 'Arial', label: 'ui.fontFamily.arial', category: 'sans-serif' },
84
+ { value: 'Times New Roman', label: 'ui.fontFamily.times-new-roman', category: 'serif' },
85
+ { value: 'Tahoma', label: 'ui.fontFamily.tahoma', category: 'sans-serif' },
86
+ { value: 'Verdana', label: 'ui.fontFamily.verdana', category: 'sans-serif' },
87
+ { value: 'Microsoft YaHei', label: 'ui.fontFamily.microsoft-yahei', category: 'sans-serif' },
88
+ { value: 'SimSun', label: 'ui.fontFamily.simsun', category: 'serif' },
89
+ { value: 'SimHei', label: 'ui.fontFamily.simhei', category: 'sans-serif' },
90
+ { value: 'Kaiti', label: 'ui.fontFamily.kaiti', category: 'serif' },
91
+ { value: 'FangSong', label: 'ui.fontFamily.fangsong', category: 'serif' },
92
+ { value: 'NSimSun', label: 'ui.fontFamily.nsimsun', category: 'serif' },
93
+ { value: 'STXinwei', label: 'ui.fontFamily.stxinwei', category: 'serif' },
94
+ { value: 'STXingkai', label: 'ui.fontFamily.stxingkai', category: 'serif' },
95
+ { value: 'STLiti', label: 'ui.fontFamily.stliti', category: 'serif' },
96
+ ...DATA_SHEET_CUSTOM_FONT_CONFIGS,
97
+ ]
98
+
99
+ /**
100
+ * Filter candidates using the same canvas-metrics check Univer uses for its
101
+ * unsupported-font indicator. This runs before createUniver(), because
102
+ * Univer snapshots the configured list while constructing FontService.
103
+ */
104
+ export function getInstalledFontConfigs(): DataSheetFontConfig[] {
105
+ if (typeof document === 'undefined') return [...DATA_SHEET_FONT_CANDIDATE_CONFIGS]
106
+ const context = document.createElement('canvas').getContext('2d')
107
+ if (context === null) return []
108
+
109
+ // Include CJK glyphs as well as Latin glyphs. Many Chinese fonts share
110
+ // nearly identical Latin metrics, so a Latin-only probe incorrectly hides
111
+ // installed CJK families from the dropdown.
112
+ const sample = 'AaBbMmWw0123456789中文汉字测试東京한글'
113
+ const size = '72px'
114
+ const baseFonts = ['monospace', 'serif', 'sans-serif'] as const
115
+ const defaultWidths = new Map<string, number>()
116
+ for (const base of baseFonts) {
117
+ context.font = `${size} ${base}`
118
+ defaultWidths.set(base, context.measureText(sample).width)
119
+ }
120
+
121
+ return DATA_SHEET_FONT_CANDIDATE_CONFIGS.filter(font => baseFonts.some(base => {
122
+ context.font = `${size} "${font.value}", ${base}`
123
+ return context.measureText(sample).width !== defaultWidths.get(base)
124
+ }))
125
+ }
126
+
127
+ /**
128
+ * Give every sheet the shared default font family.
129
+ *
130
+ * The sheet default is a migration target: this fixes workbooks created before
131
+ * Datasheet switched from Arial to PingFang SC. Cell-level styles stay untouched,
132
+ * so an explicit font choice is still respected.
133
+ */
134
+ export function withDefaultSheetFont(workbookData: object): object {
135
+ const root = workbookData as { sheets?: Record<string, Record<string, unknown>> }
136
+ if (root.sheets === undefined || typeof root.sheets !== 'object') return workbookData
137
+ let changed = false
138
+ const sheets = Object.fromEntries(Object.entries(root.sheets).map(([id, sheet]) => {
139
+ const currentStyle = sheet.defaultStyle
140
+ const defaultStyle = currentStyle !== null && typeof currentStyle === 'object' && !Array.isArray(currentStyle)
141
+ ? currentStyle as Record<string, unknown>
142
+ : {}
143
+ if (defaultStyle.ff === DEFAULT_SHEET_FONT_FAMILY) return [id, sheet]
144
+ changed = true
145
+ return [id, { ...sheet, defaultStyle: { ...defaultStyle, ff: DEFAULT_SHEET_FONT_FAMILY } }]
146
+ }))
147
+ return changed ? { ...root, sheets } : workbookData
148
+ }
@@ -0,0 +1,33 @@
1
+ /* Keep every horizontal Univer menu bar anchored to the left. */
2
+
3
+ [data-u-comp="ribbon-header-menu"] [role="tablist"],
4
+ [data-u-comp="ribbon-toolbar"],
5
+ [data-u-comp="mobile-ribbon-toolbar"],
6
+ [data-u-comp="slide-tab-bar"] {
7
+ justify-content: flex-start !important;
8
+ }
9
+
10
+ /* Make Univer read as the canvas inside the shell, not as a second app bar. */
11
+ [data-u-comp="ribbon-header-menu"],
12
+ [data-u-comp="ribbon-toolbar"],
13
+ [data-u-comp="mobile-ribbon-toolbar"],
14
+ [data-u-comp="slide-tab-bar"] {
15
+ border-color: var(--tita-line) !important;
16
+ background: var(--tita-surface) !important;
17
+ }
18
+
19
+ [data-u-comp="ribbon-toolbar"] {
20
+ min-height: 36px !important;
21
+ }
22
+
23
+ [data-u-comp="ribbon-header-menu"] {
24
+ min-height: 34px !important;
25
+ }
26
+
27
+ [data-u-comp="ribbon-header-menu"] [role="tablist"] {
28
+ min-height: 34px !important;
29
+ }
30
+
31
+ [data-u-comp="slide-tab-bar"] {
32
+ min-height: 28px !important;
33
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Univer-side collaboration seam used by Datasheet.
3
+ *
4
+ * Univer exposes `onMutationExecutedForCollab` specifically for collaboration
5
+ * implementations. We use that native seam, but keep the transport and
6
+ * persistence outside Univer so the plugin does not depend on Univer Pro.
7
+ */
8
+
9
+ import {
10
+ IUniverInstanceService,
11
+ Inject,
12
+ ICommandService,
13
+ Injector,
14
+ Plugin,
15
+ UniverInstanceType,
16
+ type ICommandInfo,
17
+ type IExecutionOptions,
18
+ } from '@univerjs/presets'
19
+ import { UNIVER_PLUGIN_VERSION } from './version.ts'
20
+
21
+ export interface DataSheetCollaborationConfig {
22
+ onMutation?: (commandInfo: Readonly<ICommandInfo>, options?: IExecutionOptions) => void
23
+ }
24
+
25
+ /** Connects Univer's native mutation stream to the Datasheet session. */
26
+ export class DataSheetCollaborationPlugin extends Plugin {
27
+ static override pluginName = 'dsh.data-sheet.collaboration'
28
+ static override packageName = 'dsh-data-table'
29
+ static override version = UNIVER_PLUGIN_VERSION
30
+ static override type = UniverInstanceType.UNIVER_SHEET
31
+
32
+ constructor(
33
+ private readonly _config: DataSheetCollaborationConfig | undefined,
34
+ @Inject(Injector) protected readonly _injector: Injector,
35
+ @ICommandService private readonly _commandService: ICommandService,
36
+ @IUniverInstanceService _univerInstanceService: IUniverInstanceService,
37
+ ) {
38
+ super()
39
+ }
40
+
41
+ override onStarting(): void {
42
+ this.disposeWithMe(this._commandService.onMutationExecutedForCollab((commandInfo, options) => {
43
+ if (options?.onlyLocal || options?.fromChangeset || options?.fromCollab) return
44
+ this._config?.onMutation?.(commandInfo, options)
45
+ }))
46
+ }
47
+ }
@@ -0,0 +1,236 @@
1
+ /**
2
+ * Univer-side export plugin for dsh-data-table.
3
+ *
4
+ * This follows Univer's normal plugin shape: commands are registered with
5
+ * ICommandService. The browser-facing exporter stays a small adapter over
6
+ * the live Workbook model, so menu actions always export the current
7
+ * in-memory edits.
8
+ * @module dsh-data-table/univer-export-plugin
9
+ */
10
+
11
+ import {
12
+ CommandType,
13
+ Inject,
14
+ ICommandService,
15
+ IUniverInstanceService,
16
+ Injector,
17
+ Plugin,
18
+ UniverInstanceType,
19
+ type Workbook,
20
+ } from '@univerjs/presets'
21
+ import { downloadBlob, downloadWorkbookCsv, downloadWorkbookXlsx, readWorkbookXlsx } from '../../xlsx-export.ts'
22
+ import { UNIVER_PLUGIN_VERSION } from './version.ts'
23
+
24
+ function dataSheetAssetPath(path: string): string {
25
+ const transport = (globalThis as { __DSH_TRANSPORT__?: { ownsHost?: boolean } }).__DSH_TRANSPORT__
26
+ return transport?.ownsHost === true
27
+ ? `/api/data-sheet?path=${encodeURIComponent(path)}`
28
+ : path
29
+ }
30
+
31
+ export const EXPORT_CSV_COMMAND_ID = 'dsh.data-sheet.export-csv'
32
+ export const EXPORT_XLSX_COMMAND_ID = 'dsh.data-sheet.export-xlsx'
33
+ export const IMPORT_XLSX_COMMAND_ID = 'dsh.data-sheet.import-xlsx'
34
+
35
+ /** Univer plugin that owns the datasheet export commands and DSH menu bridge. */
36
+ export class DataSheetExportPlugin extends Plugin {
37
+ static override pluginName = 'dsh.data-sheet.export'
38
+ static override packageName = 'dsh-data-table'
39
+ static override version = UNIVER_PLUGIN_VERSION
40
+ static override type = UniverInstanceType.UNIVER_SHEET
41
+
42
+ constructor(
43
+ _config: undefined,
44
+ @Inject(Injector) protected readonly _injector: Injector,
45
+ @ICommandService private readonly _commandService: ICommandService,
46
+ @IUniverInstanceService private readonly _univerInstanceService: IUniverInstanceService,
47
+ ) {
48
+ super()
49
+ }
50
+
51
+ override onStarting(): void {
52
+ this.disposeWithMe(this._commandService.registerCommand({
53
+ id: EXPORT_CSV_COMMAND_ID,
54
+ type: CommandType.COMMAND,
55
+ handler: () => this.export('csv'),
56
+ }))
57
+ this.disposeWithMe(this._commandService.registerCommand({
58
+ id: EXPORT_XLSX_COMMAND_ID,
59
+ type: CommandType.COMMAND,
60
+ handler: () => this.export('xlsx'),
61
+ }))
62
+ this.disposeWithMe(this._commandService.registerCommand({
63
+ id: IMPORT_XLSX_COMMAND_ID,
64
+ type: CommandType.COMMAND,
65
+ handler: () => {
66
+ this.importFile('xlsx')
67
+ return true
68
+ },
69
+ }))
70
+ // The compact DSH header owns import/export. Keep the bridge event-based
71
+ // so the React shell does not depend on Univer's private Injector or
72
+ // command service implementation.
73
+ const onExportCsv = (): void => { void this.export('csv') }
74
+ const onExportXlsx = (): void => { void this.export('xlsx') }
75
+ const onExportJson = (): void => { void this.export('json') }
76
+ const onImportXlsx = (): void => { this.importFile('xlsx') }
77
+ // The project chooser read the file's bytes on the Host side; parsing is the
78
+ // same pipeline, so it enters here rather than in a second implementation.
79
+ const onImportBytes = (event: Event): void => {
80
+ const detail = (event as CustomEvent<{ data?: ArrayBuffer; name?: string }>).detail
81
+ if (detail?.data === undefined) return
82
+ void this.importBuffer(detail.data, detail.name ?? '导入文件')
83
+ }
84
+ document.addEventListener('data-sheet:import-bytes', onImportBytes)
85
+ const onImportCsv = (): void => { this.importFile('csv') }
86
+ window.addEventListener('data-sheet:request-export-csv', onExportCsv)
87
+ window.addEventListener('data-sheet:request-export-xlsx', onExportXlsx)
88
+ window.addEventListener('data-sheet:request-export-json', onExportJson)
89
+ window.addEventListener('data-sheet:request-import-xlsx', onImportXlsx)
90
+ window.addEventListener('data-sheet:request-import-csv', onImportCsv)
91
+ window.addEventListener('data-sheet:import-bytes', onImportBytes)
92
+ this.disposeWithMe({
93
+ dispose: () => {
94
+ window.removeEventListener('data-sheet:request-export-csv', onExportCsv)
95
+ window.removeEventListener('data-sheet:request-export-xlsx', onExportXlsx)
96
+ window.removeEventListener('data-sheet:request-export-json', onExportJson)
97
+ window.removeEventListener('data-sheet:request-import-xlsx', onImportXlsx)
98
+ window.removeEventListener('data-sheet:request-import-csv', onImportCsv)
99
+ window.removeEventListener('data-sheet:import-bytes', onImportBytes)
100
+ },
101
+ })
102
+ }
103
+
104
+ private async export(format: 'csv' | 'xlsx' | 'json'): Promise<boolean> {
105
+ const workbook = this._univerInstanceService.getCurrentUnitOfType<Workbook>(UniverInstanceType.UNIVER_SHEET)
106
+ if (workbook == null) return false
107
+ const snapshot = workbook.getSnapshot()
108
+ const filename = snapshotWorkbookName(snapshot) || workbook.name || 'workbook'
109
+ if (format === 'json') {
110
+ // The workbook snapshot is already the plugin's own persistence format,
111
+ // so a JSON export is a lossless, round-trippable dump.
112
+ downloadBlob(new Blob([JSON.stringify(snapshot, null, 2)], { type: 'application/json;charset=utf-8' }), `${safeFilename(filename)}.json`)
113
+ return true
114
+ }
115
+ try {
116
+ const result = await exportInWorker(format, snapshot)
117
+ if (result === null) return false
118
+ if (format === 'csv') {
119
+ downloadBlob(new Blob([result as string], { type: 'text/csv;charset=utf-8' }), `${safeFilename(filename)}.csv`)
120
+ } else {
121
+ downloadBlob(new Blob([result as ArrayBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), `${safeFilename(filename)}.xlsx`)
122
+ }
123
+ } catch {
124
+ // A server started before the worker route existed, or a restricted
125
+ // browser, still gets a functional export through the synchronous path.
126
+ if (format === 'csv') downloadWorkbookCsv(snapshot, filename)
127
+ else downloadWorkbookXlsx(snapshot, filename)
128
+ }
129
+ return true
130
+ }
131
+
132
+ private importFile(format: 'xlsx' | 'csv'): void {
133
+ const input = document.createElement('input')
134
+ input.type = 'file'
135
+ input.accept = format === 'csv'
136
+ ? '.csv,text/csv'
137
+ : '.xlsx,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel'
138
+ input.addEventListener('change', () => {
139
+ const file = input.files?.[0]
140
+ if (file === undefined) return
141
+ if (file.size > 25 * 1024 * 1024) {
142
+ window.dispatchEvent(new CustomEvent('data-sheet:import-error', { detail: { message: `${format === 'csv' ? 'CSV' : 'Excel'} 文件过大(最大 25 MB)` } }))
143
+ return
144
+ }
145
+ void file.arrayBuffer().then(data => this.importBuffer(data, file.name))
146
+ })
147
+ input.click()
148
+ }
149
+
150
+ /**
151
+ * Parse one buffer and hand the workbook to the panel.
152
+ *
153
+ * Shared by both ways in — the OS file dialog and the project chooser, which
154
+ * reads the bytes over HTTP because a browser cannot open a path. Everything
155
+ * after the bytes arrive is one pipeline, so the two entry points cannot drift
156
+ * into two imports.
157
+ *
158
+ * @param data - The file's bytes.
159
+ * @param name - The name the panel reports and the worker partly decides from.
160
+ */
161
+ private async importBuffer(data: ArrayBuffer, name: string): Promise<void> {
162
+ try {
163
+ const compatibilityCopy = data.slice(0)
164
+ const snapshot = await importInWorker(data, name).catch(error => {
165
+ // Older servers may not expose the worker route. Keep import
166
+ // functional with a synchronous compatibility fallback in that case.
167
+ if (error instanceof Error && /Worker/.test(error.message)) return readWorkbookXlsx(compatibilityCopy, name)
168
+ throw error
169
+ })
170
+ window.dispatchEvent(new CustomEvent('data-sheet:import', { detail: { snapshot, filename: name } }))
171
+ } catch (error) {
172
+ window.dispatchEvent(new CustomEvent('data-sheet:import-error', { detail: { message: error instanceof Error ? error.message : String(error) } }))
173
+ }
174
+ }
175
+ }
176
+
177
+ function importInWorker(data: ArrayBuffer, filename: string): Promise<object> {
178
+ if (typeof Worker === 'undefined') return Promise.reject(new Error('当前浏览器不支持 Worker'))
179
+ return new Promise((resolve, reject) => {
180
+ const worker = new Worker(dataSheetAssetPath('/data-sheet/xlsx-import-worker.js'))
181
+ const timeout = window.setTimeout(() => {
182
+ worker.terminate()
183
+ reject(new Error('导入超时'))
184
+ }, 60_000)
185
+ worker.onmessage = event => {
186
+ window.clearTimeout(timeout)
187
+ worker.terminate()
188
+ const result = event.data as { ok?: boolean; snapshot?: unknown; error?: string }
189
+ if (result.ok !== true || typeof result.snapshot !== 'object' || result.snapshot === null) {
190
+ reject(new Error(result.error ?? '导入失败'))
191
+ } else {
192
+ resolve(result.snapshot as object)
193
+ }
194
+ }
195
+ worker.onerror = event => {
196
+ window.clearTimeout(timeout)
197
+ worker.terminate()
198
+ reject(new Error(event.message || '导入 Worker 加载失败'))
199
+ }
200
+ worker.postMessage({ data, filename }, [data])
201
+ })
202
+ }
203
+
204
+ function snapshotWorkbookName(snapshot: unknown): string | null {
205
+ if (typeof snapshot !== 'object' || snapshot === null) return null
206
+ const name = (snapshot as { name?: unknown }).name
207
+ return typeof name === 'string' && name.trim().length > 0 ? name.trim() : null
208
+ }
209
+
210
+ function exportInWorker(format: 'csv' | 'xlsx', snapshot: unknown): Promise<string | ArrayBuffer | null> {
211
+ if (typeof Worker === 'undefined') return Promise.reject(new Error('当前浏览器不支持 Worker'))
212
+ return new Promise((resolve, reject) => {
213
+ const worker = new Worker(dataSheetAssetPath('/data-sheet/xlsx-export-worker.js'))
214
+ const timeout = window.setTimeout(() => {
215
+ worker.terminate()
216
+ reject(new Error('导出超时'))
217
+ }, 60_000)
218
+ worker.onmessage = event => {
219
+ window.clearTimeout(timeout)
220
+ worker.terminate()
221
+ const data = event.data as { ok?: boolean; value?: unknown; error?: string }
222
+ if (data.ok !== true) reject(new Error(data.error ?? '导出失败'))
223
+ else resolve((data.value ?? null) as string | ArrayBuffer | null)
224
+ }
225
+ worker.onerror = event => {
226
+ window.clearTimeout(timeout)
227
+ worker.terminate()
228
+ reject(new Error(event.message || '导出 Worker 加载失败'))
229
+ }
230
+ worker.postMessage({ format, snapshot })
231
+ })
232
+ }
233
+
234
+ function safeFilename(value: string): string {
235
+ return value.replace(/[\\/:*?"<>|]/g, '-').trim() || 'workbook'
236
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Datasheet edit-history entry point for the open-source Univer canvas.
3
+ *
4
+ * Univer Pro's history viewer is intentionally not used. The DSH host owns
5
+ * durable operation logs/checkpoints and opens its own history panel when the
6
+ * command is executed.
7
+ */
8
+
9
+ import {
10
+ CommandType,
11
+ Inject,
12
+ ICommandService,
13
+ Injector,
14
+ Plugin,
15
+ UniverInstanceType,
16
+ } from '@univerjs/presets'
17
+ import { UNIVER_PLUGIN_VERSION } from './version.ts'
18
+ export const SHOW_HISTORY_COMMAND_ID = 'dsh.data-sheet.show-history'
19
+
20
+ export interface DataSheetHistoryPluginConfig {
21
+ onOpenHistory?: () => void
22
+ }
23
+
24
+ /** Registers the DSH history panel command on the Univer ribbon. */
25
+ export class DataSheetHistoryPlugin extends Plugin {
26
+ static override pluginName = 'dsh.data-sheet.history'
27
+ static override packageName = 'dsh-data-table'
28
+ static override version = UNIVER_PLUGIN_VERSION
29
+ static override type = UniverInstanceType.UNIVER_SHEET
30
+
31
+ constructor(
32
+ private readonly _config: DataSheetHistoryPluginConfig | undefined,
33
+ @Inject(Injector) protected readonly _injector: Injector,
34
+ @ICommandService private readonly _commandService: ICommandService,
35
+ ) {
36
+ super()
37
+ }
38
+
39
+ override onStarting(): void {
40
+ this.disposeWithMe(this._commandService.registerCommand({
41
+ id: SHOW_HISTORY_COMMAND_ID,
42
+ type: CommandType.COMMAND,
43
+ handler: () => {
44
+ this._config?.onOpenHistory?.()
45
+ return true
46
+ },
47
+ }))
48
+ }
49
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The version every Data Sheet Univer plugin declares.
3
+ *
4
+ * Univer's `PluginService` compares a plugin's declared `version` against its
5
+ * core version and logs `Plugin version mismatch` when they differ. Our three
6
+ * adapters are not `@univerjs/*` packages, but declaring the pinned core
7
+ * version is what keeps that warning out of the console.
8
+ *
9
+ * `tests/univer-plugin-version.test.mjs` pins this constant to the installed
10
+ * `@univerjs/presets` version, so upgrading Univer cannot silently bring the
11
+ * warning back.
12
+ */
13
+ export const UNIVER_PLUGIN_VERSION = '0.25.1'