@dou-ui/sheet 0.0.0-stage → 0.1.0-alpha.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 (262) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/cell-types.js +20 -0
  4. package/dist/cell-types.js.map +1 -0
  5. package/dist/code/code-formula-bar.js +6 -0
  6. package/dist/code/code-formula-bar.js.map +1 -0
  7. package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js +192 -0
  8. package/dist/code/code-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  9. package/dist/code/index.js +12 -0
  10. package/dist/code/index.js.map +1 -0
  11. package/dist/code/language.js +51 -0
  12. package/dist/code/language.js.map +1 -0
  13. package/dist/code/style.d.ts +1 -0
  14. package/dist/code/style.js +2 -0
  15. package/dist/collaboration/anchor.js +143 -0
  16. package/dist/collaboration/anchor.js.map +1 -0
  17. package/dist/collaboration/index.js +770 -0
  18. package/dist/collaboration/index.js.map +1 -0
  19. package/dist/collaboration/peers.js +87 -0
  20. package/dist/collaboration/peers.js.map +1 -0
  21. package/dist/collaboration/shared.js +450 -0
  22. package/dist/collaboration/shared.js.map +1 -0
  23. package/dist/components/cell-panel.js +6 -0
  24. package/dist/components/cell-panel.js.map +1 -0
  25. package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js +70 -0
  26. package/dist/components/cell-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/components/cell-renders.js +40 -0
  28. package/dist/components/cell-renders.js.map +1 -0
  29. package/dist/components/date-panel.js +6 -0
  30. package/dist/components/date-panel.js.map +1 -0
  31. package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js +48 -0
  32. package/dist/components/date-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  33. package/dist/components/filter-panel.js +6 -0
  34. package/dist/components/filter-panel.js.map +1 -0
  35. package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js +259 -0
  36. package/dist/components/filter-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/components/format-dialog.js +6 -0
  38. package/dist/components/format-dialog.js.map +1 -0
  39. package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js +432 -0
  40. package/dist/components/format-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/components/format-list.js +6 -0
  42. package/dist/components/format-list.js.map +1 -0
  43. package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js +187 -0
  44. package/dist/components/format-list.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/components/format-presets.js +97 -0
  46. package/dist/components/format-presets.js.map +1 -0
  47. package/dist/components/option-panel.js +6 -0
  48. package/dist/components/option-panel.js.map +1 -0
  49. package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js +117 -0
  50. package/dist/components/option-panel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  51. package/dist/components/sheet-comment.js +6 -0
  52. package/dist/components/sheet-comment.js.map +1 -0
  53. package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js +104 -0
  54. package/dist/components/sheet-comment.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/sheet-formula-bar.js +6 -0
  56. package/dist/components/sheet-formula-bar.js.map +1 -0
  57. package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js +124 -0
  58. package/dist/components/sheet-formula-bar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/components/sheet-link.js +6 -0
  60. package/dist/components/sheet-link.js.map +1 -0
  61. package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js +249 -0
  62. package/dist/components/sheet-link.vue_vue_type_script_setup_true_lang.js.map +1 -0
  63. package/dist/components/sheet-menu.js +6 -0
  64. package/dist/components/sheet-menu.js.map +1 -0
  65. package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js +115 -0
  66. package/dist/components/sheet-menu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  67. package/dist/components/sheet-name-box.js +6 -0
  68. package/dist/components/sheet-name-box.js.map +1 -0
  69. package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js +91 -0
  70. package/dist/components/sheet-name-box.vue_vue_type_script_setup_true_lang.js.map +1 -0
  71. package/dist/components/sheet-note.js +6 -0
  72. package/dist/components/sheet-note.js.map +1 -0
  73. package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js +146 -0
  74. package/dist/components/sheet-note.vue_vue_type_script_setup_true_lang.js.map +1 -0
  75. package/dist/components/sheet-outline.js +6 -0
  76. package/dist/components/sheet-outline.js.map +1 -0
  77. package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js +237 -0
  78. package/dist/components/sheet-outline.vue_vue_type_script_setup_true_lang.js.map +1 -0
  79. package/dist/components/sheet-tabs.js +6 -0
  80. package/dist/components/sheet-tabs.js.map +1 -0
  81. package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js +487 -0
  82. package/dist/components/sheet-tabs.vue_vue_type_script_setup_true_lang.js.map +1 -0
  83. package/dist/components/sheet-toolbar.js +6 -0
  84. package/dist/components/sheet-toolbar.js.map +1 -0
  85. package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js +1562 -0
  86. package/dist/components/sheet-toolbar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  87. package/dist/components/validation-dialog.js +6 -0
  88. package/dist/components/validation-dialog.js.map +1 -0
  89. package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js +370 -0
  90. package/dist/components/validation-dialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  91. package/dist/context.js +12 -0
  92. package/dist/context.js.map +1 -0
  93. package/dist/core/address.js +256 -0
  94. package/dist/core/address.js.map +1 -0
  95. package/dist/core/axis.js +72 -0
  96. package/dist/core/axis.js.map +1 -0
  97. package/dist/core/cell-type.js +30 -0
  98. package/dist/core/cell-type.js.map +1 -0
  99. package/dist/core/clipboard.js +141 -0
  100. package/dist/core/clipboard.js.map +1 -0
  101. package/dist/core/commands.js +63 -0
  102. package/dist/core/commands.js.map +1 -0
  103. package/dist/core/comments.js +74 -0
  104. package/dist/core/comments.js.map +1 -0
  105. package/dist/core/conditional.js +362 -0
  106. package/dist/core/conditional.js.map +1 -0
  107. package/dist/core/csv.js +191 -0
  108. package/dist/core/csv.js.map +1 -0
  109. package/dist/core/data.js +118 -0
  110. package/dist/core/data.js.map +1 -0
  111. package/dist/core/document.js +187 -0
  112. package/dist/core/document.js.map +1 -0
  113. package/dist/core/extension.js +60 -0
  114. package/dist/core/extension.js.map +1 -0
  115. package/dist/core/file.js +336 -0
  116. package/dist/core/file.js.map +1 -0
  117. package/dist/core/fill.js +153 -0
  118. package/dist/core/fill.js.map +1 -0
  119. package/dist/core/find.js +42 -0
  120. package/dist/core/find.js.map +1 -0
  121. package/dist/core/format.js +404 -0
  122. package/dist/core/format.js.map +1 -0
  123. package/dist/core/group.js +134 -0
  124. package/dist/core/group.js.map +1 -0
  125. package/dist/core/history.js +68 -0
  126. package/dist/core/history.js.map +1 -0
  127. package/dist/core/index.js +17 -0
  128. package/dist/core/link.js +34 -0
  129. package/dist/core/link.js.map +1 -0
  130. package/dist/core/merge.js +105 -0
  131. package/dist/core/merge.js.map +1 -0
  132. package/dist/core/model.js +48 -0
  133. package/dist/core/model.js.map +1 -0
  134. package/dist/core/nav.js +44 -0
  135. package/dist/core/nav.js.map +1 -0
  136. package/dist/core/paint.js +106 -0
  137. package/dist/core/paint.js.map +1 -0
  138. package/dist/core/plain-cell-types.js +54 -0
  139. package/dist/core/plain-cell-types.js.map +1 -0
  140. package/dist/core/protect.js +246 -0
  141. package/dist/core/protect.js.map +1 -0
  142. package/dist/core/selection.js +37 -0
  143. package/dist/core/selection.js.map +1 -0
  144. package/dist/core/transaction.js +1582 -0
  145. package/dist/core/transaction.js.map +1 -0
  146. package/dist/core/validation.js +135 -0
  147. package/dist/core/validation.js.map +1 -0
  148. package/dist/core/versions.js +161 -0
  149. package/dist/core/versions.js.map +1 -0
  150. package/dist/export/color.js +36 -0
  151. package/dist/export/color.js.map +1 -0
  152. package/dist/export/draw.js +316 -0
  153. package/dist/export/draw.js.map +1 -0
  154. package/dist/export/index.js +390 -0
  155. package/dist/export/index.js.map +1 -0
  156. package/dist/formula/edit.js +210 -0
  157. package/dist/formula/edit.js.map +1 -0
  158. package/dist/formula/engine.js +526 -0
  159. package/dist/formula/engine.js.map +1 -0
  160. package/dist/formula/error.js +39 -0
  161. package/dist/formula/error.js.map +1 -0
  162. package/dist/formula/functions.js +1493 -0
  163. package/dist/formula/functions.js.map +1 -0
  164. package/dist/formula/help.js +408 -0
  165. package/dist/formula/help.js.map +1 -0
  166. package/dist/formula/index.js +7 -0
  167. package/dist/formula/parse.js +369 -0
  168. package/dist/formula/parse.js.map +1 -0
  169. package/dist/formula/values.js +123 -0
  170. package/dist/formula/values.js.map +1 -0
  171. package/dist/formulas.js +30 -0
  172. package/dist/formulas.js.map +1 -0
  173. package/dist/index.js +39 -0
  174. package/dist/index.js.map +1 -0
  175. package/dist/locale.js +1312 -0
  176. package/dist/locale.js.map +1 -0
  177. package/dist/sheet.js +6 -0
  178. package/dist/sheet.js.map +1 -0
  179. package/dist/sheet.vue_vue_type_script_setup_true_lang.js +7166 -0
  180. package/dist/sheet.vue_vue_type_script_setup_true_lang.js.map +1 -0
  181. package/dist/style.css +1 -0
  182. package/dist/style.d.ts +1 -0
  183. package/dist/style.js +17 -0
  184. package/dist/types/cell-types.d.ts +2 -0
  185. package/dist/types/code/code-formula-bar.vue.d.ts +3 -0
  186. package/dist/types/code/index.d.ts +12 -0
  187. package/dist/types/code/language.d.ts +13 -0
  188. package/dist/types/collaboration/anchor.d.ts +65 -0
  189. package/dist/types/collaboration/index.d.ts +59 -0
  190. package/dist/types/collaboration/peers.d.ts +21 -0
  191. package/dist/types/collaboration/shared.d.ts +75 -0
  192. package/dist/types/components/cell-panel.vue.d.ts +20 -0
  193. package/dist/types/components/cell-renders.d.ts +9 -0
  194. package/dist/types/components/date-panel.vue.d.ts +9 -0
  195. package/dist/types/components/filter-panel.vue.d.ts +21 -0
  196. package/dist/types/components/format-dialog.vue.d.ts +24 -0
  197. package/dist/types/components/format-list.vue.d.ts +25 -0
  198. package/dist/types/components/format-presets.d.ts +30 -0
  199. package/dist/types/components/option-panel.vue.d.ts +13 -0
  200. package/dist/types/components/sheet-comment.vue.d.ts +29 -0
  201. package/dist/types/components/sheet-formula-bar.vue.d.ts +3 -0
  202. package/dist/types/components/sheet-link.vue.d.ts +32 -0
  203. package/dist/types/components/sheet-menu.vue.d.ts +20 -0
  204. package/dist/types/components/sheet-name-box.vue.d.ts +3 -0
  205. package/dist/types/components/sheet-note.vue.d.ts +22 -0
  206. package/dist/types/components/sheet-outline.vue.d.ts +36 -0
  207. package/dist/types/components/sheet-tabs.vue.d.ts +9 -0
  208. package/dist/types/components/sheet-toolbar.vue.d.ts +11 -0
  209. package/dist/types/components/validation-dialog.vue.d.ts +25 -0
  210. package/dist/types/context.d.ts +189 -0
  211. package/dist/types/core/address.d.ts +109 -0
  212. package/dist/types/core/axis.d.ts +23 -0
  213. package/dist/types/core/cell-type.d.ts +157 -0
  214. package/dist/types/core/clipboard.d.ts +48 -0
  215. package/dist/types/core/commands.d.ts +76 -0
  216. package/dist/types/core/comments.d.ts +22 -0
  217. package/dist/types/core/conditional.d.ts +114 -0
  218. package/dist/types/core/csv.d.ts +93 -0
  219. package/dist/types/core/data.d.ts +26 -0
  220. package/dist/types/core/document.d.ts +49 -0
  221. package/dist/types/core/extension.d.ts +177 -0
  222. package/dist/types/core/file.d.ts +301 -0
  223. package/dist/types/core/fill.d.ts +23 -0
  224. package/dist/types/core/find.d.ts +39 -0
  225. package/dist/types/core/format.d.ts +47 -0
  226. package/dist/types/core/group.d.ts +76 -0
  227. package/dist/types/core/history.d.ts +27 -0
  228. package/dist/types/core/index.d.ts +33 -0
  229. package/dist/types/core/link.d.ts +14 -0
  230. package/dist/types/core/merge.d.ts +26 -0
  231. package/dist/types/core/model.d.ts +363 -0
  232. package/dist/types/core/nav.d.ts +15 -0
  233. package/dist/types/core/paint.d.ts +19 -0
  234. package/dist/types/core/plain-cell-types.d.ts +6 -0
  235. package/dist/types/core/protect.d.ts +34 -0
  236. package/dist/types/core/selection.d.ts +25 -0
  237. package/dist/types/core/transaction.d.ts +470 -0
  238. package/dist/types/core/validation.d.ts +55 -0
  239. package/dist/types/core/versions.d.ts +38 -0
  240. package/dist/types/export/color.d.ts +7 -0
  241. package/dist/types/export/draw.d.ts +98 -0
  242. package/dist/types/export/index.d.ts +47 -0
  243. package/dist/types/formula/edit.d.ts +62 -0
  244. package/dist/types/formula/engine.d.ts +99 -0
  245. package/dist/types/formula/error.d.ts +30 -0
  246. package/dist/types/formula/functions.d.ts +62 -0
  247. package/dist/types/formula/help.d.ts +12 -0
  248. package/dist/types/formula/index.d.ts +13 -0
  249. package/dist/types/formula/parse.d.ts +92 -0
  250. package/dist/types/formula/values.d.ts +65 -0
  251. package/dist/types/formulas.d.ts +32 -0
  252. package/dist/types/index.d.ts +225 -0
  253. package/dist/types/locale.d.ts +531 -0
  254. package/dist/types/sheet.vue.d.ts +60 -0
  255. package/dist/types/types.d.ts +498 -0
  256. package/dist/types/use-comments.d.ts +47 -0
  257. package/dist/types/use-messages.d.ts +7 -0
  258. package/dist/use-comments.js +130 -0
  259. package/dist/use-comments.js.map +1 -0
  260. package/dist/use-messages.js +29 -0
  261. package/dist/use-messages.js.map +1 -0
  262. package/package.json +93 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 daidr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Temporary Holding Version
1
+ # @dou-ui/sheet
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [DouUI](https://github.com/daidr/dou-ui) 的电子表格:虚拟滚动的单元格网格、公式、格式、评论、历史版本与协同编辑。
4
+
5
+ ```sh
6
+ bun add @dou-ui/sheet dou-ui @dou-ui/code
7
+ ```
8
+
9
+ 用法见 [文档](https://ui.daidr.me/sheet/)。
10
+
11
+ 许可证:MIT
@@ -0,0 +1,20 @@
1
+ import { plainCellTypes } from "./core/plain-cell-types.js";
2
+ import { CellCheck, CellOption } from "./components/cell-renders.js";
3
+ import date_panel_default from "./components/date-panel.js";
4
+ import option_panel_default from "./components/option-panel.js";
5
+ // src/cell-types.ts
6
+ var editors = {
7
+ date: { panel: date_panel_default },
8
+ select: {
9
+ render: CellOption,
10
+ panel: option_panel_default
11
+ },
12
+ checkbox: { render: CellCheck }
13
+ };
14
+ var builtinCellTypes = plainCellTypes.map((type) => ({
15
+ ...type,
16
+ ...editors[type.name]
17
+ }));
18
+ export { builtinCellTypes };
19
+
20
+ //# sourceMappingURL=cell-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cell-types.js","names":["DatePanel","OptionPanel"],"sources":["../src/cell-types.ts"],"sourcesContent":["import { CellCheck, CellOption } from './components/cell-renders'\nimport DatePanel from './components/date-panel.vue'\nimport OptionPanel from './components/option-panel.vue'\nimport type { SheetCellType } from './core/cell-type'\nimport { plainCellTypes } from './core/plain-cell-types'\n\n// what the grid draws and edits the built-in types with\nconst editors: Record<string, Partial<SheetCellType>> = {\n date: { panel: DatePanel },\n select: { render: CellOption, panel: OptionPanel },\n checkbox: { render: CellCheck },\n}\n\nexport const builtinCellTypes: readonly SheetCellType[] = plainCellTypes.map((type) => ({\n ...type,\n ...editors[type.name],\n}))\n"],"mappings":";;;;;AAOA,IAAM,UAAkD;CACtD,MAAM,EAAE,OAAOA,mBAAU;CACzB,QAAQ;EAAE,QAAQ;EAAY,OAAOC;CAAY;CACjD,UAAU,EAAE,QAAQ,UAAU;AAChC;AAEA,IAAa,mBAA6C,eAAe,KAAK,UAAU;CACtF,GAAG;CACH,GAAG,QAAQ,KAAK;AAClB,EAAE"}
@@ -0,0 +1,6 @@
1
+ import code_formula_bar_vue_vue_type_script_setup_true_lang_default from "./code-formula-bar.vue_vue_type_script_setup_true_lang.js";
2
+ // src/code/code-formula-bar.vue
3
+ var code_formula_bar_default = code_formula_bar_vue_vue_type_script_setup_true_lang_default;
4
+ export { code_formula_bar_default as default };
5
+
6
+ //# sourceMappingURL=code-formula-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-formula-bar.js","names":["_sfc_main"],"sources":["../../src/code/code-formula-bar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n DouCodeInput,\n defineCodeExtension,\n type CodeDecoration,\n type CodeDiagnostic,\n type CodeEditorExpose,\n type CodeTransactionResult,\n} from '@dou-ui/code'\nimport { FunctionIcon } from '@dou-ui/icons'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n watchEffect,\n} from 'vue'\nimport SheetNameBox from '../components/sheet-name-box.vue'\nimport { useSheet } from '../context'\nimport { formulaReferences } from '../formula/edit'\nimport { formulaTokens, parseFormula, SheetFormulaSyntaxError } from '../formula/parse'\nimport { format } from '../locale'\nimport { sheetFormula } from './language'\n\n/**\n * The formula bar, with the formula in `@dou-ui/code`'s code input:\n * colored as it is typed, brackets matched, and mistakes underlined. It\n * edits the cell the way the built-in bar does, with the same function\n * list, argument hints and pointing at cells.\n */\ndefineOptions({ name: 'DouSheetCodeFormulaBar' })\n\nconst sheet = useSheet()\nconst { editor, messages: m } = sheet\n\nconst root = useTemplateRef<HTMLElement>('root')\nconst input = shallowRef<CodeEditorExpose>()\n\nconst editingHere = computed(() => !!editor.cell.value)\nconst text = computed(() =>\n editingHere.value ? editor.text.value : editor.textAt(sheet.active.value),\n)\nconst isFormula = computed(() => text.value.startsWith('='))\n\n/** Each reference in the color it has on the cells. */\nconst references = computed(() => (editingHere.value ? formulaReferences(text.value) : []))\n\nconst functionNames = computed(() => new Set(editor.functions.value.map((f) => f.name)))\n\n/** Text that can't be read as a formula, and functions there are none of. */\nfunction lint(doc: string): CodeDiagnostic[] {\n if (!doc.startsWith('=') || doc.trim() === '=') return []\n const out: CodeDiagnostic[] = []\n try {\n parseFormula(doc)\n } catch (error) {\n if (!(error instanceof SheetFormulaSyntaxError)) throw error\n const at = Math.min(doc.length, error.at + 1)\n out.push({\n from: at,\n to: Math.min(doc.length, at + 1),\n severity: 'error',\n message: m.value.formulaSyntax,\n })\n }\n const tokens = formulaTokens(doc)\n for (const [i, token] of tokens.entries()) {\n const next = tokens[i + 1]\n if (token.kind !== 'name' || next?.text !== '(') continue\n if (functionNames.value.has(token.text.toUpperCase())) continue\n out.push({\n from: token.start,\n to: token.end,\n severity: 'warning',\n message: format(m.value.unknownFunction, {\n name: token.text.toUpperCase(),\n }),\n })\n }\n return out\n}\n\nconst extension = defineCodeExtension({\n name: 'sheet-formula',\n decorations: (): CodeDecoration[] =>\n references.value.map((ref) => ({\n type: 'mark',\n from: ref.start,\n to: ref.end,\n class: `dou-sheet-code-bar__ref is-ref-${ref.color}`,\n })),\n lint: (ctx) => lint(ctx.doc.toString()),\n})\nconst extensions = [extension]\n\n// ---------------------------------------------------------------- the cell's edit, both ways\n\n/** Set while the cell's text is written into the box, so it isn't sent back. */\nlet syncing = false\n\nfunction onTransaction(result: CodeTransactionResult) {\n if (syncing || sheet.readonly.value) return\n const head = result.state.selection.ranges[result.state.selection.main]!.head\n if (!result.changes.empty) {\n const value = result.state.doc.toString()\n if (!editor.input(value, head)) {\n // the cell can't be edited: back to what it holds\n writeBox(text.value, editor.caret.value)\n }\n } else if (editingHere.value) editor.moveCaret(head)\n}\n\n/** Puts the cell's text and caret in the box, unless they are there already. */\nfunction writeBox(value: string, caret: number) {\n const box = input.value\n if (!box) return\n syncing = true\n try {\n if (box.doc.toString() !== value)\n box.transact((tr) => tr.replace(0, tr.doc.length, value), {\n action: 'external',\n history: false,\n })\n const main = box.selection.ranges[box.selection.main]!\n if (editingHere.value && (main.head !== caret || main.anchor !== caret))\n box.select(Math.min(caret, value.length))\n } finally {\n syncing = false\n }\n}\n\n// pointing at cells, Tab completing a name: the cell's edit moves, the box follows\nwatch([text, () => editor.caret.value], ([value, caret]) => writeBox(value, caret), {\n flush: 'sync',\n})\n\n// Enter, Tab, Escape, the function list and pointing work as in the cell: before the box's own keys\nfunction onKey(event: KeyboardEvent) {\n if (event.isComposing) return\n if (editingHere.value) {\n // a new line in the formula, as Alt + Enter does in the cell\n if (event.key === 'Enter' && event.altKey) {\n event.preventDefault()\n event.stopPropagation()\n input.value?.transact((tr) => tr.replaceSelection('\\n'), {\n action: 'input',\n scroll: true,\n })\n return\n }\n if (editor.key(event)) {\n event.stopPropagation()\n if (!editor.cell.value) sheet.focus()\n }\n return\n }\n if (event.key === 'Escape' || event.key === 'Enter') {\n event.preventDefault()\n event.stopPropagation()\n sheet.focus()\n }\n}\n\nfunction onBlur(event: FocusEvent) {\n // a press on a cell finished the edit already; going elsewhere saves it, as leaving the cell does\n const next = event.relatedTarget as Element | null\n if (!editor.cell.value || !document.hasFocus()) return\n if (next?.closest('.dou-sheet__input, .dou-sheet__assist')) return\n editor.commit()\n}\n\nlet detach: (() => void) | undefined\nonMounted(() => {\n const textarea = root.value?.querySelector('textarea')\n const anchor = root.value?.querySelector<HTMLElement>('.dou-code-editor') ?? undefined\n if (textarea) detach = editor.attach(textarea, { managed: true, anchor })\n})\n// the function list under the cell belongs to the box while it edits\nwatchEffect(() => {\n const textarea = root.value?.querySelector('textarea')\n if (!textarea) return\n if (editingHere.value) {\n textarea.setAttribute('aria-autocomplete', 'list')\n textarea.setAttribute('aria-controls', editor.helpId)\n } else {\n textarea.removeAttribute('aria-autocomplete')\n textarea.removeAttribute('aria-controls')\n }\n})\nonBeforeUnmount(() => detach?.())\n</script>\n\n<template>\n <div ref=\"root\" class=\"dou-sheet-formula-bar dou-sheet-code-bar\">\n <SheetNameBox />\n <span class=\"dou-sheet-formula-bar__mark\" aria-hidden=\"true\"><FunctionIcon /></span>\n <div class=\"dou-sheet-code-bar__box\" @keydown.capture=\"onKey\">\n <DouCodeInput\n ref=\"input\"\n :model-value=\"text\"\n class=\"dou-sheet-code-bar__input\"\n multiline\n :autosize=\"{ minRows: 1, maxRows: 5 }\"\n :language=\"isFormula ? sheetFormula : null\"\n :extensions=\"extensions\"\n :readonly=\"sheet.readonly.value\"\n :aria-label=\"m.formulaBox\"\n @transaction=\"onTransaction\"\n @blur=\"onBlur\"\n />\n </div>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,192 @@
1
+ import { SheetFormulaSyntaxError, formulaTokens, parseFormula } from "../formula/parse.js";
2
+ import { formulaReferences } from "../formula/edit.js";
3
+ import { format } from "../locale.js";
4
+ import { useSheet } from "../context.js";
5
+ import sheet_name_box_default from "../components/sheet-name-box.js";
6
+ import { sheetFormula } from "./language.js";
7
+ import { computed, createElementBlock, createElementVNode, createVNode, defineComponent, onBeforeUnmount, onMounted, openBlock, shallowRef, unref, useTemplateRef, watch, watchEffect } from "vue";
8
+ import { FunctionIcon } from "@dou-ui/icons";
9
+ import { DouCodeInput, defineCodeExtension } from "@dou-ui/code";
10
+ // src/code/code-formula-bar.vue?vue&type=script&setup=true&lang.ts
11
+ var _hoisted_1 = {
12
+ class: "dou-sheet-formula-bar__mark",
13
+ "aria-hidden": "true"
14
+ };
15
+ /**
16
+ * The formula bar, with the formula in `@dou-ui/code`'s code input:
17
+ * colored as it is typed, brackets matched, and mistakes underlined. It
18
+ * edits the cell the way the built-in bar does, with the same function
19
+ * list, argument hints and pointing at cells.
20
+ */
21
+ var code_formula_bar_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
22
+ name: "DouSheetCodeFormulaBar",
23
+ __name: "code-formula-bar",
24
+ setup(__props) {
25
+ const sheet = useSheet();
26
+ const { editor, messages: m } = sheet;
27
+ const root = useTemplateRef("root");
28
+ const input = shallowRef();
29
+ const editingHere = computed(() => !!editor.cell.value);
30
+ const text = computed(() => editingHere.value ? editor.text.value : editor.textAt(sheet.active.value));
31
+ const isFormula = computed(() => text.value.startsWith("="));
32
+ /** Each reference in the color it has on the cells. */
33
+ const references = computed(() => editingHere.value ? formulaReferences(text.value) : []);
34
+ const functionNames = computed(() => new Set(editor.functions.value.map((f) => f.name)));
35
+ /** Text that can't be read as a formula, and functions there are none of. */
36
+ function lint(doc) {
37
+ if (!doc.startsWith("=") || doc.trim() === "=") return [];
38
+ const out = [];
39
+ try {
40
+ parseFormula(doc);
41
+ } catch (error) {
42
+ if (!(error instanceof SheetFormulaSyntaxError)) throw error;
43
+ const at = Math.min(doc.length, error.at + 1);
44
+ out.push({
45
+ from: at,
46
+ to: Math.min(doc.length, at + 1),
47
+ severity: "error",
48
+ message: m.value.formulaSyntax
49
+ });
50
+ }
51
+ const tokens = formulaTokens(doc);
52
+ for (const [i, token] of tokens.entries()) {
53
+ const next = tokens[i + 1];
54
+ if (token.kind !== "name" || next?.text !== "(") continue;
55
+ if (functionNames.value.has(token.text.toUpperCase())) continue;
56
+ out.push({
57
+ from: token.start,
58
+ to: token.end,
59
+ severity: "warning",
60
+ message: format(m.value.unknownFunction, { name: token.text.toUpperCase() })
61
+ });
62
+ }
63
+ return out;
64
+ }
65
+ const extensions = [defineCodeExtension({
66
+ name: "sheet-formula",
67
+ decorations: () => references.value.map((ref) => ({
68
+ type: "mark",
69
+ from: ref.start,
70
+ to: ref.end,
71
+ class: `dou-sheet-code-bar__ref is-ref-${ref.color}`
72
+ })),
73
+ lint: (ctx) => lint(ctx.doc.toString())
74
+ })];
75
+ /** Set while the cell's text is written into the box, so it isn't sent back. */
76
+ let syncing = false;
77
+ function onTransaction(result) {
78
+ if (syncing || sheet.readonly.value) return;
79
+ const head = result.state.selection.ranges[result.state.selection.main].head;
80
+ if (!result.changes.empty) {
81
+ const value = result.state.doc.toString();
82
+ if (!editor.input(value, head)) writeBox(text.value, editor.caret.value);
83
+ } else if (editingHere.value) editor.moveCaret(head);
84
+ }
85
+ /** Puts the cell's text and caret in the box, unless they are there already. */
86
+ function writeBox(value, caret) {
87
+ const box = input.value;
88
+ if (!box) return;
89
+ syncing = true;
90
+ try {
91
+ if (box.doc.toString() !== value) box.transact((tr) => tr.replace(0, tr.doc.length, value), {
92
+ action: "external",
93
+ history: false
94
+ });
95
+ const main = box.selection.ranges[box.selection.main];
96
+ if (editingHere.value && (main.head !== caret || main.anchor !== caret)) box.select(Math.min(caret, value.length));
97
+ } finally {
98
+ syncing = false;
99
+ }
100
+ }
101
+ watch([text, () => editor.caret.value], ([value, caret]) => writeBox(value, caret), { flush: "sync" });
102
+ function onKey(event) {
103
+ if (event.isComposing) return;
104
+ if (editingHere.value) {
105
+ if (event.key === "Enter" && event.altKey) {
106
+ event.preventDefault();
107
+ event.stopPropagation();
108
+ input.value?.transact((tr) => tr.replaceSelection("\n"), {
109
+ action: "input",
110
+ scroll: true
111
+ });
112
+ return;
113
+ }
114
+ if (editor.key(event)) {
115
+ event.stopPropagation();
116
+ if (!editor.cell.value) sheet.focus();
117
+ }
118
+ return;
119
+ }
120
+ if (event.key === "Escape" || event.key === "Enter") {
121
+ event.preventDefault();
122
+ event.stopPropagation();
123
+ sheet.focus();
124
+ }
125
+ }
126
+ function onBlur(event) {
127
+ const next = event.relatedTarget;
128
+ if (!editor.cell.value || !document.hasFocus()) return;
129
+ if (next?.closest(".dou-sheet__input, .dou-sheet__assist")) return;
130
+ editor.commit();
131
+ }
132
+ let detach;
133
+ onMounted(() => {
134
+ const textarea = root.value?.querySelector("textarea");
135
+ const anchor = root.value?.querySelector(".dou-code-editor") ?? void 0;
136
+ if (textarea) detach = editor.attach(textarea, {
137
+ managed: true,
138
+ anchor
139
+ });
140
+ });
141
+ watchEffect(() => {
142
+ const textarea = root.value?.querySelector("textarea");
143
+ if (!textarea) return;
144
+ if (editingHere.value) {
145
+ textarea.setAttribute("aria-autocomplete", "list");
146
+ textarea.setAttribute("aria-controls", editor.helpId);
147
+ } else {
148
+ textarea.removeAttribute("aria-autocomplete");
149
+ textarea.removeAttribute("aria-controls");
150
+ }
151
+ });
152
+ onBeforeUnmount(() => detach?.());
153
+ return (_ctx, _cache) => {
154
+ return openBlock(), createElementBlock("div", {
155
+ ref_key: "root",
156
+ ref: root,
157
+ class: "dou-sheet-formula-bar dou-sheet-code-bar"
158
+ }, [
159
+ createVNode(sheet_name_box_default),
160
+ createElementVNode("span", _hoisted_1, [createVNode(unref(FunctionIcon))]),
161
+ createElementVNode("div", {
162
+ class: "dou-sheet-code-bar__box",
163
+ onKeydownCapture: onKey
164
+ }, [createVNode(unref(DouCodeInput), {
165
+ ref_key: "input",
166
+ ref: input,
167
+ "model-value": text.value,
168
+ class: "dou-sheet-code-bar__input",
169
+ multiline: "",
170
+ autosize: {
171
+ minRows: 1,
172
+ maxRows: 5
173
+ },
174
+ language: isFormula.value ? unref(sheetFormula) : null,
175
+ extensions,
176
+ readonly: unref(sheet).readonly.value,
177
+ "aria-label": unref(m).formulaBox,
178
+ onTransaction,
179
+ onBlur
180
+ }, null, 8, [
181
+ "model-value",
182
+ "language",
183
+ "readonly",
184
+ "aria-label"
185
+ ])], 32)
186
+ ], 512);
187
+ };
188
+ }
189
+ });
190
+ export { code_formula_bar_vue_vue_type_script_setup_true_lang_default as default };
191
+
192
+ //# sourceMappingURL=code-formula-bar.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-formula-bar.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","SheetNameBox","_createElementVNode","_unref"],"sources":["../../src/code/code-formula-bar.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n DouCodeInput,\n defineCodeExtension,\n type CodeDecoration,\n type CodeDiagnostic,\n type CodeEditorExpose,\n type CodeTransactionResult,\n} from '@dou-ui/code'\nimport { FunctionIcon } from '@dou-ui/icons'\nimport {\n computed,\n onBeforeUnmount,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n watchEffect,\n} from 'vue'\nimport SheetNameBox from '../components/sheet-name-box.vue'\nimport { useSheet } from '../context'\nimport { formulaReferences } from '../formula/edit'\nimport { formulaTokens, parseFormula, SheetFormulaSyntaxError } from '../formula/parse'\nimport { format } from '../locale'\nimport { sheetFormula } from './language'\n\n/**\n * The formula bar, with the formula in `@dou-ui/code`'s code input:\n * colored as it is typed, brackets matched, and mistakes underlined. It\n * edits the cell the way the built-in bar does, with the same function\n * list, argument hints and pointing at cells.\n */\ndefineOptions({ name: 'DouSheetCodeFormulaBar' })\n\nconst sheet = useSheet()\nconst { editor, messages: m } = sheet\n\nconst root = useTemplateRef<HTMLElement>('root')\nconst input = shallowRef<CodeEditorExpose>()\n\nconst editingHere = computed(() => !!editor.cell.value)\nconst text = computed(() =>\n editingHere.value ? editor.text.value : editor.textAt(sheet.active.value),\n)\nconst isFormula = computed(() => text.value.startsWith('='))\n\n/** Each reference in the color it has on the cells. */\nconst references = computed(() => (editingHere.value ? formulaReferences(text.value) : []))\n\nconst functionNames = computed(() => new Set(editor.functions.value.map((f) => f.name)))\n\n/** Text that can't be read as a formula, and functions there are none of. */\nfunction lint(doc: string): CodeDiagnostic[] {\n if (!doc.startsWith('=') || doc.trim() === '=') return []\n const out: CodeDiagnostic[] = []\n try {\n parseFormula(doc)\n } catch (error) {\n if (!(error instanceof SheetFormulaSyntaxError)) throw error\n const at = Math.min(doc.length, error.at + 1)\n out.push({\n from: at,\n to: Math.min(doc.length, at + 1),\n severity: 'error',\n message: m.value.formulaSyntax,\n })\n }\n const tokens = formulaTokens(doc)\n for (const [i, token] of tokens.entries()) {\n const next = tokens[i + 1]\n if (token.kind !== 'name' || next?.text !== '(') continue\n if (functionNames.value.has(token.text.toUpperCase())) continue\n out.push({\n from: token.start,\n to: token.end,\n severity: 'warning',\n message: format(m.value.unknownFunction, {\n name: token.text.toUpperCase(),\n }),\n })\n }\n return out\n}\n\nconst extension = defineCodeExtension({\n name: 'sheet-formula',\n decorations: (): CodeDecoration[] =>\n references.value.map((ref) => ({\n type: 'mark',\n from: ref.start,\n to: ref.end,\n class: `dou-sheet-code-bar__ref is-ref-${ref.color}`,\n })),\n lint: (ctx) => lint(ctx.doc.toString()),\n})\nconst extensions = [extension]\n\n// ---------------------------------------------------------------- the cell's edit, both ways\n\n/** Set while the cell's text is written into the box, so it isn't sent back. */\nlet syncing = false\n\nfunction onTransaction(result: CodeTransactionResult) {\n if (syncing || sheet.readonly.value) return\n const head = result.state.selection.ranges[result.state.selection.main]!.head\n if (!result.changes.empty) {\n const value = result.state.doc.toString()\n if (!editor.input(value, head)) {\n // the cell can't be edited: back to what it holds\n writeBox(text.value, editor.caret.value)\n }\n } else if (editingHere.value) editor.moveCaret(head)\n}\n\n/** Puts the cell's text and caret in the box, unless they are there already. */\nfunction writeBox(value: string, caret: number) {\n const box = input.value\n if (!box) return\n syncing = true\n try {\n if (box.doc.toString() !== value)\n box.transact((tr) => tr.replace(0, tr.doc.length, value), {\n action: 'external',\n history: false,\n })\n const main = box.selection.ranges[box.selection.main]!\n if (editingHere.value && (main.head !== caret || main.anchor !== caret))\n box.select(Math.min(caret, value.length))\n } finally {\n syncing = false\n }\n}\n\n// pointing at cells, Tab completing a name: the cell's edit moves, the box follows\nwatch([text, () => editor.caret.value], ([value, caret]) => writeBox(value, caret), {\n flush: 'sync',\n})\n\n// Enter, Tab, Escape, the function list and pointing work as in the cell: before the box's own keys\nfunction onKey(event: KeyboardEvent) {\n if (event.isComposing) return\n if (editingHere.value) {\n // a new line in the formula, as Alt + Enter does in the cell\n if (event.key === 'Enter' && event.altKey) {\n event.preventDefault()\n event.stopPropagation()\n input.value?.transact((tr) => tr.replaceSelection('\\n'), {\n action: 'input',\n scroll: true,\n })\n return\n }\n if (editor.key(event)) {\n event.stopPropagation()\n if (!editor.cell.value) sheet.focus()\n }\n return\n }\n if (event.key === 'Escape' || event.key === 'Enter') {\n event.preventDefault()\n event.stopPropagation()\n sheet.focus()\n }\n}\n\nfunction onBlur(event: FocusEvent) {\n // a press on a cell finished the edit already; going elsewhere saves it, as leaving the cell does\n const next = event.relatedTarget as Element | null\n if (!editor.cell.value || !document.hasFocus()) return\n if (next?.closest('.dou-sheet__input, .dou-sheet__assist')) return\n editor.commit()\n}\n\nlet detach: (() => void) | undefined\nonMounted(() => {\n const textarea = root.value?.querySelector('textarea')\n const anchor = root.value?.querySelector<HTMLElement>('.dou-code-editor') ?? undefined\n if (textarea) detach = editor.attach(textarea, { managed: true, anchor })\n})\n// the function list under the cell belongs to the box while it edits\nwatchEffect(() => {\n const textarea = root.value?.querySelector('textarea')\n if (!textarea) return\n if (editingHere.value) {\n textarea.setAttribute('aria-autocomplete', 'list')\n textarea.setAttribute('aria-controls', editor.helpId)\n } else {\n textarea.removeAttribute('aria-autocomplete')\n textarea.removeAttribute('aria-controls')\n }\n})\nonBeforeUnmount(() => detach?.())\n</script>\n\n<template>\n <div ref=\"root\" class=\"dou-sheet-formula-bar dou-sheet-code-bar\">\n <SheetNameBox />\n <span class=\"dou-sheet-formula-bar__mark\" aria-hidden=\"true\"><FunctionIcon /></span>\n <div class=\"dou-sheet-code-bar__box\" @keydown.capture=\"onKey\">\n <DouCodeInput\n ref=\"input\"\n :model-value=\"text\"\n class=\"dou-sheet-code-bar__input\"\n multiline\n :autosize=\"{ minRows: 1, maxRows: 5 }\"\n :language=\"isFormula ? sheetFormula : null\"\n :extensions=\"extensions\"\n :readonly=\"sheet.readonly.value\"\n :aria-label=\"m.formulaBox\"\n @transaction=\"onTransaction\"\n @blur=\"onBlur\"\n />\n </div>\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { sheetFormula } from "./language.js";
2
+ import code_formula_bar_default from "./code-formula-bar.js";
3
+ import { withInstall } from "dou-ui";
4
+ // src/code/index.ts
5
+ /**
6
+ * The formula bar with the formula in `@dou-ui/code`'s code input. Use it
7
+ * in place of `DouSheetFormulaBar`; needs `@dou-ui/code` and its styles.
8
+ */
9
+ var DouSheetCodeFormulaBar = withInstall(code_formula_bar_default);
10
+ export { DouSheetCodeFormulaBar, sheetFormula };
11
+
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["CodeFormulaBar"],"sources":["../../src/code/index.ts"],"sourcesContent":["import { withInstall } from 'dou-ui'\nimport CodeFormulaBar from './code-formula-bar.vue'\n\n/**\n * The formula bar with the formula in `@dou-ui/code`'s code input. Use it\n * in place of `DouSheetFormulaBar`; needs `@dou-ui/code` and its styles.\n */\nexport const DouSheetCodeFormulaBar = withInstall(CodeFormulaBar)\nexport { sheetFormula } from './language'\nexport type { SheetFormulaState } from './language'\n\ndeclare module 'vue' {\n export interface GlobalComponents {\n DouSheetCodeFormulaBar: typeof DouSheetCodeFormulaBar\n }\n}\n"],"mappings":";;;;;;;;AAOA,IAAa,yBAAyB,YAAYA,wBAAc"}
@@ -0,0 +1,51 @@
1
+ import { defineCodeLanguage } from "@dou-ui/code";
2
+ // src/code/language.ts
3
+ var SHEET = String.raw`(?:'(?:[^']|'')+'|[\p{L}_][\p{L}\p{N}_.]*)!`;
4
+ var CELL = String.raw`\$?[A-Za-z]{1,3}\$?\d+`;
5
+ var REF = new RegExp(String.raw`^(?:${SHEET})?(?:${CELL}(?::${CELL})?|\$?[A-Za-z]{1,3}:\$?[A-Za-z]{1,3}|\$?\d+:\$?\d+)(?![\p{L}\p{N}_(])`, "u");
6
+ var ERROR = /^#(?:NULL!|DIV\/0!|VALUE!|REF!|NAME\?|NUM!|N\/A|SPILL!|CALC!)/i;
7
+ var NUMBER = /^(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?%?/;
8
+ var NAME = /^[\p{L}_][\p{L}\p{N}_.]*/u;
9
+ /**
10
+ * Spreadsheet formulas, as the sheet writes them: `=SUM(A1:B2, "text")`.
11
+ * Function names, references, "text", numbers, error values and
12
+ * `TRUE` / `FALSE` each have their color. For the text after the `=`, or
13
+ * with it; a value typed into a cell isn't a formula, so leave the
14
+ * language out for it.
15
+ */
16
+ var sheetFormula = defineCodeLanguage({
17
+ name: "sheet-formula",
18
+ startState: () => ({ quote: false }),
19
+ copyState: (state) => ({ ...state }),
20
+ sameState: (a, b) => a.quote === b.quote,
21
+ token(stream, state) {
22
+ if (state.quote || stream.peek() === "\"") {
23
+ if (!state.quote) stream.next();
24
+ state.quote = true;
25
+ while (!stream.eol()) if (stream.next() === "\"") {
26
+ if (stream.eat("\"")) continue;
27
+ state.quote = false;
28
+ break;
29
+ }
30
+ return "string";
31
+ }
32
+ if (stream.eatSpace()) return null;
33
+ if (stream.match(ERROR)) return "invalid";
34
+ if (stream.match(REF)) return "variable";
35
+ if (stream.match(NUMBER)) return "number";
36
+ const name = stream.match(NAME);
37
+ if (name) {
38
+ if (stream.match(/^\s*\(/, false)) return "function";
39
+ return /^(?:TRUE|FALSE)$/i.test(name[0]) ? "keyword" : "variable";
40
+ }
41
+ if (stream.match(/^(?:<>|<=|>=|[-+*/^&=<>%])/)) return "operator";
42
+ if (stream.eat(/[(),;{}]/)) return "punctuation";
43
+ stream.next();
44
+ return null;
45
+ },
46
+ brackets: "(){}",
47
+ autoClose: "(\""
48
+ });
49
+ export { sheetFormula };
50
+
51
+ //# sourceMappingURL=language.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language.js","names":[],"sources":["../../src/code/language.ts"],"sourcesContent":["import { defineCodeLanguage, type CodeLanguage, type CodeTokenType } from '@dou-ui/code'\n\nexport interface SheetFormulaState {\n /** A \"text\" value still open at the line's end. */\n quote: boolean\n}\n\nconst SHEET = String.raw`(?:'(?:[^']|'')+'|[\\p{L}_][\\p{L}\\p{N}_.]*)!`\nconst CELL = String.raw`\\$?[A-Za-z]{1,3}\\$?\\d+`\nconst REF = new RegExp(\n String.raw`^(?:${SHEET})?(?:${CELL}(?::${CELL})?|\\$?[A-Za-z]{1,3}:\\$?[A-Za-z]{1,3}|\\$?\\d+:\\$?\\d+)(?![\\p{L}\\p{N}_(])`,\n 'u',\n)\nconst ERROR = /^#(?:NULL!|DIV\\/0!|VALUE!|REF!|NAME\\?|NUM!|N\\/A|SPILL!|CALC!)/i\nconst NUMBER = /^(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?%?/\nconst NAME = /^[\\p{L}_][\\p{L}\\p{N}_.]*/u\n\n/**\n * Spreadsheet formulas, as the sheet writes them: `=SUM(A1:B2, \"text\")`.\n * Function names, references, \"text\", numbers, error values and\n * `TRUE` / `FALSE` each have their color. For the text after the `=`, or\n * with it; a value typed into a cell isn't a formula, so leave the\n * language out for it.\n */\nexport const sheetFormula: CodeLanguage<SheetFormulaState> = defineCodeLanguage<SheetFormulaState>({\n name: 'sheet-formula',\n startState: () => ({ quote: false }),\n copyState: (state) => ({ ...state }),\n sameState: (a, b) => a.quote === b.quote,\n token(stream, state): CodeTokenType | null {\n if (state.quote || stream.peek() === '\"') {\n if (!state.quote) stream.next()\n state.quote = true\n while (!stream.eol()) {\n if (stream.next() === '\"') {\n if (stream.eat('\"')) continue\n state.quote = false\n break\n }\n }\n return 'string'\n }\n if (stream.eatSpace()) return null\n if (stream.match(ERROR)) return 'invalid'\n if (stream.match(REF)) return 'variable'\n if (stream.match(NUMBER)) return 'number'\n const name = stream.match(NAME)\n if (name) {\n if (stream.match(/^\\s*\\(/, false)) return 'function'\n return /^(?:TRUE|FALSE)$/i.test(name[0]) ? 'keyword' : 'variable'\n }\n if (stream.match(/^(?:<>|<=|>=|[-+*/^&=<>%])/)) return 'operator'\n if (stream.eat(/[(),;{}]/)) return 'punctuation'\n stream.next()\n return null\n },\n brackets: '(){}',\n autoClose: '(\"',\n})\n"],"mappings":";;AAOA,IAAM,QAAQ,OAAO,GAAG;AACxB,IAAM,OAAO,OAAO,GAAG;AACvB,IAAM,MAAM,IAAI,OACd,OAAO,GAAG,OAAO,MAAM,OAAO,KAAK,MAAM,KAAK,wEAC9C,GACF;AACA,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,OAAO;;;;;;;;AASb,IAAa,eAAgD,mBAAsC;CACjG,MAAM;CACN,mBAAmB,EAAE,OAAO,MAAM;CAClC,YAAY,WAAW,EAAE,GAAG,MAAM;CAClC,YAAY,GAAG,MAAM,EAAE,UAAU,EAAE;CACnC,MAAM,QAAQ,OAA6B;EACzC,IAAI,MAAM,SAAS,OAAO,KAAK,MAAM,MAAK;GACxC,IAAI,CAAC,MAAM,OAAO,OAAO,KAAK;GAC9B,MAAM,QAAQ;GACd,OAAO,CAAC,OAAO,IAAI,GACjB,IAAI,OAAO,KAAK,MAAM,MAAK;IACzB,IAAI,OAAO,IAAI,IAAG,GAAG;IACrB,MAAM,QAAQ;IACd;GACF;GAEF,OAAO;EACT;EACA,IAAI,OAAO,SAAS,GAAG,OAAO;EAC9B,IAAI,OAAO,MAAM,KAAK,GAAG,OAAO;EAChC,IAAI,OAAO,MAAM,GAAG,GAAG,OAAO;EAC9B,IAAI,OAAO,MAAM,MAAM,GAAG,OAAO;EACjC,MAAM,OAAO,OAAO,MAAM,IAAI;EAC9B,IAAI,MAAM;GACR,IAAI,OAAO,MAAM,UAAU,KAAK,GAAG,OAAO;GAC1C,OAAO,oBAAoB,KAAK,KAAK,EAAE,IAAI,YAAY;EACzD;EACA,IAAI,OAAO,MAAM,4BAA4B,GAAG,OAAO;EACvD,IAAI,OAAO,IAAI,UAAU,GAAG,OAAO;EACnC,OAAO,KAAK;EACZ,OAAO;CACT;CACA,UAAU;CACV,WAAW;AACb,CAAC"}
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,2 @@
1
+ import '@dou-ui/code/style'
2
+ import '../style.css'
@@ -0,0 +1,143 @@
1
+ import { eachRef, writeRef } from "../core/address.js";
2
+ import { compactCell } from "../core/model.js";
3
+ // src/collaboration/anchor.ts
4
+ /** The ids of a sheet's rows or columns, in order, with a lookup of each one's number. */
5
+ var SheetLines = class {
6
+ ids;
7
+ at = null;
8
+ constructor(ids) {
9
+ this.ids = ids;
10
+ }
11
+ /** The number of a line, `-1` when it is gone. */
12
+ indexOf(id) {
13
+ if (!this.at) {
14
+ this.at = /* @__PURE__ */ new Map();
15
+ this.ids.forEach((line, index) => this.at.set(line, index));
16
+ }
17
+ return this.at.get(id) ?? -1;
18
+ }
19
+ /** Call after changing `ids`. */
20
+ changed() {
21
+ this.at = null;
22
+ }
23
+ };
24
+ /** The sheets of a workbook, by id and by name. */
25
+ var SheetLayout = class {
26
+ sheets = /* @__PURE__ */ new Map();
27
+ byName(name) {
28
+ for (const sheet of this.sheets.values()) if (sheet.name === name) return sheet;
29
+ }
30
+ };
31
+ /** The anchors of a formula's references, or `undefined` when it has none to keep. */
32
+ function anchorFormula(formula, here, layout) {
33
+ const refs = [];
34
+ let any = false;
35
+ eachRef(formula, (named, a, b, text) => {
36
+ const target = named == null ? here : layout.byName(named);
37
+ if (!target) {
38
+ refs.push(0);
39
+ return text;
40
+ }
41
+ any = true;
42
+ const row = (n) => n == null ? null : target.rows.ids[n] ?? n;
43
+ const col = (n) => n == null ? null : target.cols.ids[n] ?? n;
44
+ refs.push([
45
+ named == null ? null : target.id,
46
+ row(a.row),
47
+ col(a.col),
48
+ row(b.row),
49
+ col(b.col)
50
+ ]);
51
+ return text;
52
+ });
53
+ return any ? refs : void 0;
54
+ }
55
+ function lineOf(lines, end) {
56
+ return end == null ? void 0 : typeof end === "number" ? end : lines.indexOf(end);
57
+ }
58
+ /**
59
+ * A formula with its references where their lines are now. A reference
60
+ * whose line or sheet is gone reads `#REF!`; one whose sheet was renamed
61
+ * names it anew. Unchanged references keep their text as written.
62
+ */
63
+ function resolveFormula(formula, refs, here, layout) {
64
+ let i = 0;
65
+ return eachRef(formula, (named, a, b, text) => {
66
+ const ref = refs[i++];
67
+ if (!ref) return text;
68
+ const [sheetId, rowA, colA, rowB, colB] = ref;
69
+ const target = sheetId == null ? here : layout.sheets.get(sheetId);
70
+ if (!target) return "#REF!";
71
+ const renamed = named != null && target.name !== named;
72
+ const prefix = renamed ? void 0 : text.includes("!") ? text.slice(0, text.lastIndexOf("!") + 1) : void 0;
73
+ const r1 = lineOf(target.rows, rowA);
74
+ const c1 = lineOf(target.cols, colA);
75
+ const r2 = lineOf(target.rows, rowB);
76
+ const c2 = lineOf(target.cols, colB);
77
+ if (r1 === -1 || c1 === -1 || r2 === -1 || c2 === -1) return `${prefix ?? (named != null ? `${target.name}!` : "")}#REF!`;
78
+ if (!renamed && r1 === a.row && c1 === a.col && r2 === b.row && c2 === b.col) return text;
79
+ const single = a === b;
80
+ const from = {
81
+ ...a,
82
+ row: r1,
83
+ col: c1
84
+ };
85
+ const to = single ? from : {
86
+ ...b,
87
+ row: r2,
88
+ col: c2
89
+ };
90
+ return writeRef(named == null ? void 0 : target.name, from, to, single, prefix);
91
+ });
92
+ }
93
+ /** A range such as `A1:C4`, anchored. */
94
+ function anchorRange(range, here, layout) {
95
+ const r = anchorFormula(`=${range}`, here, layout);
96
+ return r ? {
97
+ t: range,
98
+ r
99
+ } : { t: range };
100
+ }
101
+ /** A range where its lines are now; `null` when they are gone. */
102
+ function resolveRange(stored, here, layout) {
103
+ if (!stored.r) return stored.t;
104
+ const text = resolveFormula(`=${stored.t}`, stored.r, here, layout).slice(1);
105
+ return text.includes("#REF!") ? null : text;
106
+ }
107
+ /** A formula, or text that may be one, anchored. */
108
+ function anchorText(text, here, layout) {
109
+ const r = text.startsWith("=") ? anchorFormula(text, here, layout) : void 0;
110
+ return r ? {
111
+ t: text,
112
+ r
113
+ } : { t: text };
114
+ }
115
+ function resolveText(stored, here, layout) {
116
+ return stored.r ? resolveFormula(stored.t, stored.r, here, layout) : stored.t;
117
+ }
118
+ /** Where a cell keeps the anchors of its formula in the shared document. */
119
+ var REFS = "$refs";
120
+ var isFormula = (value) => typeof value === "string" && value.startsWith("=");
121
+ /** A cell as the shared document keeps it: as it is, with the anchors of its formula beside. */
122
+ function anchorCell(cell, here, layout) {
123
+ const value = typeof cell === "object" && cell !== null ? cell.value : cell;
124
+ if (!isFormula(value)) return cell ?? void 0;
125
+ const refs = anchorFormula(value, here, layout);
126
+ if (!refs) return cell;
127
+ return {
128
+ ...typeof cell === "object" && cell !== null ? cell : { value },
129
+ [REFS]: refs
130
+ };
131
+ }
132
+ /** Whether a cell kept in the shared document has references to resolve. */
133
+ var hasRefs = (stored) => typeof stored === "object" && stored !== null && "$refs" in stored;
134
+ /** A cell kept in the shared document, with its formula's references where they are now. */
135
+ function resolveCell(stored, here, layout) {
136
+ if (!hasRefs(stored)) return stored;
137
+ const { [REFS]: refs, ...cell } = stored;
138
+ if (isFormula(cell.value)) cell.value = resolveFormula(cell.value, refs, here, layout);
139
+ return compactCell(cell);
140
+ }
141
+ export { REFS, SheetLayout, SheetLines, anchorCell, anchorFormula, anchorRange, anchorText, hasRefs, lineOf, resolveCell, resolveFormula, resolveRange, resolveText };
142
+
143
+ //# sourceMappingURL=anchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor.js","names":[],"sources":["../../src/collaboration/anchor.ts"],"sourcesContent":["import { eachRef, writeRef } from '../core/address'\nimport { compactCell, type SheetCell, type SheetCellInput } from '../core/model'\n\n/*\n * Formulas and ranges are written with row and column numbers, which change\n * when someone inserts or deletes lines. In the shared document each\n * reference is kept with the ids of its rows and columns besides the text,\n * so it reads right again once the lines it points at have moved, also by\n * changes this side has not seen yet when it is written.\n */\n\n/** The ids of a sheet's rows or columns, in order, with a lookup of each one's number. */\nexport class SheetLines {\n private at: Map<string, number> | null = null\n\n constructor(public ids: string[]) {}\n\n /** The number of a line, `-1` when it is gone. */\n indexOf(id: string) {\n if (!this.at) {\n this.at = new Map()\n this.ids.forEach((line, index) => this.at!.set(line, index))\n }\n return this.at.get(id) ?? -1\n }\n\n /** Call after changing `ids`. */\n changed() {\n this.at = null\n }\n}\n\n/** A sheet as references see it: its id, its name and its lines. */\nexport interface LayoutSheet {\n id: string\n name: string\n rows: SheetLines\n cols: SheetLines\n}\n\n/** The sheets of a workbook, by id and by name. */\nexport class SheetLayout {\n readonly sheets = new Map<string, LayoutSheet>()\n\n byName(name: string) {\n for (const sheet of this.sheets.values()) if (sheet.name === name) return sheet\n return undefined\n }\n}\n\n/** One end of a reference: a line id, a number past the sheet's lines, or `null` for none (`B:B` has no row). */\ntype End = string | number | null\n\n/**\n * A reference held by ids: the sheet it names (`null`: the formula's own\n * sheet), then the rows and columns of its two ends. `0` for a reference\n * to a sheet that isn't there, kept as written.\n */\nexport type AnchoredRef = 0 | [sheet: string | null, rowA: End, colA: End, rowB: End, colB: End]\n\n/** Text with references, and their anchors in the order they come. */\nexport interface AnchoredText {\n t: string\n r?: AnchoredRef[]\n}\n\n/** The anchors of a formula's references, or `undefined` when it has none to keep. */\nexport function anchorFormula(\n formula: string,\n here: LayoutSheet,\n layout: SheetLayout,\n): AnchoredRef[] | undefined {\n const refs: AnchoredRef[] = []\n let any = false\n eachRef(formula, (named, a, b, text) => {\n const target = named == null ? here : layout.byName(named)\n if (!target) {\n refs.push(0)\n return text\n }\n any = true\n const row = (n?: number): End => (n == null ? null : (target.rows.ids[n] ?? n))\n const col = (n?: number): End => (n == null ? null : (target.cols.ids[n] ?? n))\n refs.push([named == null ? null : target.id, row(a.row), col(a.col), row(b.row), col(b.col)])\n return text\n })\n return any ? refs : undefined\n}\n\n/** The number of a line: its id's place, `-1` when it is gone, or the number kept for one past the ids. */\nexport function lineOf(lines: SheetLines, end: string | number): number\nexport function lineOf(lines: SheetLines, end: End): number | undefined\nexport function lineOf(lines: SheetLines, end: End) {\n return end == null ? undefined : typeof end === 'number' ? end : lines.indexOf(end)\n}\n\n/**\n * A formula with its references where their lines are now. A reference\n * whose line or sheet is gone reads `#REF!`; one whose sheet was renamed\n * names it anew. Unchanged references keep their text as written.\n */\nexport function resolveFormula(\n formula: string,\n refs: readonly AnchoredRef[],\n here: LayoutSheet,\n layout: SheetLayout,\n) {\n let i = 0\n return eachRef(formula, (named, a, b, text) => {\n const ref = refs[i++]\n if (!ref) return text\n const [sheetId, rowA, colA, rowB, colB] = ref\n const target = sheetId == null ? here : layout.sheets.get(sheetId)\n if (!target) return '#REF!'\n const renamed = named != null && target.name !== named\n const prefix = renamed\n ? undefined\n : text.includes('!')\n ? text.slice(0, text.lastIndexOf('!') + 1)\n : undefined\n const r1 = lineOf(target.rows, rowA)\n const c1 = lineOf(target.cols, colA)\n const r2 = lineOf(target.rows, rowB)\n const c2 = lineOf(target.cols, colB)\n if (r1 === -1 || c1 === -1 || r2 === -1 || c2 === -1)\n return `${prefix ?? (named != null ? `${target.name}!` : '')}#REF!`\n if (!renamed && r1 === a.row && c1 === a.col && r2 === b.row && c2 === b.col) return text\n const single = a === b\n const from = { ...a, row: r1, col: c1 }\n const to = single ? from : { ...b, row: r2, col: c2 }\n return writeRef(named == null ? undefined : target.name, from, to, single, prefix)\n })\n}\n\n/** A range such as `A1:C4`, anchored. */\nexport function anchorRange(range: string, here: LayoutSheet, layout: SheetLayout): AnchoredText {\n const r = anchorFormula(`=${range}`, here, layout)\n return r ? { t: range, r } : { t: range }\n}\n\n/** A range where its lines are now; `null` when they are gone. */\nexport function resolveRange(stored: AnchoredText, here: LayoutSheet, layout: SheetLayout) {\n if (!stored.r) return stored.t\n const text = resolveFormula(`=${stored.t}`, stored.r, here, layout).slice(1)\n return text.includes('#REF!') ? null : text\n}\n\n/** A formula, or text that may be one, anchored. */\nexport function anchorText(text: string, here: LayoutSheet, layout: SheetLayout): AnchoredText {\n const r = text.startsWith('=') ? anchorFormula(text, here, layout) : undefined\n return r ? { t: text, r } : { t: text }\n}\n\nexport function resolveText(stored: AnchoredText, here: LayoutSheet, layout: SheetLayout) {\n return stored.r ? resolveFormula(stored.t, stored.r, here, layout) : stored.t\n}\n\n/** Where a cell keeps the anchors of its formula in the shared document. */\nexport const REFS = '$refs'\n\nconst isFormula = (value: unknown): value is string =>\n typeof value === 'string' && value.startsWith('=')\n\n/** A cell as the shared document keeps it: as it is, with the anchors of its formula beside. */\nexport function anchorCell(cell: SheetCellInput, here: LayoutSheet, layout: SheetLayout): unknown {\n const value = typeof cell === 'object' && cell !== null ? cell.value : cell\n if (!isFormula(value)) return cell ?? undefined\n const refs = anchorFormula(value, here, layout)\n if (!refs) return cell\n const fields = typeof cell === 'object' && cell !== null ? cell : { value }\n return { ...fields, [REFS]: refs }\n}\n\n/** Whether a cell kept in the shared document has references to resolve. */\nexport const hasRefs = (stored: unknown): stored is SheetCell & { [REFS]: AnchoredRef[] } =>\n typeof stored === 'object' && stored !== null && REFS in stored\n\n/** A cell kept in the shared document, with its formula's references where they are now. */\nexport function resolveCell(stored: unknown, here: LayoutSheet, layout: SheetLayout) {\n if (!hasRefs(stored)) return stored as SheetCellInput\n const { [REFS]: refs, ...cell } = stored\n if (isFormula(cell.value)) cell.value = resolveFormula(cell.value, refs, here, layout)\n return compactCell(cell)\n}\n"],"mappings":";;;;AAYA,IAAa,aAAb,MAAwB;CAGH;CAFnB,KAAyC;CAEzC,YAAY,KAAsB;EAAf,KAAA,MAAA;CAAgB;;CAGnC,QAAQ,IAAY;EAClB,IAAI,CAAC,KAAK,IAAI;GACZ,KAAK,qBAAK,IAAI,IAAI;GAClB,KAAK,IAAI,SAAS,MAAM,UAAU,KAAK,GAAI,IAAI,MAAM,KAAK,CAAC;EAC7D;EACA,OAAO,KAAK,GAAG,IAAI,EAAE,KAAK;CAC5B;;CAGA,UAAU;EACR,KAAK,KAAK;CACZ;AACF;;AAWA,IAAa,cAAb,MAAyB;CACvB,yBAAkB,IAAI,IAAyB;CAE/C,OAAO,MAAc;EACnB,KAAK,MAAM,SAAS,KAAK,OAAO,OAAO,GAAG,IAAI,MAAM,SAAS,MAAM,OAAO;CAE5E;AACF;;AAmBA,SAAgB,cACd,SACA,MACA,QAC2B;CAC3B,MAAM,OAAsB,CAAC;CAC7B,IAAI,MAAM;CACV,QAAQ,UAAU,OAAO,GAAG,GAAG,SAAS;EACtC,MAAM,SAAS,SAAS,OAAO,OAAO,OAAO,OAAO,KAAK;EACzD,IAAI,CAAC,QAAQ;GACX,KAAK,KAAK,CAAC;GACX,OAAO;EACT;EACA,MAAM;EACN,MAAM,OAAO,MAAqB,KAAK,OAAO,OAAQ,OAAO,KAAK,IAAI,MAAM;EAC5E,MAAM,OAAO,MAAqB,KAAK,OAAO,OAAQ,OAAO,KAAK,IAAI,MAAM;EAC5E,KAAK,KAAK;GAAC,SAAS,OAAO,OAAO,OAAO;GAAI,IAAI,EAAE,GAAG;GAAG,IAAI,EAAE,GAAG;GAAG,IAAI,EAAE,GAAG;GAAG,IAAI,EAAE,GAAG;EAAC,CAAC;EAC5F,OAAO;CACT,CAAC;CACD,OAAO,MAAM,OAAO,KAAA;AACtB;AAKA,SAAgB,OAAO,OAAmB,KAAU;CAClD,OAAO,OAAO,OAAO,KAAA,IAAY,OAAO,QAAQ,WAAW,MAAM,MAAM,QAAQ,GAAG;AACpF;;;;;;AAOA,SAAgB,eACd,SACA,MACA,MACA,QACA;CACA,IAAI,IAAI;CACR,OAAO,QAAQ,UAAU,OAAO,GAAG,GAAG,SAAS;EAC7C,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,KAAK,OAAO;EACjB,MAAM,CAAC,SAAS,MAAM,MAAM,MAAM,QAAQ;EAC1C,MAAM,SAAS,WAAW,OAAO,OAAO,OAAO,OAAO,IAAI,OAAO;EACjE,IAAI,CAAC,QAAQ,OAAO;EACpB,MAAM,UAAU,SAAS,QAAQ,OAAO,SAAS;EACjD,MAAM,SAAS,UACX,KAAA,IACA,KAAK,SAAS,GAAG,IACf,KAAK,MAAM,GAAG,KAAK,YAAY,GAAG,IAAI,CAAC,IACvC,KAAA;EACN,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI;EACnC,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI;EACnC,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI;EACnC,MAAM,KAAK,OAAO,OAAO,MAAM,IAAI;EACnC,IAAI,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,IAChD,OAAO,GAAG,WAAW,SAAS,OAAO,GAAG,OAAO,KAAK,KAAK,IAAI;EAC/D,IAAI,CAAC,WAAW,OAAO,EAAE,OAAO,OAAO,EAAE,OAAO,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,OAAO;EACrF,MAAM,SAAS,MAAM;EACrB,MAAM,OAAO;GAAE,GAAG;GAAG,KAAK;GAAI,KAAK;EAAG;EACtC,MAAM,KAAK,SAAS,OAAO;GAAE,GAAG;GAAG,KAAK;GAAI,KAAK;EAAG;EACpD,OAAO,SAAS,SAAS,OAAO,KAAA,IAAY,OAAO,MAAM,MAAM,IAAI,QAAQ,MAAM;CACnF,CAAC;AACH;;AAGA,SAAgB,YAAY,OAAe,MAAmB,QAAmC;CAC/F,MAAM,IAAI,cAAc,IAAI,SAAS,MAAM,MAAM;CACjD,OAAO,IAAI;EAAE,GAAG;EAAO;CAAE,IAAI,EAAE,GAAG,MAAM;AAC1C;;AAGA,SAAgB,aAAa,QAAsB,MAAmB,QAAqB;CACzF,IAAI,CAAC,OAAO,GAAG,OAAO,OAAO;CAC7B,MAAM,OAAO,eAAe,IAAI,OAAO,KAAK,OAAO,GAAG,MAAM,MAAM,CAAC,CAAC,MAAM,CAAC;CAC3E,OAAO,KAAK,SAAS,OAAO,IAAI,OAAO;AACzC;;AAGA,SAAgB,WAAW,MAAc,MAAmB,QAAmC;CAC7F,MAAM,IAAI,KAAK,WAAW,GAAG,IAAI,cAAc,MAAM,MAAM,MAAM,IAAI,KAAA;CACrE,OAAO,IAAI;EAAE,GAAG;EAAM;CAAE,IAAI,EAAE,GAAG,KAAK;AACxC;AAEA,SAAgB,YAAY,QAAsB,MAAmB,QAAqB;CACxF,OAAO,OAAO,IAAI,eAAe,OAAO,GAAG,OAAO,GAAG,MAAM,MAAM,IAAI,OAAO;AAC9E;;AAGA,IAAa,OAAO;AAEpB,IAAM,aAAa,UACjB,OAAO,UAAU,YAAY,MAAM,WAAW,GAAG;;AAGnD,SAAgB,WAAW,MAAsB,MAAmB,QAA8B;CAChG,MAAM,QAAQ,OAAO,SAAS,YAAY,SAAS,OAAO,KAAK,QAAQ;CACvE,IAAI,CAAC,UAAU,KAAK,GAAG,OAAO,QAAQ,KAAA;CACtC,MAAM,OAAO,cAAc,OAAO,MAAM,MAAM;CAC9C,IAAI,CAAC,MAAM,OAAO;CAElB,OAAO;EAAE,GADM,OAAO,SAAS,YAAY,SAAS,OAAO,OAAO,EAAE,MAAM;GACrD,OAAO;CAAK;AACnC;;AAGA,IAAa,WAAW,WACtB,OAAO,WAAW,YAAY,WAAW,QAAA,WAAgB;;AAG3D,SAAgB,YAAY,QAAiB,MAAmB,QAAqB;CACnF,IAAI,CAAC,QAAQ,MAAM,GAAG,OAAO;CAC7B,MAAM,GAAG,OAAO,MAAM,GAAG,SAAS;CAClC,IAAI,UAAU,KAAK,KAAK,GAAG,KAAK,QAAQ,eAAe,KAAK,OAAO,MAAM,MAAM,MAAM;CACrF,OAAO,YAAY,IAAI;AACzB"}