@heycys/gallery 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +50 -2
- package/THIRD-PARTY-NOTICES.md +3303 -0
- package/assets/writing-preferences.md +107 -0
- package/bin/gallery.mjs +10 -0
- package/browser/editor/components/bookmark/icons.mjs +6 -0
- package/browser/editor/components/bookmark/index.mjs +80 -0
- package/browser/editor/components/bookmark/page.mjs +147 -0
- package/browser/editor/components/builders.mjs +19 -0
- package/browser/editor/components/callout/index.mjs +64 -0
- package/browser/editor/components/code/index.mjs +327 -0
- package/browser/editor/components/code/page.mjs +561 -0
- package/browser/editor/components/colors.mjs +50 -0
- package/browser/editor/components/columns/index.mjs +104 -0
- package/browser/editor/components/columns/page.mjs +310 -0
- package/browser/editor/components/details/index.mjs +73 -0
- package/browser/editor/components/details/page.mjs +86 -0
- package/browser/editor/components/dialog/index.mjs +84 -0
- package/browser/editor/components/dialog/page.mjs +201 -0
- package/browser/editor/components/divider/index.mjs +48 -0
- package/browser/editor/components/embed/icons.mjs +11 -0
- package/browser/editor/components/embed/index.mjs +123 -0
- package/browser/editor/components/embed/page.mjs +309 -0
- package/browser/editor/components/figure/index.mjs +87 -0
- package/browser/editor/components/figure/page.mjs +42 -0
- package/browser/editor/components/file/icons.mjs +14 -0
- package/browser/editor/components/file/index.mjs +77 -0
- package/browser/editor/components/file/page.mjs +114 -0
- package/browser/editor/components/flowchart/add.mjs +123 -0
- package/browser/editor/components/flowchart/index.mjs +246 -0
- package/browser/editor/components/flowchart/page.mjs +453 -0
- package/browser/editor/components/heading/index.mjs +53 -0
- package/browser/editor/components/heading/page.mjs +6 -0
- package/browser/editor/components/highlight/index.mjs +63 -0
- package/browser/editor/components/icon/index.mjs +57 -0
- package/browser/editor/components/icon/page.mjs +286 -0
- package/browser/editor/components/icons.mjs +48 -0
- package/browser/editor/components/image/crop.mjs +189 -0
- package/browser/editor/components/image/index.mjs +104 -0
- package/browser/editor/components/image/page.mjs +385 -0
- package/browser/editor/components/image/viewer.mjs +213 -0
- package/browser/editor/components/installed/index.mjs +179 -0
- package/browser/editor/components/installed/page.mjs +523 -0
- package/browser/editor/components/installed/served.mjs +35 -0
- package/browser/editor/components/kit.mjs +67 -0
- package/browser/editor/components/list/index.mjs +194 -0
- package/browser/editor/components/list/join.mjs +68 -0
- package/browser/editor/components/list/numbers.mjs +107 -0
- package/browser/editor/components/list/page.mjs +632 -0
- package/browser/editor/components/math/index.mjs +88 -0
- package/browser/editor/components/math/page.mjs +236 -0
- package/browser/editor/components/math/tex-logo.mjs +6 -0
- package/browser/editor/components/media/icons.mjs +19 -0
- package/browser/editor/components/media/page.mjs +192 -0
- package/browser/editor/components/media/parts.mjs +60 -0
- package/browser/editor/components/media/size.mjs +20 -0
- package/browser/editor/components/media/toolbar.mjs +37 -0
- package/browser/editor/components/media/write.mjs +7 -0
- package/browser/editor/components/pages.mjs +46 -0
- package/browser/editor/components/paragraph/index.mjs +43 -0
- package/browser/editor/components/paragraph/page.mjs +52 -0
- package/browser/editor/components/placeholder-bar.mjs +17 -0
- package/browser/editor/components/placeholder.mjs +128 -0
- package/browser/editor/components/quote/index.mjs +33 -0
- package/browser/editor/components/registry.mjs +859 -0
- package/browser/editor/components/rows.mjs +16 -0
- package/browser/editor/components/section/index.mjs +42 -0
- package/browser/editor/components/section/page.mjs +141 -0
- package/browser/editor/components/set-apart.mjs +24 -0
- package/browser/editor/components/sheets/index.mjs +137 -0
- package/browser/editor/components/sheets/page.mjs +227 -0
- package/browser/editor/components/sheets/pills.mjs +226 -0
- package/browser/editor/components/table/grid.mjs +73 -0
- package/browser/editor/components/table/index.mjs +308 -0
- package/browser/editor/components/table/page.mjs +683 -0
- package/browser/editor/components/table/slots.mjs +41 -0
- package/browser/editor/components/widget/index.mjs +50 -0
- package/browser/editor/page/annotate/anchors.mjs +230 -0
- package/browser/editor/page/annotate/card.mjs +102 -0
- package/browser/editor/page/annotate/index.mjs +1656 -0
- package/browser/editor/page/at-menu/index.mjs +317 -0
- package/browser/editor/page/autosave.mjs +1023 -0
- package/browser/editor/page/beside.mjs +21 -0
- package/browser/editor/page/block-info.mjs +63 -0
- package/browser/editor/page/block-menu/colors.mjs +84 -0
- package/browser/editor/page/block-menu/index.mjs +217 -0
- package/browser/editor/page/blocks.mjs +255 -0
- package/browser/editor/page/caret.mjs +682 -0
- package/browser/editor/page/changes/bar.mjs +102 -0
- package/browser/editor/page/changes/ghost.mjs +206 -0
- package/browser/editor/page/changes/gone-words.mjs +94 -0
- package/browser/editor/page/changes/index.mjs +447 -0
- package/browser/editor/page/changes/words.mjs +27 -0
- package/browser/editor/page/chip-fills.mjs +126 -0
- package/browser/editor/page/clipboard/import/colors.mjs +192 -0
- package/browser/editor/page/clipboard/import/html.mjs +792 -0
- package/browser/editor/page/clipboard/import/inline.mjs +232 -0
- package/browser/editor/page/clipboard/import/languages.mjs +42 -0
- package/browser/editor/page/clipboard/import/markdown.mjs +760 -0
- package/browser/editor/page/clipboard/import/math.mjs +100 -0
- package/browser/editor/page/clipboard/import/office.mjs +245 -0
- package/browser/editor/page/clipboard/import/read.mjs +120 -0
- package/browser/editor/page/clipboard/import/rich.mjs +29 -0
- package/browser/editor/page/clipboard/import/to-blocks.mjs +290 -0
- package/browser/editor/page/clipboard/index.mjs +816 -0
- package/browser/editor/page/clipboard/own/blocks.mjs +211 -0
- package/browser/editor/page/clipboard/own/chart-keys.mjs +58 -0
- package/browser/editor/page/clipboard/own/describe.mjs +124 -0
- package/browser/editor/page/clipboard/own/export.mjs +167 -0
- package/browser/editor/page/clipboard/own/ids.mjs +39 -0
- package/browser/editor/page/clipboard/own/index.mjs +13 -0
- package/browser/editor/page/clipboard/own/rules.mjs +44 -0
- package/browser/editor/page/clipboard/own/selection.mjs +159 -0
- package/browser/editor/page/clipboard/own/writers.mjs +315 -0
- package/browser/editor/page/columns/index.mjs +360 -0
- package/browser/editor/page/commit.mjs +1813 -0
- package/browser/editor/page/conflicts.mjs +249 -0
- package/browser/editor/page/convert.mjs +831 -0
- package/browser/editor/page/core.mjs +1693 -0
- package/browser/editor/page/drag/drop.mjs +307 -0
- package/browser/editor/page/drag/index.mjs +351 -0
- package/browser/editor/page/drag/preview.mjs +126 -0
- package/browser/editor/page/edge-scroll.mjs +50 -0
- package/browser/editor/page/editor.mjs +1780 -0
- package/browser/editor/page/emoji-picker/emoji-tab.mjs +287 -0
- package/browser/editor/page/emoji-picker/glyph-html.mjs +26 -0
- package/browser/editor/page/emoji-picker/grid.mjs +81 -0
- package/browser/editor/page/emoji-picker/icon-tab.mjs +217 -0
- package/browser/editor/page/emoji-picker/icons.mjs +31 -0
- package/browser/editor/page/emoji-picker/index.mjs +166 -0
- package/browser/editor/page/emoji-picker/styles.mjs +161 -0
- package/browser/editor/page/emoji-picker/support.mjs +204 -0
- package/browser/editor/page/emoji-picker/upload.mjs +236 -0
- package/browser/editor/page/export-report.mjs +23 -0
- package/browser/editor/page/fills.mjs +62 -0
- package/browser/editor/page/find/index.mjs +107 -0
- package/browser/editor/page/flags.mjs +70 -0
- package/browser/editor/page/fold/index.mjs +348 -0
- package/browser/editor/page/fold/rule.mjs +125 -0
- package/browser/editor/page/folded.mjs +23 -0
- package/browser/editor/page/format-bar/bar.mjs +449 -0
- package/browser/editor/page/format-bar/brush.mjs +77 -0
- package/browser/editor/page/format-bar/colors.mjs +46 -0
- package/browser/editor/page/format-bar/index.mjs +404 -0
- package/browser/editor/page/formula/index.mjs +236 -0
- package/browser/editor/page/formula/panel.mjs +336 -0
- package/browser/editor/page/formula/symbols.mjs +156 -0
- package/browser/editor/page/frame.mjs +74 -0
- package/browser/editor/page/frames.mjs +196 -0
- package/browser/editor/page/geometry.mjs +402 -0
- package/browser/editor/page/gesture.mjs +45 -0
- package/browser/editor/page/handle/index.mjs +650 -0
- package/browser/editor/page/handle-sizes.mjs +14 -0
- package/browser/editor/page/hints/index.mjs +84 -0
- package/browser/editor/page/history.mjs +401 -0
- package/browser/editor/page/insert/index.mjs +256 -0
- package/browser/editor/page/kept.mjs +38 -0
- package/browser/editor/page/links/address.mjs +40 -0
- package/browser/editor/page/links/index.mjs +866 -0
- package/browser/editor/page/links/pages.mjs +131 -0
- package/browser/editor/page/links/views.mjs +369 -0
- package/browser/editor/page/long-runs.mjs +75 -0
- package/browser/editor/page/look.mjs +77 -0
- package/browser/editor/page/made.mjs +24 -0
- package/browser/editor/page/margin.mjs +373 -0
- package/browser/editor/page/markdown/index.mjs +88 -0
- package/browser/editor/page/markdown/rules.mjs +33 -0
- package/browser/editor/page/marks.mjs +377 -0
- package/browser/editor/page/media-menu/index.mjs +158 -0
- package/browser/editor/page/menu.mjs +544 -0
- package/browser/editor/page/merge.mjs +124 -0
- package/browser/editor/page/notices.mjs +142 -0
- package/browser/editor/page/offered.mjs +32 -0
- package/browser/editor/page/outline/folds.mjs +53 -0
- package/browser/editor/page/outline/index.mjs +783 -0
- package/browser/editor/page/outline/list.mjs +184 -0
- package/browser/editor/page/outline/read.mjs +201 -0
- package/browser/editor/page/outline/strip.mjs +287 -0
- package/browser/editor/page/outline/tree.mjs +248 -0
- package/browser/editor/page/overlay-layer.mjs +227 -0
- package/browser/editor/page/overlays.mjs +205 -0
- package/browser/editor/page/own.mjs +28 -0
- package/browser/editor/page/pads.mjs +71 -0
- package/browser/editor/page/page-objects.mjs +105 -0
- package/browser/editor/page/panel.mjs +65 -0
- package/browser/editor/page/placement.mjs +58 -0
- package/browser/editor/page/post.mjs +41 -0
- package/browser/editor/page/present-links.mjs +50 -0
- package/browser/editor/page/quiet.mjs +48 -0
- package/browser/editor/page/resize/index.mjs +327 -0
- package/browser/editor/page/select-all/index.mjs +262 -0
- package/browser/editor/page/selection/delete.mjs +61 -0
- package/browser/editor/page/selection/index.mjs +164 -0
- package/browser/editor/page/selection/marquee.mjs +174 -0
- package/browser/editor/page/session.mjs +168 -0
- package/browser/editor/page/slash-menu/index.mjs +291 -0
- package/browser/editor/page/storage.mjs +48 -0
- package/browser/editor/page/sync-state.mjs +267 -0
- package/browser/editor/page/table/aligns.mjs +29 -0
- package/browser/editor/page/table/cell-bar.mjs +141 -0
- package/browser/editor/page/table/cells.mjs +527 -0
- package/browser/editor/page/table/icons.mjs +40 -0
- package/browser/editor/page/table/index.mjs +990 -0
- package/browser/editor/page/table/lists.mjs +187 -0
- package/browser/editor/page/table/widths.mjs +313 -0
- package/browser/editor/page/tex.mjs +32 -0
- package/browser/editor/page/text-select/index.mjs +671 -0
- package/browser/editor/page/tooltip.mjs +98 -0
- package/browser/editor/page/type-grid.mjs +83 -0
- package/browser/editor/page/typing/code-edges.mjs +274 -0
- package/browser/editor/page/typing/index.mjs +282 -0
- package/browser/editor/page/typing/leave.mjs +68 -0
- package/browser/editor/page/ui.mjs +160 -0
- package/browser/shared/annotations.mjs +569 -0
- package/browser/shared/code-folds.mjs +14 -0
- package/browser/shared/code-languages.mjs +70 -0
- package/browser/shared/code-lines.mjs +30 -0
- package/browser/shared/colors.mjs +30 -0
- package/browser/shared/component-catalog.mjs +573 -0
- package/browser/shared/components/bookmark.mjs +26 -0
- package/browser/shared/components/callout.mjs +9 -0
- package/browser/shared/components/chart.mjs +20 -0
- package/browser/shared/components/code.mjs +37 -0
- package/browser/shared/components/columns.mjs +16 -0
- package/browser/shared/components/details.mjs +15 -0
- package/browser/shared/components/dialog.mjs +28 -0
- package/browser/shared/components/diff.mjs +18 -0
- package/browser/shared/components/divider.mjs +6 -0
- package/browser/shared/components/embed.mjs +25 -0
- package/browser/shared/components/figure.mjs +14 -0
- package/browser/shared/components/file.mjs +23 -0
- package/browser/shared/components/heading.mjs +6 -0
- package/browser/shared/components/highlight.mjs +9 -0
- package/browser/shared/components/icon.mjs +18 -0
- package/browser/shared/components/image.mjs +39 -0
- package/browser/shared/components/index.mjs +396 -0
- package/browser/shared/components/installed.mjs +232 -0
- package/browser/shared/components/list.mjs +146 -0
- package/browser/shared/components/math.mjs +49 -0
- package/browser/shared/components/mention.mjs +33 -0
- package/browser/shared/components/page.mjs +46 -0
- package/browser/shared/components/paragraph.mjs +9 -0
- package/browser/shared/components/quote.mjs +6 -0
- package/browser/shared/components/section.mjs +8 -0
- package/browser/shared/components/sheets.mjs +80 -0
- package/browser/shared/components/state.mjs +20 -0
- package/browser/shared/components/table.mjs +49 -0
- package/browser/shared/components/text.mjs +14 -0
- package/browser/shared/components/widget.mjs +10 -0
- package/browser/shared/copy-ids.mjs +72 -0
- package/browser/shared/css-references.mjs +110 -0
- package/browser/shared/document-look.mjs +178 -0
- package/browser/shared/emoji/custom.mjs +91 -0
- package/browser/shared/emoji/data/LICENSE-lucide.txt +43 -0
- package/browser/shared/emoji/data/LICENSE-mingcute.txt +202 -0
- package/browser/shared/emoji/data/LICENSE-tabler.txt +21 -0
- package/browser/shared/emoji/data/README.md +28 -0
- package/browser/shared/emoji/data/categories.json +1 -0
- package/browser/shared/emoji/data/icons.json +1 -0
- package/browser/shared/emoji/data/keywords-en.json +1 -0
- package/browser/shared/emoji/data/keywords-zh.json +1 -0
- package/browser/shared/emoji/data/names.json +1 -0
- package/browser/shared/emoji/data/positions.json +1 -0
- package/browser/shared/emoji/data/twemoji-index.json +1 -0
- package/browser/shared/emoji/data/twemoji-svg.bin +0 -0
- package/browser/shared/emoji/data.mjs +194 -0
- package/browser/shared/emoji/emoji.mjs +38 -0
- package/browser/shared/emoji/glyphs.mjs +134 -0
- package/browser/shared/emoji/icon-value.mjs +91 -0
- package/browser/shared/escape.mjs +20 -0
- package/browser/shared/export-wrap.mjs +89 -0
- package/browser/shared/files.mjs +33 -0
- package/browser/shared/html-tree.mjs +59 -0
- package/browser/shared/http.mjs +22 -0
- package/browser/shared/i18n/en.mjs +1223 -0
- package/browser/shared/i18n/index.mjs +132 -0
- package/browser/shared/ids.mjs +24 -0
- package/browser/shared/import-types.mjs +23 -0
- package/browser/shared/inline-spacing.mjs +97 -0
- package/browser/shared/layers.mjs +42 -0
- package/browser/shared/long-runs.mjs +39 -0
- package/browser/shared/media.mjs +162 -0
- package/browser/shared/new-names.mjs +67 -0
- package/browser/shared/number-reading.mjs +92 -0
- package/browser/shared/old-names.mjs +143 -0
- package/browser/shared/outline.mjs +194 -0
- package/browser/shared/page-address.mjs +140 -0
- package/browser/shared/page-links.mjs +86 -0
- package/browser/shared/paths.mjs +73 -0
- package/browser/shared/preferences.mjs +116 -0
- package/browser/shared/preview-server.mjs +247 -0
- package/browser/shared/qa-levels.mjs +93 -0
- package/browser/shared/reading-place.mjs +91 -0
- package/browser/shared/renamed-storage.mjs +220 -0
- package/browser/shared/reports.mjs +46 -0
- package/browser/shared/search.mjs +85 -0
- package/browser/shared/session.mjs +77 -0
- package/browser/shared/table-chart.mjs +113 -0
- package/browser/shared/table-hides.mjs +120 -0
- package/browser/shared/table-slots.mjs +75 -0
- package/browser/shared/words.mjs +23 -0
- package/browser/shared/workspace-look.mjs +91 -0
- package/browser/shared/workspace.mjs +535 -0
- package/browser/shared/writing-preferences.mjs +68 -0
- package/browser/shared/zoom.mjs +57 -0
- package/dist/chunk-2B5E4CDJ.mjs +2 -0
- package/dist/chunk-342HXE3Q.mjs +2 -0
- package/dist/chunk-3HIRPVLU.mjs +2 -0
- package/dist/chunk-43B75J5T.mjs +2 -0
- package/dist/chunk-4FS7Z7WR.mjs +2 -0
- package/dist/chunk-4K5KC6V2.mjs +2 -0
- package/dist/chunk-5L7RYZCL.mjs +2 -0
- package/dist/chunk-5MHMDLZD.mjs +4 -0
- package/dist/chunk-5ZKJ3H4P.mjs +8 -0
- package/dist/chunk-64K7IPLO.mjs +255 -0
- package/dist/chunk-6QXGZM36.mjs +8 -0
- package/dist/chunk-6RGJOMJP.mjs +16 -0
- package/dist/chunk-742D2WWJ.mjs +19 -0
- package/dist/chunk-7DTINW6U.mjs +48 -0
- package/dist/chunk-A55HN5OK.mjs +2 -0
- package/dist/chunk-AGDILNWB.mjs +2 -0
- package/dist/chunk-AJ73XJF3.mjs +2 -0
- package/dist/chunk-AUZGSZJH.mjs +13 -0
- package/dist/chunk-BFE45AKL.mjs +2 -0
- package/dist/chunk-BGGDRNYQ.mjs +10 -0
- package/dist/chunk-BXO2ZY5P.mjs +2 -0
- package/dist/chunk-C564NU2H.mjs +77 -0
- package/dist/chunk-CEH4MRCC.mjs +2 -0
- package/dist/chunk-CY2FNNAB.mjs +16 -0
- package/dist/chunk-DFUDV4LX.mjs +2 -0
- package/dist/chunk-DKXG4XDG.mjs +2 -0
- package/dist/chunk-E7LWZRXY.mjs +4 -0
- package/dist/chunk-EZQ34M3F.mjs +124 -0
- package/dist/chunk-EZY3WC6Z.mjs +15 -0
- package/dist/chunk-FDLXYYG4.mjs +4 -0
- package/dist/chunk-FUKQNOQS.mjs +9 -0
- package/dist/chunk-GB5SOYQJ.mjs +7 -0
- package/dist/chunk-GRAXKKG4.mjs +2 -0
- package/dist/chunk-HYMEEXKN.mjs +4 -0
- package/dist/chunk-IVDLMMBD.mjs +2 -0
- package/dist/chunk-JPOSLGOC.mjs +6 -0
- package/dist/chunk-JVHHHGEA.mjs +3 -0
- package/dist/chunk-L3QKH4OK.mjs +26 -0
- package/dist/chunk-LAE5NQ4B.mjs +2 -0
- package/dist/chunk-LCTHTZIL.mjs +960 -0
- package/dist/chunk-LEF6DRCK.mjs +59 -0
- package/dist/chunk-LKX55H76.mjs +2 -0
- package/dist/chunk-LS4F7JUM.mjs +2 -0
- package/dist/chunk-MAFIGVXY.mjs +2 -0
- package/dist/chunk-NO5NJCHO.mjs +2 -0
- package/dist/chunk-NQPVAU63.mjs +2 -0
- package/dist/chunk-NSKUTQ5J.mjs +5 -0
- package/dist/chunk-O35FIXRB.mjs +2 -0
- package/dist/chunk-P2CAZPDP.mjs +3 -0
- package/dist/chunk-PL6GHLGD.mjs +15 -0
- package/dist/chunk-QAIHRH3I.mjs +13 -0
- package/dist/chunk-QJIR2BLP.mjs +6 -0
- package/dist/chunk-QR6A54KJ.mjs +3 -0
- package/dist/chunk-QUPLVPB2.mjs +7 -0
- package/dist/chunk-R7BNENLY.mjs +4 -0
- package/dist/chunk-S6O4UHLC.mjs +2 -0
- package/dist/chunk-SGJWQKEI.mjs +2 -0
- package/dist/chunk-SYGN7GLU.mjs +2 -0
- package/dist/chunk-TMYZB6AV.mjs +2 -0
- package/dist/chunk-TX6JH7TR.mjs +2 -0
- package/dist/chunk-TYK6VNAB.mjs +10 -0
- package/dist/chunk-U3SSPL4K.mjs +8 -0
- package/dist/chunk-U6KNPJPR.mjs +2 -0
- package/dist/chunk-UALRNVSE.mjs +4 -0
- package/dist/chunk-UH4SIXTR.mjs +2 -0
- package/dist/chunk-UMHUSOPJ.mjs +2 -0
- package/dist/chunk-V3HXVQEM.mjs +2 -0
- package/dist/chunk-V5JTW2LH.mjs +27 -0
- package/dist/chunk-V5VXUJKG.mjs +2 -0
- package/dist/chunk-V6XZ4VIR.mjs +2 -0
- package/dist/chunk-VBXMADMP.mjs +2 -0
- package/dist/chunk-VNV55RUA.mjs +2 -0
- package/dist/chunk-VPD2PS35.mjs +2 -0
- package/dist/chunk-W3BGBJQW.mjs +2 -0
- package/dist/chunk-W4VKN3GF.mjs +7 -0
- package/dist/chunk-W5BXXPDJ.mjs +3 -0
- package/dist/chunk-W7XHE4CT.mjs +2 -0
- package/dist/chunk-XNROSH2T.mjs +4 -0
- package/dist/chunk-XUNHRCOG.mjs +6 -0
- package/dist/chunk-Y34NR5JL.mjs +2 -0
- package/dist/chunk-Y6RLRPG3.mjs +3 -0
- package/dist/chunk-YEY3RSFQ.mjs +2 -0
- package/dist/cli.mjs +2 -0
- package/dist/server.mjs +2 -0
- package/dist/worker.mjs +5 -0
- package/kit/charts.js +355 -0
- package/kit/code.js +164 -0
- package/kit/dialogs.js +157 -0
- package/kit/math.js +2004 -0
- package/kit/report.css +2932 -0
- package/kit/runtime.js +1782 -0
- package/kit/sheets.js +123 -0
- package/kit/state.js +217 -0
- package/kit/tables.js +1499 -0
- package/kit/tokens.js +29 -0
- package/kit/ui.js +658 -0
- package/package.json +41 -4
- package/release.json +25 -0
- package/sdk/column-widths.d.ts +56 -0
- package/sdk/doc-charts.d.ts +82 -0
- package/sdk/doc-code.d.ts +28 -0
- package/sdk/doc-dialogs.d.ts +4 -0
- package/sdk/doc-kit.d.ts +147 -0
- package/sdk/doc-math.d.ts +3 -0
- package/sdk/doc-sheets.d.ts +15 -0
- package/sdk/doc-state.d.ts +41 -0
- package/sdk/doc-tables.d.ts +24 -0
- package/sdk/doc-tokens.d.ts +22 -0
- package/sdk/index.d.ts +30 -0
- package/skill/SKILL.md +150 -0
- package/skill/agents/openai.yaml +5 -0
- package/skill/references/building-components.md +367 -0
- package/skill/references/example-report.html +356 -0
- package/skill/references/writing-html.md +187 -0
- package/skill/sdk/column-widths.d.ts +56 -0
- package/skill/sdk/doc-charts.d.ts +82 -0
- package/skill/sdk/doc-code.d.ts +28 -0
- package/skill/sdk/doc-dialogs.d.ts +4 -0
- package/skill/sdk/doc-kit.d.ts +147 -0
- package/skill/sdk/doc-math.d.ts +3 -0
- package/skill/sdk/doc-sheets.d.ts +15 -0
- package/skill/sdk/doc-state.d.ts +41 -0
- package/skill/sdk/doc-tables.d.ts +24 -0
- package/skill/sdk/doc-tokens.d.ts +22 -0
- package/skill/sdk/index.d.ts +30 -0
- package/starter/doc.html +21 -0
- package/starter/doc.json +5 -0
- package/vendor/d3.v7.9.0.min.js +2 -0
- package/vendor/katex/auto-render.min.js +1 -0
- package/vendor/katex/contrib/mhchem.min.js +1 -0
- package/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/vendor/katex/katex.min.css +1 -0
- package/vendor/katex/katex.min.js +1 -0
- package/vendor/pdfjs/LICENSE +177 -0
- package/vendor/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Add-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5pc-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/B5pc-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS1-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS1-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/CNS2-V.bcmap +3 -0
- package/vendor/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
- package/vendor/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Ext-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GB-H.bcmap +4 -0
- package/vendor/pdfjs/cmaps/GB-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBT-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Hankaku.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Hiragana.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Katakana.bcmap +0 -0
- package/vendor/pdfjs/cmaps/LICENSE +36 -0
- package/vendor/pdfjs/cmaps/NWP-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/NWP-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/Roman.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
- package/vendor/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/V.bcmap +0 -0
- package/vendor/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
- package/vendor/pdfjs/legacy/build/pdf.min.mjs +27 -0
- package/vendor/pdfjs/legacy/build/pdf.worker.min.mjs +27 -0
- package/vendor/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
- package/vendor/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
- package/vendor/pdfjs/standard_fonts/LICENSE_LIBERATION +363 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
- package/vendor/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
- package/vendor/types/@types/d3/LICENSE +21 -0
- package/vendor/types/@types/d3/index.d.ts +39 -0
- package/vendor/types/@types/d3/package.json +81 -0
- package/vendor/types/@types/d3-array/LICENSE +21 -0
- package/vendor/types/@types/d3-array/index.d.ts +1118 -0
- package/vendor/types/@types/d3-array/package.json +56 -0
- package/vendor/types/@types/d3-axis/LICENSE +21 -0
- package/vendor/types/@types/d3-axis/index.d.ts +293 -0
- package/vendor/types/@types/d3-axis/package.json +47 -0
- package/vendor/types/@types/d3-brush/LICENSE +21 -0
- package/vendor/types/@types/d3-brush/index.d.ts +255 -0
- package/vendor/types/@types/d3-brush/package.json +42 -0
- package/vendor/types/@types/d3-chord/LICENSE +21 -0
- package/vendor/types/@types/d3-chord/index.d.ts +471 -0
- package/vendor/types/@types/d3-chord/package.json +40 -0
- package/vendor/types/@types/d3-color/LICENSE +21 -0
- package/vendor/types/@types/d3-color/index.d.ts +669 -0
- package/vendor/types/@types/d3-color/package.json +55 -0
- package/vendor/types/@types/d3-contour/LICENSE +21 -0
- package/vendor/types/@types/d3-contour/index.d.ts +222 -0
- package/vendor/types/@types/d3-contour/package.json +38 -0
- package/vendor/types/@types/d3-delaunay/LICENSE +21 -0
- package/vendor/types/@types/d3-delaunay/index.d.ts +316 -0
- package/vendor/types/@types/d3-delaunay/package.json +30 -0
- package/vendor/types/@types/d3-dispatch/LICENSE +21 -0
- package/vendor/types/@types/d3-dispatch/index.d.ts +96 -0
- package/vendor/types/@types/d3-dispatch/package.json +51 -0
- package/vendor/types/@types/d3-drag/LICENSE +21 -0
- package/vendor/types/@types/d3-drag/index.d.ts +395 -0
- package/vendor/types/@types/d3-drag/package.json +42 -0
- package/vendor/types/@types/d3-dsv/LICENSE +21 -0
- package/vendor/types/@types/d3-dsv/index.d.ts +482 -0
- package/vendor/types/@types/d3-dsv/package.json +45 -0
- package/vendor/types/@types/d3-ease/LICENSE +21 -0
- package/vendor/types/@types/d3-ease/index.d.ts +316 -0
- package/vendor/types/@types/d3-ease/package.json +40 -0
- package/vendor/types/@types/d3-fetch/LICENSE +21 -0
- package/vendor/types/@types/d3-fetch/index.d.ts +282 -0
- package/vendor/types/@types/d3-fetch/package.json +37 -0
- package/vendor/types/@types/d3-force/LICENSE +21 -0
- package/vendor/types/@types/d3-force/index.d.ts +899 -0
- package/vendor/types/@types/d3-force/package.json +45 -0
- package/vendor/types/@types/d3-format/LICENSE +21 -0
- package/vendor/types/@types/d3-format/index.d.ts +337 -0
- package/vendor/types/@types/d3-format/package.json +45 -0
- package/vendor/types/@types/d3-geo/LICENSE +21 -0
- package/vendor/types/@types/d3-geo/index.d.ts +1371 -0
- package/vendor/types/@types/d3-geo/package.json +48 -0
- package/vendor/types/@types/d3-hierarchy/LICENSE +21 -0
- package/vendor/types/@types/d3-hierarchy/index.d.ts +928 -0
- package/vendor/types/@types/d3-hierarchy/package.json +50 -0
- package/vendor/types/@types/d3-interpolate/LICENSE +21 -0
- package/vendor/types/@types/d3-interpolate/index.d.ts +387 -0
- package/vendor/types/@types/d3-interpolate/package.json +47 -0
- package/vendor/types/@types/d3-path/LICENSE +21 -0
- package/vendor/types/@types/d3-path/index.d.ts +108 -0
- package/vendor/types/@types/d3-path/package.json +41 -0
- package/vendor/types/@types/d3-polygon/LICENSE +21 -0
- package/vendor/types/@types/d3-polygon/index.d.ts +41 -0
- package/vendor/types/@types/d3-polygon/package.json +40 -0
- package/vendor/types/@types/d3-quadtree/LICENSE +21 -0
- package/vendor/types/@types/d3-quadtree/index.d.ts +204 -0
- package/vendor/types/@types/d3-quadtree/package.json +45 -0
- package/vendor/types/@types/d3-random/LICENSE +21 -0
- package/vendor/types/@types/d3-random/index.d.ts +313 -0
- package/vendor/types/@types/d3-random/package.json +41 -0
- package/vendor/types/@types/d3-scale/LICENSE +21 -0
- package/vendor/types/@types/d3-scale/index.d.ts +2669 -0
- package/vendor/types/@types/d3-scale/package.json +53 -0
- package/vendor/types/@types/d3-scale-chromatic/LICENSE +21 -0
- package/vendor/types/@types/d3-scale-chromatic/index.d.ts +520 -0
- package/vendor/types/@types/d3-scale-chromatic/package.json +46 -0
- package/vendor/types/@types/d3-selection/LICENSE +21 -0
- package/vendor/types/@types/d3-selection/index.d.ts +1210 -0
- package/vendor/types/@types/d3-selection/package.json +56 -0
- package/vendor/types/@types/d3-shape/LICENSE +21 -0
- package/vendor/types/@types/d3-shape/index.d.ts +2792 -0
- package/vendor/types/@types/d3-shape/package.json +53 -0
- package/vendor/types/@types/d3-time/LICENSE +21 -0
- package/vendor/types/@types/d3-time/index.d.ts +697 -0
- package/vendor/types/@types/d3-time/package.json +46 -0
- package/vendor/types/@types/d3-time-format/LICENSE +21 -0
- package/vendor/types/@types/d3-time-format/index.d.ts +202 -0
- package/vendor/types/@types/d3-time-format/package.json +40 -0
- package/vendor/types/@types/d3-timer/LICENSE +21 -0
- package/vendor/types/@types/d3-timer/index.d.ts +68 -0
- package/vendor/types/@types/d3-timer/package.json +45 -0
- package/vendor/types/@types/d3-transition/LICENSE +21 -0
- package/vendor/types/@types/d3-transition/index.d.ts +664 -0
- package/vendor/types/@types/d3-transition/package.json +47 -0
- package/vendor/types/@types/d3-zoom/LICENSE +21 -0
- package/vendor/types/@types/d3-zoom/index.d.ts +611 -0
- package/vendor/types/@types/d3-zoom/package.json +48 -0
- package/vendor/types/@types/geojson/LICENSE +21 -0
- package/vendor/types/@types/geojson/index.d.ts +202 -0
- package/vendor/types/@types/geojson/package.json +46 -0
- package/vendor/typescript/LICENSE.txt +55 -0
- package/vendor/typescript/lib.decorators.d.ts +384 -0
- package/vendor/typescript/lib.decorators.legacy.d.ts +22 -0
- package/vendor/typescript/lib.dom.d.ts +39429 -0
- package/vendor/typescript/lib.dom.iterable.d.ts +571 -0
- package/vendor/typescript/lib.es2015.collection.d.ts +147 -0
- package/vendor/typescript/lib.es2015.core.d.ts +597 -0
- package/vendor/typescript/lib.es2015.d.ts +28 -0
- package/vendor/typescript/lib.es2015.generator.d.ts +77 -0
- package/vendor/typescript/lib.es2015.iterable.d.ts +605 -0
- package/vendor/typescript/lib.es2015.promise.d.ts +81 -0
- package/vendor/typescript/lib.es2015.proxy.d.ts +128 -0
- package/vendor/typescript/lib.es2015.reflect.d.ts +144 -0
- package/vendor/typescript/lib.es2015.symbol.d.ts +46 -0
- package/vendor/typescript/lib.es2015.symbol.wellknown.d.ts +326 -0
- package/vendor/typescript/lib.es2016.array.include.d.ts +116 -0
- package/vendor/typescript/lib.es2016.d.ts +21 -0
- package/vendor/typescript/lib.es2016.intl.d.ts +31 -0
- package/vendor/typescript/lib.es2017.arraybuffer.d.ts +21 -0
- package/vendor/typescript/lib.es2017.d.ts +26 -0
- package/vendor/typescript/lib.es2017.date.d.ts +31 -0
- package/vendor/typescript/lib.es2017.intl.d.ts +44 -0
- package/vendor/typescript/lib.es2017.object.d.ts +49 -0
- package/vendor/typescript/lib.es2017.sharedmemory.d.ts +135 -0
- package/vendor/typescript/lib.es2017.string.d.ts +45 -0
- package/vendor/typescript/lib.es2017.typedarrays.d.ts +53 -0
- package/vendor/typescript/lib.es2018.asyncgenerator.d.ts +77 -0
- package/vendor/typescript/lib.es2018.asynciterable.d.ts +53 -0
- package/vendor/typescript/lib.es2018.d.ts +24 -0
- package/vendor/typescript/lib.es2018.intl.d.ts +83 -0
- package/vendor/typescript/lib.es2018.promise.d.ts +30 -0
- package/vendor/typescript/lib.es2018.regexp.d.ts +37 -0
- package/vendor/typescript/lib.es2019.array.d.ts +79 -0
- package/vendor/typescript/lib.es2019.d.ts +24 -0
- package/vendor/typescript/lib.es2019.intl.d.ts +23 -0
- package/vendor/typescript/lib.es2019.object.d.ts +33 -0
- package/vendor/typescript/lib.es2019.string.d.ts +37 -0
- package/vendor/typescript/lib.es2019.symbol.d.ts +24 -0
- package/vendor/typescript/lib.es2020.bigint.d.ts +765 -0
- package/vendor/typescript/lib.es2020.d.ts +27 -0
- package/vendor/typescript/lib.es2020.date.d.ts +42 -0
- package/vendor/typescript/lib.es2020.intl.d.ts +474 -0
- package/vendor/typescript/lib.es2020.number.d.ts +28 -0
- package/vendor/typescript/lib.es2020.promise.d.ts +47 -0
- package/vendor/typescript/lib.es2020.sharedmemory.d.ts +99 -0
- package/vendor/typescript/lib.es2020.string.d.ts +44 -0
- package/vendor/typescript/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/vendor/typescript/lib.es2021.d.ts +23 -0
- package/vendor/typescript/lib.es2021.intl.d.ts +166 -0
- package/vendor/typescript/lib.es2021.promise.d.ts +48 -0
- package/vendor/typescript/lib.es2021.string.d.ts +33 -0
- package/vendor/typescript/lib.es2021.weakref.d.ts +78 -0
- package/vendor/typescript/lib.es2022.array.d.ts +121 -0
- package/vendor/typescript/lib.es2022.d.ts +25 -0
- package/vendor/typescript/lib.es2022.error.d.ts +75 -0
- package/vendor/typescript/lib.es2022.intl.d.ts +145 -0
- package/vendor/typescript/lib.es2022.object.d.ts +26 -0
- package/vendor/typescript/lib.es2022.regexp.d.ts +39 -0
- package/vendor/typescript/lib.es2022.string.d.ts +25 -0
- package/vendor/typescript/lib.es5.d.ts +4601 -0
- package/vendor/typescript/package.json +4 -0
- package/vendor/typescript/typescript.js +446 -0
- package/web/assets/index-Bh74DfsV.css +1 -0
- package/web/assets/index-UW0RyFFt.js +13 -0
- package/web/index.html +14 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { MEDIA_CLASS } from "../../../shared/components/index.mjs";
|
|
2
|
+
import { SPAN, SPAN_SIZE, UPLOAD_LIMITS, sizeLimit } from "../../../shared/media.mjs";
|
|
3
|
+
import { gestureLock } from "../../page/gesture.mjs";
|
|
4
|
+
import { openCrop } from "./crop.mjs";
|
|
5
|
+
import { openViewer } from "./viewer.mjs";
|
|
6
|
+
import { svg } from "../icons.mjs";
|
|
7
|
+
import { closePopup, openPopup } from "../../page/emoji-picker/support.mjs";
|
|
8
|
+
import { ICONS } from "../../page/menu.mjs";
|
|
9
|
+
import { onSettle, own } from "../../page/overlays.mjs";
|
|
10
|
+
import { drawAt, shapeOf } from "../../page/overlay-layer.mjs";
|
|
11
|
+
import { keptByComponent } from "../../page/page-objects.mjs";
|
|
12
|
+
import { addStyle, element } from "../../page/ui.mjs";
|
|
13
|
+
import { TOOL_ICONS } from "../media/icons.mjs";
|
|
14
|
+
import { barClass } from "../placeholder-bar.mjs";
|
|
15
|
+
import { captionNode, captionOf, fileOf, showFile } from "../media/parts.mjs";
|
|
16
|
+
import { SNAP, columnRoom, readingRoom } from "../media/size.mjs";
|
|
17
|
+
import { mediaBar, toolButton } from "../media/toolbar.mjs";
|
|
18
|
+
import { ALIGN, cropOf, imageOf, newImage } from "./index.mjs";
|
|
19
|
+
import { t } from "../../../shared/i18n/index.mjs";
|
|
20
|
+
import { zoomable } from "../../../shared/zoom.mjs";
|
|
21
|
+
|
|
22
|
+
// 图片 on the page (notion-lite's src/blocks/image/edit/, Notion's media block). A new image (the "/"
|
|
23
|
+
// menu's 图片, made from an empty block: convert.mjs) is a placeholder, a gray bar saying 添加图片,
|
|
24
|
+
// until a picture is chosen in the 上传 / 链接 menu (media-menu/) that opens below it at once and on
|
|
25
|
+
// a click (../media/page.mjs): a file (an image, 10 MB at most) goes to the report's folder, a link's picture is
|
|
26
|
+
// downloaded there by the server (an export never reaches the web); either is one undo step. The
|
|
27
|
+
// picture shows where the server serves the folder; what the file is stays in data-ge-src.
|
|
28
|
+
// With the pointer on a picture, Notion's toolbar stands at its top right (对齐, 标题, 展开, 更多:
|
|
29
|
+
// the block menu) and a handle at each side; dragging one resizes the picture (a share of the reading
|
|
30
|
+
// width, at most the width it stands in, both sides at once while centered; snapping to the whole of
|
|
31
|
+
// that width, a share of 1: styles/sizes.css), one undo step on
|
|
32
|
+
// letting go (Esc puts it back). 标题 shows its caption (empty ones show only then) with the caret
|
|
33
|
+
// in it; Enter there makes a paragraph after the image. A double-click on the picture (or on any
|
|
34
|
+
// other picture that opens large: a table's, a card's), or 展开, shows it alone over the page (a
|
|
35
|
+
// click or Esc closes it). The block menu has 替换图片, 标题, 对齐 ›
|
|
36
|
+
// and 恢复原始大小 (menuItems). A picture pasted (an image file on the clipboard) becomes an image
|
|
37
|
+
// below the block the caret is in (`acceptsFile`, `fromFiles`).
|
|
38
|
+
|
|
39
|
+
const MAX_BYTES = UPLOAD_LIMITS.image;
|
|
40
|
+
// 裁剪图片's row: a crop mark, drawn as the menus' other icons are.
|
|
41
|
+
const CROP_ICON = svg('<path d="M6 2.75V13a1 1 0 0 0 1 1h10.25"/><path d="M2.75 6H13a1 1 0 0 1 1 1v10.25"/>');
|
|
42
|
+
|
|
43
|
+
const STYLE = `
|
|
44
|
+
/* The placeholder of an image with no picture yet (Notion's 605415): every empty block's, served with the page (../placeholder.mjs). */
|
|
45
|
+
[data-ge-editing] .doc-image > img { cursor: default; }
|
|
46
|
+
/* The handles (Notion's 681598); the toolbar is the media blocks' (../media/toolbar.mjs). */
|
|
47
|
+
.ge-layer > .ge-image-handle { pointer-events: auto; }
|
|
48
|
+
.ge-image-align { display: flex; align-items: center; padding: 2px; border-radius: 6px; background: var(--c-popBac); box-shadow: var(--c-shaOutLg); }
|
|
49
|
+
.ge-image-align-sep { width: 1px; height: 16px; margin: 0 2px; background: var(--ca-borSecTra); }
|
|
50
|
+
.ge-image-handle { display: flex; align-items: center; justify-content: center; width: 15px; cursor: col-resize; }
|
|
51
|
+
/* A plain gray bar, no border (the embed's corners the same). */
|
|
52
|
+
.ge-image-handle::after { content: ""; width: 4px; height: 40px; max-height: 50%; border-radius: 4px; background: light-dark(rgb(55 53 47 / 35%), rgb(255 255 255 / 38%)); transition: background 120ms ease; }
|
|
53
|
+
.ge-image-handle:hover::after, html[data-ge-image-resize] .ge-image-handle::after { background: light-dark(rgb(55 53 47 / 60%), rgb(255 255 255 / 62%)); }
|
|
54
|
+
${gestureLock("data-ge-image-resize", { cursor: "col-resize" })}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const ALIGNS = [["left", t("左对齐"), "alignLeft"], ["center", t("居中对齐"), "alignCenter"], ["right", t("右对齐"), "alignRight"]];
|
|
58
|
+
const sideOf = (figure) => figure.classList.contains(ALIGN[0]) ? "left" : figure.classList.contains(ALIGN[1]) ? "right" : "center";
|
|
59
|
+
const sideLook = (side) => ({ classes: { [ALIGN[0]]: side === "left", [ALIGN[1]]: side === "right" } });
|
|
60
|
+
|
|
61
|
+
// A picture of the report's folder (`path`, assets/<file>) where the server serves it (`url`), and an
|
|
62
|
+
// empty caption; cropped (`cropped`: { original, crop }), the picture it was cropped from and what of it is kept.
|
|
63
|
+
function pictureParts(doc, path, url, caption = "", cropped = null) {
|
|
64
|
+
const img = doc.createElement("img");
|
|
65
|
+
showFile(img, "src", path, url);
|
|
66
|
+
img.alt = "";
|
|
67
|
+
img.draggable = false;
|
|
68
|
+
if (cropped) {
|
|
69
|
+
img.setAttribute("data-original", cropped.original);
|
|
70
|
+
img.setAttribute("data-crop", cropped.crop);
|
|
71
|
+
}
|
|
72
|
+
return [img, captionNode(doc, caption)];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Images on the page, with what the editor gives them: the media blocks' shared parts (`pages.media`:
|
|
77
|
+
* ../media/page.mjs block("image"): the undo steps, say, active(), select, the block menu, the
|
|
78
|
+
* upload of kind "image", the menu, the caption) and assetUrl(path) (where the server serves a file
|
|
79
|
+
* of the report's folder).
|
|
80
|
+
*/
|
|
81
|
+
export function create({ pages, assetUrl }) {
|
|
82
|
+
const media = pages.media.block("image");
|
|
83
|
+
const { say, active, look, openMenu } = media;
|
|
84
|
+
addStyle(STYLE);
|
|
85
|
+
|
|
86
|
+
// ---------- a picture chosen ----------
|
|
87
|
+
|
|
88
|
+
/** The 上传 / 链接 menu of an image, below its placeholder (or its picture: 替换图片). */
|
|
89
|
+
const pick = (figure) => media.pick(figure, {
|
|
90
|
+
width: 360, // Notion's 540 stood far out past the block
|
|
91
|
+
tabs: [{ key: "upload", label: t("上传") }, { key: "link", label: t("链接") }],
|
|
92
|
+
upload: { label: t("上传文件"), accept: "image/*" },
|
|
93
|
+
link: { placeholder: t("粘贴图片链接…"), button: t("嵌入图片"), caption: t("适用于网络上的任何图片。") },
|
|
94
|
+
onUpload: (file) => uploadInto(figure, file),
|
|
95
|
+
onEmbed: (url) => fetchInto(figure, url),
|
|
96
|
+
}, (each) => each.querySelector(`:scope > .${barClass(MEDIA_CLASS.image)}`) ?? imageOf(each) ?? each);
|
|
97
|
+
|
|
98
|
+
async function uploadInto(figure, file, options = {}) {
|
|
99
|
+
if (!/^image\//.test(file.type)) return say(t("很抱歉,不支持该文件类型。"), "error");
|
|
100
|
+
if (file.size > MAX_BYTES) return say(t("图片太大(最多 {0})。", sizeLimit("image")), "error");
|
|
101
|
+
return media.attempt(figure, t("正在上传…"), t("无法上传这张图片"), async () => {
|
|
102
|
+
const pixels = await pixelSize(file);
|
|
103
|
+
place(figure, (await media.uploadFile(file)).path, pixels, options);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// A picture's size in pixels ({ width, height }), or null when the browser cannot read it.
|
|
108
|
+
async function pixelSize(file) {
|
|
109
|
+
try {
|
|
110
|
+
const bitmap = await createImageBitmap(file);
|
|
111
|
+
const size = { width: bitmap.width, height: bitmap.height };
|
|
112
|
+
bitmap.close();
|
|
113
|
+
return size;
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// The share of the reading width that `pixels` take on this screen, or "" for the kit's own size:
|
|
119
|
+
// a picture as wide as the width `figure` stands in or wider, or one that would stand taller than
|
|
120
|
+
// 80% of this window (a phone's screenshot), which the kit shows at most that tall on every
|
|
121
|
+
// reader's window (styles/image.css), where a span would hold it at its width however tall.
|
|
122
|
+
function naturalShare(figure, pixels) {
|
|
123
|
+
if (!pixels?.width) return "";
|
|
124
|
+
const room = columnRoom(figure);
|
|
125
|
+
const ratio = devicePixelRatio || 1;
|
|
126
|
+
const width = pixels.width / ratio;
|
|
127
|
+
if (!(room > 0) || width >= room || pixels.height / ratio > innerHeight * 0.8) return "";
|
|
128
|
+
return String(Math.max(SPAN_SIZE.min, Math.round((width / readingRoom(figure)) * 1000) / 1000));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const fetchInto = (figure, url, options = {}) => media.attempt(figure, t("正在下载…"), t("无法下载这张图片"), async () => {
|
|
132
|
+
place(figure, (await media.uploadUrl(url)).path, null, options);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// The picture in: a new image in the place of the placeholder, or of the image that had one
|
|
136
|
+
// (替换图片, with its caption, side and width), never the same element, so that undo brings back
|
|
137
|
+
// what stood there (a placeholder never written, an image as it was) and the file loses the new
|
|
138
|
+
// one. One undo step; the image selected.
|
|
139
|
+
//
|
|
140
|
+
// A new picture from this computer (`pixels`: its size in pixels) shows as large as it was on the
|
|
141
|
+
// screen it was taken on (D7 of the polish plan): its pixels over this screen's device pixel ratio,
|
|
142
|
+
// as a share of the reading width, never past the width it stands in (a screenshot on a high-density
|
|
143
|
+
// screen once showed twice its size); one that tall is left to the kit's 80% of the window
|
|
144
|
+
// (naturalShare). A picture replaced keeps the width the old one had.
|
|
145
|
+
// `cropped`: { original, crop } said on the picture (a crop's); `quiet`: its own word said by the caller.
|
|
146
|
+
function place(figure, path, pixels = null, { cropped = null, quiet = false, pasted = false } = {}) {
|
|
147
|
+
if (!figure.isConnected) return;
|
|
148
|
+
const doc = figure.ownerDocument;
|
|
149
|
+
const replacing = Boolean(imageOf(figure));
|
|
150
|
+
const next = newImage(doc);
|
|
151
|
+
next.className = figure.className;
|
|
152
|
+
const span = figure.style.getPropertyValue(SPAN) || (replacing ? "" : naturalShare(figure, pixels));
|
|
153
|
+
if (span) next.style.setProperty(SPAN, span);
|
|
154
|
+
next.replaceChildren(...pictureParts(doc, path, assetUrl(path), captionOf(figure)?.innerHTML ?? "", cropped));
|
|
155
|
+
media.place(figure, next, { replacing, pasted });
|
|
156
|
+
if (replacing && !quiet) say(t("已替换图片 · Ctrl+Z 撤销"));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------- the toolbar and the handles ----------
|
|
160
|
+
|
|
161
|
+
let hovered = null; // the image the pointer is on
|
|
162
|
+
let resizing = null; // { figure, side, x, start, room, before, centered }
|
|
163
|
+
const bar = mediaBar(t("图片操作"));
|
|
164
|
+
const tool = (label, tip, icon, run) => toolButton({ label, tip, icon, run, alive: () => hovered?.isConnected });
|
|
165
|
+
const tools = {
|
|
166
|
+
align: tool(t("对齐方式"), t("设置区块对齐"), () => TOOL_ICONS[{ left: "alignLeft", center: "alignCenter", right: "alignRight" }[sideOf(hovered)]], (button) => alignPopup(hovered, button)),
|
|
167
|
+
caption: tool(t("标题@caption"), t("添加标题"), TOOL_ICONS.caption, () => media.caption(hovered)),
|
|
168
|
+
expand: tool(t("展开"), t("全屏查看"), TOOL_ICONS.expand, () => view(hovered)),
|
|
169
|
+
more: tool(t("更多"), t("打开区块操作菜单"), TOOL_ICONS.more, (button) => {
|
|
170
|
+
const rect = button.getBoundingClientRect();
|
|
171
|
+
openMenu(hovered, { left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom });
|
|
172
|
+
}),
|
|
173
|
+
};
|
|
174
|
+
bar.append(...Object.values(tools));
|
|
175
|
+
const handles = { left: element("div", { class: "ge-image-handle", "data-side": "left" }), right: element("div", { class: "ge-image-handle", "data-side": "right" }) };
|
|
176
|
+
|
|
177
|
+
// The toolbar and the handles over the picture of `figure`, or away.
|
|
178
|
+
function show(figure) {
|
|
179
|
+
hovered = figure;
|
|
180
|
+
const img = figure && imageOf(figure);
|
|
181
|
+
const shape = img && shapeOf(img);
|
|
182
|
+
if (!shape) {
|
|
183
|
+
hovered = null;
|
|
184
|
+
for (const node of [bar, handles.left, handles.right]) node.remove();
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const alive = () => hovered === figure && figure.isConnected;
|
|
188
|
+
for (const node of [bar, handles.left, handles.right]) own(node, "image tools", { owner: figure, alive });
|
|
189
|
+
for (const button of Object.values(tools)) button.draw();
|
|
190
|
+
const { rect } = shape;
|
|
191
|
+
tools.align.style.display = figure.style.getPropertyValue(SPAN).trim() === "1" ? "none" : ""; // a picture as wide as it can be has no side
|
|
192
|
+
if (bar.parentNode !== shape.layer) shape.layer.append(bar); // in the page before its width is measured
|
|
193
|
+
drawAt(bar, shape.layer, rect.right - 4 - bar.offsetWidth, rect.top + 4);
|
|
194
|
+
for (const [side, handle] of Object.entries(handles)) {
|
|
195
|
+
handle.style.height = `${Math.round(rect.bottom - rect.top)}px`;
|
|
196
|
+
drawAt(handle, shape.layer, side === "left" ? rect.left : rect.right - 15, rect.top);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
document.addEventListener("mousemove", (event) => {
|
|
201
|
+
if (resizing || [bar, handles.left, handles.right].some((node) => node.contains(event.target))) return;
|
|
202
|
+
const figure = active() && !keptByComponent(event.target) ? event.target.closest?.("main figure.doc-image") ?? null : null;
|
|
203
|
+
if (figure !== hovered) show(figure && imageOf(figure) ? figure : null);
|
|
204
|
+
}, { passive: true, capture: true });
|
|
205
|
+
addEventListener("scroll", () => { if (hovered && !resizing) show(hovered); }, { passive: true, capture: true });
|
|
206
|
+
document.documentElement.addEventListener("mouseleave", () => { if (!resizing) show(null); });
|
|
207
|
+
// The hovered picture taken off the page by an undo, a redo or a commit: the tools go at once, not at the next pointer move.
|
|
208
|
+
onSettle(() => { if (hovered && !hovered.isConnected && !resizing) show(null); });
|
|
209
|
+
|
|
210
|
+
// Dragging a handle: the picture's width as a share of the reading width, at most the width it
|
|
211
|
+
// stands in (1 when it reaches that), live; one undo step on letting go.
|
|
212
|
+
for (const [side, handle] of Object.entries(handles)) {
|
|
213
|
+
handle.addEventListener("pointerdown", (event) => {
|
|
214
|
+
if (event.button !== 0 || !hovered) return;
|
|
215
|
+
event.preventDefault();
|
|
216
|
+
const figure = hovered;
|
|
217
|
+
const room = columnRoom(figure);
|
|
218
|
+
resizing = { figure, side, x: event.clientX, start: imageOf(figure).getBoundingClientRect().width, room, page: readingRoom(figure), before: figure.style.getPropertyValue(SPAN), centered: sideOf(figure) === "center" };
|
|
219
|
+
handle.setPointerCapture?.(event.pointerId);
|
|
220
|
+
document.documentElement.setAttribute("data-ge-image-resize", "");
|
|
221
|
+
});
|
|
222
|
+
handle.addEventListener("pointermove", (event) => {
|
|
223
|
+
if (!resizing) return;
|
|
224
|
+
const { figure, x, start, room, page, centered } = resizing;
|
|
225
|
+
const delta = (event.clientX - x) * (side === "right" ? 1 : -1) * (centered ? 2 : 1);
|
|
226
|
+
const width = Math.max(Math.min(room, page * SPAN_SIZE.min), Math.min(room, start + delta));
|
|
227
|
+
figure.style.setProperty(SPAN, room - width <= SNAP ? "1" : String(Math.round((width / page) * 1000) / 1000));
|
|
228
|
+
show(figure);
|
|
229
|
+
});
|
|
230
|
+
const end = (keep) => {
|
|
231
|
+
if (!resizing) return;
|
|
232
|
+
const { figure, before } = resizing;
|
|
233
|
+
resizing = null;
|
|
234
|
+
document.documentElement.removeAttribute("data-ge-image-resize");
|
|
235
|
+
const after = figure.style.getPropertyValue(SPAN);
|
|
236
|
+
if (before) figure.style.setProperty(SPAN, before);
|
|
237
|
+
else figure.style.removeProperty(SPAN);
|
|
238
|
+
if (keep && after !== before && look(figure, { sizes: { [SPAN]: after || null } })) say(t("图片宽度 {0}% · Ctrl+Z 撤销", Math.round(Number(after) * 100)));
|
|
239
|
+
show(figure);
|
|
240
|
+
};
|
|
241
|
+
handle.addEventListener("pointerup", () => end(true));
|
|
242
|
+
handle.addEventListener("pointercancel", () => end(false));
|
|
243
|
+
handle.addEventListener("lostpointercapture", () => end(true));
|
|
244
|
+
}
|
|
245
|
+
document.addEventListener("keydown", (event) => {
|
|
246
|
+
if (event.key !== "Escape" || !resizing) return;
|
|
247
|
+
event.preventDefault();
|
|
248
|
+
event.stopPropagation();
|
|
249
|
+
const { figure, before } = resizing;
|
|
250
|
+
resizing = null;
|
|
251
|
+
document.documentElement.removeAttribute("data-ge-image-resize");
|
|
252
|
+
if (before) figure.style.setProperty(SPAN, before);
|
|
253
|
+
else figure.style.removeProperty(SPAN);
|
|
254
|
+
show(figure);
|
|
255
|
+
}, true);
|
|
256
|
+
|
|
257
|
+
// 对齐: Notion's small popover of the three sides, under its button.
|
|
258
|
+
function alignPopup(figure, button) {
|
|
259
|
+
const el = document.createElement("div");
|
|
260
|
+
el.className = "ge-image-align";
|
|
261
|
+
el.setAttribute("data-doc-dev", "");
|
|
262
|
+
const current = sideOf(figure);
|
|
263
|
+
el.innerHTML = ALIGNS.map(([side, label, name], index) => `${index ? '<div class="ge-image-align-sep"></div>' : ""}<div role="button" class="ge-media-tool"${side === current ? " data-on" : ""} data-side="${side}" aria-label="${label}">${TOOL_ICONS[name]}</div>`).join("");
|
|
264
|
+
el.addEventListener("mousedown", (event) => event.preventDefault());
|
|
265
|
+
el.addEventListener("click", (event) => {
|
|
266
|
+
const side = event.target.closest("[data-side]")?.dataset.side;
|
|
267
|
+
if (!side) return;
|
|
268
|
+
closePopup(popup);
|
|
269
|
+
align(figure, side);
|
|
270
|
+
});
|
|
271
|
+
const rect = button.getBoundingClientRect();
|
|
272
|
+
const popup = openPopup({ origin: { left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom, width: rect.width, height: rect.height }, placement: "bottom", align: "center", gap: 8, content: el });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function align(figure, side) {
|
|
276
|
+
if (look(figure, sideLook(side))) say(t("已{0} · Ctrl+Z 撤销", ALIGNS.find(([each]) => each === side)[1]));
|
|
277
|
+
if (hovered === figure) show(figure);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ---------- the viewer ----------
|
|
281
|
+
|
|
282
|
+
// The viewer (viewer.mjs: the wheel zooms, 下载, the page's other pictures), on an image block's picture.
|
|
283
|
+
const view = (figure) => openViewer(imageOf(figure), download);
|
|
284
|
+
|
|
285
|
+
// 下载: the picture saved, by the name it has in the report's folder (`img`: an image block's, or
|
|
286
|
+
// any picture the viewer shows).
|
|
287
|
+
async function download(img) {
|
|
288
|
+
if (!img) return;
|
|
289
|
+
const kept = fileOf(img, "src") ?? img.getAttribute("src") ?? "";
|
|
290
|
+
const type = /^data:image\/([a-z+]+)/.exec(kept)?.[1]?.replace("+xml", "") ?? null;
|
|
291
|
+
const name = type ? `image.${type}` : kept.split(/[?#]/)[0].split("/").filter(Boolean).pop() || "image.png";
|
|
292
|
+
try {
|
|
293
|
+
const response = await fetch(img.src);
|
|
294
|
+
if (!response.ok) throw new Error(String(response.status));
|
|
295
|
+
const url = URL.createObjectURL(await response.blob());
|
|
296
|
+
const link = element("a", { href: url, download: name });
|
|
297
|
+
document.body.append(link);
|
|
298
|
+
link.click();
|
|
299
|
+
link.remove();
|
|
300
|
+
setTimeout(() => URL.revokeObjectURL(url), 2000);
|
|
301
|
+
} catch {
|
|
302
|
+
say(t("没能下载这张图片。"), "error");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 裁剪图片 (crop.mjs, notion-lite's: nothing is lost): the dialog shows the picture it was cropped
|
|
307
|
+
// from, when it was, with the box kept then, so what was cut away can come back. What is kept, a new
|
|
308
|
+
// picture of the report's folder in its place (its caption, side and width kept), that original and
|
|
309
|
+
// the box kept said on it; the whole picture kept, the original back. One undo step.
|
|
310
|
+
function crop(figure) {
|
|
311
|
+
const img = figure && imageOf(figure);
|
|
312
|
+
if (!img) return;
|
|
313
|
+
const original = img.getAttribute("data-original");
|
|
314
|
+
const from = original ?? fileOf(img, "src");
|
|
315
|
+
openCrop(img, async (blob, kept) => {
|
|
316
|
+
if (!figure.isConnected) return;
|
|
317
|
+
try {
|
|
318
|
+
if (!kept) {
|
|
319
|
+
if (!original) return; // nothing cut away, nothing to bring back
|
|
320
|
+
place(figure, original, null, { quiet: true });
|
|
321
|
+
return say(t("已恢复原图 · Ctrl+Z 撤销"));
|
|
322
|
+
}
|
|
323
|
+
place(figure, (await media.uploadFile(blob, "crop.png")).path, null, { cropped: from ? { original: from, crop: kept } : null, quiet: true });
|
|
324
|
+
say(t("已裁剪图片 · Ctrl+Z 撤销"));
|
|
325
|
+
} catch (error) {
|
|
326
|
+
say(t("无法保存裁剪的图片:{0}", error.message), "error");
|
|
327
|
+
}
|
|
328
|
+
}, { src: original ? assetUrl(original) : img.src, crop: original ? cropOf(img.getAttribute("data-crop")) : null });
|
|
329
|
+
}
|
|
330
|
+
// A double-click on a picture that opens large (src/shared/zoom.mjs: an image block's, or one in a
|
|
331
|
+
// table, a card, a column) views it, notion-lite's rule while editing (726447: a double-click on a
|
|
332
|
+
// page that can be edited, a click on one that cannot: the kit's viewer, runtime/zoom.js, leaves a
|
|
333
|
+
// click on the page edited to the editor, which selects the block).
|
|
334
|
+
document.addEventListener("dblclick", (event) => {
|
|
335
|
+
const img = event.target;
|
|
336
|
+
if (img?.localName !== "img" || !active() || !zoomable(img)) return;
|
|
337
|
+
event.preventDefault();
|
|
338
|
+
openViewer(img, download);
|
|
339
|
+
}, true);
|
|
340
|
+
// ---------- the block menu, pasting ----------
|
|
341
|
+
|
|
342
|
+
/** An image's rows in its block menu. */
|
|
343
|
+
function menuItems(target) {
|
|
344
|
+
if (!target?.matches?.("figure.doc-image") || !imageOf(target)) return [];
|
|
345
|
+
const rows = [
|
|
346
|
+
{ label: t("替换图片"), icon: ICONS.reset, run: () => setTimeout(() => pick(target)) },
|
|
347
|
+
{ label: t("标题@caption"), icon: TOOL_ICONS.caption, run: () => setTimeout(() => media.caption(target)) },
|
|
348
|
+
{ label: t("对齐"), icon: TOOL_ICONS[{ left: "alignLeft", center: "alignCenter", right: "alignRight" }[sideOf(target)]], width: 180,
|
|
349
|
+
submenu: () => ALIGNS.map(([side, label, name]) => ({ label, icon: TOOL_ICONS[name], current: side === sideOf(target), run: () => align(target, side) })) },
|
|
350
|
+
];
|
|
351
|
+
if (target.style.getPropertyValue(SPAN)) rows.push({ label: t("恢复原始大小"), icon: ICONS.reset, run: () => { if (look(target, { sizes: { [SPAN]: null } })) say(t("已恢复原始大小 · Ctrl+Z 撤销")); } });
|
|
352
|
+
rows.push({ label: t("裁剪图片"), icon: CROP_ICON, run: () => setTimeout(() => crop(target)) });
|
|
353
|
+
rows.push({ label: t("全屏查看"), icon: TOOL_ICONS.expand, run: () => view(target) });
|
|
354
|
+
rows.push({ label: t("下载"), icon: TOOL_ICONS.download, run: () => download(imageOf(target)) });
|
|
355
|
+
return rows;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* An image pasted with its picture's address (clipboard/): the picture downloaded into the
|
|
360
|
+
* report's folder (a data: address uploaded), one undo step with the paste (`options`).
|
|
361
|
+
*/
|
|
362
|
+
async function fromLink(figure, src, options) {
|
|
363
|
+
if (!/^data:/i.test(src)) return fetchInto(figure, src, options);
|
|
364
|
+
try {
|
|
365
|
+
const blob = await (await fetch(src)).blob();
|
|
366
|
+
return uploadInto(figure, new File([blob], `image.${(blob.type.split("/")[1] ?? "png").replace("svg+xml", "svg").replace("jpeg", "jpg")}`, { type: blob.type }), options);
|
|
367
|
+
} catch {
|
|
368
|
+
return undefined;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
pick, menuItems, fromLink,
|
|
374
|
+
/** Whether a file makes an image. */
|
|
375
|
+
acceptsFile: (file) => /^image\//.test(file.type),
|
|
376
|
+
/** An image made of `file`, put where the paste puts it (`put`), its picture uploaded. Returns whether it took it. */
|
|
377
|
+
fromFiles: (put, [file]) => media.paste(put, file, newImage, uploadInto),
|
|
378
|
+
/** A new one: its picture chosen next. */
|
|
379
|
+
onCreated(figure) {
|
|
380
|
+
pick(figure);
|
|
381
|
+
return true;
|
|
382
|
+
},
|
|
383
|
+
get nodes() { return [bar, handles.left, handles.right].filter((node) => node.isConnected); },
|
|
384
|
+
};
|
|
385
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { Z } from "../../../shared/layers.mjs";
|
|
2
|
+
import { tooltip } from "../../page/tooltip.mjs";
|
|
3
|
+
import { addStyleTo, element, mountOver, overlayHost } from "../../page/ui.mjs";
|
|
4
|
+
import { t } from "../../../shared/i18n/index.mjs";
|
|
5
|
+
import { zoomable } from "../../../shared/zoom.mjs";
|
|
6
|
+
|
|
7
|
+
// The picture over the page (notion-lite's blocks/image/edit/viewer.js, Notion's 523009 → 749527,
|
|
8
|
+
// with Feishu's wheel): the image's toolbar 展开, its block menu's 全屏查看, and a double-click on a
|
|
9
|
+
// picture of the page that opens large (notion-lite's rule while editing; which pictures is
|
|
10
|
+
// src/shared/zoom.mjs's: an image block's, or one in a table, a card, a column; a reader's single
|
|
11
|
+
// click opens the kit's viewer instead, runtime/zoom.js, which leaves the page edited alone). The picture fits the
|
|
12
|
+
// window (32px around it from 1020px wide), never larger than itself. The wheel zooms around the
|
|
13
|
+
// pointer (25% to 400%), as do −, + and the keys − and +; the percentage puts it back to 100%; a
|
|
14
|
+
// zoomed picture is dragged about. A bar at the bottom: ‹ › (when the page has more pictures, ← →
|
|
15
|
+
// too), −, the percentage, +, 下载, 关闭; it and the pointer hide after two seconds still. Esc, the
|
|
16
|
+
// space bar or a click beside the picture closes it. In a workbench it covers the workbench's window
|
|
17
|
+
// (ui.mjs overlayHost), its keys heard in either document.
|
|
18
|
+
|
|
19
|
+
const STYLE = `
|
|
20
|
+
.ge-image-viewer { position: fixed; inset: 0; z-index: ${Z.viewer}; display: flex; align-items: center; justify-content: center; overflow: hidden;
|
|
21
|
+
background: rgb(15 15 15 / 80%); opacity: 0; transition: opacity 150ms; user-select: none; }
|
|
22
|
+
.ge-image-viewer[data-shown] { opacity: 1; }
|
|
23
|
+
/* The picture's own cursor (grab, grabbing) is set inline while it is moved, which only !important beats. */
|
|
24
|
+
.ge-image-viewer[data-idle], .ge-image-viewer[data-idle] img { cursor: none !important; }
|
|
25
|
+
.ge-image-viewer > img { display: block; max-width: none; object-fit: contain; transform-origin: center; transition: transform 80ms ease-out; }
|
|
26
|
+
.ge-viewer-bar { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 10px; font: 14px/1 ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; transition: opacity 200ms; }
|
|
27
|
+
.ge-image-viewer[data-idle] .ge-viewer-bar { opacity: 0; pointer-events: none; }
|
|
28
|
+
.ge-viewer-group { display: flex; align-items: center; border-radius: 4px; background: rgb(0 0 0 / 62%); }
|
|
29
|
+
.ge-viewer-button { display: flex; align-items: center; justify-content: center; min-width: 28px; height: 28px; padding: 6px; border-radius: 4px; color: #fff; cursor: pointer; transition: background 20ms ease-in; }
|
|
30
|
+
.ge-viewer-button:hover { background: rgb(255 255 255 / 5.5%); }
|
|
31
|
+
.ge-viewer-button[data-off] { opacity: .4; pointer-events: none; }
|
|
32
|
+
.ge-viewer-button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
|
|
33
|
+
.ge-viewer-zoom { width: 50px; color: rgb(255 255 255 / 50%); font-size: 13px; }
|
|
34
|
+
.ge-viewer-sep { width: 1px; height: 16px; background: rgb(255 255 255 / 28%); }
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
const icon = (path) => `<svg viewBox="0 0 16 16" aria-hidden="true">${path}</svg>`;
|
|
38
|
+
const ICONS = {
|
|
39
|
+
prev: icon('<path d="M13 8H3M7.5 3.5 3 8l4.5 4.5"/>'),
|
|
40
|
+
next: icon('<path d="M3 8h10M8.5 3.5 13 8l-4.5 4.5"/>'),
|
|
41
|
+
out: icon('<path d="M3 8h10"/>'),
|
|
42
|
+
in: icon('<path d="M3 8h10M8 3v10"/>'),
|
|
43
|
+
download: icon('<path d="M8 2.75v7.5M4.75 7.25 8 10.5l3.25-3.25M3 13.25h10"/>'),
|
|
44
|
+
close: icon('<path d="m4 4 8 8M12 4l-8 8"/>'),
|
|
45
|
+
};
|
|
46
|
+
const ZOOM = { min: 0.25, max: 4 };
|
|
47
|
+
|
|
48
|
+
let viewer = null; // { node, img, pictures, index, zoom, x, y, moved, timer, keys, wake, host }
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Open the viewer on `picture` (an <img> of the page); `download(picture)` saves one (page.mjs).
|
|
52
|
+
* The page's pictures that open large are gone through in document order, `picture` among them
|
|
53
|
+
* whatever its size: 展开 and 全屏查看 ask for it by name, so an image block showing its picture under
|
|
54
|
+
* ZOOM_LEAST (a 32px picture at its own size) or one not loaded yet opens too; the double-click goes
|
|
55
|
+
* by the reader's rule (zoomable) before it calls this.
|
|
56
|
+
*/
|
|
57
|
+
export function openViewer(picture, download) {
|
|
58
|
+
closeViewer();
|
|
59
|
+
const pictures = [...document.querySelectorAll("main img")].filter((img) => img === picture || zoomable(img));
|
|
60
|
+
if (!pictures.includes(picture)) return;
|
|
61
|
+
const host = overlayHost();
|
|
62
|
+
addStyleTo(host.doc, STYLE);
|
|
63
|
+
const img = element("img", { alt: "", draggable: "false" });
|
|
64
|
+
const button = (name, label, text) => {
|
|
65
|
+
const node = element("div", { class: "ge-viewer-button", role: "button", "aria-label": label, "data-act": name });
|
|
66
|
+
if (text) node.textContent = text;
|
|
67
|
+
else node.innerHTML = ICONS[name];
|
|
68
|
+
if (!text && host.doc === document) tooltip(node, label);
|
|
69
|
+
else if (!text) node.title = label; // the editor's tooltips stand on the page, not over the workbench
|
|
70
|
+
return node;
|
|
71
|
+
};
|
|
72
|
+
const zoomed = button("reset", "100%", "100%");
|
|
73
|
+
zoomed.classList.add("ge-viewer-zoom");
|
|
74
|
+
const groups = [];
|
|
75
|
+
if (pictures.length > 1) groups.push(element("div", { class: "ge-viewer-group" }, button("prev", t("上一张")), button("next", t("下一张"))));
|
|
76
|
+
groups.push(element("div", { class: "ge-viewer-group" }, button("out", t("缩小")), zoomed, button("in", t("放大")), element("div", { class: "ge-viewer-sep" }), button("download", t("下载")), element("div", { class: "ge-viewer-sep" }), button("close", t("关闭"))));
|
|
77
|
+
const node = mountOver(host, element("div", { class: "ge-image-viewer", role: "dialog", "aria-label": t("查看图片") }, img, element("div", { class: "ge-viewer-bar" }, ...groups)));
|
|
78
|
+
const v = { node, img, pictures, index: pictures.indexOf(picture), zoom: 1, x: 0, y: 0, moved: false, timer: 0, download, host };
|
|
79
|
+
viewer = v;
|
|
80
|
+
|
|
81
|
+
node.addEventListener("click", (event) => {
|
|
82
|
+
const act = event.target.closest?.("[data-act]")?.getAttribute("data-act");
|
|
83
|
+
if (act) return run(act);
|
|
84
|
+
if (event.target === img) return;
|
|
85
|
+
if (!event.target.closest(".ge-viewer-bar") && !v.moved) closeViewer(); // a click beside the picture
|
|
86
|
+
});
|
|
87
|
+
node.addEventListener("wheel", (event) => {
|
|
88
|
+
event.preventDefault();
|
|
89
|
+
zoomTo(v.zoom * Math.exp(-event.deltaY * 0.0015), around(event));
|
|
90
|
+
}, { passive: false });
|
|
91
|
+
node.addEventListener("pointerdown", (event) => {
|
|
92
|
+
v.moved = false;
|
|
93
|
+
if (event.button !== 0 || event.target !== img || v.zoom <= 1) return;
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
const start = { x: event.clientX, y: event.clientY, panX: v.x, panY: v.y };
|
|
96
|
+
img.style.cursor = "grabbing";
|
|
97
|
+
const move = (moving) => {
|
|
98
|
+
if (Math.abs(moving.clientX - start.x) + Math.abs(moving.clientY - start.y) > 3) v.moved = true;
|
|
99
|
+
v.x = start.panX + moving.clientX - start.x;
|
|
100
|
+
v.y = start.panY + moving.clientY - start.y;
|
|
101
|
+
paint();
|
|
102
|
+
};
|
|
103
|
+
const up = () => {
|
|
104
|
+
host.win.removeEventListener("pointermove", move, true);
|
|
105
|
+
host.win.removeEventListener("pointerup", up, true);
|
|
106
|
+
paint();
|
|
107
|
+
};
|
|
108
|
+
host.win.addEventListener("pointermove", move, true);
|
|
109
|
+
host.win.addEventListener("pointerup", up, true);
|
|
110
|
+
});
|
|
111
|
+
v.keys = (event) => {
|
|
112
|
+
const done = () => { event.preventDefault(); event.stopPropagation(); };
|
|
113
|
+
if (event.key === "Escape" || event.key === " ") { done(); closeViewer(); }
|
|
114
|
+
else if (event.key === "ArrowLeft") { done(); show(v.index - 1); }
|
|
115
|
+
else if (event.key === "ArrowRight") { done(); show(v.index + 1); }
|
|
116
|
+
else if (event.key === "+" || event.key === "=") { done(); zoomTo(v.zoom * 1.25); }
|
|
117
|
+
else if (event.key === "-" || event.key === "_") { done(); zoomTo(v.zoom / 1.25); }
|
|
118
|
+
else if (!(event.ctrlKey || event.metaKey)) done(); // the page takes no keys meanwhile
|
|
119
|
+
};
|
|
120
|
+
v.wake = () => {
|
|
121
|
+
node.removeAttribute("data-idle");
|
|
122
|
+
clearTimeout(v.timer);
|
|
123
|
+
v.timer = setTimeout(() => viewer === v && node.setAttribute("data-idle", ""), 2000);
|
|
124
|
+
};
|
|
125
|
+
for (const doc of new Set([document, host.doc])) doc.addEventListener("keydown", v.keys, true);
|
|
126
|
+
host.win.addEventListener("pointermove", v.wake, true);
|
|
127
|
+
host.win.addEventListener("resize", fit);
|
|
128
|
+
img.addEventListener("load", fit);
|
|
129
|
+
document.activeElement?.blur?.();
|
|
130
|
+
show(v.index);
|
|
131
|
+
v.wake();
|
|
132
|
+
node.getBoundingClientRect(); // its first style taken, so that showing it fades in
|
|
133
|
+
node.setAttribute("data-shown", "");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** The viewer gone, if it is open. */
|
|
137
|
+
export function closeViewer() {
|
|
138
|
+
const v = viewer;
|
|
139
|
+
if (!v) return;
|
|
140
|
+
viewer = null;
|
|
141
|
+
for (const doc of new Set([document, v.host.doc])) doc.removeEventListener("keydown", v.keys, true);
|
|
142
|
+
v.host.win.removeEventListener("pointermove", v.wake, true);
|
|
143
|
+
v.host.win.removeEventListener("resize", fit);
|
|
144
|
+
clearTimeout(v.timer);
|
|
145
|
+
v.node.remove();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function run(act) {
|
|
149
|
+
const v = viewer;
|
|
150
|
+
if (act === "close") closeViewer();
|
|
151
|
+
else if (act === "prev") show(v.index - 1);
|
|
152
|
+
else if (act === "next") show(v.index + 1);
|
|
153
|
+
else if (act === "in") zoomTo(v.zoom * 1.25);
|
|
154
|
+
else if (act === "out") zoomTo(v.zoom / 1.25);
|
|
155
|
+
else if (act === "reset") zoomTo(1);
|
|
156
|
+
else if (act === "download") v.download(v.pictures[v.index]);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function show(index) {
|
|
160
|
+
const v = viewer;
|
|
161
|
+
v.index = Math.max(0, Math.min(v.pictures.length - 1, index));
|
|
162
|
+
v.zoom = 1;
|
|
163
|
+
v.x = 0;
|
|
164
|
+
v.y = 0;
|
|
165
|
+
v.img.src = v.pictures[v.index].currentSrc || v.pictures[v.index].src;
|
|
166
|
+
v.node.querySelector('[data-act="prev"]')?.toggleAttribute("data-off", v.index === 0);
|
|
167
|
+
v.node.querySelector('[data-act="next"]')?.toggleAttribute("data-off", v.index === v.pictures.length - 1);
|
|
168
|
+
fit();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// The picture fitted into the window it covers (32px around it from 1020px wide), never past its own size.
|
|
172
|
+
function fit() {
|
|
173
|
+
const v = viewer;
|
|
174
|
+
if (!v?.img.naturalWidth) return;
|
|
175
|
+
const { naturalWidth: width, naturalHeight: height } = v.img;
|
|
176
|
+
const { innerWidth: across, innerHeight: down } = v.host.win;
|
|
177
|
+
const gap = across >= 1020 ? 32 : 0;
|
|
178
|
+
const scale = Math.min(1, (across - 2 * gap) / width, (down - 2 * gap) / height);
|
|
179
|
+
v.img.style.width = `${width * scale}px`;
|
|
180
|
+
v.img.style.height = `${height * scale}px`;
|
|
181
|
+
paint();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Where the pointer is, from the window's middle (the zoom's center).
|
|
185
|
+
function around(event) {
|
|
186
|
+
const rect = viewer.node.getBoundingClientRect();
|
|
187
|
+
return { x: event.clientX - (rect.left + rect.width / 2), y: event.clientY - (rect.top + rect.height / 2) };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function zoomTo(value, at = null) {
|
|
191
|
+
const v = viewer;
|
|
192
|
+
const zoom = Math.max(ZOOM.min, Math.min(ZOOM.max, Math.round(value * 1000) / 1000));
|
|
193
|
+
if (at) {
|
|
194
|
+
const k = zoom / v.zoom;
|
|
195
|
+
v.x = at.x - (at.x - v.x) * k;
|
|
196
|
+
v.y = at.y - (at.y - v.y) * k;
|
|
197
|
+
}
|
|
198
|
+
v.zoom = zoom;
|
|
199
|
+
if (zoom <= 1) {
|
|
200
|
+
v.x = 0;
|
|
201
|
+
v.y = 0;
|
|
202
|
+
}
|
|
203
|
+
paint();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function paint() {
|
|
207
|
+
const v = viewer;
|
|
208
|
+
v.img.style.transform = `translate(${v.x}px, ${v.y}px) scale(${v.zoom})`;
|
|
209
|
+
v.img.style.cursor = v.zoom > 1 ? "grab" : "default";
|
|
210
|
+
v.node.querySelector(".ge-viewer-zoom").textContent = `${Math.round(v.zoom * 100)}%`;
|
|
211
|
+
v.node.querySelector('[data-act="out"]').toggleAttribute("data-off", v.zoom <= ZOOM.min);
|
|
212
|
+
v.node.querySelector('[data-act="in"]').toggleAttribute("data-off", v.zoom >= ZOOM.max);
|
|
213
|
+
}
|