@heycys/gallery 0.1.2 → 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/embed/page.mjs +1 -1
- package/browser/editor/components/file/page.mjs +4 -4
- package/browser/editor/components/heading/index.mjs +7 -6
- package/browser/editor/components/icons.mjs +3 -0
- 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 +6 -2
- package/browser/editor/components/installed/page.mjs +80 -13
- 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 +17 -5
- package/browser/editor/components/table/index.mjs +4 -2
- package/browser/editor/page/after/index.mjs +288 -0
- package/browser/editor/page/align.mjs +91 -0
- 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/hint.mjs +64 -27
- package/browser/editor/page/board/index.mjs +160 -71
- package/browser/editor/page/board/motion.mjs +177 -0
- package/browser/editor/page/board/settings.mjs +4 -3
- package/browser/editor/page/clipboard/index.mjs +10 -3
- package/browser/editor/page/clipboard/own/blocks.mjs +3 -4
- package/browser/editor/page/clipboard/own/describe.mjs +6 -2
- package/browser/editor/page/commit.mjs +2 -2
- package/browser/editor/page/core.mjs +3 -1
- package/browser/editor/page/custom-page.mjs +15 -11
- package/browser/editor/page/editor.mjs +31 -14
- package/browser/editor/page/history.mjs +19 -4
- package/browser/editor/page/insert/index.mjs +20 -22
- package/browser/editor/page/menu.mjs +15 -7
- package/browser/editor/page/page-objects.mjs +3 -7
- package/browser/editor/page/present-links.mjs +5 -4
- package/browser/editor/page/present-shell.mjs +63 -0
- package/browser/editor/page/selection/index.mjs +10 -2
- package/browser/editor/page/table/binding.mjs +87 -0
- package/browser/editor/page/table/icons.mjs +0 -2
- package/browser/editor/page/table/index.mjs +10 -14
- package/browser/editor/page/table/views.mjs +5 -52
- package/browser/editor/page/table/widths.mjs +82 -10
- package/browser/editor/page/typing/index.mjs +44 -12
- package/browser/editor/page/typing/leave.mjs +19 -5
- package/browser/shared/block-packs.mjs +23 -8
- package/browser/shared/component-catalog.mjs +15 -8
- package/browser/shared/component-source.mjs +3 -1
- package/browser/shared/components/heading.mjs +2 -1
- package/browser/shared/components/installed.mjs +1 -1
- package/browser/shared/components/page.mjs +2 -0
- package/browser/shared/components/paragraph.mjs +8 -1
- package/browser/shared/components/table.mjs +1 -0
- package/browser/shared/emoji/line-icons.mjs +37 -0
- package/browser/shared/http.mjs +9 -0
- package/browser/shared/i18n/en.mjs +40 -17
- package/browser/shared/outline.mjs +30 -2
- package/browser/shared/pack-manifest.mjs +12 -1
- package/browser/shared/pages.mjs +169 -57
- package/browser/shared/pinyin.mjs +92 -0
- package/browser/shared/present-step.mjs +17 -0
- package/browser/shared/sidebar-head.mjs +70 -0
- package/browser/shared/web-links.mjs +5 -0
- package/dist/chunk-2OHANJ6Q.mjs +2 -0
- package/dist/{chunk-QOUEFUCH.mjs → chunk-3MBRL2PM.mjs} +1 -1
- package/dist/{chunk-NWR2LT5B.mjs → chunk-4OKWZY5E.mjs} +1 -1
- package/dist/{chunk-RMECZA2K.mjs → chunk-5K44HLTZ.mjs} +1 -1
- package/dist/{chunk-NFMCP2HI.mjs → chunk-5XA2ZBAE.mjs} +2 -2
- package/dist/{chunk-OUUP3WKT.mjs → chunk-67N2QJYT.mjs} +1 -1
- package/dist/chunk-6KBYRA2C.mjs +2 -0
- package/dist/{chunk-SX4LJYT6.mjs → chunk-6N3PX4XX.mjs} +1 -1
- package/dist/{chunk-RFDZXFJF.mjs → chunk-7JDX4E65.mjs} +1 -1
- package/dist/chunk-7M2BQQGZ.mjs +2 -0
- package/dist/{chunk-ZUNVAXLH.mjs → chunk-7OG26PGF.mjs} +1 -1
- package/dist/{chunk-B4P2CM2J.mjs → chunk-AHN3NFKJ.mjs} +1 -1
- package/dist/chunk-ALZ6ZENZ.mjs +3 -0
- package/dist/{chunk-UGWYKHBL.mjs → chunk-AR5D57ZD.mjs} +2 -2
- package/dist/{chunk-W3BGBJQW.mjs → chunk-BFJGHSQN.mjs} +1 -1
- package/dist/{chunk-HLYV7RIH.mjs → chunk-CMA72MAG.mjs} +1 -1
- package/dist/{chunk-D4CKRD3V.mjs → chunk-DAZL73VK.mjs} +2 -2
- package/dist/{chunk-6VTU6KEO.mjs → chunk-DJISHPUL.mjs} +1 -1
- package/dist/{chunk-BPL64HGA.mjs → chunk-EAIFITAV.mjs} +1 -1
- package/dist/chunk-EP25HDAJ.mjs +2 -0
- package/dist/{chunk-6EZ7FNIK.mjs → chunk-F4ZA6JRZ.mjs} +1 -1
- package/dist/{chunk-3KJHLHUO.mjs → chunk-F6HVDZR4.mjs} +1 -1
- package/dist/{chunk-3NJACR4W.mjs → chunk-FDMAXMQA.mjs} +1 -1
- package/dist/chunk-FETSREUN.mjs +5 -0
- package/dist/{chunk-RKPWLGZ3.mjs → chunk-GHOYKMQ3.mjs} +1 -1
- package/dist/chunk-HDWTZ763.mjs +12 -0
- package/dist/{chunk-VTKNEYT3.mjs → chunk-HPOI4ZX7.mjs} +1 -1
- package/dist/{chunk-OW5NWPOJ.mjs → chunk-HXG7EOPJ.mjs} +1 -1
- package/dist/{chunk-V6RIYQZZ.mjs → chunk-ITOH5EGO.mjs} +1 -1
- package/dist/{chunk-ZWPMCK7P.mjs → chunk-IV64FFI4.mjs} +1 -1
- package/dist/chunk-J43Z6LSS.mjs +2 -0
- package/dist/chunk-J5PUIV3Y.mjs +4 -0
- package/dist/{chunk-KTKHRC6H.mjs → chunk-JA7G53PC.mjs} +1 -1
- package/dist/{chunk-NWFBE2YA.mjs → chunk-JLTZF4LA.mjs} +1 -1
- package/dist/{chunk-GY3FAUVM.mjs → chunk-JZT7I2OJ.mjs} +1 -1
- package/dist/{chunk-QKXMPUXC.mjs → chunk-K5XATEOO.mjs} +1 -1
- package/dist/chunk-L2SUIS5S.mjs +2 -0
- package/dist/{chunk-TEZAWDSQ.mjs → chunk-LM4XFQHZ.mjs} +1 -1
- package/dist/{chunk-5ZJA7CXT.mjs → chunk-MN7BZL4R.mjs} +1 -1
- package/dist/chunk-MTYYHM2G.mjs +15 -0
- package/dist/{chunk-HMYTM3GT.mjs → chunk-MXUBKDRO.mjs} +1 -1
- package/dist/{chunk-MHW7ZKOU.mjs → chunk-OEXWRJME.mjs} +1 -1
- package/dist/{chunk-CRJEG7MT.mjs → chunk-OFHXGWOX.mjs} +1 -1
- package/dist/chunk-ORID3AE7.mjs +166 -0
- package/dist/{chunk-32ZUEFZ7.mjs → chunk-PGDE24N5.mjs} +1 -1
- package/dist/{chunk-UNOYVIYR.mjs → chunk-POTA2FV4.mjs} +1 -1
- package/dist/{chunk-N7AZZLGT.mjs → chunk-QE5RG76S.mjs} +18 -17
- package/dist/{chunk-N76HWBA3.mjs → chunk-R2ZDLJYT.mjs} +1 -1
- package/dist/chunk-SWUTTZCN.mjs +2 -0
- package/dist/{chunk-POQSE4C2.mjs → chunk-TR7TWGHB.mjs} +1 -1
- package/dist/chunk-U5XL7D6A.mjs +3 -0
- package/dist/{chunk-PVER7LSC.mjs → chunk-U7NZI6N4.mjs} +2 -2
- package/dist/{chunk-Q47PLKIJ.mjs → chunk-UGWMMEJ5.mjs} +1 -1
- package/dist/chunk-UJQJKNGK.mjs +2 -0
- package/dist/chunk-UYVCQK3H.mjs +22 -0
- package/dist/{chunk-FJYN7RTH.mjs → chunk-VFX2KNHP.mjs} +1 -1
- package/dist/{chunk-UBBRTJ2R.mjs → chunk-VS7JIGJW.mjs} +1 -1
- package/dist/{chunk-NVRNLK25.mjs → chunk-W7665ZEC.mjs} +2 -2
- package/dist/{chunk-NG375ILQ.mjs → chunk-WQDQWCX5.mjs} +1 -1
- package/dist/chunk-YLPSMDIS.mjs +5 -0
- package/dist/{chunk-VXACTLO3.mjs → chunk-YNAWBAYN.mjs} +1 -1
- package/dist/{chunk-ZB4H7ZN4.mjs → chunk-YROX2O22.mjs} +1 -1
- package/dist/{chunk-YQGT4AB2.mjs → chunk-ZDLPUOAG.mjs} +1 -1
- package/dist/chunk-ZQS6H473.mjs +16 -0
- package/dist/{chunk-OJKMINIU.mjs → chunk-ZWWC4KLF.mjs} +15 -15
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +5 -5
- package/kit/code.js +15 -15
- package/kit/report.css +120 -41
- package/kit/runtime.js +45 -7
- package/kit/tables.js +2 -0
- package/kit/ui.js +2 -0
- package/package.json +1 -1
- package/packs/gallery/chart-view/kit.js +3 -3
- package/packs/gallery/chart-view/writing.md +1 -1
- package/packs/gallery/countdown/component.json +1 -1
- package/packs/gallery/countdown/kit.js +89 -29
- package/packs/gallery/countdown/preview.svg +1 -1
- package/packs/gallery/countdown/style.css +88 -100
- package/packs/gallery/countdown/writing.md +2 -2
- package/packs/gallery/habit/component.json +3 -3
- package/packs/gallery/habit/kit.js +114 -75
- package/packs/gallery/habit/preview.svg +1 -1
- package/packs/gallery/habit/style.css +133 -205
- package/packs/gallery/habit/writing.md +2 -2
- package/packs/gallery/heatmap/component.json +2 -2
- package/packs/gallery/heatmap/kit.js +335 -173
- package/packs/gallery/heatmap/preview.svg +1 -1
- package/packs/gallery/heatmap/style.css +158 -170
- package/packs/gallery/heatmap/writing.md +2 -2
- package/packs/gallery/kanban/kit.js +3 -3
- package/packs/gallery/kanban/writing.md +1 -1
- package/packs/gallery/metric/kit.js +3 -3
- package/packs/gallery/metric/writing.md +1 -1
- package/packs/gallery/note/component.json +3 -3
- package/packs/gallery/note/kit.js +40 -13
- package/packs/gallery/note/preview.svg +1 -1
- package/packs/gallery/note/style.css +51 -30
- package/packs/gallery/note/writing.md +2 -2
- package/packs/gallery/recent/component.json +2 -2
- package/packs/gallery/recent/kit.js +141 -86
- package/packs/gallery/recent/preview.svg +1 -1
- package/packs/gallery/recent/style.css +53 -126
- package/packs/gallery/recent/writing.md +2 -2
- package/packs/gallery/static/component.json +2 -2
- package/packs/gallery/static/preview.svg +1 -1
- package/packs/gallery/static/style.css +99 -66
- package/packs/gallery/static/writing.md +2 -2
- package/packs/gallery/stats/component.json +3 -3
- package/packs/gallery/stats/kit.js +253 -72
- package/packs/gallery/stats/preview.svg +1 -1
- package/packs/gallery/stats/style.css +64 -142
- package/packs/gallery/stats/writing.md +2 -2
- package/packs/gallery/today/component.json +2 -2
- package/packs/gallery/today/kit.js +62 -27
- package/packs/gallery/today/preview.svg +1 -1
- package/packs/gallery/today/style.css +101 -72
- package/packs/gallery/today/writing.md +2 -2
- package/packs/gallery/todos/component.json +1 -1
- package/packs/gallery/todos/kit.js +218 -71
- package/packs/gallery/todos/preview.svg +1 -1
- package/packs/gallery/todos/style.css +170 -223
- package/packs/gallery/todos/writing.md +1 -1
- package/packs/gallery/weather/component.json +2 -2
- package/packs/gallery/weather/kit.js +165 -90
- package/packs/gallery/weather/preview.svg +1 -1
- package/packs/gallery/weather/style.css +100 -218
- package/packs/gallery/weather/writing.md +1 -1
- 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/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 +9 -9
- package/skill/SKILL.md +12 -12
- package/skill/references/building-blocks.md +4 -4
- package/skill/references/pages-and-data.md +13 -9
- package/skill/references/writing-html.md +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-2NRBY6AJ.mjs +0 -2
- package/dist/chunk-35NQ4PLQ.mjs +0 -2
- package/dist/chunk-4AV456RQ.mjs +0 -2
- package/dist/chunk-5XYHDBJ5.mjs +0 -2
- package/dist/chunk-6A53MZYZ.mjs +0 -2
- package/dist/chunk-6EXH3ORZ.mjs +0 -166
- package/dist/chunk-BVEFGE4B.mjs +0 -2
- package/dist/chunk-D4EURAX4.mjs +0 -4
- package/dist/chunk-DQCE7TJY.mjs +0 -5
- package/dist/chunk-FWNRPMCJ.mjs +0 -12
- package/dist/chunk-FWW4CSAZ.mjs +0 -2
- package/dist/chunk-JVHHHGEA.mjs +0 -3
- package/dist/chunk-PZDLJJTJ.mjs +0 -3
- package/dist/chunk-SXHBYZST.mjs +0 -16
- package/dist/chunk-UFNYFFKO.mjs +0 -20
- package/dist/chunk-UKSHDZZ6.mjs +0 -2
- package/dist/chunk-VJPFVNNW.mjs +0 -15
- package/dist/chunk-VS3ZMVGX.mjs +0 -5
- package/web/assets/index-BK2e_07w.js +0 -13
- package/web/assets/index-CWFI83mF.css +0 -1
|
@@ -3,21 +3,32 @@
|
|
|
3
3
|
// { "name": "喝八杯水", "days": ["2026-11-05", "2026-11-06"] }. The card draws the name in a field of its
|
|
4
4
|
// own (DocKit.input: written as the reader presses Enter or leaves it, never while an input method
|
|
5
5
|
// composes), the streak (the days in a row up to today, or up to yesterday while today is not checked
|
|
6
|
-
// yet, so that a streak lasts the day it is to be kept), how many days in all,
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// and
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
6
|
+
// yet, so that a streak lasts the day it is to be kept), how many days in all, and a button that checks
|
|
7
|
+
// today in, or takes today's check-in back when it is there. Each press and each name is one
|
|
8
|
+
// context.editJSON, one undo step, the JSON written back on one line as it was: what the reader does is
|
|
9
|
+
// in the file, and nothing else is (the streak and the days are worked out as it draws). It draws from
|
|
10
|
+
// the part on every `source` (an undo, an Agent's write) and again as a day begins (the kit's `clock`,
|
|
11
|
+
// "day"), so that "today" moves at midnight. Where nothing takes its writes (an export, a page that has
|
|
12
|
+
// not come to edit yet: context.canEdit() false) the name is read-only and the button a plain line saying
|
|
13
|
+
// whether today is done. Its words are the page's language (the UI's where Gallery says it, else the
|
|
14
|
+
// page's lang).
|
|
15
|
+
//
|
|
16
|
+
// Its face (the pack's design B, in the kit's card tokens), laid out by the card's cells (`data-layout`,
|
|
17
|
+
// by context.size, read again on `layout`): "wide" (4 × 2, the default) a head of the chip, a flame in
|
|
18
|
+
// its warm color, the name (the field) and the days in all after it (共 41 天), the streak, the hero, and
|
|
19
|
+
// 天连续 after it, the button at its right (a pale blue 打卡, a pale green ✓ 已打卡 a press takes back),
|
|
20
|
+
// and this week at the bottom, Monday to Sunday, seven circles (`weekOf`): a day done filled with the
|
|
21
|
+
// accent and ticked, one not done a soft gray with its initial, today ringed in the accent (今), filled
|
|
22
|
+
// and ringed twice once done, the days to come an outline; "narrow" (2 wide) the name alone at the top,
|
|
23
|
+
// a flame and the streak, and the button as wide as the card at the bottom (the name shown as words of
|
|
24
|
+
// up to two lines, the field over them unseen until a press or Tab brings it, so that a long name is
|
|
25
|
+
// never cut to a few characters); "tall" (4 high) the head, the streak and the button, and the last five
|
|
26
|
+
// weeks as a month (`monthOf`), Monday first, the days of the streak the accent's, the days done before
|
|
27
|
+
// it its pale tint, the others bare, today ringed, the days to come an outline, with 最近五周 and how
|
|
28
|
+
// many of them were done (打了 27 天) over it. A habit never
|
|
29
|
+
// checked in (no days at all) says 还没打过卡 where the streak stands (the face's data-fresh), the chip
|
|
30
|
+
// gray and no count of days, until the first check-in. Start a block of your own from it with gallery
|
|
31
|
+
// block new <id> --recipe habit.
|
|
21
32
|
|
|
22
33
|
const WORDS = {
|
|
23
34
|
zh: {
|
|
@@ -27,14 +38,14 @@ const WORDS = {
|
|
|
27
38
|
undo: "再按一下,撤回今天的打卡",
|
|
28
39
|
todayDone: "今天已打卡",
|
|
29
40
|
todayOpen: "今天还没打卡",
|
|
30
|
-
streak: "
|
|
41
|
+
streak: "天连续",
|
|
31
42
|
unit: () => "天",
|
|
32
43
|
total: (/** @type {number} */ days) => `共 ${days} 天`,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
week: "
|
|
37
|
-
|
|
44
|
+
fresh: ["还没打过卡", "今天开始第 1 天"],
|
|
45
|
+
weeks: "最近五周",
|
|
46
|
+
got: (/** @type {number} */ days) => ["打了 ", String(days), " 天"],
|
|
47
|
+
week: "这一周",
|
|
48
|
+
initials: ["日", "一", "二", "三", "四", "五", "六"],
|
|
38
49
|
today: "今",
|
|
39
50
|
day: (/** @type {number} */ month, /** @type {number} */ day, /** @type {boolean} */ done) => `${month}月${day}日${done ? ",已打卡" : ",没打卡"}`,
|
|
40
51
|
},
|
|
@@ -45,15 +56,15 @@ const WORDS = {
|
|
|
45
56
|
undo: "Press again to take today's check-in back",
|
|
46
57
|
todayDone: "Done today",
|
|
47
58
|
todayOpen: "Not done today",
|
|
48
|
-
streak: "
|
|
59
|
+
streak: "in a row",
|
|
49
60
|
unit: (/** @type {number} */ days) => (days === 1 ? "day" : "days"),
|
|
50
61
|
total: (/** @type {number} */ days) => `${days} ${days === 1 ? "day" : "days"} in all`,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
week: "
|
|
55
|
-
|
|
56
|
-
today: "Today",
|
|
62
|
+
fresh: ["No check-ins yet", "today can be day 1"],
|
|
63
|
+
weeks: "Last five weeks",
|
|
64
|
+
got: (/** @type {number} */ days) => ["", String(days), ` ${days === 1 ? "day" : "days"} done`],
|
|
65
|
+
week: "This week",
|
|
66
|
+
initials: ["S", "M", "T", "W", "T", "F", "S"],
|
|
67
|
+
today: "", // a week's circle is too small for "Today": its initial, ringed as today
|
|
57
68
|
day: (/** @type {number} */ month, /** @type {number} */ day, /** @type {boolean} */ done) => `${["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][month - 1]} ${day}${done ? ", done" : ", not done"}`,
|
|
58
69
|
},
|
|
59
70
|
};
|
|
@@ -88,6 +99,12 @@ function dayAfter(day, count) {
|
|
|
88
99
|
return `${moved.getUTCFullYear()}-${two(moved.getUTCMonth() + 1)}-${two(moved.getUTCDate())}`;
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
/** The weekday of a day written YYYY-MM-DD, 0 for Sunday. @param {string} day */
|
|
103
|
+
function weekdayOf(day) {
|
|
104
|
+
const [year, month, date] = day.split("-").map(Number);
|
|
105
|
+
return new Date(Date.UTC(year, month - 1, date)).getUTCDay();
|
|
106
|
+
}
|
|
107
|
+
|
|
91
108
|
/**
|
|
92
109
|
* The habit `data` is (context.readJSON's, or the draft context.editJSON hands a change): its name ("" for
|
|
93
110
|
* none yet) and its days, as they stand; throws saying why it is none, and the block draws nothing over it.
|
|
@@ -133,30 +150,30 @@ function toggled(days, today) {
|
|
|
133
150
|
}
|
|
134
151
|
|
|
135
152
|
/**
|
|
136
|
-
* The
|
|
137
|
-
* Sunday)
|
|
153
|
+
* The days of the `weeks` weeks that end with the one `today` is in, Monday first, oldest first: each its
|
|
154
|
+
* day (YYYY-MM-DD), its weekday (0 for Sunday), whether it was done, whether it is today, one to come
|
|
155
|
+
* (after today) and one of the streak (`streak`: the days of streakOf, back from today or yesterday).
|
|
138
156
|
* @param {string[]} days
|
|
139
157
|
* @param {string} today
|
|
158
|
+
* @param {number} [weeks]
|
|
140
159
|
*/
|
|
141
|
-
function
|
|
160
|
+
function monthOf(days, today, weeks = 5) {
|
|
142
161
|
const done = new Set(days);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
const streak = streakOf(days, today);
|
|
163
|
+
const last = done.has(today) ? today : dayAfter(today, -1);
|
|
164
|
+
const first = dayAfter(today, -((weekdayOf(today) + 6) % 7) - 7 * (weeks - 1));
|
|
165
|
+
return Array.from({ length: weeks * 7 }, (_, index) => {
|
|
166
|
+
const day = dayAfter(first, index);
|
|
167
|
+
return { day, weekday: weekdayOf(day), done: done.has(day), today: day === today, future: day > today, streak: day <= last && day > dayAfter(last, -streak) };
|
|
147
168
|
});
|
|
148
169
|
}
|
|
149
170
|
|
|
150
171
|
/**
|
|
151
|
-
*
|
|
172
|
+
* The week `today` is in, Monday to Sunday, as monthOf draws a day.
|
|
152
173
|
* @param {string[]} days
|
|
153
174
|
* @param {string} today
|
|
154
|
-
* @param {number} [span]
|
|
155
175
|
*/
|
|
156
|
-
|
|
157
|
-
const first = dayAfter(today, 1 - span);
|
|
158
|
-
return new Set(days.filter((day) => day >= first && day <= today)).size;
|
|
159
|
-
}
|
|
176
|
+
const weekOf = (days, today) => monthOf(days, today, 1);
|
|
160
177
|
|
|
161
178
|
/**
|
|
162
179
|
* Today checked in, or taken back: one write (context.editJSON), what a press of the button calls, and
|
|
@@ -195,46 +212,52 @@ function made(tag, kind) {
|
|
|
195
212
|
return node;
|
|
196
213
|
}
|
|
197
214
|
|
|
215
|
+
const FLAME = '<path d="M12 20.8a6 6 0 0 0 6-6c0-3.6-2.4-5.6-3.6-8.6-.3-.8-1.3-1-1.8-.3-1.4 2-2 3.6-2 5-.9-.6-1.4-1.5-1.6-2.4-.1-.6-.9-.8-1.2-.2C6.9 9.6 6 11.4 6 14.8a6 6 0 0 0 6 6z"/>';
|
|
216
|
+
const CHECK = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5.5 12.5l4 4 9-9"/></svg>';
|
|
217
|
+
|
|
198
218
|
DocKit.component({
|
|
199
219
|
id: "gallery/habit",
|
|
200
|
-
on: ["source", "editable", "clock"],
|
|
220
|
+
on: ["source", "editable", "clock", "layout"],
|
|
201
221
|
mount(host, context) {
|
|
202
222
|
const words = WORDS[languageOf(document.documentElement)];
|
|
203
223
|
const face = made("div", "face");
|
|
204
224
|
const head = made("div", "head");
|
|
205
225
|
const chip = made("span", "chip");
|
|
206
226
|
chip.setAttribute("aria-hidden", "true");
|
|
207
|
-
chip.innerHTML =
|
|
227
|
+
chip.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">${FLAME}</svg>`;
|
|
208
228
|
const name = made("input", "name");
|
|
209
229
|
name.type = "text";
|
|
210
230
|
name.placeholder = words.name;
|
|
211
231
|
name.spellcheck = false;
|
|
212
232
|
name.setAttribute("aria-label", words.name);
|
|
233
|
+
// A narrow card's name as words of up to two lines over the field, which stays the one a press or Tab reaches (style.css).
|
|
234
|
+
const label = made("span", "label");
|
|
235
|
+
label.setAttribute("aria-hidden", "true");
|
|
213
236
|
const total = made("span", "total");
|
|
214
|
-
head.append(chip, name, total);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
237
|
+
head.append(chip, name, label, total);
|
|
238
|
+
// The streak: its count large and its unit after it (a narrow card a flame before it), or, never
|
|
239
|
+
// checked in, a line inviting the first.
|
|
240
|
+
const row = made("div", "row");
|
|
218
241
|
const streak = made("p", "streak");
|
|
219
|
-
const
|
|
220
|
-
|
|
242
|
+
const flame = made("span", "flame");
|
|
243
|
+
flame.setAttribute("aria-hidden", "true");
|
|
244
|
+
flame.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${FLAME}</svg>`;
|
|
221
245
|
const count = made("strong", "count");
|
|
222
246
|
const unit = made("span", "unit");
|
|
223
|
-
streak.append(
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
247
|
+
streak.append(flame, count, unit);
|
|
248
|
+
const fresh = made("p", "fresh");
|
|
249
|
+
const press = made("button", "check");
|
|
250
|
+
press.type = "button";
|
|
251
|
+
row.append(streak, fresh, press);
|
|
252
|
+
// A tall card's five weeks: what they are and how many were done, over the month.
|
|
253
|
+
const caption = made("div", "caption");
|
|
254
|
+
const captionName = made("span", "caption-name");
|
|
255
|
+
captionName.textContent = words.weeks;
|
|
256
|
+
const captionCount = made("span", "caption-count");
|
|
257
|
+
caption.append(captionName, captionCount);
|
|
232
258
|
const week = made("ol", "week");
|
|
233
259
|
week.setAttribute("aria-label", words.week);
|
|
234
|
-
|
|
235
|
-
const fresh = made("p", "fresh");
|
|
236
|
-
fresh.textContent = words.fresh;
|
|
237
|
-
face.append(head, ring, streak, fresh, press, week);
|
|
260
|
+
face.append(head, row, caption, week);
|
|
238
261
|
host.append(face);
|
|
239
262
|
const named = DocKit.input(name, { signal: context.signal, commit: (value) => rename(context, value) });
|
|
240
263
|
press.addEventListener("click", () => {
|
|
@@ -243,6 +266,9 @@ DocKit.component({
|
|
|
243
266
|
|
|
244
267
|
const draw = (/** @type {string} */ reason = "", /** @type {unknown} */ detail = null) => {
|
|
245
268
|
if (reason === "clock" && detail !== "day") return; // a minute moves no day
|
|
269
|
+
const size = context.size;
|
|
270
|
+
const layout = !size ? "wide" : size.w <= 2 ? "narrow" : size.h >= 4 ? "tall" : "wide";
|
|
271
|
+
if (face.dataset.layout !== layout) face.dataset.layout = layout;
|
|
246
272
|
const data = context.readJSON("habit");
|
|
247
273
|
if (data === undefined) return; // no JSON: the instance has failed, and Gallery shows what it holds
|
|
248
274
|
let habit;
|
|
@@ -256,33 +282,46 @@ DocKit.component({
|
|
|
256
282
|
const done = habit.days.includes(today);
|
|
257
283
|
name.readOnly = !writes;
|
|
258
284
|
named.set(habit.name);
|
|
285
|
+
label.textContent = habit.name || words.name;
|
|
286
|
+
label.toggleAttribute("data-empty", !habit.name);
|
|
259
287
|
// Where nothing is written, the button is a line saying how today stands: nothing to press.
|
|
260
288
|
press.disabled = !writes;
|
|
261
289
|
press.classList.toggle("gallery-habit-done", done);
|
|
262
|
-
|
|
290
|
+
if (writes && done) press.innerHTML = `${CHECK}<span>${words.checked}</span>`;
|
|
291
|
+
else press.textContent = writes ? words.check : (done ? words.todayDone : words.todayOpen);
|
|
263
292
|
press.title = writes && done ? words.undo : "";
|
|
264
293
|
press.setAttribute("aria-pressed", String(done));
|
|
265
294
|
face.toggleAttribute("data-fresh", habit.days.length === 0);
|
|
266
295
|
const days = streakOf(habit.days, today);
|
|
267
296
|
count.textContent = String(days);
|
|
268
|
-
unit.textContent = words.unit(days);
|
|
297
|
+
unit.textContent = layout === "narrow" ? words.unit(days) : words.streak;
|
|
298
|
+
fresh.replaceChildren(...(layout === "narrow" ? [words.fresh[0]] : [words.fresh[0], document.createElement("br"), words.fresh[1]]));
|
|
269
299
|
total.textContent = habit.days.length > 0 ? words.total(new Set(habit.days).size) : "";
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
300
|
+
const span = layout === "tall" ? 5 : 1;
|
|
301
|
+
const shown = monthOf(habit.days, today, span);
|
|
302
|
+
week.dataset.weeks = String(span);
|
|
303
|
+
const [before, got, after] = words.got(shown.filter((day) => day.done && !day.future).length);
|
|
304
|
+
const bold = document.createElement("b");
|
|
305
|
+
bold.textContent = got;
|
|
306
|
+
captionCount.replaceChildren(before, bold, after);
|
|
307
|
+
const initials = span === 5 ? [1, 2, 3, 4, 5, 6, 0].map((weekday) => {
|
|
308
|
+
const item = made("li", "initial");
|
|
309
|
+
item.setAttribute("aria-hidden", "true");
|
|
310
|
+
item.textContent = words.initials[weekday];
|
|
311
|
+
return item;
|
|
312
|
+
}) : [];
|
|
313
|
+
week.replaceChildren(...initials, ...shown.map(({ day, weekday, done: kept, today: now, future, streak: inStreak }) => {
|
|
276
314
|
const item = made("li", "day");
|
|
277
315
|
item.classList.toggle("gallery-habit-kept", kept);
|
|
278
|
-
item.classList.toggle("gallery-habit-today",
|
|
316
|
+
item.classList.toggle("gallery-habit-today", now);
|
|
317
|
+
item.classList.toggle("gallery-habit-future", future);
|
|
318
|
+
item.classList.toggle("gallery-habit-streak-day", inStreak);
|
|
279
319
|
const [, month, date] = day.split("-").map(Number);
|
|
280
320
|
item.setAttribute("aria-label", words.day(month, date, kept));
|
|
281
321
|
item.title = words.day(month, date, kept);
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
item.append(dot, label);
|
|
322
|
+
// A week's circle says its day by its initial (今 for today), a month's by its date; a day done of a week, a tick.
|
|
323
|
+
if (span === 1 && kept && !future) item.innerHTML = CHECK;
|
|
324
|
+
else item.textContent = span === 5 ? String(date) : now && words.today ? words.today : words.initials[weekday];
|
|
286
325
|
return item;
|
|
287
326
|
}));
|
|
288
327
|
};
|
|
@@ -1 +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="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 120"><rect width="240" height="120" rx="8" fill="#f3f3f1"/><rect x="16.5" y="12.5" width="207" height="95" rx="8" fill="#ffffff" stroke="#e6e6e3"/><rect x="28" y="22" width="10" height="10" rx="3" fill="#fdf1dd"/><rect x="42" y="24.5" width="54" height="5" rx="2.5" fill="#37352f"/><rect x="100" y="24.5" width="20" height="5" rx="2.5" fill="#d4d3cf"/><rect x="28" y="42" width="24" height="20" rx="3" fill="#1d1d1b"/><rect x="56" y="56" width="22" height="5" rx="2.5" fill="#a6a5a1"/><rect x="176" y="42" width="36" height="18" rx="5" fill="#ebf2fa"/><rect x="186" y="48.5" width="16" height="5" rx="2.5" fill="#4084cf"/><circle cx="37" cy="88" r="9" fill="#4084cf"/><path d="M33.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="66" cy="88" r="9" fill="#4084cf"/><path d="M62.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="95" cy="88" r="9" fill="#4084cf"/><path d="M91.5 88l2.5 2.5 4.5-5" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/><circle cx="124" cy="88" r="8.4" fill="none" stroke="#4084cf" stroke-width="1.3"/><circle cx="153" cy="88" r="8.6" fill="none" stroke="#ebebe9"/><circle cx="182" cy="88" r="8.6" fill="none" stroke="#ebebe9"/><circle cx="211" cy="88" r="8.6" fill="none" stroke="#ebebe9"/></svg>
|