@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,334 @@
1
+ // gallery/habit (习惯打卡): one habit, checked in once a day. Its data part, a script of JSON, holds the
2
+ // habit's name and the days it was done, each YYYY-MM-DD by the reader's clock, in order:
3
+ // { "name": "喝八杯水", "days": ["2026-11-05", "2026-11-06"] }. The card draws the name in a field of its
4
+ // own (DocKit.input: written as the reader presses Enter or leaves it, never while an input method
5
+ // composes), the streak (the days in a row up to today, or up to yesterday while today is not checked
6
+ // yet, so that a streak lasts the day it is to be kept), how many days in all, and a button that checks
7
+ // today in, or takes today's check-in back when it is there. Each press and each name is one
8
+ // context.editJSON, one undo step, the JSON written back on one line as it was: what the reader does is
9
+ // in the file, and nothing else is (the streak and the days are worked out as it draws). It draws from
10
+ // the part on every `source` (an undo, an Agent's write) and again as a day begins (the kit's `clock`,
11
+ // "day"), so that "today" moves at midnight. Where nothing takes its writes (an export, a page that has
12
+ // not come to edit yet: context.canEdit() false) the name is read-only and the button a plain line saying
13
+ // whether today is done. Its words are the page's language (the UI's where Gallery says it, else the
14
+ // page's lang).
15
+ //
16
+ // Its face (the pack's design B, in the kit's card tokens), laid out by the card's cells (`data-layout`,
17
+ // by context.size, read again on `layout`): "wide" (4 × 2, the default) a head of the chip, a flame in
18
+ // its warm color, the name (the field) and the days in all after it (共 41 天), the streak, the hero, and
19
+ // 天连续 after it, the button at its right (a pale blue 打卡, a pale green ✓ 已打卡 a press takes back),
20
+ // and this week at the bottom, Monday to Sunday, seven circles (`weekOf`): a day done filled with the
21
+ // accent and ticked, one not done a soft gray with its initial, today ringed in the accent (今), filled
22
+ // and ringed twice once done, the days to come an outline; "narrow" (2 wide) the name alone at the top,
23
+ // a flame and the streak, and the button as wide as the card at the bottom (the name shown as words of
24
+ // up to two lines, the field over them unseen until a press or Tab brings it, so that a long name is
25
+ // never cut to a few characters); "tall" (4 high) the head, the streak and the button, and the last five
26
+ // weeks as a month (`monthOf`), Monday first, the days of the streak the accent's, the days done before
27
+ // it its pale tint, the others bare, today ringed, the days to come an outline, with 最近五周 and how
28
+ // many of them were done (打了 27 天) over it. A habit never
29
+ // checked in (no days at all) says 还没打过卡 where the streak stands (the face's data-fresh), the chip
30
+ // gray and no count of days, until the first check-in. Start a block of your own from it with gallery
31
+ // block new <id> --recipe habit.
32
+
33
+ const WORDS = {
34
+ zh: {
35
+ name: "给习惯起个名字",
36
+ check: "打卡",
37
+ checked: "已打卡",
38
+ undo: "再按一下,撤回今天的打卡",
39
+ todayDone: "今天已打卡",
40
+ todayOpen: "今天还没打卡",
41
+ streak: "天连续",
42
+ unit: () => "天",
43
+ total: (/** @type {number} */ days) => `共 ${days} 天`,
44
+ fresh: ["还没打过卡", "今天开始第 1 天"],
45
+ weeks: "最近五周",
46
+ got: (/** @type {number} */ days) => ["打了 ", String(days), " 天"],
47
+ week: "这一周",
48
+ initials: ["日", "一", "二", "三", "四", "五", "六"],
49
+ today: "今",
50
+ day: (/** @type {number} */ month, /** @type {number} */ day, /** @type {boolean} */ done) => `${month}月${day}日${done ? ",已打卡" : ",没打卡"}`,
51
+ },
52
+ en: {
53
+ name: "Name this habit",
54
+ check: "Check in",
55
+ checked: "Done",
56
+ undo: "Press again to take today's check-in back",
57
+ todayDone: "Done today",
58
+ todayOpen: "Not done today",
59
+ streak: "in a row",
60
+ unit: (/** @type {number} */ days) => (days === 1 ? "day" : "days"),
61
+ total: (/** @type {number} */ days) => `${days} ${days === 1 ? "day" : "days"} in all`,
62
+ fresh: ["No check-ins yet", "today can be day 1"],
63
+ weeks: "Last five weeks",
64
+ got: (/** @type {number} */ days) => ["", String(days), ` ${days === 1 ? "day" : "days"} done`],
65
+ week: "This week",
66
+ initials: ["S", "M", "T", "W", "T", "F", "S"],
67
+ today: "", // a week's circle is too small for "Today": its initial, ringed as today
68
+ day: (/** @type {number} */ month, /** @type {number} */ day, /** @type {boolean} */ done) => `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][month - 1]} ${day}${done ? ", done" : ", not done"}`,
69
+ },
70
+ };
71
+
72
+ /** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
73
+ function languageOf(/** @type {HTMLElement} */ root) {
74
+ const ui = root.getAttribute("data-ge-language");
75
+ return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
76
+ }
77
+
78
+ const DAY = /^\d{4}-\d{2}-\d{2}$/;
79
+
80
+ /**
81
+ * A day of the reader's clock as the data writes it, YYYY-MM-DD.
82
+ * @param {Date} date
83
+ */
84
+ function dayOf(date) {
85
+ const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
86
+ return `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())}`;
87
+ }
88
+
89
+ /**
90
+ * The day `count` days after `day` (before it for a count below 0), both YYYY-MM-DD, by the calendar
91
+ * (counted in UTC, so that a change of the clocks changes nothing).
92
+ * @param {string} day
93
+ * @param {number} count
94
+ */
95
+ function dayAfter(day, count) {
96
+ const [year, month, date] = day.split("-").map(Number);
97
+ const moved = new Date(Date.UTC(year, month - 1, date + count));
98
+ const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
99
+ return `${moved.getUTCFullYear()}-${two(moved.getUTCMonth() + 1)}-${two(moved.getUTCDate())}`;
100
+ }
101
+
102
+ /** The weekday of a day written YYYY-MM-DD, 0 for Sunday. @param {string} day */
103
+ function weekdayOf(day) {
104
+ const [year, month, date] = day.split("-").map(Number);
105
+ return new Date(Date.UTC(year, month - 1, date)).getUTCDay();
106
+ }
107
+
108
+ /**
109
+ * The habit `data` is (context.readJSON's, or the draft context.editJSON hands a change): its name ("" for
110
+ * none yet) and its days, as they stand; throws saying why it is none, and the block draws nothing over it.
111
+ * @param {any} data
112
+ * @returns {{ name: string, days: string[] }}
113
+ */
114
+ function readHabit(data) {
115
+ if (data === null || typeof data !== "object" || Array.isArray(data)) throw new Error("its data is no object: a habit holds { \"name\": \"…\", \"days\": [\"YYYY-MM-DD\", …] }");
116
+ const name = data.name ?? "";
117
+ if (typeof name !== "string") throw new Error("its name is no string");
118
+ const days = data.days ?? [];
119
+ if (!Array.isArray(days) || !days.every((day) => typeof day === "string" && DAY.test(day))) throw new Error("its days are no list of dates written YYYY-MM-DD");
120
+ return { name, days };
121
+ }
122
+
123
+ /**
124
+ * The days in a row that end today, or yesterday while today is not checked yet (a streak lasts the day
125
+ * it is to be kept); 0 when neither was done.
126
+ * @param {string[]} days
127
+ * @param {string} today
128
+ */
129
+ function streakOf(days, today) {
130
+ const done = new Set(days);
131
+ let day = done.has(today) ? today : dayAfter(today, -1);
132
+ let count = 0;
133
+ while (done.has(day)) {
134
+ count += 1;
135
+ day = dayAfter(day, -1);
136
+ }
137
+ return count;
138
+ }
139
+
140
+ /**
141
+ * `days` with `today` checked in, or taken back where it was: in order, each once.
142
+ * @param {string[]} days
143
+ * @param {string} today
144
+ */
145
+ function toggled(days, today) {
146
+ const done = new Set(days);
147
+ if (done.has(today)) done.delete(today);
148
+ else done.add(today);
149
+ return [...done].sort();
150
+ }
151
+
152
+ /**
153
+ * The days of the `weeks` weeks that end with the one `today` is in, Monday first, oldest first: each its
154
+ * day (YYYY-MM-DD), its weekday (0 for Sunday), whether it was done, whether it is today, one to come
155
+ * (after today) and one of the streak (`streak`: the days of streakOf, back from today or yesterday).
156
+ * @param {string[]} days
157
+ * @param {string} today
158
+ * @param {number} [weeks]
159
+ */
160
+ function monthOf(days, today, weeks = 5) {
161
+ const done = new Set(days);
162
+ const streak = streakOf(days, today);
163
+ const last = done.has(today) ? today : dayAfter(today, -1);
164
+ const first = dayAfter(today, -((weekdayOf(today) + 6) % 7) - 7 * (weeks - 1));
165
+ return Array.from({ length: weeks * 7 }, (_, index) => {
166
+ const day = dayAfter(first, index);
167
+ return { day, weekday: weekdayOf(day), done: done.has(day), today: day === today, future: day > today, streak: day <= last && day > dayAfter(last, -streak) };
168
+ });
169
+ }
170
+
171
+ /**
172
+ * The week `today` is in, Monday to Sunday, as monthOf draws a day.
173
+ * @param {string[]} days
174
+ * @param {string} today
175
+ */
176
+ const weekOf = (days, today) => monthOf(days, today, 1);
177
+
178
+ /**
179
+ * Today checked in, or taken back: one write (context.editJSON), what a press of the button calls, and
180
+ * the example too. Whether it was taken.
181
+ * @param {DocComponentContext} context
182
+ * @param {string} today
183
+ */
184
+ function pressToday(context, today) {
185
+ return context.editJSON("habit", (data) => {
186
+ data.days = toggled(readHabit(data).days, today);
187
+ });
188
+ }
189
+
190
+ /**
191
+ * The habit named `name`, one write (context.editJSON): what the name's field calls once the reader is
192
+ * done with it. Whether it was taken.
193
+ * @param {DocComponentContext} context
194
+ * @param {string} name
195
+ */
196
+ function rename(context, name) {
197
+ return context.editJSON("habit", (data) => {
198
+ readHabit(data);
199
+ data.name = name.trim();
200
+ });
201
+ }
202
+
203
+ /**
204
+ * An element of the face, of `kind` (its class).
205
+ * @template {keyof HTMLElementTagNameMap} K
206
+ * @param {K} tag
207
+ * @param {string} kind
208
+ */
209
+ function made(tag, kind) {
210
+ const node = document.createElement(tag);
211
+ node.className = `gallery-habit-${kind}`;
212
+ return node;
213
+ }
214
+
215
+ const FLAME = '<path d="M12 20.8a6 6 0 0 0 6-6c0-3.6-2.4-5.6-3.6-8.6-.3-.8-1.3-1-1.8-.3-1.4 2-2 3.6-2 5-.9-.6-1.4-1.5-1.6-2.4-.1-.6-.9-.8-1.2-.2C6.9 9.6 6 11.4 6 14.8a6 6 0 0 0 6 6z"/>';
216
+ const CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5.5 12.5l4 4 9-9"/></svg>';
217
+
218
+ DocKit.component({
219
+ id: "gallery/habit",
220
+ on: ["source", "editable", "clock", "layout"],
221
+ mount(host, context) {
222
+ const words = WORDS[languageOf(document.documentElement)];
223
+ const face = made("div", "face");
224
+ const head = made("div", "head");
225
+ const chip = made("span", "chip");
226
+ chip.setAttribute("aria-hidden", "true");
227
+ chip.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">${FLAME}</svg>`;
228
+ const name = made("input", "name");
229
+ name.type = "text";
230
+ name.placeholder = words.name;
231
+ name.spellcheck = false;
232
+ name.setAttribute("aria-label", words.name);
233
+ // A narrow card's name as words of up to two lines over the field, which stays the one a press or Tab reaches (style.css).
234
+ const label = made("span", "label");
235
+ label.setAttribute("aria-hidden", "true");
236
+ const total = made("span", "total");
237
+ head.append(chip, name, label, total);
238
+ // The streak: its count large and its unit after it (a narrow card a flame before it), or, never
239
+ // checked in, a line inviting the first.
240
+ const row = made("div", "row");
241
+ const streak = made("p", "streak");
242
+ const flame = made("span", "flame");
243
+ flame.setAttribute("aria-hidden", "true");
244
+ flame.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${FLAME}</svg>`;
245
+ const count = made("strong", "count");
246
+ const unit = made("span", "unit");
247
+ streak.append(flame, count, unit);
248
+ const fresh = made("p", "fresh");
249
+ const press = made("button", "check");
250
+ press.type = "button";
251
+ row.append(streak, fresh, press);
252
+ // A tall card's five weeks: what they are and how many were done, over the month.
253
+ const caption = made("div", "caption");
254
+ const captionName = made("span", "caption-name");
255
+ captionName.textContent = words.weeks;
256
+ const captionCount = made("span", "caption-count");
257
+ caption.append(captionName, captionCount);
258
+ const week = made("ol", "week");
259
+ week.setAttribute("aria-label", words.week);
260
+ face.append(head, row, caption, week);
261
+ host.append(face);
262
+ const named = DocKit.input(name, { signal: context.signal, commit: (value) => rename(context, value) });
263
+ press.addEventListener("click", () => {
264
+ if (context.canEdit()) pressToday(context, dayOf(new Date()));
265
+ }, { signal: context.signal });
266
+
267
+ const draw = (/** @type {string} */ reason = "", /** @type {unknown} */ detail = null) => {
268
+ if (reason === "clock" && detail !== "day") return; // a minute moves no day
269
+ const size = context.size;
270
+ const layout = !size ? "wide" : size.w <= 2 ? "narrow" : size.h >= 4 ? "tall" : "wide";
271
+ if (face.dataset.layout !== layout) face.dataset.layout = layout;
272
+ const data = context.readJSON("habit");
273
+ if (data === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
274
+ let habit;
275
+ try {
276
+ habit = readHabit(data);
277
+ } catch (error) {
278
+ return context.fail(error);
279
+ }
280
+ const today = dayOf(new Date());
281
+ const writes = context.canEdit();
282
+ const done = habit.days.includes(today);
283
+ name.readOnly = !writes;
284
+ named.set(habit.name);
285
+ label.textContent = habit.name || words.name;
286
+ label.toggleAttribute("data-empty", !habit.name);
287
+ // Where nothing is written, the button is a line saying how today stands: nothing to press.
288
+ press.disabled = !writes;
289
+ press.classList.toggle("gallery-habit-done", done);
290
+ if (writes && done) press.innerHTML = `${CHECK}<span>${words.checked}</span>`;
291
+ else press.textContent = writes ? words.check : (done ? words.todayDone : words.todayOpen);
292
+ press.title = writes && done ? words.undo : "";
293
+ press.setAttribute("aria-pressed", String(done));
294
+ face.toggleAttribute("data-fresh", habit.days.length === 0);
295
+ const days = streakOf(habit.days, today);
296
+ count.textContent = String(days);
297
+ unit.textContent = layout === "narrow" ? words.unit(days) : words.streak;
298
+ fresh.replaceChildren(...(layout === "narrow" ? [words.fresh[0]] : [words.fresh[0], document.createElement("br"), words.fresh[1]]));
299
+ total.textContent = habit.days.length > 0 ? words.total(new Set(habit.days).size) : "";
300
+ const span = layout === "tall" ? 5 : 1;
301
+ const shown = monthOf(habit.days, today, span);
302
+ week.dataset.weeks = String(span);
303
+ const [before, got, after] = words.got(shown.filter((day) => day.done && !day.future).length);
304
+ const bold = document.createElement("b");
305
+ bold.textContent = got;
306
+ captionCount.replaceChildren(before, bold, after);
307
+ const initials = span === 5 ? [1, 2, 3, 4, 5, 6, 0].map((weekday) => {
308
+ const item = made("li", "initial");
309
+ item.setAttribute("aria-hidden", "true");
310
+ item.textContent = words.initials[weekday];
311
+ return item;
312
+ }) : [];
313
+ week.replaceChildren(...initials, ...shown.map(({ day, weekday, done: kept, today: now, future, streak: inStreak }) => {
314
+ const item = made("li", "day");
315
+ item.classList.toggle("gallery-habit-kept", kept);
316
+ item.classList.toggle("gallery-habit-today", now);
317
+ item.classList.toggle("gallery-habit-future", future);
318
+ item.classList.toggle("gallery-habit-streak-day", inStreak);
319
+ const [, month, date] = day.split("-").map(Number);
320
+ item.setAttribute("aria-label", words.day(month, date, kept));
321
+ item.title = words.day(month, date, kept);
322
+ // A week's circle says its day by its initial (今 for today), a month's by its date; a day done of a week, a tick.
323
+ if (span === 1 && kept && !future) item.innerHTML = CHECK;
324
+ else item.textContent = span === 5 ? String(date) : now && words.today ? words.today : words.initials[weekday];
325
+ return item;
326
+ }));
327
+ };
328
+ draw();
329
+ return { update: draw };
330
+ },
331
+ example(host, context) {
332
+ pressToday(context, dayOf(new Date()));
333
+ },
334
+ });
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 120"><rect width="240" height="120" rx="8" fill="#f3f3f1"/><rect x="16.5" y="12.5" width="207" height="95" rx="8" fill="#ffffff" stroke="#e6e6e3"/><rect x="28" y="22" width="10" height="10" rx="3" fill="#fdf1dd"/><rect x="42" y="24.5" width="54" height="5" rx="2.5" fill="#37352f"/><rect x="100" y="24.5" width="20" height="5" rx="2.5" fill="#d4d3cf"/><rect x="28" y="42" width="24" height="20" rx="3" fill="#1d1d1b"/><rect x="56" y="56" width="22" height="5" rx="2.5" fill="#a6a5a1"/><rect x="176" y="42" width="36" height="18" rx="5" fill="#ebf2fa"/><rect x="186" y="48.5" width="16" height="5" rx="2.5" fill="#4084cf"/><circle cx="37" cy="88" r="9" fill="#4084cf"/><path d="M33.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="66" cy="88" r="9" fill="#4084cf"/><path d="M62.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="95" cy="88" r="9" fill="#4084cf"/><path d="M91.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="124" cy="88" r="8.4" fill="none" stroke="#4084cf" stroke-width="1.3"/><circle cx="153" cy="88" r="8.6" fill="none" stroke="#ebebe9"/><circle cx="182" cy="88" r="8.6" fill="none" stroke="#ebebe9"/><circle cx="211" cy="88" r="8.6" fill="none" stroke="#ebebe9"/></svg>
@@ -0,0 +1,174 @@
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 pack's design B, in the kit's card tokens, laid out by the card's cells
3
+ (the face's data-layout): "wide" (4 × 2) the head (a flame's warm chip, the name, a field with no line
4
+ until it is typed in, the days in all after it, faint), the streak (36px) and 天连续 with the button at
5
+ its right, and this week's seven circles at the bottom; "narrow" (2 × 2) the name alone (13px, 600, two lines at most), a
6
+ flame and the streak (40px), and the button as wide as the card; "tall" (4 × 4) the head, the streak and
7
+ the button, 最近五周 and its count, and five weeks of circles of 26px. A day done the accent, ticked; one
8
+ done before the streak (a month's) the accent's pale tint; today ringed in the accent; the days to come
9
+ an outline. The button has no line: a pale blue 打卡, a pale green ✓ 已打卡, a line of words where nothing
10
+ writes. Never checked in: 还没打过卡 where the streak stands, the chip gray. Light and dark. */
11
+ [data-doc-component="gallery/habit"] {
12
+ font-family: var(--gallery-font);
13
+ font-size: 13px;
14
+ line-height: 1.5;
15
+ color: var(--gallery-text);
16
+ > .gallery-habit-face { display: flex; flex-direction: column; box-sizing: border-box; min-height: 0; }
17
+ > .gallery-habit-face > .gallery-habit-head {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: 8px;
21
+ flex: none;
22
+ height: 20px;
23
+ min-width: 0;
24
+ padding-inline-end: var(--gallery-grip-room, 0px);
25
+ }
26
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-chip {
27
+ flex: none;
28
+ display: grid;
29
+ place-items: center;
30
+ width: var(--gallery-chip-size);
31
+ height: var(--gallery-chip-size);
32
+ border-radius: var(--gallery-chip-radius);
33
+ background: var(--gallery-warm-soft);
34
+ color: var(--gallery-warm);
35
+ }
36
+ > .gallery-habit-face[data-fresh] > .gallery-habit-head > .gallery-habit-chip { background: var(--gallery-fill); color: var(--gallery-muted); }
37
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-chip > svg { display: block; width: var(--gallery-chip-icon); height: var(--gallery-chip-icon); }
38
+ /* The name: a field drawn as the head's title, as wide as its words (field-sizing), a soft fill while typed in. */
39
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name {
40
+ field-sizing: content;
41
+ min-width: 2em;
42
+ max-width: 100%;
43
+ flex: 0 1 auto;
44
+ box-sizing: border-box;
45
+ height: 20px;
46
+ margin: 0 -4px;
47
+ padding: 0 4px;
48
+ border: 0;
49
+ border-radius: 4px;
50
+ outline: 0;
51
+ background: transparent;
52
+ font: inherit;
53
+ font-size: var(--gallery-title-size);
54
+ line-height: var(--gallery-title-line);
55
+ font-weight: 600;
56
+ color: var(--gallery-text);
57
+ text-overflow: ellipsis;
58
+ }
59
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name::placeholder { color: var(--gallery-faint); font-weight: 500; }
60
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name:not(:read-only):is(:hover, :focus) { background: var(--gallery-hover); }
61
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-name:read-only { cursor: default; }
62
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-label { display: none; }
63
+ > .gallery-habit-face > .gallery-habit-head > .gallery-habit-total { flex: none; font-size: var(--gallery-meta-size); color: var(--gallery-faint); white-space: nowrap; font-variant-numeric: tabular-nums; }
64
+ > .gallery-habit-face > .gallery-habit-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 8px; margin-top: 10px; flex: none; }
65
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-streak { display: flex; align-items: baseline; margin: 0; min-width: 0; }
66
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-flame { display: none; align-self: center; margin-right: 4px; color: var(--gallery-warm); }
67
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-flame > svg { display: block; width: 18px; height: 18px; }
68
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-count {
69
+ font-size: 36px;
70
+ line-height: 1;
71
+ font-weight: var(--gallery-numeral-weight);
72
+ letter-spacing: var(--gallery-numeral-tracking);
73
+ font-variant-numeric: lining-nums;
74
+ color: var(--gallery-text-strong);
75
+ }
76
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-unit { margin-left: 3px; font-size: var(--gallery-unit); font-weight: 500; color: var(--gallery-muted); white-space: nowrap; }
77
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-fresh { display: none; margin: 0; font-size: 12.5px; line-height: 18px; color: var(--gallery-faint); }
78
+ > .gallery-habit-face[data-fresh] > .gallery-habit-row > .gallery-habit-streak { display: none; }
79
+ > .gallery-habit-face[data-fresh] > .gallery-habit-row > .gallery-habit-fresh { display: block; }
80
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check {
81
+ display: inline-flex;
82
+ align-items: center;
83
+ justify-content: center;
84
+ gap: 5px;
85
+ flex: none;
86
+ height: 30px;
87
+ padding: 0 14px;
88
+ border: 0;
89
+ border-radius: 8px;
90
+ background: var(--gallery-accent-soft);
91
+ color: var(--gallery-accent-ink);
92
+ font: inherit;
93
+ font-size: 13px;
94
+ font-weight: 600;
95
+ white-space: nowrap;
96
+ cursor: pointer;
97
+ transition: background-color .12s ease-out;
98
+ }
99
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check:hover { background: color-mix(in srgb, var(--gallery-accent) 18%, var(--gallery-accent-soft)); }
100
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check:focus-visible { outline: 2px solid var(--gallery-accent-wash); outline-offset: 1px; }
101
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check.gallery-habit-done { background: var(--gallery-good-soft); color: var(--gallery-good-ink); }
102
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check.gallery-habit-done:hover { background: color-mix(in srgb, var(--gallery-good) 18%, var(--gallery-good-soft)); }
103
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check > svg { display: block; width: 13px; height: 13px; }
104
+ > .gallery-habit-face > .gallery-habit-row > .gallery-habit-check:disabled { padding: 0; background: transparent; color: var(--gallery-faint); font-weight: 500; cursor: default; }
105
+ > .gallery-habit-face > .gallery-habit-caption { display: none; }
106
+ /* This week: seven circles at the bottom, 4px in from either side, so that today's second ring, done,
107
+ stays inside the content on a Monday and a Sunday too. */
108
+ > .gallery-habit-face > .gallery-habit-week { display: flex; justify-content: space-between; margin: auto 0 0; padding: 0 4px; list-style: none; }
109
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-day {
110
+ display: grid;
111
+ place-items: center;
112
+ flex: none;
113
+ width: 28px;
114
+ height: 28px;
115
+ border-radius: 50%;
116
+ background: var(--gallery-fill);
117
+ font-size: 11px;
118
+ line-height: 1;
119
+ color: var(--gallery-faint);
120
+ font-variant-numeric: tabular-nums;
121
+ }
122
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-day > svg { display: block; width: 13px; height: 13px; }
123
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-kept { background: var(--gallery-accent); color: #fff; }
124
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-today { background: transparent; box-shadow: inset 0 0 0 1.5px var(--gallery-accent); color: var(--gallery-accent-ink); font-weight: 600; }
125
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-today.gallery-habit-kept { background: var(--gallery-accent); color: #fff; box-shadow: 0 0 0 2px var(--gallery-card-fill), 0 0 0 3.5px var(--gallery-accent); }
126
+ > .gallery-habit-face > .gallery-habit-week > .gallery-habit-future { background: transparent; box-shadow: inset 0 0 0 1px var(--gallery-hair); color: var(--gallery-faintest); }
127
+
128
+ /* A narrow card: the name, the streak with its flame, the button as wide as the card. */
129
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > :is(.gallery-habit-chip, .gallery-habit-total) { display: none; }
130
+ /* Its name: the words, 13px and 600 on 18px lines, two lines at most and then cut (…), 12px clear of the
131
+ card's edge (the grip's dots end 9px into the content); the field lies over them unseen, the one a
132
+ press or Tab reaches, and stands in their place, one line, while it has the focus. */
133
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head { position: relative; display: block; height: auto; padding-inline-end: 0; }
134
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-label {
135
+ display: -webkit-box;
136
+ -webkit-box-orient: vertical;
137
+ -webkit-line-clamp: 2;
138
+ overflow: hidden;
139
+ margin: 0 -4px;
140
+ padding: 0 16px 0 4px;
141
+ border-radius: 4px;
142
+ font-size: 13px;
143
+ line-height: 18px;
144
+ font-weight: 600;
145
+ color: var(--gallery-text);
146
+ overflow-wrap: anywhere;
147
+ }
148
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-label[data-empty] { font-weight: 500; color: var(--gallery-faint); }
149
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-name { position: absolute; inset: 0 auto auto 0; width: calc(100% + 8px); max-width: none; height: 100%; opacity: 0; line-height: 18px; }
150
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-name:read-only { pointer-events: none; }
151
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-name:not(:read-only):hover + .gallery-habit-label { background: var(--gallery-hover); }
152
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-name:not(:read-only):focus { width: calc(100% + 8px - var(--gallery-grip-room, 0px) * var(--gallery-grip-shown, 0)); height: 18px; opacity: 1; }
153
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-head > .gallery-habit-name:not(:read-only):focus + .gallery-habit-label { visibility: hidden; }
154
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-row { display: contents; }
155
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-row > :is(.gallery-habit-streak, .gallery-habit-fresh) { margin: auto 0 10px; }
156
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-flame { display: block; }
157
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-row > .gallery-habit-streak > .gallery-habit-count { font-size: 40px; }
158
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-row > .gallery-habit-check { width: 100%; margin-top: auto; }
159
+ > .gallery-habit-face[data-layout="narrow"] > .gallery-habit-week { display: none; }
160
+ /* A tall card: five weeks of circles under 最近五周. */
161
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-caption { display: flex; justify-content: space-between; margin: auto 0 8px; font-size: 11.5px; line-height: 16px; color: var(--gallery-faint); white-space: nowrap; }
162
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-caption b { font-weight: 600; color: var(--gallery-muted); }
163
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week { display: grid; grid-template-columns: repeat(7, 1fr); row-gap: 5px; justify-items: center; margin: 0; padding: 0; }
164
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-initial { height: 14px; font-size: 10.5px; line-height: 14px; color: var(--gallery-faint); }
165
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-day { width: 26px; height: 26px; font-size: 10.5px; background: transparent; color: var(--gallery-faint); }
166
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-kept { background: var(--gallery-accent-soft); color: var(--gallery-accent-ink); }
167
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-kept.gallery-habit-streak-day { background: var(--gallery-accent); color: #fff; }
168
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-today { background: transparent; box-shadow: inset 0 0 0 1.5px var(--gallery-accent); color: var(--gallery-accent-ink); }
169
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-today.gallery-habit-kept { background: var(--gallery-accent); color: #fff; box-shadow: 0 0 0 2px var(--gallery-card-fill), 0 0 0 3.5px var(--gallery-accent); }
170
+ > .gallery-habit-face[data-layout="tall"] > .gallery-habit-week > .gallery-habit-future { background: transparent; box-shadow: inset 0 0 0 1px var(--gallery-hair); color: var(--gallery-faintest); }
171
+ }
172
+ /* On a custom page the face fills the card the board frames. */
173
+ .gallery-card > [data-doc-component="gallery/habit"] { height: 100%; }
174
+ .gallery-card > [data-doc-component="gallery/habit"] > .gallery-habit-face { 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, this week's seven days), 2 × 2 (the name, the streak, the button as wide as the card) and 4 × 4 (the last five weeks as a month).
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
+ In Gallery 风格's look (the kit's card tokens, light and dark): a head of a small gray chip and a title, its end clear of the card's grip; one hero; the rest small and gray; the accent on the data and on today alone. Its head is a flame's warm chip, the habit's name (a field: click to rename) and the days in all (共 41 天); the streak is the hero (36px, 天连续 after it), the button at its right a pale blue 打卡, a pale green ✓ 已打卡 once pressed (a press takes it back). A 4 × 2 card's foot is this week, seven circles Monday to Sunday: a day done the accent with a tick, one missed a soft gray, today ringed in the accent (今), the days to come an outline. A 4 × 4 card shows the last five weeks as a month instead, the days of the streak in the accent, those done before it its pale tint, with how many were done. Never checked in, it says 还没打过卡 where the streak stands. It changes by itself at midnight.
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "gallery/heatmap",
3
+ "apiVersion": 1,
4
+ "version": "2.0.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, 4], [12, 4], [4, 4], [12, 3], [8, 3], [8, 2]], "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>