@inkbar/vue 0.3.0 → 0.5.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 (101) hide show
  1. package/README.md +17 -12
  2. package/dist/components/InkAnnotation.js.map +1 -1
  3. package/dist/components/InkAnnotation.vue.d.ts.map +1 -1
  4. package/dist/components/InkAnnotation.vue_vue_type_script_setup_true_lang.js +16 -24
  5. package/dist/components/InkAnnotation.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/InkColorMenu.js +7 -0
  7. package/dist/components/InkColorMenu.js.map +1 -0
  8. package/dist/components/InkColorMenu.vue.d.ts +34 -0
  9. package/dist/components/InkColorMenu.vue.d.ts.map +1 -0
  10. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js +153 -0
  11. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  12. package/dist/components/InkHighlightMenu.js +7 -0
  13. package/dist/components/InkHighlightMenu.js.map +1 -0
  14. package/dist/components/{InkSuggestionCard.vue.d.ts → InkHighlightMenu.vue.d.ts} +7 -6
  15. package/dist/components/InkHighlightMenu.vue.d.ts.map +1 -0
  16. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js +150 -0
  17. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  18. package/dist/components/InkLineStyleMenu.js +7 -0
  19. package/dist/components/InkLineStyleMenu.js.map +1 -0
  20. package/dist/components/InkLineStyleMenu.vue.d.ts +14 -0
  21. package/dist/components/InkLineStyleMenu.vue.d.ts.map +1 -0
  22. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js +109 -0
  23. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  24. package/dist/components/InkRoot.js.map +1 -1
  25. package/dist/components/InkRoot.vue.d.ts +730 -202
  26. package/dist/components/InkRoot.vue.d.ts.map +1 -1
  27. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +122 -87
  28. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/components/InkShapeMenu.js +7 -0
  30. package/dist/components/InkShapeMenu.js.map +1 -0
  31. package/dist/components/InkShapeMenu.vue.d.ts +18 -0
  32. package/dist/components/InkShapeMenu.vue.d.ts.map +1 -0
  33. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js +126 -0
  34. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  35. package/dist/components/InkSignatureDialog.js +7 -0
  36. package/dist/components/InkSignatureDialog.js.map +1 -0
  37. package/dist/components/InkSignatureDialog.vue.d.ts +21 -0
  38. package/dist/components/InkSignatureDialog.vue.d.ts.map +1 -0
  39. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js +58 -0
  40. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  41. package/dist/components/InkSignatureMenu.js +7 -0
  42. package/dist/components/InkSignatureMenu.js.map +1 -0
  43. package/dist/components/InkSignatureMenu.vue.d.ts +20 -0
  44. package/dist/components/InkSignatureMenu.vue.d.ts.map +1 -0
  45. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js +218 -0
  46. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  47. package/dist/components/InkTextStyleMenu.js +7 -0
  48. package/dist/components/InkTextStyleMenu.js.map +1 -0
  49. package/dist/components/InkTextStyleMenu.vue.d.ts +14 -0
  50. package/dist/components/InkTextStyleMenu.vue.d.ts.map +1 -0
  51. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js +200 -0
  52. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  53. package/dist/components/InkThreadPopover.js +7 -0
  54. package/dist/components/InkThreadPopover.js.map +1 -0
  55. package/dist/components/{InkNotePopover.vue.d.ts → InkThreadPopover.vue.d.ts} +4 -4
  56. package/dist/components/InkThreadPopover.vue.d.ts.map +1 -0
  57. package/dist/components/{InkNotePopover.vue_vue_type_script_setup_true_lang.js → InkThreadPopover.vue_vue_type_script_setup_true_lang.js} +44 -42
  58. package/dist/components/InkThreadPopover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  59. package/dist/components/InkToolButton.js.map +1 -1
  60. package/dist/components/InkToolButton.vue.d.ts.map +1 -1
  61. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js +27 -20
  62. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  63. package/dist/components/InkViewport.js.map +1 -1
  64. package/dist/components/InkViewport.vue.d.ts +1 -1
  65. package/dist/components/InkViewport.vue.d.ts.map +1 -1
  66. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +15 -2
  67. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/SignatureForm.js +7 -0
  69. package/dist/components/SignatureForm.js.map +1 -0
  70. package/dist/components/SignatureForm.vue.d.ts +14 -0
  71. package/dist/components/SignatureForm.vue.d.ts.map +1 -0
  72. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js +181 -0
  73. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js.map +1 -0
  74. package/dist/composables/useAnnotations.d.ts +1551 -630
  75. package/dist/composables/useAnnotations.d.ts.map +1 -1
  76. package/dist/composables/useAnnotations.js +13 -18
  77. package/dist/composables/useAnnotations.js.map +1 -1
  78. package/dist/composables/useToolOptions.d.ts +11 -0
  79. package/dist/composables/useToolOptions.d.ts.map +1 -0
  80. package/dist/composables/useToolOptions.js +16 -0
  81. package/dist/composables/useToolOptions.js.map +1 -0
  82. package/dist/composables/useToolStyle.d.ts +32 -0
  83. package/dist/composables/useToolStyle.d.ts.map +1 -0
  84. package/dist/composables/useToolStyle.js +24 -0
  85. package/dist/composables/useToolStyle.js.map +1 -0
  86. package/dist/context.d.ts +21 -2
  87. package/dist/context.d.ts.map +1 -1
  88. package/dist/context.js.map +1 -1
  89. package/dist/index.d.ts +13 -4
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +32 -24
  92. package/package.json +5 -5
  93. package/dist/components/InkNotePopover.js +0 -7
  94. package/dist/components/InkNotePopover.js.map +0 -1
  95. package/dist/components/InkNotePopover.vue.d.ts.map +0 -1
  96. package/dist/components/InkNotePopover.vue_vue_type_script_setup_true_lang.js.map +0 -1
  97. package/dist/components/InkSuggestionCard.js +0 -7
  98. package/dist/components/InkSuggestionCard.js.map +0 -1
  99. package/dist/components/InkSuggestionCard.vue.d.ts.map +0 -1
  100. package/dist/components/InkSuggestionCard.vue_vue_type_script_setup_true_lang.js +0 -85
  101. package/dist/components/InkSuggestionCard.vue_vue_type_script_setup_true_lang.js.map +0 -1
package/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  ---
22
22
 
23
- Drop a PDF viewer into your Vue app and let people highlight text, leave notes with replies and review redactions. `@inkbar/vue` gives you components and composables to build your own toolbars, plus note and suggestion popovers, all styled by `@inkbar/theme`.
23
+ Drop a PDF viewer into your Vue app and let people highlight text, leave notes with replies and redact. `@inkbar/vue` gives you components and composables to build your own toolbars, plus a popover for comment threads, all styled by `@inkbar/theme`.
24
24
 
25
25
  Annotations are plain typed objects. Bind them with `v-model` to keep them in your own state, or let Inkbar hold them with undo and redo.
26
26
 
@@ -50,8 +50,7 @@ import {
50
50
  InkPageCount,
51
51
  InkNextPage,
52
52
  InkZoomSelect,
53
- InkNotePopover,
54
- InkSuggestionCard,
53
+ InkThreadPopover,
55
54
  } from '@inkbar/vue'
56
55
  import type { Annotation } from '@inkbar/core'
57
56
  import { assets } from 'virtual:inkbar-assets'
@@ -69,7 +68,7 @@ const annotations = ref<Annotation[]>([])
69
68
  v-model:annotations="annotations"
70
69
  >
71
70
  <InkToolbar>
72
- <InkToolButton tool="view" />
71
+ <InkToolButton tool="select-text" />
73
72
  <InkToolButton tool="select" />
74
73
  <InkToolButton tool="highlight" />
75
74
  <InkToolButton tool="redact-area" />
@@ -86,8 +85,7 @@ const annotations = ref<Annotation[]>([])
86
85
  <InkNextPage />
87
86
  <InkZoomSelect />
88
87
  </InkToolbar>
89
- <InkNotePopover />
90
- <InkSuggestionCard />
88
+ <InkThreadPopover />
91
89
  </InkRoot>
92
90
  </template>
93
91
  ```
@@ -116,15 +114,21 @@ Inside `InkRoot`, `useHistory()` returns the same object. Its `batch(fn)` runs `
116
114
 
117
115
  `key` identifies the document. Reuse the same key when only the signed URL changes and the document is not reloaded.
118
116
 
119
- ## Note popover
117
+ ## Thread popover
120
118
 
121
- `InkNotePopover` opens the thread of the activated note. A new note has no text yet, so the form first writes the note's own text (labelled "Comment"); after that it adds replies.
119
+ `InkThreadPopover` opens the comment thread of the activated note or text markup (a highlight, underline, strikeout or squiggly). A new note or highlight has no text yet, so the form first writes its own `contents` (labelled "Comment"); after that it adds replies. A highlight with a comment shows a small marker at its end. Replies show in the thread only; the page draws just the note or highlight they answer.
122
120
 
123
- A root note with no text and no replies is removed when its popover closes, or when activation moves to another annotation, so abandoned notes do not stay on the page. Locked notes are never removed. If you add notes yourself (`add({ type: 'text', ... })`), give them `contents`, or they will be removed the first time someone opens and closes them.
121
+ A root note with no text and no replies is removed when its popover closes, or when activation moves to another annotation, so abandoned notes do not stay on the page. A highlight stays: the mark is the point. Locked annotations are never removed. If you add notes yourself (`add({ type: 'text', ... })`), give them `contents`, or they will be removed the first time someone opens and closes them.
122
+
123
+ The highlight tool leaves `contents` free for the comment. `doc.text(page)` returns the page's text items; match the markup's `quads` against them to get the marked text. `InkHighlightMenu` is a split button for the tool: it picks the markup kind and its colour.
124
+
125
+ ## Signatures
126
+
127
+ `InkSignatureMenu` lists saved signatures, picks one for the `signature` tool, removes them, and opens `InkSignatureDialog` to draw, type or upload a new one. These are marks on the page, not cryptographic signatures. Pass `signatures` to `InkRoot` to keep them somewhere: `createLocalSignatureStore(key)` from `@inkbar/core` uses `localStorage`, and without it they last until reload. `signatureFonts` lists the handwriting fonts the Type tab offers; load them with `@font-face`. A placed signature keeps its aspect ratio when resized.
124
128
 
125
129
  ## Custom rendering
126
130
 
127
- Slots let you render parts yourself. `InkViewport` has `loading`, `empty`, `error`, `annotation` and `page-error` slots. `InkNotePopover` and `InkSuggestionCard` have a scoped default slot that receives the popover's props, and the default slot of `InkToolButton` receives `{ active, label }`. The props are typed as `AnnotationSlotProps`, `NotePopoverSlotProps` and `SuggestionCardSlotProps`, the same types the React and Svelte packages export.
131
+ Slots let you render parts yourself. `InkViewport` has `loading`, `empty`, `error`, `annotation` and `page-error` slots. `InkThreadPopover` has a scoped default slot that receives the popover's props, and the default slot of `InkToolButton` receives `{ active, label }`. The props are typed as `AnnotationSlotProps` and `ThreadPopoverSlotProps`, the same types the React and Svelte packages export.
128
132
 
129
133
  `InkRoot`, `InkToolbar`, `InkToolButton`, `InkUndo`, `InkRedo`, `InkPrevPage`, `InkNextPage`, `InkZoomIn` and `InkZoomOut` take `as-child` to render your own element in place of theirs, such as a button from your design system. Put that element in the default slot. The control keeps its behaviour and accessible name.
130
134
 
@@ -134,10 +138,11 @@ The scroll area takes focus. From there:
134
138
 
135
139
  - With the `highlight` or `redact-area` tool active, `Enter` turns the text selection into a mark.
136
140
  - With the `note` tool active, `Enter` places a note at the centre of the current page and opens it.
141
+ - With the `signature` tool active, `Enter` places the chosen signature at the centre of the current page.
137
142
 
138
143
  On a focused annotation:
139
144
 
140
- - `Enter` or `Space` selects and activates it. A note opens its thread and a suggested redaction its card; other types are only selected.
145
+ - `Enter` or `Space` selects and activates it. A note or text markup opens its thread; other types are only selected.
141
146
  - `ArrowUp` and `ArrowDown` move to the previous or next annotation on the page.
142
147
  - `Shift` + arrow moves it by 1 pt, or by 10 pt with `Alt` as well.
143
148
  - `Ctrl` or `Cmd` + `Shift` + arrow resizes an area redaction, text box or shape.
@@ -151,7 +156,7 @@ Components carry state on data attributes, for example `[data-annotation][data-s
151
156
 
152
157
  ## Composables
153
158
 
154
- `useDocument`, `useAnnotations`, `useTool`, `useSelection`, `useZoom`, `usePage`, `useHistory` and `useEmbedded` read the state of the nearest `InkRoot`. Build your own toolbar or side panel from them.
159
+ `useDocument`, `useAnnotations`, `useTool`, `useSelection`, `useZoom`, `usePage`, `useHistory` and `useEmbedded` read the state of the nearest `InkRoot`. Build your own toolbar or side panel from them. Tool options, such as the shape kind, last as long as `InkRoot`. The tool style that `useToolStyle` reads and sets (colours, line style, text style) belongs to the document: opening another one starts again from the theme's defaults.
155
160
 
156
161
  ## Licence
157
162
 
@@ -1 +1 @@
1
- {"version":3,"file":"InkAnnotation.js","names":["_sfc_main","InkAnnotation_vue_vue_type_script_setup_true_lang_default","InkAnnotation_default"],"sources":["../../src/components/InkAnnotation.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Slot props for one annotation. It renders only its default slot: the overlay already draws\n * the default visual for every annotation that is not custom, so this never draws a second\n * one. InkPage teleports it into the annotation's overlay element.\n */\nimport { acceptSuggestion } from '@inkbar/core'\nimport { computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport type { AnnotationSlotProps, AnnotationState } from './annotation-slot'\nimport type { Annotation } from '@inkbar/core'\n\nconst props = withDefaults(\n defineProps<{\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n }>(),\n { element: undefined }\n)\n\ndefineSlots<{ default?(props: AnnotationSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\n\nconst observed = shallowRef<AnnotationState | null>(null)\nlet observer: MutationObserver | undefined\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\nwatch(\n () => props.element,\n (el) => {\n observer?.disconnect()\n observer = undefined\n observed.value = el ? readState(el) : null\n if (!el) return\n observer = new MutationObserver(() => {\n observed.value = readState(el)\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n },\n { immediate: true }\n)\nonBeforeUnmount(() => observer?.disconnect())\n\nconst isSuggestion = computed(\n () => props.annotation.type === 'redact' && props.annotation.origin === 'suggested'\n)\n\nconst slotProps = computed<AnnotationSlotProps>(() => {\n const { id } = props.annotation\n const store = () => ctx.document.value?.annotations\n return {\n annotation: props.annotation,\n state: observed.value ?? (ctx.selection.value.includes(id) ? 'selected' : 'idle'),\n locked: props.annotation.locked === true,\n select: () => store()?.select([id]),\n remove: () => void store()?.remove(id),\n accept: () => {\n const s = store()\n if (s && isSuggestion.value) acceptSuggestion(s, id)\n },\n dismiss: () => {\n if (isSuggestion.value) store()?.remove(id)\n },\n }\n})\n</script>\n\n<template>\n <slot v-bind=\"slotProps\" />\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"InkAnnotation.js","names":["_sfc_main","InkAnnotation_vue_vue_type_script_setup_true_lang_default","InkAnnotation_default"],"sources":["../../src/components/InkAnnotation.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Slot props for one annotation. It renders only its default slot: the overlay already draws\n * the default visual for every annotation that is not custom, so this never draws a second\n * one. InkPage teleports it into the annotation's overlay element.\n */\nimport { computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport type { AnnotationSlotProps, AnnotationState } from './annotation-slot'\nimport type { Annotation } from '@inkbar/core'\n\nconst props = withDefaults(\n defineProps<{\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n }>(),\n { element: undefined }\n)\n\ndefineSlots<{ default?(props: AnnotationSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\n\nconst observed = shallowRef<AnnotationState | null>(null)\nlet observer: MutationObserver | undefined\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\nwatch(\n () => props.element,\n (el) => {\n observer?.disconnect()\n observer = undefined\n observed.value = el ? readState(el) : null\n if (!el) return\n observer = new MutationObserver(() => {\n observed.value = readState(el)\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n },\n { immediate: true }\n)\nonBeforeUnmount(() => observer?.disconnect())\n\nconst slotProps = computed<AnnotationSlotProps>(() => {\n const { id } = props.annotation\n const store = () => ctx.document.value?.annotations\n return {\n annotation: props.annotation,\n state: observed.value ?? (ctx.selection.value.includes(id) ? 'selected' : 'idle'),\n locked: props.annotation.locked === true,\n select: () => store()?.select([id]),\n remove: () => void store()?.remove(id),\n }\n})\n</script>\n\n<template>\n <slot v-bind=\"slotProps\" />\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"InkAnnotation.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkAnnotation.vue"],"names":[],"mappings":"AAwFA,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,mBAAmB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,KAAK,WAAW,GAAG;IACf,UAAU,EAAE,UAAU,CAAA;IACtB,mFAAmF;IACnF,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CAClC,CAAC;AAMJ,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAA;CAAE,CAAC;AAuErE,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":"InkAnnotation.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkAnnotation.vue"],"names":[],"mappings":"AA2EA,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,mBAAmB,CAAA;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,KAAK,WAAW,GAAG;IACf,UAAU,EAAE,UAAU,CAAA;IACtB,mFAAmF;IACnF,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CAClC,CAAC;AAMJ,KAAK,WAAW,GAAG;IAAE,OAAO,CAAC,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAA;CAAE,CAAC;AA4DrE,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,48 +1,40 @@
1
1
  import { injectInkContext as e } from "../context.js";
2
2
  import { computed as t, defineComponent as n, guardReactiveProps as r, normalizeProps as i, onBeforeUnmount as a, renderSlot as o, shallowRef as s, watch as c } from "vue";
3
- import { acceptSuggestion as l } from "@inkbar/core";
4
3
  //#region src/components/InkAnnotation.vue?vue&type=script&setup=true&lang.ts
5
- var u = /*@__PURE__*/ n({
4
+ var l = /*@__PURE__*/ n({
6
5
  __name: "InkAnnotation",
7
6
  props: {
8
7
  annotation: {},
9
8
  element: { default: void 0 }
10
9
  },
11
10
  setup(n) {
12
- let u = n, d = e(), f = s(null), p;
13
- function m(e) {
11
+ let l = n, u = e(), d = s(null), f;
12
+ function p(e) {
14
13
  let t = e.dataset.state;
15
14
  return t === "idle" || t === "hover" || t === "selected" ? t : null;
16
15
  }
17
- c(() => u.element, (e) => {
18
- p?.disconnect(), p = void 0, f.value = e ? m(e) : null, e && (p = new MutationObserver(() => {
19
- f.value = m(e);
20
- }), p.observe(e, {
16
+ c(() => l.element, (e) => {
17
+ f?.disconnect(), f = void 0, d.value = e ? p(e) : null, e && (f = new MutationObserver(() => {
18
+ d.value = p(e);
19
+ }), f.observe(e, {
21
20
  attributes: !0,
22
21
  attributeFilter: ["data-state"]
23
22
  }));
24
- }, { immediate: !0 }), a(() => p?.disconnect());
25
- let h = t(() => u.annotation.type === "redact" && u.annotation.origin === "suggested"), g = t(() => {
26
- let { id: e } = u.annotation, t = () => d.document.value?.annotations;
23
+ }, { immediate: !0 }), a(() => f?.disconnect());
24
+ let m = t(() => {
25
+ let { id: e } = l.annotation, t = () => u.document.value?.annotations;
27
26
  return {
28
- annotation: u.annotation,
29
- state: f.value ?? (d.selection.value.includes(e) ? "selected" : "idle"),
30
- locked: u.annotation.locked === !0,
27
+ annotation: l.annotation,
28
+ state: d.value ?? (u.selection.value.includes(e) ? "selected" : "idle"),
29
+ locked: l.annotation.locked === !0,
31
30
  select: () => t()?.select([e]),
32
- remove: () => void t()?.remove(e),
33
- accept: () => {
34
- let n = t();
35
- n && h.value && l(n, e);
36
- },
37
- dismiss: () => {
38
- h.value && t()?.remove(e);
39
- }
31
+ remove: () => void t()?.remove(e)
40
32
  };
41
33
  });
42
- return (e, t) => o(e.$slots, "default", i(r(g.value)));
34
+ return (e, t) => o(e.$slots, "default", i(r(m.value)));
43
35
  }
44
36
  });
45
37
  //#endregion
46
- export { u as default };
38
+ export { l as default };
47
39
 
48
40
  //# sourceMappingURL=InkAnnotation.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InkAnnotation.vue_vue_type_script_setup_true_lang.js","names":["_renderSlot","_normalizeProps","_guardReactiveProps","InkAnnotation_vue_vue_type_script_setup_true_lang_default","props","__props","ctx","injectInkContext","observed","shallowRef","observer","readState","s","el","watch","onBeforeUnmount","isSuggestion","computed","slotProps","store","id","acceptSuggestion","renderSlot","_ctx","normalizeProps","guardReactiveProps"],"sources":["../../src/components/InkAnnotation.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Slot props for one annotation. It renders only its default slot: the overlay already draws\n * the default visual for every annotation that is not custom, so this never draws a second\n * one. InkPage teleports it into the annotation's overlay element.\n */\nimport { acceptSuggestion } from '@inkbar/core'\nimport { computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport type { AnnotationSlotProps, AnnotationState } from './annotation-slot'\nimport type { Annotation } from '@inkbar/core'\n\nconst props = withDefaults(\n defineProps<{\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n }>(),\n { element: undefined }\n)\n\ndefineSlots<{ default?(props: AnnotationSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\n\nconst observed = shallowRef<AnnotationState | null>(null)\nlet observer: MutationObserver | undefined\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\nwatch(\n () => props.element,\n (el) => {\n observer?.disconnect()\n observer = undefined\n observed.value = el ? readState(el) : null\n if (!el) return\n observer = new MutationObserver(() => {\n observed.value = readState(el)\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n },\n { immediate: true }\n)\nonBeforeUnmount(() => observer?.disconnect())\n\nconst isSuggestion = computed(\n () => props.annotation.type === 'redact' && props.annotation.origin === 'suggested'\n)\n\nconst slotProps = computed<AnnotationSlotProps>(() => {\n const { id } = props.annotation\n const store = () => ctx.document.value?.annotations\n return {\n annotation: props.annotation,\n state: observed.value ?? (ctx.selection.value.includes(id) ? 'selected' : 'idle'),\n locked: props.annotation.locked === true,\n select: () => store()?.select([id]),\n remove: () => void store()?.remove(id),\n accept: () => {\n const s = store()\n if (s && isSuggestion.value) acceptSuggestion(s, id)\n },\n dismiss: () => {\n if (isSuggestion.value) store()?.remove(id)\n },\n }\n})\n</script>\n\n<template>\n <slot v-bind=\"slotProps\" />\n</template>\n"],"mappings":";;;;;;;;;;;EAcA,IAAMI,IAAQC,GAWRC,IAAMC,EAAiB,GAEvBC,IAAWC,EAAmC,IAAI,GACpDC;EACJ,SAASC,EAAU,GAAyC;GAC1D,IAAMC,IAAIC,EAAG,QAAQ;GACrB,OAAOD,MAAM,UAAUA,MAAM,WAAWA,MAAM,aAAaA,IAAI;EACjE;EAeA,AAdAE,QACQV,EAAM,UACX,MAAO;GAIN,AAHAM,GAAU,WAAW,GACrB,IAAW,KAAA,GACX,EAAS,QAAQG,IAAKF,EAAUE,CAAE,IAAI,MACjCA,MACL,IAAW,IAAI,uBAAuB;IACpC,EAAS,QAAQF,EAAUE,CAAE;GAC/B,CAAC,GACDH,EAAS,QAAQG,GAAI;IAAE,YAAY;IAAM,iBAAiB,CAAC,YAAY;GAAE,CAAC;EAC5E,GACA,EAAE,WAAW,GAAK,CACpB,GACAE,QAAsBL,GAAU,WAAW,CAAC;EAE5C,IAAMM,IAAeC,QACbb,EAAM,WAAW,SAAS,YAAYA,EAAM,WAAW,WAAW,WAC1E,GAEMc,IAAYD,QAAoC;GACpD,IAAM,EAAE,UAAOb,EAAM,YACfe,UAAcb,EAAI,SAAS,OAAO;GACxC,OAAO;IACL,YAAYF,EAAM;IAClB,OAAOI,EAAS,UAAUF,EAAI,UAAU,MAAM,SAASc,CAAE,IAAI,aAAa;IAC1E,QAAQhB,EAAM,WAAW,WAAW;IACpC,cAAce,EAAM,CAAC,EAAE,OAAO,CAACC,CAAE,CAAC;IAClC,cAAc,KAAKD,EAAM,CAAC,EAAE,OAAOC,CAAE;IACrC,cAAc;KACZ,IAAMR,IAAIO,EAAM;KAChB,AAAIP,KAAKI,EAAa,SAAOK,EAAiBT,GAAGQ,CAAE;IACrD;IACA,eAAe;KACb,AAAIJ,EAAa,SAAOG,EAAM,CAAC,EAAE,OAAOC,CAAE;IAC5C;GACF;EACF,CAAC;mBAICpB,EAA2BuB,EAAA,QAAA,WAAAtB,EAAAC,EAAbgB,EAAA,KAAS,CAAA,CAAA"}
1
+ {"version":3,"file":"InkAnnotation.vue_vue_type_script_setup_true_lang.js","names":["_renderSlot","_normalizeProps","_guardReactiveProps","InkAnnotation_vue_vue_type_script_setup_true_lang_default","props","__props","ctx","injectInkContext","observed","shallowRef","observer","readState","s","el","watch","onBeforeUnmount","slotProps","computed","store","id","renderSlot","_ctx","normalizeProps","guardReactiveProps"],"sources":["../../src/components/InkAnnotation.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Slot props for one annotation. It renders only its default slot: the overlay already draws\n * the default visual for every annotation that is not custom, so this never draws a second\n * one. InkPage teleports it into the annotation's overlay element.\n */\nimport { computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport { injectInkContext } from '../context'\n\nimport type { AnnotationSlotProps, AnnotationState } from './annotation-slot'\nimport type { Annotation } from '@inkbar/core'\n\nconst props = withDefaults(\n defineProps<{\n annotation: Annotation\n /** The overlay element; its `data-state` (which includes hover) drives `state`. */\n element?: HTMLElement | undefined\n }>(),\n { element: undefined }\n)\n\ndefineSlots<{ default?(props: AnnotationSlotProps): unknown }>()\n\nconst ctx = injectInkContext()\n\nconst observed = shallowRef<AnnotationState | null>(null)\nlet observer: MutationObserver | undefined\nfunction readState(el: HTMLElement): AnnotationState | null {\n const s = el.dataset.state\n return s === 'idle' || s === 'hover' || s === 'selected' ? s : null\n}\nwatch(\n () => props.element,\n (el) => {\n observer?.disconnect()\n observer = undefined\n observed.value = el ? readState(el) : null\n if (!el) return\n observer = new MutationObserver(() => {\n observed.value = readState(el)\n })\n observer.observe(el, { attributes: true, attributeFilter: ['data-state'] })\n },\n { immediate: true }\n)\nonBeforeUnmount(() => observer?.disconnect())\n\nconst slotProps = computed<AnnotationSlotProps>(() => {\n const { id } = props.annotation\n const store = () => ctx.document.value?.annotations\n return {\n annotation: props.annotation,\n state: observed.value ?? (ctx.selection.value.includes(id) ? 'selected' : 'idle'),\n locked: props.annotation.locked === true,\n select: () => store()?.select([id]),\n remove: () => void store()?.remove(id),\n }\n})\n</script>\n\n<template>\n <slot v-bind=\"slotProps\" />\n</template>\n"],"mappings":";;;;;;;;;;EAaA,IAAMI,IAAQC,GAWRC,IAAMC,EAAiB,GAEvBC,IAAWC,EAAmC,IAAI,GACpDC;EACJ,SAASC,EAAU,GAAyC;GAC1D,IAAMC,IAAIC,EAAG,QAAQ;GACrB,OAAOD,MAAM,UAAUA,MAAM,WAAWA,MAAM,aAAaA,IAAI;EACjE;EAeA,AAdAE,QACQV,EAAM,UACX,MAAO;GAIN,AAHAM,GAAU,WAAW,GACrB,IAAW,KAAA,GACX,EAAS,QAAQG,IAAKF,EAAUE,CAAE,IAAI,MACjCA,MACL,IAAW,IAAI,uBAAuB;IACpC,EAAS,QAAQF,EAAUE,CAAE;GAC/B,CAAC,GACDH,EAAS,QAAQG,GAAI;IAAE,YAAY;IAAM,iBAAiB,CAAC,YAAY;GAAE,CAAC;EAC5E,GACA,EAAE,WAAW,GAAK,CACpB,GACAE,QAAsBL,GAAU,WAAW,CAAC;EAE5C,IAAMM,IAAYC,QAAoC;GACpD,IAAM,EAAE,UAAOb,EAAM,YACfc,UAAcZ,EAAI,SAAS,OAAO;GACxC,OAAO;IACL,YAAYF,EAAM;IAClB,OAAOI,EAAS,UAAUF,EAAI,UAAU,MAAM,SAASa,CAAE,IAAI,aAAa;IAC1E,QAAQf,EAAM,WAAW,WAAW;IACpC,cAAcc,EAAM,CAAC,EAAE,OAAO,CAACC,CAAE,CAAC;IAClC,cAAc,KAAKD,EAAM,CAAC,EAAE,OAAOC,CAAE;GACvC;EACF,CAAC;mBAICnB,EAA2BqB,EAAA,QAAA,WAAApB,EAAAC,EAAbc,EAAA,KAAS,CAAA,CAAA"}
@@ -0,0 +1,7 @@
1
+ import e from "./InkColorMenu.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkColorMenu.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkColorMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkColorMenu.js","names":["_sfc_main","InkColorMenu_vue_vue_type_script_setup_true_lang_default","InkColorMenu_default"],"sources":["../../src/components/InkColorMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * A colour menu for one colour property (border, fill or text) of the selection or the active\n * tool. The trigger shows the current colour as a swatch: split when the selection disagrees,\n * slashed for no fill. The panel is a palette grid, plus \"No fill\" for `fill` and \"Custom…\",\n * which opens a native colour input. The menu disables when nothing supports the property.\n */\nimport {\n COLOR_COLUMNS,\n colorMenuModel,\n focusInitialMenuItem,\n handleMenuKeys,\n menuItems,\n type ColorProperty,\n} from '@inkbar/core/dom'\nimport { Check } from '@inkbar/icons'\nimport {\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, defineComponent, mergeProps, ref, useAttrs, watch } from 'vue'\n\nimport { useToolStyle } from '../composables/useToolStyle'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { StyleGroup } from '@inkbar/core'\n\ndefineOptions({ inheritAttrs: false })\nconst attrs = useAttrs()\n\n/** Stands in for the toolbar item when the menu is nested in another panel. */\nconst PassThrough = defineComponent({\n inheritAttrs: false,\n setup:\n (_, { slots }) =>\n () =>\n slots.default?.(),\n})\n\nconst props = defineProps<{\n /** The colour this menu sets. */\n property: ColorProperty\n /** Accessible name; defaults to \"Border colour\", \"Fill colour\" or \"Text colour\". */\n label?: string\n /**\n * Renders the trigger outside the toolbar's roving focus, for a menu nested in another\n * panel (the text style menu's text colour).\n */\n standalone?: boolean\n /**\n * Scopes the menu to one style group: it shows and sets that group's colour whatever tool\n * is active, and recolours the selection only when it is all in the group.\n */\n group?: StyleGroup | undefined\n /** The colour new annotations get while the style leaves it unset; the swatch shows it. */\n fallback?: string | undefined\n}>()\n\nconst { current, supported, set } = useToolStyle(() => props.group)\nconst open = ref(false)\nconst customInput = ref<HTMLInputElement | null>(null)\n\nconst model = computed(() =>\n colorMenuModel(props.property, current.value, supported.value, props.fallback)\n)\nconst name = computed(() => props.label ?? model.value.label)\nconst trigger = computed(() => model.value.trigger)\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\n/** ArrowDown opens on the first item; a click opens on the checked one. */\nlet focusFirst = false\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' || e.defaultPrevented || open.value || !model.value.enabled)\n return\n e.preventDefault()\n focusFirst = true\n open.value = true\n}\n\nfunction onOpenAutoFocus(e: Event): void {\n e.preventDefault()\n // One menu is open at a time.\n const menu = document.querySelector(\n `[data-ink-menu=\"color-${props.property}\"] [role=\"menu\"]`\n )\n if (menu) {\n if (focusFirst) menuItems(menu)[0]?.focus({ preventScroll: true })\n else focusInitialMenuItem(menu)\n }\n focusFirst = false\n}\n\n// Reka's typed props stop at its own; ARIA goes through bound objects.\nconst triggerAttrs = computed(() => ({\n 'aria-label': name.value,\n title: name.value,\n 'aria-haspopup': 'menu' 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': name.value }))\nconst innerAttrs = computed(() => ({\n role: 'menu',\n 'aria-label': name.value,\n onKeydown: (e: KeyboardEvent) => handleMenuKeys(e, e.currentTarget as HTMLElement),\n}))\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <component :is=\"standalone ? PassThrough : ToolbarButton\" as-child>\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n class=\"ink-menu-trigger ink-color-menu\"\n :data-ink-color-menu=\"property\"\n :data-state=\"open ? 'open' : 'closed'\"\n v-bind=\"triggerBindings\"\n >\n <slot>\n <span\n class=\"ink-swatch\"\n data-ink-swatch\n aria-hidden=\"true\"\n :data-property=\"property\"\n :data-kind=\"trigger.kind\"\n :data-color=\"trigger.kind === 'color' ? trigger.color : undefined\"\n :style=\"\n trigger.kind === 'color' ? { '--ink-swatch': trigger.color } : undefined\n \"\n />\n </slot>\n </button>\n </PopoverTrigger>\n </component>\n <PopoverPortal>\n <PopoverContent\n class=\"ink-select-content ink-menu-content\"\n data-ink-select-content\n :data-ink-menu=\"`color-${property}`\"\n side=\"bottom\"\n align=\"start\"\n :side-offset=\"4\"\n :collision-padding=\"8\"\n v-bind=\"menuAttrs\"\n @open-auto-focus=\"onOpenAutoFocus\"\n >\n <div v-bind=\"innerAttrs\">\n <button\n v-if=\"model.noFill\"\n type=\"button\"\n role=\"menuitemradio\"\n class=\"ink-select-item ink-menu-item\"\n data-ink-select-item\n tabindex=\"-1\"\n :aria-checked=\"model.noFill.checked\"\n :data-state=\"model.noFill.checked ? 'checked' : 'unchecked'\"\n @click=\"set(model.noFill.patch)\"\n >\n No fill\n <span v-if=\"model.noFill.checked\" class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </span>\n </button>\n <div\n role=\"group\"\n aria-label=\"Colours\"\n class=\"ink-color-grid\"\n :data-ink-menu-columns=\"COLOR_COLUMNS\"\n >\n <button\n v-for=\"sw in model.swatches\"\n :key=\"sw.key\"\n type=\"button\"\n role=\"menuitemradio\"\n class=\"ink-swatch-item\"\n tabindex=\"-1\"\n :aria-label=\"sw.label\"\n :aria-checked=\"sw.checked\"\n :data-state=\"sw.checked ? 'checked' : 'unchecked'\"\n :style=\"{ '--ink-swatch': sw.color }\"\n @click=\"set(sw.patch)\"\n />\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"ink-select-item ink-menu-item\"\n data-ink-select-item\n tabindex=\"-1\"\n @click=\"customInput?.click()\"\n >\n Custom…\n </button>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n <input\n ref=\"customInput\"\n type=\"color\"\n class=\"ink-color-input\"\n aria-label=\"Custom colour\"\n :data-ink-color-input=\"property\"\n tabindex=\"-1\"\n :value=\"model.customValue.toLowerCase()\"\n @change=\"set(model.custom(($event.target as HTMLInputElement).value))\"\n />\n</template>\n"],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import { ColorProperty } from '@inkbar/core/dom';
2
+ import { StyleGroup } from '@inkbar/core';
3
+ type __VLS_Props = {
4
+ /** The colour this menu sets. */
5
+ property: ColorProperty;
6
+ /** Accessible name; defaults to "Border colour", "Fill colour" or "Text colour". */
7
+ label?: string;
8
+ /**
9
+ * Renders the trigger outside the toolbar's roving focus, for a menu nested in another
10
+ * panel (the text style menu's text colour).
11
+ */
12
+ standalone?: boolean;
13
+ /**
14
+ * Scopes the menu to one style group: it shows and sets that group's colour whatever tool
15
+ * is active, and recolours the selection only when it is all in the group.
16
+ */
17
+ group?: StyleGroup | undefined;
18
+ /** The colour new annotations get while the style leaves it unset; the swatch shows it. */
19
+ fallback?: string | undefined;
20
+ };
21
+ declare var __VLS_21: {};
22
+ type __VLS_Slots = {} & {
23
+ default?: (props: typeof __VLS_21) => any;
24
+ };
25
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
26
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
27
+ declare const _default: typeof __VLS_export;
28
+ export default _default;
29
+ type __VLS_WithSlots<T, S> = T & {
30
+ new (): {
31
+ $slots: S;
32
+ };
33
+ };
34
+ //# sourceMappingURL=InkColorMenu.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkColorMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkColorMenu.vue"],"names":[],"mappings":"AA6OA,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAA;AAezB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAe9C,KAAK,WAAW,GAAG;IACjB,iCAAiC;IACjC,QAAQ,EAAE,aAAa,CAAA;IACvB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;IAC9B,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC9B,CAAC;AAqTF,QAAA,IAAI,QAAQ,IAAY,CAAC;AACzB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAGhD,QAAA,MAAM,UAAU,kSAEd,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"}
@@ -0,0 +1,153 @@
1
+ import { useToolStyle as e } from "../composables/useToolStyle.js";
2
+ import t from "./InkIcon.js";
3
+ import { Fragment as n, computed as r, createBlock as ee, createCommentVNode as i, createElementBlock as a, createElementVNode as o, createTextVNode as s, createVNode as c, defineComponent as l, guardReactiveProps as u, mergeProps as d, normalizeProps as f, normalizeStyle as p, openBlock as m, ref as h, renderList as g, renderSlot as _, resolveDynamicComponent as v, unref as y, useAttrs as b, watch as x, withCtx as S } from "vue";
4
+ import { COLOR_COLUMNS as C, colorMenuModel as w, focusInitialMenuItem as T, handleMenuKeys as E, menuItems as D } from "@inkbar/core/dom";
5
+ import { PopoverContent as O, PopoverPortal as k, PopoverRoot as A, PopoverTrigger as j, ToolbarButton as M } from "reka-ui";
6
+ import { Check as N } from "@inkbar/icons";
7
+ //#region src/components/InkColorMenu.vue?vue&type=script&setup=true&lang.ts
8
+ var P = ["data-ink-color-menu", "data-state"], F = [
9
+ "data-property",
10
+ "data-kind",
11
+ "data-color"
12
+ ], I = ["aria-checked", "data-state"], L = {
13
+ key: 0,
14
+ class: "ink-select-indicator"
15
+ }, R = ["data-ink-menu-columns"], z = [
16
+ "aria-label",
17
+ "aria-checked",
18
+ "data-state",
19
+ "onClick"
20
+ ], B = ["data-ink-color-input", "value"], V = /*@__PURE__*/ l({
21
+ inheritAttrs: !1,
22
+ __name: "InkColorMenu",
23
+ props: {
24
+ property: {},
25
+ label: {},
26
+ standalone: { type: Boolean },
27
+ group: {},
28
+ fallback: {}
29
+ },
30
+ setup(V) {
31
+ let H = b(), U = l({
32
+ inheritAttrs: !1,
33
+ setup: (e, { slots: t }) => () => t.default?.()
34
+ }), W = V, { current: G, supported: K, set: q } = e(() => W.group), J = h(!1), Y = h(null), X = r(() => w(W.property, G.value, K.value, W.fallback)), Z = r(() => W.label ?? X.value.label), Q = r(() => X.value.trigger);
35
+ x(() => X.value.enabled, (e) => {
36
+ e || (J.value = !1);
37
+ });
38
+ let $ = !1;
39
+ function te(e) {
40
+ e.key !== "ArrowDown" || e.defaultPrevented || J.value || !X.value.enabled || (e.preventDefault(), $ = !0, J.value = !0);
41
+ }
42
+ function ne(e) {
43
+ e.preventDefault();
44
+ let t = document.querySelector(`[data-ink-menu="color-${W.property}"] [role="menu"]`);
45
+ t && ($ ? D(t)[0]?.focus({ preventScroll: !0 }) : T(t)), $ = !1;
46
+ }
47
+ let re = r(() => ({
48
+ "aria-label": Z.value,
49
+ title: Z.value,
50
+ "aria-haspopup": "menu",
51
+ onKeydown: te,
52
+ "data-mixed": X.value.mixed ? "" : void 0
53
+ })), ie = r(() => d(H, re.value, { disabled: (H.disabled ?? !1) !== !1 || !X.value.enabled })), ae = r(() => ({ "aria-label": Z.value })), oe = r(() => ({
54
+ role: "menu",
55
+ "aria-label": Z.value,
56
+ onKeydown: (e) => E(e, e.currentTarget)
57
+ }));
58
+ return (e, r) => (m(), a(n, null, [c(y(A), {
59
+ open: J.value,
60
+ "onUpdate:open": r[2] ||= (e) => J.value = e
61
+ }, {
62
+ default: S(() => [(m(), ee(v(V.standalone ? y(U) : y(M)), { "as-child": "" }, {
63
+ default: S(() => [c(y(j), { "as-child": "" }, {
64
+ default: S(() => [o("button", d({
65
+ type: "button",
66
+ class: "ink-menu-trigger ink-color-menu",
67
+ "data-ink-color-menu": V.property,
68
+ "data-state": J.value ? "open" : "closed"
69
+ }, ie.value), [_(e.$slots, "default", {}, () => [o("span", {
70
+ class: "ink-swatch",
71
+ "data-ink-swatch": "",
72
+ "aria-hidden": "true",
73
+ "data-property": V.property,
74
+ "data-kind": Q.value.kind,
75
+ "data-color": Q.value.kind === "color" ? Q.value.color : void 0,
76
+ style: p(Q.value.kind === "color" ? { "--ink-swatch": Q.value.color } : void 0)
77
+ }, null, 12, F)])], 16, P)]),
78
+ _: 3
79
+ })]),
80
+ _: 3
81
+ })), c(y(k), null, {
82
+ default: S(() => [c(y(O), d({
83
+ class: "ink-select-content ink-menu-content",
84
+ "data-ink-select-content": "",
85
+ "data-ink-menu": `color-${V.property}`,
86
+ side: "bottom",
87
+ align: "start",
88
+ "side-offset": 4,
89
+ "collision-padding": 8
90
+ }, ae.value, { onOpenAutoFocus: ne }), {
91
+ default: S(() => [o("div", f(u(oe.value)), [
92
+ X.value.noFill ? (m(), a("button", {
93
+ key: 0,
94
+ type: "button",
95
+ role: "menuitemradio",
96
+ class: "ink-select-item ink-menu-item",
97
+ "data-ink-select-item": "",
98
+ tabindex: "-1",
99
+ "aria-checked": X.value.noFill.checked,
100
+ "data-state": X.value.noFill.checked ? "checked" : "unchecked",
101
+ onClick: r[0] ||= (e) => y(q)(X.value.noFill.patch)
102
+ }, [r[4] ||= s(" No fill ", -1), X.value.noFill.checked ? (m(), a("span", L, [c(t, {
103
+ icon: y(N),
104
+ size: 16
105
+ }, null, 8, ["icon"])])) : i("", !0)], 8, I)) : i("", !0),
106
+ o("div", {
107
+ role: "group",
108
+ "aria-label": "Colours",
109
+ class: "ink-color-grid",
110
+ "data-ink-menu-columns": y(C)
111
+ }, [(m(!0), a(n, null, g(X.value.swatches, (e) => (m(), a("button", {
112
+ key: e.key,
113
+ type: "button",
114
+ role: "menuitemradio",
115
+ class: "ink-swatch-item",
116
+ tabindex: "-1",
117
+ "aria-label": e.label,
118
+ "aria-checked": e.checked,
119
+ "data-state": e.checked ? "checked" : "unchecked",
120
+ style: p({ "--ink-swatch": e.color }),
121
+ onClick: (t) => y(q)(e.patch)
122
+ }, null, 12, z))), 128))], 8, R),
123
+ o("button", {
124
+ type: "button",
125
+ role: "menuitem",
126
+ class: "ink-select-item ink-menu-item",
127
+ "data-ink-select-item": "",
128
+ tabindex: "-1",
129
+ onClick: r[1] ||= (e) => Y.value?.click()
130
+ }, " Custom… ")
131
+ ], 16)]),
132
+ _: 1
133
+ }, 16, ["data-ink-menu"])]),
134
+ _: 1
135
+ })]),
136
+ _: 3
137
+ }, 8, ["open"]), o("input", {
138
+ ref_key: "customInput",
139
+ ref: Y,
140
+ type: "color",
141
+ class: "ink-color-input",
142
+ "aria-label": "Custom colour",
143
+ "data-ink-color-input": V.property,
144
+ tabindex: "-1",
145
+ value: X.value.customValue.toLowerCase(),
146
+ onChange: r[3] ||= (e) => y(q)(X.value.custom(e.target.value))
147
+ }, null, 40, B)], 64));
148
+ }
149
+ });
150
+ //#endregion
151
+ export { V as default };
152
+
153
+ //# sourceMappingURL=InkColorMenu.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkColorMenu.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_Fragment","_createVNode","_unref","_withCtx","_createBlock","_resolveDynamicComponent","_createElementVNode","_mergeProps","_renderSlot","_normalizeStyle","_normalizeProps","_guardReactiveProps","_createTextVNode","InkIcon","_createCommentVNode","_renderList","InkIcon_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","InkColorMenu_vue_vue_type_script_setup_true_lang_default","attrs","useAttrs","PassThrough","defineComponent","slots","props","__props","useToolStyle","open","ref","customInput","model","computed","colorMenuModel","current","supported","name","trigger","enabled","focusFirst","onTriggerKeydown","onOpenAutoFocus","menu","menuItems","focusInitialMenuItem","triggerAttrs","triggerBindings","mergeProps","menuAttrs","innerAttrs","handleMenuKeys","openBlock","createElementBlock","Fragment","createVNode","unref","PopoverRoot","_cache","$event","withCtx","createBlock","resolveDynamicComponent","ToolbarButton","PopoverTrigger","createElementVNode","renderSlot","_ctx","normalizeStyle","PopoverPortal","PopoverContent","normalizeProps","guardReactiveProps","set","createTextVNode","Check","createCommentVNode","COLOR_COLUMNS","renderList","sw"],"sources":["../../src/components/InkColorMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * A colour menu for one colour property (border, fill or text) of the selection or the active\n * tool. The trigger shows the current colour as a swatch: split when the selection disagrees,\n * slashed for no fill. The panel is a palette grid, plus \"No fill\" for `fill` and \"Custom…\",\n * which opens a native colour input. The menu disables when nothing supports the property.\n */\nimport {\n COLOR_COLUMNS,\n colorMenuModel,\n focusInitialMenuItem,\n handleMenuKeys,\n menuItems,\n type ColorProperty,\n} from '@inkbar/core/dom'\nimport { Check } from '@inkbar/icons'\nimport {\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, defineComponent, mergeProps, ref, useAttrs, watch } from 'vue'\n\nimport { useToolStyle } from '../composables/useToolStyle'\n\nimport InkIcon from './InkIcon.vue'\n\nimport type { StyleGroup } from '@inkbar/core'\n\ndefineOptions({ inheritAttrs: false })\nconst attrs = useAttrs()\n\n/** Stands in for the toolbar item when the menu is nested in another panel. */\nconst PassThrough = defineComponent({\n inheritAttrs: false,\n setup:\n (_, { slots }) =>\n () =>\n slots.default?.(),\n})\n\nconst props = defineProps<{\n /** The colour this menu sets. */\n property: ColorProperty\n /** Accessible name; defaults to \"Border colour\", \"Fill colour\" or \"Text colour\". */\n label?: string\n /**\n * Renders the trigger outside the toolbar's roving focus, for a menu nested in another\n * panel (the text style menu's text colour).\n */\n standalone?: boolean\n /**\n * Scopes the menu to one style group: it shows and sets that group's colour whatever tool\n * is active, and recolours the selection only when it is all in the group.\n */\n group?: StyleGroup | undefined\n /** The colour new annotations get while the style leaves it unset; the swatch shows it. */\n fallback?: string | undefined\n}>()\n\nconst { current, supported, set } = useToolStyle(() => props.group)\nconst open = ref(false)\nconst customInput = ref<HTMLInputElement | null>(null)\n\nconst model = computed(() =>\n colorMenuModel(props.property, current.value, supported.value, props.fallback)\n)\nconst name = computed(() => props.label ?? model.value.label)\nconst trigger = computed(() => model.value.trigger)\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\n/** ArrowDown opens on the first item; a click opens on the checked one. */\nlet focusFirst = false\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' || e.defaultPrevented || open.value || !model.value.enabled)\n return\n e.preventDefault()\n focusFirst = true\n open.value = true\n}\n\nfunction onOpenAutoFocus(e: Event): void {\n e.preventDefault()\n // One menu is open at a time.\n const menu = document.querySelector(\n `[data-ink-menu=\"color-${props.property}\"] [role=\"menu\"]`\n )\n if (menu) {\n if (focusFirst) menuItems(menu)[0]?.focus({ preventScroll: true })\n else focusInitialMenuItem(menu)\n }\n focusFirst = false\n}\n\n// Reka's typed props stop at its own; ARIA goes through bound objects.\nconst triggerAttrs = computed(() => ({\n 'aria-label': name.value,\n title: name.value,\n 'aria-haspopup': 'menu' 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': name.value }))\nconst innerAttrs = computed(() => ({\n role: 'menu',\n 'aria-label': name.value,\n onKeydown: (e: KeyboardEvent) => handleMenuKeys(e, e.currentTarget as HTMLElement),\n}))\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <component :is=\"standalone ? PassThrough : ToolbarButton\" as-child>\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n class=\"ink-menu-trigger ink-color-menu\"\n :data-ink-color-menu=\"property\"\n :data-state=\"open ? 'open' : 'closed'\"\n v-bind=\"triggerBindings\"\n >\n <slot>\n <span\n class=\"ink-swatch\"\n data-ink-swatch\n aria-hidden=\"true\"\n :data-property=\"property\"\n :data-kind=\"trigger.kind\"\n :data-color=\"trigger.kind === 'color' ? trigger.color : undefined\"\n :style=\"\n trigger.kind === 'color' ? { '--ink-swatch': trigger.color } : undefined\n \"\n />\n </slot>\n </button>\n </PopoverTrigger>\n </component>\n <PopoverPortal>\n <PopoverContent\n class=\"ink-select-content ink-menu-content\"\n data-ink-select-content\n :data-ink-menu=\"`color-${property}`\"\n side=\"bottom\"\n align=\"start\"\n :side-offset=\"4\"\n :collision-padding=\"8\"\n v-bind=\"menuAttrs\"\n @open-auto-focus=\"onOpenAutoFocus\"\n >\n <div v-bind=\"innerAttrs\">\n <button\n v-if=\"model.noFill\"\n type=\"button\"\n role=\"menuitemradio\"\n class=\"ink-select-item ink-menu-item\"\n data-ink-select-item\n tabindex=\"-1\"\n :aria-checked=\"model.noFill.checked\"\n :data-state=\"model.noFill.checked ? 'checked' : 'unchecked'\"\n @click=\"set(model.noFill.patch)\"\n >\n No fill\n <span v-if=\"model.noFill.checked\" class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </span>\n </button>\n <div\n role=\"group\"\n aria-label=\"Colours\"\n class=\"ink-color-grid\"\n :data-ink-menu-columns=\"COLOR_COLUMNS\"\n >\n <button\n v-for=\"sw in model.swatches\"\n :key=\"sw.key\"\n type=\"button\"\n role=\"menuitemradio\"\n class=\"ink-swatch-item\"\n tabindex=\"-1\"\n :aria-label=\"sw.label\"\n :aria-checked=\"sw.checked\"\n :data-state=\"sw.checked ? 'checked' : 'unchecked'\"\n :style=\"{ '--ink-swatch': sw.color }\"\n @click=\"set(sw.patch)\"\n />\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n class=\"ink-select-item ink-menu-item\"\n data-ink-select-item\n tabindex=\"-1\"\n @click=\"customInput?.click()\"\n >\n Custom…\n </button>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n <input\n ref=\"customInput\"\n type=\"color\"\n class=\"ink-color-input\"\n aria-label=\"Custom colour\"\n :data-ink-color-input=\"property\"\n tabindex=\"-1\"\n :value=\"model.customValue.toLowerCase()\"\n @change=\"set(model.custom(($event.target as HTMLInputElement).value))\"\n />\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import e from "./InkHighlightMenu.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkHighlightMenu.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkHighlightMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkHighlightMenu.js","names":["_sfc_main","InkHighlightMenu_vue_vue_type_script_setup_true_lang_default","InkHighlightMenu_default"],"sources":["../../src/components/InkHighlightMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * A split button for the highlight tool. The main part activates the tool with the current\n * markup kind and draws that kind's icon; the chevron opens a menu of the four kinds plus\n * the markup colour. Choosing a kind switches to the tool with it. The colour is a nested\n * `InkColorMenu` scoped to the `markup` style group, so it works whatever tool is active.\n */\nimport {\n focusInitialMenuItem,\n handleMenuKeys,\n highlightMenuModel,\n MARKUP_ICONS,\n MARKUP_KINDS,\n menuItems,\n type HighlightOptions,\n type MarkupKind,\n} from '@inkbar/core/dom'\nimport { ChevronDown } from '@inkbar/icons'\nimport {\n PopoverAnchor,\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, ref } from 'vue'\n\nimport { useDocument } from '../composables/useDocument'\nimport { useTool } from '../composables/useTool'\nimport { useToolOptions } from '../composables/useToolOptions'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\ndefineOptions({ inheritAttrs: false })\nconst { tool, setTool } = useTool()\nconst { options, setOptions } = useToolOptions<HighlightOptions>('highlight')\nconst { document: doc } = useDocument()\nconst open = ref(false)\n\nconst model = computed(() => highlightMenuModel(options.value, MARKUP_KINDS))\nconst active = computed(() => tool.value === 'highlight')\n/** The colour the chosen kind gets while the markup style leaves it unset. */\nconst fallback = computed(() => doc.value?.annotations.defaults.color(model.value.kind))\nconst icon = computed(() => MARKUP_ICONS[model.value.kind])\n\n/** ArrowDown opens on the first item; a click opens on the checked one. */\nlet focusFirst = false\nfunction onTriggerKeydown(e: KeyboardEvent): void {\n if (e.key !== 'ArrowDown' || e.defaultPrevented || open.value) return\n e.preventDefault()\n focusFirst = true\n open.value = true\n}\n\nfunction onOpenAutoFocus(e: Event): void {\n e.preventDefault()\n // One highlight menu is open at a time.\n const menu = document.querySelector('[data-ink-menu=\"highlight\"] [role=\"menu\"]')\n if (menu) {\n if (focusFirst) menuItems(menu)[0]?.focus({ preventScroll: true })\n else focusInitialMenuItem(menu)\n }\n focusFirst = false\n}\n\nfunction choose(kind: MarkupKind): void {\n setOptions({ kind })\n setTool('highlight')\n open.value = false\n}\n\n// Reka's typed props stop at its own; ARIA and listeners go through bound objects.\nconst mainAttrs = computed(() => ({\n 'aria-pressed': String(active.value),\n 'aria-label': model.value.label,\n title: model.value.label,\n onClick: () => setTool('highlight'),\n}))\nconst triggerAttrs = {\n 'aria-label': 'Choose highlight',\n title: 'Choose highlight',\n 'aria-haspopup': 'menu' as const,\n onKeydown: onTriggerKeydown,\n}\nconst menuAttrs = { 'aria-label': 'Highlights' }\n/** The colour trigger is an item of this menu, reached with the arrow keys. */\nconst colourAttrs = { role: 'menuitem', tabindex: -1 }\nconst innerAttrs = {\n role: 'menu',\n 'aria-label': 'Highlights',\n // Capture, so the arrow keys move on from the colour item before its own ArrowDown\n // opens the nested menu.\n onKeydownCapture: (e: KeyboardEvent) =>\n handleMenuKeys(e, e.currentTarget as HTMLElement),\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <PopoverAnchor as-child>\n <div\n role=\"group\"\n aria-label=\"Highlight\"\n class=\"ink-split-button ink-highlight-menu\"\n data-ink-highlight-menu\n v-bind=\"$attrs\"\n >\n <ToolbarButton\n class=\"ink-tool-button ink-highlight-button\"\n data-ink-tool-button\n data-ink-highlight-button\n data-tool=\"highlight\"\n :data-kind=\"model.kind\"\n :data-state=\"active ? 'on' : 'off'\"\n v-bind=\"mainAttrs\"\n >\n <slot :active=\"active\" :kind=\"model.kind\"><InkIcon :icon=\"icon\" /></slot>\n </ToolbarButton>\n <ToolbarButton as-child>\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n class=\"ink-menu-trigger ink-highlight-menu-trigger\"\n data-ink-highlight-menu-trigger\n :data-state=\"open ? 'open' : 'closed'\"\n v-bind=\"triggerAttrs\"\n >\n <InkIcon :icon=\"ChevronDown\" />\n </button>\n </PopoverTrigger>\n </ToolbarButton>\n <PopoverPortal>\n <PopoverContent\n class=\"ink-select-content ink-menu-content\"\n data-ink-select-content\n data-ink-menu=\"highlight\"\n side=\"bottom\"\n align=\"start\"\n :side-offset=\"4\"\n :collision-padding=\"8\"\n v-bind=\"menuAttrs\"\n @open-auto-focus=\"onOpenAutoFocus\"\n >\n <div v-bind=\"innerAttrs\">\n <div role=\"group\" aria-label=\"Kinds\" class=\"ink-highlight-kinds\">\n <button\n v-for=\"item in model.items\"\n :key=\"item.kind\"\n type=\"button\"\n role=\"menuitemradio\"\n class=\"ink-select-item ink-menu-item ink-highlight-item\"\n data-ink-select-item\n tabindex=\"-1\"\n :data-key=\"item.kind\"\n :aria-checked=\"item.checked\"\n :data-state=\"item.checked ? 'checked' : 'unchecked'\"\n @click=\"choose(item.kind)\"\n >\n <InkIcon :icon=\"MARKUP_ICONS[item.kind]\" :size=\"16\" />\n {{ item.label }}\n </button>\n </div>\n <div role=\"separator\" class=\"ink-select-separator\" />\n <div role=\"group\" aria-label=\"Colour\" class=\"ink-highlight-colour\">\n <span class=\"ink-highlight-colour-label\" aria-hidden=\"true\">Colour</span>\n <InkColorMenu\n property=\"border\"\n group=\"markup\"\n label=\"Highlight colour\"\n standalone\n :fallback=\"fallback\"\n v-bind=\"colourAttrs\"\n />\n </div>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </div>\n </PopoverAnchor>\n </PopoverRoot>\n</template>\n"],"mappings":""}
@@ -1,8 +1,9 @@
1
- import { SuggestionCardSlotProps } from '@inkbar/core/dom';
2
- export type { ConfidenceBucket } from '@inkbar/core';
3
- export type { SuggestionCardSlotProps } from '@inkbar/core/dom';
4
- type __VLS_Slots = {
5
- default?(props: SuggestionCardSlotProps): unknown;
1
+ declare var __VLS_21: {
2
+ active: boolean;
3
+ kind: "highlight" | "underline" | "strikeout" | "squiggly";
4
+ };
5
+ type __VLS_Slots = {} & {
6
+ default?: (props: typeof __VLS_21) => any;
6
7
  };
7
8
  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>;
8
9
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -13,4 +14,4 @@ type __VLS_WithSlots<T, S> = T & {
13
14
  $slots: S;
14
15
  };
15
16
  };
16
- //# sourceMappingURL=InkSuggestionCard.vue.d.ts.map
17
+ //# sourceMappingURL=InkHighlightMenu.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkHighlightMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkHighlightMenu.vue"],"names":[],"mappings":"AA8hBA,QAAA,IAAI,QAAQ;;;CAAY,CAAC;AACzB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAGhD,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"}