omni-viewer-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +80 -0
- package/THIRD_PARTY_NOTICES.md +49 -0
- package/dist/assets/audio-engine/audio_engine.mjs +2 -0
- package/dist/assets/audio-engine/audio_engine.wasm +0 -0
- package/dist/assets/pdfjs/pdf.worker.min.mjs +21 -0
- package/dist/host/index.d.ts +133 -0
- package/dist/host/index.js +10 -0
- package/dist/i18n/catalog.en.d.ts +1 -0
- package/dist/i18n/catalog.en.js +411 -0
- package/dist/i18n/catalog.ko.d.ts +1 -0
- package/dist/i18n/catalog.ko.js +68 -0
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +41 -0
- package/dist/licenses/emscripten.txt +101 -0
- package/dist/licenses/kissfft.txt +28 -0
- package/dist/licenses/pdfjs-dist.txt +177 -0
- package/dist/parsers/a2l/index.d.ts +1 -0
- package/dist/parsers/a2l/index.js +1 -0
- package/dist/parsers/archive/index.d.ts +22 -0
- package/dist/parsers/archive/index.js +46 -0
- package/dist/parsers/archive/model.d.ts +29 -0
- package/dist/parsers/archive/model.js +1 -0
- package/dist/parsers/archive/worker.d.ts +21 -0
- package/dist/parsers/archive/worker.js +1 -0
- package/dist/parsers/arxml/index.d.ts +1 -0
- package/dist/parsers/arxml/index.js +1 -0
- package/dist/parsers/asc/index.d.ts +1 -0
- package/dist/parsers/asc/index.js +1 -0
- package/dist/parsers/audio/index.d.ts +9 -0
- package/dist/parsers/audio/index.js +46 -0
- package/dist/parsers/automotive/index.d.ts +33 -0
- package/dist/parsers/automotive/index.js +973 -0
- package/dist/parsers/blf/index.d.ts +1 -0
- package/dist/parsers/blf/index.js +1 -0
- package/dist/parsers/csv/delimiter.d.ts +31 -0
- package/dist/parsers/csv/delimiter.js +151 -0
- package/dist/parsers/csv/index.d.ts +30 -0
- package/dist/parsers/csv/index.js +108 -0
- package/dist/parsers/csv/parseText.d.ts +20 -0
- package/dist/parsers/csv/parseText.js +108 -0
- package/dist/parsers/csv/sort.d.ts +26 -0
- package/dist/parsers/csv/sort.js +224 -0
- package/dist/parsers/csv/statistics.d.ts +49 -0
- package/dist/parsers/csv/statistics.js +150 -0
- package/dist/parsers/dbc/index.d.ts +56 -0
- package/dist/parsers/dbc/index.js +94 -0
- package/dist/parsers/doc-binary/index.d.ts +35 -0
- package/dist/parsers/doc-binary/index.js +267 -0
- package/dist/parsers/doc-binary/vscode-parser.d.ts +142 -0
- package/dist/parsers/doc-binary/vscode-parser.js +3747 -0
- package/dist/parsers/excel/index.d.ts +17 -0
- package/dist/parsers/excel/index.js +406 -0
- package/dist/parsers/excel/model.d.ts +80 -0
- package/dist/parsers/excel/model.js +48 -0
- package/dist/parsers/excel/serialize.d.ts +3 -0
- package/dist/parsers/excel/serialize.js +78 -0
- package/dist/parsers/hdf5/index.d.ts +75 -0
- package/dist/parsers/hdf5/index.js +658 -0
- package/dist/parsers/hdf5/node.d.ts +21 -0
- package/dist/parsers/hdf5/node.js +95 -0
- package/dist/parsers/json/index.d.ts +15 -0
- package/dist/parsers/json/index.js +102 -0
- package/dist/parsers/json/model.d.ts +42 -0
- package/dist/parsers/json/model.js +140 -0
- package/dist/parsers/json/parse.d.ts +22 -0
- package/dist/parsers/json/parse.js +279 -0
- package/dist/parsers/json/tokenizer.d.ts +17 -0
- package/dist/parsers/json/tokenizer.js +175 -0
- package/dist/parsers/jsonl/index.d.ts +14 -0
- package/dist/parsers/jsonl/index.js +18 -0
- package/dist/parsers/jsonl/model.d.ts +23 -0
- package/dist/parsers/jsonl/model.js +1 -0
- package/dist/parsers/jsonl/parse.d.ts +7 -0
- package/dist/parsers/jsonl/parse.js +34 -0
- package/dist/parsers/markdown/index.d.ts +37 -0
- package/dist/parsers/markdown/index.js +59 -0
- package/dist/parsers/mat/index.d.ts +31 -0
- package/dist/parsers/mat/index.js +426 -0
- package/dist/parsers/mermaid/index.d.ts +5 -0
- package/dist/parsers/mermaid/index.js +3 -0
- package/dist/parsers/mf4/index.d.ts +1 -0
- package/dist/parsers/mf4/index.js +1 -0
- package/dist/parsers/parquet/index.d.ts +21 -0
- package/dist/parsers/parquet/index.js +68 -0
- package/dist/parsers/pcap/index.d.ts +1 -0
- package/dist/parsers/pcap/index.js +1 -0
- package/dist/parsers/pcapng/index.d.ts +1 -0
- package/dist/parsers/pcapng/index.js +1 -0
- package/dist/parsers/plantuml/index.d.ts +5 -0
- package/dist/parsers/plantuml/index.js +4 -0
- package/dist/parsers/ppt-binary/index.d.ts +5 -0
- package/dist/parsers/ppt-binary/index.js +62 -0
- package/dist/parsers/ppt-binary/pptBinaryBuildContext.d.ts +12 -0
- package/dist/parsers/ppt-binary/pptBinaryBuildContext.js +40 -0
- package/dist/parsers/ppt-binary/pptBinaryContainer.d.ts +4 -0
- package/dist/parsers/ppt-binary/pptBinaryContainer.js +174 -0
- package/dist/parsers/ppt-binary/pptBinaryTypes.d.ts +125 -0
- package/dist/parsers/ppt-binary/pptBinaryTypes.js +1 -0
- package/dist/parsers/ppt-binary/pptSlideLayouts.d.ts +9 -0
- package/dist/parsers/ppt-binary/pptSlideLayouts.js +510 -0
- package/dist/parsers/ppt-binary/vscode-parser.d.ts +116 -0
- package/dist/parsers/ppt-binary/vscode-parser.js +2853 -0
- package/dist/parsers/ppt-binary/vscode.d.ts +4 -0
- package/dist/parsers/ppt-binary/vscode.js +12 -0
- package/dist/parsers/pptx/index.d.ts +15 -0
- package/dist/parsers/pptx/index.js +88 -0
- package/dist/parsers/pptx/vscode-parser.d.ts +167 -0
- package/dist/parsers/pptx/vscode-parser.js +1503 -0
- package/dist/parsers/pptx/vscode.d.ts +4 -0
- package/dist/parsers/pptx/vscode.js +18 -0
- package/dist/parsers/pptx/zip-reader.d.ts +3 -0
- package/dist/parsers/pptx/zip-reader.js +20 -0
- package/dist/parsers/proto/index.d.ts +90 -0
- package/dist/parsers/proto/index.js +197 -0
- package/dist/parsers/psd/index.d.ts +16 -0
- package/dist/parsers/psd/index.js +10 -0
- package/dist/parsers/shapefile/dbf.d.ts +23 -0
- package/dist/parsers/shapefile/dbf.js +112 -0
- package/dist/parsers/shapefile/index.d.ts +44 -0
- package/dist/parsers/shapefile/index.js +119 -0
- package/dist/parsers/shapefile/reproject.d.ts +10 -0
- package/dist/parsers/shapefile/reproject.js +41 -0
- package/dist/parsers/slide-model.d.ts +106 -0
- package/dist/parsers/slide-model.js +1 -0
- package/dist/parsers/toml/index.d.ts +15 -0
- package/dist/parsers/toml/index.js +18 -0
- package/dist/parsers/toml/model.d.ts +15 -0
- package/dist/parsers/toml/model.js +1 -0
- package/dist/parsers/toml/parse.d.ts +16 -0
- package/dist/parsers/toml/parse.js +266 -0
- package/dist/parsers/types.d.ts +103 -0
- package/dist/parsers/types.js +106 -0
- package/dist/parsers/video/index.d.ts +6 -0
- package/dist/parsers/video/index.js +2 -0
- package/dist/parsers/yaml/index.d.ts +16 -0
- package/dist/parsers/yaml/index.js +58 -0
- package/dist/parsers/yaml/model.d.ts +22 -0
- package/dist/parsers/yaml/model.js +1 -0
- package/dist/parsers/yaml/self-loading.d.ts +3 -0
- package/dist/parsers/yaml/self-loading.js +19 -0
- package/dist/parsers/zip-scan.d.ts +8 -0
- package/dist/parsers/zip-scan.js +80 -0
- package/dist/registry/container.d.ts +17 -0
- package/dist/registry/container.js +49 -0
- package/dist/registry/index.d.ts +133 -0
- package/dist/registry/index.js +348 -0
- package/dist/registry/probe.d.ts +3 -0
- package/dist/registry/probe.js +177 -0
- package/dist/registry/sniff.d.ts +17 -0
- package/dist/registry/sniff.js +57 -0
- package/dist/styles/archive.css +10 -0
- package/dist/styles/audio.css +66 -0
- package/dist/styles/automotive.css +1 -0
- package/dist/styles/csv.css +262 -0
- package/dist/styles/excel.css +212 -0
- package/dist/styles/fallback.css +48 -0
- package/dist/styles/hdf5.css +3 -0
- package/dist/styles/hwp.css +12 -0
- package/dist/styles/image.css +115 -0
- package/dist/styles/json.css +342 -0
- package/dist/styles/jsonl.css +1 -0
- package/dist/styles/markdown.css +10 -0
- package/dist/styles/mat.css +2 -0
- package/dist/styles/mermaid.css +1 -0
- package/dist/styles/parquet.css +2 -0
- package/dist/styles/pdf.css +551 -0
- package/dist/styles/plantuml.css +1 -0
- package/dist/styles/ppt.css +1 -0
- package/dist/styles/proto.css +2 -0
- package/dist/styles/psd.css +1 -0
- package/dist/styles/shapefile.css +25 -0
- package/dist/styles/toml.css +1 -0
- package/dist/styles/video.css +74 -0
- package/dist/styles/word.css +685 -0
- package/dist/styles/yaml.css +1 -0
- package/dist/viewers/a2l/index.d.ts +15 -0
- package/dist/viewers/a2l/index.js +5 -0
- package/dist/viewers/archive/archive-preview-decoder.d.ts +4 -0
- package/dist/viewers/archive/archive-preview-decoder.js +223 -0
- package/dist/viewers/archive/controller.d.ts +24 -0
- package/dist/viewers/archive/controller.js +18 -0
- package/dist/viewers/archive/index.d.ts +25 -0
- package/dist/viewers/archive/index.js +230 -0
- package/dist/viewers/archive/preview.d.ts +2 -0
- package/dist/viewers/archive/preview.js +2 -0
- package/dist/viewers/archive/styles.d.ts +1 -0
- package/dist/viewers/archive/styles.js +11 -0
- package/dist/viewers/arxml/index.d.ts +15 -0
- package/dist/viewers/arxml/index.js +5 -0
- package/dist/viewers/asc/index.d.ts +15 -0
- package/dist/viewers/asc/index.js +5 -0
- package/dist/viewers/audio/controller.d.ts +33 -0
- package/dist/viewers/audio/controller.js +49 -0
- package/dist/viewers/audio/engine.d.ts +44 -0
- package/dist/viewers/audio/engine.js +108 -0
- package/dist/viewers/audio/index.d.ts +92 -0
- package/dist/viewers/audio/index.js +448 -0
- package/dist/viewers/audio/self-loading.d.ts +7 -0
- package/dist/viewers/audio/self-loading.js +42 -0
- package/dist/viewers/audio/styles.d.ts +1 -0
- package/dist/viewers/audio/styles.js +73 -0
- package/dist/viewers/automotive/index.d.ts +8 -0
- package/dist/viewers/automotive/index.js +152 -0
- package/dist/viewers/automotive/styles.d.ts +1 -0
- package/dist/viewers/automotive/styles.js +1 -0
- package/dist/viewers/avro/index.d.ts +15 -0
- package/dist/viewers/avro/index.js +5 -0
- package/dist/viewers/bag/index.d.ts +15 -0
- package/dist/viewers/bag/index.js +5 -0
- package/dist/viewers/blf/index.d.ts +15 -0
- package/dist/viewers/blf/index.js +5 -0
- package/dist/viewers/csv/controller.d.ts +126 -0
- package/dist/viewers/csv/controller.js +598 -0
- package/dist/viewers/csv/index.d.ts +48 -0
- package/dist/viewers/csv/index.js +846 -0
- package/dist/viewers/csv/styles.d.ts +1 -0
- package/dist/viewers/csv/styles.js +267 -0
- package/dist/viewers/db3/index.d.ts +15 -0
- package/dist/viewers/db3/index.js +5 -0
- package/dist/viewers/dbc/index.d.ts +15 -0
- package/dist/viewers/dbc/index.js +5 -0
- package/dist/viewers/diagram.d.ts +14 -0
- package/dist/viewers/diagram.js +95 -0
- package/dist/viewers/excel/controller.d.ts +108 -0
- package/dist/viewers/excel/controller.js +548 -0
- package/dist/viewers/excel/grid.d.ts +28 -0
- package/dist/viewers/excel/grid.js +99 -0
- package/dist/viewers/excel/index.d.ts +37 -0
- package/dist/viewers/excel/index.js +620 -0
- package/dist/viewers/excel/self-loading.d.ts +6 -0
- package/dist/viewers/excel/self-loading.js +13 -0
- package/dist/viewers/excel/styles.d.ts +1 -0
- package/dist/viewers/excel/styles.js +216 -0
- package/dist/viewers/fallback/index.d.ts +17 -0
- package/dist/viewers/fallback/index.js +130 -0
- package/dist/viewers/fallback/styles.d.ts +1 -0
- package/dist/viewers/fallback/styles.js +49 -0
- package/dist/viewers/hdf5/index.d.ts +19 -0
- package/dist/viewers/hdf5/index.js +170 -0
- package/dist/viewers/hdf5/styles.d.ts +1 -0
- package/dist/viewers/hdf5/styles.js +4 -0
- package/dist/viewers/hwp/controller.d.ts +19 -0
- package/dist/viewers/hwp/controller.js +22 -0
- package/dist/viewers/hwp/index.d.ts +39 -0
- package/dist/viewers/hwp/index.js +271 -0
- package/dist/viewers/hwp/self-loading.d.ts +2 -0
- package/dist/viewers/hwp/self-loading.js +6 -0
- package/dist/viewers/hwp/styles.d.ts +1 -0
- package/dist/viewers/hwp/styles.js +13 -0
- package/dist/viewers/image/controller.d.ts +210 -0
- package/dist/viewers/image/controller.js +336 -0
- package/dist/viewers/image/decode.d.ts +54 -0
- package/dist/viewers/image/decode.js +150 -0
- package/dist/viewers/image/index.d.ts +38 -0
- package/dist/viewers/image/index.js +749 -0
- package/dist/viewers/image/limits.d.ts +18 -0
- package/dist/viewers/image/limits.js +20 -0
- package/dist/viewers/image/styles.d.ts +1 -0
- package/dist/viewers/image/styles.js +119 -0
- package/dist/viewers/json/controller.d.ts +89 -0
- package/dist/viewers/json/controller.js +411 -0
- package/dist/viewers/json/index.d.ts +25 -0
- package/dist/viewers/json/index.js +503 -0
- package/dist/viewers/json/styles.d.ts +1 -0
- package/dist/viewers/json/styles.js +346 -0
- package/dist/viewers/json/transforms.d.ts +27 -0
- package/dist/viewers/json/transforms.js +253 -0
- package/dist/viewers/jsonl/controller.d.ts +48 -0
- package/dist/viewers/jsonl/controller.js +136 -0
- package/dist/viewers/jsonl/index.d.ts +22 -0
- package/dist/viewers/jsonl/index.js +184 -0
- package/dist/viewers/jsonl/styles.d.ts +1 -0
- package/dist/viewers/jsonl/styles.js +1 -0
- package/dist/viewers/markdown/controller.d.ts +50 -0
- package/dist/viewers/markdown/controller.js +62 -0
- package/dist/viewers/markdown/index.d.ts +64 -0
- package/dist/viewers/markdown/index.js +425 -0
- package/dist/viewers/markdown/math.d.ts +21 -0
- package/dist/viewers/markdown/math.js +100 -0
- package/dist/viewers/markdown/self-loading.d.ts +5 -0
- package/dist/viewers/markdown/self-loading.js +48 -0
- package/dist/viewers/markdown/styles.d.ts +1 -0
- package/dist/viewers/markdown/styles.js +11 -0
- package/dist/viewers/mat/index.d.ts +19 -0
- package/dist/viewers/mat/index.js +113 -0
- package/dist/viewers/mat/styles.d.ts +1 -0
- package/dist/viewers/mat/styles.js +3 -0
- package/dist/viewers/media.d.ts +9 -0
- package/dist/viewers/media.js +77 -0
- package/dist/viewers/mermaid/index.d.ts +17 -0
- package/dist/viewers/mermaid/index.js +6 -0
- package/dist/viewers/mermaid/self-loading.d.ts +2 -0
- package/dist/viewers/mermaid/self-loading.js +2 -0
- package/dist/viewers/mf4/index.d.ts +15 -0
- package/dist/viewers/mf4/index.js +5 -0
- package/dist/viewers/parquet/controller.d.ts +37 -0
- package/dist/viewers/parquet/controller.js +26 -0
- package/dist/viewers/parquet/index.d.ts +23 -0
- package/dist/viewers/parquet/index.js +134 -0
- package/dist/viewers/parquet/styles.d.ts +1 -0
- package/dist/viewers/parquet/styles.js +3 -0
- package/dist/viewers/pcap/index.d.ts +15 -0
- package/dist/viewers/pcap/index.js +5 -0
- package/dist/viewers/pcapng/index.d.ts +15 -0
- package/dist/viewers/pcapng/index.js +5 -0
- package/dist/viewers/pdf/controller.d.ts +120 -0
- package/dist/viewers/pdf/controller.js +191 -0
- package/dist/viewers/pdf/editing.d.ts +26 -0
- package/dist/viewers/pdf/editing.js +265 -0
- package/dist/viewers/pdf/index.d.ts +88 -0
- package/dist/viewers/pdf/index.js +1400 -0
- package/dist/viewers/pdf/self-loading.d.ts +6 -0
- package/dist/viewers/pdf/self-loading.js +14 -0
- package/dist/viewers/pdf/styles.d.ts +1 -0
- package/dist/viewers/pdf/styles.js +555 -0
- package/dist/viewers/plantuml/index.d.ts +17 -0
- package/dist/viewers/plantuml/index.js +6 -0
- package/dist/viewers/plantuml/self-loading.d.ts +2 -0
- package/dist/viewers/plantuml/self-loading.js +2 -0
- package/dist/viewers/ppt/chart.d.ts +8 -0
- package/dist/viewers/ppt/chart.js +83 -0
- package/dist/viewers/ppt/controller.d.ts +34 -0
- package/dist/viewers/ppt/controller.js +27 -0
- package/dist/viewers/ppt/index.d.ts +33 -0
- package/dist/viewers/ppt/index.js +101 -0
- package/dist/viewers/ppt/render.d.ts +5 -0
- package/dist/viewers/ppt/render.js +144 -0
- package/dist/viewers/ppt/self-loading.d.ts +9 -0
- package/dist/viewers/ppt/self-loading.js +4 -0
- package/dist/viewers/ppt/styles.d.ts +1 -0
- package/dist/viewers/ppt/styles.js +1 -0
- package/dist/viewers/proto/index.d.ts +17 -0
- package/dist/viewers/proto/index.js +170 -0
- package/dist/viewers/proto/styles.d.ts +1 -0
- package/dist/viewers/proto/styles.js +2 -0
- package/dist/viewers/psd/index.d.ts +27 -0
- package/dist/viewers/psd/index.js +39 -0
- package/dist/viewers/psd/self-loading.d.ts +10 -0
- package/dist/viewers/psd/self-loading.js +20 -0
- package/dist/viewers/psd/styles.d.ts +1 -0
- package/dist/viewers/psd/styles.js +1 -0
- package/dist/viewers/reqif/index.d.ts +15 -0
- package/dist/viewers/reqif/index.js +5 -0
- package/dist/viewers/shapefile/index.d.ts +35 -0
- package/dist/viewers/shapefile/index.js +336 -0
- package/dist/viewers/shapefile/self-loading.d.ts +7 -0
- package/dist/viewers/shapefile/self-loading.js +32 -0
- package/dist/viewers/shapefile/styles.d.ts +1 -0
- package/dist/viewers/shapefile/styles.js +28 -0
- package/dist/viewers/stp/index.d.ts +15 -0
- package/dist/viewers/stp/index.js +5 -0
- package/dist/viewers/structured-styles.d.ts +1 -0
- package/dist/viewers/structured-styles.js +1 -0
- package/dist/viewers/structured.d.ts +36 -0
- package/dist/viewers/structured.js +138 -0
- package/dist/viewers/toml/controller.d.ts +38 -0
- package/dist/viewers/toml/controller.js +61 -0
- package/dist/viewers/toml/index.d.ts +18 -0
- package/dist/viewers/toml/index.js +34 -0
- package/dist/viewers/types.d.ts +36 -0
- package/dist/viewers/types.js +9 -0
- package/dist/viewers/video/controller.d.ts +29 -0
- package/dist/viewers/video/controller.js +54 -0
- package/dist/viewers/video/index.d.ts +18 -0
- package/dist/viewers/video/index.js +305 -0
- package/dist/viewers/video/styles.d.ts +1 -0
- package/dist/viewers/video/styles.js +79 -0
- package/dist/viewers/word/controller.d.ts +19 -0
- package/dist/viewers/word/controller.js +22 -0
- package/dist/viewers/word/docx-preprocess.d.ts +63 -0
- package/dist/viewers/word/docx-preprocess.js +136 -0
- package/dist/viewers/word/index.d.ts +32 -0
- package/dist/viewers/word/index.js +187 -0
- package/dist/viewers/word/normalize-docx.d.ts +2 -0
- package/dist/viewers/word/normalize-docx.js +50 -0
- package/dist/viewers/word/paginate.d.ts +1 -0
- package/dist/viewers/word/paginate.js +1035 -0
- package/dist/viewers/word/self-loading.d.ts +2 -0
- package/dist/viewers/word/self-loading.js +7 -0
- package/dist/viewers/word/styles.d.ts +1 -0
- package/dist/viewers/word/styles.js +686 -0
- package/dist/viewers/yaml/controller.d.ts +42 -0
- package/dist/viewers/yaml/controller.js +41 -0
- package/dist/viewers/yaml/index.d.ts +21 -0
- package/dist/viewers/yaml/index.js +20 -0
- package/package.json +375 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const excelViewerCss = "\n/* Reverse-contamination guard (DESIGN.md \u00A76, ADR 40): in 'scoped' mode host\n global element selectors (button/table/input\u2026) must be neutralized. Harmless\n in shadow mode. Custom properties pierce 'all', so --omni-* tokens still\n apply. Component rules below win (later + higher specificity). */\n.omni-viewer--excel {\n all: initial;\n}\n.omni-viewer--excel :where(button, select, option, input, label,\n table, thead, tbody, tr, th, td, pre) {\n all: revert;\n}\n\n:host, .omni-viewer--excel {\n display: block;\n height: 100%;\n box-sizing: border-box;\n color: var(--omni-fg, #d4d4d4);\n background: var(--omni-bg, #1e1e1e);\n font-family: var(--omni-font, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);\n font-size: var(--omni-font-size, 13px);\n}\n.omni-excel {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.omni-excel__toolbar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px;\n padding: 6px 8px;\n border-bottom: 1px solid var(--omni-border, #333);\n}\n.omni-excel__toolbar label {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n.omni-excel__toolbar select,\n.omni-excel__search {\n background: var(--omni-input-bg, #2a2a2a);\n color: inherit;\n border: 1px solid var(--omni-border, #333);\n border-radius: 3px;\n padding: 2px 6px;\n}\n.omni-excel__toolbar button {\n background: var(--omni-button-bg, #333);\n color: inherit;\n border: 1px solid var(--omni-border, #333);\n border-radius: 3px;\n padding: 2px 8px;\n cursor: pointer;\n}\n.omni-excel__toolbar button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.omni-excel__spacer { flex: 1 1 auto; }\n.omni-excel__meta { color: var(--omni-fg-muted, #999); white-space: nowrap; }\n.omni-excel__diagnostics {\n padding: 4px 8px;\n border-bottom: 1px solid var(--omni-border, #333);\n color: var(--omni-fg-muted, #999);\n font-size: 0.92em;\n}\n.omni-excel__diag-error { color: var(--omni-error, #f48771); }\n.omni-excel__body {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n}\n.omni-excel__empty {\n padding: 24px;\n text-align: center;\n color: var(--omni-fg-muted, #999);\n}\n.omni-excel__raw {\n margin: 0;\n padding: 8px 12px;\n white-space: pre;\n font-family: var(--omni-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n}\n.omni-excel__table {\n border-collapse: collapse;\n width: max-content;\n min-width: 100%;\n}\n.omni-excel__table th,\n.omni-excel__table td {\n border: 1px solid var(--omni-border, #333);\n padding: 3px 8px;\n text-align: left;\n white-space: pre;\n vertical-align: top;\n}\n.omni-excel__table thead th {\n position: sticky;\n top: 0;\n background: var(--omni-header-bg, #252525);\n cursor: pointer;\n user-select: none;\n}\n.omni-excel__table tbody td {\n cursor: text;\n}\n.omni-excel__cell-input {\n box-sizing: border-box;\n width: 100%;\n min-width: 80px;\n margin: -3px -8px;\n padding: 3px 8px;\n border: 1px solid var(--omni-accent, #0e639c);\n background: var(--omni-input-bg, #2a2a2a);\n color: inherit;\n font: inherit;\n}\n.omni-excel__resize-handle {\n position: absolute;\n top: 0;\n right: 0;\n width: 7px;\n height: 100%;\n cursor: col-resize;\n user-select: none;\n touch-action: none;\n}\n.omni-excel__resize-handle:hover {\n background: var(--omni-accent, #0e639c);\n opacity: 0.6;\n}\n.omni-excel__sort-indicator { margin-left: 4px; }\n.omni-excel__hit { background: var(--omni-highlight, rgba(255, 214, 0, 0.25)); }\n.omni-excel__footer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 4px 8px;\n border-top: 1px solid var(--omni-border, #333);\n}\n.omni-excel__footer button {\n background: var(--omni-button-bg, #333);\n color: inherit;\n border: 1px solid var(--omni-border, #333);\n border-radius: 3px;\n padding: 2px 8px;\n cursor: pointer;\n}\n.omni-excel__footer button:disabled { opacity: 0.5; cursor: default; }\n.omni-excel__toast {\n position: absolute;\n bottom: 12px;\n left: 50%;\n transform: translateX(-50%);\n background: var(--omni-toast-bg, #333);\n color: var(--omni-fg, #d4d4d4);\n border: 1px solid var(--omni-border, #333);\n border-radius: 4px;\n padding: 6px 12px;\n pointer-events: none;\n}\n.omni-excel__dirty { color: var(--omni-warn, #d7a017); white-space: nowrap; }\n.omni-excel__cell-input {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n color: inherit;\n background: var(--omni-input-bg, #2a2a2a);\n border: 1px solid var(--omni-accent, #3794ff);\n padding: 2px 6px;\n}\n.omni-excel__menu {\n position: absolute;\n z-index: 10;\n display: flex;\n flex-direction: column;\n min-width: 140px;\n background: var(--omni-menu-bg, #2a2a2a);\n border: 1px solid var(--omni-border, #333);\n border-radius: 4px;\n padding: 4px 0;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);\n}\n.omni-excel__menu button {\n background: none;\n border: none;\n color: inherit;\n text-align: left;\n padding: 4px 12px;\n cursor: pointer;\n}\n.omni-excel__menu button:hover { background: var(--omni-hover-bg, #333); }\n\n/* Grid render mode (X3): WYSIWYG. Cell inline styles (from the file) win over\n these base rules; borders/alignment default here when the file omits them. */\n.omni-excel__grid {\n border-collapse: collapse;\n table-layout: fixed;\n width: max-content;\n}\n.omni-excel__grid td {\n border: 1px solid var(--omni-border, #333);\n padding: 2px 6px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: top;\n}\n";
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// Excel viewer stylesheet. Single source for both delivery forms (DESIGN.md §6):
|
|
2
|
+
// the build emits dist/styles/excel.css from this constant, and the renderer
|
|
3
|
+
// injects it into the shadow root. Only --omni-* tokens (with fallbacks).
|
|
4
|
+
export const excelViewerCss = `
|
|
5
|
+
/* Reverse-contamination guard (DESIGN.md §6, ADR 40): in 'scoped' mode host
|
|
6
|
+
global element selectors (button/table/input…) must be neutralized. Harmless
|
|
7
|
+
in shadow mode. Custom properties pierce 'all', so --omni-* tokens still
|
|
8
|
+
apply. Component rules below win (later + higher specificity). */
|
|
9
|
+
.omni-viewer--excel {
|
|
10
|
+
all: initial;
|
|
11
|
+
}
|
|
12
|
+
.omni-viewer--excel :where(button, select, option, input, label,
|
|
13
|
+
table, thead, tbody, tr, th, td, pre) {
|
|
14
|
+
all: revert;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:host, .omni-viewer--excel {
|
|
18
|
+
display: block;
|
|
19
|
+
height: 100%;
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
color: var(--omni-fg, #d4d4d4);
|
|
22
|
+
background: var(--omni-bg, #1e1e1e);
|
|
23
|
+
font-family: var(--omni-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
|
|
24
|
+
font-size: var(--omni-font-size, 13px);
|
|
25
|
+
}
|
|
26
|
+
.omni-excel {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
height: 100%;
|
|
30
|
+
min-height: 0;
|
|
31
|
+
}
|
|
32
|
+
.omni-excel__toolbar {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
flex-wrap: wrap;
|
|
36
|
+
gap: 8px;
|
|
37
|
+
padding: 6px 8px;
|
|
38
|
+
border-bottom: 1px solid var(--omni-border, #333);
|
|
39
|
+
}
|
|
40
|
+
.omni-excel__toolbar label {
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 4px;
|
|
44
|
+
}
|
|
45
|
+
.omni-excel__toolbar select,
|
|
46
|
+
.omni-excel__search {
|
|
47
|
+
background: var(--omni-input-bg, #2a2a2a);
|
|
48
|
+
color: inherit;
|
|
49
|
+
border: 1px solid var(--omni-border, #333);
|
|
50
|
+
border-radius: 3px;
|
|
51
|
+
padding: 2px 6px;
|
|
52
|
+
}
|
|
53
|
+
.omni-excel__toolbar button {
|
|
54
|
+
background: var(--omni-button-bg, #333);
|
|
55
|
+
color: inherit;
|
|
56
|
+
border: 1px solid var(--omni-border, #333);
|
|
57
|
+
border-radius: 3px;
|
|
58
|
+
padding: 2px 8px;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
}
|
|
61
|
+
.omni-excel__toolbar button:disabled {
|
|
62
|
+
opacity: 0.5;
|
|
63
|
+
cursor: default;
|
|
64
|
+
}
|
|
65
|
+
.omni-excel__spacer { flex: 1 1 auto; }
|
|
66
|
+
.omni-excel__meta { color: var(--omni-fg-muted, #999); white-space: nowrap; }
|
|
67
|
+
.omni-excel__diagnostics {
|
|
68
|
+
padding: 4px 8px;
|
|
69
|
+
border-bottom: 1px solid var(--omni-border, #333);
|
|
70
|
+
color: var(--omni-fg-muted, #999);
|
|
71
|
+
font-size: 0.92em;
|
|
72
|
+
}
|
|
73
|
+
.omni-excel__diag-error { color: var(--omni-error, #f48771); }
|
|
74
|
+
.omni-excel__body {
|
|
75
|
+
flex: 1 1 auto;
|
|
76
|
+
min-height: 0;
|
|
77
|
+
overflow: auto;
|
|
78
|
+
}
|
|
79
|
+
.omni-excel__empty {
|
|
80
|
+
padding: 24px;
|
|
81
|
+
text-align: center;
|
|
82
|
+
color: var(--omni-fg-muted, #999);
|
|
83
|
+
}
|
|
84
|
+
.omni-excel__raw {
|
|
85
|
+
margin: 0;
|
|
86
|
+
padding: 8px 12px;
|
|
87
|
+
white-space: pre;
|
|
88
|
+
font-family: var(--omni-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
89
|
+
}
|
|
90
|
+
.omni-excel__table {
|
|
91
|
+
border-collapse: collapse;
|
|
92
|
+
width: max-content;
|
|
93
|
+
min-width: 100%;
|
|
94
|
+
}
|
|
95
|
+
.omni-excel__table th,
|
|
96
|
+
.omni-excel__table td {
|
|
97
|
+
border: 1px solid var(--omni-border, #333);
|
|
98
|
+
padding: 3px 8px;
|
|
99
|
+
text-align: left;
|
|
100
|
+
white-space: pre;
|
|
101
|
+
vertical-align: top;
|
|
102
|
+
}
|
|
103
|
+
.omni-excel__table thead th {
|
|
104
|
+
position: sticky;
|
|
105
|
+
top: 0;
|
|
106
|
+
background: var(--omni-header-bg, #252525);
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
user-select: none;
|
|
109
|
+
}
|
|
110
|
+
.omni-excel__table tbody td {
|
|
111
|
+
cursor: text;
|
|
112
|
+
}
|
|
113
|
+
.omni-excel__cell-input {
|
|
114
|
+
box-sizing: border-box;
|
|
115
|
+
width: 100%;
|
|
116
|
+
min-width: 80px;
|
|
117
|
+
margin: -3px -8px;
|
|
118
|
+
padding: 3px 8px;
|
|
119
|
+
border: 1px solid var(--omni-accent, #0e639c);
|
|
120
|
+
background: var(--omni-input-bg, #2a2a2a);
|
|
121
|
+
color: inherit;
|
|
122
|
+
font: inherit;
|
|
123
|
+
}
|
|
124
|
+
.omni-excel__resize-handle {
|
|
125
|
+
position: absolute;
|
|
126
|
+
top: 0;
|
|
127
|
+
right: 0;
|
|
128
|
+
width: 7px;
|
|
129
|
+
height: 100%;
|
|
130
|
+
cursor: col-resize;
|
|
131
|
+
user-select: none;
|
|
132
|
+
touch-action: none;
|
|
133
|
+
}
|
|
134
|
+
.omni-excel__resize-handle:hover {
|
|
135
|
+
background: var(--omni-accent, #0e639c);
|
|
136
|
+
opacity: 0.6;
|
|
137
|
+
}
|
|
138
|
+
.omni-excel__sort-indicator { margin-left: 4px; }
|
|
139
|
+
.omni-excel__hit { background: var(--omni-highlight, rgba(255, 214, 0, 0.25)); }
|
|
140
|
+
.omni-excel__footer {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
justify-content: center;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
padding: 4px 8px;
|
|
146
|
+
border-top: 1px solid var(--omni-border, #333);
|
|
147
|
+
}
|
|
148
|
+
.omni-excel__footer button {
|
|
149
|
+
background: var(--omni-button-bg, #333);
|
|
150
|
+
color: inherit;
|
|
151
|
+
border: 1px solid var(--omni-border, #333);
|
|
152
|
+
border-radius: 3px;
|
|
153
|
+
padding: 2px 8px;
|
|
154
|
+
cursor: pointer;
|
|
155
|
+
}
|
|
156
|
+
.omni-excel__footer button:disabled { opacity: 0.5; cursor: default; }
|
|
157
|
+
.omni-excel__toast {
|
|
158
|
+
position: absolute;
|
|
159
|
+
bottom: 12px;
|
|
160
|
+
left: 50%;
|
|
161
|
+
transform: translateX(-50%);
|
|
162
|
+
background: var(--omni-toast-bg, #333);
|
|
163
|
+
color: var(--omni-fg, #d4d4d4);
|
|
164
|
+
border: 1px solid var(--omni-border, #333);
|
|
165
|
+
border-radius: 4px;
|
|
166
|
+
padding: 6px 12px;
|
|
167
|
+
pointer-events: none;
|
|
168
|
+
}
|
|
169
|
+
.omni-excel__dirty { color: var(--omni-warn, #d7a017); white-space: nowrap; }
|
|
170
|
+
.omni-excel__cell-input {
|
|
171
|
+
width: 100%;
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
font: inherit;
|
|
174
|
+
color: inherit;
|
|
175
|
+
background: var(--omni-input-bg, #2a2a2a);
|
|
176
|
+
border: 1px solid var(--omni-accent, #3794ff);
|
|
177
|
+
padding: 2px 6px;
|
|
178
|
+
}
|
|
179
|
+
.omni-excel__menu {
|
|
180
|
+
position: absolute;
|
|
181
|
+
z-index: 10;
|
|
182
|
+
display: flex;
|
|
183
|
+
flex-direction: column;
|
|
184
|
+
min-width: 140px;
|
|
185
|
+
background: var(--omni-menu-bg, #2a2a2a);
|
|
186
|
+
border: 1px solid var(--omni-border, #333);
|
|
187
|
+
border-radius: 4px;
|
|
188
|
+
padding: 4px 0;
|
|
189
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
|
|
190
|
+
}
|
|
191
|
+
.omni-excel__menu button {
|
|
192
|
+
background: none;
|
|
193
|
+
border: none;
|
|
194
|
+
color: inherit;
|
|
195
|
+
text-align: left;
|
|
196
|
+
padding: 4px 12px;
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
}
|
|
199
|
+
.omni-excel__menu button:hover { background: var(--omni-hover-bg, #333); }
|
|
200
|
+
|
|
201
|
+
/* Grid render mode (X3): WYSIWYG. Cell inline styles (from the file) win over
|
|
202
|
+
these base rules; borders/alignment default here when the file omits them. */
|
|
203
|
+
.omni-excel__grid {
|
|
204
|
+
border-collapse: collapse;
|
|
205
|
+
table-layout: fixed;
|
|
206
|
+
width: max-content;
|
|
207
|
+
}
|
|
208
|
+
.omni-excel__grid td {
|
|
209
|
+
border: 1px solid var(--omni-border, #333);
|
|
210
|
+
padding: 2px 6px;
|
|
211
|
+
overflow: hidden;
|
|
212
|
+
text-overflow: ellipsis;
|
|
213
|
+
white-space: nowrap;
|
|
214
|
+
vertical-align: top;
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { HostContext } from '../../host/index.js';
|
|
2
|
+
import { type MountOptions, type ViewerHandle, type ViewerInput } from '../types.js';
|
|
3
|
+
export { fallbackViewerCss } from './styles.js';
|
|
4
|
+
export declare const FALLBACK_VIEWER_META: {
|
|
5
|
+
id: string;
|
|
6
|
+
displayNameKey: string;
|
|
7
|
+
extensions: string[];
|
|
8
|
+
priority: number;
|
|
9
|
+
requiredServices: readonly [];
|
|
10
|
+
optionalServices: readonly [];
|
|
11
|
+
inputOwnership: "borrows";
|
|
12
|
+
};
|
|
13
|
+
export interface FallbackMountOptions extends MountOptions {
|
|
14
|
+
/** Why the fallback is showing (catalog key), e.g. 'fallback.reason.missing-dependency'. */
|
|
15
|
+
reasonKey?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function mountFallbackViewer(input: ViewerInput, container: HTMLElement, ctx: HostContext, options?: FallbackMountOptions): Promise<ViewerHandle>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Shared fallback viewer — the terminal node of every fallback chain
|
|
2
|
+
// (DESIGN.md §7, ADR 30). Text preview when the bytes decode as UTF-8,
|
|
3
|
+
// hex dump otherwise. Identical on every platform by construction.
|
|
4
|
+
import { MountAbortedError, VIEWER_ROOT_CLASS } from '../types.js';
|
|
5
|
+
import { fallbackViewerCss } from './styles.js';
|
|
6
|
+
export { fallbackViewerCss } from './styles.js';
|
|
7
|
+
export const FALLBACK_VIEWER_META = {
|
|
8
|
+
id: 'fallback',
|
|
9
|
+
displayNameKey: 'fallback.title.text',
|
|
10
|
+
extensions: [],
|
|
11
|
+
priority: -1,
|
|
12
|
+
requiredServices: [],
|
|
13
|
+
optionalServices: [],
|
|
14
|
+
inputOwnership: 'borrows'
|
|
15
|
+
};
|
|
16
|
+
const TEXT_PREVIEW_BYTES = 256 * 1024;
|
|
17
|
+
const HEX_PREVIEW_BYTES = 4 * 1024;
|
|
18
|
+
const HEX_BYTES_PER_LINE = 16;
|
|
19
|
+
export async function mountFallbackViewer(input, container, ctx, options = {}) {
|
|
20
|
+
if (options.signal?.aborted)
|
|
21
|
+
throw new MountAbortedError();
|
|
22
|
+
const isolation = options.styleIsolation ?? 'shadow';
|
|
23
|
+
let root;
|
|
24
|
+
if (isolation === 'shadow' && typeof container.attachShadow === 'function') {
|
|
25
|
+
root = container.shadowRoot ?? container.attachShadow({ mode: 'open' });
|
|
26
|
+
const style = document.createElement('style');
|
|
27
|
+
style.textContent = fallbackViewerCss;
|
|
28
|
+
root.appendChild(style);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
container.classList.add(VIEWER_ROOT_CLASS, 'omni-viewer--fallback');
|
|
32
|
+
root = container;
|
|
33
|
+
}
|
|
34
|
+
const t = ctx.i18n.t.bind(ctx.i18n);
|
|
35
|
+
const frame = document.createElement('div');
|
|
36
|
+
frame.className = 'omni-fallback';
|
|
37
|
+
if (options.reasonKey) {
|
|
38
|
+
const reason = document.createElement('div');
|
|
39
|
+
reason.className = 'omni-fallback__reason';
|
|
40
|
+
reason.textContent = t(options.reasonKey);
|
|
41
|
+
frame.appendChild(reason);
|
|
42
|
+
}
|
|
43
|
+
const text = tryDecodeText(input.data);
|
|
44
|
+
const title = document.createElement('div');
|
|
45
|
+
title.className = 'omni-fallback__title';
|
|
46
|
+
title.textContent =
|
|
47
|
+
text !== null ? t('fallback.title.text') : t('fallback.title.hex');
|
|
48
|
+
frame.appendChild(title);
|
|
49
|
+
const pre = document.createElement('pre');
|
|
50
|
+
pre.className = 'omni-fallback__content';
|
|
51
|
+
let truncatedAt = null;
|
|
52
|
+
if (text !== null) {
|
|
53
|
+
pre.textContent = text.content;
|
|
54
|
+
if (text.truncated)
|
|
55
|
+
truncatedAt = TEXT_PREVIEW_BYTES;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
pre.textContent = hexDump(input.data.subarray(0, HEX_PREVIEW_BYTES));
|
|
59
|
+
if (input.data.byteLength > HEX_PREVIEW_BYTES)
|
|
60
|
+
truncatedAt = HEX_PREVIEW_BYTES;
|
|
61
|
+
}
|
|
62
|
+
frame.appendChild(pre);
|
|
63
|
+
if (truncatedAt !== null) {
|
|
64
|
+
const note = document.createElement('div');
|
|
65
|
+
note.className = 'omni-fallback__note';
|
|
66
|
+
note.textContent = t('fallback.truncated', { bytes: truncatedAt });
|
|
67
|
+
frame.appendChild(note);
|
|
68
|
+
}
|
|
69
|
+
root.appendChild(frame);
|
|
70
|
+
return {
|
|
71
|
+
dispose() {
|
|
72
|
+
if (root instanceof ShadowRoot) {
|
|
73
|
+
root.replaceChildren();
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
root.replaceChildren();
|
|
77
|
+
root.classList.remove(VIEWER_ROOT_CLASS, 'omni-viewer--fallback');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function tryDecodeText(data) {
|
|
83
|
+
const slice = data.subarray(0, TEXT_PREVIEW_BYTES);
|
|
84
|
+
try {
|
|
85
|
+
const content = new TextDecoder('utf-8', { fatal: true }).decode(slice);
|
|
86
|
+
// Control characters (other than tab/newline/CR) mean "not really text".
|
|
87
|
+
// eslint-disable-next-line no-control-regex
|
|
88
|
+
if (/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/.test(content))
|
|
89
|
+
return null;
|
|
90
|
+
return { content, truncated: data.byteLength > TEXT_PREVIEW_BYTES };
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// A multi-byte sequence cut at the slice boundary would throw; retry
|
|
94
|
+
// with a few bytes trimmed before concluding "binary".
|
|
95
|
+
if (data.byteLength > TEXT_PREVIEW_BYTES) {
|
|
96
|
+
try {
|
|
97
|
+
const trimmed = new TextDecoder('utf-8', { fatal: true }).decode(slice.subarray(0, TEXT_PREVIEW_BYTES - 4));
|
|
98
|
+
// eslint-disable-next-line no-control-regex
|
|
99
|
+
if (/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/.test(trimmed))
|
|
100
|
+
return null;
|
|
101
|
+
return { content: trimmed, truncated: true };
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function hexDump(data) {
|
|
111
|
+
const lines = [];
|
|
112
|
+
for (let offset = 0; offset < data.byteLength; offset += HEX_BYTES_PER_LINE) {
|
|
113
|
+
const chunk = data.subarray(offset, offset + HEX_BYTES_PER_LINE);
|
|
114
|
+
const hex = [];
|
|
115
|
+
let ascii = '';
|
|
116
|
+
for (let i = 0; i < HEX_BYTES_PER_LINE; i++) {
|
|
117
|
+
const byte = chunk[i];
|
|
118
|
+
if (byte === undefined) {
|
|
119
|
+
hex.push(' ');
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
hex.push(byte.toString(16).padStart(2, '0'));
|
|
123
|
+
ascii += byte >= 0x20 && byte <= 0x7e ? String.fromCharCode(byte) : '.';
|
|
124
|
+
}
|
|
125
|
+
lines.push(`${offset.toString(16).padStart(8, '0')} ${hex.slice(0, 8).join(' ')} ${hex
|
|
126
|
+
.slice(8)
|
|
127
|
+
.join(' ')} |${ascii}|`);
|
|
128
|
+
}
|
|
129
|
+
return lines.join('\n');
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const fallbackViewerCss = "\n/* Reverse-contamination guard for 'scoped' mode \u2014 see csv/styles.ts. */\n.omni-viewer--fallback {\n all: initial;\n}\n.omni-viewer--fallback :where(pre, code, div) {\n all: revert;\n}\n\n:host, .omni-viewer--fallback {\n display: block;\n height: 100%;\n box-sizing: border-box;\n color: var(--omni-fg, #d4d4d4);\n background: var(--omni-bg, #1e1e1e);\n font-family: var(--omni-font, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);\n font-size: var(--omni-font-size, 13px);\n}\n.omni-fallback {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\n.omni-fallback__reason {\n padding: 6px 8px;\n color: var(--omni-warning-fg, #cca700);\n border-bottom: 1px solid var(--omni-border, #3c3c3c);\n}\n.omni-fallback__title {\n padding: 6px 8px;\n color: var(--omni-fg-muted, #9d9d9d);\n border-bottom: 1px solid var(--omni-border, #3c3c3c);\n}\n.omni-fallback__content {\n flex: 1;\n min-height: 0;\n overflow: auto;\n margin: 0;\n padding: 8px;\n font-family: var(--omni-font-mono, \"SF Mono\", Monaco, Menlo, Consolas, monospace);\n white-space: pre;\n}\n.omni-fallback__note {\n padding: 4px 8px;\n color: var(--omni-fg-muted, #9d9d9d);\n border-top: 1px solid var(--omni-border, #3c3c3c);\n}\n";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const fallbackViewerCss = `
|
|
2
|
+
/* Reverse-contamination guard for 'scoped' mode — see csv/styles.ts. */
|
|
3
|
+
.omni-viewer--fallback {
|
|
4
|
+
all: initial;
|
|
5
|
+
}
|
|
6
|
+
.omni-viewer--fallback :where(pre, code, div) {
|
|
7
|
+
all: revert;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
:host, .omni-viewer--fallback {
|
|
11
|
+
display: block;
|
|
12
|
+
height: 100%;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
color: var(--omni-fg, #d4d4d4);
|
|
15
|
+
background: var(--omni-bg, #1e1e1e);
|
|
16
|
+
font-family: var(--omni-font, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif);
|
|
17
|
+
font-size: var(--omni-font-size, 13px);
|
|
18
|
+
}
|
|
19
|
+
.omni-fallback {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
height: 100%;
|
|
23
|
+
min-height: 0;
|
|
24
|
+
}
|
|
25
|
+
.omni-fallback__reason {
|
|
26
|
+
padding: 6px 8px;
|
|
27
|
+
color: var(--omni-warning-fg, #cca700);
|
|
28
|
+
border-bottom: 1px solid var(--omni-border, #3c3c3c);
|
|
29
|
+
}
|
|
30
|
+
.omni-fallback__title {
|
|
31
|
+
padding: 6px 8px;
|
|
32
|
+
color: var(--omni-fg-muted, #9d9d9d);
|
|
33
|
+
border-bottom: 1px solid var(--omni-border, #3c3c3c);
|
|
34
|
+
}
|
|
35
|
+
.omni-fallback__content {
|
|
36
|
+
flex: 1;
|
|
37
|
+
min-height: 0;
|
|
38
|
+
overflow: auto;
|
|
39
|
+
margin: 0;
|
|
40
|
+
padding: 8px;
|
|
41
|
+
font-family: var(--omni-font-mono, "SF Mono", Monaco, Menlo, Consolas, monospace);
|
|
42
|
+
white-space: pre;
|
|
43
|
+
}
|
|
44
|
+
.omni-fallback__note {
|
|
45
|
+
padding: 4px 8px;
|
|
46
|
+
color: var(--omni-fg-muted, #9d9d9d);
|
|
47
|
+
border-top: 1px solid var(--omni-border, #3c3c3c);
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ClipboardService, HostContext } from '../../host/index.js';
|
|
2
|
+
import { type Hdf5Document } from '../../parsers/hdf5/index.js';
|
|
3
|
+
import { type MountOptions, type ViewerHandle, type ViewerInput } from '../types.js';
|
|
4
|
+
export { hdf5ViewerCss } from './styles.js';
|
|
5
|
+
export declare const HDF5_VIEWER_META: {
|
|
6
|
+
id: string;
|
|
7
|
+
displayNameKey: string;
|
|
8
|
+
extensions: string[];
|
|
9
|
+
priority: number;
|
|
10
|
+
requiredServices: readonly [];
|
|
11
|
+
optionalServices: readonly ["clipboard"];
|
|
12
|
+
inputOwnership: "borrows";
|
|
13
|
+
};
|
|
14
|
+
export type Hdf5ViewerContext = HostContext & {
|
|
15
|
+
clipboard?: ClipboardService;
|
|
16
|
+
};
|
|
17
|
+
export declare function mountHdf5Viewer(input: ViewerInput, container: HTMLElement, ctx: Hdf5ViewerContext, options?: MountOptions): Promise<ViewerHandle>;
|
|
18
|
+
/** Mount a pre-parsed model, allowing Node adapters to retain random-access parsing. */
|
|
19
|
+
export declare function mountHdf5Document(document: Hdf5Document, fileName: string, container: HTMLElement, ctx: Hdf5ViewerContext, options?: MountOptions): ViewerHandle;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { parseHdf5 } from '../../parsers/hdf5/index.js';
|
|
2
|
+
import { MountAbortedError, VIEWER_ROOT_CLASS } from '../types.js';
|
|
3
|
+
import { hdf5ViewerCss } from './styles.js';
|
|
4
|
+
export { hdf5ViewerCss } from './styles.js';
|
|
5
|
+
export const HDF5_VIEWER_META = {
|
|
6
|
+
id: 'hdf5',
|
|
7
|
+
displayNameKey: 'hdf5.title',
|
|
8
|
+
extensions: ['h5', 'hdf5', 'he5'],
|
|
9
|
+
priority: 20,
|
|
10
|
+
requiredServices: [],
|
|
11
|
+
optionalServices: ['clipboard'],
|
|
12
|
+
inputOwnership: 'borrows'
|
|
13
|
+
};
|
|
14
|
+
export async function mountHdf5Viewer(input, container, ctx, options = {}) {
|
|
15
|
+
if (options.signal?.aborted)
|
|
16
|
+
throw new MountAbortedError();
|
|
17
|
+
const document = parseHdf5(input.data);
|
|
18
|
+
if (options.signal?.aborted)
|
|
19
|
+
throw new MountAbortedError();
|
|
20
|
+
return mountHdf5Document(document, input.fileName, container, ctx, options);
|
|
21
|
+
}
|
|
22
|
+
/** Mount a pre-parsed model, allowing Node adapters to retain random-access parsing. */
|
|
23
|
+
export function mountHdf5Document(document, fileName, container, ctx, options = {}) {
|
|
24
|
+
if (options.signal?.aborted)
|
|
25
|
+
throw new MountAbortedError();
|
|
26
|
+
let root = container;
|
|
27
|
+
let injectedStyle;
|
|
28
|
+
if ((options.styleIsolation ?? 'shadow') === 'shadow' && container.attachShadow) {
|
|
29
|
+
root = container.shadowRoot ?? container.attachShadow({ mode: 'open' });
|
|
30
|
+
const style = element('style');
|
|
31
|
+
style.textContent = hdf5ViewerCss;
|
|
32
|
+
root.append(style);
|
|
33
|
+
injectedStyle = style;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
container.classList.add(VIEWER_ROOT_CLASS, 'omni-viewer--hdf5');
|
|
37
|
+
}
|
|
38
|
+
const frame = element('div', 'omni-hdf5');
|
|
39
|
+
const header = element('header', 'omni-hdf5__header');
|
|
40
|
+
const heading = element('div');
|
|
41
|
+
heading.append(element('div', 'omni-hdf5__eyebrow', document.format), element('h1', undefined, fileName), element('div', 'omni-hdf5__subtitle', `${document.title} · ${document.fileSize}`));
|
|
42
|
+
header.append(heading);
|
|
43
|
+
const summary = element('section', 'omni-hdf5__summary');
|
|
44
|
+
for (const item of document.summary) {
|
|
45
|
+
const card = element('div', 'omni-hdf5__summary-item');
|
|
46
|
+
card.append(element('div', 'omni-hdf5__summary-value', String(item.value)), element('div', 'omni-hdf5__summary-label', item.label));
|
|
47
|
+
summary.append(card);
|
|
48
|
+
}
|
|
49
|
+
const toolbar = element('div', 'omni-hdf5__toolbar');
|
|
50
|
+
const search = element('input', 'omni-hdf5__search');
|
|
51
|
+
search.type = 'search';
|
|
52
|
+
search.placeholder = ctx.i18n.t('hdf5.search');
|
|
53
|
+
search.setAttribute('aria-label', ctx.i18n.t('hdf5.search'));
|
|
54
|
+
const tabs = element('div', 'omni-hdf5__tabs');
|
|
55
|
+
const copy = element('button', undefined, ctx.i18n.t('hdf5.copyJson'));
|
|
56
|
+
copy.type = 'button';
|
|
57
|
+
if (!ctx.clipboard) {
|
|
58
|
+
copy.disabled = true;
|
|
59
|
+
copy.title = ctx.i18n.t('common.noClipboard');
|
|
60
|
+
}
|
|
61
|
+
toolbar.append(search, tabs, copy);
|
|
62
|
+
const warnings = element('section', 'omni-hdf5__warnings');
|
|
63
|
+
warnings.setAttribute('role', 'status');
|
|
64
|
+
for (const warning of document.warnings)
|
|
65
|
+
warnings.append(element('div', undefined, warning));
|
|
66
|
+
if (document.warnings.length === 0)
|
|
67
|
+
warnings.hidden = true;
|
|
68
|
+
const content = element('main', 'omni-hdf5__content');
|
|
69
|
+
frame.append(header, summary, toolbar, warnings, content);
|
|
70
|
+
root.append(frame);
|
|
71
|
+
let activeTab = 0;
|
|
72
|
+
let raw = false;
|
|
73
|
+
let copyResetTimer;
|
|
74
|
+
const disposers = [];
|
|
75
|
+
const on = (target, type, listener) => {
|
|
76
|
+
target.addEventListener(type, listener);
|
|
77
|
+
disposers.push(() => target.removeEventListener(type, listener));
|
|
78
|
+
};
|
|
79
|
+
const renderTabs = () => {
|
|
80
|
+
tabs.replaceChildren();
|
|
81
|
+
document.tables.forEach((table, index) => {
|
|
82
|
+
const button = element('button', undefined, table.title);
|
|
83
|
+
button.type = 'button';
|
|
84
|
+
button.setAttribute('aria-pressed', String(!raw && activeTab === index));
|
|
85
|
+
button.onclick = () => { activeTab = index; raw = false; renderTabs(); renderContent(); };
|
|
86
|
+
tabs.append(button);
|
|
87
|
+
});
|
|
88
|
+
if (document.rawPreview) {
|
|
89
|
+
const button = element('button', undefined, ctx.i18n.t('hdf5.structure'));
|
|
90
|
+
button.type = 'button';
|
|
91
|
+
button.setAttribute('aria-pressed', String(raw));
|
|
92
|
+
button.onclick = () => { raw = true; renderTabs(); renderContent(); };
|
|
93
|
+
tabs.append(button);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const matchingRows = (table) => {
|
|
97
|
+
const query = search.value.trim().toLowerCase();
|
|
98
|
+
if (!query)
|
|
99
|
+
return table.rows;
|
|
100
|
+
return table.rows.filter(row => row.some(cell => String(cell).toLowerCase().includes(query)));
|
|
101
|
+
};
|
|
102
|
+
const renderContent = () => {
|
|
103
|
+
content.replaceChildren();
|
|
104
|
+
if (raw) {
|
|
105
|
+
content.append(element('pre', undefined, document.rawPreview ?? ''));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const table = document.tables[activeTab];
|
|
109
|
+
if (!table) {
|
|
110
|
+
content.append(element('div', 'omni-hdf5__empty', ctx.i18n.t('hdf5.noData')));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const rows = matchingRows(table);
|
|
114
|
+
const visible = rows.slice(0, 1000);
|
|
115
|
+
const panelHeader = element('div', 'omni-hdf5__panel-header');
|
|
116
|
+
panelHeader.append(element('h2', undefined, table.title), element('span', undefined, ctx.i18n.t(rows.length > visible.length ? 'hdf5.matchingRowsLimited' : 'hdf5.matchingRows', rows.length > visible.length ? { visible: visible.length, total: rows.length } : { count: rows.length })));
|
|
117
|
+
const wrap = element('div', 'omni-hdf5__table-wrap');
|
|
118
|
+
const tableElement = element('table');
|
|
119
|
+
const head = element('thead');
|
|
120
|
+
const headerRow = element('tr');
|
|
121
|
+
for (const label of table.headers)
|
|
122
|
+
headerRow.append(element('th', undefined, label));
|
|
123
|
+
head.append(headerRow);
|
|
124
|
+
const body = element('tbody');
|
|
125
|
+
for (const row of visible) {
|
|
126
|
+
const tr = element('tr');
|
|
127
|
+
for (const cell of row) {
|
|
128
|
+
const value = String(cell);
|
|
129
|
+
const td = element('td', undefined, value);
|
|
130
|
+
td.title = value;
|
|
131
|
+
tr.append(td);
|
|
132
|
+
}
|
|
133
|
+
body.append(tr);
|
|
134
|
+
}
|
|
135
|
+
tableElement.append(head, body);
|
|
136
|
+
wrap.append(tableElement);
|
|
137
|
+
content.append(panelHeader, wrap);
|
|
138
|
+
};
|
|
139
|
+
on(search, 'input', () => renderContent());
|
|
140
|
+
on(copy, 'click', () => {
|
|
141
|
+
if (!ctx.clipboard)
|
|
142
|
+
return;
|
|
143
|
+
void ctx.clipboard.writeText(JSON.stringify(document, null, 2));
|
|
144
|
+
copy.textContent = ctx.i18n.t('common.copied');
|
|
145
|
+
if (copyResetTimer !== undefined)
|
|
146
|
+
clearTimeout(copyResetTimer);
|
|
147
|
+
copyResetTimer = setTimeout(() => { copy.textContent = ctx.i18n.t('hdf5.copyJson'); }, 1200);
|
|
148
|
+
});
|
|
149
|
+
renderTabs();
|
|
150
|
+
renderContent();
|
|
151
|
+
return {
|
|
152
|
+
dispose() {
|
|
153
|
+
if (copyResetTimer !== undefined)
|
|
154
|
+
clearTimeout(copyResetTimer);
|
|
155
|
+
disposers.splice(0).forEach(dispose => dispose());
|
|
156
|
+
frame.remove();
|
|
157
|
+
injectedStyle?.remove();
|
|
158
|
+
if (!(root instanceof ShadowRoot))
|
|
159
|
+
container.classList.remove(VIEWER_ROOT_CLASS, 'omni-viewer--hdf5');
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function element(tag, className, text) {
|
|
164
|
+
const node = document.createElement(tag);
|
|
165
|
+
if (className)
|
|
166
|
+
node.className = className;
|
|
167
|
+
if (text !== undefined)
|
|
168
|
+
node.textContent = text;
|
|
169
|
+
return node;
|
|
170
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const hdf5ViewerCss = "\n.omni-hdf5{height:100%;min-height:0;display:flex;flex-direction:column;background:var(--omni-bg,#fff);color:var(--omni-fg,#222);font:13px system-ui,sans-serif}.omni-hdf5__header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:18px 20px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-panel-bg,#f7f7f7)}.omni-hdf5__eyebrow{color:var(--omni-muted,#666);font-size:12px;text-transform:uppercase}.omni-hdf5 h1{margin:2px 0 4px;font-size:20px}.omni-hdf5__subtitle{color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;background:var(--omni-border,#ddd);border-bottom:1px solid var(--omni-border,#ddd)}.omni-hdf5__summary-item{min-height:64px;padding:12px 14px;background:var(--omni-bg,#fff)}.omni-hdf5__summary-value{font-size:20px;font-weight:650}.omni-hdf5__summary-label{margin-top:4px;color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__toolbar{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-toolbar-bg,#f5f5f5)}.omni-hdf5__search{width:min(320px,36vw);min-width:180px;border:1px solid var(--omni-border,#ccc);background:var(--omni-input-bg,#fff);color:inherit;padding:7px 9px;border-radius:4px}.omni-hdf5__tabs{display:flex;flex-wrap:wrap;gap:4px;flex:1}.omni-hdf5 button{border:1px solid var(--omni-border,#ccc);border-radius:4px;background:var(--omni-button-bg,#eee);color:inherit;cursor:pointer;padding:7px 10px}.omni-hdf5 button:hover{background:var(--omni-hover,#e5e5e5)}.omni-hdf5 button[aria-pressed=true]{background:var(--omni-accent,#0e639c);color:var(--omni-accent-fg,#fff)}.omni-hdf5 button:disabled{opacity:.5;cursor:default}.omni-hdf5__warnings{padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-warning-bg,#fff4ce);color:var(--omni-warning-fg,#5f4700)}.omni-hdf5__content{min-height:0;flex:1;overflow:auto}.omni-hdf5__panel-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-bg,#fff)}.omni-hdf5__panel-header h2{margin:0;font-size:15px}.omni-hdf5__panel-header span{color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__table-wrap{overflow:auto}.omni-hdf5 table{width:100%;border-collapse:collapse}.omni-hdf5 th,.omni-hdf5 td{border-bottom:1px solid var(--omni-border,#ddd);padding:7px 9px;text-align:left;vertical-align:top;white-space:nowrap}.omni-hdf5 th{background:var(--omni-header-bg,#f5f5f5);font-weight:650}.omni-hdf5 td{max-width:520px;overflow:hidden;text-overflow:ellipsis}.omni-hdf5 tr:hover td{background:var(--omni-hover,#f4f4f4)}.omni-hdf5 pre{margin:0;padding:14px;font:13px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap}.omni-hdf5__empty{padding:24px;color:var(--omni-muted,#666)}\n@media(max-width:720px){.omni-hdf5__header,.omni-hdf5__toolbar{align-items:stretch;flex-direction:column}.omni-hdf5__search{width:auto}}\n";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export const hdf5ViewerCss = `
|
|
2
|
+
.omni-hdf5{height:100%;min-height:0;display:flex;flex-direction:column;background:var(--omni-bg,#fff);color:var(--omni-fg,#222);font:13px system-ui,sans-serif}.omni-hdf5__header{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;padding:18px 20px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-panel-bg,#f7f7f7)}.omni-hdf5__eyebrow{color:var(--omni-muted,#666);font-size:12px;text-transform:uppercase}.omni-hdf5 h1{margin:2px 0 4px;font-size:20px}.omni-hdf5__subtitle{color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:1px;background:var(--omni-border,#ddd);border-bottom:1px solid var(--omni-border,#ddd)}.omni-hdf5__summary-item{min-height:64px;padding:12px 14px;background:var(--omni-bg,#fff)}.omni-hdf5__summary-value{font-size:20px;font-weight:650}.omni-hdf5__summary-label{margin-top:4px;color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__toolbar{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-toolbar-bg,#f5f5f5)}.omni-hdf5__search{width:min(320px,36vw);min-width:180px;border:1px solid var(--omni-border,#ccc);background:var(--omni-input-bg,#fff);color:inherit;padding:7px 9px;border-radius:4px}.omni-hdf5__tabs{display:flex;flex-wrap:wrap;gap:4px;flex:1}.omni-hdf5 button{border:1px solid var(--omni-border,#ccc);border-radius:4px;background:var(--omni-button-bg,#eee);color:inherit;cursor:pointer;padding:7px 10px}.omni-hdf5 button:hover{background:var(--omni-hover,#e5e5e5)}.omni-hdf5 button[aria-pressed=true]{background:var(--omni-accent,#0e639c);color:var(--omni-accent-fg,#fff)}.omni-hdf5 button:disabled{opacity:.5;cursor:default}.omni-hdf5__warnings{padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-warning-bg,#fff4ce);color:var(--omni-warning-fg,#5f4700)}.omni-hdf5__content{min-height:0;flex:1;overflow:auto}.omni-hdf5__panel-header{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--omni-border,#ddd);background:var(--omni-bg,#fff)}.omni-hdf5__panel-header h2{margin:0;font-size:15px}.omni-hdf5__panel-header span{color:var(--omni-muted,#666);font-size:12px}.omni-hdf5__table-wrap{overflow:auto}.omni-hdf5 table{width:100%;border-collapse:collapse}.omni-hdf5 th,.omni-hdf5 td{border-bottom:1px solid var(--omni-border,#ddd);padding:7px 9px;text-align:left;vertical-align:top;white-space:nowrap}.omni-hdf5 th{background:var(--omni-header-bg,#f5f5f5);font-weight:650}.omni-hdf5 td{max-width:520px;overflow:hidden;text-overflow:ellipsis}.omni-hdf5 tr:hover td{background:var(--omni-hover,#f4f4f4)}.omni-hdf5 pre{margin:0;padding:14px;font:13px/1.45 ui-monospace,SFMono-Regular,Consolas,monospace;white-space:pre-wrap}.omni-hdf5__empty{padding:24px;color:var(--omni-muted,#666)}
|
|
3
|
+
@media(max-width:720px){.omni-hdf5__header,.omni-hdf5__toolbar{align-items:stretch;flex-direction:column}.omni-hdf5__search{width:auto}}
|
|
4
|
+
`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface HwpViewState {
|
|
2
|
+
zoom: number;
|
|
3
|
+
}
|
|
4
|
+
export type HwpAction = {
|
|
5
|
+
type: 'zoom-in';
|
|
6
|
+
} | {
|
|
7
|
+
type: 'zoom-out';
|
|
8
|
+
} | {
|
|
9
|
+
type: 'reset-zoom';
|
|
10
|
+
};
|
|
11
|
+
export interface HwpController {
|
|
12
|
+
readonly state: HwpViewState;
|
|
13
|
+
dispatch(action: HwpAction): void;
|
|
14
|
+
subscribe(listener: (state: HwpViewState) => void): () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare const HWP_MIN_ZOOM = 0.25;
|
|
17
|
+
export declare const HWP_MAX_ZOOM = 2.5;
|
|
18
|
+
export declare const HWP_ZOOM_STEP = 0.1;
|
|
19
|
+
export declare function createHwpController(): HwpController;
|