@inkbar/vue 0.6.0 → 0.7.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 +5 -1
- package/dist/components/InkFindBar.js +7 -0
- package/dist/components/InkFindBar.js.map +1 -0
- package/dist/components/InkFindBar.vue.d.ts +4 -0
- package/dist/components/InkFindBar.vue.d.ts.map +1 -0
- package/dist/components/InkFindBar.vue_vue_type_script_setup_true_lang.js +133 -0
- package/dist/components/InkFindBar.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/InkRoot.js.map +1 -1
- package/dist/components/InkRoot.vue.d.ts.map +1 -1
- package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +120 -109
- package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/InkSearchButton.js +7 -0
- package/dist/components/InkSearchButton.js.map +1 -0
- package/dist/components/InkSearchButton.vue.d.ts +19 -0
- package/dist/components/InkSearchButton.vue.d.ts.map +1 -0
- package/dist/components/InkSearchButton.vue_vue_type_script_setup_true_lang.js +43 -0
- package/dist/components/InkSearchButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/InkViewport.js.map +1 -1
- package/dist/components/InkViewport.vue.d.ts.map +1 -1
- package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/SignatureForm.vue.d.ts +2 -2
- package/dist/composables/useSearch.d.ts +12 -0
- package/dist/composables/useSearch.d.ts.map +1 -0
- package/dist/composables/useSearch.js +27 -0
- package/dist/composables/useSearch.js.map +1 -0
- package/dist/context.d.ts +7 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -27
- package/package.json +6 -5
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { provideInkContext as e } from "../context.js";
|
|
2
2
|
import { useReadable as t } from "../use-readable.js";
|
|
3
3
|
import { createRefHistory as n } from "../ref-history.js";
|
|
4
|
-
import { computed as r, createBlock as
|
|
5
|
-
import { InkError as p, createMemorySignatureStore as
|
|
6
|
-
import { FONT_FAMILIES as
|
|
4
|
+
import { computed as r, createBlock as i, defineComponent as a, mergeProps as ee, onBeforeUnmount as te, onMounted as ne, onUnmounted as re, onUpdated as ie, openBlock as ae, ref as o, renderSlot as s, shallowRef as c, unref as l, useTemplateRef as u, watch as d, withCtx as f } from "vue";
|
|
5
|
+
import { InkError as p, createMemorySignatureStore as oe, createSignatureLibrary as se, openDocument as ce, readonly as m, writable as h } from "@inkbar/core";
|
|
6
|
+
import { FONT_FAMILIES as le, SIGNATURE_FONTS as ue, createPluginHost as de, createSearchController as g, createToolOptions as fe, cssVariableDefaults as pe, handleFindKey as me, pageSelectionText as _, trackToolStyle as v, viewerSearchOf as y } from "@inkbar/core/dom";
|
|
7
7
|
import { Primitive as b } from "reka-ui";
|
|
8
8
|
//#region src/components/InkRoot.vue?vue&type=script&setup=true&lang.ts
|
|
9
|
-
var x = /*@__PURE__*/
|
|
9
|
+
var x = /*@__PURE__*/ a({
|
|
10
10
|
__name: "InkRoot",
|
|
11
11
|
props: {
|
|
12
12
|
src: {},
|
|
@@ -45,111 +45,121 @@ var x = /*@__PURE__*/ i({
|
|
|
45
45
|
"error",
|
|
46
46
|
"activate"
|
|
47
47
|
],
|
|
48
|
-
setup(
|
|
49
|
-
let
|
|
50
|
-
function
|
|
51
|
-
let e =
|
|
52
|
-
|
|
48
|
+
setup(a, { expose: x, emit: he }) {
|
|
49
|
+
let S = a, C = he, w = u("primitive"), T = c(null);
|
|
50
|
+
function E() {
|
|
51
|
+
let e = w.value?.$el;
|
|
52
|
+
T.value = e instanceof HTMLElement ? e : null;
|
|
53
53
|
}
|
|
54
|
-
let
|
|
54
|
+
let D = c(null), O = c(null), k = t(() => D.value?.status ?? null, { state: "idle" }), A = r(() => O.value ?? k.value), j = t(() => D.value?.annotations.list ?? null, []), M = t(() => D.value?.annotations.selection ?? null, []), N = c(null), P = c(null), F = o(S.tool ?? "select-text"), I = o(null), L = r(() => S.annotations !== void 0);
|
|
55
55
|
function R(e) {
|
|
56
|
-
I.value = e, e &&
|
|
56
|
+
I.value = e, e && C("activate", e);
|
|
57
57
|
}
|
|
58
58
|
let z = () => {};
|
|
59
|
-
function
|
|
59
|
+
function ge(e) {
|
|
60
60
|
return e === null ? null : typeof e == "string" ? e : "key" in e ? e.key : e;
|
|
61
61
|
}
|
|
62
|
-
let
|
|
63
|
-
function
|
|
64
|
-
let e =
|
|
65
|
-
|
|
62
|
+
let B = 0;
|
|
63
|
+
function V() {
|
|
64
|
+
let e = D.value;
|
|
65
|
+
D.value = null, e?.destroy();
|
|
66
66
|
}
|
|
67
|
-
async function
|
|
68
|
-
let e = ++
|
|
69
|
-
if (
|
|
70
|
-
|
|
67
|
+
async function H() {
|
|
68
|
+
let e = ++B, t = S.src;
|
|
69
|
+
if (V(), U.clear(), t === null) {
|
|
70
|
+
O.value = null;
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
|
|
73
|
+
O.value = { state: "loading" }, E();
|
|
74
74
|
let n;
|
|
75
75
|
try {
|
|
76
|
-
n = await
|
|
77
|
-
assets:
|
|
78
|
-
password:
|
|
79
|
-
defaults:
|
|
80
|
-
history: L.value ? !1 :
|
|
76
|
+
n = await ce(t, {
|
|
77
|
+
assets: S.assets,
|
|
78
|
+
password: S.password,
|
|
79
|
+
defaults: S.defaults ?? (T.value ? pe(T.value) : void 0),
|
|
80
|
+
history: L.value ? !1 : S.history ?? !0,
|
|
81
81
|
annotations: L.value ? {
|
|
82
82
|
mode: "controlled",
|
|
83
|
-
initial:
|
|
83
|
+
initial: S.annotations ?? [],
|
|
84
84
|
onChange: (e, t) => {
|
|
85
|
-
|
|
85
|
+
C("update:annotations", e), C("change", t);
|
|
86
86
|
}
|
|
87
87
|
} : { mode: "uncontrolled" }
|
|
88
88
|
});
|
|
89
89
|
} catch (t) {
|
|
90
|
-
if (e !==
|
|
90
|
+
if (e !== B) return;
|
|
91
91
|
let n = t instanceof p ? t : new p("InvalidPdf", t instanceof Error ? t.message : String(t), {}, t);
|
|
92
|
-
|
|
92
|
+
O.value = {
|
|
93
93
|
state: "error",
|
|
94
94
|
error: n
|
|
95
|
-
},
|
|
95
|
+
}, C("error", n);
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
|
-
if (e !==
|
|
98
|
+
if (e !== B) {
|
|
99
99
|
n.destroy();
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
|
-
n.annotations.mode === "controlled" &&
|
|
102
|
+
n.annotations.mode === "controlled" && S.annotations !== void 0 && n.annotations.setControlledValue(S.annotations), D.value = n, O.value = null;
|
|
103
103
|
let r = n.status.get();
|
|
104
|
-
r.state === "ready" ?
|
|
104
|
+
r.state === "ready" ? C("ready", n) : r.state === "error" && C("error", r.error);
|
|
105
105
|
}
|
|
106
|
-
let
|
|
107
|
-
source: () =>
|
|
108
|
-
apply: (e) =>
|
|
109
|
-
enabled: r(() => L.value &&
|
|
110
|
-
store: () =>
|
|
111
|
-
}),
|
|
112
|
-
canUndo: r(() => L.value ?
|
|
113
|
-
canRedo: r(() => L.value ?
|
|
114
|
-
undo: () => L.value ?
|
|
115
|
-
redo: () => L.value ?
|
|
116
|
-
clear: () => L.value ?
|
|
106
|
+
let U = n({
|
|
107
|
+
source: () => S.annotations,
|
|
108
|
+
apply: (e) => D.value?.annotations.replaceAll(e, "history"),
|
|
109
|
+
enabled: r(() => L.value && S.history === !0),
|
|
110
|
+
store: () => D.value?.annotations.mode === "controlled" ? D.value.annotations : null
|
|
111
|
+
}), _e = t(() => D.value?.history.canUndo ?? null, !1), ve = t(() => D.value?.history.canRedo ?? null, !1), W = {
|
|
112
|
+
canUndo: r(() => L.value ? U.canUndo.value : _e.value),
|
|
113
|
+
canRedo: r(() => L.value ? U.canRedo.value : ve.value),
|
|
114
|
+
undo: () => L.value ? U.undo() : D.value?.history.undo(),
|
|
115
|
+
redo: () => L.value ? U.redo() : D.value?.history.redo(),
|
|
116
|
+
clear: () => L.value ? U.clear() : D.value?.history.clear(),
|
|
117
117
|
batch: (e) => {
|
|
118
|
-
L.value ?
|
|
118
|
+
L.value ? U.batch(e) : D.value ? D.value.history.batch(e) : e();
|
|
119
119
|
},
|
|
120
|
-
track: (e) => L.value ?
|
|
121
|
-
react: (e) => L.value ?
|
|
122
|
-
},
|
|
123
|
-
d(
|
|
124
|
-
let
|
|
125
|
-
d(
|
|
126
|
-
let
|
|
127
|
-
d(I, (e) =>
|
|
128
|
-
let X =
|
|
129
|
-
function
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
120
|
+
track: (e) => L.value ? U.track(e) : D.value?.history.track(e) ?? z,
|
|
121
|
+
react: (e) => L.value ? U.react(e) : D.value?.history.react(e) ?? z
|
|
122
|
+
}, G = h(null);
|
|
123
|
+
d(D, (e) => G.set(e), { flush: "sync" });
|
|
124
|
+
let K = c(null), q = h(null);
|
|
125
|
+
d(K, (e) => q.set(e), { flush: "sync" });
|
|
126
|
+
let J = h(null);
|
|
127
|
+
d(I, (e) => J.set(e), { flush: "sync" });
|
|
128
|
+
let Y = c(null), X = c(null);
|
|
129
|
+
function ye() {
|
|
130
|
+
let e = g({
|
|
131
|
+
document: m(G),
|
|
132
|
+
viewport: () => N.value
|
|
133
|
+
});
|
|
134
|
+
X.value = e, Y.value = de({
|
|
135
|
+
plugins: S.plugins ?? [],
|
|
136
|
+
document: m(G),
|
|
137
|
+
history: () => W,
|
|
138
|
+
activated: m(J),
|
|
135
139
|
setActivated: (e) => {
|
|
136
|
-
(e === null ||
|
|
140
|
+
(e === null || D.value?.annotations.get(e)) && R(e);
|
|
137
141
|
},
|
|
138
|
-
root:
|
|
139
|
-
decorate: () =>
|
|
140
|
-
viewport: () => N.value
|
|
142
|
+
root: m(q),
|
|
143
|
+
decorate: () => S.decorateAnnotation,
|
|
144
|
+
viewport: () => N.value,
|
|
145
|
+
search: y(e)
|
|
141
146
|
});
|
|
142
147
|
}
|
|
143
|
-
let
|
|
144
|
-
|
|
148
|
+
let be = { onKeydown: xe };
|
|
149
|
+
function xe(e) {
|
|
150
|
+
let t = X.value, n = e.currentTarget;
|
|
151
|
+
t && n instanceof HTMLElement && me(e, t, () => _(n));
|
|
152
|
+
}
|
|
153
|
+
let Z = c(null), Q;
|
|
154
|
+
d(D, (e) => {
|
|
145
155
|
if (!e) {
|
|
146
156
|
Z.value = null, Q = void 0;
|
|
147
157
|
return;
|
|
148
158
|
}
|
|
149
|
-
let t =
|
|
159
|
+
let t = v({
|
|
150
160
|
store: e.annotations,
|
|
151
|
-
history: { batch: (e) =>
|
|
152
|
-
tools: [...
|
|
161
|
+
history: { batch: (e) => W.batch(e) },
|
|
162
|
+
tools: [...S.tools ?? [], ...Y.value?.tools ?? []],
|
|
153
163
|
tool: F.value
|
|
154
164
|
});
|
|
155
165
|
Q = (e) => t.setTool(e), Z.value = t.toolStyle;
|
|
@@ -157,75 +167,76 @@ var x = /*@__PURE__*/ i({
|
|
|
157
167
|
immediate: !0,
|
|
158
168
|
flush: "sync"
|
|
159
169
|
}), d(F, (e) => Q?.(e)), ne(() => {
|
|
160
|
-
|
|
170
|
+
E();
|
|
161
171
|
try {
|
|
162
|
-
|
|
172
|
+
ye();
|
|
163
173
|
} finally {
|
|
164
|
-
|
|
174
|
+
H();
|
|
165
175
|
}
|
|
166
|
-
}),
|
|
167
|
-
e &&
|
|
168
|
-
}), d(() =>
|
|
176
|
+
}), ie(E), d([() => ge(S.src), () => S.password], () => void H()), d(() => S.annotations, (e) => {
|
|
177
|
+
e && D.value?.annotations.mode === "controlled" && D.value.annotations.setControlledValue(e);
|
|
178
|
+
}), d(() => S.tool, (e) => {
|
|
169
179
|
e && (F.value = e);
|
|
170
180
|
});
|
|
171
|
-
function
|
|
181
|
+
function Se(e) {
|
|
172
182
|
let t = P.value;
|
|
173
|
-
F.value === e && t?.active.get() === e && t.set(e), F.value = e,
|
|
183
|
+
F.value === e && t?.active.get() === e && t.set(e), F.value = e, C("update:tool", e);
|
|
174
184
|
}
|
|
175
185
|
te(() => {
|
|
176
|
-
|
|
177
|
-
}),
|
|
178
|
-
X.value?.destroy(), X.value = null;
|
|
186
|
+
B++, V();
|
|
187
|
+
}), re(() => {
|
|
188
|
+
Y.value?.destroy(), Y.value = null, X.value?.destroy(), X.value = null;
|
|
179
189
|
});
|
|
180
|
-
let $ = r(() =>
|
|
190
|
+
let $ = r(() => se(S.signatures ?? oe()));
|
|
181
191
|
d($, (e) => void e.refresh(), { immediate: !0 });
|
|
182
|
-
let
|
|
192
|
+
let Ce = fe();
|
|
183
193
|
return e({
|
|
184
|
-
assets: r(() =>
|
|
185
|
-
document:
|
|
194
|
+
assets: r(() => S.assets),
|
|
195
|
+
document: D,
|
|
186
196
|
status: A,
|
|
187
197
|
annotations: j,
|
|
188
198
|
selection: M,
|
|
189
199
|
viewport: N,
|
|
190
200
|
tools: P,
|
|
191
201
|
tool: F,
|
|
192
|
-
setTool:
|
|
193
|
-
hostTools: r(() =>
|
|
194
|
-
decorateAnnotation: r(() =>
|
|
195
|
-
fonts: r(() =>
|
|
196
|
-
toolOptions:
|
|
202
|
+
setTool: Se,
|
|
203
|
+
hostTools: r(() => S.tools),
|
|
204
|
+
decorateAnnotation: r(() => S.decorateAnnotation),
|
|
205
|
+
fonts: r(() => S.fonts ?? le),
|
|
206
|
+
toolOptions: Ce,
|
|
197
207
|
signatures: $,
|
|
198
|
-
signatureFonts: r(() =>
|
|
208
|
+
signatureFonts: r(() => S.signatureFonts ?? ue),
|
|
199
209
|
toolStyle: Z,
|
|
200
|
-
zoomModel: r(() =>
|
|
201
|
-
pageModel: r(() =>
|
|
202
|
-
reportZoom: (e) =>
|
|
203
|
-
reportPage: (e) =>
|
|
210
|
+
zoomModel: r(() => S.zoom),
|
|
211
|
+
pageModel: r(() => S.page),
|
|
212
|
+
reportZoom: (e) => C("update:zoom", e),
|
|
213
|
+
reportPage: (e) => C("update:page", e),
|
|
204
214
|
activated: I,
|
|
205
215
|
setActivated: R,
|
|
206
|
-
pluginHost:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
216
|
+
pluginHost: Y,
|
|
217
|
+
search: X,
|
|
218
|
+
viewportEl: K,
|
|
219
|
+
history: W,
|
|
220
|
+
rootEl: T
|
|
210
221
|
}), x({
|
|
211
|
-
document:
|
|
222
|
+
document: D,
|
|
212
223
|
status: A,
|
|
213
|
-
rootEl:
|
|
214
|
-
history:
|
|
215
|
-
}), (e, t) => (
|
|
224
|
+
rootEl: T,
|
|
225
|
+
history: W
|
|
226
|
+
}), (e, t) => (ae(), i(l(b), ee({
|
|
216
227
|
ref_key: "primitive",
|
|
217
|
-
ref:
|
|
218
|
-
"as-child":
|
|
228
|
+
ref: w,
|
|
229
|
+
"as-child": S.asChild,
|
|
219
230
|
as: "div",
|
|
220
231
|
"data-ink-root": "",
|
|
221
232
|
"data-state": A.value.state
|
|
222
|
-
}, {
|
|
223
|
-
default: f(() => [
|
|
233
|
+
}, be), {
|
|
234
|
+
default: f(() => [s(e.$slots, "default", {
|
|
224
235
|
status: A.value,
|
|
225
|
-
document:
|
|
236
|
+
document: D.value
|
|
226
237
|
})]),
|
|
227
238
|
_: 3
|
|
228
|
-
},
|
|
239
|
+
}, 16, ["as-child", "data-state"]));
|
|
229
240
|
}
|
|
230
241
|
});
|
|
231
242
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkRoot.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_renderSlot","InkRoot_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","primitive","useTemplateRef","rootEl","shallowRef","syncRootEl","el","document","override","documentStatus","useReadable","status","computed","annotationList","selection","viewport","toolController","internalTool","ref","activated","controlled","setActivated","id","noop","identity","src","generation","release","doc","open","gen","refHistory","openDocument","cssVariableDefaults","next","change","cause","error","InkError","s","createRefHistory","list","coreCanUndo","coreCanRedo","inkHistory","fn","store","hostDocument","writable","viewportEl","hostRoot","hostActivated","pluginHost","setUpPlugins","createPluginHost","readonly","toolStyle","setStyleTool","watch","tracker","trackToolStyle","onMounted","onUpdated","t","setTool","tc","onBeforeUnmount","onUnmounted","signatures","createSignatureLibrary","createMemorySignatureStore","lib","toolOptions","createToolOptions","provideInkContext","FONT_FAMILIES","SIGNATURE_FONTS","z","p","openBlock","createBlock","unref","Primitive","withCtx","renderSlot","_ctx"],"sources":["../../src/components/InkRoot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n createMemorySignatureStore,\n createSignatureLibrary,\n InkError,\n openDocument,\n readonly,\n writable,\n} from '@inkbar/core'\nimport {\n createPluginHost,\n createToolOptions,\n cssVariableDefaults,\n FONT_FAMILIES,\n SIGNATURE_FONTS,\n trackToolStyle,\n} from '@inkbar/core/dom'\nimport { Primitive } from 'reka-ui'\nimport {\n computed,\n onBeforeUnmount,\n onUnmounted,\n onMounted,\n onUpdated,\n ref,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { provideInkContext, type InkHistory, type InkStatus } from '../context'\nimport { createRefHistory } from '../ref-history'\nimport { useReadable } from '../use-readable'\n\nimport type {\n Annotation,\n AnnotationChange,\n AnnotationDefaults,\n DocumentSource,\n InkDocument,\n PdfAssets,\n SignatureStore,\n} from '@inkbar/core'\nimport type {\n DecorateAnnotation,\n InkPlugin,\n PluginHost,\n Tool,\n ToolController,\n ToolId,\n ToolStyle,\n Viewport,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n src: DocumentSource | null\n assets: PdfAssets\n password?: string | undefined\n /** Colour defaults. Without it, the theme's CSS variables on the root element apply. */\n defaults?: AnnotationDefaults | undefined\n /**\n * Pass (with v-model) to put annotations under the host's control. The mode is fixed when a\n * document opens: passing or dropping this prop later takes effect on the next open.\n */\n annotations?: Annotation[] | undefined\n tool?: ToolId | undefined\n /**\n * Host tools, added to the built-ins; one with a built-in's id replaces it. Read when a\n * document opens.\n */\n tools?: Tool[] | undefined\n /**\n * Plugins, set up once when the root is created; a later change to this prop is not\n * applied. Their tools join `tools`, their decoration and page layers apply to every\n * document, and their commands are placed with `InkCommand` or `useCommand`.\n */\n plugins?: InkPlugin[] | undefined\n /**\n * Adds `data-*` attributes, classes and a screen-reader description to each annotation's\n * element (see `DecorateAnnotation`). Decorations re-apply whenever the annotations change\n * and when this prop changes, without rebuilding the viewer. Pass a new function when its\n * output would change for any other reason.\n */\n decorateAnnotation?: DecorateAnnotation | undefined\n /**\n * The font families text boxes offer, replacing the PDF standard families\n * (`FONT_FAMILIES`). Fonts beyond those are the PDF writer's to embed.\n */\n fonts?: string[] | undefined\n /**\n * Where saved signatures live. Default: memory, gone on reload.\n * `createLocalSignatureStore` keeps them in the browser; a host can keep them anywhere.\n * A new store takes effect at once, for the menus and the `signature` tool alike.\n */\n signatures?: SignatureStore | undefined\n /** The handwriting fonts a typed signature offers; the host loads them. */\n signatureFonts?: string[] | undefined\n page?: number | undefined\n zoom?: ZoomValue | undefined\n /** Undo history. Defaults to on for uncontrolled, off for controlled. */\n history?: boolean | undefined\n asChild?: boolean\n }>(),\n {\n password: undefined,\n defaults: undefined,\n annotations: undefined,\n tool: undefined,\n tools: undefined,\n plugins: undefined,\n decorateAnnotation: undefined,\n fonts: undefined,\n signatures: undefined,\n signatureFonts: undefined,\n page: undefined,\n zoom: undefined,\n history: undefined,\n asChild: false,\n }\n)\n\nconst emit = defineEmits<{\n 'update:annotations': [next: Annotation[]]\n change: [change: AnnotationChange]\n 'update:tool': [tool: ToolId]\n 'update:page': [page: number]\n 'update:zoom': [zoom: ZoomValue]\n ready: [doc: InkDocument]\n error: [error: InkError]\n activate: [id: string]\n}>()\n\ntype TestHookElement = HTMLElement & { __inkDocument?: InkDocument | undefined }\n\n// A template ref on Primitive is a component instance; the context needs its element.\nconst primitive = useTemplateRef<{ $el: unknown }>('primitive')\nconst rootEl = shallowRef<HTMLElement | null>(null)\nfunction syncRootEl(): void {\n const el = primitive.value?.$el\n rootEl.value = el instanceof HTMLElement ? el : null\n}\n\nconst document = shallowRef<InkDocument | null>(null)\n/** Overrides the document's status while opening, and when opening itself failed. */\nconst override = shallowRef<InkStatus | null>(null)\nconst idle: InkStatus = { state: 'idle' }\nconst documentStatus = useReadable<InkStatus>(() => document.value?.status ?? null, idle)\nconst status = computed<InkStatus>(() => override.value ?? documentStatus.value)\nconst annotationList = useReadable<readonly Annotation[]>(\n () => document.value?.annotations.list ?? null,\n []\n)\nconst selection = useReadable<readonly string[]>(\n () => document.value?.annotations.selection ?? null,\n []\n)\nconst viewport = shallowRef<Viewport | null>(null)\nconst toolController = shallowRef<ToolController | null>(null)\nconst internalTool = ref<ToolId>(props.tool ?? 'select-text')\nconst activated = ref<string | null>(null)\n\nconst controlled = computed(() => props.annotations !== undefined)\n\nfunction setActivated(id: string | null): void {\n activated.value = id\n if (id) emit('activate', id)\n}\n\nconst noop = () => {}\n\n/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */\nfunction identity(src: DocumentSource | null): unknown {\n if (src === null) return null\n if (typeof src === 'string') return src\n if ('key' in src) return src.key\n return src\n}\n\nfunction setTestHook(doc: InkDocument | undefined): void {\n if (import.meta.env.DEV && rootEl.value)\n (rootEl.value as TestHookElement).__inkDocument = doc\n}\n\nlet generation = 0\nfunction release(): void {\n // Cleared first, so the plugins close their stores while the document is still alive.\n const doc = document.value\n document.value = null\n doc?.destroy()\n setTestHook(undefined)\n}\n\nasync function open(): Promise<void> {\n const gen = ++generation\n const src = props.src\n release()\n refHistory.clear()\n if (src === null) {\n override.value = null\n return\n }\n override.value = { state: 'loading' }\n syncRootEl()\n let doc: InkDocument\n try {\n doc = await openDocument(src, {\n assets: props.assets,\n password: props.password,\n defaults:\n props.defaults ?? (rootEl.value ? cssVariableDefaults(rootEl.value) : undefined),\n // Controlled hosts get the ref history below; core's own stack stays off.\n history: controlled.value ? false : (props.history ?? true),\n annotations: controlled.value\n ? {\n mode: 'controlled',\n initial: props.annotations ?? [],\n onChange: (next, change) => {\n emit('update:annotations', next)\n emit('change', change)\n },\n }\n : { mode: 'uncontrolled' },\n })\n } catch (cause) {\n if (gen !== generation) return\n const error =\n cause instanceof InkError\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n override.value = { state: 'error', error }\n emit('error', error)\n return\n }\n if (gen !== generation) {\n doc.destroy()\n return\n }\n // The prop may have changed while the file loaded, when there was no store to apply it to.\n if (doc.annotations.mode === 'controlled' && props.annotations !== undefined)\n doc.annotations.setControlledValue(props.annotations)\n document.value = doc\n override.value = null\n setTestHook(doc)\n const s = doc.status.get()\n if (s.state === 'ready') emit('ready', doc)\n else if (s.state === 'error') emit('error', s.error)\n}\n\nconst refHistory = createRefHistory({\n source: () => props.annotations,\n apply: (list) => document.value?.annotations.replaceAll(list, 'history'),\n enabled: computed(() => controlled.value && props.history === true),\n store: () =>\n document.value?.annotations.mode === 'controlled' ? document.value.annotations : null,\n})\nconst coreCanUndo = useReadable(() => document.value?.history.canUndo ?? null, false)\nconst coreCanRedo = useReadable(() => document.value?.history.canRedo ?? null, false)\nconst inkHistory: InkHistory = {\n canUndo: computed(() =>\n controlled.value ? refHistory.canUndo.value : coreCanUndo.value\n ),\n canRedo: computed(() =>\n controlled.value ? refHistory.canRedo.value : coreCanRedo.value\n ),\n undo: () => (controlled.value ? refHistory.undo() : document.value?.history.undo()),\n redo: () => (controlled.value ? refHistory.redo() : document.value?.history.redo()),\n clear: () => (controlled.value ? refHistory.clear() : document.value?.history.clear()),\n batch: (fn) => {\n if (controlled.value) refHistory.batch(fn)\n else if (document.value) document.value.history.batch(fn)\n else fn()\n },\n track: (store) =>\n controlled.value\n ? refHistory.track(store)\n : (document.value?.history.track(store) ?? noop),\n react: (fn) =>\n controlled.value ? refHistory.react(fn) : (document.value?.history.react(fn) ?? noop),\n}\n\n/*\n * One plugin host for the root's life, built once mounted so that no `setup` runs on the\n * server, where nothing would clean it up. Until then `pluginHost` is null, and InkCommand\n * renders its command disabled. The host follows `hostDocument`, which is set after `document`\n * (a sync watch): when the host reads `inkHistory` for a new document, it is that document's\n * history.\n */\nconst hostDocument = writable<InkDocument | null>(null)\nwatch(document, (doc) => hostDocument.set(doc), { flush: 'sync' })\nconst viewportEl = shallowRef<HTMLElement | null>(null)\nconst hostRoot = writable<HTMLElement | null>(null)\nwatch(viewportEl, (el) => hostRoot.set(el), { flush: 'sync' })\nconst hostActivated = writable<string | null>(null)\nwatch(activated, (id) => hostActivated.set(id), { flush: 'sync' })\nconst pluginHost = shallowRef<PluginHost | null>(null)\nfunction setUpPlugins(): void {\n pluginHost.value = createPluginHost({\n plugins: props.plugins ?? [],\n document: readonly(hostDocument),\n history: () => inkHistory,\n activated: readonly(hostActivated),\n // As in `createViewer`: an id not in the open document is ignored.\n setActivated: (id) => {\n if (id === null || document.value?.annotations.get(id)) setActivated(id)\n },\n root: readonly(hostRoot),\n decorate: () => props.decorateAnnotation,\n viewport: () => viewport.value,\n })\n}\n\n/** The document's tool style; it batches through `inkHistory`, whichever mode is on. */\nconst toolStyle = shallowRef<ToolStyle | null>(null)\nlet setStyleTool: ((id: ToolId) => void) | undefined\nwatch(\n document,\n (doc) => {\n if (!doc) {\n toolStyle.value = null\n setStyleTool = undefined\n return\n }\n const tracker = trackToolStyle({\n store: doc.annotations,\n history: { batch: (fn) => inkHistory.batch(fn) },\n // The plugins' tools too, so a plugin tool's style group applies (the host is set by now:\n // it is built on mount, before the first document opens).\n tools: [...(props.tools ?? []), ...(pluginHost.value?.tools ?? [])],\n tool: internalTool.value,\n })\n setStyleTool = (id) => tracker.setTool(id)\n toolStyle.value = tracker.toolStyle\n },\n // Sync: the style is in place before InkViewport's watcher mounts the engine with it.\n { immediate: true, flush: 'sync' }\n)\nwatch(internalTool, (id) => setStyleTool?.(id))\n\n// Plugins and the document on the client only: on the server InkRoot renders its empty slot.\n// The plugins first, so the first document opens with their stores and reactions.\nonMounted(() => {\n syncRootEl()\n // A plugin whose setup throws still leaves the document to open; the error then goes to\n // Vue's error handling (`onErrorCaptured`, `app.config.errorHandler`).\n try {\n setUpPlugins()\n } finally {\n void open()\n }\n})\nonUpdated(syncRootEl)\n\n// Separate sources, so a new `{ url, key }` object with the same key compares equal.\nwatch([() => identity(props.src), () => props.password], () => void open())\n\nwatch(\n () => props.annotations,\n (next) => {\n if (next && document.value?.annotations.mode === 'controlled')\n document.value.annotations.setControlledValue(next)\n }\n)\n\nwatch(\n () => props.tool,\n (t) => {\n if (t) internalTool.value = t\n }\n)\n\nfunction setTool(id: ToolId): void {\n // Picking the active tool again starts it afresh, as after a one-shot tool's use.\n const tc = toolController.value\n if (internalTool.value === id && tc?.active.get() === id) tc.set(id)\n internalTool.value = id\n emit('update:tool', id)\n}\n\nonBeforeUnmount(() => {\n generation++\n release()\n})\n\n// After the children: InkViewport's engine, and the plugin layers with it, are gone by now, as\n// in `createViewer`, so no layer `destroy` runs after the plugins' cleanups.\nonUnmounted(() => {\n pluginHost.value?.destroy()\n pluginHost.value = null\n})\n\nconst signatures = computed(() =>\n createSignatureLibrary(props.signatures ?? createMemorySignatureStore())\n)\nwatch(signatures, (lib) => void lib.refresh(), { immediate: true })\n/** Tool options last as long as the root; the tool style is per document. */\nconst toolOptions = createToolOptions()\n\nprovideInkContext({\n assets: computed(() => props.assets),\n document,\n status,\n annotations: annotationList,\n selection,\n viewport,\n tools: toolController,\n tool: internalTool,\n setTool,\n hostTools: computed(() => props.tools),\n decorateAnnotation: computed(() => props.decorateAnnotation),\n fonts: computed(() => props.fonts ?? FONT_FAMILIES),\n toolOptions,\n signatures,\n signatureFonts: computed(() => props.signatureFonts ?? SIGNATURE_FONTS),\n toolStyle,\n zoomModel: computed(() => props.zoom),\n pageModel: computed(() => props.page),\n reportZoom: (z) => emit('update:zoom', z),\n reportPage: (p) => emit('update:page', p),\n activated,\n setActivated,\n pluginHost,\n viewportEl,\n history: inkHistory,\n rootEl,\n})\n\n// `history` is what `useHistory()` returns inside the root, for hosts that hold a template ref:\n// a controlled host calls `history.clear()` after loading its saved list.\ndefineExpose({ document, status, rootEl, history: inkHistory })\n</script>\n\n<template>\n <Primitive\n ref=\"primitive\"\n :as-child=\"props.asChild\"\n as=\"div\"\n data-ink-root\n :data-state=\"status.state\"\n >\n <slot :status=\"status\" :document=\"document\" />\n </Primitive>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InkRoot.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_mergeProps","_withCtx","_renderSlot","InkRoot_vue_vue_type_script_setup_true_lang_default","__expose","__emit","props","__props","emit","primitive","useTemplateRef","rootEl","shallowRef","syncRootEl","el","document","override","documentStatus","useReadable","status","computed","annotationList","selection","viewport","toolController","internalTool","ref","activated","controlled","setActivated","id","noop","identity","src","generation","release","doc","open","gen","refHistory","openDocument","cssVariableDefaults","next","change","cause","error","InkError","s","createRefHistory","list","coreCanUndo","coreCanRedo","inkHistory","fn","store","hostDocument","writable","viewportEl","hostRoot","hostActivated","pluginHost","search","setUpPlugins","controller","createSearchController","readonly","createPluginHost","viewerSearchOf","rootListeners","onKeydown","root","handleFindKey","pageSelectionText","toolStyle","setStyleTool","watch","tracker","trackToolStyle","onMounted","onUpdated","t","setTool","tc","onBeforeUnmount","onUnmounted","signatures","createSignatureLibrary","createMemorySignatureStore","lib","toolOptions","createToolOptions","provideInkContext","FONT_FAMILIES","SIGNATURE_FONTS","z","p","openBlock","createBlock","unref","Primitive","mergeProps","withCtx","renderSlot","_ctx"],"sources":["../../src/components/InkRoot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n createMemorySignatureStore,\n createSignatureLibrary,\n InkError,\n openDocument,\n readonly,\n writable,\n} from '@inkbar/core'\nimport {\n createPluginHost,\n createSearchController,\n createToolOptions,\n handleFindKey,\n pageSelectionText,\n viewerSearchOf,\n cssVariableDefaults,\n FONT_FAMILIES,\n SIGNATURE_FONTS,\n trackToolStyle,\n} from '@inkbar/core/dom'\nimport { Primitive } from 'reka-ui'\nimport {\n computed,\n onBeforeUnmount,\n onUnmounted,\n onMounted,\n onUpdated,\n ref,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { provideInkContext, type InkHistory, type InkStatus } from '../context'\nimport { createRefHistory } from '../ref-history'\nimport { useReadable } from '../use-readable'\n\nimport type {\n Annotation,\n AnnotationChange,\n AnnotationDefaults,\n DocumentSource,\n InkDocument,\n PdfAssets,\n SignatureStore,\n} from '@inkbar/core'\nimport type {\n DecorateAnnotation,\n InkPlugin,\n PluginHost,\n SearchController,\n Tool,\n ToolController,\n ToolId,\n ToolStyle,\n Viewport,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n src: DocumentSource | null\n assets: PdfAssets\n password?: string | undefined\n /** Colour defaults. Without it, the theme's CSS variables on the root element apply. */\n defaults?: AnnotationDefaults | undefined\n /**\n * Pass (with v-model) to put annotations under the host's control. The mode is fixed when a\n * document opens: passing or dropping this prop later takes effect on the next open.\n */\n annotations?: Annotation[] | undefined\n tool?: ToolId | undefined\n /**\n * Host tools, added to the built-ins; one with a built-in's id replaces it. Read when a\n * document opens.\n */\n tools?: Tool[] | undefined\n /**\n * Plugins, set up once when the root is created; a later change to this prop is not\n * applied. Their tools join `tools`, their decoration and page layers apply to every\n * document, and their commands are placed with `InkCommand` or `useCommand`.\n */\n plugins?: InkPlugin[] | undefined\n /**\n * Adds `data-*` attributes, classes and a screen-reader description to each annotation's\n * element (see `DecorateAnnotation`). Decorations re-apply whenever the annotations change\n * and when this prop changes, without rebuilding the viewer. Pass a new function when its\n * output would change for any other reason.\n */\n decorateAnnotation?: DecorateAnnotation | undefined\n /**\n * The font families text boxes offer, replacing the PDF standard families\n * (`FONT_FAMILIES`). Fonts beyond those are the PDF writer's to embed.\n */\n fonts?: string[] | undefined\n /**\n * Where saved signatures live. Default: memory, gone on reload.\n * `createLocalSignatureStore` keeps them in the browser; a host can keep them anywhere.\n * A new store takes effect at once, for the menus and the `signature` tool alike.\n */\n signatures?: SignatureStore | undefined\n /** The handwriting fonts a typed signature offers; the host loads them. */\n signatureFonts?: string[] | undefined\n page?: number | undefined\n zoom?: ZoomValue | undefined\n /** Undo history. Defaults to on for uncontrolled, off for controlled. */\n history?: boolean | undefined\n asChild?: boolean\n }>(),\n {\n password: undefined,\n defaults: undefined,\n annotations: undefined,\n tool: undefined,\n tools: undefined,\n plugins: undefined,\n decorateAnnotation: undefined,\n fonts: undefined,\n signatures: undefined,\n signatureFonts: undefined,\n page: undefined,\n zoom: undefined,\n history: undefined,\n asChild: false,\n }\n)\n\nconst emit = defineEmits<{\n 'update:annotations': [next: Annotation[]]\n change: [change: AnnotationChange]\n 'update:tool': [tool: ToolId]\n 'update:page': [page: number]\n 'update:zoom': [zoom: ZoomValue]\n ready: [doc: InkDocument]\n error: [error: InkError]\n activate: [id: string]\n}>()\n\ntype TestHookElement = HTMLElement & { __inkDocument?: InkDocument | undefined }\n\n// A template ref on Primitive is a component instance; the context needs its element.\nconst primitive = useTemplateRef<{ $el: unknown }>('primitive')\nconst rootEl = shallowRef<HTMLElement | null>(null)\nfunction syncRootEl(): void {\n const el = primitive.value?.$el\n rootEl.value = el instanceof HTMLElement ? el : null\n}\n\nconst document = shallowRef<InkDocument | null>(null)\n/** Overrides the document's status while opening, and when opening itself failed. */\nconst override = shallowRef<InkStatus | null>(null)\nconst idle: InkStatus = { state: 'idle' }\nconst documentStatus = useReadable<InkStatus>(() => document.value?.status ?? null, idle)\nconst status = computed<InkStatus>(() => override.value ?? documentStatus.value)\nconst annotationList = useReadable<readonly Annotation[]>(\n () => document.value?.annotations.list ?? null,\n []\n)\nconst selection = useReadable<readonly string[]>(\n () => document.value?.annotations.selection ?? null,\n []\n)\nconst viewport = shallowRef<Viewport | null>(null)\nconst toolController = shallowRef<ToolController | null>(null)\nconst internalTool = ref<ToolId>(props.tool ?? 'select-text')\nconst activated = ref<string | null>(null)\n\nconst controlled = computed(() => props.annotations !== undefined)\n\nfunction setActivated(id: string | null): void {\n activated.value = id\n if (id) emit('activate', id)\n}\n\nconst noop = () => {}\n\n/** Signed URLs change; the key does not. Bytes and Blobs are their own identity. */\nfunction identity(src: DocumentSource | null): unknown {\n if (src === null) return null\n if (typeof src === 'string') return src\n if ('key' in src) return src.key\n return src\n}\n\nfunction setTestHook(doc: InkDocument | undefined): void {\n if (import.meta.env.DEV && rootEl.value)\n (rootEl.value as TestHookElement).__inkDocument = doc\n}\n\nlet generation = 0\nfunction release(): void {\n // Cleared first, so the plugins close their stores while the document is still alive.\n const doc = document.value\n document.value = null\n doc?.destroy()\n setTestHook(undefined)\n}\n\nasync function open(): Promise<void> {\n const gen = ++generation\n const src = props.src\n release()\n refHistory.clear()\n if (src === null) {\n override.value = null\n return\n }\n override.value = { state: 'loading' }\n syncRootEl()\n let doc: InkDocument\n try {\n doc = await openDocument(src, {\n assets: props.assets,\n password: props.password,\n defaults:\n props.defaults ?? (rootEl.value ? cssVariableDefaults(rootEl.value) : undefined),\n // Controlled hosts get the ref history below; core's own stack stays off.\n history: controlled.value ? false : (props.history ?? true),\n annotations: controlled.value\n ? {\n mode: 'controlled',\n initial: props.annotations ?? [],\n onChange: (next, change) => {\n emit('update:annotations', next)\n emit('change', change)\n },\n }\n : { mode: 'uncontrolled' },\n })\n } catch (cause) {\n if (gen !== generation) return\n const error =\n cause instanceof InkError\n ? cause\n : new InkError(\n 'InvalidPdf',\n cause instanceof Error ? cause.message : String(cause),\n {},\n cause\n )\n override.value = { state: 'error', error }\n emit('error', error)\n return\n }\n if (gen !== generation) {\n doc.destroy()\n return\n }\n // The prop may have changed while the file loaded, when there was no store to apply it to.\n if (doc.annotations.mode === 'controlled' && props.annotations !== undefined)\n doc.annotations.setControlledValue(props.annotations)\n document.value = doc\n override.value = null\n setTestHook(doc)\n const s = doc.status.get()\n if (s.state === 'ready') emit('ready', doc)\n else if (s.state === 'error') emit('error', s.error)\n}\n\nconst refHistory = createRefHistory({\n source: () => props.annotations,\n apply: (list) => document.value?.annotations.replaceAll(list, 'history'),\n enabled: computed(() => controlled.value && props.history === true),\n store: () =>\n document.value?.annotations.mode === 'controlled' ? document.value.annotations : null,\n})\nconst coreCanUndo = useReadable(() => document.value?.history.canUndo ?? null, false)\nconst coreCanRedo = useReadable(() => document.value?.history.canRedo ?? null, false)\nconst inkHistory: InkHistory = {\n canUndo: computed(() =>\n controlled.value ? refHistory.canUndo.value : coreCanUndo.value\n ),\n canRedo: computed(() =>\n controlled.value ? refHistory.canRedo.value : coreCanRedo.value\n ),\n undo: () => (controlled.value ? refHistory.undo() : document.value?.history.undo()),\n redo: () => (controlled.value ? refHistory.redo() : document.value?.history.redo()),\n clear: () => (controlled.value ? refHistory.clear() : document.value?.history.clear()),\n batch: (fn) => {\n if (controlled.value) refHistory.batch(fn)\n else if (document.value) document.value.history.batch(fn)\n else fn()\n },\n track: (store) =>\n controlled.value\n ? refHistory.track(store)\n : (document.value?.history.track(store) ?? noop),\n react: (fn) =>\n controlled.value ? refHistory.react(fn) : (document.value?.history.react(fn) ?? noop),\n}\n\n/*\n * One plugin host for the root's life, built once mounted so that no `setup` runs on the\n * server, where nothing would clean it up. Until then `pluginHost` is null, and InkCommand\n * renders its command disabled. The host follows `hostDocument`, which is set after `document`\n * (a sync watch): when the host reads `inkHistory` for a new document, it is that document's\n * history.\n */\nconst hostDocument = writable<InkDocument | null>(null)\nwatch(document, (doc) => hostDocument.set(doc), { flush: 'sync' })\nconst viewportEl = shallowRef<HTMLElement | null>(null)\nconst hostRoot = writable<HTMLElement | null>(null)\nwatch(viewportEl, (el) => hostRoot.set(el), { flush: 'sync' })\nconst hostActivated = writable<string | null>(null)\nwatch(activated, (id) => hostActivated.set(id), { flush: 'sync' })\nconst pluginHost = shallowRef<PluginHost | null>(null)\n/** One search controller for the root's life, built with the plugin host that shares it. */\nconst search = shallowRef<SearchController | null>(null)\nfunction setUpPlugins(): void {\n const controller = createSearchController({\n document: readonly(hostDocument),\n viewport: () => viewport.value,\n })\n search.value = controller\n pluginHost.value = createPluginHost({\n plugins: props.plugins ?? [],\n document: readonly(hostDocument),\n history: () => inkHistory,\n activated: readonly(hostActivated),\n // As in `createViewer`: an id not in the open document is ignored.\n setActivated: (id) => {\n if (id === null || document.value?.annotations.get(id)) setActivated(id)\n },\n root: readonly(hostRoot),\n decorate: () => props.decorateAnnotation,\n viewport: () => viewport.value,\n search: viewerSearchOf(controller),\n })\n}\n\n// Reka's typed props stop at its own; listeners go through a bound object.\nconst rootListeners = { onKeydown }\n\n/** Ctrl/Cmd+F while focus is in the root and a find bar is mounted; else the browser's. */\nfunction onKeydown(e: KeyboardEvent): void {\n const controller = search.value\n const root = e.currentTarget\n if (controller && root instanceof HTMLElement)\n handleFindKey(e, controller, () => pageSelectionText(root))\n}\n\n/** The document's tool style; it batches through `inkHistory`, whichever mode is on. */\nconst toolStyle = shallowRef<ToolStyle | null>(null)\nlet setStyleTool: ((id: ToolId) => void) | undefined\nwatch(\n document,\n (doc) => {\n if (!doc) {\n toolStyle.value = null\n setStyleTool = undefined\n return\n }\n const tracker = trackToolStyle({\n store: doc.annotations,\n history: { batch: (fn) => inkHistory.batch(fn) },\n // The plugins' tools too, so a plugin tool's style group applies (the host is set by now:\n // it is built on mount, before the first document opens).\n tools: [...(props.tools ?? []), ...(pluginHost.value?.tools ?? [])],\n tool: internalTool.value,\n })\n setStyleTool = (id) => tracker.setTool(id)\n toolStyle.value = tracker.toolStyle\n },\n // Sync: the style is in place before InkViewport's watcher mounts the engine with it.\n { immediate: true, flush: 'sync' }\n)\nwatch(internalTool, (id) => setStyleTool?.(id))\n\n// Plugins and the document on the client only: on the server InkRoot renders its empty slot.\n// The plugins first, so the first document opens with their stores and reactions.\nonMounted(() => {\n syncRootEl()\n // A plugin whose setup throws still leaves the document to open; the error then goes to\n // Vue's error handling (`onErrorCaptured`, `app.config.errorHandler`).\n try {\n setUpPlugins()\n } finally {\n void open()\n }\n})\nonUpdated(syncRootEl)\n\n// Separate sources, so a new `{ url, key }` object with the same key compares equal.\nwatch([() => identity(props.src), () => props.password], () => void open())\n\nwatch(\n () => props.annotations,\n (next) => {\n if (next && document.value?.annotations.mode === 'controlled')\n document.value.annotations.setControlledValue(next)\n }\n)\n\nwatch(\n () => props.tool,\n (t) => {\n if (t) internalTool.value = t\n }\n)\n\nfunction setTool(id: ToolId): void {\n // Picking the active tool again starts it afresh, as after a one-shot tool's use.\n const tc = toolController.value\n if (internalTool.value === id && tc?.active.get() === id) tc.set(id)\n internalTool.value = id\n emit('update:tool', id)\n}\n\nonBeforeUnmount(() => {\n generation++\n release()\n})\n\n// After the children: InkViewport's engine, and the plugin layers with it, are gone by now, as\n// in `createViewer`, so no layer `destroy` runs after the plugins' cleanups.\nonUnmounted(() => {\n pluginHost.value?.destroy()\n pluginHost.value = null\n search.value?.destroy()\n search.value = null\n})\n\nconst signatures = computed(() =>\n createSignatureLibrary(props.signatures ?? createMemorySignatureStore())\n)\nwatch(signatures, (lib) => void lib.refresh(), { immediate: true })\n/** Tool options last as long as the root; the tool style is per document. */\nconst toolOptions = createToolOptions()\n\nprovideInkContext({\n assets: computed(() => props.assets),\n document,\n status,\n annotations: annotationList,\n selection,\n viewport,\n tools: toolController,\n tool: internalTool,\n setTool,\n hostTools: computed(() => props.tools),\n decorateAnnotation: computed(() => props.decorateAnnotation),\n fonts: computed(() => props.fonts ?? FONT_FAMILIES),\n toolOptions,\n signatures,\n signatureFonts: computed(() => props.signatureFonts ?? SIGNATURE_FONTS),\n toolStyle,\n zoomModel: computed(() => props.zoom),\n pageModel: computed(() => props.page),\n reportZoom: (z) => emit('update:zoom', z),\n reportPage: (p) => emit('update:page', p),\n activated,\n setActivated,\n pluginHost,\n search,\n viewportEl,\n history: inkHistory,\n rootEl,\n})\n\n// `history` is what `useHistory()` returns inside the root, for hosts that hold a template ref:\n// a controlled host calls `history.clear()` after loading its saved list.\ndefineExpose({ document, status, rootEl, history: inkHistory })\n</script>\n\n<template>\n <Primitive\n ref=\"primitive\"\n :as-child=\"props.asChild\"\n as=\"div\"\n data-ink-root\n :data-state=\"status.state\"\n v-bind=\"rootListeners\"\n >\n <slot :status=\"status\" :document=\"document\" />\n </Primitive>\n</template>\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InkSearchButton.js","names":["_sfc_main","InkSearchButton_vue_vue_type_script_setup_true_lang_default","InkSearchButton_default"],"sources":["../../src/components/InkSearchButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Opens the find bar; pressed while it is open. Pressing it again focuses the field. Place it\n * in a toolbar next to `InkFindBar`, which it needs for the field to focus.\n */\nimport { Search } from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed, mergeProps, nextTick } from 'vue'\n\nimport { useDocument } from '../composables/useDocument'\nimport { useSearch } from '../composables/useSearch'\nimport { useInkContext } from '../context'\n\nimport InkIcon from './InkIcon.vue'\n\n// Bound below, under the button's own label, so a caller's attributes cannot replace its copy.\ndefineOptions({ inheritAttrs: false })\n\nwithDefaults(defineProps<{ asChild?: boolean }>(), { asChild: false })\nconst ctx = useInkContext('InkSearchButton')\nconst { state, open } = useSearch()\nconst { isReady } = useDocument()\n\nasync function onClick(): Promise<void> {\n open()\n // The bar shows on the next render; its field takes focus then.\n await nextTick()\n const field = ctx.rootEl.value?.querySelector<HTMLInputElement>(\n '[data-ink-find-bar] input'\n )\n field?.focus()\n field?.select()\n}\n// Reka's typed props stop at its own; ARIA and listeners go through a bound object.\nconst attrs = computed(() => ({\n 'aria-label': 'Find',\n title: 'Find',\n 'aria-pressed': state.value.open,\n 'data-state': state.value.open ? 'on' : 'off',\n onClick,\n}))\n/** Disabled until a document is open, whatever the caller's `disabled` says, as in React and Svelte. */\nconst disabled = (fromCaller: unknown): boolean =>\n !isReady.value || (fromCaller != null && fromCaller !== false)\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n class=\"ink-search-button\"\n data-ink-search-button\n v-bind=\"mergeProps($attrs, attrs, { disabled: disabled($attrs.disabled) })\"\n >\n <slot><InkIcon :icon=\"Search\" /></slot>\n </ToolbarButton>\n</template>\n"],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
asChild?: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare var __VLS_7: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_7) => any;
|
|
7
|
+
};
|
|
8
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
9
|
+
asChild: boolean;
|
|
10
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=InkSearchButton.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InkSearchButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkSearchButton.vue"],"names":[],"mappings":"AA4EA,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAwEzC,QAAA,IAAI,OAAO,IAAW,CAAC;AACvB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAG/C,QAAA,MAAM,UAAU;;6EAGd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useInkContext as e } from "../context.js";
|
|
2
|
+
import { useDocument as t } from "../composables/useDocument.js";
|
|
3
|
+
import { useSearch as n } from "../composables/useSearch.js";
|
|
4
|
+
import r from "./InkIcon.js";
|
|
5
|
+
import { computed as i, createBlock as a, createVNode as o, defineComponent as s, mergeProps as c, nextTick as l, openBlock as u, renderSlot as d, unref as f, withCtx as p } from "vue";
|
|
6
|
+
import { ToolbarButton as m } from "reka-ui";
|
|
7
|
+
import { Search as h } from "@inkbar/icons";
|
|
8
|
+
//#region src/components/InkSearchButton.vue?vue&type=script&setup=true&lang.ts
|
|
9
|
+
var g = /*@__PURE__*/ s({
|
|
10
|
+
inheritAttrs: !1,
|
|
11
|
+
__name: "InkSearchButton",
|
|
12
|
+
props: { asChild: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: !1
|
|
15
|
+
} },
|
|
16
|
+
setup(s) {
|
|
17
|
+
let g = e("InkSearchButton"), { state: _, open: v } = n(), { isReady: y } = t();
|
|
18
|
+
async function b() {
|
|
19
|
+
v(), await l();
|
|
20
|
+
let e = g.rootEl.value?.querySelector("[data-ink-find-bar] input");
|
|
21
|
+
e?.focus(), e?.select();
|
|
22
|
+
}
|
|
23
|
+
let x = i(() => ({
|
|
24
|
+
"aria-label": "Find",
|
|
25
|
+
title: "Find",
|
|
26
|
+
"aria-pressed": _.value.open,
|
|
27
|
+
"data-state": _.value.open ? "on" : "off",
|
|
28
|
+
onClick: b
|
|
29
|
+
})), S = (e) => !y.value || e != null && e !== !1;
|
|
30
|
+
return (e, t) => (u(), a(f(m), c({
|
|
31
|
+
"as-child": s.asChild,
|
|
32
|
+
class: "ink-search-button",
|
|
33
|
+
"data-ink-search-button": ""
|
|
34
|
+
}, c(e.$attrs, x.value, { disabled: S(e.$attrs.disabled) })), {
|
|
35
|
+
default: p(() => [d(e.$slots, "default", {}, () => [o(r, { icon: f(h) }, null, 8, ["icon"])])]),
|
|
36
|
+
_: 3
|
|
37
|
+
}, 16, ["as-child"]));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { g as default };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=InkSearchButton.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InkSearchButton.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_mergeProps","_withCtx","_renderSlot","_createVNode","InkIcon","InkIcon_default","InkSearchButton_vue_vue_type_script_setup_true_lang_default","ctx","useInkContext","useSearch","useDocument","onClick","open","nextTick","field","attrs","computed","state","disabled","isReady","fromCaller","openBlock","createBlock","unref","ToolbarButton","mergeProps","__props","_ctx","withCtx","renderSlot","createVNode","Search"],"sources":["../../src/components/InkSearchButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Opens the find bar; pressed while it is open. Pressing it again focuses the field. Place it\n * in a toolbar next to `InkFindBar`, which it needs for the field to focus.\n */\nimport { Search } from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed, mergeProps, nextTick } from 'vue'\n\nimport { useDocument } from '../composables/useDocument'\nimport { useSearch } from '../composables/useSearch'\nimport { useInkContext } from '../context'\n\nimport InkIcon from './InkIcon.vue'\n\n// Bound below, under the button's own label, so a caller's attributes cannot replace its copy.\ndefineOptions({ inheritAttrs: false })\n\nwithDefaults(defineProps<{ asChild?: boolean }>(), { asChild: false })\nconst ctx = useInkContext('InkSearchButton')\nconst { state, open } = useSearch()\nconst { isReady } = useDocument()\n\nasync function onClick(): Promise<void> {\n open()\n // The bar shows on the next render; its field takes focus then.\n await nextTick()\n const field = ctx.rootEl.value?.querySelector<HTMLInputElement>(\n '[data-ink-find-bar] input'\n )\n field?.focus()\n field?.select()\n}\n// Reka's typed props stop at its own; ARIA and listeners go through a bound object.\nconst attrs = computed(() => ({\n 'aria-label': 'Find',\n title: 'Find',\n 'aria-pressed': state.value.open,\n 'data-state': state.value.open ? 'on' : 'off',\n onClick,\n}))\n/** Disabled until a document is open, whatever the caller's `disabled` says, as in React and Svelte. */\nconst disabled = (fromCaller: unknown): boolean =>\n !isReady.value || (fromCaller != null && fromCaller !== false)\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n class=\"ink-search-button\"\n data-ink-search-button\n v-bind=\"mergeProps($attrs, attrs, { disabled: disabled($attrs.disabled) })\"\n >\n <slot><InkIcon :icon=\"Search\" /></slot>\n </ToolbarButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAmBA,IAAMW,IAAMC,EAAc,iBAAiB,GACrC,EAAE,UAAO,YAASC,EAAU,GAC5B,EAAE,eAAYC,EAAY;EAEhC,eAAeC,IAAyB;GAGtC,AAFAC,EAAK,GAEL,MAAMC,EAAS;GACf,IAAMC,IAAQP,EAAI,OAAO,OAAO,cAC9B,2BACF;GAEA,AADAO,GAAO,MAAM,GACbA,GAAO,OAAO;EAChB;EAEA,IAAMC,IAAQC,SAAgB;GAC5B,cAAc;GACd,OAAO;GACP,gBAAgBC,EAAM,MAAM;GAC5B,cAAcA,EAAM,MAAM,OAAO,OAAO;GACxC;EACF,EAAE,GAEIC,KAAY,MAChB,CAACC,EAAQ,SAAUC,KAAc,QAAQA,MAAe;oBAIxDvB,EAAA,GAAAC,EAOgBC,EAAAyB,CAAA,GAPhBxB,EAOgB;GANb,YAAU0B,EAAA;GACX,OAAM;GACN,0BAAA;EACQ,GAAAD,EAAW7B,EAAAA,QAAQmB,EAAA,OAAK,EAAA,UAAcG,EAAStB,EAAAA,OAAO,QAAQ,EAAA,CAAA,CAAA,GAAA;GAEtE,SAAAK,QAAuC,CAAvCC,EAAuCyB,EAAA,QAAA,WAAA,CAAA,SAAA,CAAjCxB,EAA0BC,GAAA,EAAhB,MAAML,EAAAgC,CAAA,EAAM,GAAA,MAAA,GAAA,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkViewport.js","names":["_sfc_main","InkViewport_vue_vue_type_script_setup_true_lang_default","InkViewport_default"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ToolId,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n ...(ctx.hostTools.value ? { tools: ctx.hostTools.value } : {}),\n // The engine adds the plugins' tools and layers, and decorates through the host, which\n // reads `decorateAnnotation` first.\n ...(ctx.pluginHost.value ? { plugins: ctx.pluginHost.value } : {}),\n // Read through, so the watch below can re-apply a new function without a rebuild.\n decorateAnnotation: (a) => ctx.decorateAnnotation.value?.(a),\n ...(ctx.toolStyle.value ? { toolStyle: ctx.toolStyle.value } : {}),\n toolHistory: { batch: (fn) => ctx.history.batch(fn) },\n toolOptions: ctx.toolOptions,\n fonts: [...ctx.fonts.value],\n // Read through, so a new `signatures` store reaches the tool as well as the menus.\n signatureLibrary: () => ctx.signatures.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n // A tool that switches itself (a one-shot tool once used) is reported as a pick.\n const followTool = (id: ToolId): void => {\n if (id !== ctx.tool.value) ctx.setTool(id)\n }\n stops = [\n vp.zoom.subscribe(reportZoom),\n vp.currentPage.subscribe(reportPage),\n tc.active.subscribe(followTool),\n ]\n // Whatever the build restored is reported once; nothing is when it matched.\n reportZoom(vp.zoom.get())\n reportPage(vp.currentPage.get())\n },\n onPageMount: (page, mount, host) => {\n pages.value = [...pages.value, { build, page, host, mount, error: null, custom }]\n },\n onPageUnmount: (page) => {\n pages.value = pages.value.filter((p) => p.page !== page)\n },\n onPageError: (page, err) => {\n pages.value = pages.value.map((p) => (p.page === page ? { ...p, error: err } : p))\n },\n })\n}\n\nonMounted(() => {\n ctx.viewportEl.value = scroll.value\n watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\n\n// A new decorateAnnotation re-applies to the mounted annotation elements at once.\nwatch(\n () => ctx.decorateAnnotation.value,\n () => engine.value?.redecorate()\n)\nwatch(\n () => ctx.zoomModel.value,\n (z: ZoomValue | undefined) => {\n const vp = engine.value?.viewport\n if (vp && z !== undefined && z !== vp.zoom.get()) vp.setZoom(z)\n }\n)\nwatch(\n () => ctx.pageModel.value,\n (p) => {\n const vp = engine.value?.viewport\n if (!vp || p === undefined || p === lastReportedPage) return\n if (p !== vp.currentPage.get()) vp.scrollToPage(p)\n }\n)\nwatch(\n () => ctx.tool.value,\n (t) => {\n const tc = engine.value?.tools\n if (tc && tc.active.get() !== t) tc.set(t)\n }\n)\nwatch(\n () => props.mode,\n (m) => engine.value?.viewport.setMode(m)\n)\nwatch(\n () => props.rotation,\n (r) => engine.value?.viewport.setRotation(r)\n)\n// Gap and buffer are construction options: rebuild for the same document, keeping zoom and page.\n// The slots are already updated when this runs, so it carries the annotation slot too: a slot\n// toggle in the same tick is then recorded here and `onBeforeUpdate` finds nothing left to do.\nwatch([() => props.gap, () => props.buffer], ([gap, buffer]) =>\n rebuild({ gap, buffer, customAnnotations: !!slots.annotation })\n)\n\n// Slots are not reactive, so a change to whether the annotation slot is given is caught here.\n// `onBeforeUpdate` runs after the new slots are in place and before this render: the rebuild\n// swaps `pages` for the new build's pages synchronously, so the render that follows never pairs\n// the annotation slot with an overlay built without it (or the reverse). The rebuild keeps the\n// scroll position.\nonBeforeUpdate(() => {\n const next = !!slots.annotation\n if (engine.value && next !== custom) rebuild({ customAnnotations: next })\n})\n\nonBeforeUnmount(() => {\n teardown()\n if (ctx.viewportEl.value === scroll.value) ctx.viewportEl.value = null\n})\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"InkViewport.js","names":["_sfc_main","InkViewport_vue_vue_type_script_setup_true_lang_default","InkViewport_default"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ToolId,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n ...(ctx.hostTools.value ? { tools: ctx.hostTools.value } : {}),\n // The engine adds the plugins' tools and layers, and decorates through the host, which\n // reads `decorateAnnotation` first.\n ...(ctx.pluginHost.value ? { plugins: ctx.pluginHost.value } : {}),\n // The engine draws the search matches on the pages.\n ...(ctx.search.value ? { search: ctx.search.value } : {}),\n // Read through, so the watch below can re-apply a new function without a rebuild.\n decorateAnnotation: (a) => ctx.decorateAnnotation.value?.(a),\n ...(ctx.toolStyle.value ? { toolStyle: ctx.toolStyle.value } : {}),\n toolHistory: { batch: (fn) => ctx.history.batch(fn) },\n toolOptions: ctx.toolOptions,\n fonts: [...ctx.fonts.value],\n // Read through, so a new `signatures` store reaches the tool as well as the menus.\n signatureLibrary: () => ctx.signatures.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n // A tool that switches itself (a one-shot tool once used) is reported as a pick.\n const followTool = (id: ToolId): void => {\n if (id !== ctx.tool.value) ctx.setTool(id)\n }\n stops = [\n vp.zoom.subscribe(reportZoom),\n vp.currentPage.subscribe(reportPage),\n tc.active.subscribe(followTool),\n ]\n // Whatever the build restored is reported once; nothing is when it matched.\n reportZoom(vp.zoom.get())\n reportPage(vp.currentPage.get())\n },\n onPageMount: (page, mount, host) => {\n pages.value = [...pages.value, { build, page, host, mount, error: null, custom }]\n },\n onPageUnmount: (page) => {\n pages.value = pages.value.filter((p) => p.page !== page)\n },\n onPageError: (page, err) => {\n pages.value = pages.value.map((p) => (p.page === page ? { ...p, error: err } : p))\n },\n })\n}\n\nonMounted(() => {\n ctx.viewportEl.value = scroll.value\n watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\n\n// A new decorateAnnotation re-applies to the mounted annotation elements at once.\nwatch(\n () => ctx.decorateAnnotation.value,\n () => engine.value?.redecorate()\n)\nwatch(\n () => ctx.zoomModel.value,\n (z: ZoomValue | undefined) => {\n const vp = engine.value?.viewport\n if (vp && z !== undefined && z !== vp.zoom.get()) vp.setZoom(z)\n }\n)\nwatch(\n () => ctx.pageModel.value,\n (p) => {\n const vp = engine.value?.viewport\n if (!vp || p === undefined || p === lastReportedPage) return\n if (p !== vp.currentPage.get()) vp.scrollToPage(p)\n }\n)\nwatch(\n () => ctx.tool.value,\n (t) => {\n const tc = engine.value?.tools\n if (tc && tc.active.get() !== t) tc.set(t)\n }\n)\nwatch(\n () => props.mode,\n (m) => engine.value?.viewport.setMode(m)\n)\nwatch(\n () => props.rotation,\n (r) => engine.value?.viewport.setRotation(r)\n)\n// Gap and buffer are construction options: rebuild for the same document, keeping zoom and page.\n// The slots are already updated when this runs, so it carries the annotation slot too: a slot\n// toggle in the same tick is then recorded here and `onBeforeUpdate` finds nothing left to do.\nwatch([() => props.gap, () => props.buffer], ([gap, buffer]) =>\n rebuild({ gap, buffer, customAnnotations: !!slots.annotation })\n)\n\n// Slots are not reactive, so a change to whether the annotation slot is given is caught here.\n// `onBeforeUpdate` runs after the new slots are in place and before this render: the rebuild\n// swaps `pages` for the new build's pages synchronously, so the render that follows never pairs\n// the annotation slot with an overlay built without it (or the reverse). The rebuild keeps the\n// scroll position.\nonBeforeUpdate(() => {\n const next = !!slots.annotation\n if (engine.value && next !== custom) rebuild({ customAnnotations: next })\n})\n\nonBeforeUnmount(() => {\n teardown()\n if (ctx.viewportEl.value === scroll.value) ctx.viewportEl.value = null\n})\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkViewport.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkViewport.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"InkViewport.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkViewport.vue"],"names":[],"mappings":"AA4UA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EACV,UAAU,EAIV,YAAY,EAEb,MAAM,kBAAkB,CAAA;AAGzB,KAAK,WAAW,GAAG;IACf,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC;AAMJ,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,IAAI,OAAO,CAAA;IACnB,KAAK,CAAC,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAA;IAC3C,KAAK,CAAC,IAAI,OAAO,CAAA;IACjB,UAAU,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAA;IAChD,wFAAwF;IACxF,YAAY,CAAC,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAA;CACjE,CAAC;AAsUF,QAAA,MAAM,UAAU;;;;;6EAGd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -50,6 +50,7 @@ var T = ["data-state"], E = {
|
|
|
50
50
|
tool: M.tool.value,
|
|
51
51
|
...M.hostTools.value ? { tools: M.hostTools.value } : {},
|
|
52
52
|
...M.pluginHost.value ? { plugins: M.pluginHost.value } : {},
|
|
53
|
+
...M.search.value ? { search: M.search.value } : {},
|
|
53
54
|
decorateAnnotation: (e) => M.decorateAnnotation.value?.(e),
|
|
54
55
|
...M.toolStyle.value ? { toolStyle: M.toolStyle.value } : {},
|
|
55
56
|
toolHistory: { batch: (e) => M.history.batch(e) },
|