visio-react-viewer 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -4
- package/dist/assets/{edit-worker-DRgXgRud.js → edit-worker-BcXrV_St.js} +203 -31
- package/dist/index.js +949 -139
- package/dist/third-party/Inter-OFL.txt +92 -0
- package/dist/types/packages/bindings/src/common.d.ts +11 -0
- package/dist/types/packages/bindings/src/react.d.ts +8 -3
- package/dist/types/src/office-ui.d.ts +2 -0
- package/dist/types/src/ribbon-action.d.ts +34 -0
- package/dist/types/src/ribbon-home.d.ts +6 -0
- package/dist/types/src/ribbon-parts.d.ts +20 -0
- package/dist/types/src/ribbon-router.d.ts +17 -0
- package/dist/types/src/ribbon-view.d.ts +2 -0
- package/dist/types/src/ribbon.d.ts +6 -0
- package/dist/types/src/status-bar.d.ts +7 -0
- package/dist/types/src/styles/index.d.ts +5 -0
- package/dist/types/src/styles.d.ts +1 -1
- package/dist/types/src/viewer-chrome.d.ts +11 -2
- package/dist/types/src/viewer-commands.d.ts +31 -0
- package/dist/types/src/viewer-draw-tool.d.ts +17 -0
- package/dist/types/src/viewer-input.d.ts +4 -2
- package/dist/types/src/viewer-search.d.ts +2 -1
- package/package.json +4 -3
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Copyright (c) 2016 The Inter Project Authors (https://github.com/rsms/inter)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
-----------------------------------------------------------
|
|
8
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
9
|
+
-----------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
PREAMBLE
|
|
12
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
13
|
+
development of collaborative font projects, to support the font creation
|
|
14
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
15
|
+
open framework in which fonts may be shared and improved in partnership
|
|
16
|
+
with others.
|
|
17
|
+
|
|
18
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
19
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
20
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
21
|
+
redistributed and/or sold with any software provided that any reserved
|
|
22
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
23
|
+
however, cannot be released under any other type of license. The
|
|
24
|
+
requirement for fonts to remain under this license does not apply
|
|
25
|
+
to any document created using the fonts or their derivatives.
|
|
26
|
+
|
|
27
|
+
DEFINITIONS
|
|
28
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
29
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
30
|
+
include source files, build scripts and documentation.
|
|
31
|
+
|
|
32
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
33
|
+
copyright statement(s).
|
|
34
|
+
|
|
35
|
+
"Original Version" refers to the collection of Font Software components as
|
|
36
|
+
distributed by the Copyright Holder(s).
|
|
37
|
+
|
|
38
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
39
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
40
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
41
|
+
new environment.
|
|
42
|
+
|
|
43
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
44
|
+
writer or other person who contributed to the Font Software.
|
|
45
|
+
|
|
46
|
+
PERMISSION AND CONDITIONS
|
|
47
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
48
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
49
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
50
|
+
Software, subject to the following conditions:
|
|
51
|
+
|
|
52
|
+
1) Neither the Font Software nor any of its individual components,
|
|
53
|
+
in Original or Modified Versions, may be sold by itself.
|
|
54
|
+
|
|
55
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
56
|
+
redistributed and/or sold with any software, provided that each copy
|
|
57
|
+
contains the above copyright notice and this license. These can be
|
|
58
|
+
included either as stand-alone text files, human-readable headers or
|
|
59
|
+
in the appropriate machine-readable metadata fields within text or
|
|
60
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
61
|
+
|
|
62
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
63
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
64
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
65
|
+
presented to the users.
|
|
66
|
+
|
|
67
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
68
|
+
Software shall not be used to promote, endorse or advertise any
|
|
69
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
70
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
71
|
+
permission.
|
|
72
|
+
|
|
73
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
74
|
+
must be distributed entirely under this license, and must not be
|
|
75
|
+
distributed under any other license. The requirement for fonts to
|
|
76
|
+
remain under this license does not apply to any document created
|
|
77
|
+
using the Font Software.
|
|
78
|
+
|
|
79
|
+
TERMINATION
|
|
80
|
+
This license becomes null and void if any of the above conditions are
|
|
81
|
+
not met.
|
|
82
|
+
|
|
83
|
+
DISCLAIMER
|
|
84
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
85
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
86
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
87
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
88
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
89
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
90
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
91
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
92
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mountViewer, type MountedViewer } from '../../../src/binding.js';
|
|
2
|
+
import type { ViewerState } from '../../../src/controller.js';
|
|
2
3
|
import { eventKeys, propertyKeys, type ViewerCallbacks, type ViewerOptions, type ViewerProperties } from '../../../src/contract.js';
|
|
3
4
|
/** Framework props permit undefined; omitted values preserve the shared binding's state. */
|
|
4
5
|
export type ViewerProps = {
|
|
@@ -16,6 +17,16 @@ export declare function viewerOptions(props: ViewerProps): ViewerOptions;
|
|
|
16
17
|
export declare function mountFrameworkViewer(container: HTMLElement, initial: ViewerOptions): MountedViewer;
|
|
17
18
|
/** Lazy imperative methods reject both before mount and after unmount. */
|
|
18
19
|
export declare function viewerHandle(current: () => MountedViewer | undefined): ViewerHandle;
|
|
20
|
+
/**
|
|
21
|
+
* Framework-neutral view of the controller's state for native hooks, composables, signals and
|
|
22
|
+
* stores. `current` returns the mounted handle or nothing; before mount and after unmount the
|
|
23
|
+
* snapshot is `null` and subscribing is a no-op that the binding repeats once mounted.
|
|
24
|
+
*/
|
|
25
|
+
export interface ViewerStateSource {
|
|
26
|
+
subscribe(onChange: () => void): () => void;
|
|
27
|
+
getSnapshot(): ViewerState | null;
|
|
28
|
+
}
|
|
29
|
+
export declare function viewerStateSource(current: () => Pick<ViewerHandle, 'controller'> | null | undefined): ViewerStateSource;
|
|
19
30
|
/** Native framework emits and callback-map props share one complete event inventory. */
|
|
20
31
|
export declare function withEventEmitter(props: ViewerProps, emit: (name: keyof ViewerCallbacks, value: unknown) => void): ViewerOptions;
|
|
21
32
|
export { mountViewer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type CSSProperties } from 'react';
|
|
2
|
-
import { type ViewerHandle, type ViewerProps } from './common.js';
|
|
1
|
+
import { type CSSProperties, type RefObject } from 'react';
|
|
2
|
+
import { type ViewerHandle, type ViewerProps, type ViewerState } from './common.js';
|
|
3
3
|
export interface VisioViewerProps extends ViewerProps {
|
|
4
4
|
className?: string | undefined;
|
|
5
5
|
style?: CSSProperties | undefined;
|
|
@@ -7,4 +7,9 @@ export interface VisioViewerProps extends ViewerProps {
|
|
|
7
7
|
}
|
|
8
8
|
/** React owns only the host and lifecycle; the shared element owns all viewer behavior. */
|
|
9
9
|
export declare const VisioViewer: import("react").ForwardRefExoticComponent<VisioViewerProps & import("react").RefAttributes<ViewerHandle>>;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Reactive viewer state (page, zoom, selection, search, edit and undo state) for the `ref`
|
|
12
|
+
* given to `<VisioViewer>`, through React's external-store hook. `null` until mounted.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useVisioViewerState(ref: RefObject<ViewerHandle | null | undefined>): ViewerState | null;
|
|
15
|
+
export type { ViewerState, ViewerHandle, ViewerCallbacks, ViewerOptions, ViewerEvents, ViewerEditState, VsdxExportResult, } from './common.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Every command the Visio ribbon, status bar or a shortcut can raise, as a `ribbon-action` event. */
|
|
2
|
+
export type VisioRibbonAction = {
|
|
3
|
+
type: 'history';
|
|
4
|
+
key: 'undo' | 'redo';
|
|
5
|
+
} | {
|
|
6
|
+
type: 'tool';
|
|
7
|
+
tool: 'pointer' | 'rectangle';
|
|
8
|
+
} | {
|
|
9
|
+
type: 'delete';
|
|
10
|
+
} | {
|
|
11
|
+
type: 'pane';
|
|
12
|
+
pane: 'pages' | 'inspector';
|
|
13
|
+
} | {
|
|
14
|
+
type: 'reveal';
|
|
15
|
+
panel: 'edit' | 'notes' | 'selection' | 'layers';
|
|
16
|
+
focusText?: boolean;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'grid';
|
|
19
|
+
} | {
|
|
20
|
+
type: 'fullscreen';
|
|
21
|
+
} | {
|
|
22
|
+
type: 'zoom';
|
|
23
|
+
mode: 'fit' | 'width' | 'actual';
|
|
24
|
+
} | {
|
|
25
|
+
type: 'search';
|
|
26
|
+
} | {
|
|
27
|
+
type: 'page';
|
|
28
|
+
step: 1 | -1;
|
|
29
|
+
};
|
|
30
|
+
/** Event name shared by every ribbon control; detail is the typed action. */
|
|
31
|
+
export declare const RIBBON_ACTION_EVENT = "ribbon-action";
|
|
32
|
+
export type RibbonActionEvent = CustomEvent<VisioRibbonAction>;
|
|
33
|
+
/** Internal, non-composed event: it stays inside the viewer's shadow tree. */
|
|
34
|
+
export declare function emitRibbonAction(target: EventTarget, action: VisioRibbonAction): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visio's Home tab, limited to commands this build can honestly perform: Undo, Tools and
|
|
3
|
+
* Editing. Clipboard, Font, Paragraph, Shape Styles and Arrange wait for core edit commands.
|
|
4
|
+
* The compact (phone) layout folds every group but Undo into the Tools disclosure.
|
|
5
|
+
*/
|
|
6
|
+
export declare function buildHomePanel(doc: Document, panel: HTMLElement): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type VisioRibbonAction } from './ribbon-action.js';
|
|
2
|
+
/** A shared `office-ui-button` with Visio-specific state hooks. */
|
|
3
|
+
export type RibbonCommand = HTMLElement & {
|
|
4
|
+
disabled: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A large stacked ribbon command. `id` is a stable name for state sync and tests; the typed
|
|
8
|
+
* `action` is what runs. Labels, icons and shortcuts are static application strings.
|
|
9
|
+
*/
|
|
10
|
+
export declare function tool(doc: Document, id: string, label: string, icon: string, action: VisioRibbonAction, options?: {
|
|
11
|
+
keys?: [aria: string, hint: string];
|
|
12
|
+
pressed?: boolean;
|
|
13
|
+
controls?: string;
|
|
14
|
+
}): RibbonCommand;
|
|
15
|
+
/** A labelled ribbon group (the shared `office-ui-ribbon-group`). */
|
|
16
|
+
export declare function group(doc: Document, label: string, children: readonly HTMLElement[], className?: string): HTMLElement;
|
|
17
|
+
/** A keyboard-navigable row of groups (the shared `office-ui-toolbar`). */
|
|
18
|
+
export declare function commandRow(doc: Document, label: string, children: readonly HTMLElement[]): HTMLElement;
|
|
19
|
+
/** Muted two-line guidance at the end of a ribbon panel. */
|
|
20
|
+
export declare function hint(doc: Document, lines: readonly string[]): HTMLElement;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ViewerController } from './controller.js';
|
|
2
|
+
import type { VisioRibbonAction } from './ribbon-action.js';
|
|
3
|
+
/** The controllers a ribbon action can reach. The element supplies each one. */
|
|
4
|
+
export interface RibbonTargets {
|
|
5
|
+
controller: ViewerController;
|
|
6
|
+
history(key: 'undo' | 'redo'): void;
|
|
7
|
+
deleteSelection(): void;
|
|
8
|
+
setTool(tool: 'pointer' | 'rectangle'): void;
|
|
9
|
+
toggleGrid(): void;
|
|
10
|
+
toggleFullscreen(): void;
|
|
11
|
+
togglePane(pane: 'pages' | 'inspector'): void;
|
|
12
|
+
reveal(panel: 'edit' | 'notes' | 'selection' | 'layers', focusText: boolean): void;
|
|
13
|
+
fit(mode: 'page' | 'width'): void;
|
|
14
|
+
focusSearch(): void;
|
|
15
|
+
}
|
|
16
|
+
/** Routes a ribbon, status-bar or shortcut action to the controller that owns it. */
|
|
17
|
+
export declare function routeRibbonAction(targets: RibbonTargets, action: VisioRibbonAction): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { VisioRibbonAction } from './ribbon-action.js';
|
|
2
|
+
/**
|
|
3
|
+
* The Visio ribbon: a tab list and one panel per tab. Tab switching and keyboard movement
|
|
4
|
+
* belong to the chrome; commands emit `ribbon-action` events for the router.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createRibbon(doc: Document): HTMLElement;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visio's status bar on the shared `office-ui-status-bar`: page and shape metrics, a live
|
|
3
|
+
* message region, compatibility notes, the host footer slot and the shared zoom slider.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createStatusBar(doc: Document): HTMLElement;
|
|
6
|
+
/** Visio's page tabs under the drawing, on the shared document tab strip. */
|
|
7
|
+
export declare function createPageTabs(doc: Document): HTMLElement;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Inherited public tokens use local fallback aliases so host themes are never shadowed. */
|
|
2
|
-
export declare const viewerStyles = "\n:host {\n --_vv-bg:var(--vv-background,#eceae8); --_vv-surface:var(--vv-surface,#fff);\n --_vv-secondary:var(--vv-secondary,#f3f2f1); --_vv-ink:var(--vv-ink,#1f1f1f);\n --_vv-muted:var(--vv-muted,#605e5c); --_vv-border:var(--vv-border,#e1dfdd);\n --_vv-accent:var(--vv-accent,#3955a3); --_vv-accent-soft:var(--vv-accent-soft,rgba(57,85,163,.10));\n display:flex; flex-direction:column; min-width:0; min-height:320px; height:100%; overflow:hidden;\n color:var(--_vv-ink); background:var(--_vv-bg); font:12px/1.5 \"Segoe UI\",Arial,sans-serif; contain:layout;\n}\n* { box-sizing:border-box; }\n[hidden] { display:none !important; }\nbutton,select,input,textarea { font:inherit; color:inherit; border:1px solid var(--_vv-border); background:var(--_vv-surface); border-radius:4px; min-height:28px; padding:3px 8px; }\nbutton { cursor:pointer; }\nbutton:hover:enabled { background:var(--_vv-accent-soft); border-color:var(--_vv-accent); }\nbutton:disabled { opacity:.4; cursor:default; }\nbutton:focus-visible,select:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible { outline:2px solid var(--vv-focus,var(--_vv-accent)); outline-offset:2px; }\nbutton[aria-pressed=\"true\"] { color:var(--_vv-accent); background:var(--_vv-accent-soft); }\n.toolbar { flex:none; min-width:0; border-bottom:1px solid var(--_vv-border); background:var(--_vv-surface); }\n.ribbon-primary { height:32px; display:flex; align-items:center; gap:6px; padding:2px 8px; }\n.page-picker { display:flex; min-width:0; align-items:center; gap:8px; color:var(--_vv-muted); font-size:11px; }\n.page-picker select { width:190px; max-width:42vw; height:26px; min-height:26px; padding:2px 6px; font-size:11px; color:var(--_vv-ink); }\n.page-stepper { display:flex; align-items:center; gap:2px; }\n.page-stepper button { width:26px; height:26px; min-height:26px; padding:0; font-size:18px; line-height:22px; background:transparent; border-color:transparent; }\n.spacer { flex:1; }\n.local-label { color:var(--_vv-muted); font-size:10px; white-space:nowrap; }\n.ribbon-tabs { height:35px; display:flex; align-items:stretch; padding:0 4px; border-bottom:1px solid var(--_vv-border); }\n.ribbon-tabs button { position:relative; min-height:34px; padding:7px 14px; border:0; border-radius:0; background:transparent; color:var(--_vv-muted); font-size:12px; font-weight:500; }\n.ribbon-tabs button[aria-selected=\"true\"] { color:var(--_vv-accent); }\n.ribbon-tabs button[aria-selected=\"true\"]::after { content:\"\"; position:absolute; inset:auto 0 -1px; height:2.5px; background:var(--_vv-accent); }\n.ribbon-content { min-height:82px; display:flex; align-items:stretch; gap:0; padding:2px 4px; overflow-x:auto; }\n.ribbon-group { display:flex; flex-direction:column; justify-content:space-between; flex:none; gap:2px; padding:3px 10px 4px; border-right:1px solid var(--_vv-border); }\n.group-label { font-size:10px; line-height:12px; color:var(--_vv-muted); text-align:center; }\n.ribbon-actions { display:flex; align-items:stretch; gap:2px; flex:1; }\n.ribbon-command { display:flex; flex-direction:column; justify-content:center; align-items:center; gap:2px; min-width:70px; padding:2px 6px; border-color:transparent; background:transparent; font-size:11px; white-space:nowrap; }\n.command-icon { display:grid; place-items:center; width:26px; height:26px; color:var(--_vv-accent); }\n.command-icon::before { content:\"\"; width:24px; height:24px; background:currentColor; mask:var(--command-symbol) center / contain no-repeat; }\n[data-icon=\"selection\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22m5%203%2013%209-6%201-3%206z%22%2F%3E%3C%2Fsvg%3E\"); }\n[data-icon=\"edit\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%205h16M12%205v14M8%2019h8%22%2F%3E%3C%2Fsvg%3E\"); }\n[data-icon=\"layers\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22m3%208%209-5%209%205-9%205zM3%2012l9%205%209-5M3%2016l9%205%209-5%22%2F%3E%3C%2Fsvg%3E\"); }\n[data-icon=\"pages\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%225%22%20y%3D%223%22%20width%3D%2214%22%20height%3D%2218%22%20rx%3D%221%22%2F%3E%3Cpath%20d%3D%22M8%208h8M8%2012h8M8%2016h5%22%2F%3E%3C%2Fsvg%3E\"); }\n[data-icon=\"inspector\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%224%22%20width%3D%2218%22%20height%3D%2216%22%20rx%3D%221%22%2F%3E%3Cpath%20d%3D%22M14%204v16M17%208h1M17%2012h1M17%2016h1%22%2F%3E%3C%2Fsvg%3E\"); }\n[data-icon=\"notes\"] { --command-symbol:url(\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.6%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M4%204h16v12H9l-5%204z%22%2F%3E%3Cpath%20d%3D%22M8%208h8M8%2012h5%22%2F%3E%3C%2Fsvg%3E\"); }\n.ribbon-command[data-chrome=\"edit\"] .command-icon { font-family:ui-serif,Georgia,serif; text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:3px; }\n.ribbon-hint { align-self:center; flex:none; margin:0; padding:0 16px; font-size:11px; line-height:18px; color:var(--_vv-muted); }\n.search-group { width:330px; }\n.search-controls { display:flex; align-items:center; gap:4px; flex-wrap:wrap; }\n.search-controls label { display:flex; align-items:center; min-width:0; gap:6px; flex:1; font-size:11px; }\n.search-controls input { width:100%; min-width:0; padding:3px 6px; font-size:11px; }\n.search-controls button { padding:3px 6px; font-size:10px; background:var(--_vv-secondary); }\n.search-controls [role=\"status\"] { display:block; width:100%; min-height:15px; font-size:10px; line-height:15px; color:var(--_vv-muted); overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\n.workspace { position:relative; display:flex; flex:1; min-width:0; min-height:0; overflow:hidden; }\n.page-rail { flex:0 0 180px; width:180px; min-width:0; overflow:auto; border-right:1px solid var(--_vv-border); background:var(--_vv-secondary); }\n.pane-heading { height:37px; display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 10px; border-bottom:1px solid var(--_vv-border); font-size:11px; font-weight:600; }\n.pane-heading [data-page-count],.inspector-kind { color:var(--_vv-muted); font-size:10px; font-weight:400; }\n.page-list { list-style:none; padding:8px 5px; margin:0; display:flex; flex-direction:column; gap:4px; }\n.page-link { display:flex; align-items:center; position:relative; width:100%; min-width:0; gap:4px; padding:4px 5px 4px 2px; border:0; border-radius:0; background:transparent; color:var(--_vv-muted); text-align:left; }\n.page-link[aria-current=\"page\"] { background:var(--_vv-accent-soft); }\n.page-link[aria-current=\"page\"]::before { content:\"\"; position:absolute; left:0; top:4px; bottom:4px; width:3px; border-radius:0 2px 2px 0; background:var(--_vv-accent); }\n.page-number { flex:0 0 20px; width:20px; padding-right:3px; font-size:10px; text-align:right; }\n.page-card { display:flex; flex-direction:column; align-items:flex-start; min-width:0; width:100%; min-height:98px; gap:3px; padding:10px; border:1px solid var(--_vv-border); border-radius:2px; background:var(--_vv-surface); }\n.page-link[aria-current=\"page\"] .page-card { border-color:var(--_vv-accent); }\n.page-link[aria-current=\"page\"] .page-number { color:var(--_vv-accent); font-weight:600; }\n.page-mark { color:var(--_vv-muted); font-size:20px; line-height:23px; }\n.page-name { color:var(--_vv-ink); font-size:11px; font-weight:500; line-height:16px; overflow-wrap:anywhere; }\n.page-meta { color:var(--_vv-muted); font-size:9px; line-height:14px; }\n.page-empty { margin:12px; color:var(--_vv-muted); font-size:11px; }\n.viewport { position:relative; display:flex; flex-direction:column; flex:1; overflow:auto; min-width:0; min-height:0; padding:16px 4px; background:var(--_vv-bg); }\n.paper { display:block; flex:none; background:white; box-shadow:var(--vv-shadow,0 2px 8px rgb(0 0 0 / 14%)); margin:auto; }\n.paper [data-shape-id] { cursor:pointer; }\n.paper [data-selected=\"true\"] > [data-geometry] { stroke:var(--_vv-accent) !important; stroke-width:.025 !important; }\n.inspector-pane { flex:0 0 288px; width:288px; min-width:0; overflow:auto; border-left:1px solid var(--_vv-border); background:var(--_vv-secondary); }\n.inspector-body { display:flex; flex-direction:column; gap:12px; padding:12px 10px; }\n.inspector-card,.edit-controls,.layer-controls { min-width:0; padding:8px; margin:0; border:1px solid var(--_vv-border); border-radius:4px; background:var(--_vv-surface); font-size:11px; line-height:17px; }\n.document-card h2 { margin:0 0 8px; font-size:10px; font-weight:500; letter-spacing:.5px; text-transform:uppercase; color:var(--_vv-muted); }\n.current-page-name { margin:0 0 8px; font-size:12px; font-weight:500; overflow-wrap:anywhere; }\n.document-card dl { display:grid; grid-template-columns:1fr auto; gap:4px 10px; margin:0; font-size:11px; }\n.document-card dt { color:var(--_vv-muted); }\n.document-card dd { margin:0; text-align:right; overflow-wrap:anywhere; }\n.selection-hint { margin:0; padding:0 2px; color:var(--_vv-muted); font-size:11px; }\nsummary { cursor:pointer; min-height:22px; line-height:22px; font-weight:500; }\nsummary::marker { color:var(--_vv-muted); font-size:10px; }\n.shape-inspector div { max-height:260px; overflow:auto; }\n.shape-inspector p { margin:6px 0; overflow-wrap:anywhere; }\n.shape-inspector dl { display:grid; grid-template-columns:minmax(60px,1fr) 1.5fr; gap:6px 10px; }\n.shape-inspector dt { font-weight:500; }\n.shape-inspector dd { margin:0; overflow-wrap:anywhere; white-space:pre-wrap; }\n.shape-inspector h3 { margin:12px 0 5px; font-size:11px; }\n.shape-inspector a { color:var(--_vv-accent); overflow-wrap:anywhere; }\n.edit-controls p,.layer-controls p { margin:6px 0; color:var(--_vv-muted); overflow-wrap:anywhere; }\n.edit-controls textarea { display:block; width:100%; resize:vertical; max-height:180px; margin-top:4px; background:var(--_vv-secondary); }\n.edit-controls label { display:block; margin-top:8px; }\n.edit-actions { display:flex; flex-wrap:wrap; gap:4px; margin-top:8px; }\n.edit-actions button { font-size:11px; padding:3px 7px; }\n.edit-actions [data-edit=\"apply\"]:enabled { background:var(--_vv-accent); border-color:var(--_vv-accent); color:var(--vv-accent-ink,#fff); }\n.edit-controls [data-geometry] { min-width:0; margin:8px 0 0; padding:6px; border:1px solid var(--_vv-border); }\n.edit-controls [data-geometry-field] { display:block; width:100%; min-width:0; margin-top:4px; }\n.edit-controls [data-geometry-error] { color:var(--vv-danger,#b42318); }\n.edit-controls [data-edit-error] { color:var(--vv-danger,#b42318); }\n.edit-controls [data-edit-diagnostics] { max-height:100px; overflow:auto; padding-left:16px; }\n.layer-controls [data-layer-list] { max-height:240px; overflow:auto; }\n.layer-controls fieldset { border:1px solid var(--_vv-border); margin:6px 0; padding:6px; min-width:0; }\n.layer-controls legend { max-width:100%; overflow-wrap:anywhere; }\n.layer-controls fieldset div { display:flex; align-items:center; gap:6px; margin:3px 0; }\n.layer-controls label { display:flex; align-items:center; gap:6px; overflow-wrap:anywhere; }\n.layer-controls input { flex-shrink:0; width:16px; height:16px; min-height:16px; padding:0; accent-color:var(--_vv-accent); }\n.notes ul { max-height:220px; overflow:auto; padding-left:17px; margin:6px 0 0; color:var(--_vv-muted); }\n.notes li { margin:5px 0; overflow-wrap:anywhere; }\n.notes-strip { flex:none; display:flex; align-items:center; justify-content:space-between; min-height:25.5px; padding:0 12px; border-top:1px solid var(--_vv-border); background:var(--_vv-bg); color:var(--_vv-muted); font-size:10px; }\n.notes-strip button { min-height:24.5px; padding:2px 0; border:0; background:transparent; color:var(--_vv-muted); font-size:11px; }\n.notes-strip button::before { content:\"\u25B8\"; margin-right:6px; }\n.notes-strip button[aria-expanded=\"true\"]::before { content:\"\u25BE\"; }\n.status { flex:none; display:flex; align-items:center; justify-content:space-between; gap:12px; min-width:0; min-height:29px; padding:0 8px 0 12px; border-top:1px solid var(--_vv-border); color:var(--_vv-muted); background:var(--_vv-surface); font-size:10px; }\n.status-message { display:flex; gap:16px; min-width:0; }\n.status-message span { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\n.zoom-controls { display:flex; flex:none; align-items:center; gap:3px; }\n.zoom-controls button { min-height:24px; height:24px; padding:1px 6px; border-color:transparent; background:transparent; font-size:10px; }\n.zoom-controls [data-action=\"in\"],.zoom-controls [data-action=\"out\"] { min-width:24px; padding:0; font-size:17px; line-height:20px; }\n.zoom-divider { width:1px; height:14px; background:var(--_vv-border); margin:0 3px; }\n.zoom { min-width:40px; font-size:10px; text-align:center; font-variant-numeric:tabular-nums; }\n.empty { max-width:360px; margin:60px auto; padding:16px; text-align:center; color:var(--_vv-muted); font-size:12px; }\n.empty strong { display:block; color:var(--_vv-ink); font-size:18px; font-weight:500; margin-bottom:8px; }\n@media(max-width:1100px) { .ribbon-hint { display:none; } [data-diagnostics] { display:none; } }\n@media(max-width:760px) {\n button,select,input,textarea { min-height:44px; }\n button { min-width:44px; }\n summary { min-height:44px; line-height:44px; }\n .ribbon-primary { height:52px; padding:4px 8px; }\n .page-picker { flex:1; }\n .page-picker select { width:100%; max-width:none; min-height:44px; height:44px; font-size:12px; }\n .page-stepper button { width:44px; min-height:44px; height:44px; }\n .local-label,.ribbon-primary>.spacer { display:none; }\n .ribbon-tabs { height:44px; }\n .ribbon-tabs button { min-height:44px; padding:8px 16px; }\n .ribbon-content { min-height:86px; }\n .ribbon-group { padding:4px 8px; }\n .search-group { width:100%; border-right:0; }\n .search-controls { gap:4px; }\n .search-controls label { font-size:12px; }\n .search-controls input { font-size:12px; }\n .search-controls button { min-width:44px; font-size:0; padding:3px; }\n .search-controls [data-action=\"search-previous\"]::before { content:\"\u2039\"; font-size:22px; }\n .search-controls [data-action=\"search-next\"]::before { content:\"\u203A\"; font-size:22px; }\n #home-panel>.ribbon-group:not(.search-group) { display:none; }\n .ribbon-command { min-width:90px; }\n .workspace { display:block; overflow:auto; }\n .page-rail { width:100%; max-height:190px; border-right:0; border-bottom:1px solid var(--_vv-border); }\n .page-list { flex-direction:row; overflow-x:auto; }\n .page-list li { flex:0 0 155px; }\n .page-card { min-height:86px; }\n .viewport { height:340px; min-height:260px; padding:16px 4px; }\n .inspector-pane { width:100%; overflow:visible; border-left:0; border-top:1px solid var(--_vv-border); }\n .inspector-body { gap:8px; padding:10px; }\n .inspector-card,.edit-controls,.layer-controls { font-size:12px; }\n .layer-controls label { min-height:44px; }\n .layer-controls input { min-width:20px; width:20px; height:20px; min-height:20px; }\n .notes-strip { min-height:44px; padding:0 10px; }\n .notes-strip button { min-height:44px; }\n .status { flex-wrap:wrap; gap:0; padding:4px 8px; }\n .status-message { width:100%; min-height:18px; }\n .zoom-controls { justify-content:flex-end; width:100%; }\n .zoom-controls button { min-height:44px; height:44px; min-width:44px; font-size:11px; }\n .zoom-controls [data-action=\"in\"],.zoom-controls [data-action=\"out\"] { min-width:44px; font-size:20px; }\n .zoom { font-size:11px; }\n}\n@media(pointer:coarse) {\n button,select,input,textarea { min-height:44px; }\n button { min-width:44px; }\n summary,.layer-controls label { min-height:44px; line-height:44px; }\n .ribbon-primary { min-height:52px; height:52px; }\n .page-picker select,.page-stepper button { min-height:44px; height:44px; }\n .page-stepper button { min-width:44px; }\n .ribbon-tabs { min-height:44px; height:44px; }\n .ribbon-tabs button { min-height:44px; }\n .ribbon-content { min-height:96px; }\n .search-group { width:380px; max-width:100%; }\n .zoom-controls button,.notes-strip button { min-height:44px; height:44px; }\n .zoom-controls [data-action=\"in\"],.zoom-controls [data-action=\"out\"] { min-width:44px; }\n .layer-controls input { min-height:20px; }\n}\n@media(prefers-reduced-motion:reduce) { * { scroll-behavior:auto !important; } }\n";
|
|
2
|
+
export declare const viewerStyles = "\n:host {\n --_vv-bg:var(--vv-background,#eceae8); --_vv-surface:var(--vv-surface,#fff);\n --_vv-secondary:var(--vv-secondary,#f3f2f1); --_vv-ink:var(--vv-ink,#1f1f1f);\n --_vv-muted:var(--vv-muted,#605e5c); --_vv-border:var(--vv-border,#e1dfdd);\n --_vv-accent:var(--vv-accent,#3955a3); --_vv-accent-soft:var(--vv-accent-soft,rgba(57,85,163,.10));\n display:flex; flex-direction:column; min-width:0; min-height:320px; height:100%; overflow:hidden;\n color:var(--_vv-ink); background:var(--_vv-bg); font:12px/1.5 \"Segoe UI\",Arial,sans-serif; contain:layout;\n}\n* { box-sizing:border-box; }\n[hidden] { display:none !important; }\nbutton,select,input,textarea { font:inherit; color:inherit; border:1px solid var(--_vv-border); background:var(--_vv-surface); border-radius:4px; min-height:28px; padding:3px 8px; }\nbutton { cursor:pointer; }\nbutton:hover:enabled { background:var(--_vv-accent-soft); border-color:var(--_vv-accent); }\nbutton:disabled { opacity:.4; cursor:default; }\nbutton:focus-visible,select:focus-visible,input:focus-visible,textarea:focus-visible,summary:focus-visible,[tabindex]:focus-visible { outline:2px solid var(--vv-focus,var(--_vv-accent)); outline-offset:2px; }\nbutton[aria-pressed=\"true\"] { color:var(--_vv-accent); background:var(--_vv-accent-soft); }\n.toolbar { flex:none; min-width:0; border-bottom:1px solid var(--_vv-border); background:var(--_vv-surface); }\n.spacer { flex:1; }\n.ribbon-tabs { height:35px; display:flex; align-items:stretch; padding:0 4px; border-bottom:1px solid var(--_vv-border); }\n.ribbon-tabs button { position:relative; min-height:34px; padding:7px 14px; border:0; border-radius:0; background:transparent; color:var(--_vv-muted); font-size:12px; font-weight:500; }\n.ribbon-tabs button[aria-selected=\"true\"] { color:var(--_vv-accent); }\n.ribbon-tabs button[aria-selected=\"true\"]::after { content:\"\"; position:absolute; inset:auto 0 -1px; height:2.5px; background:var(--_vv-accent); }\n.ribbon-content { min-height:82px; display:flex; align-items:stretch; gap:0; padding:2px 4px; overflow-x:auto; }\n.ribbon-group { display:flex; flex-direction:column; justify-content:space-between; flex:none; gap:2px; padding:3px 10px 4px; border-right:1px solid var(--_vv-border); }\n.group-label { font-size:10px; line-height:12px; color:var(--_vv-muted); text-align:center; }\n.ribbon-actions { display:flex; align-items:stretch; gap:2px; flex:1; }\n.ribbon-command { display:flex; flex-direction:column; justify-content:center; align-items:center; gap:2px; min-width:70px; padding:2px 6px; border-color:transparent; background:transparent; font-size:11px; white-space:nowrap; }\n.ribbon-hint { align-self:center; flex:none; margin:0; padding:0 16px; font-size:11px; line-height:18px; color:var(--_vv-muted); }\n.search-group { width:330px; }\n.search-controls { display:flex; align-items:center; gap:4px; flex-wrap:wrap; }\n.search-controls label { display:flex; align-items:center; min-width:0; gap:6px; flex:1; font-size:11px; }\n.search-controls input { width:100%; min-width:0; padding:3px 6px; font-size:11px; }\n.search-controls button { padding:3px 6px; font-size:10px; background:var(--_vv-secondary); }\n.search-controls [role=\"status\"] { display:block; width:100%; min-height:15px; font-size:10px; line-height:15px; color:var(--_vv-muted); overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\n.workspace { position:relative; display:flex; flex:1; min-width:0; min-height:0; overflow:hidden; }\n.page-rail { flex:0 0 180px; width:180px; min-width:0; overflow:auto; border-right:1px solid var(--_vv-border); background:var(--_vv-secondary); }\n.pane-heading { height:37px; display:flex; align-items:center; justify-content:space-between; gap:8px; padding:8px 10px; border-bottom:1px solid var(--_vv-border); font-size:11px; font-weight:600; }\n.pane-heading [data-page-count],.inspector-kind { color:var(--_vv-muted); font-size:10px; font-weight:400; }\n.page-list { list-style:none; padding:8px 5px; margin:0; display:flex; flex-direction:column; gap:4px; }\n.page-link { display:flex; align-items:center; position:relative; width:100%; min-width:0; gap:4px; padding:4px 5px 4px 2px; border:0; border-radius:0; background:transparent; color:var(--_vv-muted); text-align:left; }\n.page-link[aria-current=\"page\"] { background:var(--_vv-accent-soft); }\n.page-link[aria-current=\"page\"]::before { content:\"\"; position:absolute; left:0; top:4px; bottom:4px; width:3px; border-radius:0 2px 2px 0; background:var(--_vv-accent); }\n.page-number { flex:0 0 20px; width:20px; padding-right:3px; font-size:10px; text-align:right; }\n.page-card { display:flex; flex-direction:column; align-items:flex-start; min-width:0; width:100%; min-height:98px; gap:3px; padding:10px; border:1px solid var(--_vv-border); border-radius:2px; background:var(--_vv-surface); }\n.page-link[aria-current=\"page\"] .page-card { border-color:var(--_vv-accent); }\n.page-link[aria-current=\"page\"] .page-number { color:var(--_vv-accent); font-weight:600; }\n.page-mark { color:var(--_vv-muted); font-size:20px; line-height:23px; }\n.page-name { color:var(--_vv-ink); font-size:11px; font-weight:500; line-height:16px; overflow-wrap:anywhere; }\n.page-meta { color:var(--_vv-muted); font-size:9px; line-height:14px; }\n.page-empty { margin:12px; color:var(--_vv-muted); font-size:11px; }\n.viewport { position:relative; display:flex; flex-direction:column; flex:1; overflow:auto; min-width:0; min-height:0; padding:16px 4px; background:var(--_vv-bg); }\n.paper { display:block; flex:none; background:white; box-shadow:var(--vv-shadow,0 2px 8px rgb(0 0 0 / 14%)); margin:auto; }\n.paper [data-shape-id] { cursor:pointer; }\n.paper [data-selected=\"true\"] > [data-geometry] { stroke:var(--_vv-accent) !important; stroke-width:.025 !important; }\n.inspector-pane { flex:0 0 288px; width:288px; min-width:0; overflow:auto; border-left:1px solid var(--_vv-border); background:var(--_vv-secondary); }\n.inspector-body { display:flex; flex-direction:column; gap:12px; padding:12px 10px; }\n.inspector-card,.edit-controls,.layer-controls { min-width:0; padding:8px; margin:0; border:1px solid var(--_vv-border); border-radius:4px; background:var(--_vv-surface); font-size:11px; line-height:17px; }\n.document-card h2 { margin:0 0 8px; font-size:10px; font-weight:500; letter-spacing:.5px; text-transform:uppercase; color:var(--_vv-muted); }\n.current-page-name { margin:0 0 8px; font-size:12px; font-weight:500; overflow-wrap:anywhere; }\n.document-card dl { display:grid; grid-template-columns:1fr auto; gap:4px 10px; margin:0; font-size:11px; }\n.document-card dt { color:var(--_vv-muted); }\n.document-card dd { margin:0; text-align:right; overflow-wrap:anywhere; }\n.selection-hint { margin:0; padding:0 2px; color:var(--_vv-muted); font-size:11px; }\nsummary { cursor:pointer; min-height:22px; line-height:22px; font-weight:500; }\nsummary::marker { color:var(--_vv-muted); font-size:10px; }\n.shape-inspector div { max-height:260px; overflow:auto; }\n.shape-inspector p { margin:6px 0; overflow-wrap:anywhere; }\n.shape-inspector dl { display:grid; grid-template-columns:minmax(60px,1fr) 1.5fr; gap:6px 10px; }\n.shape-inspector dt { font-weight:500; }\n.shape-inspector dd { margin:0; overflow-wrap:anywhere; white-space:pre-wrap; }\n.shape-inspector h3 { margin:12px 0 5px; font-size:11px; }\n.shape-inspector a { color:var(--_vv-accent); overflow-wrap:anywhere; }\n.edit-controls p,.layer-controls p { margin:6px 0; color:var(--_vv-muted); overflow-wrap:anywhere; }\n.edit-controls textarea { display:block; width:100%; resize:vertical; max-height:180px; margin-top:4px; background:var(--_vv-secondary); }\n.edit-controls label { display:block; margin-top:8px; }\n.edit-actions { display:flex; flex-wrap:wrap; gap:4px; margin-top:8px; }\n.edit-actions button { font-size:11px; padding:3px 7px; }\n.edit-actions [data-edit=\"apply\"]:enabled { background:var(--_vv-accent); border-color:var(--_vv-accent); color:var(--vv-accent-ink,#fff); }\n.edit-controls [data-geometry] { min-width:0; margin:8px 0 0; padding:6px; border:1px solid var(--_vv-border); }\n.edit-controls [data-geometry-field] { display:block; width:100%; min-width:0; margin-top:4px; }\n.edit-controls [data-geometry-error] { color:var(--vv-danger,#b42318); }\n.edit-controls [data-edit-error] { color:var(--vv-danger,#b42318); }\n.edit-controls [data-edit-diagnostics] { max-height:100px; overflow:auto; padding-left:16px; }\n.layer-controls [data-layer-list] { max-height:240px; overflow:auto; }\n.layer-controls fieldset { border:1px solid var(--_vv-border); margin:6px 0; padding:6px; min-width:0; }\n.layer-controls legend { max-width:100%; overflow-wrap:anywhere; }\n.layer-controls fieldset div { display:flex; align-items:center; gap:6px; margin:3px 0; }\n.layer-controls label { display:flex; align-items:center; gap:6px; overflow-wrap:anywhere; }\n.layer-controls input { flex-shrink:0; width:16px; height:16px; min-height:16px; padding:0; accent-color:var(--_vv-accent); }\n.notes ul { max-height:220px; overflow:auto; padding-left:17px; margin:6px 0 0; color:var(--_vv-muted); }\n.notes li { margin:5px 0; overflow-wrap:anywhere; }\n.notes-strip { flex:none; display:flex; align-items:center; justify-content:space-between; min-height:25.5px; padding:0 12px; border-top:1px solid var(--_vv-border); background:var(--_vv-bg); color:var(--_vv-muted); font-size:10px; }\n.notes-strip button { min-height:24.5px; padding:2px 0; border:0; background:transparent; color:var(--_vv-muted); font-size:11px; }\n.notes-strip button::before { content:\"\u25B8\"; margin-right:6px; }\n.notes-strip button[aria-expanded=\"true\"]::before { content:\"\u25BE\"; }\n.status { flex:none; display:flex; align-items:center; justify-content:space-between; gap:12px; min-width:0; min-height:29px; padding:0 8px 0 12px; border-top:1px solid var(--_vv-border); color:var(--_vv-muted); background:var(--_vv-surface); font-size:10px; }\n.status-message { display:flex; gap:16px; min-width:0; }\n.status-message span { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }\n.empty { max-width:360px; margin:60px auto; padding:16px; text-align:center; color:var(--_vv-muted); font-size:12px; }\n.empty strong { display:block; color:var(--_vv-ink); font-size:18px; font-weight:500; margin-bottom:8px; }\n@media(max-width:1100px) { .ribbon-hint { display:none; } [data-diagnostics] { display:none; } }\n@media(max-width:760px) {\n button,select,input,textarea { min-height:44px; }\n button { min-width:44px; }\n summary { min-height:44px; line-height:44px; }\n .ribbon-tabs { height:44px; }\n .ribbon-tabs button { min-height:44px; padding:8px 16px; }\n .ribbon-content { min-height:86px; }\n .ribbon-group { padding:4px 8px; }\n .search-group { width:100%; border-right:0; }\n .search-controls { gap:4px; }\n .search-controls label { font-size:12px; }\n .search-controls input { font-size:12px; }\n .search-controls button { min-width:44px; font-size:0; padding:3px; }\n .search-controls [data-action=\"search-previous\"]::before { content:\"\u2039\"; font-size:22px; }\n .search-controls [data-action=\"search-next\"]::before { content:\"\u203A\"; font-size:22px; }\n #home-panel>.ribbon-group:not(.search-group):not(.undo-group) { display:none; }\n .ribbon-command { min-width:90px; }\n .workspace { display:block; overflow:auto; }\n .page-rail { width:100%; max-height:190px; border-right:0; border-bottom:1px solid var(--_vv-border); }\n .page-list { flex-direction:row; overflow-x:auto; }\n .page-list li { flex:0 0 155px; }\n .page-card { min-height:86px; }\n .viewport { height:340px; min-height:260px; padding:16px 4px; }\n .inspector-pane { width:100%; overflow:visible; border-left:0; border-top:1px solid var(--_vv-border); }\n .inspector-body { gap:8px; padding:10px; }\n .inspector-card,.edit-controls,.layer-controls { font-size:12px; }\n .layer-controls label { min-height:44px; }\n .layer-controls input { min-width:20px; width:20px; height:20px; min-height:20px; }\n .notes-strip { min-height:44px; padding:0 10px; }\n .notes-strip button { min-height:44px; }\n .status { flex-wrap:wrap; gap:0; padding:4px 8px; }\n .status-message { width:100%; min-height:18px; }\n}\n@media(pointer:coarse) {\n button,select,input,textarea { min-height:44px; }\n button { min-width:44px; }\n summary,.layer-controls label { min-height:44px; line-height:44px; }\n .ribbon-tabs { min-height:44px; height:44px; }\n .ribbon-tabs button { min-height:44px; }\n .ribbon-content { min-height:96px; }\n .search-group { width:380px; max-width:100%; }\n .notes-strip button { min-height:44px; height:44px; }\n .layer-controls input { min-height:20px; }\n}\n/* Suite ribbon: tabs lead directly into Visio command groups. */\n.ribbon-tabs { height:40px; }\n.ribbon-tabs button { min-height:39px; padding:8px 16px; }\n.ribbon-content { min-height:104px; padding:4px 4px; }\n.search-group { order:2; width:320px; }\n.ribbon-hint { order:3; padding:10px 18px; }\n.ribbon-command { min-width:82px; }\n.pane-close { display:none; }\n@media(max-width:760px) {\n .ribbon-tabs { height:44px; }\n .ribbon-tabs button { min-height:44px; }\n .ribbon-content { min-height:54px; padding:4px 0; }\n .search-group { flex:0 0 100%; width:100%; min-height:54px; }\n .search-feedback,.group-label { display:none; }\n .ribbon-content { overflow-x:auto; scroll-snap-type:x mandatory; }\n .workspace { display:flex; position:relative; overflow:hidden; }\n .viewport { flex:1; width:100%; height:100%; min-height:0; padding:16px 4px; }\n .inspector-pane { position:absolute; inset:0 0 0 auto; width:min(320px,100%); z-index:4; overflow:auto; border-left:1px solid var(--_vv-border); box-shadow:-8px 0 24px #0002; }\n .pane-close { display:block; width:44px; height:44px; padding:0; font-size:22px; background:transparent; border:0; }\n .inspector-kind { margin-left:auto; }\n .page-rail { position:absolute; inset:0 auto 0 0; width:180px; max-height:none; z-index:3; border-right:1px solid var(--_vv-border); background:var(--_vv-secondary); }\n .page-list { flex-direction:column; }\n .page-list li { flex:none; }\n .notes-strip { display:none; }\n .status { min-height:48px; padding:2px 8px; }\n .status-message { display:none; }\n}\n.toolbar { position:relative; }\n.ribbon-tools { display:flex; flex:none; order:0; }\n.tools-content { display:flex; align-items:stretch; }\n.ribbon-tools>summary { display:none; }\n.ribbon-command { font-size:12px; min-width:88px; }\n.ribbon-hint { font-size:12px; line-height:20px; flex:1; }\n.group-label { font-size:11px; line-height:14px; }\n.inspector-card,.edit-controls,.layer-controls { font-size:12px; line-height:18px; }\n.selection-hint,.document-card dl { font-size:12px; }\n.pane-heading { font-size:12px; }\n.inspector-pane .pane-heading { position:sticky; top:0; z-index:1; background:var(--_vv-secondary); flex:none; }\n.status .notes-strip { border:0; padding:0 8px; background:transparent; min-height:28px; }\n.status .notes-strip>span { display:none; }\n.status-message { flex:1; }\n@media(max-width:760px) {\n #home-panel { overflow:visible; min-height:54px; padding:4px; }\n .ribbon-tools { display:block; flex:0 0 84px; width:84px; order:1; }\n .ribbon-tools>summary { display:flex; min-height:44px; align-items:center; justify-content:center; gap:6px; padding:0 10px; border:1px solid var(--_vv-border); background:var(--_vv-surface); border-radius:4px; font-size:12px; cursor:pointer; list-style:none; }\n .ribbon-tools>summary::-webkit-details-marker { display:none; }\n .ribbon-tools .tools-content { display:flex; position:absolute; top:100%; left:4px; right:4px; z-index:6; flex-direction:column; padding:12px; gap:12px; border:1px solid var(--_vv-border); border-radius:4px; background:var(--_vv-surface); box-shadow:0 12px 28px #0003; max-height:60vh; overflow:auto; }\n .ribbon-tools:not([open])>.tools-content { display:none; }\n .ribbon-tools .ribbon-group { display:flex; width:100%; min-height:64px; border:0; padding:0; }\n .ribbon-tools .ribbon-actions { justify-content:space-between; }\n .ribbon-tools .ribbon-command { min-width:88px; font-size:12px; }\n .ribbon-tools .search-group { order:1; flex:auto; }\n .ribbon-tools .search-feedback { display:block; }\n .status { flex-wrap:nowrap; gap:4px; min-height:48px; }\n .status .notes-strip { display:none; }\n}\n@media(pointer:coarse) { .ribbon-tabs {height:45px;min-height:45px;} .ribbon-tabs button {min-height:44px;height:44px;} }\n@media(prefers-reduced-motion:reduce) { * { scroll-behavior:auto !important; } }\n";
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import type { ViewerController, ViewerState } from './controller.js';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Static workspace markup (legacy; migrate to builders when next changed). The ribbon, page
|
|
4
|
+
* tabs and status bar are built by `createRibbon`, `createPageTabs` and `createStatusBar`.
|
|
5
|
+
* All document labels are inserted as text.
|
|
6
|
+
*/
|
|
7
|
+
export declare const viewerChromeTemplate = "<div class=\"workspace\">\n <nav id=\"page-rail\" class=\"page-rail\" aria-label=\"Diagram pages\"><div class=\"pane-heading\"><span>Pages</span><span data-page-count>0</span></div><ol class=\"page-list\"></ol><p class=\"page-empty\">Open a drawing to see its pages.</p></nav>\n <div class=\"viewport\" tabindex=\"0\" role=\"region\" aria-label=\"Diagram canvas\"></div>\n <aside id=\"inspector-pane\" class=\"inspector-pane\" aria-label=\"Drawing inspector\">\n <div class=\"pane-heading\"><span>Inspector</span><span class=\"inspector-kind\">Drawing</span><button class=\"pane-close\" type=\"button\" data-chrome=\"inspector\" aria-label=\"Close inspector\">\u00D7</button></div>\n <div class=\"inspector-body\">\n <section class=\"inspector-card document-card\" aria-label=\"Current page\"><h2>Current page</h2><p class=\"current-page-name\" data-page-name>No diagram open</p><dl><dt>Size</dt><dd data-page-size>No page</dd><dt>Shapes</dt><dd data-page-shapes>No shapes</dd></dl></section>\n <p class=\"selection-hint\">Select a shape on the canvas to see its data and links.</p>\n <details class=\"shape-inspector inspector-card\" hidden><summary>Selected shape</summary><div></div></details>\n <details class=\"edit-controls\"><summary>Edit diagram (experimental)</summary><p id=\"edit-warning\">Experimental source-backed editing. Unsupported targets are rejected. Native Visio compatibility is not verified. Keep your original file.</p><p data-edit-target></p><label for=\"edit-text\">Selected shape text</label><textarea id=\"edit-text\" rows=\"3\" aria-describedby=\"edit-warning edit-target edit-status\"></textarea><div class=\"edit-actions\"><button type=\"button\" data-edit=\"apply\">Apply text</button><button type=\"button\" data-edit=\"cancel\">Cancel</button><button type=\"button\" data-edit=\"undo\">Undo</button><button type=\"button\" data-edit=\"redo\">Redo</button></div><p id=\"edit-status\" role=\"status\" aria-live=\"polite\"></p><p data-edit-error role=\"alert\" hidden></p><ul data-edit-diagnostics></ul><fieldset data-geometry><legend>Geometry (experimental)</legend><p>Pin X/Y use drawing inches, bottom-left origin, Y up. Resize holds the rotation pin fixed. Core rejects unsupported formulas, protected cells, unsafe group/master dependencies and referenced deletion. Native Visio reopen fidelity is unverified.</p><label>New rectangle ID <input data-geometry-field=\"id\" type=\"text\" maxlength=\"256\"></label><label>Rectangle text (optional) <input data-geometry-field=\"text\" type=\"text\" maxlength=\"1000000\"></label><label>Pin X (inches) <input data-geometry-field=\"x\" type=\"number\" step=\"any\"></label><label>Pin Y (inches) <input data-geometry-field=\"y\" type=\"number\" step=\"any\"></label><label>Width (inches) <input data-geometry-field=\"width\" type=\"number\" min=\"0\" step=\"any\"></label><label>Height (inches) <input data-geometry-field=\"height\" type=\"number\" min=\"0\" step=\"any\"></label><div class=\"edit-actions\"><button type=\"button\" data-geometry-action=\"create-rectangle\">Create rectangle</button><button type=\"button\" data-geometry-action=\"move-shape\">Move selected</button><button type=\"button\" data-geometry-action=\"resize-shape\">Resize selected</button><button type=\"button\" data-geometry-action=\"delete-shape\">Delete selected</button></div><p data-geometry-error role=\"alert\" hidden></p></fieldset></details><details class=\"layer-controls\" hidden><summary>Layers</summary><p>Display changes only. SVG and print snapshots use saved visibility. Guides, NoShow and unknown hidden reasons remain hidden.</p><div data-layer-list></div><p data-layer-status role=\"status\"></p><button type=\"button\" data-layer-reset=\"all\">Reset all layers</button></details>\n <details class=\"notes inspector-card\"><summary>Compatibility notes</summary><ul></ul></details>\n </div>\n </aside>\n</div>";
|
|
4
8
|
/** Presentation state stays local; page navigation uses the same controller as every binding. */
|
|
5
9
|
export declare class ViewerChrome {
|
|
6
10
|
#private;
|
|
7
11
|
constructor(root: ShadowRoot, controller: ViewerController);
|
|
8
12
|
wire(): () => void;
|
|
13
|
+
showTab(tab: 'home' | 'view'): void;
|
|
14
|
+
/** Show or hide a task pane; compact layouts close the Tools menu afterwards. */
|
|
15
|
+
togglePane(pane: 'pages' | 'inspector'): void;
|
|
16
|
+
/** Open an inspector disclosure; text editing may focus the text field directly (F2). */
|
|
17
|
+
reveal(kind: 'notes' | 'selection' | 'edit' | 'layers', focusText?: boolean): void;
|
|
9
18
|
render(state: ViewerState, noteCount: number): void;
|
|
10
19
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ViewerController, ViewerState } from './controller.js';
|
|
2
|
+
import { type VisioRibbonAction } from './ribbon-action.js';
|
|
3
|
+
export type CanvasTool = 'pointer' | 'rectangle';
|
|
4
|
+
interface CommandHost {
|
|
5
|
+
root: ShadowRoot;
|
|
6
|
+
viewport: HTMLElement;
|
|
7
|
+
controller: ViewerController;
|
|
8
|
+
fit(mode: 'page' | 'width'): void;
|
|
9
|
+
togglePane(pane: 'pages' | 'inspector'): void;
|
|
10
|
+
reveal(panel: 'edit' | 'notes' | 'selection' | 'layers', focusText: boolean): void;
|
|
11
|
+
focusSearch(): void;
|
|
12
|
+
/** Transient command feedback for the status bar; document text is never interpreted as markup. */
|
|
13
|
+
announce(message: string): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Visio command state (tool, grid, pending edits) and keyboard shortcuts. Ribbon controls emit
|
|
17
|
+
* typed `ribbon-action` events and shortcuts build the same actions; both go through
|
|
18
|
+
* `routeRibbonAction`. Document mutation stays in the controller and core.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ViewerCommands {
|
|
21
|
+
#private;
|
|
22
|
+
private readonly host;
|
|
23
|
+
constructor(host: CommandHost);
|
|
24
|
+
get tool(): CanvasTool;
|
|
25
|
+
/** Run one typed action, exactly as a ribbon control or shortcut would. */
|
|
26
|
+
run(action: VisioRibbonAction): void;
|
|
27
|
+
wire(): () => void;
|
|
28
|
+
setTool(tool: CanvasTool): void;
|
|
29
|
+
render(state: ViewerState): void;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { VisioPage } from 'ooxml-core/visio';
|
|
2
|
+
import type { ViewerController } from './controller.js';
|
|
3
|
+
/** Next free numeric shape ID on the page tree. Core still rejects any collision. */
|
|
4
|
+
export declare function nextShapeId(page: VisioPage): string;
|
|
5
|
+
/** Drag-to-draw rectangle tool. The preview is viewer-only; the shape is created by core. */
|
|
6
|
+
export declare class RectangleDrawTool {
|
|
7
|
+
#private;
|
|
8
|
+
private readonly viewport;
|
|
9
|
+
private readonly controller;
|
|
10
|
+
private readonly options;
|
|
11
|
+
constructor(viewport: HTMLElement, controller: ViewerController, options: {
|
|
12
|
+
active(): boolean;
|
|
13
|
+
announce(message: string): void;
|
|
14
|
+
});
|
|
15
|
+
get drawing(): boolean;
|
|
16
|
+
wire(): () => void;
|
|
17
|
+
}
|
|
@@ -2,9 +2,11 @@ import type { ViewerController } from './controller.js';
|
|
|
2
2
|
interface Controls {
|
|
3
3
|
viewport: HTMLDivElement;
|
|
4
4
|
commandRoot: ShadowRoot;
|
|
5
|
-
|
|
5
|
+
zoomSlider: HTMLElement & {
|
|
6
|
+
value: number;
|
|
7
|
+
};
|
|
6
8
|
searchInput: HTMLInputElement;
|
|
7
9
|
}
|
|
8
10
|
/** Own every DOM listener and abort them together when the surface is disposed. */
|
|
9
|
-
export declare function wireViewerInputs(controls: Controls, controller: ViewerController, fit: () => void): () => void;
|
|
11
|
+
export declare function wireViewerInputs(controls: Controls, controller: ViewerController, fit: (mode: 'page' | 'width') => void): () => void;
|
|
10
12
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ViewerState } from './controller.js';
|
|
2
|
-
|
|
2
|
+
/** Builds the Find group: a search field, previous/next result buttons and a live status. */
|
|
3
|
+
export declare function createSearchGroup(doc: Document): HTMLElement;
|
|
3
4
|
export interface SearchControls {
|
|
4
5
|
input: HTMLInputElement;
|
|
5
6
|
status: HTMLSpanElement;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "visio-react-viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Local-first Visio viewer for react",
|
|
5
5
|
"homepage": "https://christophervr.github.io/visio-viewer/",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"emf-converter": "4.8.9",
|
|
31
|
-
"ooxml-core": "^0.
|
|
32
|
-
"
|
|
31
|
+
"ooxml-core": "^0.12.0",
|
|
32
|
+
"ooxml-ui": "^0.2.0",
|
|
33
|
+
"visio-core": "^0.2.0"
|
|
33
34
|
},
|
|
34
35
|
"peerDependencies": {
|
|
35
36
|
"react": ">=18"
|