@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,186 @@
|
|
|
1
|
+
/* 柔光风格's static card has no script: what its content holds, any HTML, is what a reader sees. Its content
|
|
2
|
+
(the instance's one div) is the card's face: on a custom page it is taken out over the card's padding and
|
|
3
|
+
given the soft frame's, by the card's size (the instance is a container of it: 16px at the sides of a card
|
|
4
|
+
one cell high, its line in the middle; 18px on a 2 × 2 card; 24px on one 3 cells high or more; else 20px),
|
|
5
|
+
with a faint wash of the accent from the card's top over whatever fill the card has (the board's, or one
|
|
6
|
+
the page gives it). It gives the HTML the soft cards' reading look: a heading it starts with, where more
|
|
7
|
+
follows, is drawn as the cards' head row (a chip of lines in the accent's soft tint, the title; small words
|
|
8
|
+
in it its quiet meta at the end); a list a dot an item, an item that is one link a row like the sidebar's
|
|
9
|
+
(a small square with a link's picture before it, small words in it at its end), a paragraph that is one
|
|
10
|
+
link the accent's with an arrow out after it; a table of hairlines, its first column words and the others
|
|
11
|
+
numbers at the right; on a 2 × 2 card what follows the heading at the bottom; on a card one cell high its
|
|
12
|
+
line in the middle, a link there after a chip of a page and before an arrow out, a first small span (an
|
|
13
|
+
emoji) on a chip. Each rule weighs nothing (:where()), so that the page's own <style> and an inline style
|
|
14
|
+
win. Its colors are a share of the color it stands in (currentColor), but the chips', the links' and the
|
|
15
|
+
wash's, so that the page may color a card. The grip's corner: the first thing in it keeps its end clear.
|
|
16
|
+
Nothing in it: the cards' empty face. Every selector stands in the instance. */
|
|
17
|
+
[data-doc-component="gallery-soft/static"] {
|
|
18
|
+
--soft-font: "PingFang SC", "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
|
|
19
|
+
--soft-num: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
20
|
+
--soft-accent: light-dark(#3e7ac6, #7eade2);
|
|
21
|
+
--soft-accent-ink: light-dark(#356cb3, #98bee9);
|
|
22
|
+
--soft-accent-soft: light-dark(#ecf3fb, rgb(126 173 226 / 14%));
|
|
23
|
+
--soft-wash: linear-gradient(180deg, light-dark(rgb(62 122 198 / 6%), rgb(126 173 226 / 7%)) 0%, transparent 52%);
|
|
24
|
+
--soft-pad: 20px;
|
|
25
|
+
--soft-grip-room: 0px;
|
|
26
|
+
--soft-lines: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 7h14M5 12h14M5 17h8.5'/%3E%3C/svg%3E");
|
|
27
|
+
--soft-link: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1'/%3E%3Cpath d='M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1'/%3E%3C/svg%3E");
|
|
28
|
+
--soft-doc: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 3.5h6.8L18 7.7V20.5H7z'/%3E%3Cpath d='M13.5 3.5V8H18'/%3E%3C/svg%3E");
|
|
29
|
+
--soft-out: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 16L16.5 7.5'/%3E%3Cpath d='M9.5 7.5h7v7'/%3E%3C/svg%3E");
|
|
30
|
+
> div {
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
font: 13.5px/1.5 var(--soft-font);
|
|
36
|
+
overflow-wrap: break-word;
|
|
37
|
+
text-wrap: pretty;
|
|
38
|
+
-webkit-font-smoothing: antialiased;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/* On a custom page: the content over the card's whole room, its padding the soft frame's by the card's size
|
|
42
|
+
(the board's line takes the first pixel of it). (:first-child: the board's rule that takes the outer margins
|
|
43
|
+
off an instance's first and last child weighs as much as a class more.) */
|
|
44
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] { height: 100%; container-type: size; }
|
|
45
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] > div:first-child {
|
|
46
|
+
--soft-grip-room: max(0px, calc(40px - var(--soft-pad)));
|
|
47
|
+
height: calc(100% + 2 * var(--gallery-card-pad));
|
|
48
|
+
margin: calc(-1 * var(--gallery-card-pad));
|
|
49
|
+
padding: calc(var(--soft-pad) - 1px);
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
border-radius: calc(var(--gallery-card-radius) - 1px);
|
|
52
|
+
background: var(--soft-wash);
|
|
53
|
+
}
|
|
54
|
+
@container (min-height: 141px) {
|
|
55
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] > div:first-child { --soft-pad: 24px; }
|
|
56
|
+
}
|
|
57
|
+
@container (min-height: 61px) and (max-height: 140px) and (max-width: 140px) {
|
|
58
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] > div:first-child { --soft-pad: 18px; }
|
|
59
|
+
}
|
|
60
|
+
@container (max-height: 60px) {
|
|
61
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] > div:first-child { --soft-pad: 16px; padding-block: 0; justify-content: center; }
|
|
62
|
+
}
|
|
63
|
+
/* Its HTML's look. In the instance's scope, each rule as light as its elements (a page's own rule of a class wins
|
|
64
|
+
over it, and it wins over the kit's rules of an element alone, by the scope's nearness). */
|
|
65
|
+
@scope ([data-doc-component="gallery-soft/static"]) {
|
|
66
|
+
:where(:scope > div > *) { flex: none; margin: 0; }
|
|
67
|
+
:where(:scope > div > :first-child) { padding-inline-end: var(--soft-grip-room); }
|
|
68
|
+
h1, h2, h3, h4, h5, h6 { margin: 10px 0 4px; font-size: 15px; line-height: 1.4; font-weight: 600; }
|
|
69
|
+
:is(p, ul, ol, dl, blockquote, table, figure, pre) + :is(p, ul, ol, dl, blockquote, table, figure, pre) { margin-top: 8px; }
|
|
70
|
+
a { color: var(--soft-accent-ink); text-decoration: none; }
|
|
71
|
+
a:hover { text-decoration: underline; }
|
|
72
|
+
small { font-size: 12px; color: color-mix(in srgb, currentColor 62%, transparent); }
|
|
73
|
+
img, svg, video { max-width: 100%; align-self: flex-start; }
|
|
74
|
+
img, video { height: auto; }
|
|
75
|
+
code { padding: 0 4px; border-radius: 4px; background: color-mix(in srgb, currentColor 6%, transparent); font-family: var(--doc-mono); font-size: .9em; }
|
|
76
|
+
blockquote { padding-inline-start: 12px; border-inline-start: 3px solid color-mix(in srgb, currentColor 18%, transparent); color: color-mix(in srgb, currentColor 65%, transparent); }
|
|
77
|
+
hr { margin: 10px 0; border: 0; border-top: 1px solid color-mix(in srgb, currentColor 8%, transparent); }
|
|
78
|
+
/* The heading it starts with, where more follows: the cards' head row, a chip of lines before it, small words in it its quiet meta at the end. */
|
|
79
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) {
|
|
80
|
+
position: relative;
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
gap: 10px;
|
|
84
|
+
min-height: 28px;
|
|
85
|
+
margin: 0;
|
|
86
|
+
font-size: 14px;
|
|
87
|
+
line-height: 20px;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
}
|
|
90
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child)::before { content: ""; flex: none; width: 28px; height: 28px; border-radius: 8px; background: var(--soft-accent-soft); }
|
|
91
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child)::after {
|
|
92
|
+
content: "";
|
|
93
|
+
position: absolute;
|
|
94
|
+
top: 50%;
|
|
95
|
+
left: 6px;
|
|
96
|
+
width: 16px;
|
|
97
|
+
height: 16px;
|
|
98
|
+
margin-top: -8px;
|
|
99
|
+
background: var(--soft-accent);
|
|
100
|
+
-webkit-mask: var(--soft-lines) center / contain no-repeat;
|
|
101
|
+
mask: var(--soft-lines) center / contain no-repeat;
|
|
102
|
+
}
|
|
103
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) > small { margin-left: auto; margin-inline-end: calc(-1 * var(--soft-grip-room)); font-weight: 400; white-space: nowrap; opacity: calc(1 - var(--gallery-grip-shown, 0)); transition: opacity .12s ease-out; }
|
|
104
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) + * { margin-top: 10px; }
|
|
105
|
+
/* Its subtitle: a paragraph of small words alone under the head; what follows it a little apart. */
|
|
106
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child + p:has(> small:only-child) { margin-top: 6px; }
|
|
107
|
+
p:has(> small:only-child) > small { font-size: 13px; }
|
|
108
|
+
p:has(> small:only-child) + * { margin-top: 10px; }
|
|
109
|
+
/* A list: a dot an item. */
|
|
110
|
+
ul { display: flex; flex-direction: column; gap: 8px; padding: 0; list-style: none; }
|
|
111
|
+
ul > li { display: flex; gap: 10px; align-items: baseline; }
|
|
112
|
+
ul > li::before { content: ""; flex: none; width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .38; transform: translateY(-2px); }
|
|
113
|
+
ol { padding-inline-start: 1.4em; }
|
|
114
|
+
/* An item that is one link: a row like the sidebar's, a link's picture on a soft square before it, its small words at its end. */
|
|
115
|
+
ul:has(> li > a:only-child) { gap: 0; }
|
|
116
|
+
ul > li:has(> a:only-child)::before { display: none; }
|
|
117
|
+
li > a:only-child { position: relative; display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; height: 30px; margin: 0 -6px; padding: 0 6px; border-radius: 6px; color: inherit; }
|
|
118
|
+
li > a:only-child:hover { text-decoration: none; background: color-mix(in srgb, currentColor 6%, transparent); }
|
|
119
|
+
li > a:only-child::before { content: ""; flex: none; width: 18px; height: 18px; border-radius: 5px; background: color-mix(in srgb, currentColor 7%, transparent); }
|
|
120
|
+
li > a:only-child::after { content: ""; position: absolute; top: 50%; left: 9px; width: 12px; height: 12px; margin-top: -6px; background: color-mix(in srgb, currentColor 55%, transparent); -webkit-mask: var(--soft-link) center / contain no-repeat; mask: var(--soft-link) center / contain no-repeat; }
|
|
121
|
+
/* one to a page of the workspace (no scheme: ../<slug>/doc.html, #…, /…) a page's picture */
|
|
122
|
+
li > a:only-child:not([href*=":"])::after { -webkit-mask-image: var(--soft-doc); mask-image: var(--soft-doc); }
|
|
123
|
+
li > a:only-child > small { margin-left: auto; font: 11.5px var(--soft-num); color: color-mix(in srgb, currentColor 45%, transparent); white-space: nowrap; }
|
|
124
|
+
/* A paragraph that is one link: the accent's, an arrow out after it; the last such at the card's bottom. */
|
|
125
|
+
p > a:only-child { display: inline-flex; align-items: center; gap: 3px; font-size: 13px; }
|
|
126
|
+
p > a:only-child::after { content: ""; width: 13px; height: 13px; background: currentColor; -webkit-mask: var(--soft-out) center / contain no-repeat; mask: var(--soft-out) center / contain no-repeat; }
|
|
127
|
+
:scope > div > p:last-child:not(:first-child):has(> a:only-child) { margin-top: auto; padding-top: 8px; }
|
|
128
|
+
/* A table: hairlines between the rows, its head small and muted, its columns after the first numbers at the right. */
|
|
129
|
+
table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
|
|
130
|
+
th { padding: 0 0 4px; text-align: left; font-size: 11.5px; font-weight: 500; color: color-mix(in srgb, currentColor 62%, transparent); }
|
|
131
|
+
td { padding: 3px 0; text-align: left; box-shadow: inset 0 1px 0 color-mix(in srgb, currentColor 7%, transparent); }
|
|
132
|
+
:is(th, td):not(:first-child) { text-align: right; font-family: var(--soft-num); }
|
|
133
|
+
}
|
|
134
|
+
/* A 2 × 2 card: what follows the heading at the bottom, the head and the rows a size smaller. */
|
|
135
|
+
@container (min-height: 61px) and (max-height: 140px) and (max-width: 140px) {
|
|
136
|
+
@scope ([data-doc-component="gallery-soft/static"]) {
|
|
137
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) { gap: 8px; min-height: 24px; font-size: 13px; }
|
|
138
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child)::before { width: 24px; height: 24px; border-radius: 7px; }
|
|
139
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child)::after { left: 5px; width: 14px; height: 14px; margin-top: -7px; }
|
|
140
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) + * { margin-top: auto; }
|
|
141
|
+
li > a:only-child { gap: 8px; height: 26px; font-size: 13px; }
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* A card 2 cells high and wider than 2: a list of link rows a size closer (26px) and nearer the head, so that three rows fit above the padding. */
|
|
145
|
+
@container (min-height: 61px) and (max-height: 140px) and (min-width: 141px) {
|
|
146
|
+
@scope ([data-doc-component="gallery-soft/static"]) {
|
|
147
|
+
:scope > div > :is(h1, h2, h3, h4, h5, h6):first-child:not(:last-child) + ul:has(> li > a:only-child) { margin-top: 4px; }
|
|
148
|
+
li > a:only-child { height: 26px; }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/* A card one cell high: its one line in the middle, a link after a chip of a page and before an arrow out, a first small span on a chip. */
|
|
152
|
+
@container (max-height: 60px) {
|
|
153
|
+
@scope ([data-doc-component="gallery-soft/static"]) {
|
|
154
|
+
:scope > div > p { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; white-space: nowrap; }
|
|
155
|
+
:scope > div > p > span:first-child { display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 7px; background: var(--soft-accent-soft); font-size: 14px; }
|
|
156
|
+
:scope > div > p:has(> a:only-child)::before { content: ""; flex: none; width: 26px; height: 26px; border-radius: 7px; background: var(--soft-accent-soft); }
|
|
157
|
+
:scope > div > p > a:only-child { position: relative; display: flex; flex: 1; gap: 10px; min-width: 0; font-size: 13.5px; color: inherit; }
|
|
158
|
+
:scope > div > p > a:only-child::before { content: ""; position: absolute; top: 50%; left: -30px; width: 14px; height: 14px; margin-top: -7px; background: var(--soft-accent); -webkit-mask: var(--soft-doc) center / contain no-repeat; mask: var(--soft-doc) center / contain no-repeat; }
|
|
159
|
+
/* its arrow out at the card's end, in the grip's room, faded while the grip shows */
|
|
160
|
+
:scope > div > p > a:only-child::after { position: absolute; top: 50%; right: calc(-1 * var(--soft-grip-room)); width: 14px; height: 14px; margin-top: -7px; background: color-mix(in srgb, currentColor 40%, transparent); opacity: calc(1 - var(--gallery-grip-shown, 0)); transition: opacity .12s ease-out; }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/* Nothing in it: the cards' empty face, in the middle of the card, a share of its color as all else of it: a
|
|
164
|
+
soft disc with lines in it (the instance's ::before, one mask, over the content), then a short line (还没有
|
|
165
|
+
内容) over what to do, muted (the content's ::before and ::after). */
|
|
166
|
+
[data-doc-component="gallery-soft/static"]:has(> div:empty) { position: relative; }
|
|
167
|
+
[data-doc-component="gallery-soft/static"]:has(> div:empty)::before {
|
|
168
|
+
content: "";
|
|
169
|
+
position: absolute;
|
|
170
|
+
z-index: 1;
|
|
171
|
+
top: calc(50% - 48px);
|
|
172
|
+
left: calc(50% - 22px);
|
|
173
|
+
width: 44px;
|
|
174
|
+
height: 44px;
|
|
175
|
+
background: color-mix(in srgb, currentColor 55%, transparent);
|
|
176
|
+
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 44'%3E%3Ccircle cx='22' cy='22' r='22' fill-opacity='.13'/%3E%3Cg transform='translate(12 12) scale(.8333)' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 7h14M5 12h14M5 17h8.5'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
|
|
177
|
+
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 44 44'%3E%3Ccircle cx='22' cy='22' r='22' fill-opacity='.13'/%3E%3Cg transform='translate(12 12) scale(.8333)' fill='none' stroke='black' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 7h14M5 12h14M5 17h8.5'/%3E%3C/g%3E%3C/svg%3E") center / contain no-repeat;
|
|
178
|
+
}
|
|
179
|
+
[data-doc-component="gallery-soft/static"] > div:empty { align-items: center; justify-content: center; gap: 4px; min-height: 120px; padding-top: 74px; text-align: center; }
|
|
180
|
+
.gallery-card > [data-doc-component="gallery-soft/static"] > div:first-child:empty { min-height: 0; padding-top: 74px; }
|
|
181
|
+
[data-doc-component="gallery-soft/static"] > div:empty::before { content: "还没有内容"; font-size: 13px; }
|
|
182
|
+
[data-doc-component="gallery-soft/static"] > div:empty::after { content: "跟 Agent 说要在这里放什么"; font-size: 12px; color: color-mix(in srgb, currentColor 62%, transparent); }
|
|
183
|
+
:root[data-ge-language="en"] [data-doc-component="gallery-soft/static"] > div:empty::before,
|
|
184
|
+
:root:not([data-ge-language])[lang|="en" i] [data-doc-component="gallery-soft/static"] > div:empty::before { content: "Nothing here yet"; }
|
|
185
|
+
:root[data-ge-language="en"] [data-doc-component="gallery-soft/static"] > div:empty::after,
|
|
186
|
+
:root:not([data-ge-language])[lang|="en" i] [data-doc-component="gallery-soft/static"] > div:empty::after { content: "Tell your Agent what this card should show"; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div data-doc-component="gallery-soft/static"><div></div></div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 静态卡片 (gallery-soft/static)
|
|
2
|
+
|
|
3
|
+
A card that shows any HTML you write, as it is: nothing on it changes in the page, and it has no script. Use it on a custom page for whatever only shows (a heading for a group of cards, links the user opens often, a short list, a picture, a table of a few rows); make a block of your own only where the card needs behavior or data that changes. Its places are `page` alone: a document already has a block for everything that only shows, and you write its HTML as it is there (writing-html.md), so no document's menu offers it.
|
|
4
|
+
|
|
5
|
+
It is 柔光风格's (the pack `gallery-soft`, off until the user turns it on in 设置 › 组件列表): the same card as Gallery 风格's `gallery/static`, its settings, its data and what the user does on it the same, in the soft look of design A (a faint wash of blue from the card's top, rounded chips, big numbers). Write it only where the user asked for 柔光风格 or the page already holds its cards.
|
|
6
|
+
|
|
7
|
+
## How to write it
|
|
8
|
+
|
|
9
|
+
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 gallery-soft/static`, and write the HTML in the instance's one `<div>`, as example.html does:
|
|
10
|
+
|
|
11
|
+
- the content, the `div` right inside the instance (its part `content`, edited as `none`): any HTML, headings, paragraphs, lists, links, a table, a picture. No `<script>`, no form fields, no `on…` attributes: the card only shows.
|
|
12
|
+
- a picture: a file of the page's `assets/` (`pages/<slug>/assets/`), written `assets/<file>` (a name of letters, digits, dots, dashes and underscores, right in that folder), which the server serves at `/pages/<slug>/assets/<file>`: put the file there first (`gallery page check` says a picture whose file is not there), and never `cover.png` alone, which nothing serves. A small SVG or PNG may be a `data:` address in the `<img>` itself.
|
|
13
|
+
- the look: 柔光风格's (How it looks, below), each rule as light as the elements it names, so that a page's own `<style>` or a `style` attribute changes any of it. It sets no color but the links', the chips' and a faint wash of blue from the card's top: its words are the color they stand in, the page's text or the color your page gives the card (`.gallery-card[data-card-id="…"] { background: …; color: … }`) or a wrapper of the content (`style="color: …"`), every heading in it too, and its small words, list dots, quotes and lines a share of that color. Write colors of your own for both themes (`:root[data-doc-effective-theme="dark"]` on a custom page), a link's too where its fill is dark.
|
|
14
|
+
- Size: any whole number of cells, 1 to 12 wide and 1 to 24 high, 4 × 2 by default (the 大小 menu lists 4 × 2, 2 × 2, 4 × 4, 8 × 2, 2 × 1 and 4 × 1): write `data-w` and `data-h` to fit what you wrote (`gallery page add <slug> gallery-soft/static --w <w> --h <h>` does too). The user changes it by dragging the card's lower right corner, or from the 大小 menu of the grip at the card's top right, which lists the common sizes. The card does not grow with what it holds: what does not fit scrolls inside it, so give it the height it needs.
|
|
15
|
+
|
|
16
|
+
An empty one (`<div></div>`, what a menu adds) says that it has nothing yet (还没有内容, 跟 Agent 说要在这里放什么), so that the user asks you for it.
|
|
17
|
+
|
|
18
|
+
## How it looks
|
|
19
|
+
|
|
20
|
+
What you wrote, in 柔光风格's soft look: a heading it starts with, where more follows, is the card's head row (a chip of lines in the accent's soft tint and the title; small words in the heading, `<h3>十一月开销 <small>截至 11月12日</small></h3>`, its quiet meta at the end); a paragraph of small words alone right under it a muted subtitle; a list a dot an item; a list whose items are each one link, rows like the sidebar's (`<li><a href="…">Gallery 仓库 <small>github.com</small></a></li>`: a link's picture on a soft square before it, the small words at its end); a last paragraph that is one link, the accent's with an arrow out, at the card's bottom; a table of hairlines, its columns after the first numbers at the right; on a 2 × 2 card what follows the heading at the bottom; on a card one cell high its one line in the middle, a paragraph that is one link after a chip of a page and before an arrow out, a first `<span>` of it (an emoji: `<p><span>📌</span> 这周专心发版</p>`) on a chip. The user changes it only by asking you: to change it, write the HTML in `page.html` again, that card alone, its `data-card-id` and place kept.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "gallery-soft/stats",
|
|
3
|
+
"apiVersion": 1,
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"name": { "zh": "工作区统计", "en": "Workspace numbers" },
|
|
6
|
+
"description": { "zh": "文档数、总字数、待办完成了几项、本周编辑了几篇,每个数下面一件小东西:字数的走势、本周每天的编辑", "en": "How many documents, words in all, to-dos done, documents edited this week, each with a small thing under it: the words' trend, this week's edits by day" },
|
|
7
|
+
"words": "gongzuoqutongji tongji shuzi stats statistics numbers count words 统计 工作区 字数 文档数 待办",
|
|
8
|
+
"parts": {},
|
|
9
|
+
"runtime": { "generated": [":scope > .gallery-soft-stats-face"] },
|
|
10
|
+
"places": ["page"],
|
|
11
|
+
"card": { "sizes": [[8, 2], [12, 2], [4, 2], [4, 4]], "resize": true },
|
|
12
|
+
"needs": ["workspace"]
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<div data-doc-component="gallery-soft/stats"></div>
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// gallery-soft/stats (工作区统计, 柔光风格): Gallery 风格's gallery/stats in the soft look, the same numbers.
|
|
2
|
+
// Four numbers of the workspace, read through context.workspace.query("stats") (its manifest's needs hold
|
|
3
|
+
// "workspace"): its documents, the words of all its documents, its to-dos done of all, and the documents
|
|
4
|
+
// edited this week (since Monday, 0:00); a workspace with none of them shows each 0. Under each number a small
|
|
5
|
+
// thing of its own: the words a document holds on average; how the words grew over the last 30 days (a line,
|
|
6
|
+
// its end ringed; a card 12 cells wide adds the words added this week in a green pill, against the last 14
|
|
7
|
+
// days), from the workspace's record of edits (query("activity"), the words each day added); the share of
|
|
8
|
+
// the to-dos done as a bar; and this week's edits day by day as small bars, today's in the accent, the days
|
|
9
|
+
// to come a stub. It reads again whenever the workspace says they changed (the `data` signal, "stats" and
|
|
10
|
+
// "activity": a document written, a to-do checked, a document made or gone) and as a day begins (the kit's
|
|
11
|
+
// clock: a new week starts on a Monday). It holds no part and writes nothing: all it shows is drawn (the
|
|
12
|
+
// manifest's `runtime`). Where the workspace cannot be read (an exported file, where it has no server; a
|
|
13
|
+
// server that does not answer) each number is a dash and a line says why; where its record of edits cannot
|
|
14
|
+
// be read the line and the bars are left out. The words are the page's language; a big number of words is
|
|
15
|
+
// said short (12.6 万字, 126.5K words) as the language does.
|
|
16
|
+
//
|
|
17
|
+
// Its face, laid out by its card's size (`context.size`, read again on `layout`; data-w, data-h, data-pad): no
|
|
18
|
+
// head of its own, each number's small chip and name the head of its cell. A card 8 or 12 cells wide and 2
|
|
19
|
+
// high holds the four side by side, a hairline between them, each like a small card; a 4 × 4 card two by two;
|
|
20
|
+
// a 4 × 2 card two by two, each its name over its number alone.
|
|
21
|
+
|
|
22
|
+
const WORDS = {
|
|
23
|
+
zh: {
|
|
24
|
+
documents: "文档",
|
|
25
|
+
todos: "待办完成",
|
|
26
|
+
words: "总字数",
|
|
27
|
+
week: "本周编辑",
|
|
28
|
+
pieces: "篇",
|
|
29
|
+
wordsUnit: "字",
|
|
30
|
+
wordsBig: "万字",
|
|
31
|
+
average: (/** @type {string} */ count) => ["平均每篇", count, "字"],
|
|
32
|
+
added: "本周新增",
|
|
33
|
+
offline: "在 Gallery 里打开时显示",
|
|
34
|
+
failed: "读不到工作区的统计",
|
|
35
|
+
locale: "zh-CN",
|
|
36
|
+
},
|
|
37
|
+
en: {
|
|
38
|
+
documents: "Documents",
|
|
39
|
+
todos: "To-dos done",
|
|
40
|
+
words: "Words",
|
|
41
|
+
week: "Edited this week",
|
|
42
|
+
pieces: "",
|
|
43
|
+
wordsUnit: "words",
|
|
44
|
+
wordsBig: "words",
|
|
45
|
+
average: (/** @type {string} */ count) => ["", count, "words a document"],
|
|
46
|
+
added: "this week",
|
|
47
|
+
offline: "Shown when opened in Gallery",
|
|
48
|
+
failed: "The workspace's numbers could not be read",
|
|
49
|
+
locale: "en",
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
|
|
54
|
+
function languageOf(/** @type {HTMLElement} */ root) {
|
|
55
|
+
const ui = root.getAttribute("data-ge-language");
|
|
56
|
+
return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A count as the card writes it, in `language`: whole and grouped up to 99,999 (12,345), shorter past
|
|
61
|
+
* it (12.3万, 123.5K), as the language writes a big number.
|
|
62
|
+
* @param {number} value
|
|
63
|
+
* @param {"zh" | "en"} language
|
|
64
|
+
*/
|
|
65
|
+
function countOf(value, language) {
|
|
66
|
+
const big = Math.abs(value) >= 100_000;
|
|
67
|
+
return new Intl.NumberFormat(WORDS[language].locale, big ? { notation: "compact", maximumFractionDigits: 1 } : { maximumFractionDigits: 0 }).format(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The words of the workspace as the card's figure writes them, in `language`: { value, unit }, whole and
|
|
72
|
+
* grouped under 10,000 (8,420 字), in 万 past it in Chinese (12.6 万字) and short in English (126.5K words).
|
|
73
|
+
* @param {number} value
|
|
74
|
+
* @param {"zh" | "en"} language
|
|
75
|
+
*/
|
|
76
|
+
function wordsOf(value, language) {
|
|
77
|
+
const words = WORDS[language];
|
|
78
|
+
if (Math.abs(value) < 10_000) return { value: countOf(value, language), unit: words.wordsUnit };
|
|
79
|
+
if (language === "zh") return { value: (value / 10_000).toFixed(1).replace(/\.0$/, ""), unit: words.wordsBig };
|
|
80
|
+
return { value: new Intl.NumberFormat("en", { notation: "compact", maximumFractionDigits: 1 }).format(value), unit: words.wordsBig };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The four cells the card shows of `stats` (workspace.query("stats")'s data), or of none (null: a dash
|
|
85
|
+
* each), in `language`: [{ key, label, value, unit }].
|
|
86
|
+
* @param {{ documents: number, todos: { done: number, total: number }, words: number, editedThisWeek: number } | null} stats
|
|
87
|
+
* @param {"zh" | "en"} language
|
|
88
|
+
*/
|
|
89
|
+
function cellsOf(stats, language) {
|
|
90
|
+
const words = WORDS[language];
|
|
91
|
+
const dash = "—";
|
|
92
|
+
const written = stats ? wordsOf(stats.words, language) : { value: dash, unit: words.wordsBig };
|
|
93
|
+
return [
|
|
94
|
+
{ key: "documents", label: words.documents, value: stats ? countOf(stats.documents, language) : dash, unit: words.pieces },
|
|
95
|
+
{ key: "words", label: words.words, value: written.value, unit: written.unit },
|
|
96
|
+
{ key: "todos", label: words.todos, value: stats ? countOf(stats.todos.done, language) : dash, unit: stats ? `/ ${countOf(stats.todos.total, language)}` : "" },
|
|
97
|
+
{ key: "week", label: words.week, value: stats ? countOf(stats.editedThisWeek, language) : dash, unit: words.pieces },
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** A local day as the record writes it, YYYY-MM-DD. @param {Date} date */
|
|
102
|
+
const dayOf = (date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* What the record of edits (`days`, workspace.query("activity")'s data, the last first or last; any order)
|
|
106
|
+
* says the cells' feet draw, at `now`, the workspace's words now being `words`: `climb`, the words the
|
|
107
|
+
* workspace held at the end of each of those days, the oldest first (the words now, less what each later day
|
|
108
|
+
* added); `added`, the words this week added (since Monday); `week`, this week's edits day by day, Monday
|
|
109
|
+
* first, null for a day still to come.
|
|
110
|
+
* @param {Array<{ date: string, edits: number, words: number }>} days
|
|
111
|
+
* @param {number} words
|
|
112
|
+
* @param {Date} now
|
|
113
|
+
*/
|
|
114
|
+
function trendOf(days, words, now) {
|
|
115
|
+
const sorted = [...days].sort((a, b) => (a.date < b.date ? -1 : a.date > b.date ? 1 : 0));
|
|
116
|
+
const climb = new Array(sorted.length);
|
|
117
|
+
let held = words;
|
|
118
|
+
for (let index = sorted.length - 1; index >= 0; index--) {
|
|
119
|
+
climb[index] = held;
|
|
120
|
+
held -= sorted[index].words;
|
|
121
|
+
}
|
|
122
|
+
const monday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - ((now.getDay() + 6) % 7), 12);
|
|
123
|
+
const byDay = new Map(sorted.map((day) => [day.date, day]));
|
|
124
|
+
const week = Array.from({ length: 7 }, (_, index) => {
|
|
125
|
+
const date = new Date(monday.getFullYear(), monday.getMonth(), monday.getDate() + index, 12);
|
|
126
|
+
return dayOf(date) > dayOf(now) ? null : byDay.get(dayOf(date))?.edits ?? 0;
|
|
127
|
+
});
|
|
128
|
+
const added = sorted.filter((day) => day.date >= dayOf(monday) && day.date <= dayOf(now)).reduce((sum, day) => sum + day.words, 0);
|
|
129
|
+
return { climb, added, week };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* How much of `all` is done, as a whole percent, as every soft card says it (the to-dos' ring, the stats'
|
|
134
|
+
* bar): rounded, but 100 only when all are done and 0 only when none is (18 of 27: 67; 199 of 200: 99;
|
|
135
|
+
* 1 of 300: 1).
|
|
136
|
+
* @param {number} done
|
|
137
|
+
* @param {number} all
|
|
138
|
+
*/
|
|
139
|
+
function percentDone(done, all) {
|
|
140
|
+
if (!(all > 0) || !(done > 0)) return 0;
|
|
141
|
+
if (done >= all) return 100;
|
|
142
|
+
return Math.min(99, Math.max(1, Math.round((100 * done) / all)));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The size the face is laid out by: its card's cells (`context.size`), or `fallback` (the manifest's first
|
|
147
|
+
* size) where no card is; and the frame's padding for it, as the soft cards pad theirs: "xs" on a card one
|
|
148
|
+
* cell high, "s" on a small one (2 × 2 and less), "l" on one 3 cells high or more, else "m".
|
|
149
|
+
* @param {DocComponentSize | null | undefined} size
|
|
150
|
+
* @param {[number, number]} fallback
|
|
151
|
+
*/
|
|
152
|
+
function sizeOf(size, fallback) {
|
|
153
|
+
const w = size?.w ?? fallback[0];
|
|
154
|
+
const h = size?.h ?? fallback[1];
|
|
155
|
+
return { w, h, pad: h === 1 ? "xs" : w <= 2 && h <= 2 ? "s" : h >= 3 ? "l" : "m" };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* An element of the face, of `kind` (its class).
|
|
160
|
+
* @template {keyof HTMLElementTagNameMap} K
|
|
161
|
+
* @param {K} tag
|
|
162
|
+
* @param {string} kind
|
|
163
|
+
* @param {string} [text]
|
|
164
|
+
*/
|
|
165
|
+
function made(tag, kind, text) {
|
|
166
|
+
const node = document.createElement(tag);
|
|
167
|
+
node.className = `gallery-soft-stats-${kind}`;
|
|
168
|
+
if (text !== undefined) node.textContent = text;
|
|
169
|
+
return node;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const ICONS = {
|
|
173
|
+
documents: '<path d="M8.5 6.5h-2A1.5 1.5 0 0 0 5 8v11.5A1.5 1.5 0 0 0 6.5 21H15a1.5 1.5 0 0 0 1.5-1.5v-1"/><path d="M9 3h6.5L19.5 7v10a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 7.5 17V4.5A1.5 1.5 0 0 1 9 3z"/>',
|
|
174
|
+
words: '<path d="M6 6.5h12M12 6.5V19M9.5 19h5"/>',
|
|
175
|
+
todos: '<path d="M4 7l1.8 1.8L9.2 5.4"/><path d="M4 14.5l1.8 1.8 3.4-3.4"/><path d="M12.5 7.5H20M12.5 15H20"/>',
|
|
176
|
+
week: '<path d="M14.5 5.5l4 4L9 19H5v-4z"/>',
|
|
177
|
+
};
|
|
178
|
+
const line = (/** @type {string} */ paths, /** @type {number} */ width = 1.8) => `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${width}" stroke-linecap="round" stroke-linejoin="round">${paths}</svg>`;
|
|
179
|
+
|
|
180
|
+
let sparks = 0; // the sparklines drawn on the page, each gradient's id its own
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* A line of `values`, `width` x `height` px, the room under it washed with the accent, its last point ringed.
|
|
184
|
+
* @param {number[]} values
|
|
185
|
+
* @param {number} width
|
|
186
|
+
* @param {number} height
|
|
187
|
+
*/
|
|
188
|
+
function sparkOf(values, width, height) {
|
|
189
|
+
const id = `gallery-soft-stats-spark-${++sparks}`;
|
|
190
|
+
const most = Math.max(...values);
|
|
191
|
+
const least = Math.min(...values);
|
|
192
|
+
const points = values.map((value, index) => [values.length > 1 ? (index / (values.length - 1)) * width : width, height - 2 - ((value - least) / (most - least || 1)) * (height - 5)]);
|
|
193
|
+
const path = points.map(([x, y], index) => `${index ? "L" : "M"}${x.toFixed(1)} ${y.toFixed(1)}`).join(" ");
|
|
194
|
+
const [lastX, lastY] = points[points.length - 1];
|
|
195
|
+
const holder = made("span", "spark");
|
|
196
|
+
holder.innerHTML = `<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" aria-hidden="true"><defs><linearGradient id="${id}" x1="0" y1="0" x2="0" y2="1"><stop offset="0" class="gallery-soft-stats-wash-top"/><stop offset="1" class="gallery-soft-stats-wash-end"/></linearGradient></defs><path d="${path} L${width} ${height} L0 ${height} Z" fill="url(#${id})"/><path class="gallery-soft-stats-spark-line" d="${path}"/><circle class="gallery-soft-stats-end" cx="${lastX.toFixed(1)}" cy="${lastY.toFixed(1)}" r="2.6"/></svg>`;
|
|
197
|
+
return holder;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
DocKit.component({
|
|
201
|
+
id: "gallery-soft/stats",
|
|
202
|
+
on: ["data", "clock", "layout"],
|
|
203
|
+
mount(host, context) {
|
|
204
|
+
const language = languageOf(document.documentElement);
|
|
205
|
+
const words = WORDS[language];
|
|
206
|
+
const face = made("div", "face");
|
|
207
|
+
const grid = made("dl", "grid");
|
|
208
|
+
const note = made("p", "line");
|
|
209
|
+
note.hidden = true;
|
|
210
|
+
face.append(grid, note);
|
|
211
|
+
host.append(face);
|
|
212
|
+
const workspace = context.workspace;
|
|
213
|
+
if (!workspace) return void context.fail(new Error("its manifest's needs hold \"workspace\": context.workspace is not there"));
|
|
214
|
+
/** @type {Parameters<typeof cellsOf>[0]} */
|
|
215
|
+
let stats = null;
|
|
216
|
+
/** @type {Array<{ date: string, edits: number, words: number }> | null} */
|
|
217
|
+
let record = null;
|
|
218
|
+
let failure = "";
|
|
219
|
+
// The cells drawn anew: each its chip and name, its number and unit, and its foot as the card's size has room for.
|
|
220
|
+
const draw = () => {
|
|
221
|
+
const { w, h, pad } = sizeOf(context.size, [8, 2]);
|
|
222
|
+
const layout = h <= 2 && w >= 6 ? "row" : h <= 2 ? "compact" : "quad";
|
|
223
|
+
Object.assign(face.dataset, { w: String(w), h: String(h), pad, layout });
|
|
224
|
+
face.toggleAttribute("data-zero", stats !== null && stats.documents === 0 && stats.words === 0 && stats.todos.total === 0);
|
|
225
|
+
const cells = cellsOf(stats, language);
|
|
226
|
+
const trend = stats && record ? trendOf(record, stats.words, new Date()) : null;
|
|
227
|
+
const showFeet = layout !== "compact" && stats !== null && !face.hasAttribute("data-zero");
|
|
228
|
+
grid.replaceChildren(...cells.map(({ key, label, value, unit }) => {
|
|
229
|
+
const cell = made("div", "cell");
|
|
230
|
+
cell.dataset.stat = key;
|
|
231
|
+
const name = made("dt", "label");
|
|
232
|
+
const chip = made("span", "chip");
|
|
233
|
+
chip.setAttribute("aria-hidden", "true");
|
|
234
|
+
chip.innerHTML = line(ICONS[/** @type {keyof typeof ICONS} */ (key)], layout === "compact" ? 2 : 1.8);
|
|
235
|
+
name.append(chip, label);
|
|
236
|
+
const figure = made("dd", "figure");
|
|
237
|
+
figure.append(made("span", "number", value), ...(unit ? [made("span", "unit", unit)] : []));
|
|
238
|
+
cell.append(name, figure);
|
|
239
|
+
if (showFeet && stats) {
|
|
240
|
+
const foot = made("dd", "foot");
|
|
241
|
+
if (key === "documents" && stats.documents > 0) {
|
|
242
|
+
const [before, count, after] = words.average(countOf(Math.round(stats.words / stats.documents), language));
|
|
243
|
+
const said = made("span", "said");
|
|
244
|
+
said.append(...(before ? [`${before} `] : []), made("b", "average", count), ` ${after}`);
|
|
245
|
+
foot.append(said);
|
|
246
|
+
} else if (key === "todos" && stats.todos.total > 0) {
|
|
247
|
+
const bar = made("span", "bar");
|
|
248
|
+
const fill = made("i", "fill");
|
|
249
|
+
fill.style.width = `${((100 * stats.todos.done) / stats.todos.total).toFixed(1)}%`;
|
|
250
|
+
bar.append(fill);
|
|
251
|
+
foot.append(bar, made("b", "share", `${percentDone(stats.todos.done, stats.todos.total)}%`));
|
|
252
|
+
} else if (key === "week" && trend) {
|
|
253
|
+
const most = Math.max(1, ...trend.week.map((edits) => edits ?? 0));
|
|
254
|
+
const bars = made("span", "bars");
|
|
255
|
+
bars.setAttribute("aria-hidden", "true");
|
|
256
|
+
const today = (new Date().getDay() + 6) % 7;
|
|
257
|
+
bars.append(...trend.week.map((edits, index) => {
|
|
258
|
+
const bar = made("i", "day");
|
|
259
|
+
if (edits === null) bar.classList.add("gallery-soft-stats-future");
|
|
260
|
+
else bar.style.height = `${Math.max(3, Math.round((edits / most) * 24))}px`;
|
|
261
|
+
if (index === today) bar.classList.add("gallery-soft-stats-today");
|
|
262
|
+
return bar;
|
|
263
|
+
}));
|
|
264
|
+
foot.append(bars);
|
|
265
|
+
} else if (key === "words" && trend && trend.climb.length > 1) {
|
|
266
|
+
if (w >= 12 && h <= 2) {
|
|
267
|
+
const pill = made("span", trend.added < 0 ? "fell" : "grew");
|
|
268
|
+
pill.innerHTML = line(trend.added < 0 ? '<path d="M4 7.5l5.5 5.5 3.5-3.5L20 17"/><path d="M14.5 17H20v-5.5"/>' : '<path d="M4 16.5l5.5-5.5 3.5 3.5L20 7"/><path d="M14.5 7H20v5.5"/>', 2.2);
|
|
269
|
+
pill.append(countOf(Math.abs(trend.added), language));
|
|
270
|
+
foot.append(pill, made("span", "added", words.added), made("span", "room"));
|
|
271
|
+
} else foot.append(made("span", "room"));
|
|
272
|
+
}
|
|
273
|
+
cell.append(foot);
|
|
274
|
+
}
|
|
275
|
+
return cell;
|
|
276
|
+
}));
|
|
277
|
+
// The sparklines, as wide as their room once it is laid out.
|
|
278
|
+
if (trend) {
|
|
279
|
+
for (const room of /** @type {NodeListOf<HTMLElement>} */ (grid.querySelectorAll(".gallery-soft-stats-room"))) {
|
|
280
|
+
const wide = room.parentElement?.querySelector(".gallery-soft-stats-grew, .gallery-soft-stats-fell") !== null;
|
|
281
|
+
const width = Math.max(40, Math.floor(room.clientWidth));
|
|
282
|
+
room.replaceChildren(sparkOf(wide ? trend.climb.slice(-14) : trend.climb, width, layout === "quad" ? 24 : 22));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
note.hidden = !failure;
|
|
286
|
+
note.textContent = failure;
|
|
287
|
+
};
|
|
288
|
+
let asking = 0; // the last read asked: an older answer that comes after it is dropped
|
|
289
|
+
const read = () => {
|
|
290
|
+
const ticket = ++asking;
|
|
291
|
+
workspace.query("stats").then(({ data }) => {
|
|
292
|
+
if (ticket !== asking || context.signal.aborted) return;
|
|
293
|
+
stats = data;
|
|
294
|
+
failure = "";
|
|
295
|
+
draw();
|
|
296
|
+
}, (/** @type {any} */ error) => {
|
|
297
|
+
if (ticket !== asking || context.signal.aborted) return;
|
|
298
|
+
stats = null;
|
|
299
|
+
failure = error?.code === "offline" ? words.offline : words.failed;
|
|
300
|
+
draw();
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
let reading = 0;
|
|
304
|
+
const readRecord = () => {
|
|
305
|
+
const ticket = ++reading;
|
|
306
|
+
workspace.query("activity", { days: 30 }).then(({ data }) => {
|
|
307
|
+
if (ticket !== reading || context.signal.aborted) return;
|
|
308
|
+
record = data;
|
|
309
|
+
draw();
|
|
310
|
+
}, () => {
|
|
311
|
+
if (ticket !== reading || context.signal.aborted) return;
|
|
312
|
+
record = null;
|
|
313
|
+
draw();
|
|
314
|
+
});
|
|
315
|
+
};
|
|
316
|
+
draw();
|
|
317
|
+
read();
|
|
318
|
+
readRecord();
|
|
319
|
+
// The sparklines' room changes with the card's width: drawn again as it does.
|
|
320
|
+
if (typeof ResizeObserver === "function") {
|
|
321
|
+
let width = 0;
|
|
322
|
+
const watch = new ResizeObserver(() => {
|
|
323
|
+
if (Math.round(face.clientWidth) === width) return;
|
|
324
|
+
width = Math.round(face.clientWidth);
|
|
325
|
+
draw();
|
|
326
|
+
});
|
|
327
|
+
watch.observe(face);
|
|
328
|
+
context.signal?.addEventListener("abort", () => watch.disconnect(), { once: true });
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
update(reason, detail) {
|
|
332
|
+
if (reason === "data" && detail === "stats") read();
|
|
333
|
+
else if (reason === "data" && detail === "activity") readRecord();
|
|
334
|
+
else if (reason === "clock" && detail === "day") {
|
|
335
|
+
read();
|
|
336
|
+
readRecord();
|
|
337
|
+
} else if (reason === "layout") draw();
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
},
|
|
341
|
+
});
|
|
@@ -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="26" y="24" width="10" height="10" rx="4.5" fill="#ecf3fb"/><rect x="28" y="28" width="6" height="2" rx="1" fill="#3e7ac6"/><rect x="40" y="26" width="20" height="5" rx="2.5" fill="#c4c2bd"/><rect x="27" y="44" width="20" height="14" rx="7" fill="#1f1f1f"/><rect x="50" y="50" width="9" height="6" rx="3" fill="#8d8c88"/><rect x="68.5" y="13" width="1" height="94" fill="#efeeec"/><rect x="77.5" y="24" width="10" height="10" rx="4.5" fill="#ecf3fb"/><rect x="79.5" y="28" width="6" height="2" rx="1" fill="#3e7ac6"/><rect x="91.5" y="26" width="20" height="5" rx="2.5" fill="#c4c2bd"/><rect x="78.5" y="44" width="20" height="14" rx="7" fill="#1f1f1f"/><rect x="101.5" y="50" width="9" height="6" rx="3" fill="#8d8c88"/><rect x="120" y="13" width="1" height="94" fill="#efeeec"/><rect x="129" y="24" width="10" height="10" rx="4.5" fill="#ecf3fb"/><rect x="131" y="28" width="6" height="2" rx="1" fill="#3e7ac6"/><rect x="143" y="26" width="20" height="5" rx="2.5" fill="#c4c2bd"/><rect x="130" y="44" width="20" height="14" rx="7" fill="#1f1f1f"/><rect x="153" y="50" width="9" height="6" rx="3" fill="#8d8c88"/><rect x="171.5" y="13" width="1" height="94" fill="#efeeec"/><rect x="180.5" y="24" width="10" height="10" rx="4.5" fill="#ecf3fb"/><rect x="182.5" y="28" width="6" height="2" rx="1" fill="#3e7ac6"/><rect x="194.5" y="26" width="20" height="5" rx="2.5" fill="#c4c2bd"/><rect x="181.5" y="44" width="20" height="14" rx="7" fill="#1f1f1f"/><rect x="204.5" y="50" width="9" height="6" rx="3" fill="#8d8c88"/><rect x="27" y="86" width="34" height="4" rx="2" fill="#c4c2bd"/><path d="M78 92 L90 90 L98 88 L106 86 L114 84" fill="none" stroke="#3e7ac6" stroke-width="1.6" stroke-linecap="round"/><circle cx="114" cy="84" r="2" fill="#fff" stroke="#3e7ac6" stroke-width="1.4"/><rect x="130" y="86" width="26" height="4" rx="2" fill="#efeff0"/><rect x="130" y="86" width="17" height="4" rx="2" fill="#3e7ac6"/><rect x="181" y="82" width="4" height="10" rx="1" fill="#afcaea"/><rect x="187" y="88" width="4" height="4" rx="1" fill="#afcaea"/><rect x="193" y="86" width="4" height="6" rx="1" fill="#afcaea"/><rect x="199" y="83" width="4" height="9" rx="1" fill="#3e7ac6"/></svg>
|