@inkbar/vue 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +16 -9
  2. package/dist/components/InkColorMenu.js +7 -0
  3. package/dist/components/InkColorMenu.js.map +1 -0
  4. package/dist/components/InkColorMenu.vue.d.ts +32 -0
  5. package/dist/components/InkColorMenu.vue.d.ts.map +1 -0
  6. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js +152 -0
  7. package/dist/components/InkColorMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  8. package/dist/components/InkHighlightMenu.js +7 -0
  9. package/dist/components/InkHighlightMenu.js.map +1 -0
  10. package/dist/components/InkHighlightMenu.vue.d.ts +17 -0
  11. package/dist/components/InkHighlightMenu.vue.d.ts.map +1 -0
  12. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js +140 -0
  13. package/dist/components/InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  14. package/dist/components/InkLineStyleMenu.js +7 -0
  15. package/dist/components/InkLineStyleMenu.js.map +1 -0
  16. package/dist/components/InkLineStyleMenu.vue.d.ts +14 -0
  17. package/dist/components/InkLineStyleMenu.vue.d.ts.map +1 -0
  18. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js +109 -0
  19. package/dist/components/InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  20. package/dist/components/InkRoot.js.map +1 -1
  21. package/dist/components/InkRoot.vue.d.ts +573 -29
  22. package/dist/components/InkRoot.vue.d.ts.map +1 -1
  23. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js +117 -88
  24. package/dist/components/InkRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/InkShapeMenu.js +7 -0
  26. package/dist/components/InkShapeMenu.js.map +1 -0
  27. package/dist/components/InkShapeMenu.vue.d.ts +18 -0
  28. package/dist/components/InkShapeMenu.vue.d.ts.map +1 -0
  29. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js +118 -0
  30. package/dist/components/InkShapeMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  31. package/dist/components/InkSignatureDialog.js +7 -0
  32. package/dist/components/InkSignatureDialog.js.map +1 -0
  33. package/dist/components/InkSignatureDialog.vue.d.ts +21 -0
  34. package/dist/components/InkSignatureDialog.vue.d.ts.map +1 -0
  35. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js +58 -0
  36. package/dist/components/InkSignatureDialog.vue_vue_type_script_setup_true_lang.js.map +1 -0
  37. package/dist/components/InkSignatureMenu.js +7 -0
  38. package/dist/components/InkSignatureMenu.js.map +1 -0
  39. package/dist/components/InkSignatureMenu.vue.d.ts +20 -0
  40. package/dist/components/InkSignatureMenu.vue.d.ts.map +1 -0
  41. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js +213 -0
  42. package/dist/components/InkSignatureMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  43. package/dist/components/InkTextStyleMenu.js +7 -0
  44. package/dist/components/InkTextStyleMenu.js.map +1 -0
  45. package/dist/components/InkTextStyleMenu.vue.d.ts +14 -0
  46. package/dist/components/InkTextStyleMenu.vue.d.ts.map +1 -0
  47. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js +200 -0
  48. package/dist/components/InkTextStyleMenu.vue_vue_type_script_setup_true_lang.js.map +1 -0
  49. package/dist/components/InkThreadPopover.js +7 -0
  50. package/dist/components/InkThreadPopover.js.map +1 -0
  51. package/dist/components/{InkNotePopover.vue.d.ts → InkThreadPopover.vue.d.ts} +4 -4
  52. package/dist/components/InkThreadPopover.vue.d.ts.map +1 -0
  53. package/dist/components/{InkNotePopover.vue_vue_type_script_setup_true_lang.js → InkThreadPopover.vue_vue_type_script_setup_true_lang.js} +44 -42
  54. package/dist/components/InkThreadPopover.vue_vue_type_script_setup_true_lang.js.map +1 -0
  55. package/dist/components/InkToolButton.js.map +1 -1
  56. package/dist/components/InkToolButton.vue.d.ts.map +1 -1
  57. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js +27 -20
  58. package/dist/components/InkToolButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  59. package/dist/components/InkViewport.js.map +1 -1
  60. package/dist/components/InkViewport.vue.d.ts +1 -1
  61. package/dist/components/InkViewport.vue.d.ts.map +1 -1
  62. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js +6 -0
  63. package/dist/components/InkViewport.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/SignatureForm.js +7 -0
  65. package/dist/components/SignatureForm.js.map +1 -0
  66. package/dist/components/SignatureForm.vue.d.ts +14 -0
  67. package/dist/components/SignatureForm.vue.d.ts.map +1 -0
  68. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js +181 -0
  69. package/dist/components/SignatureForm.vue_vue_type_script_setup_true_lang.js.map +1 -0
  70. package/dist/composables/useAnnotations.d.ts +1523 -131
  71. package/dist/composables/useAnnotations.d.ts.map +1 -1
  72. package/dist/composables/useAnnotations.js.map +1 -1
  73. package/dist/composables/useToolOptions.d.ts +11 -0
  74. package/dist/composables/useToolOptions.d.ts.map +1 -0
  75. package/dist/composables/useToolOptions.js +16 -0
  76. package/dist/composables/useToolOptions.js.map +1 -0
  77. package/dist/composables/useToolStyle.d.ts +32 -0
  78. package/dist/composables/useToolStyle.d.ts.map +1 -0
  79. package/dist/composables/useToolStyle.js +24 -0
  80. package/dist/composables/useToolStyle.js.map +1 -0
  81. package/dist/context.d.ts +14 -2
  82. package/dist/context.d.ts.map +1 -1
  83. package/dist/context.js.map +1 -1
  84. package/dist/index.d.ts +12 -2
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +33 -24
  87. package/package.json +5 -5
  88. package/dist/components/InkNotePopover.js +0 -7
  89. package/dist/components/InkNotePopover.js.map +0 -1
  90. package/dist/components/InkNotePopover.vue.d.ts.map +0 -1
  91. package/dist/components/InkNotePopover.vue_vue_type_script_setup_true_lang.js.map +0 -1
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 review redactions. `@inkbar/vue` gives you components and composables to build your own toolbars, plus thread and suggestion popovers, 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,7 +50,7 @@ import {
50
50
  InkPageCount,
51
51
  InkNextPage,
52
52
  InkZoomSelect,
53
- InkNotePopover,
53
+ InkThreadPopover,
54
54
  InkSuggestionCard,
55
55
  } from '@inkbar/vue'
56
56
  import type { Annotation } from '@inkbar/core'
@@ -69,7 +69,7 @@ const annotations = ref<Annotation[]>([])
69
69
  v-model:annotations="annotations"
70
70
  >
71
71
  <InkToolbar>
72
- <InkToolButton tool="view" />
72
+ <InkToolButton tool="select-text" />
73
73
  <InkToolButton tool="select" />
74
74
  <InkToolButton tool="highlight" />
75
75
  <InkToolButton tool="redact-area" />
@@ -86,7 +86,7 @@ const annotations = ref<Annotation[]>([])
86
86
  <InkNextPage />
87
87
  <InkZoomSelect />
88
88
  </InkToolbar>
89
- <InkNotePopover />
89
+ <InkThreadPopover />
90
90
  <InkSuggestionCard />
91
91
  </InkRoot>
92
92
  </template>
@@ -116,15 +116,21 @@ Inside `InkRoot`, `useHistory()` returns the same object. Its `batch(fn)` runs `
116
116
 
117
117
  `key` identifies the document. Reuse the same key when only the signed URL changes and the document is not reloaded.
118
118
 
119
- ## Note popover
119
+ ## Thread popover
120
120
 
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.
121
+ `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
122
 
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.
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. 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.
124
+
125
+ 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.
126
+
127
+ ## Signatures
128
+
129
+ `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
130
 
125
131
  ## Custom rendering
126
132
 
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.
133
+ Slots let you render parts yourself. `InkViewport` has `loading`, `empty`, `error`, `annotation` and `page-error` slots. `InkThreadPopover` 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`, `ThreadPopoverSlotProps` and `SuggestionCardSlotProps`, the same types the React and Svelte packages export.
128
134
 
129
135
  `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
136
 
@@ -134,6 +140,7 @@ The scroll area takes focus. From there:
134
140
 
135
141
  - With the `highlight` or `redact-area` tool active, `Enter` turns the text selection into a mark.
136
142
  - With the `note` tool active, `Enter` places a note at the centre of the current page and opens it.
143
+ - With the `signature` tool active, `Enter` places the chosen signature at the centre of the current page.
137
144
 
138
145
  On a focused annotation:
139
146
 
@@ -151,7 +158,7 @@ Components carry state on data attributes, for example `[data-annotation][data-s
151
158
 
152
159
  ## Composables
153
160
 
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.
161
+ `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
162
 
156
163
  ## Licence
157
164
 
@@ -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}>()\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)\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,32 @@
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
+ };
19
+ declare var __VLS_21: {};
20
+ type __VLS_Slots = {} & {
21
+ default?: (props: typeof __VLS_21) => any;
22
+ };
23
+ 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>;
24
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
25
+ declare const _default: typeof __VLS_export;
26
+ export default _default;
27
+ type __VLS_WithSlots<T, S> = T & {
28
+ new (): {
29
+ $slots: S;
30
+ };
31
+ };
32
+ //# 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":"AA2OA,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;CAC/B,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,152 @@
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
+ },
29
+ setup(V) {
30
+ let H = b(), U = l({
31
+ inheritAttrs: !1,
32
+ setup: (e, { slots: t }) => () => t.default?.()
33
+ }), 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)), Z = r(() => W.label ?? X.value.label), Q = r(() => X.value.trigger);
34
+ x(() => X.value.enabled, (e) => {
35
+ e || (J.value = !1);
36
+ });
37
+ let $ = !1;
38
+ function te(e) {
39
+ e.key !== "ArrowDown" || e.defaultPrevented || J.value || !X.value.enabled || (e.preventDefault(), $ = !0, J.value = !0);
40
+ }
41
+ function ne(e) {
42
+ e.preventDefault();
43
+ let t = document.querySelector(`[data-ink-menu="color-${W.property}"] [role="menu"]`);
44
+ t && ($ ? D(t)[0]?.focus({ preventScroll: !0 }) : T(t)), $ = !1;
45
+ }
46
+ let re = r(() => ({
47
+ "aria-label": Z.value,
48
+ title: Z.value,
49
+ "aria-haspopup": "menu",
50
+ onKeydown: te,
51
+ "data-mixed": X.value.mixed ? "" : void 0
52
+ })), ie = r(() => d(H, re.value, { disabled: (H.disabled ?? !1) !== !1 || !X.value.enabled })), ae = r(() => ({ "aria-label": Z.value })), oe = r(() => ({
53
+ role: "menu",
54
+ "aria-label": Z.value,
55
+ onKeydown: (e) => E(e, e.currentTarget)
56
+ }));
57
+ return (e, r) => (m(), a(n, null, [c(y(A), {
58
+ open: J.value,
59
+ "onUpdate:open": r[2] ||= (e) => J.value = e
60
+ }, {
61
+ default: S(() => [(m(), ee(v(V.standalone ? y(U) : y(M)), { "as-child": "" }, {
62
+ default: S(() => [c(y(j), { "as-child": "" }, {
63
+ default: S(() => [o("button", d({
64
+ type: "button",
65
+ class: "ink-menu-trigger ink-color-menu",
66
+ "data-ink-color-menu": V.property,
67
+ "data-state": J.value ? "open" : "closed"
68
+ }, ie.value), [_(e.$slots, "default", {}, () => [o("span", {
69
+ class: "ink-swatch",
70
+ "data-ink-swatch": "",
71
+ "aria-hidden": "true",
72
+ "data-property": V.property,
73
+ "data-kind": Q.value.kind,
74
+ "data-color": Q.value.kind === "color" ? Q.value.color : void 0,
75
+ style: p(Q.value.kind === "color" ? { "--ink-swatch": Q.value.color } : void 0)
76
+ }, null, 12, F)])], 16, P)]),
77
+ _: 3
78
+ })]),
79
+ _: 3
80
+ })), c(y(k), null, {
81
+ default: S(() => [c(y(O), d({
82
+ class: "ink-select-content ink-menu-content",
83
+ "data-ink-select-content": "",
84
+ "data-ink-menu": `color-${V.property}`,
85
+ side: "bottom",
86
+ align: "start",
87
+ "side-offset": 4,
88
+ "collision-padding": 8
89
+ }, ae.value, { onOpenAutoFocus: ne }), {
90
+ default: S(() => [o("div", f(u(oe.value)), [
91
+ X.value.noFill ? (m(), a("button", {
92
+ key: 0,
93
+ type: "button",
94
+ role: "menuitemradio",
95
+ class: "ink-select-item ink-menu-item",
96
+ "data-ink-select-item": "",
97
+ tabindex: "-1",
98
+ "aria-checked": X.value.noFill.checked,
99
+ "data-state": X.value.noFill.checked ? "checked" : "unchecked",
100
+ onClick: r[0] ||= (e) => y(q)(X.value.noFill.patch)
101
+ }, [r[4] ||= s(" No fill ", -1), X.value.noFill.checked ? (m(), a("span", L, [c(t, {
102
+ icon: y(N),
103
+ size: 16
104
+ }, null, 8, ["icon"])])) : i("", !0)], 8, I)) : i("", !0),
105
+ o("div", {
106
+ role: "group",
107
+ "aria-label": "Colours",
108
+ class: "ink-color-grid",
109
+ "data-ink-menu-columns": y(C)
110
+ }, [(m(!0), a(n, null, g(X.value.swatches, (e) => (m(), a("button", {
111
+ key: e.key,
112
+ type: "button",
113
+ role: "menuitemradio",
114
+ class: "ink-swatch-item",
115
+ tabindex: "-1",
116
+ "aria-label": e.label,
117
+ "aria-checked": e.checked,
118
+ "data-state": e.checked ? "checked" : "unchecked",
119
+ style: p({ "--ink-swatch": e.color }),
120
+ onClick: (t) => y(q)(e.patch)
121
+ }, null, 12, z))), 128))], 8, R),
122
+ o("button", {
123
+ type: "button",
124
+ role: "menuitem",
125
+ class: "ink-select-item ink-menu-item",
126
+ "data-ink-select-item": "",
127
+ tabindex: "-1",
128
+ onClick: r[1] ||= (e) => Y.value?.click()
129
+ }, " Custom… ")
130
+ ], 16)]),
131
+ _: 1
132
+ }, 16, ["data-ink-menu"])]),
133
+ _: 1
134
+ })]),
135
+ _: 3
136
+ }, 8, ["open"]), o("input", {
137
+ ref_key: "customInput",
138
+ ref: Y,
139
+ type: "color",
140
+ class: "ink-color-input",
141
+ "aria-label": "Custom colour",
142
+ "data-ink-color-input": V.property,
143
+ tabindex: "-1",
144
+ value: X.value.customValue.toLowerCase(),
145
+ onChange: r[3] ||= (e) => y(q)(X.value.custom(e.target.value))
146
+ }, null, 40, B)], 64));
147
+ }
148
+ });
149
+ //#endregion
150
+ export { V as default };
151
+
152
+ //# 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}>()\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)\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 PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, ref } from 'vue'\n\nimport { useTool } from '../composables/useTool'\nimport { useToolOptions } from '../composables/useToolOptions'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\nconst { tool, setTool } = useTool()\nconst { options, setOptions } = useToolOptions<HighlightOptions>('highlight')\nconst open = ref(false)\n\nconst model = computed(() => highlightMenuModel(options.value, MARKUP_KINDS))\nconst active = computed(() => tool.value === 'highlight')\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 <div\n role=\"group\"\n aria-label=\"Highlight\"\n class=\"ink-split-button ink-highlight-menu\"\n data-ink-highlight-menu\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 <PopoverRoot v-model:open=\"open\">\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 v-bind=\"colourAttrs\"\n />\n </div>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n </div>\n</template>\n"],"mappings":""}
@@ -0,0 +1,17 @@
1
+ declare var __VLS_7: {
2
+ active: boolean;
3
+ kind: "highlight" | "underline" | "strikeout" | "squiggly";
4
+ };
5
+ type __VLS_Slots = {} & {
6
+ default?: (props: typeof __VLS_7) => any;
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>;
9
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
12
+ type __VLS_WithSlots<T, S> = T & {
13
+ new (): {
14
+ $slots: S;
15
+ };
16
+ };
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":"AA4fA,QAAA,IAAI,OAAO;;;CAAW,CAAC;AACvB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAG/C,QAAA,MAAM,UAAU,+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"}
@@ -0,0 +1,140 @@
1
+ import { useTool as e } from "../composables/useTool.js";
2
+ import { useToolOptions as t } from "../composables/useToolOptions.js";
3
+ import n from "./InkIcon.js";
4
+ import r from "./InkColorMenu.js";
5
+ import { Fragment as i, computed as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, createVNode as l, defineComponent as u, guardReactiveProps as d, mergeProps as f, normalizeProps as p, openBlock as m, ref as h, renderList as g, renderSlot as _, toDisplayString as v, unref as y, withCtx as b } from "vue";
6
+ import { MARKUP_ICONS as x, MARKUP_KINDS as S, focusInitialMenuItem as C, handleMenuKeys as w, highlightMenuModel as T, menuItems as E } from "@inkbar/core/dom";
7
+ import { PopoverContent as D, PopoverPortal as O, PopoverRoot as k, PopoverTrigger as A, ToolbarButton as j } from "reka-ui";
8
+ import { ChevronDown as M } from "@inkbar/icons";
9
+ //#region src/components/InkHighlightMenu.vue?vue&type=script&setup=true&lang.ts
10
+ var N = {
11
+ role: "group",
12
+ "aria-label": "Highlight",
13
+ class: "ink-split-button ink-highlight-menu",
14
+ "data-ink-highlight-menu": ""
15
+ }, P = ["data-state"], F = {
16
+ role: "group",
17
+ "aria-label": "Kinds",
18
+ class: "ink-highlight-kinds"
19
+ }, ee = [
20
+ "data-key",
21
+ "aria-checked",
22
+ "data-state",
23
+ "onClick"
24
+ ], I = {
25
+ role: "group",
26
+ "aria-label": "Colour",
27
+ class: "ink-highlight-colour"
28
+ }, L = /*@__PURE__*/ u({
29
+ __name: "InkHighlightMenu",
30
+ setup(u) {
31
+ let { tool: L, setTool: R } = e(), { options: z, setOptions: B } = t("highlight"), V = h(!1), H = a(() => T(z.value, S)), U = a(() => L.value === "highlight"), W = a(() => x[H.value.kind]), G = !1;
32
+ function K(e) {
33
+ e.key !== "ArrowDown" || e.defaultPrevented || V.value || (e.preventDefault(), G = !0, V.value = !0);
34
+ }
35
+ function q(e) {
36
+ e.preventDefault();
37
+ let t = document.querySelector("[data-ink-menu=\"highlight\"] [role=\"menu\"]");
38
+ t && (G ? E(t)[0]?.focus({ preventScroll: !0 }) : C(t)), G = !1;
39
+ }
40
+ function J(e) {
41
+ B({ kind: e }), R("highlight"), V.value = !1;
42
+ }
43
+ let Y = a(() => ({
44
+ "aria-pressed": String(U.value),
45
+ "aria-label": H.value.label,
46
+ title: H.value.label,
47
+ onClick: () => R("highlight")
48
+ })), X = {
49
+ "aria-label": "Choose highlight",
50
+ title: "Choose highlight",
51
+ "aria-haspopup": "menu",
52
+ onKeydown: K
53
+ }, Z = { "aria-label": "Highlights" }, Q = {
54
+ role: "menuitem",
55
+ tabindex: -1
56
+ }, $ = {
57
+ role: "menu",
58
+ "aria-label": "Highlights",
59
+ onKeydownCapture: (e) => w(e, e.currentTarget)
60
+ };
61
+ return (e, t) => (m(), o("div", N, [l(y(j), f({
62
+ class: "ink-tool-button ink-highlight-button",
63
+ "data-ink-tool-button": "",
64
+ "data-ink-highlight-button": "",
65
+ "data-tool": "highlight",
66
+ "data-kind": H.value.kind,
67
+ "data-state": U.value ? "on" : "off"
68
+ }, Y.value), {
69
+ default: b(() => [_(e.$slots, "default", {
70
+ active: U.value,
71
+ kind: H.value.kind
72
+ }, () => [l(n, { icon: W.value }, null, 8, ["icon"])])]),
73
+ _: 3
74
+ }, 16, ["data-kind", "data-state"]), l(y(k), {
75
+ open: V.value,
76
+ "onUpdate:open": t[0] ||= (e) => V.value = e
77
+ }, {
78
+ default: b(() => [l(y(j), { "as-child": "" }, {
79
+ default: b(() => [l(y(A), { "as-child": "" }, {
80
+ default: b(() => [s("button", f({
81
+ type: "button",
82
+ class: "ink-menu-trigger ink-highlight-menu-trigger",
83
+ "data-ink-highlight-menu-trigger": "",
84
+ "data-state": V.value ? "open" : "closed"
85
+ }, X), [l(n, { icon: y(M) }, null, 8, ["icon"])], 16, P)]),
86
+ _: 1
87
+ })]),
88
+ _: 1
89
+ }), l(y(O), null, {
90
+ default: b(() => [l(y(D), f({
91
+ class: "ink-select-content ink-menu-content",
92
+ "data-ink-select-content": "",
93
+ "data-ink-menu": "highlight",
94
+ side: "bottom",
95
+ align: "start",
96
+ "side-offset": 4,
97
+ "collision-padding": 8
98
+ }, Z, { onOpenAutoFocus: q }), {
99
+ default: b(() => [s("div", p(d($)), [
100
+ s("div", F, [(m(!0), o(i, null, g(H.value.items, (e) => (m(), o("button", {
101
+ key: e.kind,
102
+ type: "button",
103
+ role: "menuitemradio",
104
+ class: "ink-select-item ink-menu-item ink-highlight-item",
105
+ "data-ink-select-item": "",
106
+ tabindex: "-1",
107
+ "data-key": e.kind,
108
+ "aria-checked": e.checked,
109
+ "data-state": e.checked ? "checked" : "unchecked",
110
+ onClick: (t) => J(e.kind)
111
+ }, [l(n, {
112
+ icon: y(x)[e.kind],
113
+ size: 16
114
+ }, null, 8, ["icon"]), c(" " + v(e.label), 1)], 8, ee))), 128))]),
115
+ t[2] ||= s("div", {
116
+ role: "separator",
117
+ class: "ink-select-separator"
118
+ }, null, -1),
119
+ s("div", I, [t[1] ||= s("span", {
120
+ class: "ink-highlight-colour-label",
121
+ "aria-hidden": "true"
122
+ }, "Colour", -1), l(r, f({
123
+ property: "border",
124
+ group: "markup",
125
+ label: "Highlight colour",
126
+ standalone: ""
127
+ }, Q), null, 16)])
128
+ ], 16)]),
129
+ _: 1
130
+ }, 16)]),
131
+ _: 1
132
+ })]),
133
+ _: 1
134
+ }, 8, ["open"])]));
135
+ }
136
+ });
137
+ //#endregion
138
+ export { L as default };
139
+
140
+ //# sourceMappingURL=InkHighlightMenu.vue_vue_type_script_setup_true_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkHighlightMenu.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","_unref","_mergeProps","_withCtx","_renderSlot","InkIcon","_createElementVNode","_normalizeProps","_guardReactiveProps","_Fragment","_renderList","_createTextVNode","_toDisplayString","InkColorMenu","InkIcon_default","InkColorMenu_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","InkHighlightMenu_vue_vue_type_script_setup_true_lang_default","useTool","useToolOptions","open","ref","model","computed","highlightMenuModel","options","MARKUP_KINDS","active","tool","icon","MARKUP_ICONS","focusFirst","onTriggerKeydown","onOpenAutoFocus","menu","menuItems","focusInitialMenuItem","choose","setOptions","setTool","mainAttrs","triggerAttrs","menuAttrs","colourAttrs","innerAttrs","handleMenuKeys","openBlock","createElementBlock","createVNode","unref","ToolbarButton","mergeProps","withCtx","renderSlot","_ctx","PopoverRoot","_cache","$event","PopoverTrigger","createElementVNode","ChevronDown","PopoverPortal","PopoverContent","normalizeProps","guardReactiveProps","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 PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, ref } from 'vue'\n\nimport { useTool } from '../composables/useTool'\nimport { useToolOptions } from '../composables/useToolOptions'\n\nimport InkColorMenu from './InkColorMenu.vue'\nimport InkIcon from './InkIcon.vue'\n\nconst { tool, setTool } = useTool()\nconst { options, setOptions } = useToolOptions<HighlightOptions>('highlight')\nconst open = ref(false)\n\nconst model = computed(() => highlightMenuModel(options.value, MARKUP_KINDS))\nconst active = computed(() => tool.value === 'highlight')\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 <div\n role=\"group\"\n aria-label=\"Highlight\"\n class=\"ink-split-button ink-highlight-menu\"\n data-ink-highlight-menu\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 <PopoverRoot v-model:open=\"open\">\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 v-bind=\"colourAttrs\"\n />\n </div>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import e from "./InkLineStyleMenu.vue_vue_type_script_setup_true_lang.js";
2
+ //#region src/components/InkLineStyleMenu.vue
3
+ var t = e;
4
+ //#endregion
5
+ export { t as default };
6
+
7
+ //# sourceMappingURL=InkLineStyleMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkLineStyleMenu.js","names":["_sfc_main","InkLineStyleMenu_vue_vue_type_script_setup_true_lang_default","InkLineStyleMenu_default"],"sources":["../../src/components/InkLineStyleMenu.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/*\n * Line weight, solid or dashed, and arrowheads, for the selection or the active tool. Each\n * section disables when nothing selected (or no active tool) supports its props. The trigger\n * carries `data-mixed` when the selection disagrees on any of them; a section with no single\n * value shows no checkmark.\n */\nimport {\n focusInitialMenuItem,\n handleMenuKeys,\n lineStyleMenuModel,\n menuItems,\n} from '@inkbar/core/dom'\nimport { Check, Minus } from '@inkbar/icons'\nimport {\n PopoverContent,\n PopoverPortal,\n PopoverRoot,\n PopoverTrigger,\n ToolbarButton,\n} from 'reka-ui'\nimport { computed, mergeProps, ref, useAttrs, watch } from 'vue'\n\nimport { useToolStyle } from '../composables/useToolStyle'\n\nimport InkIcon from './InkIcon.vue'\n\n// The host's attributes go on the trigger: the root is a renderless popover.\ndefineOptions({ inheritAttrs: false })\nconst attrs = useAttrs()\n\nconst { current, supported, set } = useToolStyle()\nconst open = ref(false)\n\nconst model = computed(() => lineStyleMenuModel(current.value, supported.value))\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('[data-ink-menu=\"line-style\"] [role=\"menu\"]')\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': 'Line style',\n title: 'Line style',\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 = { 'aria-label': 'Line style' }\nconst innerAttrs = {\n role: 'menu',\n 'aria-label': 'Line style',\n onKeydown: (e: KeyboardEvent) => handleMenuKeys(e, e.currentTarget as HTMLElement),\n}\n</script>\n\n<template>\n <PopoverRoot v-model:open=\"open\">\n <ToolbarButton as-child>\n <PopoverTrigger as-child>\n <button\n type=\"button\"\n class=\"ink-menu-trigger ink-line-style-menu\"\n data-ink-line-style-menu\n :data-state=\"open ? 'open' : 'closed'\"\n v-bind=\"triggerBindings\"\n >\n <slot><InkIcon :icon=\"Minus\" /></slot>\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=\"line-style\"\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\n v-for=\"section in model.sections\"\n :key=\"section.label\"\n role=\"group\"\n class=\"ink-menu-group\"\n :aria-label=\"section.label\"\n :aria-disabled=\"section.disabled || undefined\"\n :data-disabled=\"section.disabled ? '' : undefined\"\n >\n <div class=\"ink-menu-label\" aria-hidden=\"true\">{{ section.label }}</div>\n <button\n v-for=\"item in section.items\"\n :key=\"item.key\"\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=\"item.checked\"\n :disabled=\"section.disabled\"\n :data-state=\"item.checked ? 'checked' : 'unchecked'\"\n @click=\"set(item.patch)\"\n >\n {{ item.label }}\n <span v-if=\"item.checked\" class=\"ink-select-indicator\">\n <InkIcon :icon=\"Check\" :size=\"16\" />\n </span>\n </button>\n </div>\n </div>\n </PopoverContent>\n </PopoverPortal>\n </PopoverRoot>\n</template>\n"],"mappings":""}
@@ -0,0 +1,14 @@
1
+ declare var __VLS_21: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_21) => any;
4
+ };
5
+ 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>;
6
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ type __VLS_WithSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };
14
+ //# sourceMappingURL=InkLineStyleMenu.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InkLineStyleMenu.vue.d.ts","sourceRoot":"","sources":["../../src/components/InkLineStyleMenu.vue"],"names":[],"mappings":"AAmbA,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,+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"}