@heycys/gallery 0.1.0 → 0.1.2

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 (465) hide show
  1. package/THIRD-PARTY-NOTICES.md +51 -1
  2. package/browser/editor/components/callout/index.mjs +40 -15
  3. package/browser/editor/components/columns/page.mjs +45 -32
  4. package/browser/editor/components/details/index.mjs +2 -1
  5. package/browser/editor/components/dialog/index.mjs +2 -1
  6. package/browser/editor/components/dialog/page.mjs +0 -18
  7. package/browser/editor/components/divider/index.mjs +1 -1
  8. package/browser/editor/components/embed/index.mjs +2 -2
  9. package/browser/editor/components/figure/page.mjs +10 -1
  10. package/browser/editor/components/file/page.mjs +2 -2
  11. package/browser/editor/components/flowchart/add.mjs +7 -6
  12. package/browser/editor/components/flowchart/page.mjs +1 -1
  13. package/browser/editor/components/heading/index.mjs +2 -0
  14. package/browser/editor/components/heading/page.mjs +6 -0
  15. package/browser/editor/components/highlight/index.mjs +4 -20
  16. package/browser/editor/components/icons.mjs +13 -2
  17. package/browser/editor/components/image/crop.mjs +6 -9
  18. package/browser/editor/components/image/page.mjs +2 -2
  19. package/browser/editor/components/installed/index.mjs +82 -29
  20. package/browser/editor/components/installed/page.mjs +146 -34
  21. package/browser/editor/components/installed/served.mjs +6 -5
  22. package/browser/editor/components/instances.mjs +18 -0
  23. package/browser/editor/components/kit.mjs +3 -0
  24. package/browser/editor/components/list/page.mjs +3 -6
  25. package/browser/editor/components/media/page.mjs +44 -14
  26. package/browser/editor/components/pages.mjs +2 -2
  27. package/browser/editor/components/registry.mjs +68 -33
  28. package/browser/editor/components/section/index.mjs +2 -1
  29. package/browser/editor/components/set-apart.mjs +24 -0
  30. package/browser/editor/components/table/index.mjs +64 -5
  31. package/browser/editor/components/table/page.mjs +30 -19
  32. package/browser/editor/page/annotate/anchors.mjs +4 -3
  33. package/browser/editor/page/annotate/card.mjs +3 -6
  34. package/browser/editor/page/annotate/index.mjs +61 -34
  35. package/browser/editor/page/autosave.mjs +357 -38
  36. package/browser/editor/page/beside.mjs +5 -5
  37. package/browser/editor/page/block-menu/colors.mjs +3 -1
  38. package/browser/editor/page/block-menu/index.mjs +8 -6
  39. package/browser/editor/page/blocks.mjs +16 -7
  40. package/browser/editor/page/board/client.mjs +57 -0
  41. package/browser/editor/page/board/hint.mjs +145 -0
  42. package/browser/editor/page/board/history.mjs +119 -0
  43. package/browser/editor/page/board/index.mjs +970 -0
  44. package/browser/editor/page/board/settings.mjs +209 -0
  45. package/browser/editor/page/caret.mjs +5 -2
  46. package/browser/editor/page/changes/bar.mjs +94 -0
  47. package/browser/editor/page/changes/ghost.mjs +206 -0
  48. package/browser/editor/page/changes/gone-words.mjs +94 -0
  49. package/browser/editor/page/changes/index.mjs +447 -0
  50. package/browser/editor/page/changes/words.mjs +27 -0
  51. package/browser/editor/page/clipboard/import/colors.mjs +3 -3
  52. package/browser/editor/page/clipboard/import/html.mjs +29 -6
  53. package/browser/editor/page/clipboard/import/inline.mjs +32 -0
  54. package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
  55. package/browser/editor/page/clipboard/import/read.mjs +6 -1
  56. package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
  57. package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
  58. package/browser/editor/page/clipboard/index.mjs +156 -26
  59. package/browser/editor/page/clipboard/own/blocks.mjs +25 -16
  60. package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
  61. package/browser/editor/page/clipboard/own/describe.mjs +16 -7
  62. package/browser/editor/page/clipboard/own/export.mjs +6 -6
  63. package/browser/editor/page/clipboard/own/selection.mjs +3 -3
  64. package/browser/editor/page/clipboard/own/writers.mjs +0 -11
  65. package/browser/editor/page/columns/index.mjs +48 -46
  66. package/browser/editor/page/commit.mjs +98 -25
  67. package/browser/editor/page/conflicts.mjs +13 -33
  68. package/browser/editor/page/convert.mjs +8 -7
  69. package/browser/editor/page/core.mjs +81 -27
  70. package/browser/editor/page/custom-page.mjs +106 -0
  71. package/browser/editor/page/drag/index.mjs +40 -24
  72. package/browser/editor/page/drag/preview.mjs +9 -4
  73. package/browser/editor/page/editor.mjs +120 -28
  74. package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
  75. package/browser/editor/page/emoji-picker/grid.mjs +7 -5
  76. package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
  77. package/browser/editor/page/emoji-picker/icons.mjs +0 -1
  78. package/browser/editor/page/emoji-picker/index.mjs +11 -9
  79. package/browser/editor/page/emoji-picker/styles.mjs +156 -2
  80. package/browser/editor/page/emoji-picker/support.mjs +6 -4
  81. package/browser/editor/page/emoji-picker/upload.mjs +14 -13
  82. package/browser/editor/page/fills.mjs +5 -3
  83. package/browser/editor/page/fold/index.mjs +348 -0
  84. package/browser/editor/page/fold/rule.mjs +125 -0
  85. package/browser/editor/page/folded.mjs +23 -0
  86. package/browser/editor/page/format-bar/bar.mjs +2 -1
  87. package/browser/editor/page/format-bar/index.mjs +1 -1
  88. package/browser/editor/page/geometry.mjs +8 -6
  89. package/browser/editor/page/handle/index.mjs +22 -14
  90. package/browser/editor/page/hints/index.mjs +1 -1
  91. package/browser/editor/page/history.mjs +24 -4
  92. package/browser/editor/page/insert/index.mjs +30 -17
  93. package/browser/editor/page/links/index.mjs +5 -3
  94. package/browser/editor/page/links/pages.mjs +27 -9
  95. package/browser/editor/page/long-runs.mjs +75 -0
  96. package/browser/editor/page/look.mjs +69 -6
  97. package/browser/editor/page/margin.mjs +63 -27
  98. package/browser/editor/page/media-menu/index.mjs +6 -7
  99. package/browser/editor/page/menu.mjs +86 -31
  100. package/browser/editor/page/merge.mjs +24 -0
  101. package/browser/editor/page/notices.mjs +3 -3
  102. package/browser/editor/page/offered.mjs +1 -1
  103. package/browser/editor/page/outline/folds.mjs +11 -10
  104. package/browser/editor/page/outline/index.mjs +131 -45
  105. package/browser/editor/page/outline/list.mjs +23 -11
  106. package/browser/editor/page/outline/read.mjs +1 -1
  107. package/browser/editor/page/outline/strip.mjs +7 -1
  108. package/browser/editor/page/page-objects.mjs +13 -2
  109. package/browser/editor/page/panel.mjs +9 -13
  110. package/browser/editor/page/present-links.mjs +11 -2
  111. package/browser/editor/page/resize/index.mjs +42 -29
  112. package/browser/editor/page/selection/delete.mjs +8 -6
  113. package/browser/editor/page/selection/index.mjs +10 -3
  114. package/browser/editor/page/served.mjs +14 -0
  115. package/browser/editor/page/session.mjs +101 -6
  116. package/browser/editor/page/slash-menu/index.mjs +3 -3
  117. package/browser/editor/page/table/cell-bar.mjs +4 -1
  118. package/browser/editor/page/table/cells.mjs +103 -47
  119. package/browser/editor/page/table/icons.mjs +3 -1
  120. package/browser/editor/page/table/index.mjs +40 -16
  121. package/browser/editor/page/table/pictures.mjs +299 -0
  122. package/browser/editor/page/table/views.mjs +150 -0
  123. package/browser/editor/page/table/widths.mjs +9 -4
  124. package/browser/editor/page/text-select/index.mjs +43 -14
  125. package/browser/editor/page/todo-writes.mjs +75 -0
  126. package/browser/editor/page/tooltip.mjs +1 -1
  127. package/browser/editor/page/type-grid.mjs +4 -3
  128. package/browser/editor/page/typing/code-edges.mjs +63 -17
  129. package/browser/editor/page/typing/index.mjs +65 -9
  130. package/browser/editor/page/typing/leave.mjs +1 -1
  131. package/browser/editor/page/ui.mjs +13 -0
  132. package/browser/shared/annotations.mjs +8 -10
  133. package/browser/shared/block-packs.mjs +404 -0
  134. package/browser/shared/board-places.mjs +224 -0
  135. package/browser/shared/card-size.mjs +59 -0
  136. package/browser/shared/code-folds.mjs +5 -1
  137. package/browser/shared/colors.mjs +17 -14
  138. package/browser/shared/component-catalog.mjs +345 -54
  139. package/browser/shared/component-source.mjs +37 -0
  140. package/browser/shared/components/callout.mjs +4 -2
  141. package/browser/shared/components/index.mjs +72 -9
  142. package/browser/shared/components/installed.mjs +110 -8
  143. package/browser/shared/components/page.mjs +22 -3
  144. package/browser/shared/components/state.mjs +5 -1
  145. package/browser/shared/components/table.mjs +1 -1
  146. package/browser/shared/components/text.mjs +2 -2
  147. package/browser/shared/document-look.mjs +183 -0
  148. package/browser/shared/drafts.mjs +432 -0
  149. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  150. package/browser/shared/emoji/data/README.md +4 -2
  151. package/browser/shared/emoji/data/categories.json +1 -1
  152. package/browser/shared/emoji/data/keywords-en.json +1 -1
  153. package/browser/shared/emoji/data/keywords-zh.json +1 -1
  154. package/browser/shared/emoji/data/names.json +1 -1
  155. package/browser/shared/emoji/data/positions.json +1 -1
  156. package/browser/shared/emoji/data/twemoji-index.json +1 -1
  157. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  158. package/browser/shared/emoji/data.mjs +10 -12
  159. package/browser/shared/emoji/emoji.mjs +8 -7
  160. package/browser/shared/emoji/icon-value.mjs +4 -3
  161. package/browser/shared/extension-sidebar.mjs +126 -0
  162. package/browser/shared/extensions.mjs +79 -0
  163. package/browser/shared/file-table.mjs +101 -0
  164. package/browser/shared/html-tree.mjs +11 -5
  165. package/browser/shared/i18n/en.mjs +374 -35
  166. package/browser/shared/json-layout.mjs +47 -0
  167. package/browser/shared/long-runs.mjs +39 -0
  168. package/browser/shared/net-cache.mjs +133 -0
  169. package/browser/shared/net-keys.mjs +32 -0
  170. package/browser/shared/net-policy.mjs +177 -0
  171. package/browser/shared/new-names.mjs +5 -2
  172. package/browser/shared/outline-shape.mjs +128 -0
  173. package/browser/shared/outline.mjs +458 -0
  174. package/browser/shared/pack-manifest.mjs +77 -0
  175. package/browser/shared/page-address.mjs +6 -3
  176. package/browser/shared/page-cards.mjs +308 -0
  177. package/browser/shared/page-links.mjs +69 -6
  178. package/browser/shared/pages.mjs +388 -0
  179. package/browser/shared/paths.mjs +6 -0
  180. package/browser/shared/preferences.mjs +10 -4
  181. package/browser/shared/preview-server.mjs +3 -7
  182. package/browser/shared/session.mjs +13 -5
  183. package/browser/shared/shipped-blocks.mjs +299 -0
  184. package/browser/shared/table-chart.mjs +33 -1
  185. package/browser/shared/todos.mjs +83 -0
  186. package/browser/shared/user-directory.mjs +24 -0
  187. package/browser/shared/versions.mjs +14 -0
  188. package/browser/shared/web-links.mjs +134 -0
  189. package/browser/shared/workspace-columns.mjs +120 -0
  190. package/browser/shared/workspace-look.mjs +91 -0
  191. package/browser/shared/workspace-name.mjs +154 -0
  192. package/browser/shared/workspace-query.mjs +125 -0
  193. package/browser/shared/workspace-registry.mjs +272 -0
  194. package/browser/shared/workspace.mjs +171 -20
  195. package/browser/shared/zoom.mjs +5 -5
  196. package/dist/chunk-2NRBY6AJ.mjs +2 -0
  197. package/dist/chunk-32ZUEFZ7.mjs +2 -0
  198. package/dist/chunk-35NQ4PLQ.mjs +2 -0
  199. package/dist/chunk-3KJHLHUO.mjs +2 -0
  200. package/dist/chunk-3NJACR4W.mjs +2 -0
  201. package/dist/chunk-4AV456RQ.mjs +2 -0
  202. package/dist/chunk-4OZWXZE5.mjs +5 -0
  203. package/dist/chunk-5XYHDBJ5.mjs +2 -0
  204. package/dist/chunk-5ZJA7CXT.mjs +2 -0
  205. package/dist/chunk-6A53MZYZ.mjs +2 -0
  206. package/dist/chunk-6EXH3ORZ.mjs +166 -0
  207. package/dist/chunk-6EZ7FNIK.mjs +3 -0
  208. package/dist/{chunk-UXUK4PMC.mjs → chunk-6QBHU4DF.mjs} +1 -1
  209. package/dist/{chunk-6U2SLSDN.mjs → chunk-6VTU6KEO.mjs} +1 -1
  210. package/dist/chunk-B4P2CM2J.mjs +3 -0
  211. package/dist/chunk-BPL64HGA.mjs +4 -0
  212. package/dist/chunk-BVEFGE4B.mjs +2 -0
  213. package/dist/chunk-BZ5RAF7L.mjs +2 -0
  214. package/dist/chunk-CRJEG7MT.mjs +2 -0
  215. package/dist/{chunk-B3VTYBYR.mjs → chunk-D4CKRD3V.mjs} +91 -91
  216. package/dist/chunk-D4EURAX4.mjs +4 -0
  217. package/dist/chunk-DQCE7TJY.mjs +5 -0
  218. package/dist/chunk-DR73Y2UJ.mjs +3 -0
  219. package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
  220. package/dist/{chunk-DB4WKGYF.mjs → chunk-ERLAIBOA.mjs} +2 -2
  221. package/dist/chunk-EURLTOTZ.mjs +4 -0
  222. package/dist/chunk-FJYN7RTH.mjs +4 -0
  223. package/dist/chunk-FWNRPMCJ.mjs +12 -0
  224. package/dist/chunk-FWW4CSAZ.mjs +2 -0
  225. package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
  226. package/dist/chunk-GY3FAUVM.mjs +2 -0
  227. package/dist/chunk-HLYV7RIH.mjs +2 -0
  228. package/dist/chunk-HMYTM3GT.mjs +15 -0
  229. package/dist/chunk-IA4PSIMD.mjs +2 -0
  230. package/dist/chunk-JEUK3ZO7.mjs +2 -0
  231. package/dist/chunk-JVHHHGEA.mjs +3 -0
  232. package/dist/chunk-KTKHRC6H.mjs +2 -0
  233. package/dist/chunk-L7UP52JO.mjs +2 -0
  234. package/dist/chunk-MHW7ZKOU.mjs +2 -0
  235. package/dist/chunk-N76HWBA3.mjs +10 -0
  236. package/dist/chunk-N7AZZLGT.mjs +548 -0
  237. package/dist/chunk-NAMN3RAF.mjs +2 -0
  238. package/dist/{chunk-YXAUQPVK.mjs → chunk-NFMCP2HI.mjs} +3 -3
  239. package/dist/chunk-NG375ILQ.mjs +2 -0
  240. package/dist/chunk-NVRNLK25.mjs +6 -0
  241. package/dist/chunk-NWFBE2YA.mjs +2 -0
  242. package/dist/chunk-NWR2LT5B.mjs +2 -0
  243. package/dist/chunk-OJKMINIU.mjs +20 -0
  244. package/dist/chunk-OUUP3WKT.mjs +2 -0
  245. package/dist/chunk-OW5NWPOJ.mjs +10 -0
  246. package/dist/chunk-PAREWQGB.mjs +4 -0
  247. package/dist/chunk-POQSE4C2.mjs +2 -0
  248. package/dist/chunk-PUOQ65NC.mjs +2 -0
  249. package/dist/{chunk-Z52HTUW7.mjs → chunk-PVER7LSC.mjs} +2 -2
  250. package/dist/chunk-PZDLJJTJ.mjs +3 -0
  251. package/dist/chunk-Q47PLKIJ.mjs +15 -0
  252. package/dist/chunk-Q4UEPUWF.mjs +2 -0
  253. package/dist/chunk-QKXMPUXC.mjs +2 -0
  254. package/dist/chunk-QOUEFUCH.mjs +16 -0
  255. package/dist/chunk-RFDZXFJF.mjs +13 -0
  256. package/dist/chunk-RKPWLGZ3.mjs +4 -0
  257. package/dist/chunk-RMECZA2K.mjs +2 -0
  258. package/dist/{chunk-EUX7IC5J.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
  259. package/dist/chunk-SX4LJYT6.mjs +8 -0
  260. package/dist/chunk-SXHBYZST.mjs +16 -0
  261. package/dist/chunk-TANZRINB.mjs +2 -0
  262. package/dist/chunk-TEZAWDSQ.mjs +2 -0
  263. package/dist/chunk-UBBRTJ2R.mjs +24 -0
  264. package/dist/chunk-UFNYFFKO.mjs +20 -0
  265. package/dist/chunk-UGWYKHBL.mjs +170 -0
  266. package/dist/chunk-UKSHDZZ6.mjs +2 -0
  267. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  268. package/dist/chunk-UNOYVIYR.mjs +2 -0
  269. package/dist/chunk-V6RIYQZZ.mjs +4 -0
  270. package/dist/chunk-VJPFVNNW.mjs +15 -0
  271. package/dist/chunk-VS3ZMVGX.mjs +5 -0
  272. package/dist/chunk-VTKNEYT3.mjs +6 -0
  273. package/dist/chunk-VXACTLO3.mjs +3 -0
  274. package/dist/chunk-W3BGBJQW.mjs +2 -0
  275. package/dist/chunk-YI43RG4P.mjs +2 -0
  276. package/dist/chunk-YQGT4AB2.mjs +6 -0
  277. package/dist/chunk-ZB4H7ZN4.mjs +2 -0
  278. package/dist/{chunk-ACOPDCNB.mjs → chunk-ZHEHPMBK.mjs} +1 -1
  279. package/dist/chunk-ZTHICSSF.mjs +2 -0
  280. package/dist/chunk-ZUNVAXLH.mjs +2 -0
  281. package/dist/chunk-ZWPMCK7P.mjs +2 -0
  282. package/dist/cli.mjs +1 -1
  283. package/dist/server.mjs +1 -1
  284. package/dist/{chunk-EVJ3BX3M.mjs → update-fetch.mjs} +1 -1
  285. package/dist/worker.mjs +1 -1
  286. package/kit/board.css +95 -0
  287. package/kit/board.js +250 -0
  288. package/kit/charts.js +5 -71
  289. package/kit/code.js +14 -14
  290. package/kit/math.js +18 -2
  291. package/kit/report.css +500 -151
  292. package/kit/runtime.js +1720 -170
  293. package/kit/state.js +10 -1
  294. package/kit/tables.js +172 -37
  295. package/kit/ui.js +166 -27
  296. package/package.json +2 -1
  297. package/packs/gallery/card/component.json +14 -0
  298. package/packs/gallery/card/example.html +10 -0
  299. package/packs/gallery/card/preview.svg +1 -0
  300. package/packs/gallery/card/style.css +6 -0
  301. package/packs/gallery/card/template.html +6 -0
  302. package/packs/gallery/card/writing.md +14 -0
  303. package/packs/gallery/chart-card/component.json +15 -0
  304. package/packs/gallery/chart-card/example.html +14 -0
  305. package/packs/gallery/chart-card/kit.js +130 -0
  306. package/packs/gallery/chart-card/preview.svg +1 -0
  307. package/packs/gallery/chart-card/style.css +42 -0
  308. package/packs/gallery/chart-card/template.html +13 -0
  309. package/packs/gallery/chart-card/writing.md +20 -0
  310. package/packs/gallery/chart-view/component.json +20 -0
  311. package/packs/gallery/chart-view/example.html +13 -0
  312. package/packs/gallery/chart-view/kit.js +355 -0
  313. package/packs/gallery/chart-view/preview.svg +1 -0
  314. package/packs/gallery/chart-view/style.css +94 -0
  315. package/packs/gallery/chart-view/template.html +3 -0
  316. package/packs/gallery/chart-view/writing.md +22 -0
  317. package/packs/gallery/countdown/component.json +18 -0
  318. package/packs/gallery/countdown/example.html +3 -0
  319. package/packs/gallery/countdown/kit.js +156 -0
  320. package/packs/gallery/countdown/preview.svg +1 -0
  321. package/packs/gallery/countdown/style.css +130 -0
  322. package/packs/gallery/countdown/template.html +3 -0
  323. package/packs/gallery/countdown/writing.md +22 -0
  324. package/packs/gallery/habit/component.json +14 -0
  325. package/packs/gallery/habit/example.html +3 -0
  326. package/packs/gallery/habit/kit.js +295 -0
  327. package/packs/gallery/habit/preview.svg +1 -0
  328. package/packs/gallery/habit/style.css +246 -0
  329. package/packs/gallery/habit/template.html +3 -0
  330. package/packs/gallery/habit/writing.md +21 -0
  331. package/packs/gallery/heatmap/component.json +18 -0
  332. package/packs/gallery/heatmap/example.html +3 -0
  333. package/packs/gallery/heatmap/kit.js +351 -0
  334. package/packs/gallery/heatmap/preview.svg +1 -0
  335. package/packs/gallery/heatmap/style.css +201 -0
  336. package/packs/gallery/heatmap/template.html +3 -0
  337. package/packs/gallery/heatmap/writing.md +21 -0
  338. package/packs/gallery/kanban/component.json +18 -0
  339. package/packs/gallery/kanban/example.html +12 -0
  340. package/packs/gallery/kanban/kit.js +540 -0
  341. package/packs/gallery/kanban/preview.svg +1 -0
  342. package/packs/gallery/kanban/style.css +212 -0
  343. package/packs/gallery/kanban/template.html +3 -0
  344. package/packs/gallery/kanban/writing.md +20 -0
  345. package/packs/gallery/metric/component.json +22 -0
  346. package/packs/gallery/metric/example.html +15 -0
  347. package/packs/gallery/metric/kit.js +248 -0
  348. package/packs/gallery/metric/preview.svg +1 -0
  349. package/packs/gallery/metric/style.css +92 -0
  350. package/packs/gallery/metric/template.html +3 -0
  351. package/packs/gallery/metric/writing.md +23 -0
  352. package/packs/gallery/note/component.json +14 -0
  353. package/packs/gallery/note/example.html +3 -0
  354. package/packs/gallery/note/kit.js +102 -0
  355. package/packs/gallery/note/preview.svg +1 -0
  356. package/packs/gallery/note/style.css +76 -0
  357. package/packs/gallery/note/template.html +3 -0
  358. package/packs/gallery/note/writing.md +18 -0
  359. package/packs/gallery/pack.json +8 -0
  360. package/packs/gallery/recent/component.json +13 -0
  361. package/packs/gallery/recent/example.html +1 -0
  362. package/packs/gallery/recent/kit.js +238 -0
  363. package/packs/gallery/recent/preview.svg +1 -0
  364. package/packs/gallery/recent/style.css +158 -0
  365. package/packs/gallery/recent/template.html +1 -0
  366. package/packs/gallery/recent/writing.md +15 -0
  367. package/packs/gallery/static/component.json +13 -0
  368. package/packs/gallery/static/example.html +11 -0
  369. package/packs/gallery/static/preview.svg +1 -0
  370. package/packs/gallery/static/style.css +138 -0
  371. package/packs/gallery/static/template.html +1 -0
  372. package/packs/gallery/static/writing.md +18 -0
  373. package/packs/gallery/stats/component.json +13 -0
  374. package/packs/gallery/stats/example.html +1 -0
  375. package/packs/gallery/stats/kit.js +166 -0
  376. package/packs/gallery/stats/preview.svg +1 -0
  377. package/packs/gallery/stats/style.css +151 -0
  378. package/packs/gallery/stats/template.html +1 -0
  379. package/packs/gallery/stats/writing.md +11 -0
  380. package/packs/gallery/today/component.json +12 -0
  381. package/packs/gallery/today/example.html +1 -0
  382. package/packs/gallery/today/kit.js +185 -0
  383. package/packs/gallery/today/preview.svg +1 -0
  384. package/packs/gallery/today/style.css +120 -0
  385. package/packs/gallery/today/template.html +1 -0
  386. package/packs/gallery/today/writing.md +14 -0
  387. package/packs/gallery/todos/component.json +19 -0
  388. package/packs/gallery/todos/example.html +3 -0
  389. package/packs/gallery/todos/kit.js +342 -0
  390. package/packs/gallery/todos/preview.svg +1 -0
  391. package/packs/gallery/todos/style.css +267 -0
  392. package/packs/gallery/todos/template.html +3 -0
  393. package/packs/gallery/todos/writing.md +30 -0
  394. package/packs/gallery/weather/component.json +19 -0
  395. package/packs/gallery/weather/example.html +3 -0
  396. package/packs/gallery/weather/kit.js +312 -0
  397. package/packs/gallery/weather/preview.svg +1 -0
  398. package/packs/gallery/weather/style.css +258 -0
  399. package/packs/gallery/weather/template.html +3 -0
  400. package/packs/gallery/weather/writing.md +26 -0
  401. package/packs/gallery-soft/pack.json +8 -0
  402. package/release.json +13 -11
  403. package/sdk/doc-kit.d.ts +404 -7
  404. package/sdk/doc-state.d.ts +2 -0
  405. package/skill/SKILL.md +71 -26
  406. package/skill/references/block-script.md +140 -0
  407. package/skill/references/building-blocks.md +257 -0
  408. package/skill/references/example-report.html +1 -1
  409. package/skill/references/extensions.md +59 -0
  410. package/skill/references/pages-and-data.md +221 -0
  411. package/skill/references/writing-html.md +9 -7
  412. package/skill/sdk/doc-kit.d.ts +404 -7
  413. package/skill/sdk/doc-state.d.ts +2 -0
  414. package/web/assets/index-BK2e_07w.js +13 -0
  415. package/web/assets/index-CWFI83mF.css +1 -0
  416. package/web/index.html +2 -2
  417. package/browser/editor/components/callout/page.mjs +0 -13
  418. package/dist/chunk-2PBALTR3.mjs +0 -57
  419. package/dist/chunk-3LA3EMDE.mjs +0 -15
  420. package/dist/chunk-5FRMCDPY.mjs +0 -16
  421. package/dist/chunk-5LEK2CBS.mjs +0 -2
  422. package/dist/chunk-5OFN5AHC.mjs +0 -2
  423. package/dist/chunk-5SIYS5HN.mjs +0 -2
  424. package/dist/chunk-5TEK3RAD.mjs +0 -2
  425. package/dist/chunk-6CYG3Z4V.mjs +0 -2
  426. package/dist/chunk-7GHT2UCA.mjs +0 -15
  427. package/dist/chunk-7QQBR7PB.mjs +0 -2
  428. package/dist/chunk-ATCJYAR4.mjs +0 -2
  429. package/dist/chunk-C7HWOBIF.mjs +0 -2
  430. package/dist/chunk-E7VYDG2X.mjs +0 -2
  431. package/dist/chunk-EZY3WC6Z.mjs +0 -15
  432. package/dist/chunk-FQGQH4KM.mjs +0 -2
  433. package/dist/chunk-G7TOXONE.mjs +0 -6
  434. package/dist/chunk-GPF4YWWB.mjs +0 -9
  435. package/dist/chunk-GYQV7Y4J.mjs +0 -120
  436. package/dist/chunk-HMHK3EQ6.mjs +0 -2
  437. package/dist/chunk-HQQMJCQJ.mjs +0 -10
  438. package/dist/chunk-IERUOGC3.mjs +0 -6
  439. package/dist/chunk-ITNLYXXV.mjs +0 -3
  440. package/dist/chunk-L4DVONOG.mjs +0 -2
  441. package/dist/chunk-LAE5NQ4B.mjs +0 -2
  442. package/dist/chunk-LC7YNQFG.mjs +0 -2
  443. package/dist/chunk-LHTFLRB6.mjs +0 -4
  444. package/dist/chunk-NFIBI4IP.mjs +0 -26
  445. package/dist/chunk-NSKUTQ5J.mjs +0 -5
  446. package/dist/chunk-O52JMOCZ.mjs +0 -2
  447. package/dist/chunk-P2CAZPDP.mjs +0 -3
  448. package/dist/chunk-QMQUXTU4.mjs +0 -12
  449. package/dist/chunk-QVWVFC5K.mjs +0 -6
  450. package/dist/chunk-QYKCJ7FG.mjs +0 -8
  451. package/dist/chunk-QZY6Q64C.mjs +0 -2
  452. package/dist/chunk-TDQP3DKQ.mjs +0 -10
  453. package/dist/chunk-TX6JH7TR.mjs +0 -2
  454. package/dist/chunk-UNUEWH4S.mjs +0 -2
  455. package/dist/chunk-V4CPWKMZ.mjs +0 -2
  456. package/dist/chunk-VACRB2NE.mjs +0 -3
  457. package/dist/chunk-W63L7367.mjs +0 -7
  458. package/dist/chunk-W7CXPCRV.mjs +0 -6
  459. package/dist/chunk-XINNG4F2.mjs +0 -4
  460. package/dist/chunk-YL2DPWVS.mjs +0 -4
  461. package/dist/chunk-YZ5Z6H4W.mjs +0 -4
  462. package/dist/chunk-ZBIM6ARY.mjs +0 -216
  463. package/skill/references/building-components.md +0 -327
  464. package/web/assets/index-B6Ai3wsa.js +0 -13
  465. package/web/assets/index-SYPC3EZy.css +0 -1
@@ -0,0 +1,299 @@
1
+ import { UPLOAD_LIMITS, mediaUrl, sizeLimit } from "../../../shared/media.mjs";
2
+ import { cellPicture, pictureFile } from "../../components/table/index.mjs";
3
+ import { ownHTML } from "../core.mjs";
4
+ import { gestureLock } from "../gesture.mjs";
5
+ import { drawAt, drawBox, layerOf } from "../overlay-layer.mjs";
6
+ import { onSettle, own } from "../overlays.mjs";
7
+ import { blobBase64 } from "../post.mjs";
8
+ import { addStyle, element } from "../ui.mjs";
9
+ import { t } from "../../../shared/i18n/index.mjs";
10
+
11
+ // 单元格里的图片 (the user's, 2026-11-09: no image block, a light one; Markdown tables hold pictures):
12
+ // an <img> amid a table cell's words, a picture of the document's folder (components/table/ cellPicture; the
13
+ // file takes it as source/blocks.mjs cellPictureProblem says, the kit lays it out: table.css). notion-
14
+ // lite has none; this is the plainest that works, flat:
15
+ // - A press on one selects it (the selection around it, a 2px blue frame over it, no caret): Delete
16
+ // or Backspace then takes it out, a typed character takes its place, Esc puts the caret after it;
17
+ // the arrows go past it as past a character (the browser's: an <img> in an editable text is one).
18
+ // - A gray bar at its right edge (the image block's handle) under the pointer or while it is
19
+ // selected: dragged, the picture's width in pixels (its height by its ratio), at least MIN_WIDTH,
20
+ // at most its table's frame, written as its width attribute; one undo step on letting go, Esc
21
+ // putting it back.
22
+ // - Where pictures come from (clipboard/, table/cells.mjs): a picture file pasted into a cell (a
23
+ // screenshot, a copied picture) sent to the document's folder as an image block's (fromFiles); the
24
+ // pictures of cells pasted (another program's table, a Markdown table, the page's own cells of
25
+ // another document) each made a file of the folder first (resolve: one of the folder as it is,
26
+ // another document's, a data: one and a web one copied in, the server downloading a web one as it
27
+ // does an image block's link), then put in by what pastedLines makes of each (maker): a picture of
28
+ // no file a link to it (a web one) or its alt words.
29
+
30
+ const MIN_WIDTH = 16;
31
+ const MAX_PICTURES = 50; // the pictures a paste copies in at most (each a download)
32
+ const WIDTH = /^[1-9]\d{0,3}$/;
33
+ const WEB = /^https?:\/\/[^\s"<>]+$/i;
34
+ const DATA = /^data:image\/[a-z0-9.+-]+;base64,/i;
35
+ // A file of a document's folder as the preview serves it (a copy of the page's HTML), or as a cell's text writes it.
36
+ const SERVED = /^(?:https?:\/\/[^/]+)?\/__gallery\/edit\/asset\/([^/?#]+)\/(assets\/[^/?#]+)$/;
37
+ const FOLDER_FILE = /^assets\/[A-Za-z0-9][A-Za-z0-9._-]{0,80}$/;
38
+ const CELL = '[data-ge-kind="cell"]';
39
+ // The name of a picture's file in its address (its last part, its escapes read).
40
+ const nameOf = (src) => {
41
+ const name = src.split(/[?#]/)[0].split("/").pop() || src;
42
+ try {
43
+ return decodeURIComponent(name);
44
+ } catch {
45
+ return name;
46
+ }
47
+ };
48
+
49
+ const STYLE = `
50
+ [data-ge-editing] ${CELL}[contenteditable="true"] img { cursor: default; }
51
+ .ge-layer > .ge-cellpic-handle { pointer-events: auto; }
52
+ .ge-cellpic-frame { box-sizing: border-box; border: 2px solid var(--ge-accent); border-radius: 2px; pointer-events: none; }
53
+ /* The image block's handle (image/page.mjs): a plain gray bar, no border. */
54
+ .ge-cellpic-handle { display: flex; align-items: center; justify-content: center; width: 12px; cursor: col-resize; }
55
+ .ge-cellpic-handle::after { content: ""; width: 4px; height: 32px; max-height: 70%; border-radius: 4px; background: light-dark(rgb(55 53 47 / 35%), rgb(255 255 255 / 38%)); transition: background 120ms ease; }
56
+ .ge-cellpic-handle:hover::after, html[data-ge-cellpic-resize] .ge-cellpic-handle::after { background: light-dark(rgb(55 53 47 / 60%), rgb(255 255 255 / 62%)); }
57
+ ${gestureLock("data-ge-cellpic-resize", { cursor: "col-resize" })}
58
+ `;
59
+
60
+ // The report this page shows (its main's data-doc-id: its folder's name).
61
+ const thisReport = () => document.querySelector(".doc-page")?.dataset.docId ?? null;
62
+
63
+ /**
64
+ * active(): whether the tools may act. recordStep(host, before): a text step of a text block
65
+ * (history.mjs). say: the status line. upload(kind, body): POST /__gallery/edit/upload, the server's
66
+ * answer (an Error when it fails).
67
+ */
68
+ export function createCellPictures({ active, recordStep, say, upload }) {
69
+ addStyle(STYLE);
70
+ let hovered = null; // the picture under the pointer
71
+ let picked = null; // the picture selected
72
+ let drag = null; // its edge dragged: { img, host, x, start, before, had }
73
+ const frame = element("div", { class: "ge-cellpic-frame", "data-doc-dev": "" });
74
+ const handle = element("div", { class: "ge-cellpic-handle", "data-doc-dev": "" });
75
+ // The picture they are drawn for: the frame the selected one's (or the dragged one's), the bar any of them.
76
+ const framed = () => drag?.img ?? picked;
77
+ const barred = () => drag?.img ?? picked ?? hovered;
78
+ own(frame, "cell picture", { alive: () => Boolean(framed()?.isConnected) });
79
+ own(handle, "cell picture", { alive: () => Boolean(barred()?.isConnected) });
80
+ // The cell of the picture drawn for, watched: a picture taken out (Delete, undo, someone else's
81
+ // words merged) takes them away at once, before the page draws again.
82
+ const watch = new MutationObserver(() => {
83
+ if (!barred()?.isConnected) draw();
84
+ });
85
+
86
+ // A picture of a cell the reader writes in, and that cell; or null.
87
+ const pictureAt = (node) => {
88
+ const img = node?.closest?.("img");
89
+ const host = img?.closest(CELL);
90
+ return img && host?.getAttribute("contenteditable") === "true" && host.closest("main") && !host.closest("[data-ge-lock], [inert]") && pictureFile(img) ? { img, host } : null;
91
+ };
92
+
93
+ function draw() {
94
+ if (picked && !picked.isConnected) picked = null;
95
+ if (hovered && !hovered.isConnected) hovered = null;
96
+ const img = barred();
97
+ watch.disconnect();
98
+ if (!img?.isConnected || !active()) {
99
+ frame.remove();
100
+ handle.remove();
101
+ return;
102
+ }
103
+ watch.observe(img.closest(CELL) ?? img.parentNode, { childList: true, subtree: true });
104
+ const layer = layerOf(img);
105
+ const rect = img.getBoundingClientRect();
106
+ if (img === framed()) drawBox(frame, layer, rect);
107
+ else frame.remove();
108
+ const origin = layer.getBoundingClientRect();
109
+ handle.style.height = `${Math.max(20, Math.round(rect.height))}px`;
110
+ drawAt(handle, layer, rect.right - origin.left - 2, rect.top - origin.top + Math.min(0, (rect.height - 20) / 2));
111
+ }
112
+
113
+ // Whether the selection is the picture alone (a press on it, or the browser's own).
114
+ const around = (img) => {
115
+ const selection = getSelection();
116
+ if (!selection.rangeCount || !img.parentNode) return false;
117
+ const range = selection.getRangeAt(0);
118
+ const at = [...img.parentNode.childNodes].indexOf(img);
119
+ return range.startContainer === img.parentNode && range.endContainer === img.parentNode && range.startOffset === at && range.endOffset === at + 1;
120
+ };
121
+ function pick({ img, host }) {
122
+ if (document.activeElement !== host) host.focus({ preventScroll: true });
123
+ const range = document.createRange();
124
+ range.selectNode(img);
125
+ getSelection().removeAllRanges();
126
+ getSelection().addRange(range);
127
+ picked = img;
128
+ draw();
129
+ }
130
+
131
+ // ---------- the pointer ----------
132
+
133
+ document.addEventListener("pointermove", (event) => {
134
+ if (drag) return;
135
+ const at = pictureAt(event.target);
136
+ const next = at ? at.img : event.target === handle ? hovered : null;
137
+ if (next !== hovered) {
138
+ hovered = next;
139
+ draw();
140
+ }
141
+ }, { passive: true });
142
+ // A press on a picture selects it, before the cells' tools (a drag between cells) and the caret hear it.
143
+ window.addEventListener("pointerdown", (event) => {
144
+ const at = event.button === 0 && active() ? pictureAt(event.target) : null;
145
+ if (!at) return;
146
+ event.preventDefault();
147
+ event.stopImmediatePropagation();
148
+ pick(at);
149
+ }, true);
150
+ window.addEventListener("mousedown", (event) => {
151
+ if (event.button === 0 && active() && (pictureAt(event.target) || event.target === handle)) event.preventDefault(); // no caret, no drag of the picture
152
+ }, true);
153
+ document.addEventListener("selectionchange", () => {
154
+ if (picked && !(picked.isConnected && around(picked))) {
155
+ picked = null;
156
+ draw();
157
+ }
158
+ });
159
+ document.addEventListener("keydown", (event) => {
160
+ if (event.key !== "Escape" || event.isComposing) return;
161
+ if (drag) return void (event.preventDefault(), event.stopImmediatePropagation(), end(false));
162
+ if (!picked || !around(picked)) return;
163
+ event.preventDefault();
164
+ event.stopImmediatePropagation();
165
+ const range = document.createRange();
166
+ range.setStartAfter(picked);
167
+ range.collapse(true);
168
+ getSelection().removeAllRanges();
169
+ getSelection().addRange(range);
170
+ }, true);
171
+ for (const type of ["scroll", "resize"]) window.addEventListener(type, () => { if (drag || picked || hovered) draw(); }, { capture: true, passive: true });
172
+ onSettle(draw);
173
+
174
+ // ---------- its width ----------
175
+
176
+ handle.addEventListener("pointerdown", (event) => {
177
+ const img = picked ?? hovered;
178
+ const host = img?.closest(CELL);
179
+ if (event.button !== 0 || !host || !active()) return;
180
+ event.preventDefault();
181
+ event.stopPropagation();
182
+ handle.setPointerCapture(event.pointerId);
183
+ drag = { img, host, x: event.clientX, start: img.getBoundingClientRect().width, before: ownHTML(host), had: img.getAttribute("width") };
184
+ document.documentElement.setAttribute("data-ge-cellpic-resize", "");
185
+ });
186
+ handle.addEventListener("pointermove", (event) => {
187
+ if (!drag) return;
188
+ const room = drag.host.closest(".doc-table-wrap")?.clientWidth || 2000; // never wider than its table's frame
189
+ drag.img.setAttribute("width", String(Math.round(Math.max(MIN_WIDTH, Math.min(room, drag.start + event.clientX - drag.x)))));
190
+ draw();
191
+ });
192
+ function end(keep) {
193
+ if (!drag) return;
194
+ const { img, host, before, had } = drag;
195
+ drag = null;
196
+ document.documentElement.removeAttribute("data-ge-cellpic-resize");
197
+ if (!keep) {
198
+ if (had === null) img.removeAttribute("width");
199
+ else img.setAttribute("width", had);
200
+ } else if (img.getAttribute("width") !== had) recordStep(host, before);
201
+ draw();
202
+ }
203
+ handle.addEventListener("pointerup", () => end(true));
204
+ handle.addEventListener("pointercancel", () => end(false));
205
+
206
+ // ---------- pictures pasted ----------
207
+
208
+ const sent = async (blob, name) => (await upload("image", { name, type: blob.type, data: await blobBase64(blob) })).path;
209
+
210
+ /**
211
+ * Picture files pasted into a cell (a screenshot, a copied picture), each sent to the document's
212
+ * folder as an image block's (10 MB at most): the cell's pictures, in order, those that could not
213
+ * go said.
214
+ */
215
+ async function fromFiles(files) {
216
+ const pictures = [...files].filter((file) => /^image\//.test(file.type));
217
+ if (pictures.some((file) => file.size > UPLOAD_LIMITS.image)) say(t("图片太大(最多 {0})。", sizeLimit("image")), "error");
218
+ const made = await Promise.all(pictures.filter((file) => file.size <= UPLOAD_LIMITS.image).map(async (file) => {
219
+ try {
220
+ return cellPicture(document, await sent(file, file.name || `image.${file.type.split("/")[1] ?? "png"}`), { alt: "" });
221
+ } catch (error) {
222
+ say(t("{0}:{1}", t("无法上传这张图片"), error.message), "error");
223
+ return null;
224
+ }
225
+ }));
226
+ return made.filter(Boolean);
227
+ }
228
+
229
+ // A pasted picture's address as a file of this document's folder ({ path }), or null.
230
+ async function fileOf(src, from, here) {
231
+ const served = SERVED.exec(src);
232
+ const [report, file] = served ? [decodeURIComponent(served[1]), served[2]] : FOLDER_FILE.test(src) ? [from ?? here, src] : [null, null];
233
+ if (file && report === here) return { path: file };
234
+ const copied = async (address, name) => {
235
+ const response = await fetch(address);
236
+ const blob = response.ok ? await response.blob() : null;
237
+ return blob && /^image\//.test(blob.type) && blob.size <= UPLOAD_LIMITS.image ? { path: await sent(blob, name) } : null;
238
+ };
239
+ if (file && report) return copied(mediaUrl("asset", encodeURIComponent(report), file), file.slice("assets/".length));
240
+ if (DATA.test(src)) return copied(src, "image");
241
+ if (WEB.test(src)) return { path: (await upload("image", { url: src })).path };
242
+ return null;
243
+ }
244
+
245
+ /**
246
+ * The pictures of pasted cells (`htmls`: their inline HTML) as files of this document's folder: a
247
+ * Map of each address to { path } (assets/<file>), or null where none could be had. `from`: the
248
+ * report the page's own cells came from (their assets/ that report's).
249
+ */
250
+ async function resolve(htmls, from = null) {
251
+ const addresses = new Set();
252
+ const template = document.createElement("template");
253
+ for (const html of htmls) {
254
+ if (!html.includes("<img")) continue;
255
+ template.innerHTML = html;
256
+ for (const img of template.content.querySelectorAll("img[src]")) addresses.add(img.getAttribute("src"));
257
+ }
258
+ const found = new Map();
259
+ if (addresses.size === 0) return found;
260
+ const here = thisReport();
261
+ const list = [...addresses];
262
+ if (list.some((src) => !(SERVED.exec(src)?.[1] === here || (FOLDER_FILE.test(src) && (from ?? here) === here)))) say(t("正在下载…"));
263
+ await Promise.all(list.slice(0, MAX_PICTURES).map(async (src) => found.set(src, await fileOf(src, from, here).catch(() => null))));
264
+ return found;
265
+ }
266
+
267
+ /**
268
+ * What pastedLines makes of a pasted picture (`found`: resolve's answer): the cell's picture, its
269
+ * alt and width kept; else a web one a link to it (`links`), any other its alt words (undefined:
270
+ * an element that is no picture).
271
+ */
272
+ const maker = (found, links = true) => (img) => {
273
+ if (img.localName !== "img") return undefined;
274
+ const src = img.getAttribute("src") ?? "";
275
+ const alt = img.getAttribute("alt") ?? "";
276
+ const width = img.getAttribute("width") ?? "";
277
+ const file = found.get(src);
278
+ if (file) return cellPicture(document, file.path, { alt, width: WIDTH.test(width) ? Number(width) : null });
279
+ if (links && WEB.test(src)) {
280
+ const link = document.createElement("a");
281
+ link.setAttribute("href", src);
282
+ link.textContent = alt || nameOf(src);
283
+ return link;
284
+ }
285
+ return alt ? document.createTextNode(alt) : null;
286
+ };
287
+
288
+ return {
289
+ fromFiles, resolve, maker,
290
+ /** The tools' nodes (kept in the top layer with a modal dialog). */
291
+ get nodes() { return [frame, handle].filter((node) => node.isConnected); },
292
+ /** Take them away (the page stops editing). */
293
+ hide() {
294
+ hovered = picked = null;
295
+ if (drag) end(false);
296
+ draw();
297
+ },
298
+ };
299
+ }
@@ -0,0 +1,150 @@
1
+ import { TABLE } from "../../components/kit.mjs";
2
+ import { insertRow, moveRow, removeRows, tableState } from "../../components/table/page.mjs";
3
+ import { tableOf } from "../../components/table/grid.mjs";
4
+ import { ownHTML } from "../core.mjs";
5
+ import { menuEntry, viewKeys } from "../page-objects.mjs";
6
+ import { CHART_SOURCE, TABLE_READERS, VIEW_FROM, nextChartKey } from "../../../shared/table-chart.mjs";
7
+ import { t } from "../../../shared/i18n/index.mjs";
8
+ import { TABLE_ICONS } from "./icons.mjs";
9
+
10
+ // The views of a table (docs/editor.md, "Table views"; the plan's 阶段 4): an instance of a custom
11
+ // block whose needs hold "tables", bound to a table of the document by the key its frame carries
12
+ // (shared/table-chart.mjs VIEW_FROM, the key a chart drawn from a table reads it by), reads the table's
13
+ // rows (the kit's context.table()) and changes them only by asking: a doc-table-intent the kit puts on
14
+ // the instance (runtime/kernel.js), which these tools answer at once, made as the table's own tools make
15
+ // a change, so that a view has no commit, undo or conflict of its own:
16
+ //
17
+ // set one cell's words: a text step of that cell (history.mjs recordStep), its commit a cell's text
18
+ // as typing's is, merged word by word with someone else's change of the cell (source/merge.mjs);
19
+ // move a row put before or after another, the cells it names set in the same step (a card dropped
20
+ // in another column: its status and its place);
21
+ // add a row put in after another or last, its cells' words those it names;
22
+ // remove a row taken out (never the last of the body, as the tools' 删除);
23
+ // check nothing: answered as the others would be (the kit's table().canEdit()), so that a view of a
24
+ // table these tools do not manage shows it read-only;
25
+ //
26
+ // move, add and remove are the table tools' operations (components/table/page.mjs moveRow, insertRow,
27
+ // removeRows) in one undo step each (index.mjs change), their commit the table's operation, which a
28
+ // change someone else made to the table meanwhile holds back as a conflict with its card, as any. Only a
29
+ // table these tools manage (GRID: written as the kit writes one) and with no merged cell takes them: a
30
+ // view of any other is read-only, as it is in an export (the kit asks nothing there). Its rows of data
31
+ // are those after its header row: the head's rows, or with no head its body's first row, which a view
32
+ // reads its columns' names from; no intent puts a row there or takes that one.
33
+ //
34
+ // 视图 › of a table's block menu (menuRow) lists the custom blocks that read tables and that the
35
+ // document's menus would offer (their `readsTables` row of the custom blocks' menu variants, which follows
36
+ // the 组件列表 switches; page-objects.mjs viewKeys: no other menu lists them, as one put in unbound only
37
+ // says it has no table) and puts one in right after the table bound to it, in one undo step: the table's key
38
+ // where it names this table (the first frame carrying it, as the kit and the checks read a key), or a new
39
+ // one (the first of t1, t2 … the page does not hold) put on its frame in that step (a table made from "/"
40
+ // has none; the second of two an Agent wrote with one key is not the one it names). The commit writes
41
+ // both, and the server makes sure of the key against the file (source/chart-keys.mjs relinkMade); a key
42
+ // it gives the pair anew the page follows, its undo steps too (page/commit.mjs apply, history.mjs rekeyed).
43
+
44
+ /**
45
+ * active(): whether the page edits now. change(unit, mutate, said, touched): the table tools' one undo
46
+ * step (index.mjs). tableAt(node): the table unit these tools manage that a node is in. recordStep(host,
47
+ * before): a text step of a text block (history.mjs). insertBelow(unit, key, { attributes, done }): a
48
+ * block of the menu's `key` put in below a block in one undo step, `attributes` ([element, names]) recorded
49
+ * with it and `done(made)` run in it on the new block (editor.mjs insertBelow). drawn(): the tools drawn
50
+ * again (a row taken out).
51
+ */
52
+ export function createViews({ active, change, tableAt, recordStep, insertBelow, drawn = () => {} }) {
53
+ const merged = (rows) => rows.some((row) => [...row.cells].some((cell) => cell.rowSpan !== 1 || cell.colSpan !== 1));
54
+ const writable = (cell) => cell?.getAttribute("contenteditable") === "true";
55
+ const holds = (cell, text) => cell.textContent === text && cell.childElementCount === 0;
56
+
57
+ // What a view asks (`detail` of doc-table-intent: kernel.js tableView), made, or refused (false).
58
+ function run({ table, op, row = null, before = null, after = null, cells = [] }) {
59
+ if (!active() || !table?.isConnected) return false;
60
+ const unit = tableAt(table);
61
+ if (!unit || tableOf(unit) !== table) return false;
62
+ const state = tableState(unit);
63
+ if (merged(state.rows) || !Array.isArray(cells) || !cells.every(([column, text]) => Number.isInteger(column) && column >= 0 && column < state.columns && typeof text === "string")) return false;
64
+ // A view's table().canEdit(): whether an intent of this table would be taken now, nothing changed.
65
+ if (op === "check") return true;
66
+ // Its rows of data: after the header a view reads its names from (the head, else the body's first row).
67
+ const all = state.rows;
68
+ const data = all.slice(Math.max(1, state.head?.rows.length ?? 0));
69
+ const ofData = (node) => data.includes(node);
70
+ const cellsOf = (target) => cells.map(([column]) => target.cells[column]);
71
+ if (op === "set") {
72
+ if (!ofData(row) || cells.length !== 1) return false;
73
+ const [[column, text]] = cells;
74
+ const cell = row.cells[column];
75
+ if (!writable(cell)) return false;
76
+ if (holds(cell, text)) return true;
77
+ const was = ownHTML(cell);
78
+ cell.textContent = text;
79
+ recordStep(cell, was);
80
+ return true;
81
+ }
82
+ if (op === "move") {
83
+ const target = before ?? after;
84
+ if (!ofData(row) || (target && !ofData(target)) || !cellsOf(row).every(writable)) return false;
85
+ const from = all.indexOf(row);
86
+ const rest = all.filter((node) => node !== row);
87
+ const to = !target || target === row ? from : before ? rest.indexOf(before) : rest.indexOf(after) + 1;
88
+ if (to === from && cells.every(([column, text]) => holds(row.cells[column], text))) return true;
89
+ return change(unit, () => {
90
+ if (to !== from && moveRow(unit, from, to) === false) return false;
91
+ for (const [column, text] of cells) row.cells[column].textContent = text;
92
+ return true;
93
+ }, null, cellsOf(row)) !== null;
94
+ }
95
+ if (op === "add") {
96
+ if (after && !ofData(after)) return false;
97
+ const at = after ? all.indexOf(after) + 1 : all.length;
98
+ return change(unit, () => {
99
+ const made = insertRow(unit, at);
100
+ for (const [column, text] of cells) if (made.cells[column]) made.cells[column].textContent = text;
101
+ return made;
102
+ }, null) !== null;
103
+ }
104
+ if (op === "remove") {
105
+ if (!ofData(row)) return false;
106
+ const at = all.indexOf(row);
107
+ const done = change(unit, () => removeRows(unit, at, at), null) !== null;
108
+ drawn();
109
+ return done;
110
+ }
111
+ return false;
112
+ }
113
+ document.addEventListener("doc-table-intent", (event) => {
114
+ if (run(event.detail ?? {})) event.preventDefault();
115
+ });
116
+
117
+ // The frame a key names, as the kit reads it (runtime/table-reading.js frameOf) and the checks do: the
118
+ // first that carries it, none of a dev block's.
119
+ const frameOf = (key) => [...document.querySelectorAll(`[${CHART_SOURCE}]`)].find((node) => node.getAttribute(CHART_SOURCE) === key && node.matches(TABLE.frame) && !node.closest("[data-doc-dev]")) ?? null;
120
+ // A view of the block `key` put in right after `unit`, bound to its table: by its key where that names
121
+ // it, else by a new one put on it in the same step (a table made from "/" has none; one of two an Agent
122
+ // wrote with one key is not the one it names, the first: a view by it would read and change that one).
123
+ function insertView(unit, key) {
124
+ const own = unit.getAttribute(CHART_SOURCE);
125
+ const taken = new Set([...document.querySelectorAll([CHART_SOURCE, ...TABLE_READERS].map((name) => `[${name}]`).join(", "))].flatMap((node) => [CHART_SOURCE, ...TABLE_READERS].map((name) => node.getAttribute(name)).filter((value) => value !== null)));
126
+ const bound = own !== null && frameOf(own) === unit ? own : nextChartKey(taken);
127
+ insertBelow(unit, key, {
128
+ attributes: [[unit, [CHART_SOURCE]]],
129
+ done(made) {
130
+ made?.setAttribute(VIEW_FROM, bound);
131
+ if (bound !== own) unit.setAttribute(CHART_SOURCE, bound);
132
+ },
133
+ });
134
+ }
135
+
136
+ return {
137
+ /** The 视图 › row of a table's block menu: one for each custom block that reads tables, or null where there is none or the table cannot be read as rows (no frame, a merged cell). */
138
+ menuRow(unit) {
139
+ const keys = viewKeys();
140
+ if (keys.length === 0 || !unit.matches(TABLE.frame) || merged(tableState(unit).rows)) return null;
141
+ return {
142
+ label: t("视图"), icon: TABLE_ICONS.view,
143
+ submenu: () => viewKeys().map((key) => {
144
+ const row = menuEntry(key).variant;
145
+ return { label: row.label, icon: row.icon, run: () => insertView(unit, key) };
146
+ }),
147
+ };
148
+ },
149
+ };
150
+ }
@@ -2,6 +2,7 @@ import { SPAN } from "../../../shared/media.mjs";
2
2
  import { COLUMN_WIDTH, MIN_COLUMN_WIDTH, widthOf } from "../../components/table/index.mjs";
3
3
  import { relayout, tableParts, tableState } from "../../components/table/page.mjs";
4
4
  import { widthHolder } from "../../../shared/table-slots.mjs";
5
+ import { GONE_WORDS } from "../core.mjs";
5
6
  import { gestureLock } from "../gesture.mjs";
6
7
  import { drawBox } from "../overlay-layer.mjs";
7
8
  import { hideTooltip, tooltip } from "../tooltip.mjs";
@@ -15,7 +16,7 @@ import { t } from "../../../shared/i18n/index.mjs";
15
16
  // index.mjs COLUMN_WIDTH; shared/table-slots.mjs widthHolder: a merged cell holds none), the kit laying the table
16
17
  // out at them (tables/layout.js manualLayout); the first
17
18
  // drag of a table the kit lays out gives every column the width it has then. A double click fits
18
- // the column to its widest cell, unwrapped. The menus' 一键调整列宽 takes the widths off (the kit's
19
+ // the column to its widest cell, unwrapped. The menus' 自动调整列宽 takes the widths off (the kit's
19
20
  // again) or gives each column its width as it is; 均分列宽 shares the columns' room out equally.
20
21
  // Sizing columns takes the table's own width off (--doc-span: the table is as wide as its
21
22
  // columns again).
@@ -114,18 +115,22 @@ export function createColumnWidths(tools) {
114
115
  relayout(unit);
115
116
  }
116
117
 
117
- // A column fitted to its widest cell of it alone, unwrapped (+1px).
118
+ // A column fitted to its widest cell of it alone, unwrapped (+1px): by its words, not the words an
119
+ // Agent took out that the page shows in it (changes/: out of the layout while it is measured).
118
120
  function fit(unit, index) {
119
121
  const { slots } = tableState(unit);
120
122
  const widest = Math.max(0, ...[...slots.places].filter(([, place]) => place.c === index && place.cols === 1).map(([cell]) => {
121
123
  const style = getComputedStyle(cell);
122
124
  const was = cell.style.whiteSpace;
125
+ const gone = [...cell.querySelectorAll(GONE_WORDS)];
126
+ for (const mark of gone) mark.hidden = true;
123
127
  cell.style.whiteSpace = "nowrap";
124
128
  const range = document.createRange();
125
129
  range.selectNodeContents(cell);
126
130
  const width = range.getBoundingClientRect().width + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);
127
131
  cell.style.whiteSpace = was;
128
132
  if (cell.getAttribute("style") === "") cell.removeAttribute("style");
133
+ for (const mark of gone) mark.hidden = false;
129
134
  return width;
130
135
  }));
131
136
  const widths = shown(unit);
@@ -291,9 +296,9 @@ export function createColumnWidths(tools) {
291
296
  /** The edges plain again (the tools no longer stand by the table). */
292
297
  disarm() { armed = null; },
293
298
  get dragging() { return drag !== null; },
294
- /** 一键调整列宽: the kit's widths, from the columns' words (the reader's taken off; sizing a column fixes them again). */
299
+ /** 自动调整列宽: the kit's widths, from the columns' words (the reader's taken off; sizing a column fixes them again). */
295
300
  fit(unit) {
296
- if (set(unit, null, t("已一键调整列宽"))) return true;
301
+ if (set(unit, null, t("已自动调整列宽"))) return true;
297
302
  tools.say(t("列宽已按内容调整,无需再调。"));
298
303
  return false;
299
304
  },
@@ -1,9 +1,10 @@
1
1
  import { chipBox } from "../chip-fills.mjs";
2
2
  import { DETAILS, DIALOG } from "../../components/kit.mjs";
3
3
  import { boxRole } from "../../components/registry.mjs";
4
- import { UNIT, can, isHost, mergeInto, partsOf, removalTarget, takeOut, textEnd, unitElement } from "../core.mjs";
4
+ import { UNIT, can, isEmpty, isHost, mergeInto, partsOf, removalTarget, takeOut, textEnd, unitElement } from "../core.mjs";
5
5
  import { atomOf, caretAt, caretAtOffset, dragPlace, editable, hosts, pointRange, select } from "../caret.mjs";
6
6
  import { edgeFollower } from "../edge-scroll.mjs";
7
+ import { FOLDED } from "../folded.mjs";
7
8
  import { gapScore } from "../geometry.mjs";
8
9
  import { endsGesture, gestureLock } from "../gesture.mjs";
9
10
  import { joinCode } from "../marks.mjs";
@@ -21,8 +22,10 @@ import { t } from "../../../shared/i18n/index.mjs";
21
22
  // the window's edges), drawn with the CSS Custom Highlight API in the selection's own colors, the
22
23
  // browser's selecting held off meanwhile; back in that block, the browser's again. Shift+click in
23
24
  // another block selects from the caret to there.
24
- // Its text is that of body text, headings and list items (in quotes, highlight blocks, columns…).
25
- // A block holding none (a code block, a table, a file, an image, a formula block, a callout, a
25
+ // Its text is that of body text, headings and list items (in quotes, highlight blocks, callouts, columns…),
26
+ // and the page's title's, which a deletion takes its part of but never joins with the body's (notion-lite's
27
+ // selection runs from its page title into the blocks; the user's: what is left of the body stays in the body).
28
+ // A block holding none (a code block, a table, a file, an image, a formula block, a
26
29
  // divider…) is taken whole as it passes it, filled as a selected block is (selection/ mark), its
27
30
  // own text not marked: over one, an end of the selection stands before it or after it, as the drag
28
31
  // goes, and a press begun in one (its code, a cell) takes it whole once it has left it.
@@ -107,6 +110,10 @@ function lineStrips(texts, origin) {
107
110
 
108
111
  // The text blocks it takes text from, and a deletion joins: body text, headings, list items.
109
112
  const isText = (host) => isHost(host) && (host.getAttribute("data-ge-kind") ?? "flow") === "flow";
113
+ // The page's title: text it takes too (drawn, copied, deleted), kept apart: a deletion leaves it what
114
+ // stands outside the selection and joins nothing to it (remove).
115
+ const isTitle = (host) => isHost(host) && host.getAttribute("data-ge-kind") === "title";
116
+ const isPiece = (host) => isText(host) || isTitle(host);
110
117
  const textHosts = (unit) => [...unit.querySelectorAll("[data-ge-block], [data-ge-new]")].filter((node) => isHost(node) && isText(node));
111
118
 
112
119
  // The outermost block around `node` holding no text of the body (a code block, a table, a file…),
@@ -193,12 +200,12 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
193
200
  function pointAt(x, y, from) {
194
201
  const place = dragPlace([from.node, from.offset], x, y);
195
202
  const host = place && editable(place[0]);
196
- if (host?.closest("main") && isText(host)) return { host, node: place[0], offset: place[1] };
203
+ if (host?.closest("main") && isPiece(host)) return { host, node: place[0], offset: place[1] };
197
204
  const whole = wholeOf(document.elementFromPoint(x, y));
198
205
  if (whole) return edge(whole, !from || before(from, edge(whole, false)));
199
206
  let best = null;
200
207
  let bestScore = null;
201
- for (const each of hosts().filter((node) => node.closest("main") && isText(node))) {
208
+ for (const each of hosts().filter((node) => node.closest("main") && isPiece(node))) {
202
209
  const rect = each.getBoundingClientRect();
203
210
  // By height, then (level ones: columns side by side) by width; of nested ones, the innermost.
204
211
  const score = gapScore(rect, x, y);
@@ -219,7 +226,7 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
219
226
  // Where the selection starts, `focus` being its other end: the press's place in body text; begun
220
227
  // in a block taken whole (its code, a cell), that block's edge away from `focus`.
221
228
  function startOf(anchor, focus) {
222
- if (isText(anchor.host)) return anchor;
229
+ if (isPiece(anchor.host)) return anchor;
223
230
  const whole = wholeOf(anchor.host) ?? unitElement(anchor.host);
224
231
  if (!whole) return anchor;
225
232
  const head = edge(whole, false);
@@ -242,7 +249,7 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
242
249
  // text it reaches: none when its text stands before the start (the selection begun in a block the
243
250
  // item holds) or after the end.
244
251
  const reaches = (host) => host === selection.start.host || host === selection.end.host || (range.isPointInRange(host, 0) && range.isPointInRange(host, textEnd(host)));
245
- const texts = hosts().filter((host) => host.closest("main") && isText(host) && range.intersectsNode(host) && reaches(host) && !folded(host)).map((host) => {
252
+ const texts = hosts().filter((host) => host.closest("main") && isPiece(host) && range.intersectsNode(host) && reaches(host) && !folded(host)).map((host) => {
246
253
  const part = document.createRange();
247
254
  part.setStart(host, 0);
248
255
  part.setEnd(host, textEnd(host));
@@ -250,6 +257,20 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
250
257
  if (host === selection.end.host) part.setEnd(selection.end.node, selection.end.offset);
251
258
  return { host, range: part };
252
259
  });
260
+ // What a folded heading hides (fold/) between the ends goes with the selection, wherever in the
261
+ // heading's words it begins: its text blocks' text in full and its other blocks whole (below), as
262
+ // a deletion takes the blocks between the ends whole (unitsBetween), so a copy or a cut carries
263
+ // what the deletion takes. An end is never in what is hidden (hosts() are those shown), so what is
264
+ // hidden and in the range lies between the ends.
265
+ const hidden = [...document.querySelectorAll(`main [${FOLDED}] :is([data-ge-block], [data-ge-new]), main :is([data-ge-block], [data-ge-new])[${FOLDED}]`)]
266
+ .filter((host) => isHost(host) && isText(host) && range.intersectsNode(host) && !folded(host));
267
+ for (const host of hidden) {
268
+ const part = document.createRange();
269
+ part.setStart(host, 0);
270
+ part.setEnd(host, textEnd(host));
271
+ texts.push({ host, range: part });
272
+ }
273
+ if (hidden.length > 0) texts.sort((a, b) => (a.host.compareDocumentPosition(b.host) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1));
253
274
  const wholes = [...wholeClosed];
254
275
  for (const unit of document.querySelectorAll(`main :is(${UNIT})`)) {
255
276
  if (wholes.some((other) => other === unit || other.contains(unit))) continue;
@@ -348,7 +369,7 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
348
369
 
349
370
  // Drawn again over its text blocks turned into another type (`texts`: where its pieces are now, in
350
371
  // page order), as notion-lite's placeCaret(keep) keeps a selection; when one of them holds no text of
351
- // the body now (a callout, a disclosure's title, code), let go instead. Returns whether it is drawn.
372
+ // the body now (a disclosure's title, code), let go instead. Returns whether it is drawn.
352
373
  function reselect(texts) {
353
374
  if (!cross) return false;
354
375
  if (texts.length === 0 || !texts.every(({ host }) => host.isConnected && isText(host))) {
@@ -481,7 +502,7 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
481
502
  select(range);
482
503
  return;
483
504
  }
484
- const texts = hosts().filter((host) => host.closest("main") && isText(host));
505
+ const texts = hosts().filter((host) => host.closest("main") && isPiece(host));
485
506
  const next = texts.find((host) => before(point, { node: host, offset: 0 }));
486
507
  const previous = texts.filter((host) => before({ node: host, offset: textEnd(host) }, point)).at(-1);
487
508
  const host = forward ? next ?? previous : previous ?? next;
@@ -489,14 +510,17 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
489
510
  }
490
511
 
491
512
  // Delete it: the first block keeps its text before it and takes the last block's after it, the
492
- // blocks between go (those taken whole among them); one undo step, the caret where it began.
513
+ // blocks between go (those taken whole among them); one undo step, the caret where it began. From
514
+ // the page's title (`apart`) nothing joins: the title keeps what stands before it (empty, it says
515
+ // 未命名文档), the last block what stands after it in a block of its own (gone when that is nothing).
493
516
  // Returns whether it went.
494
517
  function remove() {
495
518
  const selection = cross;
496
519
  const { start, end } = selection;
497
520
  letGo();
498
521
  if (!(start.host ?? start.node).isConnected || !(end.host ?? end.node).isConnected) return false;
499
- if (![start.host, end.host].every((host) => !host || isText(host))) {
522
+ const apart = isTitle(start.host) || isTitle(end.host);
523
+ if (![start.host, end.host].every((host) => !host || isPiece(host))) {
500
524
  say(t("跨块删除只支持正文、标题和列表里的文字。"));
501
525
  return false;
502
526
  }
@@ -538,9 +562,14 @@ export function createTextSelection({ isEditing, struct, say, keepText, selectUn
538
562
  }
539
563
  for (const target of targets) takeOut(target);
540
564
  // Joined unless the two cannot be (a block that may not merge, lists that cannot go along):
541
- // then each keeps what is left of its text.
542
- if (start.host && end.host && mergeInto(start.host, end.host, { anyKind: true }) && endTarget !== end.host && endTarget.isConnected) takeOut(endTarget);
543
- if (start.host) joinCode(start.host); // inline code meeting inline code at the join is one piece
565
+ // then each keeps what is left of its text. Apart from the title, the last block left empty
566
+ // goes as the blocks between do (it was all selected), else it stays with its rest.
567
+ if (apart) {
568
+ const last = isTitle(end.host) ? null : end.host;
569
+ if (last && endTarget && isEmpty(last) && can(last, "remove") && !keepText(endTarget)) takeOut(endTarget);
570
+ } else if (start.host && end.host && mergeInto(start.host, end.host, { anyKind: true }) && endTarget !== end.host && endTarget.isConnected) takeOut(endTarget);
571
+ if (start.host && !apart) joinCode(start.host); // inline code meeting inline code at the join is one piece
572
+ if (isTitle(start.host) && isEmpty(start.host)) start.host.replaceChildren(); // no <br> left in an emptied title
544
573
  return { touched: touched.filter((host) => host.isConnected), focus: start.host ?? end.host ?? null };
545
574
  });
546
575
  if (!result) return false;