@heycys/gallery 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. package/THIRD-PARTY-NOTICES.md +2 -2
  2. package/browser/editor/components/align.mjs +58 -0
  3. package/browser/editor/components/code/index.mjs +1 -1
  4. package/browser/editor/components/columns/page.mjs +4 -4
  5. package/browser/editor/components/embed/index.mjs +2 -2
  6. package/browser/editor/components/embed/page.mjs +1 -1
  7. package/browser/editor/components/file/page.mjs +4 -4
  8. package/browser/editor/components/flowchart/add.mjs +7 -6
  9. package/browser/editor/components/flowchart/page.mjs +1 -1
  10. package/browser/editor/components/heading/index.mjs +7 -6
  11. package/browser/editor/components/icons.mjs +11 -0
  12. package/browser/editor/components/image/crop.mjs +6 -9
  13. package/browser/editor/components/image/index.mjs +2 -0
  14. package/browser/editor/components/image/page.mjs +172 -90
  15. package/browser/editor/components/installed/index.mjs +15 -4
  16. package/browser/editor/components/installed/page.mjs +103 -25
  17. package/browser/editor/components/installed/served.mjs +6 -5
  18. package/browser/editor/components/instances.mjs +18 -0
  19. package/browser/editor/components/list/page.mjs +3 -6
  20. package/browser/editor/components/media/icons.mjs +13 -8
  21. package/browser/editor/components/media/page.mjs +5 -3
  22. package/browser/editor/components/media/toolbar.mjs +12 -3
  23. package/browser/editor/components/paragraph/index.mjs +4 -3
  24. package/browser/editor/components/registry.mjs +30 -9
  25. package/browser/editor/components/table/index.mjs +61 -2
  26. package/browser/editor/components/table/page.mjs +1 -1
  27. package/browser/editor/page/after/index.mjs +288 -0
  28. package/browser/editor/page/align.mjs +91 -0
  29. package/browser/editor/page/annotate/card.mjs +3 -6
  30. package/browser/editor/page/autosave.mjs +310 -37
  31. package/browser/editor/page/beside.mjs +5 -6
  32. package/browser/editor/page/block-menu/index.mjs +6 -3
  33. package/browser/editor/page/blocks.mjs +3 -1
  34. package/browser/editor/page/board/client.mjs +57 -0
  35. package/browser/editor/page/board/hint.mjs +182 -0
  36. package/browser/editor/page/board/history.mjs +119 -0
  37. package/browser/editor/page/board/index.mjs +1059 -0
  38. package/browser/editor/page/board/motion.mjs +177 -0
  39. package/browser/editor/page/board/settings.mjs +210 -0
  40. package/browser/editor/page/caret.mjs +1 -1
  41. package/browser/editor/page/changes/bar.mjs +6 -14
  42. package/browser/editor/page/changes/index.mjs +2 -2
  43. package/browser/editor/page/clipboard/import/html.mjs +29 -6
  44. package/browser/editor/page/clipboard/import/inline.mjs +32 -0
  45. package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
  46. package/browser/editor/page/clipboard/import/read.mjs +6 -1
  47. package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
  48. package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
  49. package/browser/editor/page/clipboard/index.mjs +133 -15
  50. package/browser/editor/page/clipboard/own/blocks.mjs +13 -14
  51. package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
  52. package/browser/editor/page/clipboard/own/describe.mjs +6 -2
  53. package/browser/editor/page/clipboard/own/selection.mjs +1 -1
  54. package/browser/editor/page/columns/index.mjs +48 -46
  55. package/browser/editor/page/commit.mjs +80 -22
  56. package/browser/editor/page/conflicts.mjs +7 -7
  57. package/browser/editor/page/core.mjs +34 -16
  58. package/browser/editor/page/custom-page.mjs +110 -0
  59. package/browser/editor/page/editor.mjs +71 -17
  60. package/browser/editor/page/emoji-picker/styles.mjs +7 -12
  61. package/browser/editor/page/emoji-picker/upload.mjs +2 -2
  62. package/browser/editor/page/handle/index.mjs +5 -8
  63. package/browser/editor/page/history.mjs +41 -6
  64. package/browser/editor/page/insert/index.mjs +20 -22
  65. package/browser/editor/page/links/index.mjs +5 -3
  66. package/browser/editor/page/links/pages.mjs +27 -9
  67. package/browser/editor/page/look.mjs +54 -3
  68. package/browser/editor/page/margin.mjs +18 -3
  69. package/browser/editor/page/media-menu/index.mjs +6 -7
  70. package/browser/editor/page/menu.mjs +33 -14
  71. package/browser/editor/page/notices.mjs +2 -2
  72. package/browser/editor/page/page-objects.mjs +9 -2
  73. package/browser/editor/page/panel.mjs +4 -9
  74. package/browser/editor/page/present-links.mjs +15 -5
  75. package/browser/editor/page/present-shell.mjs +63 -0
  76. package/browser/editor/page/resize/index.mjs +42 -29
  77. package/browser/editor/page/selection/index.mjs +10 -2
  78. package/browser/editor/page/served.mjs +14 -0
  79. package/browser/editor/page/session.mjs +48 -4
  80. package/browser/editor/page/slash-menu/index.mjs +3 -3
  81. package/browser/editor/page/table/binding.mjs +87 -0
  82. package/browser/editor/page/table/cells.mjs +102 -46
  83. package/browser/editor/page/table/index.mjs +24 -9
  84. package/browser/editor/page/table/pictures.mjs +299 -0
  85. package/browser/editor/page/table/views.mjs +103 -0
  86. package/browser/editor/page/table/widths.mjs +82 -10
  87. package/browser/editor/page/text-select/index.mjs +26 -12
  88. package/browser/editor/page/todo-writes.mjs +75 -0
  89. package/browser/editor/page/typing/index.mjs +97 -15
  90. package/browser/editor/page/typing/leave.mjs +19 -5
  91. package/browser/editor/page/ui.mjs +13 -0
  92. package/browser/shared/block-packs.mjs +419 -0
  93. package/browser/shared/board-places.mjs +224 -0
  94. package/browser/shared/card-size.mjs +59 -0
  95. package/browser/shared/colors.mjs +3 -2
  96. package/browser/shared/component-catalog.mjs +330 -46
  97. package/browser/shared/component-source.mjs +39 -0
  98. package/browser/shared/components/heading.mjs +2 -1
  99. package/browser/shared/components/index.mjs +12 -3
  100. package/browser/shared/components/installed.mjs +35 -3
  101. package/browser/shared/components/page.mjs +20 -8
  102. package/browser/shared/components/paragraph.mjs +8 -1
  103. package/browser/shared/components/state.mjs +5 -1
  104. package/browser/shared/components/table.mjs +1 -0
  105. package/browser/shared/document-look.mjs +10 -5
  106. package/browser/shared/drafts.mjs +432 -0
  107. package/browser/shared/emoji/line-icons.mjs +37 -0
  108. package/browser/shared/extension-sidebar.mjs +126 -0
  109. package/browser/shared/extensions.mjs +79 -0
  110. package/browser/shared/file-table.mjs +101 -0
  111. package/browser/shared/http.mjs +9 -0
  112. package/browser/shared/i18n/en.mjs +330 -27
  113. package/browser/shared/json-layout.mjs +47 -0
  114. package/browser/shared/net-cache.mjs +133 -0
  115. package/browser/shared/net-keys.mjs +32 -0
  116. package/browser/shared/net-policy.mjs +177 -0
  117. package/browser/shared/outline-shape.mjs +128 -0
  118. package/browser/shared/outline.mjs +359 -67
  119. package/browser/shared/pack-manifest.mjs +88 -0
  120. package/browser/shared/page-address.mjs +6 -3
  121. package/browser/shared/page-cards.mjs +308 -0
  122. package/browser/shared/page-links.mjs +69 -6
  123. package/browser/shared/pages.mjs +500 -0
  124. package/browser/shared/paths.mjs +6 -0
  125. package/browser/shared/pinyin.mjs +92 -0
  126. package/browser/shared/present-step.mjs +17 -0
  127. package/browser/shared/preview-server.mjs +3 -7
  128. package/browser/shared/session.mjs +8 -1
  129. package/browser/shared/shipped-blocks.mjs +299 -0
  130. package/browser/shared/sidebar-head.mjs +70 -0
  131. package/browser/shared/table-chart.mjs +33 -1
  132. package/browser/shared/todos.mjs +83 -0
  133. package/browser/shared/user-directory.mjs +24 -0
  134. package/browser/shared/versions.mjs +14 -0
  135. package/browser/shared/web-links.mjs +139 -0
  136. package/browser/shared/workspace-columns.mjs +120 -0
  137. package/browser/shared/workspace-name.mjs +154 -0
  138. package/browser/shared/workspace-query.mjs +125 -0
  139. package/browser/shared/workspace-registry.mjs +272 -0
  140. package/browser/shared/workspace.mjs +171 -20
  141. package/dist/chunk-2OHANJ6Q.mjs +2 -0
  142. package/dist/chunk-3MBRL2PM.mjs +16 -0
  143. package/dist/chunk-4OKWZY5E.mjs +2 -0
  144. package/dist/chunk-4OZWXZE5.mjs +5 -0
  145. package/dist/chunk-5K44HLTZ.mjs +2 -0
  146. package/dist/{chunk-5ZKJ3H4P.mjs → chunk-5XA2ZBAE.mjs} +3 -3
  147. package/dist/{chunk-4FS7Z7WR.mjs → chunk-67N2QJYT.mjs} +1 -1
  148. package/dist/chunk-6KBYRA2C.mjs +2 -0
  149. package/dist/chunk-6N3PX4XX.mjs +8 -0
  150. package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
  151. package/dist/chunk-7JDX4E65.mjs +13 -0
  152. package/dist/chunk-7M2BQQGZ.mjs +2 -0
  153. package/dist/chunk-7OG26PGF.mjs +2 -0
  154. package/dist/chunk-AHN3NFKJ.mjs +3 -0
  155. package/dist/chunk-ALZ6ZENZ.mjs +3 -0
  156. package/dist/chunk-AR5D57ZD.mjs +170 -0
  157. package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
  158. package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
  159. package/dist/chunk-CMA72MAG.mjs +2 -0
  160. package/dist/{chunk-LCTHTZIL.mjs → chunk-DAZL73VK.mjs} +91 -91
  161. package/dist/{chunk-Y6RLRPG3.mjs → chunk-DJISHPUL.mjs} +1 -1
  162. package/dist/chunk-DR73Y2UJ.mjs +3 -0
  163. package/dist/{chunk-FDLXYYG4.mjs → chunk-EAIFITAV.mjs} +1 -1
  164. package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
  165. package/dist/chunk-EP25HDAJ.mjs +2 -0
  166. package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
  167. package/dist/chunk-EURLTOTZ.mjs +4 -0
  168. package/dist/chunk-F4ZA6JRZ.mjs +3 -0
  169. package/dist/chunk-F6HVDZR4.mjs +2 -0
  170. package/dist/chunk-FDMAXMQA.mjs +2 -0
  171. package/dist/chunk-FETSREUN.mjs +5 -0
  172. package/dist/chunk-GHOYKMQ3.mjs +4 -0
  173. package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
  174. package/dist/chunk-HDWTZ763.mjs +12 -0
  175. package/dist/chunk-HPOI4ZX7.mjs +6 -0
  176. package/dist/{chunk-BGGDRNYQ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
  177. package/dist/chunk-IA4PSIMD.mjs +2 -0
  178. package/dist/{chunk-E7LWZRXY.mjs → chunk-ITOH5EGO.mjs} +1 -1
  179. package/dist/chunk-IV64FFI4.mjs +2 -0
  180. package/dist/chunk-J43Z6LSS.mjs +2 -0
  181. package/dist/chunk-J5PUIV3Y.mjs +4 -0
  182. package/dist/chunk-JA7G53PC.mjs +2 -0
  183. package/dist/chunk-JEUK3ZO7.mjs +2 -0
  184. package/dist/chunk-JLTZF4LA.mjs +2 -0
  185. package/dist/chunk-JZT7I2OJ.mjs +2 -0
  186. package/dist/chunk-K5XATEOO.mjs +2 -0
  187. package/dist/chunk-L2SUIS5S.mjs +2 -0
  188. package/dist/chunk-L7UP52JO.mjs +2 -0
  189. package/dist/chunk-LM4XFQHZ.mjs +2 -0
  190. package/dist/chunk-MN7BZL4R.mjs +2 -0
  191. package/dist/chunk-MTYYHM2G.mjs +15 -0
  192. package/dist/chunk-MXUBKDRO.mjs +15 -0
  193. package/dist/chunk-NAMN3RAF.mjs +2 -0
  194. package/dist/{chunk-SYGN7GLU.mjs → chunk-OEXWRJME.mjs} +1 -1
  195. package/dist/chunk-OFHXGWOX.mjs +2 -0
  196. package/dist/chunk-ORID3AE7.mjs +166 -0
  197. package/dist/chunk-PAREWQGB.mjs +4 -0
  198. package/dist/chunk-PGDE24N5.mjs +2 -0
  199. package/dist/chunk-POTA2FV4.mjs +2 -0
  200. package/dist/chunk-PUOQ65NC.mjs +2 -0
  201. package/dist/chunk-Q4UEPUWF.mjs +2 -0
  202. package/dist/chunk-QE5RG76S.mjs +549 -0
  203. package/dist/chunk-R2ZDLJYT.mjs +10 -0
  204. package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
  205. package/dist/chunk-SWUTTZCN.mjs +2 -0
  206. package/dist/chunk-TANZRINB.mjs +2 -0
  207. package/dist/chunk-TR7TWGHB.mjs +2 -0
  208. package/dist/chunk-U5XL7D6A.mjs +3 -0
  209. package/dist/{chunk-XNROSH2T.mjs → chunk-U7NZI6N4.mjs} +2 -2
  210. package/dist/chunk-UGWMMEJ5.mjs +15 -0
  211. package/dist/chunk-UJQJKNGK.mjs +2 -0
  212. package/dist/chunk-UYVCQK3H.mjs +22 -0
  213. package/dist/chunk-VFX2KNHP.mjs +4 -0
  214. package/dist/chunk-VS7JIGJW.mjs +24 -0
  215. package/dist/chunk-W7665ZEC.mjs +6 -0
  216. package/dist/chunk-WQDQWCX5.mjs +2 -0
  217. package/dist/chunk-YI43RG4P.mjs +2 -0
  218. package/dist/chunk-YLPSMDIS.mjs +5 -0
  219. package/dist/chunk-YNAWBAYN.mjs +3 -0
  220. package/dist/chunk-YROX2O22.mjs +2 -0
  221. package/dist/chunk-ZDLPUOAG.mjs +6 -0
  222. package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
  223. package/dist/chunk-ZQS6H473.mjs +16 -0
  224. package/dist/chunk-ZTHICSSF.mjs +2 -0
  225. package/dist/chunk-ZWWC4KLF.mjs +20 -0
  226. package/dist/cli.mjs +1 -1
  227. package/dist/server.mjs +1 -1
  228. package/dist/{chunk-U6KNPJPR.mjs → update-fetch.mjs} +1 -1
  229. package/dist/worker.mjs +1 -1
  230. package/kit/board.css +95 -0
  231. package/kit/board.js +250 -0
  232. package/kit/charts.js +5 -71
  233. package/kit/code.js +17 -17
  234. package/kit/report.css +335 -18
  235. package/kit/runtime.js +1638 -125
  236. package/kit/state.js +10 -1
  237. package/kit/tables.js +130 -43
  238. package/kit/ui.js +79 -35
  239. package/package.json +2 -1
  240. package/packs/gallery/card/component.json +14 -0
  241. package/packs/gallery/card/example.html +10 -0
  242. package/packs/gallery/card/preview.svg +1 -0
  243. package/packs/gallery/card/style.css +6 -0
  244. package/packs/gallery/card/template.html +6 -0
  245. package/packs/gallery/card/writing.md +14 -0
  246. package/packs/gallery/chart-card/component.json +15 -0
  247. package/packs/gallery/chart-card/example.html +14 -0
  248. package/packs/gallery/chart-card/kit.js +130 -0
  249. package/packs/gallery/chart-card/preview.svg +1 -0
  250. package/packs/gallery/chart-card/style.css +42 -0
  251. package/packs/gallery/chart-card/template.html +13 -0
  252. package/packs/gallery/chart-card/writing.md +20 -0
  253. package/packs/gallery/chart-view/component.json +20 -0
  254. package/packs/gallery/chart-view/example.html +13 -0
  255. package/packs/gallery/chart-view/kit.js +355 -0
  256. package/packs/gallery/chart-view/preview.svg +1 -0
  257. package/packs/gallery/chart-view/style.css +94 -0
  258. package/packs/gallery/chart-view/template.html +3 -0
  259. package/packs/gallery/chart-view/writing.md +22 -0
  260. package/packs/gallery/countdown/component.json +18 -0
  261. package/packs/gallery/countdown/example.html +3 -0
  262. package/packs/gallery/countdown/kit.js +216 -0
  263. package/packs/gallery/countdown/preview.svg +1 -0
  264. package/packs/gallery/countdown/style.css +118 -0
  265. package/packs/gallery/countdown/template.html +3 -0
  266. package/packs/gallery/countdown/writing.md +22 -0
  267. package/packs/gallery/habit/component.json +14 -0
  268. package/packs/gallery/habit/example.html +3 -0
  269. package/packs/gallery/habit/kit.js +334 -0
  270. package/packs/gallery/habit/preview.svg +1 -0
  271. package/packs/gallery/habit/style.css +174 -0
  272. package/packs/gallery/habit/template.html +3 -0
  273. package/packs/gallery/habit/writing.md +21 -0
  274. package/packs/gallery/heatmap/component.json +18 -0
  275. package/packs/gallery/heatmap/example.html +3 -0
  276. package/packs/gallery/heatmap/kit.js +513 -0
  277. package/packs/gallery/heatmap/preview.svg +1 -0
  278. package/packs/gallery/heatmap/style.css +189 -0
  279. package/packs/gallery/heatmap/template.html +3 -0
  280. package/packs/gallery/heatmap/writing.md +21 -0
  281. package/packs/gallery/kanban/component.json +18 -0
  282. package/packs/gallery/kanban/example.html +12 -0
  283. package/packs/gallery/kanban/kit.js +540 -0
  284. package/packs/gallery/kanban/preview.svg +1 -0
  285. package/packs/gallery/kanban/style.css +212 -0
  286. package/packs/gallery/kanban/template.html +3 -0
  287. package/packs/gallery/kanban/writing.md +20 -0
  288. package/packs/gallery/metric/component.json +22 -0
  289. package/packs/gallery/metric/example.html +15 -0
  290. package/packs/gallery/metric/kit.js +248 -0
  291. package/packs/gallery/metric/preview.svg +1 -0
  292. package/packs/gallery/metric/style.css +92 -0
  293. package/packs/gallery/metric/template.html +3 -0
  294. package/packs/gallery/metric/writing.md +23 -0
  295. package/packs/gallery/note/component.json +14 -0
  296. package/packs/gallery/note/example.html +3 -0
  297. package/packs/gallery/note/kit.js +129 -0
  298. package/packs/gallery/note/preview.svg +1 -0
  299. package/packs/gallery/note/style.css +97 -0
  300. package/packs/gallery/note/template.html +3 -0
  301. package/packs/gallery/note/writing.md +18 -0
  302. package/packs/gallery/pack.json +8 -0
  303. package/packs/gallery/recent/component.json +13 -0
  304. package/packs/gallery/recent/example.html +1 -0
  305. package/packs/gallery/recent/kit.js +293 -0
  306. package/packs/gallery/recent/preview.svg +1 -0
  307. package/packs/gallery/recent/style.css +85 -0
  308. package/packs/gallery/recent/template.html +1 -0
  309. package/packs/gallery/recent/writing.md +15 -0
  310. package/packs/gallery/static/component.json +13 -0
  311. package/packs/gallery/static/example.html +11 -0
  312. package/packs/gallery/static/preview.svg +1 -0
  313. package/packs/gallery/static/style.css +171 -0
  314. package/packs/gallery/static/template.html +1 -0
  315. package/packs/gallery/static/writing.md +18 -0
  316. package/packs/gallery/stats/component.json +13 -0
  317. package/packs/gallery/stats/example.html +1 -0
  318. package/packs/gallery/stats/kit.js +347 -0
  319. package/packs/gallery/stats/preview.svg +1 -0
  320. package/packs/gallery/stats/style.css +73 -0
  321. package/packs/gallery/stats/template.html +1 -0
  322. package/packs/gallery/stats/writing.md +11 -0
  323. package/packs/gallery/today/component.json +12 -0
  324. package/packs/gallery/today/example.html +1 -0
  325. package/packs/gallery/today/kit.js +220 -0
  326. package/packs/gallery/today/preview.svg +1 -0
  327. package/packs/gallery/today/style.css +149 -0
  328. package/packs/gallery/today/template.html +1 -0
  329. package/packs/gallery/today/writing.md +14 -0
  330. package/packs/gallery/todos/component.json +19 -0
  331. package/packs/gallery/todos/example.html +3 -0
  332. package/packs/gallery/todos/kit.js +489 -0
  333. package/packs/gallery/todos/preview.svg +1 -0
  334. package/packs/gallery/todos/style.css +214 -0
  335. package/packs/gallery/todos/template.html +3 -0
  336. package/packs/gallery/todos/writing.md +30 -0
  337. package/packs/gallery/weather/component.json +19 -0
  338. package/packs/gallery/weather/example.html +3 -0
  339. package/packs/gallery/weather/kit.js +387 -0
  340. package/packs/gallery/weather/preview.svg +1 -0
  341. package/packs/gallery/weather/style.css +140 -0
  342. package/packs/gallery/weather/template.html +3 -0
  343. package/packs/gallery/weather/writing.md +26 -0
  344. package/packs/gallery-soft/countdown/component.json +18 -0
  345. package/packs/gallery-soft/countdown/example.html +3 -0
  346. package/packs/gallery-soft/countdown/kit.js +206 -0
  347. package/packs/gallery-soft/countdown/preview.svg +1 -0
  348. package/packs/gallery-soft/countdown/style.css +211 -0
  349. package/packs/gallery-soft/countdown/template.html +3 -0
  350. package/packs/gallery-soft/countdown/writing.md +24 -0
  351. package/packs/gallery-soft/habit/component.json +14 -0
  352. package/packs/gallery-soft/habit/example.html +3 -0
  353. package/packs/gallery-soft/habit/kit.js +366 -0
  354. package/packs/gallery-soft/habit/preview.svg +1 -0
  355. package/packs/gallery-soft/habit/style.css +251 -0
  356. package/packs/gallery-soft/habit/template.html +3 -0
  357. package/packs/gallery-soft/habit/writing.md +23 -0
  358. package/packs/gallery-soft/heatmap/component.json +18 -0
  359. package/packs/gallery-soft/heatmap/example.html +3 -0
  360. package/packs/gallery-soft/heatmap/kit.js +498 -0
  361. package/packs/gallery-soft/heatmap/preview.svg +1 -0
  362. package/packs/gallery-soft/heatmap/style.css +181 -0
  363. package/packs/gallery-soft/heatmap/template.html +3 -0
  364. package/packs/gallery-soft/heatmap/writing.md +23 -0
  365. package/packs/gallery-soft/note/component.json +14 -0
  366. package/packs/gallery-soft/note/example.html +3 -0
  367. package/packs/gallery-soft/note/kit.js +162 -0
  368. package/packs/gallery-soft/note/preview.svg +1 -0
  369. package/packs/gallery-soft/note/style.css +148 -0
  370. package/packs/gallery-soft/note/template.html +3 -0
  371. package/packs/gallery-soft/note/writing.md +20 -0
  372. package/packs/gallery-soft/pack.json +8 -0
  373. package/packs/gallery-soft/recent/component.json +13 -0
  374. package/packs/gallery-soft/recent/example.html +1 -0
  375. package/packs/gallery-soft/recent/kit.js +335 -0
  376. package/packs/gallery-soft/recent/preview.svg +1 -0
  377. package/packs/gallery-soft/recent/style.css +160 -0
  378. package/packs/gallery-soft/recent/template.html +1 -0
  379. package/packs/gallery-soft/recent/writing.md +17 -0
  380. package/packs/gallery-soft/static/component.json +13 -0
  381. package/packs/gallery-soft/static/example.html +12 -0
  382. package/packs/gallery-soft/static/preview.svg +1 -0
  383. package/packs/gallery-soft/static/style.css +186 -0
  384. package/packs/gallery-soft/static/template.html +1 -0
  385. package/packs/gallery-soft/static/writing.md +20 -0
  386. package/packs/gallery-soft/stats/component.json +13 -0
  387. package/packs/gallery-soft/stats/example.html +1 -0
  388. package/packs/gallery-soft/stats/kit.js +341 -0
  389. package/packs/gallery-soft/stats/preview.svg +1 -0
  390. package/packs/gallery-soft/stats/style.css +119 -0
  391. package/packs/gallery-soft/stats/template.html +1 -0
  392. package/packs/gallery-soft/stats/writing.md +13 -0
  393. package/packs/gallery-soft/today/component.json +12 -0
  394. package/packs/gallery-soft/today/example.html +1 -0
  395. package/packs/gallery-soft/today/kit.js +222 -0
  396. package/packs/gallery-soft/today/preview.svg +1 -0
  397. package/packs/gallery-soft/today/style.css +178 -0
  398. package/packs/gallery-soft/today/template.html +1 -0
  399. package/packs/gallery-soft/today/writing.md +16 -0
  400. package/packs/gallery-soft/todos/component.json +19 -0
  401. package/packs/gallery-soft/todos/example.html +3 -0
  402. package/packs/gallery-soft/todos/kit.js +527 -0
  403. package/packs/gallery-soft/todos/preview.svg +1 -0
  404. package/packs/gallery-soft/todos/style.css +212 -0
  405. package/packs/gallery-soft/todos/template.html +3 -0
  406. package/packs/gallery-soft/todos/writing.md +32 -0
  407. package/packs/gallery-soft/weather/component.json +19 -0
  408. package/packs/gallery-soft/weather/example.html +3 -0
  409. package/packs/gallery-soft/weather/kit.js +411 -0
  410. package/packs/gallery-soft/weather/preview.svg +1 -0
  411. package/packs/gallery-soft/weather/style.css +185 -0
  412. package/packs/gallery-soft/weather/template.html +3 -0
  413. package/packs/gallery-soft/weather/writing.md +28 -0
  414. package/release.json +12 -10
  415. package/sdk/doc-kit.d.ts +396 -5
  416. package/sdk/doc-state.d.ts +2 -0
  417. package/skill/SKILL.md +56 -23
  418. package/skill/references/block-script.md +140 -0
  419. package/skill/references/building-blocks.md +257 -0
  420. package/skill/references/extensions.md +59 -0
  421. package/skill/references/pages-and-data.md +225 -0
  422. package/skill/references/writing-html.md +8 -4
  423. package/skill/sdk/doc-kit.d.ts +396 -5
  424. package/skill/sdk/doc-state.d.ts +2 -0
  425. package/web/assets/index-BM_K-Auu.css +1 -0
  426. package/web/assets/index-DRslOBiv.js +15 -0
  427. package/web/index.html +2 -2
  428. package/dist/chunk-3HIRPVLU.mjs +0 -2
  429. package/dist/chunk-5MHMDLZD.mjs +0 -4
  430. package/dist/chunk-64K7IPLO.mjs +0 -255
  431. package/dist/chunk-6QXGZM36.mjs +0 -8
  432. package/dist/chunk-6RGJOMJP.mjs +0 -16
  433. package/dist/chunk-AJ73XJF3.mjs +0 -2
  434. package/dist/chunk-AUZGSZJH.mjs +0 -13
  435. package/dist/chunk-BFE45AKL.mjs +0 -2
  436. package/dist/chunk-BXO2ZY5P.mjs +0 -2
  437. package/dist/chunk-CEH4MRCC.mjs +0 -2
  438. package/dist/chunk-CY2FNNAB.mjs +0 -16
  439. package/dist/chunk-DFUDV4LX.mjs +0 -2
  440. package/dist/chunk-DKXG4XDG.mjs +0 -2
  441. package/dist/chunk-EZQ34M3F.mjs +0 -124
  442. package/dist/chunk-EZY3WC6Z.mjs +0 -15
  443. package/dist/chunk-FUKQNOQS.mjs +0 -9
  444. package/dist/chunk-JPOSLGOC.mjs +0 -6
  445. package/dist/chunk-JVHHHGEA.mjs +0 -3
  446. package/dist/chunk-L3QKH4OK.mjs +0 -26
  447. package/dist/chunk-LAE5NQ4B.mjs +0 -2
  448. package/dist/chunk-LEF6DRCK.mjs +0 -59
  449. package/dist/chunk-NO5NJCHO.mjs +0 -2
  450. package/dist/chunk-NQPVAU63.mjs +0 -2
  451. package/dist/chunk-NSKUTQ5J.mjs +0 -5
  452. package/dist/chunk-O35FIXRB.mjs +0 -2
  453. package/dist/chunk-P2CAZPDP.mjs +0 -3
  454. package/dist/chunk-PL6GHLGD.mjs +0 -15
  455. package/dist/chunk-QJIR2BLP.mjs +0 -6
  456. package/dist/chunk-QUPLVPB2.mjs +0 -7
  457. package/dist/chunk-R7BNENLY.mjs +0 -4
  458. package/dist/chunk-S6O4UHLC.mjs +0 -2
  459. package/dist/chunk-SGJWQKEI.mjs +0 -2
  460. package/dist/chunk-TX6JH7TR.mjs +0 -2
  461. package/dist/chunk-TYK6VNAB.mjs +0 -10
  462. package/dist/chunk-UALRNVSE.mjs +0 -4
  463. package/dist/chunk-V3HXVQEM.mjs +0 -2
  464. package/dist/chunk-V5VXUJKG.mjs +0 -2
  465. package/dist/chunk-VBXMADMP.mjs +0 -2
  466. package/dist/chunk-VNV55RUA.mjs +0 -2
  467. package/dist/chunk-VPD2PS35.mjs +0 -2
  468. package/dist/chunk-W4VKN3GF.mjs +0 -7
  469. package/dist/chunk-W5BXXPDJ.mjs +0 -3
  470. package/dist/chunk-XUNHRCOG.mjs +0 -6
  471. package/skill/references/building-components.md +0 -367
  472. package/web/assets/index-Bh74DfsV.css +0 -1
  473. package/web/assets/index-UW0RyFFt.js +0 -13
@@ -0,0 +1,225 @@
1
+ # Custom pages, and what a block reads beyond its own parts
2
+
3
+ A block stands in a document, on a custom page (自定义页: a page of the user's that you design, a board of cards being one way to write it; SKILL.md, Custom pages, is the flow on a page) or in both. [building-blocks.md](building-blocks.md) is the block itself (the kinds of part, the files, the manifest, an instance, its style, and the two places side by side in A document and a custom page) and [block-script.md](block-script.md) is its script. This page holds what only some blocks need: the manifest fields that place a block, size it as a card and give it settings; the flow of a block made for a page; and the three things a block may read beyond its own parts, each a `needs` entry: the workspace's data (`workspace`), a table of its document (`tables`) and the web (`net:<host>`).
4
+
5
+ ## A page is yours to design
6
+
7
+ A custom page's `page.html` is written as the request wants it: any HTML, CSS and script of your own, a board of cards, or both on one page. A board is what the user rearranges: its cards are moved, resized, added and deleted on the page, and what a card holds (a block's parts) is the user's to change; what the page's own HTML and script show, only you change. Write it inside `<main class="gallery-page">` (the page then follows the workbench's theme: its dark colors under `:root[data-doc-effective-theme="dark"]`), and its own files (a picture, a stylesheet, a script) in `pages/<slug>/assets/`, written `assets/<file>`. `gallery page check` takes a page's own scripts and stylesheets as they are, and fails what still matters: a board's cards where it has them, a file of `assets/` that is not there, a page that throws or does not load. A blank page the user made in the sidebar (新建页面: its slug `page-…`, an empty `<main class="gallery-page">`, which shows the user to ask an Agent) is one to write whole.
8
+
9
+ ## Places, cards, settings and needs
10
+
11
+ A block stands in a document's flow, or as a card on a custom page's board (自定义页: a page of the workspace's own, its board laid out on a grid of square cells, twelve to a row), or both: one block, one manifest and one `context` for either. Four fields of the manifest say how; each may be left out.
12
+
13
+ ```json
14
+ {
15
+ "places": ["page", "document"],
16
+ "card": { "sizes": [[2, 2], [4, 2], [4, 4]], "resize": true, "fit": "fixed", "bare": false },
17
+ "settings": [
18
+ { "key": "city", "label": { "zh": "城市", "en": "City" }, "type": "text", "default": "上海" },
19
+ { "key": "unit", "label": { "zh": "单位", "en": "Unit" }, "type": "select", "options": ["℃", "℉"], "default": "℃" }
20
+ ],
21
+ "needs": ["workspace", "net:api.open-meteo.com"]
22
+ }
23
+ ```
24
+
25
+ | Field | What it holds |
26
+ | --- | --- |
27
+ | `places` | `"document"`, `"page"` or both, each once: `["document"]` when left out. A block of a page's alone is in no document's menu until the user switches it on (设置 › 组件列表, 在文档菜单里显示); a custom page lists only blocks whose places hold `page` and that the user has not switched off (the master switch at the right of a block's line in 设置 › 组件列表 takes it out of every menu and of that list; what is written of it keeps showing, and `gallery page add` still names it), and a card of one whose places do not, written on a page all the same, says so there and does not run |
28
+ | `card` | its size on a board, in cells: `sizes`, the sizes the user picks from, `[w, h]` each, 1 to 12 wide and 1 to 24 high, the first the default (a phone's small, medium and large widget; the card's 大小 menu lists them, and dragging its corner snaps to the nearest, so a block that takes any size of the board's cells writes `min` and `max` beside them, `"min": { "w": 1, "h": 1 }, "max": { "w": 12, "h": 24 }`: the sizes then only the common ones the menu lists, each inside `min` and `max`); or, with no `sizes`, `w` (4 when left out) and `h` (the fewest whole cells its content takes when left out), with `min` and `max` as `{ w, h }`, which hold the default between them. `resize`: whether the user may drag its edge (false when left out); `fit`: `"fixed"` (the default: what does not fit scrolls in the card) or `"content"` (the card grows with what it holds and pushes the cards under it down, for a list that changes length); `bare`: true for no frame of the board's around it; `consent`: for a block online, the line Gallery's consent banner on its card says, `{ "zh": "允许联网之后显示汇率", "en": "Allow internet access to show the rates" }` (what the user gets once they allow it; left out, 允许联网之后显示内容). With `sizes` and `"content"` together the width is the size the user picked, and the height is the content's, in whole cells, drawn and never written: a size's `h` is only the `data-h` the file holds, where `gallery page add` and the page's service put the card and what stands beside it, so write the cells its content takes at a usual length; a longer content is drawn higher and pushes the cards under it down, a shorter one is drawn lower and leaves its room empty. Read only where its places hold `page` |
29
+ | `settings` | the fields of the card's form (its menu's 设置…), each `{ key, label: { zh, en }, type, options, default, required }`: `key` a lowercase letter then letters and digits, each once; `type` one of `text`, `number`, `select` (with `options`, a list of words), `date` (`YYYY-MM-DD`), `switch`, `document` (a document's slug); `default` of that type; `required: true` for a setting the card cannot show anything without (weather's city: a card with none asks the reader for it, and `gallery page check` notes it). A block with settings has a part named `settings`, edited as data, a `<script type="application/json">` holding their values by key, which its `template.html` holds as a new card's (`{}` takes each default), and reads them with `context.readJSON("settings")` |
30
+ | `needs` | what it uses, each once: `workspace` (the workspace's data: its to-dos, recent documents, counts, edits by day, a table of another document: The workspace's data, below), `tables` (it is a view of a table of its document: A view of a table, below), `net:<host>` (the network, of that host alone: a lowercase host name, no port and no path, `*.` first for the names under it, never the name itself; the user consents first: Going online, below). 设置 › 组件列表 shows them |
31
+
32
+ A cell is 64px square whatever the window, 16px from the next, so a card `w` cells wide is `w × 64 + (w − 1) × 16` px (4 cells: 304px; 12: 944px, the board's whole row, in the middle of the page) and as high by `h`; the frame's 16px padding comes off that for the block (a 4 × 2 card holds 272 × 112 px; the frame's line is a ring outside it). A wider window or the sidebar folded only leaves more room beside the board. A narrower one (the sidebar dragged wide, a small window) shows fewer columns, as many as fit, 4 at the least: the cards one after another in the order of their places, each as large as it is but no wider than the row (`context.size.w` says it, on `layout`), never written; the page's file keeps its twelve-column places. So size a card for the content at 64px cells, and take a big number or a long list's room from its cells, never from the window.
33
+
34
+ What a reader edits in each place is in [Which kind of part](building-blocks.md#which-kind-of-part) and [A document and a custom page](building-blocks.md#a-document-and-a-custom-page). So a block for a custom page keeps what a reader changes in a data part, with a field of its own or the card's settings, and no slot. On a page each `context.edit` is written at once, a step of the page's own undo (Ctrl+Z there takes it back, and the part with it); one made after someone else changed the same card is refused and the page shown again as the file is, so the block draws from what its parts hold (`source`), never from what it wrote last. `gallery block check` refuses a slot on such a block, notes each of its text parts (read-only on a custom page), notes a `card` on a block whose places hold no page, and fails a block with settings whose template holds no JSON object in its settings part. A field the manifest gets wrong (a place it does not know, a size off the grid, a setting's type or default, a need it does not know) keeps the block from loading, and `gallery block list` says why.
35
+
36
+ ## A block for a custom page
37
+
38
+ Gallery's own blocks in a workspace (`components/gallery/<name>/`) follow Gallery: a copy as it was added is brought up to a newer Gallery's by itself, as the workspace's server starts or reads its blocks, so change no file of one (a copy someone changed stays at its version, Gallery's newer one not put over it); for a card like one of them, start your own from it with `gallery block new <id> --recipe <name>`.
39
+
40
+ Make one only where no block of Gallery's does the job and the card does something or keeps data the user changes: a card that only shows what you write is `gallery/static` (SKILL.md, Custom pages; a heading it starts with, where more follows, is drawn as the cards' head row). The flow is [the one of building-blocks.md](building-blocks.md#the-flow), with the page in place of the document:
41
+
42
+ 1. `gallery page list` and `gallery block list`, then `gallery block new <id> --page` (with `--data` for a card that keeps what a reader enters, as the goals card below: its field, its buttons and an `example()` that works on an empty card), its places `["page"]` already (and `"document"` too only when a document may hold it).
43
+ 2. Its files: the manifest with `card` and, where the user sets something per card, `settings`; `template.html` holding a new card's data, the settings part `{}`; `kit.js` drawing from the parts on `source`, writing them by `context.edit` or `context.editJSON`, and reading its size on `layout` (`context.size`, the card's cells and pixels: lay a small card out otherwise than a big one). What a reader types goes through a field the block draws (`DocKit.input`: Enter or leaving it commits, never while an input method composes), never a text part, which a page shows read-only; no slot (a page holds no document's blocks: the check refuses one). Then `gallery block check <id>` until it prints `OK`.
44
+ 3. `gallery page add <slug> <id>` puts a card of it on the page, at the first free spot by its default size, and prints its `data-card-id`. Where the card has settings the user or the request names (a city, an owner), give them with the add: `--set <key>=<value>` for each (`gallery page add home local/goals --set title=本周目标`; no JSON to quote, so no quoting for a shell to take out, and each value held to its setting's type before anything is written). One it cannot show anything without, marked `required: true` in the manifest, left out, the add says so after the card and `gallery page check` notes it: ask the user, or take it from what the workspace says (写作偏好 where it names them, the documents) and tell them in the handoff which you did. A card already on the page takes its setting by a hand edit of its settings part, in the card's own `<script type="application/json">`, `{"title":"…"}` as the block's writing.md shows, the page re-read right before and that part alone changed; the user has the card's grip (top right) › 设置….
45
+ 4. `gallery page try <slug> <card id> <gesture>` for each gesture a reader makes on it (`--press`, `--drag … --to`, `--key`, `--type`, `--select`, `--then` and `--steps`, as `gallery block try` takes them, on a scratch copy of the page): its `Wrote:` lines name the card's data parts and say `nothing else in page.html changed (card ids aside)`; a write anywhere else, the card's place or another card, fails. Then the page's own undo (Ctrl+Z) gives the copy back, and a fresh page reads the card back as it was. A setting is the card's menu's 设置…, which the block only reads: its way back needs no trial.
46
+ 5. `gallery page check <slug>`, until it prints `OK`, then open its pictures (1280, 1920 and 600px wide, light and dark): a card whose content does not fit it scrolls inside it, which the check fails; give it the cells it needs, or `"fit": "content"` for one whose length changes (the check pictures the card as the file's data fills it now, a new card's, so a list that grows is seen long by trying a gesture on it that adds entries, or by filling it as the user will). A card that reads the workspace (Gallery's `todos`, `recent`, `stats`, `heatmap`, or your own block that reads `context.workspace`) is pictured once the workspace has answered, for up to 15 seconds; one still unanswered is a `note page.html:<line>: card <id> (<block>): the workspace had not answered its read of …` line, and the `OK` line then ends `; but N cards were pictured before the workspace answered it (see "note" above), so their pictures do not show what they read`. Such a picture says nothing of what the card shows: open the page in Gallery to see it, or run the check again.
47
+
48
+ Its look: the kit's card tokens, as Gallery's own cards draw theirs, so that it sits among them in both themes. Its type is `--gallery-font`, 13px. A head 20px high of a chip (`--gallery-chip-size` square, `--gallery-chip-radius`, `--gallery-fill` behind an icon of lines in `--gallery-muted`, `--gallery-chip-icon` wide) and a title (`--gallery-title-size`, 600, `--gallery-text`), a quiet meta right after it where the card has a few words to say of itself (`--gallery-meta-size`, `--gallery-faint`: 共 24 天, 今天 3 篇), 8px apart, the row one line, its end kept clear of the card's grip, which the board puts in the card's top-right corner (`padding-inline-end: var(--gallery-grip-room, 0px)` on its first row); one hero, a big number at `--gallery-numeral-weight` and `--gallery-numeral-tracking` in `--gallery-text-strong` (`--gallery-hero-size` for the card's one main number, `--gallery-figure-size` for one among others), its unit after it at `--gallery-unit` (13px), 3px from it, in `--gallery-muted`; labels in `--gallery-muted`, captions in `--gallery-faint`, lines `--gallery-hair`; the accent for a ring or a bar toward a target (on `--gallery-track`), green and red (`--gallery-good`, `--gallery-bad`, their `-soft` for a pill) only for a good or a bad state; `--gallery-face-gap` between rows; what the card is about in the middle of the room under its head at every size (a foot, a date or a week, at the bottom); the pieces of a meta line a muted 3px dot apart. With nothing to show yet, the cards' empty face under its head: a line of what is so (13.5px, 600) over what to do (12px, `--gallery-faint`), and one pale button where the reader can do it. The frame is the board's: draw no border, fill or shadow of the card's own. A button has no line: a primary one pale (`--gallery-accent-soft`, its words in `--gallery-accent-ink`), the others no fill until the pointer is on them (`--gallery-hover`).
49
+
50
+ A goals card, its title a setting and its goals a script of data, a field adding one and a box ticking one off:
51
+
52
+ ```json
53
+ {
54
+ "id": "local/goals",
55
+ "apiVersion": 1,
56
+ "version": "1.0.0",
57
+ "name": { "zh": "本周目标", "en": "This week's goals" },
58
+ "description": { "zh": "几个目标,在卡片上加,做完打勾", "en": "A few goals, added on the card and ticked when done" },
59
+ "words": "benzhoumubiao mubiao goals week 目标",
60
+ "parts": {
61
+ "goals": { "at": ":scope > script.goals-data", "edit": "data" },
62
+ "settings": { "at": ":scope > script.goals-settings", "edit": "data" }
63
+ },
64
+ "runtime": { "generated": [":scope > .goals-title", ":scope > .goals-list", ":scope > .goals-new"] },
65
+ "places": ["page"],
66
+ "card": { "sizes": [[4, 3], [2, 3], [4, 4]], "resize": true },
67
+ "settings": [{ "key": "title", "label": { "zh": "标题", "en": "Title" }, "type": "text", "default": "本周目标" }]
68
+ }
69
+ ```
70
+
71
+ <!-- the file holds -->
72
+ ```html
73
+ <div data-doc-component="local/goals">
74
+ <script type="application/json" class="goals-data">{"items":[]}</script>
75
+ <script type="application/json" class="goals-settings">{}</script>
76
+ </div>
77
+ ```
78
+
79
+ ```js
80
+ DocKit.component({
81
+ id: "local/goals",
82
+ on: ["source", "editable", "layout"],
83
+ mount(host, context) {
84
+ const title = document.createElement("h3");
85
+ title.className = "goals-title";
86
+ const list = document.createElement("ul");
87
+ list.className = "goals-list";
88
+ const field = document.createElement("input");
89
+ field.className = "goals-new";
90
+ field.placeholder = "加一个目标";
91
+ host.append(title, list, field);
92
+ const typed = DocKit.input(field, {
93
+ signal: context.signal,
94
+ commit(value) {
95
+ if (!value.trim()) return;
96
+ context.editJSON("goals", (data) => { data.items.push({ text: value.trim(), done: false }); });
97
+ typed.set("");
98
+ },
99
+ });
100
+ context.listen(list, "change", (event) => {
101
+ const box = event.target;
102
+ if (!(box instanceof HTMLInputElement)) return;
103
+ context.editJSON("goals", (data) => { data.items[Number(box.value)].done = box.checked; });
104
+ });
105
+ const draw = () => {
106
+ const data = context.readJSON("goals");
107
+ if (data === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
108
+ title.textContent = context.readJSON("settings")?.title || "本周目标";
109
+ list.replaceChildren(...data.items.map((/** @type {{ text: string, done: boolean }} */ item, /** @type {number} */ at) => {
110
+ const row = document.createElement("li");
111
+ const box = document.createElement("input");
112
+ box.type = "checkbox";
113
+ box.value = String(at);
114
+ box.checked = item.done;
115
+ box.disabled = !context.canEdit();
116
+ row.append(box, ` ${item.text}`);
117
+ return row;
118
+ }));
119
+ field.hidden = !context.canEdit();
120
+ host.classList.toggle("goals-narrow", (context.size?.w ?? 4) < 3);
121
+ };
122
+ draw();
123
+ return { update: draw };
124
+ },
125
+ });
126
+ ```
127
+
128
+ Tried on its card, a goal typed and a box ticked: `gallery page try home c7 --type .goals-new 跑步三次 --then Enter`, then `gallery page try home c7 --steps steps.json` with `[{ "type": [".goals-new", "读完一本书"], "then": "Enter" }, { "press": ".goals-list li:first-child input" }]`.
129
+
130
+ ## The workspace's data
131
+
132
+ A block whose manifest's `needs` hold `"workspace"` reads what the workspace holds, no consent asked (it is the user's own; `context.workspace` is there for such a block alone). `context.workspace.query(kind, options)` resolves to `{ data, at }` of one kind:
133
+
134
+ | Kind | Options | `data` |
135
+ | --- | --- | --- |
136
+ | `todos` | `{ done, slugs, limit }` | `[{ ref, text, done, slug, title, icon, path }]`: each to-do of every document, those of the document edited last first, `icon` its document's (as `recent` gives it), `path` the headings above it, `ref` what `setTodo` names it by |
137
+ | `recent` | `{ limit }` | `[{ slug, title, icon, edited }]` |
138
+ | `stats` | none | `{ documents, todos: { done, total }, words, editedThisWeek }` |
139
+ | `activity` | `{ days }` | `[{ date, edits, words, reader, agent }]`: the edits and the words added by day, from the day Gallery started keeping them |
140
+ | `table` | `{ slug, key, where, limit }` | `{ columns, rows: [{ values, links }], total }`: a table of another document by its key (`data-doc-chart-source`: A view of a table, below), read-only, the rows whose cells hold the words `where` names, as `context.table()` gives rows |
141
+
142
+ - List `data` in `on` and read again when `update` hears it with that kind as its `detail`: a to-do checked in any document, a document written, comes at once.
143
+ - A query that cannot be answered rejects with an `Error` whose `code` says why: `offline` (an exported file that holds none of that kind, or a server that does not answer: draw a line saying the card shows its data when opened in Gallery, never a failure), `failed` (the server answered and could not read it: say the data could not be read) and `missing` (`table`: no such document, no table of that key in it, or one with merged cells). `kind`, `options` and `unsupported` are mistakes of the block's own query.
144
+ - `context.workspace.open({ slug, block })` (or `{ page }`) opens a document, at a block of it, or a custom page, as a click on a link to it would.
145
+ - `context.workspace.setTodo(ref, done)` checks or clears a to-do by the `ref` a `todos` query gave. The server writes it into that document as the reader's own edit: a page open on the document merges it, and on a custom page the page's undo (Ctrl+Z) checks it back. It resolves to whether the document changed (`false`: it said so already) and rejects with a `code`: `changed` (the item is not as read, its words changed or it is gone: read again and draw what is there), `ambiguous` (several items alike and the file changed since), `locked` (the item is where no page can check it: in a table cell, in a block of the document's own), `missing`, `busy`, `offline`, `ref`, `failed`. Call it on the reader's gesture and draw the box from the data, never from what it last checked. An exported file has no `setTodo`: draw the boxes read-only where `if (context.workspace.setTodo)` is false.
146
+ - **In an exported file** each kind is answered from the snapshot the export embedded (the to-dos, 200 at most, the 50 documents edited last, the counts, the days and the tables the document's blocks asked for), `at` the time of the export: a figure the block draws says "截至 …" with it. A kind the snapshot holds none of rejects `offline`.
147
+ - Gallery's own `todos`, `recent`, `stats` and `heatmap` do all of this: for a card of the workspace's data start from one (`gallery block new <id> --recipe <name>`).
148
+
149
+ ## A view of a table
150
+
151
+ A block whose `needs` hold `"tables"` can be a view of a table of the document: a board of its rows, a count, a chart of your own drawing. It stands in a document, beside a table of the same document; a card of a custom page, which holds no table, that shows the rows of a document's table (a project's tasks, the ones that are the user's) is a block of your own with `needs` `["workspace"]` that reads `context.workspace.query("table", { slug, key })` (The workspace's data, above): `kanban`, `metric` and `chart-view` are of no use there. The table stays an ordinary table the reader edits as any, which any number of views (and charts drawn from a table) read at once, and a document whose block is missing or broken still shows the table, editable. The instance names the table by a key, the same one a chart drawn from a table reads it by: the table carries `data-doc-chart-source` (which Gallery moves onto the table's frame as it takes the table in), the instance `data-doc-from`.
152
+
153
+ <!-- you write -->
154
+ ```html
155
+ <table data-doc-chart-source="tasks">
156
+ <thead><tr><th>任务</th><th>状态</th><th>负责人</th></tr></thead>
157
+ <tbody>
158
+ <tr><td>写方案</td><td>待办</td><td>小王</td></tr>
159
+ <tr><td>做评审</td><td>进行中</td><td>小李</td></tr>
160
+ </tbody>
161
+ </table>
162
+ <div class="board" data-doc-component="local/board" data-doc-from="tasks">
163
+ <h3>本周任务</h3>
164
+ </div>
165
+ ```
166
+
167
+ A key is a letter, then letters, digits, `_` or `-`, 32 at most, and names one table of the document. The reader binds one in the page too: a block that reads tables is a row of "/" like any, and one made there reads the nearest table above it, the table given a new key when it has none or an earlier table carries the same key; its handle's 设置… lists the document's tables to read another. Its template holds no `data-doc-from`: each instance has its own.
168
+
169
+ ```js
170
+ DocKit.component({
171
+ id: "local/board",
172
+ on: ["data", "editable"],
173
+ mount(host, context) {
174
+ const draw = () => context.frame(() => {
175
+ const table = context.table();
176
+ if (!table) return; /* no table to read: say so in the block */
177
+ if (!table.columns.includes("状态")) return; /* the column renamed: say which one it looks for */
178
+ /* a card a row: table.rows, each { el, values, links }; keep a row's card while the row is the same object */
179
+ });
180
+ draw();
181
+ return { update: draw };
182
+ },
183
+ });
184
+ ```
185
+
186
+ - `context.table()` reads the table when it is called: `columns`, the header's words, and `rows`, each `{ el, values, links }` as `context.rows` gives them, its values by the header's words (a number where a cell writes one, its words, or `null`), in the file's order (a reader sorting the table by its header leaves it). A row is the same object until it or the header changes, so keep what you drew of a row while it is the same and draw again only the rows that are new: a view of a long table that draws everything again at each keystroke in it slows typing in the table. `null` where it has no table to read: no `data-doc-from`, no table carrying that key, a table with a merged cell, on a custom page (which holds no table), and for a block whose needs hold no `"tables"`.
187
+ - It hears its table by `data`, its detail `"table"`, whenever a change leaves the rows other than they were (a cell typed in, a row added, moved or taken out, the key changed, the table deleted or put back by an undo), also once it has a table where it had none; or by `table.subscribe(listener)`, which returns the function that takes the listener off. Read the table again each time.
188
+ - It changes the table only by asking: `table.set(row, column, text)` (one cell's words, plain), `table.add(values, { after })`, `table.move(row, { before | after, values })` (its cells of `values` set in the same step: a card dropped in another column) and `table.remove(row)`. Each is one undo step of the page's, made as the table's own tools make it, and answers whether it was made: the file follows by itself, someone else's change of the same cell is merged word by word with the reader's, and a move, add or removal over someone else's change of the table waits on a card for the reader. `false` in an exported file and in 演示视图, before the page edits, for a row no longer in the table, for the last row of the body (`remove`) and for a table Gallery's tools do not manage (a merged cell, a `<tfoot>`, rows of different lengths). A name the header does not have throws.
189
+ - `table.canEdit()` says whether the page would take a change of the table now, asked with no change: false in an exported file, in 演示视图, before the page edits and for a table Gallery's tools do not manage, so draw the view read-only there (no handle, no button that adds or takes out a row) rather than show controls whose every write answers `false`.
190
+ - The reader puts a view in from "/" (or 在下方新建), below the table it is to read or any block after it: it reads the nearest table above it. An Agent writes the table's key and the instance's `data-doc-from` itself, as above.
191
+ - Task boards, numbers and charts over a table are views Gallery ships: `gallery/kanban`, `gallery/metric` and `gallery/chart-view` (`gallery block add <name>`, before the instance is written: one written first stays read-only until the block is added; `gallery block show gallery/<name>` prints how to write each, a table and then the instance below it, its settings one line of JSON). Use them first; write a view of your own only for one they do not give.
192
+ - Never write the table yourself: not its cells, not its rows, not by `context.edit`, which writes the block's own parts alone. What the view draws is its own; the table is the document's.
193
+ - Keep what a reader only chooses in the view (its sort, a filter, what is folded) in `context.state`, never in the table.
194
+ - A column it reads by its name may be renamed by the reader: then say in the block which column it looks for, and keep the name in the block's own data part (the column it groups by), where the reader or you can change it, rather than fix it in the script.
195
+ - Its own parts are as any block's: a title, a data part of its own (what it counts, which column it groups by). A view has no slot of the table's rows: the table stands beside it.
196
+ - `gallery check` fails a `data-doc-from` that no table's frame carries, or that two carry, or that is not on an instance, and notes a table with merged cells, a table of more than 500 rows (every view of a table reads it again as it is typed in), a block whose needs hold no `"tables"`, and a view written above its table (it works there; each block's writing.md writes the table first, and so does the example).
197
+
198
+ ## Going online
199
+
200
+ A block that shows something of the web (a rate, the weather, a feed) names each host it reaches in its needs, `"needs": ["net:api.frankfurter.dev"]`, and reads it with `context.fetch(url, { as })`, which only such a block has: Gallery's server fetches for it (a GET, no cookie, an answer of JSON or text of at most 512 KB, kept a minute and given again when the network is not there), from those hosts alone, an address of the public internet alone (nothing of this computer or a private network), and only once the user has allowed it. Never a bare `fetch`, which the check refuses and an export blocks. Before you write the block, `curl -i` the address you mean to ask: an API that has moved answers a 301 or 302 to another host, and then every fetch rejects `host` (a redirect to a host the needs do not name is refused), so name the host the address ends at, or take another API, one that needs no key (the sample's does not).
201
+
202
+ ```js
203
+ DocKit.component({
204
+ id: "local/rate",
205
+ on: ["source"],
206
+ async mount(host, context) {
207
+ const line = document.createElement("p");
208
+ host.append(line);
209
+ try {
210
+ const { data, at } = await context.fetch("https://api.frankfurter.dev/v2/rate/USD/CNY");
211
+ line.textContent = `1 USD = ${data.rate} CNY · ${new Date(at).toLocaleTimeString()}`;
212
+ } catch (error) {
213
+ const { code } = /** @type {DocFetchError} */ (error);
214
+ line.textContent = code === "consent" ? "允许联网之后显示汇率" : code === "offline" ? "现在连不上网" : "没能取到汇率";
215
+ if (!code) throw error;
216
+ }
217
+ },
218
+ });
219
+ ```
220
+
221
+ - **It resolves** with `{ data, at, cached }`: `data` the answer's JSON (`as: "json"`, the default) or its text (`as: "text"`), `at` when it was fetched (an ISO time: say it on the card, 更新于 …, as an answer may be old where the network is not there), `cached` whether it was given from what was kept. Fetch again on `source` (a setting changed) and on a timer (`context.interval`, every few minutes at least: an answer of the last minute is given again, and a block may make 20 fetches a minute).
222
+ - **It rejects** with an `Error` whose `code` says why, which the block draws a state for: `consent` (the user has not allowed it yet; `hosts`, those waiting), `offline` (no network or the site not reached, and nothing kept; in an exported file, nothing embedded), `status` (the site answered an error, `status`), `type` (no JSON or text), `too-large`, `rate`, `key`, `private` (below), and `host` or `url` for an address it may not ask for (a host its needs do not name, or a redirect to one; another port, a user in it, not http(s), its own or a redirect's): fix the block. `private` is usually the reader's network setup, not the block: the address the name resolved to is on this computer or a private network, and no proxy on this computer took the name (the address is http, there is no proxy, the proxy is on another machine, or it is not running; an https address whose name resolves so is reached through a proxy on this computer by its name, its certificate held to the name). The Error's message names the host and the address, and `host` is set. Draw a plain state for it in the reader's words, as `gallery/weather` does (网络设置把天气服务指向了本地地址), not the generic failure.
223
+ - **Consent.** Until the user allows the block, every fetch rejects `consent` and Gallery draws over its card, under its head row, a banner of its own: your manifest's `card.consent` (else 允许联网之后显示内容), 数据来自 the site its hosts share (else <host> 等 N 个网站) and a button, 允许访问 (on a card three cells wide or less, the line over the button); pressed, Gallery asks the user, and once they say yes the block starts again by itself (its mount runs anew, and fetches). The user can take it back in 设置 › 组件列表 (允许联网), and the block starts again and asks. Draw a short state of your own for `consent` too (the button stands over it). In the handoff, tell the user to press 允许访问 on the card; never write the consent into `gallery.json` (its `components.net`) yourself, nor ask `gallery block try` or `gallery page try` to: it is the user's to give, and `gallery page check`'s pictures show the card asking.
224
+ - **A key.** An API that wants one in its address names where it goes by `{key}`, in its path or its query (`https://api.example.com/v6/{key}/latest`, `…/latest?apikey={key}`), and `gallery block key <host> <key>` keeps the user's key for that host in the workspace (`.gallery/keys.json`): the server writes it in as it fetches, and no page, cache or export ever holds it. Never write a key into the block's files or a page. Prefer an API that needs none. An API that takes its key in a header alone is not reached.
225
+ - **A document and its export.** In a document an instance fetches as on a page; its export holds what the document's instances were given last (`context.fetch` answers from it, `cached: true`) and, for an address it holds nothing of, rejects `offline`: draw a placeholder for that, as the example does. `context.place` is `"export"` there.
@@ -42,7 +42,7 @@ Each block by the name Gallery's menu gives it (the user's word for it), what yo
42
42
  `gallery new` writes the head, the header with the title, and a starter section, which you replace; the source line and the opening summary are yours to write.
43
43
 
44
44
  - `data-doc-id` is the slug, `<html lang>` the page's language.
45
- - `doc.json`, beside the page, holds its `title`, `description` and `type` (free text naming the kind of document; `gallery new`'s `report` is fine), and may hold `source`: the most precise locator of the dataset, experiment report, document or query the materials come from (say so when that is only a supplied draft or example). Its `title`, `icon` and `description` are the sidebar's; the title and icon are the page's header's too. Change any of them with `gallery set <slug> --title "…" --icon <emoji, or none> --description "…"` (SKILL.md, "Organizing documents"), which writes the header and `doc.json` in step; never by hand in either. It may also hold `look`, the reader's 字体与布局 (the page's font, text size, spacing and column width, chosen in Gallery's 更多 menu: `{ "font": "serif" | "mixed", "size": "small" | "large", "spacing": "compact" | "loose", "width": "narrow" | "wide" }`, where `"font": "sans"` or `"size"`, `"spacing"`, `"width": "default"` say a default chosen over the workspace's). The workspace's `gallery.json` may hold a `look` of the same shape too, the reader's default for every document (字体与布局's 应用到全部文档), which a document's own choices override one by one; a new document has none of its own and shows it. Both are the reader's: keep them as they are whenever you rewrite `doc.json`, never write either into the page, and add or change them only when the user asks (`gallery check` takes either).
45
+ - `doc.json`, beside the page, holds its `title`, `description` and `type` (free text naming the kind of document; `gallery new`'s `report` is fine), and may hold `source`: the most precise locator of the dataset, experiment report, document or query the materials come from (say so when that is only a supplied draft or example). Its `title`, `icon` and `description` are the sidebar's; the title and icon are the page's header's too. Change any of them with `gallery set <slug> --title "…" --icon <emoji, or none> --description "…"` (SKILL.md, "Organizing documents"), which writes the header and `doc.json` in step; never by hand in either. It may also hold `look`, the reader's 字体与布局 (the page's font, text size, spacing and column width, and its 全宽 switch under 目录, chosen in Gallery's 更多 menu: `{ "font": "serif" | "mixed", "size": "small" | "large", "spacing": "compact" | "loose", "width": "narrow" | "wide", "full": "full" }`, where `"font": "sans"` or `"size"`, `"spacing"`, `"width"`, `"full": "default"` say a default chosen over the workspace's; `"full": "full"` shows the page at the full width of its area whatever its `width` is). The workspace's `gallery.json` may hold a `look` of the same shape too, the reader's default for every document (字体与布局's 应用到全部文档), which a document's own choices override one by one; a new document has none of its own and shows it. Both are the reader's: keep them as they are whenever you rewrite `doc.json`, never write either into the page, and add or change them only when the user asks (`gallery check` takes either).
46
46
  - The header holds the title, an icon before it if any (`.doc-icon`, which `gallery set --icon` writes), and at most one line of small text, the source line. The source line says in words a reader elsewhere understands where the materials come from (组内项目 X 的论文终稿与 rebuttal 材料), or names a file of `materials/`; never a path of this machine (`D:\…`, `C:\Users\…`, `/home/…`), which the checks make a `fix` line. The same holds for a scope line's 来源. Nothing else goes between the title and the opening summary.
47
47
  - The opening summary comes right after the header, before the first section: `<section class="doc-summary" aria-label="概括">` (a 写作偏好 written before may write `aria-label="报告概括"`: the same block; keep the label 写作偏好 gives), a few headings as paragraphs of bold words (no `h2`–`h6`), each followed by a paragraph or a list. 写作偏好 may say what it holds; when it says nothing, a document written from materials still has one, unless the user asks for another structure or you convert a finished report. Its headings are short noun phrases that fit the kind of report (实验背景, 用途, 展区与展品 …); 写作偏好 says which.
48
48
  - A section groups a chapter and draws nothing: its title is the heading in it, an `<hr>` at its top a line above it. That `<hr>` is a block of its own, with its id: the first section after the summary has none, each after it one. To reorder sections, move the `<hr>` elements themselves, ids and all, so that this still holds; never delete one and write another. Sections are optional; a short document may put its text straight in `main`.
@@ -78,6 +78,8 @@ A picture comes from a file right in the document's `assets/` (no folder in it),
78
78
 
79
79
  A picture with no width shows at its own size, at most its column's width and 80% of the window's height (a tall scan shows whole, narrower); `width="360"` (pixels) gives it that share of the 712px reading width, `width="50%"` half the width it stands in. The share holds on a narrow page too: `width="300"` is 0.42 of a phone's 336px, 141px. A picture whose words the reader must read (a scan, a page, a screenshot of text) takes no width. A reader's click on a picture opens it large with its caption; you write nothing for it. A picture in a link follows the link; an icon or a picture shown under 48px does not open.
80
80
 
81
+ A small picture in a table's cell (a thumbnail, a logo, a product shot beside its row's words) stands amid the cell's words: `<td>猫 <img src="assets/cat.png" alt="小猫" width="120"></td>`, a file of `assets/` as any picture, `width` in pixels or none (it then shows 240px wide at most), no other attribute; the user resizes it by its edge. Written any other way, the cell is read-only (`gallery check` says why).
82
+
81
83
  ## Kit blocks
82
84
 
83
85
  The blocks HTML has no element for, written with the kit's classes as the example writes them.
@@ -88,6 +90,8 @@ The blocks HTML has no element for, written with the kit's classes as the exampl
88
90
 
89
91
  **A block's color** (颜色): a class on the block, never a `style`, of the colors gray, brown, orange, yellow, green, blue, purple, pink and red. A paragraph, a heading, a list item or a flowchart step takes its words' color (`doc-text-<color>`), a fill (`doc-highlight-<color>`) or both; a disclosure, a code block (on its `<pre>`), a callout or a highlight panel a fill only; a table cell one of the two. Words in a line take theirs from `<mark>` or a `<span style>`.
90
92
 
93
+ **A block's alignment and indent** (对齐与缩进): `doc-align-center` or `doc-align-right` on a paragraph, an `h1`–`h4` or a table's frame (`div.doc-table-wrap`, when the table is narrower than the text), the left being none; `doc-indent-1` … `doc-indent-8` move a paragraph or a heading in by two body characters a level. A `text-align: center` or `right` in a paragraph's or heading's `style` is rewritten as the class.
94
+
91
95
  **Columns** (`div.doc-columns` of 2 to 5 `div.doc-column`): what the reader compares across, or a picture with its words beside it (the picture's column first, so that on a phone it stands above them). `style="--doc-column-ratio: .4"` on a column gives it that share of the row: write it on every column of the row, the shares adding up to 1, or on none, and the columns share the row equally (one written on some columns only fails the check). Pictures side by side in columns: crop them to one ratio, so that their captions line up. A column holds any block but a row of columns, a section or a Sheet area. On a screen under 640px the columns stand one under another: never point at one as the left or right.
92
96
 
93
97
  **A process or steps** (步骤流程图, `ol.doc-flow`): one step an item, drawn as a card, arrows between them. A step's title is a paragraph of bold words, then any blocks it holds; an icon may stand first in it, drawn in its number's place. The kit numbers the steps (write no 1, ① or 第一步) and lays them out in rows that fill the width; `data-direction="row"` on the list keeps them in one row, `"column"` one a row; on a step it says where the arrow after it goes. A step written the short way (`<li>收集数据<p>…</p></li>`) is rewritten as a node. A flowchart has no title or caption of its own and stands in no `<figure>`: the sentence before it says what it shows; a legend goes in a `p.doc-note` beside it. A step takes a color as a list item does. A flowchart is for steps in order, each after the one before; a flow that branches, merges or loops is a drawing of boxes and arrows like the example's, and a structure or diagram a figure ([below](#figures-and-charts)).
@@ -96,7 +100,7 @@ The blocks HTML has no element for, written with the kit's classes as the exampl
96
100
 
97
101
  **Detail card** (详情卡片): a term's details over the page, opened by a link in the text; its `<dialog>` stands right after the link's paragraph, its id letters, digits, `-` and `_`, a letter first, and no other element's, and it starts with a plain `<h3>` of its title, the blocks after it (with no title, it starts with its blocks). `gallery qa` opens each one and checks it; its pictures show the blocks in it that changed, and `--tiles` the whole card.
98
102
 
99
- **A link to another document** of the workspace is an ordinary relative link between the two files, by the other's folder name (its slug, which `gallery list` prints, `gallery list <address>` for an address the user gave you), never a title or a server's address: `<a href="../<slug>/doc.html">its title</a>`, `<a href="../<slug>/doc.html#<block id>">` for one of its blocks, `<a href="#<block id>">` for a block of this document, the ids being the blocks' `data-block-id`. A click goes there inside Gallery, and an export of the two together links their files; a link to a document left out of an export keeps its words. The editor's page block is the same link shown with the document's icon and title (`<a class="doc-link-mention" href="../<slug>/doc.html"><span class="doc-link-mention-icon"></span>its title</a>`, written exactly so): the words in the file are read when it was made, the page shows the title the document has now. An ordinary link is what you write. `gallery check` notes a link to a document or a block that is not there, and a relative link that leads to no document (a title for the folder, a folder with no `doc.html` after it).
103
+ **A link to another document** of the workspace is an ordinary relative link between the two files, by the other's folder name (its slug, which `gallery list` prints, `gallery list <address>` for an address the user gave you), never a title or a server's address: `<a href="../<slug>/doc.html">its title</a>`, `<a href="../<slug>/doc.html#<block id>">` for one of its blocks, `<a href="#<block id>">` for a block of this document, the ids being the blocks' `data-block-id`. A click goes there inside Gallery, and an export of the two together links their files; a link to a document left out of an export keeps its words. The editor's page block is the same link shown with the document's icon and title (`<a class="doc-link-mention" href="../<slug>/doc.html"><span class="doc-link-mention-icon"></span>its title</a>`, written exactly so): the words in the file are read when it was made, the page shows the title the document has now. An ordinary link is what you write. `gallery check` notes a link to a document or a block that is not there, and a relative link that leads to no document (a title for the folder, a folder with no `doc.html` after it). A slug of the shape `doc-` and eight lowercase letters or digits (`doc-tacti90g`) is the workbench's own: the eight are the document's page id in its address, and `gallery new` and `gallery import` refuse one that another document's id already is. Choose a slug of words.
100
104
 
101
105
  **Files, bookmarks and embeds**: cards, written as the example writes them; keep what matters of each in the document's own text. A file's or an embed's caption is always there (`<figcaption></figcaption>` when there is none). A file is one file of `assets/` the reader saves: its link's `download` the name it is saved as, its size if you give it; keep it small, as the export embeds it. A bookmark is a paragraph holding only its link, `<p><a class="doc-bookmark" href="https://…" title="…">…</a></p>`: an `https://` address, its words the page's title, its `title` its description; the tools write the card (`figure.doc-bookmark`) and fetch nothing. In the card, an icon of `assets/` may go first in its address (`<img class="doc-bookmark-icon">`), a cover last in its link (`<span class="doc-bookmark-cover"><img></span>`). An embed shows an HTML or PDF file of `assets/` (`doc-embed--file`; an HTML file's `sandbox` never `allow-same-origin`, a PDF's none), shown offline too, or an `https://` page with a `sandbox`, shown only online; `--doc-embed-height` on the figure sets its height.
102
106
 
@@ -168,7 +172,7 @@ DocCharts.define("table-dots", ({ host, data, tokens, width }) => {
168
172
  - A `viewBox` scales the drawing, its text with it: 14-unit text in a viewBox 800 wide reads at 6px on a 360px phone. Size the text in the viewBox's units so that it reads at 11px or more at 360px, or lay the drawing out for narrow widths (HTML that wraps, an `@media` rule, or a chart of your own drawn from its width). The other way too: a viewBox sized for a phone grows its text with the card on a wide page (14 units in a viewBox 320 wide read at 31px drawn 712px wide), so give such an SVG a `max-width` (the example's `.branch`: 360px).
169
173
  - `gallery qa` pictures it, warns `overflow-in-block` when its words run past their box at some width (give them room in an `@media` rule), `cut-in-block` when a box of a fixed height cuts off its words or marks (let it grow: `min-height`) and `svg-text-small` when a viewBox draws its text under 11px.
170
174
 
171
- **A whole block** (整体块): a layout of your own that is no figure (a strip of metrics, a comparison panel, controls your script handles), as the example's `.metric-strip` is. Give it a class of your own (never `doc-…`) and style it in the page's `<style>` with the kit's variables. The user moves it whole and can fix its words in the preview; `gallery qa` warns `overflow-in-block` and `cut-in-block` as for a drawing. A drawing, a diagram or a timeline is a figure, in a card, not a whole block.
175
+ **A whole block** (整体块): a layout of your own that is no figure (a strip of metrics, a comparison panel, controls your script handles that only change what a reader looks at), as the example's `.metric-strip` is. Give it a class of your own (never `doc-…`) and style it in the page's `<style>` with the kit's variables. The user moves it whole and can fix its words in the preview; `gallery qa` warns `overflow-in-block` and `cut-in-block` as for a drawing. A drawing, a diagram or a timeline is a figure, in a card, not a whole block.
172
176
 
173
177
  **A picture**: a diagram, scan or photo the materials come with ([Pictures](#pictures)).
174
178
 
@@ -176,7 +180,7 @@ DocCharts.define("table-dots", ({ host, data, tokens, width }) => {
176
180
 
177
181
  - The kit's classes on what you write as plain HTML (a `<details>` given `doc-details`): write the plain element.
178
182
  - Attributes in curly quotes (`class=”x”`, which HTML reads as part of the value): an editing tool keeping a file's “…” may make them; look at the quotes of the tags you add.
179
- - A bare `<button>` in the text: a link opens a detail card; an interactive figure is a chart of your own (`DocCharts.define(type, { mount })`), and controls of your own a whole block your script handles.
183
+ - A bare `<button>` in the text: a link opens a detail card; an interactive figure is a chart of your own (`DocCharts.define(type, { mount })`), and controls of your own, for what a reader only looks through (a filter, a toggle), a whole block your script handles. A plain `<select>` among them needs nothing for its dropdown: the kit opens its own flat menu for every select, light and dark, never the browser's square popup (the select keeps its `value` and `change`; for a choice from a button of your own, `DocKit.choose`: [block-script.md](block-script.md)). A document's own script cannot write the file: a control that must keep what a reader enters (a ledger, a checklist, a form, a score) is a custom block's data part, even when the user does not say to use it again ([building-blocks.md](building-blocks.md): `gallery block new <id> --data`).
180
184
  - `<colgroup>`, column widths or `.number`: the kit measures columns and aligns numbers.
181
185
  - base64 `data:` or remote addresses for scripts, styles, fonts and pictures: put the file in `assets/` and write `assets/<file>`, which the export embeds. Links to web pages are fine.
182
186
  - Looks of your own on the kit's blocks (a paragraph, a table, a callout): gradients, shadows, frames, margins or type sizes; the kit sets them. The sizes this page names are the exception, each in its block's `style`: `--doc-table-height`, `--doc-code-height`, `--doc-embed-height`.