@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.
- package/THIRD-PARTY-NOTICES.md +2 -2
- package/browser/editor/components/align.mjs +58 -0
- package/browser/editor/components/code/index.mjs +1 -1
- package/browser/editor/components/columns/page.mjs +4 -4
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/embed/page.mjs +1 -1
- package/browser/editor/components/file/page.mjs +4 -4
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/heading/index.mjs +7 -6
- package/browser/editor/components/icons.mjs +11 -0
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/image/index.mjs +2 -0
- package/browser/editor/components/image/page.mjs +172 -90
- package/browser/editor/components/installed/index.mjs +15 -4
- package/browser/editor/components/installed/page.mjs +103 -25
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/media/icons.mjs +13 -8
- package/browser/editor/components/media/page.mjs +5 -3
- package/browser/editor/components/media/toolbar.mjs +12 -3
- package/browser/editor/components/paragraph/index.mjs +4 -3
- package/browser/editor/components/registry.mjs +30 -9
- package/browser/editor/components/table/index.mjs +61 -2
- package/browser/editor/components/table/page.mjs +1 -1
- package/browser/editor/page/after/index.mjs +288 -0
- package/browser/editor/page/align.mjs +91 -0
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/autosave.mjs +310 -37
- package/browser/editor/page/beside.mjs +5 -6
- package/browser/editor/page/block-menu/index.mjs +6 -3
- package/browser/editor/page/blocks.mjs +3 -1
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +182 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +1059 -0
- package/browser/editor/page/board/motion.mjs +177 -0
- package/browser/editor/page/board/settings.mjs +210 -0
- package/browser/editor/page/caret.mjs +1 -1
- package/browser/editor/page/changes/bar.mjs +6 -14
- package/browser/editor/page/changes/index.mjs +2 -2
- package/browser/editor/page/clipboard/import/html.mjs +29 -6
- package/browser/editor/page/clipboard/import/inline.mjs +32 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
- package/browser/editor/page/clipboard/import/read.mjs +6 -1
- package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
- package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
- package/browser/editor/page/clipboard/index.mjs +133 -15
- package/browser/editor/page/clipboard/own/blocks.mjs +13 -14
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/describe.mjs +6 -2
- package/browser/editor/page/clipboard/own/selection.mjs +1 -1
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +80 -22
- package/browser/editor/page/conflicts.mjs +7 -7
- package/browser/editor/page/core.mjs +34 -16
- package/browser/editor/page/custom-page.mjs +110 -0
- package/browser/editor/page/editor.mjs +71 -17
- package/browser/editor/page/emoji-picker/styles.mjs +7 -12
- package/browser/editor/page/emoji-picker/upload.mjs +2 -2
- package/browser/editor/page/handle/index.mjs +5 -8
- package/browser/editor/page/history.mjs +41 -6
- package/browser/editor/page/insert/index.mjs +20 -22
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/look.mjs +54 -3
- package/browser/editor/page/margin.mjs +18 -3
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +33 -14
- package/browser/editor/page/notices.mjs +2 -2
- package/browser/editor/page/page-objects.mjs +9 -2
- package/browser/editor/page/panel.mjs +4 -9
- package/browser/editor/page/present-links.mjs +15 -5
- package/browser/editor/page/present-shell.mjs +63 -0
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/selection/index.mjs +10 -2
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +48 -4
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/binding.mjs +87 -0
- package/browser/editor/page/table/cells.mjs +102 -46
- package/browser/editor/page/table/index.mjs +24 -9
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +103 -0
- package/browser/editor/page/table/widths.mjs +82 -10
- package/browser/editor/page/text-select/index.mjs +26 -12
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/typing/index.mjs +97 -15
- package/browser/editor/page/typing/leave.mjs +19 -5
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/block-packs.mjs +419 -0
- package/browser/shared/board-places.mjs +224 -0
- package/browser/shared/card-size.mjs +59 -0
- package/browser/shared/colors.mjs +3 -2
- package/browser/shared/component-catalog.mjs +330 -46
- package/browser/shared/component-source.mjs +39 -0
- package/browser/shared/components/heading.mjs +2 -1
- package/browser/shared/components/index.mjs +12 -3
- package/browser/shared/components/installed.mjs +35 -3
- package/browser/shared/components/page.mjs +20 -8
- package/browser/shared/components/paragraph.mjs +8 -1
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/components/table.mjs +1 -0
- package/browser/shared/document-look.mjs +10 -5
- package/browser/shared/drafts.mjs +432 -0
- package/browser/shared/emoji/line-icons.mjs +37 -0
- package/browser/shared/extension-sidebar.mjs +126 -0
- package/browser/shared/extensions.mjs +79 -0
- package/browser/shared/file-table.mjs +101 -0
- package/browser/shared/http.mjs +9 -0
- package/browser/shared/i18n/en.mjs +330 -27
- package/browser/shared/json-layout.mjs +47 -0
- package/browser/shared/net-cache.mjs +133 -0
- package/browser/shared/net-keys.mjs +32 -0
- package/browser/shared/net-policy.mjs +177 -0
- package/browser/shared/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +359 -67
- package/browser/shared/pack-manifest.mjs +88 -0
- package/browser/shared/page-address.mjs +6 -3
- package/browser/shared/page-cards.mjs +308 -0
- package/browser/shared/page-links.mjs +69 -6
- package/browser/shared/pages.mjs +500 -0
- package/browser/shared/paths.mjs +6 -0
- package/browser/shared/pinyin.mjs +92 -0
- package/browser/shared/present-step.mjs +17 -0
- package/browser/shared/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +8 -1
- package/browser/shared/shipped-blocks.mjs +299 -0
- package/browser/shared/sidebar-head.mjs +70 -0
- package/browser/shared/table-chart.mjs +33 -1
- package/browser/shared/todos.mjs +83 -0
- package/browser/shared/user-directory.mjs +24 -0
- package/browser/shared/versions.mjs +14 -0
- package/browser/shared/web-links.mjs +139 -0
- package/browser/shared/workspace-columns.mjs +120 -0
- package/browser/shared/workspace-name.mjs +154 -0
- package/browser/shared/workspace-query.mjs +125 -0
- package/browser/shared/workspace-registry.mjs +272 -0
- package/browser/shared/workspace.mjs +171 -20
- package/dist/chunk-2OHANJ6Q.mjs +2 -0
- package/dist/chunk-3MBRL2PM.mjs +16 -0
- package/dist/chunk-4OKWZY5E.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5K44HLTZ.mjs +2 -0
- package/dist/{chunk-5ZKJ3H4P.mjs → chunk-5XA2ZBAE.mjs} +3 -3
- package/dist/{chunk-4FS7Z7WR.mjs → chunk-67N2QJYT.mjs} +1 -1
- package/dist/chunk-6KBYRA2C.mjs +2 -0
- package/dist/chunk-6N3PX4XX.mjs +8 -0
- package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/chunk-7JDX4E65.mjs +13 -0
- package/dist/chunk-7M2BQQGZ.mjs +2 -0
- package/dist/chunk-7OG26PGF.mjs +2 -0
- package/dist/chunk-AHN3NFKJ.mjs +3 -0
- package/dist/chunk-ALZ6ZENZ.mjs +3 -0
- package/dist/chunk-AR5D57ZD.mjs +170 -0
- package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
- package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
- package/dist/chunk-CMA72MAG.mjs +2 -0
- package/dist/{chunk-LCTHTZIL.mjs → chunk-DAZL73VK.mjs} +91 -91
- package/dist/{chunk-Y6RLRPG3.mjs → chunk-DJISHPUL.mjs} +1 -1
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-FDLXYYG4.mjs → chunk-EAIFITAV.mjs} +1 -1
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/chunk-EP25HDAJ.mjs +2 -0
- package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-F4ZA6JRZ.mjs +3 -0
- package/dist/chunk-F6HVDZR4.mjs +2 -0
- package/dist/chunk-FDMAXMQA.mjs +2 -0
- package/dist/chunk-FETSREUN.mjs +5 -0
- package/dist/chunk-GHOYKMQ3.mjs +4 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-HDWTZ763.mjs +12 -0
- package/dist/chunk-HPOI4ZX7.mjs +6 -0
- package/dist/{chunk-BGGDRNYQ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/{chunk-E7LWZRXY.mjs → chunk-ITOH5EGO.mjs} +1 -1
- package/dist/chunk-IV64FFI4.mjs +2 -0
- package/dist/chunk-J43Z6LSS.mjs +2 -0
- package/dist/chunk-J5PUIV3Y.mjs +4 -0
- package/dist/chunk-JA7G53PC.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-JLTZF4LA.mjs +2 -0
- package/dist/chunk-JZT7I2OJ.mjs +2 -0
- package/dist/chunk-K5XATEOO.mjs +2 -0
- package/dist/chunk-L2SUIS5S.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/chunk-LM4XFQHZ.mjs +2 -0
- package/dist/chunk-MN7BZL4R.mjs +2 -0
- package/dist/chunk-MTYYHM2G.mjs +15 -0
- package/dist/chunk-MXUBKDRO.mjs +15 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-SYGN7GLU.mjs → chunk-OEXWRJME.mjs} +1 -1
- package/dist/chunk-OFHXGWOX.mjs +2 -0
- package/dist/chunk-ORID3AE7.mjs +166 -0
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-PGDE24N5.mjs +2 -0
- package/dist/chunk-POTA2FV4.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QE5RG76S.mjs +549 -0
- package/dist/chunk-R2ZDLJYT.mjs +10 -0
- package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SWUTTZCN.mjs +2 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TR7TWGHB.mjs +2 -0
- package/dist/chunk-U5XL7D6A.mjs +3 -0
- package/dist/{chunk-XNROSH2T.mjs → chunk-U7NZI6N4.mjs} +2 -2
- package/dist/chunk-UGWMMEJ5.mjs +15 -0
- package/dist/chunk-UJQJKNGK.mjs +2 -0
- package/dist/chunk-UYVCQK3H.mjs +22 -0
- package/dist/chunk-VFX2KNHP.mjs +4 -0
- package/dist/chunk-VS7JIGJW.mjs +24 -0
- package/dist/chunk-W7665ZEC.mjs +6 -0
- package/dist/chunk-WQDQWCX5.mjs +2 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YLPSMDIS.mjs +5 -0
- package/dist/chunk-YNAWBAYN.mjs +3 -0
- package/dist/chunk-YROX2O22.mjs +2 -0
- package/dist/chunk-ZDLPUOAG.mjs +6 -0
- package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZQS6H473.mjs +16 -0
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZWWC4KLF.mjs +20 -0
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/{chunk-U6KNPJPR.mjs → update-fetch.mjs} +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +95 -0
- package/kit/board.js +250 -0
- package/kit/charts.js +5 -71
- package/kit/code.js +17 -17
- package/kit/report.css +335 -18
- package/kit/runtime.js +1638 -125
- package/kit/state.js +10 -1
- package/kit/tables.js +130 -43
- package/kit/ui.js +79 -35
- package/package.json +2 -1
- package/packs/gallery/card/component.json +14 -0
- package/packs/gallery/card/example.html +10 -0
- package/packs/gallery/card/preview.svg +1 -0
- package/packs/gallery/card/style.css +6 -0
- package/packs/gallery/card/template.html +6 -0
- package/packs/gallery/card/writing.md +14 -0
- package/packs/gallery/chart-card/component.json +15 -0
- package/packs/gallery/chart-card/example.html +14 -0
- package/packs/gallery/chart-card/kit.js +130 -0
- package/packs/gallery/chart-card/preview.svg +1 -0
- package/packs/gallery/chart-card/style.css +42 -0
- package/packs/gallery/chart-card/template.html +13 -0
- package/packs/gallery/chart-card/writing.md +20 -0
- package/packs/gallery/chart-view/component.json +20 -0
- package/packs/gallery/chart-view/example.html +13 -0
- package/packs/gallery/chart-view/kit.js +355 -0
- package/packs/gallery/chart-view/preview.svg +1 -0
- package/packs/gallery/chart-view/style.css +94 -0
- package/packs/gallery/chart-view/template.html +3 -0
- package/packs/gallery/chart-view/writing.md +22 -0
- package/packs/gallery/countdown/component.json +18 -0
- package/packs/gallery/countdown/example.html +3 -0
- package/packs/gallery/countdown/kit.js +216 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +118 -0
- package/packs/gallery/countdown/template.html +3 -0
- package/packs/gallery/countdown/writing.md +22 -0
- package/packs/gallery/habit/component.json +14 -0
- package/packs/gallery/habit/example.html +3 -0
- package/packs/gallery/habit/kit.js +334 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +174 -0
- package/packs/gallery/habit/template.html +3 -0
- package/packs/gallery/habit/writing.md +21 -0
- package/packs/gallery/heatmap/component.json +18 -0
- package/packs/gallery/heatmap/example.html +3 -0
- package/packs/gallery/heatmap/kit.js +513 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +189 -0
- package/packs/gallery/heatmap/template.html +3 -0
- package/packs/gallery/heatmap/writing.md +21 -0
- package/packs/gallery/kanban/component.json +18 -0
- package/packs/gallery/kanban/example.html +12 -0
- package/packs/gallery/kanban/kit.js +540 -0
- package/packs/gallery/kanban/preview.svg +1 -0
- package/packs/gallery/kanban/style.css +212 -0
- package/packs/gallery/kanban/template.html +3 -0
- package/packs/gallery/kanban/writing.md +20 -0
- package/packs/gallery/metric/component.json +22 -0
- package/packs/gallery/metric/example.html +15 -0
- package/packs/gallery/metric/kit.js +248 -0
- package/packs/gallery/metric/preview.svg +1 -0
- package/packs/gallery/metric/style.css +92 -0
- package/packs/gallery/metric/template.html +3 -0
- package/packs/gallery/metric/writing.md +23 -0
- package/packs/gallery/note/component.json +14 -0
- package/packs/gallery/note/example.html +3 -0
- package/packs/gallery/note/kit.js +129 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +97 -0
- package/packs/gallery/note/template.html +3 -0
- package/packs/gallery/note/writing.md +18 -0
- package/packs/gallery/pack.json +8 -0
- package/packs/gallery/recent/component.json +13 -0
- package/packs/gallery/recent/example.html +1 -0
- package/packs/gallery/recent/kit.js +293 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +85 -0
- package/packs/gallery/recent/template.html +1 -0
- package/packs/gallery/recent/writing.md +15 -0
- package/packs/gallery/static/component.json +13 -0
- package/packs/gallery/static/example.html +11 -0
- package/packs/gallery/static/preview.svg +1 -0
- package/packs/gallery/static/style.css +171 -0
- package/packs/gallery/static/template.html +1 -0
- package/packs/gallery/static/writing.md +18 -0
- package/packs/gallery/stats/component.json +13 -0
- package/packs/gallery/stats/example.html +1 -0
- package/packs/gallery/stats/kit.js +347 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +73 -0
- package/packs/gallery/stats/template.html +1 -0
- package/packs/gallery/stats/writing.md +11 -0
- package/packs/gallery/today/component.json +12 -0
- package/packs/gallery/today/example.html +1 -0
- package/packs/gallery/today/kit.js +220 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +149 -0
- package/packs/gallery/today/template.html +1 -0
- package/packs/gallery/today/writing.md +14 -0
- package/packs/gallery/todos/component.json +19 -0
- package/packs/gallery/todos/example.html +3 -0
- package/packs/gallery/todos/kit.js +489 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +214 -0
- package/packs/gallery/todos/template.html +3 -0
- package/packs/gallery/todos/writing.md +30 -0
- package/packs/gallery/weather/component.json +19 -0
- package/packs/gallery/weather/example.html +3 -0
- package/packs/gallery/weather/kit.js +387 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +140 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/countdown/component.json +18 -0
- package/packs/gallery-soft/countdown/example.html +3 -0
- package/packs/gallery-soft/countdown/kit.js +206 -0
- package/packs/gallery-soft/countdown/preview.svg +1 -0
- package/packs/gallery-soft/countdown/style.css +211 -0
- package/packs/gallery-soft/countdown/template.html +3 -0
- package/packs/gallery-soft/countdown/writing.md +24 -0
- package/packs/gallery-soft/habit/component.json +14 -0
- package/packs/gallery-soft/habit/example.html +3 -0
- package/packs/gallery-soft/habit/kit.js +366 -0
- package/packs/gallery-soft/habit/preview.svg +1 -0
- package/packs/gallery-soft/habit/style.css +251 -0
- package/packs/gallery-soft/habit/template.html +3 -0
- package/packs/gallery-soft/habit/writing.md +23 -0
- package/packs/gallery-soft/heatmap/component.json +18 -0
- package/packs/gallery-soft/heatmap/example.html +3 -0
- package/packs/gallery-soft/heatmap/kit.js +498 -0
- package/packs/gallery-soft/heatmap/preview.svg +1 -0
- package/packs/gallery-soft/heatmap/style.css +181 -0
- package/packs/gallery-soft/heatmap/template.html +3 -0
- package/packs/gallery-soft/heatmap/writing.md +23 -0
- package/packs/gallery-soft/note/component.json +14 -0
- package/packs/gallery-soft/note/example.html +3 -0
- package/packs/gallery-soft/note/kit.js +162 -0
- package/packs/gallery-soft/note/preview.svg +1 -0
- package/packs/gallery-soft/note/style.css +148 -0
- package/packs/gallery-soft/note/template.html +3 -0
- package/packs/gallery-soft/note/writing.md +20 -0
- package/packs/gallery-soft/pack.json +8 -0
- package/packs/gallery-soft/recent/component.json +13 -0
- package/packs/gallery-soft/recent/example.html +1 -0
- package/packs/gallery-soft/recent/kit.js +335 -0
- package/packs/gallery-soft/recent/preview.svg +1 -0
- package/packs/gallery-soft/recent/style.css +160 -0
- package/packs/gallery-soft/recent/template.html +1 -0
- package/packs/gallery-soft/recent/writing.md +17 -0
- package/packs/gallery-soft/static/component.json +13 -0
- package/packs/gallery-soft/static/example.html +12 -0
- package/packs/gallery-soft/static/preview.svg +1 -0
- package/packs/gallery-soft/static/style.css +186 -0
- package/packs/gallery-soft/static/template.html +1 -0
- package/packs/gallery-soft/static/writing.md +20 -0
- package/packs/gallery-soft/stats/component.json +13 -0
- package/packs/gallery-soft/stats/example.html +1 -0
- package/packs/gallery-soft/stats/kit.js +341 -0
- package/packs/gallery-soft/stats/preview.svg +1 -0
- package/packs/gallery-soft/stats/style.css +119 -0
- package/packs/gallery-soft/stats/template.html +1 -0
- package/packs/gallery-soft/stats/writing.md +13 -0
- package/packs/gallery-soft/today/component.json +12 -0
- package/packs/gallery-soft/today/example.html +1 -0
- package/packs/gallery-soft/today/kit.js +222 -0
- package/packs/gallery-soft/today/preview.svg +1 -0
- package/packs/gallery-soft/today/style.css +178 -0
- package/packs/gallery-soft/today/template.html +1 -0
- package/packs/gallery-soft/today/writing.md +16 -0
- package/packs/gallery-soft/todos/component.json +19 -0
- package/packs/gallery-soft/todos/example.html +3 -0
- package/packs/gallery-soft/todos/kit.js +527 -0
- package/packs/gallery-soft/todos/preview.svg +1 -0
- package/packs/gallery-soft/todos/style.css +212 -0
- package/packs/gallery-soft/todos/template.html +3 -0
- package/packs/gallery-soft/todos/writing.md +32 -0
- package/packs/gallery-soft/weather/component.json +19 -0
- package/packs/gallery-soft/weather/example.html +3 -0
- package/packs/gallery-soft/weather/kit.js +411 -0
- package/packs/gallery-soft/weather/preview.svg +1 -0
- package/packs/gallery-soft/weather/style.css +185 -0
- package/packs/gallery-soft/weather/template.html +3 -0
- package/packs/gallery-soft/weather/writing.md +28 -0
- package/release.json +12 -10
- package/sdk/doc-kit.d.ts +396 -5
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +56 -23
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +225 -0
- package/skill/references/writing-html.md +8 -4
- package/skill/sdk/doc-kit.d.ts +396 -5
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BM_K-Auu.css +1 -0
- package/web/assets/index-DRslOBiv.js +15 -0
- package/web/index.html +2 -2
- package/dist/chunk-3HIRPVLU.mjs +0 -2
- package/dist/chunk-5MHMDLZD.mjs +0 -4
- package/dist/chunk-64K7IPLO.mjs +0 -255
- package/dist/chunk-6QXGZM36.mjs +0 -8
- package/dist/chunk-6RGJOMJP.mjs +0 -16
- package/dist/chunk-AJ73XJF3.mjs +0 -2
- package/dist/chunk-AUZGSZJH.mjs +0 -13
- package/dist/chunk-BFE45AKL.mjs +0 -2
- package/dist/chunk-BXO2ZY5P.mjs +0 -2
- package/dist/chunk-CEH4MRCC.mjs +0 -2
- package/dist/chunk-CY2FNNAB.mjs +0 -16
- package/dist/chunk-DFUDV4LX.mjs +0 -2
- package/dist/chunk-DKXG4XDG.mjs +0 -2
- package/dist/chunk-EZQ34M3F.mjs +0 -124
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FUKQNOQS.mjs +0 -9
- package/dist/chunk-JPOSLGOC.mjs +0 -6
- package/dist/chunk-JVHHHGEA.mjs +0 -3
- package/dist/chunk-L3QKH4OK.mjs +0 -26
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LEF6DRCK.mjs +0 -59
- package/dist/chunk-NO5NJCHO.mjs +0 -2
- package/dist/chunk-NQPVAU63.mjs +0 -2
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O35FIXRB.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-PL6GHLGD.mjs +0 -15
- package/dist/chunk-QJIR2BLP.mjs +0 -6
- package/dist/chunk-QUPLVPB2.mjs +0 -7
- package/dist/chunk-R7BNENLY.mjs +0 -4
- package/dist/chunk-S6O4UHLC.mjs +0 -2
- package/dist/chunk-SGJWQKEI.mjs +0 -2
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-TYK6VNAB.mjs +0 -10
- package/dist/chunk-UALRNVSE.mjs +0 -4
- package/dist/chunk-V3HXVQEM.mjs +0 -2
- package/dist/chunk-V5VXUJKG.mjs +0 -2
- package/dist/chunk-VBXMADMP.mjs +0 -2
- package/dist/chunk-VNV55RUA.mjs +0 -2
- package/dist/chunk-VPD2PS35.mjs +0 -2
- package/dist/chunk-W4VKN3GF.mjs +0 -7
- package/dist/chunk-W5BXXPDJ.mjs +0 -3
- package/dist/chunk-XUNHRCOG.mjs +0 -6
- package/skill/references/building-components.md +0 -367
- package/web/assets/index-Bh74DfsV.css +0 -1
- 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
|
+
}
|