Skip to content

Commit b707678

Browse files
authored
Merge pull request #581 from embedpdf/feature/callout-annotation
Feature/callout annotation
2 parents f335f28 + a2492c8 commit b707678

47 files changed

Lines changed: 2290 additions & 24 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@embedpdf/engines': minor
3+
---
4+
5+
Support callout free text in the PDFium executor: read/write `/CL`, `/LE`, `/IT`, stroke width and colors, `/TextColor`, and remap rectangle differences (`/RD`) between native PDFium order and the model shape.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@embedpdf/models': minor
3+
---
4+
5+
Extend free text annotation typing for callouts: add `PdfAnnotationColorType.TextColor` and optional `calloutLine`, `lineEnding`, `strokeWidth`, and `strokeColor` on `PdfFreeTextAnnoObject`.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@embedpdf/pdfium': minor
3+
---
4+
5+
Expose EmbedPDF callout line helpers in the WASM bindings (`EPDFAnnot_GetCalloutLineCount`, `EPDFAnnot_GetCalloutLine`, `EPDFAnnot_SetCalloutLine`) and refresh bundled `pdfium.js` / `pdfium.cjs` / `pdfium.wasm`.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@embedpdf/plugin-annotation': minor
3+
---
4+
5+
Add callout free text (`FreeTextCallout`): creation handler and preview data, vertex config and patch pipeline, default `freeTextCallout` tool, and built-in renderers for React, Vue, and Svelte (including preview components and shared `calloutVertexConfig`).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@embedpdf/snippet': minor
3+
---
4+
5+
Wire callout into the snippet viewer: callout icon, `annotation:add-callout` command, annotation toolbar and overflow menu entries, translations, and sidebar property schema for `freeTextCallout` (including opaque stroke color control).
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<script lang="ts">
2+
import type { SVGAttributes } from 'svelte/elements';
3+
4+
interface Props extends SVGAttributes<SVGSVGElement> {
5+
title?: string;
6+
}
7+
8+
let { class: className, title, ...rest }: Props = $props();
9+
</script>
10+
11+
<svg
12+
class={className}
13+
fill="none"
14+
stroke="currentColor"
15+
viewBox="0 0 24 24"
16+
stroke-width={2}
17+
stroke-linecap="round"
18+
stroke-linejoin="round"
19+
aria-hidden={!title}
20+
role={title ? 'img' : 'presentation'}
21+
{...rest}
22+
>
23+
{#if title}
24+
<title>{title}</title>
25+
{/if}
26+
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
27+
<path d="M20 6v4a1 1 0 0 1 -1 1h-14a1 1 0 0 1 -1 -1v-4a1 1 0 0 1 1 -1h14a1 1 0 0 1 1 1" />
28+
<path d="M17 11v6h-9" fill="none" />
29+
<path d="M8 15l-2 2l2 2" fill="none" />
30+
</svg>

examples/svelte-tailwind/src/lib/components/icons/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ export { default as FormSelectIcon } from './FormSelectIcon.svelte';
7474
export { default as FormListboxIcon } from './FormListboxIcon.svelte';
7575
export { default as WidgetEditIcon } from './WidgetEditIcon.svelte';
7676
export { default as RubberStampIcon } from './RubberStampIcon.svelte';
77+
export { default as CalloutIcon } from './CalloutIcon.svelte';

examples/svelte-tailwind/src/lib/components/icons/registry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import FormListboxIcon from './FormListboxIcon.svelte';
7575
import WidgetEditIcon from './WidgetEditIcon.svelte';
7676
import RubberStampIcon from './RubberStampIcon.svelte';
7777
import SignatureIcon from './SignatureIcon.svelte';
78+
import CalloutIcon from './CalloutIcon.svelte';
7879

7980
// Define the standard Prop type for your icons for consistency
8081
export interface IconProps extends SVGAttributes<SVGSVGElement> {
@@ -156,6 +157,7 @@ export const iconRegistry = {
156157
'widget-edit': WidgetEditIcon,
157158
'rubber-stamp': RubberStampIcon,
158159
signature: SignatureIcon,
160+
callout: CalloutIcon,
159161
} as const;
160162

161163
// Extract valid keys for Type Safety

examples/svelte-tailwind/src/lib/config/commands.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,37 @@ export const commands: Record<string, Command<State>> = {
881881
},
882882
},
883883

884+
'annotation:add-callout': {
885+
id: 'annotation:add-callout',
886+
labelKey: 'annotation.callout',
887+
icon: 'callout',
888+
iconProps: ({ state }) => ({
889+
primaryColor: getToolDefaultsById(state.plugins.annotation, 'freeTextCallout')?.strokeColor,
890+
secondaryColor: getToolDefaultsById(state.plugins.annotation, 'freeTextCallout')?.color,
891+
}),
892+
categories: ['annotation', 'annotation-text'],
893+
action: ({ registry, documentId }) => {
894+
const annotation = registry.getPlugin<AnnotationPlugin>(ANNOTATION_PLUGIN_ID)?.provides();
895+
const annotationScope = annotation?.forDocument(documentId);
896+
if (!annotationScope) return;
897+
898+
if (annotationScope.getActiveTool()?.id === 'freeTextCallout') {
899+
annotationScope.setActiveTool(null);
900+
} else {
901+
annotationScope.setActiveTool('freeTextCallout');
902+
}
903+
},
904+
active: ({ state, documentId }) => {
905+
return (
906+
state.plugins[ANNOTATION_PLUGIN_ID]?.documents[documentId]?.activeToolId ===
907+
'freeTextCallout'
908+
);
909+
},
910+
disabled: ({ state, documentId }) => {
911+
return lacksPermission(state, documentId, PdfPermissionFlag.ModifyAnnotations);
912+
},
913+
},
914+
884915
'annotation:add-highlight': {
885916
id: 'annotation:add-highlight',
886917
labelKey: 'annotation.highlight',

examples/svelte-tailwind/src/lib/config/translations.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ export const englishTranslations: Locale = {
122122
polyline: 'Polyline',
123123
ink: 'Ink',
124124
stamp: 'Stamp',
125+
comment: 'Comment',
126+
callout: 'Callout',
125127
overflowTools: 'Overflow Tools',
126128
group: 'Group',
127129
ungroup: 'Ungroup',
@@ -319,6 +321,8 @@ export const spanishTranslations: Locale = {
319321
polyline: 'Polilínea',
320322
ink: 'Tinta',
321323
stamp: 'Sello',
324+
comment: 'Comentario',
325+
callout: 'Llamada',
322326
overflowTools: 'Más herramientas',
323327
group: 'Agrupar',
324328
ungroup: 'Desagrupar',
@@ -517,6 +521,8 @@ export const germanTranslations: Locale = {
517521
polyline: 'Polylinie',
518522
ink: 'Stift',
519523
stamp: 'Stempel',
524+
comment: 'Kommentar',
525+
callout: 'Legende',
520526
overflowTools: 'Weitere Werkzeuge',
521527
group: 'Gruppieren',
522528
ungroup: 'Gruppierung aufheben',
@@ -715,6 +721,8 @@ export const dutchTranslations: Locale = {
715721
polyline: 'Polylijn',
716722
ink: 'Inkt',
717723
stamp: 'Stempel',
724+
comment: 'Commentaar',
725+
callout: 'Callout',
718726
overflowTools: 'Meer gereedschappen',
719727
group: 'Groeperen',
720728
ungroup: 'Degroeperen',

0 commit comments

Comments
 (0)