@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
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { OUTER, UNIT, blocksIn, boxKind, heldIn, newHost, newTail, placeBefore, unitElement, withLeads } from "../core.mjs";
|
|
2
2
|
import { containerType } from "../convert.mjs";
|
|
3
3
|
import { begin, done, made } from "../made.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { caretBeside } from "../beside.mjs";
|
|
5
5
|
import { caretAt, nearestOnLine, placeCaret, selectAt } from "../caret.mjs";
|
|
6
6
|
import { sectionOps } from "../page-objects.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { endOf, hoverAt, innerBox, measure } from "../geometry.mjs";
|
|
8
8
|
import { BOXED, HOLDS_ONE, accepts } from "../../components/registry.mjs";
|
|
9
9
|
import { DIALOG } from "../../components/kit.mjs";
|
|
10
10
|
|
|
@@ -18,9 +18,9 @@ import { DIALOG } from "../../components/kit.mjs";
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* struct(parents, touched, mutate): the editor's undoable structural change (history.mjs). blocks():
|
|
21
|
-
* the block tools (blocks.mjs).
|
|
21
|
+
* the block tools (blocks.mjs). after: the caret after a block (after/).
|
|
22
22
|
*/
|
|
23
|
-
export function createInsert({ struct, blocks }) {
|
|
23
|
+
export function createInsert({ struct, blocks, after }) {
|
|
24
24
|
// An empty paragraph right before the block of a text block, the caret staying where it is.
|
|
25
25
|
// Returns whether one could go there.
|
|
26
26
|
function paragraphBefore(host) {
|
|
@@ -54,10 +54,10 @@ export function createInsert({ struct, blocks }) {
|
|
|
54
54
|
// (geometry.mjs endOf). Under the last block of a box whose end is its own padding (endIsPadding: a
|
|
55
55
|
// highlight block, a callout, a disclosure's content; the user's, 2026-11-06, as notion-lite's click-blank.js
|
|
56
56
|
// makes a block only below the page and in a column) it is a gap like any other, below. Right of
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
// paragraph after it;
|
|
60
|
-
//
|
|
57
|
+
// a boxed block (a code block, a callout, a file…: not text) or a row of columns, at its height
|
|
58
|
+
// (boxedBeside), the caret after it, at its bottom right (after/: Backspace deletes it, Enter or a
|
|
59
|
+
// key makes a paragraph after it; the user's, 2026-11-09: a click there selected it before).
|
|
60
|
+
// Elsewhere beside text, the caret goes into the text block on that line (the nearest of those
|
|
61
61
|
// side by side), where the line is nearest the click (Notion's way); in the gap between two
|
|
62
62
|
// blocks, or beside a block of no text, into the nearer of the blocks around it that is text, in the
|
|
63
63
|
// innermost box at that height (boxBeside: the press may be on the page's margin, the block in a
|
|
@@ -82,7 +82,7 @@ export function createInsert({ struct, blocks }) {
|
|
|
82
82
|
if (end) return newParagraph(end.box, end.after);
|
|
83
83
|
const top = y + scrollY;
|
|
84
84
|
const beside = boxedBeside(main, x, y, target);
|
|
85
|
-
if (beside) return
|
|
85
|
+
if (beside) return after.place(beside);
|
|
86
86
|
const host = hoverAt(measure(main, { top, bottom: top }), x + scrollX, top, { reach: Infinity, skip: (unit) => !unit.text });
|
|
87
87
|
if (host) return caretNear(host, x, y);
|
|
88
88
|
for (let around = boxBeside(box, x, y); around; around = around === box ? null : around.parentElement.closest("[data-ge-box]")) {
|
|
@@ -157,26 +157,24 @@ export function createInsert({ struct, blocks }) {
|
|
|
157
157
|
const texts = [unit, ...unit.querySelectorAll("[data-ge-block], [data-ge-new]")].filter((node) => node.isContentEditable && node.getClientRects().length > 0 && !node.closest("details:not([open]) > :not(summary)"));
|
|
158
158
|
return (last ? texts.at(-1) : texts[0]) ?? null;
|
|
159
159
|
}
|
|
160
|
-
// A boxed block or a row of columns at height `y` with (x, y) right of
|
|
161
|
-
//
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
// the gap's (columns/: it drags, a click alone changes nothing), or past the row, which is selected.
|
|
160
|
+
// A boxed block or a row of columns at height `y` with (x, y) right of it: between its right edge
|
|
161
|
+
// and the text area's it stands in (a table, a picture narrower than its column: the user's,
|
|
162
|
+
// 2026-11-09, the caret after it where a click there once selected it, 2026-11-07, and later went to
|
|
163
|
+
// the nearest text), in the padding of the box it stands in (a highlight block's, a callout's) or in the
|
|
164
|
+
// page's margin; or null. Never in another text area (the blank box `target` the press was on holds the
|
|
165
|
+
// block: a column further right is no place beside one in the column left of it). The innermost,
|
|
166
|
+
// but never a block inside a row of columns the click is to the right of too (the caret goes after
|
|
167
|
+
// the row): past a column's edge is the gap to the next column, whose press is the gap's (columns/:
|
|
168
|
+
// it drags, a click alone changes nothing), or past the row.
|
|
170
169
|
function boxedBeside(main, x, y, target) {
|
|
171
170
|
let found = null;
|
|
172
171
|
const right = (unit) => {
|
|
173
172
|
const rect = unit.getBoundingClientRect();
|
|
174
173
|
if (y < rect.top || y > rect.bottom || (target?.contains && !target.contains(unit))) return false;
|
|
175
|
-
|
|
176
|
-
return x > Math.max(rect.right, contentOf(box.getBoundingClientRect(), getComputedStyle(box)).right);
|
|
174
|
+
return x > rect.right;
|
|
177
175
|
};
|
|
178
176
|
for (const unit of main.querySelectorAll(`[data-ge-unit-kind]`)) {
|
|
179
|
-
if (!
|
|
177
|
+
if (!caretBeside(unit) || !unit.parentElement?.hasAttribute("data-ge-box") || unit.parentElement.closest("details:not([open])")) continue;
|
|
180
178
|
if (!right(unit)) continue;
|
|
181
179
|
const row = unit.parentElement.closest('[data-ge-unit-kind="columns"]');
|
|
182
180
|
if (row && main.contains(row) && right(row)) continue;
|
|
@@ -9,7 +9,7 @@ import { placeBox } from "../placement.mjs";
|
|
|
9
9
|
import { tooltip } from "../tooltip.mjs";
|
|
10
10
|
import { addStyle, copyAddress, element, fadeIn, mount, swallowNext } from "../ui.mjs";
|
|
11
11
|
import { typedHref } from "./address.mjs";
|
|
12
|
-
import { findPages, heldList, pageRows, placeIn, readPages, titleIn, trashed } from "./pages.mjs";
|
|
12
|
+
import { findPages, heldList, pageRows, placeIn, readPages, titleIn, trashed, webLinkIn } from "./pages.mjs";
|
|
13
13
|
import { DIALOG_TRIGGER } from "../../components/dialog/index.mjs";
|
|
14
14
|
import { DIALOG_ICON } from "../../components/icons.mjs";
|
|
15
15
|
import { VIEWS, closeOffer, closeViews, hasViews, hrefOf, isPageChip, offerViews, openViews, pageChip, refetch, viewNodes, viewOf, viewsHold } from "./views.mjs";
|
|
@@ -668,12 +668,14 @@ async function listedPage(address) {
|
|
|
668
668
|
|
|
669
669
|
/**
|
|
670
670
|
* Whether a page alone in a tab may leave for a workbench's `hash`, which only the list reads: not for
|
|
671
|
-
* one that names no document, said as the workbench says it, the page staying.
|
|
671
|
+
* one that names no document, said as the workbench says it, the page staying. A web link of the sidebar,
|
|
672
|
+
* or an entry of an extension's column with an address (#~<id>/<entry id>), is a place the workbench
|
|
673
|
+
* opens (in its content area), so it goes there. With no answer it goes,
|
|
672
674
|
* for the workbench to say.
|
|
673
675
|
*/
|
|
674
676
|
export async function leadsToPage(hash) {
|
|
675
677
|
const list = await readPages(use.own());
|
|
676
|
-
if (!list || placeIn(list, `#${hash}`)) return true;
|
|
678
|
+
if (!list || placeIn(list, `#${hash}`) || webLinkIn(list, hash)) return true;
|
|
677
679
|
use.say(inTrash(list.trash, hash) ? t("这个页面已删除。") : t("没有找到这个页面。"));
|
|
678
680
|
return false;
|
|
679
681
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { iconUrl } from "../../../shared/emoji/icon-value.mjs";
|
|
2
2
|
import { escapeAttribute } from "../../../shared/escape.mjs";
|
|
3
3
|
import { addressOn, decoded, hashAddress } from "../../../shared/page-address.mjs";
|
|
4
|
+
import { DOCS, isTop, topOf } from "../../../shared/outline-shape.mjs";
|
|
5
|
+
import { entryOfKey } from "../../../shared/extension-sidebar.mjs";
|
|
4
6
|
import { inTrash, namedLinks, pageLink, pageLinks } from "../../../shared/page-links.mjs";
|
|
5
7
|
import { PAGE_ICON } from "../../components/icons.mjs";
|
|
8
|
+
import { t } from "../../../shared/i18n/index.mjs";
|
|
6
9
|
|
|
7
10
|
// The documents of the workspace, as a link's card, a page block's box and "@" look for them
|
|
8
11
|
// (docs/editor.md, "Links"): one search for the three. The list is read once for each opening from
|
|
9
12
|
// what the workbench reads itself (GET /__gallery/workspace/outline: no route of its own, nothing
|
|
10
|
-
// pushed), in the sidebar's order,
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
+
// pushed), in the sidebar's order, column after column (栏: shared/outline-shape.mjs), each document with
|
|
14
|
+
// the title of the one above it in the sidebar; 写作偏好 is no page to link to, nor is a web link of the
|
|
15
|
+
// sidebar (kind "link": no file of its own to link to; the documents under one are pages all the same) or a
|
|
16
|
+
// draft of another workspace (kind "draft": its file is that workspace's, which no relative link reaches),
|
|
17
|
+
// and this page has the title it shows now, not the one last saved. A list that cannot be read is no
|
|
18
|
+
// results, and the field goes on taking addresses.
|
|
13
19
|
//
|
|
14
20
|
// What a copy writes is an address by a page's link, and a copy cannot wait for an answer: the
|
|
15
21
|
// clipboard takes a write only in the click itself. So the page holds the list ready, the last one
|
|
@@ -31,8 +37,8 @@ let shown = () => null; // this page, as readPages takes it
|
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
39
|
* The workspace's documents: { pages: [{ slug, title, icon, parent }] (`parent`: the title of the one
|
|
34
|
-
* it is under, or null), links: their links (shared/page-links.mjs), trash: what the trash holds }, or
|
|
35
|
-
* null when the list cannot be read. `own`: this page, { slug, title } as it shows it.
|
|
40
|
+
* it is under, or null), links: their links (shared/page-links.mjs), trash: what the trash holds but web links }, or
|
|
41
|
+
* null when the list cannot be read (`webs`: the links of the sidebar's web links, which are no pages). `own`: this page, { slug, title } as it shows it.
|
|
36
42
|
*/
|
|
37
43
|
export async function readPages(own = null) {
|
|
38
44
|
const listed = await fetch(OUTLINE).then((answer) => answer.json()).catch(() => null);
|
|
@@ -41,13 +47,18 @@ export async function readPages(own = null) {
|
|
|
41
47
|
const pages = [];
|
|
42
48
|
const walk = (parent) => {
|
|
43
49
|
for (const slug of listed.outline?.children?.[parent] ?? []) {
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
const report = listed.reports[slug];
|
|
51
|
+
if (!report || report.instructions) continue;
|
|
52
|
+
// An untitled document is named 未命名文档, as the workbench names it (its link's words: its page id alone).
|
|
53
|
+
if (report.kind !== "link" && report.kind !== "draft") pages.push({ slug, title: titleOf(slug) || t("未命名文档"), icon: report.icon ?? null, parent: isTop(parent) ? null : titleOf(parent) || t("未命名文档") });
|
|
46
54
|
walk(slug);
|
|
47
55
|
}
|
|
48
56
|
};
|
|
49
|
-
walk(
|
|
50
|
-
|
|
57
|
+
for (const { id } of listed.outline?.groups ?? [{ id: DOCS }]) walk(topOf(id));
|
|
58
|
+
// The sidebar's web links, by their links as a workbench's hash holds them: no page to link to, but an address the workbench opens.
|
|
59
|
+
const web = Object.values(listed.reports).filter((report) => report.kind === "link").map(({ slug, title }) => ({ slug, title }));
|
|
60
|
+
// And the extensions' columns (their entries: an address #~<id>/<entry id> the workbench opens too).
|
|
61
|
+
held = { pages, links: pageLinks(pages.map(({ slug }) => ({ slug, title: titleOf(slug) }))), webs: pageLinks(web), extensions: listed.extensions ?? [], trash: (listed.trash ?? []).filter(({ kind }) => kind !== "link") };
|
|
51
62
|
return held;
|
|
52
63
|
}
|
|
53
64
|
|
|
@@ -118,6 +129,13 @@ export function placeIn(list, text) {
|
|
|
118
129
|
return page ? { ...page, block: place.block } : null;
|
|
119
130
|
}
|
|
120
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Whether workbench hash `hash` (no #) names a web link of the sidebar, or an entry of an extension's
|
|
134
|
+
* column that has an address (#~<id>/<entry id>): the workbench opens it in its content area, though it
|
|
135
|
+
* is no page to link to.
|
|
136
|
+
*/
|
|
137
|
+
export const webLinkIn = (list, hash) => Boolean(hashAddress(decoded(hash), list.webs) || entryOfKey(list.extensions, decoded(hash))?.url);
|
|
138
|
+
|
|
121
139
|
/** The title of the page `text` is an address of, of `list` or of its trash, or null: what stands for a link to it where its address would be a folder's. */
|
|
122
140
|
export function titleIn(list, text) {
|
|
123
141
|
const binned = addressOn(text, pageLinks(list.trash), globalThis.location?.origin)?.slug;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
// What every popup of the editor is painted with, written once: Notion's neutral palette, its blue
|
|
2
2
|
// and its two shadows, light and dark by light-dark() (the page's color-scheme decides). A sheet of
|
|
3
|
-
// `:root` custom properties, put in every document the editor draws in (ui.mjs addStyleTo), so a
|
|
3
|
+
// `:root` custom properties and the one button look (BUTTONS), put in every document the editor draws in (ui.mjs addStyleTo), so a
|
|
4
4
|
// menu, a card, a bar, a notice reads them wherever it stands and none declares a palette of its
|
|
5
5
|
// own. Values are Notion's own as notion-lite carries them (view/theme/notion-vars.css), which this
|
|
6
6
|
// editor follows; the page's content colors (--doc-*, the kit's tokens.css) are another matter.
|
|
7
7
|
//
|
|
8
8
|
// The blue is two tokens because notion-lite has two, for two jobs: --ge-accent (its
|
|
9
|
-
// --c-bluBacAccPri: a
|
|
10
|
-
// and --c-inpBluFocRin: the ring round a focused field).
|
|
9
|
+
// --c-bluBacAccPri: a switch, a chosen icon, a table's tools, the bars that mark a place) and
|
|
10
|
+
// --ge-focus (its --c-butBluFocRin and --c-inpBluFocRin: the ring round a focused field). A button is
|
|
11
|
+
// neither: the one button look is BUTTONS below, whose primary is a pale blue (--ge-btn-primary*), the
|
|
12
|
+
// workbench's, never the solid --ge-accent.
|
|
11
13
|
//
|
|
12
14
|
// Two shadows, because Notion has two surfaces: --ge-shadow, a card standing over the text (the
|
|
13
15
|
// format bar, the formula and link cards, the conflicts, a notice), and --ge-shadow-pop, a menu
|
|
@@ -15,6 +17,38 @@
|
|
|
15
17
|
// emoji-picker/support.mjs keeps notion-lite's --c-* variables only for the media menu and the image's
|
|
16
18
|
// alignment bar.
|
|
17
19
|
|
|
20
|
+
/**
|
|
21
|
+
* The one look of a button the editor draws on a page (the Agent changes' bar, the conflict card and the lost
|
|
22
|
+
* texts' panel, the crop window, a list's number, the icon picker's upload, the media menu): rules in the
|
|
23
|
+
* palette's sheet, so that every document the editor draws in has them from the first paint and no style
|
|
24
|
+
* repeats them. `.ge-btn` is a text button (ui.mjs textButton): no line and no fill, a gray under the
|
|
25
|
+
* pointer and while the keys are on it, a deeper one pressed; `data-primary` the pale blue (add, confirm,
|
|
26
|
+
* save), with `data-danger` the pale red (a delete); `data-quiet` a small one for looking, not deciding
|
|
27
|
+
* (收起, 定位). `.disabled` and `aria-disabled` are how a button made of a div says it cannot be pressed.
|
|
28
|
+
* `.ge-icon-btn` is the look of an icon button standing alone (a 批注's marker and its delete): no fill under
|
|
29
|
+
* the pointer (the icon goes darker), a gray only while it is pressed. The tools of a bar (the format bar's,
|
|
30
|
+
* the link card's) and a menu's rows are gray under the pointer, as Notion's are. Text fields are not
|
|
31
|
+
* buttons: they keep their thin outline.
|
|
32
|
+
*/
|
|
33
|
+
const OFF = ":disabled, .disabled, [aria-disabled=\"true\"]";
|
|
34
|
+
export const BUTTONS = `
|
|
35
|
+
.ge-btn { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; height: 28px; margin: 0; padding: 0 10px; border: 0; border-radius: 6px; box-shadow: none; background: transparent; color: var(--ge-tx); font: inherit; font-weight: 500; line-height: 1; white-space: nowrap; cursor: pointer; user-select: none; transition: background 20ms ease-in; }
|
|
36
|
+
.ge-btn:is(:hover, :focus-visible):not(${OFF}) { outline: none; background: var(--ge-hover); }
|
|
37
|
+
.ge-btn:active:not(${OFF}) { background: var(--ge-press); }
|
|
38
|
+
.ge-btn[data-primary] { background: var(--ge-btn-primary); color: var(--ge-btn-primary-text); }
|
|
39
|
+
.ge-btn[data-primary]:is(:hover, :focus-visible):not(${OFF}) { background: var(--ge-btn-primary-hover); }
|
|
40
|
+
.ge-btn[data-primary]:active:not(${OFF}) { background: var(--ge-btn-primary-press); }
|
|
41
|
+
.ge-btn[data-primary][data-danger] { background: var(--ge-btn-danger); color: var(--ge-btn-danger-text); }
|
|
42
|
+
.ge-btn[data-primary][data-danger]:is(:hover, :focus-visible):not(${OFF}) { background: var(--ge-btn-danger-hover); }
|
|
43
|
+
.ge-btn[data-primary][data-danger]:active:not(${OFF}) { background: var(--ge-btn-danger-press); }
|
|
44
|
+
.ge-btn[data-quiet] { height: 24px; padding: 0 6px; color: var(--ge-tx2); font-weight: 400; }
|
|
45
|
+
.ge-btn[data-quiet]:is(:hover, :focus-visible):not(${OFF}) { color: var(--ge-tx); }
|
|
46
|
+
.ge-btn:is(${OFF}) { opacity: .45; cursor: default; }
|
|
47
|
+
.ge-icon-btn { border: 0; box-shadow: none; background: transparent; cursor: pointer; transition: background 20ms ease-in, color 20ms ease-in; }
|
|
48
|
+
.ge-icon-btn:hover:not(:disabled) { color: var(--ge-ico); }
|
|
49
|
+
.ge-icon-btn:active:not(:disabled) { background: var(--ge-press); }
|
|
50
|
+
`;
|
|
51
|
+
|
|
18
52
|
export const TOKENS = `
|
|
19
53
|
:root {
|
|
20
54
|
--ge-tx: light-dark(#2c2c2b, #f0efed);
|
|
@@ -40,6 +74,17 @@ export const TOKENS = `
|
|
|
40
74
|
--ge-focus: #2383e2;
|
|
41
75
|
--ge-red: light-dark(#eb5757, #ff6b6b);
|
|
42
76
|
--ge-quote: light-dark(rgb(28 19 1 / 16%), rgb(255 255 235 / 16%));
|
|
77
|
+
/* Buttons (BUTTONS below; the user's rule, restated 2026-11-09): a primary is a pale blue fill, always shown, its words the
|
|
78
|
+
deeper blue; a primary that cannot be taken back a pale red; every other button has no fill and no line, a gray under
|
|
79
|
+
the pointer (--ge-hover) and a deeper one pressed (--ge-press). The workbench's own values (--btnPriBg, --btnDanBg: tokens.css). */
|
|
80
|
+
--ge-btn-primary: light-dark(rgb(35 131 226 / 14%), rgb(67 155 255 / 24%));
|
|
81
|
+
--ge-btn-primary-hover: light-dark(rgb(35 131 226 / 22%), rgb(67 155 255 / 34%));
|
|
82
|
+
--ge-btn-primary-press: light-dark(rgb(35 131 226 / 30%), rgb(67 155 255 / 44%));
|
|
83
|
+
--ge-btn-primary-text: light-dark(#1a69bd, #7ab8ff);
|
|
84
|
+
--ge-btn-danger: light-dark(rgb(235 87 87 / 14%), rgb(255 104 92 / 24%));
|
|
85
|
+
--ge-btn-danger-hover: light-dark(rgb(235 87 87 / 22%), rgb(255 104 92 / 34%));
|
|
86
|
+
--ge-btn-danger-press: light-dark(rgb(235 87 87 / 30%), rgb(255 104 92 / 44%));
|
|
87
|
+
--ge-btn-danger-text: light-dark(#c4403c, #ff9a90);
|
|
43
88
|
--ge-fill: light-dark(rgb(35 131 226 / 14%), rgb(35 131 226 / 28%));
|
|
44
89
|
--ge-halo: rgb(35 131 226 / 14%);
|
|
45
90
|
--ge-select: light-dark(rgb(35 131 226 / 28%), rgb(35 131 226 / 45%));
|
|
@@ -55,6 +100,11 @@ export const TOKENS = `
|
|
|
55
100
|
--ge-toast-bg: light-dark(#0f0f0f, #2f2f2f);
|
|
56
101
|
/* The quiet gray a heading is lit with for a moment when the outline goes to it (outline/), never a blue. */
|
|
57
102
|
--ge-outline-flash: light-dark(rgb(33 27 23 / 7%), rgb(255 255 255 / 8%));
|
|
103
|
+
/* The lines a size is dragged by (resize/, columns/), grays like Notion's column resizer (its border.primaryTranslucent), never a
|
|
104
|
+
bright blue (the user, 2026-11-07): where a drag may start, the line being dragged, and that line where it snaps. */
|
|
105
|
+
--ge-guide: light-dark(rgb(55 53 47 / 16%), rgb(255 255 255 / 14%));
|
|
106
|
+
--ge-guide-hot: light-dark(rgb(55 53 47 / 36%), rgb(255 255 255 / 32%));
|
|
107
|
+
--ge-guide-snap: light-dark(rgb(55 53 47 / 62%), rgb(255 255 255 / 58%));
|
|
58
108
|
/* 批注 (annotate/): a warm mark on the words an annotation is about, its 2px underline leading (a faint fill, so it is never
|
|
59
109
|
taken for the report's own yellow background), a block anchor's bar; stronger for the one shown. */
|
|
60
110
|
--ge-note: light-dark(rgb(255 212 0 / 6%), rgb(255 212 0 / 6%));
|
|
@@ -74,4 +124,5 @@ export const TOKENS = `
|
|
|
74
124
|
--ge-diff-del-fill: light-dark(rgb(223 22 0 / 4.5%), rgb(255 104 92 / 10%));
|
|
75
125
|
--ge-diff-del-text: light-dark(#cf5148, #ff8f85);
|
|
76
126
|
}
|
|
127
|
+
${BUTTONS}
|
|
77
128
|
`;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OLD_OUTLINE_OPEN_KEY, OLD_PREFERENCES_KEY, OUTLINE_OPEN_KEY, PREFERENCES_KEY } from "../../shared/preferences.mjs";
|
|
2
2
|
import { LOOK_ATTRIBUTES } from "../../shared/document-look.mjs";
|
|
3
|
+
import { ADD, HANDLE } from "./handle-sizes.mjs";
|
|
3
4
|
|
|
4
5
|
// The right side of the page while it is edited (docs/editor.md, "The outline and the right side"): the
|
|
5
6
|
// outline (目录, outline/) docked at the window's right edge, the cards of 批注 (annotate/) between it and
|
|
@@ -52,9 +53,18 @@ import { LOOK_ATTRIBUTES } from "../../shared/document-look.mjs";
|
|
|
52
53
|
// column stands where it will stay from the first paint, and by setMargin() after that.
|
|
53
54
|
// When they move the column, the page hears a resize, so what stands over the text (the format bar, a
|
|
54
55
|
// selection's strips, a card) is placed again.
|
|
56
|
+
//
|
|
57
|
+
// The edge room is also the page's gutters (the kit's --doc-page-gutter and --doc-wide-gutter, page.css),
|
|
58
|
+
// set by MARGIN_STYLE, which the edit service puts in the page's head: the column the kit lets show
|
|
59
|
+
// (data-doc-ready, the frame a workbench swaps the page in on) stands where the editor keeps it, its lines
|
|
60
|
+
// broken as they stay, before the editor has started, the outline off and no 批注 as much as with them.
|
|
61
|
+
// (Until 2026-11-09 the handle put them in once the page edited: in a workbench with its sidebar open, a
|
|
62
|
+
// page 795px wide came in with the kit's 20px gutters, its column 712 wide and 42 in, and moved to 667 and
|
|
63
|
+
// 64 a few frames later, its lines breaking anew: the user's report on 0.1.1.)
|
|
55
64
|
|
|
56
65
|
/**
|
|
57
|
-
* The numbers: the edge room (the least room either side of the column keeps
|
|
66
|
+
* The numbers: the edge room (the least room either side of the column keeps, and the page's gutters:
|
|
67
|
+
* the bar's square left of the block handle's grip, the grip, its gap and room to breathe, 64), the least it gives up
|
|
58
68
|
* to (the block handle's: its 38px, its 12px gap, 2px), the column, the least a full-width column
|
|
59
69
|
* keeps, the outline in full (its default width, the least and the most it is dragged to), its
|
|
60
70
|
* list's inset in its panel (`guide`: the column's right room ends there, at the list's edge, its
|
|
@@ -65,7 +75,7 @@ import { LOOK_ATTRIBUTES } from "../../shared/document-look.mjs";
|
|
|
65
75
|
* clear; one focused comes 20px left, and no button shows then), a card's width, the least it gives up
|
|
66
76
|
* to, and the room past it (clear of the outline's list: its guide and grip).
|
|
67
77
|
*/
|
|
68
|
-
export const MARGIN = Object.freeze({ edge:
|
|
78
|
+
export const MARGIN = Object.freeze({ edge: ADD.width + HANDLE.width + HANDLE.gap + 12, start: 52, column: 712, least: 560, full: 200, fullMin: 160, fullMax: 360, guide: 8, grip: 4, strip: 36, hysteresis: 16, lane: 60, card: 308, cardLeast: 240, cardEnd: 20 });
|
|
69
79
|
|
|
70
80
|
/**
|
|
71
81
|
* The outline's width in full for the reader's choice `chosen` (px; 0 or none: the default), within
|
|
@@ -116,8 +126,13 @@ export function marginLayout({ width, outline = false, collapsed = false, notes
|
|
|
116
126
|
|
|
117
127
|
const SLIDE = 200; // ms: the column's slide as the page comes to have 批注 or has none left
|
|
118
128
|
|
|
119
|
-
/**
|
|
129
|
+
/**
|
|
130
|
+
* The page's rules for the room: its gutters the edge room, and on screen the column placed (and
|
|
131
|
+
* narrowed only when it must).
|
|
132
|
+
*/
|
|
120
133
|
export const MARGIN_STYLE = `
|
|
134
|
+
/* The handle's room beside the page's blocks, the page's gutters from its first paint (a page the editor edits: this sheet is in the head the edit service serves); resize/ and the workbench's sidebar read --ge-edge-room. */
|
|
135
|
+
:root { --ge-edge-room: ${MARGIN.edge}px; --doc-page-gutter: var(--ge-edge-room); --doc-wide-gutter: var(--ge-edge-room); }
|
|
121
136
|
@media screen {
|
|
122
137
|
:root[data-ge-margin] {
|
|
123
138
|
/* The least room either side of the column keeps (marginLayout's side: the edge room, less where the page is short of it, down to the handle's). */
|
|
@@ -28,15 +28,14 @@ const STYLE = `
|
|
|
28
28
|
.nmedia-menu-tab.active::after { content: ""; position: absolute; left: 8px; right: 8px; bottom: 0; border-bottom: 2px solid var(--c-texPri); }
|
|
29
29
|
.nmedia-menu-body { padding: 12px 12px 10px; }
|
|
30
30
|
.nmedia-menu-inner { display: flex; justify-content: center; padding: 4px; }
|
|
31
|
-
|
|
32
|
-
.nmedia-menu-upload
|
|
31
|
+
/* Its buttons are the editor's one button look (look.mjs BUTTONS): the pale blue primary, here what the tab does. */
|
|
32
|
+
.nmedia-menu-upload, .nmedia-menu-embed { width: 100%; font-size: 14px; }
|
|
33
33
|
.nmedia-menu-link { flex-direction: column; align-items: stretch; gap: 8px; }
|
|
34
34
|
.nmedia-menu-input { display: flex; align-items: center; gap: 4px; width: 100%; height: 28px; padding: 3px 6px; border-radius: 6px; background: var(--ca-bacSecTra); box-shadow: 0 0 0 1px var(--ca-borPriTra); box-sizing: border-box; }
|
|
35
35
|
.nmedia-menu-input:focus-within { box-shadow: var(--c-inpBluFocRin); }
|
|
36
36
|
.nmedia-menu-input input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; padding: 0; font: inherit; font-size: 14px; line-height: 20px; color: var(--c-texPri); }
|
|
37
37
|
.nmedia-menu-input input::placeholder { color: var(--c-texTer); }
|
|
38
|
-
.nmedia-menu-embed {
|
|
39
|
-
.nmedia-menu-embed:hover { filter: brightness(.94); }
|
|
38
|
+
.nmedia-menu-embed { max-width: 300px; margin: 0 auto; }
|
|
40
39
|
.nmedia-menu-caption { margin: -6px 0 4px; padding: 4px 0; font-size: 12px; line-height: 1.4; color: var(--c-texSec); text-align: center; }
|
|
41
40
|
.nmedia-menu.dragover .nmedia-menu-body { background: var(--ca-bluBacSecTra); }
|
|
42
41
|
.nmedia-menu-choose { margin-top: 8px; }
|
|
@@ -76,10 +75,10 @@ export function openMediaMenu(anchor, { tabs, width, upload = {}, link = {}, onU
|
|
|
76
75
|
`<div class="nmedia-menu-tab-wrap"><div role="tab" class="nmedia-menu-tab${key === current ? " active" : ""}" aria-selected="${key === current}" data-tab="${key}">${esc(label)}</div></div>`).join("")}</div>` : "")
|
|
77
76
|
+ `<div class="nmedia-menu-body">${current === "upload"
|
|
78
77
|
? (upload.primary
|
|
79
|
-
? `<div class="nmedia-menu-inner nmedia-menu-link"><div role="button" tabindex="0" class="nmedia-menu-embed nmedia-menu-choose" data-do="upload">${esc(upload.label ?? t("选择文件"))}</div>${upload.caption ? `<div class="nmedia-menu-caption">${esc(upload.caption)}</div>` : ""}</div>`
|
|
80
|
-
: `<div class="nmedia-menu-inner"><div role="button" tabindex="0" class="nmedia-menu-upload" data-do="upload">${esc(upload.label ?? t("上传文件"))}</div></div>`)
|
|
78
|
+
? `<div class="nmedia-menu-inner nmedia-menu-link"><div role="button" tabindex="0" class="ge-btn nmedia-menu-embed nmedia-menu-choose" data-primary data-do="upload">${esc(upload.label ?? t("选择文件"))}</div>${upload.caption ? `<div class="nmedia-menu-caption">${esc(upload.caption)}</div>` : ""}</div>`
|
|
79
|
+
: `<div class="nmedia-menu-inner"><div role="button" tabindex="0" class="ge-btn nmedia-menu-upload" data-primary data-do="upload">${esc(upload.label ?? t("上传文件"))}</div></div>`)
|
|
81
80
|
: `<div class="nmedia-menu-inner nmedia-menu-link"><div class="nmedia-menu-input"><input type="url" placeholder="${esc(link.placeholder ?? t("粘贴链接…"))}" autocomplete="off"></div>`
|
|
82
|
-
+ `<div role="button" tabindex="0" class="nmedia-menu-embed" data-do="embed">${esc(link.button ?? t("嵌入链接"))}</div>`
|
|
81
|
+
+ `<div role="button" tabindex="0" class="ge-btn nmedia-menu-embed" data-primary data-do="embed">${esc(link.button ?? t("嵌入链接"))}</div>`
|
|
83
82
|
+ (link.caption ? `<div class="nmedia-menu-caption">${esc(link.caption)}</div>` : "") + "</div>"}</div>`;
|
|
84
83
|
const input = el.querySelector("input");
|
|
85
84
|
if (input) {
|
|
@@ -37,6 +37,8 @@ const STYLE = `
|
|
|
37
37
|
}
|
|
38
38
|
/* A width given (data-sized: opts.width, placed by place()): that width, whatever the rows hold. */
|
|
39
39
|
.ge-pop[data-sized] { min-width: 0; max-width: calc(100vw - 16px); }
|
|
40
|
+
/* A short list of one kind of word (a card's 大小 ›: 4 × 2): only as wide as its rows, no 180px floor. */
|
|
41
|
+
.ge-pop[data-compact] { min-width: 0; }
|
|
40
42
|
@keyframes ge-pop-in { from { opacity: 0; transform: scale(.98); } }
|
|
41
43
|
@media (prefers-reduced-motion: reduce) { .ge-pop { animation: none; } }
|
|
42
44
|
.ge-pop-title { display: flex; align-items: center; gap: 8px; padding: 8px 12px; color: var(--ge-tx2); font-size: 12px; font-weight: 500; line-height: 14px; }
|
|
@@ -58,6 +60,7 @@ const STYLE = `
|
|
|
58
60
|
words and the hint takes what is left, cut short with an ellipsis where it is too long (an English
|
|
59
61
|
row's current choice once took the whole row, its label drawn 0px wide). */
|
|
60
62
|
.ge-pop-label:has(+ .ge-pop-hint) { flex: 1 0 auto; max-width: 100%; }
|
|
63
|
+
.ge-pop-of { color: var(--ge-tx3); }
|
|
61
64
|
.ge-pop-hint { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--ge-tx3); font-size: 12px; white-space: nowrap; }
|
|
62
65
|
/* A row of a page (its title, the page it is under as its hint): a long title is what an ellipsis
|
|
63
66
|
cuts, and the page above keeps its words, up to a part of the row. */
|
|
@@ -83,8 +86,8 @@ const STYLE = `
|
|
|
83
86
|
/* A note wraps at the card's width and never widens it (no width of its own: contain). */
|
|
84
87
|
.ge-pop-note { contain: inline-size; padding: 0 12px 6px 40px; color: var(--ge-tx3); font-size: 12px; line-height: 1.5; }
|
|
85
88
|
.ge-pop-empty { padding: 8px 12px; color: var(--ge-tx3); }
|
|
86
|
-
/* What a row makes, shown beside it under the pointer (a component package's preview.svg). */
|
|
87
|
-
.ge-pop-preview { display: block; width: 240px; max-height: 180px; border-radius: 4px; object-fit: contain; background: var(--ge-bg); }
|
|
89
|
+
/* What a row makes, shown beside it under the pointer (a component package's preview.svg), in the middle of the bubble: its description under it wraps wider than the picture. */
|
|
90
|
+
.ge-pop-preview { display: block; width: 240px; max-width: 100%; max-height: 180px; margin: 0 auto; border-radius: 4px; object-fit: contain; object-position: center; background: var(--ge-bg); }
|
|
88
91
|
.ge-pop-search { position: sticky; top: 0; z-index: 1; padding: 8px 8px 6px; background: var(--ge-bg); }
|
|
89
92
|
.ge-pop-search input { box-sizing: border-box; width: 100%; height: 28px; margin: 0; padding: 0 8px; border: 0; border-radius: 6px; outline: none; background: var(--ge-hover); color: var(--ge-tx); font: inherit; box-shadow: inset 0 0 0 1px var(--ge-line); }
|
|
90
93
|
.ge-pop-search input:focus { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ge-tx3) 60%, transparent); }
|
|
@@ -125,10 +128,12 @@ const opened = new Set(); // the menus open now, whichever part of the page open
|
|
|
125
128
|
export const menuOpen = () => opened.size > 0;
|
|
126
129
|
|
|
127
130
|
/**
|
|
128
|
-
* items: rows { label, run, icon?, hint?, long?, current?, checked?, disabled?, note?, preview? } (
|
|
131
|
+
* items: rows { label, run, icon?, of?, hint?, long?, current?, checked?, disabled?, note?, preview? } (of: what
|
|
132
|
+
* the label is of, grey after it, a block's pack where two rows have one name; long:
|
|
129
133
|
* a label of any length, a page's title, cut before its hint is; current: the choice
|
|
130
134
|
* made, checked and not to be chosen again; checked: a switch that is on, checked and clicked to turn
|
|
131
|
-
* it off;
|
|
135
|
+
* it off; selected: the choice of a dropdown (a field's list of options), checked as current is but
|
|
136
|
+
* still a row to click, which closes the card with nothing changed; preview: { src, says }, a picture of what the row makes, where it has one, and a line on it,
|
|
132
137
|
* shown at the row's right while the pointer rests on it, notion-lite's row tooltip) (or { label, icon?, submenu:
|
|
133
138
|
* () => items, width?, search? } opening a submenu, with a search field at its top when `search` is
|
|
134
139
|
* given, as `opts.search` below, and `search.empty` the words shown when nothing is found; a row
|
|
@@ -140,10 +145,14 @@ export const menuOpen = () => opened.size > 0;
|
|
|
140
145
|
* as its rows (FIT; SEARCHING with a search field). around: the rect of the block a handle
|
|
141
146
|
* (the anchor) stands for; the menu keeps clear of that block: left of it beside the handle, else
|
|
142
147
|
* below or above it (scrolling inside when only part of it fits), and over it only when the block
|
|
143
|
-
* leaves no room at all
|
|
148
|
+
* leaves no room at all; a tall block (more than TALL high: a table, a formula, a highlight, an image)
|
|
149
|
+
* has it beside the handle, left of it or, with no room there,
|
|
150
|
+
* right of it over the block, centered on the handle, never over the handle. side: "right": beside the anchor, right of it (left of it when there is no
|
|
144
151
|
* room), level with it (a section's bar). Without either the menu stands below the anchor (the
|
|
145
152
|
* caret), or above it when there is no room below; align: "end", its right edge at the anchor's.
|
|
146
|
-
* icons: false, rows of words alone (no column for icons: a code block's languages
|
|
153
|
+
* icons: false, rows of words alone (no column for icons: a code block's languages; a row that opens a
|
|
154
|
+
* submenu says it of its own as `icons: false`, and `compact: true` makes it only as wide as its rows, no
|
|
155
|
+
* 180px floor: a card's 大小 ›); height: the
|
|
147
156
|
* card's greatest height, in px (its rows scroll inside it past that). stand(size): where the card
|
|
148
157
|
* stands, its { left, top } for its { width, height }, in place of all of these rules (a pasted
|
|
149
158
|
* address's 选择视图, by the format bar's rule: placement.mjs besideText). inside: an element the rows
|
|
@@ -221,7 +230,8 @@ export function createMenu() {
|
|
|
221
230
|
if (row.split) row.setAttribute("data-split", "");
|
|
222
231
|
if (item.long) row.setAttribute("data-long", "");
|
|
223
232
|
if (options.icons !== false) words.append(element("span", { class: "ge-pop-icon", html: item.icon ?? "" }));
|
|
224
|
-
|
|
233
|
+
// A row's pack where two rows have one name (我的待办 · 柔光风格): grey, after the name, in the label.
|
|
234
|
+
words.append(item.of ? element("span", { class: "ge-pop-label" }, item.label, element("span", { class: "ge-pop-of", text: ` · ${item.of}` })) : element("span", { class: "ge-pop-label", text: item.label }));
|
|
225
235
|
if (item.hint) words.append(element("span", { class: "ge-pop-hint", text: item.hint }));
|
|
226
236
|
if (row.split) row.append(words, element("span", { class: "ge-pop-more", html: `<span class="ge-pop-arrow">${ICONS.chevron}</span>` }));
|
|
227
237
|
else if (item.submenu) row.append(element("span", { class: "ge-pop-arrow", html: ICONS.chevron }));
|
|
@@ -230,11 +240,12 @@ export function createMenu() {
|
|
|
230
240
|
row.submenu = item.submenu;
|
|
231
241
|
row.subWidth = item.width;
|
|
232
242
|
row.subSearch = item.search;
|
|
243
|
+
row.subLook = { icons: item.icons, compact: item.compact };
|
|
233
244
|
}
|
|
234
|
-
if (item.current || item.checked) {
|
|
235
|
-
row.append(element("span", { class: "ge-pop-check", html: ICONS.check, "aria-label": item.
|
|
245
|
+
if (item.current || item.checked || item.selected) {
|
|
246
|
+
row.append(element("span", { class: "ge-pop-check", html: ICONS.check, "aria-label": item.checked ? t("已开启") : t("当前") }));
|
|
236
247
|
row.setAttribute("data-current", "");
|
|
237
|
-
if (item.checked) row.setAttribute("aria-checked", "true");
|
|
248
|
+
if (item.checked || item.selected) row.setAttribute("aria-checked", "true");
|
|
238
249
|
}
|
|
239
250
|
row.disabled = Boolean(item.disabled || item.current);
|
|
240
251
|
row.run = item.run;
|
|
@@ -267,6 +278,7 @@ export function createMenu() {
|
|
|
267
278
|
}
|
|
268
279
|
|
|
269
280
|
const clamp = (value, low, high) => Math.max(low, Math.min(high, value));
|
|
281
|
+
const TALL = 34; // px: a block taller than this (a line of text is 26px) is a tall one: its menu may stand over it
|
|
270
282
|
|
|
271
283
|
function place() {
|
|
272
284
|
if (options.inside) return;
|
|
@@ -315,11 +327,16 @@ export function createMenu() {
|
|
|
315
327
|
const below = innerHeight - margin - (block.bottom + gap);
|
|
316
328
|
const above = block.top - gap - margin;
|
|
317
329
|
const beside = anchor.left - gap - width;
|
|
318
|
-
|
|
319
|
-
|
|
330
|
+
// A block of more than a line (a table, a formula, a highlight, an image: taller than TALL) may
|
|
331
|
+
// have the menu over it: beside its handle, right of it where there is no room left of it,
|
|
332
|
+
// rather than below the block, away from the handle.
|
|
333
|
+
const middle = (anchor.top + anchor.bottom) / 2;
|
|
334
|
+
const onRight = block.bottom - block.top > TALL && anchor.right + gap + width <= innerWidth - margin;
|
|
335
|
+
if (beside >= margin || onRight) {
|
|
336
|
+
// Beside the handle (never over it), left first, centered on it.
|
|
320
337
|
fit(room);
|
|
321
|
-
left = beside;
|
|
322
|
-
top = clamp(
|
|
338
|
+
left = beside >= margin ? beside : anchor.right + gap;
|
|
339
|
+
top = clamp(middle - height / 2, margin, innerHeight - margin - height);
|
|
323
340
|
} else if (Math.max(below, above) >= Math.min(height, 180)) {
|
|
324
341
|
// Below the block, else above it; in the larger of the two when it fits in neither.
|
|
325
342
|
left = clamp(anchor.left, margin, innerWidth - width - margin);
|
|
@@ -360,6 +377,7 @@ export function createMenu() {
|
|
|
360
377
|
const search = row.subSearch && { placeholder: row.subSearch.placeholder, filter: (text) => closing(row.subSearch.filter(text)) };
|
|
361
378
|
sub.open(items, row.getBoundingClientRect(), {
|
|
362
379
|
side: "right", gap: 0, height: Math.round(innerHeight * 0.7), highlight: keys, width: row.subWidth, label: row.textContent, search, empty: row.subSearch?.empty, focus: keys,
|
|
380
|
+
...(row.subLook.icons === false ? { icons: false } : {}), ...(row.subLook.compact ? { compact: true } : {}),
|
|
363
381
|
onClose: () => {
|
|
364
382
|
row.removeAttribute("aria-expanded");
|
|
365
383
|
if (subRow === row) {
|
|
@@ -439,6 +457,7 @@ export function createMenu() {
|
|
|
439
457
|
opened.add(menu);
|
|
440
458
|
node = element("div", { class: "ge-pop", role: "menu", "aria-label": opts.label ?? t("菜单") });
|
|
441
459
|
if (options.width) node.setAttribute("data-sized", "");
|
|
460
|
+
if (options.compact) node.setAttribute("data-compact", "");
|
|
442
461
|
if (opts.inside) {
|
|
443
462
|
node.setAttribute("data-inside", "");
|
|
444
463
|
opts.inside.append(node);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Z } from "../../shared/layers.mjs";
|
|
2
2
|
import { PANEL_STYLE, onPanels, panelGone, panelRoom, panelShown } from "./panel.mjs";
|
|
3
|
-
import { addStyle,
|
|
3
|
+
import { addStyle, element, mount, textButton } from "./ui.mjs";
|
|
4
4
|
import { t } from "../../shared/i18n/index.mjs";
|
|
5
5
|
import { preference } from "../../shared/preferences.mjs";
|
|
6
6
|
import { routine } from "./quiet.mjs";
|
|
@@ -128,7 +128,7 @@ export function showPanel(title) {
|
|
|
128
128
|
closePanel();
|
|
129
129
|
addStyle(PANEL_STYLE);
|
|
130
130
|
panel = mount(element("div", { class: "ge-panel", role: "region", "aria-label": title },
|
|
131
|
-
element("div", { class: "ge-panel-head" }, element("span", { text: title }),
|
|
131
|
+
element("div", { class: "ge-panel-head" }, element("span", { text: title }), textButton(t("关闭"), closePanel, { quiet: true }))));
|
|
132
132
|
panelShown(panel);
|
|
133
133
|
}
|
|
134
134
|
|
|
@@ -31,8 +31,15 @@ export function menuEntry(key) {
|
|
|
31
31
|
/** The row of a key of a menu of blocks: its type's, or its variant's; null for neither. */
|
|
32
32
|
export const menuRow = (key) => TYPE_INFO[key] ?? menuEntry(key).variant;
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
// Every variant there is now: [key, row].
|
|
35
|
+
const variants = () => Object.keys(TYPE_COMPONENT).flatMap((type) => Object.entries(pageOfType(type)?.menuVariants?.() ?? {}).map(([name, row]) => [`${type}:${name}`, row]));
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The keys of the variants the menus of blocks offer now ("/", 在下方新建, the handle's +, 转换成): every
|
|
39
|
+
* one, a view of a table (`readsTables`: a custom block whose needs hold "tables") too, which binds
|
|
40
|
+
* itself to the table above it as it is made (components/installed/page.mjs; page/table/binding.mjs).
|
|
41
|
+
*/
|
|
42
|
+
export const variantKeys = () => variants().map(([key]) => key);
|
|
36
43
|
|
|
37
44
|
/** The page objects, in the order they are made. */
|
|
38
45
|
export const pageObjects = () => Object.values(pages);
|
|
@@ -3,8 +3,10 @@ import { Z } from "../../shared/layers.mjs";
|
|
|
3
3
|
// The editor's bottom panels: the conflicts' (conflicts.mjs, left) and the lost texts' (notices.mjs,
|
|
4
4
|
// right) are the same card, and the bar of the Agent's changes (changes/bar.mjs, in the middle) is its
|
|
5
5
|
// buttons in a row: a small muted head with a red dot, items under it, the reader's words as
|
|
6
|
-
// a quote, one
|
|
7
|
-
//
|
|
6
|
+
// a quote, one pale blue primary button, the rest with no line and no fill (gray under the pointer) or, looking
|
|
7
|
+
// only, quiet text: all of them the editor's one button look (look.mjs BUTTONS, ui.mjs textButton), none of
|
|
8
|
+
// their own here. No notice covers one: while one stands, the toast stands above it (notices.mjs, and the
|
|
9
|
+
// workbench's, told the room).
|
|
8
10
|
|
|
9
11
|
const PANELS = ".ge-conflicts:not([hidden]), .ge-panel, .ge-changes:not([hidden])";
|
|
10
12
|
|
|
@@ -55,11 +57,4 @@ export const PANEL_STYLE = `
|
|
|
55
57
|
:is(.ge-conflict, .ge-panel-item) p + .ge-version { margin-top: 6px; }
|
|
56
58
|
:is(.ge-conflicts, .ge-panel) .ge-version { margin: 0; padding: 0 0 0 10px; border-left: 2px solid var(--ge-quote); overflow-wrap: anywhere; }
|
|
57
59
|
:is(.ge-conflicts, .ge-panel) .ge-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 12px; }
|
|
58
|
-
:is(.ge-conflicts, .ge-panel) button { height: 28px; padding: 0 10px; border: 1px solid var(--ge-edge); border-radius: 6px; background: transparent; color: inherit; font: inherit; font-weight: 500; white-space: nowrap; cursor: pointer; }
|
|
59
|
-
:is(.ge-conflicts, .ge-panel) button:hover:not(:disabled) { background: var(--ge-hover); }
|
|
60
|
-
:is(.ge-conflicts, .ge-panel) button[data-primary] { border-color: transparent; background: var(--ge-accent); color: #fff; }
|
|
61
|
-
:is(.ge-conflicts, .ge-panel) button[data-primary]:hover:not(:disabled) { background: var(--ge-accent-hover); }
|
|
62
|
-
:is(.ge-conflicts, .ge-panel) button[data-quiet] { height: 24px; padding: 0 6px; border-color: transparent; color: var(--ge-tx2); font-weight: 400; }
|
|
63
|
-
:is(.ge-conflicts, .ge-panel) button[data-quiet]:hover:not(:disabled) { color: var(--ge-tx); background: transparent; }
|
|
64
|
-
:is(.ge-conflicts, .ge-panel) button:disabled { opacity: .45; cursor: default; }
|
|
65
60
|
`;
|