@openpen/module-api 1.2.0 → 1.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 (36) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +7 -1
  3. package/dist/_chunks/{AppButtonDropdown.vue_vue_type_style_index_0_lang-DBVFUpxc.js → AppButtonDropdown.vue_vue_type_style_index_0_lang-B9dHU-LE.js} +3 -2
  4. package/dist/_chunks/AppButtonDropdown.vue_vue_type_style_index_0_lang-B9dHU-LE.js.map +1 -0
  5. package/dist/host/index.d.ts +1 -1
  6. package/dist/host/index.js +2 -0
  7. package/dist/host/index.js.map +1 -1
  8. package/dist/host/stroke-store.d.ts +1 -0
  9. package/dist/host/tools.d.ts +9 -0
  10. package/dist/host/types.d.ts +19 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/index.js +5 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/types/contributions.d.ts +7 -5
  15. package/dist/types/control-bar-layout.d.ts +19 -148
  16. package/dist/types/module.d.ts +7 -1
  17. package/dist/types/tool.d.ts +14 -3
  18. package/dist/uikit/components/AppButtonDropdown.vue.d.ts +1 -1
  19. package/dist/uikit/components/AppPopoverPanel.vue.d.ts +28 -0
  20. package/dist/uikit/components/AppPopoverRow.vue.d.ts +26 -0
  21. package/dist/uikit/components/AppSegmented.vue.d.ts +6 -1
  22. package/dist/uikit/components/AppSelect.vue.d.ts +7 -0
  23. package/dist/uikit/components/AppSlider.vue.d.ts +14 -0
  24. package/dist/uikit/components/AppSwatchPicker.vue.d.ts +37 -0
  25. package/dist/uikit/components/AppToggle.vue.d.ts +2 -0
  26. package/dist/uikit/components/AppToggleButton.vue.d.ts +28 -0
  27. package/dist/uikit/index.d.ts +9 -3
  28. package/dist/uikit/index.js +346 -109
  29. package/dist/uikit/index.js.map +1 -1
  30. package/dist/uikit/internal.js +1 -1
  31. package/dist/uikit/module-api.css +287 -86
  32. package/dist/uikit/primitives.d.ts +4 -2
  33. package/dist/uikit/tokens.css +7 -6
  34. package/dist/use-module-context.d.ts +1 -2
  35. package/package.json +4 -4
  36. package/dist/_chunks/AppButtonDropdown.vue_vue_type_style_index_0_lang-DBVFUpxc.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"AppButtonDropdown.vue_vue_type_style_index_0_lang-DBVFUpxc.js","sources":["../../src/uikit/components/AppDialog.vue","../../src/uikit/composables/useDialog.ts","../../src/uikit/composables/dialog-internal-keys.ts"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * AppDialog — High-level wrapper (Layer 1).\n *\n * Plugin authors use this component without needing to know about inject\n * keys, Reka UI, modal manager mutual exclusion, or the animating guard.\n *\n * Public API is stable: switching the underlying headless library in the\n * future does not break the plugin author's code.\n *\n * Implementation notes:\n * - `open` prop is the single source of truth (controlled mode). The\n * component emits `update:open` for two-way binding. Internally it also\n * registers with the modal manager for mutual exclusion (same pattern as\n * AppPopover): when `open` turns true we call manager.open(); when\n * another panel causes the manager to close us we emit update:open(false).\n * - `persistent`: when true, ESC and backdrop clicks are suppressed via\n * @interact-outside.prevent and @escape-key-down.prevent on DialogContent.\n * - `danger`: adds class `openpen-modal-danger` on the content element as a\n * styling hook for destructive-action dialogs (no default style yet).\n * - animating guard: auto-close during ControlBar scaleY animation.\n * - usePassthroughGuard: registered on the dialog content element so the\n * transparent Electron window remains clickable when dialog is open.\n * - Styles are unscoped because DialogContent is teleported outside the\n * component's DOM subtree (same reason as AppPopover).\n *\n * CSS class names (.openpen-modal-*) are intentionally kept as the carried-over\n * internal styling tokens — renaming carries no DX benefit and risks accidental\n * style breakage in any code path still referencing them.\n */\nimport { computed, inject, onBeforeUnmount, ref, useTemplateRef, watch } from 'vue'\nimport {\n DialogRoot,\n DialogTrigger,\n DialogPortal,\n DialogContent,\n DialogOverlay,\n DialogClose,\n DialogTitle,\n DialogDescription,\n} from '../primitives'\n// Inject keys MUST come from the package barrel — see AppPopover.vue\n// header comment for why relative imports break Symbol identity in prod.\nimport {\n MODAL_MANAGER_KEY,\n CONTROL_BAR_ANIMATING_KEY,\n HOST_DIALOG_OPEN_COUNT_KEY,\n} from '@openpen/module-api'\nimport { usePassthroughGuard } from '../../host/passthrough'\n\n// ── OpenPen-owned types (MUST NOT reference reka-ui types) ───────────────────\n\nexport interface AppDialogProps {\n /** Globally unique modal id; used for modal-stack mutual exclusion. */\n modalId: string\n /** Dialog title displayed in the dialog header. */\n title: string\n /** Controlled open state. The parent must handle update:open to toggle. */\n open: boolean\n /**\n * When true, ESC key and backdrop clicks do not close the dialog.\n * Use for confirmations that require an explicit button press.\n */\n persistent?: boolean\n /**\n * When true, adds the `openpen-modal-danger` CSS class on the content\n * element — a hook for styling destructive-action dialogs.\n */\n danger?: boolean\n}\n\nexport interface AppDialogSlots {\n /**\n * Trigger slot; scope exposes active state + toggle / open / close actions.\n * MUST NOT write @click=\"toggle\" on the trigger — DialogTrigger's as-child\n * handles activation automatically; toggle/open/close are escape hatches for\n * programmatic control only.\n */\n trigger: (scope: {\n active: boolean\n toggle: () => void\n open: () => void\n close: () => void\n }) => unknown\n /** Dialog body content slot. */\n default: () => unknown\n /** Optional footer slot (action buttons etc.). */\n footer?: () => unknown\n}\n\nconst props = withDefaults(defineProps<AppDialogProps>(), {\n persistent: false,\n danger: false,\n})\n\nconst emit = defineEmits<{\n 'update:open': [value: boolean]\n}>()\n\ndefineSlots<AppDialogSlots>()\n\n// ── 1. Inject host context (plugin author never sees these) ───────────────────\n\nconst modalManager = inject(MODAL_MANAGER_KEY)\nconst animating = inject(CONTROL_BAR_ANIMATING_KEY)\nconst dialogOpenCount = inject(HOST_DIALOG_OPEN_COUNT_KEY, null)\n\n// Track whether THIS instance currently holds a count, so we never double\n// increment / decrement (e.g. on rapid open / close cycles or unmount-while-open).\nlet counted = false\n\nfunction acquireCount() {\n if (counted || !dialogOpenCount) return\n dialogOpenCount.value += 1\n counted = true\n}\n\nfunction releaseCount() {\n if (!counted || !dialogOpenCount) return\n dialogOpenCount.value -= 1\n counted = false\n}\n\nonBeforeUnmount(releaseCount)\n\n// ── 2. Modal manager mutual exclusion + controlled open prop ─────────────────\n//\n// The `open` prop is the canonical state. We watch it and push changes into\n// the modal manager. When the manager closes us (e.g. another panel opens),\n// we detect that via the computed isManagerOpen and emit update:open(false).\n\nfunction openDialog() {\n modalManager?.open(props.modalId)\n emit('update:open', true)\n}\n\nfunction closeDialog() {\n modalManager?.close(props.modalId)\n emit('update:open', false)\n}\n\nfunction toggleDialog() {\n if (props.open) {\n closeDialog()\n } else {\n openDialog()\n }\n}\n\n// When the prop turns true: register with the manager + bump host dialog count.\n// When it turns false: unregister + release count. Keeps everything in sync.\nwatch(\n () => props.open,\n (newOpen) => {\n if (newOpen) {\n modalManager?.open(props.modalId)\n acquireCount()\n } else {\n modalManager?.close(props.modalId)\n releaseCount()\n }\n },\n { immediate: true }\n)\n\n// When the manager closes us (another panel opened), emit update:open(false)\n// so the parent's v-model updates.\nconst isManagerOpen = computed(() => modalManager?.isOpen(props.modalId) ?? props.open)\n\nwatch(isManagerOpen, (managerOpen) => {\n if (!managerOpen && props.open) {\n emit('update:open', false)\n }\n})\n\n// Effective open state passed to Reka UI's DialogRoot.\nconst isOpen = computed(() => props.open && isManagerOpen.value)\n\n// Sync Reka UI's internal close events (ESC, overlay click) back to caller\n// unless `persistent` suppresses them.\nfunction onUpdateOpen(v: boolean) {\n if (!v && props.persistent) {\n // Persistent mode: ignore Reka UI close attempts; stay open.\n return\n }\n if (v) {\n openDialog()\n } else {\n closeDialog()\n }\n}\n\n// ── 3. ControlBar animation guard — auto-close during transitions ─────────────\n\nwatch(\n () => animating?.value,\n (isAnimating) => {\n if (isAnimating && props.open) {\n closeDialog()\n }\n }\n)\n\n// ── 4. Passthrough guard integration ─────────────────────────────────────────\n//\n// DialogContent is a Vue component; normalize to HTMLElement via watcher.\n\nconst contentInstance = useTemplateRef<HTMLElement | { $el?: HTMLElement } | null>('content')\nconst contentEl = ref<HTMLElement | null>(null)\n\nwatch(contentInstance, (instance) => {\n if (!instance) {\n contentEl.value = null\n } else if (instance instanceof HTMLElement) {\n contentEl.value = instance\n } else if (typeof instance === 'object' && '$el' in instance && instance.$el instanceof HTMLElement) {\n contentEl.value = instance.$el\n } else {\n contentEl.value = null\n }\n})\n\nusePassthroughGuard(contentEl)\n</script>\n\n<template>\n <DialogRoot :open=\"isOpen\" @update:open=\"onUpdateOpen\">\n <DialogTrigger as-child>\n <slot\n name=\"trigger\"\n :active=\"isOpen\"\n :toggle=\"toggleDialog\"\n :open=\"openDialog\"\n :close=\"closeDialog\"\n />\n </DialogTrigger>\n <DialogPortal>\n <DialogOverlay class=\"openpen-modal-overlay\" />\n <DialogContent\n ref=\"content\"\n class=\"openpen-modal-content openpen-interactive\"\n :class=\"{ 'openpen-modal-danger': danger }\"\n @interact-outside=\"(e: Event) => persistent && e.preventDefault()\"\n @escape-key-down=\"(e: KeyboardEvent) => persistent && e.preventDefault()\"\n >\n <DialogTitle class=\"openpen-modal-title\">{{ title }}</DialogTitle>\n <DialogDescription class=\"openpen-modal-description sr-only\" />\n <div class=\"openpen-modal-body\">\n <slot />\n </div>\n <div v-if=\"$slots.footer\" class=\"openpen-modal-footer\">\n <slot name=\"footer\" />\n </div>\n <DialogClose class=\"openpen-modal-close\" aria-label=\"Close\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M1 1L13 13M13 1L1 13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </DialogClose>\n </DialogContent>\n </DialogPortal>\n </DialogRoot>\n</template>\n\n<!-- Styles MUST be unscoped — Vue scoped CSS does not follow Teleport targets,\n so .openpen-modal-* classes would not receive the scoped data-v-* attribute\n when rendered inside the portal. -->\n<style>\n/* ── Overlay (transparent click absorber, NOT a dim backdrop) ─────────────────\n OpenPen's overlay window is transparent + frameless. A traditional dim/blur\n backdrop renders as a small dark patch only over the visible chrome — visually\n jarring. The overlay is therefore kept fully transparent here; its only job\n is to absorb outside clicks (so Reka can dispatch interact-outside → close\n when not persistent) and to protect the canvas from stray clicks while the\n dialog is open. Host containers (e.g. ControlBar) render their own \"locked\"\n visual state via HOST_DIALOG_OPEN_COUNT_KEY. */\n.openpen-modal-overlay {\n position: fixed;\n inset: 0;\n background: transparent;\n z-index: 200;\n pointer-events: auto;\n}\n\n/* ── Dialog content panel ────────────────────────────────────────────────── */\n.openpen-modal-content {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 201;\n min-width: 320px;\n max-width: min(480px, calc(100vw - 48px));\n max-height: calc(100vh - 96px);\n overflow-y: auto;\n\n background: var(--openpen-color-surface-popup);\n border: 1px solid var(--openpen-color-border-hi);\n border-radius: var(--openpen-radius-lg);\n box-shadow: var(--openpen-shadow);\n backdrop-filter: var(--openpen-blur);\n -webkit-backdrop-filter: var(--openpen-blur);\n\n color: var(--openpen-color-text-primary);\n font-size: 13px;\n padding: var(--openpen-space-lg);\n pointer-events: auto;\n}\n\n/* ── Title ───────────────────────────────────────────────────────────────── */\n.openpen-modal-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--openpen-color-text-primary);\n margin: 0 0 var(--openpen-space-md) 0;\n padding-right: 28px; /* leave room for close button */\n line-height: 1.4;\n}\n\n/* ── Visually hidden description (a11y) ──────────────────────────────────── */\n.openpen-modal-description.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n\n/* ── Body ────────────────────────────────────────────────────────────────── */\n.openpen-modal-body {\n color: var(--openpen-color-text-primary);\n}\n\n/* ── Footer ──────────────────────────────────────────────────────────────── */\n.openpen-modal-footer {\n display: flex;\n justify-content: flex-end;\n gap: var(--openpen-space-sm);\n margin-top: var(--openpen-space-lg);\n padding-top: var(--openpen-space-md);\n border-top: 1px solid var(--openpen-color-border);\n}\n\n/* ── Close button ────────────────────────────────────────────────────────── */\n.openpen-modal-close {\n position: absolute;\n top: var(--openpen-space-md);\n right: var(--openpen-space-md);\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n background: transparent;\n color: var(--openpen-color-text-dim);\n border-radius: var(--openpen-radius-sm);\n cursor: pointer;\n transition: background var(--openpen-duration-fast), color var(--openpen-duration-fast);\n}\n\n.openpen-modal-close:hover {\n background: var(--openpen-color-control-hover);\n color: var(--openpen-color-text-primary);\n}\n\n/* ── Open / close animations ─────────────────────────────────────────────────\n Reka UI's Presence keeps the element in the DOM until the CSS animation\n ends, so [data-state=\"closed\"] animations DO play on close.\n Pattern matches AppPopover keyframes (200ms bounce enter, 150ms ease leave). */\n\n/* Overlay is always transparent — no fade-in/out animation needed.\n Only the dialog content panel animates. */\n\n.openpen-modal-content[data-state='open'] {\n animation: openpen-modal-in 200ms cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n.openpen-modal-content[data-state='closed'] {\n animation: openpen-modal-out 150ms ease forwards;\n}\n\n@keyframes openpen-modal-in {\n from { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }\n to { opacity: 1; transform: translate(-50%, -50%) scale(1); }\n}\n@keyframes openpen-modal-out {\n from { opacity: 1; transform: translate(-50%, -50%) scale(1); }\n to { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }\n}\n</style>\n","/**\n * useDialog — imperative dialog API for OpenPen modules.\n *\n * Returns a DialogApi with confirm/alert/prompt/custom methods that each\n * return a Promise. At most one imperative dialog is open at a time; extra\n * calls are queued and executed sequentially.\n *\n * The active request is stored in a module-scoped reactive store. DialogHost\n * (mounted by the host at bootstrap) reads this store and renders the dialog.\n *\n * Usage:\n * const dialog = useDialog()\n * const ok = await dialog.confirm({ title: 'Delete?', message: '...' })\n */\nimport type { Component } from 'vue'\nimport { ref } from 'vue'\n\n// ── Public option types ───────────────────────────────────────────────────────\n\ninterface BaseDialogOptions {\n title: string\n persistent?: boolean\n danger?: boolean\n}\n\nexport interface DialogConfirmOptions extends BaseDialogOptions {\n message: string\n okLabel?: string\n cancelLabel?: string\n}\n\nexport interface DialogAlertOptions extends BaseDialogOptions {\n message: string\n okLabel?: string\n}\n\nexport interface DialogPromptOptions extends BaseDialogOptions {\n message: string\n defaultValue?: string\n placeholder?: string\n okLabel?: string\n cancelLabel?: string\n}\n\nexport interface DialogCustomOptions<T = unknown> extends BaseDialogOptions {\n component: Component\n componentProps?: Record<string, unknown>\n /** Phantom type field for TypeScript to infer the resolution payload type. */\n __payloadType?: T\n}\n\n// ── Internal request types (tagged union) ─────────────────────────────────────\n\ntype DialogRequest =\n | { kind: 'confirm'; opts: DialogConfirmOptions; resolve: (v: boolean) => void }\n | { kind: 'alert'; opts: DialogAlertOptions; resolve: () => void }\n | { kind: 'prompt'; opts: DialogPromptOptions; resolve: (v: string | null) => void }\n | { kind: 'custom'; opts: DialogCustomOptions<unknown>; resolve: (v: unknown) => void }\n\n// ── Module-scoped store ───────────────────────────────────────────────────────\n//\n// Single reactive ref holds the currently rendered request. DialogHost watches\n// this and renders the appropriate dialog. When DialogHost resolves a request,\n// it calls resolveActive() which drains the queue.\n\nexport const _activeRequest = ref<DialogRequest | null>(null)\n\nconst _queue: (() => void)[] = []\nlet _processing = false\n\nfunction _enqueue(run: () => void): void {\n if (_processing) {\n _queue.push(run)\n } else {\n _processing = true\n run()\n }\n}\n\n/**\n * Called by DialogHost when the dialog is resolved (ok/cancel/dismiss).\n * Advances the queue if there are pending requests.\n */\nexport function _resolveActive(): void {\n _activeRequest.value = null\n const next = _queue.shift()\n if (next) {\n next()\n } else {\n _processing = false\n }\n}\n\n// ── Public API ────────────────────────────────────────────────────────────────\n\nexport interface DialogApi {\n confirm(opts: DialogConfirmOptions): Promise<boolean>\n alert(opts: DialogAlertOptions): Promise<void>\n prompt(opts: DialogPromptOptions): Promise<string | null>\n custom<T = unknown>(opts: DialogCustomOptions<T>): Promise<T | null>\n}\n\nexport function useDialog(): DialogApi {\n return {\n confirm(opts: DialogConfirmOptions): Promise<boolean> {\n return new Promise<boolean>((resolve) => {\n _enqueue(() => {\n _activeRequest.value = { kind: 'confirm', opts, resolve }\n })\n })\n },\n\n alert(opts: DialogAlertOptions): Promise<void> {\n return new Promise<void>((resolve) => {\n _enqueue(() => {\n _activeRequest.value = { kind: 'alert', opts, resolve }\n })\n })\n },\n\n prompt(opts: DialogPromptOptions): Promise<string | null> {\n return new Promise<string | null>((resolve) => {\n _enqueue(() => {\n _activeRequest.value = { kind: 'prompt', opts, resolve }\n })\n })\n },\n\n custom<T = unknown>(opts: DialogCustomOptions<T>): Promise<T | null> {\n return new Promise<T | null>((resolve) => {\n _enqueue(() => {\n _activeRequest.value = {\n kind: 'custom',\n opts: opts as DialogCustomOptions<unknown>,\n resolve: resolve as (v: unknown) => void,\n }\n })\n })\n },\n }\n}\n","/**\n * dialog-internal-keys.ts — Internal injection keys for the imperative dialog system.\n *\n * HOST-INTERNAL: Do not export from any public barrel. Plugin authors must\n * never see or depend on these keys; they exist only so DialogHost can\n * provide the handle that useDialogPluginComponent() reads.\n */\nimport type { InjectionKey } from 'vue'\nimport type { DialogPluginComponentHandle } from './useDialogPluginComponent'\n\n/**\n * Injection key that DialogHost provides to custom dialog components.\n * Components rendered via useDialog().custom() use useDialogPluginComponent()\n * which injects this key to get ok/cancel/dismiss callbacks.\n */\nexport const DIALOG_PLUGIN_HANDLE_KEY: InjectionKey<DialogPluginComponentHandle<unknown>> =\n Symbol('openpen:dialog-plugin-handle')\n"],"names":["_createBlock","_unref","_createVNode","_renderSlot","_normalizeClass","_createElementVNode","$slots","_openBlock","_createElementBlock"],"mappings":"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"}