@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,366 @@
1
+ // gallery-soft/habit (习惯打卡, 柔光风格): Gallery 风格's gallery/habit in the soft look, the same logic and
2
+ // data. One habit, checked in once a day. Its data part, a script of JSON, holds the habit's name and the
3
+ // days it was done, each YYYY-MM-DD by the reader's clock, in order: { "name": "喝八杯水", "days":
4
+ // ["2026-11-05", "2026-11-06"] }. The card draws the name in a field of its own in its head (DocKit.input:
5
+ // written as the reader presses Enter or leaves it, never while an input method composes), the streak (the
6
+ // days in a row up to today, or up to yesterday while today is not checked yet, so that a streak lasts the
7
+ // day it is to be kept), how many days in all, and a way to check today in, or take today's check-in back
8
+ // when it is there. Each press and each name is one context.editJSON, one undo step, the JSON written back on
9
+ // one line as it was: what the reader does is in the file, and nothing else is (the streak, the days and the
10
+ // calendar are worked out as it draws). It draws from the part on every `source` (an undo, an Agent's write)
11
+ // and again as a day begins (the kit's `clock`, "day"), so that "today" moves at midnight. Where nothing
12
+ // takes its writes (an export, a page that has not come to edit yet: context.canEdit() false) the name is
13
+ // read-only and nothing can be pressed: the button a plain line saying whether today is done.
14
+ //
15
+ // Its face, laid out by its card's size (`context.size`, read again on `layout`; data-w, data-h, data-pad):
16
+ // a head of a flame's warm chip, the name and the days in all at its end (共 42 天); the streak the hero
17
+ // (连续打卡 over its count). A 4 × 2 card sets the last seven days beside it as a row of dots, a check in
18
+ // each one done, today's the button itself (a ring with a plus that a press fills); a 2 × 2 card the streak
19
+ // over a button as wide as the card (打卡, or 已打卡 in green); a 4 × 4 card the streak, the longest one and
20
+ // the button, over the last four weeks as a calendar, Monday first, each day done tinted, today ringed. A
21
+ // habit never checked in shows, where the streak stands, a line inviting the first (还没打过卡, 从今天开始).
22
+ // Its words are the page's language (the UI's where Gallery says it, else the page's lang).
23
+
24
+ const WORDS = {
25
+ zh: {
26
+ name: "给习惯起个名字",
27
+ nameShort: "起个名字",
28
+ check: "打卡",
29
+ checked: "已打卡",
30
+ undo: "再按一下,撤回今天的打卡",
31
+ todayDone: "今天已打卡",
32
+ todayOpen: "今天还没打卡",
33
+ streak: "连续打卡",
34
+ streakShort: "连续",
35
+ unit: () => "天",
36
+ total: (/** @type {number} */ days) => `共 ${days} 天`,
37
+ longest: (/** @type {number} */ days) => `最长 ${days} 天`,
38
+ fresh: "还没打过卡",
39
+ freshHow: "从今天开始",
40
+ week: "最近七天",
41
+ weekdays: ["日", "一", "二", "三", "四", "五", "六"],
42
+ monday: ["一", "二", "三", "四", "五", "六", "日"],
43
+ today: "今",
44
+ day: (/** @type {number} */ month, /** @type {number} */ day, /** @type {boolean} */ done) => `${month}月${day}日${done ? ",已打卡" : ",没打卡"}`,
45
+ },
46
+ en: {
47
+ name: "Name this habit",
48
+ nameShort: "Name it",
49
+ check: "Check in",
50
+ checked: "Done",
51
+ undo: "Press again to take today's check-in back",
52
+ todayDone: "Done today",
53
+ todayOpen: "Not done today",
54
+ streak: "Streak",
55
+ streakShort: "Streak",
56
+ unit: (/** @type {number} */ days) => (days === 1 ? "day" : "days"),
57
+ total: (/** @type {number} */ days) => `${days} ${days === 1 ? "day" : "days"} in all`,
58
+ longest: (/** @type {number} */ days) => `Best ${days}`,
59
+ fresh: "No check-ins yet",
60
+ freshHow: "Start today",
61
+ week: "The last seven days",
62
+ weekdays: ["S", "M", "T", "W", "T", "F", "S"],
63
+ monday: ["M", "T", "W", "T", "F", "S", "S"],
64
+ today: "Today",
65
+ 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"}`,
66
+ },
67
+ };
68
+
69
+ /** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
70
+ function languageOf(/** @type {HTMLElement} */ root) {
71
+ const ui = root.getAttribute("data-ge-language");
72
+ return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
73
+ }
74
+
75
+ const DAY = /^\d{4}-\d{2}-\d{2}$/;
76
+
77
+ /**
78
+ * A day of the reader's clock as the data writes it, YYYY-MM-DD.
79
+ * @param {Date} date
80
+ */
81
+ function dayOf(date) {
82
+ const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
83
+ return `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())}`;
84
+ }
85
+
86
+ /**
87
+ * The day `count` days after `day` (before it for a count below 0), both YYYY-MM-DD, by the calendar
88
+ * (counted in UTC, so that a change of the clocks changes nothing).
89
+ * @param {string} day
90
+ * @param {number} count
91
+ */
92
+ function dayAfter(day, count) {
93
+ const [year, month, date] = day.split("-").map(Number);
94
+ const moved = new Date(Date.UTC(year, month - 1, date + count));
95
+ const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
96
+ return `${moved.getUTCFullYear()}-${two(moved.getUTCMonth() + 1)}-${two(moved.getUTCDate())}`;
97
+ }
98
+
99
+ /** The weekday of a day (YYYY-MM-DD), 0 for Sunday. @param {string} day */
100
+ function weekdayOf(day) {
101
+ const [year, month, date] = day.split("-").map(Number);
102
+ return new Date(Date.UTC(year, month - 1, date)).getUTCDay();
103
+ }
104
+
105
+ /**
106
+ * The habit `data` is (context.readJSON's, or the draft context.editJSON hands a change): its name ("" for
107
+ * none yet) and its days, as they stand; throws saying why it is none, and the block draws nothing over it.
108
+ * @param {any} data
109
+ * @returns {{ name: string, days: string[] }}
110
+ */
111
+ function readHabit(data) {
112
+ 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\", …] }");
113
+ const name = data.name ?? "";
114
+ if (typeof name !== "string") throw new Error("its name is no string");
115
+ const days = data.days ?? [];
116
+ 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");
117
+ return { name, days };
118
+ }
119
+
120
+ /**
121
+ * The days in a row that end today, or yesterday while today is not checked yet (a streak lasts the day
122
+ * it is to be kept); 0 when neither was done.
123
+ * @param {string[]} days
124
+ * @param {string} today
125
+ */
126
+ function streakOf(days, today) {
127
+ const done = new Set(days);
128
+ let day = done.has(today) ? today : dayAfter(today, -1);
129
+ let count = 0;
130
+ while (done.has(day)) {
131
+ count += 1;
132
+ day = dayAfter(day, -1);
133
+ }
134
+ return count;
135
+ }
136
+
137
+ /**
138
+ * The longest run of days in a row the habit was done, 0 for none (the 4 × 4 card's 最长).
139
+ * @param {string[]} days
140
+ */
141
+ function longestOf(days) {
142
+ const sorted = [...new Set(days)].sort();
143
+ let longest = 0;
144
+ let run = 0;
145
+ sorted.forEach((day, index) => {
146
+ run = index > 0 && dayAfter(sorted[index - 1], 1) === day ? run + 1 : 1;
147
+ longest = Math.max(longest, run);
148
+ });
149
+ return longest;
150
+ }
151
+
152
+ /**
153
+ * `days` with `today` checked in, or taken back where it was: in order, each once.
154
+ * @param {string[]} days
155
+ * @param {string} today
156
+ */
157
+ function toggled(days, today) {
158
+ const done = new Set(days);
159
+ if (done.has(today)) done.delete(today);
160
+ else done.add(today);
161
+ return [...done].sort();
162
+ }
163
+
164
+ /**
165
+ * The seven days that end today, the oldest first: each its day (YYYY-MM-DD), its weekday (0 for
166
+ * Sunday) and whether it was done.
167
+ * @param {string[]} days
168
+ * @param {string} today
169
+ */
170
+ function weekOf(days, today) {
171
+ const done = new Set(days);
172
+ return Array.from({ length: 7 }, (_, index) => {
173
+ const day = dayAfter(today, index - 6);
174
+ return { day, weekday: weekdayOf(day), done: done.has(day) };
175
+ });
176
+ }
177
+
178
+ /**
179
+ * The last `weeks` weeks to the one of `today`, Monday first, as the 4 × 4 card's calendar draws them: each
180
+ * day its date (YYYY-MM-DD), whether it was done, whether it is today and whether it is still to come.
181
+ * @param {string[]} days
182
+ * @param {string} today
183
+ * @param {number} [weeks]
184
+ */
185
+ function calendarOf(days, today, weeks = 4) {
186
+ const done = new Set(days);
187
+ const first = dayAfter(today, -((weekdayOf(today) + 6) % 7) - 7 * (weeks - 1));
188
+ return Array.from({ length: 7 * weeks }, (_, index) => {
189
+ const day = dayAfter(first, index);
190
+ return { day, done: done.has(day), today: day === today, future: day > today };
191
+ });
192
+ }
193
+
194
+ /**
195
+ * Today checked in, or taken back: one write (context.editJSON), what a press of the button calls, and
196
+ * the example too. Whether it was taken.
197
+ * @param {DocComponentContext} context
198
+ * @param {string} today
199
+ */
200
+ function pressToday(context, today) {
201
+ return context.editJSON("habit", (data) => {
202
+ data.days = toggled(readHabit(data).days, today);
203
+ });
204
+ }
205
+
206
+ /**
207
+ * The habit named `name`, one write (context.editJSON): what the name's field calls once the reader is
208
+ * done with it. Whether it was taken.
209
+ * @param {DocComponentContext} context
210
+ * @param {string} name
211
+ */
212
+ function rename(context, name) {
213
+ return context.editJSON("habit", (data) => {
214
+ readHabit(data);
215
+ data.name = name.trim();
216
+ });
217
+ }
218
+
219
+ /**
220
+ * The size the face is laid out by: its card's cells (`context.size`), or `fallback` (the manifest's first
221
+ * size) where no card is; and the frame's padding for it, as the soft cards pad theirs: "xs" on a card one
222
+ * cell high, "s" on a small one (2 × 2 and less), "l" on one 3 cells high or more, else "m".
223
+ * @param {DocComponentSize | null | undefined} size
224
+ * @param {[number, number]} fallback
225
+ */
226
+ function sizeOf(size, fallback) {
227
+ const w = size?.w ?? fallback[0];
228
+ const h = size?.h ?? fallback[1];
229
+ return { w, h, pad: h === 1 ? "xs" : w <= 2 && h <= 2 ? "s" : h >= 3 ? "l" : "m" };
230
+ }
231
+
232
+ /**
233
+ * An element of the face, of `kind` (its class).
234
+ * @template {keyof HTMLElementTagNameMap} K
235
+ * @param {K} tag
236
+ * @param {string} kind
237
+ * @param {string} [text]
238
+ */
239
+ function made(tag, kind, text) {
240
+ const node = document.createElement(tag);
241
+ node.className = `gallery-soft-habit-${kind}`;
242
+ if (text !== undefined) node.textContent = text;
243
+ return node;
244
+ }
245
+
246
+ const CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.5l4.3 4.3L19 7.3"/></svg>';
247
+ const PLUS = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg>';
248
+
249
+ DocKit.component({
250
+ id: "gallery-soft/habit",
251
+ on: ["source", "editable", "clock", "layout"],
252
+ mount(host, context) {
253
+ const words = WORDS[languageOf(document.documentElement)];
254
+ const face = made("div", "face");
255
+ const head = made("div", "head");
256
+ const chip = made("span", "chip");
257
+ chip.setAttribute("aria-hidden", "true");
258
+ chip.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.2c.6 3 4.8 5 4.8 9.8a4.8 4.8 0 0 1-9.6 0c0-2.1.9-3.6 2.1-4.6.2 1.6 1 2.5 2 2.8-.6-2.6-.3-5.2.7-8z"/></svg>';
259
+ const name = made("input", "name");
260
+ name.type = "text";
261
+ name.placeholder = words.name;
262
+ name.spellcheck = false;
263
+ name.setAttribute("aria-label", words.name);
264
+ const total = made("span", "total");
265
+ head.append(chip, name, total);
266
+ // The streak: its label over its count, the count large and its unit after it; the longest beside it on a tall card.
267
+ const streak = made("div", "streak");
268
+ const label = made("span", "label", words.streak);
269
+ const figure = made("p", "figure");
270
+ const before = made("span", "before", words.streakShort);
271
+ const count = made("strong", "count");
272
+ const unit = made("span", "unit");
273
+ figure.append(before, count, unit);
274
+ const longest = made("span", "longest");
275
+ const row = made("div", "row");
276
+ row.append(figure, longest);
277
+ streak.append(label, row);
278
+ // Never checked in: this, where the streak stands.
279
+ const fresh = made("p", "fresh");
280
+ fresh.append(made("span", "fresh-line", words.fresh), made("span", "fresh-how", words.freshHow));
281
+ const press = made("button", "check");
282
+ press.type = "button";
283
+ const week = made("ol", "week");
284
+ week.setAttribute("aria-label", words.week);
285
+ const calendar = made("div", "calendar");
286
+ calendar.setAttribute("aria-hidden", "true");
287
+ const top = made("div", "top");
288
+ top.append(streak, fresh, press);
289
+ face.append(head, top, week, calendar);
290
+ host.append(face);
291
+ const named = DocKit.input(name, { signal: context.signal, commit: (value) => rename(context, value) });
292
+ const pressed = () => {
293
+ if (context.canEdit()) pressToday(context, dayOf(new Date()));
294
+ };
295
+ press.addEventListener("click", pressed, { signal: context.signal });
296
+
297
+ const draw = (/** @type {string} */ reason = "", /** @type {unknown} */ detail = null) => {
298
+ if (reason === "clock" && detail !== "day") return; // a minute moves no day
299
+ const data = context.readJSON("habit");
300
+ if (data === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
301
+ let habit;
302
+ try {
303
+ habit = readHabit(data);
304
+ } catch (error) {
305
+ return context.fail(error);
306
+ }
307
+ const { w, h, pad } = sizeOf(context.size, [4, 2]);
308
+ Object.assign(face.dataset, { w: String(w), h: String(h), pad });
309
+ name.placeholder = pad === "s" ? words.nameShort : words.name; // a 2 × 2 card's head holds no more
310
+ const today = dayOf(new Date());
311
+ const writes = context.canEdit();
312
+ const done = habit.days.includes(today);
313
+ name.readOnly = !writes;
314
+ named.set(habit.name);
315
+ face.toggleAttribute("data-named", habit.name.trim() !== "");
316
+ // Where nothing is written, the button is a line saying how today stands: nothing to press.
317
+ press.disabled = !writes;
318
+ press.classList.toggle("gallery-soft-habit-done", done);
319
+ press.innerHTML = writes ? `${done ? CHECK : PLUS}<span></span>` : "<span></span>";
320
+ /** @type {HTMLElement} */ (press.lastElementChild).textContent = writes ? (done ? words.checked : words.check) : (done ? words.todayDone : words.todayOpen);
321
+ press.title = writes && done ? words.undo : "";
322
+ press.setAttribute("aria-pressed", String(done));
323
+ face.toggleAttribute("data-fresh", habit.days.length === 0);
324
+ const days = streakOf(habit.days, today);
325
+ count.textContent = String(days);
326
+ unit.textContent = words.unit(days);
327
+ total.textContent = habit.days.length > 0 ? words.total(new Set(habit.days).size) : "";
328
+ longest.textContent = habit.days.length > 0 ? words.longest(longestOf(habit.days)) : "";
329
+ // The last seven days, today's dot the button.
330
+ week.replaceChildren(...weekOf(habit.days, today).map(({ day, weekday, done: kept }) => {
331
+ const item = made("li", "day");
332
+ const now = day === today;
333
+ item.classList.toggle("gallery-soft-habit-kept", kept);
334
+ item.classList.toggle("gallery-soft-habit-today", now);
335
+ const [, month, date] = day.split("-").map(Number);
336
+ item.title = now && writes && kept ? words.undo : words.day(month, date, kept);
337
+ const dot = made(now ? "button" : "span", now ? "today-press" : "dot");
338
+ dot.innerHTML = kept ? CHECK : now ? PLUS : "";
339
+ if (now) {
340
+ // Today's dot is the button: pressed, today is checked in or taken back.
341
+ const button = /** @type {HTMLButtonElement} */ (dot);
342
+ button.type = "button";
343
+ button.disabled = !writes;
344
+ button.setAttribute("aria-pressed", String(kept));
345
+ button.setAttribute("aria-label", writes ? (kept ? words.checked : words.check) : (kept ? words.todayDone : words.todayOpen));
346
+ button.addEventListener("click", pressed);
347
+ } else item.setAttribute("aria-label", words.day(month, date, kept));
348
+ item.append(dot, made("span", "weekday", now ? words.today : words.weekdays[weekday]));
349
+ return item;
350
+ }));
351
+ // The last four weeks, Monday first, under their weekdays' initials.
352
+ calendar.replaceChildren(...words.monday.map((initial) => made("span", "initial", initial)), ...calendarOf(habit.days, today).map((one) => {
353
+ const cell = made("span", "date", String(Number(one.day.slice(8))));
354
+ cell.classList.toggle("gallery-soft-habit-on", one.done && !one.future);
355
+ cell.classList.toggle("gallery-soft-habit-now", one.today && !one.done);
356
+ cell.classList.toggle("gallery-soft-habit-future", one.future);
357
+ return cell;
358
+ }));
359
+ };
360
+ draw();
361
+ return { update: draw };
362
+ },
363
+ example(host, context) {
364
+ pressToday(context, dayOf(new Date()));
365
+ },
366
+ });
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 120"><defs><linearGradient id="w" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#3e7ac6" stop-opacity=".07"/><stop offset=".52" stop-color="#3e7ac6" stop-opacity="0"/></linearGradient></defs><rect width="240" height="120" rx="8" fill="#f3f3f1"/><rect x="16.5" y="12.5" width="207" height="95" rx="14" fill="#ffffff" stroke="#e8e7e4"/><rect x="17" y="13" width="206" height="94" rx="13.5" fill="url(#w)"/><rect x="30" y="24" width="14" height="14" rx="4.5" fill="#fdf1df"/><rect x="34" y="30" width="6" height="2" rx="1" fill="#e59a2c"/><rect x="50" y="28" width="60" height="6" rx="3" fill="#37352f"/><rect x="180" y="28" width="24" height="6" rx="3" fill="#c4c2bd"/><rect x="30" y="56" width="32" height="5" rx="2.5" fill="#c4c2bd"/><rect x="30" y="68" width="26" height="22" rx="11" fill="#1f1f1f"/><circle cx="110" cy="74" r="6" fill="#3e7ac6"/><circle cx="125.5" cy="74" r="6" fill="#3e7ac6"/><circle cx="141" cy="74" r="6" fill="#3e7ac6"/><circle cx="156.5" cy="74" r="6" fill="#3e7ac6"/><circle cx="172" cy="74" r="6" fill="#3e7ac6"/><circle cx="187.5" cy="74" r="6" fill="#3e7ac6"/><circle cx="203" cy="74" r="6" fill="none" stroke="#3e7ac6" stroke-width="1.5"/><rect x="108" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="123.5" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="139" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="154.5" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="170" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="185.5" y="86" width="4" height="3" rx="1.5" fill="#c4c2bd"/><rect x="201" y="86" width="4" height="3" rx="1.5" fill="#3e7ac6"/></svg>
@@ -0,0 +1,251 @@
1
+ /* 柔光风格's habit. Every selector starts at the instance and goes down a step at a time (>), so that nothing
2
+ here reaches the rest of the page. The soft look's tokens first, light and dark (light-dark(): the page's
3
+ color scheme, which follows its theme), then the face: a faint wash of the accent from the card's top over
4
+ the soft card's fill; a head of a flame's warm chip, the habit's name (a field with no line of its own, its
5
+ placeholder faint) and the days in all at its end, fading while the card's grip shows; the streak the hero.
6
+ By the card's size (the face's data-w, data-h and data-pad, from the script): 4 × 2, the streak under its
7
+ label and the last seven days beside it, a disc each, the accent's with a check where done, today's the
8
+ button (a ring of the accent with a plus, filled once pressed); 2 × 2, 连续 and the streak over a button as
9
+ wide as the card; 4 × 4, the streak, the longest in a gray pill and the button over the last four weeks, a
10
+ small disc a day, tinted where done, today ringed, the days to come faint. Buttons have no line: a primary
11
+ one pale blue, done pale green, a shade deeper under the pointer. On a custom page the face is the card's
12
+ whole room, taken out over the card's padding and given the soft frame's, the board's line around it;
13
+ where no card is (a document, as gallery block check shows it) the face frames itself at a 4 × 2 card's size. */
14
+ [data-doc-component="gallery-soft/habit"] {
15
+ --soft-font: "PingFang SC", "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
16
+ --soft-num: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
17
+ --soft-card: light-dark(#ffffff, #1f1f20);
18
+ --soft-card-line: light-dark(rgb(28 28 32 / 6.5%), rgb(255 255 255 / 7.5%));
19
+ --soft-card-shadow: 0 0 0 1px var(--soft-card-line), 0 1px 2px light-dark(rgb(28 28 32 / 3.5%), rgb(0 0 0 / 0%)), 0 8px 24px -14px light-dark(rgb(28 28 32 / 12%), rgb(0 0 0 / 60%));
20
+ --soft-wash: linear-gradient(180deg, light-dark(rgb(62 122 198 / 6%), rgb(126 173 226 / 7%)) 0%, transparent 52%);
21
+ --soft-text: light-dark(#37352f, #d9d9dc);
22
+ --soft-strong: light-dark(#1f1f1f, #f1f1f2);
23
+ --soft-muted: light-dark(#7a7a7f, #9d9da3);
24
+ --soft-faint: light-dark(#ababb0, #66666c);
25
+ --soft-accent: light-dark(#3e7ac6, #7eade2);
26
+ --soft-accent-ink: light-dark(#356cb3, #98bee9);
27
+ --soft-accent-soft: light-dark(#ecf3fb, rgb(126 173 226 / 14%));
28
+ --soft-accent-tint: light-dark(#d8e6f6, #2b3c52);
29
+ --soft-on-tint: light-dark(#356cb3, #f1f1f2);
30
+ --soft-on-accent: light-dark(#ffffff, #152436);
31
+ --soft-track: light-dark(rgb(28 28 32 / 7%), rgb(255 255 255 / 8%));
32
+ --soft-good: light-dark(#23874f, #6fcf97);
33
+ --soft-good-soft: light-dark(#e6f4ec, rgb(111 207 151 / 14%));
34
+ --soft-warm: light-dark(#e59a2c, #f0b257);
35
+ --soft-warm-soft: light-dark(#fdf1df, rgb(240 178 87 / 14%));
36
+ --soft-grip-room: 0px;
37
+ > .gallery-soft-habit-face {
38
+ --soft-pad: 20px;
39
+ position: relative;
40
+ box-sizing: border-box;
41
+ display: grid;
42
+ grid-template-columns: auto minmax(0, 1fr);
43
+ grid-template-rows: 28px 1fr auto;
44
+ grid-template-areas: "head head" ". ." "top week";
45
+ column-gap: 14px;
46
+ min-width: 0;
47
+ width: 304px;
48
+ max-width: 100%;
49
+ height: 144px;
50
+ padding: calc(var(--soft-pad) - var(--soft-edge, 0px));
51
+ overflow: hidden;
52
+ border-radius: 16px;
53
+ box-shadow: var(--soft-card-shadow);
54
+ background: var(--soft-wash), var(--soft-card);
55
+ color: var(--soft-text);
56
+ font: 13px/1.5 var(--soft-font);
57
+ -webkit-font-smoothing: antialiased;
58
+ }
59
+ > .gallery-soft-habit-face[data-pad="s"] { --soft-pad: 18px; }
60
+ > .gallery-soft-habit-face[data-pad="l"] { --soft-pad: 24px; }
61
+ /* The head: the warm chip, the name's field, the days in all at its end. */
62
+ > .gallery-soft-habit-face > .gallery-soft-habit-head {
63
+ grid-area: head;
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 10px;
67
+ min-width: 0;
68
+ padding-inline-end: var(--soft-grip-room);
69
+ }
70
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-chip {
71
+ display: grid;
72
+ place-items: center;
73
+ flex: none;
74
+ width: 28px;
75
+ height: 28px;
76
+ border-radius: 8px;
77
+ background: var(--soft-warm-soft);
78
+ color: var(--soft-warm);
79
+ }
80
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-chip > svg { display: block; width: 16px; height: 16px; }
81
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-name {
82
+ flex: 1 1 auto;
83
+ min-width: 0;
84
+ margin: 0;
85
+ padding: 0;
86
+ border: 0;
87
+ outline: 0;
88
+ background: transparent;
89
+ font: 600 14px/20px var(--soft-font);
90
+ color: var(--soft-strong);
91
+ text-overflow: ellipsis;
92
+ }
93
+ /* Where the name ends the head (a 2 × 2 card, or no day in all yet), it reaches into the grip's corner as far
94
+ as the padding, its end faded out under the grip while the grip shows (a mask, so that the name stays). */
95
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head > .gallery-soft-habit-name,
96
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-name:has(+ .gallery-soft-habit-total:empty) {
97
+ margin-inline-end: calc(-1 * var(--soft-grip-room));
98
+ -webkit-mask-image: linear-gradient(to left, transparent calc(var(--gallery-grip-shown, 0) * var(--soft-grip-room)), #000 calc(var(--gallery-grip-shown, 0) * (var(--soft-grip-room) + 14px)));
99
+ mask-image: linear-gradient(to left, transparent calc(var(--gallery-grip-shown, 0) * var(--soft-grip-room)), #000 calc(var(--gallery-grip-shown, 0) * (var(--soft-grip-room) + 14px)));
100
+ }
101
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-name::placeholder { color: var(--soft-faint); font-weight: 500; opacity: 1; }
102
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-name:read-only { cursor: default; }
103
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-total:empty { display: none; }
104
+ > .gallery-soft-habit-face > .gallery-soft-habit-head > .gallery-soft-habit-total {
105
+ flex: none;
106
+ margin-inline-end: calc(-1 * var(--soft-grip-room));
107
+ font-size: 12px;
108
+ color: var(--soft-muted);
109
+ white-space: nowrap;
110
+ opacity: calc(1 - var(--gallery-grip-shown, 0));
111
+ transition: opacity .12s ease-out;
112
+ }
113
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head { gap: 8px; }
114
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head > .gallery-soft-habit-chip { width: 24px; height: 24px; border-radius: 7px; }
115
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head > .gallery-soft-habit-chip > svg { width: 14px; height: 14px; }
116
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head > .gallery-soft-habit-name { font-size: 13px; }
117
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-head > .gallery-soft-habit-total { display: none; }
118
+ /* The streak: its label over the count, the count large, its unit muted. */
119
+ > .gallery-soft-habit-face > .gallery-soft-habit-top { grid-area: top; align-self: end; min-width: 0; }
120
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-label { display: block; margin-bottom: 6px; font-size: 12px; color: var(--soft-muted); white-space: nowrap; }
121
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row { display: flex; align-items: baseline; gap: 10px; }
122
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure {
123
+ margin: 0;
124
+ white-space: nowrap;
125
+ font: 700 36px/1 var(--soft-num);
126
+ letter-spacing: -.025em;
127
+ font-variant-numeric: tabular-nums;
128
+ color: var(--soft-strong);
129
+ }
130
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure > .gallery-soft-habit-count { font-weight: inherit; }
131
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure > :is(.gallery-soft-habit-before, .gallery-soft-habit-unit) {
132
+ font: 500 13px/1 var(--soft-font);
133
+ letter-spacing: 0;
134
+ color: var(--soft-muted);
135
+ }
136
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure > .gallery-soft-habit-before { display: none; margin-right: 6px; }
137
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure > .gallery-soft-habit-unit { margin-left: 4px; }
138
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-longest {
139
+ display: none;
140
+ align-items: center;
141
+ height: 20px;
142
+ padding: 0 7px;
143
+ border-radius: 6px;
144
+ background: var(--soft-track);
145
+ color: var(--soft-muted);
146
+ font: 600 11.5px/20px var(--soft-num);
147
+ white-space: nowrap;
148
+ }
149
+ /* Never checked in: a line inviting the first, where the streak stands. */
150
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-fresh { display: none; max-width: 100px; margin: 0; font-size: 12px; line-height: 1.55; color: var(--soft-text); }
151
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-fresh > span { display: block; }
152
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-fresh > .gallery-soft-habit-fresh-how { color: var(--soft-muted); }
153
+ > .gallery-soft-habit-face[data-fresh] > .gallery-soft-habit-top > .gallery-soft-habit-streak { display: none; }
154
+ > .gallery-soft-habit-face[data-fresh] > .gallery-soft-habit-top > .gallery-soft-habit-fresh { display: block; }
155
+ /* The button: no line, pale; done pale green; read-only a plain line. */
156
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check {
157
+ display: none;
158
+ align-items: center;
159
+ justify-content: center;
160
+ gap: 5px;
161
+ flex: none;
162
+ height: 28px;
163
+ padding: 0 12px;
164
+ border: 0;
165
+ border-radius: 8px;
166
+ background: var(--soft-accent-soft);
167
+ color: var(--soft-accent-ink);
168
+ font: 500 12.5px/1 var(--soft-font);
169
+ white-space: nowrap;
170
+ cursor: pointer;
171
+ transition: background-color 20ms ease-in;
172
+ }
173
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check > svg { display: block; width: 14px; height: 14px; }
174
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check:is(:hover, :focus-visible):not(:disabled) { outline: none; background: color-mix(in srgb, var(--soft-accent) 20%, var(--soft-card)); }
175
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check.gallery-soft-habit-done { background: var(--soft-good-soft); color: var(--soft-good); }
176
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check.gallery-soft-habit-done:is(:hover, :focus-visible):not(:disabled) { background: color-mix(in srgb, var(--soft-good) 20%, var(--soft-card)); }
177
+ > .gallery-soft-habit-face > .gallery-soft-habit-top > .gallery-soft-habit-check:disabled { background: transparent; color: var(--soft-muted); cursor: default; }
178
+ /* The last seven days: a disc each, today's the button; where the words beside them leave less room than
179
+ the week takes (a long word in English), the discs a little smaller, never past the padding. */
180
+ > .gallery-soft-habit-face > .gallery-soft-habit-week { grid-area: week; align-self: end; display: flex; justify-content: flex-end; gap: 5px; min-width: 0; margin: 0; padding: 0; list-style: none; }
181
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day { display: flex; flex: 0 1 22px; flex-direction: column; align-items: center; gap: 4px; min-width: 0; }
182
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > :is(.gallery-soft-habit-dot, .gallery-soft-habit-today-press) {
183
+ display: grid;
184
+ place-items: center;
185
+ box-sizing: border-box;
186
+ width: 100%;
187
+ max-width: 22px;
188
+ height: auto;
189
+ aspect-ratio: 1;
190
+ margin: 0;
191
+ padding: 0;
192
+ border: 0;
193
+ border-radius: 50%;
194
+ background: var(--soft-track);
195
+ color: transparent;
196
+ }
197
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > :is(.gallery-soft-habit-dot, .gallery-soft-habit-today-press) > svg { display: block; width: 12px; height: 12px; }
198
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-kept > .gallery-soft-habit-dot { background: var(--soft-accent); color: var(--soft-on-accent); }
199
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > .gallery-soft-habit-today-press { background: transparent; box-shadow: inset 0 0 0 1.5px var(--soft-accent); color: var(--soft-accent); cursor: pointer; transition: background-color 20ms ease-in; }
200
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > .gallery-soft-habit-today-press:is(:hover, :focus-visible):not(:disabled) { outline: none; background: var(--soft-accent-soft); }
201
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-kept > .gallery-soft-habit-today-press,
202
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-kept > .gallery-soft-habit-today-press:is(:hover, :focus-visible):not(:disabled) { background: var(--soft-accent); box-shadow: none; color: var(--soft-on-accent); }
203
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > .gallery-soft-habit-today-press:disabled { cursor: default; }
204
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-day > .gallery-soft-habit-weekday { font-size: 10.5px; line-height: 12px; color: var(--soft-muted); white-space: nowrap; }
205
+ > .gallery-soft-habit-face > .gallery-soft-habit-week > .gallery-soft-habit-today > .gallery-soft-habit-weekday { color: var(--soft-accent-ink); font-weight: 600; }
206
+ /* The last four weeks (a tall card's). */
207
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar { grid-area: calendar; display: none; grid-template-columns: repeat(7, 1fr); row-gap: 7px; justify-items: center; align-self: end; }
208
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar > .gallery-soft-habit-initial { font-size: 11px; line-height: 14px; color: var(--soft-muted); }
209
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar > .gallery-soft-habit-date {
210
+ display: grid;
211
+ place-items: center;
212
+ width: 24px;
213
+ height: 24px;
214
+ border-radius: 50%;
215
+ background: var(--soft-track);
216
+ color: var(--soft-muted);
217
+ font: 500 10.5px/1 var(--soft-num);
218
+ }
219
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar > .gallery-soft-habit-on { background: var(--soft-accent-tint); color: var(--soft-on-tint); font-weight: 600; }
220
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar > .gallery-soft-habit-now { background: transparent; box-shadow: inset 0 0 0 1.5px var(--soft-accent); color: var(--soft-accent-ink); font-weight: 600; }
221
+ > .gallery-soft-habit-face > .gallery-soft-habit-calendar > .gallery-soft-habit-future { background: transparent; color: var(--soft-faint); }
222
+ /* 2 × 2: 连续 and the streak over a button as wide as the card. */
223
+ > .gallery-soft-habit-face[data-pad="s"] { grid-template-columns: minmax(0, 1fr); grid-template-rows: 24px 1fr auto; grid-template-areas: "head" "." "top"; }
224
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-week { display: none; }
225
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-label { display: none; }
226
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure { font-size: 30px; }
227
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure > .gallery-soft-habit-before { display: inline; }
228
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-top > .gallery-soft-habit-fresh { max-width: none; line-height: 1.5; }
229
+ > .gallery-soft-habit-face[data-pad="s"] > .gallery-soft-habit-top > .gallery-soft-habit-check { display: flex; width: 100%; margin-top: 10px; }
230
+ /* 4 × 4: the streak, the longest and the button over the last four weeks. */
231
+ > .gallery-soft-habit-face[data-pad="l"] { grid-template-columns: minmax(0, 1fr); grid-template-rows: 28px auto 1fr auto; grid-template-areas: "head" "top" "." "calendar"; }
232
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-week { display: none; }
233
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-top { display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; margin-top: 18px; }
234
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-figure { font-size: 40px; }
235
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-top > .gallery-soft-habit-streak > .gallery-soft-habit-row > .gallery-soft-habit-longest { display: inline-flex; }
236
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-top > .gallery-soft-habit-fresh { max-width: none; line-height: 1.6; }
237
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-top > .gallery-soft-habit-check { display: flex; }
238
+ > .gallery-soft-habit-face[data-pad="l"] > .gallery-soft-habit-calendar { display: grid; }
239
+ }
240
+ /* On a custom page: the face over the card's whole room, its padding the soft frame's, the board's line around it; the head's end kept clear of the grip's corner. */
241
+ .gallery-card > [data-doc-component="gallery-soft/habit"] { height: 100%; }
242
+ .gallery-card > [data-doc-component="gallery-soft/habit"] > .gallery-soft-habit-face {
243
+ --soft-edge: 1px;
244
+ --soft-grip-room: max(0px, calc(40px - var(--soft-pad)));
245
+ width: auto;
246
+ max-width: none;
247
+ height: calc(100% + 2 * var(--gallery-card-pad));
248
+ margin: calc(-1 * var(--gallery-card-pad));
249
+ border-radius: calc(var(--gallery-card-radius) - 1px);
250
+ box-shadow: none;
251
+ }
@@ -0,0 +1,3 @@
1
+ <div data-doc-component="gallery-soft/habit">
2
+ <script type="application/json">{"name":"","days":[]}</script>
3
+ </div>