@heycys/gallery 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +51 -1
- package/browser/editor/components/callout/index.mjs +40 -15
- package/browser/editor/components/columns/page.mjs +45 -32
- package/browser/editor/components/details/index.mjs +2 -1
- package/browser/editor/components/dialog/index.mjs +2 -1
- package/browser/editor/components/dialog/page.mjs +0 -18
- package/browser/editor/components/divider/index.mjs +1 -1
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/figure/page.mjs +10 -1
- package/browser/editor/components/file/page.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/heading/index.mjs +2 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +4 -20
- package/browser/editor/components/icons.mjs +13 -2
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/image/page.mjs +2 -2
- package/browser/editor/components/installed/index.mjs +82 -29
- package/browser/editor/components/installed/page.mjs +146 -34
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/kit.mjs +3 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/media/page.mjs +44 -14
- package/browser/editor/components/pages.mjs +2 -2
- package/browser/editor/components/registry.mjs +68 -33
- package/browser/editor/components/section/index.mjs +2 -1
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/table/index.mjs +64 -5
- package/browser/editor/components/table/page.mjs +30 -19
- package/browser/editor/page/annotate/anchors.mjs +4 -3
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/annotate/index.mjs +61 -34
- package/browser/editor/page/autosave.mjs +357 -38
- package/browser/editor/page/beside.mjs +5 -5
- package/browser/editor/page/block-menu/colors.mjs +3 -1
- package/browser/editor/page/block-menu/index.mjs +8 -6
- package/browser/editor/page/blocks.mjs +16 -7
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +145 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +970 -0
- package/browser/editor/page/board/settings.mjs +209 -0
- package/browser/editor/page/caret.mjs +5 -2
- package/browser/editor/page/changes/bar.mjs +94 -0
- package/browser/editor/page/changes/ghost.mjs +206 -0
- package/browser/editor/page/changes/gone-words.mjs +94 -0
- package/browser/editor/page/changes/index.mjs +447 -0
- package/browser/editor/page/changes/words.mjs +27 -0
- package/browser/editor/page/clipboard/import/colors.mjs +3 -3
- 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 +156 -26
- package/browser/editor/page/clipboard/own/blocks.mjs +25 -16
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/describe.mjs +16 -7
- package/browser/editor/page/clipboard/own/export.mjs +6 -6
- package/browser/editor/page/clipboard/own/selection.mjs +3 -3
- package/browser/editor/page/clipboard/own/writers.mjs +0 -11
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +98 -25
- package/browser/editor/page/conflicts.mjs +13 -33
- package/browser/editor/page/convert.mjs +8 -7
- package/browser/editor/page/core.mjs +81 -27
- package/browser/editor/page/custom-page.mjs +106 -0
- package/browser/editor/page/drag/index.mjs +40 -24
- package/browser/editor/page/drag/preview.mjs +9 -4
- package/browser/editor/page/editor.mjs +120 -28
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +22 -13
- package/browser/editor/page/emoji-picker/grid.mjs +7 -5
- package/browser/editor/page/emoji-picker/icon-tab.mjs +4 -4
- package/browser/editor/page/emoji-picker/icons.mjs +0 -1
- package/browser/editor/page/emoji-picker/index.mjs +11 -9
- package/browser/editor/page/emoji-picker/styles.mjs +156 -2
- package/browser/editor/page/emoji-picker/support.mjs +6 -4
- package/browser/editor/page/emoji-picker/upload.mjs +14 -13
- package/browser/editor/page/fills.mjs +5 -3
- package/browser/editor/page/fold/index.mjs +348 -0
- package/browser/editor/page/fold/rule.mjs +125 -0
- package/browser/editor/page/folded.mjs +23 -0
- package/browser/editor/page/format-bar/bar.mjs +2 -1
- package/browser/editor/page/format-bar/index.mjs +1 -1
- package/browser/editor/page/geometry.mjs +8 -6
- package/browser/editor/page/handle/index.mjs +22 -14
- package/browser/editor/page/hints/index.mjs +1 -1
- package/browser/editor/page/history.mjs +24 -4
- package/browser/editor/page/insert/index.mjs +30 -17
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +69 -6
- package/browser/editor/page/margin.mjs +63 -27
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +86 -31
- package/browser/editor/page/merge.mjs +24 -0
- package/browser/editor/page/notices.mjs +3 -3
- package/browser/editor/page/offered.mjs +1 -1
- package/browser/editor/page/outline/folds.mjs +11 -10
- package/browser/editor/page/outline/index.mjs +131 -45
- package/browser/editor/page/outline/list.mjs +23 -11
- package/browser/editor/page/outline/read.mjs +1 -1
- package/browser/editor/page/outline/strip.mjs +7 -1
- package/browser/editor/page/page-objects.mjs +13 -2
- package/browser/editor/page/panel.mjs +9 -13
- package/browser/editor/page/present-links.mjs +11 -2
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/selection/delete.mjs +8 -6
- package/browser/editor/page/selection/index.mjs +10 -3
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +101 -6
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/cell-bar.mjs +4 -1
- package/browser/editor/page/table/cells.mjs +103 -47
- package/browser/editor/page/table/icons.mjs +3 -1
- package/browser/editor/page/table/index.mjs +40 -16
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +150 -0
- package/browser/editor/page/table/widths.mjs +9 -4
- package/browser/editor/page/text-select/index.mjs +43 -14
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/tooltip.mjs +1 -1
- package/browser/editor/page/type-grid.mjs +4 -3
- package/browser/editor/page/typing/code-edges.mjs +63 -17
- package/browser/editor/page/typing/index.mjs +65 -9
- package/browser/editor/page/typing/leave.mjs +1 -1
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/annotations.mjs +8 -10
- package/browser/shared/block-packs.mjs +404 -0
- package/browser/shared/board-places.mjs +224 -0
- package/browser/shared/card-size.mjs +59 -0
- package/browser/shared/code-folds.mjs +5 -1
- package/browser/shared/colors.mjs +17 -14
- package/browser/shared/component-catalog.mjs +345 -54
- package/browser/shared/component-source.mjs +37 -0
- package/browser/shared/components/callout.mjs +4 -2
- package/browser/shared/components/index.mjs +72 -9
- package/browser/shared/components/installed.mjs +110 -8
- package/browser/shared/components/page.mjs +22 -3
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/components/table.mjs +1 -1
- package/browser/shared/components/text.mjs +2 -2
- package/browser/shared/document-look.mjs +183 -0
- package/browser/shared/drafts.mjs +432 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/README.md +4 -2
- package/browser/shared/emoji/data/categories.json +1 -1
- package/browser/shared/emoji/data/keywords-en.json +1 -1
- package/browser/shared/emoji/data/keywords-zh.json +1 -1
- package/browser/shared/emoji/data/names.json +1 -1
- package/browser/shared/emoji/data/positions.json +1 -1
- package/browser/shared/emoji/data/twemoji-index.json +1 -1
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +10 -12
- package/browser/shared/emoji/emoji.mjs +8 -7
- package/browser/shared/emoji/icon-value.mjs +4 -3
- 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/html-tree.mjs +11 -5
- package/browser/shared/i18n/en.mjs +374 -35
- package/browser/shared/json-layout.mjs +47 -0
- package/browser/shared/long-runs.mjs +39 -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/new-names.mjs +5 -2
- package/browser/shared/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +458 -0
- package/browser/shared/pack-manifest.mjs +77 -0
- package/browser/shared/page-address.mjs +6 -3
- package/browser/shared/page-cards.mjs +308 -0
- package/browser/shared/page-links.mjs +69 -6
- package/browser/shared/pages.mjs +388 -0
- package/browser/shared/paths.mjs +6 -0
- package/browser/shared/preferences.mjs +10 -4
- package/browser/shared/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +13 -5
- package/browser/shared/shipped-blocks.mjs +299 -0
- package/browser/shared/table-chart.mjs +33 -1
- package/browser/shared/todos.mjs +83 -0
- package/browser/shared/user-directory.mjs +24 -0
- package/browser/shared/versions.mjs +14 -0
- package/browser/shared/web-links.mjs +134 -0
- package/browser/shared/workspace-columns.mjs +120 -0
- package/browser/shared/workspace-look.mjs +91 -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/browser/shared/zoom.mjs +5 -5
- package/dist/chunk-2NRBY6AJ.mjs +2 -0
- package/dist/chunk-32ZUEFZ7.mjs +2 -0
- package/dist/chunk-35NQ4PLQ.mjs +2 -0
- package/dist/chunk-3KJHLHUO.mjs +2 -0
- package/dist/chunk-3NJACR4W.mjs +2 -0
- package/dist/chunk-4AV456RQ.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5XYHDBJ5.mjs +2 -0
- package/dist/chunk-5ZJA7CXT.mjs +2 -0
- package/dist/chunk-6A53MZYZ.mjs +2 -0
- package/dist/chunk-6EXH3ORZ.mjs +166 -0
- package/dist/chunk-6EZ7FNIK.mjs +3 -0
- package/dist/{chunk-UXUK4PMC.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-6U2SLSDN.mjs → chunk-6VTU6KEO.mjs} +1 -1
- package/dist/chunk-B4P2CM2J.mjs +3 -0
- package/dist/chunk-BPL64HGA.mjs +4 -0
- package/dist/chunk-BVEFGE4B.mjs +2 -0
- package/dist/chunk-BZ5RAF7L.mjs +2 -0
- package/dist/chunk-CRJEG7MT.mjs +2 -0
- package/dist/{chunk-B3VTYBYR.mjs → chunk-D4CKRD3V.mjs} +91 -91
- package/dist/chunk-D4EURAX4.mjs +4 -0
- package/dist/chunk-DQCE7TJY.mjs +5 -0
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/{chunk-DB4WKGYF.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-FJYN7RTH.mjs +4 -0
- package/dist/chunk-FWNRPMCJ.mjs +12 -0
- package/dist/chunk-FWW4CSAZ.mjs +2 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-GY3FAUVM.mjs +2 -0
- package/dist/chunk-HLYV7RIH.mjs +2 -0
- package/dist/chunk-HMYTM3GT.mjs +15 -0
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-KTKHRC6H.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/chunk-MHW7ZKOU.mjs +2 -0
- package/dist/chunk-N76HWBA3.mjs +10 -0
- package/dist/chunk-N7AZZLGT.mjs +548 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-YXAUQPVK.mjs → chunk-NFMCP2HI.mjs} +3 -3
- package/dist/chunk-NG375ILQ.mjs +2 -0
- package/dist/chunk-NVRNLK25.mjs +6 -0
- package/dist/chunk-NWFBE2YA.mjs +2 -0
- package/dist/chunk-NWR2LT5B.mjs +2 -0
- package/dist/chunk-OJKMINIU.mjs +20 -0
- package/dist/chunk-OUUP3WKT.mjs +2 -0
- package/dist/chunk-OW5NWPOJ.mjs +10 -0
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-POQSE4C2.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/{chunk-Z52HTUW7.mjs → chunk-PVER7LSC.mjs} +2 -2
- package/dist/chunk-PZDLJJTJ.mjs +3 -0
- package/dist/chunk-Q47PLKIJ.mjs +15 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QKXMPUXC.mjs +2 -0
- package/dist/chunk-QOUEFUCH.mjs +16 -0
- package/dist/chunk-RFDZXFJF.mjs +13 -0
- package/dist/chunk-RKPWLGZ3.mjs +4 -0
- package/dist/chunk-RMECZA2K.mjs +2 -0
- package/dist/{chunk-EUX7IC5J.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SX4LJYT6.mjs +8 -0
- package/dist/chunk-SXHBYZST.mjs +16 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TEZAWDSQ.mjs +2 -0
- package/dist/chunk-UBBRTJ2R.mjs +24 -0
- package/dist/chunk-UFNYFFKO.mjs +20 -0
- package/dist/chunk-UGWYKHBL.mjs +170 -0
- package/dist/chunk-UKSHDZZ6.mjs +2 -0
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-UNOYVIYR.mjs +2 -0
- package/dist/chunk-V6RIYQZZ.mjs +4 -0
- package/dist/chunk-VJPFVNNW.mjs +15 -0
- package/dist/chunk-VS3ZMVGX.mjs +5 -0
- package/dist/chunk-VTKNEYT3.mjs +6 -0
- package/dist/chunk-VXACTLO3.mjs +3 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YQGT4AB2.mjs +6 -0
- package/dist/chunk-ZB4H7ZN4.mjs +2 -0
- package/dist/{chunk-ACOPDCNB.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZUNVAXLH.mjs +2 -0
- package/dist/chunk-ZWPMCK7P.mjs +2 -0
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/{chunk-EVJ3BX3M.mjs → update-fetch.mjs} +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +95 -0
- package/kit/board.js +250 -0
- package/kit/charts.js +5 -71
- package/kit/code.js +14 -14
- package/kit/math.js +18 -2
- package/kit/report.css +500 -151
- package/kit/runtime.js +1720 -170
- package/kit/state.js +10 -1
- package/kit/tables.js +172 -37
- package/kit/ui.js +166 -27
- package/package.json +2 -1
- package/packs/gallery/card/component.json +14 -0
- package/packs/gallery/card/example.html +10 -0
- package/packs/gallery/card/preview.svg +1 -0
- package/packs/gallery/card/style.css +6 -0
- package/packs/gallery/card/template.html +6 -0
- package/packs/gallery/card/writing.md +14 -0
- package/packs/gallery/chart-card/component.json +15 -0
- package/packs/gallery/chart-card/example.html +14 -0
- package/packs/gallery/chart-card/kit.js +130 -0
- package/packs/gallery/chart-card/preview.svg +1 -0
- package/packs/gallery/chart-card/style.css +42 -0
- package/packs/gallery/chart-card/template.html +13 -0
- package/packs/gallery/chart-card/writing.md +20 -0
- package/packs/gallery/chart-view/component.json +20 -0
- package/packs/gallery/chart-view/example.html +13 -0
- package/packs/gallery/chart-view/kit.js +355 -0
- package/packs/gallery/chart-view/preview.svg +1 -0
- package/packs/gallery/chart-view/style.css +94 -0
- package/packs/gallery/chart-view/template.html +3 -0
- package/packs/gallery/chart-view/writing.md +22 -0
- package/packs/gallery/countdown/component.json +18 -0
- package/packs/gallery/countdown/example.html +3 -0
- package/packs/gallery/countdown/kit.js +156 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +130 -0
- package/packs/gallery/countdown/template.html +3 -0
- package/packs/gallery/countdown/writing.md +22 -0
- package/packs/gallery/habit/component.json +14 -0
- package/packs/gallery/habit/example.html +3 -0
- package/packs/gallery/habit/kit.js +295 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +246 -0
- package/packs/gallery/habit/template.html +3 -0
- package/packs/gallery/habit/writing.md +21 -0
- package/packs/gallery/heatmap/component.json +18 -0
- package/packs/gallery/heatmap/example.html +3 -0
- package/packs/gallery/heatmap/kit.js +351 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +201 -0
- package/packs/gallery/heatmap/template.html +3 -0
- package/packs/gallery/heatmap/writing.md +21 -0
- package/packs/gallery/kanban/component.json +18 -0
- package/packs/gallery/kanban/example.html +12 -0
- package/packs/gallery/kanban/kit.js +540 -0
- package/packs/gallery/kanban/preview.svg +1 -0
- package/packs/gallery/kanban/style.css +212 -0
- package/packs/gallery/kanban/template.html +3 -0
- package/packs/gallery/kanban/writing.md +20 -0
- package/packs/gallery/metric/component.json +22 -0
- package/packs/gallery/metric/example.html +15 -0
- package/packs/gallery/metric/kit.js +248 -0
- package/packs/gallery/metric/preview.svg +1 -0
- package/packs/gallery/metric/style.css +92 -0
- package/packs/gallery/metric/template.html +3 -0
- package/packs/gallery/metric/writing.md +23 -0
- package/packs/gallery/note/component.json +14 -0
- package/packs/gallery/note/example.html +3 -0
- package/packs/gallery/note/kit.js +102 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +76 -0
- package/packs/gallery/note/template.html +3 -0
- package/packs/gallery/note/writing.md +18 -0
- package/packs/gallery/pack.json +8 -0
- package/packs/gallery/recent/component.json +13 -0
- package/packs/gallery/recent/example.html +1 -0
- package/packs/gallery/recent/kit.js +238 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +158 -0
- package/packs/gallery/recent/template.html +1 -0
- package/packs/gallery/recent/writing.md +15 -0
- package/packs/gallery/static/component.json +13 -0
- package/packs/gallery/static/example.html +11 -0
- package/packs/gallery/static/preview.svg +1 -0
- package/packs/gallery/static/style.css +138 -0
- package/packs/gallery/static/template.html +1 -0
- package/packs/gallery/static/writing.md +18 -0
- package/packs/gallery/stats/component.json +13 -0
- package/packs/gallery/stats/example.html +1 -0
- package/packs/gallery/stats/kit.js +166 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +151 -0
- package/packs/gallery/stats/template.html +1 -0
- package/packs/gallery/stats/writing.md +11 -0
- package/packs/gallery/today/component.json +12 -0
- package/packs/gallery/today/example.html +1 -0
- package/packs/gallery/today/kit.js +185 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +120 -0
- package/packs/gallery/today/template.html +1 -0
- package/packs/gallery/today/writing.md +14 -0
- package/packs/gallery/todos/component.json +19 -0
- package/packs/gallery/todos/example.html +3 -0
- package/packs/gallery/todos/kit.js +342 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +267 -0
- package/packs/gallery/todos/template.html +3 -0
- package/packs/gallery/todos/writing.md +30 -0
- package/packs/gallery/weather/component.json +19 -0
- package/packs/gallery/weather/example.html +3 -0
- package/packs/gallery/weather/kit.js +312 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +258 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/pack.json +8 -0
- package/release.json +13 -11
- package/sdk/doc-kit.d.ts +404 -7
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +71 -26
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/example-report.html +1 -1
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +221 -0
- package/skill/references/writing-html.md +9 -7
- package/skill/sdk/doc-kit.d.ts +404 -7
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BK2e_07w.js +13 -0
- package/web/assets/index-CWFI83mF.css +1 -0
- package/web/index.html +2 -2
- package/browser/editor/components/callout/page.mjs +0 -13
- package/dist/chunk-2PBALTR3.mjs +0 -57
- package/dist/chunk-3LA3EMDE.mjs +0 -15
- package/dist/chunk-5FRMCDPY.mjs +0 -16
- package/dist/chunk-5LEK2CBS.mjs +0 -2
- package/dist/chunk-5OFN5AHC.mjs +0 -2
- package/dist/chunk-5SIYS5HN.mjs +0 -2
- package/dist/chunk-5TEK3RAD.mjs +0 -2
- package/dist/chunk-6CYG3Z4V.mjs +0 -2
- package/dist/chunk-7GHT2UCA.mjs +0 -15
- package/dist/chunk-7QQBR7PB.mjs +0 -2
- package/dist/chunk-ATCJYAR4.mjs +0 -2
- package/dist/chunk-C7HWOBIF.mjs +0 -2
- package/dist/chunk-E7VYDG2X.mjs +0 -2
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FQGQH4KM.mjs +0 -2
- package/dist/chunk-G7TOXONE.mjs +0 -6
- package/dist/chunk-GPF4YWWB.mjs +0 -9
- package/dist/chunk-GYQV7Y4J.mjs +0 -120
- package/dist/chunk-HMHK3EQ6.mjs +0 -2
- package/dist/chunk-HQQMJCQJ.mjs +0 -10
- package/dist/chunk-IERUOGC3.mjs +0 -6
- package/dist/chunk-ITNLYXXV.mjs +0 -3
- package/dist/chunk-L4DVONOG.mjs +0 -2
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LC7YNQFG.mjs +0 -2
- package/dist/chunk-LHTFLRB6.mjs +0 -4
- package/dist/chunk-NFIBI4IP.mjs +0 -26
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O52JMOCZ.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-QMQUXTU4.mjs +0 -12
- package/dist/chunk-QVWVFC5K.mjs +0 -6
- package/dist/chunk-QYKCJ7FG.mjs +0 -8
- package/dist/chunk-QZY6Q64C.mjs +0 -2
- package/dist/chunk-TDQP3DKQ.mjs +0 -10
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-UNUEWH4S.mjs +0 -2
- package/dist/chunk-V4CPWKMZ.mjs +0 -2
- package/dist/chunk-VACRB2NE.mjs +0 -3
- package/dist/chunk-W63L7367.mjs +0 -7
- package/dist/chunk-W7CXPCRV.mjs +0 -6
- package/dist/chunk-XINNG4F2.mjs +0 -4
- package/dist/chunk-YL2DPWVS.mjs +0 -4
- package/dist/chunk-YZ5Z6H4W.mjs +0 -4
- package/dist/chunk-ZBIM6ARY.mjs +0 -216
- package/skill/references/building-components.md +0 -327
- package/web/assets/index-B6Ai3wsa.js +0 -13
- package/web/assets/index-SYPC3EZy.css +0 -1
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
// gallery/kanban (看板): a view of a table of the document (its manifest's needs hold "tables"; the table's
|
|
2
|
+
// frame carries the key its data-doc-from names, which the table's 视图 › puts on both). Each row of the
|
|
3
|
+
// table is a card, grouped by a column (its settings' `group`, else the column that reads as a status: one
|
|
4
|
+
// named 状态, 进度, 阶段, status…, else the one after the first whose words repeat most), the groups in
|
|
5
|
+
// the order its settings' `order` lists (empty ones too), then any other value as the rows first say it,
|
|
6
|
+
// the cards of a group in the table's order. A card is its row's first cell, the other cells' words under
|
|
7
|
+
// it, and a chip for each link its row holds: one to a document opens it (context.workspace.open: the
|
|
8
|
+
// workbench goes there), one to the web a new tab.
|
|
9
|
+
//
|
|
10
|
+
// The table is the file's whole truth and the reader's: the board writes nothing of its own but its
|
|
11
|
+
// settings. Each gesture asks the page editor through context.table(), one intent, one undo step: a card
|
|
12
|
+
// dragged (DocKit.drag) to another place of its group moves its row, to another group moves it and sets
|
|
13
|
+
// its cell of the grouping column in the same step (set alone where the group has no other card); 新建
|
|
14
|
+
// at a group's foot adds a row after the group's last, its cell of the group set, and opens its title to
|
|
15
|
+
// type in; a card's ✎ sets its first cell, its 🗑 takes the row out. Where the table can take no change
|
|
16
|
+
// (an export, 演示视图, before the page edits, a table the editor's tools do not manage: table().canEdit())
|
|
17
|
+
// the board only shows, and says why where the page edits. Its settings are its own data part
|
|
18
|
+
// (`settings`, JSON), changed by the ⚙ at its head (分组依据, which takes the order of the groups off, as
|
|
19
|
+
// that named the values of the column grouped by before), one undo step each.
|
|
20
|
+
//
|
|
21
|
+
// A card is kept while its row is the same object (context.table() gives a row anew only once it or the
|
|
22
|
+
// header changed) and only the cards whose rows changed are made again, so that a keystroke in a table of
|
|
23
|
+
// 500 rows makes one card and moves none. The words are the page's language.
|
|
24
|
+
|
|
25
|
+
const WORDS = {
|
|
26
|
+
zh: {
|
|
27
|
+
by: (/** @type {string} */ name) => `按“${name}”分组`,
|
|
28
|
+
group: "分组依据",
|
|
29
|
+
settings: "设置",
|
|
30
|
+
none: "(空)",
|
|
31
|
+
untitled: "无标题",
|
|
32
|
+
add: "新建",
|
|
33
|
+
rename: "重命名",
|
|
34
|
+
remove: "删除",
|
|
35
|
+
open: "打开",
|
|
36
|
+
cards: (/** @type {number} */ count) => `${count} 张卡片`,
|
|
37
|
+
unbound: "这个看板还没有接到表格上:在表格的菜单里选“视图 › 看板”。",
|
|
38
|
+
unread: "读不到这个看板的表格:它不在页面上了,或者有合并的单元格。",
|
|
39
|
+
missing: (/** @type {string} */ name) => `找不到列“${name}”:表格的列名改过了吗?`,
|
|
40
|
+
readOnly: "这张表格有表尾,或者各行的格数不一样,看板改不了它,这里只能看。",
|
|
41
|
+
empty: "表格里还没有行。",
|
|
42
|
+
},
|
|
43
|
+
en: {
|
|
44
|
+
by: (/** @type {string} */ name) => `Grouped by “${name}”`,
|
|
45
|
+
group: "Group by",
|
|
46
|
+
settings: "Settings",
|
|
47
|
+
none: "(empty)",
|
|
48
|
+
untitled: "Untitled",
|
|
49
|
+
add: "New",
|
|
50
|
+
rename: "Rename",
|
|
51
|
+
remove: "Delete",
|
|
52
|
+
open: "Open",
|
|
53
|
+
cards: (/** @type {number} */ count) => `${count} cards`,
|
|
54
|
+
unbound: "This board reads no table yet: pick View › Board in a table's menu.",
|
|
55
|
+
unread: "This board's table cannot be read: it is not on the page, or it has merged cells.",
|
|
56
|
+
missing: (/** @type {string} */ name) => `No column “${name}”: was the table's column renamed?`,
|
|
57
|
+
readOnly: "This table has a footer, or rows of other lengths: the board cannot change it, only show it.",
|
|
58
|
+
empty: "The table has no rows yet.",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// A column whose name says it is a status, the one a board groups by when its settings name none.
|
|
63
|
+
const STATUS = /状态|進度|进度|阶段|階段|状況|状况|status|stage|state|phase/i;
|
|
64
|
+
|
|
65
|
+
// How far off the groups a card held is still over them, in pixels.
|
|
66
|
+
const MARGIN = 24;
|
|
67
|
+
|
|
68
|
+
// The icons of a card's tools and the head's settings (16 × 16, the kit's line weight).
|
|
69
|
+
const ICONS = {
|
|
70
|
+
gear: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3 4.5h6M12 4.5h1M3 11.5h1M7 11.5h6" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><circle cx="10.5" cy="4.5" r="1.5" fill="none" stroke="currentColor" stroke-width="1.3"/><circle cx="5.5" cy="11.5" r="1.5" fill="none" stroke="currentColor" stroke-width="1.3"/></svg>',
|
|
71
|
+
rename: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M10.5 3.2l2.3 2.3-7 7H3.5v-2.3z" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/></svg>',
|
|
72
|
+
remove: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3.5 4.5h9M6.5 4.5V3h3v1.5M5 4.5l.6 8h4.8l.6-8" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round" stroke-linecap="round"/></svg>',
|
|
73
|
+
page: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4.5 2.5h4.5l2.5 2.5v8.5h-7z" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/></svg>',
|
|
74
|
+
web: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M6.5 3.5h-3v9h9v-3M9 3h4v4M13 3L7.5 8.5" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
|
|
75
|
+
add: '<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 3.5v9M3.5 8h9" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** The language the page speaks: the UI's where Gallery says it (data-ge-language), else its lang's. */
|
|
79
|
+
function languageOf(/** @type {HTMLElement} */ root) {
|
|
80
|
+
const ui = root.getAttribute("data-ge-language");
|
|
81
|
+
return (ui !== null ? ui === "en" : /^en(?:-|$)/i.test(root.lang)) ? "en" : "zh";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Words as a cell shows them, its white space one space. */
|
|
85
|
+
const wordsOf = (/** @type {Node | null | undefined} */ node) => (node?.textContent ?? "").replace(/\s+/g, " ").trim();
|
|
86
|
+
|
|
87
|
+
/** A row's value of a column as the board groups by it: its words ("" for none). */
|
|
88
|
+
const keyOf = (/** @type {DocRow} */ row, /** @type {string} */ column) => {
|
|
89
|
+
const value = row.values[column];
|
|
90
|
+
return value === null || value === undefined ? "" : String(value).trim();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* What its settings ask (context.readJSON's; {} where none is set): the column to group by ("" for the
|
|
95
|
+
* one it finds) and the order of the groups.
|
|
96
|
+
* @param {any} settings
|
|
97
|
+
*/
|
|
98
|
+
function askedOf(settings) {
|
|
99
|
+
const table = settings !== null && typeof settings === "object" && !Array.isArray(settings) ? settings : {};
|
|
100
|
+
const group = typeof table.group === "string" ? table.group.trim() : "";
|
|
101
|
+
const order = typeof table.order === "string" ? table.order.split(/[,,、]/).map((name) => name.trim()).filter(Boolean) : [];
|
|
102
|
+
return { group, order };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The column a board of `table` groups by when its settings name none: one whose name says it is a
|
|
107
|
+
* status, else the column after the first holding words (not numbers) whose values repeat most (the
|
|
108
|
+
* fewest of them), else the second, else the first.
|
|
109
|
+
* @param {DocTableView} table
|
|
110
|
+
*/
|
|
111
|
+
function groupColumnOf(table) {
|
|
112
|
+
const [first = null, ...rest] = table.columns;
|
|
113
|
+
if (rest.length === 0) return first;
|
|
114
|
+
const named = rest.find((name) => STATUS.test(name));
|
|
115
|
+
if (named) return named;
|
|
116
|
+
/** @type {[string, number] | null} */
|
|
117
|
+
let best = null;
|
|
118
|
+
for (const name of rest) {
|
|
119
|
+
if (table.rows.some((row) => typeof row.values[name] === "number")) continue;
|
|
120
|
+
const kinds = new Set(table.rows.map((row) => keyOf(row, name))).size;
|
|
121
|
+
if (best === null || kinds < best[1]) best = [name, kinds];
|
|
122
|
+
}
|
|
123
|
+
return best ? best[0] : rest[0];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* An element of the board, of `kind` (its class gallery-kanban-<kind>).
|
|
128
|
+
* @template {keyof HTMLElementTagNameMap} K
|
|
129
|
+
* @param {K} tag
|
|
130
|
+
* @param {string} kind
|
|
131
|
+
* @param {string} [text]
|
|
132
|
+
*/
|
|
133
|
+
function made(tag, kind, text) {
|
|
134
|
+
const node = document.createElement(tag);
|
|
135
|
+
node.className = `gallery-kanban-${kind}`;
|
|
136
|
+
if (text !== undefined) node.textContent = text;
|
|
137
|
+
return node;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* A button of an icon and its words for whoever cannot see it.
|
|
142
|
+
* @param {string} kind
|
|
143
|
+
* @param {string} icon
|
|
144
|
+
* @param {string} label
|
|
145
|
+
* @param {string} [text]
|
|
146
|
+
*/
|
|
147
|
+
function iconButton(kind, icon, label, text) {
|
|
148
|
+
const button = made("button", kind);
|
|
149
|
+
button.type = "button";
|
|
150
|
+
button.title = label;
|
|
151
|
+
button.setAttribute("aria-label", label);
|
|
152
|
+
button.innerHTML = icon;
|
|
153
|
+
if (text !== undefined) button.append(made("span", "words", text));
|
|
154
|
+
return button;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* `parent`'s children made `nodes`, what is there already left in place: where only some are new, each
|
|
159
|
+
* standing where the one it replaces stood, those alone are put in (a keystroke in the table changes one
|
|
160
|
+
* card, and the page lays out that much); anything else is the list anew.
|
|
161
|
+
* @param {Element} parent
|
|
162
|
+
* @param {Element[]} nodes
|
|
163
|
+
*/
|
|
164
|
+
function put(parent, nodes) {
|
|
165
|
+
const now = [...parent.children];
|
|
166
|
+
if (now.length === nodes.length) {
|
|
167
|
+
const differs = nodes.map((node, at) => node !== now[at]);
|
|
168
|
+
if (!differs.includes(true)) return;
|
|
169
|
+
if (nodes.every((node, at) => !differs[at] || !node.isConnected)) {
|
|
170
|
+
nodes.forEach((node, at) => { if (differs[at]) parent.replaceChild(node, now[at]); });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
parent.replaceChildren(...nodes);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The chips of a row's links: each anchor of its cells, a document's (one of `row.links`, which name
|
|
179
|
+
* them in the same order, by their words) or the web's.
|
|
180
|
+
* @param {DocRow} row
|
|
181
|
+
* @returns {{ anchor: HTMLAnchorElement, page: DocRow["links"][number] | null }[]}
|
|
182
|
+
*/
|
|
183
|
+
function linksIn(row) {
|
|
184
|
+
let next = 0;
|
|
185
|
+
return [...row.el.querySelectorAll("a[href]")].flatMap((anchor) => {
|
|
186
|
+
if (!(anchor instanceof HTMLAnchorElement)) return [];
|
|
187
|
+
const page = row.links[next] && row.links[next].title === wordsOf(anchor) ? row.links[next] : null;
|
|
188
|
+
if (page) next += 1;
|
|
189
|
+
return [{ anchor, page }];
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
DocKit.component({
|
|
194
|
+
id: "gallery/kanban",
|
|
195
|
+
on: ["source", "data", "editable"],
|
|
196
|
+
mount(host, context) {
|
|
197
|
+
const language = languageOf(document.documentElement);
|
|
198
|
+
const words = WORDS[language];
|
|
199
|
+
const face = made("div", "face");
|
|
200
|
+
const head = made("div", "head");
|
|
201
|
+
const caption = made("span", "caption");
|
|
202
|
+
const gear = iconButton("gear", ICONS.gear, words.settings);
|
|
203
|
+
gear.setAttribute("aria-expanded", "false");
|
|
204
|
+
head.append(caption, gear);
|
|
205
|
+
const strip = made("div", "strip");
|
|
206
|
+
strip.hidden = true;
|
|
207
|
+
const groupLabel = made("label", "setting");
|
|
208
|
+
const groupField = document.createElement("select");
|
|
209
|
+
groupLabel.append(made("span", "setting-name", words.group), groupField);
|
|
210
|
+
strip.append(groupLabel);
|
|
211
|
+
const line = made("p", "line");
|
|
212
|
+
const board = made("div", "groups");
|
|
213
|
+
face.append(head, strip, line, board);
|
|
214
|
+
host.append(face);
|
|
215
|
+
gear.addEventListener("click", () => {
|
|
216
|
+
strip.hidden = !strip.hidden;
|
|
217
|
+
gear.setAttribute("aria-expanded", String(!strip.hidden));
|
|
218
|
+
}, { signal: context.signal });
|
|
219
|
+
|
|
220
|
+
// 分组依据 picked: its settings' group, one undo step (context.editJSON), the order of the groups going
|
|
221
|
+
// with it, as it named the values of the column grouped by before.
|
|
222
|
+
const grouping = DocKit.input(groupField, {
|
|
223
|
+
commit: (value) => void context.editJSON("settings", (draft) => {
|
|
224
|
+
const settings = draft !== null && typeof draft === "object" && !Array.isArray(draft) ? draft : {};
|
|
225
|
+
settings.group = value;
|
|
226
|
+
delete settings.order;
|
|
227
|
+
return settings;
|
|
228
|
+
}),
|
|
229
|
+
signal: context.signal,
|
|
230
|
+
});
|
|
231
|
+
let groupOptions = "";
|
|
232
|
+
|
|
233
|
+
// Words written only where they change: a keystroke in the table changes one card and nothing else.
|
|
234
|
+
const write = (/** @type {HTMLElement} */ node, /** @type {string} */ text) => {
|
|
235
|
+
if (node.textContent !== text) node.textContent = text;
|
|
236
|
+
};
|
|
237
|
+
const say = (/** @type {string | null} */ text) => {
|
|
238
|
+
line.hidden = text === null;
|
|
239
|
+
write(line, text ?? "");
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/** @type {Map<DocRow, HTMLLIElement>} */
|
|
243
|
+
const cards = new Map(); // a row -> its card, while the row is the one context.table() gives
|
|
244
|
+
/** @type {WeakMap<Element, HTMLTableRowElement>} */
|
|
245
|
+
const rowOf = new WeakMap(); // a card -> its row's element
|
|
246
|
+
/** @type {Map<string, { section: HTMLElement, name: HTMLElement, count: HTMLElement, list: HTMLOListElement }>} */
|
|
247
|
+
const groups = new Map(); // a group's value -> its section
|
|
248
|
+
/** @type {{ column: string, value: string, known: Set<HTMLTableRowElement> } | null} */
|
|
249
|
+
let adding = null; // a row asked for by 新建, whose card opens its title to type in once drawn
|
|
250
|
+
let column = ""; // the column grouped by, as drawn last
|
|
251
|
+
let editing = false; // a card's title is being typed in
|
|
252
|
+
/** @type {{ card: HTMLElement, close(): void } | null} */
|
|
253
|
+
let field = null; // the title typed in, and how it ends
|
|
254
|
+
|
|
255
|
+
// The row a card stands for, as the table reads now; null once it is gone.
|
|
256
|
+
const rowNow = (/** @type {DocTableView} */ table, /** @type {Element | null} */ card) => {
|
|
257
|
+
const element = card ? rowOf.get(card) : undefined;
|
|
258
|
+
return element ? table.rows.find((row) => row.el === element) ?? null : null;
|
|
259
|
+
};
|
|
260
|
+
// The table, where it takes a change now.
|
|
261
|
+
const writable = () => {
|
|
262
|
+
const table = context.table();
|
|
263
|
+
return table && table.canEdit() ? table : null;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
const cardOf = (/** @type {DocRow} */ row, /** @type {DocTableView} */ table) => {
|
|
267
|
+
const kept = cards.get(row);
|
|
268
|
+
if (kept) return kept;
|
|
269
|
+
const card = made("li", "card");
|
|
270
|
+
const hold = made("div", "hold");
|
|
271
|
+
const title = wordsOf(row.el.cells[0]);
|
|
272
|
+
const titled = made("span", "title", title || words.untitled);
|
|
273
|
+
titled.classList.toggle("gallery-kanban-untitled", !title);
|
|
274
|
+
hold.append(titled);
|
|
275
|
+
const grouped = table.columns.lastIndexOf(column);
|
|
276
|
+
const props = [...row.el.cells].flatMap((cell, at) => {
|
|
277
|
+
const said = wordsOf(cell);
|
|
278
|
+
if (at === 0 || at === grouped || !said || at >= table.columns.length) return [];
|
|
279
|
+
const prop = made("span", "prop", said);
|
|
280
|
+
prop.title = table.columns[at];
|
|
281
|
+
return [prop];
|
|
282
|
+
});
|
|
283
|
+
if (props.length > 0) {
|
|
284
|
+
const list = made("span", "props");
|
|
285
|
+
list.append(...props);
|
|
286
|
+
hold.append(list);
|
|
287
|
+
}
|
|
288
|
+
card.append(hold);
|
|
289
|
+
const links = linksIn(row);
|
|
290
|
+
if (links.length > 0) {
|
|
291
|
+
const chips = made("div", "links");
|
|
292
|
+
for (const { anchor, page } of links) {
|
|
293
|
+
const chip = made("a", "link");
|
|
294
|
+
chip.href = anchor.getAttribute("href") ?? "";
|
|
295
|
+
chip.innerHTML = page ? ICONS.page : ICONS.web;
|
|
296
|
+
const said = wordsOf(anchor);
|
|
297
|
+
chip.append(made("span", "words", said && said !== title ? said : words.open));
|
|
298
|
+
chip.title = said;
|
|
299
|
+
if (page) chip.dataset.page = page.slug;
|
|
300
|
+
else {
|
|
301
|
+
chip.target = "_blank";
|
|
302
|
+
chip.rel = "noopener noreferrer";
|
|
303
|
+
}
|
|
304
|
+
// A document's link opens it where Gallery shows the page; in an exported file it is a link.
|
|
305
|
+
if (page) chip.addEventListener("click", (event) => {
|
|
306
|
+
if (context.place !== "document" || !context.workspace) return;
|
|
307
|
+
event.preventDefault();
|
|
308
|
+
context.workspace.open({ slug: page.slug, block: page.block });
|
|
309
|
+
});
|
|
310
|
+
chips.append(chip);
|
|
311
|
+
}
|
|
312
|
+
card.append(chips);
|
|
313
|
+
}
|
|
314
|
+
const tools = made("div", "tools");
|
|
315
|
+
tools.append(iconButton("rename", ICONS.rename, words.rename), iconButton("remove", ICONS.remove, words.remove));
|
|
316
|
+
card.append(tools);
|
|
317
|
+
rowOf.set(card, row.el);
|
|
318
|
+
cards.set(row, card);
|
|
319
|
+
return card;
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const groupOf = (/** @type {string} */ value) => {
|
|
323
|
+
const kept = groups.get(value);
|
|
324
|
+
if (kept) return kept;
|
|
325
|
+
const section = made("section", "group");
|
|
326
|
+
section.dataset.value = value;
|
|
327
|
+
const top = made("div", "group-head");
|
|
328
|
+
const name = made("span", "name", value || words.none);
|
|
329
|
+
const count = made("span", "count");
|
|
330
|
+
top.append(name, count);
|
|
331
|
+
const list = made("ol", "cards");
|
|
332
|
+
const add = iconButton("add", ICONS.add, words.add, words.add);
|
|
333
|
+
section.append(top, list, add);
|
|
334
|
+
const group = { section, name, count, list };
|
|
335
|
+
groups.set(value, group);
|
|
336
|
+
return group;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const drawNow = () => {
|
|
340
|
+
const table = context.table();
|
|
341
|
+
const settings = askedOf(context.readJSON("settings"));
|
|
342
|
+
const canWrite = Boolean(table && table.canEdit());
|
|
343
|
+
face.toggleAttribute("data-writes", context.canEdit());
|
|
344
|
+
board.toggleAttribute("data-writes", canWrite);
|
|
345
|
+
head.hidden = !table;
|
|
346
|
+
if (!table) {
|
|
347
|
+
cards.clear();
|
|
348
|
+
groups.clear();
|
|
349
|
+
write(caption, "");
|
|
350
|
+
board.replaceChildren();
|
|
351
|
+
groupField.replaceChildren();
|
|
352
|
+
groupOptions = "";
|
|
353
|
+
return say(host.hasAttribute("data-doc-from") ? words.unread : words.unbound);
|
|
354
|
+
}
|
|
355
|
+
const options = table.columns.length > 1 ? table.columns.slice(1) : [...table.columns];
|
|
356
|
+
const signed = JSON.stringify(options);
|
|
357
|
+
if (signed !== groupOptions) {
|
|
358
|
+
groupOptions = signed;
|
|
359
|
+
groupField.replaceChildren(...options.map((name) => new Option(name, name)));
|
|
360
|
+
}
|
|
361
|
+
const wanted = settings.group || groupColumnOf(table);
|
|
362
|
+
if (wanted === null || !table.columns.includes(wanted)) {
|
|
363
|
+
cards.clear();
|
|
364
|
+
groups.clear();
|
|
365
|
+
write(caption, "");
|
|
366
|
+
board.replaceChildren();
|
|
367
|
+
grouping.set(wanted ?? "");
|
|
368
|
+
return say(wanted === null ? words.empty : words.missing(wanted));
|
|
369
|
+
}
|
|
370
|
+
grouping.set(wanted);
|
|
371
|
+
if (wanted !== column) {
|
|
372
|
+
column = wanted;
|
|
373
|
+
cards.clear(); // what a card shows under its title leaves the grouping column out
|
|
374
|
+
}
|
|
375
|
+
write(caption, `${words.by(column)} · ${words.cards(table.rows.length)}`);
|
|
376
|
+
say(context.canEdit() && !canWrite ? words.readOnly : table.rows.length === 0 ? words.empty : null);
|
|
377
|
+
// The groups: those the settings list, then the rest as the rows say them, the empty value last.
|
|
378
|
+
/** @type {Map<string, DocRow[]>} */
|
|
379
|
+
const byValue = new Map(settings.order.map((value) => [value, []]));
|
|
380
|
+
for (const row of table.rows) {
|
|
381
|
+
const value = keyOf(row, column);
|
|
382
|
+
const rows = byValue.get(value);
|
|
383
|
+
if (rows) rows.push(row);
|
|
384
|
+
else byValue.set(value, [row]);
|
|
385
|
+
}
|
|
386
|
+
const empty = byValue.get("");
|
|
387
|
+
if (empty && !settings.order.includes("")) {
|
|
388
|
+
byValue.delete("");
|
|
389
|
+
byValue.set("", empty);
|
|
390
|
+
}
|
|
391
|
+
const live = new Set(table.rows);
|
|
392
|
+
for (const row of [...cards.keys()]) if (!live.has(row)) cards.delete(row);
|
|
393
|
+
put(board, [...byValue].map(([value, rows]) => {
|
|
394
|
+
const group = groupOf(value);
|
|
395
|
+
if (group.count.textContent !== String(rows.length)) group.count.textContent = String(rows.length);
|
|
396
|
+
put(group.list, rows.map((row) => cardOf(row, table)));
|
|
397
|
+
return group.section;
|
|
398
|
+
}));
|
|
399
|
+
for (const value of [...groups.keys()]) if (!byValue.has(value)) groups.delete(value);
|
|
400
|
+
// A card typed in that a change of its row (someone else's) took off: its field goes with it.
|
|
401
|
+
if (field && !field.card.isConnected) field.close();
|
|
402
|
+
// A row 新建 asked for, drawn now: its title open to type in.
|
|
403
|
+
if (adding) {
|
|
404
|
+
const asked = adding;
|
|
405
|
+
const fresh = table.rows.find((row) => !asked.known.has(row.el) && keyOf(row, asked.column) === asked.value);
|
|
406
|
+
if (fresh) {
|
|
407
|
+
adding = null;
|
|
408
|
+
const card = cards.get(fresh);
|
|
409
|
+
if (card) rename(card);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const draw = () => context.frame(() => {
|
|
414
|
+
if (dragging.dragging && !held?.isConnected) dragging.cancel();
|
|
415
|
+
drawNow();
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// A card's title typed in: its first cell set (one intent) on Enter or as the field is left;
|
|
419
|
+
// Escape leaves it as it was.
|
|
420
|
+
function rename(/** @type {HTMLElement} */ card) {
|
|
421
|
+
const table = writable();
|
|
422
|
+
const row = table ? rowNow(table, card) : null;
|
|
423
|
+
if (!table || !row || editing) return;
|
|
424
|
+
editing = true;
|
|
425
|
+
const ends = new AbortController();
|
|
426
|
+
const input = made("input", "field");
|
|
427
|
+
input.type = "text";
|
|
428
|
+
input.value = wordsOf(row.el.cells[0]);
|
|
429
|
+
input.setAttribute("aria-label", words.rename);
|
|
430
|
+
card.setAttribute("data-editing", "");
|
|
431
|
+
card.prepend(input);
|
|
432
|
+
const close = () => {
|
|
433
|
+
if (!editing) return;
|
|
434
|
+
editing = false;
|
|
435
|
+
field = null;
|
|
436
|
+
ends.abort();
|
|
437
|
+
input.remove();
|
|
438
|
+
card.removeAttribute("data-editing");
|
|
439
|
+
};
|
|
440
|
+
field = { card, close };
|
|
441
|
+
DocKit.input(input, {
|
|
442
|
+
commit(value) {
|
|
443
|
+
const now = writable();
|
|
444
|
+
const target = now ? rowNow(now, card) : null;
|
|
445
|
+
if (now && target && now.columns.length > 0) now.set(target, now.columns[0], value.trim());
|
|
446
|
+
close();
|
|
447
|
+
},
|
|
448
|
+
signal: ends.signal,
|
|
449
|
+
});
|
|
450
|
+
input.addEventListener("blur", close, { signal: ends.signal });
|
|
451
|
+
context.signal.addEventListener("abort", close, { once: true, signal: ends.signal });
|
|
452
|
+
input.focus();
|
|
453
|
+
input.select();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
board.addEventListener("click", (event) => {
|
|
457
|
+
const target = event.target instanceof Element ? event.target : null;
|
|
458
|
+
const button = target?.closest("button");
|
|
459
|
+
if (!button || !board.contains(button)) return;
|
|
460
|
+
const table = writable();
|
|
461
|
+
if (!table) return;
|
|
462
|
+
if (button.classList.contains("gallery-kanban-add")) {
|
|
463
|
+
const value = button.closest(".gallery-kanban-group")?.getAttribute("data-value") ?? "";
|
|
464
|
+
const mates = table.rows.filter((row) => keyOf(row, column) === value);
|
|
465
|
+
const title = table.columns[0];
|
|
466
|
+
adding = { column, value, known: new Set(table.rows.map((row) => row.el)) };
|
|
467
|
+
const values = title === column ? { [column]: value } : { [title]: "", [column]: value };
|
|
468
|
+
if (!table.add(values, mates.length > 0 ? { after: mates[mates.length - 1] } : {})) adding = null;
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const card = button.closest(".gallery-kanban-card");
|
|
472
|
+
if (!(card instanceof HTMLElement)) return;
|
|
473
|
+
if (button.classList.contains("gallery-kanban-rename")) rename(card);
|
|
474
|
+
else if (button.classList.contains("gallery-kanban-remove")) {
|
|
475
|
+
const row = rowNow(table, card);
|
|
476
|
+
if (row) table.remove(row);
|
|
477
|
+
}
|
|
478
|
+
}, { signal: context.signal });
|
|
479
|
+
|
|
480
|
+
// A card dragged (DocKit.drag, from its words: its links and buttons are presses): where it would go
|
|
481
|
+
// is marked as the pointer moves, and on its release over a group the table is asked once. Where a
|
|
482
|
+
// card dropped at (x, y) goes: nowhere off the groups, past a margin around them; else the group under
|
|
483
|
+
// it, or the nearest, before the card shown in it whose middle is below the pointer, else at its end.
|
|
484
|
+
const marker = made("li", "drop");
|
|
485
|
+
/** @type {HTMLElement | null} */
|
|
486
|
+
let held = null;
|
|
487
|
+
/** @param {number} x @param {number} y @param {HTMLElement} item */
|
|
488
|
+
const spotAt = (x, y, item) => {
|
|
489
|
+
held = item;
|
|
490
|
+
const area = board.getBoundingClientRect();
|
|
491
|
+
if (x < area.left - MARGIN || x > area.right + MARGIN || y < area.top - MARGIN || y > area.bottom + MARGIN) return null;
|
|
492
|
+
/** @type {{ section: HTMLElement, list: HTMLOListElement } | null} */
|
|
493
|
+
let group = null;
|
|
494
|
+
let nearest = Infinity;
|
|
495
|
+
for (const each of groups.values()) {
|
|
496
|
+
if (!each.section.isConnected) continue;
|
|
497
|
+
const { left, right } = each.section.getBoundingClientRect();
|
|
498
|
+
const far = x < left ? left - x : x > right ? x - right : 0;
|
|
499
|
+
if (far < nearest) [group, nearest] = [each, far];
|
|
500
|
+
}
|
|
501
|
+
if (!group) return null;
|
|
502
|
+
const next = [...group.list.children].find((card) => {
|
|
503
|
+
if (card === item || card === marker) return false;
|
|
504
|
+
const { top, height } = card.getBoundingClientRect();
|
|
505
|
+
return y < top + height / 2;
|
|
506
|
+
}) ?? null;
|
|
507
|
+
return { into: group.list, before: next, value: group.section.getAttribute("data-value") ?? "", card: next };
|
|
508
|
+
};
|
|
509
|
+
const dragging = DocKit.drag(board, {
|
|
510
|
+
items: ".gallery-kanban-card",
|
|
511
|
+
handle: ".gallery-kanban-hold",
|
|
512
|
+
enabled: () => !editing && writable() !== null,
|
|
513
|
+
marker,
|
|
514
|
+
signal: context.signal,
|
|
515
|
+
over: spotAt,
|
|
516
|
+
drop(item, { value, card }) {
|
|
517
|
+
held = null;
|
|
518
|
+
const table = writable();
|
|
519
|
+
const row = table ? rowNow(table, item) : null;
|
|
520
|
+
if (!table || !row || !table.columns.includes(column)) return;
|
|
521
|
+
const before = card ? rowNow(table, card) : null;
|
|
522
|
+
const mates = table.rows.filter((other) => other !== row && keyOf(other, column) === value);
|
|
523
|
+
const same = keyOf(row, column) === value;
|
|
524
|
+
const values = same ? undefined : { [column]: value };
|
|
525
|
+
if (same) {
|
|
526
|
+
// Where it was: before the card after it in its group, or at the group's end as its last.
|
|
527
|
+
const own = table.rows.filter((other) => keyOf(other, column) === value);
|
|
528
|
+
const at = own.indexOf(row);
|
|
529
|
+
if (before ? own[at + 1] === before : at === own.length - 1) return;
|
|
530
|
+
}
|
|
531
|
+
if (before) table.move(row, { before, values });
|
|
532
|
+
else if (mates.length > 0) table.move(row, { after: mates[mates.length - 1], values });
|
|
533
|
+
else if (!same) table.set(row, column, value);
|
|
534
|
+
},
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
drawNow();
|
|
538
|
+
return { update: draw };
|
|
539
|
+
},
|
|
540
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 120"><rect width="240" height="120" rx="8" fill="#f2f4f7"/><rect x="14" y="14" width="66" height="92" rx="7" fill="#e8ebf0"/><rect x="87" y="14" width="66" height="92" rx="7" fill="#e8ebf0"/><rect x="160" y="14" width="66" height="92" rx="7" fill="#e8ebf0"/><rect x="20" y="20" width="30" height="7" rx="3.5" fill="#98a2b3"/><rect x="93" y="20" width="36" height="7" rx="3.5" fill="#2678d8"/><rect x="166" y="20" width="32" height="7" rx="3.5" fill="#2f9e6e"/><rect x="20" y="34" width="54" height="24" rx="5" fill="#ffffff" stroke="#d0d5dd"/><rect x="26" y="41" width="34" height="5" rx="2.5" fill="#475467"/><rect x="26" y="49" width="20" height="4" rx="2" fill="#98a2b3"/><rect x="20" y="63" width="54" height="24" rx="5" fill="#ffffff" stroke="#d0d5dd"/><rect x="26" y="70" width="28" height="5" rx="2.5" fill="#475467"/><rect x="26" y="78" width="22" height="4" rx="2" fill="#98a2b3"/><rect x="93" y="34" width="54" height="24" rx="5" fill="#ffffff" stroke="#d0d5dd"/><rect x="99" y="41" width="38" height="5" rx="2.5" fill="#475467"/><rect x="99" y="49" width="18" height="4" rx="2" fill="#98a2b3"/><rect x="166" y="34" width="54" height="24" rx="5" fill="#ffffff" stroke="#d0d5dd"/><rect x="172" y="41" width="30" height="5" rx="2.5" fill="#475467"/><rect x="172" y="49" width="24" height="4" rx="2" fill="#98a2b3"/><rect x="166" y="63" width="54" height="24" rx="5" fill="#ffffff" stroke="#d0d5dd"/><rect x="172" y="70" width="36" height="5" rx="2.5" fill="#475467"/><rect x="172" y="78" width="16" height="4" rx="2" fill="#98a2b3"/></svg>
|