@inkbar/vue 0.8.0 → 0.10.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.
Files changed (144) hide show
  1. package/README.md +70 -4
  2. package/dist/components/InkDownloadButton.js +7 -0
  3. package/dist/components/InkDownloadButton.js.map +1 -0
  4. package/dist/components/InkDownloadButton.vue.d.ts +21 -0
  5. package/dist/components/InkDownloadButton.vue.d.ts.map +1 -0
  6. package/dist/components/InkDownloadButton.vue_vue_type_script_setup_true_lang.js +42 -0
  7. package/dist/components/InkDownloadButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  8. package/dist/components/InkFindBar.js.map +1 -1
  9. package/dist/components/InkFindBar.vue.d.ts.map +1 -1
  10. package/dist/components/InkFindBar.vue_vue_type_script_setup_true_lang.js +48 -48
  11. package/dist/components/InkFindBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/InkHighlightMenu.js.map +1 -1
  13. package/dist/components/InkHighlightMenu.vue.d.ts.map +1 -1
  14. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js +67 -65
  15. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  16. package/dist/components/InkPanel.js +7 -0
  17. package/dist/components/InkPanel.js.map +1 -0
  18. package/dist/components/InkPanel.vue.d.ts +21 -0
  19. package/dist/components/InkPanel.vue.d.ts.map +1 -0
  20. package/dist/components/InkPanel.vue_vue_type_script_setup_true_lang.js +48 -0
  21. package/dist/components/InkPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  22. package/dist/components/InkPrintButton.js +7 -0
  23. package/dist/components/InkPrintButton.js.map +1 -0
  24. package/dist/components/InkPrintButton.vue.d.ts +19 -0
  25. package/dist/components/InkPrintButton.vue.d.ts.map +1 -0
  26. package/dist/components/InkPrintButton.vue_vue_type_script_setup_true_lang.js +39 -0
  27. package/dist/components/InkPrintButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  28. package/dist/components/InkRecordList.js +7 -0
  29. package/dist/components/InkRecordList.js.map +1 -0
  30. package/dist/components/InkRecordList.vue.d.ts +35 -0
  31. package/dist/components/InkRecordList.vue.d.ts.map +1 -0
  32. package/dist/components/InkRecordList.vue_vue_type_script_setup_true_lang.js +41 -0
  33. package/dist/components/InkRecordList.vue_vue_type_script_setup_true_lang.js.map +1 -0
  34. package/dist/components/InkRoot.js.map +1 -1
  35. package/dist/components/InkRoot.vue.d.ts +48 -4
  36. package/dist/components/InkRoot.vue.d.ts.map +1 -1
  37. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +177 -164
  38. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  39. package/dist/components/InkSearchResults.js +7 -0
  40. package/dist/components/InkSearchResults.js.map +1 -0
  41. package/dist/components/InkSearchResults.vue.d.ts +9 -0
  42. package/dist/components/InkSearchResults.vue.d.ts.map +1 -0
  43. package/dist/components/InkSearchResults.vue_vue_type_script_setup_true_lang.js +52 -0
  44. package/dist/components/InkSearchResults.vue_vue_type_script_setup_true_lang.js.map +1 -0
  45. package/dist/components/InkShapeMenu.js.map +1 -1
  46. package/dist/components/InkShapeMenu.vue.d.ts.map +1 -1
  47. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js +58 -56
  48. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/InkSidebar.js +7 -0
  50. package/dist/components/InkSidebar.js.map +1 -0
  51. package/dist/components/InkSidebar.vue.d.ts +34 -0
  52. package/dist/components/InkSidebar.vue.d.ts.map +1 -0
  53. package/dist/components/InkSidebar.vue_vue_type_script_setup_true_lang.js +95 -0
  54. package/dist/components/InkSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/InkSignatureDialog.js.map +1 -1
  56. package/dist/components/InkSignatureDialog.vue.d.ts +3 -2
  57. package/dist/components/InkSignatureDialog.vue.d.ts.map +1 -1
  58. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/InkSignatureMenu.js.map +1 -1
  60. package/dist/components/InkSignatureMenu.vue.d.ts.map +1 -1
  61. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js +77 -75
  62. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/InkThumbnail.js +7 -0
  64. package/dist/components/InkThumbnail.js.map +1 -0
  65. package/dist/components/InkThumbnail.vue.d.ts +18 -0
  66. package/dist/components/InkThumbnail.vue.d.ts.map +1 -0
  67. package/dist/components/InkThumbnail.vue_vue_type_script_setup_true_lang.js +49 -0
  68. package/dist/components/InkThumbnail.vue_vue_type_script_setup_true_lang.js.map +1 -0
  69. package/dist/components/InkThumbnails.js +7 -0
  70. package/dist/components/InkThumbnails.js.map +1 -0
  71. package/dist/components/InkThumbnails.vue.d.ts +27 -0
  72. package/dist/components/InkThumbnails.vue.d.ts.map +1 -0
  73. package/dist/components/InkThumbnails.vue_vue_type_script_setup_true_lang.js +107 -0
  74. package/dist/components/InkThumbnails.vue_vue_type_script_setup_true_lang.js.map +1 -0
  75. package/dist/components/InkToolButton.js.map +1 -1
  76. package/dist/components/InkToolButton.vue.d.ts.map +1 -1
  77. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js +39 -36
  78. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  79. package/dist/components/InkToolbarButton.js +7 -0
  80. package/dist/components/InkToolbarButton.js.map +1 -0
  81. package/dist/components/InkToolbarButton.vue.d.ts +22 -0
  82. package/dist/components/InkToolbarButton.vue.d.ts.map +1 -0
  83. package/dist/components/InkToolbarButton.vue_vue_type_script_setup_true_lang.js +32 -0
  84. package/dist/components/InkToolbarButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  85. package/dist/components/InkViewport.js.map +1 -1
  86. package/dist/components/InkViewport.vue.d.ts.map +1 -1
  87. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +37 -36
  88. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  89. package/dist/components/InkZoomSelect.js.map +1 -1
  90. package/dist/components/InkZoomSelect.vue.d.ts.map +1 -1
  91. package/dist/components/InkZoomSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  92. package/dist/components/InkZoomSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  93. package/dist/components/RecordCards.js +7 -0
  94. package/dist/components/RecordCards.js.map +1 -0
  95. package/dist/components/RecordCards.vue.d.ts +25 -0
  96. package/dist/components/RecordCards.vue.d.ts.map +1 -0
  97. package/dist/components/RecordCards.vue_vue_type_script_setup_true_lang.js +120 -0
  98. package/dist/components/RecordCards.vue_vue_type_script_setup_true_lang.js.map +1 -0
  99. package/dist/components/SidebarTrigger.js +7 -0
  100. package/dist/components/SidebarTrigger.js.map +1 -0
  101. package/dist/components/SidebarTrigger.vue.d.ts +9 -0
  102. package/dist/components/SidebarTrigger.vue.d.ts.map +1 -0
  103. package/dist/components/SidebarTrigger.vue_vue_type_script_setup_true_lang.js +33 -0
  104. package/dist/components/SidebarTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
  105. package/dist/components/SignatureForm.js.map +1 -1
  106. package/dist/components/SignatureForm.vue.d.ts.map +1 -1
  107. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js +56 -55
  108. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/sidebar-context.d.ts +21 -0
  110. package/dist/components/sidebar-context.d.ts.map +1 -0
  111. package/dist/components/sidebar-context.js +7 -0
  112. package/dist/components/sidebar-context.js.map +1 -0
  113. package/dist/composables/useAnnotations.d.ts +91 -0
  114. package/dist/composables/useAnnotations.d.ts.map +1 -1
  115. package/dist/composables/useRecordSelection.d.ts +12 -0
  116. package/dist/composables/useRecordSelection.d.ts.map +1 -0
  117. package/dist/composables/useRecordSelection.js +15 -0
  118. package/dist/composables/useRecordSelection.js.map +1 -0
  119. package/dist/composables/useRecords.d.ts +14 -0
  120. package/dist/composables/useRecords.d.ts.map +1 -0
  121. package/dist/composables/useRecords.js +16 -0
  122. package/dist/composables/useRecords.js.map +1 -0
  123. package/dist/composables/useRegisteredTool.d.ts +21 -0
  124. package/dist/composables/useRegisteredTool.d.ts.map +1 -0
  125. package/dist/composables/useRegisteredTool.js +25 -0
  126. package/dist/composables/useRegisteredTool.js.map +1 -0
  127. package/dist/composables/useSearch.d.ts.map +1 -1
  128. package/dist/composables/useSearch.js +1 -0
  129. package/dist/composables/useSearch.js.map +1 -1
  130. package/dist/composables/useToolOptions.d.ts +8 -0
  131. package/dist/composables/useToolOptions.d.ts.map +1 -1
  132. package/dist/composables/useToolOptions.js +10 -5
  133. package/dist/composables/useToolOptions.js.map +1 -1
  134. package/dist/context.d.ts +5 -0
  135. package/dist/context.d.ts.map +1 -1
  136. package/dist/context.js.map +1 -1
  137. package/dist/index.d.ts +12 -0
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/index.js +40 -29
  140. package/dist/to-readable.d.ts +7 -0
  141. package/dist/to-readable.d.ts.map +1 -0
  142. package/dist/to-readable.js +11 -0
  143. package/dist/to-readable.js.map +1 -0
  144. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"InkToolButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkToolButton.vue"],"names":[],"mappings":"AAkGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAgB9C,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAkFnF,QAAA,IAAI,OAAO;;;CAAW,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"}
1
+ {"version":3,"file":"InkToolButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkToolButton.vue"],"names":[],"mappings":"AAgGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAW9C,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAyGnF,QAAA,IAAI,OAAO;;;CAAW,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"}
@@ -1,12 +1,14 @@
1
1
  import { useInkContext as e } from "../context.js";
2
- import { useTool as t } from "../composables/useTool.js";
3
- import n from "./InkIcon.js";
4
- import { computed as r, createBlock as i, createCommentVNode as a, defineComponent as o, mergeProps as s, openBlock as c, renderSlot as l, unref as u, withCtx as d } from "vue";
5
- import { TOOL_LABELS as f } from "@inkbar/core/dom";
6
- import { ToolbarButton as p } from "reka-ui";
7
- import { Highlighter as m, MessageSquare as h, PenLine as g, PenTool as _, Signature as v, Square as y, SquareDashedMousePointer as b, TextCursor as x, Type as S } from "@inkbar/icons";
2
+ import { useRegisteredTool as t } from "../composables/useRegisteredTool.js";
3
+ import { useTool as n } from "../composables/useTool.js";
4
+ import r from "./InkIcon.js";
5
+ import { computed as i, createBlock as a, createCommentVNode as o, defineComponent as s, mergeProps as c, openBlock as l, renderSlot as u, unref as d, useAttrs as f, withCtx as p } from "vue";
6
+ import { TOOL_LABELS as m, withHostTools as h } from "@inkbar/core/dom";
7
+ import { ToolbarButton as g } from "reka-ui";
8
+ import { SquareDashedMousePointer as _, TextCursor as v } from "@inkbar/icons";
8
9
  //#region src/components/InkToolButton.vue?vue&type=script&setup=true&lang.ts
9
- var C = /*@__PURE__*/ o({
10
+ var y = /*@__PURE__*/ s({
11
+ inheritAttrs: !1,
10
12
  __name: "InkToolButton",
11
13
  props: {
12
14
  tool: {},
@@ -16,37 +18,38 @@ var C = /*@__PURE__*/ o({
16
18
  default: !1
17
19
  }
18
20
  },
19
- setup(o) {
20
- let C = {
21
- "select-text": x,
22
- select: b,
23
- highlight: m,
24
- "redact-area": y,
25
- sketch: _,
26
- draw: g,
27
- note: h,
28
- freetext: S,
29
- signature: v
30
- }, w = o, T = e("InkToolButton"), { tool: E, setTool: D } = t(), O = r(() => E.value === w.tool), k = r(() => [...T.hostTools.value ?? [], ...T.pluginHost.value?.tools ?? []].find((e) => e.id === w.tool)), A = r(() => w.label ?? f[w.tool] ?? k.value?.label ?? w.tool), j = r(() => C[w.tool] ?? k.value?.icon), M = r(() => ({
31
- "aria-pressed": String(O.value),
32
- "aria-label": A.value,
33
- title: A.value,
34
- onClick: () => D(w.tool)
35
- }));
36
- return (e, t) => (c(), i(u(p), s({
37
- "as-child": o.asChild,
21
+ setup(s) {
22
+ let y = {
23
+ "select-text": v,
24
+ select: _
25
+ }, b = s, x = e("InkToolButton"), { tool: S, setTool: C } = n(), w = i(() => S.value === b.tool), T = t(() => b.tool), E = i(() => h([...x.hostTools.value ?? [], ...x.pluginHost.value?.tools ?? []]).find((e) => e.id === b.tool)), D = i(() => b.label ?? m[b.tool] ?? E.value?.label ?? b.tool), O = i(() => y[b.tool] ?? E.value?.icon), k = f(), A = () => T.value ? c({
26
+ "aria-pressed": String(w.value),
27
+ "aria-label": D.value,
28
+ title: D.value,
29
+ onClick: () => C(b.tool)
30
+ }, k) : {
31
+ ...k,
32
+ "aria-hidden": "true",
33
+ disabled: !0,
34
+ "aria-pressed": void 0,
35
+ "aria-label": void 0,
36
+ title: void 0,
37
+ onClick: void 0
38
+ };
39
+ return (e, t) => (l(), a(d(g), c({
40
+ "as-child": s.asChild,
38
41
  class: "ink-tool-button",
39
42
  "data-ink-tool-button": "",
40
- "data-tool": o.tool,
41
- "data-state": O.value ? "on" : "off"
42
- }, M.value), {
43
- default: d(() => [l(e.$slots, "default", {
44
- active: O.value,
45
- label: A.value
46
- }, () => [j.value ? (c(), i(n, {
43
+ "data-tool": s.tool,
44
+ "data-state": w.value ? "on" : "off"
45
+ }, A()), {
46
+ default: p(() => [d(T) ? u(e.$slots, "default", {
47
+ active: w.value,
48
+ label: D.value
49
+ }, () => [O.value ? (l(), a(r, {
47
50
  key: 0,
48
- icon: j.value
49
- }, null, 8, ["icon"])) : a("", !0)])]),
51
+ icon: O.value
52
+ }, null, 8, ["icon"])) : o("", !0)], void 0, 0) : o("", !0)]),
50
53
  _: 3
51
54
  }, 16, [
52
55
  "as-child",
@@ -56,6 +59,6 @@ var C = /*@__PURE__*/ o({
56
59
  }
57
60
  });
58
61
  //#endregion
59
- export { C as default };
62
+ export { y as default };
60
63
 
61
64
  //# sourceMappingURL=InkToolButton.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InkToolButton.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_mergeProps","_withCtx","_renderSlot","InkIcon","_createCommentVNode","InkIcon_default","InkToolButton_vue_vue_type_script_setup_true_lang_default","ICONS","TextCursor","SquareDashedMousePointer","Highlighter","Square","PenTool","PenLine","MessageSquare","Type","Signature","props","__props","ctx","useInkContext","current","useTool","active","computed","own","t","name","TOOL_LABELS","icon","attrs","setTool","openBlock","createBlock","unref","ToolbarButton","mergeProps","withCtx","renderSlot","_ctx","createCommentVNode"],"sources":["../../src/components/InkToolButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TOOL_LABELS } from '@inkbar/core/dom'\nimport {\n Highlighter,\n MessageSquare,\n PenLine,\n PenTool,\n Signature,\n Square,\n SquareDashedMousePointer,\n TextCursor,\n Type,\n} from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed } from 'vue'\n\nimport { useTool } from '../composables/useTool'\nimport { useInkContext } from '../context'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ToolId } from '@inkbar/core/dom'\nimport type { IconNode } from '@inkbar/icons'\n\nconst ICONS: Readonly<Partial<Record<ToolId, IconNode>>> = {\n 'select-text': TextCursor,\n select: SquareDashedMousePointer,\n highlight: Highlighter,\n 'redact-area': Square,\n sketch: PenTool,\n draw: PenLine,\n note: MessageSquare,\n freetext: Type,\n signature: Signature,\n}\n\nconst props = withDefaults(\n defineProps<{ tool: ToolId; label?: string | undefined; asChild?: boolean }>(),\n { label: undefined, asChild: false }\n)\n\nconst ctx = useInkContext('InkToolButton')\nconst { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\n/** A host or plugin tool by this id, for the name and icon core has none for. */\nconst own = computed(() =>\n [...(ctx.hostTools.value ?? []), ...(ctx.pluginHost.value?.tools ?? [])].find(\n (t) => t.id === props.tool\n )\n)\n// `label` and the slot win; then core's name and icon; then the tool's own.\nconst name = computed(\n () => props.label ?? TOOL_LABELS[props.tool] ?? own.value?.label ?? props.tool\n)\nconst icon = computed(() => ICONS[props.tool] ?? own.value?.icon)\n// Reka's typed props stop at its own; ARIA and listeners go through a bound object.\nconst attrs = computed(() => ({\n 'aria-pressed': String(active.value),\n 'aria-label': name.value,\n title: name.value,\n onClick: () => setTool(props.tool),\n}))\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n class=\"ink-tool-button\"\n data-ink-tool-button\n :data-tool=\"tool\"\n :data-state=\"active ? 'on' : 'off'\"\n v-bind=\"attrs\"\n >\n <slot :active=\"active\" :label=\"name\"><InkIcon v-if=\"icon\" :icon=\"icon\" /></slot>\n </ToolbarButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAwBA,IAAMU,IAAqD;GACzD,eAAeC;GACf,QAAQC;GACR,WAAWC;GACX,eAAeC;GACf,QAAQC;GACR,MAAMC;GACN,MAAMC;GACN,UAAUC;GACV,WAAWC;EACb,GAEMC,IAAQC,GAKRC,IAAMC,EAAc,eAAe,GACnC,EAAE,MAAMC,GAAS,eAAYC,EAAQ,GACrCC,IAASC,QAAeH,EAAQ,UAAUJ,EAAM,IAAI,GAEpDQ,IAAMD,QACV,CAAC,GAAIL,EAAI,UAAU,SAAS,CAAC,GAAI,GAAIA,EAAI,WAAW,OAAO,SAAS,CAAC,CAAE,CAAC,CAAC,MACtE,MAAMO,EAAE,OAAOT,EAAM,IACxB,CACF,GAEMU,IAAOH,QACLP,EAAM,SAASW,EAAYX,EAAM,SAASQ,EAAI,OAAO,SAASR,EAAM,IAC5E,GACMY,IAAOL,QAAejB,EAAMU,EAAM,SAASQ,EAAI,OAAO,IAAI,GAE1DK,IAAQN,SAAgB;GAC5B,gBAAgB,OAAOD,EAAO,KAAK;GACnC,cAAcI,EAAK;GACnB,OAAOA,EAAK;GACZ,eAAeI,EAAQd,EAAM,IAAI;EACnC,EAAE;oBAIApB,EAAA,GAAAC,EASgBC,EAAAoC,CAAA,GAThBnC,EASgB;GARb,YAAUkB,EAAA;GACX,OAAM;GACN,wBAAA;GACC,aAAWA,EAAA;GACX,cAAYK,EAAA,QAAM,OAAA;EACX,GAAAO,EAAA,KAAK,GAAA;GAEb,SAAA7B,QAAgF,CAAhFC,EAAgFqC,EAAA,QAAA,WAAA;IAAzE,QAAQhB,EAAA;IAAS,OAAOI,EAAA;GAA/B,SAAgF,CAA5BE,EAAA,SAAfhC,EAAA,GAAAC,EAAoCK,GAAA;;IAAd,MAAM0B,EAAA"}
1
+ {"version":3,"file":"InkToolButton.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_mergeProps","_withCtx","_renderSlot","InkIcon","_createCommentVNode","InkIcon_default","InkToolButton_vue_vue_type_script_setup_true_lang_default","ICONS","TextCursor","SquareDashedMousePointer","props","__props","ctx","useInkContext","current","useTool","active","computed","registered","useRegisteredTool","own","withHostTools","t","name","TOOL_LABELS","icon","hostAttrs","useAttrs","bound","mergeProps","setTool","openBlock","createBlock","unref","ToolbarButton","withCtx","renderSlot","_ctx","createCommentVNode"],"sources":["../../src/components/InkToolButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TOOL_LABELS, withHostTools } from '@inkbar/core/dom'\nimport { SquareDashedMousePointer, TextCursor } from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed, mergeProps, useAttrs } from 'vue'\n\nimport { useRegisteredTool } from '../composables/useRegisteredTool'\nimport { useTool } from '../composables/useTool'\nimport { useInkContext } from '../context'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ToolId } from '@inkbar/core/dom'\nimport type { IconNode } from '@inkbar/icons'\n\nconst ICONS: Readonly<Partial<Record<ToolId, IconNode>>> = {\n 'select-text': TextCursor,\n select: SquareDashedMousePointer,\n}\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{ tool: ToolId; label?: string | undefined; asChild?: boolean }>(),\n { label: undefined, asChild: false }\n)\n\nconst ctx = useInkContext('InkToolButton')\nconst { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\nconst registered = useRegisteredTool(() => props.tool)\n/** The registered tool by this id, for the name and icon core has none for. */\nconst own = computed(() =>\n withHostTools([\n ...(ctx.hostTools.value ?? []),\n ...(ctx.pluginHost.value?.tools ?? []),\n ]).find((t) => t.id === props.tool)\n)\n// `label` and the slot win; then core's name and icon; then the tool's own.\nconst name = computed(\n () => props.label ?? TOOL_LABELS[props.tool] ?? own.value?.label ?? props.tool\n)\nconst icon = computed(() => ICONS[props.tool] ?? own.value?.icon)\n// Reka's typed props stop at its own; ARIA and listeners go through a bound object. A tool\n// nobody registered leaves the button disabled, hidden from assistive tech and unnamed.\nconst hostAttrs = useAttrs()\n// A function, not a computed: `useAttrs()` is not reactive, so the render reads it afresh.\nconst bound = () =>\n registered.value\n ? mergeProps(\n {\n 'aria-pressed': String(active.value),\n 'aria-label': name.value,\n title: name.value,\n onClick: () => setTool(props.tool),\n },\n hostAttrs\n )\n : {\n ...hostAttrs,\n 'aria-hidden': 'true' as const,\n disabled: true,\n 'aria-pressed': undefined,\n 'aria-label': undefined,\n title: undefined,\n onClick: undefined,\n }\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n class=\"ink-tool-button\"\n data-ink-tool-button\n :data-tool=\"tool\"\n :data-state=\"active ? 'on' : 'off'\"\n v-bind=\"bound()\"\n >\n <template v-if=\"registered\">\n <slot :active=\"active\" :label=\"name\"><InkIcon v-if=\"icon\" :icon=\"icon\" /></slot>\n </template>\n </ToolbarButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAeA,IAAMU,IAAqD;GACzD,eAAeC;GACf,QAAQC;EACV,GAIMC,IAAQC,GAKRC,IAAMC,EAAc,eAAe,GACnC,EAAE,MAAMC,GAAS,eAAYC,EAAQ,GACrCC,IAASC,QAAeH,EAAQ,UAAUJ,EAAM,IAAI,GACpDQ,IAAaC,QAAwBT,EAAM,IAAI,GAE/CU,IAAMH,QACVI,EAAc,CACZ,GAAIT,EAAI,UAAU,SAAS,CAAC,GAC5B,GAAIA,EAAI,WAAW,OAAO,SAAS,CAAC,CACtC,CAAC,CAAC,CAAC,MAAM,MAAMU,EAAE,OAAOZ,EAAM,IAAI,CACpC,GAEMa,IAAON,QACLP,EAAM,SAASc,EAAYd,EAAM,SAASU,EAAI,OAAO,SAASV,EAAM,IAC5E,GACMe,IAAOR,QAAeV,EAAMG,EAAM,SAASU,EAAI,OAAO,IAAI,GAG1DM,IAAYC,EAAS,GAErBC,UACJV,EAAW,QACPW,EACE;GACE,gBAAgB,OAAOb,EAAO,KAAK;GACnC,cAAcO,EAAK;GACnB,OAAOA,EAAK;GACZ,eAAeO,EAAQpB,EAAM,IAAI;EACnC,GACAgB,CACF,IACA;GACE,GAAGA;GACH,eAAe;GACf,UAAU;GACV,gBAAgB,KAAA;GAChB,cAAc,KAAA;GACd,OAAO,KAAA;GACP,SAAS,KAAA;EACX;oBAIJ7B,EAAA,GAAAC,EAWgBC,EAAAmC,CAAA,GAXhBlC,EAWgB;GAVb,YAAUW,EAAA;GACX,OAAM;GACN,wBAAA;GACC,aAAWA,EAAA;GACX,cAAYK,EAAA,QAAM,OAAA;EACX,GAAAY,EAAK,CAAA,GAAA;GAEb,SAAA3B,QAEW,CAFKF,EAAAmB,CAAA,IACdhB,EAAgFmC,EAAA,QAAA,WAAA;IAAzE,QAAQrB,EAAA;IAAS,OAAOO,EAAA;GAA/B,SAAgF,CAA5BE,EAAA,SAAf5B,EAAA,GAAAC,EAAoCK,GAAA;;IAAd,MAAMsB,EAAA"}
@@ -0,0 +1,7 @@
1
+ import e from "./InkToolbarButton.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkToolbarButton.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkToolbarButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkToolbarButton.js","names":["_sfc_main","InkToolbarButton_vue_vue_type_script_setup_true_lang_default","InkToolbarButton_default"],"sources":["../../src/components/InkToolbarButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Your own button in an `InkToolbar`. It joins the toolbar's arrow-key focus and takes the\n * theme's toolbar button styles; what it shows and does is up to you. Button attributes and\n * listeners, such as `aria-label` and `@click`, pass through to the button.\n */\nimport { ToolbarButton } from 'reka-ui'\n\nimport type { ButtonHTMLAttributes } from 'vue'\n\ninterface InkToolbarButtonProps extends /* @vue-ignore */ ButtonHTMLAttributes {\n asChild?: boolean\n disabled?: boolean\n}\n\nwithDefaults(defineProps<InkToolbarButtonProps>(), { asChild: false, disabled: false })\n// Reka's typed props stop at its own; plain attributes go through a bound object.\nconst attrs = { type: 'button' }\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n :disabled=\"disabled\"\n class=\"ink-toolbar-button\"\n data-ink-toolbar-button\n v-bind=\"attrs\"\n >\n <slot />\n </ToolbarButton>\n</template>\n"],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { ButtonHTMLAttributes } from 'vue';
2
+ interface InkToolbarButtonProps extends /* @vue-ignore */ ButtonHTMLAttributes {
3
+ asChild?: boolean;
4
+ disabled?: boolean;
5
+ }
6
+ declare var __VLS_7: {};
7
+ type __VLS_Slots = {} & {
8
+ default?: (props: typeof __VLS_7) => any;
9
+ };
10
+ declare const __VLS_base: import('vue').DefineComponent<InkToolbarButtonProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<InkToolbarButtonProps> & Readonly<{}>, {
11
+ asChild: boolean;
12
+ disabled: boolean;
13
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
14
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
17
+ type __VLS_WithSlots<T, S> = T & {
18
+ new (): {
19
+ $slots: S;
20
+ };
21
+ };
22
+ //# sourceMappingURL=InkToolbarButton.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkToolbarButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkToolbarButton.vue"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,KAAK,CAAA;AAG/C,UAAU,qBAAsB,SAAQ,iBAAiB,CAAC,oBAAoB;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AA2CD,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,32 @@
1
+ import { createBlock as e, defineComponent as t, mergeProps as n, openBlock as r, renderSlot as i, unref as a, withCtx as o } from "vue";
2
+ import { ToolbarButton as s } from "reka-ui";
3
+ //#region src/components/InkToolbarButton.vue?vue&type=script&setup=true&lang.ts
4
+ var c = /*@__PURE__*/ t({
5
+ __name: "InkToolbarButton",
6
+ props: {
7
+ asChild: {
8
+ type: Boolean,
9
+ default: !1
10
+ },
11
+ disabled: {
12
+ type: Boolean,
13
+ default: !1
14
+ }
15
+ },
16
+ setup(t) {
17
+ let c = { type: "button" };
18
+ return (l, u) => (r(), e(a(s), n({
19
+ "as-child": t.asChild,
20
+ disabled: t.disabled,
21
+ class: "ink-toolbar-button",
22
+ "data-ink-toolbar-button": ""
23
+ }, c), {
24
+ default: o(() => [i(l.$slots, "default")]),
25
+ _: 3
26
+ }, 16, ["as-child", "disabled"]));
27
+ }
28
+ });
29
+ //#endregion
30
+ export { c as default };
31
+
32
+ //# sourceMappingURL=InkToolbarButton.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkToolbarButton.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_mergeProps","_withCtx","_renderSlot","InkToolbarButton_vue_vue_type_script_setup_true_lang_default","attrs","openBlock","createBlock","unref","ToolbarButton","mergeProps","__props","withCtx","renderSlot","_ctx"],"sources":["../../src/components/InkToolbarButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Your own button in an `InkToolbar`. It joins the toolbar's arrow-key focus and takes the\n * theme's toolbar button styles; what it shows and does is up to you. Button attributes and\n * listeners, such as `aria-label` and `@click`, pass through to the button.\n */\nimport { ToolbarButton } from 'reka-ui'\n\nimport type { ButtonHTMLAttributes } from 'vue'\n\ninterface InkToolbarButtonProps extends /* @vue-ignore */ ButtonHTMLAttributes {\n asChild?: boolean\n disabled?: boolean\n}\n\nwithDefaults(defineProps<InkToolbarButtonProps>(), { asChild: false, disabled: false })\n// Reka's typed props stop at its own; plain attributes go through a bound object.\nconst attrs = { type: 'button' }\n</script>\n\n<template>\n <ToolbarButton\n :as-child=\"asChild\"\n :disabled=\"disabled\"\n class=\"ink-toolbar-button\"\n data-ink-toolbar-button\n v-bind=\"attrs\"\n >\n <slot />\n </ToolbarButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;EAiBA,IAAMO,IAAQ,EAAE,MAAM,SAAS;oBAI7BP,EAAA,GAAAC,EAQgBC,EAAAS,CAAA,GARhBR,EAQgB;GAPb,YAAUU,EAAA;GACV,UAAUA,EAAA;GACX,OAAM;GACN,2BAAA;EACQ,GAAAN,CAAK,GAAA;GAEb,SAAAH,QAAQ,CAARC,EAAQW,EAAA,QAAA,SAAA,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 *\n * Form fields render in the engine's form layer. A signature field's \"Sign\" opens\n * `InkSignFieldPopover`, and a form script's alert shows in `InkFormAlert`; both are mounted\n * here, so hosts compose nothing for them.\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 InkFormAlert from './InkFormAlert.vue'\nimport InkPage from './InkPage.vue'\nimport InkSignFieldPopover from './InkSignFieldPopover.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkDocument, InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n SignFieldRequest,\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/** A key per document, so the field menu and its dialog start afresh for each one. */\nconst documentKeys = new WeakMap<InkDocument, number>()\nlet documentKeyCount = 0\nfunction documentKey(doc: InkDocument | null): number {\n if (!doc) return 0\n let key = documentKeys.get(doc)\n if (key === undefined) {\n key = ++documentKeyCount\n documentKeys.set(doc, key)\n }\n return key\n}\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/** The signature field whose menu is open. */\nconst signRequest = shallowRef<SignFieldRequest | null>(null)\n/** The form script's message on show, and how many have been shown. */\nconst alertMessage = shallowRef<string | null>(null)\nconst alertsShown = shallowRef(0)\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 // Their fields and the document they came from are gone.\n signRequest.value = null\n alertMessage.value = null\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 ...(ctx.formHighlight.value === undefined\n ? {}\n : { formHighlight: ctx.formHighlight.value }),\n // The field's own button again, while its menu is open, closes the menu.\n onSignField: (req) => {\n signRequest.value = signRequest.value?.widget === req.widget ? null : req\n },\n onFormAction: (a) => ctx.reportFormAction(a),\n onFormAlert: (message) => {\n alertMessage.value = message\n alertsShown.value += 1\n },\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)\n// The tint follows `formHighlight` in place, without a new document.\nwatch(\n () => ctx.formHighlight.value,\n (on) => engine.value?.setFormHighlight(on ?? true)\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 <!-- Keyed by document, so the menu and its dialog start afresh for each one. -->\n <InkSignFieldPopover\n :key=\"documentKey(ctx.document.value)\"\n :request=\"signRequest\"\n @close=\"signRequest = null\"\n />\n <InkFormAlert\n :message=\"alertMessage\"\n :shown=\"alertsShown\"\n :fallback=\"scroll\"\n @close=\"alertMessage = null\"\n />\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 *\n * Form fields render in the engine's form layer. A signature field's \"Sign\" opens\n * `InkSignFieldPopover`, and a form script's alert shows in `InkFormAlert`; both are mounted\n * here, so hosts compose nothing for them.\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 { toolIdsOf } from '../composables/useRegisteredTool'\nimport { injectInkContext } from '../context'\n\nimport InkFormAlert from './InkFormAlert.vue'\nimport InkPage from './InkPage.vue'\nimport InkSignFieldPopover from './InkSignFieldPopover.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkDocument, InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n SignFieldRequest,\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/** A key per document, so the field menu and its dialog start afresh for each one. */\nconst documentKeys = new WeakMap<InkDocument, number>()\nlet documentKeyCount = 0\nfunction documentKey(doc: InkDocument | null): number {\n if (!doc) return 0\n let key = documentKeys.get(doc)\n if (key === undefined) {\n key = ++documentKeyCount\n documentKeys.set(doc, key)\n }\n return key\n}\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/** The signature field whose menu is open. */\nconst signRequest = shallowRef<SignFieldRequest | null>(null)\n/** The form script's message on show, and how many have been shown. */\nconst alertMessage = shallowRef<string | null>(null)\nconst alertsShown = shallowRef(0)\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 ctx.openedToolIds.value = null\n pages.value = []\n // Their fields and the document they came from are gone.\n signRequest.value = null\n alertMessage.value = null\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 // The tools this viewer registers, from the same inputs; a later `tools` waits for a rebuild.\n ctx.openedToolIds.value = toolIdsOf(ctx.hostTools.value, ctx.pluginHost.value)\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 ...(ctx.formHighlight.value === undefined\n ? {}\n : { formHighlight: ctx.formHighlight.value }),\n // The field's own button again, while its menu is open, closes the menu.\n onSignField: (req) => {\n signRequest.value = signRequest.value?.widget === req.widget ? null : req\n },\n onFormAction: (a) => ctx.reportFormAction(a),\n onFormAlert: (message) => {\n alertMessage.value = message\n alertsShown.value += 1\n },\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)\n// The tint follows `formHighlight` in place, without a new document.\nwatch(\n () => ctx.formHighlight.value,\n (on) => engine.value?.setFormHighlight(on ?? true)\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 <!-- Keyed by document, so the menu and its dialog start afresh for each one. -->\n <InkSignFieldPopover\n :key=\"documentKey(ctx.document.value)\"\n :request=\"signRequest\"\n @close=\"signRequest = null\"\n />\n <InkFormAlert\n :message=\"alertMessage\"\n :shown=\"alertsShown\"\n :fallback=\"scroll\"\n @close=\"alertMessage = null\"\n />\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"InkViewport.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkViewport.vue"],"names":[],"mappings":"AA2YA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,KAAK,EACV,UAAU,EAKV,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;AAqaF,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"}
1
+ {"version":3,"file":"InkViewport.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkViewport.vue"],"names":[],"mappings":"AAgZA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,KAAK,EACV,UAAU,EAKV,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;AAwaF,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"}
@@ -1,8 +1,9 @@
1
1
  import { injectInkContext as e } from "../context.js";
2
- import t from "./InkFormAlert.js";
3
- import n from "./InkPage.js";
4
- import r from "./InkSignFieldPopover.js";
5
- import { Fragment as i, computed as a, createBlock as o, createCommentVNode as ee, createElementBlock as s, createElementVNode as c, createSlots as l, createTextVNode as u, createVNode as d, defineComponent as f, mergeProps as p, onBeforeUnmount as m, onBeforeUpdate as h, onMounted as g, openBlock as _, renderList as v, renderSlot as y, shallowRef as b, toDisplayString as x, unref as S, useSlots as C, useTemplateRef as w, watch as T, withCtx as E } from "vue";
2
+ import { toolIdsOf as t } from "../composables/useRegisteredTool.js";
3
+ import n from "./InkFormAlert.js";
4
+ import r from "./InkPage.js";
5
+ import i from "./InkSignFieldPopover.js";
6
+ import { Fragment as a, computed as o, createBlock as s, createCommentVNode as ee, createElementBlock as c, createElementVNode as l, createSlots as u, createTextVNode as d, createVNode as f, defineComponent as p, mergeProps as m, onBeforeUnmount as h, onBeforeUpdate as g, onMounted as _, openBlock as v, renderList as y, renderSlot as b, shallowRef as x, toDisplayString as S, unref as C, useSlots as w, useTemplateRef as te, watch as T, withCtx as E } from "vue";
6
7
  import { mountViewer as D } from "@inkbar/core/dom";
7
8
  //#region src/components/InkViewport.vue?vue&type=script&setup=true&lang.ts
8
9
  var O = ["data-state"], k = {
@@ -17,7 +18,7 @@ var O = ["data-state"], k = {
17
18
  }, j = ["title"], M = {
18
19
  key: 2,
19
20
  class: "ink-status ink-empty"
20
- }, N = /*@__PURE__*/ f({
21
+ }, N = /*@__PURE__*/ p({
21
22
  __name: "InkViewport",
22
23
  props: {
23
24
  mode: { default: "continuous" },
@@ -25,29 +26,29 @@ var O = ["data-state"], k = {
25
26
  gap: { default: 16 },
26
27
  buffer: { default: 2 }
27
28
  },
28
- setup(f) {
29
- let N = f, P = C(), F = e(), I = w("scroll"), L = /* @__PURE__ */ new WeakMap(), R = 0;
29
+ setup(p) {
30
+ let N = p, P = w(), F = e(), I = te("scroll"), L = /* @__PURE__ */ new WeakMap(), R = 0;
30
31
  function z(e) {
31
32
  if (!e) return 0;
32
33
  let t = L.get(e);
33
34
  return t === void 0 && (t = ++R, L.set(e, t)), t;
34
35
  }
35
- let B = b([]), V = a(() => F.status.value.state), H = a(() => F.status.value.state === "error" ? F.status.value.error : null), U = b(null), W = b(null), G = b(null), K = b(0), q = 0, J = !1, Y = [], X, Z;
36
+ let B = x([]), V = o(() => F.status.value.state), H = o(() => F.status.value.state === "error" ? F.status.value.error : null), U = x(null), W = x(null), G = x(null), K = x(0), q = 0, J = !1, Y = [], X, Z;
36
37
  function Q() {
37
38
  for (let e of Y) e();
38
- Y = [], U.value?.destroy(), U.value = null, F.viewport.value && (F.viewport.value = null), F.tools.value && (F.tools.value = null), B.value = [], W.value = null, G.value = null;
39
+ Y = [], U.value?.destroy(), U.value = null, F.viewport.value && (F.viewport.value = null), F.tools.value && (F.tools.value = null), F.openedToolIds.value = null, B.value = [], W.value = null, G.value = null;
39
40
  }
40
41
  function $(e) {
41
42
  let t = U.value;
42
43
  t && (q += 1, e.customAnnotations !== void 0 && (J = e.customAnnotations), t.rebuild(e));
43
44
  }
44
- function te() {
45
+ function ne() {
45
46
  Q(), X = void 0, Z = void 0;
46
- let e = F.document.value, t = I.value;
47
- if (!e || !t || F.status.value.state !== "ready") return;
48
- let n = !0;
49
- q += 1, J = !!P.annotation, U.value = D({
50
- container: t,
47
+ let e = F.document.value, n = I.value;
48
+ if (!e || !n || F.status.value.state !== "ready") return;
49
+ let r = !0;
50
+ q += 1, J = !!P.annotation, F.openedToolIds.value = t(F.hostTools.value, F.pluginHost.value), U.value = D({
51
+ container: n,
51
52
  document: e,
52
53
  zoom: F.zoomModel.value ?? "fit-width",
53
54
  ...F.pageModel.value === void 0 ? {} : { page: F.pageModel.value },
@@ -76,20 +77,20 @@ var O = ["data-state"], k = {
76
77
  },
77
78
  onActivate: (e) => F.setActivated(e),
78
79
  onBuild: (e, t) => {
79
- F.viewport.value = e, F.tools.value = t, n && (n = !1, X = e.zoom.get(), Z = 0);
80
+ F.viewport.value = e, F.tools.value = t, r && (r = !1, X = e.zoom.get(), Z = 0);
80
81
  for (let e of Y) e();
81
- let r = (e) => {
82
+ let n = (e) => {
82
83
  e !== X && (X = e, F.reportZoom(e));
83
84
  }, i = (e) => {
84
85
  e !== Z && (Z = e, F.reportPage(e));
85
86
  };
86
87
  Y = [
87
- e.zoom.subscribe(r),
88
+ e.zoom.subscribe(n),
88
89
  e.currentPage.subscribe(i),
89
90
  t.active.subscribe((e) => {
90
91
  e !== F.tool.value && F.setTool(e);
91
92
  })
92
- ], r(e.zoom.get()), i(e.currentPage.get());
93
+ ], n(e.zoom.get()), i(e.currentPage.get());
93
94
  },
94
95
  onPageMount: (e, t, n) => {
95
96
  B.value = [...B.value, {
@@ -112,8 +113,8 @@ var O = ["data-state"], k = {
112
113
  }
113
114
  });
114
115
  }
115
- return g(() => {
116
- F.viewportEl.value = I.value, T([() => F.document.value, () => F.status.value.state], te, { immediate: !0 });
116
+ return _(() => {
117
+ F.viewportEl.value = I.value, T([() => F.document.value, () => F.status.value.state], ne, { immediate: !0 });
117
118
  }), T(() => F.decorateAnnotation.value, () => U.value?.redecorate()), T(() => F.formHighlight.value, (e) => U.value?.setFormHighlight(e ?? !0)), T(() => F.zoomModel.value, (e) => {
118
119
  let t = U.value?.viewport;
119
120
  t && e !== void 0 && e !== t.zoom.get() && t.setZoom(e);
@@ -127,21 +128,21 @@ var O = ["data-state"], k = {
127
128
  gap: e,
128
129
  buffer: t,
129
130
  customAnnotations: !!P.annotation
130
- })), h(() => {
131
+ })), g(() => {
131
132
  let e = !!P.annotation;
132
133
  U.value && e !== J && $({ customAnnotations: e });
133
- }), m(() => {
134
+ }), h(() => {
134
135
  Q(), F.viewportEl.value === I.value && (F.viewportEl.value = null);
135
- }), (e, a) => (_(), s("div", {
136
+ }), (e, t) => (v(), c("div", {
136
137
  class: "ink-viewport-root",
137
138
  "data-ink-viewport-root": "",
138
139
  "data-state": V.value
139
140
  }, [
140
- V.value === "loading" ? (_(), s("div", k, [y(e.$slots, "loading", {}, () => [a[2] ||= u("Loading document…", -1)])])) : H.value ? (_(), s("div", A, [y(e.$slots, "error", { error: H.value }, () => [a[3] ||= c("p", { class: "ink-error-title" }, "This document could not be opened.", -1), c("p", null, [c("code", {
141
+ V.value === "loading" ? (v(), c("div", k, [b(e.$slots, "loading", {}, () => [t[2] ||= d("Loading document…", -1)])])) : H.value ? (v(), c("div", A, [b(e.$slots, "error", { error: H.value }, () => [t[3] ||= l("p", { class: "ink-error-title" }, "This document could not be opened.", -1), l("p", null, [l("code", {
141
142
  class: "ink-error-code",
142
143
  title: H.value.message
143
- }, x(H.value.code), 9, j)])])])) : V.value === "idle" ? (_(), s("div", M, [y(e.$slots, "empty")])) : ee("", !0),
144
- c("div", {
144
+ }, S(H.value.code), 9, j)])])])) : V.value === "idle" ? (v(), c("div", M, [b(e.$slots, "empty")])) : ee("", !0),
145
+ l("div", {
145
146
  ref_key: "scroll",
146
147
  ref: I,
147
148
  class: "ink-scroll",
@@ -150,20 +151,20 @@ var O = ["data-state"], k = {
150
151
  role: "document",
151
152
  "aria-label": "Document"
152
153
  }, null, 512),
153
- (_(!0), s(i, null, v(B.value, (t) => (_(), o(n, {
154
+ (v(!0), c(a, null, y(B.value, (t) => (v(), s(r, {
154
155
  key: `${t.build}:${t.page}`,
155
156
  page: t.page,
156
157
  host: t.host,
157
158
  mount: t.mount,
158
159
  error: t.error,
159
160
  "custom-annotations": t.custom
160
- }, l({ _: 2 }, [P.annotation ? {
161
+ }, u({ _: 2 }, [P.annotation ? {
161
162
  name: "annotation",
162
- fn: E((t) => [y(e.$slots, "annotation", p({ ref_for: !0 }, t))]),
163
+ fn: E((t) => [b(e.$slots, "annotation", m({ ref_for: !0 }, t))]),
163
164
  key: "0"
164
165
  } : void 0, P["page-error"] ? {
165
166
  name: "page-error",
166
- fn: E((t) => [y(e.$slots, "page-error", p({ ref_for: !0 }, t))]),
167
+ fn: E((t) => [b(e.$slots, "page-error", m({ ref_for: !0 }, t))]),
167
168
  key: "1"
168
169
  } : void 0]), 1032, [
169
170
  "page",
@@ -172,16 +173,16 @@ var O = ["data-state"], k = {
172
173
  "error",
173
174
  "custom-annotations"
174
175
  ]))), 128)),
175
- (_(), o(r, {
176
- key: z(S(F).document.value),
176
+ (v(), s(i, {
177
+ key: z(C(F).document.value),
177
178
  request: W.value,
178
- onClose: a[0] ||= (e) => W.value = null
179
+ onClose: t[0] ||= (e) => W.value = null
179
180
  }, null, 8, ["request"])),
180
- d(t, {
181
+ f(n, {
181
182
  message: G.value,
182
183
  shown: K.value,
183
184
  fallback: I.value,
184
- onClose: a[1] ||= (e) => G.value = null
185
+ onClose: t[1] ||= (e) => G.value = null
185
186
  }, null, 8, [
186
187
  "message",
187
188
  "shown",
@@ -1 +1 @@
1
- {"version":3,"file":"InkViewport.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createElementBlock","_renderSlot","_createTextVNode","_createElementVNode","_toDisplayString","_createCommentVNode","_Fragment","_renderList","_createBlock","InkPage","_createSlots","_withCtx","_mergeProps","InkSignFieldPopover","_unref","_createVNode","InkFormAlert","InkFormAlert_default","InkPage_default","InkSignFieldPopover_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","InkViewport_vue_vue_type_script_setup_true_lang_default","props","__props","slots","useSlots","ctx","injectInkContext","scroll","useTemplateRef","documentKeys","documentKeyCount","documentKey","doc","key","pages","shallowRef","state","computed","error","engine","signRequest","alertMessage","alertsShown","build","custom","stops","lastReportedZoom","lastReportedPage","teardown","stop","rebuild","e","opts","setup","el","first","mountViewer","a","fn","req","message","id","vp","tc","reportZoom","z","reportPage","p","page","err","onMounted","watch","on","t","m","r","gap","buffer","onBeforeUpdate","next","onBeforeUnmount","openBlock","createElementBlock","renderSlot","_ctx","_cache","createTextVNode","createElementVNode","toDisplayString","createCommentVNode","Fragment","renderList","createBlock","createSlots","withCtx","mergeProps","slotProps","unref","createVNode"],"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 *\n * Form fields render in the engine's form layer. A signature field's \"Sign\" opens\n * `InkSignFieldPopover`, and a form script's alert shows in `InkFormAlert`; both are mounted\n * here, so hosts compose nothing for them.\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 InkFormAlert from './InkFormAlert.vue'\nimport InkPage from './InkPage.vue'\nimport InkSignFieldPopover from './InkSignFieldPopover.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkDocument, InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n SignFieldRequest,\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/** A key per document, so the field menu and its dialog start afresh for each one. */\nconst documentKeys = new WeakMap<InkDocument, number>()\nlet documentKeyCount = 0\nfunction documentKey(doc: InkDocument | null): number {\n if (!doc) return 0\n let key = documentKeys.get(doc)\n if (key === undefined) {\n key = ++documentKeyCount\n documentKeys.set(doc, key)\n }\n return key\n}\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/** The signature field whose menu is open. */\nconst signRequest = shallowRef<SignFieldRequest | null>(null)\n/** The form script's message on show, and how many have been shown. */\nconst alertMessage = shallowRef<string | null>(null)\nconst alertsShown = shallowRef(0)\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 // Their fields and the document they came from are gone.\n signRequest.value = null\n alertMessage.value = null\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 ...(ctx.formHighlight.value === undefined\n ? {}\n : { formHighlight: ctx.formHighlight.value }),\n // The field's own button again, while its menu is open, closes the menu.\n onSignField: (req) => {\n signRequest.value = signRequest.value?.widget === req.widget ? null : req\n },\n onFormAction: (a) => ctx.reportFormAction(a),\n onFormAlert: (message) => {\n alertMessage.value = message\n alertsShown.value += 1\n },\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)\n// The tint follows `formHighlight` in place, without a new document.\nwatch(\n () => ctx.formHighlight.value,\n (on) => engine.value?.setFormHighlight(on ?? true)\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 <!-- Keyed by document, so the menu and its dialog start afresh for each one. -->\n <InkSignFieldPopover\n :key=\"documentKey(ctx.document.value)\"\n :request=\"signRequest\"\n @close=\"signRequest = null\"\n />\n <InkFormAlert\n :message=\"alertMessage\"\n :shown=\"alertsShown\"\n :fallback=\"scroll\"\n @close=\"alertMessage = null\"\n />\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"InkViewport.vue_vue_type_script_setup_true_lang.js","names":["_useSlots","_openBlock","_createElementBlock","_renderSlot","_createTextVNode","_createElementVNode","_toDisplayString","_createCommentVNode","_Fragment","_renderList","_createBlock","InkPage","_createSlots","_withCtx","_mergeProps","InkSignFieldPopover","_unref","_createVNode","InkFormAlert","InkFormAlert_default","InkPage_default","InkSignFieldPopover_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","InkViewport_vue_vue_type_script_setup_true_lang_default","props","__props","slots","useSlots","ctx","injectInkContext","scroll","useTemplateRef","documentKeys","documentKeyCount","documentKey","doc","key","pages","shallowRef","state","computed","error","engine","signRequest","alertMessage","alertsShown","build","custom","stops","lastReportedZoom","lastReportedPage","teardown","stop","rebuild","e","opts","setup","el","first","toolIdsOf","mountViewer","a","fn","req","message","id","vp","tc","reportZoom","z","reportPage","p","page","err","onMounted","watch","on","t","m","r","gap","buffer","onBeforeUpdate","next","onBeforeUnmount","openBlock","createElementBlock","renderSlot","_ctx","_cache","createTextVNode","createElementVNode","toDisplayString","createCommentVNode","Fragment","renderList","createBlock","createSlots","withCtx","mergeProps","slotProps","unref","createVNode"],"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 *\n * Form fields render in the engine's form layer. A signature field's \"Sign\" opens\n * `InkSignFieldPopover`, and a form script's alert shows in `InkFormAlert`; both are mounted\n * here, so hosts compose nothing for them.\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 { toolIdsOf } from '../composables/useRegisteredTool'\nimport { injectInkContext } from '../context'\n\nimport InkFormAlert from './InkFormAlert.vue'\nimport InkPage from './InkPage.vue'\nimport InkSignFieldPopover from './InkSignFieldPopover.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkDocument, InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n SignFieldRequest,\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/** A key per document, so the field menu and its dialog start afresh for each one. */\nconst documentKeys = new WeakMap<InkDocument, number>()\nlet documentKeyCount = 0\nfunction documentKey(doc: InkDocument | null): number {\n if (!doc) return 0\n let key = documentKeys.get(doc)\n if (key === undefined) {\n key = ++documentKeyCount\n documentKeys.set(doc, key)\n }\n return key\n}\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/** The signature field whose menu is open. */\nconst signRequest = shallowRef<SignFieldRequest | null>(null)\n/** The form script's message on show, and how many have been shown. */\nconst alertMessage = shallowRef<string | null>(null)\nconst alertsShown = shallowRef(0)\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 ctx.openedToolIds.value = null\n pages.value = []\n // Their fields and the document they came from are gone.\n signRequest.value = null\n alertMessage.value = null\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 // The tools this viewer registers, from the same inputs; a later `tools` waits for a rebuild.\n ctx.openedToolIds.value = toolIdsOf(ctx.hostTools.value, ctx.pluginHost.value)\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 ...(ctx.formHighlight.value === undefined\n ? {}\n : { formHighlight: ctx.formHighlight.value }),\n // The field's own button again, while its menu is open, closes the menu.\n onSignField: (req) => {\n signRequest.value = signRequest.value?.widget === req.widget ? null : req\n },\n onFormAction: (a) => ctx.reportFormAction(a),\n onFormAlert: (message) => {\n alertMessage.value = message\n alertsShown.value += 1\n },\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)\n// The tint follows `formHighlight` in place, without a new document.\nwatch(\n () => ctx.formHighlight.value,\n (on) => engine.value?.setFormHighlight(on ?? true)\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 <!-- Keyed by document, so the menu and its dialog start afresh for each one. -->\n <InkSignFieldPopover\n :key=\"documentKey(ctx.document.value)\"\n :request=\"signRequest\"\n @close=\"signRequest = null\"\n />\n <InkFormAlert\n :message=\"alertMessage\"\n :shown=\"alertsShown\"\n :fallback=\"scroll\"\n @close=\"alertMessage = null\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"InkZoomSelect.js","names":["_sfc_main","InkZoomSelect_vue_vue_type_script_setup_true_lang_default","InkZoomSelect_default"],"sources":["../../src/components/InkZoomSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ZOOM_LEVELS } from '@inkbar/core/dom'\nimport { Check, ChevronDown } from '@inkbar/icons'\nimport {\n SelectContent,\n SelectIcon,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectPortal,\n SelectRoot,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n SelectViewport,\n} from 'reka-ui'\nimport { computed } from 'vue'\n\nimport { useZoom } from '../composables/useZoom'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ZoomValue } from '@inkbar/core/dom'\n\nconst CUSTOM = 'custom:'\n\nconst { zoom, scale, setZoom } = useZoom()\n\nconst level = (z: number) => ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\n/** A numeric zoom that is not one of the levels (zoom in and out multiply). */\nconst custom = computed(() =>\n typeof zoom.value === 'number' && level(zoom.value) === undefined ? zoom.value : null\n)\nconst value = computed(() => {\n const z = zoom.value\n if (typeof z !== 'number') return z\n return custom.value === null ? String(level(z)) : `${CUSTOM}${z}`\n})\n\nfunction onChange(v: unknown): void {\n if (typeof v !== 'string' || v === value.value) return\n const next: ZoomValue =\n v === 'fit-width' || v === 'fit-page' ? v : Number(v.replace(CUSTOM, ''))\n setZoom(next)\n}\n\nconst FITS = [\n { value: 'fit-width', label: 'Fit width' },\n { value: 'fit-page', label: 'Fit page' },\n]\n// Reka's typed props stop at its own; ARIA goes through a bound object.\nconst triggerAttrs = { 'aria-label': 'Zoom' }\nconst percent = (z: number) => `${Math.round(z * 100)}%`\n/** The levels, with a custom zoom in its place among them. */\nconst levels = computed(() => {\n const list = ZOOM_LEVELS.map((l) => ({ z: l, value: String(l), label: percent(l) }))\n const c = custom.value\n if (c !== null) list.push({ z: c, value: `${CUSTOM}${c}`, label: percent(scale.value) })\n return list.sort((a, b) => a.z - b.z)\n})\n</script>\n\n<template>\n <SelectRoot :model-value=\"value\" @update:model-value=\"onChange\">\n <SelectTrigger\n class=\"ink-zoom-select ink-select-trigger\"\n data-ink-zoom-select\n v-bind=\"triggerAttrs\"\n >\n <SelectValue class=\"ink-select-value\" />\n <SelectIcon class=\"ink-select-icon\">\n <InkIcon :icon=\"ChevronDown\" :size=\"16\" />\n </SelectIcon>\n </SelectTrigger>\n <SelectPortal>\n <SelectContent\n class=\"ink-select-content\"\n data-ink-select-content\n position=\"popper\"\n side=\"top\"\n :side-offset=\"4\"\n >\n <SelectViewport>\n <SelectItem\n v-for=\"o in FITS\"\n :key=\"o.value\"\n :value=\"o.value\"\n class=\"ink-select-item\"\n data-ink-select-item\n >\n <SelectItemText>{{ o.label }}</SelectItemText>\n <SelectItemIndicator class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </SelectItemIndicator>\n </SelectItem>\n <SelectSeparator class=\"ink-select-separator\" />\n <SelectItem\n v-for=\"o in levels\"\n :key=\"o.value\"\n :value=\"o.value\"\n class=\"ink-select-item\"\n data-ink-select-item\n >\n <SelectItemText>{{ o.label }}</SelectItemText>\n <SelectItemIndicator class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"InkZoomSelect.js","names":["_sfc_main","InkZoomSelect_vue_vue_type_script_setup_true_lang_default","InkZoomSelect_default"],"sources":["../../src/components/InkZoomSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ZOOM_LEVELS } from '@inkbar/core/dom'\nimport { Check, ChevronDown } from '@inkbar/icons'\nimport {\n SelectContent,\n SelectIcon,\n SelectItem,\n SelectItemIndicator,\n SelectItemText,\n SelectPortal,\n SelectRoot,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n SelectViewport,\n} from 'reka-ui'\nimport { computed } from 'vue'\n\nimport { useZoom } from '../composables/useZoom'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ZoomValue } from '@inkbar/core/dom'\n\nconst CUSTOM = 'custom:'\n\nconst { zoom, scale, setZoom } = useZoom()\n\nconst level = (z: number) => ZOOM_LEVELS.find((l) => Math.abs(l - z) < 0.001)\n/** A numeric zoom that is not one of the levels (zoom in and out multiply). */\nconst custom = computed(() =>\n typeof zoom.value === 'number' && level(zoom.value) === undefined ? zoom.value : null\n)\nconst value = computed(() => {\n const z = zoom.value\n if (typeof z !== 'number') return z\n return custom.value === null ? String(level(z)) : `${CUSTOM}${z}`\n})\n\nfunction onChange(v: unknown): void {\n if (typeof v !== 'string' || v === value.value) return\n const next: ZoomValue =\n v === 'fit-width' || v === 'fit-page' ? v : Number(v.replace(CUSTOM, ''))\n setZoom(next)\n}\n\nconst FITS = [\n { value: 'fit-width', label: 'Fit width' },\n { value: 'fit-page', label: 'Fit page' },\n]\n// Reka's typed props stop at its own; ARIA goes through a bound object.\nconst triggerAttrs = { 'aria-label': 'Zoom' }\nconst percent = (z: number) => `${Math.round(z * 100)}%`\n/** The levels, with a custom zoom in its place among them. */\nconst levels = computed(() => {\n const list = ZOOM_LEVELS.map((l) => ({ z: l, value: String(l), label: percent(l) }))\n const c = custom.value\n if (c !== null) list.push({ z: c, value: `${CUSTOM}${c}`, label: percent(scale.value) })\n return list.sort((a, b) => a.z - b.z)\n})\n</script>\n\n<template>\n <SelectRoot :model-value=\"value\" @update:model-value=\"onChange\">\n <SelectTrigger\n class=\"ink-select ink-select-trigger ink-zoom-select\"\n data-ink-zoom-select\n v-bind=\"triggerAttrs\"\n >\n <SelectValue class=\"ink-select-value\" />\n <SelectIcon class=\"ink-select-icon\">\n <InkIcon :icon=\"ChevronDown\" :size=\"16\" />\n </SelectIcon>\n </SelectTrigger>\n <SelectPortal>\n <SelectContent\n class=\"ink-select-content\"\n data-ink-select-content\n position=\"popper\"\n side=\"top\"\n :side-offset=\"4\"\n >\n <SelectViewport>\n <SelectItem\n v-for=\"o in FITS\"\n :key=\"o.value\"\n :value=\"o.value\"\n class=\"ink-select-item\"\n data-ink-select-item\n >\n <SelectItemText>{{ o.label }}</SelectItemText>\n <SelectItemIndicator class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </SelectItemIndicator>\n </SelectItem>\n <SelectSeparator class=\"ink-select-separator\" />\n <SelectItem\n v-for=\"o in levels\"\n :key=\"o.value\"\n :value=\"o.value\"\n class=\"ink-select-item\"\n data-ink-select-item\n >\n <SelectItemText>{{ o.label }}</SelectItemText>\n <SelectItemIndicator class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </SelectItemIndicator>\n </SelectItem>\n </SelectViewport>\n </SelectContent>\n </SelectPortal>\n </SelectRoot>\n</template>\n"],"mappings":""}