@heycys/gallery 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD-PARTY-NOTICES.md +1 -1
- package/browser/editor/components/columns/page.mjs +4 -4
- package/browser/editor/components/embed/index.mjs +2 -2
- package/browser/editor/components/flowchart/add.mjs +7 -6
- package/browser/editor/components/flowchart/page.mjs +1 -1
- package/browser/editor/components/icons.mjs +8 -0
- package/browser/editor/components/image/crop.mjs +6 -9
- package/browser/editor/components/installed/index.mjs +11 -4
- package/browser/editor/components/installed/page.mjs +27 -16
- package/browser/editor/components/installed/served.mjs +6 -5
- package/browser/editor/components/instances.mjs +18 -0
- package/browser/editor/components/list/page.mjs +3 -6
- package/browser/editor/components/registry.mjs +13 -4
- package/browser/editor/components/table/index.mjs +59 -2
- package/browser/editor/components/table/page.mjs +1 -1
- package/browser/editor/page/annotate/card.mjs +3 -6
- package/browser/editor/page/autosave.mjs +310 -37
- package/browser/editor/page/board/client.mjs +57 -0
- package/browser/editor/page/board/hint.mjs +145 -0
- package/browser/editor/page/board/history.mjs +119 -0
- package/browser/editor/page/board/index.mjs +970 -0
- package/browser/editor/page/board/settings.mjs +209 -0
- package/browser/editor/page/caret.mjs +1 -1
- package/browser/editor/page/changes/bar.mjs +6 -14
- package/browser/editor/page/changes/index.mjs +2 -2
- package/browser/editor/page/clipboard/import/html.mjs +29 -6
- package/browser/editor/page/clipboard/import/inline.mjs +32 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +58 -13
- package/browser/editor/page/clipboard/import/read.mjs +6 -1
- package/browser/editor/page/clipboard/import/to-blocks.mjs +44 -12
- package/browser/editor/page/clipboard/import/yuque.mjs +622 -0
- package/browser/editor/page/clipboard/index.mjs +124 -13
- package/browser/editor/page/clipboard/own/blocks.mjs +11 -11
- package/browser/editor/page/clipboard/own/chart-keys.mjs +41 -28
- package/browser/editor/page/clipboard/own/selection.mjs +1 -1
- package/browser/editor/page/columns/index.mjs +48 -46
- package/browser/editor/page/commit.mjs +80 -22
- package/browser/editor/page/conflicts.mjs +7 -7
- package/browser/editor/page/core.mjs +31 -15
- package/browser/editor/page/custom-page.mjs +106 -0
- package/browser/editor/page/editor.mjs +51 -14
- package/browser/editor/page/emoji-picker/styles.mjs +7 -12
- package/browser/editor/page/emoji-picker/upload.mjs +2 -2
- package/browser/editor/page/handle/index.mjs +5 -8
- package/browser/editor/page/history.mjs +24 -4
- package/browser/editor/page/links/index.mjs +5 -3
- package/browser/editor/page/links/pages.mjs +27 -9
- package/browser/editor/page/look.mjs +54 -3
- package/browser/editor/page/margin.mjs +18 -3
- package/browser/editor/page/media-menu/index.mjs +6 -7
- package/browser/editor/page/menu.mjs +18 -7
- package/browser/editor/page/notices.mjs +2 -2
- package/browser/editor/page/page-objects.mjs +13 -2
- package/browser/editor/page/panel.mjs +4 -9
- package/browser/editor/page/present-links.mjs +11 -2
- package/browser/editor/page/resize/index.mjs +42 -29
- package/browser/editor/page/served.mjs +14 -0
- package/browser/editor/page/session.mjs +48 -4
- package/browser/editor/page/slash-menu/index.mjs +3 -3
- package/browser/editor/page/table/cells.mjs +102 -46
- package/browser/editor/page/table/icons.mjs +2 -0
- package/browser/editor/page/table/index.mjs +29 -10
- package/browser/editor/page/table/pictures.mjs +299 -0
- package/browser/editor/page/table/views.mjs +150 -0
- package/browser/editor/page/text-select/index.mjs +26 -12
- package/browser/editor/page/todo-writes.mjs +75 -0
- package/browser/editor/page/typing/index.mjs +53 -3
- package/browser/editor/page/ui.mjs +13 -0
- package/browser/shared/block-packs.mjs +404 -0
- package/browser/shared/board-places.mjs +224 -0
- package/browser/shared/card-size.mjs +59 -0
- package/browser/shared/colors.mjs +3 -2
- package/browser/shared/component-catalog.mjs +323 -46
- package/browser/shared/component-source.mjs +37 -0
- package/browser/shared/components/index.mjs +12 -3
- package/browser/shared/components/installed.mjs +35 -3
- package/browser/shared/components/page.mjs +18 -8
- package/browser/shared/components/state.mjs +5 -1
- package/browser/shared/document-look.mjs +10 -5
- package/browser/shared/drafts.mjs +432 -0
- package/browser/shared/extension-sidebar.mjs +126 -0
- package/browser/shared/extensions.mjs +79 -0
- package/browser/shared/file-table.mjs +101 -0
- package/browser/shared/i18n/en.mjs +307 -27
- package/browser/shared/json-layout.mjs +47 -0
- package/browser/shared/net-cache.mjs +133 -0
- package/browser/shared/net-keys.mjs +32 -0
- package/browser/shared/net-policy.mjs +177 -0
- package/browser/shared/outline-shape.mjs +128 -0
- package/browser/shared/outline.mjs +331 -67
- package/browser/shared/pack-manifest.mjs +77 -0
- package/browser/shared/page-address.mjs +6 -3
- package/browser/shared/page-cards.mjs +308 -0
- package/browser/shared/page-links.mjs +69 -6
- package/browser/shared/pages.mjs +388 -0
- package/browser/shared/paths.mjs +6 -0
- package/browser/shared/preview-server.mjs +3 -7
- package/browser/shared/session.mjs +8 -1
- package/browser/shared/shipped-blocks.mjs +299 -0
- package/browser/shared/table-chart.mjs +33 -1
- package/browser/shared/todos.mjs +83 -0
- package/browser/shared/user-directory.mjs +24 -0
- package/browser/shared/versions.mjs +14 -0
- package/browser/shared/web-links.mjs +134 -0
- package/browser/shared/workspace-columns.mjs +120 -0
- package/browser/shared/workspace-name.mjs +154 -0
- package/browser/shared/workspace-query.mjs +125 -0
- package/browser/shared/workspace-registry.mjs +272 -0
- package/browser/shared/workspace.mjs +171 -20
- package/dist/chunk-2NRBY6AJ.mjs +2 -0
- package/dist/chunk-32ZUEFZ7.mjs +2 -0
- package/dist/chunk-35NQ4PLQ.mjs +2 -0
- package/dist/chunk-3KJHLHUO.mjs +2 -0
- package/dist/chunk-3NJACR4W.mjs +2 -0
- package/dist/chunk-4AV456RQ.mjs +2 -0
- package/dist/chunk-4OZWXZE5.mjs +5 -0
- package/dist/chunk-5XYHDBJ5.mjs +2 -0
- package/dist/chunk-5ZJA7CXT.mjs +2 -0
- package/dist/chunk-6A53MZYZ.mjs +2 -0
- package/dist/chunk-6EXH3ORZ.mjs +166 -0
- package/dist/chunk-6EZ7FNIK.mjs +3 -0
- package/dist/{chunk-V5JTW2LH.mjs → chunk-6QBHU4DF.mjs} +1 -1
- package/dist/{chunk-Y6RLRPG3.mjs → chunk-6VTU6KEO.mjs} +1 -1
- package/dist/chunk-B4P2CM2J.mjs +3 -0
- package/dist/{chunk-FDLXYYG4.mjs → chunk-BPL64HGA.mjs} +1 -1
- package/dist/chunk-BVEFGE4B.mjs +2 -0
- package/dist/{chunk-LS4F7JUM.mjs → chunk-BZ5RAF7L.mjs} +1 -1
- package/dist/chunk-CRJEG7MT.mjs +2 -0
- package/dist/{chunk-LCTHTZIL.mjs → chunk-D4CKRD3V.mjs} +91 -91
- package/dist/chunk-D4EURAX4.mjs +4 -0
- package/dist/chunk-DQCE7TJY.mjs +5 -0
- package/dist/chunk-DR73Y2UJ.mjs +3 -0
- package/dist/{chunk-TMYZB6AV.mjs → chunk-EKNHM3P4.mjs} +1 -1
- package/dist/{chunk-GB5SOYQJ.mjs → chunk-ERLAIBOA.mjs} +2 -2
- package/dist/chunk-EURLTOTZ.mjs +4 -0
- package/dist/chunk-FJYN7RTH.mjs +4 -0
- package/dist/chunk-FWNRPMCJ.mjs +12 -0
- package/dist/chunk-FWW4CSAZ.mjs +2 -0
- package/dist/{chunk-2B5E4CDJ.mjs → chunk-GPIWQ4X4.mjs} +1 -1
- package/dist/chunk-GY3FAUVM.mjs +2 -0
- package/dist/chunk-HLYV7RIH.mjs +2 -0
- package/dist/chunk-HMYTM3GT.mjs +15 -0
- package/dist/chunk-IA4PSIMD.mjs +2 -0
- package/dist/chunk-JEUK3ZO7.mjs +2 -0
- package/dist/chunk-KTKHRC6H.mjs +2 -0
- package/dist/chunk-L7UP52JO.mjs +2 -0
- package/dist/{chunk-SYGN7GLU.mjs → chunk-MHW7ZKOU.mjs} +1 -1
- package/dist/chunk-N76HWBA3.mjs +10 -0
- package/dist/chunk-N7AZZLGT.mjs +548 -0
- package/dist/chunk-NAMN3RAF.mjs +2 -0
- package/dist/{chunk-5ZKJ3H4P.mjs → chunk-NFMCP2HI.mjs} +3 -3
- package/dist/chunk-NG375ILQ.mjs +2 -0
- package/dist/chunk-NVRNLK25.mjs +6 -0
- package/dist/chunk-NWFBE2YA.mjs +2 -0
- package/dist/chunk-NWR2LT5B.mjs +2 -0
- package/dist/chunk-OJKMINIU.mjs +20 -0
- package/dist/{chunk-4FS7Z7WR.mjs → chunk-OUUP3WKT.mjs} +1 -1
- package/dist/{chunk-BGGDRNYQ.mjs → chunk-OW5NWPOJ.mjs} +1 -1
- package/dist/chunk-PAREWQGB.mjs +4 -0
- package/dist/chunk-POQSE4C2.mjs +2 -0
- package/dist/chunk-PUOQ65NC.mjs +2 -0
- package/dist/{chunk-XNROSH2T.mjs → chunk-PVER7LSC.mjs} +2 -2
- package/dist/chunk-PZDLJJTJ.mjs +3 -0
- package/dist/chunk-Q47PLKIJ.mjs +15 -0
- package/dist/chunk-Q4UEPUWF.mjs +2 -0
- package/dist/chunk-QKXMPUXC.mjs +2 -0
- package/dist/chunk-QOUEFUCH.mjs +16 -0
- package/dist/chunk-RFDZXFJF.mjs +13 -0
- package/dist/chunk-RKPWLGZ3.mjs +4 -0
- package/dist/chunk-RMECZA2K.mjs +2 -0
- package/dist/{chunk-7DTINW6U.mjs → chunk-SQ6Y2ZMA.mjs} +2 -2
- package/dist/chunk-SX4LJYT6.mjs +8 -0
- package/dist/chunk-SXHBYZST.mjs +16 -0
- package/dist/chunk-TANZRINB.mjs +2 -0
- package/dist/chunk-TEZAWDSQ.mjs +2 -0
- package/dist/chunk-UBBRTJ2R.mjs +24 -0
- package/dist/chunk-UFNYFFKO.mjs +20 -0
- package/dist/chunk-UGWYKHBL.mjs +170 -0
- package/dist/chunk-UKSHDZZ6.mjs +2 -0
- package/dist/chunk-UNOYVIYR.mjs +2 -0
- package/dist/{chunk-E7LWZRXY.mjs → chunk-V6RIYQZZ.mjs} +1 -1
- package/dist/chunk-VJPFVNNW.mjs +15 -0
- package/dist/chunk-VS3ZMVGX.mjs +5 -0
- package/dist/chunk-VTKNEYT3.mjs +6 -0
- package/dist/chunk-VXACTLO3.mjs +3 -0
- package/dist/chunk-YI43RG4P.mjs +2 -0
- package/dist/chunk-YQGT4AB2.mjs +6 -0
- package/dist/chunk-ZB4H7ZN4.mjs +2 -0
- package/dist/{chunk-IVDLMMBD.mjs → chunk-ZHEHPMBK.mjs} +1 -1
- package/dist/chunk-ZTHICSSF.mjs +2 -0
- package/dist/chunk-ZUNVAXLH.mjs +2 -0
- package/dist/chunk-ZWPMCK7P.mjs +2 -0
- package/dist/cli.mjs +1 -1
- package/dist/server.mjs +1 -1
- package/dist/{chunk-U6KNPJPR.mjs → update-fetch.mjs} +1 -1
- package/dist/worker.mjs +1 -1
- package/kit/board.css +95 -0
- package/kit/board.js +250 -0
- package/kit/charts.js +5 -71
- package/kit/code.js +14 -14
- package/kit/report.css +255 -17
- package/kit/runtime.js +1600 -125
- package/kit/state.js +10 -1
- package/kit/tables.js +128 -43
- package/kit/ui.js +77 -35
- package/package.json +2 -1
- package/packs/gallery/card/component.json +14 -0
- package/packs/gallery/card/example.html +10 -0
- package/packs/gallery/card/preview.svg +1 -0
- package/packs/gallery/card/style.css +6 -0
- package/packs/gallery/card/template.html +6 -0
- package/packs/gallery/card/writing.md +14 -0
- package/packs/gallery/chart-card/component.json +15 -0
- package/packs/gallery/chart-card/example.html +14 -0
- package/packs/gallery/chart-card/kit.js +130 -0
- package/packs/gallery/chart-card/preview.svg +1 -0
- package/packs/gallery/chart-card/style.css +42 -0
- package/packs/gallery/chart-card/template.html +13 -0
- package/packs/gallery/chart-card/writing.md +20 -0
- package/packs/gallery/chart-view/component.json +20 -0
- package/packs/gallery/chart-view/example.html +13 -0
- package/packs/gallery/chart-view/kit.js +355 -0
- package/packs/gallery/chart-view/preview.svg +1 -0
- package/packs/gallery/chart-view/style.css +94 -0
- package/packs/gallery/chart-view/template.html +3 -0
- package/packs/gallery/chart-view/writing.md +22 -0
- package/packs/gallery/countdown/component.json +18 -0
- package/packs/gallery/countdown/example.html +3 -0
- package/packs/gallery/countdown/kit.js +156 -0
- package/packs/gallery/countdown/preview.svg +1 -0
- package/packs/gallery/countdown/style.css +130 -0
- package/packs/gallery/countdown/template.html +3 -0
- package/packs/gallery/countdown/writing.md +22 -0
- package/packs/gallery/habit/component.json +14 -0
- package/packs/gallery/habit/example.html +3 -0
- package/packs/gallery/habit/kit.js +295 -0
- package/packs/gallery/habit/preview.svg +1 -0
- package/packs/gallery/habit/style.css +246 -0
- package/packs/gallery/habit/template.html +3 -0
- package/packs/gallery/habit/writing.md +21 -0
- package/packs/gallery/heatmap/component.json +18 -0
- package/packs/gallery/heatmap/example.html +3 -0
- package/packs/gallery/heatmap/kit.js +351 -0
- package/packs/gallery/heatmap/preview.svg +1 -0
- package/packs/gallery/heatmap/style.css +201 -0
- package/packs/gallery/heatmap/template.html +3 -0
- package/packs/gallery/heatmap/writing.md +21 -0
- package/packs/gallery/kanban/component.json +18 -0
- package/packs/gallery/kanban/example.html +12 -0
- package/packs/gallery/kanban/kit.js +540 -0
- package/packs/gallery/kanban/preview.svg +1 -0
- package/packs/gallery/kanban/style.css +212 -0
- package/packs/gallery/kanban/template.html +3 -0
- package/packs/gallery/kanban/writing.md +20 -0
- package/packs/gallery/metric/component.json +22 -0
- package/packs/gallery/metric/example.html +15 -0
- package/packs/gallery/metric/kit.js +248 -0
- package/packs/gallery/metric/preview.svg +1 -0
- package/packs/gallery/metric/style.css +92 -0
- package/packs/gallery/metric/template.html +3 -0
- package/packs/gallery/metric/writing.md +23 -0
- package/packs/gallery/note/component.json +14 -0
- package/packs/gallery/note/example.html +3 -0
- package/packs/gallery/note/kit.js +102 -0
- package/packs/gallery/note/preview.svg +1 -0
- package/packs/gallery/note/style.css +76 -0
- package/packs/gallery/note/template.html +3 -0
- package/packs/gallery/note/writing.md +18 -0
- package/packs/gallery/pack.json +8 -0
- package/packs/gallery/recent/component.json +13 -0
- package/packs/gallery/recent/example.html +1 -0
- package/packs/gallery/recent/kit.js +238 -0
- package/packs/gallery/recent/preview.svg +1 -0
- package/packs/gallery/recent/style.css +158 -0
- package/packs/gallery/recent/template.html +1 -0
- package/packs/gallery/recent/writing.md +15 -0
- package/packs/gallery/static/component.json +13 -0
- package/packs/gallery/static/example.html +11 -0
- package/packs/gallery/static/preview.svg +1 -0
- package/packs/gallery/static/style.css +138 -0
- package/packs/gallery/static/template.html +1 -0
- package/packs/gallery/static/writing.md +18 -0
- package/packs/gallery/stats/component.json +13 -0
- package/packs/gallery/stats/example.html +1 -0
- package/packs/gallery/stats/kit.js +166 -0
- package/packs/gallery/stats/preview.svg +1 -0
- package/packs/gallery/stats/style.css +151 -0
- package/packs/gallery/stats/template.html +1 -0
- package/packs/gallery/stats/writing.md +11 -0
- package/packs/gallery/today/component.json +12 -0
- package/packs/gallery/today/example.html +1 -0
- package/packs/gallery/today/kit.js +185 -0
- package/packs/gallery/today/preview.svg +1 -0
- package/packs/gallery/today/style.css +120 -0
- package/packs/gallery/today/template.html +1 -0
- package/packs/gallery/today/writing.md +14 -0
- package/packs/gallery/todos/component.json +19 -0
- package/packs/gallery/todos/example.html +3 -0
- package/packs/gallery/todos/kit.js +342 -0
- package/packs/gallery/todos/preview.svg +1 -0
- package/packs/gallery/todos/style.css +267 -0
- package/packs/gallery/todos/template.html +3 -0
- package/packs/gallery/todos/writing.md +30 -0
- package/packs/gallery/weather/component.json +19 -0
- package/packs/gallery/weather/example.html +3 -0
- package/packs/gallery/weather/kit.js +312 -0
- package/packs/gallery/weather/preview.svg +1 -0
- package/packs/gallery/weather/style.css +258 -0
- package/packs/gallery/weather/template.html +3 -0
- package/packs/gallery/weather/writing.md +26 -0
- package/packs/gallery-soft/pack.json +8 -0
- package/release.json +12 -10
- package/sdk/doc-kit.d.ts +396 -5
- package/sdk/doc-state.d.ts +2 -0
- package/skill/SKILL.md +56 -23
- package/skill/references/block-script.md +140 -0
- package/skill/references/building-blocks.md +257 -0
- package/skill/references/extensions.md +59 -0
- package/skill/references/pages-and-data.md +221 -0
- package/skill/references/writing-html.md +6 -4
- package/skill/sdk/doc-kit.d.ts +396 -5
- package/skill/sdk/doc-state.d.ts +2 -0
- package/web/assets/index-BK2e_07w.js +13 -0
- package/web/assets/index-CWFI83mF.css +1 -0
- package/web/index.html +2 -2
- package/dist/chunk-3HIRPVLU.mjs +0 -2
- package/dist/chunk-5MHMDLZD.mjs +0 -4
- package/dist/chunk-64K7IPLO.mjs +0 -255
- package/dist/chunk-6QXGZM36.mjs +0 -8
- package/dist/chunk-6RGJOMJP.mjs +0 -16
- package/dist/chunk-AJ73XJF3.mjs +0 -2
- package/dist/chunk-AUZGSZJH.mjs +0 -13
- package/dist/chunk-BFE45AKL.mjs +0 -2
- package/dist/chunk-BXO2ZY5P.mjs +0 -2
- package/dist/chunk-CEH4MRCC.mjs +0 -2
- package/dist/chunk-CY2FNNAB.mjs +0 -16
- package/dist/chunk-DFUDV4LX.mjs +0 -2
- package/dist/chunk-DKXG4XDG.mjs +0 -2
- package/dist/chunk-EZQ34M3F.mjs +0 -124
- package/dist/chunk-EZY3WC6Z.mjs +0 -15
- package/dist/chunk-FUKQNOQS.mjs +0 -9
- package/dist/chunk-JPOSLGOC.mjs +0 -6
- package/dist/chunk-L3QKH4OK.mjs +0 -26
- package/dist/chunk-LAE5NQ4B.mjs +0 -2
- package/dist/chunk-LEF6DRCK.mjs +0 -59
- package/dist/chunk-NO5NJCHO.mjs +0 -2
- package/dist/chunk-NQPVAU63.mjs +0 -2
- package/dist/chunk-NSKUTQ5J.mjs +0 -5
- package/dist/chunk-O35FIXRB.mjs +0 -2
- package/dist/chunk-P2CAZPDP.mjs +0 -3
- package/dist/chunk-PL6GHLGD.mjs +0 -15
- package/dist/chunk-QJIR2BLP.mjs +0 -6
- package/dist/chunk-QUPLVPB2.mjs +0 -7
- package/dist/chunk-R7BNENLY.mjs +0 -4
- package/dist/chunk-S6O4UHLC.mjs +0 -2
- package/dist/chunk-SGJWQKEI.mjs +0 -2
- package/dist/chunk-TX6JH7TR.mjs +0 -2
- package/dist/chunk-TYK6VNAB.mjs +0 -10
- package/dist/chunk-UALRNVSE.mjs +0 -4
- package/dist/chunk-V3HXVQEM.mjs +0 -2
- package/dist/chunk-V5VXUJKG.mjs +0 -2
- package/dist/chunk-VBXMADMP.mjs +0 -2
- package/dist/chunk-VNV55RUA.mjs +0 -2
- package/dist/chunk-VPD2PS35.mjs +0 -2
- package/dist/chunk-W4VKN3GF.mjs +0 -7
- package/dist/chunk-W5BXXPDJ.mjs +0 -3
- package/dist/chunk-XUNHRCOG.mjs +0 -6
- package/skill/references/building-components.md +0 -367
- package/web/assets/index-Bh74DfsV.css +0 -1
- package/web/assets/index-UW0RyFFt.js +0 -13
|
@@ -18,8 +18,9 @@ import { SOLO, connectWorkbench } from "./session.mjs";
|
|
|
18
18
|
import { lookOfElement } from "../../shared/document-look.mjs";
|
|
19
19
|
import { belowTargets, convertBlock, convertGroup, groupParents, groupTargets, noTextToCarry, targetsOf, touchedBy, turnInto, turnParents, turnUnit, typeOf } from "./convert.mjs";
|
|
20
20
|
import { joinCode, rangeAt, rangeOffsets } from "./marks.mjs";
|
|
21
|
-
import { addStyle,
|
|
21
|
+
import { addStyle, copyAddress, element, layer, textButton } from "./ui.mjs";
|
|
22
22
|
import { createClipboard } from "./clipboard/index.mjs";
|
|
23
|
+
import { serveFiles } from "./served.mjs";
|
|
23
24
|
import { createFormatting } from "./format-bar/index.mjs";
|
|
24
25
|
import { connectHints, hideHint, readOnlyReason, scheduleHint, trackPointer } from "./hints/index.mjs";
|
|
25
26
|
import { createInsert } from "./insert/index.mjs";
|
|
@@ -58,6 +59,7 @@ import { goBackTo, placeIn, unmoved } from "../../shared/reading-place.mjs";
|
|
|
58
59
|
import { heldList, holdPages } from "./links/pages.mjs";
|
|
59
60
|
import { hideBlocks } from "./offered.mjs";
|
|
60
61
|
import { local, storageOf } from "./storage.mjs";
|
|
62
|
+
import { createTodoWrites } from "./todo-writes.mjs";
|
|
61
63
|
import { language, t } from "../../shared/i18n/index.mjs";
|
|
62
64
|
|
|
63
65
|
// In-place editing for the live preview (`npm run dev:local` only; never exported).
|
|
@@ -268,7 +270,12 @@ const { newParagraph } = insert;
|
|
|
268
270
|
|
|
269
271
|
// The icon picker's images go into the report's folder (editor/media-store.mjs), where the server serves them.
|
|
270
272
|
const assetUrl = (file) => mediaUrl("asset", MAP.slug, file);
|
|
273
|
+
serveFiles(assetUrl); // a table cell's pictures (单元格里的图片) show where the server serves them
|
|
271
274
|
connectPicker({ slug: MAP.slug, token: MAP.token, notify: say });
|
|
275
|
+
// A block of the page checking a to-do of a document (context.workspace.setTodo: ./todo-writes.mjs): written
|
|
276
|
+
// by the workspace's service, this one's too as any write it did not make, which the page merges; no step of
|
|
277
|
+
// its undo (only a custom page keeps one: board/).
|
|
278
|
+
createTodoWrites({ token: MAP.token }).listen();
|
|
272
279
|
// Whether a block tool may act: the page edits, no reload is on its way and no field of a component is being edited.
|
|
273
280
|
const active = () => editing && !autosave?.state.reloading && !fieldOpen();
|
|
274
281
|
// A picture or file sent to the report's folder (kind: "image", "file" or "embed"): the server's answer.
|
|
@@ -372,6 +379,7 @@ const clipboard = createClipboard({
|
|
|
372
379
|
pageLink: pageLinkOf,
|
|
373
380
|
titleBold: () => formatting?.armed ?? false, // a node's empty title: what is pasted there bold, as typed
|
|
374
381
|
showCaret,
|
|
382
|
+
pictures: () => tables?.pictures ?? null, // a table cell's (table/pictures.mjs)
|
|
375
383
|
});
|
|
376
384
|
|
|
377
385
|
// ---------- editing ----------
|
|
@@ -440,17 +448,19 @@ function enter() {
|
|
|
440
448
|
conflicts.add(entries.map((entry) => ({ ...entry, key: `r:${entry.key}`, revert: entry.key, kind: entry.written ? "reverted-source" : entry.unit === undefined ? "reverted" : "reverted-unit" })));
|
|
441
449
|
say(t("AI 的写入把你之前保存的 {0} 处修改改回去了:在左下方选择保留哪一边。", entries.length), "error");
|
|
442
450
|
},
|
|
451
|
+
listed: () => showLost(), // a block the page before this one made, which someone else's write took out
|
|
443
452
|
});
|
|
444
453
|
conflicts = createConflicts({ act: decide, nodeOf: conflictNode, restorable, copyBlock: (node) => clipboard.copyBlocks([node]), say });
|
|
445
454
|
editing = true;
|
|
446
455
|
document.documentElement.setAttribute("data-ge-editing", "");
|
|
456
|
+
typing.untitled(); // an empty title says 未命名文档 from the start
|
|
447
457
|
blocks?.folds.start(); // what was folded, folded again in this task: no frame shows it open (fold/)
|
|
448
458
|
refresh();
|
|
449
459
|
for (const page of pageObjects()) page.entered?.();
|
|
450
460
|
}
|
|
451
461
|
|
|
452
462
|
// What the page says when what a component wrote went by a manifest that changed: given up, the page shown again.
|
|
453
|
-
const outdatedNotice = () => t("
|
|
463
|
+
const outdatedNotice = () => t("自定义块刚刚变了,这次改动没有保存,页面已按新的块重新显示。");
|
|
454
464
|
|
|
455
465
|
// What 仍然调整 wrote over someone else's change of what a component writes, by page unit: the step that
|
|
456
466
|
// gives theirs back (installed/ overwrite), and when its write went in, all of it (commit.mjs `forced`).
|
|
@@ -465,9 +475,10 @@ const keepsOverwrite = (asked) => !asked && [...overwrites.values()].some(({ lan
|
|
|
465
475
|
|
|
466
476
|
// A commit was taken in (commit.mjs): a block merged with someone else's words shows the merge;
|
|
467
477
|
// what the file refused is flagged and held back, the rest goes on.
|
|
468
|
-
function committed({ conflicts: held, merged, outdated, forced = [] }, receipt) {
|
|
478
|
+
function committed({ conflicts: held, merged, outdated, forced = [], rekeyed = [] }, receipt) {
|
|
469
479
|
agentChanges?.committed(receipt);
|
|
470
480
|
for (const host of merged) history.merged(host);
|
|
481
|
+
history.rekeyed(rekeyed); // the keys of tables the file gave otherwise, in the steps that recorded them
|
|
471
482
|
for (const unit of forced) {
|
|
472
483
|
const written = overwrites.get(unit);
|
|
473
484
|
if (!written || written.landed > 0) continue;
|
|
@@ -485,7 +496,7 @@ function committed({ conflicts: held, merged, outdated, forced = [] }, receipt)
|
|
|
485
496
|
conflicts.add(held);
|
|
486
497
|
const conflicted = held.filter((entry) => !unfit(entry) && !packageChanged(entry)).length;
|
|
487
498
|
const packaged = held.filter(packageChanged).length;
|
|
488
|
-
say(conflicted > 0 ? t("{0} 处修改和文件的最新版本冲突,没有保存:在左下方选择怎么处理。", conflicted) : packaged > 0 ? t("
|
|
499
|
+
say(conflicted > 0 ? t("{0} 处修改和文件的最新版本冲突,没有保存:在左下方选择怎么处理。", conflicted) : packaged > 0 ? t("自定义块刚刚变了,{0} 处修改没有保存:在左下方选择怎么处理。", packaged) : t("{0} 处内容文档存不下,没有保存:在左下方选择怎么处理。", held.length), "error");
|
|
489
500
|
}
|
|
490
501
|
else if (outdated || merged.length > 0 || receipt.texts?.some((entry) => entry.status === "merged")) {
|
|
491
502
|
const count = receipt.texts.filter((entry) => entry.status === "merged").length;
|
|
@@ -612,6 +623,7 @@ function markChanged(now = false) {
|
|
|
612
623
|
conflicts?.reflag();
|
|
613
624
|
}
|
|
614
625
|
if (messageKind() === "error") settle(); // the reader is dealing with it
|
|
626
|
+
typing.untitled(); // a title emptied (or filled) by any change says 未命名文档 (or nothing) at once
|
|
615
627
|
lastChange = Date.now();
|
|
616
628
|
discrete ||= now;
|
|
617
629
|
const counting = checkPending;
|
|
@@ -691,7 +703,10 @@ function afterConvert(focus, type, said) {
|
|
|
691
703
|
* heading) and the new block turns into the type; below any other block, an empty paragraph of its
|
|
692
704
|
* box does (the first box out that takes one). One undo step.
|
|
693
705
|
*/
|
|
694
|
-
|
|
706
|
+
// `also` (a table's 视图 ›: page/table/views.mjs): `attributes` ([element, names]) the step records too, and
|
|
707
|
+
// `done(made)` run in it on the new block (the element where the empty paragraph was), so that what binds
|
|
708
|
+
// the block to the one above it is the same step.
|
|
709
|
+
function insertBelow(target, type, typed = null, also = null) {
|
|
695
710
|
const splits = isHost(target) && can(target, "split");
|
|
696
711
|
let after = target;
|
|
697
712
|
while (!splits && after && !accepts(after.parentElement?.getAttribute("data-ge-box-kind"), "paragraph")) after = after.parentElement?.closest(OUTER);
|
|
@@ -709,10 +724,12 @@ function insertBelow(target, type, typed = null) {
|
|
|
709
724
|
after.after(fresh);
|
|
710
725
|
}
|
|
711
726
|
if (!fresh) return null;
|
|
727
|
+
const prior = fresh.previousSibling; // what the new block stands right after, made where the paragraph was
|
|
712
728
|
const turned = type === "paragraph" && fresh.localName === "p" ? { focus: null, created: [] } : convertBlock(fresh, type, { fresh: true });
|
|
729
|
+
also?.done?.(fresh.isConnected ? fresh : prior?.nextElementSibling ?? null);
|
|
713
730
|
const focus = turned.focus ?? fresh;
|
|
714
731
|
return { touched: splits ? [target, focus] : [focus], focus, created: turned.created };
|
|
715
|
-
});
|
|
732
|
+
}, { attributes: also?.attributes ?? [] });
|
|
716
733
|
if (result) afterConvert(result.focus, type, t("已插入{0}", menuRow(type).label));
|
|
717
734
|
}
|
|
718
735
|
|
|
@@ -1160,7 +1177,8 @@ async function newSubpage(title) {
|
|
|
1160
1177
|
}
|
|
1161
1178
|
|
|
1162
1179
|
// The report's title as the reader sees it now (while editing, the title block's text).
|
|
1163
|
-
const
|
|
1180
|
+
const titleNode = () => document.querySelector('[data-ge-kind="title"]') ?? document.querySelector("h1.doc-title, .doc-header h1");
|
|
1181
|
+
const currentTitle = () => titleNode()?.textContent.replace(/\s+/g, " ").trim() ?? "";
|
|
1164
1182
|
|
|
1165
1183
|
// This page, as the list of pages takes it (links/pages.mjs).
|
|
1166
1184
|
const thisPage = () => ({ slug: MAP.slug, title: currentTitle() });
|
|
@@ -1454,8 +1472,20 @@ function handOff() {
|
|
|
1454
1472
|
function connect() {
|
|
1455
1473
|
// The look the page shows (字体与布局: its <html>'s, src/shared/document-look.mjs), which the workbench's
|
|
1456
1474
|
// 更多 marks as chosen; told again when it changes (the kit's ui.js, doc-look-change).
|
|
1457
|
-
|
|
1475
|
+
// `title`: null for a page with no title at all (the workbench names it by its doc.json); "" an untitled one (未命名文档).
|
|
1476
|
+
workbench = connectWorkbench({ slug: MAP.slug, snapshot: () => ({ title: titleNode() ? currentTitle() : null, icon: pageIcon(), look: lookOfElement(document.documentElement), state: sessionState(), annotations: annotate?.count() }), commands: COMMANDS, modals: modalOps() });
|
|
1458
1477
|
addEventListener("doc-look-change", () => workbench?.update());
|
|
1478
|
+
// A block's context.workspace.open (the kit's runtime/workspace.js): a document, or a block of one, goes
|
|
1479
|
+
// where a link to it goes (goTo: in the workbench, its address; on its own, the page once saved); a custom
|
|
1480
|
+
// page, the workbench's #@<slug>, or /pages/<slug> once saved.
|
|
1481
|
+
addEventListener("doc-open-request", (event) => {
|
|
1482
|
+
const { slug = null, block = null, page = null } = event.detail ?? {};
|
|
1483
|
+
event.preventDefault();
|
|
1484
|
+
if (page) {
|
|
1485
|
+
if (window.parent !== window && !SOLO) workbench?.open({ hash: `@${page}` });
|
|
1486
|
+
else COMMANDS["prepare-close"]().then(() => location.assign(`/pages/${page}`));
|
|
1487
|
+
} else goTo({ slug, block }, `/generated/${slug}.html${block ? `#${encodeURIComponent(block)}` : ""}`);
|
|
1488
|
+
});
|
|
1459
1489
|
relayTo(workbench ? workbench.notice : null, workbench ? workbench.noticeRoom : null); // the workbench shows the page's notices, above the page's bottom panels
|
|
1460
1490
|
handOff();
|
|
1461
1491
|
// A page on its own in a frame (?solo: the 写作偏好 dialog's, which no session asks to save) is saved
|
|
@@ -1514,6 +1544,10 @@ async function start() {
|
|
|
1514
1544
|
TAB = newTab();
|
|
1515
1545
|
session.set(keys.tab, TAB);
|
|
1516
1546
|
}
|
|
1547
|
+
// What earlier pages of the document committed, made and wrote (this tab's, and those of tabs no longer
|
|
1548
|
+
// open), asked of at once where this page opened on another version of the file than they last knew
|
|
1549
|
+
// (its cards and list said through the workbench).
|
|
1550
|
+
autosave?.opened(open);
|
|
1517
1551
|
const prefix = pendingKey(MAP.slug, "");
|
|
1518
1552
|
const left = local.keys().filter((key) => key.startsWith(prefix) && key !== pendingKey(MAP.slug, TAB) && !open.has(key.slice(prefix.length)));
|
|
1519
1553
|
if (left.length === 0) return;
|
|
@@ -1573,7 +1607,7 @@ function showLost() {
|
|
|
1573
1607
|
if (block) {
|
|
1574
1608
|
panelItem(
|
|
1575
1609
|
element("p", { text: t("文件里的这一块已被修改:复制你的版本,再粘贴到页面上。") }),
|
|
1576
|
-
element("div", { class: "ge-actions" },
|
|
1610
|
+
element("div", { class: "ge-actions" }, textButton(t("复制这一块"), () => { if (!clipboard.copyBlocks([block])) say(t("没能完成,请再试一次。"), "error"); })),
|
|
1577
1611
|
);
|
|
1578
1612
|
continue;
|
|
1579
1613
|
}
|
|
@@ -1581,10 +1615,10 @@ function showLost() {
|
|
|
1581
1615
|
panelItem(
|
|
1582
1616
|
element("p", { text: LOST[item.why] ?? LOST.refused }),
|
|
1583
1617
|
element("div", { class: "ge-version", text }),
|
|
1584
|
-
element("div", { class: "ge-actions" },
|
|
1618
|
+
element("div", { class: "ge-actions" }, textButton(t("复制文字"), () => navigator.clipboard?.writeText(text).then(() => say(t("已复制。"))))),
|
|
1585
1619
|
);
|
|
1586
1620
|
}
|
|
1587
|
-
panelItem(element("div", { class: "ge-actions" },
|
|
1621
|
+
panelItem(element("div", { class: "ge-actions" }, textButton(t("都处理好了,不再保留"), () => {
|
|
1588
1622
|
local.remove(lostKey(MAP.slug));
|
|
1589
1623
|
closePanel();
|
|
1590
1624
|
}, { primary: true })));
|
|
@@ -1617,10 +1651,13 @@ function boot() {
|
|
|
1617
1651
|
copyLink: SOLO ? null : copyBlockLink, // what ?solo shows (写作偏好) only its dialog opens: no address leads there
|
|
1618
1652
|
linkAhead: () => holdPages(thisPage),
|
|
1619
1653
|
});
|
|
1620
|
-
resize = createResize({ units, active, look: lookStep, say, owns: (node) => tables?.owns(node) ?? false });
|
|
1621
|
-
gaps = createColumnGaps({ active, struct, look: lookStep, say });
|
|
1654
|
+
resize = createResize({ units, active, look: lookStep, say, settle, owns: (node) => tables?.owns(node) ?? false });
|
|
1655
|
+
gaps = createColumnGaps({ active, struct, look: lookStep, say, settle });
|
|
1622
1656
|
for (const page of pageObjects()) page.install?.(); // the round "+" at a flowchart node's right, renaming Sheet tabs
|
|
1623
|
-
tables = createTableEditing({
|
|
1657
|
+
tables = createTableEditing({
|
|
1658
|
+
active, struct, look: lookStep, selectBlock: (unit) => blocks.select(unit), resizeTable: (event, unit, axis) => resize.startTable(event, unit, axis), say, cellsOf: (data) => clipboard.cellsOf(data), upload: uploadTo, typedKey,
|
|
1659
|
+
recordStep, insertBelow: (unit, type, also) => insertBelow(unit, type, null, also),
|
|
1660
|
+
});
|
|
1624
1661
|
selectAll = createSelectAll({ blocks, say, cells: { table: () => tables.selectedTable, clear: () => tables.clear() } });
|
|
1625
1662
|
createFrame(() => editing);
|
|
1626
1663
|
createFlags(() => editing);
|
|
@@ -64,14 +64,14 @@ export const PICKER_CSS = `
|
|
|
64
64
|
.nmm-cell.focus-visible { background: var(--ge-press); }
|
|
65
65
|
.nmm-cell img { display: block; }
|
|
66
66
|
.nmm-cell img.notion-custom-emoji { object-fit: contain; color: transparent; }
|
|
67
|
-
/* 添加表情符号: the custom group's first cell, a round plus (26, 3 around,
|
|
68
|
-
|
|
69
|
-
.nmm-cell.nmm-add-cell { width: 26px; height: 26px; margin: 3px; box-sizing: border-box; border-radius: 50%;
|
|
67
|
+
/* 添加表情符号: the custom group's first cell, a round plus (26, 3 around, the plus --ge-ico3, no line round
|
|
68
|
+
it: gray under the pointer as a cell); with no result, a button (28 high, 13px / 500, no line either) */
|
|
69
|
+
.nmm-cell.nmm-add-cell { width: 26px; height: 26px; margin: 3px; box-sizing: border-box; border-radius: 50%; --nmm-icon: var(--ge-ico3); }
|
|
70
70
|
.nmm-cell.nmm-add-cell.focused { --nmm-icon: var(--ge-ico); }
|
|
71
71
|
.nmm-empty { padding: 8px 12px; }
|
|
72
72
|
.nmm-empty-caption { display: flex; align-items: center; height: 20px; padding: 0 4px; font-size: 12px; font-weight: 500; color: var(--ge-tx3); }
|
|
73
73
|
.nmm-empty.with-add { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
|
|
74
|
-
.nmm-cell.nmm-add-button { justify-content: flex-start; gap: 6px; width: max-content; height: 28px; padding: 0 10px 0 8px; box-sizing: border-box; border-radius: 6px;
|
|
74
|
+
.nmm-cell.nmm-add-button { justify-content: flex-start; gap: 6px; width: max-content; height: 28px; padding: 0 10px 0 8px; box-sizing: border-box; border-radius: 6px; font-size: 13px; font-weight: 500; line-height: 1; color: var(--ge-tx); white-space: nowrap; --nmm-icon: var(--ge-ico2); }
|
|
75
75
|
|
|
76
76
|
/* The category bar: a --ge-line above it, 6 12 8; buttons 28 x 28, icons 18 in --ge-ico3; the group scrolled
|
|
77
77
|
to on --ge-hover, its icon --ge-ico; a group with no emoji faded to .35 and not to be clicked (自定义 and
|
|
@@ -106,8 +106,8 @@ export const PICKER_CSS = `
|
|
|
106
106
|
|
|
107
107
|
/* The 上传 tab and the 添加表情符号 popup (upload.mjs): the zone an image goes in on --ge-field, a 1px
|
|
108
108
|
--ge-edge inside it, rounded 8, deeper while a file is dragged over it (--ge-hover, --ge-ico3), never blue;
|
|
109
|
-
保存
|
|
110
|
-
|
|
109
|
+
保存 the pale blue primary and 取消 / 返回 the plain text button (look.mjs BUTTONS: .ge-btn, dimmed while it cannot be
|
|
110
|
+
clicked); the checkbox checked --ge-tx2 with a white tick; an error --ge-red */
|
|
111
111
|
.nmm-upload { display: flex; flex-direction: column; padding: 0 16px; font-size: 14px; color: var(--ge-tx); }
|
|
112
112
|
.nmm-upload-title { margin-top: 14px; font-size: 14px; font-weight: 600; }
|
|
113
113
|
.nmm-upload-description { margin-top: 2px; font-size: 12px; color: var(--ge-tx2); }
|
|
@@ -142,12 +142,7 @@ export const PICKER_CSS = `
|
|
|
142
142
|
.nmm-upload-name-error { margin-top: 10px; font-size: 12px; color: var(--ge-red); }
|
|
143
143
|
.nmm-upload-name-error[hidden], .nmm-upload [hidden] { display: none; }
|
|
144
144
|
.nmm-upload-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 16px 0 12px; }
|
|
145
|
-
.nmm-upload-secondary, .nmm-upload-save {
|
|
146
|
-
.nmm-upload-secondary { color: var(--ge-tx2); }
|
|
147
|
-
.nmm-upload-secondary:hover { background: var(--ge-hover); color: var(--ge-tx); }
|
|
148
|
-
.nmm-upload-save { color: var(--ge-tx); font-weight: 500; }
|
|
149
|
-
.nmm-upload-save:not(.disabled):hover { background: var(--ge-hover); }
|
|
150
|
-
.nmm-upload-save.disabled { color: var(--ge-tx3); cursor: default; }
|
|
145
|
+
.nmm-upload-secondary, .nmm-upload-save { font-size: 14px; }
|
|
151
146
|
.nmm-custom-emoji-popup { min-width: 280px; border-radius: 10px; background: var(--ge-bg); box-shadow: var(--ge-shadow-pop); }
|
|
152
147
|
|
|
153
148
|
/* A button reached by Tab: a gray fill, not the browser's dark or blue ring; the checkbox a gray ring */
|
|
@@ -76,8 +76,8 @@ export function createUploadForm({ showTitle = false, largeEmoji = false, allowU
|
|
|
76
76
|
`<label class="nmm-upload-name" hidden><div class="nmm-upload-name-label">${T.nameLabel}</div>` +
|
|
77
77
|
`<div class="nmm-upload-input"><input type="text" placeholder="${T.namePlaceholder}" autocomplete="off" spellcheck="false"></div>` +
|
|
78
78
|
`<div class="nmm-upload-name-error" hidden></div></label>` +
|
|
79
|
-
`<div class="nmm-upload-footer"><div role="button" tabindex="0" class="nmm-upload-secondary" data-act="secondary"></div>` +
|
|
80
|
-
`<div role="button" tabindex="0" class="nmm-upload-save" data-act="save">${T.save}</div></div>` +
|
|
79
|
+
`<div class="nmm-upload-footer"><div role="button" tabindex="0" class="ge-btn nmm-upload-secondary" data-act="secondary"></div>` +
|
|
80
|
+
`<div role="button" tabindex="0" class="ge-btn nmm-upload-save" data-primary data-act="save">${T.save}</div></div>` +
|
|
81
81
|
`<input type="file" accept="${ACCEPT}" hidden>`;
|
|
82
82
|
|
|
83
83
|
const zone = el.querySelector('.nmm-upload-zone'), wrap = el.querySelector('.nmm-upload-zone-wrap');
|
|
@@ -44,13 +44,12 @@ import { t } from "../../../shared/i18n/index.mjs";
|
|
|
44
44
|
// (lineAt, blocks.mjs). The handle and the bar are drawn in the editor's own layer (overlay-layer.mjs:
|
|
45
45
|
// the one of the block they stand beside), never inside a block, each belonging to the block it stands
|
|
46
46
|
// beside (overlays.mjs). A press ends when the pointer comes up, is cancelled, or the handle loses the
|
|
47
|
-
// pointer capture (then a drag under way is cancelled, never dropped).
|
|
47
|
+
// pointer capture (then a drag under way is cancelled, never dropped). On a page the editor edits, its
|
|
48
48
|
// side gutters (the kit's --doc-page-gutter, --doc-wide-gutter) are at least the room the
|
|
49
|
-
// handle takes left of a block, and a little (
|
|
50
|
-
//
|
|
51
|
-
// the right. A wide window, whose column
|
|
52
|
-
|
|
53
|
-
const EDGE = ADD.width + HANDLE.width + HANDLE.gap + 12; // the page's gutter while editing: the bar's square, the grip, its gap, and room to breathe (64)
|
|
49
|
+
// handle takes left of a block, and a little (margin.mjs MARGIN.edge, from the page's first paint: the
|
|
50
|
+
// head's MARGIN_STYLE): on a narrow window the handle stands in the margin, never over the text, as
|
|
51
|
+
// Feishu's and Notion's do; the section bar has the same room on the right. A wide window, whose column
|
|
52
|
+
// leaves more than that, does not change.
|
|
54
53
|
|
|
55
54
|
const STYLE = `
|
|
56
55
|
.ge-handle { position: absolute; left: 0; top: 0; z-index: ${IN_LAYER.handle}; display: flex; align-items: center; height: ${HANDLE.height}px; touch-action: none; }
|
|
@@ -84,8 +83,6 @@ const STYLE = `
|
|
|
84
83
|
.ge-section-bar::before { content: ""; position: absolute; top: 0; bottom: 0; left: 6px; width: 4px; border-radius: 2px; background: light-dark(rgb(55 53 47 / 14%), rgb(255 255 255 / 14%)); transition: background .08s ease-in; }
|
|
85
84
|
.ge-section-bar:hover::before { background: light-dark(rgb(55 53 47 / 28%), rgb(255 255 255 / 26%)); }
|
|
86
85
|
.ge-section-bar[data-active]::before { background: color-mix(in srgb, var(--doc-accent, #2678d8) 60%, transparent); }
|
|
87
|
-
/* Room for the handle beside the page's blocks: the page's gutters while editing (resize/ reads --ge-edge-room). */
|
|
88
|
-
:root[data-ge-editing] { --ge-edge-room: ${EDGE}px; --doc-page-gutter: var(--ge-edge-room); --doc-wide-gutter: var(--ge-edge-room); }
|
|
89
86
|
`;
|
|
90
87
|
|
|
91
88
|
// Notion's grip in size (its dragHandle icon at its icons' 20px): 2.5px dots 5px apart across and 6px down (notion-lite's were 5px down, the grip 2px shorter than Notion's: the user, 2026-10-26).
|
|
@@ -148,6 +148,23 @@ export function createHistory({ changed, beforeUndo, blocks, afterText, refuse =
|
|
|
148
148
|
for (const stack of [undoStack, redoStack]) if (stack.includes(step)) stack.splice(stack.indexOf(step), 1);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// An attribute the file gave another value than the page had (`changes`: [element, name, from, to],
|
|
152
|
+
// `to` null for none; a key of a table a commit gave a pair anew: page/commit.mjs apply), the page's
|
|
153
|
+
// element set so: the steps that recorded `from` of it record `to` instead, so that an undo or a redo
|
|
154
|
+
// puts back what the file has, never the value it changed (a table's 视图 › redone with the key its view
|
|
155
|
+
// no longer carries).
|
|
156
|
+
function rekeyed(changes) {
|
|
157
|
+
if (changes.length === 0) return;
|
|
158
|
+
for (const step of [...undoStack, ...redoStack]) {
|
|
159
|
+
for (const recorded of [step.attributesBefore, step.attributesAfter]) {
|
|
160
|
+
for (const [element, name, from, to] of changes) {
|
|
161
|
+
const values = recorded?.get(element);
|
|
162
|
+
if (values?.some(([each, value]) => each === name && value === from)) recorded.set(element, values.map(([each, value]) => [each, each === name && value === from ? to : value]));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
151
168
|
// What a step puts into a block (`from`: what the step left there, `to`: what it puts back): as
|
|
152
169
|
// recorded, unless someone else's words were merged into the block since the step; then the step's
|
|
153
170
|
// change three ways against what the block holds now (null: the two touch the same place).
|
|
@@ -174,8 +191,10 @@ export function createHistory({ changed, beforeUndo, blocks, afterText, refuse =
|
|
|
174
191
|
// after undo and redo (a deleted Sheet tab switches the Sheet shown). A step that names no text block
|
|
175
192
|
// it came from keeps where the caret stood, which undo puts back, as notion-lite's selectionBefore.
|
|
176
193
|
// `attributes`: [element, [names]] whose attributes the step records too (a table's cells: their
|
|
177
|
-
// spans and widths, which its operations change: components/table/page.mjs).
|
|
178
|
-
|
|
194
|
+
// spans and widths, which its operations change: components/table/page.mjs). `caret`: where the caret
|
|
195
|
+
// stood in the first text block it touched is kept too, which undo puts back (notion-lite's Enter in the
|
|
196
|
+
// page's title, enter.js: "撤销后光标回到回车前的位置"; typing/ enterBody).
|
|
197
|
+
function struct(parents, touched, mutate, { attributes = [], caret = false } = {}) {
|
|
179
198
|
closeTyping();
|
|
180
199
|
// What the change may leave untidy is tidied after it by the components that know (rows of
|
|
181
200
|
// columns with a column emptied, lists set side by side: tidy), so what they name is recorded
|
|
@@ -189,7 +208,7 @@ export function createHistory({ changed, beforeUndo, blocks, afterText, refuse =
|
|
|
189
208
|
}
|
|
190
209
|
// A text block among the parents (a list item whose lists change) keeps its text through undo too.
|
|
191
210
|
touched = [...new Set([...touched, ...parents.filter(isHost)])];
|
|
192
|
-
const place = touched[0] ? null : caretPlace(parents[0]);
|
|
211
|
+
const place = touched[0] && !caret ? null : caretPlace(parents[0]);
|
|
193
212
|
const before = parents.map(contentOf);
|
|
194
213
|
const htmlBefore = new Map(touched.map((node) => [node, ownHTML(node)]));
|
|
195
214
|
const classesBefore = new Map(touched.map((node) => [node, new Set(node.classList)]));
|
|
@@ -219,7 +238,7 @@ export function createHistory({ changed, beforeUndo, blocks, afterText, refuse =
|
|
|
219
238
|
.filter(({ added, removed }) => added.length > 0 || removed.length > 0),
|
|
220
239
|
attributesBefore,
|
|
221
240
|
attributesAfter: attributesOf(),
|
|
222
|
-
focusBefore: touched[0] ?? place?.host,
|
|
241
|
+
focusBefore: (caret ? place?.host : null) ?? touched[0] ?? place?.host,
|
|
223
242
|
caretBefore: place?.offsets ?? null,
|
|
224
243
|
focusAfter: result.focus,
|
|
225
244
|
select: result.select ?? null,
|
|
@@ -381,6 +400,7 @@ export function createHistory({ changed, beforeUndo, blocks, afterText, refuse =
|
|
|
381
400
|
sourceStep,
|
|
382
401
|
fold,
|
|
383
402
|
drop,
|
|
403
|
+
rekeyed,
|
|
384
404
|
closeTyping,
|
|
385
405
|
struct,
|
|
386
406
|
finish,
|
|
@@ -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). */
|