@heycys/gallery 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (806) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -2
  3. package/THIRD-PARTY-NOTICES.md +3303 -0
  4. package/assets/writing-preferences.md +107 -0
  5. package/bin/gallery.mjs +10 -0
  6. package/browser/editor/components/bookmark/icons.mjs +6 -0
  7. package/browser/editor/components/bookmark/index.mjs +80 -0
  8. package/browser/editor/components/bookmark/page.mjs +147 -0
  9. package/browser/editor/components/builders.mjs +19 -0
  10. package/browser/editor/components/callout/index.mjs +64 -0
  11. package/browser/editor/components/code/index.mjs +327 -0
  12. package/browser/editor/components/code/page.mjs +561 -0
  13. package/browser/editor/components/colors.mjs +50 -0
  14. package/browser/editor/components/columns/index.mjs +104 -0
  15. package/browser/editor/components/columns/page.mjs +310 -0
  16. package/browser/editor/components/details/index.mjs +73 -0
  17. package/browser/editor/components/details/page.mjs +86 -0
  18. package/browser/editor/components/dialog/index.mjs +84 -0
  19. package/browser/editor/components/dialog/page.mjs +201 -0
  20. package/browser/editor/components/divider/index.mjs +48 -0
  21. package/browser/editor/components/embed/icons.mjs +11 -0
  22. package/browser/editor/components/embed/index.mjs +123 -0
  23. package/browser/editor/components/embed/page.mjs +309 -0
  24. package/browser/editor/components/figure/index.mjs +87 -0
  25. package/browser/editor/components/figure/page.mjs +42 -0
  26. package/browser/editor/components/file/icons.mjs +14 -0
  27. package/browser/editor/components/file/index.mjs +77 -0
  28. package/browser/editor/components/file/page.mjs +114 -0
  29. package/browser/editor/components/flowchart/add.mjs +123 -0
  30. package/browser/editor/components/flowchart/index.mjs +246 -0
  31. package/browser/editor/components/flowchart/page.mjs +453 -0
  32. package/browser/editor/components/heading/index.mjs +53 -0
  33. package/browser/editor/components/heading/page.mjs +6 -0
  34. package/browser/editor/components/highlight/index.mjs +63 -0
  35. package/browser/editor/components/icon/index.mjs +57 -0
  36. package/browser/editor/components/icon/page.mjs +286 -0
  37. package/browser/editor/components/icons.mjs +48 -0
  38. package/browser/editor/components/image/crop.mjs +189 -0
  39. package/browser/editor/components/image/index.mjs +104 -0
  40. package/browser/editor/components/image/page.mjs +385 -0
  41. package/browser/editor/components/image/viewer.mjs +213 -0
  42. package/browser/editor/components/installed/index.mjs +179 -0
  43. package/browser/editor/components/installed/page.mjs +523 -0
  44. package/browser/editor/components/installed/served.mjs +35 -0
  45. package/browser/editor/components/kit.mjs +67 -0
  46. package/browser/editor/components/list/index.mjs +194 -0
  47. package/browser/editor/components/list/join.mjs +68 -0
  48. package/browser/editor/components/list/numbers.mjs +107 -0
  49. package/browser/editor/components/list/page.mjs +632 -0
  50. package/browser/editor/components/math/index.mjs +88 -0
  51. package/browser/editor/components/math/page.mjs +236 -0
  52. package/browser/editor/components/math/tex-logo.mjs +6 -0
  53. package/browser/editor/components/media/icons.mjs +19 -0
  54. package/browser/editor/components/media/page.mjs +192 -0
  55. package/browser/editor/components/media/parts.mjs +60 -0
  56. package/browser/editor/components/media/size.mjs +20 -0
  57. package/browser/editor/components/media/toolbar.mjs +37 -0
  58. package/browser/editor/components/media/write.mjs +7 -0
  59. package/browser/editor/components/pages.mjs +46 -0
  60. package/browser/editor/components/paragraph/index.mjs +43 -0
  61. package/browser/editor/components/paragraph/page.mjs +52 -0
  62. package/browser/editor/components/placeholder-bar.mjs +17 -0
  63. package/browser/editor/components/placeholder.mjs +128 -0
  64. package/browser/editor/components/quote/index.mjs +33 -0
  65. package/browser/editor/components/registry.mjs +859 -0
  66. package/browser/editor/components/rows.mjs +16 -0
  67. package/browser/editor/components/section/index.mjs +42 -0
  68. package/browser/editor/components/section/page.mjs +141 -0
  69. package/browser/editor/components/set-apart.mjs +24 -0
  70. package/browser/editor/components/sheets/index.mjs +137 -0
  71. package/browser/editor/components/sheets/page.mjs +227 -0
  72. package/browser/editor/components/sheets/pills.mjs +226 -0
  73. package/browser/editor/components/table/grid.mjs +73 -0
  74. package/browser/editor/components/table/index.mjs +308 -0
  75. package/browser/editor/components/table/page.mjs +683 -0
  76. package/browser/editor/components/table/slots.mjs +41 -0
  77. package/browser/editor/components/widget/index.mjs +50 -0
  78. package/browser/editor/page/annotate/anchors.mjs +230 -0
  79. package/browser/editor/page/annotate/card.mjs +102 -0
  80. package/browser/editor/page/annotate/index.mjs +1656 -0
  81. package/browser/editor/page/at-menu/index.mjs +317 -0
  82. package/browser/editor/page/autosave.mjs +1023 -0
  83. package/browser/editor/page/beside.mjs +21 -0
  84. package/browser/editor/page/block-info.mjs +63 -0
  85. package/browser/editor/page/block-menu/colors.mjs +84 -0
  86. package/browser/editor/page/block-menu/index.mjs +217 -0
  87. package/browser/editor/page/blocks.mjs +255 -0
  88. package/browser/editor/page/caret.mjs +682 -0
  89. package/browser/editor/page/changes/bar.mjs +102 -0
  90. package/browser/editor/page/changes/ghost.mjs +206 -0
  91. package/browser/editor/page/changes/gone-words.mjs +94 -0
  92. package/browser/editor/page/changes/index.mjs +447 -0
  93. package/browser/editor/page/changes/words.mjs +27 -0
  94. package/browser/editor/page/chip-fills.mjs +126 -0
  95. package/browser/editor/page/clipboard/import/colors.mjs +192 -0
  96. package/browser/editor/page/clipboard/import/html.mjs +792 -0
  97. package/browser/editor/page/clipboard/import/inline.mjs +232 -0
  98. package/browser/editor/page/clipboard/import/languages.mjs +42 -0
  99. package/browser/editor/page/clipboard/import/markdown.mjs +760 -0
  100. package/browser/editor/page/clipboard/import/math.mjs +100 -0
  101. package/browser/editor/page/clipboard/import/office.mjs +245 -0
  102. package/browser/editor/page/clipboard/import/read.mjs +120 -0
  103. package/browser/editor/page/clipboard/import/rich.mjs +29 -0
  104. package/browser/editor/page/clipboard/import/to-blocks.mjs +290 -0
  105. package/browser/editor/page/clipboard/index.mjs +816 -0
  106. package/browser/editor/page/clipboard/own/blocks.mjs +211 -0
  107. package/browser/editor/page/clipboard/own/chart-keys.mjs +58 -0
  108. package/browser/editor/page/clipboard/own/describe.mjs +124 -0
  109. package/browser/editor/page/clipboard/own/export.mjs +167 -0
  110. package/browser/editor/page/clipboard/own/ids.mjs +39 -0
  111. package/browser/editor/page/clipboard/own/index.mjs +13 -0
  112. package/browser/editor/page/clipboard/own/rules.mjs +44 -0
  113. package/browser/editor/page/clipboard/own/selection.mjs +159 -0
  114. package/browser/editor/page/clipboard/own/writers.mjs +315 -0
  115. package/browser/editor/page/columns/index.mjs +360 -0
  116. package/browser/editor/page/commit.mjs +1813 -0
  117. package/browser/editor/page/conflicts.mjs +249 -0
  118. package/browser/editor/page/convert.mjs +831 -0
  119. package/browser/editor/page/core.mjs +1693 -0
  120. package/browser/editor/page/drag/drop.mjs +307 -0
  121. package/browser/editor/page/drag/index.mjs +351 -0
  122. package/browser/editor/page/drag/preview.mjs +126 -0
  123. package/browser/editor/page/edge-scroll.mjs +50 -0
  124. package/browser/editor/page/editor.mjs +1780 -0
  125. package/browser/editor/page/emoji-picker/emoji-tab.mjs +287 -0
  126. package/browser/editor/page/emoji-picker/glyph-html.mjs +26 -0
  127. package/browser/editor/page/emoji-picker/grid.mjs +81 -0
  128. package/browser/editor/page/emoji-picker/icon-tab.mjs +217 -0
  129. package/browser/editor/page/emoji-picker/icons.mjs +31 -0
  130. package/browser/editor/page/emoji-picker/index.mjs +166 -0
  131. package/browser/editor/page/emoji-picker/styles.mjs +161 -0
  132. package/browser/editor/page/emoji-picker/support.mjs +204 -0
  133. package/browser/editor/page/emoji-picker/upload.mjs +236 -0
  134. package/browser/editor/page/export-report.mjs +23 -0
  135. package/browser/editor/page/fills.mjs +62 -0
  136. package/browser/editor/page/find/index.mjs +107 -0
  137. package/browser/editor/page/flags.mjs +70 -0
  138. package/browser/editor/page/fold/index.mjs +348 -0
  139. package/browser/editor/page/fold/rule.mjs +125 -0
  140. package/browser/editor/page/folded.mjs +23 -0
  141. package/browser/editor/page/format-bar/bar.mjs +449 -0
  142. package/browser/editor/page/format-bar/brush.mjs +77 -0
  143. package/browser/editor/page/format-bar/colors.mjs +46 -0
  144. package/browser/editor/page/format-bar/index.mjs +404 -0
  145. package/browser/editor/page/formula/index.mjs +236 -0
  146. package/browser/editor/page/formula/panel.mjs +336 -0
  147. package/browser/editor/page/formula/symbols.mjs +156 -0
  148. package/browser/editor/page/frame.mjs +74 -0
  149. package/browser/editor/page/frames.mjs +196 -0
  150. package/browser/editor/page/geometry.mjs +402 -0
  151. package/browser/editor/page/gesture.mjs +45 -0
  152. package/browser/editor/page/handle/index.mjs +650 -0
  153. package/browser/editor/page/handle-sizes.mjs +14 -0
  154. package/browser/editor/page/hints/index.mjs +84 -0
  155. package/browser/editor/page/history.mjs +401 -0
  156. package/browser/editor/page/insert/index.mjs +256 -0
  157. package/browser/editor/page/kept.mjs +38 -0
  158. package/browser/editor/page/links/address.mjs +40 -0
  159. package/browser/editor/page/links/index.mjs +866 -0
  160. package/browser/editor/page/links/pages.mjs +131 -0
  161. package/browser/editor/page/links/views.mjs +369 -0
  162. package/browser/editor/page/long-runs.mjs +75 -0
  163. package/browser/editor/page/look.mjs +77 -0
  164. package/browser/editor/page/made.mjs +24 -0
  165. package/browser/editor/page/margin.mjs +373 -0
  166. package/browser/editor/page/markdown/index.mjs +88 -0
  167. package/browser/editor/page/markdown/rules.mjs +33 -0
  168. package/browser/editor/page/marks.mjs +377 -0
  169. package/browser/editor/page/media-menu/index.mjs +158 -0
  170. package/browser/editor/page/menu.mjs +544 -0
  171. package/browser/editor/page/merge.mjs +124 -0
  172. package/browser/editor/page/notices.mjs +142 -0
  173. package/browser/editor/page/offered.mjs +32 -0
  174. package/browser/editor/page/outline/folds.mjs +53 -0
  175. package/browser/editor/page/outline/index.mjs +783 -0
  176. package/browser/editor/page/outline/list.mjs +184 -0
  177. package/browser/editor/page/outline/read.mjs +201 -0
  178. package/browser/editor/page/outline/strip.mjs +287 -0
  179. package/browser/editor/page/outline/tree.mjs +248 -0
  180. package/browser/editor/page/overlay-layer.mjs +227 -0
  181. package/browser/editor/page/overlays.mjs +205 -0
  182. package/browser/editor/page/own.mjs +28 -0
  183. package/browser/editor/page/pads.mjs +71 -0
  184. package/browser/editor/page/page-objects.mjs +105 -0
  185. package/browser/editor/page/panel.mjs +65 -0
  186. package/browser/editor/page/placement.mjs +58 -0
  187. package/browser/editor/page/post.mjs +41 -0
  188. package/browser/editor/page/present-links.mjs +50 -0
  189. package/browser/editor/page/quiet.mjs +48 -0
  190. package/browser/editor/page/resize/index.mjs +327 -0
  191. package/browser/editor/page/select-all/index.mjs +262 -0
  192. package/browser/editor/page/selection/delete.mjs +61 -0
  193. package/browser/editor/page/selection/index.mjs +164 -0
  194. package/browser/editor/page/selection/marquee.mjs +174 -0
  195. package/browser/editor/page/session.mjs +168 -0
  196. package/browser/editor/page/slash-menu/index.mjs +291 -0
  197. package/browser/editor/page/storage.mjs +48 -0
  198. package/browser/editor/page/sync-state.mjs +267 -0
  199. package/browser/editor/page/table/aligns.mjs +29 -0
  200. package/browser/editor/page/table/cell-bar.mjs +141 -0
  201. package/browser/editor/page/table/cells.mjs +527 -0
  202. package/browser/editor/page/table/icons.mjs +40 -0
  203. package/browser/editor/page/table/index.mjs +990 -0
  204. package/browser/editor/page/table/lists.mjs +187 -0
  205. package/browser/editor/page/table/widths.mjs +313 -0
  206. package/browser/editor/page/tex.mjs +32 -0
  207. package/browser/editor/page/text-select/index.mjs +671 -0
  208. package/browser/editor/page/tooltip.mjs +98 -0
  209. package/browser/editor/page/type-grid.mjs +83 -0
  210. package/browser/editor/page/typing/code-edges.mjs +274 -0
  211. package/browser/editor/page/typing/index.mjs +282 -0
  212. package/browser/editor/page/typing/leave.mjs +68 -0
  213. package/browser/editor/page/ui.mjs +160 -0
  214. package/browser/shared/annotations.mjs +569 -0
  215. package/browser/shared/code-folds.mjs +14 -0
  216. package/browser/shared/code-languages.mjs +70 -0
  217. package/browser/shared/code-lines.mjs +30 -0
  218. package/browser/shared/colors.mjs +30 -0
  219. package/browser/shared/component-catalog.mjs +573 -0
  220. package/browser/shared/components/bookmark.mjs +26 -0
  221. package/browser/shared/components/callout.mjs +9 -0
  222. package/browser/shared/components/chart.mjs +20 -0
  223. package/browser/shared/components/code.mjs +37 -0
  224. package/browser/shared/components/columns.mjs +16 -0
  225. package/browser/shared/components/details.mjs +15 -0
  226. package/browser/shared/components/dialog.mjs +28 -0
  227. package/browser/shared/components/diff.mjs +18 -0
  228. package/browser/shared/components/divider.mjs +6 -0
  229. package/browser/shared/components/embed.mjs +25 -0
  230. package/browser/shared/components/figure.mjs +14 -0
  231. package/browser/shared/components/file.mjs +23 -0
  232. package/browser/shared/components/heading.mjs +6 -0
  233. package/browser/shared/components/highlight.mjs +9 -0
  234. package/browser/shared/components/icon.mjs +18 -0
  235. package/browser/shared/components/image.mjs +39 -0
  236. package/browser/shared/components/index.mjs +396 -0
  237. package/browser/shared/components/installed.mjs +232 -0
  238. package/browser/shared/components/list.mjs +146 -0
  239. package/browser/shared/components/math.mjs +49 -0
  240. package/browser/shared/components/mention.mjs +33 -0
  241. package/browser/shared/components/page.mjs +46 -0
  242. package/browser/shared/components/paragraph.mjs +9 -0
  243. package/browser/shared/components/quote.mjs +6 -0
  244. package/browser/shared/components/section.mjs +8 -0
  245. package/browser/shared/components/sheets.mjs +80 -0
  246. package/browser/shared/components/state.mjs +20 -0
  247. package/browser/shared/components/table.mjs +49 -0
  248. package/browser/shared/components/text.mjs +14 -0
  249. package/browser/shared/components/widget.mjs +10 -0
  250. package/browser/shared/copy-ids.mjs +72 -0
  251. package/browser/shared/css-references.mjs +110 -0
  252. package/browser/shared/document-look.mjs +178 -0
  253. package/browser/shared/emoji/custom.mjs +91 -0
  254. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  255. package/browser/shared/emoji/data/LICENSE-mingcute.txt +202 -0
  256. package/browser/shared/emoji/data/LICENSE-tabler.txt +21 -0
  257. package/browser/shared/emoji/data/README.md +28 -0
  258. package/browser/shared/emoji/data/categories.json +1 -0
  259. package/browser/shared/emoji/data/icons.json +1 -0
  260. package/browser/shared/emoji/data/keywords-en.json +1 -0
  261. package/browser/shared/emoji/data/keywords-zh.json +1 -0
  262. package/browser/shared/emoji/data/names.json +1 -0
  263. package/browser/shared/emoji/data/positions.json +1 -0
  264. package/browser/shared/emoji/data/twemoji-index.json +1 -0
  265. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  266. package/browser/shared/emoji/data.mjs +194 -0
  267. package/browser/shared/emoji/emoji.mjs +38 -0
  268. package/browser/shared/emoji/glyphs.mjs +134 -0
  269. package/browser/shared/emoji/icon-value.mjs +91 -0
  270. package/browser/shared/escape.mjs +20 -0
  271. package/browser/shared/export-wrap.mjs +89 -0
  272. package/browser/shared/files.mjs +33 -0
  273. package/browser/shared/html-tree.mjs +59 -0
  274. package/browser/shared/http.mjs +22 -0
  275. package/browser/shared/i18n/en.mjs +1223 -0
  276. package/browser/shared/i18n/index.mjs +132 -0
  277. package/browser/shared/ids.mjs +24 -0
  278. package/browser/shared/import-types.mjs +23 -0
  279. package/browser/shared/inline-spacing.mjs +97 -0
  280. package/browser/shared/layers.mjs +42 -0
  281. package/browser/shared/long-runs.mjs +39 -0
  282. package/browser/shared/media.mjs +162 -0
  283. package/browser/shared/new-names.mjs +67 -0
  284. package/browser/shared/number-reading.mjs +92 -0
  285. package/browser/shared/old-names.mjs +143 -0
  286. package/browser/shared/outline.mjs +194 -0
  287. package/browser/shared/page-address.mjs +140 -0
  288. package/browser/shared/page-links.mjs +86 -0
  289. package/browser/shared/paths.mjs +73 -0
  290. package/browser/shared/preferences.mjs +116 -0
  291. package/browser/shared/preview-server.mjs +247 -0
  292. package/browser/shared/qa-levels.mjs +93 -0
  293. package/browser/shared/reading-place.mjs +91 -0
  294. package/browser/shared/renamed-storage.mjs +220 -0
  295. package/browser/shared/reports.mjs +46 -0
  296. package/browser/shared/search.mjs +85 -0
  297. package/browser/shared/session.mjs +77 -0
  298. package/browser/shared/table-chart.mjs +113 -0
  299. package/browser/shared/table-hides.mjs +120 -0
  300. package/browser/shared/table-slots.mjs +75 -0
  301. package/browser/shared/words.mjs +23 -0
  302. package/browser/shared/workspace-look.mjs +91 -0
  303. package/browser/shared/workspace.mjs +535 -0
  304. package/browser/shared/writing-preferences.mjs +68 -0
  305. package/browser/shared/zoom.mjs +57 -0
  306. package/dist/chunk-2B5E4CDJ.mjs +2 -0
  307. package/dist/chunk-342HXE3Q.mjs +2 -0
  308. package/dist/chunk-3HIRPVLU.mjs +2 -0
  309. package/dist/chunk-43B75J5T.mjs +2 -0
  310. package/dist/chunk-4FS7Z7WR.mjs +2 -0
  311. package/dist/chunk-4K5KC6V2.mjs +2 -0
  312. package/dist/chunk-5L7RYZCL.mjs +2 -0
  313. package/dist/chunk-5MHMDLZD.mjs +4 -0
  314. package/dist/chunk-5ZKJ3H4P.mjs +8 -0
  315. package/dist/chunk-64K7IPLO.mjs +255 -0
  316. package/dist/chunk-6QXGZM36.mjs +8 -0
  317. package/dist/chunk-6RGJOMJP.mjs +16 -0
  318. package/dist/chunk-742D2WWJ.mjs +19 -0
  319. package/dist/chunk-7DTINW6U.mjs +48 -0
  320. package/dist/chunk-A55HN5OK.mjs +2 -0
  321. package/dist/chunk-AGDILNWB.mjs +2 -0
  322. package/dist/chunk-AJ73XJF3.mjs +2 -0
  323. package/dist/chunk-AUZGSZJH.mjs +13 -0
  324. package/dist/chunk-BFE45AKL.mjs +2 -0
  325. package/dist/chunk-BGGDRNYQ.mjs +10 -0
  326. package/dist/chunk-BXO2ZY5P.mjs +2 -0
  327. package/dist/chunk-C564NU2H.mjs +77 -0
  328. package/dist/chunk-CEH4MRCC.mjs +2 -0
  329. package/dist/chunk-CY2FNNAB.mjs +16 -0
  330. package/dist/chunk-DFUDV4LX.mjs +2 -0
  331. package/dist/chunk-DKXG4XDG.mjs +2 -0
  332. package/dist/chunk-E7LWZRXY.mjs +4 -0
  333. package/dist/chunk-EZQ34M3F.mjs +124 -0
  334. package/dist/chunk-EZY3WC6Z.mjs +15 -0
  335. package/dist/chunk-FDLXYYG4.mjs +4 -0
  336. package/dist/chunk-FUKQNOQS.mjs +9 -0
  337. package/dist/chunk-GB5SOYQJ.mjs +7 -0
  338. package/dist/chunk-GRAXKKG4.mjs +2 -0
  339. package/dist/chunk-HYMEEXKN.mjs +4 -0
  340. package/dist/chunk-IVDLMMBD.mjs +2 -0
  341. package/dist/chunk-JPOSLGOC.mjs +6 -0
  342. package/dist/chunk-JVHHHGEA.mjs +3 -0
  343. package/dist/chunk-L3QKH4OK.mjs +26 -0
  344. package/dist/chunk-LAE5NQ4B.mjs +2 -0
  345. package/dist/chunk-LCTHTZIL.mjs +960 -0
  346. package/dist/chunk-LEF6DRCK.mjs +59 -0
  347. package/dist/chunk-LKX55H76.mjs +2 -0
  348. package/dist/chunk-LS4F7JUM.mjs +2 -0
  349. package/dist/chunk-MAFIGVXY.mjs +2 -0
  350. package/dist/chunk-NO5NJCHO.mjs +2 -0
  351. package/dist/chunk-NQPVAU63.mjs +2 -0
  352. package/dist/chunk-NSKUTQ5J.mjs +5 -0
  353. package/dist/chunk-O35FIXRB.mjs +2 -0
  354. package/dist/chunk-P2CAZPDP.mjs +3 -0
  355. package/dist/chunk-PL6GHLGD.mjs +15 -0
  356. package/dist/chunk-QAIHRH3I.mjs +13 -0
  357. package/dist/chunk-QJIR2BLP.mjs +6 -0
  358. package/dist/chunk-QR6A54KJ.mjs +3 -0
  359. package/dist/chunk-QUPLVPB2.mjs +7 -0
  360. package/dist/chunk-R7BNENLY.mjs +4 -0
  361. package/dist/chunk-S6O4UHLC.mjs +2 -0
  362. package/dist/chunk-SGJWQKEI.mjs +2 -0
  363. package/dist/chunk-SYGN7GLU.mjs +2 -0
  364. package/dist/chunk-TMYZB6AV.mjs +2 -0
  365. package/dist/chunk-TX6JH7TR.mjs +2 -0
  366. package/dist/chunk-TYK6VNAB.mjs +10 -0
  367. package/dist/chunk-U3SSPL4K.mjs +8 -0
  368. package/dist/chunk-U6KNPJPR.mjs +2 -0
  369. package/dist/chunk-UALRNVSE.mjs +4 -0
  370. package/dist/chunk-UH4SIXTR.mjs +2 -0
  371. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  372. package/dist/chunk-V3HXVQEM.mjs +2 -0
  373. package/dist/chunk-V5JTW2LH.mjs +27 -0
  374. package/dist/chunk-V5VXUJKG.mjs +2 -0
  375. package/dist/chunk-V6XZ4VIR.mjs +2 -0
  376. package/dist/chunk-VBXMADMP.mjs +2 -0
  377. package/dist/chunk-VNV55RUA.mjs +2 -0
  378. package/dist/chunk-VPD2PS35.mjs +2 -0
  379. package/dist/chunk-W3BGBJQW.mjs +2 -0
  380. package/dist/chunk-W4VKN3GF.mjs +7 -0
  381. package/dist/chunk-W5BXXPDJ.mjs +3 -0
  382. package/dist/chunk-W7XHE4CT.mjs +2 -0
  383. package/dist/chunk-XNROSH2T.mjs +4 -0
  384. package/dist/chunk-XUNHRCOG.mjs +6 -0
  385. package/dist/chunk-Y34NR5JL.mjs +2 -0
  386. package/dist/chunk-Y6RLRPG3.mjs +3 -0
  387. package/dist/chunk-YEY3RSFQ.mjs +2 -0
  388. package/dist/cli.mjs +2 -0
  389. package/dist/server.mjs +2 -0
  390. package/dist/worker.mjs +5 -0
  391. package/kit/charts.js +355 -0
  392. package/kit/code.js +164 -0
  393. package/kit/dialogs.js +157 -0
  394. package/kit/math.js +2004 -0
  395. package/kit/report.css +2932 -0
  396. package/kit/runtime.js +1782 -0
  397. package/kit/sheets.js +123 -0
  398. package/kit/state.js +217 -0
  399. package/kit/tables.js +1499 -0
  400. package/kit/tokens.js +29 -0
  401. package/kit/ui.js +658 -0
  402. package/package.json +41 -4
  403. package/release.json +25 -0
  404. package/sdk/column-widths.d.ts +56 -0
  405. package/sdk/doc-charts.d.ts +82 -0
  406. package/sdk/doc-code.d.ts +28 -0
  407. package/sdk/doc-dialogs.d.ts +4 -0
  408. package/sdk/doc-kit.d.ts +147 -0
  409. package/sdk/doc-math.d.ts +3 -0
  410. package/sdk/doc-sheets.d.ts +15 -0
  411. package/sdk/doc-state.d.ts +41 -0
  412. package/sdk/doc-tables.d.ts +24 -0
  413. package/sdk/doc-tokens.d.ts +22 -0
  414. package/sdk/index.d.ts +30 -0
  415. package/skill/SKILL.md +150 -0
  416. package/skill/agents/openai.yaml +5 -0
  417. package/skill/references/building-components.md +367 -0
  418. package/skill/references/example-report.html +356 -0
  419. package/skill/references/writing-html.md +187 -0
  420. package/skill/sdk/column-widths.d.ts +56 -0
  421. package/skill/sdk/doc-charts.d.ts +82 -0
  422. package/skill/sdk/doc-code.d.ts +28 -0
  423. package/skill/sdk/doc-dialogs.d.ts +4 -0
  424. package/skill/sdk/doc-kit.d.ts +147 -0
  425. package/skill/sdk/doc-math.d.ts +3 -0
  426. package/skill/sdk/doc-sheets.d.ts +15 -0
  427. package/skill/sdk/doc-state.d.ts +41 -0
  428. package/skill/sdk/doc-tables.d.ts +24 -0
  429. package/skill/sdk/doc-tokens.d.ts +22 -0
  430. package/skill/sdk/index.d.ts +30 -0
  431. package/starter/doc.html +21 -0
  432. package/starter/doc.json +5 -0
  433. package/vendor/d3.v7.9.0.min.js +2 -0
  434. package/vendor/katex/auto-render.min.js +1 -0
  435. package/vendor/katex/contrib/mhchem.min.js +1 -0
  436. package/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  437. package/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  438. package/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  439. package/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  440. package/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  441. package/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  442. package/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  443. package/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  444. package/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  445. package/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  446. package/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  447. package/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  448. package/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  449. package/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  450. package/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  451. package/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  452. package/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  453. package/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  454. package/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  455. package/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  456. package/vendor/katex/katex.min.css +1 -0
  457. package/vendor/katex/katex.min.js +1 -0
  458. package/vendor/pdfjs/LICENSE +177 -0
  459. package/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  460. package/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  461. package/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
  462. package/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  463. package/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  464. package/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
  465. package/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  466. package/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  467. package/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  468. package/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  469. package/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  470. package/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  471. package/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  472. package/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  473. package/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  474. package/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
  475. package/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  476. package/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  477. package/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
  478. package/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  479. package/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  480. package/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  481. package/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  482. package/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  483. package/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  484. package/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  485. package/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  486. package/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  487. package/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  488. package/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  489. package/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  490. package/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  491. package/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  492. package/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  493. package/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  494. package/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  495. package/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  496. package/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  497. package/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  498. package/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  499. package/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  500. package/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  501. package/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  502. package/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  503. package/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  504. package/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  505. package/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
  506. package/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
  507. package/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  508. package/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  509. package/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  510. package/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  511. package/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  512. package/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  513. package/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  514. package/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  515. package/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  516. package/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  517. package/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  518. package/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  519. package/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  520. package/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  521. package/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
  522. package/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
  523. package/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
  524. package/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  525. package/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  526. package/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
  527. package/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  528. package/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  529. package/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
  530. package/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
  531. package/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  532. package/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  533. package/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  534. package/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  535. package/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  536. package/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  537. package/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  538. package/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  539. package/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
  540. package/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
  541. package/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  542. package/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  543. package/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  544. package/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  545. package/vendor/pdfjs/cmaps/H.bcmap +0 -0
  546. package/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  547. package/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  548. package/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  549. package/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  550. package/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  551. package/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  552. package/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  553. package/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  554. package/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  555. package/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  556. package/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  557. package/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  558. package/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
  559. package/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
  560. package/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  561. package/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  562. package/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
  563. package/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  564. package/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  565. package/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
  566. package/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  567. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  568. package/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  569. package/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  570. package/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  571. package/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  572. package/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
  573. package/vendor/pdfjs/cmaps/LICENSE +36 -0
  574. package/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
  575. package/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
  576. package/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  577. package/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  578. package/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
  579. package/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  580. package/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  581. package/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  582. package/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  583. package/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  584. package/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  585. package/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  586. package/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  587. package/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  588. package/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  589. package/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  590. package/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  591. package/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  592. package/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  593. package/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  594. package/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  595. package/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  596. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  597. package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  598. package/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  599. package/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  600. package/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  601. package/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  602. package/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  603. package/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  604. package/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  605. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  606. package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  607. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  608. package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  609. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  610. package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  611. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  612. package/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  613. package/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  614. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  615. package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  616. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  617. package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  618. package/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  619. package/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  620. package/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  621. package/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  622. package/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  623. package/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  624. package/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  625. package/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  626. package/vendor/pdfjs/cmaps/V.bcmap +0 -0
  627. package/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  628. package/vendor/pdfjs/legacy/build/pdf.min.mjs +27 -0
  629. package/vendor/pdfjs/legacy/build/pdf.worker.min.mjs +27 -0
  630. package/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  631. package/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  632. package/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  633. package/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  634. package/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  635. package/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  636. package/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  637. package/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  638. package/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  639. package/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  640. package/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  641. package/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
  642. package/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  643. package/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  644. package/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  645. package/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  646. package/vendor/types/@types/d3/LICENSE +21 -0
  647. package/vendor/types/@types/d3/index.d.ts +39 -0
  648. package/vendor/types/@types/d3/package.json +81 -0
  649. package/vendor/types/@types/d3-array/LICENSE +21 -0
  650. package/vendor/types/@types/d3-array/index.d.ts +1118 -0
  651. package/vendor/types/@types/d3-array/package.json +56 -0
  652. package/vendor/types/@types/d3-axis/LICENSE +21 -0
  653. package/vendor/types/@types/d3-axis/index.d.ts +293 -0
  654. package/vendor/types/@types/d3-axis/package.json +47 -0
  655. package/vendor/types/@types/d3-brush/LICENSE +21 -0
  656. package/vendor/types/@types/d3-brush/index.d.ts +255 -0
  657. package/vendor/types/@types/d3-brush/package.json +42 -0
  658. package/vendor/types/@types/d3-chord/LICENSE +21 -0
  659. package/vendor/types/@types/d3-chord/index.d.ts +471 -0
  660. package/vendor/types/@types/d3-chord/package.json +40 -0
  661. package/vendor/types/@types/d3-color/LICENSE +21 -0
  662. package/vendor/types/@types/d3-color/index.d.ts +669 -0
  663. package/vendor/types/@types/d3-color/package.json +55 -0
  664. package/vendor/types/@types/d3-contour/LICENSE +21 -0
  665. package/vendor/types/@types/d3-contour/index.d.ts +222 -0
  666. package/vendor/types/@types/d3-contour/package.json +38 -0
  667. package/vendor/types/@types/d3-delaunay/LICENSE +21 -0
  668. package/vendor/types/@types/d3-delaunay/index.d.ts +316 -0
  669. package/vendor/types/@types/d3-delaunay/package.json +30 -0
  670. package/vendor/types/@types/d3-dispatch/LICENSE +21 -0
  671. package/vendor/types/@types/d3-dispatch/index.d.ts +96 -0
  672. package/vendor/types/@types/d3-dispatch/package.json +51 -0
  673. package/vendor/types/@types/d3-drag/LICENSE +21 -0
  674. package/vendor/types/@types/d3-drag/index.d.ts +395 -0
  675. package/vendor/types/@types/d3-drag/package.json +42 -0
  676. package/vendor/types/@types/d3-dsv/LICENSE +21 -0
  677. package/vendor/types/@types/d3-dsv/index.d.ts +482 -0
  678. package/vendor/types/@types/d3-dsv/package.json +45 -0
  679. package/vendor/types/@types/d3-ease/LICENSE +21 -0
  680. package/vendor/types/@types/d3-ease/index.d.ts +316 -0
  681. package/vendor/types/@types/d3-ease/package.json +40 -0
  682. package/vendor/types/@types/d3-fetch/LICENSE +21 -0
  683. package/vendor/types/@types/d3-fetch/index.d.ts +282 -0
  684. package/vendor/types/@types/d3-fetch/package.json +37 -0
  685. package/vendor/types/@types/d3-force/LICENSE +21 -0
  686. package/vendor/types/@types/d3-force/index.d.ts +899 -0
  687. package/vendor/types/@types/d3-force/package.json +45 -0
  688. package/vendor/types/@types/d3-format/LICENSE +21 -0
  689. package/vendor/types/@types/d3-format/index.d.ts +337 -0
  690. package/vendor/types/@types/d3-format/package.json +45 -0
  691. package/vendor/types/@types/d3-geo/LICENSE +21 -0
  692. package/vendor/types/@types/d3-geo/index.d.ts +1371 -0
  693. package/vendor/types/@types/d3-geo/package.json +48 -0
  694. package/vendor/types/@types/d3-hierarchy/LICENSE +21 -0
  695. package/vendor/types/@types/d3-hierarchy/index.d.ts +928 -0
  696. package/vendor/types/@types/d3-hierarchy/package.json +50 -0
  697. package/vendor/types/@types/d3-interpolate/LICENSE +21 -0
  698. package/vendor/types/@types/d3-interpolate/index.d.ts +387 -0
  699. package/vendor/types/@types/d3-interpolate/package.json +47 -0
  700. package/vendor/types/@types/d3-path/LICENSE +21 -0
  701. package/vendor/types/@types/d3-path/index.d.ts +108 -0
  702. package/vendor/types/@types/d3-path/package.json +41 -0
  703. package/vendor/types/@types/d3-polygon/LICENSE +21 -0
  704. package/vendor/types/@types/d3-polygon/index.d.ts +41 -0
  705. package/vendor/types/@types/d3-polygon/package.json +40 -0
  706. package/vendor/types/@types/d3-quadtree/LICENSE +21 -0
  707. package/vendor/types/@types/d3-quadtree/index.d.ts +204 -0
  708. package/vendor/types/@types/d3-quadtree/package.json +45 -0
  709. package/vendor/types/@types/d3-random/LICENSE +21 -0
  710. package/vendor/types/@types/d3-random/index.d.ts +313 -0
  711. package/vendor/types/@types/d3-random/package.json +41 -0
  712. package/vendor/types/@types/d3-scale/LICENSE +21 -0
  713. package/vendor/types/@types/d3-scale/index.d.ts +2669 -0
  714. package/vendor/types/@types/d3-scale/package.json +53 -0
  715. package/vendor/types/@types/d3-scale-chromatic/LICENSE +21 -0
  716. package/vendor/types/@types/d3-scale-chromatic/index.d.ts +520 -0
  717. package/vendor/types/@types/d3-scale-chromatic/package.json +46 -0
  718. package/vendor/types/@types/d3-selection/LICENSE +21 -0
  719. package/vendor/types/@types/d3-selection/index.d.ts +1210 -0
  720. package/vendor/types/@types/d3-selection/package.json +56 -0
  721. package/vendor/types/@types/d3-shape/LICENSE +21 -0
  722. package/vendor/types/@types/d3-shape/index.d.ts +2792 -0
  723. package/vendor/types/@types/d3-shape/package.json +53 -0
  724. package/vendor/types/@types/d3-time/LICENSE +21 -0
  725. package/vendor/types/@types/d3-time/index.d.ts +697 -0
  726. package/vendor/types/@types/d3-time/package.json +46 -0
  727. package/vendor/types/@types/d3-time-format/LICENSE +21 -0
  728. package/vendor/types/@types/d3-time-format/index.d.ts +202 -0
  729. package/vendor/types/@types/d3-time-format/package.json +40 -0
  730. package/vendor/types/@types/d3-timer/LICENSE +21 -0
  731. package/vendor/types/@types/d3-timer/index.d.ts +68 -0
  732. package/vendor/types/@types/d3-timer/package.json +45 -0
  733. package/vendor/types/@types/d3-transition/LICENSE +21 -0
  734. package/vendor/types/@types/d3-transition/index.d.ts +664 -0
  735. package/vendor/types/@types/d3-transition/package.json +47 -0
  736. package/vendor/types/@types/d3-zoom/LICENSE +21 -0
  737. package/vendor/types/@types/d3-zoom/index.d.ts +611 -0
  738. package/vendor/types/@types/d3-zoom/package.json +48 -0
  739. package/vendor/types/@types/geojson/LICENSE +21 -0
  740. package/vendor/types/@types/geojson/index.d.ts +202 -0
  741. package/vendor/types/@types/geojson/package.json +46 -0
  742. package/vendor/typescript/LICENSE.txt +55 -0
  743. package/vendor/typescript/lib.decorators.d.ts +384 -0
  744. package/vendor/typescript/lib.decorators.legacy.d.ts +22 -0
  745. package/vendor/typescript/lib.dom.d.ts +39429 -0
  746. package/vendor/typescript/lib.dom.iterable.d.ts +571 -0
  747. package/vendor/typescript/lib.es2015.collection.d.ts +147 -0
  748. package/vendor/typescript/lib.es2015.core.d.ts +597 -0
  749. package/vendor/typescript/lib.es2015.d.ts +28 -0
  750. package/vendor/typescript/lib.es2015.generator.d.ts +77 -0
  751. package/vendor/typescript/lib.es2015.iterable.d.ts +605 -0
  752. package/vendor/typescript/lib.es2015.promise.d.ts +81 -0
  753. package/vendor/typescript/lib.es2015.proxy.d.ts +128 -0
  754. package/vendor/typescript/lib.es2015.reflect.d.ts +144 -0
  755. package/vendor/typescript/lib.es2015.symbol.d.ts +46 -0
  756. package/vendor/typescript/lib.es2015.symbol.wellknown.d.ts +326 -0
  757. package/vendor/typescript/lib.es2016.array.include.d.ts +116 -0
  758. package/vendor/typescript/lib.es2016.d.ts +21 -0
  759. package/vendor/typescript/lib.es2016.intl.d.ts +31 -0
  760. package/vendor/typescript/lib.es2017.arraybuffer.d.ts +21 -0
  761. package/vendor/typescript/lib.es2017.d.ts +26 -0
  762. package/vendor/typescript/lib.es2017.date.d.ts +31 -0
  763. package/vendor/typescript/lib.es2017.intl.d.ts +44 -0
  764. package/vendor/typescript/lib.es2017.object.d.ts +49 -0
  765. package/vendor/typescript/lib.es2017.sharedmemory.d.ts +135 -0
  766. package/vendor/typescript/lib.es2017.string.d.ts +45 -0
  767. package/vendor/typescript/lib.es2017.typedarrays.d.ts +53 -0
  768. package/vendor/typescript/lib.es2018.asyncgenerator.d.ts +77 -0
  769. package/vendor/typescript/lib.es2018.asynciterable.d.ts +53 -0
  770. package/vendor/typescript/lib.es2018.d.ts +24 -0
  771. package/vendor/typescript/lib.es2018.intl.d.ts +83 -0
  772. package/vendor/typescript/lib.es2018.promise.d.ts +30 -0
  773. package/vendor/typescript/lib.es2018.regexp.d.ts +37 -0
  774. package/vendor/typescript/lib.es2019.array.d.ts +79 -0
  775. package/vendor/typescript/lib.es2019.d.ts +24 -0
  776. package/vendor/typescript/lib.es2019.intl.d.ts +23 -0
  777. package/vendor/typescript/lib.es2019.object.d.ts +33 -0
  778. package/vendor/typescript/lib.es2019.string.d.ts +37 -0
  779. package/vendor/typescript/lib.es2019.symbol.d.ts +24 -0
  780. package/vendor/typescript/lib.es2020.bigint.d.ts +765 -0
  781. package/vendor/typescript/lib.es2020.d.ts +27 -0
  782. package/vendor/typescript/lib.es2020.date.d.ts +42 -0
  783. package/vendor/typescript/lib.es2020.intl.d.ts +474 -0
  784. package/vendor/typescript/lib.es2020.number.d.ts +28 -0
  785. package/vendor/typescript/lib.es2020.promise.d.ts +47 -0
  786. package/vendor/typescript/lib.es2020.sharedmemory.d.ts +99 -0
  787. package/vendor/typescript/lib.es2020.string.d.ts +44 -0
  788. package/vendor/typescript/lib.es2020.symbol.wellknown.d.ts +41 -0
  789. package/vendor/typescript/lib.es2021.d.ts +23 -0
  790. package/vendor/typescript/lib.es2021.intl.d.ts +166 -0
  791. package/vendor/typescript/lib.es2021.promise.d.ts +48 -0
  792. package/vendor/typescript/lib.es2021.string.d.ts +33 -0
  793. package/vendor/typescript/lib.es2021.weakref.d.ts +78 -0
  794. package/vendor/typescript/lib.es2022.array.d.ts +121 -0
  795. package/vendor/typescript/lib.es2022.d.ts +25 -0
  796. package/vendor/typescript/lib.es2022.error.d.ts +75 -0
  797. package/vendor/typescript/lib.es2022.intl.d.ts +145 -0
  798. package/vendor/typescript/lib.es2022.object.d.ts +26 -0
  799. package/vendor/typescript/lib.es2022.regexp.d.ts +39 -0
  800. package/vendor/typescript/lib.es2022.string.d.ts +25 -0
  801. package/vendor/typescript/lib.es5.d.ts +4601 -0
  802. package/vendor/typescript/package.json +4 -0
  803. package/vendor/typescript/typescript.js +446 -0
  804. package/web/assets/index-Bh74DfsV.css +1 -0
  805. package/web/assets/index-UW0RyFFt.js +13 -0
  806. package/web/index.html +14 -0
@@ -0,0 +1,385 @@
1
+ import { MEDIA_CLASS } from "../../../shared/components/index.mjs";
2
+ import { SPAN, SPAN_SIZE, UPLOAD_LIMITS, sizeLimit } from "../../../shared/media.mjs";
3
+ import { gestureLock } from "../../page/gesture.mjs";
4
+ import { openCrop } from "./crop.mjs";
5
+ import { openViewer } from "./viewer.mjs";
6
+ import { svg } from "../icons.mjs";
7
+ import { closePopup, openPopup } from "../../page/emoji-picker/support.mjs";
8
+ import { ICONS } from "../../page/menu.mjs";
9
+ import { onSettle, own } from "../../page/overlays.mjs";
10
+ import { drawAt, shapeOf } from "../../page/overlay-layer.mjs";
11
+ import { keptByComponent } from "../../page/page-objects.mjs";
12
+ import { addStyle, element } from "../../page/ui.mjs";
13
+ import { TOOL_ICONS } from "../media/icons.mjs";
14
+ import { barClass } from "../placeholder-bar.mjs";
15
+ import { captionNode, captionOf, fileOf, showFile } from "../media/parts.mjs";
16
+ import { SNAP, columnRoom, readingRoom } from "../media/size.mjs";
17
+ import { mediaBar, toolButton } from "../media/toolbar.mjs";
18
+ import { ALIGN, cropOf, imageOf, newImage } from "./index.mjs";
19
+ import { t } from "../../../shared/i18n/index.mjs";
20
+ import { zoomable } from "../../../shared/zoom.mjs";
21
+
22
+ // 图片 on the page (notion-lite's src/blocks/image/edit/, Notion's media block). A new image (the "/"
23
+ // menu's 图片, made from an empty block: convert.mjs) is a placeholder, a gray bar saying 添加图片,
24
+ // until a picture is chosen in the 上传 / 链接 menu (media-menu/) that opens below it at once and on
25
+ // a click (../media/page.mjs): a file (an image, 10 MB at most) goes to the report's folder, a link's picture is
26
+ // downloaded there by the server (an export never reaches the web); either is one undo step. The
27
+ // picture shows where the server serves the folder; what the file is stays in data-ge-src.
28
+ // With the pointer on a picture, Notion's toolbar stands at its top right (对齐, 标题, 展开, 更多:
29
+ // the block menu) and a handle at each side; dragging one resizes the picture (a share of the reading
30
+ // width, at most the width it stands in, both sides at once while centered; snapping to the whole of
31
+ // that width, a share of 1: styles/sizes.css), one undo step on
32
+ // letting go (Esc puts it back). 标题 shows its caption (empty ones show only then) with the caret
33
+ // in it; Enter there makes a paragraph after the image. A double-click on the picture (or on any
34
+ // other picture that opens large: a table's, a card's), or 展开, shows it alone over the page (a
35
+ // click or Esc closes it). The block menu has 替换图片, 标题, 对齐 ›
36
+ // and 恢复原始大小 (menuItems). A picture pasted (an image file on the clipboard) becomes an image
37
+ // below the block the caret is in (`acceptsFile`, `fromFiles`).
38
+
39
+ const MAX_BYTES = UPLOAD_LIMITS.image;
40
+ // 裁剪图片's row: a crop mark, drawn as the menus' other icons are.
41
+ const CROP_ICON = svg('<path d="M6 2.75V13a1 1 0 0 0 1 1h10.25"/><path d="M2.75 6H13a1 1 0 0 1 1 1v10.25"/>');
42
+
43
+ const STYLE = `
44
+ /* The placeholder of an image with no picture yet (Notion's 605415): every empty block's, served with the page (../placeholder.mjs). */
45
+ [data-ge-editing] .doc-image > img { cursor: default; }
46
+ /* The handles (Notion's 681598); the toolbar is the media blocks' (../media/toolbar.mjs). */
47
+ .ge-layer > .ge-image-handle { pointer-events: auto; }
48
+ .ge-image-align { display: flex; align-items: center; padding: 2px; border-radius: 6px; background: var(--c-popBac); box-shadow: var(--c-shaOutLg); }
49
+ .ge-image-align-sep { width: 1px; height: 16px; margin: 0 2px; background: var(--ca-borSecTra); }
50
+ .ge-image-handle { display: flex; align-items: center; justify-content: center; width: 15px; cursor: col-resize; }
51
+ /* A plain gray bar, no border (the embed's corners the same). */
52
+ .ge-image-handle::after { content: ""; width: 4px; height: 40px; max-height: 50%; border-radius: 4px; background: light-dark(rgb(55 53 47 / 35%), rgb(255 255 255 / 38%)); transition: background 120ms ease; }
53
+ .ge-image-handle:hover::after, html[data-ge-image-resize] .ge-image-handle::after { background: light-dark(rgb(55 53 47 / 60%), rgb(255 255 255 / 62%)); }
54
+ ${gestureLock("data-ge-image-resize", { cursor: "col-resize" })}
55
+ `;
56
+
57
+ const ALIGNS = [["left", t("左对齐"), "alignLeft"], ["center", t("居中对齐"), "alignCenter"], ["right", t("右对齐"), "alignRight"]];
58
+ const sideOf = (figure) => figure.classList.contains(ALIGN[0]) ? "left" : figure.classList.contains(ALIGN[1]) ? "right" : "center";
59
+ const sideLook = (side) => ({ classes: { [ALIGN[0]]: side === "left", [ALIGN[1]]: side === "right" } });
60
+
61
+ // A picture of the report's folder (`path`, assets/<file>) where the server serves it (`url`), and an
62
+ // empty caption; cropped (`cropped`: { original, crop }), the picture it was cropped from and what of it is kept.
63
+ function pictureParts(doc, path, url, caption = "", cropped = null) {
64
+ const img = doc.createElement("img");
65
+ showFile(img, "src", path, url);
66
+ img.alt = "";
67
+ img.draggable = false;
68
+ if (cropped) {
69
+ img.setAttribute("data-original", cropped.original);
70
+ img.setAttribute("data-crop", cropped.crop);
71
+ }
72
+ return [img, captionNode(doc, caption)];
73
+ }
74
+
75
+ /**
76
+ * Images on the page, with what the editor gives them: the media blocks' shared parts (`pages.media`:
77
+ * ../media/page.mjs block("image"): the undo steps, say, active(), select, the block menu, the
78
+ * upload of kind "image", the menu, the caption) and assetUrl(path) (where the server serves a file
79
+ * of the report's folder).
80
+ */
81
+ export function create({ pages, assetUrl }) {
82
+ const media = pages.media.block("image");
83
+ const { say, active, look, openMenu } = media;
84
+ addStyle(STYLE);
85
+
86
+ // ---------- a picture chosen ----------
87
+
88
+ /** The 上传 / 链接 menu of an image, below its placeholder (or its picture: 替换图片). */
89
+ const pick = (figure) => media.pick(figure, {
90
+ width: 360, // Notion's 540 stood far out past the block
91
+ tabs: [{ key: "upload", label: t("上传") }, { key: "link", label: t("链接") }],
92
+ upload: { label: t("上传文件"), accept: "image/*" },
93
+ link: { placeholder: t("粘贴图片链接…"), button: t("嵌入图片"), caption: t("适用于网络上的任何图片。") },
94
+ onUpload: (file) => uploadInto(figure, file),
95
+ onEmbed: (url) => fetchInto(figure, url),
96
+ }, (each) => each.querySelector(`:scope > .${barClass(MEDIA_CLASS.image)}`) ?? imageOf(each) ?? each);
97
+
98
+ async function uploadInto(figure, file, options = {}) {
99
+ if (!/^image\//.test(file.type)) return say(t("很抱歉,不支持该文件类型。"), "error");
100
+ if (file.size > MAX_BYTES) return say(t("图片太大(最多 {0})。", sizeLimit("image")), "error");
101
+ return media.attempt(figure, t("正在上传…"), t("无法上传这张图片"), async () => {
102
+ const pixels = await pixelSize(file);
103
+ place(figure, (await media.uploadFile(file)).path, pixels, options);
104
+ });
105
+ }
106
+
107
+ // A picture's size in pixels ({ width, height }), or null when the browser cannot read it.
108
+ async function pixelSize(file) {
109
+ try {
110
+ const bitmap = await createImageBitmap(file);
111
+ const size = { width: bitmap.width, height: bitmap.height };
112
+ bitmap.close();
113
+ return size;
114
+ } catch {
115
+ return null;
116
+ }
117
+ }
118
+ // The share of the reading width that `pixels` take on this screen, or "" for the kit's own size:
119
+ // a picture as wide as the width `figure` stands in or wider, or one that would stand taller than
120
+ // 80% of this window (a phone's screenshot), which the kit shows at most that tall on every
121
+ // reader's window (styles/image.css), where a span would hold it at its width however tall.
122
+ function naturalShare(figure, pixels) {
123
+ if (!pixels?.width) return "";
124
+ const room = columnRoom(figure);
125
+ const ratio = devicePixelRatio || 1;
126
+ const width = pixels.width / ratio;
127
+ if (!(room > 0) || width >= room || pixels.height / ratio > innerHeight * 0.8) return "";
128
+ return String(Math.max(SPAN_SIZE.min, Math.round((width / readingRoom(figure)) * 1000) / 1000));
129
+ }
130
+
131
+ const fetchInto = (figure, url, options = {}) => media.attempt(figure, t("正在下载…"), t("无法下载这张图片"), async () => {
132
+ place(figure, (await media.uploadUrl(url)).path, null, options);
133
+ });
134
+
135
+ // The picture in: a new image in the place of the placeholder, or of the image that had one
136
+ // (替换图片, with its caption, side and width), never the same element, so that undo brings back
137
+ // what stood there (a placeholder never written, an image as it was) and the file loses the new
138
+ // one. One undo step; the image selected.
139
+ //
140
+ // A new picture from this computer (`pixels`: its size in pixels) shows as large as it was on the
141
+ // screen it was taken on (D7 of the polish plan): its pixels over this screen's device pixel ratio,
142
+ // as a share of the reading width, never past the width it stands in (a screenshot on a high-density
143
+ // screen once showed twice its size); one that tall is left to the kit's 80% of the window
144
+ // (naturalShare). A picture replaced keeps the width the old one had.
145
+ // `cropped`: { original, crop } said on the picture (a crop's); `quiet`: its own word said by the caller.
146
+ function place(figure, path, pixels = null, { cropped = null, quiet = false, pasted = false } = {}) {
147
+ if (!figure.isConnected) return;
148
+ const doc = figure.ownerDocument;
149
+ const replacing = Boolean(imageOf(figure));
150
+ const next = newImage(doc);
151
+ next.className = figure.className;
152
+ const span = figure.style.getPropertyValue(SPAN) || (replacing ? "" : naturalShare(figure, pixels));
153
+ if (span) next.style.setProperty(SPAN, span);
154
+ next.replaceChildren(...pictureParts(doc, path, assetUrl(path), captionOf(figure)?.innerHTML ?? "", cropped));
155
+ media.place(figure, next, { replacing, pasted });
156
+ if (replacing && !quiet) say(t("已替换图片 · Ctrl+Z 撤销"));
157
+ }
158
+
159
+ // ---------- the toolbar and the handles ----------
160
+
161
+ let hovered = null; // the image the pointer is on
162
+ let resizing = null; // { figure, side, x, start, room, before, centered }
163
+ const bar = mediaBar(t("图片操作"));
164
+ const tool = (label, tip, icon, run) => toolButton({ label, tip, icon, run, alive: () => hovered?.isConnected });
165
+ const tools = {
166
+ align: tool(t("对齐方式"), t("设置区块对齐"), () => TOOL_ICONS[{ left: "alignLeft", center: "alignCenter", right: "alignRight" }[sideOf(hovered)]], (button) => alignPopup(hovered, button)),
167
+ caption: tool(t("标题@caption"), t("添加标题"), TOOL_ICONS.caption, () => media.caption(hovered)),
168
+ expand: tool(t("展开"), t("全屏查看"), TOOL_ICONS.expand, () => view(hovered)),
169
+ more: tool(t("更多"), t("打开区块操作菜单"), TOOL_ICONS.more, (button) => {
170
+ const rect = button.getBoundingClientRect();
171
+ openMenu(hovered, { left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom });
172
+ }),
173
+ };
174
+ bar.append(...Object.values(tools));
175
+ const handles = { left: element("div", { class: "ge-image-handle", "data-side": "left" }), right: element("div", { class: "ge-image-handle", "data-side": "right" }) };
176
+
177
+ // The toolbar and the handles over the picture of `figure`, or away.
178
+ function show(figure) {
179
+ hovered = figure;
180
+ const img = figure && imageOf(figure);
181
+ const shape = img && shapeOf(img);
182
+ if (!shape) {
183
+ hovered = null;
184
+ for (const node of [bar, handles.left, handles.right]) node.remove();
185
+ return;
186
+ }
187
+ const alive = () => hovered === figure && figure.isConnected;
188
+ for (const node of [bar, handles.left, handles.right]) own(node, "image tools", { owner: figure, alive });
189
+ for (const button of Object.values(tools)) button.draw();
190
+ const { rect } = shape;
191
+ tools.align.style.display = figure.style.getPropertyValue(SPAN).trim() === "1" ? "none" : ""; // a picture as wide as it can be has no side
192
+ if (bar.parentNode !== shape.layer) shape.layer.append(bar); // in the page before its width is measured
193
+ drawAt(bar, shape.layer, rect.right - 4 - bar.offsetWidth, rect.top + 4);
194
+ for (const [side, handle] of Object.entries(handles)) {
195
+ handle.style.height = `${Math.round(rect.bottom - rect.top)}px`;
196
+ drawAt(handle, shape.layer, side === "left" ? rect.left : rect.right - 15, rect.top);
197
+ }
198
+ }
199
+
200
+ document.addEventListener("mousemove", (event) => {
201
+ if (resizing || [bar, handles.left, handles.right].some((node) => node.contains(event.target))) return;
202
+ const figure = active() && !keptByComponent(event.target) ? event.target.closest?.("main figure.doc-image") ?? null : null;
203
+ if (figure !== hovered) show(figure && imageOf(figure) ? figure : null);
204
+ }, { passive: true, capture: true });
205
+ addEventListener("scroll", () => { if (hovered && !resizing) show(hovered); }, { passive: true, capture: true });
206
+ document.documentElement.addEventListener("mouseleave", () => { if (!resizing) show(null); });
207
+ // The hovered picture taken off the page by an undo, a redo or a commit: the tools go at once, not at the next pointer move.
208
+ onSettle(() => { if (hovered && !hovered.isConnected && !resizing) show(null); });
209
+
210
+ // Dragging a handle: the picture's width as a share of the reading width, at most the width it
211
+ // stands in (1 when it reaches that), live; one undo step on letting go.
212
+ for (const [side, handle] of Object.entries(handles)) {
213
+ handle.addEventListener("pointerdown", (event) => {
214
+ if (event.button !== 0 || !hovered) return;
215
+ event.preventDefault();
216
+ const figure = hovered;
217
+ const room = columnRoom(figure);
218
+ resizing = { figure, side, x: event.clientX, start: imageOf(figure).getBoundingClientRect().width, room, page: readingRoom(figure), before: figure.style.getPropertyValue(SPAN), centered: sideOf(figure) === "center" };
219
+ handle.setPointerCapture?.(event.pointerId);
220
+ document.documentElement.setAttribute("data-ge-image-resize", "");
221
+ });
222
+ handle.addEventListener("pointermove", (event) => {
223
+ if (!resizing) return;
224
+ const { figure, x, start, room, page, centered } = resizing;
225
+ const delta = (event.clientX - x) * (side === "right" ? 1 : -1) * (centered ? 2 : 1);
226
+ const width = Math.max(Math.min(room, page * SPAN_SIZE.min), Math.min(room, start + delta));
227
+ figure.style.setProperty(SPAN, room - width <= SNAP ? "1" : String(Math.round((width / page) * 1000) / 1000));
228
+ show(figure);
229
+ });
230
+ const end = (keep) => {
231
+ if (!resizing) return;
232
+ const { figure, before } = resizing;
233
+ resizing = null;
234
+ document.documentElement.removeAttribute("data-ge-image-resize");
235
+ const after = figure.style.getPropertyValue(SPAN);
236
+ if (before) figure.style.setProperty(SPAN, before);
237
+ else figure.style.removeProperty(SPAN);
238
+ if (keep && after !== before && look(figure, { sizes: { [SPAN]: after || null } })) say(t("图片宽度 {0}% · Ctrl+Z 撤销", Math.round(Number(after) * 100)));
239
+ show(figure);
240
+ };
241
+ handle.addEventListener("pointerup", () => end(true));
242
+ handle.addEventListener("pointercancel", () => end(false));
243
+ handle.addEventListener("lostpointercapture", () => end(true));
244
+ }
245
+ document.addEventListener("keydown", (event) => {
246
+ if (event.key !== "Escape" || !resizing) return;
247
+ event.preventDefault();
248
+ event.stopPropagation();
249
+ const { figure, before } = resizing;
250
+ resizing = null;
251
+ document.documentElement.removeAttribute("data-ge-image-resize");
252
+ if (before) figure.style.setProperty(SPAN, before);
253
+ else figure.style.removeProperty(SPAN);
254
+ show(figure);
255
+ }, true);
256
+
257
+ // 对齐: Notion's small popover of the three sides, under its button.
258
+ function alignPopup(figure, button) {
259
+ const el = document.createElement("div");
260
+ el.className = "ge-image-align";
261
+ el.setAttribute("data-doc-dev", "");
262
+ const current = sideOf(figure);
263
+ el.innerHTML = ALIGNS.map(([side, label, name], index) => `${index ? '<div class="ge-image-align-sep"></div>' : ""}<div role="button" class="ge-media-tool"${side === current ? " data-on" : ""} data-side="${side}" aria-label="${label}">${TOOL_ICONS[name]}</div>`).join("");
264
+ el.addEventListener("mousedown", (event) => event.preventDefault());
265
+ el.addEventListener("click", (event) => {
266
+ const side = event.target.closest("[data-side]")?.dataset.side;
267
+ if (!side) return;
268
+ closePopup(popup);
269
+ align(figure, side);
270
+ });
271
+ const rect = button.getBoundingClientRect();
272
+ const popup = openPopup({ origin: { left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom, width: rect.width, height: rect.height }, placement: "bottom", align: "center", gap: 8, content: el });
273
+ }
274
+
275
+ function align(figure, side) {
276
+ if (look(figure, sideLook(side))) say(t("已{0} · Ctrl+Z 撤销", ALIGNS.find(([each]) => each === side)[1]));
277
+ if (hovered === figure) show(figure);
278
+ }
279
+
280
+ // ---------- the viewer ----------
281
+
282
+ // The viewer (viewer.mjs: the wheel zooms, 下载, the page's other pictures), on an image block's picture.
283
+ const view = (figure) => openViewer(imageOf(figure), download);
284
+
285
+ // 下载: the picture saved, by the name it has in the report's folder (`img`: an image block's, or
286
+ // any picture the viewer shows).
287
+ async function download(img) {
288
+ if (!img) return;
289
+ const kept = fileOf(img, "src") ?? img.getAttribute("src") ?? "";
290
+ const type = /^data:image\/([a-z+]+)/.exec(kept)?.[1]?.replace("+xml", "") ?? null;
291
+ const name = type ? `image.${type}` : kept.split(/[?#]/)[0].split("/").filter(Boolean).pop() || "image.png";
292
+ try {
293
+ const response = await fetch(img.src);
294
+ if (!response.ok) throw new Error(String(response.status));
295
+ const url = URL.createObjectURL(await response.blob());
296
+ const link = element("a", { href: url, download: name });
297
+ document.body.append(link);
298
+ link.click();
299
+ link.remove();
300
+ setTimeout(() => URL.revokeObjectURL(url), 2000);
301
+ } catch {
302
+ say(t("没能下载这张图片。"), "error");
303
+ }
304
+ }
305
+
306
+ // 裁剪图片 (crop.mjs, notion-lite's: nothing is lost): the dialog shows the picture it was cropped
307
+ // from, when it was, with the box kept then, so what was cut away can come back. What is kept, a new
308
+ // picture of the report's folder in its place (its caption, side and width kept), that original and
309
+ // the box kept said on it; the whole picture kept, the original back. One undo step.
310
+ function crop(figure) {
311
+ const img = figure && imageOf(figure);
312
+ if (!img) return;
313
+ const original = img.getAttribute("data-original");
314
+ const from = original ?? fileOf(img, "src");
315
+ openCrop(img, async (blob, kept) => {
316
+ if (!figure.isConnected) return;
317
+ try {
318
+ if (!kept) {
319
+ if (!original) return; // nothing cut away, nothing to bring back
320
+ place(figure, original, null, { quiet: true });
321
+ return say(t("已恢复原图 · Ctrl+Z 撤销"));
322
+ }
323
+ place(figure, (await media.uploadFile(blob, "crop.png")).path, null, { cropped: from ? { original: from, crop: kept } : null, quiet: true });
324
+ say(t("已裁剪图片 · Ctrl+Z 撤销"));
325
+ } catch (error) {
326
+ say(t("无法保存裁剪的图片:{0}", error.message), "error");
327
+ }
328
+ }, { src: original ? assetUrl(original) : img.src, crop: original ? cropOf(img.getAttribute("data-crop")) : null });
329
+ }
330
+ // A double-click on a picture that opens large (src/shared/zoom.mjs: an image block's, or one in a
331
+ // table, a card, a column) views it, notion-lite's rule while editing (726447: a double-click on a
332
+ // page that can be edited, a click on one that cannot: the kit's viewer, runtime/zoom.js, leaves a
333
+ // click on the page edited to the editor, which selects the block).
334
+ document.addEventListener("dblclick", (event) => {
335
+ const img = event.target;
336
+ if (img?.localName !== "img" || !active() || !zoomable(img)) return;
337
+ event.preventDefault();
338
+ openViewer(img, download);
339
+ }, true);
340
+ // ---------- the block menu, pasting ----------
341
+
342
+ /** An image's rows in its block menu. */
343
+ function menuItems(target) {
344
+ if (!target?.matches?.("figure.doc-image") || !imageOf(target)) return [];
345
+ const rows = [
346
+ { label: t("替换图片"), icon: ICONS.reset, run: () => setTimeout(() => pick(target)) },
347
+ { label: t("标题@caption"), icon: TOOL_ICONS.caption, run: () => setTimeout(() => media.caption(target)) },
348
+ { label: t("对齐"), icon: TOOL_ICONS[{ left: "alignLeft", center: "alignCenter", right: "alignRight" }[sideOf(target)]], width: 180,
349
+ submenu: () => ALIGNS.map(([side, label, name]) => ({ label, icon: TOOL_ICONS[name], current: side === sideOf(target), run: () => align(target, side) })) },
350
+ ];
351
+ if (target.style.getPropertyValue(SPAN)) rows.push({ label: t("恢复原始大小"), icon: ICONS.reset, run: () => { if (look(target, { sizes: { [SPAN]: null } })) say(t("已恢复原始大小 · Ctrl+Z 撤销")); } });
352
+ rows.push({ label: t("裁剪图片"), icon: CROP_ICON, run: () => setTimeout(() => crop(target)) });
353
+ rows.push({ label: t("全屏查看"), icon: TOOL_ICONS.expand, run: () => view(target) });
354
+ rows.push({ label: t("下载"), icon: TOOL_ICONS.download, run: () => download(imageOf(target)) });
355
+ return rows;
356
+ }
357
+
358
+ /**
359
+ * An image pasted with its picture's address (clipboard/): the picture downloaded into the
360
+ * report's folder (a data: address uploaded), one undo step with the paste (`options`).
361
+ */
362
+ async function fromLink(figure, src, options) {
363
+ if (!/^data:/i.test(src)) return fetchInto(figure, src, options);
364
+ try {
365
+ const blob = await (await fetch(src)).blob();
366
+ return uploadInto(figure, new File([blob], `image.${(blob.type.split("/")[1] ?? "png").replace("svg+xml", "svg").replace("jpeg", "jpg")}`, { type: blob.type }), options);
367
+ } catch {
368
+ return undefined;
369
+ }
370
+ }
371
+
372
+ return {
373
+ pick, menuItems, fromLink,
374
+ /** Whether a file makes an image. */
375
+ acceptsFile: (file) => /^image\//.test(file.type),
376
+ /** An image made of `file`, put where the paste puts it (`put`), its picture uploaded. Returns whether it took it. */
377
+ fromFiles: (put, [file]) => media.paste(put, file, newImage, uploadInto),
378
+ /** A new one: its picture chosen next. */
379
+ onCreated(figure) {
380
+ pick(figure);
381
+ return true;
382
+ },
383
+ get nodes() { return [bar, handles.left, handles.right].filter((node) => node.isConnected); },
384
+ };
385
+ }
@@ -0,0 +1,213 @@
1
+ import { Z } from "../../../shared/layers.mjs";
2
+ import { tooltip } from "../../page/tooltip.mjs";
3
+ import { addStyleTo, element, mountOver, overlayHost } from "../../page/ui.mjs";
4
+ import { t } from "../../../shared/i18n/index.mjs";
5
+ import { zoomable } from "../../../shared/zoom.mjs";
6
+
7
+ // The picture over the page (notion-lite's blocks/image/edit/viewer.js, Notion's 523009 → 749527,
8
+ // with Feishu's wheel): the image's toolbar 展开, its block menu's 全屏查看, and a double-click on a
9
+ // picture of the page that opens large (notion-lite's rule while editing; which pictures is
10
+ // src/shared/zoom.mjs's: an image block's, or one in a table, a card, a column; a reader's single
11
+ // click opens the kit's viewer instead, runtime/zoom.js, which leaves the page edited alone). The picture fits the
12
+ // window (32px around it from 1020px wide), never larger than itself. The wheel zooms around the
13
+ // pointer (25% to 400%), as do −, + and the keys − and +; the percentage puts it back to 100%; a
14
+ // zoomed picture is dragged about. A bar at the bottom: ‹ › (when the page has more pictures, ← →
15
+ // too), −, the percentage, +, 下载, 关闭; it and the pointer hide after two seconds still. Esc, the
16
+ // space bar or a click beside the picture closes it. In a workbench it covers the workbench's window
17
+ // (ui.mjs overlayHost), its keys heard in either document.
18
+
19
+ const STYLE = `
20
+ .ge-image-viewer { position: fixed; inset: 0; z-index: ${Z.viewer}; display: flex; align-items: center; justify-content: center; overflow: hidden;
21
+ background: rgb(15 15 15 / 80%); opacity: 0; transition: opacity 150ms; user-select: none; }
22
+ .ge-image-viewer[data-shown] { opacity: 1; }
23
+ /* The picture's own cursor (grab, grabbing) is set inline while it is moved, which only !important beats. */
24
+ .ge-image-viewer[data-idle], .ge-image-viewer[data-idle] img { cursor: none !important; }
25
+ .ge-image-viewer > img { display: block; max-width: none; object-fit: contain; transform-origin: center; transition: transform 80ms ease-out; }
26
+ .ge-viewer-bar { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; font: 14px/1 ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; transition: opacity 200ms; }
27
+ .ge-image-viewer[data-idle] .ge-viewer-bar { opacity: 0; pointer-events: none; }
28
+ .ge-viewer-group { display: flex; align-items: center; border-radius: 4px; background: rgb(0 0 0 / 62%); }
29
+ .ge-viewer-button { display: flex; align-items: center; justify-content: center; min-width: 28px; height: 28px; padding: 6px; border-radius: 4px; color: #fff; cursor: pointer; transition: background 20ms ease-in; }
30
+ .ge-viewer-button:hover { background: rgb(255 255 255 / 5.5%); }
31
+ .ge-viewer-button[data-off] { opacity: .4; pointer-events: none; }
32
+ .ge-viewer-button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
33
+ .ge-viewer-zoom { width: 50px; color: rgb(255 255 255 / 50%); font-size: 13px; }
34
+ .ge-viewer-sep { width: 1px; height: 16px; background: rgb(255 255 255 / 28%); }
35
+ `;
36
+
37
+ const icon = (path) => `<svg viewBox="0 0 16 16" aria-hidden="true">${path}</svg>`;
38
+ const ICONS = {
39
+ prev: icon('<path d="M13 8H3M7.5 3.5 3 8l4.5 4.5"/>'),
40
+ next: icon('<path d="M3 8h10M8.5 3.5 13 8l-4.5 4.5"/>'),
41
+ out: icon('<path d="M3 8h10"/>'),
42
+ in: icon('<path d="M3 8h10M8 3v10"/>'),
43
+ download: icon('<path d="M8 2.75v7.5M4.75 7.25 8 10.5l3.25-3.25M3 13.25h10"/>'),
44
+ close: icon('<path d="m4 4 8 8M12 4l-8 8"/>'),
45
+ };
46
+ const ZOOM = { min: 0.25, max: 4 };
47
+
48
+ let viewer = null; // { node, img, pictures, index, zoom, x, y, moved, timer, keys, wake, host }
49
+
50
+ /**
51
+ * Open the viewer on `picture` (an <img> of the page); `download(picture)` saves one (page.mjs).
52
+ * The page's pictures that open large are gone through in document order, `picture` among them
53
+ * whatever its size: 展开 and 全屏查看 ask for it by name, so an image block showing its picture under
54
+ * ZOOM_LEAST (a 32px picture at its own size) or one not loaded yet opens too; the double-click goes
55
+ * by the reader's rule (zoomable) before it calls this.
56
+ */
57
+ export function openViewer(picture, download) {
58
+ closeViewer();
59
+ const pictures = [...document.querySelectorAll("main img")].filter((img) => img === picture || zoomable(img));
60
+ if (!pictures.includes(picture)) return;
61
+ const host = overlayHost();
62
+ addStyleTo(host.doc, STYLE);
63
+ const img = element("img", { alt: "", draggable: "false" });
64
+ const button = (name, label, text) => {
65
+ const node = element("div", { class: "ge-viewer-button", role: "button", "aria-label": label, "data-act": name });
66
+ if (text) node.textContent = text;
67
+ else node.innerHTML = ICONS[name];
68
+ if (!text && host.doc === document) tooltip(node, label);
69
+ else if (!text) node.title = label; // the editor's tooltips stand on the page, not over the workbench
70
+ return node;
71
+ };
72
+ const zoomed = button("reset", "100%", "100%");
73
+ zoomed.classList.add("ge-viewer-zoom");
74
+ const groups = [];
75
+ if (pictures.length > 1) groups.push(element("div", { class: "ge-viewer-group" }, button("prev", t("上一张")), button("next", t("下一张"))));
76
+ groups.push(element("div", { class: "ge-viewer-group" }, button("out", t("缩小")), zoomed, button("in", t("放大")), element("div", { class: "ge-viewer-sep" }), button("download", t("下载")), element("div", { class: "ge-viewer-sep" }), button("close", t("关闭"))));
77
+ const node = mountOver(host, element("div", { class: "ge-image-viewer", role: "dialog", "aria-label": t("查看图片") }, img, element("div", { class: "ge-viewer-bar" }, ...groups)));
78
+ const v = { node, img, pictures, index: pictures.indexOf(picture), zoom: 1, x: 0, y: 0, moved: false, timer: 0, download, host };
79
+ viewer = v;
80
+
81
+ node.addEventListener("click", (event) => {
82
+ const act = event.target.closest?.("[data-act]")?.getAttribute("data-act");
83
+ if (act) return run(act);
84
+ if (event.target === img) return;
85
+ if (!event.target.closest(".ge-viewer-bar") && !v.moved) closeViewer(); // a click beside the picture
86
+ });
87
+ node.addEventListener("wheel", (event) => {
88
+ event.preventDefault();
89
+ zoomTo(v.zoom * Math.exp(-event.deltaY * 0.0015), around(event));
90
+ }, { passive: false });
91
+ node.addEventListener("pointerdown", (event) => {
92
+ v.moved = false;
93
+ if (event.button !== 0 || event.target !== img || v.zoom <= 1) return;
94
+ event.preventDefault();
95
+ const start = { x: event.clientX, y: event.clientY, panX: v.x, panY: v.y };
96
+ img.style.cursor = "grabbing";
97
+ const move = (moving) => {
98
+ if (Math.abs(moving.clientX - start.x) + Math.abs(moving.clientY - start.y) > 3) v.moved = true;
99
+ v.x = start.panX + moving.clientX - start.x;
100
+ v.y = start.panY + moving.clientY - start.y;
101
+ paint();
102
+ };
103
+ const up = () => {
104
+ host.win.removeEventListener("pointermove", move, true);
105
+ host.win.removeEventListener("pointerup", up, true);
106
+ paint();
107
+ };
108
+ host.win.addEventListener("pointermove", move, true);
109
+ host.win.addEventListener("pointerup", up, true);
110
+ });
111
+ v.keys = (event) => {
112
+ const done = () => { event.preventDefault(); event.stopPropagation(); };
113
+ if (event.key === "Escape" || event.key === " ") { done(); closeViewer(); }
114
+ else if (event.key === "ArrowLeft") { done(); show(v.index - 1); }
115
+ else if (event.key === "ArrowRight") { done(); show(v.index + 1); }
116
+ else if (event.key === "+" || event.key === "=") { done(); zoomTo(v.zoom * 1.25); }
117
+ else if (event.key === "-" || event.key === "_") { done(); zoomTo(v.zoom / 1.25); }
118
+ else if (!(event.ctrlKey || event.metaKey)) done(); // the page takes no keys meanwhile
119
+ };
120
+ v.wake = () => {
121
+ node.removeAttribute("data-idle");
122
+ clearTimeout(v.timer);
123
+ v.timer = setTimeout(() => viewer === v && node.setAttribute("data-idle", ""), 2000);
124
+ };
125
+ for (const doc of new Set([document, host.doc])) doc.addEventListener("keydown", v.keys, true);
126
+ host.win.addEventListener("pointermove", v.wake, true);
127
+ host.win.addEventListener("resize", fit);
128
+ img.addEventListener("load", fit);
129
+ document.activeElement?.blur?.();
130
+ show(v.index);
131
+ v.wake();
132
+ node.getBoundingClientRect(); // its first style taken, so that showing it fades in
133
+ node.setAttribute("data-shown", "");
134
+ }
135
+
136
+ /** The viewer gone, if it is open. */
137
+ export function closeViewer() {
138
+ const v = viewer;
139
+ if (!v) return;
140
+ viewer = null;
141
+ for (const doc of new Set([document, v.host.doc])) doc.removeEventListener("keydown", v.keys, true);
142
+ v.host.win.removeEventListener("pointermove", v.wake, true);
143
+ v.host.win.removeEventListener("resize", fit);
144
+ clearTimeout(v.timer);
145
+ v.node.remove();
146
+ }
147
+
148
+ function run(act) {
149
+ const v = viewer;
150
+ if (act === "close") closeViewer();
151
+ else if (act === "prev") show(v.index - 1);
152
+ else if (act === "next") show(v.index + 1);
153
+ else if (act === "in") zoomTo(v.zoom * 1.25);
154
+ else if (act === "out") zoomTo(v.zoom / 1.25);
155
+ else if (act === "reset") zoomTo(1);
156
+ else if (act === "download") v.download(v.pictures[v.index]);
157
+ }
158
+
159
+ function show(index) {
160
+ const v = viewer;
161
+ v.index = Math.max(0, Math.min(v.pictures.length - 1, index));
162
+ v.zoom = 1;
163
+ v.x = 0;
164
+ v.y = 0;
165
+ v.img.src = v.pictures[v.index].currentSrc || v.pictures[v.index].src;
166
+ v.node.querySelector('[data-act="prev"]')?.toggleAttribute("data-off", v.index === 0);
167
+ v.node.querySelector('[data-act="next"]')?.toggleAttribute("data-off", v.index === v.pictures.length - 1);
168
+ fit();
169
+ }
170
+
171
+ // The picture fitted into the window it covers (32px around it from 1020px wide), never past its own size.
172
+ function fit() {
173
+ const v = viewer;
174
+ if (!v?.img.naturalWidth) return;
175
+ const { naturalWidth: width, naturalHeight: height } = v.img;
176
+ const { innerWidth: across, innerHeight: down } = v.host.win;
177
+ const gap = across >= 1020 ? 32 : 0;
178
+ const scale = Math.min(1, (across - 2 * gap) / width, (down - 2 * gap) / height);
179
+ v.img.style.width = `${width * scale}px`;
180
+ v.img.style.height = `${height * scale}px`;
181
+ paint();
182
+ }
183
+
184
+ // Where the pointer is, from the window's middle (the zoom's center).
185
+ function around(event) {
186
+ const rect = viewer.node.getBoundingClientRect();
187
+ return { x: event.clientX - (rect.left + rect.width / 2), y: event.clientY - (rect.top + rect.height / 2) };
188
+ }
189
+
190
+ function zoomTo(value, at = null) {
191
+ const v = viewer;
192
+ const zoom = Math.max(ZOOM.min, Math.min(ZOOM.max, Math.round(value * 1000) / 1000));
193
+ if (at) {
194
+ const k = zoom / v.zoom;
195
+ v.x = at.x - (at.x - v.x) * k;
196
+ v.y = at.y - (at.y - v.y) * k;
197
+ }
198
+ v.zoom = zoom;
199
+ if (zoom <= 1) {
200
+ v.x = 0;
201
+ v.y = 0;
202
+ }
203
+ paint();
204
+ }
205
+
206
+ function paint() {
207
+ const v = viewer;
208
+ v.img.style.transform = `translate(${v.x}px, ${v.y}px) scale(${v.zoom})`;
209
+ v.img.style.cursor = v.zoom > 1 ? "grab" : "default";
210
+ v.node.querySelector(".ge-viewer-zoom").textContent = `${Math.round(v.zoom * 100)}%`;
211
+ v.node.querySelector('[data-act="out"]').toggleAttribute("data-off", v.zoom <= ZOOM.min);
212
+ v.node.querySelector('[data-act="in"]').toggleAttribute("data-off", v.zoom >= ZOOM.max);
213
+ }