@inkbar/vue 0.7.0 → 0.9.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 (79) hide show
  1. package/README.md +14 -2
  2. package/dist/components/InkFormAlert.js +7 -0
  3. package/dist/components/InkFormAlert.js.map +1 -0
  4. package/dist/components/InkFormAlert.vue.d.ts +16 -0
  5. package/dist/components/InkFormAlert.vue.d.ts.map +1 -0
  6. package/dist/components/InkFormAlert.vue_vue_type_script_setup_true_lang.js +90 -0
  7. package/dist/components/InkFormAlert.vue_vue_type_script_setup_true_lang.js.map +1 -0
  8. package/dist/components/InkHighlightMenu.js.map +1 -1
  9. package/dist/components/InkHighlightMenu.vue.d.ts.map +1 -1
  10. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js +67 -65
  11. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  12. package/dist/components/InkRoot.js.map +1 -1
  13. package/dist/components/InkRoot.vue.d.ts +24 -5
  14. package/dist/components/InkRoot.vue.d.ts.map +1 -1
  15. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +197 -148
  16. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  17. package/dist/components/InkShapeMenu.js.map +1 -1
  18. package/dist/components/InkShapeMenu.vue.d.ts.map +1 -1
  19. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js +58 -56
  20. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/InkSignFieldPopover.js +7 -0
  22. package/dist/components/InkSignFieldPopover.js.map +1 -0
  23. package/dist/components/InkSignFieldPopover.vue.d.ts +13 -0
  24. package/dist/components/InkSignFieldPopover.vue.d.ts.map +1 -0
  25. package/dist/components/InkSignFieldPopover.vue_vue_type_script_setup_true_lang.js +116 -0
  26. package/dist/components/InkSignFieldPopover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  27. package/dist/components/InkSignatureDialog.js.map +1 -1
  28. package/dist/components/InkSignatureDialog.vue.d.ts +10 -1
  29. package/dist/components/InkSignatureDialog.vue.d.ts.map +1 -1
  30. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js +9 -2
  31. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/components/InkSignatureMenu.js.map +1 -1
  33. package/dist/components/InkSignatureMenu.vue.d.ts.map +1 -1
  34. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js +69 -154
  35. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  36. package/dist/components/InkToolButton.js.map +1 -1
  37. package/dist/components/InkToolButton.vue.d.ts.map +1 -1
  38. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js +39 -36
  39. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/components/InkToolbarButton.js +7 -0
  41. package/dist/components/InkToolbarButton.js.map +1 -0
  42. package/dist/components/InkToolbarButton.vue.d.ts +22 -0
  43. package/dist/components/InkToolbarButton.vue.d.ts.map +1 -0
  44. package/dist/components/InkToolbarButton.vue_vue_type_script_setup_true_lang.js +32 -0
  45. package/dist/components/InkToolbarButton.vue_vue_type_script_setup_true_lang.js.map +1 -0
  46. package/dist/components/InkViewport.js.map +1 -1
  47. package/dist/components/InkViewport.vue.d.ts.map +1 -1
  48. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +123 -91
  49. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/SignatureForm.js.map +1 -1
  51. package/dist/components/SignatureForm.vue.d.ts +5 -1
  52. package/dist/components/SignatureForm.vue.d.ts.map +1 -1
  53. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js +64 -57
  54. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  55. package/dist/components/SignatureMenuPanel.js +7 -0
  56. package/dist/components/SignatureMenuPanel.js.map +1 -0
  57. package/dist/components/SignatureMenuPanel.vue.d.ts +15 -0
  58. package/dist/components/SignatureMenuPanel.vue.d.ts.map +1 -0
  59. package/dist/components/SignatureMenuPanel.vue_vue_type_script_setup_true_lang.js +116 -0
  60. package/dist/components/SignatureMenuPanel.vue_vue_type_script_setup_true_lang.js.map +1 -0
  61. package/dist/composables/useForm.d.ts +18 -0
  62. package/dist/composables/useForm.d.ts.map +1 -0
  63. package/dist/composables/useForm.js +17 -0
  64. package/dist/composables/useForm.js.map +1 -0
  65. package/dist/composables/useRegisteredTool.d.ts +21 -0
  66. package/dist/composables/useRegisteredTool.d.ts.map +1 -0
  67. package/dist/composables/useRegisteredTool.js +25 -0
  68. package/dist/composables/useRegisteredTool.js.map +1 -0
  69. package/dist/composables/useToolOptions.d.ts +8 -0
  70. package/dist/composables/useToolOptions.d.ts.map +1 -1
  71. package/dist/composables/useToolOptions.js +10 -5
  72. package/dist/composables/useToolOptions.js.map +1 -1
  73. package/dist/context.d.ts +12 -1
  74. package/dist/context.d.ts.map +1 -1
  75. package/dist/context.js.map +1 -1
  76. package/dist/index.d.ts +3 -0
  77. package/dist/index.d.ts.map +1 -1
  78. package/dist/index.js +29 -27
  79. package/package.json +5 -5
package/README.md CHANGED
@@ -52,6 +52,7 @@ import {
52
52
  InkZoomSelect,
53
53
  InkThreadPopover,
54
54
  } from '@inkbar/vue'
55
+ import { highlightTool, noteTool, redactAreaTool } from '@inkbar/core/dom'
55
56
  import type { Annotation } from '@inkbar/core'
56
57
  import { assets } from 'virtual:inkbar-assets'
57
58
  import '@inkbar/theme/theme.css'
@@ -59,12 +60,14 @@ import '@inkbar/theme/theme.css'
59
60
  defineProps<{ signedUrl: string; documentId: string }>()
60
61
 
61
62
  const annotations = ref<Annotation[]>([])
63
+ const tools = [highlightTool(), redactAreaTool(), noteTool()]
62
64
  </script>
63
65
 
64
66
  <template>
65
67
  <InkRoot
66
68
  :src="{ url: signedUrl, key: documentId }"
67
69
  :assets="assets"
70
+ :tools="tools"
68
71
  v-model:annotations="annotations"
69
72
  >
70
73
  <InkToolbar>
@@ -90,7 +93,9 @@ const annotations = ref<Annotation[]>([])
90
93
  </template>
91
94
  ```
92
95
 
93
- Each control is a separate component, so put them in any order or leave some out. Buttons show icons from `@inkbar/icons`. Put your own in a button's default slot to replace one, and use `InkIcon` to put the same icons on your own buttons.
96
+ `select-text` and `select` are always there. Every other tool is opt-in: pass the ones you offer through `tools`, from the tool factories in `@inkbar/core/dom`, or `allTools()` for all of them. A button for a tool you did not pass renders disabled and hidden, a tool menu renders nothing, and each logs an `InkError('UnknownTool')` to the console once. If the active tool leaves `tools`, the viewer switches to `select-text` and reports it through `update:tool`.
97
+
98
+ Each control is a separate component, so put them in any order or leave some out. Buttons show icons from `@inkbar/icons`. Put your own in a button's default slot to replace one, and use `InkIcon` to put the same icons on your own buttons. For a button of your own, such as `<InkToolbarButton @click="download">Download</InkToolbarButton>`, use `InkToolbarButton`: it joins the toolbar's arrow-key focus and looks like the other buttons.
94
99
 
95
100
  `v-model:annotations` makes your list the source of truth. Leave it off and Inkbar keeps the state itself, with undo and redo.
96
101
 
@@ -114,6 +119,12 @@ Inside `InkRoot`, `useHistory()` returns the same object. Its `batch(fn)` runs `
114
119
 
115
120
  `key` identifies the document. Reuse the same key when only the signed URL changes and the document is not reloaded.
116
121
 
122
+ ## Forms
123
+
124
+ `InkViewport` fills the PDF's form fields and runs the form's scripts. `useForm()` returns the fields, their values, and `set` and `reset`. Bind `v-model:fields` to hold the values in your own state. The form never submits, opens a link, sends mail or prints: `@form-action` hands each request to you. `:form-highlight="false"` turns off the field tint, and a change applies to the open document in place.
125
+
126
+ The [forms guide](https://inkbar.dev/docs/guides/forms/) covers controlled fields, form actions, scripts, signature fields and saving values as Gloss.
127
+
117
128
  ## Thread popover
118
129
 
119
130
  `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.
@@ -124,7 +135,7 @@ The highlight tool leaves `contents` free for the comment. `doc.text(page)` retu
124
135
 
125
136
  ## Signatures
126
137
 
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.
138
+ `InkSignatureMenu` lists saved signatures, picks one for the `signature` tool, removes them, and opens `InkSignatureDialog` to draw, type or upload a new one. The menu needs `signatureTool()` in `tools`. The dialog and signature form fields work without it; the dialog then only saves the signature. 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.
128
139
 
129
140
  ## Plugins
130
141
 
@@ -161,6 +172,7 @@ The scroll area takes focus. From there:
161
172
  - With the `highlight` or `redact-area` tool active, `Enter` turns the text selection into a mark.
162
173
  - With the `note` tool active, `Enter` places a note at the centre of the current page and opens it.
163
174
  - With the `signature` tool active, `Enter` places the chosen signature at the centre of the current page.
175
+ - `Ctrl` or `Cmd` + `Z` undoes. `Ctrl` or `Cmd` + `Shift` + `Z`, or `Ctrl` + `Y`, redoes. `Ctrl` and `Cmd` both work on every platform. The keys do what `InkUndo` and `InkRedo` do, from anywhere in `InkRoot`, toolbars included, and act only while that button is enabled. In a text field or editable content the keys stay with the element, so a field keeps its own text undo. In a `<select>` they are left to the browser, which does nothing with them.
164
176
 
165
177
  On a focused annotation:
166
178
 
@@ -0,0 +1,7 @@
1
+ import e from "./InkFormAlert.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkFormAlert.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkFormAlert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkFormAlert.js","names":["_sfc_main","InkFormAlert_vue_vue_type_script_setup_true_lang_default","InkFormAlert_default"],"sources":["../../src/components/InkFormAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * A form script's `app.alert`: the message and OK, shown without blocking (no overlay, not\n * modal), so the form stays usable around it. InkViewport mounts it; hosts compose nothing.\n * OK, or Escape while focus is in the alert, closes it, and focus goes back where it was. A\n * press outside leaves it open, and Escape anywhere else stays with the viewer. A new message\n * replaces the one shown.\n */\nimport { FORM_LABELS } from '@inkbar/core/dom'\nimport {\n DialogContent,\n DialogDescription,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n} from 'reka-ui'\nimport { computed, nextTick, useTemplateRef, watch } from 'vue'\n\nconst props = defineProps<{\n /** The message to show (text, not markup); `null` while none is. */\n message: string | null\n /** Counts the times a message was shown, so the same text shown again takes focus again. */\n shown: number\n /** Where focus goes when nothing it can return to is left. */\n fallback?: HTMLElement | null | undefined\n}>()\nconst emit = defineEmits<{ close: [] }>()\n\nconst open = computed(() => props.message !== null)\nconst ok = useTemplateRef<HTMLButtonElement>('ok')\n/** Where focus was when the alert opened. */\nlet returnTo: HTMLElement | null = null\n\nwatch(\n () => props.message !== null,\n (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement\n returnTo = active instanceof HTMLElement && active !== document.body ? active : null\n },\n { flush: 'sync', immediate: true }\n)\n// Another message while one shows: OK takes focus again.\nwatch(\n () => props.shown,\n () => void nextTick(() => ok.value?.focus({ preventScroll: true }))\n)\n\nfunction onOpenAutoFocus(e: Event): void {\n e.preventDefault()\n ok.value?.focus({ preventScroll: true })\n}\n\n/** Set while closing from inside the alert, which is when focus goes back. */\nlet hadFocus = false\nfunction close(): void {\n const content = ok.value?.closest('[data-ink-form-alert]')\n hadFocus = !!content?.contains(document.activeElement)\n emit('close')\n}\n\nfunction onCloseAutoFocus(e: Event): void {\n e.preventDefault()\n if (!hadFocus) return\n hadFocus = false\n const back = returnTo?.isConnected === true ? returnTo : (props.fallback ?? null)\n back?.focus({ preventScroll: true })\n}\n\nfunction onEscape(e: KeyboardEvent): void {\n const content = ok.value?.closest('[data-ink-form-alert]')\n if (!(e.target instanceof Node) || !content?.contains(e.target)) {\n e.preventDefault()\n return\n }\n e.preventDefault()\n close()\n}\n\nfunction onOpenChange(next: boolean): void {\n if (!next) close()\n}\n\n// Reka's typed props stop at its own; ARIA goes through a bound object.\nconst contentAttrs = { role: 'alertdialog' }\n</script>\n\n<template>\n <DialogRoot :open=\"open\" :modal=\"false\" @update:open=\"onOpenChange\">\n <DialogPortal>\n <DialogContent\n class=\"ink-dialog ink-form-alert\"\n data-ink-form-alert\n v-bind=\"contentAttrs\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @interact-outside.prevent\n @escape-key-down=\"onEscape\"\n >\n <DialogTitle class=\"ink-dialog-title\">{{ FORM_LABELS.alert }}</DialogTitle>\n <!-- Set as text, without the whitespace a template would add around it. -->\n <DialogDescription as-child>\n <p\n class=\"ink-form-alert-message\"\n data-ink-form-alert-message\n v-text=\"props.message\"\n />\n </DialogDescription>\n <div class=\"ink-dialog-actions\">\n <button\n ref=\"ok\"\n type=\"button\"\n class=\"ink-button\"\n data-variant=\"primary\"\n data-ink-form-alert-ok\n @click=\"close\"\n >\n {{ FORM_LABELS.ok }}\n </button>\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1,16 @@
1
+ type __VLS_Props = {
2
+ /** The message to show (text, not markup); `null` while none is. */
3
+ message: string | null;
4
+ /** Counts the times a message was shown, so the same text shown again takes focus again. */
5
+ shown: number;
6
+ /** Where focus goes when nothing it can return to is left. */
7
+ fallback?: HTMLElement | null | undefined;
8
+ };
9
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
10
+ close: () => any;
11
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ onClose?: () => any;
13
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
16
+ //# sourceMappingURL=InkFormAlert.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkFormAlert.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkFormAlert.vue"],"names":[],"mappings":"AAgJA,KAAK,WAAW,GAAG;IACjB,oEAAoE;IACpE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAA;CAC1C,CAAC;AAsNF,QAAA,MAAM,YAAY;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -0,0 +1,90 @@
1
+ import { computed as e, createBlock as t, createElementVNode as n, createTextVNode as r, createVNode as i, defineComponent as a, mergeProps as o, nextTick as s, openBlock as c, toDisplayString as l, unref as u, useTemplateRef as d, watch as f, withCtx as p, withModifiers as m } from "vue";
2
+ import { FORM_LABELS as h } from "@inkbar/core/dom";
3
+ import { DialogContent as g, DialogDescription as _, DialogPortal as v, DialogRoot as y, DialogTitle as b } from "reka-ui";
4
+ //#region src/components/InkFormAlert.vue?vue&type=script&setup=true&lang.ts
5
+ var x = ["textContent"], S = { class: "ink-dialog-actions" }, C = /*@__PURE__*/ a({
6
+ __name: "InkFormAlert",
7
+ props: {
8
+ message: {},
9
+ shown: {},
10
+ fallback: {}
11
+ },
12
+ emits: ["close"],
13
+ setup(a, { emit: C }) {
14
+ let w = a, T = C, E = e(() => w.message !== null), D = d("ok"), O = null;
15
+ f(() => w.message !== null, (e) => {
16
+ if (!e) return;
17
+ let t = document.activeElement;
18
+ O = t instanceof HTMLElement && t !== document.body ? t : null;
19
+ }, {
20
+ flush: "sync",
21
+ immediate: !0
22
+ }), f(() => w.shown, () => void s(() => D.value?.focus({ preventScroll: !0 })));
23
+ function k(e) {
24
+ e.preventDefault(), D.value?.focus({ preventScroll: !0 });
25
+ }
26
+ let A = !1;
27
+ function j() {
28
+ A = !!(D.value?.closest("[data-ink-form-alert]"))?.contains(document.activeElement), T("close");
29
+ }
30
+ function M(e) {
31
+ e.preventDefault(), A && (A = !1, (O?.isConnected === !0 ? O : w.fallback ?? null)?.focus({ preventScroll: !0 }));
32
+ }
33
+ function N(e) {
34
+ let t = D.value?.closest("[data-ink-form-alert]");
35
+ !(e.target instanceof Node) || !t?.contains(e.target) ? e.preventDefault() : (e.preventDefault(), j());
36
+ }
37
+ function P(e) {
38
+ e || j();
39
+ }
40
+ let F = { role: "alertdialog" };
41
+ return (e, a) => (c(), t(u(y), {
42
+ open: E.value,
43
+ modal: !1,
44
+ "onUpdate:open": P
45
+ }, {
46
+ default: p(() => [i(u(v), null, {
47
+ default: p(() => [i(u(g), o({
48
+ class: "ink-dialog ink-form-alert",
49
+ "data-ink-form-alert": ""
50
+ }, F, {
51
+ onOpenAutoFocus: k,
52
+ onCloseAutoFocus: M,
53
+ onInteractOutside: a[0] ||= m(() => {}, ["prevent"]),
54
+ onEscapeKeyDown: N
55
+ }), {
56
+ default: p(() => [
57
+ i(u(b), { class: "ink-dialog-title" }, {
58
+ default: p(() => [r(l(u(h).alert), 1)]),
59
+ _: 1
60
+ }),
61
+ i(u(_), { "as-child": "" }, {
62
+ default: p(() => [n("p", {
63
+ class: "ink-form-alert-message",
64
+ "data-ink-form-alert-message": "",
65
+ textContent: l(w.message)
66
+ }, null, 8, x)]),
67
+ _: 1
68
+ }),
69
+ n("div", S, [n("button", {
70
+ ref_key: "ok",
71
+ ref: D,
72
+ type: "button",
73
+ class: "ink-button",
74
+ "data-variant": "primary",
75
+ "data-ink-form-alert-ok": "",
76
+ onClick: j
77
+ }, l(u(h).ok), 513)])
78
+ ]),
79
+ _: 1
80
+ }, 16)]),
81
+ _: 1
82
+ })]),
83
+ _: 1
84
+ }, 8, ["open"]));
85
+ }
86
+ });
87
+ //#endregion
88
+ export { C as default };
89
+
90
+ //# sourceMappingURL=InkFormAlert.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkFormAlert.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","_unref","_withCtx","_createVNode","_mergeProps","_withModifiers","_createTextVNode","_toDisplayString","_createElementVNode","_hoisted_1","_hoisted_2","InkFormAlert_vue_vue_type_script_setup_true_lang_default","__emit","props","__props","emit","open","computed","ok","useTemplateRef","returnTo","watch","isOpen","active","nextTick","onOpenAutoFocus","hadFocus","close","onCloseAutoFocus","onEscape","content","onOpenChange","next","contentAttrs","openBlock","createBlock","unref","DialogRoot","withCtx","createVNode","DialogPortal","DialogContent","mergeProps","_cache","withModifiers","DialogTitle","createTextVNode","toDisplayString","FORM_LABELS","DialogDescription","createElementVNode"],"sources":["../../src/components/InkFormAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * A form script's `app.alert`: the message and OK, shown without blocking (no overlay, not\n * modal), so the form stays usable around it. InkViewport mounts it; hosts compose nothing.\n * OK, or Escape while focus is in the alert, closes it, and focus goes back where it was. A\n * press outside leaves it open, and Escape anywhere else stays with the viewer. A new message\n * replaces the one shown.\n */\nimport { FORM_LABELS } from '@inkbar/core/dom'\nimport {\n DialogContent,\n DialogDescription,\n DialogPortal,\n DialogRoot,\n DialogTitle,\n} from 'reka-ui'\nimport { computed, nextTick, useTemplateRef, watch } from 'vue'\n\nconst props = defineProps<{\n /** The message to show (text, not markup); `null` while none is. */\n message: string | null\n /** Counts the times a message was shown, so the same text shown again takes focus again. */\n shown: number\n /** Where focus goes when nothing it can return to is left. */\n fallback?: HTMLElement | null | undefined\n}>()\nconst emit = defineEmits<{ close: [] }>()\n\nconst open = computed(() => props.message !== null)\nconst ok = useTemplateRef<HTMLButtonElement>('ok')\n/** Where focus was when the alert opened. */\nlet returnTo: HTMLElement | null = null\n\nwatch(\n () => props.message !== null,\n (isOpen) => {\n if (!isOpen) return\n const active = document.activeElement\n returnTo = active instanceof HTMLElement && active !== document.body ? active : null\n },\n { flush: 'sync', immediate: true }\n)\n// Another message while one shows: OK takes focus again.\nwatch(\n () => props.shown,\n () => void nextTick(() => ok.value?.focus({ preventScroll: true }))\n)\n\nfunction onOpenAutoFocus(e: Event): void {\n e.preventDefault()\n ok.value?.focus({ preventScroll: true })\n}\n\n/** Set while closing from inside the alert, which is when focus goes back. */\nlet hadFocus = false\nfunction close(): void {\n const content = ok.value?.closest('[data-ink-form-alert]')\n hadFocus = !!content?.contains(document.activeElement)\n emit('close')\n}\n\nfunction onCloseAutoFocus(e: Event): void {\n e.preventDefault()\n if (!hadFocus) return\n hadFocus = false\n const back = returnTo?.isConnected === true ? returnTo : (props.fallback ?? null)\n back?.focus({ preventScroll: true })\n}\n\nfunction onEscape(e: KeyboardEvent): void {\n const content = ok.value?.closest('[data-ink-form-alert]')\n if (!(e.target instanceof Node) || !content?.contains(e.target)) {\n e.preventDefault()\n return\n }\n e.preventDefault()\n close()\n}\n\nfunction onOpenChange(next: boolean): void {\n if (!next) close()\n}\n\n// Reka's typed props stop at its own; ARIA goes through a bound object.\nconst contentAttrs = { role: 'alertdialog' }\n</script>\n\n<template>\n <DialogRoot :open=\"open\" :modal=\"false\" @update:open=\"onOpenChange\">\n <DialogPortal>\n <DialogContent\n class=\"ink-dialog ink-form-alert\"\n data-ink-form-alert\n v-bind=\"contentAttrs\"\n @open-auto-focus=\"onOpenAutoFocus\"\n @close-auto-focus=\"onCloseAutoFocus\"\n @interact-outside.prevent\n @escape-key-down=\"onEscape\"\n >\n <DialogTitle class=\"ink-dialog-title\">{{ FORM_LABELS.alert }}</DialogTitle>\n <!-- Set as text, without the whitespace a template would add around it. -->\n <DialogDescription as-child>\n <p\n class=\"ink-form-alert-message\"\n data-ink-form-alert-message\n v-text=\"props.message\"\n />\n </DialogDescription>\n <div class=\"ink-dialog-actions\">\n <button\n ref=\"ok\"\n type=\"button\"\n class=\"ink-button\"\n data-variant=\"primary\"\n data-ink-form-alert-ok\n @click=\"close\"\n >\n {{ FORM_LABELS.ok }}\n </button>\n </div>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n"],"mappings":";;;;;;;;;;;;;EAkBA,IAAMc,IAAQC,GAQRC,IAAOH,GAEPI,IAAOC,QAAeJ,EAAM,YAAY,IAAI,GAC5CK,IAAKC,EAAkC,IAAI,GAE7CC,IAA+B;EAYnC,AAVAC,QACQR,EAAM,YAAY,OACvB,MAAW;GACV,IAAI,CAACS,GAAQ;GACb,IAAMC,IAAS,SAAS;GACxB,IAAWA,aAAkB,eAAeA,MAAW,SAAS,OAAOA,IAAS;EAClF,GACA;GAAE,OAAO;GAAQ,WAAW;EAAK,CACnC,GAEAF,QACQR,EAAM,aACN,KAAKW,QAAeN,EAAG,OAAO,MAAM,EAAE,eAAe,GAAK,CAAC,CAAC,CACpE;EAEA,SAASO,EAAgB,GAAgB;GAEvC,AADA,EAAE,eAAe,GACjBP,EAAG,OAAO,MAAM,EAAE,eAAe,GAAK,CAAC;EACzC;EAGA,IAAIQ,IAAW;EACf,SAASC,IAAc;GAGrB,AADA,IAAW,CAAC,EADIT,EAAG,OAAO,QAAQ,uBAAuB,EAAA,EACnC,SAAS,SAAS,aAAa,GACrDH,EAAK,OAAO;EACd;EAEA,SAASa,EAAiB,GAAgB;GAExC,AADA,EAAE,eAAe,GACZF,MACL,IAAW,KACEN,GAAU,gBAAgB,KAAOA,IAAYP,EAAM,YAAY,KAAA,EACtE,MAAM,EAAE,eAAe,GAAK,CAAC;EACrC;EAEA,SAASgB,EAAS,GAAwB;GACxC,IAAMC,IAAUZ,EAAG,OAAO,QAAQ,uBAAuB;GACzD,AAAI,EAAE,EAAE,kBAAkB,SAAS,CAACY,GAAS,SAAS,EAAE,MAAM,IAC5D,EAAE,eAAe,KAGnB,EAAE,eAAe,GACjBH,EAAM;EACR;EAEA,SAASI,EAAa,GAAqB;GACzC,AAAKC,KAAML,EAAM;EACnB;EAGA,IAAMM,IAAe,EAAE,MAAM,cAAc;oBAIzClC,EAAA,GAAAC,EAkCaC,EAAAoC,CAAA,GAAA;GAlCA,MAAMrB,EAAA;GAAO,OAAO;GAAQ,iBAAae;;GACpD,SAAA7B,QAgCe,CAhCfC,EAgCeF,EAAAuC,CAAA,GAAA,MAAA;IA/Bb,SAAAtC,QA8BgB,CA9BhBC,EA8BgBF,EAAAwC,CAAA,GA9BhBrC,EA8BgB;KA7Bd,OAAM;KACN,uBAAA;IACQ,GAAA6B,GAAY;KACF;KACC;KAClB,mBAAgB,AAAAU,EAAA,OAAAtC,QAAjB,CAAA,GAAyB,CAAA,SAAA,CAAA;KACxB,iBAAiBwB;;KAElB,SAAA3B,QAA2E;MAA3EC,EAA2EF,EAAA4C,CAAA,GAAA,EAA9D,OAAM,mBAAkB,GAAA;OAAC,SAAA3C,QAAuB,CAApBI,EAAAC,EAAAN,EAAA+C,CAAA,CAAW,CAAC,KAAK,GAAA,CAAA,CAAA,CAAA;;;MAE1D7C,EAMoBF,EAAAgD,CAAA,GAAA,EAND,YAAA,GAAQ,GAAA;OACzB,SAAA/C,QAIE,CAJFM,EAIE,KAAA;QAHA,OAAM;QACN,+BAAA;QACA,aAAAD,EAAQM,EAAM,OAAO;;;;MAGzBL,EAWM,OAXNE,GAWM,CAVJF,EASS,UAAA;OARH,SAAA;OAAJ,KAAIU;OACJ,MAAK;OACL,OAAM;OACN,gBAAa;OACb,0BAAA;OACC,SAAOS;MAEL,GAAApB,EAAAN,EAAA+C,CAAA,CAAW,CAAC,EAAE,GAAA,GAAA,CAAA,CAAA"}
@@ -1 +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
+ {"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 { useRegisteredTool } from '../composables/useRegisteredTool'\nimport { useTool } from '../composables/useTool'\nimport { useToolOptionsWhile } from '../composables/useToolOptions'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\ndefineOptions({ inheritAttrs: false })\nconst { tool, setTool } = useTool()\n// Nothing renders while no `highlight` tool is registered.\nconst registered = useRegisteredTool('highlight')\nconst { options, setOptions } = useToolOptionsWhile<HighlightOptions>(\n 'highlight',\n registered\n)\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-if=\"registered\" 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 +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"}
1
+ {"version":3,"file":"InkHighlightMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkHighlightMenu.vue"],"names":[],"mappings":"AAgjBA,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"}
@@ -1,99 +1,101 @@
1
- import { useDocument as e } from "../composables/useDocument.js";
2
- import { useTool as t } from "../composables/useTool.js";
3
- import { useToolOptions as n } from "../composables/useToolOptions.js";
4
- import r from "./InkIcon.js";
5
- import i from "./InkColorMenu.js";
6
- import { Fragment as a, computed as o, createBlock as s, createElementBlock as c, createElementVNode as l, createTextVNode as u, createVNode as d, defineComponent as f, guardReactiveProps as p, mergeProps as m, normalizeProps as h, openBlock as g, ref as _, renderList as v, renderSlot as y, toDisplayString as b, unref as x, withCtx as S } from "vue";
7
- import { MARKUP_ICONS as C, MARKUP_KINDS as w, focusInitialMenuItem as T, handleMenuKeys as E, highlightMenuModel as D, menuItems as O } from "@inkbar/core/dom";
8
- import { PopoverAnchor as k, PopoverContent as A, PopoverPortal as j, PopoverRoot as M, PopoverTrigger as N, ToolbarButton as P } from "reka-ui";
9
- import { ChevronDown as F } from "@inkbar/icons";
1
+ import { useRegisteredTool as e } from "../composables/useRegisteredTool.js";
2
+ import { useDocument as t } from "../composables/useDocument.js";
3
+ import { useTool as n } from "../composables/useTool.js";
4
+ import { useToolOptionsWhile as r } from "../composables/useToolOptions.js";
5
+ import i from "./InkIcon.js";
6
+ import a from "./InkColorMenu.js";
7
+ import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createTextVNode as f, createVNode as p, defineComponent as m, guardReactiveProps as h, mergeProps as g, normalizeProps as _, openBlock as v, ref as y, renderList as b, renderSlot as x, toDisplayString as S, unref as C, withCtx as w } from "vue";
8
+ import { MARKUP_ICONS as T, MARKUP_KINDS as E, focusInitialMenuItem as D, handleMenuKeys as O, highlightMenuModel as k, menuItems as A } from "@inkbar/core/dom";
9
+ import { PopoverAnchor as j, PopoverContent as M, PopoverPortal as N, PopoverRoot as P, PopoverTrigger as F, ToolbarButton as I } from "reka-ui";
10
+ import { ChevronDown as L } from "@inkbar/icons";
10
11
  //#region src/components/InkHighlightMenu.vue?vue&type=script&setup=true&lang.ts
11
- var ee = ["data-state"], I = {
12
+ var R = ["data-state"], z = {
12
13
  role: "group",
13
14
  "aria-label": "Kinds",
14
15
  class: "ink-highlight-kinds"
15
- }, L = [
16
+ }, B = [
16
17
  "data-key",
17
18
  "aria-checked",
18
19
  "data-state",
19
20
  "onClick"
20
- ], R = {
21
+ ], ee = {
21
22
  role: "group",
22
23
  "aria-label": "Colour",
23
24
  class: "ink-highlight-colour"
24
- }, z = /*@__PURE__*/ f({
25
+ }, V = /*@__PURE__*/ m({
25
26
  inheritAttrs: !1,
26
27
  __name: "InkHighlightMenu",
27
- setup(f) {
28
- let { tool: z, setTool: B } = t(), { options: V, setOptions: H } = n("highlight"), { document: U } = e(), W = _(!1), G = o(() => D(V.value, w)), K = o(() => z.value === "highlight"), q = o(() => U.value?.annotations.defaults.color(G.value.kind)), J = o(() => C[G.value.kind]), Y = !1;
29
- function X(e) {
30
- e.key !== "ArrowDown" || e.defaultPrevented || W.value || (e.preventDefault(), Y = !0, W.value = !0);
28
+ setup(m) {
29
+ let { tool: V, setTool: H } = n(), U = e("highlight"), { options: W, setOptions: G } = r("highlight", U), { document: K } = t(), q = y(!1), J = s(() => k(W.value, E)), Y = s(() => V.value === "highlight"), X = s(() => K.value?.annotations.defaults.color(J.value.kind)), Z = s(() => T[J.value.kind]), Q = !1;
30
+ function $(e) {
31
+ e.key !== "ArrowDown" || e.defaultPrevented || q.value || (e.preventDefault(), Q = !0, q.value = !0);
31
32
  }
32
- function Z(e) {
33
+ function te(e) {
33
34
  e.preventDefault();
34
35
  let t = document.querySelector("[data-ink-menu=\"highlight\"] [role=\"menu\"]");
35
- t && (Y ? O(t)[0]?.focus({ preventScroll: !0 }) : T(t)), Y = !1;
36
+ t && (Q ? A(t)[0]?.focus({ preventScroll: !0 }) : D(t)), Q = !1;
36
37
  }
37
- function Q(e) {
38
- H({ kind: e }), B("highlight"), W.value = !1;
38
+ function ne(e) {
39
+ G({ kind: e }), H("highlight"), q.value = !1;
39
40
  }
40
- let $ = o(() => ({
41
- "aria-pressed": String(K.value),
42
- "aria-label": G.value.label,
43
- title: G.value.label,
44
- onClick: () => B("highlight")
45
- })), te = {
41
+ let re = s(() => ({
42
+ "aria-pressed": String(Y.value),
43
+ "aria-label": J.value.label,
44
+ title: J.value.label,
45
+ onClick: () => H("highlight")
46
+ })), ie = {
46
47
  "aria-label": "Choose highlight",
47
48
  title: "Choose highlight",
48
49
  "aria-haspopup": "menu",
49
- onKeydown: X
50
- }, ne = { "aria-label": "Highlights" }, re = {
50
+ onKeydown: $
51
+ }, ae = { "aria-label": "Highlights" }, oe = {
51
52
  role: "menuitem",
52
53
  tabindex: -1
53
- }, ie = {
54
+ }, se = {
54
55
  role: "menu",
55
56
  "aria-label": "Highlights",
56
- onKeydownCapture: (e) => E(e, e.currentTarget)
57
+ onKeydownCapture: (e) => O(e, e.currentTarget)
57
58
  };
58
- return (e, t) => (g(), s(x(M), {
59
- open: W.value,
60
- "onUpdate:open": t[0] ||= (e) => W.value = e
59
+ return (e, t) => C(U) ? (v(), c(C(P), {
60
+ key: 0,
61
+ open: q.value,
62
+ "onUpdate:open": t[0] ||= (e) => q.value = e
61
63
  }, {
62
- default: S(() => [d(x(k), { "as-child": "" }, {
63
- default: S(() => [l("div", m({
64
+ default: w(() => [p(C(j), { "as-child": "" }, {
65
+ default: w(() => [d("div", g({
64
66
  role: "group",
65
67
  "aria-label": "Highlight",
66
68
  class: "ink-split-button ink-highlight-menu",
67
69
  "data-ink-highlight-menu": ""
68
70
  }, e.$attrs), [
69
- d(x(P), m({
71
+ p(C(I), g({
70
72
  class: "ink-tool-button ink-highlight-button",
71
73
  "data-ink-tool-button": "",
72
74
  "data-ink-highlight-button": "",
73
75
  "data-tool": "highlight",
74
- "data-kind": G.value.kind,
75
- "data-state": K.value ? "on" : "off"
76
- }, $.value), {
77
- default: S(() => [y(e.$slots, "default", {
78
- active: K.value,
79
- kind: G.value.kind
80
- }, () => [d(r, { icon: J.value }, null, 8, ["icon"])])]),
76
+ "data-kind": J.value.kind,
77
+ "data-state": Y.value ? "on" : "off"
78
+ }, re.value), {
79
+ default: w(() => [x(e.$slots, "default", {
80
+ active: Y.value,
81
+ kind: J.value.kind
82
+ }, () => [p(i, { icon: Z.value }, null, 8, ["icon"])])]),
81
83
  _: 3
82
84
  }, 16, ["data-kind", "data-state"]),
83
- d(x(P), { "as-child": "" }, {
84
- default: S(() => [d(x(N), { "as-child": "" }, {
85
- default: S(() => [l("button", m({
85
+ p(C(I), { "as-child": "" }, {
86
+ default: w(() => [p(C(F), { "as-child": "" }, {
87
+ default: w(() => [d("button", g({
86
88
  type: "button",
87
89
  class: "ink-menu-trigger ink-highlight-menu-trigger",
88
90
  "data-ink-highlight-menu-trigger": "",
89
- "data-state": W.value ? "open" : "closed"
90
- }, te), [d(r, { icon: x(F) }, null, 8, ["icon"])], 16, ee)]),
91
+ "data-state": q.value ? "open" : "closed"
92
+ }, ie), [p(i, { icon: C(L) }, null, 8, ["icon"])], 16, R)]),
91
93
  _: 1
92
94
  })]),
93
95
  _: 1
94
96
  }),
95
- d(x(j), null, {
96
- default: S(() => [d(x(A), m({
97
+ p(C(N), null, {
98
+ default: w(() => [p(C(M), g({
97
99
  class: "ink-select-content ink-menu-content",
98
100
  "data-ink-select-content": "",
99
101
  "data-ink-menu": "highlight",
@@ -101,9 +103,9 @@ var ee = ["data-state"], I = {
101
103
  align: "start",
102
104
  "side-offset": 4,
103
105
  "collision-padding": 8
104
- }, ne, { onOpenAutoFocus: Z }), {
105
- default: S(() => [l("div", h(p(ie)), [
106
- l("div", I, [(g(!0), c(a, null, v(G.value.items, (e) => (g(), c("button", {
106
+ }, ae, { onOpenAutoFocus: te }), {
107
+ default: w(() => [d("div", _(h(se)), [
108
+ d("div", z, [(v(!0), u(o, null, b(J.value.items, (e) => (v(), u("button", {
107
109
  key: e.kind,
108
110
  type: "button",
109
111
  role: "menuitemradio",
@@ -113,25 +115,25 @@ var ee = ["data-state"], I = {
113
115
  "data-key": e.kind,
114
116
  "aria-checked": e.checked,
115
117
  "data-state": e.checked ? "checked" : "unchecked",
116
- onClick: (t) => Q(e.kind)
117
- }, [d(r, {
118
- icon: x(C)[e.kind],
118
+ onClick: (t) => ne(e.kind)
119
+ }, [p(i, {
120
+ icon: C(T)[e.kind],
119
121
  size: 16
120
- }, null, 8, ["icon"]), u(" " + b(e.label), 1)], 8, L))), 128))]),
121
- t[2] ||= l("div", {
122
+ }, null, 8, ["icon"]), f(" " + S(e.label), 1)], 8, B))), 128))]),
123
+ t[2] ||= d("div", {
122
124
  role: "separator",
123
125
  class: "ink-select-separator"
124
126
  }, null, -1),
125
- l("div", R, [t[1] ||= l("span", {
127
+ d("div", ee, [t[1] ||= d("span", {
126
128
  class: "ink-highlight-colour-label",
127
129
  "aria-hidden": "true"
128
- }, "Colour", -1), d(i, m({
130
+ }, "Colour", -1), p(a, g({
129
131
  property: "border",
130
132
  group: "markup",
131
133
  label: "Highlight colour",
132
134
  standalone: "",
133
- fallback: q.value
134
- }, re), null, 16, ["fallback"])])
135
+ fallback: X.value
136
+ }, oe), null, 16, ["fallback"])])
135
137
  ], 16)]),
136
138
  _: 1
137
139
  }, 16)]),
@@ -141,10 +143,10 @@ var ee = ["data-state"], I = {
141
143
  _: 3
142
144
  })]),
143
145
  _: 3
144
- }, 8, ["open"]));
146
+ }, 8, ["open"])) : l("", !0);
145
147
  }
146
148
  });
147
149
  //#endregion
148
- export { z as default };
150
+ export { V as default };
149
151
 
150
152
  //# sourceMappingURL=InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InkHighlightMenu.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_openBlock","_createBlock","_unref","_withCtx","_createVNode","_createElementVNode","_mergeProps","_renderSlot","InkIcon","_normalizeProps","_guardReactiveProps","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","InkColorMenu","InkIcon_default","InkColorMenu_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","InkHighlightMenu_vue_vue_type_script_setup_true_lang_default","useTool","useToolOptions","doc","useDocument","open","ref","model","computed","highlightMenuModel","options","MARKUP_KINDS","active","tool","fallback","icon","MARKUP_ICONS","focusFirst","onTriggerKeydown","onOpenAutoFocus","menu","menuItems","focusInitialMenuItem","choose","setOptions","setTool","mainAttrs","triggerAttrs","menuAttrs","colourAttrs","innerAttrs","handleMenuKeys","openBlock","createBlock","unref","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","createElementVNode","mergeProps","_ctx","ToolbarButton","renderSlot","PopoverTrigger","ChevronDown","PopoverPortal","PopoverContent","normalizeProps","guardReactiveProps","createElementBlock","Fragment","renderList","item","createTextVNode","toDisplayString"],"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":"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"}
1
+ {"version":3,"file":"InkHighlightMenu.vue_vue_type_script_setup_true_lang.js","names":["$attrs","_unref","_openBlock","_createBlock","_withCtx","_createVNode","_createElementVNode","_mergeProps","_renderSlot","InkIcon","_normalizeProps","_guardReactiveProps","_createElementBlock","_Fragment","_renderList","_createTextVNode","_toDisplayString","InkColorMenu","_createCommentVNode","InkIcon_default","InkColorMenu_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","InkHighlightMenu_vue_vue_type_script_setup_true_lang_default","useTool","registered","useRegisteredTool","useToolOptionsWhile","doc","useDocument","open","ref","model","computed","highlightMenuModel","options","MARKUP_KINDS","active","tool","fallback","icon","MARKUP_ICONS","focusFirst","onTriggerKeydown","onOpenAutoFocus","menu","menuItems","focusInitialMenuItem","choose","setOptions","setTool","mainAttrs","triggerAttrs","menuAttrs","colourAttrs","innerAttrs","handleMenuKeys","unref","openBlock","createBlock","PopoverRoot","_cache","$event","withCtx","createVNode","PopoverAnchor","createElementVNode","mergeProps","_ctx","ToolbarButton","renderSlot","PopoverTrigger","ChevronDown","PopoverPortal","PopoverContent","normalizeProps","guardReactiveProps","createElementBlock","Fragment","renderList","item","createTextVNode","toDisplayString","createCommentVNode"],"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 { useRegisteredTool } from '../composables/useRegisteredTool'\nimport { useTool } from '../composables/useTool'\nimport { useToolOptionsWhile } from '../composables/useToolOptions'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\ndefineOptions({ inheritAttrs: false })\nconst { tool, setTool } = useTool()\n// Nothing renders while no `highlight` tool is registered.\nconst registered = useRegisteredTool('highlight')\nconst { options, setOptions } = useToolOptionsWhile<HighlightOptions>(\n 'highlight',\n registered\n)\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-if=\"registered\" 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":"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"}