@embedpdf/viewer-chrome 3.0.0-next.4 → 3.0.0-next.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","names":[],"sources":["../src/config/commands.ts"],"sourcesContent":["/**\n * The command vocabulary — the semantic layer. Ported in spirit from the v2\n * snippet's commands.ts, but every command is a pure value: label key, icon,\n * shortcut, derivations, and a `run` (or a declarative surface target). The\n * v2 `registry.getPlugin<T>(id)?.provides()` string-and-cast dance becomes a\n * typed `ctx.get(Token)`.\n *\n * Wiring reality (chrome-parity scope):\n * zoom/pan/pointer/spread/scroll/rotate → real Stage / Interaction / PageEdit\n * modes → shell exclusive surfaces ('mode')\n * panels / menus / modals → declarative shell targets\n * annotate + shape tools → real interaction tools\n * form tools → real form plugin palette (draw-to-place)\n * insert/redact tools → inert interaction tools (demo-tools)\n * history undo/redo → disabled (no history plugin in v3 yet)\n */\nimport type { CommandDef, IconAccent } from '@embedpdf/react/commands';\nimport { DocumentsToken } from '@embedpdf/react/runtime';\nimport { StageToken, ZoomMode } from '@embedpdf/react/stage';\nimport type { SpreadMode } from '@embedpdf/react/stage';\nimport { InteractionToken } from '@embedpdf/react/interaction';\nimport { ShellToken } from '@embedpdf/react/shell';\nimport { AnnotationToken } from '@embedpdf/react/annotation';\nimport { fieldKeyOf, FormToken } from '@embedpdf/react/form';\nimport { LinkToken, type PdfLinkTarget } from '@embedpdf/react/link';\n\n// ── helpers ────────────────────────────────────────────────────────────────\ntype Ctx = Parameters<NonNullable<CommandDef['run']>>[0];\n\nconst stage = (c: Ctx) => c.tryGet(StageToken);\nconst interaction = (c: Ctx) => c.tryGet(InteractionToken);\nconst anno = (c: Ctx) => c.tryGet(AnnotationToken);\n\n// ── annotation-selection predicates (drive the floating strip's contents) ────\nconst hasAnnotationSelection = (c: Ctx) => (anno(c)?.selection().length ?? 0) > 0;\n/** v2 gated strip items per subtype (comment hidden on links/widgets) — here\n * it's one derivation over the selected DTOs instead of per-command lookups. */\nconst selectionSubtypes = (c: Ctx) => new Set((anno(c)?.getSelected() ?? []).map((a) => a.subtype));\n/**\n * The selection's `link` value: a target, `null` (linkable but none set), or\n * `undefined` when the selection cannot carry a link at all (widgets, mixed\n * link states) — the schema decides, never a subtype blocklist.\n */\nconst selectionLink = (c: Ctx): PdfLinkTarget | null | undefined => {\n const p = anno(c)?.getSelectionProps();\n if (!p || !p.specs.some((s) => s.key === 'link') || p.mixed.includes('link')) return undefined;\n return (p.values.link ?? null) as PdfLinkTarget | null;\n};\n\n// ── tool icon accents: THIS viewer's design decision ─────────────────────────\n// A tool declares which drawing default each colored part of its glyph previews.\n// This is intentionally explicit at the command definition: property-panel order\n// does not determine icon meaning, and another viewer may make a different choice.\ntype ColorKey = 'color' | 'interiorColor' | 'fontColor';\nexport interface ToolAccentDefinition {\n primary: ColorKey;\n secondary?: ColorKey;\n}\n\n/**\n * toolId → the SAME icon + accent definition its toolbar button uses, recorded\n * as a side effect of the `tool()` command definitions below — ONE source of\n * truth, so the tool cursor (ui/tool-cursor.tsx) and the button can never\n * drift apart.\n */\nexport const TOOL_ICONS: Record<string, { icon: string; accent?: ToolAccentDefinition }> = {};\n\nconst toolAccent = (\n c: Ctx,\n toolId: string,\n accent: ToolAccentDefinition | undefined,\n): IconAccent | null => {\n if (!accent) return null;\n const anno = c.tryGet(AnnotationToken);\n if (!anno) return null;\n const d = anno.currentDefaults(toolId);\n return {\n primary: d[accent.primary] ?? undefined,\n secondary: accent.secondary ? (d[accent.secondary] ?? undefined) : undefined,\n };\n};\n\n/** A tool command: activates a real interaction tool; active = it's the tool.\n * The icon previews the tool's current defaults — keyed by the SAME toolId\n * as run/active, so the accent can't drift to another tool's colors. */\nconst tool = (\n id: string,\n toolId: string,\n labelKey: string,\n icon: string,\n accent?: ToolAccentDefinition,\n): CommandDef => {\n TOOL_ICONS[toolId] = { icon, ...(accent ? { accent } : {}) };\n return {\n id,\n labelKey,\n icon,\n categories: ['tool'],\n run: (c) => interaction(c)?.activateTool(toolId),\n active: (c) => interaction(c)?.activeToolId() === toolId,\n enabled: (c) => interaction(c) != null,\n iconAccent: (c) => toolAccent(c, toolId, accent),\n };\n};\n\n/** A fixed zoom level (fraction), e.g. 1 = 100%. */\nconst zoomLevel = (id: string, level: number, label: string): CommandDef => ({\n id,\n labelKey: label,\n categories: ['zoom', 'zoom-level'],\n run: (c) => stage(c)?.zoomTo({ level }),\n enabled: (c) => stage(c) != null,\n});\n\nconst spread = (id: string, mode: SpreadMode, labelKey: string, icon: string): CommandDef => ({\n id,\n labelKey,\n icon,\n categories: ['page', 'spread'],\n run: (c) => stage(c)?.setSpread(mode),\n active: (c) => stage(c)?.spread() === mode,\n enabled: (c) => stage(c) != null,\n});\n\nexport const defaultCommands: CommandDef[] = [\n // ── zoom ───────────────────────────────────────────────────────────────\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n icon: 'zoomIn',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (c) => stage(c)?.zoomIn(),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n icon: 'zoomOut',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (c) => stage(c)?.zoomOut(),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n icon: 'fitToPage',\n shortcut: 'Mod+0',\n categories: ['zoom'],\n run: (c) => stage(c)?.fitPage(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.FitPage,\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n icon: 'fitToWidth',\n shortcut: 'Mod+1',\n categories: ['zoom'],\n run: (c) => stage(c)?.fitWidth(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.FitWidth,\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:automatic',\n labelKey: 'commands.zoom.automatic',\n categories: ['zoom'],\n run: (c) => stage(c)?.automatic(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.Automatic,\n enabled: (c) => stage(c) != null,\n },\n zoomLevel('zoom:50', 0.5, 'commands.zoom.p50'),\n zoomLevel('zoom:100', 1, 'commands.zoom.p100'),\n zoomLevel('zoom:150', 1.5, 'commands.zoom.p150'),\n zoomLevel('zoom:200', 2, 'commands.zoom.p200'),\n zoomLevel('zoom:400', 4, 'commands.zoom.p400'),\n {\n id: 'zoom:menu',\n labelKey: 'commands.zoom.menu',\n icon: 'zoomIn',\n categories: ['zoom'],\n menu: 'zoom',\n },\n\n // ── tools ──────────────────────────────────────────────────────────────\n {\n id: 'pan:toggle',\n labelKey: 'commands.pan',\n icon: 'hand',\n categories: ['tools'],\n run: (c) => interaction(c)?.activateTool('pan'),\n active: (c) => interaction(c)?.activeToolId() === 'pan',\n enabled: (c) => interaction(c) != null,\n },\n {\n id: 'pointer:toggle',\n labelKey: 'commands.pointer',\n icon: 'pointer',\n categories: ['tools'],\n run: (c) => interaction(c)?.activateTool('pointer'),\n active: (c) => interaction(c)?.activeToolId() === 'pointer',\n enabled: (c) => interaction(c) != null,\n },\n\n // ── panels (declarative shell targets) ──────────────────────────────────\n {\n id: 'panel:sidebar',\n labelKey: 'commands.sidebar',\n icon: 'sidebar',\n categories: ['panel'],\n panel: { id: 'sidebar', exclusive: 'left' },\n },\n {\n id: 'panel:search',\n labelKey: 'commands.search',\n icon: 'search',\n categories: ['panel'],\n panel: { id: 'search', exclusive: 'right' },\n },\n {\n id: 'panel:comment',\n labelKey: 'commands.comment',\n icon: 'comment',\n categories: ['panel'],\n panel: { id: 'comment', exclusive: 'right' },\n },\n {\n id: 'panel:annotation-style',\n labelKey: 'commands.style',\n icon: 'palette',\n categories: ['panel'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n },\n\n // ── menus (declarative) ─────────────────────────────────────────────────\n {\n id: 'document:menu',\n labelKey: 'commands.menu',\n icon: 'menu',\n categories: ['document'],\n menu: 'document',\n },\n {\n id: 'page:settings',\n labelKey: 'commands.viewControls',\n icon: 'viewSettings',\n categories: ['page'],\n menu: 'page-settings',\n },\n\n // ── document actions ────────────────────────────────────────────────────\n {\n id: 'document:download',\n labelKey: 'commands.download',\n icon: 'download',\n categories: ['document'],\n run: (c) => {\n const id = c.documentId ?? undefined;\n c.tryGet(DocumentsToken)\n ?.download(id)\n .then((bytes) => {\n const blob = new Blob([bytes as BlobPart], { type: 'application/pdf' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'document.pdf';\n a.click();\n URL.revokeObjectURL(url);\n })\n .catch((e) => console.warn('[snippet-react] download failed', e));\n },\n enabled: (c) => c.tryGet(DocumentsToken) != null && c.documentId != null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.print',\n icon: 'print',\n shortcut: 'Mod+p',\n categories: ['document'],\n run: () => window.print(),\n },\n {\n id: 'document:fullscreen',\n labelKey: 'commands.fullscreen',\n icon: 'externalLink',\n categories: ['document'],\n run: () => {\n if (document.fullscreenElement) document.exitFullscreen();\n else document.documentElement.requestFullscreen().catch(() => {});\n },\n active: () => Boolean(document.fullscreenElement),\n },\n\n // ── page settings (spread / scroll / rotate) ────────────────────────────\n spread('spread:none', 'none', 'commands.spread.none', 'singlePage'),\n spread('spread:odd', 'odd', 'commands.spread.odd', 'doublePage'),\n spread('spread:even', 'even', 'commands.spread.even', 'book2'),\n {\n id: 'scroll:vertical',\n labelKey: 'commands.scroll.vertical',\n icon: 'vertical',\n categories: ['page', 'scroll'],\n run: (c) => stage(c)?.setLayout('vertical'),\n active: (c) => stage(c)?.layout() === 'vertical',\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'scroll:horizontal',\n labelKey: 'commands.scroll.horizontal',\n icon: 'horizontal',\n categories: ['page', 'scroll'],\n run: (c) => stage(c)?.setLayout('horizontal'),\n active: (c) => stage(c)?.layout() === 'horizontal',\n enabled: (c) => stage(c) != null,\n },\n // VIEW rotation (Adobe's \"Rotate View\"): rotates how every page displays in\n // the main stage lens — non-persistent, nothing written to the PDF. The\n // PERMANENT per-page rotation (PageEditToken.rotateBy) belongs in a\n // page-organize surface, not behind the view-settings buttons.\n {\n id: 'rotate:clockwise',\n labelKey: 'commands.rotate.clockwise',\n icon: 'rotateClockwise',\n categories: ['page', 'rotate'],\n run: (c) => stage(c)?.rotateView(90),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'rotate:counter-clockwise',\n labelKey: 'commands.rotate.counterclockwise',\n icon: 'rotateCounterClockwise',\n categories: ['page', 'rotate'],\n run: (c) => stage(c)?.rotateView(-90),\n enabled: (c) => stage(c) != null,\n },\n\n // ── modes (shell exclusive surfaces, tag 'mode') ────────────────────────\n {\n id: 'mode:view',\n labelKey: 'commands.mode.view',\n categories: ['mode'],\n // View = no mode band. Close any open mode surface and drop to pointer.\n run: (c) => {\n const shell = c.tryGet(ShellToken);\n for (const m of MODE_SURFACES) shell?.close(m);\n interaction(c)?.activateTool('pointer');\n },\n active: (c) => {\n const shell = c.tryGet(ShellToken);\n return shell ? MODE_SURFACES.every((m) => !shell.isOpen(m)) : true;\n },\n },\n modeCommand('mode:annotate', 'commands.mode.annotate'),\n modeCommand('mode:shapes', 'commands.mode.shapes'),\n modeCommand('mode:insert', 'commands.mode.insert'),\n modeCommand('mode:form', 'commands.mode.form', 'form-edit'),\n modeCommand('mode:redact', 'commands.mode.redact'),\n\n // ── annotate tools (real interaction tools) ─────────────────────────────\n tool('annotation:add-highlight', 'highlight', 'commands.annotate.highlight', 'highlight', {\n primary: 'color',\n }),\n tool('annotation:add-strikeout', 'strikeout', 'commands.annotate.strikeout', 'strikethrough', {\n primary: 'color',\n }),\n tool('annotation:add-underline', 'underline', 'commands.annotate.underline', 'underline', {\n primary: 'color',\n }),\n tool('annotation:add-squiggly', 'squiggly', 'commands.annotate.squiggly', 'squiggly', {\n primary: 'color',\n }),\n tool('annotation:add-ink', 'ink', 'commands.annotate.ink', 'pencilMarker', {\n primary: 'color',\n }),\n tool(\n 'annotation:add-ink-highlight',\n 'ink-highlight',\n 'commands.annotate.inkHighlight',\n 'inkHighlighter',\n { primary: 'color' },\n ),\n tool('annotation:add-text', 'free-text', 'commands.annotate.text', 'freeText', {\n primary: 'fontColor',\n }),\n tool('annotation:add-insert-text', 'insert-text', 'commands.annotate.insertText', 'insertText', {\n primary: 'color',\n }),\n tool(\n 'annotation:add-replace-text',\n 'replace-text',\n 'commands.annotate.replaceText',\n 'replaceText',\n { primary: 'color' },\n ),\n tool('annotation:add-callout', 'free-text-callout', 'commands.annotate.callout', 'callout', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n // Sticky note (\"comment\") — click-to-place; the icon renders from the\n // engine-baked /AP in the tool's current color.\n tool('annotation:add-note', 'note', 'commands.annotate.note', 'message'),\n // Link — drag an invisible hit rectangle, then set the target in the style\n // panel's Link control (create-then-edit). While active, existing links\n // become editable rects instead of navigating.\n tool('annotation:add-link', 'link', 'commands.annotate.link', 'link'),\n\n // ── shape tools (real interaction tools) ────────────────────────────────\n tool('annotation:add-rectangle', 'square', 'commands.shapes.rectangle', 'square', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-circle', 'circle', 'commands.shapes.circle', 'circle', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-line', 'line', 'commands.shapes.line', 'line', { primary: 'color' }),\n // The arrow tool is a `line` preset (a line with an arrowhead) — registered by\n // the annotationPlugin `tools` config in App.tsx, activated like any other tool.\n tool('annotation:add-arrow', 'arrow', 'commands.shapes.arrow', 'lineArrow', {\n primary: 'color',\n }),\n tool('annotation:add-polygon', 'polygon', 'commands.shapes.polygon', 'polygon', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-polyline', 'polyline', 'commands.shapes.polyline', 'zigzag', {\n primary: 'color',\n }),\n\n // ── insert tools (stamp/attachment real; signature/image inert) ─────────\n tool('insert:add-stamp', 'stamp', 'commands.insert.stamp', 'rubberStamp'),\n // File attachment — click the spot, pick the file (the attachment provider).\n tool('insert:add-attachment', 'attachment', 'commands.insert.attachment', 'paperclip'),\n tool('insert:add-signature', 'signature', 'commands.insert.signature', 'signature'),\n tool('insert:add-image', 'image', 'commands.insert.image', 'photo'),\n\n // ── form tools (the form plugin's draw-to-place palette) ────────────────\n tool('form:add-textfield', 'form-text', 'commands.form.textfield', 'formTextfield'),\n tool('form:add-checkbox', 'form-checkbox', 'commands.form.checkbox', 'formCheckbox'),\n tool('form:add-radio', 'form-radio', 'commands.form.radio', 'formRadio'),\n tool('form:add-select', 'form-combobox', 'commands.form.select', 'formSelect'),\n tool('form:add-listbox', 'form-listbox', 'commands.form.listbox', 'formListbox'),\n\n // ── redaction (v2 parity: the toolbar arms the tool; the panel owns the\n // destructive verbs — Apply All / Clear live in the redaction sidebar) ────\n tool('redaction:redact', 'redact', 'commands.redact.mark', 'redactArea'),\n {\n id: 'panel:redaction',\n labelKey: 'commands.redact.panel',\n icon: 'redactionSidebar',\n categories: ['panel'],\n panel: { id: 'redaction', exclusive: 'right' },\n },\n\n // ── annotation selection (the floating strip's verbs) ──────────────────\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotate.delete',\n icon: 'trash',\n categories: ['annotation'],\n run: (c) => {\n const a = anno(c);\n if (!a) return;\n const form = c.tryGet(FormToken);\n const dtos = a.getSelected();\n const widgets = form ? dtos.filter((d) => d.subtype === 'widget') : [];\n if (widgets.length === 0) {\n a.deleteSelection();\n return;\n }\n // Widgets are FIELD-plane citizens: deleting one goes through doc.forms\n // (the field and every widget of it cascade), never the raw annotation —\n // otherwise the /AcroForm entry would be orphaned.\n const keys = new Set<string>();\n for (const w of widgets) {\n const objnum = w.ref.kind === 'objectNumber' ? w.ref.annotObjectNumber : 0;\n const field = objnum > 0 ? form!.fieldForWidget(objnum) : null;\n if (field) keys.add(fieldKeyOf(field));\n }\n for (const key of keys) void form!.deleteField(key);\n for (const d of dtos) if (d.subtype !== 'widget') void a.delete(d.ref);\n a.deselect();\n },\n visible: hasAnnotationSelection,\n // Mirrors the engine's own authorization: locked/unauthorized annotations\n // keep the button visible but disabled (the engine still enforces).\n enabled: (c) => {\n const a = anno(c);\n const refs = a?.getSelection() ?? [];\n return refs.length > 0 && refs.every((r) => a!.canDelete(r));\n },\n },\n {\n id: 'annotation:comment',\n labelKey: 'commands.comment',\n icon: 'comment',\n categories: ['annotation'],\n // Same 'comment' surface panel:comment toggles — `active` derives from it.\n panel: { id: 'comment', exclusive: 'right' },\n visible: (c) => hasAnnotationSelection(c) && !selectionSubtypes(c).has('widget'),\n },\n {\n id: 'annotation:style',\n labelKey: 'commands.style',\n icon: 'palette',\n categories: ['annotation'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n // The kind table decides: no declared editable props → no style button\n // (v2 hardcoded a subtype blocklist for this).\n visible: (c) => (anno(c)?.getSelectionProps().specs.length ?? 0) > 0,\n },\n {\n id: 'annotation:group',\n labelKey: 'commands.annotate.group',\n icon: 'group',\n categories: ['annotation'],\n run: (c) => void anno(c)?.group(),\n visible: (c) => anno(c)?.canGroup() ?? false,\n },\n {\n id: 'annotation:ungroup',\n labelKey: 'commands.annotate.ungroup',\n icon: 'ungroup',\n categories: ['annotation'],\n run: (c) => void anno(c)?.ungroup(),\n visible: (c) => anno(c)?.canUngroup() ?? false,\n },\n\n // ── link strip items (v2's \"Link / Go to link / Remove link\") ───────────\n {\n // Make the selection a link: opens the style panel, whose Link control\n // sets the target (create-then-edit — the plugin materializes the\n // attached child annotations).\n id: 'annotation:link',\n labelKey: 'commands.annotate.link',\n icon: 'link',\n categories: ['annotation'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n visible: (c) => selectionLink(c) === null,\n },\n {\n id: 'annotation:goto-link',\n labelKey: 'commands.annotate.gotoLink',\n icon: 'externalLink',\n categories: ['annotation'],\n run: (c) => {\n const target = selectionLink(c);\n if (target) c.tryGet(LinkToken)?.activate(target);\n },\n visible: (c) => selectionLink(c) != null,\n },\n {\n id: 'annotation:remove-link',\n labelKey: 'commands.annotate.removeLink',\n icon: 'linkOff',\n categories: ['annotation'],\n run: (c) => anno(c)?.updateSelection({ link: null }),\n visible: (c) => selectionLink(c) != null,\n },\n\n // ── history (no plugin yet → disabled, shows the disabled styling) ──────\n {\n id: 'history:undo',\n labelKey: 'commands.undo',\n icon: 'arrowBackUp',\n categories: ['history'],\n run: () => {},\n enabled: () => false,\n },\n {\n id: 'history:redo',\n labelKey: 'commands.redo',\n icon: 'arrowForwardUp',\n categories: ['history'],\n run: () => {},\n enabled: () => false,\n },\n];\n\n// ── mode helpers ─────────────────────────────────────────────────────────────\n// Modes are exclusive shell surfaces tagged 'mode'; the secondary band renders\n// whichever one is open. Kept below the array to keep the list readable.\nexport const MODE_SURFACES = [\n 'mode:annotate',\n 'mode:shapes',\n 'mode:insert',\n 'mode:form',\n 'mode:redact',\n] as const;\n\nfunction modeCommand(\n id: (typeof MODE_SURFACES)[number],\n labelKey: string,\n toolId: string = 'pointer',\n): CommandDef {\n return {\n id,\n labelKey,\n categories: ['mode'],\n // A mode tab is a shell surface AND a tool policy: the Form tab flips the\n // pointer into form design ('form-edit' — widgets select/move/resize like\n // annotations); every other tab (and closing one) drops back to the\n // default pointer, where widgets are fill controls again.\n run: (c) => {\n const shell = c.tryGet(ShellToken);\n shell?.toggle(id, { exclusive: 'mode' });\n interaction(c)?.activateTool(shell?.isOpen(id) ? toolId : 'pointer');\n },\n active: (c) => c.tryGet(ShellToken)?.isOpen(id) ?? false,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","names":[],"sources":["../src/config/commands.ts"],"sourcesContent":["/**\n * The command vocabulary — the semantic layer. Ported in spirit from the v2\n * snippet's commands.ts, but every command is a pure value: label key, icon,\n * shortcut, derivations, and a `run` (or a declarative surface target). The\n * v2 `registry.getPlugin<T>(id)?.provides()` string-and-cast dance becomes a\n * typed `ctx.get(Token)`.\n *\n * Wiring reality (chrome-parity scope):\n * zoom/pan/pointer/spread/scroll/rotate → real Stage / Interaction / PageEdit\n * modes → shell exclusive surfaces ('mode')\n * panels / menus / modals → declarative shell targets\n * annotate + shape tools → real interaction tools\n * form tools → real form plugin palette (draw-to-place)\n * insert/redact tools → inert interaction tools (demo-tools)\n * history undo/redo → disabled (no history plugin in v3 yet)\n */\nimport type { CommandDef, IconAccent } from '@embedpdf/react/commands';\nimport { DocumentsToken } from '@embedpdf/react/runtime';\nimport { StageToken, ZoomMode } from '@embedpdf/react/stage';\nimport type { SpreadMode } from '@embedpdf/react/stage';\nimport { InteractionToken } from '@embedpdf/react/interaction';\nimport { ShellToken } from '@embedpdf/react/shell';\nimport { AnnotationToken } from '@embedpdf/react/annotation';\nimport { copySelection, SelectionToken, type TextRange } from '@embedpdf/react/selection';\nimport { fieldKeyOf, FormToken } from '@embedpdf/react/form';\nimport { LinkToken, type PdfLinkTarget } from '@embedpdf/react/link';\n\n// ── helpers ────────────────────────────────────────────────────────────────\ntype Ctx = Parameters<NonNullable<CommandDef['run']>>[0];\n\nconst stage = (c: Ctx) => c.tryGet(StageToken);\nconst interaction = (c: Ctx) => c.tryGet(InteractionToken);\nconst anno = (c: Ctx) => c.tryGet(AnnotationToken);\nconst textSelection = (c: Ctx) => c.tryGet(SelectionToken);\nconst sameTextRange = (a: TextRange | null, b: TextRange | null): boolean =>\n a === b ||\n (!!a &&\n !!b &&\n a.start.pon === b.start.pon &&\n a.start.index === b.start.index &&\n a.end.pon === b.end.pon &&\n a.end.index === b.end.index);\n\n// ── annotation-selection predicates (drive the floating strip's contents) ────\nconst hasAnnotationSelection = (c: Ctx) => (anno(c)?.selection().length ?? 0) > 0;\n/** v2 gated strip items per subtype (comment hidden on links/widgets) — here\n * it's one derivation over the selected DTOs instead of per-command lookups. */\nconst selectionSubtypes = (c: Ctx) => new Set((anno(c)?.getSelected() ?? []).map((a) => a.subtype));\n/**\n * The selection's `link` value: a target, `null` (linkable but none set), or\n * `undefined` when the selection cannot carry a link at all (widgets, mixed\n * link states) — the schema decides, never a subtype blocklist.\n */\nconst selectionLink = (c: Ctx): PdfLinkTarget | null | undefined => {\n const p = anno(c)?.getSelectionProps();\n if (!p || !p.specs.some((s) => s.key === 'link') || p.mixed.includes('link')) return undefined;\n return (p.values.link ?? null) as PdfLinkTarget | null;\n};\n\n// ── tool icon accents: THIS viewer's design decision ─────────────────────────\n// A tool declares which drawing default each colored part of its glyph previews.\n// This is intentionally explicit at the command definition: property-panel order\n// does not determine icon meaning, and another viewer may make a different choice.\ntype ColorKey = 'color' | 'interiorColor' | 'fontColor';\nexport interface ToolAccentDefinition {\n primary: ColorKey;\n secondary?: ColorKey;\n}\n\n/**\n * toolId → the SAME icon + accent definition its toolbar button uses, recorded\n * as a side effect of the `tool()` command definitions below — ONE source of\n * truth, so the tool cursor (ui/tool-cursor.tsx) and the button can never\n * drift apart.\n */\nexport const TOOL_ICONS: Record<string, { icon: string; accent?: ToolAccentDefinition }> = {};\n\nconst toolAccent = (\n c: Ctx,\n toolId: string,\n accent: ToolAccentDefinition | undefined,\n): IconAccent | null => {\n if (!accent) return null;\n const anno = c.tryGet(AnnotationToken);\n if (!anno) return null;\n const d = anno.currentDefaults(toolId);\n return {\n primary: d[accent.primary] ?? undefined,\n secondary: accent.secondary ? (d[accent.secondary] ?? undefined) : undefined,\n };\n};\n\n/** A tool command: activates a real interaction tool; active = it's the tool.\n * The icon previews the tool's current defaults — keyed by the SAME toolId\n * as run/active, so the accent can't drift to another tool's colors. */\nconst tool = (\n id: string,\n toolId: string,\n labelKey: string,\n icon: string,\n accent?: ToolAccentDefinition,\n): CommandDef => {\n TOOL_ICONS[toolId] = { icon, ...(accent ? { accent } : {}) };\n return {\n id,\n labelKey,\n icon,\n categories: ['tool'],\n run: (c) => interaction(c)?.activateTool(toolId),\n active: (c) => interaction(c)?.activeToolId() === toolId,\n enabled: (c) => interaction(c) != null,\n iconAccent: (c) => toolAccent(c, toolId, accent),\n };\n};\n\n/** A fixed zoom level (fraction), e.g. 1 = 100%. */\nconst zoomLevel = (id: string, level: number, label: string): CommandDef => ({\n id,\n labelKey: label,\n categories: ['zoom', 'zoom-level'],\n run: (c) => stage(c)?.zoomTo({ level }),\n enabled: (c) => stage(c) != null,\n});\n\nconst spread = (id: string, mode: SpreadMode, labelKey: string, icon: string): CommandDef => ({\n id,\n labelKey,\n icon,\n categories: ['page', 'spread'],\n run: (c) => stage(c)?.setSpread(mode),\n active: (c) => stage(c)?.spread() === mode,\n enabled: (c) => stage(c) != null,\n});\n\nexport const defaultCommands: CommandDef[] = [\n // ── zoom ───────────────────────────────────────────────────────────────\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n icon: 'zoomIn',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (c) => stage(c)?.zoomIn(),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n icon: 'zoomOut',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (c) => stage(c)?.zoomOut(),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n icon: 'fitToPage',\n shortcut: 'Mod+0',\n categories: ['zoom'],\n run: (c) => stage(c)?.fitPage(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.FitPage,\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n icon: 'fitToWidth',\n shortcut: 'Mod+1',\n categories: ['zoom'],\n run: (c) => stage(c)?.fitWidth(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.FitWidth,\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'zoom:automatic',\n labelKey: 'commands.zoom.automatic',\n categories: ['zoom'],\n run: (c) => stage(c)?.automatic(),\n active: (c) => stage(c)?.zoomMode() === ZoomMode.Automatic,\n enabled: (c) => stage(c) != null,\n },\n zoomLevel('zoom:50', 0.5, 'commands.zoom.p50'),\n zoomLevel('zoom:100', 1, 'commands.zoom.p100'),\n zoomLevel('zoom:150', 1.5, 'commands.zoom.p150'),\n zoomLevel('zoom:200', 2, 'commands.zoom.p200'),\n zoomLevel('zoom:400', 4, 'commands.zoom.p400'),\n {\n id: 'zoom:menu',\n labelKey: 'commands.zoom.menu',\n icon: 'zoomIn',\n categories: ['zoom'],\n menu: 'zoom',\n },\n\n // ── tools ──────────────────────────────────────────────────────────────\n {\n id: 'pan:toggle',\n labelKey: 'commands.pan',\n icon: 'hand',\n categories: ['tools'],\n run: (c) => interaction(c)?.activateTool('pan'),\n active: (c) => interaction(c)?.activeToolId() === 'pan',\n enabled: (c) => interaction(c) != null,\n },\n {\n id: 'pointer:toggle',\n labelKey: 'commands.pointer',\n icon: 'pointer',\n categories: ['tools'],\n run: (c) => interaction(c)?.activateTool('pointer'),\n active: (c) => interaction(c)?.activeToolId() === 'pointer',\n enabled: (c) => interaction(c) != null,\n },\n\n // ── panels (declarative shell targets) ──────────────────────────────────\n {\n id: 'panel:sidebar',\n labelKey: 'commands.sidebar',\n icon: 'sidebar',\n categories: ['panel'],\n panel: { id: 'sidebar', exclusive: 'left' },\n },\n {\n id: 'panel:search',\n labelKey: 'commands.search',\n icon: 'search',\n categories: ['panel'],\n panel: { id: 'search', exclusive: 'right' },\n },\n {\n id: 'panel:comment',\n labelKey: 'commands.comment',\n icon: 'comment',\n categories: ['panel'],\n panel: { id: 'comment', exclusive: 'right' },\n },\n {\n id: 'panel:annotation-style',\n labelKey: 'commands.style',\n icon: 'palette',\n categories: ['panel'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n },\n\n // ── menus (declarative) ─────────────────────────────────────────────────\n {\n id: 'document:menu',\n labelKey: 'commands.menu',\n icon: 'menu',\n categories: ['document'],\n menu: 'document',\n },\n {\n id: 'page:settings',\n labelKey: 'commands.viewControls',\n icon: 'viewSettings',\n categories: ['page'],\n menu: 'page-settings',\n },\n\n // ── document actions ────────────────────────────────────────────────────\n {\n id: 'document:download',\n labelKey: 'commands.download',\n icon: 'download',\n categories: ['document'],\n run: (c) => {\n const id = c.documentId ?? undefined;\n c.tryGet(DocumentsToken)\n ?.download(id)\n .then((bytes) => {\n const blob = new Blob([bytes as BlobPart], { type: 'application/pdf' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'document.pdf';\n a.click();\n URL.revokeObjectURL(url);\n })\n .catch((e) => console.warn('[snippet-react] download failed', e));\n },\n enabled: (c) => c.tryGet(DocumentsToken) != null && c.documentId != null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.print',\n icon: 'print',\n shortcut: 'Mod+p',\n categories: ['document'],\n run: () => window.print(),\n },\n {\n id: 'document:fullscreen',\n labelKey: 'commands.fullscreen',\n icon: 'externalLink',\n categories: ['document'],\n run: () => {\n if (document.fullscreenElement) document.exitFullscreen();\n else document.documentElement.requestFullscreen().catch(() => {});\n },\n active: () => Boolean(document.fullscreenElement),\n },\n\n // ── page settings (spread / scroll / rotate) ────────────────────────────\n spread('spread:none', 'none', 'commands.spread.none', 'singlePage'),\n spread('spread:odd', 'odd', 'commands.spread.odd', 'doublePage'),\n spread('spread:even', 'even', 'commands.spread.even', 'book2'),\n {\n id: 'scroll:vertical',\n labelKey: 'commands.scroll.vertical',\n icon: 'vertical',\n categories: ['page', 'scroll'],\n run: (c) => stage(c)?.setLayout('vertical'),\n active: (c) => stage(c)?.layout() === 'vertical',\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'scroll:horizontal',\n labelKey: 'commands.scroll.horizontal',\n icon: 'horizontal',\n categories: ['page', 'scroll'],\n run: (c) => stage(c)?.setLayout('horizontal'),\n active: (c) => stage(c)?.layout() === 'horizontal',\n enabled: (c) => stage(c) != null,\n },\n // VIEW rotation (Adobe's \"Rotate View\"): rotates how every page displays in\n // the main stage lens — non-persistent, nothing written to the PDF. The\n // PERMANENT per-page rotation (PageEditToken.rotateBy) belongs in a\n // page-organize surface, not behind the view-settings buttons.\n {\n id: 'rotate:clockwise',\n labelKey: 'commands.rotate.clockwise',\n icon: 'rotateClockwise',\n categories: ['page', 'rotate'],\n run: (c) => stage(c)?.rotateView(90),\n enabled: (c) => stage(c) != null,\n },\n {\n id: 'rotate:counter-clockwise',\n labelKey: 'commands.rotate.counterclockwise',\n icon: 'rotateCounterClockwise',\n categories: ['page', 'rotate'],\n run: (c) => stage(c)?.rotateView(-90),\n enabled: (c) => stage(c) != null,\n },\n\n // ── modes (shell exclusive surfaces, tag 'mode') ────────────────────────\n {\n id: 'mode:view',\n labelKey: 'commands.mode.view',\n categories: ['mode'],\n // View = no mode band. Close any open mode surface and drop to pointer.\n run: (c) => {\n const shell = c.tryGet(ShellToken);\n for (const m of MODE_SURFACES) shell?.close(m);\n interaction(c)?.activateTool('pointer');\n },\n active: (c) => {\n const shell = c.tryGet(ShellToken);\n return shell ? MODE_SURFACES.every((m) => !shell.isOpen(m)) : true;\n },\n },\n modeCommand('mode:annotate', 'commands.mode.annotate'),\n modeCommand('mode:shapes', 'commands.mode.shapes'),\n modeCommand('mode:insert', 'commands.mode.insert'),\n modeCommand('mode:form', 'commands.mode.form', 'form-edit'),\n modeCommand('mode:redact', 'commands.mode.redact'),\n\n // ── annotate tools (real interaction tools) ─────────────────────────────\n tool('annotation:add-highlight', 'highlight', 'commands.annotate.highlight', 'highlight', {\n primary: 'color',\n }),\n tool('annotation:add-strikeout', 'strikeout', 'commands.annotate.strikeout', 'strikethrough', {\n primary: 'color',\n }),\n tool('annotation:add-underline', 'underline', 'commands.annotate.underline', 'underline', {\n primary: 'color',\n }),\n tool('annotation:add-squiggly', 'squiggly', 'commands.annotate.squiggly', 'squiggly', {\n primary: 'color',\n }),\n tool('annotation:add-ink', 'ink', 'commands.annotate.ink', 'pencilMarker', {\n primary: 'color',\n }),\n tool(\n 'annotation:add-ink-highlight',\n 'ink-highlight',\n 'commands.annotate.inkHighlight',\n 'inkHighlighter',\n { primary: 'color' },\n ),\n tool('annotation:add-text', 'free-text', 'commands.annotate.text', 'freeText', {\n primary: 'fontColor',\n }),\n tool('annotation:add-insert-text', 'insert-text', 'commands.annotate.insertText', 'insertText', {\n primary: 'color',\n }),\n tool(\n 'annotation:add-replace-text',\n 'replace-text',\n 'commands.annotate.replaceText',\n 'replaceText',\n { primary: 'color' },\n ),\n tool('annotation:add-callout', 'free-text-callout', 'commands.annotate.callout', 'callout', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n // Sticky note (\"comment\") — click-to-place; the icon renders from the\n // engine-baked /AP in the tool's current color.\n tool('annotation:add-note', 'note', 'commands.annotate.note', 'message'),\n // Link — drag an invisible hit rectangle, then set the target in the style\n // panel's Link control (create-then-edit). While active, existing links\n // become editable rects instead of navigating.\n tool('annotation:add-link', 'link', 'commands.annotate.link', 'link'),\n\n // ── shape tools (real interaction tools) ────────────────────────────────\n tool('annotation:add-rectangle', 'square', 'commands.shapes.rectangle', 'square', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-circle', 'circle', 'commands.shapes.circle', 'circle', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-line', 'line', 'commands.shapes.line', 'line', { primary: 'color' }),\n // The arrow tool is a `line` preset (a line with an arrowhead) — registered by\n // the annotationPlugin `tools` config in App.tsx, activated like any other tool.\n tool('annotation:add-arrow', 'arrow', 'commands.shapes.arrow', 'lineArrow', {\n primary: 'color',\n }),\n tool('annotation:add-polygon', 'polygon', 'commands.shapes.polygon', 'polygon', {\n primary: 'color',\n secondary: 'interiorColor',\n }),\n tool('annotation:add-polyline', 'polyline', 'commands.shapes.polyline', 'zigzag', {\n primary: 'color',\n }),\n\n // ── insert tools (stamp/attachment real; signature/image inert) ─────────\n tool('insert:add-stamp', 'stamp', 'commands.insert.stamp', 'rubberStamp'),\n // File attachment — click the spot, pick the file (the attachment provider).\n tool('insert:add-attachment', 'attachment', 'commands.insert.attachment', 'paperclip'),\n tool('insert:add-signature', 'signature', 'commands.insert.signature', 'signature'),\n tool('insert:add-image', 'image', 'commands.insert.image', 'photo'),\n\n // ── form tools (the form plugin's draw-to-place palette) ────────────────\n tool('form:add-textfield', 'form-text', 'commands.form.textfield', 'formTextfield'),\n tool('form:add-checkbox', 'form-checkbox', 'commands.form.checkbox', 'formCheckbox'),\n tool('form:add-radio', 'form-radio', 'commands.form.radio', 'formRadio'),\n tool('form:add-select', 'form-combobox', 'commands.form.select', 'formSelect'),\n tool('form:add-listbox', 'form-listbox', 'commands.form.listbox', 'formListbox'),\n\n // ── redaction (v2 parity: the toolbar arms the tool; the panel owns the\n // destructive verbs — Apply All / Clear live in the redaction sidebar) ────\n tool('redaction:redact', 'redact', 'commands.redact.mark', 'redactArea'),\n {\n id: 'panel:redaction',\n labelKey: 'commands.redact.panel',\n icon: 'redactionSidebar',\n categories: ['panel'],\n panel: { id: 'redaction', exclusive: 'right' },\n },\n\n // ── annotation selection (the floating strip's verbs) ──────────────────\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotate.delete',\n icon: 'trash',\n categories: ['annotation'],\n run: (c) => {\n const a = anno(c);\n if (!a) return;\n const form = c.tryGet(FormToken);\n const dtos = a.getSelected();\n const widgets = form ? dtos.filter((d) => d.subtype === 'widget') : [];\n if (widgets.length === 0) {\n a.deleteSelection();\n return;\n }\n // Widgets are FIELD-plane citizens: deleting one goes through doc.forms\n // (the field and every widget of it cascade), never the raw annotation —\n // otherwise the /AcroForm entry would be orphaned.\n const keys = new Set<string>();\n for (const w of widgets) {\n const objnum = w.ref.kind === 'objectNumber' ? w.ref.annotObjectNumber : 0;\n const field = objnum > 0 ? form!.fieldForWidget(objnum) : null;\n if (field) keys.add(fieldKeyOf(field));\n }\n for (const key of keys) void form!.deleteField(key);\n for (const d of dtos) if (d.subtype !== 'widget') void a.delete(d.ref);\n a.deselect();\n },\n visible: hasAnnotationSelection,\n // Mirrors the engine's own authorization: locked/unauthorized annotations\n // keep the button visible but disabled (the engine still enforces).\n enabled: (c) => {\n const a = anno(c);\n const refs = a?.getSelection() ?? [];\n return refs.length > 0 && refs.every((r) => a!.canDelete(r));\n },\n },\n {\n id: 'annotation:comment',\n labelKey: 'commands.comment',\n icon: 'comment',\n categories: ['annotation'],\n // Same 'comment' surface panel:comment toggles — `active` derives from it.\n panel: { id: 'comment', exclusive: 'right' },\n visible: (c) => hasAnnotationSelection(c) && !selectionSubtypes(c).has('widget'),\n },\n {\n id: 'annotation:style',\n labelKey: 'commands.style',\n icon: 'palette',\n categories: ['annotation'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n // The kind table decides: no declared editable props → no style button\n // (v2 hardcoded a subtype blocklist for this).\n visible: (c) => (anno(c)?.getSelectionProps().specs.length ?? 0) > 0,\n },\n {\n id: 'annotation:group',\n labelKey: 'commands.annotate.group',\n icon: 'group',\n categories: ['annotation'],\n run: (c) => void anno(c)?.group(),\n visible: (c) => anno(c)?.canGroup() ?? false,\n },\n {\n id: 'annotation:ungroup',\n labelKey: 'commands.annotate.ungroup',\n icon: 'ungroup',\n categories: ['annotation'],\n run: (c) => void anno(c)?.ungroup(),\n visible: (c) => anno(c)?.canUngroup() ?? false,\n },\n\n // ── text selection (the selection strip's verbs) ────────────────────────\n {\n id: 'selection:copy',\n labelKey: 'commands.selection.copy',\n icon: 'copy',\n categories: ['selection'],\n // The permission story rides `visible`: a deployment denying\n // doc.text.copy shows no Copy at all — and with zero visible commands\n // the strip renders nothing, so there is never an empty bubble.\n visible: (c) => {\n const s = textSelection(c);\n return !!s && s.hasSelection() && s.canCopy();\n },\n // Async Clipboard write inside the click's activation window; instant\n // when <SelectionClipboard>'s commit prefetch already fetched the text.\n // A successful copy consumes the selection, which also dismisses its strip.\n run: (c) => {\n const s = textSelection(c);\n if (!s) return;\n const copiedRange = s.snapshot().range;\n void copySelection(s).then(\n (text) => {\n // Clipboard writes can outlive the click. Never let an older copy\n // completion clear a newer selection the user made in the meantime.\n if (text !== '' && sameTextRange(s.snapshot().range, copiedRange)) s.clear();\n },\n () => {}, // Copy failed: preserve the selection so the user can retry.\n );\n },\n },\n\n // ── link strip items (v2's \"Link / Go to link / Remove link\") ───────────\n {\n // Make the selection a link: opens the style panel, whose Link control\n // sets the target (create-then-edit — the plugin materializes the\n // attached child annotations).\n id: 'annotation:link',\n labelKey: 'commands.annotate.link',\n icon: 'link',\n categories: ['annotation'],\n panel: { id: 'annotation-style', exclusive: 'right' },\n visible: (c) => selectionLink(c) === null,\n },\n {\n id: 'annotation:goto-link',\n labelKey: 'commands.annotate.gotoLink',\n icon: 'externalLink',\n categories: ['annotation'],\n run: (c) => {\n const target = selectionLink(c);\n if (target) c.tryGet(LinkToken)?.activate(target);\n },\n visible: (c) => selectionLink(c) != null,\n },\n {\n id: 'annotation:remove-link',\n labelKey: 'commands.annotate.removeLink',\n icon: 'linkOff',\n categories: ['annotation'],\n run: (c) => anno(c)?.updateSelection({ link: null }),\n visible: (c) => selectionLink(c) != null,\n },\n\n // ── history (no plugin yet → disabled, shows the disabled styling) ──────\n {\n id: 'history:undo',\n labelKey: 'commands.undo',\n icon: 'arrowBackUp',\n categories: ['history'],\n run: () => {},\n enabled: () => false,\n },\n {\n id: 'history:redo',\n labelKey: 'commands.redo',\n icon: 'arrowForwardUp',\n categories: ['history'],\n run: () => {},\n enabled: () => false,\n },\n];\n\n// ── mode helpers ─────────────────────────────────────────────────────────────\n// Modes are exclusive shell surfaces tagged 'mode'; the secondary band renders\n// whichever one is open. Kept below the array to keep the list readable.\nexport const MODE_SURFACES = [\n 'mode:annotate',\n 'mode:shapes',\n 'mode:insert',\n 'mode:form',\n 'mode:redact',\n] as const;\n\nfunction modeCommand(\n id: (typeof MODE_SURFACES)[number],\n labelKey: string,\n toolId: string = 'pointer',\n): CommandDef {\n return {\n id,\n labelKey,\n categories: ['mode'],\n // A mode tab is a shell surface AND a tool policy: the Form tab flips the\n // pointer into form design ('form-edit' — widgets select/move/resize like\n // annotations); every other tab (and closing one) drops back to the\n // default pointer, where widgets are fill controls again.\n run: (c) => {\n const shell = c.tryGet(ShellToken);\n shell?.toggle(id, { exclusive: 'mode' });\n interaction(c)?.activateTool(shell?.isOpen(id) ? toolId : 'pointer');\n },\n active: (c) => c.tryGet(ShellToken)?.isOpen(id) ?? false,\n };\n}\n"],"mappings":"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"}
@@ -77,6 +77,10 @@ const es = {
77
77
  ungroup: "Desagrupar",
78
78
  strip: "Acciones de anotación"
79
79
  },
80
+ selection: {
81
+ copy: "Copiar",
82
+ strip: "Acciones de selección de texto"
83
+ },
80
84
  shapes: {
81
85
  rectangle: "Rectángulo",
82
86
  circle: "Círculo",
@@ -163,4 +167,4 @@ const es = {
163
167
  //#endregion
164
168
  export { es };
165
169
 
166
- //# sourceMappingURL=es-D0PzYE9Z.js.map
170
+ //# sourceMappingURL=es-CfmzJaGm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"es-CfmzJaGm.js","names":[],"sources":["../src/locales/es.ts"],"sourcesContent":["import type { Locale } from '@embedpdf/react/i18n';\n\n/** Spanish pack — loaded lazily (see the i18n `loaders` config in App). The\n * longer Spanish labels are exactly what makes the measured toolbar re-solve\n * on locale switch, with zero configuration. */\nexport const es: Locale = {\n code: 'es',\n name: 'Español',\n translations: {\n commands: {\n zoom: {\n in: 'Acercar',\n out: 'Alejar',\n fitPage: 'Ajustar a la página',\n fitWidth: 'Ajustar al ancho',\n automatic: 'Automático',\n menu: 'Zoom',\n level: 'Nivel de zoom',\n p50: '50 %',\n p100: '100 %',\n p150: '150 %',\n p200: '200 %',\n p400: '400 %',\n },\n pan: 'Desplazar',\n pointer: 'Puntero',\n sidebar: 'Barra lateral',\n search: 'Buscar',\n comment: 'Comentario',\n style: 'Estilo',\n menu: 'Menú',\n viewControls: 'Controles de vista',\n download: 'Descargar',\n print: 'Imprimir',\n fullscreen: 'Pantalla completa',\n spread: {\n group: 'Diseño de página',\n none: 'Una página',\n odd: 'Dos páginas',\n even: 'Portada',\n },\n scroll: { group: 'Desplazamiento', vertical: 'Vertical', horizontal: 'Horizontal' },\n rotate: {\n group: 'Girar',\n clockwise: 'Girar a la derecha',\n counterclockwise: 'Girar a la izquierda',\n },\n mode: {\n group: 'Modo',\n view: 'Ver',\n annotate: 'Anotar',\n shapes: 'Formas',\n insert: 'Insertar',\n form: 'Formulario',\n redact: 'Redactar',\n },\n annotate: {\n highlight: 'Resaltar',\n strikeout: 'Tachar',\n underline: 'Subrayar',\n squiggly: 'Ondulado',\n ink: 'Dibujar',\n inkHighlight: 'Resaltador a mano alzada',\n text: 'Texto',\n insertText: 'Insertar texto',\n replaceText: 'Reemplazar texto',\n callout: 'Llamada',\n note: 'Comentario',\n link: 'Enlace',\n gotoLink: 'Ir al enlace',\n removeLink: 'Quitar enlace',\n delete: 'Eliminar',\n group: 'Agrupar',\n ungroup: 'Desagrupar',\n strip: 'Acciones de anotación',\n },\n selection: {\n copy: 'Copiar',\n strip: 'Acciones de selección de texto',\n },\n shapes: {\n rectangle: 'Rectángulo',\n circle: 'Círculo',\n line: 'Línea',\n arrow: 'Flecha',\n polygon: 'Polígono',\n polyline: 'Polilínea',\n },\n insert: {\n attachment: 'Adjuntar archivo',\n stamp: 'Sello',\n signature: 'Firma',\n image: 'Imagen',\n },\n form: {\n textfield: 'Campo de texto',\n checkbox: 'Casilla',\n radio: 'Botón de opción',\n select: 'Desplegable',\n listbox: 'Lista',\n },\n redact: {\n mark: 'Marcar para redacción',\n applyAll: 'Aplicar redacciones',\n clearAll: 'Borrar marcas',\n panel: 'Redacciones',\n },\n undo: 'Deshacer',\n redo: 'Rehacer',\n },\n passwordPrompt: {\n title: 'Contraseña requerida',\n required: 'Este documento está protegido con contraseña. Introdúcela para abrirlo.',\n incorrect: 'La contraseña es incorrecta. Inténtalo de nuevo.',\n incorrectWarning: 'Contraseña incorrecta',\n label: 'Contraseña',\n placeholder: 'Introduce la contraseña',\n cancel: 'Cancelar',\n open: 'Abrir',\n opening: 'Abriendo…',\n },\n documentError: {\n title: 'No se pudo abrir el documento',\n unknown: 'El documento no se pudo abrir.',\n close: 'Cerrar documento',\n },\n demo: {\n starting: 'Iniciando el visor…',\n opening: 'Abriendo el documento…',\n more: 'Más',\n thumbnails: 'Miniaturas',\n outline: 'Esquema',\n searchPlaceholder: 'Buscar en el documento…',\n searchTitle: 'Buscar',\n searchCaseSensitive: 'Distinguir mayúsculas',\n searchWholeWord: 'Palabra completa',\n searchRegex: 'Expresión regular',\n searchSearching: 'Buscando…',\n searchResults: '{count} resultados encontrados',\n searchNoResults: 'Sin resultados',\n searchPage: 'Página {page}',\n commentsTitle: 'Comentarios',\n styleTitle: 'Estilo',\n empty: 'Aquí todavía no hay nada en este panel de demostración.',\n page: 'Página {current} de {total}',\n cancel: 'Cancelar',\n pageBadge: 'pág. {page}',\n redactionTitle: 'Redacciones',\n redactionEmpty:\n 'No hay redacciones pendientes. Usa la herramienta Redactar para marcar texto o áreas.',\n redactionArea: 'Marca de área',\n redactionText: 'Marca de texto',\n redactionRemove: 'Quitar marca',\n redactConfirmTitle: '¿Aplicar redacciones?',\n redactConfirmBody:\n 'Eliminar permanentemente el contenido bajo {count} marcas de redacción. No se puede deshacer.',\n redactConfirmCollateral: 'También se eliminarán {count} otras anotaciones.',\n redactApply: 'Aplicar',\n redactApplying: 'Aplicando…',\n redactLabelTitle: 'Etiqueta de redacción',\n redactLabelPlaceholder: 'p. ej. REDACTADO',\n redactLabelRepeat: 'Repetir etiqueta en toda la región',\n },\n },\n};\n"],"mappings":";;;;AAKA,MAAa,KAAa;CACxB,MAAM;CACN,MAAM;CACN,cAAc;EACZ,UAAU;GACR,MAAM;IACJ,IAAI;IACJ,KAAK;IACL,SAAS;IACT,UAAU;IACV,WAAW;IACX,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;GACR;GACA,KAAK;GACL,SAAS;GACT,SAAS;GACT,QAAQ;GACR,SAAS;GACT,OAAO;GACP,MAAM;GACN,cAAc;GACd,UAAU;GACV,OAAO;GACP,YAAY;GACZ,QAAQ;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,MAAM;GACR;GACA,QAAQ;IAAE,OAAO;IAAkB,UAAU;IAAY,YAAY;GAAa;GAClF,QAAQ;IACN,OAAO;IACP,WAAW;IACX,kBAAkB;GACpB;GACA,MAAM;IACJ,OAAO;IACP,MAAM;IACN,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,QAAQ;GACV;GACA,UAAU;IACR,WAAW;IACX,WAAW;IACX,WAAW;IACX,UAAU;IACV,KAAK;IACL,cAAc;IACd,MAAM;IACN,YAAY;IACZ,aAAa;IACb,SAAS;IACT,MAAM;IACN,MAAM;IACN,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,OAAO;IACP,SAAS;IACT,OAAO;GACT;GACA,WAAW;IACT,MAAM;IACN,OAAO;GACT;GACA,QAAQ;IACN,WAAW;IACX,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,UAAU;GACZ;GACA,QAAQ;IACN,YAAY;IACZ,OAAO;IACP,WAAW;IACX,OAAO;GACT;GACA,MAAM;IACJ,WAAW;IACX,UAAU;IACV,OAAO;IACP,QAAQ;IACR,SAAS;GACX;GACA,QAAQ;IACN,MAAM;IACN,UAAU;IACV,UAAU;IACV,OAAO;GACT;GACA,MAAM;GACN,MAAM;EACR;EACA,gBAAgB;GACd,OAAO;GACP,UAAU;GACV,WAAW;GACX,kBAAkB;GAClB,OAAO;GACP,aAAa;GACb,QAAQ;GACR,MAAM;GACN,SAAS;EACX;EACA,eAAe;GACb,OAAO;GACP,SAAS;GACT,OAAO;EACT;EACA,MAAM;GACJ,UAAU;GACV,SAAS;GACT,MAAM;GACN,YAAY;GACZ,SAAS;GACT,mBAAmB;GACnB,aAAa;GACb,qBAAqB;GACrB,iBAAiB;GACjB,aAAa;GACb,iBAAiB;GACjB,eAAe;GACf,iBAAiB;GACjB,YAAY;GACZ,eAAe;GACf,YAAY;GACZ,OAAO;GACP,MAAM;GACN,QAAQ;GACR,WAAW;GACX,gBAAgB;GAChB,gBACE;GACF,eAAe;GACf,eAAe;GACf,iBAAiB;GACjB,oBAAoB;GACpB,mBACE;GACF,yBAAyB;GACzB,aAAa;GACb,gBAAgB;GAChB,kBAAkB;GAClB,wBAAwB;GACxB,mBAAmB;EACrB;CACF;AACF"}
@@ -77,6 +77,10 @@ const es = {
77
77
  ungroup: "Desagrupar",
78
78
  strip: "Acciones de anotación"
79
79
  },
80
+ selection: {
81
+ copy: "Copiar",
82
+ strip: "Acciones de selección de texto"
83
+ },
80
84
  shapes: {
81
85
  rectangle: "Rectángulo",
82
86
  circle: "Círculo",
@@ -163,4 +167,4 @@ const es = {
163
167
  //#endregion
164
168
  exports.es = es;
165
169
 
166
- //# sourceMappingURL=es-C5084JO6.cjs.map
170
+ //# sourceMappingURL=es-DtxmixGA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"es-DtxmixGA.cjs","names":[],"sources":["../src/locales/es.ts"],"sourcesContent":["import type { Locale } from '@embedpdf/react/i18n';\n\n/** Spanish pack — loaded lazily (see the i18n `loaders` config in App). The\n * longer Spanish labels are exactly what makes the measured toolbar re-solve\n * on locale switch, with zero configuration. */\nexport const es: Locale = {\n code: 'es',\n name: 'Español',\n translations: {\n commands: {\n zoom: {\n in: 'Acercar',\n out: 'Alejar',\n fitPage: 'Ajustar a la página',\n fitWidth: 'Ajustar al ancho',\n automatic: 'Automático',\n menu: 'Zoom',\n level: 'Nivel de zoom',\n p50: '50 %',\n p100: '100 %',\n p150: '150 %',\n p200: '200 %',\n p400: '400 %',\n },\n pan: 'Desplazar',\n pointer: 'Puntero',\n sidebar: 'Barra lateral',\n search: 'Buscar',\n comment: 'Comentario',\n style: 'Estilo',\n menu: 'Menú',\n viewControls: 'Controles de vista',\n download: 'Descargar',\n print: 'Imprimir',\n fullscreen: 'Pantalla completa',\n spread: {\n group: 'Diseño de página',\n none: 'Una página',\n odd: 'Dos páginas',\n even: 'Portada',\n },\n scroll: { group: 'Desplazamiento', vertical: 'Vertical', horizontal: 'Horizontal' },\n rotate: {\n group: 'Girar',\n clockwise: 'Girar a la derecha',\n counterclockwise: 'Girar a la izquierda',\n },\n mode: {\n group: 'Modo',\n view: 'Ver',\n annotate: 'Anotar',\n shapes: 'Formas',\n insert: 'Insertar',\n form: 'Formulario',\n redact: 'Redactar',\n },\n annotate: {\n highlight: 'Resaltar',\n strikeout: 'Tachar',\n underline: 'Subrayar',\n squiggly: 'Ondulado',\n ink: 'Dibujar',\n inkHighlight: 'Resaltador a mano alzada',\n text: 'Texto',\n insertText: 'Insertar texto',\n replaceText: 'Reemplazar texto',\n callout: 'Llamada',\n note: 'Comentario',\n link: 'Enlace',\n gotoLink: 'Ir al enlace',\n removeLink: 'Quitar enlace',\n delete: 'Eliminar',\n group: 'Agrupar',\n ungroup: 'Desagrupar',\n strip: 'Acciones de anotación',\n },\n selection: {\n copy: 'Copiar',\n strip: 'Acciones de selección de texto',\n },\n shapes: {\n rectangle: 'Rectángulo',\n circle: 'Círculo',\n line: 'Línea',\n arrow: 'Flecha',\n polygon: 'Polígono',\n polyline: 'Polilínea',\n },\n insert: {\n attachment: 'Adjuntar archivo',\n stamp: 'Sello',\n signature: 'Firma',\n image: 'Imagen',\n },\n form: {\n textfield: 'Campo de texto',\n checkbox: 'Casilla',\n radio: 'Botón de opción',\n select: 'Desplegable',\n listbox: 'Lista',\n },\n redact: {\n mark: 'Marcar para redacción',\n applyAll: 'Aplicar redacciones',\n clearAll: 'Borrar marcas',\n panel: 'Redacciones',\n },\n undo: 'Deshacer',\n redo: 'Rehacer',\n },\n passwordPrompt: {\n title: 'Contraseña requerida',\n required: 'Este documento está protegido con contraseña. Introdúcela para abrirlo.',\n incorrect: 'La contraseña es incorrecta. Inténtalo de nuevo.',\n incorrectWarning: 'Contraseña incorrecta',\n label: 'Contraseña',\n placeholder: 'Introduce la contraseña',\n cancel: 'Cancelar',\n open: 'Abrir',\n opening: 'Abriendo…',\n },\n documentError: {\n title: 'No se pudo abrir el documento',\n unknown: 'El documento no se pudo abrir.',\n close: 'Cerrar documento',\n },\n demo: {\n starting: 'Iniciando el visor…',\n opening: 'Abriendo el documento…',\n more: 'Más',\n thumbnails: 'Miniaturas',\n outline: 'Esquema',\n searchPlaceholder: 'Buscar en el documento…',\n searchTitle: 'Buscar',\n searchCaseSensitive: 'Distinguir mayúsculas',\n searchWholeWord: 'Palabra completa',\n searchRegex: 'Expresión regular',\n searchSearching: 'Buscando…',\n searchResults: '{count} resultados encontrados',\n searchNoResults: 'Sin resultados',\n searchPage: 'Página {page}',\n commentsTitle: 'Comentarios',\n styleTitle: 'Estilo',\n empty: 'Aquí todavía no hay nada en este panel de demostración.',\n page: 'Página {current} de {total}',\n cancel: 'Cancelar',\n pageBadge: 'pág. {page}',\n redactionTitle: 'Redacciones',\n redactionEmpty:\n 'No hay redacciones pendientes. Usa la herramienta Redactar para marcar texto o áreas.',\n redactionArea: 'Marca de área',\n redactionText: 'Marca de texto',\n redactionRemove: 'Quitar marca',\n redactConfirmTitle: '¿Aplicar redacciones?',\n redactConfirmBody:\n 'Eliminar permanentemente el contenido bajo {count} marcas de redacción. No se puede deshacer.',\n redactConfirmCollateral: 'También se eliminarán {count} otras anotaciones.',\n redactApply: 'Aplicar',\n redactApplying: 'Aplicando…',\n redactLabelTitle: 'Etiqueta de redacción',\n redactLabelPlaceholder: 'p. ej. REDACTADO',\n redactLabelRepeat: 'Repetir etiqueta en toda la región',\n },\n },\n};\n"],"mappings":";;;;AAKA,MAAa,KAAa;CACxB,MAAM;CACN,MAAM;CACN,cAAc;EACZ,UAAU;GACR,MAAM;IACJ,IAAI;IACJ,KAAK;IACL,SAAS;IACT,UAAU;IACV,WAAW;IACX,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;GACR;GACA,KAAK;GACL,SAAS;GACT,SAAS;GACT,QAAQ;GACR,SAAS;GACT,OAAO;GACP,MAAM;GACN,cAAc;GACd,UAAU;GACV,OAAO;GACP,YAAY;GACZ,QAAQ;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,MAAM;GACR;GACA,QAAQ;IAAE,OAAO;IAAkB,UAAU;IAAY,YAAY;GAAa;GAClF,QAAQ;IACN,OAAO;IACP,WAAW;IACX,kBAAkB;GACpB;GACA,MAAM;IACJ,OAAO;IACP,MAAM;IACN,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,QAAQ;GACV;GACA,UAAU;IACR,WAAW;IACX,WAAW;IACX,WAAW;IACX,UAAU;IACV,KAAK;IACL,cAAc;IACd,MAAM;IACN,YAAY;IACZ,aAAa;IACb,SAAS;IACT,MAAM;IACN,MAAM;IACN,UAAU;IACV,YAAY;IACZ,QAAQ;IACR,OAAO;IACP,SAAS;IACT,OAAO;GACT;GACA,WAAW;IACT,MAAM;IACN,OAAO;GACT;GACA,QAAQ;IACN,WAAW;IACX,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,UAAU;GACZ;GACA,QAAQ;IACN,YAAY;IACZ,OAAO;IACP,WAAW;IACX,OAAO;GACT;GACA,MAAM;IACJ,WAAW;IACX,UAAU;IACV,OAAO;IACP,QAAQ;IACR,SAAS;GACX;GACA,QAAQ;IACN,MAAM;IACN,UAAU;IACV,UAAU;IACV,OAAO;GACT;GACA,MAAM;GACN,MAAM;EACR;EACA,gBAAgB;GACd,OAAO;GACP,UAAU;GACV,WAAW;GACX,kBAAkB;GAClB,OAAO;GACP,aAAa;GACb,QAAQ;GACR,MAAM;GACN,SAAS;EACX;EACA,eAAe;GACb,OAAO;GACP,SAAS;GACT,OAAO;EACT;EACA,MAAM;GACJ,UAAU;GACV,SAAS;GACT,MAAM;GACN,YAAY;GACZ,SAAS;GACT,mBAAmB;GACnB,aAAa;GACb,qBAAqB;GACrB,iBAAiB;GACjB,aAAa;GACb,iBAAiB;GACjB,eAAe;GACf,iBAAiB;GACjB,YAAY;GACZ,eAAe;GACf,YAAY;GACZ,OAAO;GACP,MAAM;GACN,QAAQ;GACR,WAAW;GACX,gBAAgB;GAChB,gBACE;GACF,eAAe;GACf,eAAe;GACf,iBAAiB;GACjB,oBAAoB;GACpB,mBACE;GACF,yBAAyB;GACzB,aAAa;GACb,gBAAgB;GAChB,kBAAkB;GAClB,wBAAwB;GACxB,mBAAmB;EACrB;CACF;AACF"}
package/dist/index.cjs CHANGED
@@ -171,6 +171,10 @@ const en = {
171
171
  ungroup: "Ungroup",
172
172
  strip: "Annotation actions"
173
173
  },
174
+ selection: {
175
+ copy: "Copy",
176
+ strip: "Text selection actions"
177
+ },
174
178
  shapes: {
175
179
  rectangle: "Rectangle",
176
180
  circle: "Circle",
@@ -1323,19 +1327,13 @@ function AppToolbar({ bar, className }) {
1323
1327
  });
1324
1328
  }
1325
1329
  //#endregion
1326
- //#region src/ui/annotation-strip.tsx
1330
+ //#region src/ui/strip-bar.tsx
1327
1331
  /**
1328
- * The annotation selection strip — v2's floating "selection menu" rebuilt as
1329
- * chrome. Three parties, none of them this file's business to compute:
1330
- *
1331
- * config/chrome.ts `strips.annotation` declares WHAT may appear
1332
- * each command's visible/enabled decides WHICH items show
1333
- * <AnnotationMenu> solves WHERE (camera transform,
1334
- * rotate-knob dodging, pointer isolation)
1335
- *
1336
- * useStripView is the live intersection: hidden commands drop out, empty
1337
- * groups vanish, null when nothing applies. This file only draws pixels.
1338
- * Mounted in the Stage `overlay` slot.
1332
+ * The floating strip's PIXELS, shared by every contextual strip (annotation
1333
+ * selection, text selection, …): a rounded toolbar of command buttons with
1334
+ * derived group separators. The WHERE is each strip's menu component
1335
+ * (`<AnnotationMenu>`, `<SelectionMenu>`); the WHICH is the commands'
1336
+ * `visible`/`enabled` derivations via `useStripView`. This file only draws.
1339
1337
  */
1340
1338
  function StripButton({ cmd, run }) {
1341
1339
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1353,6 +1351,34 @@ function StripButton({ cmd, run }) {
1353
1351
  })
1354
1352
  });
1355
1353
  }
1354
+ function StripBar({ view, label }) {
1355
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1356
+ role: "toolbar",
1357
+ "aria-label": label,
1358
+ className: "border-border-subtle bg-elevated flex items-center gap-1 rounded-lg border p-1 shadow-xl",
1359
+ children: view.groups.map((g, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [i > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1360
+ "aria-hidden": true,
1361
+ className: "bg-border h-5 w-px"
1362
+ }), g.commands.map((cmd) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StripButton, {
1363
+ cmd,
1364
+ run: () => view.execute(cmd.id)
1365
+ }, cmd.id))] }, g.id))
1366
+ });
1367
+ }
1368
+ //#endregion
1369
+ //#region src/ui/annotation-strip.tsx
1370
+ /**
1371
+ * The ANNOTATION-selection floating strip:
1372
+ *
1373
+ * config/chrome.ts `strips.annotation` declares WHAT may appear
1374
+ * each command's visible/enabled decides WHICH items show
1375
+ * <AnnotationMenu> solves WHERE (camera transform,
1376
+ * rotate-knob dodging, pointer isolation)
1377
+ *
1378
+ * useStripView is the live intersection: hidden commands drop out, empty
1379
+ * groups vanish, null when nothing applies. Mounted in the Stage `overlay`
1380
+ * slot. The pixels are the shared <StripBar>.
1381
+ */
1356
1382
  function AnnotationStrip() {
1357
1383
  const t = (0, _embedpdf_react_i18n.useT)();
1358
1384
  const view = (0, _embedpdf_react_toolbar.useStripView)(useStripSchema("annotation"));
@@ -1360,17 +1386,36 @@ function AnnotationStrip() {
1360
1386
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_annotation_menu.AnnotationMenu, {
1361
1387
  placement: "bottom",
1362
1388
  gap: 15,
1363
- children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1364
- role: "toolbar",
1365
- "aria-label": t("commands.annotate.strip"),
1366
- className: "border-border-subtle bg-elevated flex items-center gap-1 rounded-lg border p-1 shadow-xl",
1367
- children: view.groups.map((g, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [i > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1368
- "aria-hidden": true,
1369
- className: "bg-border h-5 w-px"
1370
- }), g.commands.map((cmd) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StripButton, {
1371
- cmd,
1372
- run: () => view.execute(cmd.id)
1373
- }, cmd.id))] }, g.id))
1389
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StripBar, {
1390
+ view,
1391
+ label: t("commands.annotate.strip")
1392
+ })
1393
+ });
1394
+ }
1395
+ //#endregion
1396
+ //#region src/ui/selection-strip.tsx
1397
+ /**
1398
+ * The TEXT-SELECTION floating strip:
1399
+ *
1400
+ * config/chrome.ts `strips.selection` declares WHAT may appear
1401
+ * each command's visible/enabled decides WHICH items show
1402
+ * <SelectionMenu> solves WHERE (settles on pointer-up,
1403
+ * camera transform, pointer isolation)
1404
+ *
1405
+ * `useStripView` is the live intersection: with copy denied (no
1406
+ * doc.text.copy) every command drops out and this renders nothing — no
1407
+ * empty bubble. Mounted in the Stage `overlay` slot.
1408
+ */
1409
+ function SelectionStrip() {
1410
+ const t = (0, _embedpdf_react_i18n.useT)();
1411
+ const view = (0, _embedpdf_react_toolbar.useStripView)(useStripSchema("selection"));
1412
+ if (!view) return null;
1413
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_selection.SelectionMenu, {
1414
+ placement: "bottom",
1415
+ gap: 12,
1416
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StripBar, {
1417
+ view,
1418
+ label: t("commands.selection.strip")
1374
1419
  })
1375
1420
  });
1376
1421
  }
@@ -3354,10 +3399,12 @@ function Shell() {
3354
3399
  className: "relative min-w-0 flex-1",
3355
3400
  children: [
3356
3401
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ArmedToolCursor, {}),
3402
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_selection.SelectionClipboard, {}),
3357
3403
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_stage.Stage, {
3358
3404
  interaction: true,
3359
3405
  overlay: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
3360
3406
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AnnotationStrip, {}),
3407
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectionStrip, {}),
3361
3408
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_scrollbar.Scrollbar, { axis: "y" }),
3362
3409
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_scrollbar.Scrollbar, { axis: "x" })
3363
3410
  ] }),
@@ -3365,7 +3412,6 @@ function Shell() {
3365
3412
  style: { background: "var(--ep-canvas)" },
3366
3413
  children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
3367
3414
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_render.RenderLayer, { annotations: false }),
3368
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_render.TileLayer, { annotations: false }),
3369
3415
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_selection.SelectionLayer, {}),
3370
3416
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_search.SearchLayer, {}),
3371
3417
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_link.LinkLayer, {}),
@@ -3404,7 +3450,7 @@ function Shell() {
3404
3450
  * changing these props on a mounted viewer does not rebuild the workspace.
3405
3451
  */
3406
3452
  /** Lazy built-in packs — a strings override for one of these wraps its loader. */
3407
- const BUILTIN_LOADERS = { es: () => Promise.resolve().then(() => require("./es-C5084JO6.cjs")).then((m) => m.es) };
3453
+ const BUILTIN_LOADERS = { es: () => Promise.resolve().then(() => require("./es-DtxmixGA.cjs")).then((m) => m.es) };
3408
3454
  const isDict = (v) => typeof v === "object" && v !== null;
3409
3455
  /**
3410
3456
  * Deep-merge `over` into `base` (immutably), expanding dotted keys —