@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
@@ -11,8 +11,9 @@ import { t } from "../../../shared/i18n/index.mjs";
11
11
 
12
12
  // Resizing chart cards and tables in the preview ("Sizes" in the kit's styles/sizes.css). With the pointer on the
13
13
  // right edge of a card or table, or on its bottom edge (a chart's plot height, a table's scroll
14
- // height), the cursor changes; dragging shows a blue line where the edge goes and the size that
15
- // makes, and letting go applies it as one undo step (Esc cancels). Widths are shares of the width
14
+ // height), the cursor changes; dragging shows a gray line where the edge goes (darker where it
15
+ // snaps) and the bottom notice says the size that makes while the drag lasts (no label beside the
16
+ // line: the user, 2026-11-07), and letting go applies it as one undo step (Esc cancels). Widths are shares of the width
16
17
  // the block stands in: the reading width, or its column's. A card's width snaps to the middle and
17
18
  // to the end; a centered card grows on both sides. A table's
18
19
  // width moves its own right end by as much as the pointer moves, also when the table is wider than
@@ -23,17 +24,19 @@ import { t } from "../../../shared/i18n/index.mjs";
23
24
  // height of its frame: shorter than its code, the code scrolls inside it, and the edge snaps to the
24
25
  // height that shows all of it (no height of its own). Letting go where the drag started changes
25
26
  // nothing. Anything that ends the press another way (the capture lost, the window losing the
26
- // focus, the page hidden) cancels it; the lines and the label belong to the drag (overlays.mjs). A
27
- // code block's bottom edge has no label: the line alone (where it snaps, the status line says after).
27
+ // focus, the page hidden) cancels it; the lines belong to the drag (overlays.mjs), and the notice it
28
+ // put up goes with it. Snapping takes the edge within SNAP (6px) of a place, little enough that a
29
+ // size near one can still be had (14px before 2026-11-07, which the user found too strong).
28
30
 
29
31
  const STYLE = `
30
32
  ${gestureLock("data-ge-resize=\"x\"", { cursor: "ew-resize" })}
31
33
  ${gestureLock("data-ge-resize=\"y\"", { cursor: "ns-resize" })}
32
- .ge-resize-line { position: fixed; left: 0; top: 0; z-index: ${Z.guide}; border-radius: 2px; background: rgb(151 197 241); pointer-events: none; }
33
- .ge-resize-label { position: fixed; left: 0; top: 0; z-index: ${Z.label}; padding: 2px 7px; border-radius: 5px; background: var(--doc-accent, #2678d8); color: #fff; font: 12px/18px var(--doc-font, system-ui, sans-serif); white-space: nowrap; pointer-events: none; }
34
+ .ge-resize-line { position: fixed; left: 0; top: 0; z-index: ${Z.guide}; border-radius: 1px; background: var(--ge-guide-hot); pointer-events: none; }
35
+ .ge-resize-line[data-snap] { background: var(--ge-guide-snap); }
34
36
  `;
35
37
  const GRAB = { inside: 3, outside: 8 }; // how near an edge the pointer takes it, inside and outside the block (px)
36
- const SNAP = 14; // px
38
+ const SNAP = 6; // px
39
+ const LIVE = 60000; // ms: the notice saying the size dragged to stays while the drag lasts (it is taken off when it ends)
37
40
  const MIN_WIDTH = 160; // px: the least a card's edge is dragged to (a table's is its columns' floors)
38
41
  // The sizes (name and range) are each component's description's (registry SIZES): the same ones the
39
42
  // server checks a size by.
@@ -45,11 +48,12 @@ const heightRange = (kind) => range(kind, heightOf(kind));
45
48
 
46
49
  /**
47
50
  * units: Map(id -> { kind }) from the edit map. active(): whether resizing may start.
48
- * look(element, { sizes }, select): the editor's undoable change of sizes. say(text): the status line.
51
+ * look(element, { sizes }, select): the editor's undoable change of sizes. say(text, kind, hold): the
52
+ * bottom notice; settle(): the notice taken off.
49
53
  * owns(node): whether a table's right and bottom edges are the table tools' (table/widths.mjs: a
50
54
  * click arms one, a drag then is this tool's, `startTable`).
51
55
  */
52
- export function createResize({ units, active, look, say, owns = () => false }) {
56
+ export function createResize({ units, active, look, say, settle = () => {}, owns = () => false }) {
53
57
  addStyle(STYLE);
54
58
  let hover = null; // { node, axis } under the pointer
55
59
  let drag = null;
@@ -134,12 +138,12 @@ export function createResize({ units, active, look, say, owns = () => false }) {
134
138
  const snaps = [{ x: table.press, label: t("原宽度"), keep: true }, { x: table.press + (box.width - table.width), label: t("铺满正文") }];
135
139
  const snap = snaps.find((candidate) => Math.abs(candidate.x - edge) <= SNAP);
136
140
  if (snap) edge = snap.x;
137
- if (snap?.keep) return { edge, label: snap.label, value: drag.before };
141
+ if (snap?.keep) return { edge, label: snap.label, value: drag.before, snapped: true };
138
142
  // Rounded up, so the frame is never narrower than where it was let go (at the floors, say).
139
143
  const share = Math.ceil(Math.max(range("table", SPAN).min, width(edge) / box.width) * 1000) / 1000;
140
144
  const label = snap?.label ?? (share > 1 ? t("超宽表 · 表宽 {0}px,横向滚动", Math.round(width(edge)))
141
145
  : edge <= narrowest + 0.5 ? t("最窄 · {0}%", Math.round(share * 100)) : `${Math.round(share * 100)}%`);
142
- return { edge, label, value: Math.abs(share - 1) < 0.005 ? "1" : String(Math.min(share, range("table", SPAN).max)) };
146
+ return { edge, label, value: Math.abs(share - 1) < 0.005 ? "1" : String(Math.min(share, range("table", SPAN).max)), snapped: Boolean(snap) };
143
147
  }
144
148
 
145
149
  // Where the edge may go and where it snaps: back where it started (no change), the middle (a
@@ -158,13 +162,13 @@ export function createResize({ units, active, look, say, owns = () => false }) {
158
162
  let edge = Math.min(Math.max(x, near), far);
159
163
  const snap = snaps.find((candidate) => Math.abs(candidate.x - edge) <= SNAP);
160
164
  if (snap) edge = snap.x;
161
- if (snap?.keep) return { edge, label: snap.label, value: drag.before };
165
+ if (snap?.keep) return { edge, label: snap.label, value: drag.before, snapped: true };
162
166
  const share = Math.round(Math.max(range(kind, SPAN).min, shareAt(edge)) * 1000) / 1000;
163
167
  const whole = Math.abs(share - 1) < 0.005;
164
168
  const label = snap?.label ?? `${Math.round(share * 100)}%${centered ? t(" · 居中") : ""}`;
165
169
  // A card at the whole width is the default.
166
170
  const value = whole ? (kind === "figure" && !centered ? null : "1") : String(Math.min(share, range(kind, SPAN).max));
167
- return { edge, label, value };
171
+ return { edge, label, value, snapped: Boolean(snap) };
168
172
  }
169
173
 
170
174
  // ---------- heights ----------
@@ -184,8 +188,8 @@ export function createResize({ units, active, look, say, owns = () => false }) {
184
188
  const header = rect.height - code.getBoundingClientRect().height;
185
189
  const whole = rect.height + (code.scrollHeight - code.clientHeight); // all its lines, no scrolling
186
190
  const height = Math.min(Math.max(y - rect.top, Math.min(whole, header + heightRange(kind).min)), whole);
187
- if (before !== null && Math.abs(rect.top + height - rect.bottom) <= SNAP / 2) return { edge: rect.bottom, label: t("原高度"), value: before };
188
- if (whole - height <= SNAP) return { edge: rect.top + whole, label: t("显示全部代码"), value: null };
191
+ if (before !== null && Math.abs(rect.top + height - rect.bottom) <= SNAP / 2) return { edge: rect.bottom, label: t("原高度"), value: before, snapped: true };
192
+ if (whole - height <= SNAP) return { edge: rect.top + whole, label: t("显示全部代码"), value: null, snapped: true };
189
193
  const frame = Math.round(height - header);
190
194
  return { edge: rect.top + header + frame, label: t("高 {0}px · 其余滚动查看", frame), value: `${frame}px` };
191
195
  }
@@ -194,19 +198,20 @@ export function createResize({ units, active, look, say, owns = () => false }) {
194
198
  const drawn = drawnHeight(svg);
195
199
  const scale = svg.getBoundingClientRect().height / drawn || 1;
196
200
  const floor = 160; // the least a chart is drawn at (a softer floor than the one a size is checked by)
197
- if (Math.abs(rect.bottom - y) <= SNAP) return { edge: rect.bottom, label: t("原高度"), value: before };
201
+ if (Math.abs(rect.bottom - y) <= SNAP) return { edge: rect.bottom, label: t("原高度"), value: before, snapped: true };
198
202
  // Level with a card beside it (in another column of its row): the bottoms meet.
199
203
  const beside = drag.beside.find((bottom) => Math.abs(bottom - y) <= SNAP);
200
204
  const height = Math.round(Math.min(Math.max(drawn + ((beside ?? y) - rect.bottom) / scale, floor), heightRange(kind).max));
201
205
  const edge = rect.bottom + (height - drawn) * scale;
202
- return { edge, label: beside !== undefined && Math.abs(edge - beside) < 1.5 ? t("与旁边对齐 · 图表高 {0}px", height) : t("图表高 {0}px", height), value: `${height}px` };
206
+ const level = beside !== undefined && Math.abs(edge - beside) < 1.5;
207
+ return { edge, label: level ? t("与旁边对齐 · 图表高 {0}px", height) : t("图表高 {0}px", height), value: `${height}px`, snapped: level };
203
208
  }
204
209
  const all = node.scrollHeight + (node.offsetHeight - node.clientHeight);
205
210
  let height = Math.min(Math.max(y - rect.top, heightRange(kind).min), all);
206
- if (Math.abs(rect.top + height - rect.bottom) <= SNAP / 2) return { edge: rect.bottom, label: t("原高度"), value: drag.before };
211
+ if (Math.abs(rect.top + height - rect.bottom) <= SNAP / 2) return { edge: rect.bottom, label: t("原高度"), value: drag.before, snapped: true };
207
212
  if (height >= all - 2) {
208
213
  const fits = all <= scrollHeight(node); // the default scroll area shows them all
209
- return { edge: rect.top + all, label: t("显示全部行"), value: fits ? null : "none" };
214
+ return { edge: rect.top + all, label: t("显示全部行"), value: fits ? null : "none", snapped: true };
210
215
  }
211
216
  height = Math.round(height);
212
217
  return { edge: rect.top + height, label: t("高 {0}px", height), value: `${height}px` };
@@ -231,6 +236,7 @@ export function createResize({ units, active, look, say, owns = () => false }) {
231
236
  const rect = node.getBoundingClientRect();
232
237
  drag = {
233
238
  node, axis, kind, name, before, rect,
239
+ press: { x: event.clientX, y: event.clientY },
234
240
  box: contentBox(node.parentElement),
235
241
  // A card's height snaps level with the cards beside it: the bottoms of those in the other columns of its row.
236
242
  beside: axis === "y" && kind === "figure" ? besideBottoms(node) : [],
@@ -243,19 +249,22 @@ export function createResize({ units, active, look, say, owns = () => false }) {
243
249
  press: event.clientX,
244
250
  atEnd: node.scrollLeft + node.clientWidth >= node.scrollWidth - 2,
245
251
  } : null,
246
- label: kind === "code" ? null : element("div", { class: "ge-resize-label" }),
247
252
  result: null,
253
+ told: null, // what the notice says now
248
254
  };
249
255
  const session = drag;
250
256
  session.lines = (session.centered ? [0, 1] : [0]).map(() => element("div", { class: "ge-resize-line" }));
251
- for (const part of [session.label, ...session.lines].filter(Boolean)) mount(own(part, "resize", { owner: node, alive: () => drag === session }));
257
+ for (const part of session.lines) mount(own(part, "resize", { owner: node, alive: () => drag === session }));
252
258
  note("resize", `start ${axis}`);
253
259
  document.documentElement.setPointerCapture?.(event.pointerId);
254
260
  update(event.clientX, event.clientY);
255
261
  }
256
262
 
263
+ // What is being resized, in the notice's words: 卡片 and 宽度, 表格 and 高度, 代码块 and 高度.
264
+ const what = (kind, axis) => [kind === "figure" ? t("卡片") : kind === "code" ? t("代码块") : t("表格"), axis === "x" ? t("宽度") : t("高度")];
265
+
257
266
  function update(x, y) {
258
- const { axis, rect, box, lines, label } = drag;
267
+ const { axis, kind, rect, box, lines } = drag;
259
268
  drag.result = axis === "x" ? widthAt(x) : heightAt(y);
260
269
  const { edge } = drag.result;
261
270
  if (axis === "x") {
@@ -264,24 +273,28 @@ export function createResize({ units, active, look, say, owns = () => false }) {
264
273
  width: "2px", height: `${Math.round(rect.height)}px`,
265
274
  transform: `translate(${Math.round((index ? mirror : edge) - 1)}px, ${Math.round(rect.top)}px)`,
266
275
  }));
267
- if (label) label.style.transform = `translate(${Math.round(Math.min(edge + 10, innerWidth - label.offsetWidth - 8))}px, ${Math.round(Math.max(8, y - 30))}px)`;
268
276
  } else {
269
277
  Object.assign(lines[0].style, { width: `${Math.round(rect.width)}px`, height: "2px", transform: `translate(${Math.round(rect.left)}px, ${Math.round(edge - 1)}px)` });
270
- if (label) label.style.transform = `translate(${Math.round(Math.min(x + 12, innerWidth - label.offsetWidth - 8))}px, ${Math.round(Math.min(edge + 8, innerHeight - 28))}px)`;
271
278
  }
272
- if (label) label.textContent = drag.result.label;
279
+ lines.forEach((line) => line.toggleAttribute("data-snap", Boolean(drag.result.snapped)));
280
+ // The size in the bottom notice once the pointer has moved (a press alone says nothing), said again
281
+ // only when it changes (a workbench is told each time).
282
+ if (!drag.told && Math.hypot(x - drag.press.x, y - drag.press.y) < 2) return;
283
+ const told = t("{0}{1}:{2}", ...what(kind, axis), drag.result.label);
284
+ if (told !== drag.told) say(told, "note", LIVE);
285
+ drag.told = told;
273
286
  }
274
287
 
275
288
  function finish(commit) {
276
289
  if (!drag) return;
277
- const { node, axis, kind, name, before, lines, label, result, table } = drag;
290
+ const { node, axis, kind, name, lines, result, table, told } = drag;
278
291
  note("resize", commit ? "released" : "cancelled");
279
292
  drag = null;
280
293
  lines.forEach((line) => line.remove());
281
- label?.remove();
294
+ if (told) settle(); // the size dragged to: what is said next (or nothing) replaces it
282
295
  setHover(null);
283
296
  if (commit && result && look(node, { sizes: { [name]: result.value } }, null)) {
284
- say(t("已调整{0}{1}:{2} · Ctrl+Z 撤销", kind === "figure" ? t("卡片") : kind === "code" ? t("代码块") : t("表格"), axis === "x" ? t("宽度") : t("高度"), result.label));
297
+ say(t("已调整{0}{1}:{2} · Ctrl+Z 撤销", ...what(kind, axis), result.label));
285
298
  // Scrolled to its end, a table stays so: its new end shows at the frame's edge, ready for the
286
299
  // next drag (after tables.js has laid it out again, on the next frame).
287
300
  if (table?.atEnd) requestAnimationFrame(() => requestAnimationFrame(() => { node.scrollLeft = node.scrollWidth; }));
@@ -322,6 +335,6 @@ export function createResize({ units, active, look, say, owns = () => false }) {
322
335
  setHover(null);
323
336
  },
324
337
  /** The editor's UI nodes to keep in the top layer when a modal dialog opens. */
325
- get nodes() { return drag ? [...drag.lines, drag.label].filter(Boolean) : []; },
338
+ get nodes() { return drag ? [...drag.lines] : []; },
326
339
  };
327
340
  }
@@ -10,19 +10,21 @@ import { t } from "../../../shared/i18n/index.mjs";
10
10
  // tab is clicked (undo clicks it back). One undo step, which selects the blocks again. A box that
11
11
  // always holds a block gets an empty paragraph once they are gone (core.mjs tidyEmptied), the caret
12
12
  // in it. That one empty paragraph stays (keptAnyway: it would be put back as it is), so deleting
13
- // only it does nothing and says nothing.
13
+ // only it does nothing and says nothing. A folded heading goes with what it hides, or as the section
14
+ // it covers whole (fold/ takenWith).
14
15
 
15
16
  /**
16
17
  * info: block-info.mjs. selection: selection/index.mjs. struct(parents, touched, mutate): the
17
18
  * editor's undoable structural change (history.mjs). say: the status line. closeMenu(): the block
18
- * menu closes. forget(): the handle forgets the block it stood beside.
19
+ * menu closes. forget(): the handle forgets the block it stood beside. folds: the headings' folds (fold/).
19
20
  */
20
- export function createDelete({ info, selection, struct, say, closeMenu, forget }) {
21
- const { kindOf, nameOf, keepText } = info;
21
+ export function createDelete({ info, selection, struct, say, closeMenu, forget, folds = null }) {
22
+ const { kindOf, nameOf, keepText, named } = info;
22
23
 
23
24
  return function remove(targets = selection.picked) {
24
25
  closeMenu();
25
- const list = ordered([targets].flat().filter(alive)).filter((target) => !keptAnyway(target));
26
+ const picked = ordered([targets].flat().filter(alive));
27
+ const list = (folds ? folds.takenWith(picked) : picked).filter((target) => !keptAnyway(target));
26
28
  if (list.length === 0) return;
27
29
  const refused = list.map((target) => [target, keepText(target, list)]).find(([, reason]) => reason);
28
30
  if (refused) {
@@ -53,7 +55,7 @@ export function createDelete({ info, selection, struct, say, closeMenu, forget }
53
55
  });
54
56
  if (done?.caret) caretAt(done.caret, "start");
55
57
  const emptied = nodes.some((node) => !list.includes(node));
56
- const name = list.length === 1 ? nameOf(nodes[0]) : t("{0} 块", list.length);
58
+ const name = list.length === 1 ? nameOf(nodes[0]) : folds ? folds.namedWith(picked, list, named) : t("{0} 块", list.length);
57
59
  say(t("已删除{0}{1}{2} · Ctrl+Z 撤销", name, emptied ? t("(外层已空,一并删除)") : "", tabs.length > 0 ? t(",连同其中的内容") : ""));
58
60
  };
59
61
  }
@@ -2,6 +2,7 @@ import { unitElement, unitsOf, withLeads } from "../core.mjs";
2
2
  import { alive, ordered } from "../block-info.mjs";
3
3
  import { entersAfter } from "../beside.mjs";
4
4
  import { createFills } from "../fills.mjs";
5
+ import { FOLDED } from "../folded.mjs";
5
6
  import { describe, note, report } from "../overlays.mjs";
6
7
  import { t } from "../../../shared/i18n/index.mjs";
7
8
 
@@ -20,6 +21,12 @@ import { t } from "../../../shared/i18n/index.mjs";
20
21
  // page, made to match the selection the moment it changes (render), never on a later frame, so no
21
22
  // fill outlives its block's selection, and none is drawn while the block tools are off. The frames
22
23
  // only keep them where their blocks are (paint); a fill that cannot be drawn goes.
24
+ //
25
+ // What a folded heading hides (fold/) is never selected: select() leaves it out, Shift+↑/↓ and ↑/↓
26
+ // pass over it; what takes a folded heading away whole takes it along when it acts (fold/ takenWith).
27
+
28
+ // Whether a block is hidden by a folded heading (data-ge-folded on it or a block around it).
29
+ const folded = (node) => node.closest(`[${FOLDED}]`) !== null;
23
30
 
24
31
  /**
25
32
  * info: block-info.mjs. active(): whether block tools may show. say(text, kind, hold): the status
@@ -37,7 +44,7 @@ export function createSelection({ info, active, say, closeMenu, schedule }) {
37
44
  /** Select a block, or several (none is clearing); `quiet`: without saying so. */
38
45
  function select(targets, { quiet = false } = {}) {
39
46
  closeMenu();
40
- const next = ordered([targets].flat().filter(alive));
47
+ const next = ordered([targets].flat().filter(alive)).filter((node) => !folded(node));
41
48
  if (next.length === 0) return clear();
42
49
  if (next.length !== picked.length || next.some((node, index) => node !== picked[index])) {
43
50
  picked = next;
@@ -79,7 +86,7 @@ export function createSelection({ info, active, say, closeMenu, schedule }) {
79
86
  // Shift+↑/↓: the selection widens (or narrows) by one block among the anchor's neighbours.
80
87
  function extend(delta) {
81
88
  const container = anchor?.parentElement;
82
- const list = container ? unitsOf(container) : [];
89
+ const list = container ? unitsOf(container).filter((unit) => !folded(unit)) : [];
83
90
  const at = list.indexOf(anchor);
84
91
  if (at < 0) return;
85
92
  const inside = picked.map((node) => list.indexOf(node)).filter((index) => index >= 0);
@@ -94,7 +101,7 @@ export function createSelection({ info, active, say, closeMenu, schedule }) {
94
101
  function sibling(node, forward) {
95
102
  for (let next = forward ? node.nextElementSibling : withLeads(node)[0].previousElementSibling; next; next = forward ? next.nextElementSibling : next.previousElementSibling) {
96
103
  const unit = unitElement(next);
97
- if (unit && unit.parentElement === node.parentElement && unit !== node) return unit;
104
+ if (unit && unit.parentElement === node.parentElement && unit !== node && !folded(unit)) return unit;
98
105
  }
99
106
  return null;
100
107
  }
@@ -0,0 +1,14 @@
1
+ // Where the page shows a file of the report's folder (assets/<file>): the server's asset route,
2
+ // which editor.mjs gives (serveFiles) once it knows the report. A picture in a table cell's text is
3
+ // shown there (components/table/ cellPicture). No imports: a component's index.mjs reads it while
4
+ // the registry is still being made.
5
+
6
+ let fileUrl = (path) => path;
7
+
8
+ /** Where the page shows a file of the report's folder from now on: `urlOf(path)`. */
9
+ export const serveFiles = (urlOf) => {
10
+ fileUrl = urlOf;
11
+ };
12
+
13
+ /** Where the page shows `path`, a file of the report's folder (assets/<file>). */
14
+ export const servedFile = (path) => fileUrl(path);
@@ -1,20 +1,41 @@
1
1
  import { OLD_PROTOCOL, PROTOCOL, PROTOCOLS, VERSION, keyCombo } from "../../shared/session.mjs";
2
+ import { lookOf, lookOfElement } from "../../shared/document-look.mjs";
2
3
 
3
4
  // The report page inside a workbench (an iframe of the same origin): it answers a few commands and
4
5
  // tells the workbench its state, never the report's content. Nothing happens when the page is not
5
6
  // embedded. The protocol is src/shared/session.mjs; how a workbench uses it, docs/workbench.md.
6
7
  //
7
- // A message counts only from the parent window, of this origin and protocol. A command names the
8
+ // A workbench of another workspace shows a draft of this one from its own origin (docs/workbench.md
9
+ // "Drafts of other workspaces"), naming that origin in the frame's address (?shell=<origin>): the page
10
+ // then asks its own server whether that is a Gallery server of this computer (GET
11
+ // /__gallery/workspace/shell: on the registry, running, its token and process as it announces them),
12
+ // and talks to it alone once it is, holding what it says until then; one that is not hears nothing and
13
+ // is heard by nothing, so that no other page of this computer drives a document by framing it. Going,
14
+ // such a page says `bye` (the workbench of another origin cannot see it go).
15
+ //
16
+ // A message counts only from the parent window, of this origin (or the shell's, vouched for) and protocol. A command names the
8
17
  // report it is meant for: one for another report (the iframe went to another page meanwhile) is
9
18
  // refused. Every command gets exactly one reply, once it is done. Besides the editor's commands the
10
- // session itself answers four: `theme` (show the report light or dark, or as the reader chose, without
11
- // storing it), `keys` (key combinations to hand to the workbench when the page does not use them),
19
+ // session itself answers five: `theme` (show the report light or dark, or as the reader chose, without
20
+ // storing it), `look` (show the document in a look, 字体与布局: { look }, src/shared/document-look.mjs; the
21
+ // workbench writes it into doc.json), `keys` (key combinations to hand to the workbench when the page does not use them),
12
22
  // `scroll-top` (back to the top when scrolled down) and `close-card` (the detail card on top closes as a
13
23
  // press on its backdrop closes it: the workbench asks on a press on its own bars, or Esc there, while
14
- // the page says a card is open, `card` in what it sends).
24
+ // the page says a card is open, `card` in what it sends). A card stands in the middle of the
25
+ // workbench's window, not of the frame (centreCards, below). A block's 允许访问 (doc-net-consent, the kit's)
26
+ // is sent as `consent`.
15
27
 
16
28
  /** A page opened in a frame on its own (?solo), not as the workbench's report: no session, its own notices. */
17
29
  export const SOLO = new URLSearchParams(location.search).has("solo");
30
+ /** The origin of a workbench of another workspace showing this page (?shell=<origin>), or null: this one's. */
31
+ const SHELL = (() => {
32
+ const named = new URLSearchParams(location.search).get("shell");
33
+ return named && named !== location.origin ? named : null;
34
+ })();
35
+
36
+ // Whether this page's server vouches for the workbench at `origin` (GET /__gallery/workspace/shell).
37
+ const vouched = (origin) => fetch(`/__gallery/workspace/shell?origin=${encodeURIComponent(origin)}`, { cache: "no-store" })
38
+ .then((answer) => answer.json()).then((answer) => answer?.shell === true, () => false);
18
39
 
19
40
  /**
20
41
  * slug: the report's; snapshot(): { title, state } (state: STATE_FLAGS of src/shared/session.mjs);
@@ -34,11 +55,29 @@ export const SOLO = new URLSearchParams(location.search).has("solo");
34
55
  */
35
56
  export function connectWorkbench({ slug, snapshot, commands, modals }) {
36
57
  if (window.parent === window || SOLO) return null;
58
+ centreCards(modals);
59
+ // The workbench's origin: this one's, or the shell's once this page's server vouched for it (null till
60
+ // then: what the page says is held, and is dropped when it does not).
61
+ let parentOrigin = SHELL ? null : location.origin;
62
+ let held = SHELL ? [] : null;
63
+ if (SHELL) {
64
+ vouched(SHELL).then((ok) => {
65
+ const waiting = held;
66
+ held = null;
67
+ if (!ok) return;
68
+ parentOrigin = SHELL;
69
+ for (const [type, fields, protocols] of waiting) send(type, fields, protocols);
70
+ // A workbench of another origin sees no pagehide of this page: it is told.
71
+ addEventListener("pagehide", () => send("bye", {}), { once: true });
72
+ });
73
+ }
37
74
  // The id the workbench speaks (src/shared/session.mjs, OLD_PROTOCOL): null until its first command,
38
75
  // and meanwhile every message goes under both, so that a workbench of either version hears it.
39
76
  let spoken = null;
40
77
  const send = (type, fields, protocols = spoken ? [spoken] : [PROTOCOL, OLD_PROTOCOL]) => {
41
- for (const protocol of protocols) window.parent.postMessage({ protocol, v: VERSION, type, slug, ...fields }, location.origin);
78
+ if (held) return void held.push([type, fields, protocols]);
79
+ if (!parentOrigin) return;
80
+ for (const protocol of protocols) window.parent.postMessage({ protocol, v: VERSION, type, slug, ...fields }, parentOrigin);
42
81
  };
43
82
  let last = null;
44
83
  const update = () => {
@@ -60,12 +99,28 @@ export function connectWorkbench({ slug, snapshot, commands, modals }) {
60
99
  event.preventDefault();
61
100
  send("key", { key });
62
101
  });
102
+ // A block's card asks the reader to let it online (its 允许访问 button: the kit's net.js): the workbench
103
+ // opens its consent dialog, the one 设置 › 组件列表 opens, and writes what the reader says; the page
104
+ // hears it on its event stream, and the kit starts the instance again.
105
+ addEventListener("doc-net-consent", (event) => {
106
+ const { block, hosts } = event.detail ?? {};
107
+ if (typeof block !== "string") return;
108
+ event.preventDefault();
109
+ send("consent", { block, hosts: Array.isArray(hosts) ? hosts : [] });
110
+ });
63
111
  const own = {
64
112
  async theme({ theme = null }) {
65
113
  if (theme !== null && theme !== "light" && theme !== "dark") return { ok: false, reason: "theme" };
66
114
  dispatchEvent(new CustomEvent("doc-theme-request", { detail: { theme } })); // the kit's ui.js
67
115
  return { ok: true };
68
116
  },
117
+ // The document's look shown at once (the kit's ui.js puts it on <html> and lays out again), never
118
+ // stored here: the workbench writes doc.json. Answers with the look the page shows then.
119
+ async look({ look = null }) {
120
+ if (look !== null && (typeof look !== "object" || Array.isArray(look))) return { ok: false, reason: "look" };
121
+ dispatchEvent(new CustomEvent("doc-look-request", { detail: { look: lookOf(look) } }));
122
+ return { ok: true, look: lookOfElement(document.documentElement) };
123
+ },
69
124
  async keys({ keys: list }) {
70
125
  if (!Array.isArray(list) || !list.every((key) => typeof key === "string")) return { ok: false, reason: "keys" };
71
126
  keys = new Set(list);
@@ -86,7 +141,7 @@ export function connectWorkbench({ slug, snapshot, commands, modals }) {
86
141
 
87
142
  addEventListener("message", async (event) => {
88
143
  const message = event.data;
89
- if (event.source !== window.parent || event.origin !== location.origin) return;
144
+ if (event.source !== window.parent || !parentOrigin || event.origin !== parentOrigin) return;
90
145
  if (!PROTOCOLS.includes(message?.protocol) || message.v !== VERSION || message.type !== "command") return;
91
146
  spoken = message.protocol;
92
147
  const run = Object.hasOwn(all, message.name) ? all[message.name] : null;
@@ -115,3 +170,43 @@ export function connectWorkbench({ slug, snapshot, commands, modals }) {
115
170
  workspace: () => send("workspace", {}),
116
171
  };
117
172
  }
173
+
174
+ // A detail card stands in the middle of the workbench's window, as the workbench's own dialogs do
175
+ // (组件列表, 写作偏好), not in the middle of this frame right of its sidebar and under its top bar;
176
+ // the workbench covers its bars while the page says a card is open (`card`), the card's backdrop
177
+ // the rest. The kit's dialog.css puts the card's middle at --doc-dialog-centre-x and -y, as far as
178
+ // the frame lets it stay clear of its sides, and makes it 80% as high as --doc-dialog-window-height.
179
+ // They are read from the frame's place in the workbench's window (of this origin, as every message
180
+ // of the session is), and said in a sheet the document adopts, which is in no markup (a copy of the
181
+ // view, the file); again as the frame changes size (the window resized, the sidebar opened, closed or
182
+ // dragged wider) and as a card opens or closes.
183
+ function centreCards(modals) {
184
+ let sheet;
185
+ try {
186
+ sheet = new CSSStyleSheet();
187
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
188
+ } catch {
189
+ return; // a browser with no constructed sheets: the card in the middle of the frame
190
+ }
191
+ let said = null;
192
+ const place = () => {
193
+ let rule = "";
194
+ try {
195
+ const frame = window.frameElement;
196
+ const outer = frame?.ownerDocument.documentElement;
197
+ if (outer) {
198
+ const box = frame.getBoundingClientRect();
199
+ const style = frame.ownerDocument.defaultView.getComputedStyle(frame);
200
+ const left = box.left + frame.clientLeft + parseFloat(style.paddingLeft);
201
+ const top = box.top + frame.clientTop + parseFloat(style.paddingTop);
202
+ rule = `:root { --doc-dialog-centre-x: ${outer.clientWidth / 2 - left}px; --doc-dialog-centre-y: ${outer.clientHeight / 2 - top}px; --doc-dialog-window-height: ${outer.clientHeight}px; }`;
203
+ }
204
+ } catch { /* a frame of another origin's page, or one taken away: in the middle of the frame */ }
205
+ if (rule === said) return;
206
+ said = rule;
207
+ sheet.replaceSync(rule);
208
+ };
209
+ place();
210
+ addEventListener("resize", place);
211
+ modals.listen(place);
212
+ }
@@ -42,12 +42,12 @@ const INLINE = {
42
42
  };
43
43
 
44
44
  // Groups of the unfiltered menu: 基本区块, 高级区块 (media, code, tabs and formula blocks: what
45
- // holds more than text; the types' own `menu`, registry.mjs MENU_GROUPS), 组件 (what the variants
46
- // are now: the workspace's), and what is no block under 内联.
45
+ // holds more than text; the types' own `menu`, registry.mjs MENU_GROUPS), 自定义块 (what the variants
46
+ // are now: the workspace's custom blocks, plan §4.1's name for the group 组件 was), and what is no block under 内联.
47
47
  const SECTIONS = [
48
48
  { title: t("基本区块"), types: () => MENU_GROUPS.basic },
49
49
  { title: t("高级区块"), types: () => MENU_GROUPS.advanced },
50
- { title: t("组件@group"), types: variantKeys },
50
+ { title: t("自定义块"), types: variantKeys },
51
51
  ];
52
52
 
53
53
  const infoOf = (key) => INLINE[key] ?? menuRow(key);
@@ -2,7 +2,7 @@ import { belowControl, colorSection, colorSwatch, FORMAT_ICONS, formatLook, list
2
2
  import { HIGHLIGHTS, TEXT_COLORS } from "../marks.mjs";
3
3
  import { placeBox } from "../placement.mjs";
4
4
  import { hideTooltip, shortcut } from "../tooltip.mjs";
5
- import { element, fadeIn, fadeOut, mount } from "../ui.mjs";
5
+ import { addStyle, element, fadeIn, fadeOut, mount } from "../ui.mjs";
6
6
  import { alignItems } from "./aligns.mjs";
7
7
  import { TABLE_ICONS } from "./icons.mjs";
8
8
  import { t } from "../../../shared/i18n/index.mjs";
@@ -19,6 +19,8 @@ import { t } from "../../../shared/i18n/index.mjs";
19
19
  const APPEAR = 120;
20
20
  const PANEL = 120;
21
21
  const GAP = 8; // between the cells and the bar
22
+ // A cell's fill is a block's: its swatches and its "A" show --doc-fill, not the words' deeper fill the kit gives a span.
23
+ const STYLE = `.ge-cell-bar :is(.ge-ink-sample, .ge-swatch > span)[class*="doc-highlight-"] { background: var(--doc-fill); }`;
22
24
 
23
25
  /**
24
26
  * run(command, value): "color" with { kind: "text" | "background", color } (null: none), "bold", "align" with an
@@ -27,6 +29,7 @@ const GAP = 8; // between the cells and the bar
27
29
  */
28
30
  export function createCellBar(run) {
29
31
  formatLook();
32
+ addStyle(STYLE);
30
33
  const sample = element("span", { class: "ge-ink-sample", text: "A" });
31
34
  const tools = {
32
35
  color: tool("color", t("颜色"), sample, () => toggle("colors")),