@inkbar/vue 0.3.0 → 0.4.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 (91) hide show
  1. package/README.md +16 -9
  2. package/dist/components/InkColorMenu.js +7 -0
  3. package/dist/components/InkColorMenu.js.map +1 -0
  4. package/dist/components/InkColorMenu.vue.d.ts +32 -0
  5. package/dist/components/InkColorMenu.vue.d.ts.map +1 -0
  6. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js +152 -0
  7. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  8. package/dist/components/InkHighlightMenu.js +7 -0
  9. package/dist/components/InkHighlightMenu.js.map +1 -0
  10. package/dist/components/InkHighlightMenu.vue.d.ts +17 -0
  11. package/dist/components/InkHighlightMenu.vue.d.ts.map +1 -0
  12. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js +140 -0
  13. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  14. package/dist/components/InkLineStyleMenu.js +7 -0
  15. package/dist/components/InkLineStyleMenu.js.map +1 -0
  16. package/dist/components/InkLineStyleMenu.vue.d.ts +14 -0
  17. package/dist/components/InkLineStyleMenu.vue.d.ts.map +1 -0
  18. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js +109 -0
  19. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  20. package/dist/components/InkRoot.js.map +1 -1
  21. package/dist/components/InkRoot.vue.d.ts +573 -29
  22. package/dist/components/InkRoot.vue.d.ts.map +1 -1
  23. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +117 -88
  24. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/InkShapeMenu.js +7 -0
  26. package/dist/components/InkShapeMenu.js.map +1 -0
  27. package/dist/components/InkShapeMenu.vue.d.ts +18 -0
  28. package/dist/components/InkShapeMenu.vue.d.ts.map +1 -0
  29. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js +118 -0
  30. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  31. package/dist/components/InkSignatureDialog.js +7 -0
  32. package/dist/components/InkSignatureDialog.js.map +1 -0
  33. package/dist/components/InkSignatureDialog.vue.d.ts +21 -0
  34. package/dist/components/InkSignatureDialog.vue.d.ts.map +1 -0
  35. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js +58 -0
  36. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/components/InkSignatureMenu.js +7 -0
  38. package/dist/components/InkSignatureMenu.js.map +1 -0
  39. package/dist/components/InkSignatureMenu.vue.d.ts +20 -0
  40. package/dist/components/InkSignatureMenu.vue.d.ts.map +1 -0
  41. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js +213 -0
  42. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  43. package/dist/components/InkTextStyleMenu.js +7 -0
  44. package/dist/components/InkTextStyleMenu.js.map +1 -0
  45. package/dist/components/InkTextStyleMenu.vue.d.ts +14 -0
  46. package/dist/components/InkTextStyleMenu.vue.d.ts.map +1 -0
  47. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js +200 -0
  48. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  49. package/dist/components/InkThreadPopover.js +7 -0
  50. package/dist/components/InkThreadPopover.js.map +1 -0
  51. package/dist/components/{InkNotePopover.vue.d.ts → InkThreadPopover.vue.d.ts} +4 -4
  52. package/dist/components/InkThreadPopover.vue.d.ts.map +1 -0
  53. package/dist/components/{InkNotePopover.vue_vue_type_script_setup_true_lang.js → InkThreadPopover.vue_vue_type_script_setup_true_lang.js} +44 -42
  54. package/dist/components/InkThreadPopover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/InkToolButton.js.map +1 -1
  56. package/dist/components/InkToolButton.vue.d.ts.map +1 -1
  57. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js +27 -20
  58. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/InkViewport.js.map +1 -1
  60. package/dist/components/InkViewport.vue.d.ts +1 -1
  61. package/dist/components/InkViewport.vue.d.ts.map +1 -1
  62. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +6 -0
  63. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/SignatureForm.js +7 -0
  65. package/dist/components/SignatureForm.js.map +1 -0
  66. package/dist/components/SignatureForm.vue.d.ts +14 -0
  67. package/dist/components/SignatureForm.vue.d.ts.map +1 -0
  68. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js +181 -0
  69. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js.map +1 -0
  70. package/dist/composables/useAnnotations.d.ts +1523 -131
  71. package/dist/composables/useAnnotations.d.ts.map +1 -1
  72. package/dist/composables/useAnnotations.js.map +1 -1
  73. package/dist/composables/useToolOptions.d.ts +11 -0
  74. package/dist/composables/useToolOptions.d.ts.map +1 -0
  75. package/dist/composables/useToolOptions.js +16 -0
  76. package/dist/composables/useToolOptions.js.map +1 -0
  77. package/dist/composables/useToolStyle.d.ts +32 -0
  78. package/dist/composables/useToolStyle.d.ts.map +1 -0
  79. package/dist/composables/useToolStyle.js +24 -0
  80. package/dist/composables/useToolStyle.js.map +1 -0
  81. package/dist/context.d.ts +14 -2
  82. package/dist/context.d.ts.map +1 -1
  83. package/dist/context.js.map +1 -1
  84. package/dist/index.d.ts +12 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +33 -24
  87. package/package.json +5 -5
  88. package/dist/components/InkNotePopover.js +0 -7
  89. package/dist/components/InkNotePopover.js.map +0 -1
  90. package/dist/components/InkNotePopover.vue.d.ts.map +0 -1
  91. package/dist/components/InkNotePopover.vue_vue_type_script_setup_true_lang.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_createVNode","_createElementVNode","_mergeProps","_renderSlot","InkIcon","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_toDisplayString","InkColorMenu","_withKeys","_withModifiers","InkIcon_default","InkColorMenu_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","InkTextStyleMenu_vue_vue_type_script_setup_true_lang_default","useInkContext","attrs","useAttrs","useToolStyle","open","ref","draft","model","computed","textStyleMenuModel","current","supported","fonts","sizeShown","TOGGLE_ICONS","Bold","Italic","Underline","ALIGN_ICONS","AlignLeft","AlignCenter","AlignRight","AlignJustify","enabled","onTriggerKeydown","commitSize","patch","set","nudge","direction","triggerAttrs","triggerBindings","mergeProps","menuAttrs","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","ToolbarButton","PopoverTrigger","createElementVNode","renderSlot","_ctx","ALargeSmall","PopoverPortal","PopoverContent","createElementBlock","createCommentVNode","Fragment","renderList","f","toDisplayString","Minus","withKeys","withModifiers","Plus","t","handleRadioKeys","c"],"sources":["../../src/components/InkTextStyleMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Font, size, text colour, bold, italic, underline and alignment for the selected text boxes or\n * the text tool. A popover panel rather than a menu list: it holds a select, a number input\n * with a stepper, toggle buttons and a radio group, each named and operable on its own. The\n * trigger carries `data-mixed` when the selection disagrees on any of them.\n */\nimport { handleRadioKeys, textStyleMenuModel } from '@inkbar/core/dom'\nimport {\n ALargeSmall,\n AlignCenter,\n AlignJustify,\n AlignLeft,\n AlignRight,\n Bold,\n Italic,\n Minus,\n Plus,\n Underline,\n} from '@inkbar/icons'\nimport {\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, mergeProps, ref, useAttrs, watch } from 'vue'\n\nimport { useToolStyle } from '../composables/useToolStyle'\nimport { useInkContext } from '../context'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\nconst { fonts } = useInkContext('InkTextStyleMenu')\n// The host's attributes go on the trigger: the root is a renderless popover.\ndefineOptions({ inheritAttrs: false })\nconst attrs = useAttrs()\n\nconst { current, supported, set } = useToolStyle()\nconst open = ref(false)\n/** The size as typed, until it is committed with Enter or blur. */\nconst draft = ref<string | null>(null)\n\nconst model = computed(() =>\n textStyleMenuModel(current.value, supported.value, fonts.value)\n)\nconst sizeShown = computed(\n () =>\n draft.value ?? (model.value.size.value === null ? '' : String(model.value.size.value))\n)\n\nconst TOGGLE_ICONS = { bold: Bold, italic: Italic, underline: Underline }\nconst ALIGN_ICONS = {\n left: AlignLeft,\n center: AlignCenter,\n right: AlignRight,\n justify: AlignJustify,\n}\n\n// The menu closes when the control disables (the selection cleared while it was open).\nwatch(\n () => model.value.enabled,\n (enabled) => {\n if (!enabled) open.value = false\n }\n)\n\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' || e.defaultPrevented || open.value || !model.value.enabled)\n return\n e.preventDefault()\n open.value = true\n}\n\nfunction commitSize(): void {\n if (draft.value === null) return\n if (draft.value.trim() !== '') {\n const patch = model.value.size.commit(Number(draft.value))\n if (patch) set(patch)\n }\n draft.value = null\n}\nfunction nudge(direction: 1 | -1): void {\n const patch = model.value.size.nudge(direction)\n if (patch) set(patch)\n draft.value = null\n}\n\n// Reka's typed props stop at its own; ARIA goes through bound objects.\nconst triggerAttrs = computed(() => ({\n 'aria-label': model.value.label,\n title: model.value.label,\n 'aria-haspopup': 'dialog' as const,\n onKeydown: onTriggerKeydown,\n 'data-mixed': model.value.mixed ? '' : undefined,\n}))\n/**\n * The trigger's bindings over the host's: both keydown listeners run, the host's first, and a\n * host `disabled` can disable the trigger but not enable it.\n */\nconst triggerBindings = computed(() =>\n mergeProps(attrs, triggerAttrs.value, {\n disabled: (attrs.disabled ?? false) !== false || !model.value.enabled,\n })\n)\nconst menuAttrs = computed(() => ({ 'aria-label': model.value.label }))\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <ToolbarButton as-child>\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n class=\"ink-menu-trigger ink-text-style-menu\"\n data-ink-text-style-menu\n :data-state=\"open ? 'open' : 'closed'\"\n v-bind=\"triggerBindings\"\n >\n <slot><InkIcon :icon=\"ALargeSmall\" /></slot>\n </button>\n </PopoverTrigger>\n </ToolbarButton>\n <PopoverPortal>\n <PopoverContent\n class=\"ink-select-content ink-menu-content ink-text-style-content\"\n data-ink-select-content\n data-ink-menu=\"text-style\"\n side=\"bottom\"\n align=\"start\"\n :side-offset=\"4\"\n :collision-padding=\"8\"\n v-bind=\"menuAttrs\"\n >\n <select\n class=\"ink-text-style-font\"\n :aria-label=\"model.font.label\"\n :value=\"model.font.value\"\n @change=\"set(model.font.patch(($event.target as HTMLSelectElement).value))\"\n >\n <option v-if=\"model.font.value === ''\" value=\"\" disabled hidden>Mixed</option>\n <option v-for=\"f in model.font.options\" :key=\"f\" :value=\"f\">{{ f }}</option>\n </select>\n <div class=\"ink-text-style-row\">\n <InkColorMenu property=\"textColor\" standalone />\n <div class=\"ink-text-style-size\" role=\"group\" aria-label=\"Size\">\n <button\n type=\"button\"\n class=\"ink-text-style-button\"\n aria-label=\"Decrease font size\"\n @click=\"nudge(-1)\"\n >\n <InkIcon :icon=\"Minus\" :size=\"16\" />\n </button>\n <input\n type=\"number\"\n class=\"ink-text-style-input\"\n :aria-label=\"model.size.label\"\n :min=\"model.size.min\"\n :max=\"model.size.max\"\n :step=\"model.size.step\"\n :value=\"sizeShown\"\n @input=\"draft = ($event.target as HTMLInputElement).value\"\n @blur=\"commitSize\"\n @keydown.enter.prevent=\"commitSize\"\n />\n <button\n type=\"button\"\n class=\"ink-text-style-button\"\n aria-label=\"Increase font size\"\n @click=\"nudge(1)\"\n >\n <InkIcon :icon=\"Plus\" :size=\"16\" />\n </button>\n </div>\n </div>\n <div class=\"ink-text-style-row\" role=\"group\" aria-label=\"Emphasis\">\n <button\n v-for=\"t in model.toggles\"\n :key=\"t.key\"\n type=\"button\"\n class=\"ink-text-style-button\"\n :aria-label=\"t.label\"\n :title=\"t.label\"\n :aria-pressed=\"t.pressed\"\n :data-state=\"t.pressed === true ? 'on' : 'off'\"\n :data-mixed=\"t.pressed === 'mixed' ? '' : undefined\"\n @click=\"set(t.patch)\"\n >\n <InkIcon :icon=\"TOGGLE_ICONS[t.key]\" :size=\"16\" />\n </button>\n </div>\n <div\n class=\"ink-text-style-row\"\n role=\"radiogroup\"\n :aria-label=\"model.align.label\"\n @keydown=\"handleRadioKeys($event, $event.currentTarget as HTMLElement)\"\n >\n <button\n v-for=\"c in model.align.choices\"\n :key=\"c.key\"\n type=\"button\"\n role=\"radio\"\n class=\"ink-text-style-button\"\n :aria-label=\"c.label\"\n :title=\"c.label\"\n :aria-checked=\"c.checked\"\n :tabindex=\"c.tabStop ? 0 : -1\"\n :data-state=\"c.checked ? 'on' : 'off'\"\n @click=\"set(c.patch)\"\n >\n <InkIcon :icon=\"ALIGN_ICONS[c.key]\" :size=\"16\" />\n </button>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import e from "./InkThreadPopover.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkThreadPopover.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkThreadPopover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkThreadPopover.js","names":["_sfc_main","InkThreadPopover_vue_vue_type_script_setup_true_lang_default","InkThreadPopover_default"],"sources":["../../src/components/InkThreadPopover.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The thread for the activated note or text markup, anchored to the root's overlay element.\n * Activating a reply opens the whole thread from its root. Closing (Close, Escape, a press\n * outside) clears `activated`.\n *\n * A new note, or a highlight, has no text. While its root is empty (and unlocked) the default\n * form writes the root's own `contents`, labelled \"Comment\", and the thread list stays hidden\n * until there is something in it; after that the form adds replies. Closing a note that is\n * still empty and has no replies removes it, so an abandoned note does not stay on the page.\n * Markup stays: the mark is the point.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '@inkbar/core'\nimport { threadDeleteLabel, threadPopoverLabel } from '@inkbar/core/dom'\nimport { PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\nimport { computed, ref, watch } from 'vue'\n\nimport { useAnnotations } from '../composables/useAnnotations'\nimport { injectInkContext } from '../context'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { Annotation, ThreadRoot } from '@inkbar/core'\nimport type { ThreadPopoverSlotProps } from '@inkbar/core/dom'\n\nexport type { ThreadPopoverSlotProps } from '@inkbar/core/dom'\n\ndefineSlots<{ default?(props: ThreadPopoverSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\nconst { annotations, add, update, remove } = useAnnotations()\n\nconst find = (id: string | undefined) =>\n id ? annotations.value.find((a) => a.id === id) : undefined\n\nconst note = computed<ThreadRoot | null>(() => {\n const a = find(ctx.activated.value ?? undefined)\n return a ? threadRoot(annotations.value, a) : null\n})\nconst anchor = useAnnotationElement(\n ctx,\n computed(() => note.value?.id ?? null)\n)\nconst focusReturn = useFocusReturn(ctx)\nconst open = computed(() => note.value !== null && anchor.value !== null)\nconst thread = computed<Annotation[]>(() =>\n note.value ? threadOf(annotations.value, note.value) : []\n)\n\n/** True while the default form writes the root's own text rather than a reply. */\nconst editingRoot = computed(() => {\n const root = note.value\n return root !== null && !root.locked && !root.contents?.trim()\n})\n\nconst draft = ref('')\nconst noteId = () => note.value?.id\n// Synchronous, so a render for another thread never shows the old draft.\nwatch(noteId, () => (draft.value = ''), { flush: 'sync' })\nwatch(noteId, (_next, previous) => {\n // Activation moved on from a note that never got any text: drop it.\n if (previous !== undefined) dropIfEmpty(previous)\n})\n\n/**\n * Roots this popover wrote text or a reply for. In controlled mode the write is a proposal\n * the host may not have applied yet, so the applied list still shows the note empty; these\n * are never dropped as abandoned.\n */\nconst written = new Set<string>()\n/** Notes this popover has already asked to remove, so a slow host is asked once. */\nconst dropped = new Set<string>()\n\n/** Removes an unlocked root note with no text and no replies. True when it did. */\nfunction dropIfEmpty(id: string): boolean {\n const a = find(id)\n if (!a || dropped.has(id) || written.has(id) || !isAbandonedNote(a, annotations.value))\n return false\n dropped.add(id)\n remove(id)\n return true\n}\n\nfunction reply(text: string): void {\n const root = note.value\n const contents = text.trim()\n if (!root || !contents) return\n written.add(root.id)\n add({ type: 'text', page: root.page, rect: root.rect, contents, inReplyTo: root.id })\n draft.value = ''\n}\nfunction close(): void {\n const root = note.value\n if (root && find(root.id) && isEmptyRoot(root)) {\n focusReturn.beforeRemove(anchor.value)\n dropIfEmpty(root.id)\n }\n ctx.setActivated(null)\n}\n/** A note that closing now would remove. */\nfunction isEmptyRoot(root: ThreadRoot): boolean {\n return !written.has(root.id) && isAbandonedNote(root, annotations.value)\n}\nfunction submit(): void {\n const text = draft.value.trim()\n if (!text) return\n if (editingRoot.value) {\n updateContents(text)\n draft.value = ''\n } else reply(text)\n}\n/** Locked roots cannot be removed: removing one does nothing and keeps the popover. */\nfunction removeThread(): void {\n const root = note.value\n if (!root || root.locked) return\n focusReturn.beforeRemove(anchor.value)\n // Under a slow controlled host the root stays listed for a while; it is not asked for again.\n dropped.add(root.id)\n remove(root.id)\n ctx.setActivated(null)\n}\nfunction updateContents(contents: string): void {\n if (!note.value || note.value.locked) return\n if (contents.trim()) written.add(note.value.id)\n update(note.value.id, { contents })\n}\nfunction onOpenChange(next: boolean): void {\n if (!next) close()\n}\n</script>\n\n<template>\n <PopoverRoot :open=\"open\" @update:open=\"onOpenChange\">\n <PopoverPortal>\n <PopoverContent\n v-if=\"note && anchor\"\n :reference=\"anchor\"\n class=\"ink-thread-popover\"\n data-ink-thread-popover\n side=\"right\"\n :side-offset=\"8\"\n :collision-padding=\"8\"\n v-bind=\"{ 'aria-label': threadPopoverLabel(note) }\"\n @interact-outside=\"keepOpenOnAnnotation\"\n @close-auto-focus=\"focusReturn.onCloseAutoFocus($event, anchor)\"\n >\n <slot\n :root=\"note\"\n :replies=\"thread.slice(1)\"\n :reply=\"reply\"\n :update=\"updateContents\"\n :remove=\"removeThread\"\n :close=\"close\"\n >\n <ol v-if=\"!editingRoot || thread.length > 1\" class=\"ink-thread\" data-ink-thread>\n <li\n v-for=\"item in thread\"\n :key=\"item.id\"\n class=\"ink-thread-item\"\n data-ink-thread-item\n :data-reply=\"item.inReplyTo ? '' : undefined\"\n >\n <span class=\"ink-thread-author\">{{ item.author ?? 'Anonymous' }}</span>\n <time class=\"ink-thread-time\" :datetime=\"item.createdAt\">\n {{ new Date(item.createdAt).toLocaleString() }}\n </time>\n <p class=\"ink-thread-text\">{{ item.contents }}</p>\n </li>\n </ol>\n <form class=\"ink-thread-reply\" data-ink-thread-reply @submit.prevent=\"submit\">\n <textarea\n v-model=\"draft\"\n :aria-label=\"editingRoot ? 'Comment' : 'Reply'\"\n rows=\"2\"\n :placeholder=\"editingRoot ? 'Comment' : 'Reply'\"\n />\n <div class=\"ink-thread-actions\">\n <button type=\"submit\" :disabled=\"!draft.trim()\">\n {{ editingRoot ? 'Comment' : 'Reply' }}\n </button>\n <button v-if=\"!note.locked\" type=\"button\" @click=\"removeThread\">\n {{ threadDeleteLabel(note) }}\n </button>\n <button type=\"button\" @click=\"close\">Close</button>\n </div>\n </form>\n </slot>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
@@ -1,7 +1,7 @@
1
- import { NotePopoverSlotProps } from '@inkbar/core/dom';
2
- export type { NotePopoverSlotProps } from '@inkbar/core/dom';
1
+ import { ThreadPopoverSlotProps } from '@inkbar/core/dom';
2
+ export type { ThreadPopoverSlotProps } from '@inkbar/core/dom';
3
3
  type __VLS_Slots = {
4
- default?(props: NotePopoverSlotProps): unknown;
4
+ default?(props: ThreadPopoverSlotProps): unknown;
5
5
  };
6
6
  declare const __VLS_base: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
7
7
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -12,4 +12,4 @@ type __VLS_WithSlots<T, S> = T & {
12
12
  $slots: S;
13
13
  };
14
14
  };
15
- //# sourceMappingURL=InkNotePopover.vue.d.ts.map
15
+ //# sourceMappingURL=InkThreadPopover.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkThreadPopover.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkThreadPopover.vue"],"names":[],"mappings":"AAyNA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAE9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AAG9D,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAA;CAAE,CAAC;AAyRxE,QAAA,MAAM,UAAU,+QACd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
@@ -2,30 +2,32 @@ import { injectInkContext as e } from "../context.js";
2
2
  import { useAnnotations as t } from "../composables/useAnnotations.js";
3
3
  import { useAnnotationElement as n } from "./annotation-element.js";
4
4
  import { keepOpenOnAnnotation as r, useFocusReturn as i } from "./popover-focus.js";
5
- import { Fragment as a, computed as o, createBlock as s, createCommentVNode as c, createElementBlock as l, createElementVNode as u, createVNode as d, defineComponent as f, mergeProps as p, openBlock as m, ref as h, renderList as g, renderSlot as _, toDisplayString as v, unref as y, vModelText as b, watch as x, withCtx as S, withDirectives as C, withModifiers as w } from "vue";
6
- import { isAbandonedNote as T, threadOf as E, threadRoot as ee } from "@inkbar/core";
7
- import { PopoverContent as te, PopoverPortal as ne, PopoverRoot as re } from "reka-ui";
8
- //#region src/components/InkNotePopover.vue?vue&type=script&setup=true&lang.ts
9
- var ie = {
5
+ import { Fragment as a, computed as o, createBlock as s, createCommentVNode as c, createElementBlock as l, createElementVNode as u, createVNode as ee, defineComponent as d, mergeProps as f, openBlock as p, ref as m, renderList as h, renderSlot as g, toDisplayString as _, unref as v, vModelText as y, watch as b, withCtx as x, withDirectives as te, withModifiers as S } from "vue";
6
+ import { isAbandonedNote as C, threadOf as w, threadRoot as ne } from "@inkbar/core";
7
+ import { threadDeleteLabel as re, threadPopoverLabel as ie } from "@inkbar/core/dom";
8
+ import { PopoverContent as ae, PopoverPortal as oe, PopoverRoot as se } from "reka-ui";
9
+ //#region src/components/InkThreadPopover.vue?vue&type=script&setup=true&lang.ts
10
+ var T = {
10
11
  key: 0,
11
12
  class: "ink-thread",
12
13
  "data-ink-thread": ""
13
- }, ae = ["data-reply"], D = { class: "ink-thread-author" }, O = ["datetime"], k = { class: "ink-thread-text" }, A = ["aria-label", "placeholder"], j = { class: "ink-thread-actions" }, M = ["disabled"], N = /*@__PURE__*/ f({
14
- __name: "InkNotePopover",
15
- setup(f) {
14
+ }, E = ["data-reply"], D = { class: "ink-thread-author" }, O = ["datetime"], k = { class: "ink-thread-text" }, A = ["aria-label", "placeholder"], j = { class: "ink-thread-actions" }, M = ["disabled"], N = /*@__PURE__*/ d({
15
+ __name: "InkThreadPopover",
16
+ setup(d) {
16
17
  let N = e(), { annotations: P, add: F, update: I, remove: L } = t(), R = (e) => e ? P.value.find((t) => t.id === e) : void 0, z = o(() => {
17
18
  let e = R(N.activated.value ?? void 0);
18
- return e?.type === "text" ? ee(P.value, e) : null;
19
- }), B = n(N, o(() => z.value?.id ?? null)), V = i(N), H = o(() => z.value !== null && B.value !== null), U = o(() => z.value ? E(P.value, z.value) : []), W = o(() => {
19
+ return e ? ne(P.value, e) : null;
20
+ }), B = n(N, o(() => z.value?.id ?? null)), V = i(N), H = o(() => z.value !== null && B.value !== null), U = o(() => z.value ? w(P.value, z.value) : []), W = o(() => {
20
21
  let e = z.value;
21
22
  return e !== null && !e.locked && !e.contents?.trim();
22
- }), G = h(""), K = () => z.value?.id;
23
- x(K, () => G.value = "", { flush: "sync" }), x(K, (e, t) => {
23
+ }), G = m(""), K = () => z.value?.id;
24
+ b(K, () => G.value = "", { flush: "sync" }), b(K, (e, t) => {
24
25
  t !== void 0 && Y(t);
25
26
  });
26
27
  let q = /* @__PURE__ */ new Set(), J = /* @__PURE__ */ new Set();
27
28
  function Y(e) {
28
- return J.has(e) || q.has(e) || !T(P.value, e) ? !1 : (J.add(e), L(e), !0);
29
+ let t = R(e);
30
+ return !t || J.has(e) || q.has(e) || !C(t, P.value) ? !1 : (J.add(e), L(e), !0);
29
31
  }
30
32
  function X(e) {
31
33
  let t = z.value, n = e.trim();
@@ -39,12 +41,12 @@ var ie = {
39
41
  }
40
42
  function Z() {
41
43
  let e = z.value;
42
- e && R(e.id) && oe(e) && (V.beforeRemove(B.value), Y(e.id)), N.setActivated(null);
44
+ e && R(e.id) && ce(e) && (V.beforeRemove(B.value), Y(e.id)), N.setActivated(null);
43
45
  }
44
- function oe(e) {
45
- return !q.has(e.id) && !e.locked && !e.contents?.trim() && U.value.length === 1;
46
+ function ce(e) {
47
+ return !q.has(e.id) && C(e, P.value);
46
48
  }
47
- function se() {
49
+ function le() {
48
50
  let e = G.value.trim();
49
51
  e && (W.value ? ($(e), G.value = "") : X(e));
50
52
  }
@@ -55,64 +57,64 @@ var ie = {
55
57
  function $(e) {
56
58
  z.value && !z.value.locked && (e.trim() && q.add(z.value.id), I(z.value.id, { contents: e }));
57
59
  }
58
- function ce(e) {
60
+ function ue(e) {
59
61
  e || Z();
60
62
  }
61
- return (e, t) => (m(), s(y(re), {
63
+ return (e, t) => (p(), s(v(se), {
62
64
  open: H.value,
63
- "onUpdate:open": ce
65
+ "onUpdate:open": ue
64
66
  }, {
65
- default: S(() => [d(y(ne), null, {
66
- default: S(() => [z.value && y(B) ? (m(), s(y(te), p({
67
+ default: x(() => [ee(v(oe), null, {
68
+ default: x(() => [z.value && v(B) ? (p(), s(v(ae), f({
67
69
  key: 0,
68
- reference: y(B),
69
- class: "ink-note-popover",
70
- "data-ink-note-popover": "",
70
+ reference: v(B),
71
+ class: "ink-thread-popover",
72
+ "data-ink-thread-popover": "",
71
73
  side: "right",
72
74
  "side-offset": 8,
73
75
  "collision-padding": 8
74
- }, { "aria-label": "Note thread" }, {
75
- onInteractOutside: y(r),
76
- onCloseAutoFocus: t[1] ||= (e) => y(V).onCloseAutoFocus(e, y(B))
76
+ }, { "aria-label": v(ie)(z.value) }, {
77
+ onInteractOutside: v(r),
78
+ onCloseAutoFocus: t[1] ||= (e) => v(V).onCloseAutoFocus(e, v(B))
77
79
  }), {
78
- default: S(() => [_(e.$slots, "default", {
79
- note: z.value,
80
+ default: x(() => [g(e.$slots, "default", {
81
+ root: z.value,
80
82
  replies: U.value.slice(1),
81
83
  reply: X,
82
84
  update: $,
83
85
  remove: Q,
84
86
  close: Z
85
- }, () => [!W.value || U.value.length > 1 ? (m(), l("ol", ie, [(m(!0), l(a, null, g(U.value, (e) => (m(), l("li", {
87
+ }, () => [!W.value || U.value.length > 1 ? (p(), l("ol", T, [(p(!0), l(a, null, h(U.value, (e) => (p(), l("li", {
86
88
  key: e.id,
87
89
  class: "ink-thread-item",
88
90
  "data-ink-thread-item": "",
89
91
  "data-reply": e.inReplyTo ? "" : void 0
90
92
  }, [
91
- u("span", D, v(e.author ?? "Anonymous"), 1),
93
+ u("span", D, _(e.author ?? "Anonymous"), 1),
92
94
  u("time", {
93
95
  class: "ink-thread-time",
94
96
  datetime: e.createdAt
95
- }, v(new Date(e.createdAt).toLocaleString()), 9, O),
96
- u("p", k, v(e.contents), 1)
97
- ], 8, ae))), 128))])) : c("", !0), u("form", {
97
+ }, _(new Date(e.createdAt).toLocaleString()), 9, O),
98
+ u("p", k, _(e.contents), 1)
99
+ ], 8, E))), 128))])) : c("", !0), u("form", {
98
100
  class: "ink-thread-reply",
99
101
  "data-ink-thread-reply": "",
100
- onSubmit: w(se, ["prevent"])
101
- }, [C(u("textarea", {
102
+ onSubmit: S(le, ["prevent"])
103
+ }, [te(u("textarea", {
102
104
  "onUpdate:modelValue": t[0] ||= (e) => G.value = e,
103
105
  "aria-label": W.value ? "Comment" : "Reply",
104
106
  rows: "2",
105
107
  placeholder: W.value ? "Comment" : "Reply"
106
- }, null, 8, A), [[b, G.value]]), u("div", j, [
108
+ }, null, 8, A), [[y, G.value]]), u("div", j, [
107
109
  u("button", {
108
110
  type: "submit",
109
111
  disabled: !G.value.trim()
110
- }, v(W.value ? "Comment" : "Reply"), 9, M),
111
- z.value.locked ? c("", !0) : (m(), l("button", {
112
+ }, _(W.value ? "Comment" : "Reply"), 9, M),
113
+ z.value.locked ? c("", !0) : (p(), l("button", {
112
114
  key: 0,
113
115
  type: "button",
114
116
  onClick: Q
115
- }, " Delete ")),
117
+ }, _(v(re)(z.value)), 1)),
116
118
  u("button", {
117
119
  type: "button",
118
120
  onClick: Z
@@ -129,4 +131,4 @@ var ie = {
129
131
  //#endregion
130
132
  export { N as default };
131
133
 
132
- //# sourceMappingURL=InkNotePopover.vue_vue_type_script_setup_true_lang.js.map
134
+ //# sourceMappingURL=InkThreadPopover.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkThreadPopover.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_renderSlot","_createElementBlock","_Fragment","_renderList","_createElementVNode","_toDisplayString","_createCommentVNode","_withModifiers","_withDirectives","_vModelText","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","InkThreadPopover_vue_vue_type_script_setup_true_lang_default","ctx","injectInkContext","useAnnotations","find","id","annotations","a","note","computed","threadRoot","anchor","useAnnotationElement","focusReturn","useFocusReturn","open","thread","threadOf","editingRoot","root","draft","ref","noteId","watch","previous","dropIfEmpty","written","dropped","isAbandonedNote","remove","reply","contents","text","add","close","isEmptyRoot","submit","updateContents","removeThread","update","onOpenChange","next","openBlock","createBlock","unref","PopoverRoot","withCtx","createVNode","PopoverPortal","PopoverContent","mergeProps","threadPopoverLabel","keepOpenOnAnnotation","_cache","$event","renderSlot","_ctx","createElementBlock","Fragment","renderList","item","createElementVNode","toDisplayString","createCommentVNode","withModifiers","withDirectives","vModelText","threadDeleteLabel"],"sources":["../../src/components/InkThreadPopover.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The thread for the activated note or text markup, anchored to the root's overlay element.\n * Activating a reply opens the whole thread from its root. Closing (Close, Escape, a press\n * outside) clears `activated`.\n *\n * A new note, or a highlight, has no text. While its root is empty (and unlocked) the default\n * form writes the root's own `contents`, labelled \"Comment\", and the thread list stays hidden\n * until there is something in it; after that the form adds replies. Closing a note that is\n * still empty and has no replies removes it, so an abandoned note does not stay on the page.\n * Markup stays: the mark is the point.\n */\nimport { isAbandonedNote, threadOf, threadRoot } from '@inkbar/core'\nimport { threadDeleteLabel, threadPopoverLabel } from '@inkbar/core/dom'\nimport { PopoverContent, PopoverPortal, PopoverRoot } from 'reka-ui'\nimport { computed, ref, watch } from 'vue'\n\nimport { useAnnotations } from '../composables/useAnnotations'\nimport { injectInkContext } from '../context'\n\nimport { useAnnotationElement } from './annotation-element'\nimport { keepOpenOnAnnotation, useFocusReturn } from './popover-focus'\n\nimport type { Annotation, ThreadRoot } from '@inkbar/core'\nimport type { ThreadPopoverSlotProps } from '@inkbar/core/dom'\n\nexport type { ThreadPopoverSlotProps } from '@inkbar/core/dom'\n\ndefineSlots<{ default?(props: ThreadPopoverSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\nconst { annotations, add, update, remove } = useAnnotations()\n\nconst find = (id: string | undefined) =>\n id ? annotations.value.find((a) => a.id === id) : undefined\n\nconst note = computed<ThreadRoot | null>(() => {\n const a = find(ctx.activated.value ?? undefined)\n return a ? threadRoot(annotations.value, a) : null\n})\nconst anchor = useAnnotationElement(\n ctx,\n computed(() => note.value?.id ?? null)\n)\nconst focusReturn = useFocusReturn(ctx)\nconst open = computed(() => note.value !== null && anchor.value !== null)\nconst thread = computed<Annotation[]>(() =>\n note.value ? threadOf(annotations.value, note.value) : []\n)\n\n/** True while the default form writes the root's own text rather than a reply. */\nconst editingRoot = computed(() => {\n const root = note.value\n return root !== null && !root.locked && !root.contents?.trim()\n})\n\nconst draft = ref('')\nconst noteId = () => note.value?.id\n// Synchronous, so a render for another thread never shows the old draft.\nwatch(noteId, () => (draft.value = ''), { flush: 'sync' })\nwatch(noteId, (_next, previous) => {\n // Activation moved on from a note that never got any text: drop it.\n if (previous !== undefined) dropIfEmpty(previous)\n})\n\n/**\n * Roots this popover wrote text or a reply for. In controlled mode the write is a proposal\n * the host may not have applied yet, so the applied list still shows the note empty; these\n * are never dropped as abandoned.\n */\nconst written = new Set<string>()\n/** Notes this popover has already asked to remove, so a slow host is asked once. */\nconst dropped = new Set<string>()\n\n/** Removes an unlocked root note with no text and no replies. True when it did. */\nfunction dropIfEmpty(id: string): boolean {\n const a = find(id)\n if (!a || dropped.has(id) || written.has(id) || !isAbandonedNote(a, annotations.value))\n return false\n dropped.add(id)\n remove(id)\n return true\n}\n\nfunction reply(text: string): void {\n const root = note.value\n const contents = text.trim()\n if (!root || !contents) return\n written.add(root.id)\n add({ type: 'text', page: root.page, rect: root.rect, contents, inReplyTo: root.id })\n draft.value = ''\n}\nfunction close(): void {\n const root = note.value\n if (root && find(root.id) && isEmptyRoot(root)) {\n focusReturn.beforeRemove(anchor.value)\n dropIfEmpty(root.id)\n }\n ctx.setActivated(null)\n}\n/** A note that closing now would remove. */\nfunction isEmptyRoot(root: ThreadRoot): boolean {\n return !written.has(root.id) && isAbandonedNote(root, annotations.value)\n}\nfunction submit(): void {\n const text = draft.value.trim()\n if (!text) return\n if (editingRoot.value) {\n updateContents(text)\n draft.value = ''\n } else reply(text)\n}\n/** Locked roots cannot be removed: removing one does nothing and keeps the popover. */\nfunction removeThread(): void {\n const root = note.value\n if (!root || root.locked) return\n focusReturn.beforeRemove(anchor.value)\n // Under a slow controlled host the root stays listed for a while; it is not asked for again.\n dropped.add(root.id)\n remove(root.id)\n ctx.setActivated(null)\n}\nfunction updateContents(contents: string): void {\n if (!note.value || note.value.locked) return\n if (contents.trim()) written.add(note.value.id)\n update(note.value.id, { contents })\n}\nfunction onOpenChange(next: boolean): void {\n if (!next) close()\n}\n</script>\n\n<template>\n <PopoverRoot :open=\"open\" @update:open=\"onOpenChange\">\n <PopoverPortal>\n <PopoverContent\n v-if=\"note && anchor\"\n :reference=\"anchor\"\n class=\"ink-thread-popover\"\n data-ink-thread-popover\n side=\"right\"\n :side-offset=\"8\"\n :collision-padding=\"8\"\n v-bind=\"{ 'aria-label': threadPopoverLabel(note) }\"\n @interact-outside=\"keepOpenOnAnnotation\"\n @close-auto-focus=\"focusReturn.onCloseAutoFocus($event, anchor)\"\n >\n <slot\n :root=\"note\"\n :replies=\"thread.slice(1)\"\n :reply=\"reply\"\n :update=\"updateContents\"\n :remove=\"removeThread\"\n :close=\"close\"\n >\n <ol v-if=\"!editingRoot || thread.length > 1\" class=\"ink-thread\" data-ink-thread>\n <li\n v-for=\"item in thread\"\n :key=\"item.id\"\n class=\"ink-thread-item\"\n data-ink-thread-item\n :data-reply=\"item.inReplyTo ? '' : undefined\"\n >\n <span class=\"ink-thread-author\">{{ item.author ?? 'Anonymous' }}</span>\n <time class=\"ink-thread-time\" :datetime=\"item.createdAt\">\n {{ new Date(item.createdAt).toLocaleString() }}\n </time>\n <p class=\"ink-thread-text\">{{ item.contents }}</p>\n </li>\n </ol>\n <form class=\"ink-thread-reply\" data-ink-thread-reply @submit.prevent=\"submit\">\n <textarea\n v-model=\"draft\"\n :aria-label=\"editingRoot ? 'Comment' : 'Reply'\"\n rows=\"2\"\n :placeholder=\"editingRoot ? 'Comment' : 'Reply'\"\n />\n <div class=\"ink-thread-actions\">\n <button type=\"submit\" :disabled=\"!draft.trim()\">\n {{ editingRoot ? 'Comment' : 'Reply' }}\n </button>\n <button v-if=\"!note.locked\" type=\"button\" @click=\"removeThread\">\n {{ threadDeleteLabel(note) }}\n </button>\n <button type=\"button\" @click=\"close\">Close</button>\n </div>\n </form>\n </slot>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"InkToolButton.js","names":["_sfc_main","InkToolButton_vue_vue_type_script_setup_true_lang_default","InkToolButton_default"],"sources":["../../src/components/InkToolButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TOOL_LABELS } from '@inkbar/core/dom'\nimport { Hand, Highlighter, MessageSquare, MousePointer2, Square } from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed } from 'vue'\n\nimport { useTool } from '../composables/useTool'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ToolId } from '@inkbar/core/dom'\nimport type { IconNode } from '@inkbar/icons'\n\nconst ICONS: Readonly<Record<ToolId, IconNode>> = {\n view: Hand,\n select: MousePointer2,\n highlight: Highlighter,\n 'redact-area': Square,\n note: MessageSquare,\n}\n\nconst props = withDefaults(\n defineProps<{ tool: ToolId; label?: string | undefined; asChild?: boolean }>(),\n { label: undefined, asChild: false }\n)\n\nconst { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\nconst name = computed(() => props.label ?? TOOL_LABELS[props.tool])\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 :icon=\"ICONS[tool]\" /></slot>\n </ToolbarButton>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"InkToolButton.js","names":["_sfc_main","InkToolButton_vue_vue_type_script_setup_true_lang_default","InkToolButton_default"],"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'\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 { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\n// A host tool has no built-in name or icon: `label` and the slot supply them.\nconst name = computed(() => props.label ?? TOOL_LABELS[props.tool] ?? props.tool)\nconst icon = computed(() => ICONS[props.tool])\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":""}
@@ -1 +1 @@
1
- {"version":3,"file":"InkToolButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkToolButton.vue"],"names":[],"mappings":"AA6DA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAY9C,KAAK,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAqEnF,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":"AAuFA,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;AAyEnF,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,11 +1,11 @@
1
1
  import { useTool as e } from "../composables/useTool.js";
2
2
  import t from "./InkIcon.js";
3
- import { computed as n, createBlock as r, createVNode as i, defineComponent as a, mergeProps as o, openBlock as s, renderSlot as c, unref as l, withCtx as u } from "vue";
3
+ import { computed as n, createBlock as r, createCommentVNode as i, defineComponent as a, mergeProps as o, openBlock as s, renderSlot as c, unref as l, withCtx as u } from "vue";
4
4
  import { TOOL_LABELS as d } from "@inkbar/core/dom";
5
5
  import { ToolbarButton as f } from "reka-ui";
6
- import { Hand as p, Highlighter as m, MessageSquare as h, MousePointer2 as g, Square as _ } from "@inkbar/icons";
6
+ import { Highlighter as p, MessageSquare as m, PenLine as h, PenTool as g, Signature as _, Square as v, SquareDashedMousePointer as y, TextCursor as b, Type as x } from "@inkbar/icons";
7
7
  //#region src/components/InkToolButton.vue?vue&type=script&setup=true&lang.ts
8
- var v = /*@__PURE__*/ a({
8
+ var S = /*@__PURE__*/ a({
9
9
  __name: "InkToolButton",
10
10
  props: {
11
11
  tool: {},
@@ -16,29 +16,36 @@ var v = /*@__PURE__*/ a({
16
16
  }
17
17
  },
18
18
  setup(a) {
19
- let v = {
20
- view: p,
21
- select: g,
22
- highlight: m,
23
- "redact-area": _,
24
- note: h
25
- }, y = a, { tool: b, setTool: x } = e(), S = n(() => b.value === y.tool), C = n(() => y.label ?? d[y.tool]), w = n(() => ({
26
- "aria-pressed": String(S.value),
27
- "aria-label": C.value,
28
- title: C.value,
29
- onClick: () => x(y.tool)
19
+ let S = {
20
+ "select-text": b,
21
+ select: y,
22
+ highlight: p,
23
+ "redact-area": v,
24
+ sketch: g,
25
+ draw: h,
26
+ note: m,
27
+ freetext: x,
28
+ signature: _
29
+ }, C = a, { tool: w, setTool: T } = e(), E = n(() => w.value === C.tool), D = n(() => C.label ?? d[C.tool] ?? C.tool), O = n(() => S[C.tool]), k = n(() => ({
30
+ "aria-pressed": String(E.value),
31
+ "aria-label": D.value,
32
+ title: D.value,
33
+ onClick: () => T(C.tool)
30
34
  }));
31
35
  return (e, n) => (s(), r(l(f), o({
32
36
  "as-child": a.asChild,
33
37
  class: "ink-tool-button",
34
38
  "data-ink-tool-button": "",
35
39
  "data-tool": a.tool,
36
- "data-state": S.value ? "on" : "off"
37
- }, w.value), {
40
+ "data-state": E.value ? "on" : "off"
41
+ }, k.value), {
38
42
  default: u(() => [c(e.$slots, "default", {
39
- active: S.value,
40
- label: C.value
41
- }, () => [i(t, { icon: v[a.tool] }, null, 8, ["icon"])])]),
43
+ active: E.value,
44
+ label: D.value
45
+ }, () => [O.value ? (s(), r(t, {
46
+ key: 0,
47
+ icon: O.value
48
+ }, null, 8, ["icon"])) : i("", !0)])]),
42
49
  _: 3
43
50
  }, 16, [
44
51
  "as-child",
@@ -48,6 +55,6 @@ var v = /*@__PURE__*/ a({
48
55
  }
49
56
  });
50
57
  //#endregion
51
- export { v as default };
58
+ export { S as default };
52
59
 
53
60
  //# 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","_createVNode","InkIcon","InkIcon_default","InkToolButton_vue_vue_type_script_setup_true_lang_default","ICONS","Hand","MousePointer2","Highlighter","Square","MessageSquare","props","__props","current","useTool","active","computed","name","TOOL_LABELS","attrs","setTool","openBlock","createBlock","unref","ToolbarButton","mergeProps","withCtx","renderSlot","_ctx","createVNode"],"sources":["../../src/components/InkToolButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { TOOL_LABELS } from '@inkbar/core/dom'\nimport { Hand, Highlighter, MessageSquare, MousePointer2, Square } from '@inkbar/icons'\nimport { ToolbarButton } from 'reka-ui'\nimport { computed } from 'vue'\n\nimport { useTool } from '../composables/useTool'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { ToolId } from '@inkbar/core/dom'\nimport type { IconNode } from '@inkbar/icons'\n\nconst ICONS: Readonly<Record<ToolId, IconNode>> = {\n view: Hand,\n select: MousePointer2,\n highlight: Highlighter,\n 'redact-area': Square,\n note: MessageSquare,\n}\n\nconst props = withDefaults(\n defineProps<{ tool: ToolId; label?: string | undefined; asChild?: boolean }>(),\n { label: undefined, asChild: false }\n)\n\nconst { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\nconst name = computed(() => props.label ?? TOOL_LABELS[props.tool])\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 :icon=\"ICONS[tool]\" /></slot>\n </ToolbarButton>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAaA,IAAMU,IAA4C;GAChD,MAAMC;GACN,QAAQC;GACR,WAAWC;GACX,eAAeC;GACf,MAAMC;EACR,GAEMC,IAAQC,GAKR,EAAE,MAAMC,GAAS,eAAYC,EAAQ,GACrCC,IAASC,QAAeH,EAAQ,UAAUF,EAAM,IAAI,GACpDM,IAAOD,QAAeL,EAAM,SAASO,EAAYP,EAAM,KAAK,GAE5DQ,IAAQH,SAAgB;GAC5B,gBAAgB,OAAOD,EAAO,KAAK;GACnC,cAAcE,EAAK;GACnB,OAAOA,EAAK;GACZ,eAAeG,EAAQT,EAAM,IAAI;EACnC,EAAE;oBAIAhB,EAAA,GAAAC,EASgBC,EAAA2B,CAAA,GAThB1B,EASgB;GARb,YAAUc,EAAA;GACX,OAAM;GACN,wBAAA;GACC,aAAWA,EAAA;GACX,cAAYG,EAAA,QAAM,OAAA;EACX,GAAAI,EAAA,KAAK,GAAA;GAEb,SAAApB,QAA2E,CAA3EC,EAA2E4B,EAAA,QAAA,WAAA;IAApE,QAAQb,EAAA;IAAS,OAAOE,EAAA;GAA/B,SAA2E,CAAtChB,EAA+BC,GAAA,EAArB,MAAMG,EAAMO,EAAA,MAAA,GAAA,MAAA,GAAA,CAAA,MAAA,CAAA,CAAA,CAAA,CAAA,CAAA"}
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","current","useTool","active","computed","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'\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 { tool: current, setTool } = useTool()\nconst active = computed(() => current.value === props.tool)\n// A host tool has no built-in name or icon: `label` and the slot supply them.\nconst name = computed(() => props.label ?? TOOL_LABELS[props.tool] ?? props.tool)\nconst icon = computed(() => ICONS[props.tool])\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":";;;;;;;;;;;;;;;;;;EAuBA,IAAMU,IAAqD;GACzD,eAAeC;GACf,QAAQC;GACR,WAAWC;GACX,eAAeC;GACf,QAAQC;GACR,MAAMC;GACN,MAAMC;GACN,UAAUC;GACV,WAAWC;EACb,GAEMC,IAAQC,GAKR,EAAE,MAAMC,GAAS,eAAYC,EAAQ,GACrCC,IAASC,QAAeH,EAAQ,UAAUF,EAAM,IAAI,GAEpDM,IAAOD,QAAeL,EAAM,SAASO,EAAYP,EAAM,SAASA,EAAM,IAAI,GAC1EQ,IAAOH,QAAef,EAAMU,EAAM,KAAK,GAEvCS,IAAQJ,SAAgB;GAC5B,gBAAgB,OAAOD,EAAO,KAAK;GACnC,cAAcE,EAAK;GACnB,OAAOA,EAAK;GACZ,eAAeI,EAAQV,EAAM,IAAI;EACnC,EAAE;oBAIApB,EAAA,GAAAC,EASgBC,EAAAgC,CAAA,GAThB/B,EASgB;GARb,YAAUkB,EAAA;GACX,OAAM;GACN,wBAAA;GACC,aAAWA,EAAA;GACX,cAAYG,EAAA,QAAM,OAAA;EACX,GAAAK,EAAA,KAAK,GAAA;GAEb,SAAAzB,QAAgF,CAAhFC,EAAgFiC,EAAA,QAAA,WAAA;IAAzE,QAAQd,EAAA;IAAS,OAAOE,EAAA;GAA/B,SAAgF,CAA5BE,EAAA,SAAf5B,EAAA,GAAAC,EAAoCK,GAAA;;IAAd,MAAMsB,EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"InkViewport.js","names":["_sfc_main","InkViewport_vue_vue_type_script_setup_true_lang_default","InkViewport_default"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\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 watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\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(teardown)\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"InkViewport.js","names":["_sfc_main","InkViewport_vue_vue_type_script_setup_true_lang_default","InkViewport_default"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n ...(ctx.hostTools.value ? { tools: ctx.hostTools.value } : {}),\n ...(ctx.toolStyle.value ? { toolStyle: ctx.toolStyle.value } : {}),\n toolHistory: { batch: (fn) => ctx.history.batch(fn) },\n toolOptions: ctx.toolOptions,\n fonts: [...ctx.fonts.value],\n // Read through, so a new `signatures` store reaches the tool as well as the menus.\n signatureLibrary: () => ctx.signatures.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\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 watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\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(teardown)\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":""}
@@ -23,8 +23,8 @@ type __VLS_Slots = {
23
23
  }): unknown;
24
24
  };
25
25
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
26
- mode: LayoutMode;
27
26
  rotation: ViewRotation;
27
+ mode: LayoutMode;
28
28
  gap: number;
29
29
  buffer: number;
30
30
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
@@ -1 +1 @@
1
- {"version":3,"file":"InkViewport.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkViewport.vue"],"names":[],"mappings":"AA4SA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EACV,UAAU,EAGV,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;AAuSF,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":"AAmTA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EACV,UAAU,EAGV,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;AA8SF,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"}
@@ -48,6 +48,12 @@ var T = ["data-state"], E = {
48
48
  gap: A.gap,
49
49
  buffer: A.buffer,
50
50
  tool: M.tool.value,
51
+ ...M.hostTools.value ? { tools: M.hostTools.value } : {},
52
+ ...M.toolStyle.value ? { toolStyle: M.toolStyle.value } : {},
53
+ toolHistory: { batch: (e) => M.history.batch(e) },
54
+ toolOptions: M.toolOptions,
55
+ fonts: [...M.fonts.value],
56
+ signatureLibrary: () => M.signatures.value,
51
57
  customAnnotations: z,
52
58
  onActivate: (e) => M.setActivated(e),
53
59
  onBuild: (e, t) => {
@@ -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","InkPage_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","pages","shallowRef","state","computed","error","engine","build","custom","stops","lastReportedZoom","lastReportedPage","teardown","stop","rebuild","e","opts","setup","doc","el","first","mountViewer","id","vp","tc","reportZoom","z","reportPage","p","page","err","onMounted","watch","t","m","r","gap","buffer","onBeforeUpdate","next","onBeforeUnmount","openBlock","createElementBlock","renderSlot","_ctx","_cache","createTextVNode","createElementVNode","toDisplayString","createCommentVNode","Fragment","renderList","createBlock","createSlots","withCtx","mergeProps","slotProps"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\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 watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\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(teardown)\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":"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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","InkPage_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","pages","shallowRef","state","computed","error","engine","build","custom","stops","lastReportedZoom","lastReportedPage","teardown","stop","rebuild","e","opts","setup","doc","el","first","mountViewer","fn","id","vp","tc","reportZoom","z","reportPage","p","page","err","onMounted","watch","t","m","r","gap","buffer","onBeforeUpdate","next","onBeforeUnmount","openBlock","createElementBlock","renderSlot","_ctx","_cache","createTextVNode","createElementVNode","toDisplayString","createCommentVNode","Fragment","renderList","createBlock","createSlots","withCtx","mergeProps","slotProps"],"sources":["../../src/components/InkViewport.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * The scroll element is handed to core's `mountViewer`, which builds the viewport, the page\n * layers, the tool controller and the keyboard shortcuts in it; Vue never renders children\n * into it. The engine reports each page host it mounts, and InkPage components rendered here\n * (they render nothing in place) teleport the page-error and custom-annotation slots into them.\n *\n * Two-way zoom and page: the viewport's own changes are reported through the context, and\n * the host's v-model values are applied only when they differ from the viewport's state, so\n * the echo of a reported value does nothing.\n */\nimport { mountViewer } from '@inkbar/core/dom'\nimport {\n computed,\n onBeforeUnmount,\n onBeforeUpdate,\n onMounted,\n shallowRef,\n useTemplateRef,\n watch,\n} from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport InkPage from './InkPage.vue'\n\nimport type { AnnotationSlotProps } from './annotation-slot'\nimport type { InkError } from '@inkbar/core'\nimport type {\n LayoutMode,\n PageMount,\n ViewerEngine,\n ViewRotation,\n ZoomValue,\n} from '@inkbar/core/dom'\n\nconst props = withDefaults(\n defineProps<{\n mode?: LayoutMode\n rotation?: ViewRotation\n /** Gap between pages, CSS px. */\n gap?: number\n /** Pages kept mounted either side of the visible ones. */\n buffer?: number\n }>(),\n { mode: 'continuous', rotation: 0, gap: 16, buffer: 2 }\n)\n\nconst slots = defineSlots<{\n loading?(): unknown\n error?(props: { error: InkError }): unknown\n empty?(): unknown\n annotation?(props: AnnotationSlotProps): unknown\n /** Shown inside a page that failed to render. The rest of the document stays usable. */\n 'page-error'?(props: { error: InkError; page: number }): unknown\n}>()\n\nconst ctx = injectInkContext()\nconst scroll = useTemplateRef<HTMLElement>('scroll')\n\ninterface MountedPage {\n /** The engine build the host belongs to; part of the InkPage key. */\n build: number\n page: number\n host: HTMLElement\n mount: PageMount\n error: InkError | null\n /** Whether the build that mounted the page renders the annotation slot. */\n custom: boolean\n}\n/** Page hosts, mounts and errors the engine reported; InkPage renders Teleports for them. */\nconst pages = shallowRef<MountedPage[]>([])\n\nconst state = computed(() => ctx.status.value.state)\nconst error = computed<InkError | null>(() =>\n ctx.status.value.state === 'error' ? ctx.status.value.error : null\n)\n\nconst engine = shallowRef<ViewerEngine | null>(null)\n/**\n * Numbered before each build starts, so the pages a build mounts carry its own number. A\n * rebuild gives each page a new host and mount, so pages from an earlier build must remount,\n * not be reused.\n */\nlet build = 0\n/** Whether the current build renders the annotation slot. */\nlet custom = false\nlet stops: (() => void)[] = []\n/** The zoom and page last reported to the host. */\nlet lastReportedZoom: ZoomValue | undefined\nlet lastReportedPage: number | undefined\n\nfunction teardown(): void {\n for (const stop of stops) stop()\n stops = []\n // Unmounts every page, which empties `pages` through `onPageUnmount`.\n engine.value?.destroy()\n engine.value = null\n if (ctx.viewport.value) ctx.viewport.value = null\n if (ctx.tools.value) ctx.tools.value = null\n pages.value = []\n}\n\nfunction rebuild(opts: Parameters<ViewerEngine['rebuild']>[0]): void {\n const e = engine.value\n if (!e) return\n build += 1\n if (opts.customAnnotations !== undefined) custom = opts.customAnnotations\n e.rebuild(opts)\n}\n\n// Build for a new document or status; the previous engine is torn down first.\nfunction setup(): void {\n teardown()\n lastReportedZoom = undefined\n lastReportedPage = undefined\n const doc = ctx.document.value\n const el = scroll.value\n if (!doc || !el || ctx.status.value.state !== 'ready') return\n let first = true\n build += 1\n custom = !!slots.annotation\n engine.value = mountViewer({\n container: el,\n document: doc,\n zoom: ctx.zoomModel.value ?? 'fit-width',\n ...(ctx.pageModel.value === undefined ? {} : { page: ctx.pageModel.value }),\n mode: props.mode,\n rotation: props.rotation,\n gap: props.gap,\n buffer: props.buffer,\n tool: ctx.tool.value,\n ...(ctx.hostTools.value ? { tools: ctx.hostTools.value } : {}),\n ...(ctx.toolStyle.value ? { toolStyle: ctx.toolStyle.value } : {}),\n toolHistory: { batch: (fn) => ctx.history.batch(fn) },\n toolOptions: ctx.toolOptions,\n fonts: [...ctx.fonts.value],\n // Read through, so a new `signatures` store reaches the tool as well as the menus.\n signatureLibrary: () => ctx.signatures.value,\n customAnnotations: custom,\n onActivate: (id) => ctx.setActivated(id),\n onBuild: (vp, tc) => {\n ctx.viewport.value = vp\n ctx.tools.value = tc\n if (first) {\n // A new document starts from where the viewport opens (its zoom, on the first page:\n // `createViewport` always starts at page 0); only later changes are reported, the\n // restored page among them, since the engine has already scrolled to it.\n first = false\n lastReportedZoom = vp.zoom.get()\n lastReportedPage = 0\n }\n for (const stop of stops) stop()\n const reportZoom = (z: ZoomValue): void => {\n if (z === lastReportedZoom) return\n lastReportedZoom = z\n ctx.reportZoom(z)\n }\n const reportPage = (p: number): void => {\n if (p === lastReportedPage) return\n lastReportedPage = p\n ctx.reportPage(p)\n }\n stops = [vp.zoom.subscribe(reportZoom), vp.currentPage.subscribe(reportPage)]\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 watch([() => ctx.document.value, () => ctx.status.value.state], setup, {\n immediate: true,\n })\n})\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(teardown)\n</script>\n\n<template>\n <div class=\"ink-viewport-root\" data-ink-viewport-root :data-state=\"state\">\n <div v-if=\"state === 'loading'\" class=\"ink-status\" role=\"status\" aria-live=\"polite\">\n <slot name=\"loading\">Loading document…</slot>\n </div>\n <div v-else-if=\"error\" class=\"ink-status ink-error\" role=\"alert\">\n <slot name=\"error\" :error=\"error\">\n <p class=\"ink-error-title\">This document could not be opened.</p>\n <!-- The message comes from the PDF engine and is not written for readers: it stays\n off the page, on the code's tooltip. -->\n <p>\n <code class=\"ink-error-code\" :title=\"error.message\">{{ error.code }}</code>\n </p>\n </slot>\n </div>\n <div v-else-if=\"state === 'idle'\" class=\"ink-status ink-empty\">\n <slot name=\"empty\" />\n </div>\n <div\n ref=\"scroll\"\n class=\"ink-scroll\"\n data-ink-scroll\n tabindex=\"0\"\n role=\"document\"\n aria-label=\"Document\"\n />\n <InkPage\n v-for=\"p in pages\"\n :key=\"`${p.build}:${p.page}`\"\n :page=\"p.page\"\n :host=\"p.host\"\n :mount=\"p.mount\"\n :error=\"p.error\"\n :custom-annotations=\"p.custom\"\n >\n <template v-if=\"slots.annotation\" #annotation=\"slotProps\">\n <slot name=\"annotation\" v-bind=\"slotProps\" />\n </template>\n <template v-if=\"slots['page-error']\" #page-error=\"slotProps\">\n <slot name=\"page-error\" v-bind=\"slotProps\" />\n </template>\n </InkPage>\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import e from "./SignatureForm.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/SignatureForm.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=SignatureForm.js.map