@heycys/gallery 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/THIRD-PARTY-NOTICES.md +51 -1
  2. package/browser/editor/components/callout/index.mjs +40 -15
  3. package/browser/editor/components/columns/page.mjs +45 -32
  4. package/browser/editor/components/details/index.mjs +2 -1
  5. package/browser/editor/components/dialog/index.mjs +2 -1
  6. package/browser/editor/components/dialog/page.mjs +0 -18
  7. package/browser/editor/components/divider/index.mjs +1 -1
  8. package/browser/editor/components/embed/index.mjs +2 -2
  9. package/browser/editor/components/figure/page.mjs +10 -1
  10. package/browser/editor/components/file/page.mjs +2 -2
  11. package/browser/editor/components/flowchart/add.mjs +7 -6
  12. package/browser/editor/components/flowchart/page.mjs +1 -1
  13. package/browser/editor/components/heading/index.mjs +2 -0
  14. package/browser/editor/components/heading/page.mjs +6 -0
  15. package/browser/editor/components/highlight/index.mjs +4 -20
  16. package/browser/editor/components/icons.mjs +13 -2
  17. package/browser/editor/components/image/crop.mjs +6 -9
  18. package/browser/editor/components/image/page.mjs +2 -2
  19. package/browser/editor/components/installed/index.mjs +82 -29
  20. package/browser/editor/components/installed/page.mjs +146 -34
  21. package/browser/editor/components/installed/served.mjs +6 -5
  22. package/browser/editor/components/instances.mjs +18 -0
  23. package/browser/editor/components/kit.mjs +3 -0
  24. package/browser/editor/components/list/page.mjs +3 -6
  25. package/browser/editor/components/media/page.mjs +44 -14
  26. package/browser/editor/components/pages.mjs +2 -2
  27. package/browser/editor/components/registry.mjs +68 -33
  28. package/browser/editor/components/section/index.mjs +2 -1
  29. package/browser/editor/components/set-apart.mjs +24 -0
  30. package/browser/editor/components/table/index.mjs +64 -5
  31. package/browser/editor/components/table/page.mjs +30 -19
  32. package/browser/editor/page/annotate/anchors.mjs +4 -3
  33. package/browser/editor/page/annotate/card.mjs +3 -6
  34. package/browser/editor/page/annotate/index.mjs +61 -34
  35. package/browser/editor/page/autosave.mjs +357 -38
  36. package/browser/editor/page/beside.mjs +5 -5
  37. package/browser/editor/page/block-menu/colors.mjs +3 -1
  38. package/browser/editor/page/block-menu/index.mjs +8 -6
  39. package/browser/editor/page/blocks.mjs +16 -7
  40. package/browser/editor/page/board/client.mjs +57 -0
  41. package/browser/editor/page/board/hint.mjs +145 -0
  42. package/browser/editor/page/board/history.mjs +119 -0
  43. package/browser/editor/page/board/index.mjs +970 -0
  44. package/browser/editor/page/board/settings.mjs +209 -0
  45. package/browser/editor/page/caret.mjs +5 -2
  46. package/browser/editor/page/changes/bar.mjs +94 -0
  47. package/browser/editor/page/changes/ghost.mjs +206 -0
  48. package/browser/editor/page/changes/gone-words.mjs +94 -0
  49. package/browser/editor/page/changes/index.mjs +447 -0
  50. package/browser/editor/page/changes/words.mjs +27 -0
  51. package/browser/editor/page/clipboard/import/colors.mjs +3 -3
  52. package/browser/editor/page/clipboard/import/html.mjs +29 -6
  53. package/browser/editor/page/clipboard/import/inline.mjs +32 -0
  54. package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
  55. package/browser/editor/page/clipboard/import/read.mjs +6 -1
  56. package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
  57. package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
  58. package/browser/editor/page/clipboard/index.mjs +156 -26
  59. package/browser/editor/page/clipboard/own/blocks.mjs +25 -16
  60. package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
  61. package/browser/editor/page/clipboard/own/describe.mjs +16 -7
  62. package/browser/editor/page/clipboard/own/export.mjs +6 -6
  63. package/browser/editor/page/clipboard/own/selection.mjs +3 -3
  64. package/browser/editor/page/clipboard/own/writers.mjs +0 -11
  65. package/browser/editor/page/columns/index.mjs +48 -46
  66. package/browser/editor/page/commit.mjs +98 -25
  67. package/browser/editor/page/conflicts.mjs +13 -33
  68. package/browser/editor/page/convert.mjs +8 -7
  69. package/browser/editor/page/core.mjs +81 -27
  70. package/browser/editor/page/custom-page.mjs +106 -0
  71. package/browser/editor/page/drag/index.mjs +40 -24
  72. package/browser/editor/page/drag/preview.mjs +9 -4
  73. package/browser/editor/page/editor.mjs +120 -28
  74. package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
  75. package/browser/editor/page/emoji-picker/grid.mjs +7 -5
  76. package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
  77. package/browser/editor/page/emoji-picker/icons.mjs +0 -1
  78. package/browser/editor/page/emoji-picker/index.mjs +11 -9
  79. package/browser/editor/page/emoji-picker/styles.mjs +156 -2
  80. package/browser/editor/page/emoji-picker/support.mjs +6 -4
  81. package/browser/editor/page/emoji-picker/upload.mjs +14 -13
  82. package/browser/editor/page/fills.mjs +5 -3
  83. package/browser/editor/page/fold/index.mjs +348 -0
  84. package/browser/editor/page/fold/rule.mjs +125 -0
  85. package/browser/editor/page/folded.mjs +23 -0
  86. package/browser/editor/page/format-bar/bar.mjs +2 -1
  87. package/browser/editor/page/format-bar/index.mjs +1 -1
  88. package/browser/editor/page/geometry.mjs +8 -6
  89. package/browser/editor/page/handle/index.mjs +22 -14
  90. package/browser/editor/page/hints/index.mjs +1 -1
  91. package/browser/editor/page/history.mjs +24 -4
  92. package/browser/editor/page/insert/index.mjs +30 -17
  93. package/browser/editor/page/links/index.mjs +5 -3
  94. package/browser/editor/page/links/pages.mjs +27 -9
  95. package/browser/editor/page/long-runs.mjs +75 -0
  96. package/browser/editor/page/look.mjs +69 -6
  97. package/browser/editor/page/margin.mjs +63 -27
  98. package/browser/editor/page/media-menu/index.mjs +6 -7
  99. package/browser/editor/page/menu.mjs +86 -31
  100. package/browser/editor/page/merge.mjs +24 -0
  101. package/browser/editor/page/notices.mjs +3 -3
  102. package/browser/editor/page/offered.mjs +1 -1
  103. package/browser/editor/page/outline/folds.mjs +11 -10
  104. package/browser/editor/page/outline/index.mjs +131 -45
  105. package/browser/editor/page/outline/list.mjs +23 -11
  106. package/browser/editor/page/outline/read.mjs +1 -1
  107. package/browser/editor/page/outline/strip.mjs +7 -1
  108. package/browser/editor/page/page-objects.mjs +13 -2
  109. package/browser/editor/page/panel.mjs +9 -13
  110. package/browser/editor/page/present-links.mjs +11 -2
  111. package/browser/editor/page/resize/index.mjs +42 -29
  112. package/browser/editor/page/selection/delete.mjs +8 -6
  113. package/browser/editor/page/selection/index.mjs +10 -3
  114. package/browser/editor/page/served.mjs +14 -0
  115. package/browser/editor/page/session.mjs +101 -6
  116. package/browser/editor/page/slash-menu/index.mjs +3 -3
  117. package/browser/editor/page/table/cell-bar.mjs +4 -1
  118. package/browser/editor/page/table/cells.mjs +103 -47
  119. package/browser/editor/page/table/icons.mjs +3 -1
  120. package/browser/editor/page/table/index.mjs +40 -16
  121. package/browser/editor/page/table/pictures.mjs +299 -0
  122. package/browser/editor/page/table/views.mjs +150 -0
  123. package/browser/editor/page/table/widths.mjs +9 -4
  124. package/browser/editor/page/text-select/index.mjs +43 -14
  125. package/browser/editor/page/todo-writes.mjs +75 -0
  126. package/browser/editor/page/tooltip.mjs +1 -1
  127. package/browser/editor/page/type-grid.mjs +4 -3
  128. package/browser/editor/page/typing/code-edges.mjs +63 -17
  129. package/browser/editor/page/typing/index.mjs +65 -9
  130. package/browser/editor/page/typing/leave.mjs +1 -1
  131. package/browser/editor/page/ui.mjs +13 -0
  132. package/browser/shared/annotations.mjs +8 -10
  133. package/browser/shared/block-packs.mjs +404 -0
  134. package/browser/shared/board-places.mjs +224 -0
  135. package/browser/shared/card-size.mjs +59 -0
  136. package/browser/shared/code-folds.mjs +5 -1
  137. package/browser/shared/colors.mjs +17 -14
  138. package/browser/shared/component-catalog.mjs +345 -54
  139. package/browser/shared/component-source.mjs +37 -0
  140. package/browser/shared/components/callout.mjs +4 -2
  141. package/browser/shared/components/index.mjs +72 -9
  142. package/browser/shared/components/installed.mjs +110 -8
  143. package/browser/shared/components/page.mjs +22 -3
  144. package/browser/shared/components/state.mjs +5 -1
  145. package/browser/shared/components/table.mjs +1 -1
  146. package/browser/shared/components/text.mjs +2 -2
  147. package/browser/shared/document-look.mjs +183 -0
  148. package/browser/shared/drafts.mjs +432 -0
  149. package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
  150. package/browser/shared/emoji/data/README.md +4 -2
  151. package/browser/shared/emoji/data/categories.json +1 -1
  152. package/browser/shared/emoji/data/keywords-en.json +1 -1
  153. package/browser/shared/emoji/data/keywords-zh.json +1 -1
  154. package/browser/shared/emoji/data/names.json +1 -1
  155. package/browser/shared/emoji/data/positions.json +1 -1
  156. package/browser/shared/emoji/data/twemoji-index.json +1 -1
  157. package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
  158. package/browser/shared/emoji/data.mjs +10 -12
  159. package/browser/shared/emoji/emoji.mjs +8 -7
  160. package/browser/shared/emoji/icon-value.mjs +4 -3
  161. package/browser/shared/extension-sidebar.mjs +126 -0
  162. package/browser/shared/extensions.mjs +79 -0
  163. package/browser/shared/file-table.mjs +101 -0
  164. package/browser/shared/html-tree.mjs +11 -5
  165. package/browser/shared/i18n/en.mjs +374 -35
  166. package/browser/shared/json-layout.mjs +47 -0
  167. package/browser/shared/long-runs.mjs +39 -0
  168. package/browser/shared/net-cache.mjs +133 -0
  169. package/browser/shared/net-keys.mjs +32 -0
  170. package/browser/shared/net-policy.mjs +177 -0
  171. package/browser/shared/new-names.mjs +5 -2
  172. package/browser/shared/outline-shape.mjs +128 -0
  173. package/browser/shared/outline.mjs +458 -0
  174. package/browser/shared/pack-manifest.mjs +77 -0
  175. package/browser/shared/page-address.mjs +6 -3
  176. package/browser/shared/page-cards.mjs +308 -0
  177. package/browser/shared/page-links.mjs +69 -6
  178. package/browser/shared/pages.mjs +388 -0
  179. package/browser/shared/paths.mjs +6 -0
  180. package/browser/shared/preferences.mjs +10 -4
  181. package/browser/shared/preview-server.mjs +3 -7
  182. package/browser/shared/session.mjs +13 -5
  183. package/browser/shared/shipped-blocks.mjs +299 -0
  184. package/browser/shared/table-chart.mjs +33 -1
  185. package/browser/shared/todos.mjs +83 -0
  186. package/browser/shared/user-directory.mjs +24 -0
  187. package/browser/shared/versions.mjs +14 -0
  188. package/browser/shared/web-links.mjs +134 -0
  189. package/browser/shared/workspace-columns.mjs +120 -0
  190. package/browser/shared/workspace-look.mjs +91 -0
  191. package/browser/shared/workspace-name.mjs +154 -0
  192. package/browser/shared/workspace-query.mjs +125 -0
  193. package/browser/shared/workspace-registry.mjs +272 -0
  194. package/browser/shared/workspace.mjs +171 -20
  195. package/browser/shared/zoom.mjs +5 -5
  196. package/dist/chunk-2NRBY6AJ.mjs +2 -0
  197. package/dist/chunk-32ZUEFZ7.mjs +2 -0
  198. package/dist/chunk-35NQ4PLQ.mjs +2 -0
  199. package/dist/chunk-3KJHLHUO.mjs +2 -0
  200. package/dist/chunk-3NJACR4W.mjs +2 -0
  201. package/dist/chunk-4AV456RQ.mjs +2 -0
  202. package/dist/chunk-4OZWXZE5.mjs +5 -0
  203. package/dist/chunk-5XYHDBJ5.mjs +2 -0
  204. package/dist/chunk-5ZJA7CXT.mjs +2 -0
  205. package/dist/chunk-6A53MZYZ.mjs +2 -0
  206. package/dist/chunk-6EXH3ORZ.mjs +166 -0
  207. package/dist/chunk-6EZ7FNIK.mjs +3 -0
  208. package/dist/{chunk-UXUK4PMC.mjs → chunk-6QBHU4DF.mjs} +1 -1
  209. package/dist/{chunk-6U2SLSDN.mjs → chunk-6VTU6KEO.mjs} +1 -1
  210. package/dist/chunk-B4P2CM2J.mjs +3 -0
  211. package/dist/chunk-BPL64HGA.mjs +4 -0
  212. package/dist/chunk-BVEFGE4B.mjs +2 -0
  213. package/dist/chunk-BZ5RAF7L.mjs +2 -0
  214. package/dist/chunk-CRJEG7MT.mjs +2 -0
  215. package/dist/{chunk-B3VTYBYR.mjs → chunk-D4CKRD3V.mjs} +91 -91
  216. package/dist/chunk-D4EURAX4.mjs +4 -0
  217. package/dist/chunk-DQCE7TJY.mjs +5 -0
  218. package/dist/chunk-DR73Y2UJ.mjs +3 -0
  219. package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
  220. package/dist/{chunk-DB4WKGYF.mjs → chunk-ERLAIBOA.mjs} +2 -2
  221. package/dist/chunk-EURLTOTZ.mjs +4 -0
  222. package/dist/chunk-FJYN7RTH.mjs +4 -0
  223. package/dist/chunk-FWNRPMCJ.mjs +12 -0
  224. package/dist/chunk-FWW4CSAZ.mjs +2 -0
  225. package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
  226. package/dist/chunk-GY3FAUVM.mjs +2 -0
  227. package/dist/chunk-HLYV7RIH.mjs +2 -0
  228. package/dist/chunk-HMYTM3GT.mjs +15 -0
  229. package/dist/chunk-IA4PSIMD.mjs +2 -0
  230. package/dist/chunk-JEUK3ZO7.mjs +2 -0
  231. package/dist/chunk-JVHHHGEA.mjs +3 -0
  232. package/dist/chunk-KTKHRC6H.mjs +2 -0
  233. package/dist/chunk-L7UP52JO.mjs +2 -0
  234. package/dist/chunk-MHW7ZKOU.mjs +2 -0
  235. package/dist/chunk-N76HWBA3.mjs +10 -0
  236. package/dist/chunk-N7AZZLGT.mjs +548 -0
  237. package/dist/chunk-NAMN3RAF.mjs +2 -0
  238. package/dist/{chunk-YXAUQPVK.mjs → chunk-NFMCP2HI.mjs} +3 -3
  239. package/dist/chunk-NG375ILQ.mjs +2 -0
  240. package/dist/chunk-NVRNLK25.mjs +6 -0
  241. package/dist/chunk-NWFBE2YA.mjs +2 -0
  242. package/dist/chunk-NWR2LT5B.mjs +2 -0
  243. package/dist/chunk-OJKMINIU.mjs +20 -0
  244. package/dist/chunk-OUUP3WKT.mjs +2 -0
  245. package/dist/chunk-OW5NWPOJ.mjs +10 -0
  246. package/dist/chunk-PAREWQGB.mjs +4 -0
  247. package/dist/chunk-POQSE4C2.mjs +2 -0
  248. package/dist/chunk-PUOQ65NC.mjs +2 -0
  249. package/dist/{chunk-Z52HTUW7.mjs → chunk-PVER7LSC.mjs} +2 -2
  250. package/dist/chunk-PZDLJJTJ.mjs +3 -0
  251. package/dist/chunk-Q47PLKIJ.mjs +15 -0
  252. package/dist/chunk-Q4UEPUWF.mjs +2 -0
  253. package/dist/chunk-QKXMPUXC.mjs +2 -0
  254. package/dist/chunk-QOUEFUCH.mjs +16 -0
  255. package/dist/chunk-RFDZXFJF.mjs +13 -0
  256. package/dist/chunk-RKPWLGZ3.mjs +4 -0
  257. package/dist/chunk-RMECZA2K.mjs +2 -0
  258. package/dist/{chunk-EUX7IC5J.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
  259. package/dist/chunk-SX4LJYT6.mjs +8 -0
  260. package/dist/chunk-SXHBYZST.mjs +16 -0
  261. package/dist/chunk-TANZRINB.mjs +2 -0
  262. package/dist/chunk-TEZAWDSQ.mjs +2 -0
  263. package/dist/chunk-UBBRTJ2R.mjs +24 -0
  264. package/dist/chunk-UFNYFFKO.mjs +20 -0
  265. package/dist/chunk-UGWYKHBL.mjs +170 -0
  266. package/dist/chunk-UKSHDZZ6.mjs +2 -0
  267. package/dist/chunk-UMHUSOPJ.mjs +2 -0
  268. package/dist/chunk-UNOYVIYR.mjs +2 -0
  269. package/dist/chunk-V6RIYQZZ.mjs +4 -0
  270. package/dist/chunk-VJPFVNNW.mjs +15 -0
  271. package/dist/chunk-VS3ZMVGX.mjs +5 -0
  272. package/dist/chunk-VTKNEYT3.mjs +6 -0
  273. package/dist/chunk-VXACTLO3.mjs +3 -0
  274. package/dist/chunk-W3BGBJQW.mjs +2 -0
  275. package/dist/chunk-YI43RG4P.mjs +2 -0
  276. package/dist/chunk-YQGT4AB2.mjs +6 -0
  277. package/dist/chunk-ZB4H7ZN4.mjs +2 -0
  278. package/dist/{chunk-ACOPDCNB.mjs → chunk-ZHEHPMBK.mjs} +1 -1
  279. package/dist/chunk-ZTHICSSF.mjs +2 -0
  280. package/dist/chunk-ZUNVAXLH.mjs +2 -0
  281. package/dist/chunk-ZWPMCK7P.mjs +2 -0
  282. package/dist/cli.mjs +1 -1
  283. package/dist/server.mjs +1 -1
  284. package/dist/{chunk-EVJ3BX3M.mjs → update-fetch.mjs} +1 -1
  285. package/dist/worker.mjs +1 -1
  286. package/kit/board.css +95 -0
  287. package/kit/board.js +250 -0
  288. package/kit/charts.js +5 -71
  289. package/kit/code.js +14 -14
  290. package/kit/math.js +18 -2
  291. package/kit/report.css +500 -151
  292. package/kit/runtime.js +1720 -170
  293. package/kit/state.js +10 -1
  294. package/kit/tables.js +172 -37
  295. package/kit/ui.js +166 -27
  296. package/package.json +2 -1
  297. package/packs/gallery/card/component.json +14 -0
  298. package/packs/gallery/card/example.html +10 -0
  299. package/packs/gallery/card/preview.svg +1 -0
  300. package/packs/gallery/card/style.css +6 -0
  301. package/packs/gallery/card/template.html +6 -0
  302. package/packs/gallery/card/writing.md +14 -0
  303. package/packs/gallery/chart-card/component.json +15 -0
  304. package/packs/gallery/chart-card/example.html +14 -0
  305. package/packs/gallery/chart-card/kit.js +130 -0
  306. package/packs/gallery/chart-card/preview.svg +1 -0
  307. package/packs/gallery/chart-card/style.css +42 -0
  308. package/packs/gallery/chart-card/template.html +13 -0
  309. package/packs/gallery/chart-card/writing.md +20 -0
  310. package/packs/gallery/chart-view/component.json +20 -0
  311. package/packs/gallery/chart-view/example.html +13 -0
  312. package/packs/gallery/chart-view/kit.js +355 -0
  313. package/packs/gallery/chart-view/preview.svg +1 -0
  314. package/packs/gallery/chart-view/style.css +94 -0
  315. package/packs/gallery/chart-view/template.html +3 -0
  316. package/packs/gallery/chart-view/writing.md +22 -0
  317. package/packs/gallery/countdown/component.json +18 -0
  318. package/packs/gallery/countdown/example.html +3 -0
  319. package/packs/gallery/countdown/kit.js +156 -0
  320. package/packs/gallery/countdown/preview.svg +1 -0
  321. package/packs/gallery/countdown/style.css +130 -0
  322. package/packs/gallery/countdown/template.html +3 -0
  323. package/packs/gallery/countdown/writing.md +22 -0
  324. package/packs/gallery/habit/component.json +14 -0
  325. package/packs/gallery/habit/example.html +3 -0
  326. package/packs/gallery/habit/kit.js +295 -0
  327. package/packs/gallery/habit/preview.svg +1 -0
  328. package/packs/gallery/habit/style.css +246 -0
  329. package/packs/gallery/habit/template.html +3 -0
  330. package/packs/gallery/habit/writing.md +21 -0
  331. package/packs/gallery/heatmap/component.json +18 -0
  332. package/packs/gallery/heatmap/example.html +3 -0
  333. package/packs/gallery/heatmap/kit.js +351 -0
  334. package/packs/gallery/heatmap/preview.svg +1 -0
  335. package/packs/gallery/heatmap/style.css +201 -0
  336. package/packs/gallery/heatmap/template.html +3 -0
  337. package/packs/gallery/heatmap/writing.md +21 -0
  338. package/packs/gallery/kanban/component.json +18 -0
  339. package/packs/gallery/kanban/example.html +12 -0
  340. package/packs/gallery/kanban/kit.js +540 -0
  341. package/packs/gallery/kanban/preview.svg +1 -0
  342. package/packs/gallery/kanban/style.css +212 -0
  343. package/packs/gallery/kanban/template.html +3 -0
  344. package/packs/gallery/kanban/writing.md +20 -0
  345. package/packs/gallery/metric/component.json +22 -0
  346. package/packs/gallery/metric/example.html +15 -0
  347. package/packs/gallery/metric/kit.js +248 -0
  348. package/packs/gallery/metric/preview.svg +1 -0
  349. package/packs/gallery/metric/style.css +92 -0
  350. package/packs/gallery/metric/template.html +3 -0
  351. package/packs/gallery/metric/writing.md +23 -0
  352. package/packs/gallery/note/component.json +14 -0
  353. package/packs/gallery/note/example.html +3 -0
  354. package/packs/gallery/note/kit.js +102 -0
  355. package/packs/gallery/note/preview.svg +1 -0
  356. package/packs/gallery/note/style.css +76 -0
  357. package/packs/gallery/note/template.html +3 -0
  358. package/packs/gallery/note/writing.md +18 -0
  359. package/packs/gallery/pack.json +8 -0
  360. package/packs/gallery/recent/component.json +13 -0
  361. package/packs/gallery/recent/example.html +1 -0
  362. package/packs/gallery/recent/kit.js +238 -0
  363. package/packs/gallery/recent/preview.svg +1 -0
  364. package/packs/gallery/recent/style.css +158 -0
  365. package/packs/gallery/recent/template.html +1 -0
  366. package/packs/gallery/recent/writing.md +15 -0
  367. package/packs/gallery/static/component.json +13 -0
  368. package/packs/gallery/static/example.html +11 -0
  369. package/packs/gallery/static/preview.svg +1 -0
  370. package/packs/gallery/static/style.css +138 -0
  371. package/packs/gallery/static/template.html +1 -0
  372. package/packs/gallery/static/writing.md +18 -0
  373. package/packs/gallery/stats/component.json +13 -0
  374. package/packs/gallery/stats/example.html +1 -0
  375. package/packs/gallery/stats/kit.js +166 -0
  376. package/packs/gallery/stats/preview.svg +1 -0
  377. package/packs/gallery/stats/style.css +151 -0
  378. package/packs/gallery/stats/template.html +1 -0
  379. package/packs/gallery/stats/writing.md +11 -0
  380. package/packs/gallery/today/component.json +12 -0
  381. package/packs/gallery/today/example.html +1 -0
  382. package/packs/gallery/today/kit.js +185 -0
  383. package/packs/gallery/today/preview.svg +1 -0
  384. package/packs/gallery/today/style.css +120 -0
  385. package/packs/gallery/today/template.html +1 -0
  386. package/packs/gallery/today/writing.md +14 -0
  387. package/packs/gallery/todos/component.json +19 -0
  388. package/packs/gallery/todos/example.html +3 -0
  389. package/packs/gallery/todos/kit.js +342 -0
  390. package/packs/gallery/todos/preview.svg +1 -0
  391. package/packs/gallery/todos/style.css +267 -0
  392. package/packs/gallery/todos/template.html +3 -0
  393. package/packs/gallery/todos/writing.md +30 -0
  394. package/packs/gallery/weather/component.json +19 -0
  395. package/packs/gallery/weather/example.html +3 -0
  396. package/packs/gallery/weather/kit.js +312 -0
  397. package/packs/gallery/weather/preview.svg +1 -0
  398. package/packs/gallery/weather/style.css +258 -0
  399. package/packs/gallery/weather/template.html +3 -0
  400. package/packs/gallery/weather/writing.md +26 -0
  401. package/packs/gallery-soft/pack.json +8 -0
  402. package/release.json +13 -11
  403. package/sdk/doc-kit.d.ts +404 -7
  404. package/sdk/doc-state.d.ts +2 -0
  405. package/skill/SKILL.md +71 -26
  406. package/skill/references/block-script.md +140 -0
  407. package/skill/references/building-blocks.md +257 -0
  408. package/skill/references/example-report.html +1 -1
  409. package/skill/references/extensions.md +59 -0
  410. package/skill/references/pages-and-data.md +221 -0
  411. package/skill/references/writing-html.md +9 -7
  412. package/skill/sdk/doc-kit.d.ts +404 -7
  413. package/skill/sdk/doc-state.d.ts +2 -0
  414. package/web/assets/index-BK2e_07w.js +13 -0
  415. package/web/assets/index-CWFI83mF.css +1 -0
  416. package/web/index.html +2 -2
  417. package/browser/editor/components/callout/page.mjs +0 -13
  418. package/dist/chunk-2PBALTR3.mjs +0 -57
  419. package/dist/chunk-3LA3EMDE.mjs +0 -15
  420. package/dist/chunk-5FRMCDPY.mjs +0 -16
  421. package/dist/chunk-5LEK2CBS.mjs +0 -2
  422. package/dist/chunk-5OFN5AHC.mjs +0 -2
  423. package/dist/chunk-5SIYS5HN.mjs +0 -2
  424. package/dist/chunk-5TEK3RAD.mjs +0 -2
  425. package/dist/chunk-6CYG3Z4V.mjs +0 -2
  426. package/dist/chunk-7GHT2UCA.mjs +0 -15
  427. package/dist/chunk-7QQBR7PB.mjs +0 -2
  428. package/dist/chunk-ATCJYAR4.mjs +0 -2
  429. package/dist/chunk-C7HWOBIF.mjs +0 -2
  430. package/dist/chunk-E7VYDG2X.mjs +0 -2
  431. package/dist/chunk-EZY3WC6Z.mjs +0 -15
  432. package/dist/chunk-FQGQH4KM.mjs +0 -2
  433. package/dist/chunk-G7TOXONE.mjs +0 -6
  434. package/dist/chunk-GPF4YWWB.mjs +0 -9
  435. package/dist/chunk-GYQV7Y4J.mjs +0 -120
  436. package/dist/chunk-HMHK3EQ6.mjs +0 -2
  437. package/dist/chunk-HQQMJCQJ.mjs +0 -10
  438. package/dist/chunk-IERUOGC3.mjs +0 -6
  439. package/dist/chunk-ITNLYXXV.mjs +0 -3
  440. package/dist/chunk-L4DVONOG.mjs +0 -2
  441. package/dist/chunk-LAE5NQ4B.mjs +0 -2
  442. package/dist/chunk-LC7YNQFG.mjs +0 -2
  443. package/dist/chunk-LHTFLRB6.mjs +0 -4
  444. package/dist/chunk-NFIBI4IP.mjs +0 -26
  445. package/dist/chunk-NSKUTQ5J.mjs +0 -5
  446. package/dist/chunk-O52JMOCZ.mjs +0 -2
  447. package/dist/chunk-P2CAZPDP.mjs +0 -3
  448. package/dist/chunk-QMQUXTU4.mjs +0 -12
  449. package/dist/chunk-QVWVFC5K.mjs +0 -6
  450. package/dist/chunk-QYKCJ7FG.mjs +0 -8
  451. package/dist/chunk-QZY6Q64C.mjs +0 -2
  452. package/dist/chunk-TDQP3DKQ.mjs +0 -10
  453. package/dist/chunk-TX6JH7TR.mjs +0 -2
  454. package/dist/chunk-UNUEWH4S.mjs +0 -2
  455. package/dist/chunk-V4CPWKMZ.mjs +0 -2
  456. package/dist/chunk-VACRB2NE.mjs +0 -3
  457. package/dist/chunk-W63L7367.mjs +0 -7
  458. package/dist/chunk-W7CXPCRV.mjs +0 -6
  459. package/dist/chunk-XINNG4F2.mjs +0 -4
  460. package/dist/chunk-YL2DPWVS.mjs +0 -4
  461. package/dist/chunk-YZ5Z6H4W.mjs +0 -4
  462. package/dist/chunk-ZBIM6ARY.mjs +0 -216
  463. package/skill/references/building-components.md +0 -327
  464. package/web/assets/index-B6Ai3wsa.js +0 -13
  465. package/web/assets/index-SYPC3EZy.css +0 -1
@@ -0,0 +1,246 @@
1
+ /* Every selector starts at the instance and goes down a step at a time (>), so that nothing here
2
+ reaches the rest of the page. The face fills its card on a custom page (the board draws the frame), in
3
+ the kit's card tokens, laid out as a grid: its head (the chip, the name, the days in all as its quiet
4
+ meta at the right, its end clear of the card's grip); the streak, its label small and muted over its
5
+ count, large, its unit after it, with the button at its right; the last seven days at the bottom, each
6
+ a dot over its weekday (today's 今), a day done filled with the accent and ticked, an open one the
7
+ track's gray, today ringed in the accent. Where the card has the room (past 300px wide and 130px high:
8
+ a 4 x 2 card from a window 1440px wide) the last 30 days as a ring at the left of the streak and the week, the
9
+ days done of them in its middle. The button is a primary one, pale blue with no line ("打卡"); once
10
+ today is done a pale green "✓ 已打卡" that a press takes back; where nothing is written, a plain muted
11
+ line. Low (under 124px), the streak's label goes; a narrow card (2 x 2) leaves the week out and puts
12
+ the button under the streak, as wide as its words. Never checked in (data-fresh): no streak and no
13
+ ring, a muted line where the streak stands. Light and dark. */
14
+ [data-doc-component="gallery/habit"] {
15
+ container-type: size;
16
+ height: 10em;
17
+ > .gallery-habit-face {
18
+ display: grid;
19
+ grid-template-columns: minmax(0, 1fr) auto;
20
+ grid-template-rows: auto 1fr auto;
21
+ grid-template-areas: "head head" "streak press" "week week";
22
+ align-items: center;
23
+ gap: 8px 12px;
24
+ box-sizing: border-box;
25
+ height: 100%;
26
+ min-height: 0;
27
+ color: var(--gallery-text);
28
+ font-size: 14px;
29
+ line-height: 1.4;
30
+ }
31
+ > .gallery-habit-face > .gallery-habit-head {
32
+ grid-area: head;
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 8px;
36
+ min-width: 0;
37
+ padding-inline-end: var(--gallery-grip-room, 0px);
38
+ }
39
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-chip {
40
+ flex: none;
41
+ display: inline-flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ width: var(--gallery-chip-size);
45
+ height: var(--gallery-chip-size);
46
+ border-radius: var(--gallery-chip-radius);
47
+ background: var(--gallery-accent-soft);
48
+ color: var(--gallery-accent);
49
+ }
50
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-chip > svg { width: var(--gallery-chip-icon); height: var(--gallery-chip-icon); }
51
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name {
52
+ flex: 1 1 auto;
53
+ min-width: 0;
54
+ box-sizing: border-box;
55
+ width: 0;
56
+ margin: 0 0 0 -6px;
57
+ padding: 3px 6px;
58
+ border: 0;
59
+ border-radius: 6px;
60
+ outline: 0;
61
+ background: transparent;
62
+ font: inherit;
63
+ font-size: var(--gallery-title-size);
64
+ line-height: var(--gallery-title-line);
65
+ font-weight: 600;
66
+ color: var(--gallery-text-strong);
67
+ text-overflow: ellipsis;
68
+ }
69
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name::placeholder { color: var(--doc-muted); font-weight: 500; opacity: .8; }
70
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name:not(:read-only):hover,
71
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name:not(:read-only):focus { background: var(--doc-hover); }
72
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name:read-only { cursor: default; }
73
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-total {
74
+ flex: none;
75
+ margin-inline-end: calc(-1 * var(--gallery-grip-room, 0px)); opacity: calc(1 - var(--gallery-grip-shown, 0)); transition: opacity .12s ease-out;
76
+ font-size: var(--gallery-meta-size);
77
+ line-height: var(--gallery-title-line);
78
+ color: var(--doc-muted);
79
+ white-space: nowrap;
80
+ font-variant-numeric: tabular-nums;
81
+ }
82
+ > .gallery-habit-face > .gallery-habit-check {
83
+ grid-area: press;
84
+ justify-self: end;
85
+ align-self: center;
86
+ padding: 5px 14px;
87
+ border: 0;
88
+ border-radius: 8px;
89
+ background: var(--gallery-accent-soft);
90
+ font: inherit;
91
+ font-size: 13px;
92
+ line-height: 18px;
93
+ font-weight: 500;
94
+ color: var(--gallery-accent);
95
+ white-space: nowrap;
96
+ cursor: pointer;
97
+ }
98
+ > .gallery-habit-face > .gallery-habit-check:hover { background: color-mix(in srgb, var(--gallery-accent) 15%, transparent); }
99
+ > .gallery-habit-face > .gallery-habit-check:active { background: color-mix(in srgb, var(--gallery-accent) 21%, transparent); }
100
+ > .gallery-habit-face > .gallery-habit-check.gallery-habit-done { background: var(--gallery-good-soft); color: var(--gallery-good); }
101
+ > .gallery-habit-face > .gallery-habit-check.gallery-habit-done:hover { background: color-mix(in srgb, var(--gallery-good) 16%, transparent); }
102
+ /* Nothing to press (an export, a page that takes no edits): a line saying how today stands. */
103
+ > .gallery-habit-face > .gallery-habit-check:disabled,
104
+ > .gallery-habit-face > .gallery-habit-check.gallery-habit-done:disabled {
105
+ padding-inline: 0;
106
+ background: transparent;
107
+ font-weight: 400;
108
+ color: var(--doc-muted);
109
+ cursor: default;
110
+ }
111
+ /* The streak: its label over its count, the count large, its unit small and muted after it. */
112
+ > .gallery-habit-face > .gallery-habit-streak {
113
+ grid-area: streak;
114
+ align-self: center;
115
+ display: flex;
116
+ flex-wrap: wrap;
117
+ align-items: baseline;
118
+ min-width: 0;
119
+ margin: 0;
120
+ }
121
+ > .gallery-habit-face > .gallery-habit-streak > .gallery-habit-label {
122
+ flex: 0 0 100%;
123
+ margin-bottom: 2px;
124
+ font-size: var(--gallery-meta-size);
125
+ line-height: 16px;
126
+ color: var(--doc-muted);
127
+ }
128
+ > .gallery-habit-face > .gallery-habit-streak > .gallery-habit-count {
129
+ font-size: clamp(28px, 100cqh - 100px, var(--gallery-hero-size)); /* the hero, a little less on a card too low for it beside the week */
130
+ line-height: 1;
131
+ font-weight: var(--gallery-numeral-weight);
132
+ letter-spacing: var(--gallery-numeral-tracking);
133
+ color: var(--gallery-text-strong);
134
+ font-variant-numeric: tabular-nums;
135
+ }
136
+ > .gallery-habit-face > .gallery-habit-streak > .gallery-habit-unit {
137
+ margin-inline-start: var(--gallery-unit-gap);
138
+ font-size: max(12px, calc(var(--gallery-hero-size) * .4)); /* the hero's unit (--gallery-unit-size of it) */
139
+ font-weight: 500;
140
+ color: var(--doc-muted);
141
+ }
142
+ /* Never checked in: a muted line where the streak stands. */
143
+ > .gallery-habit-face > .gallery-habit-fresh { display: none; }
144
+ > .gallery-habit-face[data-fresh] > .gallery-habit-streak { display: none; }
145
+ > .gallery-habit-face[data-fresh] > .gallery-habit-fresh {
146
+ grid-area: streak;
147
+ align-self: center;
148
+ display: block;
149
+ min-width: 0;
150
+ margin: 0;
151
+ font-size: 13px;
152
+ line-height: 1.45;
153
+ color: var(--doc-muted);
154
+ }
155
+ /* The last 30 days: a ring of the accent on the track, the days done in its middle over its label. */
156
+ > .gallery-habit-face > .gallery-habit-ring {
157
+ grid-area: ring;
158
+ display: none;
159
+ position: relative;
160
+ width: clamp(76px, calc(100cqh - 52px), 128px);
161
+ aspect-ratio: 1;
162
+ align-self: center;
163
+ }
164
+ > .gallery-habit-face > .gallery-habit-ring > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
165
+ > .gallery-habit-face > .gallery-habit-ring > svg > circle { fill: none; stroke-width: 9; }
166
+ > .gallery-habit-face > .gallery-habit-ring > svg > .gallery-habit-track { stroke: var(--gallery-track); }
167
+ > .gallery-habit-face > .gallery-habit-ring > svg > .gallery-habit-arc {
168
+ stroke: var(--gallery-accent);
169
+ stroke-linecap: round;
170
+ stroke-dasharray: calc(var(--gallery-habit-share, 0) * 100) 100;
171
+ }
172
+ > .gallery-habit-face > .gallery-habit-ring[data-none] > svg > .gallery-habit-arc { display: none; }
173
+ > .gallery-habit-face > .gallery-habit-ring > .gallery-habit-rate {
174
+ position: relative;
175
+ font-size: clamp(20px, 7cqi, 28px);
176
+ line-height: 1;
177
+ font-weight: var(--gallery-numeral-weight);
178
+ letter-spacing: var(--gallery-numeral-tracking);
179
+ font-variant-numeric: tabular-nums;
180
+ text-align: center;
181
+ }
182
+ > .gallery-habit-face > .gallery-habit-ring > .gallery-habit-rate-label {
183
+ position: relative;
184
+ margin-top: 4px;
185
+ font-size: 11px;
186
+ line-height: 14px;
187
+ color: var(--doc-muted);
188
+ text-align: center;
189
+ }
190
+ > .gallery-habit-face > .gallery-habit-week {
191
+ grid-area: week;
192
+ display: grid;
193
+ grid-template-columns: repeat(7, minmax(0, 1fr));
194
+ gap: 4px;
195
+ margin: 0;
196
+ padding: 0;
197
+ list-style: none;
198
+ }
199
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-day {
200
+ display: flex;
201
+ flex-direction: column;
202
+ align-items: center;
203
+ gap: 5px;
204
+ font-size: 11px;
205
+ line-height: 1;
206
+ color: var(--doc-muted);
207
+ }
208
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-day > .gallery-habit-dot {
209
+ box-sizing: border-box;
210
+ width: clamp(18px, 6.4cqi, 26px);
211
+ aspect-ratio: 1;
212
+ border-radius: 50%;
213
+ background: var(--gallery-track);
214
+ }
215
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-kept > .gallery-habit-dot {
216
+ background: var(--gallery-accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.5 8.3l2.2 2.2 4.8-4.9' fill='none' stroke='white' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 72% no-repeat;
217
+ }
218
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-today { color: var(--gallery-accent); font-weight: 600; }
219
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-today:not(.gallery-habit-kept) > .gallery-habit-dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--gallery-accent); }
220
+ }
221
+ /* Room for the ring: at the left of the streak and the week, the dots no wider than they need. */
222
+ @container (min-width: 300px) and (min-height: 130px) {
223
+ [data-doc-component="gallery/habit"] > .gallery-habit-face {
224
+ grid-template-columns: auto minmax(0, 1fr) auto;
225
+ grid-template-areas: "head head head" "ring streak press" "ring week week";
226
+ column-gap: 20px;
227
+ }
228
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-ring { display: flex; flex-direction: column; align-items: center; justify-content: center; }
229
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-week { align-self: end; }
230
+ /* Never checked in: no ring, the line and the week from the card's left. */
231
+ [data-doc-component="gallery/habit"] > .gallery-habit-face[data-fresh] { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "head head" "streak press" "week week"; }
232
+ [data-doc-component="gallery/habit"] > .gallery-habit-face[data-fresh] > .gallery-habit-ring { display: none; }
233
+ }
234
+ /* Low: the count alone, no label over it. */
235
+ @container (max-height: 124px) {
236
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-streak > .gallery-habit-label { display: none; }
237
+ }
238
+ /* A narrow card: the head, the streak, the button under it at its start, as wide as its words, the two in the middle of the room under the head; no week, no days in all. */
239
+ @container (max-width: 220px) {
240
+ [data-doc-component="gallery/habit"] > .gallery-habit-face { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr auto auto 1fr; grid-template-areas: "head" "." "streak" "press" "."; }
241
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-check { justify-self: start; }
242
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-week,
243
+ [data-doc-component="gallery/habit"] > .gallery-habit-face > .gallery-habit-head > .gallery-habit-total { display: none; }
244
+ }
245
+ /* On a custom page the face is the card's: as high as what the card holds inside its padding. */
246
+ .gallery-card > [data-doc-component="gallery/habit"] { height: 100%; }
@@ -0,0 +1,3 @@
1
+ <div data-doc-component="gallery/habit">
2
+ <script type="application/json">{"name":"","days":[]}</script>
3
+ </div>
@@ -0,0 +1,21 @@
1
+ # 习惯打卡 (gallery/habit)
2
+
3
+ A card for a custom page (its places are `page`): one habit, checked in once a day. It shows the habit's name, how many days in a row it was done (up to today, or up to yesterday while today is not checked yet), how many days in all, and the last seven days as dots. Use it for something the user means to do every day. For a habit counted otherwise (glasses of water in a day, minutes, a goal a week), start a block of your own from it: `gallery block new <scope>/<name> --recipe habit` copies its files, which are written to be read and changed.
4
+
5
+ ## How to write it
6
+
7
+ Put it on a custom page as a card of its board, `<section class="gallery-card" data-card-id="…" data-x data-y data-w data-h>`, holding one instance, after `gallery block add habit`, the instance as template.html has it: its data part `habit`, a `<script type="application/json">`, holding `{"name":"…","days":[]}` (on one line and compact, as the block writes it back):
8
+
9
+ - `name`: the habit, a few words (每天读书半小时); `""` shows 给习惯起个名字, and the user names it on the card.
10
+ - `days`: the days it was done, each `YYYY-MM-DD` by the user's clock, in order, each once. Leave the days of a card that is there alone: they are the user's record.
11
+
12
+ Sizes: 4 × 2 (the default: the name, the streak and the button, the week, and where the window is wide enough the last 30 days as a ring) and 2 × 2 (the name, the streak, the button under it).
13
+
14
+ ## What the user does
15
+
16
+ - presses 打卡: today goes in `days`; pressed again (✓ 已打卡), today comes out. Each press is one write, one step of the page's undo.
17
+ - clicks the name and types another: written as they press Enter or leave the field (never while a Chinese input method composes); Esc puts back the name there was.
18
+
19
+ ## How it looks
20
+
21
+ The name beside a flame's chip on the top line, the days in all at its end; the streak under it, 连续打卡 over its count, large, with the button at its right (打卡, pale blue; once done a pale green ✓ 已打卡 that a press takes back), the week at the bottom, a day done a dot filled with the accent and ticked, today ringed and named 今; on a card with the room for it, the last 30 days as a ring at the left, the days done of them in its middle; in the kit's card tokens (as every Gallery card: a head of a tinted chip and a title, its end clear of the card's grip), light and dark. It moves to the next day by itself at midnight (it hears the kit's clock). A habit never checked in shows neither the streak nor the ring but a muted line, 还没打过卡,今天开始第 1 天, until its first check-in. Where nothing can be written (an export) the button is a line saying whether today is done. The script runs with the rights of the page's own scripts, as any block's does.
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "gallery/heatmap",
3
+ "apiVersion": 1,
4
+ "version": "1.3.0",
5
+ "name": { "zh": "编辑热力图", "en": "Editing heatmap" },
6
+ "description": { "zh": "过去一年每天编辑了几次或写了多少字,像 GitHub 的贡献图", "en": "How often, or how many words, the workspace was edited each day of the past year, like GitHub's contribution graph" },
7
+ "words": "bianjireilitu reilitu heatmap activity contributions calendar 热力图 编辑 贡献 日历 字数 每天",
8
+ "parts": {
9
+ "settings": { "at": ":scope > script", "edit": "data" }
10
+ },
11
+ "runtime": { "generated": [":scope > .gallery-heatmap-face"] },
12
+ "places": ["page"],
13
+ "card": { "sizes": [[8, 3], [12, 3], [4, 3]], "resize": true },
14
+ "settings": [
15
+ { "key": "words", "label": { "zh": "按字数显示", "en": "Show words, not edits" }, "type": "switch", "default": false }
16
+ ],
17
+ "needs": ["workspace"]
18
+ }
@@ -0,0 +1,3 @@
1
+ <div data-doc-component="gallery/heatmap">
2
+ <script type="application/json">{"words":false}</script>
3
+ </div>
@@ -0,0 +1,351 @@
1
+ // gallery/heatmap (编辑热力图): the workspace's record of edits by day, as GitHub draws a year of
2
+ // contributions: a column a week (Monday at the top, as a Chinese calendar starts it), a square a day,
3
+ // darker for a day of more, read through context.workspace.query("activity") (its manifest's needs hold
4
+ // "workspace": the server's record, .gallery/state/activity.json, a reader's commits and the Agent's
5
+ // writes, by day). Its one setting, `words` (按字数显示, the card's form: the grip at its top right › 设置…, kept in its data part
6
+ // `settings`, which the board writes and this block only reads), draws the words a day added (its net
7
+ // change, a day that took more away than it added drawn as none) instead of how many edits it had. As
8
+ // many weeks as the card holds are drawn, the last ending today, at most a year's 53: the squares as big as
9
+ // the card's height lets seven of them be (3px apart, 2px where the card is low), at most so big that 53
10
+ // weeks fit its width (but 8px, or three fifths of what the height lets, at least, where the height has room
11
+ // for it: fewer weeks then); never more than the card holds, so that no day is cut off. It asks for every
12
+ // day 53 weeks draw (the record keeps as many), so that a day drawn apart (none counted then) is one before
13
+ // the record started, never one of a record older than what it asked; and the line at the top says since
14
+ // when it was kept while nothing is counted yet (从 11月8日 开始记录). It reads again whenever the
15
+ // workspace says its record changed (the `data` signal, "activity") and as a day begins (the kit's
16
+ // clock), and draws again as its card changes size (`resize`, `layout`, and its own ResizeObserver on
17
+ // the room the squares have, which hears a change of height too, as a card that got its height after the
18
+ // first draw has) or its settings change (`source`). Each square says its day and its count (its title). Where the workspace cannot be read
19
+ // (an exported file, where it has no server; a server that does not answer) the line says so. The words
20
+ // are the page's language (the UI's where Gallery says it, else the page's lang). Its head is the cards'
21
+ // (the kit's card tokens): the chip, a calendar, before its title; its squares the accent's shades, the
22
+ // grid hung from the card's left edge under the head, the weekdays' column left out where the squares are
23
+ // too small for its words, the months' names no closer than their own width. A wide card with something
24
+ // counted shows the figures beside the squares (`summaryOf`'s `figures`, the face's `data-figures`): what
25
+ // they count (期间编辑), the edits (or words) in all, large, how many days had any and today's, the period
26
+ // then the head's quiet note at its end; the room the squares have is what the figures leave. Less to more
27
+ // stands under the squares at their left where the card has the room for it, else at the head's end (left
28
+ // out on a card too narrow for it beside the line: style.css).
29
+
30
+ const WORDS = {
31
+ zh: {
32
+ title: "编辑热力图",
33
+ since: (/** @type {string} */ date) => `从 ${date} 开始记录`,
34
+ edits: (/** @type {string} */ period, /** @type {number} */ count) => `${period} ${count} 次编辑`,
35
+ words: (/** @type {string} */ period, /** @type {string} */ count) => `${period}写了 ${count} 字`,
36
+ year: "过去一年",
37
+ after: (/** @type {string} */ date) => `${date}以来`,
38
+ day: (/** @type {string} */ date, /** @type {number} */ edits, /** @type {number} */ words) => (edits === 0 ? `${date}:没有编辑` : `${date}:${edits} 次编辑,${words >= 0 ? "+" : "−"}${Math.abs(words)} 字`),
39
+ before: (/** @type {string} */ date) => `${date}:还没开始记录`,
40
+ date: (/** @type {Date} */ date) => `${date.getMonth() + 1}月${date.getDate()}日`,
41
+ weekday: (/** @type {Date} */ date) => `${date.getMonth() + 1}月${date.getDate()}日 ${["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"][date.getDay()]}`,
42
+ month: (/** @type {number} */ month) => `${month + 1}月`,
43
+ rows: ["一", "", "三", "", "五", "", ""],
44
+ yearLabel: "过去一年",
45
+ editsLabel: "期间编辑",
46
+ wordsLabel: "期间写作",
47
+ editsUnit: "次",
48
+ wordsUnit: "字",
49
+ active: (/** @type {number} */ count) => `${count} 天有编辑`,
50
+ todayEdits: (/** @type {number} */ count) => `今天 ${count} 次`,
51
+ todayWords: (/** @type {string} */ count) => `今天 ${count} 字`,
52
+ less: "少",
53
+ more: "多",
54
+ offline: "在 Gallery 里打开时显示",
55
+ failed: "读不到工作区的编辑记录",
56
+ locale: "zh-CN",
57
+ },
58
+ en: {
59
+ title: "Editing heatmap",
60
+ since: (/** @type {string} */ date) => `Recording since ${date}`,
61
+ edits: (/** @type {string} */ period, /** @type {number} */ count) => `${count} ${count === 1 ? "edit" : "edits"} ${period}`,
62
+ words: (/** @type {string} */ period, /** @type {string} */ count) => `${count} words ${period}`,
63
+ year: "in the past year",
64
+ after: (/** @type {string} */ date) => `since ${date}`,
65
+ day: (/** @type {string} */ date, /** @type {number} */ edits, /** @type {number} */ words) => (edits === 0 ? `${date}: no edits` : `${date}: ${edits} ${edits === 1 ? "edit" : "edits"}, ${words >= 0 ? "+" : "−"}${Math.abs(words)} words`),
66
+ before: (/** @type {string} */ date) => `${date}: not recorded yet`,
67
+ date: (/** @type {Date} */ date) => `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()]} ${date.getDate()}`,
68
+ weekday: (/** @type {Date} */ date) => `${["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][date.getDay()]}, ${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()]} ${date.getDate()}`,
69
+ month: (/** @type {number} */ month) => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][month],
70
+ rows: ["Mon", "", "Wed", "", "Fri", "", ""],
71
+ yearLabel: "The past year",
72
+ editsLabel: "Edits",
73
+ wordsLabel: "Words written",
74
+ editsUnit: "edits",
75
+ wordsUnit: "words",
76
+ active: (/** @type {number} */ count) => `${count} ${count === 1 ? "day" : "days"} with edits`,
77
+ todayEdits: (/** @type {number} */ count) => `${count} today`,
78
+ todayWords: (/** @type {string} */ count) => `${count} today`,
79
+ less: "Less",
80
+ more: "More",
81
+ offline: "Shown when opened in Gallery",
82
+ failed: "The workspace's record of edits could not be read",
83
+ locale: "en",
84
+ },
85
+ };
86
+
87
+ /** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
88
+ function languageOf(/** @type {HTMLElement} */ root) {
89
+ const ui = root.getAttribute("data-ge-language");
90
+ return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
91
+ }
92
+
93
+ const MOST_WEEKS = 53;
94
+ /** The days of the record it reads: as many as 53 weeks draw at the most (on a Sunday, its first square 370 days back). */
95
+ const DAYS = MOST_WEEKS * 7;
96
+ const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
97
+ /** A local day as the record writes it, YYYY-MM-DD. @param {Date} date */
98
+ const dayOf = (date) => `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())}`;
99
+ /** The day `count` days after `date` (before, negative), at noon. @param {Date} date @param {number} count */
100
+ const after = (date, count) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + count, 12);
101
+
102
+ /**
103
+ * How the squares fit a grid of `width` x `height` px (what the face has for it, its labels' room taken
104
+ * off): { cell, gap, weeks, across }. The gap is 3px, or 2px where seven squares of 9px and their gaps would not
105
+ * fit the height. The side is no more than seven of them fit the height (never cut off), at most 18px, and
106
+ * no bigger than 53 weeks across the width lets, but 8px where the height has room for that, and three
107
+ * fifths of what the height lets where that is more (a card far higher than a year's squares need, as on a
108
+ * narrow window: fewer weeks, bigger squares), 4px at the least; then as many weeks as fit across, at
109
+ * most 53, at least 1. `across` is the gap between the weeks: the gap, but where a year's 53 leave room
110
+ * across (a card far wider than high), that room shared between them, at most half a square more, so that
111
+ * a wide card's year reaches across it rather than leaving its right side empty.
112
+ * @param {number} width
113
+ * @param {number} height
114
+ */
115
+ function fitOf(width, height) {
116
+ const gap = Math.floor((height - 18) / 7) >= 9 ? 3 : 2;
117
+ const byHeight = Math.floor((height - 6 * gap) / 7);
118
+ const byWidth = Math.floor((width - (MOST_WEEKS - 1) * gap) / MOST_WEEKS);
119
+ const cell = Math.max(4, Math.min(18, byHeight, Math.max(byWidth, 8, Math.floor(byHeight * 0.6))));
120
+ const weeks = Math.max(1, Math.min(MOST_WEEKS, Math.floor((width + gap) / (cell + gap))));
121
+ const room = weeks === MOST_WEEKS ? Math.floor((width - MOST_WEEKS * cell) / (MOST_WEEKS - 1)) : gap;
122
+ const across = Math.max(gap, Math.min(room, gap + Math.floor(cell / 2)));
123
+ return { cell, gap, weeks, across };
124
+ }
125
+
126
+ /**
127
+ * The weeks drawn, the last the one of `today` (a Date), `weeks` of them: [[{ date, day, future }…7]…],
128
+ * each a column, Monday first; `future` a day after today, which is not drawn.
129
+ * @param {Date} today
130
+ * @param {number} weeks
131
+ */
132
+ function weeksOf(today, weeks) {
133
+ const monday = after(today, -((today.getDay() + 6) % 7));
134
+ const columns = [];
135
+ for (let week = weeks - 1; week >= 0; week--) {
136
+ const start = after(monday, -7 * week);
137
+ columns.push(Array.from({ length: 7 }, (_, row) => {
138
+ const date = after(start, row);
139
+ return { date, day: dayOf(date), future: dayOf(date) > dayOf(today) };
140
+ }));
141
+ }
142
+ return columns;
143
+ }
144
+
145
+ /**
146
+ * The level of a day's square, 0 (none) to 4 (the most), of `value` (its edits, or the words it added,
147
+ * none for a day that took more away) against the most of any day drawn, `most`.
148
+ * @param {number} value
149
+ * @param {number} most
150
+ */
151
+ function levelOf(value, most) {
152
+ if (!(value > 0) || !(most > 0)) return 0;
153
+ return Math.min(4, Math.max(1, Math.ceil((4 * value) / most)));
154
+ }
155
+
156
+ /**
157
+ * What the card says of the record `days` (workspace.query("activity")'s data: [{ date, edits, words }],
158
+ * from the day it started or 53 weeks back to today), in `language`, counting `words` (the setting) or
159
+ * edits: the line at the top, and the value of each day by its date (a Map), and since which day (the
160
+ * first of them: before it nothing was kept).
161
+ * @param {Array<{ date: string, edits: number, words: number }>} days
162
+ * @param {boolean} words
163
+ * @param {"zh" | "en"} language
164
+ */
165
+ function summaryOf(days, words, language) {
166
+ const said = WORDS[language];
167
+ const values = new Map(days.map((day) => [day.date, words ? Math.max(0, day.words) : day.edits]));
168
+ const since = days[0]?.date ?? null;
169
+ const edits = days.reduce((sum, day) => sum + day.edits, 0);
170
+ const sinceDate = since ? new Date(`${since}T12:00:00`) : null;
171
+ const period = days.length >= 365 || !sinceDate ? said.year : said.after(said.date(sinceDate));
172
+ let line;
173
+ if (edits === 0) line = sinceDate ? said.since(said.date(sinceDate)) : "";
174
+ else if (words) line = said.words(period, new Intl.NumberFormat(said.locale, { notation: "compact", maximumFractionDigits: 1 }).format(days.reduce((sum, day) => sum + day.words, 0)));
175
+ else line = said.edits(period, edits);
176
+ // The figures a wide card shows beside its squares: the edits (or the words) in all, how many days had
177
+ // any, and today's.
178
+ const format = (/** @type {number} */ value) => new Intl.NumberFormat(said.locale, Math.abs(value) >= 100_000 ? { notation: "compact", maximumFractionDigits: 1 } : { maximumFractionDigits: 0 }).format(value);
179
+ const written = days.reduce((sum, day) => sum + day.words, 0);
180
+ const today = days.find((day) => day.date === dayOf(new Date()));
181
+ const signed = (/** @type {number} */ value) => `${value > 0 ? "+" : value < 0 ? "−" : ""}${format(Math.abs(value))}`;
182
+ const figures = edits === 0 ? null : {
183
+ period: period === said.year ? said.yearLabel : period.replace(/^since /, "Since "),
184
+ label: words ? said.wordsLabel : said.editsLabel,
185
+ total: words ? format(Math.max(0, written)) : format(edits),
186
+ unit: words ? said.wordsUnit : said.editsUnit,
187
+ more: [said.active(days.filter((day) => day.edits > 0).length), ...(today && today.edits > 0 ? [words ? said.todayWords(signed(today.words)) : said.todayEdits(today.edits)] : [])],
188
+ };
189
+ return { line, values, since, figures };
190
+ }
191
+
192
+ /**
193
+ * An element of the face, of `kind` (its class).
194
+ * @template {keyof HTMLElementTagNameMap} K
195
+ * @param {K} tag
196
+ * @param {string} kind
197
+ * @param {string} [text]
198
+ */
199
+ function made(tag, kind, text) {
200
+ const node = document.createElement(tag);
201
+ node.className = `gallery-heatmap-${kind}`;
202
+ if (text !== undefined) node.textContent = text;
203
+ return node;
204
+ }
205
+
206
+ DocKit.component({
207
+ id: "gallery/heatmap",
208
+ on: ["data", "source", "resize", "layout", "clock"],
209
+ mount(host, context) {
210
+ const language = languageOf(document.documentElement);
211
+ const words = WORDS[language];
212
+ const face = made("div", "face");
213
+ const head = made("div", "head");
214
+ const line = made("span", "line");
215
+ const chip = made("span", "chip");
216
+ chip.setAttribute("aria-hidden", "true");
217
+ chip.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7z"/><path d="M16 3v4M8 3v4M4 11h16"/></svg>';
218
+ head.append(chip, made("span", "title", words.title), line);
219
+ const body = made("div", "body");
220
+ const months = made("div", "months");
221
+ const rows = made("div", "rows");
222
+ for (const label of words.rows) rows.append(made("span", "row", label));
223
+ const grid = made("div", "grid");
224
+ const area = made("div", "area");
225
+ area.append(months, grid);
226
+ // Beside the squares on a wide card: what they count, its edits (or words) large, and a muted line of the days with any and today's.
227
+ const aside = made("div", "aside");
228
+ const period = made("span", "label");
229
+ const total = made("span", "total");
230
+ const totalNumber = made("span", "number");
231
+ const totalUnit = made("span", "unit");
232
+ total.append(totalNumber, totalUnit);
233
+ const asideMore = made("span", "more");
234
+ aside.append(period, total, asideMore);
235
+ body.append(aside, rows, area);
236
+ const legend = made("div", "legend");
237
+ legend.append(made("span", "less", words.less), ...[0, 1, 2, 3, 4].map((level) => {
238
+ const square = made("span", "square");
239
+ square.dataset.level = String(level);
240
+ return square;
241
+ }), made("span", "more", words.more));
242
+ face.append(head, body);
243
+ host.append(face);
244
+ const workspace = context.workspace;
245
+ if (!workspace) return void context.fail(new Error("its manifest's needs hold \"workspace\": context.workspace is not there"));
246
+
247
+ /** @type {Array<{ date: string, edits: number, words: number }> | null} */
248
+ let days = null;
249
+ let failure = "";
250
+ let drawn = "";
251
+ const draw = () => {
252
+ const settings = context.readJSON("settings");
253
+ if (settings === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
254
+ const byWords = settings !== null && typeof settings === "object" && settings.words === true;
255
+ // The room the grid has: the face's, its labels' and its lines' taken off.
256
+ const today = new Date();
257
+ const summary = summaryOf(days ?? [], byWords, language);
258
+ // The figures, where there are some (the aside shows them on a card wide enough: style.css).
259
+ const figures = failure ? null : summary.figures;
260
+ face.toggleAttribute("data-figures", figures !== null);
261
+ if (figures) {
262
+ period.textContent = figures.label;
263
+ totalNumber.textContent = figures.total;
264
+ totalUnit.textContent = figures.unit;
265
+ asideMore.replaceChildren(...figures.more.map((piece) => made("span", "piece", piece)));
266
+ }
267
+ // The room the grid has: the face's, its labels' and its lines' taken off (the weekdays' column and the gap after it; the aside, where it shows,
268
+ // its margin and the gap after it: a wide card's squares had run 3px past its edge where its weeks filled the room).
269
+ const width = body.clientWidth - rows.offsetWidth - 6 - (aside.offsetWidth > 0 ? aside.offsetWidth + 6 + 6 : 0);
270
+ const height = body.clientHeight - months.offsetHeight - 4;
271
+ const { cell, gap, weeks, across } = fitOf(width, height);
272
+ // Less to more: under the squares where the room left under them holds it, else at the head's end.
273
+ const shownAside = aside.offsetWidth > 0;
274
+ const under = height - (7 * cell + 6 * gap) >= 22;
275
+ const place = under ? area : head;
276
+ if (legend.parentElement !== place) place.append(legend);
277
+ // The head's quiet note: the line, or, where the figures say the rest beside the squares, their period.
278
+ line.textContent = failure || (shownAside && figures ? figures.period : summary.line);
279
+ const key = JSON.stringify([cell, gap, weeks, across, dayOf(today), byWords, days, failure, language, aside.offsetWidth, under]);
280
+ if (key === drawn) return;
281
+ drawn = key;
282
+ face.style.setProperty("--gallery-heatmap-cell", `${cell}px`);
283
+ face.style.setProperty("--gallery-heatmap-gap", `${gap}px`);
284
+ face.style.setProperty("--gallery-heatmap-across", `${across}px`);
285
+ face.style.setProperty("--gallery-heatmap-weeks", String(weeks));
286
+ face.toggleAttribute("data-small", cell < 6);
287
+ const columns = weeksOf(today, weeks);
288
+ const most = Math.max(0, ...[...summary.values.values()]);
289
+ const byDate = new Map((days ?? []).map((item) => [item.date, item]));
290
+ grid.replaceChildren(...columns.flatMap((column) => column.map(({ date, day, future }) => {
291
+ const square = made("span", "day");
292
+ if (future) {
293
+ square.classList.add("gallery-heatmap-future");
294
+ return square;
295
+ }
296
+ const recorded = days !== null && summary.since !== null && day >= summary.since;
297
+ if (!recorded) {
298
+ square.classList.add("gallery-heatmap-before");
299
+ square.title = days === null ? words.weekday(date) : words.before(words.weekday(date));
300
+ return square;
301
+ }
302
+ const entry = byDate.get(day);
303
+ square.dataset.level = String(levelOf(summary.values.get(day) ?? 0, most));
304
+ square.title = words.day(words.weekday(date), entry?.edits ?? 0, entry?.words ?? 0);
305
+ return square;
306
+ })));
307
+ // A month's name over the week its first day falls in, none closer to the one before than its own
308
+ // width (about 26px: "12月", "Sep") and three weeks.
309
+ const apart = Math.max(3, Math.ceil(28 / (cell + across)));
310
+ let last = -apart;
311
+ months.replaceChildren(...columns.flatMap((column, index) => {
312
+ const first = column.find(({ date }) => date.getDate() === 1);
313
+ if (!first || index - last < apart) return [];
314
+ last = index;
315
+ const label = made("span", "month", words.month(first.date.getMonth()));
316
+ label.style.setProperty("--gallery-heatmap-week", String(index));
317
+ return [label];
318
+ }));
319
+ };
320
+ let asking = 0; // the last read asked: an older answer that comes after it is dropped
321
+ const read = () => {
322
+ const ticket = ++asking;
323
+ workspace.query("activity", { days: DAYS }).then(({ data }) => {
324
+ if (ticket !== asking || context.signal.aborted) return;
325
+ days = data;
326
+ failure = "";
327
+ draw();
328
+ }, (/** @type {any} */ error) => {
329
+ if (ticket !== asking || context.signal.aborted) return;
330
+ days = null;
331
+ failure = error?.code === "offline" ? words.offline : words.failed;
332
+ draw();
333
+ });
334
+ };
335
+ draw();
336
+ read();
337
+ // The room the squares have, its height too (the kit's `resize` hears its width alone): a card given its
338
+ // height after the first draw (a board laid out late) is drawn again as it gets it.
339
+ if (typeof ResizeObserver === "function") {
340
+ const watch = new ResizeObserver(() => draw());
341
+ watch.observe(body);
342
+ context.signal?.addEventListener("abort", () => watch.disconnect(), { once: true });
343
+ }
344
+ return {
345
+ update(reason, detail) {
346
+ if ((reason === "data" && detail === "activity") || (reason === "clock" && detail === "day")) read();
347
+ else if (reason !== "data" && reason !== "clock") draw();
348
+ },
349
+ };
350
+ },
351
+ });