@heycys/gallery 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/browser/editor/components/columns/page.mjs +4 -4
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/icons.mjs +8 -0
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/installed/index.mjs +11 -4
- package/browser/editor/components/installed/page.mjs +27 -16
- 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/registry.mjs +13 -4
- package/browser/editor/components/table/index.mjs +59 -2
- package/browser/editor/components/table/page.mjs +1 -1
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/autosave.mjs +310 -37
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +145 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +970 -0
- package/browser/editor/page/board/settings.mjs +209 -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 +124 -13
- package/browser/editor/page/clipboard/own/blocks.mjs +11 -11
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- 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 +31 -15
- package/browser/editor/page/custom-page.mjs +106 -0
- package/browser/editor/page/editor.mjs +51 -14
- 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 +24 -4
- 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 +18 -7
- package/browser/editor/page/notices.mjs +2 -2
- package/browser/editor/page/page-objects.mjs +13 -2
- package/browser/editor/page/panel.mjs +4 -9
- package/browser/editor/page/present-links.mjs +11 -2
- package/browser/editor/page/resize/index.mjs +42 -29
- 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/cells.mjs +102 -46
- package/browser/editor/page/table/icons.mjs +2 -0
- package/browser/editor/page/table/index.mjs +29 -10
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +150 -0
- 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 +53 -3
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/block-packs.mjs +404 -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 +323 -46
- package/browser/shared/component-source.mjs +37 -0
- package/browser/shared/components/index.mjs +12 -3
- package/browser/shared/components/installed.mjs +35 -3
- package/browser/shared/components/page.mjs +18 -8
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/document-look.mjs +10 -5
- package/browser/shared/drafts.mjs +432 -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/i18n/en.mjs +307 -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 +331 -67
- package/browser/shared/pack-manifest.mjs +77 -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 +388 -0
- package/browser/shared/paths.mjs +6 -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/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 +134 -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-2NRBY6AJ.mjs +2 -0
- package/dist/chunk-32ZUEFZ7.mjs +2 -0
- package/dist/chunk-35NQ4PLQ.mjs +2 -0
- package/dist/chunk-3KJHLHUO.mjs +2 -0
- package/dist/chunk-3NJACR4W.mjs +2 -0
- package/dist/chunk-4AV456RQ.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5XYHDBJ5.mjs +2 -0
- package/dist/chunk-5ZJA7CXT.mjs +2 -0
- package/dist/chunk-6A53MZYZ.mjs +2 -0
- package/dist/chunk-6EXH3ORZ.mjs +166 -0
- package/dist/chunk-6EZ7FNIK.mjs +3 -0
- package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-Y6RLRPG3.mjs → chunk-6VTU6KEO.mjs} +1 -1
- package/dist/chunk-B4P2CM2J.mjs +3 -0
- package/dist/{chunk-FDLXYYG4.mjs → chunk-BPL64HGA.mjs} +1 -1
- package/dist/chunk-BVEFGE4B.mjs +2 -0
- package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
- package/dist/chunk-CRJEG7MT.mjs +2 -0
- package/dist/{chunk-LCTHTZIL.mjs → chunk-D4CKRD3V.mjs} +91 -91
- package/dist/chunk-D4EURAX4.mjs +4 -0
- package/dist/chunk-DQCE7TJY.mjs +5 -0
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-FJYN7RTH.mjs +4 -0
- package/dist/chunk-FWNRPMCJ.mjs +12 -0
- package/dist/chunk-FWW4CSAZ.mjs +2 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-GY3FAUVM.mjs +2 -0
- package/dist/chunk-HLYV7RIH.mjs +2 -0
- package/dist/chunk-HMYTM3GT.mjs +15 -0
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-KTKHRC6H.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/{chunk-SYGN7GLU.mjs → chunk-MHW7ZKOU.mjs} +1 -1
- package/dist/chunk-N76HWBA3.mjs +10 -0
- package/dist/chunk-N7AZZLGT.mjs +548 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-5ZKJ3H4P.mjs → chunk-NFMCP2HI.mjs} +3 -3
- package/dist/chunk-NG375ILQ.mjs +2 -0
- package/dist/chunk-NVRNLK25.mjs +6 -0
- package/dist/chunk-NWFBE2YA.mjs +2 -0
- package/dist/chunk-NWR2LT5B.mjs +2 -0
- package/dist/chunk-OJKMINIU.mjs +20 -0
- package/dist/{chunk-4FS7Z7WR.mjs → chunk-OUUP3WKT.mjs} +1 -1
- package/dist/{chunk-BGGDRNYQ.mjs → chunk-OW5NWPOJ.mjs} +1 -1
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-POQSE4C2.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/{chunk-XNROSH2T.mjs → chunk-PVER7LSC.mjs} +2 -2
- package/dist/chunk-PZDLJJTJ.mjs +3 -0
- package/dist/chunk-Q47PLKIJ.mjs +15 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QKXMPUXC.mjs +2 -0
- package/dist/chunk-QOUEFUCH.mjs +16 -0
- package/dist/chunk-RFDZXFJF.mjs +13 -0
- package/dist/chunk-RKPWLGZ3.mjs +4 -0
- package/dist/chunk-RMECZA2K.mjs +2 -0
- package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SX4LJYT6.mjs +8 -0
- package/dist/chunk-SXHBYZST.mjs +16 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TEZAWDSQ.mjs +2 -0
- package/dist/chunk-UBBRTJ2R.mjs +24 -0
- package/dist/chunk-UFNYFFKO.mjs +20 -0
- package/dist/chunk-UGWYKHBL.mjs +170 -0
- package/dist/chunk-UKSHDZZ6.mjs +2 -0
- package/dist/chunk-UNOYVIYR.mjs +2 -0
- package/dist/{chunk-E7LWZRXY.mjs → chunk-V6RIYQZZ.mjs} +1 -1
- package/dist/chunk-VJPFVNNW.mjs +15 -0
- package/dist/chunk-VS3ZMVGX.mjs +5 -0
- package/dist/chunk-VTKNEYT3.mjs +6 -0
- package/dist/chunk-VXACTLO3.mjs +3 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YQGT4AB2.mjs +6 -0
- package/dist/chunk-ZB4H7ZN4.mjs +2 -0
- package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZUNVAXLH.mjs +2 -0
- package/dist/chunk-ZWPMCK7P.mjs +2 -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 +14 -14
- package/kit/report.css +255 -17
- package/kit/runtime.js +1600 -125
- package/kit/state.js +10 -1
- package/kit/tables.js +128 -43
- package/kit/ui.js +77 -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 +156 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +130 -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 +295 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +246 -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 +351 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +201 -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 +102 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +76 -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 +238 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +158 -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 +138 -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 +166 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +151 -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 +185 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +120 -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 +342 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +267 -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 +312 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +258 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/pack.json +8 -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 +221 -0
- package/skill/references/writing-html.md +6 -4
- package/skill/sdk/doc-kit.d.ts +396 -5
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BK2e_07w.js +13 -0
- package/web/assets/index-CWFI83mF.css +1 -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-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,351 @@
|
|
|
1
|
+
// gallery/heatmap (编辑热力图): the workspace's record of edits by day, as GitHub draws a year of
|
|
2
|
+
// contributions: a column a week (Monday at the top, as a Chinese calendar starts it), a square a day,
|
|
3
|
+
// darker for a day of more, read through context.workspace.query("activity") (its manifest's needs hold
|
|
4
|
+
// "workspace": the server's record, .gallery/state/activity.json, a reader's commits and the Agent's
|
|
5
|
+
// writes, by day). Its one setting, `words` (按字数显示, the card's form: the grip at its top right › 设置…, kept in its data part
|
|
6
|
+
// `settings`, which the board writes and this block only reads), draws the words a day added (its net
|
|
7
|
+
// change, a day that took more away than it added drawn as none) instead of how many edits it had. As
|
|
8
|
+
// many weeks as the card holds are drawn, the last ending today, at most a year's 53: the squares as big as
|
|
9
|
+
// the card's height lets seven of them be (3px apart, 2px where the card is low), at most so big that 53
|
|
10
|
+
// weeks fit its width (but 8px, or three fifths of what the height lets, at least, where the height has room
|
|
11
|
+
// for it: fewer weeks then); never more than the card holds, so that no day is cut off. It asks for every
|
|
12
|
+
// day 53 weeks draw (the record keeps as many), so that a day drawn apart (none counted then) is one before
|
|
13
|
+
// the record started, never one of a record older than what it asked; and the line at the top says since
|
|
14
|
+
// when it was kept while nothing is counted yet (从 11月8日 开始记录). It reads again whenever the
|
|
15
|
+
// workspace says its record changed (the `data` signal, "activity") and as a day begins (the kit's
|
|
16
|
+
// clock), and draws again as its card changes size (`resize`, `layout`, and its own ResizeObserver on
|
|
17
|
+
// the room the squares have, which hears a change of height too, as a card that got its height after the
|
|
18
|
+
// first draw has) or its settings change (`source`). Each square says its day and its count (its title). Where the workspace cannot be read
|
|
19
|
+
// (an exported file, where it has no server; a server that does not answer) the line says so. The words
|
|
20
|
+
// are the page's language (the UI's where Gallery says it, else the page's lang). Its head is the cards'
|
|
21
|
+
// (the kit's card tokens): the chip, a calendar, before its title; its squares the accent's shades, the
|
|
22
|
+
// grid hung from the card's left edge under the head, the weekdays' column left out where the squares are
|
|
23
|
+
// too small for its words, the months' names no closer than their own width. A wide card with something
|
|
24
|
+
// counted shows the figures beside the squares (`summaryOf`'s `figures`, the face's `data-figures`): what
|
|
25
|
+
// they count (期间编辑), the edits (or words) in all, large, how many days had any and today's, the period
|
|
26
|
+
// then the head's quiet note at its end; the room the squares have is what the figures leave. Less to more
|
|
27
|
+
// stands under the squares at their left where the card has the room for it, else at the head's end (left
|
|
28
|
+
// out on a card too narrow for it beside the line: style.css).
|
|
29
|
+
|
|
30
|
+
const WORDS = {
|
|
31
|
+
zh: {
|
|
32
|
+
title: "编辑热力图",
|
|
33
|
+
since: (/** @type {string} */ date) => `从 ${date} 开始记录`,
|
|
34
|
+
edits: (/** @type {string} */ period, /** @type {number} */ count) => `${period} ${count} 次编辑`,
|
|
35
|
+
words: (/** @type {string} */ period, /** @type {string} */ count) => `${period}写了 ${count} 字`,
|
|
36
|
+
year: "过去一年",
|
|
37
|
+
after: (/** @type {string} */ date) => `${date}以来`,
|
|
38
|
+
day: (/** @type {string} */ date, /** @type {number} */ edits, /** @type {number} */ words) => (edits === 0 ? `${date}:没有编辑` : `${date}:${edits} 次编辑,${words >= 0 ? "+" : "−"}${Math.abs(words)} 字`),
|
|
39
|
+
before: (/** @type {string} */ date) => `${date}:还没开始记录`,
|
|
40
|
+
date: (/** @type {Date} */ date) => `${date.getMonth() + 1}月${date.getDate()}日`,
|
|
41
|
+
weekday: (/** @type {Date} */ date) => `${date.getMonth() + 1}月${date.getDate()}日 ${["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"][date.getDay()]}`,
|
|
42
|
+
month: (/** @type {number} */ month) => `${month + 1}月`,
|
|
43
|
+
rows: ["一", "", "三", "", "五", "", ""],
|
|
44
|
+
yearLabel: "过去一年",
|
|
45
|
+
editsLabel: "期间编辑",
|
|
46
|
+
wordsLabel: "期间写作",
|
|
47
|
+
editsUnit: "次",
|
|
48
|
+
wordsUnit: "字",
|
|
49
|
+
active: (/** @type {number} */ count) => `${count} 天有编辑`,
|
|
50
|
+
todayEdits: (/** @type {number} */ count) => `今天 ${count} 次`,
|
|
51
|
+
todayWords: (/** @type {string} */ count) => `今天 ${count} 字`,
|
|
52
|
+
less: "少",
|
|
53
|
+
more: "多",
|
|
54
|
+
offline: "在 Gallery 里打开时显示",
|
|
55
|
+
failed: "读不到工作区的编辑记录",
|
|
56
|
+
locale: "zh-CN",
|
|
57
|
+
},
|
|
58
|
+
en: {
|
|
59
|
+
title: "Editing heatmap",
|
|
60
|
+
since: (/** @type {string} */ date) => `Recording since ${date}`,
|
|
61
|
+
edits: (/** @type {string} */ period, /** @type {number} */ count) => `${count} ${count === 1 ? "edit" : "edits"} ${period}`,
|
|
62
|
+
words: (/** @type {string} */ period, /** @type {string} */ count) => `${count} words ${period}`,
|
|
63
|
+
year: "in the past year",
|
|
64
|
+
after: (/** @type {string} */ date) => `since ${date}`,
|
|
65
|
+
day: (/** @type {string} */ date, /** @type {number} */ edits, /** @type {number} */ words) => (edits === 0 ? `${date}: no edits` : `${date}: ${edits} ${edits === 1 ? "edit" : "edits"}, ${words >= 0 ? "+" : "−"}${Math.abs(words)} words`),
|
|
66
|
+
before: (/** @type {string} */ date) => `${date}: not recorded yet`,
|
|
67
|
+
date: (/** @type {Date} */ date) => `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()]} ${date.getDate()}`,
|
|
68
|
+
weekday: (/** @type {Date} */ date) => `${["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][date.getDay()]}, ${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][date.getMonth()]} ${date.getDate()}`,
|
|
69
|
+
month: (/** @type {number} */ month) => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][month],
|
|
70
|
+
rows: ["Mon", "", "Wed", "", "Fri", "", ""],
|
|
71
|
+
yearLabel: "The past year",
|
|
72
|
+
editsLabel: "Edits",
|
|
73
|
+
wordsLabel: "Words written",
|
|
74
|
+
editsUnit: "edits",
|
|
75
|
+
wordsUnit: "words",
|
|
76
|
+
active: (/** @type {number} */ count) => `${count} ${count === 1 ? "day" : "days"} with edits`,
|
|
77
|
+
todayEdits: (/** @type {number} */ count) => `${count} today`,
|
|
78
|
+
todayWords: (/** @type {string} */ count) => `${count} today`,
|
|
79
|
+
less: "Less",
|
|
80
|
+
more: "More",
|
|
81
|
+
offline: "Shown when opened in Gallery",
|
|
82
|
+
failed: "The workspace's record of edits could not be read",
|
|
83
|
+
locale: "en",
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
|
|
88
|
+
function languageOf(/** @type {HTMLElement} */ root) {
|
|
89
|
+
const ui = root.getAttribute("data-ge-language");
|
|
90
|
+
return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const MOST_WEEKS = 53;
|
|
94
|
+
/** The days of the record it reads: as many as 53 weeks draw at the most (on a Sunday, its first square 370 days back). */
|
|
95
|
+
const DAYS = MOST_WEEKS * 7;
|
|
96
|
+
const two = (/** @type {number} */ value) => String(value).padStart(2, "0");
|
|
97
|
+
/** A local day as the record writes it, YYYY-MM-DD. @param {Date} date */
|
|
98
|
+
const dayOf = (date) => `${date.getFullYear()}-${two(date.getMonth() + 1)}-${two(date.getDate())}`;
|
|
99
|
+
/** The day `count` days after `date` (before, negative), at noon. @param {Date} date @param {number} count */
|
|
100
|
+
const after = (date, count) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + count, 12);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* How the squares fit a grid of `width` x `height` px (what the face has for it, its labels' room taken
|
|
104
|
+
* off): { cell, gap, weeks, across }. The gap is 3px, or 2px where seven squares of 9px and their gaps would not
|
|
105
|
+
* fit the height. The side is no more than seven of them fit the height (never cut off), at most 18px, and
|
|
106
|
+
* no bigger than 53 weeks across the width lets, but 8px where the height has room for that, and three
|
|
107
|
+
* fifths of what the height lets where that is more (a card far higher than a year's squares need, as on a
|
|
108
|
+
* narrow window: fewer weeks, bigger squares), 4px at the least; then as many weeks as fit across, at
|
|
109
|
+
* most 53, at least 1. `across` is the gap between the weeks: the gap, but where a year's 53 leave room
|
|
110
|
+
* across (a card far wider than high), that room shared between them, at most half a square more, so that
|
|
111
|
+
* a wide card's year reaches across it rather than leaving its right side empty.
|
|
112
|
+
* @param {number} width
|
|
113
|
+
* @param {number} height
|
|
114
|
+
*/
|
|
115
|
+
function fitOf(width, height) {
|
|
116
|
+
const gap = Math.floor((height - 18) / 7) >= 9 ? 3 : 2;
|
|
117
|
+
const byHeight = Math.floor((height - 6 * gap) / 7);
|
|
118
|
+
const byWidth = Math.floor((width - (MOST_WEEKS - 1) * gap) / MOST_WEEKS);
|
|
119
|
+
const cell = Math.max(4, Math.min(18, byHeight, Math.max(byWidth, 8, Math.floor(byHeight * 0.6))));
|
|
120
|
+
const weeks = Math.max(1, Math.min(MOST_WEEKS, Math.floor((width + gap) / (cell + gap))));
|
|
121
|
+
const room = weeks === MOST_WEEKS ? Math.floor((width - MOST_WEEKS * cell) / (MOST_WEEKS - 1)) : gap;
|
|
122
|
+
const across = Math.max(gap, Math.min(room, gap + Math.floor(cell / 2)));
|
|
123
|
+
return { cell, gap, weeks, across };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The weeks drawn, the last the one of `today` (a Date), `weeks` of them: [[{ date, day, future }…7]…],
|
|
128
|
+
* each a column, Monday first; `future` a day after today, which is not drawn.
|
|
129
|
+
* @param {Date} today
|
|
130
|
+
* @param {number} weeks
|
|
131
|
+
*/
|
|
132
|
+
function weeksOf(today, weeks) {
|
|
133
|
+
const monday = after(today, -((today.getDay() + 6) % 7));
|
|
134
|
+
const columns = [];
|
|
135
|
+
for (let week = weeks - 1; week >= 0; week--) {
|
|
136
|
+
const start = after(monday, -7 * week);
|
|
137
|
+
columns.push(Array.from({ length: 7 }, (_, row) => {
|
|
138
|
+
const date = after(start, row);
|
|
139
|
+
return { date, day: dayOf(date), future: dayOf(date) > dayOf(today) };
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
return columns;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The level of a day's square, 0 (none) to 4 (the most), of `value` (its edits, or the words it added,
|
|
147
|
+
* none for a day that took more away) against the most of any day drawn, `most`.
|
|
148
|
+
* @param {number} value
|
|
149
|
+
* @param {number} most
|
|
150
|
+
*/
|
|
151
|
+
function levelOf(value, most) {
|
|
152
|
+
if (!(value > 0) || !(most > 0)) return 0;
|
|
153
|
+
return Math.min(4, Math.max(1, Math.ceil((4 * value) / most)));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* What the card says of the record `days` (workspace.query("activity")'s data: [{ date, edits, words }],
|
|
158
|
+
* from the day it started or 53 weeks back to today), in `language`, counting `words` (the setting) or
|
|
159
|
+
* edits: the line at the top, and the value of each day by its date (a Map), and since which day (the
|
|
160
|
+
* first of them: before it nothing was kept).
|
|
161
|
+
* @param {Array<{ date: string, edits: number, words: number }>} days
|
|
162
|
+
* @param {boolean} words
|
|
163
|
+
* @param {"zh" | "en"} language
|
|
164
|
+
*/
|
|
165
|
+
function summaryOf(days, words, language) {
|
|
166
|
+
const said = WORDS[language];
|
|
167
|
+
const values = new Map(days.map((day) => [day.date, words ? Math.max(0, day.words) : day.edits]));
|
|
168
|
+
const since = days[0]?.date ?? null;
|
|
169
|
+
const edits = days.reduce((sum, day) => sum + day.edits, 0);
|
|
170
|
+
const sinceDate = since ? new Date(`${since}T12:00:00`) : null;
|
|
171
|
+
const period = days.length >= 365 || !sinceDate ? said.year : said.after(said.date(sinceDate));
|
|
172
|
+
let line;
|
|
173
|
+
if (edits === 0) line = sinceDate ? said.since(said.date(sinceDate)) : "";
|
|
174
|
+
else if (words) line = said.words(period, new Intl.NumberFormat(said.locale, { notation: "compact", maximumFractionDigits: 1 }).format(days.reduce((sum, day) => sum + day.words, 0)));
|
|
175
|
+
else line = said.edits(period, edits);
|
|
176
|
+
// The figures a wide card shows beside its squares: the edits (or the words) in all, how many days had
|
|
177
|
+
// any, and today's.
|
|
178
|
+
const format = (/** @type {number} */ value) => new Intl.NumberFormat(said.locale, Math.abs(value) >= 100_000 ? { notation: "compact", maximumFractionDigits: 1 } : { maximumFractionDigits: 0 }).format(value);
|
|
179
|
+
const written = days.reduce((sum, day) => sum + day.words, 0);
|
|
180
|
+
const today = days.find((day) => day.date === dayOf(new Date()));
|
|
181
|
+
const signed = (/** @type {number} */ value) => `${value > 0 ? "+" : value < 0 ? "−" : ""}${format(Math.abs(value))}`;
|
|
182
|
+
const figures = edits === 0 ? null : {
|
|
183
|
+
period: period === said.year ? said.yearLabel : period.replace(/^since /, "Since "),
|
|
184
|
+
label: words ? said.wordsLabel : said.editsLabel,
|
|
185
|
+
total: words ? format(Math.max(0, written)) : format(edits),
|
|
186
|
+
unit: words ? said.wordsUnit : said.editsUnit,
|
|
187
|
+
more: [said.active(days.filter((day) => day.edits > 0).length), ...(today && today.edits > 0 ? [words ? said.todayWords(signed(today.words)) : said.todayEdits(today.edits)] : [])],
|
|
188
|
+
};
|
|
189
|
+
return { line, values, since, figures };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* An element of the face, of `kind` (its class).
|
|
194
|
+
* @template {keyof HTMLElementTagNameMap} K
|
|
195
|
+
* @param {K} tag
|
|
196
|
+
* @param {string} kind
|
|
197
|
+
* @param {string} [text]
|
|
198
|
+
*/
|
|
199
|
+
function made(tag, kind, text) {
|
|
200
|
+
const node = document.createElement(tag);
|
|
201
|
+
node.className = `gallery-heatmap-${kind}`;
|
|
202
|
+
if (text !== undefined) node.textContent = text;
|
|
203
|
+
return node;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
DocKit.component({
|
|
207
|
+
id: "gallery/heatmap",
|
|
208
|
+
on: ["data", "source", "resize", "layout", "clock"],
|
|
209
|
+
mount(host, context) {
|
|
210
|
+
const language = languageOf(document.documentElement);
|
|
211
|
+
const words = WORDS[language];
|
|
212
|
+
const face = made("div", "face");
|
|
213
|
+
const head = made("div", "head");
|
|
214
|
+
const line = made("span", "line");
|
|
215
|
+
const chip = made("span", "chip");
|
|
216
|
+
chip.setAttribute("aria-hidden", "true");
|
|
217
|
+
chip.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7z"/><path d="M16 3v4M8 3v4M4 11h16"/></svg>';
|
|
218
|
+
head.append(chip, made("span", "title", words.title), line);
|
|
219
|
+
const body = made("div", "body");
|
|
220
|
+
const months = made("div", "months");
|
|
221
|
+
const rows = made("div", "rows");
|
|
222
|
+
for (const label of words.rows) rows.append(made("span", "row", label));
|
|
223
|
+
const grid = made("div", "grid");
|
|
224
|
+
const area = made("div", "area");
|
|
225
|
+
area.append(months, grid);
|
|
226
|
+
// Beside the squares on a wide card: what they count, its edits (or words) large, and a muted line of the days with any and today's.
|
|
227
|
+
const aside = made("div", "aside");
|
|
228
|
+
const period = made("span", "label");
|
|
229
|
+
const total = made("span", "total");
|
|
230
|
+
const totalNumber = made("span", "number");
|
|
231
|
+
const totalUnit = made("span", "unit");
|
|
232
|
+
total.append(totalNumber, totalUnit);
|
|
233
|
+
const asideMore = made("span", "more");
|
|
234
|
+
aside.append(period, total, asideMore);
|
|
235
|
+
body.append(aside, rows, area);
|
|
236
|
+
const legend = made("div", "legend");
|
|
237
|
+
legend.append(made("span", "less", words.less), ...[0, 1, 2, 3, 4].map((level) => {
|
|
238
|
+
const square = made("span", "square");
|
|
239
|
+
square.dataset.level = String(level);
|
|
240
|
+
return square;
|
|
241
|
+
}), made("span", "more", words.more));
|
|
242
|
+
face.append(head, body);
|
|
243
|
+
host.append(face);
|
|
244
|
+
const workspace = context.workspace;
|
|
245
|
+
if (!workspace) return void context.fail(new Error("its manifest's needs hold \"workspace\": context.workspace is not there"));
|
|
246
|
+
|
|
247
|
+
/** @type {Array<{ date: string, edits: number, words: number }> | null} */
|
|
248
|
+
let days = null;
|
|
249
|
+
let failure = "";
|
|
250
|
+
let drawn = "";
|
|
251
|
+
const draw = () => {
|
|
252
|
+
const settings = context.readJSON("settings");
|
|
253
|
+
if (settings === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
|
|
254
|
+
const byWords = settings !== null && typeof settings === "object" && settings.words === true;
|
|
255
|
+
// The room the grid has: the face's, its labels' and its lines' taken off.
|
|
256
|
+
const today = new Date();
|
|
257
|
+
const summary = summaryOf(days ?? [], byWords, language);
|
|
258
|
+
// The figures, where there are some (the aside shows them on a card wide enough: style.css).
|
|
259
|
+
const figures = failure ? null : summary.figures;
|
|
260
|
+
face.toggleAttribute("data-figures", figures !== null);
|
|
261
|
+
if (figures) {
|
|
262
|
+
period.textContent = figures.label;
|
|
263
|
+
totalNumber.textContent = figures.total;
|
|
264
|
+
totalUnit.textContent = figures.unit;
|
|
265
|
+
asideMore.replaceChildren(...figures.more.map((piece) => made("span", "piece", piece)));
|
|
266
|
+
}
|
|
267
|
+
// The room the grid has: the face's, its labels' and its lines' taken off (the weekdays' column and the gap after it; the aside, where it shows,
|
|
268
|
+
// its margin and the gap after it: a wide card's squares had run 3px past its edge where its weeks filled the room).
|
|
269
|
+
const width = body.clientWidth - rows.offsetWidth - 6 - (aside.offsetWidth > 0 ? aside.offsetWidth + 6 + 6 : 0);
|
|
270
|
+
const height = body.clientHeight - months.offsetHeight - 4;
|
|
271
|
+
const { cell, gap, weeks, across } = fitOf(width, height);
|
|
272
|
+
// Less to more: under the squares where the room left under them holds it, else at the head's end.
|
|
273
|
+
const shownAside = aside.offsetWidth > 0;
|
|
274
|
+
const under = height - (7 * cell + 6 * gap) >= 22;
|
|
275
|
+
const place = under ? area : head;
|
|
276
|
+
if (legend.parentElement !== place) place.append(legend);
|
|
277
|
+
// The head's quiet note: the line, or, where the figures say the rest beside the squares, their period.
|
|
278
|
+
line.textContent = failure || (shownAside && figures ? figures.period : summary.line);
|
|
279
|
+
const key = JSON.stringify([cell, gap, weeks, across, dayOf(today), byWords, days, failure, language, aside.offsetWidth, under]);
|
|
280
|
+
if (key === drawn) return;
|
|
281
|
+
drawn = key;
|
|
282
|
+
face.style.setProperty("--gallery-heatmap-cell", `${cell}px`);
|
|
283
|
+
face.style.setProperty("--gallery-heatmap-gap", `${gap}px`);
|
|
284
|
+
face.style.setProperty("--gallery-heatmap-across", `${across}px`);
|
|
285
|
+
face.style.setProperty("--gallery-heatmap-weeks", String(weeks));
|
|
286
|
+
face.toggleAttribute("data-small", cell < 6);
|
|
287
|
+
const columns = weeksOf(today, weeks);
|
|
288
|
+
const most = Math.max(0, ...[...summary.values.values()]);
|
|
289
|
+
const byDate = new Map((days ?? []).map((item) => [item.date, item]));
|
|
290
|
+
grid.replaceChildren(...columns.flatMap((column) => column.map(({ date, day, future }) => {
|
|
291
|
+
const square = made("span", "day");
|
|
292
|
+
if (future) {
|
|
293
|
+
square.classList.add("gallery-heatmap-future");
|
|
294
|
+
return square;
|
|
295
|
+
}
|
|
296
|
+
const recorded = days !== null && summary.since !== null && day >= summary.since;
|
|
297
|
+
if (!recorded) {
|
|
298
|
+
square.classList.add("gallery-heatmap-before");
|
|
299
|
+
square.title = days === null ? words.weekday(date) : words.before(words.weekday(date));
|
|
300
|
+
return square;
|
|
301
|
+
}
|
|
302
|
+
const entry = byDate.get(day);
|
|
303
|
+
square.dataset.level = String(levelOf(summary.values.get(day) ?? 0, most));
|
|
304
|
+
square.title = words.day(words.weekday(date), entry?.edits ?? 0, entry?.words ?? 0);
|
|
305
|
+
return square;
|
|
306
|
+
})));
|
|
307
|
+
// A month's name over the week its first day falls in, none closer to the one before than its own
|
|
308
|
+
// width (about 26px: "12月", "Sep") and three weeks.
|
|
309
|
+
const apart = Math.max(3, Math.ceil(28 / (cell + across)));
|
|
310
|
+
let last = -apart;
|
|
311
|
+
months.replaceChildren(...columns.flatMap((column, index) => {
|
|
312
|
+
const first = column.find(({ date }) => date.getDate() === 1);
|
|
313
|
+
if (!first || index - last < apart) return [];
|
|
314
|
+
last = index;
|
|
315
|
+
const label = made("span", "month", words.month(first.date.getMonth()));
|
|
316
|
+
label.style.setProperty("--gallery-heatmap-week", String(index));
|
|
317
|
+
return [label];
|
|
318
|
+
}));
|
|
319
|
+
};
|
|
320
|
+
let asking = 0; // the last read asked: an older answer that comes after it is dropped
|
|
321
|
+
const read = () => {
|
|
322
|
+
const ticket = ++asking;
|
|
323
|
+
workspace.query("activity", { days: DAYS }).then(({ data }) => {
|
|
324
|
+
if (ticket !== asking || context.signal.aborted) return;
|
|
325
|
+
days = data;
|
|
326
|
+
failure = "";
|
|
327
|
+
draw();
|
|
328
|
+
}, (/** @type {any} */ error) => {
|
|
329
|
+
if (ticket !== asking || context.signal.aborted) return;
|
|
330
|
+
days = null;
|
|
331
|
+
failure = error?.code === "offline" ? words.offline : words.failed;
|
|
332
|
+
draw();
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
draw();
|
|
336
|
+
read();
|
|
337
|
+
// The room the squares have, its height too (the kit's `resize` hears its width alone): a card given its
|
|
338
|
+
// height after the first draw (a board laid out late) is drawn again as it gets it.
|
|
339
|
+
if (typeof ResizeObserver === "function") {
|
|
340
|
+
const watch = new ResizeObserver(() => draw());
|
|
341
|
+
watch.observe(body);
|
|
342
|
+
context.signal?.addEventListener("abort", () => watch.disconnect(), { once: true });
|
|
343
|
+
}
|
|
344
|
+
return {
|
|
345
|
+
update(reason, detail) {
|
|
346
|
+
if ((reason === "data" && detail === "activity") || (reason === "clock" && detail === "day")) read();
|
|
347
|
+
else if (reason !== "data" && reason !== "clock") draw();
|
|
348
|
+
},
|
|
349
|
+
};
|
|
350
|
+
},
|
|
351
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 120"><rect width="240" height="120" rx="8" fill="#f3f3f1"/><rect x="16.5" y="12.5" width="207" height="95" rx="12" fill="#ffffff" stroke="#e7e6e3"/><rect x="30" y="24" width="14" height="14" rx="4.5" fill="#ebf2fa"/><g transform="translate(32 26) scale(.4167)" fill="none" stroke="#2e7cd1" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7z"/><path d="M16 3v4M8 3v4M4 11h16"/></g><rect x="50" y="28" width="46" height="6" rx="3" fill="#3b3a37"/><rect x="150" y="29" width="60" height="5" rx="2.5" fill="#c4c2bd"/><rect x="36" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="36" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="43" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="50" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="57" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="64" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="71" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="78" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="78" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="78" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="78" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="78" y="76" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="78" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="78" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="85" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="85" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="85" y="62" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="85" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="85" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="85" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="85" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="92" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="92" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="99" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="99" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="99" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="99" y="69" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="99" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="99" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="99" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="106" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="106" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="106" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="106" y="69" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="106" y="76" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="106" y="83" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="106" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="113" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="113" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="113" y="62" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="113" y="69" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="113" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="113" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="113" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="120" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="120" y="55" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="120" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="120" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="120" y="76" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="120" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="120" y="90" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="127" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="127" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="127" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="127" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="127" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="127" y="83" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="127" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="62" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="134" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="134" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="141" y="83" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="141" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="148" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="148" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="148" y="62" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="148" y="69" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="148" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="148" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="148" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="155" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="155" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="155" y="62" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="155" y="69" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="155" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="155" y="83" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="155" y="90" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="162" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="162" y="55" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="162" y="62" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="162" y="69" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="162" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="162" y="83" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="162" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="169" y="48" width="5.5" height="5.5" rx="1.4" fill="#2e7cd1"/><rect x="169" y="55" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="169" y="62" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="169" y="69" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="169" y="76" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="169" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="169" y="90" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="176" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="176" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="176" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="176" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="176" y="76" width="5.5" height="5.5" rx="1.4" fill="#2e7cd1"/><rect x="176" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="176" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="183" y="48" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="183" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="183" y="62" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="183" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="183" y="76" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="183" y="83" width="5.5" height="5.5" rx="1.4" fill="#2e7cd1"/><rect x="183" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="190" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="190" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="190" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="190" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="190" y="76" width="5.5" height="5.5" rx="1.4" fill="#93b9e6"/><rect x="190" y="83" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="190" y="90" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="48" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="55" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="62" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="197" y="83" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="197" y="90" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="204" y="48" width="5.5" height="5.5" rx="1.4" fill="#2e7cd1"/><rect x="204" y="55" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/><rect x="204" y="62" width="5.5" height="5.5" rx="1.4" fill="#2e7cd1"/><rect x="204" y="69" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="204" y="76" width="5.5" height="5.5" rx="1.4" fill="#efeeec"/><rect x="204" y="83" width="5.5" height="5.5" rx="1.4" fill="#5c97da"/><rect x="204" y="90" width="5.5" height="5.5" rx="1.4" fill="#c9dcf2"/></svg>
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/* Every selector starts at the instance and goes down a step at a time (>), so that nothing here
|
|
2
|
+
reaches the rest of the page. The face fills its card on a custom page (the board draws the frame), in
|
|
3
|
+
the kit's card tokens: its head (the chip, 编辑热力图, its line, the quiet note at its end (how many
|
|
4
|
+
edits, or since when it is kept; the period where the figures show), its end clear of the card's grip); the
|
|
5
|
+
weekdays down the left, the months over the weeks, the squares a column a week, Monday at the top. The
|
|
6
|
+
squares' side and gaps are the script's (--gallery-heatmap-cell, --gallery-heatmap-gap, and
|
|
7
|
+
--gallery-heatmap-across between the weeks, wider on a card far wider than high: as big as the card
|
|
8
|
+
lets them be), their corners a quarter of their side, the grid hung from the left under the head
|
|
9
|
+
and the room left over at its right; the weekdays' column left out where a square is under 6px
|
|
10
|
+
(data-small: its words would run into each other). A day drawn by its level, 0 to 4, the accent's
|
|
11
|
+
shades on the card's fill (a quarter, a half, three quarters of it, and the accent itself; in dark two
|
|
12
|
+
fifths, three fifths, four fifths, so that the first stands off the track), a day of none the track's
|
|
13
|
+
gray (a step stronger than the track, so that a year of none still reads as a grid), a day before the
|
|
14
|
+
record only outlined in that gray, an empty slot rather than a day of nothing, so that a record just
|
|
15
|
+
begun reads as starting now; a day to come none. A wide card with something counted (data-figures)
|
|
16
|
+
shows its figures beside the squares: what they count, the edits (or words) in all, large (the cards'
|
|
17
|
+
hero size), the days that had any and today's, a hairline at their right; under 150px high, today's
|
|
18
|
+
left out, under 124px what they count too. Less to more (the script places it) under the squares at their left where the room
|
|
19
|
+
under them holds it, else at the head's end, where a card too narrow for it beside the line leaves it out. */
|
|
20
|
+
[data-doc-component="gallery/heatmap"] {
|
|
21
|
+
--gallery-heatmap-0: light-dark(rgb(33 27 23 / 10%), rgb(255 255 255 / 11%));
|
|
22
|
+
--gallery-heatmap-1: light-dark(color-mix(in oklab, var(--gallery-accent) 26%, var(--gallery-card-fill)), color-mix(in oklab, var(--gallery-accent) 42%, var(--gallery-card-fill)));
|
|
23
|
+
--gallery-heatmap-2: light-dark(color-mix(in oklab, var(--gallery-accent) 50%, var(--gallery-card-fill)), color-mix(in oklab, var(--gallery-accent) 62%, var(--gallery-card-fill)));
|
|
24
|
+
--gallery-heatmap-3: light-dark(color-mix(in oklab, var(--gallery-accent) 75%, var(--gallery-card-fill)), color-mix(in oklab, var(--gallery-accent) 81%, var(--gallery-card-fill)));
|
|
25
|
+
--gallery-heatmap-4: var(--gallery-accent);
|
|
26
|
+
height: 12em;
|
|
27
|
+
container-type: size;
|
|
28
|
+
> .gallery-heatmap-face {
|
|
29
|
+
--gallery-heatmap-cell: 10px;
|
|
30
|
+
--gallery-heatmap-gap: 3px;
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
gap: var(--gallery-face-gap);
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
height: 100%;
|
|
36
|
+
min-height: 0;
|
|
37
|
+
color: var(--gallery-text);
|
|
38
|
+
font-size: 12px;
|
|
39
|
+
line-height: 1.3;
|
|
40
|
+
}
|
|
41
|
+
> .gallery-heatmap-face > .gallery-heatmap-head {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 8px;
|
|
45
|
+
flex: none;
|
|
46
|
+
min-width: 0;
|
|
47
|
+
padding-inline-end: var(--gallery-grip-room, 0px);
|
|
48
|
+
}
|
|
49
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-chip {
|
|
50
|
+
flex: none;
|
|
51
|
+
display: inline-flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
width: var(--gallery-chip-size);
|
|
55
|
+
height: var(--gallery-chip-size);
|
|
56
|
+
border-radius: var(--gallery-chip-radius);
|
|
57
|
+
background: var(--gallery-accent-soft);
|
|
58
|
+
color: var(--gallery-accent);
|
|
59
|
+
}
|
|
60
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-chip > svg { width: var(--gallery-chip-icon); height: var(--gallery-chip-icon); }
|
|
61
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-title { flex: none; font-size: var(--gallery-title-size); font-weight: 600; line-height: var(--gallery-title-line); color: var(--gallery-text-strong); }
|
|
62
|
+
/* The head's last piece (its line, or less to more where the script put it there) at the content's edge, faded while the card's grip shows. */
|
|
63
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-line:last-child,
|
|
64
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-legend { margin-inline-end: calc(-1 * var(--gallery-grip-room, 0px)); opacity: calc(1 - var(--gallery-grip-shown, 0)); transition: opacity .12s ease-out; }
|
|
65
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-line {
|
|
66
|
+
flex: 1 1 auto;
|
|
67
|
+
min-width: 0;
|
|
68
|
+
margin-inline-start: 4px;
|
|
69
|
+
font-size: var(--gallery-meta-size);
|
|
70
|
+
color: var(--doc-muted);
|
|
71
|
+
text-align: end;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
text-overflow: ellipsis;
|
|
75
|
+
}
|
|
76
|
+
> .gallery-heatmap-face > .gallery-heatmap-body {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: flex-start;
|
|
80
|
+
gap: 6px;
|
|
81
|
+
flex: 1 1 auto;
|
|
82
|
+
min-height: 0;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
}
|
|
85
|
+
/* The figures beside the squares (a wide card's, where something is counted): what they count, small and
|
|
86
|
+
muted, over the edits (or words) in all, large, their unit after them, and a muted line of the days
|
|
87
|
+
that had any and today's; a hairline at their right. */
|
|
88
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside {
|
|
89
|
+
display: none;
|
|
90
|
+
flex: none;
|
|
91
|
+
flex-direction: column;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
gap: 4px;
|
|
94
|
+
align-self: stretch;
|
|
95
|
+
width: clamp(120px, 18cqi, 190px);
|
|
96
|
+
box-sizing: border-box;
|
|
97
|
+
margin-inline-end: 6px;
|
|
98
|
+
padding-inline-end: 16px;
|
|
99
|
+
border-inline-end: 1px solid var(--doc-grid);
|
|
100
|
+
}
|
|
101
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-label { font-size: var(--gallery-meta-size); line-height: 16px; color: var(--doc-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
102
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-total { display: flex; align-items: baseline; flex-wrap: wrap; }
|
|
103
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-total > .gallery-heatmap-number {
|
|
104
|
+
font-size: var(--gallery-hero-size);
|
|
105
|
+
line-height: 1.1;
|
|
106
|
+
font-weight: var(--gallery-numeral-weight);
|
|
107
|
+
letter-spacing: var(--gallery-numeral-tracking);
|
|
108
|
+
color: var(--gallery-text-strong);
|
|
109
|
+
font-variant-numeric: tabular-nums;
|
|
110
|
+
}
|
|
111
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-total > .gallery-heatmap-unit { margin-inline-start: var(--gallery-unit-gap); font-size: max(12px, calc(var(--gallery-hero-size) * .4)); font-weight: 500; color: var(--doc-muted); }
|
|
112
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-more { display: flex; flex-direction: column; font-size: var(--gallery-meta-size); line-height: 1.5; color: var(--doc-muted); }
|
|
113
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-more > .gallery-heatmap-piece { white-space: nowrap; }
|
|
114
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-rows {
|
|
115
|
+
display: grid;
|
|
116
|
+
flex: none;
|
|
117
|
+
grid-template-rows: repeat(7, var(--gallery-heatmap-cell));
|
|
118
|
+
gap: var(--gallery-heatmap-gap);
|
|
119
|
+
margin-top: 18px;
|
|
120
|
+
color: var(--doc-muted);
|
|
121
|
+
font-size: 10px;
|
|
122
|
+
}
|
|
123
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-rows > .gallery-heatmap-row { display: flex; align-items: center; line-height: 1; }
|
|
124
|
+
> .gallery-heatmap-face[data-small] > .gallery-heatmap-body > .gallery-heatmap-rows { display: none; }
|
|
125
|
+
/* Less to more under the squares: the weekdays as much shorter at the bottom, so that they stay beside their rows. */
|
|
126
|
+
> .gallery-heatmap-face > .gallery-heatmap-body:has(> .gallery-heatmap-area > .gallery-heatmap-legend) > .gallery-heatmap-rows { margin-bottom: 18px; }
|
|
127
|
+
/* As wide as its weeks, hung from the left beside the weekdays. */
|
|
128
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area { flex: none; width: calc(var(--gallery-heatmap-weeks, 53) * (var(--gallery-heatmap-cell) + var(--gallery-heatmap-across, var(--gallery-heatmap-gap))) - var(--gallery-heatmap-across, var(--gallery-heatmap-gap))); }
|
|
129
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-months {
|
|
130
|
+
position: relative;
|
|
131
|
+
height: 14px;
|
|
132
|
+
margin-bottom: 4px;
|
|
133
|
+
color: var(--doc-muted);
|
|
134
|
+
font-size: 10px;
|
|
135
|
+
line-height: 14px;
|
|
136
|
+
}
|
|
137
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-months > .gallery-heatmap-month {
|
|
138
|
+
position: absolute;
|
|
139
|
+
top: 0;
|
|
140
|
+
left: calc(var(--gallery-heatmap-week) * (var(--gallery-heatmap-cell) + var(--gallery-heatmap-across, var(--gallery-heatmap-gap))));
|
|
141
|
+
white-space: nowrap;
|
|
142
|
+
}
|
|
143
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid {
|
|
144
|
+
display: grid;
|
|
145
|
+
grid-auto-flow: column;
|
|
146
|
+
grid-template-rows: repeat(7, var(--gallery-heatmap-cell));
|
|
147
|
+
grid-auto-columns: var(--gallery-heatmap-cell);
|
|
148
|
+
gap: var(--gallery-heatmap-gap) var(--gallery-heatmap-across, var(--gallery-heatmap-gap));
|
|
149
|
+
}
|
|
150
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day {
|
|
151
|
+
box-sizing: border-box;
|
|
152
|
+
border-radius: max(2px, calc(var(--gallery-heatmap-cell) / 4));
|
|
153
|
+
background: var(--gallery-heatmap-0);
|
|
154
|
+
}
|
|
155
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day[data-level="1"] { background: var(--gallery-heatmap-1); }
|
|
156
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day[data-level="2"] { background: var(--gallery-heatmap-2); }
|
|
157
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day[data-level="3"] { background: var(--gallery-heatmap-3); }
|
|
158
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day[data-level="4"] { background: var(--gallery-heatmap-4); }
|
|
159
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day.gallery-heatmap-before { background: transparent; box-shadow: inset 0 0 0 1px var(--gallery-heatmap-0); }
|
|
160
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-grid > .gallery-heatmap-day.gallery-heatmap-future { visibility: hidden; }
|
|
161
|
+
/* Less to more, wherever the script put it: under the squares or at the head's end. */
|
|
162
|
+
> .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-legend,
|
|
163
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-legend {
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
align-self: center;
|
|
167
|
+
gap: 3px;
|
|
168
|
+
flex: none;
|
|
169
|
+
color: var(--doc-muted);
|
|
170
|
+
font-size: 10px;
|
|
171
|
+
line-height: 1;
|
|
172
|
+
> .gallery-heatmap-less { margin-inline-end: 3px; }
|
|
173
|
+
> .gallery-heatmap-more { margin-inline-start: 3px; }
|
|
174
|
+
> .gallery-heatmap-square { width: 10px; height: 10px; border-radius: 3px; background: var(--gallery-heatmap-0); }
|
|
175
|
+
> .gallery-heatmap-square[data-level="1"] { background: var(--gallery-heatmap-1); }
|
|
176
|
+
> .gallery-heatmap-square[data-level="2"] { background: var(--gallery-heatmap-2); }
|
|
177
|
+
> .gallery-heatmap-square[data-level="3"] { background: var(--gallery-heatmap-3); }
|
|
178
|
+
> .gallery-heatmap-square[data-level="4"] { background: var(--gallery-heatmap-4); }
|
|
179
|
+
}
|
|
180
|
+
> .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-area > .gallery-heatmap-legend { align-self: flex-start; margin-top: 8px; }
|
|
181
|
+
}
|
|
182
|
+
/* A wide card (8 cells and more) with something counted: the figures beside the squares. */
|
|
183
|
+
@container (min-width: 560px) {
|
|
184
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face[data-figures] > .gallery-heatmap-body > .gallery-heatmap-aside { display: flex; }
|
|
185
|
+
}
|
|
186
|
+
/* Not so high (a 2-high card from a window 1440px wide): today's left out of the figures, which would not fit with the rest. */
|
|
187
|
+
@container (max-height: 150px) {
|
|
188
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-more > .gallery-heatmap-piece + .gallery-heatmap-piece { display: none; }
|
|
189
|
+
}
|
|
190
|
+
/* Low (a 2-high card from a window under 1440px wide): what the figures count left out too, the number the figure size. */
|
|
191
|
+
@container (max-height: 124px) {
|
|
192
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-label { display: none; }
|
|
193
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face > .gallery-heatmap-body > .gallery-heatmap-aside > .gallery-heatmap-total > .gallery-heatmap-number { font-size: var(--gallery-figure-size); }
|
|
194
|
+
}
|
|
195
|
+
/* A card too narrow for less to more beside the line: the line alone. */
|
|
196
|
+
@container (max-width: 440px) {
|
|
197
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-legend { display: none; }
|
|
198
|
+
[data-doc-component="gallery/heatmap"] > .gallery-heatmap-face > .gallery-heatmap-head > .gallery-heatmap-line { margin-inline-end: calc(-1 * var(--gallery-grip-room, 0px)); opacity: calc(1 - var(--gallery-grip-shown, 0)); transition: opacity .12s ease-out; }
|
|
199
|
+
}
|
|
200
|
+
/* On a custom page the face is the card's: as high as what the card holds inside its padding. */
|
|
201
|
+
.gallery-card > [data-doc-component="gallery/heatmap"] { height: 100%; }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 编辑热力图 (gallery/heatmap)
|
|
2
|
+
|
|
3
|
+
A card for a custom page (its places are `page`, its needs `workspace`): how much the workspace was edited each day of the past year, as GitHub draws a year of contributions, a column a week, a square a day, darker for a day of more. What it counts is Gallery's own record of edits (the reader's saves and the Agent's writes, by day, since the workspace's first start of a Gallery that keeps it): the edits of a day, or with its setting the words it added. Use it on the home page.
|
|
4
|
+
|
|
5
|
+
## Settings
|
|
6
|
+
|
|
7
|
+
Its one setting is the card's form, which the user opens from the grip at the card's top right › 设置…:
|
|
8
|
+
|
|
9
|
+
| Key | Label | Type | What it is |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| `words` | 按字数显示 | switch | each day by the words it added, not by how many edits it had |
|
|
12
|
+
|
|
13
|
+
It is kept in its data part `settings`, a `<script type="application/json">`: `{}` (template.html, what a menu adds) counts edits. Write `{"words":true}` when the user asks for the words written. The block reads it and writes nothing.
|
|
14
|
+
|
|
15
|
+
## How to write it
|
|
16
|
+
|
|
17
|
+
Put it on a custom page as a card of its board, `<section class="gallery-card" data-card-id="…" data-x data-y data-w data-h>`, holding one instance, after `gallery block add heatmap`, the instance as template.html has it. Sizes: 8 × 3 (the default: most of a year, its weekdays and less to more under the squares), 12 × 3 (a year) and 4 × 3 (the last weeks alone): as many weeks as the card holds are drawn, the last ending today.
|
|
18
|
+
|
|
19
|
+
## How it looks
|
|
20
|
+
|
|
21
|
+
编辑热力图 beside a calendar's chip, how many edits there were at the top line's end, the weekdays down the left (Monday first), the months over the weeks, the squares in the accent's shades, darker for a day of more; in the kit's card tokens (as every Gallery card: a head of a tinted chip and a title, its end clear of the card's grip), light and dark. Less to more stands under the squares where the card has the room, else at the top line's end. On a wide card (8 cells and more), once anything is counted, the figures stand at the left of the squares: 期间编辑, the edits (or words) in all, large, how many days had any and today's, the top line then saying since when. A day before the record began is an outlined square, an empty slot. Each square says its day and its count where the pointer rests on it. Until anything is counted the line says since when the record is kept (从 11月8日 开始记录). It follows by itself: a document saved, or written by the Agent, shows on today's square at once, and what was written while Gallery did not run is counted on its day when it starts. In an exported file, which has no workspace to read, the line says it shows when the page is opened in Gallery. The script runs with the rights of the page's own scripts, as any block's does.
|