visio-react-viewer 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{edit-worker-DRgXgRud.js → edit-worker-BcXrV_St.js} +203 -31
- package/dist/index.js +865 -160
- 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
|
@@ -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/* Suite ribbon: tabs lead directly into command groups, with page navigation inside. */\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.ribbon-primary { height:auto; min-height:92px; width:238px; flex:none; flex-wrap:wrap; justify-content:center; gap:2px; padding:10px 12px 18px; border-right:1px solid var(--_vv-border); position:relative; order:1; }\n.ribbon-primary .page-picker { flex-direction:column; align-items:start; gap:5px; }\n.ribbon-primary .page-picker select { width:160px; max-width:100%; }\n.ribbon-primary .spacer { display:none; }\n.ribbon-primary .local-label { position:absolute; bottom:4px; left:0; width:100%; text-align:center; }\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 .ribbon-primary { min-height:44px; height:44px; width:100%; padding:0 8px; border:0; flex-wrap:nowrap; gap:4px; order:0; }\n .ribbon-primary .page-picker { flex-direction:row; flex:1; align-items:center; gap:8px; }\n .ribbon-primary .page-picker select { flex:1; width:100%; min-width: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 .ribbon-primary,.search-group { scroll-snap-align:start; }\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-primary { width:calc(100% - 92px); min-width:0; flex:1; padding:0 4px; }\n .ribbon-primary .page-picker { font-size:0; gap:0; }\n .ribbon-primary .page-picker select { font-size:12px; }\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 .zoom-controls { width:auto; flex:1; gap:0; }\n .zoom-divider { margin:0; }\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";
|
|
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"
|