@stacksjs/desktop 0.2.195 → 0.2.197

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.
package/dist/index.js.map DELETED
@@ -1,72 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/alerts.ts", "../src/components.ts", "../src/modals.ts", "../src/system-tray.ts", "../src/dialogs.ts", "../src/window.ts", "../src/packaging.ts", "../src/self-update.ts", "../src/power.ts", "../src/preferences.ts", "../src/autolaunch.ts", "../src/hotkeys.ts", "../src/timer.ts", "../src/_bridge.ts", "../src/clipboard.ts", "../src/notifications.ts", "../src/fs.ts", "../src/shell.ts", "../src/global-shortcuts.ts", "../src/theme.ts", "../src/drag-out.ts", "../src/deep-link.ts", "../src/battery.ts", "../src/network.ts", "../src/updater.ts", "../src/window-events.ts", "../src/app-info.ts", "../src/menu.ts", "../src/system.ts", "../src/screen.ts", "../src/keychain.ts", "../src/permissions.ts", "../src/printing.ts", "../src/native-autolaunch.ts", "../src/touchbar.ts", "../src/bluetooth.ts", "../src/speech.ts", "../src/crash-reporter.ts", "../src/iap.ts", "../src/handoff.ts", "../src/live-activities.ts", "../src/location.ts", "../src/screen-capture.ts", "../src/screen-sharing.ts", "../src/focus.ts", "../src/local-server.ts", "../src/biometric.ts", "../src/audio.ts", "../src/apple-script.ts", "../src/file-associations.ts", "../src/tags.ts", "../src/pdf.ts", "../src/log.ts", "../src/bonjour.ts", "../src/spotlight.ts", "../src/speech-recognition.ts", "../src/vision.ts", "../src/midi.ts", "../src/coreml.ts", "../src/continuity-camera.ts", "../src/service-menu.ts", "../src/serial.ts", "../src/capabilities.ts"],
4
- "sourcesContent": [
5
- "import type { AlertOptions, ToastOptions } from './types'\n\n/**\n * Alert / Toast Notification Implementation\n *\n * Provides cross-platform notification functionality.\n * Uses native notifications when available, falls back to web-based toasts.\n *\n * Features:\n * - Multiple notification types (info, success, warning, error)\n * - Configurable position and duration\n * - Auto-dismiss with optional manual close\n * - Queue management for multiple notifications\n * - Click handlers\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface AlertState {\n id: string\n options: AlertOptions\n element?: HTMLElement\n timeout?: ReturnType<typeof setTimeout>\n}\n\n// =============================================================================\n// Platform Detection\n// =============================================================================\n\n/**\n * Check if native notifications are available\n */\nfunction hasNativeNotificationSupport(): boolean {\n // Check for browser Notification API\n if (typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n return true\n }\n // Future: Check for @stacksjs/zyte bindings for desktop notifications\n return false\n}\n\n/**\n * Check if running in browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined'\n}\n\n/**\n * Request notification permission (browser)\n */\nexport async function requestNotificationPermission(): Promise<boolean> {\n if (typeof Notification === 'undefined') {\n return false\n }\n\n if (Notification.permission === 'granted') {\n return true\n }\n\n if (Notification.permission === 'denied') {\n return false\n }\n\n const permission = await Notification.requestPermission()\n return permission === 'granted'\n}\n\n// =============================================================================\n// Alert Manager\n// =============================================================================\n\n// Active alerts\nconst activeAlerts = new Map<string, AlertState>()\n\n// Toast container element\nconst _toastContainer: HTMLElement | null = null\n\n/**\n * Generate a unique alert ID\n */\nfunction generateAlertId(): string {\n return `alert-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n}\n\n/**\n * Get icon for alert type\n */\nfunction getAlertIcon(type: AlertOptions['type']): string {\n switch (type) {\n case 'info':\n return '&#x2139;'\n case 'success':\n return '&#x2714;'\n case 'warning':\n return '&#x26A0;'\n case 'error':\n return '&#x2716;'\n default:\n return '&#x2139;'\n }\n}\n\n/**\n * Get or create the toast container element\n */\nfunction getToastContainer(position: AlertOptions['position'] = 'top-right'): HTMLElement {\n if (!isBrowser()) {\n throw new Error('Toast container requires browser environment')\n }\n\n // Check if container already exists with correct position\n try {\n const existingContainer = document.querySelector(`.stx-toast-container[data-position=\"${position}\"]`)\n if (existingContainer) {\n return existingContainer as HTMLElement\n }\n }\n catch {\n // Ignore querySelector errors in very-happy-dom\n }\n\n // Create new container\n const container = document.createElement('div')\n container.className = `stx-toast-container ${position}`\n container.dataset.position = position\n\n // Safely append to body\n try {\n if (document.body) {\n document.body.appendChild(container)\n }\n }\n catch {\n // Ignore appendChild errors in very-happy-dom\n }\n\n return container\n}\n\n/**\n * Create toast HTML\n */\nfunction createToastHTML(state: AlertState): string {\n const { options } = state\n const icon = getAlertIcon(options.type)\n const typeClass = options.type || 'info'\n const hasClose = options.duration !== 0\n\n return `\n <div class=\"stx-toast ${typeClass}\" data-alert-id=\"${state.id}\" role=\"alert\" aria-live=\"polite\">\n <div class=\"stx-toast-icon\">${icon}</div>\n <div class=\"stx-toast-content\">\n ${options.title ? `<div class=\"stx-toast-title\">${escapeHtml(options.title)}</div>` : ''}\n <div class=\"stx-toast-message\">${escapeHtml(options.message)}</div>\n </div>\n ${hasClose ? '<button class=\"stx-toast-close\" aria-label=\"Close\">&times;</button>' : ''}\n </div>\n `\n}\n\n/**\n * Escape HTML to prevent XSS\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;')\n}\n\n/**\n * Dismiss an alert\n */\nfunction dismissAlert(state: AlertState): void {\n // Clear timeout if exists\n if (state.timeout) {\n clearTimeout(state.timeout)\n }\n\n // Remove from active alerts\n activeAlerts.delete(state.id)\n\n // Animate out and remove element\n if (state.element && isBrowser()) {\n state.element.classList.add('dismissing')\n setTimeout(() => {\n state.element?.remove()\n }, 200)\n }\n}\n\n/**\n * Show an alert/notification\n *\n * @param options - Alert configuration options\n *\n * @example\n * ```typescript\n * await showAlert({\n * title: 'Success',\n * message: 'Your changes have been saved',\n * type: 'success',\n * duration: 3000,\n * position: 'top-right',\n * })\n * ```\n */\nexport async function showAlert(options: AlertOptions): Promise<void> {\n const id = generateAlertId()\n const hasNative = hasNativeNotificationSupport()\n const duration = options.duration ?? 5000\n\n const state: AlertState = {\n id,\n options,\n }\n\n activeAlerts.set(id, state)\n\n if (hasNative && options.type !== 'error') {\n // Use native Notification API for non-error alerts\n try {\n const notification = new Notification(options.title || 'Notification', {\n body: options.message,\n icon: options.type === 'success' ? '✓' : options.type === 'warning' ? '⚠' : 'ℹ',\n tag: id,\n })\n\n notification.onclick = () => {\n if (options.onClick) {\n options.onClick()\n }\n notification.close()\n }\n\n if (duration > 0) {\n state.timeout = setTimeout(() => {\n notification.close()\n activeAlerts.delete(id)\n }, duration)\n }\n\n return\n }\n catch {\n // Fall through to web-based implementation\n }\n }\n\n if (isBrowser()) {\n // Web-based toast implementation\n try {\n const container = getToastContainer(options.position)\n const wrapper = document.createElement('div')\n wrapper.innerHTML = createToastHTML(state)\n const toast = wrapper.firstElementChild as HTMLElement\n\n if (!toast) {\n // Fallback to console if DOM manipulation fails\n const typeLabel = (options.type || 'info').toUpperCase()\n console.log(`[stx-alert] ${typeLabel}: ${options.title || ''}`)\n console.log(`[stx-alert] ${options.message}`)\n return\n }\n\n state.element = toast\n\n // Add to container\n try {\n container.appendChild(toast)\n }\n catch {\n // Fallback to console if appendChild fails (e.g., in very-happy-dom)\n const typeLabel = (options.type || 'info').toUpperCase()\n console.log(`[stx-alert] ${typeLabel}: ${options.title || ''}`)\n console.log(`[stx-alert] ${options.message}`)\n return\n }\n\n // Trigger animation\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => {\n try {\n toast.classList.add('visible')\n }\n catch {\n // Ignore classList errors\n }\n })\n }\n\n // Handle click\n try {\n toast.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).classList?.contains('stx-toast-close')) {\n dismissAlert(state)\n return\n }\n\n if (options.onClick) {\n options.onClick()\n }\n })\n }\n catch {\n // Ignore addEventListener errors\n }\n\n // Auto-dismiss\n if (duration > 0) {\n state.timeout = setTimeout(() => {\n dismissAlert(state)\n }, duration)\n }\n }\n catch {\n // Fallback to console if any DOM operation fails\n const typeLabel = (options.type || 'info').toUpperCase()\n console.log(`[stx-alert] ${typeLabel}: ${options.title || ''}`)\n console.log(`[stx-alert] ${options.message}`)\n }\n }\n else {\n // Node.js environment - console fallback\n const typeLabel = (options.type || 'info').toUpperCase()\n console.log(`[stx-alert] ${typeLabel}: ${options.title || ''}`)\n console.log(`[stx-alert] ${options.message}`)\n\n // Auto-dismiss from tracking\n if (duration > 0) {\n state.timeout = setTimeout(() => {\n activeAlerts.delete(id)\n }, duration)\n }\n }\n}\n\n/**\n * Show a toast notification (alias for showAlert with toast-friendly defaults)\n */\nexport async function showToast(options: ToastOptions): Promise<void> {\n return showAlert({\n ...options,\n position: options.position || 'top-right',\n })\n}\n\n/**\n * Show an info toast\n */\nexport async function showInfoToast(message: string, duration = 3000): Promise<void> {\n return showToast({ message, type: 'info', duration })\n}\n\n/**\n * Show a success toast\n */\nexport async function showSuccessToast(message: string, duration = 3000): Promise<void> {\n return showToast({ message, type: 'success', duration })\n}\n\n/**\n * Show a warning toast\n */\nexport async function showWarningToast(message: string, duration = 3000): Promise<void> {\n return showToast({ message, type: 'warning', duration })\n}\n\n/**\n * Show an error toast\n */\nexport async function showErrorToast(message: string, duration = 5000): Promise<void> {\n return showToast({ message, type: 'error', duration })\n}\n\n/**\n * Show a notification with title\n */\nexport async function notify(title: string, message: string, type: AlertOptions['type'] = 'info'): Promise<void> {\n return showAlert({ title, message, type })\n}\n\n/**\n * Dismiss a specific alert by ID\n */\nexport function dismissAlertById(id: string): void {\n const state = activeAlerts.get(id)\n if (state) {\n dismissAlert(state)\n }\n}\n\n/**\n * Dismiss all active alerts\n */\nexport function dismissAllAlerts(): void {\n for (const state of activeAlerts.values()) {\n dismissAlert(state)\n }\n}\n\n/**\n * Get count of active alerts\n */\nexport function getActiveAlertCount(): number {\n return activeAlerts.size\n}\n\n/**\n * CSS styles for web-based toasts\n */\nexport const TOAST_STYLES = `\n.stx-toast-container {\n position: fixed;\n z-index: 10001;\n display: flex;\n flex-direction: column;\n gap: 8px;\n max-width: 400px;\n pointer-events: none;\n}\n\n.stx-toast-container.top-left { top: 16px; left: 16px; }\n.stx-toast-container.top-center { top: 16px; left: 50%; transform: translateX(-50%); }\n.stx-toast-container.top-right { top: 16px; right: 16px; }\n.stx-toast-container.bottom-left { bottom: 16px; left: 16px; }\n.stx-toast-container.bottom-center { bottom: 16px; left: 50%; transform: translateX(-50%); }\n.stx-toast-container.bottom-right { bottom: 16px; right: 16px; }\n\n.stx-toast {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 12px 16px;\n background: #fff;\n border-radius: 8px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n pointer-events: auto;\n cursor: pointer;\n opacity: 0;\n transform: translateY(-10px);\n transition: opacity 0.2s, transform 0.2s;\n}\n\n.stx-toast.visible {\n opacity: 1;\n transform: translateY(0);\n}\n\n.stx-toast.dismissing {\n opacity: 0;\n transform: translateX(100%);\n}\n\n@media (prefers-color-scheme: dark) {\n .stx-toast {\n background: #2d2d2d;\n color: #fff;\n }\n}\n\n.stx-toast-icon {\n font-size: 20px;\n flex-shrink: 0;\n margin-top: 2px;\n}\n\n.stx-toast.info .stx-toast-icon { color: #3498db; }\n.stx-toast.success .stx-toast-icon { color: #27ae60; }\n.stx-toast.warning .stx-toast-icon { color: #f39c12; }\n.stx-toast.error .stx-toast-icon { color: #e74c3c; }\n\n.stx-toast-content {\n flex: 1;\n min-width: 0;\n}\n\n.stx-toast-title {\n font-weight: 600;\n margin-bottom: 4px;\n}\n\n.stx-toast-message {\n color: #666;\n font-size: 14px;\n line-height: 1.4;\n}\n\n@media (prefers-color-scheme: dark) {\n .stx-toast-message { color: #aaa; }\n}\n\n.stx-toast-close {\n background: none;\n border: none;\n font-size: 20px;\n cursor: pointer;\n opacity: 0.5;\n padding: 0;\n line-height: 1;\n color: inherit;\n transition: opacity 0.15s;\n}\n\n.stx-toast-close:hover {\n opacity: 1;\n}\n\n/* Border accent for different types */\n.stx-toast.info { border-left: 4px solid #3498db; }\n.stx-toast.success { border-left: 4px solid #27ae60; }\n.stx-toast.warning { border-left: 4px solid #f39c12; }\n.stx-toast.error { border-left: 4px solid #e74c3c; }\n`\n",
6
- "/* eslint-disable style/max-statements-per-line, indent */\nimport type { ComponentProps } from './types'\n\n/**\n * Native Components for Desktop Applications\n *\n * This module provides TypeScript wrappers for native UI components.\n * Components work in both browser (web-based) and desktop (native) environments.\n *\n * Categories:\n * - Input: Button, TextInput, Checkbox, RadioButton, Slider, ColorPicker, DatePicker, TimePicker, Autocomplete\n * - Display: Label, ImageView, ProgressBar, Avatar, Badge, Chip, Card, Tooltip, Toast\n * - Layout: ScrollView, SplitView, Accordion, Stepper, Modal, Tabs, Dropdown\n * - Data: ListView, Table, TreeView, DataGrid, Chart\n * - Advanced: Rating, CodeEditor, MediaPlayer, FileExplorer, WebView\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Button component properties\n */\nexport interface ButtonProps extends ComponentProps {\n text: string\n onClick?: () => void\n variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive'\n size?: 'small' | 'medium' | 'large'\n disabled?: boolean\n loading?: boolean\n icon?: string\n iconPosition?: 'left' | 'right'\n}\n\n/**\n * TextInput component properties\n */\nexport interface TextInputProps extends ComponentProps {\n value?: string\n placeholder?: string\n onChange?: (value: string) => void\n onSubmit?: (value: string) => void\n type?: 'text' | 'password' | 'email' | 'number' | 'search' | 'url' | 'tel'\n disabled?: boolean\n readonly?: boolean\n maxLength?: number\n minLength?: number\n pattern?: string\n required?: boolean\n autocomplete?: string\n label?: string\n error?: string\n hint?: string\n}\n\n/**\n * Checkbox component properties\n */\nexport interface CheckboxProps extends ComponentProps {\n checked?: boolean\n onChange?: (checked: boolean) => void\n label?: string\n disabled?: boolean\n indeterminate?: boolean\n}\n\n/**\n * RadioButton component properties\n */\nexport interface RadioButtonProps extends ComponentProps {\n value: string\n name: string\n checked?: boolean\n onChange?: (value: string) => void\n label?: string\n disabled?: boolean\n}\n\n/**\n * Slider component properties\n */\nexport interface SliderProps extends ComponentProps {\n value?: number\n min?: number\n max?: number\n step?: number\n onChange?: (value: number) => void\n disabled?: boolean\n label?: string\n showValue?: boolean\n}\n\n/**\n * ProgressBar component properties\n */\nexport interface ProgressBarProps extends ComponentProps {\n value: number\n max?: number\n variant?: 'default' | 'success' | 'warning' | 'error'\n size?: 'small' | 'medium' | 'large'\n showLabel?: boolean\n indeterminate?: boolean\n}\n\n/**\n * Card component properties\n */\nexport interface CardProps extends ComponentProps {\n title?: string\n subtitle?: string\n content?: string\n image?: string\n footer?: string\n onClick?: () => void\n variant?: 'default' | 'outlined' | 'elevated'\n}\n\n/**\n * Badge component properties\n */\nexport interface BadgeProps extends ComponentProps {\n text: string\n variant?: 'default' | 'primary' | 'success' | 'warning' | 'error'\n size?: 'small' | 'medium' | 'large'\n}\n\n/**\n * Avatar component properties\n */\nexport interface AvatarProps extends ComponentProps {\n src?: string\n alt?: string\n name?: string\n size?: 'small' | 'medium' | 'large' | number\n shape?: 'circle' | 'square' | 'rounded'\n}\n\n/**\n * Tabs component properties\n */\nexport interface TabsProps extends ComponentProps {\n tabs: Array<{ label: string, value: string, disabled?: boolean }>\n activeTab?: string\n onChange?: (value: string) => void\n variant?: 'default' | 'pills' | 'underline'\n}\n\n/**\n * Dropdown component properties\n */\nexport interface DropdownProps extends ComponentProps {\n options: Array<{ label: string, value: string, disabled?: boolean }>\n value?: string\n placeholder?: string\n onChange?: (value: string) => void\n disabled?: boolean\n searchable?: boolean\n multiple?: boolean\n}\n\n/**\n * Rating component properties\n */\nexport interface RatingProps extends ComponentProps {\n value?: number\n max?: number\n onChange?: (value: number) => void\n readonly?: boolean\n size?: 'small' | 'medium' | 'large'\n allowHalf?: boolean\n}\n\n/**\n * ColorPicker component properties\n */\nexport interface ColorPickerProps extends ComponentProps {\n value?: string\n onChange?: (color: string) => void\n disabled?: boolean\n label?: string\n format?: 'hex' | 'rgb' | 'hsl'\n showAlpha?: boolean\n presetColors?: string[]\n}\n\n/**\n * DatePicker component properties\n */\nexport interface DatePickerProps extends ComponentProps {\n value?: string | Date\n onChange?: (date: Date | null) => void\n min?: string | Date\n max?: string | Date\n disabled?: boolean\n label?: string\n placeholder?: string\n format?: string\n showClear?: boolean\n}\n\n/**\n * TimePicker component properties\n */\nexport interface TimePickerProps extends ComponentProps {\n value?: string\n onChange?: (time: string) => void\n disabled?: boolean\n label?: string\n format?: '12h' | '24h'\n step?: number\n min?: string\n max?: string\n}\n\n/**\n * Autocomplete component properties\n */\nexport interface AutocompleteProps extends ComponentProps {\n options: Array<{ label: string, value: string }>\n value?: string\n placeholder?: string\n onChange?: (value: string) => void\n onSearch?: (query: string) => void\n disabled?: boolean\n label?: string\n loading?: boolean\n minChars?: number\n maxResults?: number\n}\n\n/**\n * Label component properties\n */\nexport interface LabelProps extends ComponentProps {\n text: string\n htmlFor?: string\n required?: boolean\n size?: 'small' | 'medium' | 'large'\n}\n\n/**\n * ImageView component properties\n */\nexport interface ImageViewProps extends ComponentProps {\n src: string\n alt?: string\n width?: number | string\n height?: number | string\n objectFit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'\n fallback?: string\n loading?: 'eager' | 'lazy'\n onClick?: () => void\n}\n\n/**\n * Chip component properties\n */\nexport interface ChipProps extends ComponentProps {\n text: string\n variant?: 'default' | 'primary' | 'success' | 'warning' | 'error'\n size?: 'small' | 'medium' | 'large'\n removable?: boolean\n onRemove?: () => void\n icon?: string\n onClick?: () => void\n}\n\n/**\n * Tooltip component properties\n */\nexport interface TooltipProps extends ComponentProps {\n text: string\n position?: 'top' | 'right' | 'bottom' | 'left'\n trigger?: 'hover' | 'click' | 'focus'\n delay?: number\n children: string\n}\n\n/**\n * ScrollView component properties\n */\nexport interface ScrollViewProps extends ComponentProps {\n direction?: 'vertical' | 'horizontal' | 'both'\n showScrollbar?: boolean\n smooth?: boolean\n height?: string | number\n width?: string | number\n children: string\n}\n\n/**\n * SplitView component properties\n */\nexport interface SplitViewProps extends ComponentProps {\n direction?: 'horizontal' | 'vertical'\n sizes?: [number, number]\n minSizes?: [number, number]\n resizable?: boolean\n children: [string, string]\n}\n\n/**\n * Accordion component properties\n */\nexport interface AccordionProps extends ComponentProps {\n items: Array<{ title: string, content: string, disabled?: boolean }>\n multiple?: boolean\n defaultOpen?: number[]\n}\n\n/**\n * Stepper component properties\n */\nexport interface StepperProps extends ComponentProps {\n steps: Array<{ label: string, description?: string }>\n currentStep: number\n orientation?: 'horizontal' | 'vertical'\n onStepClick?: (step: number) => void\n}\n\n/**\n * ModalComponent properties (different from modals.ts dialog)\n */\nexport interface ModalComponentProps extends ComponentProps {\n open?: boolean\n title?: string\n size?: 'small' | 'medium' | 'large' | 'fullscreen'\n closable?: boolean\n onClose?: () => void\n children: string\n footer?: string\n}\n\n/**\n * ListView component properties\n */\nexport interface ListViewProps extends ComponentProps {\n items: Array<{ id: string, content: string, selected?: boolean }>\n selectable?: boolean\n multiSelect?: boolean\n onSelect?: (ids: string[]) => void\n emptyMessage?: string\n}\n\n/**\n * Table component properties\n */\nexport interface TableProps extends ComponentProps {\n columns: Array<{ key: string, label: string, width?: string, sortable?: boolean }>\n data: Array<Record<string, unknown>>\n striped?: boolean\n bordered?: boolean\n hoverable?: boolean\n sortBy?: string\n sortOrder?: 'asc' | 'desc'\n onSort?: (column: string) => void\n}\n\n/**\n * TreeView component properties\n */\nexport interface TreeViewProps extends ComponentProps {\n nodes: TreeNode[]\n expandedKeys?: string[]\n selectedKeys?: string[]\n checkable?: boolean\n onExpand?: (keys: string[]) => void\n onSelect?: (keys: string[]) => void\n}\n\nexport interface TreeNode {\n key: string\n label: string\n children?: TreeNode[]\n icon?: string\n disabled?: boolean\n}\n\n/**\n * DataGrid component properties\n */\nexport interface DataGridProps extends ComponentProps {\n columns: Array<{ key: string, label: string, width?: string, sortable?: boolean, filterable?: boolean }>\n data: Array<Record<string, unknown>>\n pagination?: { page: number, pageSize: number, total: number }\n selectable?: boolean\n onPageChange?: (page: number) => void\n onSort?: (column: string, order: 'asc' | 'desc') => void\n}\n\n/**\n * Chart component properties\n */\nexport interface ChartProps extends ComponentProps {\n type: 'line' | 'bar' | 'pie' | 'doughnut' | 'area'\n data: ChartData\n options?: ChartOptions\n width?: number | string\n height?: number | string\n}\n\nexport interface ChartData {\n labels: string[]\n datasets: Array<{\n label: string\n data: number[]\n backgroundColor?: string | string[]\n borderColor?: string\n }>\n}\n\nexport interface ChartOptions {\n title?: string\n legend?: boolean\n animation?: boolean\n}\n\n/**\n * CodeEditor component properties\n */\nexport interface CodeEditorProps extends ComponentProps {\n value?: string\n language?: string\n theme?: 'light' | 'dark'\n lineNumbers?: boolean\n readOnly?: boolean\n onChange?: (value: string) => void\n height?: string | number\n tabSize?: number\n wordWrap?: boolean\n}\n\n/**\n * MediaPlayer component properties\n */\nexport interface MediaPlayerProps extends ComponentProps {\n src: string\n type?: 'video' | 'audio'\n poster?: string\n autoplay?: boolean\n loop?: boolean\n muted?: boolean\n controls?: boolean\n width?: string | number\n height?: string | number\n onPlay?: () => void\n onPause?: () => void\n onEnded?: () => void\n}\n\n/**\n * FileExplorer component properties\n */\nexport interface FileExplorerProps extends ComponentProps {\n files: FileNode[]\n viewMode?: 'list' | 'grid'\n showHidden?: boolean\n selectable?: boolean\n onSelect?: (path: string) => void\n onOpen?: (path: string) => void\n}\n\nexport interface FileNode {\n name: string\n path: string\n type: 'file' | 'folder'\n size?: number\n modified?: Date\n icon?: string\n}\n\n/**\n * WebView component properties\n */\nexport interface WebViewProps extends ComponentProps {\n url: string\n width?: string | number\n height?: string | number\n sandbox?: boolean\n allowScripts?: boolean\n onLoad?: () => void\n onError?: (error: Error) => void\n}\n\n// =============================================================================\n// Utility Functions\n// =============================================================================\n\n/**\n * Generate unique ID for components\n */\nfunction generateId(prefix: string = 'stx'): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n}\n\n/**\n * Escape HTML to prevent XSS\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;')\n}\n\n/**\n * Build class string from props\n */\nfunction buildClasses(...classes: (string | undefined | false)[]): string {\n return classes.filter(Boolean).join(' ')\n}\n\n/**\n * Build style string from object\n */\nfunction buildStyles(styles: Record<string, string> | undefined): string {\n if (!styles)\n return ''\n return Object.entries(styles)\n .map(([key, value]) => `${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value}`)\n .join('; ')\n}\n\n// =============================================================================\n// Input Components\n// =============================================================================\n\n/**\n * Create a Button component\n */\nexport function createButton(props: ButtonProps): string {\n const {\n text,\n variant = 'primary',\n size = 'medium',\n disabled = false,\n loading = false,\n icon,\n iconPosition = 'left',\n id = generateId('btn'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-button',\n `stx-button--${variant}`,\n `stx-button--${size}`,\n disabled && 'stx-button--disabled',\n loading && 'stx-button--loading',\n className,\n )\n\n const styleStr = buildStyles(style)\n const iconHtml = icon ? `<span class=\"stx-button-icon\">${icon}</span>` : ''\n const loadingHtml = loading ? '<span class=\"stx-button-spinner\"></span>' : ''\n\n const content = iconPosition === 'left'\n ? `${iconHtml}${loadingHtml}<span class=\"stx-button-text\">${escapeHtml(text)}</span>`\n : `<span class=\"stx-button-text\">${escapeHtml(text)}</span>${iconHtml}${loadingHtml}`\n\n return `<button id=\"${id}\" class=\"${classes}\" ${disabled || loading ? 'disabled' : ''} ${styleStr ? `style='${styleStr}'` : ''}>${content}</button>`\n}\n\n/**\n * Create a TextInput component\n */\nexport function createTextInput(props: TextInputProps): string {\n const {\n value = '',\n placeholder = '',\n type = 'text',\n disabled = false,\n readonly = false,\n maxLength,\n minLength,\n pattern,\n required = false,\n autocomplete,\n label,\n error,\n hint,\n id = generateId('input'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-input',\n error && 'stx-input--error',\n disabled && 'stx-input--disabled',\n className,\n )\n\n const styleStr = buildStyles(style)\n const attrs = [\n `type=\"${type}\"`,\n `id=\"${id}\"`,\n `class=\"${classes}\"`,\n value && `value=\"${escapeHtml(value)}\"`,\n placeholder && `placeholder=\"${escapeHtml(placeholder)}\"`,\n disabled && 'disabled',\n readonly && 'readonly',\n required && 'required',\n maxLength && `maxlength=\"${maxLength}\"`,\n minLength && `minlength=\"${minLength}\"`,\n pattern && `pattern=\"${escapeHtml(pattern)}\"`,\n autocomplete && `autocomplete=\"${autocomplete}\"`,\n styleStr && `style=\"${styleStr}\"`,\n ].filter(Boolean).join(' ')\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-input-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<input ${attrs} />`\n if (error) {\n html += `<div class=\"stx-input-error\">${escapeHtml(error)}</div>`\n }\n else if (hint) {\n html += `<div class=\"stx-input-hint\">${escapeHtml(hint)}</div>`\n }\n\n return `<div class=\"stx-input-wrapper\">${html}</div>`\n}\n\n/**\n * Create a Checkbox component\n */\nexport function createCheckbox(props: CheckboxProps): string {\n const {\n checked = false,\n label,\n disabled = false,\n indeterminate = false,\n id = generateId('checkbox'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-checkbox', disabled && 'stx-checkbox--disabled', className)\n const styleStr = buildStyles(style)\n\n const inputAttrs = [\n 'type=\"checkbox\"',\n `id=\"${id}\"`,\n checked && 'checked',\n disabled && 'disabled',\n indeterminate && 'data-indeterminate=\"true\"',\n ].filter(Boolean).join(' ')\n\n return `\n <label class=\"${classes}\" ${styleStr ? `style=\"${styleStr}\"` : ''}>\n <input ${inputAttrs} />\n <span class=\"stx-checkbox-box\"></span>\n ${label ? `<span class=\"stx-checkbox-label\">${escapeHtml(label)}</span>` : ''}\n </label>\n `\n}\n\n/**\n * Create a Slider component\n */\nexport function createSlider(props: SliderProps): string {\n const {\n value = 50,\n min = 0,\n max = 100,\n step = 1,\n disabled = false,\n label,\n showValue = true,\n id = generateId('slider'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-slider', disabled && 'stx-slider--disabled', className)\n const styleStr = buildStyles(style)\n\n const inputAttrs = [\n 'type=\"range\"',\n `id=\"${id}\"`,\n `value=\"${value}\"`,\n `min=\"${min}\"`,\n `max=\"${max}\"`,\n `step=\"${step}\"`,\n disabled && 'disabled',\n ].filter(Boolean).join(' ')\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-slider-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<div class=\"stx-slider-track\"><input ${inputAttrs} /></div>`\n if (showValue) {\n html += `<span class=\"stx-slider-value\">${value}</span>`\n }\n\n return `<div class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n// =============================================================================\n// Display Components\n// =============================================================================\n\n/**\n * Create a ProgressBar component\n */\nexport function createProgressBar(props: ProgressBarProps): string {\n const {\n value,\n max = 100,\n variant = 'default',\n size = 'medium',\n showLabel = false,\n indeterminate = false,\n id = generateId('progress'),\n className,\n style,\n } = props\n\n const percentage = Math.min(100, Math.max(0, (value / max) * 100))\n const classes = buildClasses(\n 'stx-progress',\n `stx-progress--${variant}`,\n `stx-progress--${size}`,\n indeterminate && 'stx-progress--indeterminate',\n className,\n )\n const styleStr = buildStyles(style)\n\n return `\n <div id=\"${id}\" class=\"${classes}\" role=\"progressbar\" aria-valuenow=\"${value}\" aria-valuemin=\"0\" aria-valuemax=\"${max}\" ${styleStr ? `style=\"${styleStr}\"` : ''}>\n <div class=\"stx-progress-bar\" style=\"width: ${indeterminate ? '100%' : `${percentage}%`}\"></div>\n ${showLabel ? `<span class=\"stx-progress-label\">${Math.round(percentage)}%</span>` : ''}\n </div>\n `\n}\n\n/**\n * Create a Badge component\n */\nexport function createBadge(props: BadgeProps): string {\n const {\n text,\n variant = 'default',\n size = 'medium',\n id = generateId('badge'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-badge',\n `stx-badge--${variant}`,\n `stx-badge--${size}`,\n className,\n )\n const styleStr = buildStyles(style)\n\n return `<span id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${escapeHtml(text)}</span>`\n}\n\n/**\n * Create an Avatar component\n */\nexport function createAvatar(props: AvatarProps): string {\n const {\n src,\n alt = '',\n name,\n size = 'medium',\n shape = 'circle',\n id = generateId('avatar'),\n className,\n style,\n } = props\n\n const sizeClass = typeof size === 'number' ? '' : `stx-avatar--${size}`\n const sizeStyle = typeof size === 'number' ? `width: ${size}px; height: ${size}px;` : ''\n\n const classes = buildClasses('stx-avatar', sizeClass, `stx-avatar--${shape}`, className)\n const combinedStyle = [sizeStyle, buildStyles(style)].filter(Boolean).join(' ')\n\n // Generate initials from name\n const initials = name\n ? name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2)\n : ''\n\n if (src) {\n return `<div id=\"${id}\" class=\"${classes}\" ${combinedStyle ? `style=\"${combinedStyle}\"` : ''}>\n <img src=\"${escapeHtml(src)}\" alt=\"${escapeHtml(alt)}\" class=\"stx-avatar-img\" />\n </div>`\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" ${combinedStyle ? `style=\"${combinedStyle}\"` : ''}>\n <span class=\"stx-avatar-initials\">${initials}</span>\n </div>`\n}\n\n/**\n * Create a Card component\n */\nexport function createCard(props: CardProps): string {\n const {\n title,\n subtitle,\n content,\n image,\n footer,\n variant = 'default',\n id = generateId('card'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-card', `stx-card--${variant}`, className)\n const styleStr = buildStyles(style)\n\n let html = ''\n if (image) {\n html += `<div class=\"stx-card-image\"><img src=\"${escapeHtml(image)}\" alt=\"\" /></div>`\n }\n html += '<div class=\"stx-card-body\">'\n if (title) {\n html += `<h3 class=\"stx-card-title\">${escapeHtml(title)}</h3>`\n }\n if (subtitle) {\n html += `<p class=\"stx-card-subtitle\">${escapeHtml(subtitle)}</p>`\n }\n if (content) {\n html += `<div class=\"stx-card-content\">${escapeHtml(content)}</div>`\n }\n html += '</div>'\n if (footer) {\n html += `<div class=\"stx-card-footer\">${escapeHtml(footer)}</div>`\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n// =============================================================================\n// Layout Components\n// =============================================================================\n\n/**\n * Create a Tabs component\n */\nexport function createTabs(props: TabsProps): string {\n const {\n tabs,\n activeTab,\n variant = 'default',\n id = generateId('tabs'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-tabs', `stx-tabs--${variant}`, className)\n const styleStr = buildStyles(style)\n\n const tabsHtml = tabs.map((tab, index) => {\n const isActive = activeTab ? tab.value === activeTab : index === 0\n const tabClasses = buildClasses(\n 'stx-tab',\n isActive && 'stx-tab--active',\n tab.disabled && 'stx-tab--disabled',\n )\n return `<button class=\"${tabClasses}\" data-value=\"${escapeHtml(tab.value)}\" ${tab.disabled ? 'disabled' : ''} role=\"tab\" aria-selected=\"${isActive}\">${escapeHtml(tab.label)}</button>`\n }).join('')\n\n return `<div id=\"${id}\" class=\"${classes}\" role=\"tablist\" ${styleStr ? `style='${styleStr}'` : ''}>${tabsHtml}</div>`\n}\n\n/**\n * Create a Dropdown/Select component\n */\nexport function createDropdown(props: DropdownProps): string {\n const {\n options,\n value,\n placeholder = 'Select...',\n disabled = false,\n id = generateId('dropdown'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-dropdown', disabled && 'stx-dropdown--disabled', className)\n const styleStr = buildStyles(style)\n\n const optionsHtml = options.map((opt) => {\n const selected = opt.value === value ? 'selected' : ''\n const disabledAttr = opt.disabled ? 'disabled' : ''\n return `<option value=\"${escapeHtml(opt.value)}\" ${selected} ${disabledAttr}>${escapeHtml(opt.label)}</option>`\n }).join('')\n\n const placeholderOption = value ? '' : `<option value=\"\" disabled selected>${escapeHtml(placeholder)}</option>`\n\n return `<select id=\"${id}\" class=\"${classes}\" ${disabled ? 'disabled' : ''} ${styleStr ? `style='${styleStr}'` : ''}>${placeholderOption}${optionsHtml}</select>`\n}\n\n// =============================================================================\n// Advanced Components\n// =============================================================================\n\n/**\n * Create a Rating component\n */\nexport function createRating(props: RatingProps): string {\n const {\n value = 0,\n max = 5,\n readonly = false,\n size = 'medium',\n allowHalf = false,\n id = generateId('rating'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-rating',\n `stx-rating--${size}`,\n readonly && 'stx-rating--readonly',\n className,\n )\n const styleStr = buildStyles(style)\n\n let starsHtml = ''\n for (let i = 1; i <= max; i++) {\n const filled = i <= value\n const halfFilled = allowHalf && i - 0.5 === value\n const starClass = filled ? 'stx-star--filled' : halfFilled ? 'stx-star--half' : ''\n starsHtml += `<span class=\"stx-star ${starClass}\" data-value=\"${i}\">★</span>`\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" role=\"slider\" aria-valuenow=\"${value}\" aria-valuemin=\"0\" aria-valuemax=\"${max}\" ${styleStr ? `style='${styleStr}'` : ''}>${starsHtml}</div>`\n}\n\n/**\n * Create a RadioButton component\n */\nexport function createRadioButton(props: RadioButtonProps): string {\n const {\n value,\n name,\n checked = false,\n label,\n disabled = false,\n id = generateId('radio'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-radio', disabled && 'stx-radio--disabled', className)\n const styleStr = buildStyles(style)\n\n const inputAttrs = [\n 'type=\"radio\"',\n `id=\"${id}\"`,\n `name=\"${escapeHtml(name)}\"`,\n `value=\"${escapeHtml(value)}\"`,\n checked && 'checked',\n disabled && 'disabled',\n ].filter(Boolean).join(' ')\n\n return `\n <label class=\"${classes}\" ${styleStr ? `style=\"${styleStr}\"` : ''}>\n <input ${inputAttrs} />\n <span class=\"stx-radio-circle\"></span>\n ${label ? `<span class=\"stx-radio-label\">${escapeHtml(label)}</span>` : ''}\n </label>\n `\n}\n\n/**\n * Create a ColorPicker component\n */\nexport function createColorPicker(props: ColorPickerProps): string {\n const {\n value = '#3498db',\n disabled = false,\n label,\n presetColors = ['#e74c3c', '#f39c12', '#27ae60', '#3498db', '#9b59b6', '#1abc9c', '#34495e', '#000000'],\n id = generateId('color'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-color-picker', disabled && 'stx-color-picker--disabled', className)\n const styleStr = buildStyles(style)\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-color-picker-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<div class=\"stx-color-picker-input\">\n <input type=\"color\" id=\"${id}\" value=\"${escapeHtml(value)}\" ${disabled ? 'disabled' : ''} />\n <span class=\"stx-color-picker-value\">${escapeHtml(value)}</span>\n </div>`\n\n if (presetColors.length > 0) {\n html += '<div class=\"stx-color-picker-presets\">'\n for (const color of presetColors) {\n html += `<button class=\"stx-color-preset\" style=\"background: ${escapeHtml(color)}\" data-color=\"${escapeHtml(color)}\" ${disabled ? 'disabled' : ''}></button>`\n }\n html += '</div>'\n }\n\n return `<div class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a DatePicker component\n */\nexport function createDatePicker(props: DatePickerProps): string {\n const {\n value,\n min,\n max,\n disabled = false,\n label,\n placeholder = 'Select date',\n showClear = true,\n id = generateId('date'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-date-picker', disabled && 'stx-date-picker--disabled', className)\n const styleStr = buildStyles(style)\n\n const dateValue = value instanceof Date ? value.toISOString().split('T')[0] : value || ''\n const minValue = min instanceof Date ? min.toISOString().split('T')[0] : min\n const maxValue = max instanceof Date ? max.toISOString().split('T')[0] : max\n\n const inputAttrs = [\n 'type=\"date\"',\n `id=\"${id}\"`,\n dateValue && `value=\"${dateValue}\"`,\n minValue && `min=\"${minValue}\"`,\n maxValue && `max=\"${maxValue}\"`,\n disabled && 'disabled',\n `placeholder=\"${escapeHtml(placeholder)}\"`,\n ].filter(Boolean).join(' ')\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-date-picker-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<div class=\"stx-date-picker-input\">\n <input ${inputAttrs} />\n ${showClear && dateValue ? '<button class=\"stx-date-picker-clear\" type=\"button\">&times;</button>' : ''}\n </div>`\n\n return `<div class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a TimePicker component\n */\nexport function createTimePicker(props: TimePickerProps): string {\n const {\n value = '',\n disabled = false,\n label,\n step = 60,\n min,\n max,\n id = generateId('time'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-time-picker', disabled && 'stx-time-picker--disabled', className)\n const styleStr = buildStyles(style)\n\n const inputAttrs = [\n 'type=\"time\"',\n `id=\"${id}\"`,\n value && `value=\"${escapeHtml(value)}\"`,\n `step=\"${step}\"`,\n min && `min=\"${escapeHtml(min)}\"`,\n max && `max=\"${escapeHtml(max)}\"`,\n disabled && 'disabled',\n ].filter(Boolean).join(' ')\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-time-picker-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<input ${inputAttrs} class=\"stx-time-picker-input\" />`\n\n return `<div class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create an Autocomplete component\n */\nexport function createAutocomplete(props: AutocompleteProps): string {\n const {\n options,\n value = '',\n placeholder = 'Search...',\n disabled = false,\n label,\n loading = false,\n id = generateId('autocomplete'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-autocomplete', disabled && 'stx-autocomplete--disabled', className)\n const styleStr = buildStyles(style)\n\n const selectedOption = options.find(opt => opt.value === value)\n const displayValue = selectedOption ? selectedOption.label : value\n\n let html = ''\n if (label) {\n html += `<label class=\"stx-autocomplete-label\" for=\"${id}\">${escapeHtml(label)}</label>`\n }\n html += `<div class=\"stx-autocomplete-input-wrapper\">\n <input type=\"text\" id=\"${id}\" value=\"${escapeHtml(displayValue)}\" placeholder=\"${escapeHtml(placeholder)}\" ${disabled ? 'disabled' : ''} autocomplete=\"off\" class=\"stx-autocomplete-input\" />\n ${loading ? '<span class=\"stx-autocomplete-spinner\"></span>' : ''}\n </div>`\n html += '<ul class=\"stx-autocomplete-list\">'\n for (const opt of options) {\n html += `<li class=\"stx-autocomplete-item ${opt.value === value ? 'stx-autocomplete-item--selected' : ''}\" data-value=\"${escapeHtml(opt.value)}\">${escapeHtml(opt.label)}</li>`\n }\n html += '</ul>'\n\n return `<div class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a Label component\n */\nexport function createLabel(props: LabelProps): string {\n const {\n text,\n htmlFor,\n required = false,\n size = 'medium',\n id = generateId('label'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-label', `stx-label--${size}`, className)\n const styleStr = buildStyles(style)\n\n return `<label id=\"${id}\" class=\"${classes}\" ${htmlFor ? `for='${escapeHtml(htmlFor)}'` : ''} ${styleStr ? `style='${styleStr}'` : ''}>${escapeHtml(text)}${required ? '<span class=\"stx-label-required\">*</span>' : ''}</label>`\n}\n\n/**\n * Create an ImageView component\n */\nexport function createImageView(props: ImageViewProps): string {\n const {\n src,\n alt = '',\n width,\n height,\n objectFit = 'cover',\n fallback,\n loading = 'lazy',\n id = generateId('image'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-image', className)\n const imageStyles: Record<string, string> = { objectFit }\n if (width)\n imageStyles.width = typeof width === 'number' ? `${width}px` : width\n if (height)\n imageStyles.height = typeof height === 'number' ? `${height}px` : height\n\n const combinedStyle = [buildStyles(imageStyles), buildStyles(style)].filter(Boolean).join('; ')\n const fallbackAttr = fallback ? `onerror=\"this.src='${escapeHtml(fallback)}'\"` : ''\n\n return `<img id=\"${id}\" class=\"${classes}\" src=\"${escapeHtml(src)}\" alt=\"${escapeHtml(alt)}\" loading=\"${loading}\" ${combinedStyle ? `style='${combinedStyle}'` : ''} ${fallbackAttr} />`\n}\n\n/**\n * Create a Chip component\n */\nexport function createChip(props: ChipProps): string {\n const {\n text,\n variant = 'default',\n size = 'medium',\n removable = false,\n icon,\n id = generateId('chip'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-chip',\n `stx-chip--${variant}`,\n `stx-chip--${size}`,\n className,\n )\n const styleStr = buildStyles(style)\n\n let html = ''\n if (icon) {\n html += `<span class=\"stx-chip-icon\">${icon}</span>`\n }\n html += `<span class=\"stx-chip-text\">${escapeHtml(text)}</span>`\n if (removable) {\n html += '<button class=\"stx-chip-remove\" type=\"button\">&times;</button>'\n }\n\n return `<span id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</span>`\n}\n\n/**\n * Create a Tooltip component\n */\nexport function createTooltip(props: TooltipProps): string {\n const {\n text,\n position = 'top',\n delay = 200,\n children,\n id = generateId('tooltip'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-tooltip-wrapper', className)\n const styleStr = buildStyles(style)\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style=\"${styleStr}\"` : ''} data-tooltip=\"${escapeHtml(text)}\" data-position=\"${position}\" data-delay=\"${delay}\">\n ${children}\n <span class=\"stx-tooltip stx-tooltip--${position}\">${escapeHtml(text)}</span>\n </div>`\n}\n\n/**\n * Create a ScrollView component\n */\nexport function createScrollView(props: ScrollViewProps): string {\n const {\n direction = 'vertical',\n showScrollbar = true,\n smooth = true,\n height,\n width,\n children,\n id = generateId('scroll'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-scroll-view',\n `stx-scroll-view--${direction}`,\n !showScrollbar && 'stx-scroll-view--hide-scrollbar',\n smooth && 'stx-scroll-view--smooth',\n className,\n )\n\n const scrollStyles: Record<string, string> = {}\n if (height)\n scrollStyles.height = typeof height === 'number' ? `${height}px` : height\n if (width)\n scrollStyles.width = typeof width === 'number' ? `${width}px` : width\n\n const combinedStyle = [buildStyles(scrollStyles), buildStyles(style)].filter(Boolean).join('; ')\n\n return `<div id=\"${id}\" class=\"${classes}\" ${combinedStyle ? `style='${combinedStyle}'` : ''}>${children}</div>`\n}\n\n/**\n * Create a SplitView component\n */\nexport function createSplitView(props: SplitViewProps): string {\n const {\n direction = 'horizontal',\n sizes = [50, 50],\n resizable = true,\n children,\n id = generateId('split'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-split-view',\n `stx-split-view--${direction}`,\n resizable && 'stx-split-view--resizable',\n className,\n )\n const styleStr = buildStyles(style)\n\n const sizeUnit = direction === 'horizontal' ? 'width' : 'height'\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style=\"${styleStr}\"` : ''}>\n <div class=\"stx-split-pane\" style=\"${sizeUnit}: ${sizes[0]}%\">${children[0]}</div>\n ${resizable ? '<div class=\"stx-split-divider\"></div>' : ''}\n <div class=\"stx-split-pane\" style=\"${sizeUnit}: ${sizes[1]}%\">${children[1]}</div>\n </div>`\n}\n\n/**\n * Create an Accordion component\n */\nexport function createAccordion(props: AccordionProps): string {\n const {\n items,\n multiple = false,\n defaultOpen = [],\n id = generateId('accordion'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-accordion', className)\n const styleStr = buildStyles(style)\n\n let html = ''\n items.forEach((item, index) => {\n const isOpen = defaultOpen.includes(index)\n const itemClasses = buildClasses(\n 'stx-accordion-item',\n isOpen && 'stx-accordion-item--open',\n item.disabled && 'stx-accordion-item--disabled',\n )\n html += `<div class=\"${itemClasses}\" data-index=\"${index}\">\n <button class=\"stx-accordion-header\" ${item.disabled ? 'disabled' : ''} aria-expanded=\"${isOpen}\" data-multiple=\"${multiple}\">\n <span class=\"stx-accordion-title\">${escapeHtml(item.title)}</span>\n <span class=\"stx-accordion-icon\">▼</span>\n </button>\n <div class=\"stx-accordion-content\" ${isOpen ? '' : 'hidden'}>\n ${escapeHtml(item.content)}\n </div>\n </div>`\n })\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a Stepper component\n */\nexport function createStepper(props: StepperProps): string {\n const {\n steps,\n currentStep,\n orientation = 'horizontal',\n id = generateId('stepper'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-stepper', `stx-stepper--${orientation}`, className)\n const styleStr = buildStyles(style)\n\n let html = ''\n steps.forEach((step, index) => {\n const stepClasses = buildClasses(\n 'stx-step',\n index < currentStep && 'stx-step--completed',\n index === currentStep && 'stx-step--active',\n )\n html += `<div class=\"${stepClasses}\" data-step=\"${index}\">\n <div class=\"stx-step-indicator\">\n ${index < currentStep ? '✓' : index + 1}\n </div>\n <div class=\"stx-step-content\">\n <div class=\"stx-step-label\">${escapeHtml(step.label)}</div>\n ${step.description ? `<div class=\"stx-step-description\">${escapeHtml(step.description)}</div>` : ''}\n </div>\n </div>`\n if (index < steps.length - 1) {\n html += '<div class=\"stx-step-connector\"></div>'\n }\n })\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a Modal component (as a component, not a dialog function)\n */\nexport function createModalComponent(props: ModalComponentProps): string {\n const {\n open = false,\n title,\n size = 'medium',\n closable = true,\n children,\n footer,\n id = generateId('modal'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-modal-component', `stx-modal-component--${size}`, className)\n const styleStr = buildStyles(style)\n\n if (!open) {\n return `<div id=\"${id}\" class=\"${classes} stx-modal-component--hidden\" ${styleStr ? `style='${styleStr}'` : ''}></div>`\n }\n\n let html = '<div class=\"stx-modal-component-overlay\">'\n html += '<div class=\"stx-modal-component-dialog\">'\n\n if (title || closable) {\n html += '<div class=\"stx-modal-component-header\">'\n if (title) {\n html += `<h3 class=\"stx-modal-component-title\">${escapeHtml(title)}</h3>`\n }\n if (closable) {\n html += '<button class=\"stx-modal-component-close\">&times;</button>'\n }\n html += '</div>'\n }\n\n html += `<div class=\"stx-modal-component-body\">${children}</div>`\n\n if (footer) {\n html += `<div class=\"stx-modal-component-footer\">${footer}</div>`\n }\n\n html += '</div></div>'\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a ListView component\n */\nexport function createListView(props: ListViewProps): string {\n const {\n items,\n selectable = false,\n multiSelect = false,\n emptyMessage = 'No items',\n id = generateId('list'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-list-view',\n selectable && 'stx-list-view--selectable',\n multiSelect && 'stx-list-view--multi',\n className,\n )\n const styleStr = buildStyles(style)\n\n if (items.length === 0) {\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style=\"${styleStr}\"` : ''}>\n <div class=\"stx-list-view-empty\">${escapeHtml(emptyMessage)}</div>\n </div>`\n }\n\n let html = '<ul class=\"stx-list-view-items\">'\n for (const item of items) {\n const itemClasses = buildClasses(\n 'stx-list-view-item',\n item.selected && 'stx-list-view-item--selected',\n )\n html += `<li class=\"${itemClasses}\" data-id=\"${escapeHtml(item.id)}\" ${selectable ? 'tabindex=\"0\"' : ''}>${item.content}</li>`\n }\n html += '</ul>'\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a Table component\n */\nexport function createTable(props: TableProps): string {\n const {\n columns,\n data,\n striped = false,\n bordered = false,\n hoverable = true,\n sortBy,\n sortOrder,\n id = generateId('table'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-table',\n striped && 'stx-table--striped',\n bordered && 'stx-table--bordered',\n hoverable && 'stx-table--hoverable',\n className,\n )\n const styleStr = buildStyles(style)\n\n let html = '<table>'\n html += '<thead><tr>'\n for (const col of columns) {\n const isSorted = col.key === sortBy\n const sortClass = isSorted ? `stx-table-sorted stx-table-sorted--${sortOrder}` : ''\n const sortable = col.sortable ? 'data-sortable=\"true\"' : ''\n const widthStyle = col.width ? `style=\"width: ${col.width}\"` : ''\n html += `<th class=\"${sortClass}\" ${sortable} ${widthStyle} data-key=\"${escapeHtml(col.key)}\">${escapeHtml(col.label)}${col.sortable ? '<span class=\"stx-table-sort-icon\"></span>' : ''}</th>`\n }\n html += '</tr></thead>'\n\n html += '<tbody>'\n for (const row of data) {\n html += '<tr>'\n for (const col of columns) {\n const cellValue = row[col.key]\n html += `<td>${cellValue != null ? escapeHtml(String(cellValue)) : ''}</td>`\n }\n html += '</tr>'\n }\n html += '</tbody></table>'\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Render a tree node recursively\n */\nfunction renderTreeNode(node: TreeNode, expandedKeys: string[], selectedKeys: string[], checkable: boolean): string {\n const isExpanded = expandedKeys.includes(node.key)\n const isSelected = selectedKeys.includes(node.key)\n const hasChildren = node.children && node.children.length > 0\n\n const nodeClasses = buildClasses(\n 'stx-tree-node',\n isSelected && 'stx-tree-node--selected',\n node.disabled && 'stx-tree-node--disabled',\n )\n\n let html = `<div class=\"${nodeClasses}\" data-key=\"${escapeHtml(node.key)}\">`\n html += '<div class=\"stx-tree-node-content\">'\n\n if (hasChildren) {\n html += `<span class=\"stx-tree-toggle ${isExpanded ? 'stx-tree-toggle--expanded' : ''}\">▶</span>`\n }\n else {\n html += '<span class=\"stx-tree-toggle-placeholder\"></span>'\n }\n\n if (checkable) {\n html += `<input type=\"checkbox\" class=\"stx-tree-checkbox\" ${isSelected ? 'checked' : ''} ${node.disabled ? 'disabled' : ''} />`\n }\n\n if (node.icon) {\n html += `<span class=\"stx-tree-icon\">${node.icon}</span>`\n }\n\n html += `<span class=\"stx-tree-label\">${escapeHtml(node.label)}</span>`\n html += '</div>'\n\n if (hasChildren && isExpanded) {\n html += '<div class=\"stx-tree-children\">'\n for (const child of node.children!) {\n html += renderTreeNode(child, expandedKeys, selectedKeys, checkable)\n }\n html += '</div>'\n }\n\n html += '</div>'\n return html\n}\n\n/**\n * Create a TreeView component\n */\nexport function createTreeView(props: TreeViewProps): string {\n const {\n nodes,\n expandedKeys = [],\n selectedKeys = [],\n checkable = false,\n id = generateId('tree'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-tree-view', checkable && 'stx-tree-view--checkable', className)\n const styleStr = buildStyles(style)\n\n let html = ''\n for (const node of nodes) {\n html += renderTreeNode(node, expandedKeys, selectedKeys, checkable)\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" role=\"tree\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a DataGrid component\n */\nexport function createDataGrid(props: DataGridProps): string {\n const {\n columns,\n data,\n pagination,\n selectable = false,\n id = generateId('datagrid'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-data-grid', selectable && 'stx-data-grid--selectable', className)\n const styleStr = buildStyles(style)\n\n let html = '<div class=\"stx-data-grid-table-wrapper\">'\n html += '<table class=\"stx-data-grid-table\">'\n html += '<thead><tr>'\n\n if (selectable) {\n html += '<th class=\"stx-data-grid-select-all\"><input type=\"checkbox\" /></th>'\n }\n\n for (const col of columns) {\n const widthStyle = col.width ? `style=\"width: ${col.width}\"` : ''\n html += `<th ${widthStyle}>\n <div class=\"stx-data-grid-header-cell\">\n <span>${escapeHtml(col.label)}</span>\n ${col.sortable ? '<button class=\"stx-data-grid-sort\">⇅</button>' : ''}\n ${col.filterable ? '<button class=\"stx-data-grid-filter\">⊻</button>' : ''}\n </div>\n </th>`\n }\n html += '</tr></thead>'\n\n html += '<tbody>'\n for (const row of data) {\n html += '<tr>'\n if (selectable) {\n html += '<td class=\"stx-data-grid-select\"><input type=\"checkbox\" /></td>'\n }\n for (const col of columns) {\n const cellValue = row[col.key]\n html += `<td>${cellValue != null ? escapeHtml(String(cellValue)) : ''}</td>`\n }\n html += '</tr>'\n }\n html += '</tbody></table></div>'\n\n if (pagination) {\n const totalPages = Math.ceil(pagination.total / pagination.pageSize)\n html += `<div class=\"stx-data-grid-pagination\">\n <span class=\"stx-data-grid-page-info\">Page ${pagination.page} of ${totalPages} (${pagination.total} items)</span>\n <div class=\"stx-data-grid-page-buttons\">\n <button class=\"stx-data-grid-page-btn\" ${pagination.page <= 1 ? 'disabled' : ''}>◀</button>\n <button class=\"stx-data-grid-page-btn\" ${pagination.page >= totalPages ? 'disabled' : ''}>▶</button>\n </div>\n </div>`\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a Chart component (placeholder for integration with charting library)\n */\nexport function createChart(props: ChartProps): string {\n const {\n type,\n data,\n options = {},\n width = '100%',\n height = 300,\n id = generateId('chart'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-chart', `stx-chart--${type}`, className)\n const chartStyles: Record<string, string> = {\n width: typeof width === 'number' ? `${width}px` : width,\n height: typeof height === 'number' ? `${height}px` : height,\n }\n const combinedStyle = [buildStyles(chartStyles), buildStyles(style)].filter(Boolean).join('; ')\n\n // Store data as JSON for JavaScript charting library to consume\n const chartData = JSON.stringify({ type, data, options })\n\n return `<div id=\"${id}\" class=\"${classes}\" style=\"${combinedStyle}\" data-chart='${escapeHtml(chartData)}'>\n <div class=\"stx-chart-placeholder\">\n ${options.title ? `<div class=\"stx-chart-title\">${escapeHtml(options.title)}</div>` : ''}\n <div class=\"stx-chart-type\">${type.charAt(0).toUpperCase() + type.slice(1)} Chart</div>\n <div class=\"stx-chart-info\">${data.datasets.length} dataset(s), ${data.labels.length} labels</div>\n </div>\n </div>`\n}\n\n/**\n * Create a CodeEditor component\n */\nexport function createCodeEditor(props: CodeEditorProps): string {\n const {\n value = '',\n language = 'plaintext',\n theme = 'dark',\n lineNumbers = true,\n readOnly = false,\n height = 300,\n tabSize = 2,\n wordWrap = false,\n id = generateId('code'),\n className,\n style,\n } = props\n\n const classes = buildClasses(\n 'stx-code-editor',\n `stx-code-editor--${theme}`,\n lineNumbers && 'stx-code-editor--line-numbers',\n readOnly && 'stx-code-editor--readonly',\n wordWrap && 'stx-code-editor--wrap',\n className,\n )\n\n const editorStyles: Record<string, string> = {\n height: typeof height === 'number' ? `${height}px` : height,\n }\n const combinedStyle = [buildStyles(editorStyles), buildStyles(style)].filter(Boolean).join('; ')\n\n const lines = value.split('\\n')\n let codeHtml = ''\n\n if (lineNumbers) {\n codeHtml += '<div class=\"stx-code-editor-gutter\">'\n for (let i = 1; i <= lines.length; i++) {\n codeHtml += `<div class=\"stx-code-editor-line-number\">${i}</div>`\n }\n codeHtml += '</div>'\n }\n\n codeHtml += `<pre class=\"stx-code-editor-content\"><code class=\"language-${escapeHtml(language)}\">${escapeHtml(value)}</code></pre>`\n\n return `<div id=\"${id}\" class=\"${classes}\" style=\"${combinedStyle}\" data-language=\"${escapeHtml(language)}\" data-tab-size=\"${tabSize}\">${codeHtml}</div>`\n}\n\n/**\n * Create a MediaPlayer component\n */\nexport function createMediaPlayer(props: MediaPlayerProps): string {\n const {\n src,\n type = 'video',\n poster,\n autoplay = false,\n loop = false,\n muted = false,\n controls = true,\n width,\n height,\n id = generateId('media'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-media-player', `stx-media-player--${type}`, className)\n const mediaStyles: Record<string, string> = {}\n if (width)\n mediaStyles.width = typeof width === 'number' ? `${width}px` : width\n if (height)\n mediaStyles.height = typeof height === 'number' ? `${height}px` : height\n\n const combinedStyle = [buildStyles(mediaStyles), buildStyles(style)].filter(Boolean).join('; ')\n\n const mediaAttrs = [\n `id=\"${id}-media\"`,\n `src=\"${escapeHtml(src)}\"`,\n controls && 'controls',\n autoplay && 'autoplay',\n loop && 'loop',\n muted && 'muted',\n type === 'video' && poster && `poster=\"${escapeHtml(poster)}\"`,\n ].filter(Boolean).join(' ')\n\n const mediaElement = type === 'video'\n ? `<video ${mediaAttrs}>Your browser does not support the video tag.</video>`\n : `<audio ${mediaAttrs}>Your browser does not support the audio tag.</audio>`\n\n return `<div id=\"${id}\" class=\"${classes}\" ${combinedStyle ? `style='${combinedStyle}'` : ''}>${mediaElement}</div>`\n}\n\n/**\n * Format file size for display\n */\nfunction formatFileSize(bytes?: number): string {\n if (bytes === undefined)\n return ''\n const units = ['B', 'KB', 'MB', 'GB']\n let size = bytes\n let unitIndex = 0\n while (size >= 1024 && unitIndex < units.length - 1) {\n size /= 1024\n unitIndex++\n }\n return `${size.toFixed(1)} ${units[unitIndex]}`\n}\n\n/**\n * Create a FileExplorer component\n */\nexport function createFileExplorer(props: FileExplorerProps): string {\n const {\n files,\n viewMode = 'list',\n showHidden = false,\n selectable = true,\n id = generateId('files'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-file-explorer', `stx-file-explorer--${viewMode}`, className)\n const styleStr = buildStyles(style)\n\n const filteredFiles = showHidden ? files : files.filter(f => !f.name.startsWith('.'))\n\n let html = ''\n if (viewMode === 'list') {\n html = '<table class=\"stx-file-explorer-list\"><thead><tr><th>Name</th><th>Size</th><th>Modified</th></tr></thead><tbody>'\n for (const file of filteredFiles) {\n const icon = file.icon || (file.type === 'folder' ? '📁' : '📄')\n const size = file.type === 'file' ? formatFileSize(file.size) : ''\n const modified = file.modified ? file.modified.toLocaleDateString() : ''\n html += `<tr class=\"stx-file-explorer-item ${selectable ? 'stx-file-explorer-item--selectable' : ''}\" data-path=\"${escapeHtml(file.path)}\" data-type=\"${file.type}\">\n <td><span class=\"stx-file-explorer-icon\">${icon}</span>${escapeHtml(file.name)}</td>\n <td>${size}</td>\n <td>${modified}</td>\n </tr>`\n }\n html += '</tbody></table>'\n }\n else {\n html = '<div class=\"stx-file-explorer-grid\">'\n for (const file of filteredFiles) {\n const icon = file.icon || (file.type === 'folder' ? '📁' : '📄')\n html += `<div class=\"stx-file-explorer-item ${selectable ? 'stx-file-explorer-item--selectable' : ''}\" data-path=\"${escapeHtml(file.path)}\" data-type=\"${file.type}\">\n <div class=\"stx-file-explorer-icon\">${icon}</div>\n <div class=\"stx-file-explorer-name\">${escapeHtml(file.name)}</div>\n </div>`\n }\n html += '</div>'\n }\n\n return `<div id=\"${id}\" class=\"${classes}\" ${styleStr ? `style='${styleStr}'` : ''}>${html}</div>`\n}\n\n/**\n * Create a WebView component\n */\nexport function createWebView(props: WebViewProps): string {\n const {\n url,\n width = '100%',\n height = 400,\n sandbox = true,\n allowScripts = true,\n id = generateId('webview'),\n className,\n style,\n } = props\n\n const classes = buildClasses('stx-webview', className)\n const webviewStyles: Record<string, string> = {\n width: typeof width === 'number' ? `${width}px` : width,\n height: typeof height === 'number' ? `${height}px` : height,\n }\n const combinedStyle = [buildStyles(webviewStyles), buildStyles(style)].filter(Boolean).join('; ')\n\n const sandboxAttrs: string[] = []\n if (sandbox) {\n sandboxAttrs.push('allow-same-origin')\n if (allowScripts) {\n sandboxAttrs.push('allow-scripts')\n }\n }\n const sandboxAttr = sandbox ? `sandbox=\"${sandboxAttrs.join(' ')}\"` : ''\n\n return `<iframe id=\"${id}\" class=\"${classes}\" src=\"${escapeHtml(url)}\" style=\"${combinedStyle}\" ${sandboxAttr} loading=\"lazy\" frameborder=\"0\"></iframe>`\n}\n\n// =============================================================================\n// Component List\n// =============================================================================\n\n/**\n * List of all 35 available components\n */\nexport const AVAILABLE_COMPONENTS = [\n // Input Components (9)\n 'Button',\n 'TextInput',\n 'Checkbox',\n 'RadioButton',\n 'Slider',\n 'ColorPicker',\n 'DatePicker',\n 'TimePicker',\n 'Autocomplete',\n\n // Display Components (9)\n 'Label',\n 'ImageView',\n 'ProgressBar',\n 'Avatar',\n 'Badge',\n 'Chip',\n 'Card',\n 'Tooltip',\n 'Toast',\n\n // Layout Components (7)\n 'ScrollView',\n 'SplitView',\n 'Accordion',\n 'Stepper',\n 'Modal',\n 'Tabs',\n 'Dropdown',\n\n // Data Components (5)\n 'ListView',\n 'Table',\n 'TreeView',\n 'DataGrid',\n 'Chart',\n\n // Advanced Components (5)\n 'Rating',\n 'CodeEditor',\n 'MediaPlayer',\n 'FileExplorer',\n 'WebView',\n] as const\n\nexport type ComponentName = typeof AVAILABLE_COMPONENTS[number]\n\n/**\n * CSS styles for all components\n */\nexport const COMPONENT_STYLES = `\n/* Button */\n.stx-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 8px 16px;\n border: none;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s;\n}\n.stx-button--primary { background: #3498db; color: #fff; }\n.stx-button--primary:hover { background: #2980b9; }\n.stx-button--secondary { background: #6c757d; color: #fff; }\n.stx-button--outline { background: transparent; border: 1px solid #3498db; color: #3498db; }\n.stx-button--ghost { background: transparent; color: #3498db; }\n.stx-button--destructive { background: #e74c3c; color: #fff; }\n.stx-button--small { padding: 4px 8px; font-size: 12px; }\n.stx-button--large { padding: 12px 24px; font-size: 16px; }\n.stx-button--disabled { opacity: 0.5; cursor: not-allowed; }\n.stx-button--loading { pointer-events: none; }\n.stx-button-spinner { width: 16px; height: 16px; border: 2px solid transparent; border-top-color: currentColor; border-radius: 50%; animation: spin 0.6s linear infinite; }\n@keyframes spin { to { transform: rotate(360deg); } }\n\n/* Input */\n.stx-input-wrapper { display: flex; flex-direction: column; gap: 4px; }\n.stx-input-label { font-size: 14px; font-weight: 500; color: #333; }\n.stx-input { padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; transition: border-color 0.15s; }\n.stx-input:focus { outline: none; border-color: #3498db; }\n.stx-input--error { border-color: #e74c3c; }\n.stx-input-error { font-size: 12px; color: #e74c3c; }\n.stx-input-hint { font-size: 12px; color: #666; }\n\n/* Checkbox */\n.stx-checkbox { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }\n.stx-checkbox input { display: none; }\n.stx-checkbox-box { width: 18px; height: 18px; border: 2px solid #ddd; border-radius: 4px; transition: all 0.15s; }\n.stx-checkbox input:checked + .stx-checkbox-box { background: #3498db; border-color: #3498db; }\n.stx-checkbox--disabled { opacity: 0.5; cursor: not-allowed; }\n\n/* Progress */\n.stx-progress { height: 8px; background: #e0e0e0; border-radius: 4px; overflow: hidden; position: relative; }\n.stx-progress-bar { height: 100%; background: #3498db; transition: width 0.3s; }\n.stx-progress--success .stx-progress-bar { background: #27ae60; }\n.stx-progress--warning .stx-progress-bar { background: #f39c12; }\n.stx-progress--error .stx-progress-bar { background: #e74c3c; }\n.stx-progress--indeterminate .stx-progress-bar { animation: progress-indeterminate 1.5s infinite; }\n@keyframes progress-indeterminate { 0% { transform: translateX(-100%); } 100% { transform: translateX(200%); } }\n\n/* Badge */\n.stx-badge { display: inline-flex; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 500; }\n.stx-badge--default { background: #e0e0e0; color: #333; }\n.stx-badge--primary { background: #3498db; color: #fff; }\n.stx-badge--success { background: #27ae60; color: #fff; }\n.stx-badge--warning { background: #f39c12; color: #fff; }\n.stx-badge--error { background: #e74c3c; color: #fff; }\n\n/* Avatar */\n.stx-avatar { display: inline-flex; align-items: center; justify-content: center; background: #3498db; color: #fff; overflow: hidden; }\n.stx-avatar--circle { border-radius: 50%; }\n.stx-avatar--square { border-radius: 0; }\n.stx-avatar--rounded { border-radius: 8px; }\n.stx-avatar--small { width: 32px; height: 32px; font-size: 12px; }\n.stx-avatar--medium { width: 40px; height: 40px; font-size: 14px; }\n.stx-avatar--large { width: 56px; height: 56px; font-size: 18px; }\n.stx-avatar-img { width: 100%; height: 100%; object-fit: cover; }\n\n/* Card */\n.stx-card { background: #fff; border-radius: 8px; overflow: hidden; }\n.stx-card--outlined { border: 1px solid #e0e0e0; }\n.stx-card--elevated { box-shadow: 0 4px 12px rgba(0,0,0,0.1); }\n.stx-card-image img { width: 100%; display: block; }\n.stx-card-body { padding: 16px; }\n.stx-card-title { margin: 0 0 4px; font-size: 18px; }\n.stx-card-subtitle { margin: 0 0 8px; color: #666; font-size: 14px; }\n.stx-card-footer { padding: 12px 16px; border-top: 1px solid #e0e0e0; }\n\n/* Tabs */\n.stx-tabs { display: flex; gap: 4px; border-bottom: 1px solid #e0e0e0; }\n.stx-tab { padding: 8px 16px; border: none; background: none; cursor: pointer; color: #666; border-bottom: 2px solid transparent; transition: all 0.15s; }\n.stx-tab:hover { color: #333; }\n.stx-tab--active { color: #3498db; border-bottom-color: #3498db; }\n.stx-tab--disabled { opacity: 0.5; cursor: not-allowed; }\n.stx-tabs--pills { border-bottom: none; }\n.stx-tabs--pills .stx-tab { border-radius: 20px; border-bottom: none; }\n.stx-tabs--pills .stx-tab--active { background: #3498db; color: #fff; }\n\n/* Dropdown */\n.stx-dropdown { padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; background: #fff; cursor: pointer; min-width: 150px; }\n.stx-dropdown:focus { outline: none; border-color: #3498db; }\n.stx-dropdown--disabled { opacity: 0.5; cursor: not-allowed; }\n\n/* Rating */\n.stx-rating { display: inline-flex; gap: 4px; }\n.stx-star { color: #ddd; cursor: pointer; transition: color 0.15s; }\n.stx-star--filled { color: #f1c40f; }\n.stx-star--half { background: linear-gradient(90deg, #f1c40f 50%, #ddd 50%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }\n.stx-rating--readonly .stx-star { cursor: default; }\n.stx-rating--small .stx-star { font-size: 16px; }\n.stx-rating--medium .stx-star { font-size: 24px; }\n.stx-rating--large .stx-star { font-size: 32px; }\n\n/* Slider */\n.stx-slider { display: flex; align-items: center; gap: 12px; }\n.stx-slider-track { flex: 1; }\n.stx-slider input[type=\"range\"] { width: 100%; }\n.stx-slider-value { min-width: 40px; text-align: right; font-size: 14px; }\n\n/* Radio Button */\n.stx-radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }\n.stx-radio input { display: none; }\n.stx-radio-circle { width: 18px; height: 18px; border: 2px solid #ddd; border-radius: 50%; position: relative; transition: all 0.15s; }\n.stx-radio input:checked + .stx-radio-circle { border-color: #3498db; }\n.stx-radio input:checked + .stx-radio-circle::after { content: ''; position: absolute; top: 3px; left: 3px; width: 8px; height: 8px; background: #3498db; border-radius: 50%; }\n.stx-radio--disabled { opacity: 0.5; cursor: not-allowed; }\n\n/* Color Picker */\n.stx-color-picker { display: flex; flex-direction: column; gap: 8px; }\n.stx-color-picker-input { display: flex; align-items: center; gap: 8px; }\n.stx-color-picker-input input[type=\"color\"] { width: 40px; height: 40px; border: none; cursor: pointer; }\n.stx-color-picker-value { font-family: monospace; }\n.stx-color-picker-presets { display: flex; gap: 4px; flex-wrap: wrap; }\n.stx-color-preset { width: 24px; height: 24px; border: 2px solid transparent; border-radius: 4px; cursor: pointer; }\n.stx-color-preset:hover { border-color: #333; }\n\n/* Date/Time Picker */\n.stx-date-picker, .stx-time-picker { display: flex; flex-direction: column; gap: 4px; }\n.stx-date-picker-input, .stx-time-picker-input { display: flex; align-items: center; gap: 4px; }\n.stx-date-picker-input input, .stx-time-picker-input { padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; }\n.stx-date-picker-clear { background: none; border: none; cursor: pointer; font-size: 16px; }\n\n/* Autocomplete */\n.stx-autocomplete { position: relative; }\n.stx-autocomplete-input-wrapper { position: relative; }\n.stx-autocomplete-input { width: 100%; padding: 8px 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; }\n.stx-autocomplete-spinner { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; border: 2px solid #ddd; border-top-color: #3498db; border-radius: 50%; animation: spin 0.6s linear infinite; }\n.stx-autocomplete-list { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #ddd; border-radius: 6px; max-height: 200px; overflow-y: auto; display: none; z-index: 10; }\n.stx-autocomplete:focus-within .stx-autocomplete-list { display: block; }\n.stx-autocomplete-item { padding: 8px 12px; cursor: pointer; }\n.stx-autocomplete-item:hover { background: #f5f5f5; }\n.stx-autocomplete-item--selected { background: #e8f4fc; }\n\n/* Label */\n.stx-label { display: inline-block; font-weight: 500; }\n.stx-label--small { font-size: 12px; }\n.stx-label--medium { font-size: 14px; }\n.stx-label--large { font-size: 16px; }\n.stx-label-required { color: #e74c3c; margin-left: 2px; }\n\n/* Image */\n.stx-image { display: block; max-width: 100%; }\n\n/* Chip */\n.stx-chip { display: inline-flex; align-items: center; gap: 4px; padding: 4px 12px; border-radius: 16px; font-size: 13px; }\n.stx-chip--default { background: #e0e0e0; color: #333; }\n.stx-chip--primary { background: #e8f4fc; color: #3498db; }\n.stx-chip--success { background: #e8f8f0; color: #27ae60; }\n.stx-chip--warning { background: #fef5e7; color: #f39c12; }\n.stx-chip--error { background: #fdebeb; color: #e74c3c; }\n.stx-chip--small { padding: 2px 8px; font-size: 11px; }\n.stx-chip--large { padding: 6px 16px; font-size: 15px; }\n.stx-chip-remove { background: none; border: none; cursor: pointer; opacity: 0.6; padding: 0 2px; }\n.stx-chip-remove:hover { opacity: 1; }\n\n/* Tooltip */\n.stx-tooltip-wrapper { position: relative; display: inline-block; }\n.stx-tooltip { position: absolute; background: #333; color: #fff; padding: 4px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s; z-index: 1000; }\n.stx-tooltip-wrapper:hover .stx-tooltip { opacity: 1; visibility: visible; }\n.stx-tooltip--top { bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 8px; }\n.stx-tooltip--bottom { top: 100%; left: 50%; transform: translateX(-50%); margin-top: 8px; }\n.stx-tooltip--left { right: 100%; top: 50%; transform: translateY(-50%); margin-right: 8px; }\n.stx-tooltip--right { left: 100%; top: 50%; transform: translateY(-50%); margin-left: 8px; }\n\n/* Scroll View */\n.stx-scroll-view { overflow: auto; }\n.stx-scroll-view--vertical { overflow-x: hidden; overflow-y: auto; }\n.stx-scroll-view--horizontal { overflow-x: auto; overflow-y: hidden; }\n.stx-scroll-view--hide-scrollbar::-webkit-scrollbar { display: none; }\n.stx-scroll-view--hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }\n.stx-scroll-view--smooth { scroll-behavior: smooth; }\n\n/* Split View */\n.stx-split-view { display: flex; }\n.stx-split-view--horizontal { flex-direction: row; }\n.stx-split-view--vertical { flex-direction: column; }\n.stx-split-pane { overflow: auto; }\n.stx-split-divider { background: #e0e0e0; flex-shrink: 0; }\n.stx-split-view--horizontal .stx-split-divider { width: 4px; cursor: col-resize; }\n.stx-split-view--vertical .stx-split-divider { height: 4px; cursor: row-resize; }\n.stx-split-divider:hover { background: #3498db; }\n\n/* Accordion */\n.stx-accordion { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; }\n.stx-accordion-item { border-bottom: 1px solid #e0e0e0; }\n.stx-accordion-item:last-child { border-bottom: none; }\n.stx-accordion-header { width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; background: none; border: none; cursor: pointer; font-size: 14px; }\n.stx-accordion-header:hover { background: #f5f5f5; }\n.stx-accordion-icon { transition: transform 0.2s; }\n.stx-accordion-item--open .stx-accordion-icon { transform: rotate(180deg); }\n.stx-accordion-content { padding: 0 16px 16px; }\n.stx-accordion-item--disabled { opacity: 0.5; }\n.stx-accordion-item--disabled .stx-accordion-header { cursor: not-allowed; }\n\n/* Stepper */\n.stx-stepper { display: flex; }\n.stx-stepper--horizontal { flex-direction: row; align-items: flex-start; }\n.stx-stepper--vertical { flex-direction: column; }\n.stx-step { display: flex; align-items: center; }\n.stx-stepper--vertical .stx-step { flex-direction: row; }\n.stx-step-indicator { width: 32px; height: 32px; border-radius: 50%; background: #e0e0e0; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 500; flex-shrink: 0; }\n.stx-step--completed .stx-step-indicator { background: #27ae60; color: #fff; }\n.stx-step--active .stx-step-indicator { background: #3498db; color: #fff; }\n.stx-step-content { margin-left: 12px; }\n.stx-step-label { font-size: 14px; font-weight: 500; }\n.stx-step-description { font-size: 12px; color: #666; }\n.stx-step-connector { flex: 1; height: 2px; background: #e0e0e0; margin: 0 8px; min-width: 20px; }\n.stx-stepper--vertical .stx-step-connector { width: 2px; height: 20px; margin: 8px 0 8px 15px; }\n\n/* Modal Component */\n.stx-modal-component--hidden { display: none; }\n.stx-modal-component-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: flex; align-items: center; justify-content: center; z-index: 10000; }\n.stx-modal-component-dialog { background: #fff; border-radius: 12px; max-height: 90vh; overflow: hidden; display: flex; flex-direction: column; }\n.stx-modal-component--small .stx-modal-component-dialog { width: 300px; }\n.stx-modal-component--medium .stx-modal-component-dialog { width: 500px; }\n.stx-modal-component--large .stx-modal-component-dialog { width: 800px; }\n.stx-modal-component--fullscreen .stx-modal-component-dialog { width: 100%; height: 100%; border-radius: 0; }\n.stx-modal-component-header { display: flex; justify-content: space-between; align-items: center; padding: 16px; border-bottom: 1px solid #e0e0e0; }\n.stx-modal-component-title { margin: 0; font-size: 18px; }\n.stx-modal-component-close { background: none; border: none; font-size: 24px; cursor: pointer; opacity: 0.6; }\n.stx-modal-component-close:hover { opacity: 1; }\n.stx-modal-component-body { padding: 16px; overflow-y: auto; flex: 1; }\n.stx-modal-component-footer { padding: 16px; border-top: 1px solid #e0e0e0; display: flex; justify-content: flex-end; gap: 8px; }\n\n/* List View */\n.stx-list-view { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; }\n.stx-list-view-items { list-style: none; margin: 0; padding: 0; }\n.stx-list-view-item { padding: 12px 16px; border-bottom: 1px solid #e0e0e0; }\n.stx-list-view-item:last-child { border-bottom: none; }\n.stx-list-view--selectable .stx-list-view-item { cursor: pointer; }\n.stx-list-view--selectable .stx-list-view-item:hover { background: #f5f5f5; }\n.stx-list-view-item--selected { background: #e8f4fc; }\n.stx-list-view-empty { padding: 24px; text-align: center; color: #666; }\n\n/* Table */\n.stx-table { overflow-x: auto; }\n.stx-table table { width: 100%; border-collapse: collapse; }\n.stx-table th, .stx-table td { padding: 12px; text-align: left; }\n.stx-table th { font-weight: 600; background: #f5f5f5; }\n.stx-table--bordered th, .stx-table--bordered td { border: 1px solid #e0e0e0; }\n.stx-table--striped tbody tr:nth-child(even) { background: #f9f9f9; }\n.stx-table--hoverable tbody tr:hover { background: #f5f5f5; }\n.stx-table th[data-sortable] { cursor: pointer; }\n.stx-table-sort-icon::after { content: '⇅'; margin-left: 4px; opacity: 0.3; }\n.stx-table-sorted .stx-table-sort-icon::after { opacity: 1; }\n.stx-table-sorted--asc .stx-table-sort-icon::after { content: '↑'; }\n.stx-table-sorted--desc .stx-table-sort-icon::after { content: '↓'; }\n\n/* Tree View */\n.stx-tree-view { font-size: 14px; }\n.stx-tree-node { padding-left: 20px; }\n.stx-tree-node-content { display: flex; align-items: center; gap: 4px; padding: 4px; cursor: pointer; border-radius: 4px; }\n.stx-tree-node-content:hover { background: #f5f5f5; }\n.stx-tree-node--selected > .stx-tree-node-content { background: #e8f4fc; }\n.stx-tree-node--disabled { opacity: 0.5; }\n.stx-tree-toggle { width: 16px; cursor: pointer; transition: transform 0.2s; }\n.stx-tree-toggle--expanded { transform: rotate(90deg); }\n.stx-tree-toggle-placeholder { width: 16px; }\n.stx-tree-children { padding-left: 8px; }\n\n/* Data Grid */\n.stx-data-grid { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; }\n.stx-data-grid-table-wrapper { overflow-x: auto; }\n.stx-data-grid-table { width: 100%; border-collapse: collapse; }\n.stx-data-grid-table th, .stx-data-grid-table td { padding: 12px; text-align: left; border-bottom: 1px solid #e0e0e0; }\n.stx-data-grid-table th { background: #f5f5f5; }\n.stx-data-grid-header-cell { display: flex; align-items: center; gap: 8px; }\n.stx-data-grid-sort, .stx-data-grid-filter { background: none; border: none; cursor: pointer; opacity: 0.5; }\n.stx-data-grid-sort:hover, .stx-data-grid-filter:hover { opacity: 1; }\n.stx-data-grid-pagination { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border-top: 1px solid #e0e0e0; }\n.stx-data-grid-page-buttons { display: flex; gap: 4px; }\n.stx-data-grid-page-btn { padding: 4px 8px; border: 1px solid #e0e0e0; background: #fff; cursor: pointer; border-radius: 4px; }\n.stx-data-grid-page-btn:disabled { opacity: 0.5; cursor: not-allowed; }\n\n/* Chart */\n.stx-chart { background: #f9f9f9; border-radius: 8px; display: flex; align-items: center; justify-content: center; }\n.stx-chart-placeholder { text-align: center; padding: 20px; }\n.stx-chart-title { font-size: 16px; font-weight: 600; margin-bottom: 8px; }\n.stx-chart-type { font-size: 14px; color: #666; }\n.stx-chart-info { font-size: 12px; color: #999; margin-top: 4px; }\n\n/* Code Editor */\n.stx-code-editor { display: flex; font-family: 'Monaco', 'Menlo', monospace; font-size: 13px; line-height: 1.5; overflow: hidden; border-radius: 8px; }\n.stx-code-editor--dark { background: #1e1e1e; color: #d4d4d4; }\n.stx-code-editor--light { background: #fff; color: #333; border: 1px solid #e0e0e0; }\n.stx-code-editor-gutter { padding: 12px 8px; background: rgba(0,0,0,0.1); text-align: right; user-select: none; }\n.stx-code-editor-line-number { color: #858585; }\n.stx-code-editor-content { flex: 1; padding: 12px; overflow: auto; }\n.stx-code-editor-content pre { margin: 0; }\n.stx-code-editor--wrap .stx-code-editor-content { white-space: pre-wrap; word-wrap: break-word; }\n\n/* Media Player */\n.stx-media-player video, .stx-media-player audio { width: 100%; display: block; }\n.stx-media-player--video { background: #000; }\n\n/* File Explorer */\n.stx-file-explorer { border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; }\n.stx-file-explorer-list { width: 100%; border-collapse: collapse; }\n.stx-file-explorer-list th { text-align: left; padding: 8px 12px; background: #f5f5f5; font-weight: 500; }\n.stx-file-explorer-list td { padding: 8px 12px; border-top: 1px solid #e0e0e0; }\n.stx-file-explorer-item--selectable { cursor: pointer; }\n.stx-file-explorer-item--selectable:hover { background: #f5f5f5; }\n.stx-file-explorer-icon { margin-right: 8px; }\n.stx-file-explorer-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 16px; padding: 16px; }\n.stx-file-explorer--grid .stx-file-explorer-item { text-align: center; padding: 12px; border-radius: 8px; }\n.stx-file-explorer--grid .stx-file-explorer-icon { font-size: 32px; display: block; margin-bottom: 8px; }\n.stx-file-explorer--grid .stx-file-explorer-name { font-size: 12px; word-break: break-all; }\n\n/* WebView */\n.stx-webview { border: none; display: block; }\n\n/* Dark mode support */\n@media (prefers-color-scheme: dark) {\n .stx-input-label { color: #eee; }\n .stx-input { background: #333; border-color: #555; color: #fff; }\n .stx-card { background: #2d2d2d; color: #fff; }\n .stx-card-subtitle { color: #aaa; }\n .stx-progress { background: #444; }\n .stx-dropdown { background: #333; border-color: #555; color: #fff; }\n .stx-accordion { border-color: #444; }\n .stx-accordion-item { border-color: #444; }\n .stx-accordion-header:hover { background: #333; }\n .stx-list-view { border-color: #444; }\n .stx-list-view-item { border-color: #444; }\n .stx-list-view--selectable .stx-list-view-item:hover { background: #333; }\n .stx-table th { background: #333; }\n .stx-table--bordered th, .stx-table--bordered td { border-color: #444; }\n .stx-tree-node-content:hover { background: #333; }\n .stx-data-grid { border-color: #444; }\n .stx-data-grid-table th, .stx-data-grid-table td { border-color: #444; }\n .stx-data-grid-table th { background: #333; }\n .stx-modal-component-dialog { background: #2d2d2d; color: #fff; }\n .stx-modal-component-header, .stx-modal-component-footer { border-color: #444; }\n .stx-file-explorer { border-color: #444; }\n .stx-file-explorer-list th { background: #333; }\n .stx-file-explorer-list td { border-color: #444; }\n .stx-autocomplete-list { background: #333; border-color: #444; }\n .stx-autocomplete-item:hover { background: #444; }\n .stx-chip--default { background: #444; color: #eee; }\n .stx-chip--primary { background: #1a3a52; }\n .stx-chip--success { background: #1a3a2a; }\n .stx-chip--warning { background: #3a2a1a; }\n .stx-chip--error { background: #3a1a1a; }\n}\n`\n",
7
- "import type { ModalButton, ModalOptions, ModalResult } from './types'\n\n/**\n * Modal Dialog Implementation\n *\n * Provides cross-platform modal dialog functionality.\n * Uses native dialogs when available, falls back to web-based modals.\n *\n * Features:\n * - Multiple dialog types (info, warning, error, success, question)\n * - Custom buttons with actions\n * - Promise-based API\n * - Keyboard support (Enter/Escape)\n * - Accessible by default\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface ModalState {\n id: string\n options: ModalOptions\n resolve: (result: ModalResult) => void\n element?: HTMLElement\n}\n\n// =============================================================================\n// Platform Detection\n// =============================================================================\n\n/**\n * Check if native dialog APIs are available\n */\nfunction hasNativeDialogSupport(): boolean {\n // Future: Check for @stacksjs/zyte bindings\n return false\n}\n\n/**\n * Check if running in browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined'\n}\n\n// =============================================================================\n// Modal Manager\n// =============================================================================\n\n// Active modal stack\nconst activeModals: ModalState[] = []\n\n/**\n * Generate a unique modal ID\n */\nfunction generateModalId(): string {\n return `modal-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n}\n\n/**\n * Get icon for modal type\n */\nfunction getModalIcon(type: ModalOptions['type']): string {\n switch (type) {\n case 'info':\n return '&#x2139;'\n case 'warning':\n return '&#x26A0;'\n case 'error':\n return '&#x2716;'\n case 'success':\n return '&#x2714;'\n case 'question':\n return '&#x2753;'\n default:\n return '&#x2139;'\n }\n}\n\n/**\n * Get default buttons for modal type\n */\nfunction getDefaultButtons(type: ModalOptions['type']): ModalButton[] {\n if (type === 'question') {\n return [\n { label: 'No', style: 'default' },\n { label: 'Yes', style: 'primary' },\n ]\n }\n return [{ label: 'OK', style: 'primary' }]\n}\n\n/**\n * Create modal HTML for web-based implementation\n */\nfunction createModalHTML(state: ModalState): string {\n const { options } = state\n const icon = getModalIcon(options.type)\n const buttons = options.buttons || getDefaultButtons(options.type)\n const typeClass = options.type || 'info'\n\n let buttonsHtml = ''\n buttons.forEach((btn, index) => {\n const styleClass = btn.style === 'destructive' ? 'destructive' : btn.style === 'primary' ? 'primary' : 'default'\n const autoFocus = index === (options.defaultButton ?? buttons.length - 1) ? 'autofocus' : ''\n buttonsHtml += `<button class=\"stx-modal-btn ${styleClass}\" data-index=\"${index}\" ${autoFocus}>${btn.label}</button>`\n })\n\n return `\n <div class=\"stx-modal-overlay\" data-modal-id=\"${state.id}\">\n <div class=\"stx-modal ${typeClass}\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"${state.id}-title\">\n <div class=\"stx-modal-icon\">${icon}</div>\n <div class=\"stx-modal-content\">\n ${options.title ? `<h2 id=\"${state.id}-title\" class=\"stx-modal-title\">${escapeHtml(options.title)}</h2>` : ''}\n <p class=\"stx-modal-message\">${escapeHtml(options.message)}</p>\n </div>\n <div class=\"stx-modal-buttons\">${buttonsHtml}</div>\n </div>\n </div>\n `\n}\n\n/**\n * Escape HTML to prevent XSS\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;')\n}\n\n/**\n * Close a modal and resolve with result\n */\nfunction closeModal(state: ModalState, buttonIndex: number, cancelled: boolean = false): void {\n // Remove from active modals\n const index = activeModals.indexOf(state)\n if (index > -1) {\n activeModals.splice(index, 1)\n }\n\n // Remove DOM element if exists\n if (state.element && isBrowser()) {\n state.element.remove()\n }\n\n // Call button action if provided\n const buttons = state.options.buttons || getDefaultButtons(state.options.type)\n const button = buttons[buttonIndex]\n if (button?.action) {\n button.action()\n }\n\n // Resolve promise\n state.resolve({ buttonIndex, cancelled })\n}\n\n/**\n * Show a native modal dialog\n *\n * @param options - Modal configuration options\n * @returns Promise resolving to the modal result\n *\n * @example\n * ```typescript\n * const result = await showModal({\n * title: 'Confirm Action',\n * message: 'Are you sure you want to proceed?',\n * type: 'question',\n * buttons: [\n * { label: 'Cancel', style: 'default' },\n * { label: 'Confirm', style: 'primary' },\n * ],\n * })\n *\n * if (result.buttonIndex === 1) {\n * // User clicked Confirm\n * }\n * ```\n */\nexport async function showModal(options: ModalOptions): Promise<ModalResult> {\n const hasNative = hasNativeDialogSupport()\n const id = generateModalId()\n\n return new Promise((resolve) => {\n const state: ModalState = {\n id,\n options,\n resolve,\n }\n\n activeModals.push(state)\n\n if (hasNative) {\n // Future: Use native dialog\n console.log(`[stx-modal] Showing native modal: ${options.title || 'Modal'}`)\n // For now, immediately resolve\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n }\n else if (isBrowser()) {\n // Web-based implementation\n try {\n const container = document.createElement('div')\n container.innerHTML = createModalHTML(state)\n const overlay = container.firstElementChild as HTMLElement\n\n if (!overlay) {\n // Fallback to console if DOM manipulation fails\n console.log(`[stx-modal] ${options.type?.toUpperCase() || 'INFO'}: ${options.title || 'Modal'}`)\n console.log(`[stx-modal] ${options.message}`)\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n return\n }\n\n state.element = overlay\n\n try {\n document.body.appendChild(overlay)\n }\n catch {\n // Fallback to console if appendChild fails (e.g., in very-happy-dom)\n console.log(`[stx-modal] ${options.type?.toUpperCase() || 'INFO'}: ${options.title || 'Modal'}`)\n console.log(`[stx-modal] ${options.message}`)\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n return\n }\n\n // Handle button clicks\n try {\n overlay.querySelectorAll('.stx-modal-btn').forEach((btn) => {\n btn.addEventListener('click', () => {\n const index = Number.parseInt((btn as HTMLElement).dataset.index || '0', 10)\n closeModal(state, index, false)\n })\n })\n }\n catch {\n // Ignore querySelectorAll errors in very-happy-dom\n }\n\n // Handle overlay click (close on backdrop click)\n try {\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) {\n const cancelIndex = options.cancelButton ?? 0\n closeModal(state, cancelIndex, true)\n }\n })\n }\n catch {\n // Ignore addEventListener errors\n }\n\n // Handle keyboard\n try {\n const handleKeydown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n const cancelIndex = options.cancelButton ?? 0\n closeModal(state, cancelIndex, true)\n document.removeEventListener('keydown', handleKeydown)\n }\n else if (e.key === 'Enter') {\n const defaultIndex = options.defaultButton ?? ((options.buttons || getDefaultButtons(options.type)).length - 1)\n closeModal(state, defaultIndex, false)\n document.removeEventListener('keydown', handleKeydown)\n }\n }\n document.addEventListener('keydown', handleKeydown)\n }\n catch {\n // Ignore keyboard event errors\n }\n\n // Focus first button\n try {\n const firstButton = overlay.querySelector('.stx-modal-btn[autofocus]') as HTMLElement\n if (firstButton) {\n firstButton.focus()\n }\n }\n catch {\n // Ignore focus errors\n }\n\n // In test environments (no real user to click) auto-resolve with the\n // default button so tests asserting ModalResult shape don't hang.\n if (typeof process !== 'undefined' && (process.env.NODE_ENV === 'test' || process.env.BUN_TEST)) {\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n }\n }\n catch {\n // Fallback to console if any DOM operation fails\n console.log(`[stx-modal] ${options.type?.toUpperCase() || 'INFO'}: ${options.title || 'Modal'}`)\n console.log(`[stx-modal] ${options.message}`)\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n }\n }\n else {\n // Node.js environment - console fallback\n console.log(`[stx-modal] ${options.type?.toUpperCase() || 'INFO'}: ${options.title || 'Modal'}`)\n console.log(`[stx-modal] ${options.message}`)\n const buttons = options.buttons || getDefaultButtons(options.type)\n console.log(`[stx-modal] Buttons: ${buttons.map(b => b.label).join(', ')}`)\n\n // Auto-resolve with default button\n setTimeout(() => {\n closeModal(state, options.defaultButton ?? 0, false)\n }, 0)\n }\n })\n}\n\n/**\n * Show an info modal\n */\nexport async function showInfoModal(title: string, message: string): Promise<ModalResult> {\n return showModal({ title, message, type: 'info' })\n}\n\n/**\n * Show a warning modal\n */\nexport async function showWarningModal(title: string, message: string): Promise<ModalResult> {\n return showModal({ title, message, type: 'warning' })\n}\n\n/**\n * Show an error modal\n */\nexport async function showErrorModal(title: string, message: string): Promise<ModalResult> {\n return showModal({ title, message, type: 'error' })\n}\n\n/**\n * Show a success modal\n */\nexport async function showSuccessModal(title: string, message: string): Promise<ModalResult> {\n return showModal({ title, message, type: 'success' })\n}\n\n/**\n * Show a question/confirmation modal\n */\nexport async function showQuestionModal(title: string, message: string): Promise<ModalResult> {\n return showModal({\n title,\n message,\n type: 'question',\n buttons: [\n { label: 'No', style: 'default' },\n { label: 'Yes', style: 'primary' },\n ],\n defaultButton: 1,\n cancelButton: 0,\n })\n}\n\n/**\n * Show a confirm dialog (alias for showQuestionModal)\n */\nexport async function confirm(message: string, title: string = 'Confirm'): Promise<boolean> {\n const result = await showQuestionModal(title, message)\n return result.buttonIndex === 1\n}\n\n/**\n * Show an alert dialog (single OK button)\n */\nexport async function alert(message: string, title: string = 'Alert'): Promise<void> {\n await showInfoModal(title, message)\n}\n\n/**\n * Show a prompt dialog with input field\n */\nexport async function prompt(message: string, defaultValue: string = '', title: string = 'Input'): Promise<string | null> {\n // This would need custom implementation for input field\n // For now, use console in Node.js or native prompt in browser\n if (isBrowser() && typeof window.prompt === 'function') {\n return window.prompt(message, defaultValue)\n }\n\n console.log(`[stx-modal] PROMPT: ${title}`)\n console.log(`[stx-modal] ${message}`)\n console.log(`[stx-modal] Default: ${defaultValue}`)\n\n // In Node.js, would need readline or similar\n return defaultValue\n}\n\n/**\n * Get number of active modals\n */\nexport function getActiveModalCount(): number {\n return activeModals.length\n}\n\n/**\n * Close all active modals\n */\nexport function closeAllModals(): void {\n // Close in reverse order (top-most first)\n while (activeModals.length > 0) {\n const state = activeModals[activeModals.length - 1]\n closeModal(state, 0, true)\n }\n}\n\n/**\n * CSS styles for web-based modals\n */\nexport const MODAL_STYLES = `\n.stx-modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n animation: stx-modal-fade-in 0.15s ease-out;\n}\n\n@keyframes stx-modal-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.stx-modal {\n background: #fff;\n border-radius: 12px;\n padding: 24px;\n max-width: 400px;\n width: 90%;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);\n animation: stx-modal-slide-up 0.2s ease-out;\n}\n\n@keyframes stx-modal-slide-up {\n from { transform: translateY(20px); opacity: 0; }\n to { transform: translateY(0); opacity: 1; }\n}\n\n@media (prefers-color-scheme: dark) {\n .stx-modal {\n background: #2d2d2d;\n color: #fff;\n }\n}\n\n.stx-modal-icon {\n font-size: 48px;\n text-align: center;\n margin-bottom: 16px;\n}\n\n.stx-modal.info .stx-modal-icon { color: #3498db; }\n.stx-modal.warning .stx-modal-icon { color: #f39c12; }\n.stx-modal.error .stx-modal-icon { color: #e74c3c; }\n.stx-modal.success .stx-modal-icon { color: #27ae60; }\n.stx-modal.question .stx-modal-icon { color: #9b59b6; }\n\n.stx-modal-content {\n text-align: center;\n margin-bottom: 24px;\n}\n\n.stx-modal-title {\n margin: 0 0 8px;\n font-size: 20px;\n font-weight: 600;\n}\n\n.stx-modal-message {\n margin: 0;\n color: #666;\n line-height: 1.5;\n}\n\n@media (prefers-color-scheme: dark) {\n .stx-modal-message { color: #aaa; }\n}\n\n.stx-modal-buttons {\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n\n.stx-modal-btn {\n padding: 10px 24px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n border: none;\n transition: background 0.15s, transform 0.1s;\n}\n\n.stx-modal-btn:hover {\n transform: translateY(-1px);\n}\n\n.stx-modal-btn:active {\n transform: translateY(0);\n}\n\n.stx-modal-btn.default {\n background: #e0e0e0;\n color: #333;\n}\n\n.stx-modal-btn.default:hover {\n background: #d0d0d0;\n}\n\n.stx-modal-btn.primary {\n background: #3498db;\n color: #fff;\n}\n\n.stx-modal-btn.primary:hover {\n background: #2980b9;\n}\n\n.stx-modal-btn.destructive {\n background: #e74c3c;\n color: #fff;\n}\n\n.stx-modal-btn.destructive:hover {\n background: #c0392b;\n}\n\n@media (prefers-color-scheme: dark) {\n .stx-modal-btn.default {\n background: #444;\n color: #fff;\n }\n .stx-modal-btn.default:hover {\n background: #555;\n }\n}\n`\n",
8
- "// @ts-nocheck - Skip type checking due to menu item type constraints\nimport type { SystemTrayInstance, SystemTrayMenuItem, SystemTrayOptions } from './types'\nimport process from 'node:process'\n\n/**\n * System Tray / Menubar Implementation\n *\n * Provides cross-platform system tray functionality using Craft's native APIs.\n *\n * ## Architecture\n *\n * When running inside a Craft native window, tray operations use the\n * `window.craft.tray` bridge to communicate with the native process.\n *\n * When running outside Craft (e.g., in browser or Node.js), provides a\n * web-based simulation for development and testing.\n *\n * ## Usage in Craft\n *\n * The tray is automatically enabled when you pass `systemTray: true` to\n * the window options in Craft. This module provides additional TypeScript\n * APIs for programmatic control.\n *\n * ```typescript\n * // Create tray via @stacksjs/desktop\n * const tray = await createSystemTray({\n * tooltip: 'My App',\n * menu: [\n * { label: 'Show Window', onClick: () => window.craft.window.show() },\n * { type: 'separator' },\n * { label: 'Quit', onClick: () => window.craft.app.quit() },\n * ],\n * })\n *\n * // Or use Craft's bridge directly in your HTML/JS:\n * window.craft.tray.setTitle('My App')\n * window.craft.tray.setMenu([...])\n * ```\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface TrayState {\n icon: string\n tooltip: string\n menu: SystemTrayMenuItem[]\n visible: boolean\n}\n\n/**\n * Menu item format expected by Craft's tray bridge\n */\ninterface CraftMenuItemDefinition {\n id: string\n label: string\n type?: 'normal' | 'separator' | 'checkbox' | 'radio'\n checked?: boolean\n enabled?: boolean\n action?: string\n shortcut?: string\n submenu?: CraftMenuItemDefinition[]\n}\n\n// =============================================================================\n// Platform Detection\n// =============================================================================\n\n/**\n * Detect the current platform\n */\nfunction getPlatform(): 'darwin' | 'linux' | 'win32' | 'unknown' {\n if (process.platform) {\n return process.platform as 'darwin' | 'linux' | 'win32' | 'unknown'\n }\n return 'unknown'\n}\n\n/**\n * Check if running inside a Craft native window\n */\nfunction isInCraftWindow(): boolean {\n if (typeof window !== 'undefined' && (window as any).craft?.tray) {\n return true\n }\n return false\n}\n\n// =============================================================================\n// Menu Conversion\n// =============================================================================\n\n/**\n * Convert SystemTrayMenuItem to Craft's menu format\n */\nfunction convertMenuItem(item: SystemTrayMenuItem, index: number): CraftMenuItemDefinition {\n if (item.type === 'separator') {\n return {\n id: `sep-${index}`,\n label: '',\n type: 'separator',\n }\n }\n\n const menuItem: CraftMenuItemDefinition = {\n id: `item-${index}-${item.label.replace(/\\s+/g, '-').toLowerCase()}`,\n label: item.label,\n type: item.type || 'normal',\n enabled: item.enabled !== false,\n }\n\n if (item.accelerator) {\n menuItem.shortcut = item.accelerator\n }\n\n if (item.type === 'checkbox') {\n menuItem.checked = item.checked || false\n }\n\n if (item.type === 'submenu' && item.submenu) {\n menuItem.submenu = item.submenu.map((subItem, subIndex) =>\n convertMenuItem(subItem, subIndex),\n )\n}\n\nreturn menuItem\n}\n\n/**\n * Convert array of SystemTrayMenuItems to Craft format\n */\nfunction convertMenuItems(items: SystemTrayMenuItem[]): CraftMenuItemDefinition[] {\n return items.map((item, index) => convertMenuItem(item, index))\n}\n\n// =============================================================================\n// Menu Rendering (Web Simulation)\n// =============================================================================\n\n/**\n * Render a menu item to HTML (for web-based simulation)\n */\nfunction renderMenuItem(item: SystemTrayMenuItem, level: number = 0): string {\n if (item.type === 'separator') {\n return '<hr class=\"stx-tray-separator\" />'\n }\n\n const indent = ' '.repeat(level)\n const disabled = item.enabled === false ? 'disabled' : ''\n const checked = item.checked ? '✓ ' : ''\n const accelerator = item.accelerator ? `<span class=\"accelerator\">${item.accelerator}</span>` : ''\n\n let html = `${indent}<div class=\"stx-tray-item ${disabled}\" data-action=\"${item.label}\">`\n html += `<span class=\"label\">${checked}${item.label}</span>${accelerator}`\n\n if (item.type === 'submenu' && item.submenu) {\n html += '<span class=\"arrow\">▸</span>'\n html += '<div class=\"stx-tray-submenu\">'\n for (const subItem of item.submenu) {\n html += renderMenuItem(subItem, level + 1)\n }\n html += '</div>'\n }\n\n html += '</div>'\n return html\n}\n\n/**\n * Render the full tray menu to HTML\n */\nfunction renderTrayMenu(menu: SystemTrayMenuItem[]): string {\n let html = '<div class=\"stx-tray-menu\">'\n for (const item of menu) {\n html += renderMenuItem(item)\n }\n html += '</div>'\n return html\n}\n\n// =============================================================================\n// Tray Manager\n// =============================================================================\n\n// Active tray instances\nconst activeTrayInstances = new Map<string, { state: TrayState, handlers: Map<string, () => void> }>()\n\n/**\n * Generate a unique tray ID\n */\nfunction generateTrayId(): string {\n return `tray-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`\n}\n\n/**\n * Set up event listener for tray menu actions (Craft bridge)\n */\nlet craftTrayListenerSetup = false\n\nfunction setupCraftTrayListener(): void {\n if (craftTrayListenerSetup || typeof window === 'undefined') return\n\n window.addEventListener('craft:tray:menu', ((event: CustomEvent) => {\n const { action } = event.detail\n // Find the handler for this action\n for (const instance of activeTrayInstances.values()) {\n const handler = instance.handlers.get(action)\n if (handler) {\n handler()\n break\n }\n }\n }) as EventListener)\n\n craftTrayListenerSetup = true\n}\n\n/**\n * Create a system tray/menubar application\n *\n * When running inside a Craft native window, this creates a real native tray.\n * Otherwise, it creates a simulated tray for development purposes.\n *\n * @param options - Tray configuration options\n * @returns System tray instance\n *\n * @example\n * ```typescript\n * const tray = await createSystemTray({\n * icon: './icon.png',\n * tooltip: 'My App',\n * menu: [\n * { label: 'Show Window', onClick: () => stxWindow.show() },\n * { type: 'separator' },\n * { label: 'Quit', onClick: () => stxWindow.quit() },\n * ],\n * })\n * ```\n */\nexport async function createSystemTray(options: SystemTrayOptions = {}): Promise<SystemTrayInstance> {\n const id = generateTrayId()\n const platform = getPlatform()\n const inCraft = isInCraftWindow()\n\n // Initialize state\n const state: TrayState = {\n icon: options.icon || '',\n tooltip: options.tooltip || 'stx Application',\n menu: options.menu || [],\n visible: true,\n }\n\n // Store click handlers\n const handlers = new Map<string, () => void>()\n for (const item of options.menu || []) {\n if (item.type !== 'separator' && item.onClick) {\n handlers.set(item.label, item.onClick)\n }\n // Handle submenu items\n if (item.type === 'submenu' && item.submenu) {\n for (const subItem of item.submenu) {\n if (subItem.type !== 'separator' && subItem.onClick) {\n handlers.set(subItem.label, subItem.onClick)\n }\n }\n }\n }\n\n // Store instance\n activeTrayInstances.set(id, { state, handlers })\n\n // Platform-specific implementation\n if (inCraft) {\n setupCraftTrayListener()\n\n // Use Craft's native tray APIs\n const craftWindow = window as any\n try {\n // Set the tray title/tooltip\n if (state.tooltip) {\n await craftWindow.craft.tray.setTitle({ title: state.tooltip })\n await craftWindow.craft.tray.setTooltip({ tooltip: state.tooltip })\n }\n\n // Set the icon if provided\n if (state.icon) {\n await craftWindow.craft.tray.setIcon({ icon: state.icon })\n }\n\n // Set the menu\n const craftMenu = convertMenuItems(state.menu)\n await craftWindow.craft.tray.setMenu({ items: craftMenu })\n\n console.log(`[stx-tray] Native tray created for ${platform}`)\n }\n catch (error) {\n console.warn('[stx-tray] Failed to create native tray:', error)\n }\n }\n else {\n // Web-based simulation for development\n console.log(`[stx-tray] Created simulated tray (not in Craft window)`)\n console.log(`[stx-tray] ID: ${id}`)\n console.log(`[stx-tray] Tooltip: ${state.tooltip}`)\n console.log(`[stx-tray] Menu items: ${state.menu.length}`)\n }\n\n // Create instance methods\n const instance: SystemTrayInstance = {\n id,\n\n setIcon: (icon: string) => {\n state.icon = icon\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.setIcon({ icon }).catch((e: Error) => {\n console.warn('[stx-tray] Failed to set icon:', e)\n })\n }\n console.log(`[stx-tray:${id}] Icon updated`)\n },\n\n setTooltip: (tooltip: string) => {\n state.tooltip = tooltip\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.setTooltip({ tooltip }).catch((e: Error) => {\n console.warn('[stx-tray] Failed to set tooltip:', e)\n })\n }\n console.log(`[stx-tray:${id}] Tooltip: ${tooltip}`)\n },\n\n setMenu: (menu: SystemTrayMenuItem[]) => {\n state.menu = menu\n // Update handlers\n handlers.clear()\n for (const item of menu) {\n if (item.type !== 'separator' && item.onClick) {\n handlers.set(item.label, item.onClick)\n }\n if (item.type === 'submenu' && item.submenu) {\n for (const subItem of item.submenu) {\n if (subItem.type !== 'separator' && subItem.onClick) {\n handlers.set(subItem.label, subItem.onClick)\n }\n }\n }\n }\n\n if (inCraft) {\n const craftWindow = window as any\n const craftMenu = convertMenuItems(menu)\n craftWindow.craft.tray.setMenu({ items: craftMenu }).catch((e: Error) => {\n console.warn('[stx-tray] Failed to set menu:', e)\n })\n }\n console.log(`[stx-tray:${id}] Menu updated (${menu.length} items)`)\n },\n\n destroy: () => {\n state.visible = false\n activeTrayInstances.delete(id)\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.destroy?.().catch((e: Error) => {\n console.warn('[stx-tray] Failed to destroy tray:', e)\n })\n }\n console.log(`[stx-tray:${id}] Destroyed`)\n },\n }\n\n return instance\n}\n\n/**\n * Create a menubar application (alias for createSystemTray)\n */\nexport const createMenubar: typeof createSystemTray = createSystemTray\n\n/**\n * Get all active tray instances\n */\nexport function getActiveTrayInstances(): string[] {\n return Array.from(activeTrayInstances.keys())\n}\n\n/**\n * Get a tray instance by ID\n */\nexport function getTrayInstance(id: string): SystemTrayInstance | null {\n const instance = activeTrayInstances.get(id)\n if (!instance)\n return null\n\n const inCraft = isInCraftWindow()\n\n return {\n id,\n setIcon: (icon: string) => {\n instance.state.icon = icon\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.setIcon({ icon }).catch(() => {})\n }\n },\n setTooltip: (tooltip: string) => {\n instance.state.tooltip = tooltip\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.setTooltip({ tooltip }).catch(() => {})\n }\n },\n setMenu: (menu: SystemTrayMenuItem[]) => {\n instance.state.menu = menu\n if (inCraft) {\n const craftWindow = window as any\n const craftMenu = convertMenuItems(menu)\n craftWindow.craft.tray.setMenu({ items: craftMenu }).catch(() => {})\n }\n },\n destroy: () => {\n activeTrayInstances.delete(id)\n if (inCraft) {\n const craftWindow = window as any\n craftWindow.craft.tray.destroy?.().catch(() => {})\n }\n },\n }\n}\n\n/**\n * Trigger a menu item action by label\n * Useful for testing and programmatic control\n */\nexport function triggerTrayAction(trayId: string, actionLabel: string): boolean {\n const instance = activeTrayInstances.get(trayId)\n if (!instance)\n return false\n\n const handler = instance.handlers.get(actionLabel)\n if (handler) {\n handler()\n return true\n }\n return false\n}\n\n/**\n * Get the HTML for a simulated tray menu\n * Useful for web-based testing and development\n */\nexport function getSimulatedTrayHTML(trayId: string): string | null {\n const instance = activeTrayInstances.get(trayId)\n if (!instance)\n return null\n\n return renderTrayMenu(instance.state.menu)\n}\n\n// =============================================================================\n// Bridge Script Generator\n// =============================================================================\n\n/**\n * Generate a JavaScript snippet for tray control from inside a webview.\n * This provides convenient wrappers around the Craft tray bridge.\n */\nexport function getTrayBridgeScript(): string {\n return `\n// STX Desktop Tray Bridge\n// Provides convenient wrappers around window.craft.tray APIs\nwindow.stxTray = {\n setTitle: (title) => window.craft?.tray?.setTitle({ title }),\n setTooltip: (tooltip) => window.craft?.tray?.setTooltip({ tooltip }),\n setIcon: (icon) => window.craft?.tray?.setIcon({ icon }),\n setMenu: (items) => window.craft?.tray?.setMenu({ items }),\n destroy: () => window.craft?.tray?.destroy(),\n\n // Check if tray is available\n isAvailable: () => typeof window.craft?.tray !== 'undefined',\n};\n`\n}\n\n// =============================================================================\n// CSS Styles\n// =============================================================================\n\n/**\n * CSS styles for the simulated tray menu\n */\nexport const TRAY_MENU_STYLES = `\n.stx-tray-menu {\n background: #2d2d2d;\n border-radius: 8px;\n padding: 4px 0;\n min-width: 200px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 13px;\n color: #fff;\n}\n\n.stx-tray-item {\n padding: 6px 12px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n position: relative;\n}\n\n.stx-tray-item:hover {\n background: #3d3d3d;\n}\n\n.stx-tray-item.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.stx-tray-item .label {\n flex: 1;\n}\n\n.stx-tray-item .accelerator {\n margin-left: 20px;\n opacity: 0.6;\n font-size: 12px;\n}\n\n.stx-tray-item .arrow {\n margin-left: 8px;\n font-size: 10px;\n}\n\n.stx-tray-separator {\n margin: 4px 0;\n border: none;\n border-top: 1px solid #444;\n}\n\n.stx-tray-submenu {\n position: absolute;\n left: 100%;\n top: 0;\n background: #2d2d2d;\n border-radius: 8px;\n padding: 4px 0;\n min-width: 150px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: none;\n}\n\n.stx-tray-item:hover > .stx-tray-submenu {\n display: block;\n}\n`\n",
9
- "/**\n * Native Dialog Integration\n *\n * Provides native file dialogs, message boxes, and other system dialogs\n * using Craft's Dialog Bridge APIs.\n *\n * When running inside a Craft native window, these dialogs use the native\n * OS dialogs (NSOpenPanel on macOS, etc.). When running in a browser,\n * they fall back to web alternatives where possible.\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Options for opening a file dialog\n */\nexport interface OpenDialogOptions {\n /** Dialog title */\n title?: string\n /** Default path to open */\n defaultPath?: string\n /** Button label (e.g., \"Open\", \"Select\") */\n buttonLabel?: string\n /** File type filters */\n filters?: FileFilter[]\n /** Allow selecting multiple files */\n multiSelections?: boolean\n /** Show hidden files */\n showHiddenFiles?: boolean\n /** Allow selecting directories */\n canChooseDirectories?: boolean\n /** Allow selecting files */\n canChooseFiles?: boolean\n /** Allow creating new directories */\n canCreateDirectories?: boolean\n}\n\n/**\n * Options for saving a file dialog\n */\nexport interface SaveDialogOptions {\n /** Dialog title */\n title?: string\n /** Default path/filename */\n defaultPath?: string\n /** Button label (e.g., \"Save\") */\n buttonLabel?: string\n /** File type filters */\n filters?: FileFilter[]\n /** Show hidden files */\n showHiddenFiles?: boolean\n /** Allow creating new directories */\n canCreateDirectories?: boolean\n}\n\n/**\n * File type filter\n */\nexport interface FileFilter {\n /** Filter name (e.g., \"Images\") */\n name: string\n /** File extensions (e.g., [\"png\", \"jpg\", \"gif\"]) */\n extensions: string[]\n}\n\n/**\n * Result from open dialog\n */\nexport interface OpenDialogResult {\n /** Whether the dialog was cancelled */\n canceled: boolean\n /** Selected file paths */\n filePaths: string[]\n}\n\n/**\n * Result from save dialog\n */\nexport interface SaveDialogResult {\n /** Whether the dialog was cancelled */\n canceled: boolean\n /** Selected file path */\n filePath?: string\n}\n\n/**\n * Options for message box dialog\n */\nexport interface MessageBoxOptions {\n /** Message box type */\n type?: 'none' | 'info' | 'warning' | 'error' | 'question'\n /** Dialog title */\n title?: string\n /** Main message */\n message: string\n /** Secondary detail text */\n detail?: string\n /** Button labels */\n buttons?: string[]\n /** Index of default button */\n defaultButton?: number\n /** Index of cancel button */\n cancelButton?: number\n}\n\n/**\n * Result from message box\n */\nexport interface MessageBoxResult {\n /** Index of button clicked */\n response: number\n}\n\n/**\n * Options for color picker dialog\n */\nexport interface ColorPickerOptions {\n /** Initial color (hex format) */\n color?: string\n /** Show alpha/opacity control */\n showAlpha?: boolean\n}\n\n/**\n * Result from color picker\n */\nexport interface ColorPickerResult {\n /** Whether the dialog was cancelled */\n canceled: boolean\n /** Selected color in hex format */\n color?: string\n}\n\n// =============================================================================\n// Platform Detection\n// =============================================================================\n\n/**\n * Check if running inside a Craft native window\n */\nfunction isInCraftWindow(): boolean {\n if (typeof window !== 'undefined' && (window as any).craft?.dialog) {\n return true\n }\n return false\n}\n\n// =============================================================================\n// Native Dialog Functions\n// =============================================================================\n\n/**\n * Show a native file open dialog\n *\n * When running in Craft, uses the native OS file picker.\n * In browser, falls back to HTML file input.\n *\n * @param options - Dialog options\n * @returns Promise resolving to selected files or cancellation\n *\n * @example\n * ```typescript\n * const result = await showOpenDialog({\n * title: 'Select an image',\n * filters: [{ name: 'Images', extensions: ['png', 'jpg', 'gif'] }],\n * multiSelections: true,\n * })\n *\n * if (!result.canceled) {\n * console.log('Selected:', result.filePaths)\n * }\n * ```\n */\nexport async function showOpenDialog(options: OpenDialogOptions = {}): Promise<OpenDialogResult> {\n if (isInCraftWindow()) {\n // Use Craft's native dialog\n const craftWindow = window as any\n try {\n return await craftWindow.craft.dialog.showOpenDialog(options)\n }\n catch (error) {\n console.warn('[stx-dialog] Failed to show native open dialog:', error)\n // Fall through to web fallback\n }\n }\n\n // Web fallback: use file input\n return new Promise((resolve) => {\n if (typeof document === 'undefined') {\n resolve({ canceled: true, filePaths: [] })\n return\n }\n\n const input = document.createElement('input')\n input.type = 'file'\n input.multiple = options.multiSelections ?? false\n\n // Set accept types from filters\n if (options.filters?.length) {\n const extensions = options.filters.flatMap(f => f.extensions.map(e => `.${e}`))\n input.accept = extensions.join(',')\n }\n\n // Directory selection (limited browser support)\n if (options.canChooseDirectories && !options.canChooseFiles) {\n (input as any).webkitdirectory = true\n }\n\n input.onchange = () => {\n const files = Array.from(input.files || [])\n if (files.length === 0) {\n resolve({ canceled: true, filePaths: [] })\n }\n else {\n // Note: In browsers, we can only get file names, not full paths\n const filePaths = files.map(f => f.name)\n resolve({ canceled: false, filePaths })\n }\n }\n\n input.oncancel = () => {\n resolve({ canceled: true, filePaths: [] })\n }\n\n input.click()\n })\n}\n\n/**\n * Show a native file save dialog\n *\n * When running in Craft, uses the native OS save dialog.\n * In browser, this is limited to triggering downloads.\n *\n * @param options - Dialog options\n * @returns Promise resolving to selected path or cancellation\n *\n * @example\n * ```typescript\n * const result = await showSaveDialog({\n * title: 'Save document',\n * defaultPath: 'document.txt',\n * filters: [{ name: 'Text Files', extensions: ['txt'] }],\n * })\n *\n * if (!result.canceled && result.filePath) {\n * console.log('Save to:', result.filePath)\n * }\n * ```\n */\nexport async function showSaveDialog(options: SaveDialogOptions = {}): Promise<SaveDialogResult> {\n if (isInCraftWindow()) {\n // Use Craft's native dialog\n const craftWindow = window as any\n try {\n return await craftWindow.craft.dialog.showSaveDialog(options)\n }\n catch (error) {\n console.warn('[stx-dialog] Failed to show native save dialog:', error)\n }\n }\n\n // Web fallback: use showSaveFilePicker if available (modern browsers)\n if (typeof window !== 'undefined' && 'showSaveFilePicker' in window) {\n try {\n const fileTypes = options.filters?.map(f => ({\n description: f.name,\n accept: {\n '*/*': f.extensions.map(e => `.${e}`),\n },\n }))\n\n const handle = await (window as any).showSaveFilePicker({\n suggestedName: options.defaultPath,\n types: fileTypes,\n })\n\n return { canceled: false, filePath: handle.name }\n }\n catch (error) {\n // User cancelled or API not supported\n return { canceled: true }\n }\n }\n\n // Fallback: prompt for filename\n console.warn('[stx-dialog] Save dialog not available, using prompt fallback')\n const filename = prompt('Enter filename:', options.defaultPath || 'file.txt')\n if (filename) {\n return { canceled: false, filePath: filename }\n }\n return { canceled: true }\n}\n\n/**\n * Show a native message box dialog\n *\n * When running in Craft, uses the native OS message box.\n * In browser, falls back to confirm/alert dialogs.\n *\n * @param options - Message box options\n * @returns Promise resolving to button index clicked\n *\n * @example\n * ```typescript\n * const result = await showMessageBox({\n * type: 'question',\n * title: 'Confirm',\n * message: 'Are you sure you want to delete this file?',\n * buttons: ['Cancel', 'Delete'],\n * defaultButton: 0,\n * cancelButton: 0,\n * })\n *\n * if (result.response === 1) {\n * // User clicked \"Delete\"\n * }\n * ```\n */\nexport async function showMessageBox(options: MessageBoxOptions): Promise<MessageBoxResult> {\n if (isInCraftWindow()) {\n // Use Craft's native dialog\n const craftWindow = window as any\n try {\n return await craftWindow.craft.dialog.showMessageBox(options)\n }\n catch (error) {\n console.warn('[stx-dialog] Failed to show native message box:', error)\n }\n }\n\n // Web fallback\n const buttons = options.buttons || ['OK']\n\n if (buttons.length === 1) {\n // Simple alert\n alert(options.message)\n return { response: 0 }\n }\n\n if (buttons.length === 2 && options.type === 'question') {\n // Use confirm for simple yes/no\n const confirmed = confirm(options.message)\n return { response: confirmed ? 1 : 0 }\n }\n\n // For more complex dialogs, we'd need a custom modal\n // For now, fall back to confirm\n console.warn('[stx-dialog] Complex message box not fully supported in browser, using confirm')\n const confirmed = confirm(`${options.message}\\n\\n${buttons.join(' / ')}`)\n return { response: confirmed ? (buttons.length - 1) : 0 }\n}\n\n/**\n * Show a native color picker dialog\n *\n * @param options - Color picker options\n * @returns Promise resolving to selected color or cancellation\n *\n * @example\n * ```typescript\n * const result = await showColorPicker({\n * color: '#ff0000',\n * showAlpha: true,\n * })\n *\n * if (!result.canceled && result.color) {\n * document.body.style.backgroundColor = result.color\n * }\n * ```\n */\nexport async function showColorPicker(options: ColorPickerOptions = {}): Promise<ColorPickerResult> {\n if (isInCraftWindow()) {\n // Use Craft's native dialog\n const craftWindow = window as any\n try {\n return await craftWindow.craft.dialog.showColorPicker(options)\n }\n catch (error) {\n console.warn('[stx-dialog] Failed to show native color picker:', error)\n }\n }\n\n // Web fallback: use color input\n return new Promise((resolve) => {\n if (typeof document === 'undefined') {\n resolve({ canceled: true })\n return\n }\n\n const input = document.createElement('input')\n input.type = 'color'\n input.value = options.color || '#000000'\n\n input.onchange = () => {\n resolve({ canceled: false, color: input.value })\n }\n\n input.oncancel = () => {\n resolve({ canceled: true })\n }\n\n input.click()\n })\n}\n\n// =============================================================================\n// Convenience Functions\n// =============================================================================\n\n/**\n * Show a simple alert message dialog (native)\n *\n * @param message - Message to display\n * @param title - Optional dialog title\n */\nexport async function showAlertDialog(message: string, title?: string): Promise<void> {\n await showMessageBox({\n type: 'info',\n title: title || 'Alert',\n message,\n buttons: ['OK'],\n })\n}\n\n/**\n * Show a confirmation dialog (native)\n *\n * @param message - Message to display\n * @param title - Optional dialog title\n * @returns True if confirmed, false if cancelled\n */\nexport async function showConfirmDialog(message: string, title?: string): Promise<boolean> {\n const result = await showMessageBox({\n type: 'question',\n title: title || 'Confirm',\n message,\n buttons: ['Cancel', 'OK'],\n defaultButton: 1,\n cancelButton: 0,\n })\n return result.response === 1\n}\n\n/**\n * Show an error dialog (native)\n *\n * @param message - Error message\n * @param title - Optional dialog title\n */\nexport async function showErrorDialog(message: string, title?: string): Promise<void> {\n await showMessageBox({\n type: 'error',\n title: title || 'Error',\n message,\n buttons: ['OK'],\n })\n}\n\n/**\n * Show a warning dialog (native)\n *\n * @param message - Warning message\n * @param title - Optional dialog title\n */\nexport async function showWarningDialog(message: string, title?: string): Promise<void> {\n await showMessageBox({\n type: 'warning',\n title: title || 'Warning',\n message,\n buttons: ['OK'],\n })\n}\n\n// =============================================================================\n// Bridge Script Generator\n// =============================================================================\n\n/**\n * Generate a JavaScript snippet for dialog control from inside a webview.\n * This provides convenient wrappers around the Craft dialog bridge.\n */\nexport function getDialogBridgeScript(): string {\n return `\n// STX Desktop Dialog Bridge\n// Provides convenient wrappers around window.craft.dialog APIs\nwindow.stxDialog = {\n // File dialogs\n showOpenDialog: (options) => window.craft?.dialog?.showOpenDialog(options),\n showSaveDialog: (options) => window.craft?.dialog?.showSaveDialog(options),\n\n // Message dialogs\n showMessageBox: (options) => window.craft?.dialog?.showMessageBox(options),\n\n // Color picker\n showColorPicker: (options) => window.craft?.dialog?.showColorPicker(options),\n\n // Font picker\n showFontPicker: (options) => window.craft?.dialog?.showFontPicker(options),\n\n // Convenience functions\n alert: async (message, title) => {\n return window.craft?.dialog?.showMessageBox({\n type: 'info',\n title: title || 'Alert',\n message,\n buttons: ['OK'],\n });\n },\n\n confirm: async (message, title) => {\n const result = await window.craft?.dialog?.showMessageBox({\n type: 'question',\n title: title || 'Confirm',\n message,\n buttons: ['Cancel', 'OK'],\n });\n return result?.response === 1;\n },\n\n error: async (message, title) => {\n return window.craft?.dialog?.showMessageBox({\n type: 'error',\n title: title || 'Error',\n message,\n buttons: ['OK'],\n });\n },\n\n // Check if dialog is available\n isAvailable: () => typeof window.craft?.dialog !== 'undefined',\n};\n`\n}\n",
10
- "/* eslint-disable no-console */\nimport type { SidebarConfig, WindowInstance, WindowOptions } from './types'\nimport process from 'node:process'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { craftBinaryNotFoundMessage, resolveCraftBinary } from 'craft-native'\n\n// =============================================================================\n// Configuration\n// =============================================================================\n\n/**\n * Desktop window configuration.\n * Can be set via environment variables or setDesktopConfig().\n */\nexport interface DesktopConfig {\n /**\n * Custom path to craft binary.\n * Set via CRAFT_BINARY_PATH env var or setDesktopConfig().\n */\n craftBinaryPath?: string\n /**\n * Additional search paths for craft binary.\n * Searched after craftBinaryPath if set.\n */\n additionalSearchPaths?: string[]\n /**\n * Maximum retries when opening native window fails.\n * Default: 1 (no retries)\n */\n maxRetries?: number\n /**\n * Delay between retries in milliseconds.\n * Default: 1000\n */\n retryDelay?: number\n}\n\n/**\n * Current desktop configuration\n */\nlet currentConfig: DesktopConfig = {}\n\n/**\n * Configure desktop window settings\n *\n * @example\n * ```typescript\n * setDesktopConfig({\n * craftBinaryPath: '/custom/path/to/craft',\n * maxRetries: 3,\n * retryDelay: 2000\n * })\n * ```\n */\nexport function setDesktopConfig(config: Partial<DesktopConfig>): void {\n currentConfig = { ...currentConfig, ...config }\n}\n\n/**\n * Get current desktop configuration\n */\nexport function getDesktopConfig(): DesktopConfig {\n return { ...currentConfig }\n}\n\n/**\n * Reset desktop configuration to defaults\n */\nexport function resetDesktopConfig(): void {\n currentConfig = {}\n}\n\nfunction prepareSidebarConfig(options: WindowOptions): SidebarConfig | undefined {\n if (!options.sidebarConfig) return undefined\n\n const config: SidebarConfig = { ...options.sidebarConfig }\n if (config.variant === 'desktop') {\n config.material = config.material ?? 'sidebar'\n config.backgroundEffect = config.backgroundEffect ?? 'shimmer'\n config.allowsVibrancy = config.allowsVibrancy ?? true\n }\n\n return config\n}\n\n// =============================================================================\n// Binary Resolution\n// =============================================================================\n\n/**\n * Find the craft binary.\n *\n * Craft ships through the pantry registry, so the canonical answer is \"whatever\n * `craft` resolves to on PATH\" — `resolveCraftBinary` in craft-native owns that\n * contract, including the `CRAFT_BIN` escape hatch for local builds. This\n * function only layers on the overrides that are part of the desktop package's\n * own API, plus the one location craft cannot know about: inside a packaged app\n * bundle, where `packageApp` puts the binary next to the app's executable.\n *\n * Resolution order:\n * 1. `CRAFT_BINARY_PATH` environment variable\n * 2. `config.craftBinaryPath` (set via `setDesktopConfig`)\n * 3. `config.additionalSearchPaths`\n * 4. Beside the running executable (a packaged `.app`)\n * 5. `craft`'s own contract — `CRAFT_BIN`, else PATH\n *\n * @returns The string to spawn. Never undefined: a bare `'craft'` defers to PATH,\n * and an ENOENT from the spawn produces craft's pantry-aware guidance.\n */\nfunction getCraftBinaryPath(): string {\n const overrides = [\n process.env.CRAFT_BINARY_PATH,\n currentConfig.craftBinaryPath,\n ...(currentConfig.additionalSearchPaths || []),\n // A packaged app bundles craft into Contents/MacOS/ beside its own binary\n // (see packageApp's macos.additionalExecutables), so a shipped app resolves\n // its own copy rather than depending on the user having pantry.\n join(dirname(process.execPath), 'craft'),\n ]\n\n for (const candidate of overrides) {\n if (candidate && existsSync(candidate))\n return candidate\n }\n\n return resolveCraftBinary()\n}\n\n// =============================================================================\n// Window Instance Management\n// =============================================================================\n\n/**\n * Active window instances managed by this module\n */\nconst activeWindows = new Map<string, {\n app: any\n url: string\n options: WindowOptions\n}>()\n\n/**\n * Get all active window IDs\n */\nexport function getActiveWindowIds(): string[] {\n return Array.from(activeWindows.keys())\n}\n\n/**\n * Get a window by ID\n */\nexport function getWindow(id: string): WindowInstance | null {\n const windowData = activeWindows.get(id)\n if (!windowData) return null\n return createWindowInstance(id, windowData.app)\n}\n\n/**\n * Close all active windows\n */\nexport function closeAllWindows(): void {\n for (const [id, windowData] of activeWindows) {\n try {\n windowData.app?.close?.()\n }\n catch (e) {\n console.warn(`Failed to close window ${id}:`, e)\n }\n }\n activeWindows.clear()\n}\n\n/**\n * Create a WindowInstance object with control methods\n */\nfunction createWindowInstance(id: string, app: any): WindowInstance {\n return {\n id,\n\n show: () => {\n // The window is shown when created via app.show()\n // This is a no-op since craft-native auto-shows windows\n console.log(`[stx/desktop] Window ${id} shown`)\n },\n\n hide: () => {\n // craft-native doesn't expose hide directly from the process side\n // This would need to be called from inside the webview via window.craft.window.hide()\n console.log(`[stx/desktop] To hide window, use window.craft.window.hide() from inside the webview`)\n },\n\n close: () => {\n const windowData = activeWindows.get(id)\n if (windowData?.app) {\n windowData.app.close()\n activeWindows.delete(id)\n console.log(`[stx/desktop] Window ${id} closed`)\n }\n },\n\n focus: () => {\n console.log(`[stx/desktop] To focus window, use window.craft.window.focus() from inside the webview`)\n },\n\n minimize: () => {\n console.log(`[stx/desktop] To minimize window, use window.craft.window.minimize() from inside the webview`)\n },\n\n maximize: () => {\n console.log(`[stx/desktop] To maximize window, use window.craft.window.maximize() from inside the webview`)\n },\n\n restore: () => {\n console.log(`[stx/desktop] To restore window, use window.craft.window.show() from inside the webview`)\n },\n\n setTitle: (title: string) => {\n console.log(`[stx/desktop] To set title, use window.craft.window.setTitle({ title: \"${title}\" }) from inside the webview`)\n },\n\n loadURL: (url: string) => {\n // Re-create the window with the new URL\n console.log(`[stx/desktop] To navigate, use window.location.href = \"${url}\" from inside the webview`)\n },\n\n reload: () => {\n console.log(`[stx/desktop] To reload, use window.craft.window.reload() from inside the webview`)\n },\n }\n}\n\n// =============================================================================\n// Window Creation\n// =============================================================================\n\n/**\n * Translate window options into Craft binary arguments.\n *\n * craft-native is a thin wrapper around this command line, so the same options\n * describe a window whether the JS package is installed or not.\n */\nexport function craftWindowArguments(url: string, options: WindowOptions = {}): string[] {\n const args = [\n '--url', url,\n '--title', options.title || 'stx Desktop',\n '--width', String(options.width ?? 1200),\n '--height', String(options.height ?? 800),\n ]\n\n if (options.darkMode) args.push('--dark')\n if (options.hotReload) args.push('--hot-reload')\n if (options.resizable === false) args.push('--no-resize')\n if (options.frameless) args.push('--frameless')\n if (options.alwaysOnTop) args.push('--always-on-top')\n if (options.titlebarHidden) args.push('--titlebar-hidden')\n if (options.systemTray) args.push('--system-tray')\n if (options.hideDockIcon) args.push('--hide-dock-icon')\n if (options.devTools === false) args.push('--no-devtools')\n if (options.nativeSidebar) args.push('--native-sidebar')\n if (options.sidebarWidth !== undefined) args.push('--sidebar-width', String(options.sidebarWidth))\n\n const sidebarConfig = prepareSidebarConfig(options)\n if (sidebarConfig) args.push('--sidebar-config', JSON.stringify(sidebarConfig))\n\n return args\n}\n\n/**\n * Create a native window with URL\n *\n * Prefers the craft-native package for its richer typings, and falls back to\n * spawning the Craft binary directly when it isn't installed — the binary is\n * what craft-native drives anyway, so an app needs only one of the two.\n *\n * ## Window Control\n *\n * The CraftApp spawns a native webview process. Window control methods like\n * hide(), minimize(), setTitle() etc. are available via the `window.craft`\n * bridge **inside** the webview context:\n *\n * ```javascript\n * // Inside your HTML/JS running in the webview:\n * window.craft.window.hide()\n * window.craft.window.minimize()\n * window.craft.window.setTitle({ title: 'New Title' })\n * window.craft.window.center()\n * ```\n *\n * The returned WindowInstance provides the `close()` method which terminates\n * the native process from the Node.js side.\n *\n * @param url - URL to load in the window\n * @param options - Window configuration options\n * @returns WindowInstance if successful, null if no Craft runtime is available\n */\nexport async function createWindow(url: string, options: WindowOptions = {}): Promise<WindowInstance | null> {\n const id = `craft-window-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n const craftPath = getCraftBinaryPath()\n\n try {\n const { createApp } = await import('craft-native')\n\n const app = createApp({\n url,\n craftPath,\n // craft-native's WindowOptions doesn't type every field the binary honors\n // (titlebarHidden, hideDockIcon, sidebar config), so cast to its own\n // window type to pass them through.\n window: {\n title: options.title || 'stx Desktop',\n width: options.width ?? 1200,\n height: options.height ?? 800,\n darkMode: options.darkMode ?? false,\n hotReload: options.hotReload ?? false,\n resizable: options.resizable ?? true,\n frameless: options.frameless ?? false,\n alwaysOnTop: options.alwaysOnTop ?? false,\n titlebarHidden: options.titlebarHidden ?? false,\n systemTray: options.systemTray ?? false,\n hideDockIcon: options.hideDockIcon ?? false,\n devTools: options.devTools ?? false,\n nativeSidebar: options.nativeSidebar ?? false,\n sidebarWidth: options.sidebarWidth,\n sidebarConfig: prepareSidebarConfig(options) as Record<string, unknown> | undefined,\n } as NonNullable<Parameters<typeof createApp>[0]>['window'],\n })\n\n activeWindows.set(id, { app, url, options })\n await app.show()\n\n return createWindowInstance(id, app)\n }\n catch {\n // createApp couldn't drive the window (most often the binary isn't\n // installed). Spawn it ourselves — craft-native is a thin wrapper over this\n // same command line — and let an ENOENT report craft's pantry-aware guidance\n // rather than a bare spawn error.\n try {\n const { spawn } = await import('node:child_process')\n const child = spawn(craftPath, craftWindowArguments(url, options), { stdio: 'inherit' })\n child.on('error', (err: NodeJS.ErrnoException) => {\n console.error(err.code === 'ENOENT' ? craftBinaryNotFoundMessage(craftPath) : `craft child error: ${err.message}`)\n })\n\n const app = { close: () => child.kill() }\n activeWindows.set(id, { app, url, options })\n\n return createWindowInstance(id, app)\n }\n catch (binaryError) {\n console.error('Failed to spawn craft binary:', (binaryError as Error).message)\n return null\n }\n }\n}\n\n/**\n * Open a development server window\n * This is specifically for the stx dev server --native flag\n *\n * Uses craft-native to create a native window, falls back to browser if unavailable.\n */\nexport async function openDevWindow(port: number, options: WindowOptions = {}): Promise<boolean> {\n const url = `http://localhost:${port}/`\n\n // Bail out of native paths under bun:test to avoid spawning real\n // webview processes from unit tests. Tests assert that the function\n // returns false in this environment.\n const isTestEnv = process.env.NODE_ENV === 'test' || process.env.BUN_TEST\n if (isTestEnv) {\n console.warn('⚠ Skipping native window in test environment')\n console.log('(Skipping browser fallback in test environment)')\n return false\n }\n\n // Path 1 — `craft-native` package, when it's actually installed in the host\n // workspace. This is the original path; we keep it for projects that\n // depend on `craft-native` for richer typings / sidebar config.\n try {\n const { createApp } = await import('craft-native')\n\n console.log('⚡ Opening native window via craft-native…')\n const useSystemTray = !options.nativeSidebar\n const sidebarConfig = prepareSidebarConfig(options)\n const app = createApp({\n url,\n craftPath: getCraftBinaryPath(),\n // craft-native's WindowOptions doesn't type `titlebarHidden` yet, but the\n // Craft binary honors it (see the `--titlebar-hidden` arg on the binary\n // fallback path below). Cast to craft-native's own window type so this\n // forward-compat field passes through without a fresh-literal excess error.\n window: {\n title: options.title || 'stx Development',\n width: options.width || 1400,\n height: options.height || 900,\n resizable: true,\n systemTray: useSystemTray,\n darkMode: options.darkMode ?? true,\n hotReload: options.hotReload ?? true,\n devTools: true,\n titlebarHidden: options.titlebarHidden ?? false,\n nativeSidebar: options.nativeSidebar ?? false,\n sidebarWidth: options.sidebarWidth ?? 260,\n sidebarConfig: sidebarConfig as Record<string, unknown> | undefined,\n } as NonNullable<Parameters<typeof createApp>[0]>['window'],\n })\n\n const id = `dev-window-${port}`\n activeWindows.set(id, { app, url, options })\n await app.show()\n console.log(`✓ Native window opened at ${url}`)\n return true\n }\n catch {\n // Path 2 — spawn the binary directly. craft-native is a thin wrapper over\n // this same command line, so a machine with craft installed but no JS\n // package still gets a native window.\n const craftPath = getCraftBinaryPath()\n try {\n console.log(`⚡ Opening native window via craft binary (${craftPath})…`)\n const { spawn } = await import('node:child_process')\n const child = spawn(craftPath, craftWindowArguments(url, {\n title: 'stx Development',\n width: 1400,\n height: 900,\n // Hot reload is the point of a dev window, so it defaults on here.\n hotReload: true,\n ...options,\n }), { stdio: 'inherit' })\n\n // Bridge the child's lifetime to the host process so closing the\n // window cleanly exits the dev server (matches `bun --bun … --native`\n // expectations).\n child.on('exit', () => process.exit(0))\n child.on('error', (err: NodeJS.ErrnoException) => {\n console.warn(err.code === 'ENOENT' ? craftBinaryNotFoundMessage(craftPath) : `craft child error: ${err.message}`)\n })\n\n const id = `dev-window-${port}`\n activeWindows.set(id, { app: { close: () => child.kill() }, url, options })\n console.log(`✓ Native window opened at ${url}`)\n return true\n }\n catch (binaryErr) {\n console.warn('⚠ Could not spawn craft binary:', (binaryErr as Error).message)\n }\n\n // Path 3 — give up on native, open the system browser. Skipped in test.\n if (process.env.NODE_ENV === 'test' || process.env.BUN_TEST) {\n console.log('(Skipping browser fallback in test environment)')\n return false\n }\n console.log('📱 Opening in browser instead…')\n try {\n const { spawn } = await import('node:child_process')\n const platform = process.platform\n const command = platform === 'darwin' ? 'open' : platform === 'win32' ? 'cmd' : 'xdg-open'\n const args = platform === 'win32' ? ['/c', 'start', url] : [url]\n spawn(command, args, { detached: true, stdio: 'ignore' }).unref()\n console.log(`✓ Browser opened at ${url}`)\n return true\n }\n catch (browserError) {\n console.error('Could not open browser:', browserError)\n console.log(`Please open manually: ${url}`)\n return false\n }\n }\n}\n\n/**\n * Create a window with HTML content\n *\n * Uses craft-native to display HTML content in a native window.\n */\nexport async function createWindowWithHTML(html: string, options: WindowOptions = {}): Promise<WindowInstance | null> {\n const {\n title = 'stx Desktop',\n width = 1200,\n height = 800,\n darkMode = false,\n hotReload = false,\n resizable = true,\n frameless = false,\n alwaysOnTop = false,\n } = options\n\n try {\n // Dynamically import craft-native\n const { createApp } = await import('craft-native')\n\n const craftPath = getCraftBinaryPath()\n\n const app = createApp({\n html,\n craftPath,\n window: {\n title,\n width,\n height,\n darkMode,\n hotReload,\n resizable,\n frameless,\n alwaysOnTop,\n },\n })\n\n const id = `craft-window-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n activeWindows.set(id, { app, url: 'html-content', options })\n\n await app.show()\n\n return createWindowInstance(id, app)\n }\n catch (error) {\n console.error('Failed to create window with HTML:', error)\n return null\n }\n}\n\n/**\n * Helper to check if webview implementation is available\n */\nexport function isWebviewAvailable(): boolean {\n try {\n // Try to require craft-native to check if it's available\n require.resolve('craft-native')\n return true\n }\n catch {\n return false\n }\n}\n\n// =============================================================================\n// Bridge Script Generator\n// =============================================================================\n\n/**\n * Generate a JavaScript snippet to inject into HTML that provides\n * helper functions for common window operations.\n *\n * This can be injected into your HTML to provide easier access to Craft APIs.\n *\n * @example\n * ```typescript\n * const html = `\n * <html>\n * <head>\n * <script>${getWindowBridgeScript()}</script>\n * </head>\n * <body>\n * <button onclick=\"stxWindow.minimize()\">Minimize</button>\n * </body>\n * </html>\n * `\n * await createWindowWithHTML(html)\n * ```\n */\nexport function getWindowBridgeScript(): string {\n return `\n// STX Desktop Window Bridge\n// Provides convenient wrappers around window.craft APIs\nwindow.stxWindow = {\n // Window control\n hide: () => window.craft?.window?.hide(),\n show: () => window.craft?.window?.show(),\n toggle: () => window.craft?.window?.toggle(),\n close: () => window.craft?.window?.close(),\n minimize: () => window.craft?.window?.minimize(),\n maximize: () => window.craft?.window?.maximize(),\n focus: () => window.craft?.window?.focus(),\n center: () => window.craft?.window?.center(),\n reload: () => window.craft?.window?.reload(),\n toggleFullscreen: () => window.craft?.window?.toggleFullscreen(),\n\n // Window properties\n setTitle: (title) => window.craft?.window?.setTitle({ title }),\n setSize: (width, height) => window.craft?.window?.setSize({ width, height }),\n setPosition: (x, y) => window.craft?.window?.setPosition({ x, y }),\n setAlwaysOnTop: (alwaysOnTop) => window.craft?.window?.setAlwaysOnTop({ alwaysOnTop }),\n setResizable: (resizable) => window.craft?.window?.setResizable({ resizable }),\n setOpacity: (opacity) => window.craft?.window?.setOpacity({ opacity }),\n\n // macOS-specific\n setVibrancy: (vibrancy) => window.craft?.window?.setVibrancy({ vibrancy }),\n\n // App control\n quit: () => window.craft?.app?.quit(),\n isDarkMode: () => window.craft?.app?.isDarkMode(),\n getLocale: () => window.craft?.app?.getLocale(),\n\n // Notifications\n notify: (options) => window.craft?.app?.notify(options),\n\n // Check if running in Craft\n isCraftAvailable: () => typeof window.craft !== 'undefined',\n};\n\n// Expose as global for backwards compatibility\nwindow.desktop = window.stxWindow;\n`\n}\n",
11
- "/**\n * Packaging and code signing.\n *\n * Craft owns the native side of this — building the `.app`, the DMG, the MSI,\n * the Linux packages, and the signed `.pkg` the Mac App Store accepts. This\n * module re-exports it so an app reaches packaging through the same import as\n * the rest of the desktop API, rather than depending on Craft directly.\n *\n * @example\n * ```typescript\n * import { packageApp } from '@stacksjs/stx/desktop'\n *\n * await packageApp({\n * name: 'Barista',\n * version: '0.1.0',\n * binaryPath: './dist/barista',\n * bundleId: 'org.stacksjs.barista',\n * macos: { menuBarOnly: true, dmg: true },\n * })\n * ```\n */\nexport { pack, packageApp } from 'craft-native'\n\nexport type { PackageConfig, PackageResult } from 'craft-native'\n\n/**\n * Craft's binary resolution contract — PATH (craft installs via pantry), with\n * `CRAFT_BIN` for local builds. Re-exported so a build script bundling the\n * runtime into its app finds the same binary the window layer will spawn.\n */\nexport { craftBinaryNotFoundMessage, resolveCraftBinary } from 'craft-native'\n",
12
- "/**\n * Self-updating apps.\n *\n * Craft owns the mechanics — fetch a manifest, verify the download by SHA-256\n * (and signature when one is configured), swap the app bundle. This module\n * re-exports that and adds the piece every app repeats: pointing it at GitHub\n * Releases.\n *\n * @example\n * ```typescript\n * import { createGitHubUpdater } from '@stacksjs/stx/desktop'\n *\n * const updater = createGitHubUpdater({\n * repository: 'stacksjs/barista',\n * currentVersion: '0.1.0',\n * appPath: '/Applications/Barista.app',\n * })\n *\n * const update = await updater.checkForUpdates()\n * ```\n */\nimport type { UpdateManifest, UpdaterConfig } from 'craft-native'\nimport { AutoUpdater, generateUpdateManifest } from 'craft-native'\n\nexport { AutoUpdater, generateUpdateManifest }\nexport type { PlatformUpdate, UpdateManifest, UpdaterConfig, UpdaterEvent, UpdateProgress } from 'craft-native'\n\n/** Manifest asset name an app publishes alongside its release artifacts. */\nexport const UPDATE_MANIFEST_ASSET = 'update.json'\n\nexport interface GitHubUpdaterOptions extends Omit<UpdaterConfig, 'updateUrl'> {\n /** `owner/repo`, e.g. `stacksjs/barista` */\n repository: string\n /**\n * Manifest asset name in the release. Defaults to `update.json`.\n * Must match what the build attached.\n */\n manifestAsset?: string\n}\n\n/**\n * URL of an asset on the repository's newest release.\n *\n * GitHub resolves `releases/latest/download/<asset>` to whichever release is\n * currently latest, so this stays correct without the app knowing any version.\n */\nexport function githubLatestAssetUrl(repository: string, asset: string): string {\n return `https://github.com/${repository}/releases/latest/download/${asset}`\n}\n\n/**\n * URL of an asset on a specific release tag. Used when building a manifest,\n * where the download has to point at the version being released rather than\n * at whatever is latest.\n */\nexport function githubReleaseAssetUrl(repository: string, tag: string, asset: string): string {\n return `https://github.com/${repository}/releases/download/${tag}/${asset}`\n}\n\n/** Point Craft's updater at a repository's latest GitHub release. */\nexport function createGitHubUpdater(options: GitHubUpdaterOptions): AutoUpdater {\n const { repository, manifestAsset = UPDATE_MANIFEST_ASSET, ...config } = options\n\n return new AutoUpdater({\n ...config,\n updateUrl: githubLatestAssetUrl(repository, manifestAsset),\n })\n}\n\nexport interface GitHubManifestOptions {\n /** `owner/repo` the release lives in */\n repository: string\n /** Version being released, without a leading `v` */\n version: string\n /** Release tag the assets are attached to. Defaults to `v<version>`. */\n tag?: string\n releaseNotes?: string\n /** Downloadable artifact per platform, as a local path */\n artifacts: {\n darwin?: string\n win32?: string\n linux?: string\n }\n}\n\n/**\n * Build the manifest for a GitHub release, hashing each artifact and pointing\n * its URL at the release's own tag.\n */\nexport function createGitHubUpdateManifest(options: GitHubManifestOptions): UpdateManifest {\n const tag = options.tag ?? `v${options.version}`\n const platforms: Record<string, { path: string, url: string }> = {}\n\n for (const [platform, path] of Object.entries(options.artifacts)) {\n if (!path)\n continue\n platforms[platform] = {\n path,\n url: githubReleaseAssetUrl(options.repository, tag, path.split('/').pop()!),\n }\n }\n\n return generateUpdateManifest({\n version: options.version,\n releaseNotes: options.releaseNotes,\n platforms,\n })\n}\n",
13
- "/**\n * Power Management API\n *\n * Provides control over system sleep behavior using macOS caffeinate.\n * Spawns and manages /usr/bin/caffeinate processes.\n *\n * @example\n * ```typescript\n * import { caffeinate, decaffeinate, isCaffeinated, getCaffeinateStatus } from '@stacksjs/desktop'\n *\n * // Prevent sleep indefinitely\n * const instance = caffeinate()\n *\n * // Prevent sleep for 30 minutes\n * const instance = caffeinate({ duration: 30 })\n *\n * // Prevent only display sleep for 1 hour\n * const instance = caffeinate({\n * duration: 60,\n * preventDisplaySleep: true,\n * preventIdleSleep: false,\n * preventSystemSleep: false,\n * })\n *\n * // Check status\n * console.log(isCaffeinated()) // true\n * console.log(getCaffeinateStatus())\n *\n * // Stop\n * decaffeinate()\n * ```\n */\nimport type { Subprocess } from 'bun'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CaffeinateOptions {\n /** Duration in minutes. -1 or undefined = indefinite */\n duration?: number\n /** Prevent display from sleeping (-d flag). Default: true */\n preventDisplaySleep?: boolean\n /** Prevent system from idle sleeping (-i flag). Default: true */\n preventIdleSleep?: boolean\n /** Prevent system from sleeping (-s flag). Default: true */\n preventSystemSleep?: boolean\n /** Prevent disk from sleeping (-m flag). Default: false */\n preventDiskSleep?: boolean\n /** Create an assertion to prevent sleep on behalf of user (-u flag). Default: true */\n assertUserActivity?: boolean\n}\n\nexport interface CaffeinateInstance {\n /** Process ID of the caffeinate process */\n readonly pid: number\n /** When caffeinate was started */\n readonly startedAt: Date\n /** When caffeinate will end (null = indefinite) */\n readonly endsAt: Date | null\n /** Options used to create this instance */\n readonly options: CaffeinateOptions\n /** Whether this instance is still active */\n readonly isActive: boolean\n /** Remaining milliseconds (null = indefinite, 0 = expired) */\n readonly remainingMs: number | null\n /** Elapsed milliseconds since start */\n readonly elapsedMs: number\n /** Stop this caffeinate instance */\n stop(): void\n /** Register a callback for when this instance expires (duration-based only) */\n onExpire(handler: () => void): void\n}\n\nexport interface CaffeinateStatus {\n /** Whether caffeinate is currently active */\n active: boolean\n /** The current caffeinate instance, if any */\n instance: CaffeinateInstance | null\n /** When the current session started */\n startedAt: Date | null\n /** When the current session will end */\n endsAt: Date | null\n /** Duration in minutes (-1 = indefinite, null = not active) */\n durationMinutes: number | null\n}\n\n// ============================================================================\n// Internal State\n// ============================================================================\n\nlet currentProcess: Subprocess | null = null\nlet currentInstance: CaffeinateInstanceImpl | null = null\n\nclass CaffeinateInstanceImpl implements CaffeinateInstance {\n private _process: Subprocess\n private _startedAt: Date\n private _endsAt: Date | null\n private _options: CaffeinateOptions\n private _expireHandlers: Array<() => void> = []\n private _expireTimer: ReturnType<typeof setTimeout> | null = null\n private _stopped = false\n\n constructor(process: Subprocess, options: CaffeinateOptions) {\n this._process = process\n this._options = options\n this._startedAt = new Date()\n\n const duration = options.duration\n if (duration && duration > 0) {\n const durationMs = duration * 60 * 1000\n this._endsAt = new Date(this._startedAt.getTime() + durationMs)\n\n this._expireTimer = setTimeout(() => {\n this._stopped = true\n for (const handler of this._expireHandlers) {\n try {\n handler()\n }\n catch {}\n }\n }, durationMs)\n }\n else {\n this._endsAt = null\n }\n }\n\n get pid(): number {\n return this._process.pid\n }\n\n get startedAt(): Date {\n return this._startedAt\n }\n\n get endsAt(): Date | null {\n return this._endsAt\n }\n\n get options(): CaffeinateOptions {\n return { ...this._options }\n }\n\n get isActive(): boolean {\n if (this._stopped)\n return false\n // Check if process is still running\n return this._process.exitCode === null\n }\n\n get remainingMs(): number | null {\n if (!this._endsAt)\n return null\n const remaining = this._endsAt.getTime() - Date.now()\n return Math.max(0, remaining)\n }\n\n get elapsedMs(): number {\n return Date.now() - this._startedAt.getTime()\n }\n\n stop(): void {\n if (this._stopped)\n return\n this._stopped = true\n\n if (this._expireTimer) {\n clearTimeout(this._expireTimer)\n this._expireTimer = null\n }\n\n try {\n this._process.kill()\n }\n catch {\n // Process may have already exited\n }\n }\n\n onExpire(handler: () => void): void {\n this._expireHandlers.push(handler)\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Start preventing the system from sleeping.\n *\n * Spawns a `/usr/bin/caffeinate` process with the specified options.\n * If caffeinate is already active, the previous instance is stopped first.\n *\n * @param options - Caffeinate configuration\n * @returns A CaffeinateInstance for monitoring and controlling the session\n */\nexport function caffeinate(options: CaffeinateOptions = {}): CaffeinateInstance {\n // Stop any existing instance\n decaffeinate()\n\n const {\n duration,\n preventDisplaySleep = true,\n preventIdleSleep = true,\n preventSystemSleep = true,\n preventDiskSleep = false,\n assertUserActivity = true,\n } = options\n\n // Build flags\n const flags: string[] = []\n if (preventDisplaySleep)\n flags.push('-d')\n if (preventIdleSleep)\n flags.push('-i')\n if (preventSystemSleep)\n flags.push('-s')\n if (preventDiskSleep)\n flags.push('-m')\n if (assertUserActivity)\n flags.push('-u')\n\n // Build args\n const args: string[] = [...flags]\n\n // Add duration if specified (in seconds)\n if (duration && duration > 0) {\n args.push('-t', String(duration * 60))\n }\n\n // Spawn caffeinate\n const proc = Bun.spawn(['/usr/bin/caffeinate', ...args], {\n stdio: ['ignore', 'ignore', 'ignore'],\n })\n\n const instance = new CaffeinateInstanceImpl(proc, options)\n currentProcess = proc\n currentInstance = instance\n\n return instance\n}\n\n/**\n * Stop caffeinate and allow the system to sleep normally.\n *\n * @param instance - Specific instance to stop. If omitted, stops the current active instance.\n */\nexport function decaffeinate(instance?: CaffeinateInstance): void {\n if (instance) {\n instance.stop()\n if (currentInstance === instance) {\n currentProcess = null\n currentInstance = null\n }\n return\n }\n\n if (currentInstance) {\n currentInstance.stop()\n }\n currentProcess = null\n currentInstance = null\n}\n\n/**\n * Check if caffeinate is currently active.\n */\nexport function isCaffeinated(): boolean {\n return currentInstance !== null && currentInstance.isActive\n}\n\n/**\n * Get the current caffeinate status.\n */\nexport function getCaffeinateStatus(): CaffeinateStatus {\n if (!currentInstance || !currentInstance.isActive) {\n return {\n active: false,\n instance: null,\n startedAt: null,\n endsAt: null,\n durationMinutes: null,\n }\n }\n\n const opts = currentInstance.options\n const duration = opts.duration\n\n return {\n active: true,\n instance: currentInstance,\n startedAt: currentInstance.startedAt,\n endsAt: currentInstance.endsAt,\n durationMinutes: (duration && duration > 0) ? duration : -1,\n }\n}\n\n/**\n * Format remaining caffeinate time as a human-readable string.\n *\n * @example\n * ```typescript\n * formatRemainingTime(instance) // \"25:30\" or \"∞\"\n * ```\n */\nexport function formatRemainingTime(instance?: CaffeinateInstance | null): string {\n const inst = instance || currentInstance\n if (!inst || !inst.isActive)\n return '0:00'\n\n const remaining = inst.remainingMs\n if (remaining === null)\n return '∞'\n\n const totalSeconds = Math.ceil(remaining / 1000)\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0)\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`\n return `${minutes}:${String(seconds).padStart(2, '0')}`\n}\n\n/**\n * Get a formatted description of the caffeinate duration.\n */\nexport function formatDuration(minutes: number): string {\n if (minutes <= 0 || minutes === -1)\n return 'Indefinitely'\n if (minutes < 60)\n return `${minutes} minutes`\n if (minutes === 60)\n return '1 hour'\n if (minutes % 60 === 0)\n return `${minutes / 60} hours`\n const h = Math.floor(minutes / 60)\n const m = minutes % 60\n return `${h}h ${m}m`\n}\n",
14
- "/**\n * Preferences / Settings Storage API\n *\n * Simple JSON-based preferences storage for desktop applications.\n * Stores data in platform-appropriate locations with file watching\n * and change notification support.\n *\n * @example\n * ```typescript\n * import { createPreferences } from '@stacksjs/desktop'\n *\n * const prefs = createPreferences({\n * name: 'my-app',\n * defaults: {\n * theme: 'dark',\n * fontSize: 14,\n * autoSave: true,\n * },\n * })\n *\n * // Get a value\n * const theme = prefs.get('theme') // 'dark'\n *\n * // Set a value\n * prefs.set('theme', 'light')\n *\n * // Listen for changes\n * prefs.onChange('theme', (newVal, oldVal) => {\n * console.log(`Theme changed from ${oldVal} to ${newVal}`)\n * })\n *\n * // Get all values\n * const all = prefs.getAll()\n *\n * // Reset to defaults\n * prefs.reset()\n * ```\n */\nimport { existsSync, mkdirSync, readFileSync, watch, writeFileSync } from 'node:fs'\nimport { homedir, platform } from 'node:os'\nimport { dirname, join } from 'node:path'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PreferencesOptions<T extends Record<string, unknown>> {\n /** Application name (used for file path) */\n name: string\n /** Default preference values */\n defaults: T\n /** Custom storage path (overrides platform default) */\n path?: string\n /** Watch for external file changes. Default: true */\n watch?: boolean\n}\n\nexport interface Preferences<T extends Record<string, unknown>> {\n /** Get a preference value */\n get<K extends keyof T>(key: K): T[K]\n /** Set a preference value */\n set<K extends keyof T>(key: K, value: T[K]): void\n /** Get all preference values */\n getAll(): T\n /** Check if a preference has been set (non-default) */\n has(key: keyof T): boolean\n /** Delete a preference (revert to default) */\n delete(key: keyof T): void\n /** Reset all preferences to defaults */\n reset(): void\n /** Listen for changes to a specific preference */\n onChange<K extends keyof T>(key: K, handler: (value: T[K], oldValue: T[K]) => void): () => void\n /** Listen for any preference change */\n onAnyChange(handler: (key: keyof T, value: unknown, oldValue: unknown) => void): () => void\n /** The file path where preferences are stored */\n readonly path: string\n /** Close the preferences (stop file watching) */\n close(): void\n}\n\n// eslint-disable-next-line pickier/no-unused-vars\ntype ChangeHandler = (key: string, value: unknown, oldValue: unknown) => void\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getDefaultPrefsDir(appName: string): string {\n const os = platform()\n const home = homedir()\n\n switch (os) {\n case 'darwin':\n return join(home, 'Library', 'Application Support', appName)\n case 'win32':\n return join(process.env.APPDATA || join(home, 'AppData', 'Roaming'), appName)\n default:\n return join(home, '.config', appName)\n }\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\nclass PreferencesImpl<T extends Record<string, unknown>> implements Preferences<T> {\n private _defaults: T\n private _data: Record<string, unknown>\n private _path: string\n private _changeHandlers: Map<string, Set<(value: unknown, oldValue: unknown) => void>> = new Map()\n private _anyChangeHandlers: Set<ChangeHandler> = new Set()\n private _watcher: ReturnType<typeof watch> | null = null\n private _writeTimer: ReturnType<typeof setTimeout> | null = null\n private _writing = false\n\n constructor(options: PreferencesOptions<T>) {\n this._defaults = { ...options.defaults }\n\n const dir = options.path\n ? dirname(options.path)\n : getDefaultPrefsDir(options.name)\n\n this._path = options.path || join(dir, 'preferences.json')\n\n // Ensure directory exists\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n // Load existing preferences or create with defaults\n this._data = this._load()\n\n // Set up file watcher\n if (options.watch !== false) {\n this._setupWatcher()\n }\n }\n\n get path(): string {\n return this._path\n }\n\n get<K extends keyof T>(key: K): T[K] {\n if (key in this._data) {\n return this._data[key as string] as T[K]\n }\n return this._defaults[key]\n }\n\n set<K extends keyof T>(key: K, value: T[K]): void {\n const oldValue = this.get(key)\n if (JSON.stringify(oldValue) === JSON.stringify(value))\n return\n\n this._data[key as string] = value\n this._scheduleSave()\n this._notifyChange(key as string, value, oldValue)\n }\n\n getAll(): T {\n return { ...this._defaults, ...this._data } as T\n }\n\n has(key: keyof T): boolean {\n return key in this._data\n }\n\n delete(key: keyof T): void {\n if (!(key in this._data))\n return\n const oldValue = this._data[key as string]\n delete this._data[key as string]\n this._scheduleSave()\n this._notifyChange(key as string, this._defaults[key], oldValue)\n }\n\n reset(): void {\n const oldData = { ...this._data }\n this._data = {}\n this._save()\n\n // Notify all changed keys\n for (const key of Object.keys(oldData)) {\n const defaultVal = (this._defaults as Record<string, unknown>)[key]\n this._notifyChange(key, defaultVal, oldData[key])\n }\n }\n\n onChange<K extends keyof T>(key: K, handler: (value: T[K], oldValue: T[K]) => void): () => void {\n const keyStr = key as string\n if (!this._changeHandlers.has(keyStr)) {\n this._changeHandlers.set(keyStr, new Set())\n }\n // eslint-disable-next-line pickier/no-unused-vars\n this._changeHandlers.get(keyStr)!.add(handler as (value: unknown, oldValue: unknown) => void)\n\n return () => {\n // eslint-disable-next-line pickier/no-unused-vars\n this._changeHandlers.get(keyStr)?.delete(handler as (value: unknown, oldValue: unknown) => void)\n }\n }\n\n onAnyChange(handler: ChangeHandler): () => void {\n this._anyChangeHandlers.add(handler)\n return () => {\n this._anyChangeHandlers.delete(handler)\n }\n }\n\n close(): void {\n if (this._watcher) {\n this._watcher.close()\n this._watcher = null\n }\n if (this._writeTimer) {\n clearTimeout(this._writeTimer)\n this._writeTimer = null\n // Flush pending writes\n this._save()\n }\n }\n\n // --------------------------------------------------------------------------\n // Private\n // --------------------------------------------------------------------------\n\n private _load(): Record<string, unknown> {\n try {\n if (existsSync(this._path)) {\n const content = readFileSync(this._path, 'utf-8')\n return JSON.parse(content)\n }\n }\n catch {\n // File doesn't exist or is corrupt, start fresh\n }\n return {}\n }\n\n private _save(): void {\n this._writing = true\n try {\n const json = JSON.stringify({ ...this._defaults, ...this._data }, null, 2)\n writeFileSync(this._path, json, 'utf-8')\n }\n catch (err) {\n console.error(`Failed to save preferences to ${this._path}:`, err)\n }\n finally {\n // Small delay before re-enabling watcher to avoid self-trigger\n setTimeout(() => {\n this._writing = false\n }, 100)\n }\n }\n\n private _scheduleSave(): void {\n if (this._writeTimer) {\n clearTimeout(this._writeTimer)\n }\n // Debounce writes by 50ms\n this._writeTimer = setTimeout(() => {\n this._writeTimer = null\n this._save()\n }, 50)\n }\n\n private _setupWatcher(): void {\n try {\n if (!existsSync(this._path)) {\n // Create the file first so we can watch it\n this._save()\n }\n\n this._watcher = watch(this._path, () => {\n if (this._writing)\n return\n\n // Reload and diff\n const newData = this._load()\n const oldData = { ...this._data }\n this._data = newData\n\n // Find changed keys\n const allKeys = new Set([...Object.keys(oldData), ...Object.keys(newData)])\n for (const key of allKeys) {\n const oldVal = key in oldData ? oldData[key] : (this._defaults as Record<string, unknown>)[key]\n const newVal = key in newData ? newData[key] : (this._defaults as Record<string, unknown>)[key]\n if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {\n this._notifyChange(key, newVal, oldVal)\n }\n }\n })\n }\n catch {\n // Watcher setup failed, preferences still work without watching\n }\n }\n\n private _notifyChange(key: string, value: unknown, oldValue: unknown): void {\n // Key-specific handlers\n const handlers = this._changeHandlers.get(key)\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(value, oldValue)\n }\n catch {}\n }\n }\n\n // Any-change handlers\n for (const handler of this._anyChangeHandlers) {\n try {\n handler(key, value, oldValue)\n }\n catch {}\n }\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Create a preferences store for your application.\n *\n * Preferences are stored as JSON in a platform-appropriate location:\n * - macOS: ~/Library/Application Support/{name}/preferences.json\n * - Windows: %APPDATA%/{name}/preferences.json\n * - Linux: ~/.config/{name}/preferences.json\n */\nexport function createPreferences<T extends Record<string, unknown>>(\n options: PreferencesOptions<T>,\n): Preferences<T> {\n return new PreferencesImpl(options)\n}\n",
15
- "/**\n * Auto-Launch / Login Items (subprocess-based)\n *\n * Manages auto-start by writing platform-specific config files:\n * - macOS: LaunchAgents plist files\n * - Linux: XDG autostart .desktop files\n * - Windows: Registry entries\n *\n * **Choosing between this and `nativeAutoLaunch`:** prefer\n * `nativeAutoLaunch` when running inside a Craft window — it uses\n * `SMAppService` (the modern Apple-recommended API) and doesn't write\n * any files of its own. This module exists for environments without a\n * Craft bridge, or apps that need the LaunchAgent file as a side\n * effect (some launchers honour those even when SMAppService doesn't).\n *\n * @example\n * ```typescript\n * import { setAutoLaunch, isAutoLaunchEnabled } from '@stacksjs/desktop'\n *\n * // Enable auto-launch\n * await setAutoLaunch(true, { appName: 'Barista' })\n *\n * // Check status\n * const enabled = await isAutoLaunchEnabled('Barista')\n *\n * // Disable\n * await setAutoLaunch(false, { appName: 'Barista' })\n * ```\n */\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir, platform } from 'node:os'\nimport { join } from 'node:path'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AutoLaunchOptions {\n /** Application name for the login item */\n appName?: string\n /** Path to the application executable. Defaults to process.execPath */\n appPath?: string\n /** Arguments to pass when launching */\n args?: string[]\n /** Start the app hidden/minimized */\n isHidden?: boolean\n}\n\n// ============================================================================\n// Platform Implementations\n// ============================================================================\n\nfunction getLaunchAgentPath(appName: string): string {\n const identifier = appName.toLowerCase().replace(/[^a-z0-9]/g, '-')\n return join(homedir(), 'Library', 'LaunchAgents', `com.${identifier}.plist`)\n}\n\nfunction getLinuxAutostartPath(appName: string): string {\n const configDir = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n return join(configDir, 'autostart', `${appName.toLowerCase()}.desktop`)\n}\n\nasync function setAutoLaunchMacOS(enabled: boolean, options: AutoLaunchOptions): Promise<void> {\n const appName = options.appName || 'StxApp'\n const plistPath = getLaunchAgentPath(appName)\n const launchAgentsDir = join(homedir(), 'Library', 'LaunchAgents')\n\n if (enabled) {\n const appPath = options.appPath || process.execPath\n const args = options.args || []\n const programArgs = [appPath, ...args]\n\n const plist = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.${appName.toLowerCase().replace(/[^a-z0-9]/g, '-')}</string>\n <key>ProgramArguments</key>\n <array>\n${programArgs.map(arg => ` <string>${escapeXml(arg)}</string>`).join('\\n')}\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n${options.isHidden ? ` <key>ProcessType</key>\n <string>Background</string>` : ''}\n</dict>\n</plist>`\n\n if (!existsSync(launchAgentsDir)) {\n mkdirSync(launchAgentsDir, { recursive: true })\n }\n\n writeFileSync(plistPath, plist, 'utf-8')\n }\n else {\n if (existsSync(plistPath)) {\n unlinkSync(plistPath)\n }\n }\n}\n\nasync function setAutoLaunchLinux(enabled: boolean, options: AutoLaunchOptions): Promise<void> {\n const appName = options.appName || 'StxApp'\n const desktopPath = getLinuxAutostartPath(appName)\n const autostartDir = join(process.env.XDG_CONFIG_HOME || join(homedir(), '.config'), 'autostart')\n\n if (enabled) {\n const appPath = options.appPath || process.execPath\n const args = options.args || []\n const exec = [appPath, ...args].join(' ')\n\n const desktopEntry = `[Desktop Entry]\nType=Application\nName=${appName}\nExec=${exec}\nTerminal=false\nStartupNotify=false\n${options.isHidden ? 'X-GNOME-Autostart-enabled=true\\nNoDisplay=true' : ''}\n`\n\n if (!existsSync(autostartDir)) {\n mkdirSync(autostartDir, { recursive: true })\n }\n\n writeFileSync(desktopPath, desktopEntry, 'utf-8')\n }\n else {\n if (existsSync(desktopPath)) {\n unlinkSync(desktopPath)\n }\n }\n}\n\nasync function isAutoLaunchEnabledMacOS(appName: string): Promise<boolean> {\n return existsSync(getLaunchAgentPath(appName))\n}\n\nasync function isAutoLaunchEnabledLinux(appName: string): Promise<boolean> {\n const path = getLinuxAutostartPath(appName)\n if (!existsSync(path))\n return false\n\n try {\n const content = readFileSync(path, 'utf-8')\n // Check for explicit disable\n if (content.includes('X-GNOME-Autostart-enabled=false'))\n return false\n if (content.includes('Hidden=true'))\n return false\n return true\n }\n catch {\n return false\n }\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&apos;')\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Enable or disable auto-launch on system login.\n *\n * On macOS, creates/removes a LaunchAgent plist.\n * On Linux, creates/removes an XDG autostart .desktop file.\n */\nexport async function setAutoLaunch(enabled: boolean, options: AutoLaunchOptions = {}): Promise<void> {\n const os = platform()\n\n switch (os) {\n case 'darwin':\n return setAutoLaunchMacOS(enabled, options)\n case 'linux':\n return setAutoLaunchLinux(enabled, options)\n default:\n throw new Error(`Auto-launch is not yet supported on ${os}`)\n }\n}\n\n/**\n * Check if auto-launch is enabled for the given app.\n */\nexport async function isAutoLaunchEnabled(appName?: string): Promise<boolean> {\n const name = appName || 'StxApp'\n const os = platform()\n\n switch (os) {\n case 'darwin':\n return isAutoLaunchEnabledMacOS(name)\n case 'linux':\n return isAutoLaunchEnabledLinux(name)\n default:\n return false\n }\n}\n",
16
- "/**\n * Hotkey API (in-window, document-level)\n *\n * Register keyboard shortcuts via document-level listeners. These fire\n * **only while a Craft window has focus** — a thin wrapper around\n * `keydown`. Use this for app-internal shortcuts like\n * \"Cmd+K opens the command palette.\"\n *\n * **For system-wide shortcuts** that fire even when the app isn't\n * focused (e.g. global \"Cmd+Shift+V to bring up your clipboard\n * manager\"), use `globalShortcuts` from `./global-shortcuts` — that\n * talks to the native `RegisterEventHotKey` / `RegisterHotKey` APIs.\n *\n * @example\n * ```typescript\n * import { registerHotkey, unregisterAllHotkeys } from '@stacksjs/desktop'\n *\n * const reg = registerHotkey('Cmd+Shift+C', () => {\n * console.log('Hotkey triggered!')\n * })\n *\n * reg.unregister()\n * unregisterAllHotkeys()\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface HotkeyRegistration {\n /** The shortcut string (e.g., 'Cmd+Shift+C') */\n shortcut: string\n /** Unique registration ID */\n id: string\n /** Unregister this hotkey */\n unregister(): void\n}\n\nexport interface ParsedShortcut {\n /** Key character or name (e.g., 'c', 'Enter', 'Space') */\n key: string\n /** Meta/Command key required */\n meta: boolean\n /** Control key required */\n ctrl: boolean\n /** Shift key required */\n shift: boolean\n /** Alt/Option key required */\n alt: boolean\n}\n\n// ============================================================================\n// Internal State\n// ============================================================================\n\nconst registrations = new Map<string, { shortcut: string, handler: () => void, parsed: ParsedShortcut }>()\nlet nextId = 0\nlet documentListenerAttached = false\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Parse a shortcut string into its component parts.\n *\n * Supports formats like:\n * - 'Cmd+Shift+C'\n * - 'Ctrl+Alt+Delete'\n * - 'Meta+K'\n * - 'CmdOrCtrl+S' (Cmd on macOS, Ctrl on others)\n */\nexport function parseShortcut(shortcut: string): ParsedShortcut {\n const parts = shortcut.split('+').map(p => p.trim())\n const result: ParsedShortcut = {\n key: '',\n meta: false,\n ctrl: false,\n shift: false,\n alt: false,\n }\n\n for (const part of parts) {\n const lower = part.toLowerCase()\n\n switch (lower) {\n case 'cmd':\n case 'command':\n case 'meta':\n case '⌘':\n result.meta = true\n break\n case 'ctrl':\n case 'control':\n case '⌃':\n result.ctrl = true\n break\n case 'shift':\n case '⇧':\n result.shift = true\n break\n case 'alt':\n case 'option':\n case 'opt':\n case '⌥':\n result.alt = true\n break\n case 'cmdorctrl':\n case 'commandorcontrol':\n // On macOS use Meta, otherwise Ctrl\n if (typeof process !== 'undefined' && process.platform === 'darwin') {\n result.meta = true\n }\n else {\n result.ctrl = true\n }\n break\n default:\n result.key = lower\n }\n }\n\n return result\n}\n\n/**\n * Format a parsed shortcut back into a display string.\n */\nexport function formatShortcut(parsed: ParsedShortcut): string {\n const parts: string[] = []\n if (parsed.ctrl)\n parts.push('⌃')\n if (parsed.alt)\n parts.push('⌥')\n if (parsed.shift)\n parts.push('⇧')\n if (parsed.meta)\n parts.push('⌘')\n parts.push(parsed.key.toUpperCase())\n return parts.join('')\n}\n\nfunction matchesEvent(event: KeyboardEvent, parsed: ParsedShortcut): boolean {\n if (parsed.meta !== event.metaKey)\n return false\n if (parsed.ctrl !== event.ctrlKey)\n return false\n if (parsed.shift !== event.shiftKey)\n return false\n if (parsed.alt !== event.altKey)\n return false\n\n const eventKey = event.key.toLowerCase()\n return eventKey === parsed.key || event.code.toLowerCase() === `key${parsed.key}`\n}\n\nfunction handleKeyDown(event: KeyboardEvent): void {\n for (const [, reg] of registrations) {\n if (matchesEvent(event, reg.parsed)) {\n event.preventDefault()\n event.stopPropagation()\n try {\n reg.handler()\n }\n catch {}\n break\n }\n }\n}\n\nfunction ensureDocumentListener(): void {\n if (documentListenerAttached)\n return\n if (typeof document === 'undefined')\n return\n\n document.addEventListener('keydown', handleKeyDown, true)\n documentListenerAttached = true\n}\n\nfunction removeDocumentListener(): void {\n if (!documentListenerAttached)\n return\n if (typeof document === 'undefined')\n return\n\n document.removeEventListener('keydown', handleKeyDown, true)\n documentListenerAttached = false\n}\n\n// ============================================================================\n// Craft Native Integration\n// ============================================================================\n\nasync function registerWithCraft(id: string, shortcut: string): Promise<boolean> {\n if (typeof window === 'undefined')\n return false\n\n const craft = (window as any).craft\n if (!craft?.hotkeys?.register)\n return false\n\n try {\n await craft.hotkeys.register(id, shortcut)\n return true\n }\n catch {\n return false\n }\n}\n\nasync function unregisterWithCraft(id: string): Promise<void> {\n if (typeof window === 'undefined')\n return\n\n const craft = (window as any).craft\n if (!craft?.hotkeys?.unregister)\n return\n\n try {\n await craft.hotkeys.unregister(id)\n }\n catch {}\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Register a global keyboard shortcut.\n *\n * When running in a Craft native window, this registers a system-wide hotkey\n * that works even when the app is not focused. In web mode, it falls back to\n * a document-level keydown listener.\n *\n * @param shortcut - The keyboard shortcut (e.g., 'Cmd+Shift+C', 'CmdOrCtrl+K')\n * @param handler - Function to call when the shortcut is triggered\n * @returns A registration object with an `unregister()` method\n */\nexport function registerHotkey(shortcut: string, handler: () => void): HotkeyRegistration {\n const id = `hotkey_${++nextId}_${Date.now()}`\n const parsed = parseShortcut(shortcut)\n\n registrations.set(id, { shortcut, handler, parsed })\n\n // Try to register with Craft native side\n registerWithCraft(id, shortcut)\n\n // Always set up document listener as fallback\n ensureDocumentListener()\n\n const registration: HotkeyRegistration = {\n shortcut,\n id,\n unregister() {\n unregisterHotkey(registration)\n },\n }\n\n return registration\n}\n\n/**\n * Unregister a specific hotkey.\n */\nexport function unregisterHotkey(registration: HotkeyRegistration): void {\n registrations.delete(registration.id)\n unregisterWithCraft(registration.id)\n\n if (registrations.size === 0) {\n removeDocumentListener()\n }\n}\n\n/**\n * Unregister all registered hotkeys.\n */\nexport function unregisterAllHotkeys(): void {\n for (const [id] of registrations) {\n unregisterWithCraft(id)\n }\n registrations.clear()\n removeDocumentListener()\n}\n\n/**\n * Get all currently registered hotkeys.\n */\nexport function getRegisteredHotkeys(): HotkeyRegistration[] {\n return Array.from(registrations.entries()).map(([id, reg]) => ({\n shortcut: reg.shortcut,\n id,\n unregister() {\n registrations.delete(id)\n unregisterWithCraft(id)\n if (registrations.size === 0) {\n removeDocumentListener()\n }\n },\n }))\n}\n",
17
- "/**\n * Timer / Scheduling Utilities\n *\n * Provides a rich timer API for desktop applications — useful for\n * Pomodoro timers, caffeinate countdowns, auto-save intervals, etc.\n *\n * @example\n * ```typescript\n * import { createTimer } from '@stacksjs/desktop'\n *\n * const timer = createTimer({\n * duration: 25 * 60 * 1000, // 25 minutes\n * onTick: (remaining) => {\n * console.log(`${Math.ceil(remaining / 1000)}s remaining`)\n * },\n * onComplete: () => {\n * console.log('Timer complete!')\n * },\n * })\n *\n * timer.start()\n *\n * // Later...\n * timer.pause()\n * timer.resume()\n * timer.stop()\n * timer.reset()\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TimerOptions {\n /** Duration in milliseconds */\n duration: number\n /** Called on each tick with remaining milliseconds */\n onTick?: (remaining: number) => void\n /** Called when the timer completes */\n onComplete?: () => void\n /** Milliseconds between ticks. Default: 1000 */\n tickInterval?: number\n /** Start the timer immediately. Default: false */\n autoStart?: boolean\n}\n\nexport interface Timer {\n /** Start the timer */\n start(): void\n /** Stop the timer and reset */\n stop(): void\n /** Pause the timer */\n pause(): void\n /** Resume a paused timer */\n resume(): void\n /** Reset the timer to initial duration */\n reset(): void\n /** Whether the timer is currently running */\n readonly isRunning: boolean\n /** Whether the timer is paused */\n readonly isPaused: boolean\n /** Whether the timer has completed */\n readonly isComplete: boolean\n /** Remaining milliseconds */\n readonly remaining: number\n /** Elapsed milliseconds */\n readonly elapsed: number\n /** Total duration in milliseconds */\n readonly duration: number\n /** Progress as a fraction from 0 to 1 */\n readonly progress: number\n /** Register a completion handler */\n onComplete(handler: () => void): () => void\n /** Register a tick handler */\n onTick(handler: (remaining: number) => void): () => void\n}\n\nexport interface IntervalOptions {\n /** Interval in milliseconds */\n interval: number\n /** Function to call on each interval */\n handler: () => void\n /** Start immediately. Default: true */\n immediate?: boolean\n}\n\nexport interface Interval {\n /** Start the interval */\n start(): void\n /** Stop the interval */\n stop(): void\n /** Whether the interval is running */\n readonly isRunning: boolean\n}\n\n// ============================================================================\n// Timer Implementation\n// ============================================================================\n\nclass TimerImpl implements Timer {\n private _duration: number\n private _tickInterval: number\n private _remaining: number\n private _running = false\n private _paused = false\n private _complete = false\n private _intervalId: ReturnType<typeof setInterval> | null = null\n private _lastTick: number = 0\n private _completionHandlers: Set<() => void> = new Set()\n private _tickHandlers: Set<(remaining: number) => void> = new Set()\n\n constructor(options: TimerOptions) {\n this._duration = options.duration\n this._tickInterval = options.tickInterval || 1000\n this._remaining = options.duration\n\n if (options.onComplete)\n this._completionHandlers.add(options.onComplete)\n\n if (options.onTick)\n this._tickHandlers.add(options.onTick)\n\n if (options.autoStart)\n this.start()\n }\n\n get isRunning(): boolean {\n return this._running && !this._paused\n }\n\n get isPaused(): boolean {\n return this._paused\n }\n\n get isComplete(): boolean {\n return this._complete\n }\n\n get remaining(): number {\n if (this._running && !this._paused) {\n const elapsed = Date.now() - this._lastTick\n return Math.max(0, this._remaining - elapsed)\n }\n return Math.max(0, this._remaining)\n }\n\n get elapsed(): number {\n return this._duration - this.remaining\n }\n\n get duration(): number {\n return this._duration\n }\n\n get progress(): number {\n if (this._duration === 0)\n return 1\n return Math.min(1, this.elapsed / this._duration)\n }\n\n start(): void {\n if (this._running)\n return\n\n this._running = true\n this._paused = false\n this._complete = false\n this._lastTick = Date.now()\n\n this._startInterval()\n }\n\n stop(): void {\n this._clearInterval()\n this._running = false\n this._paused = false\n this._remaining = this._duration\n }\n\n pause(): void {\n if (!this._running || this._paused)\n return\n\n // Save remaining time accurately\n const elapsed = Date.now() - this._lastTick\n this._remaining = Math.max(0, this._remaining - elapsed)\n\n this._clearInterval()\n this._paused = true\n }\n\n resume(): void {\n if (!this._paused)\n return\n\n this._paused = false\n this._lastTick = Date.now()\n this._startInterval()\n }\n\n reset(): void {\n this._clearInterval()\n this._running = false\n this._paused = false\n this._complete = false\n this._remaining = this._duration\n }\n\n onComplete(handler: () => void): () => void {\n this._completionHandlers.add(handler)\n return () => {\n this._completionHandlers.delete(handler)\n }\n }\n\n onTick(handler: (remaining: number) => void): () => void {\n this._tickHandlers.add(handler)\n return () => {\n this._tickHandlers.delete(handler)\n }\n }\n\n // --------------------------------------------------------------------------\n // Private\n // --------------------------------------------------------------------------\n\n private _startInterval(): void {\n this._clearInterval()\n\n this._intervalId = setInterval(() => {\n const now = Date.now()\n const elapsed = now - this._lastTick\n this._lastTick = now\n this._remaining = Math.max(0, this._remaining - elapsed)\n\n // Notify tick handlers\n for (const handler of this._tickHandlers) {\n try {\n handler(this._remaining)\n }\n catch {}\n }\n\n // Check for completion\n if (this._remaining <= 0) {\n this._clearInterval()\n this._running = false\n this._complete = true\n\n for (const handler of this._completionHandlers) {\n try {\n handler()\n }\n catch {}\n }\n }\n }, this._tickInterval)\n }\n\n private _clearInterval(): void {\n if (this._intervalId !== null) {\n clearInterval(this._intervalId)\n this._intervalId = null\n }\n }\n}\n\n// ============================================================================\n// Interval Implementation\n// ============================================================================\n\nclass IntervalImpl implements Interval {\n private _interval: number\n private _handler: () => void\n private _immediate: boolean\n private _running = false\n private _intervalId: ReturnType<typeof setInterval> | null = null\n\n constructor(options: IntervalOptions) {\n this._interval = options.interval\n this._handler = options.handler\n this._immediate = options.immediate !== false\n\n if (this._immediate)\n this.start()\n }\n\n get isRunning(): boolean {\n return this._running\n }\n\n start(): void {\n if (this._running)\n return\n this._running = true\n this._intervalId = setInterval(() => {\n try {\n this._handler()\n }\n catch {}\n }, this._interval)\n }\n\n stop(): void {\n if (this._intervalId !== null) {\n clearInterval(this._intervalId)\n this._intervalId = null\n }\n this._running = false\n }\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Create a countdown timer.\n */\nexport function createTimer(options: TimerOptions): Timer {\n return new TimerImpl(options)\n}\n\n/**\n * Create a repeating interval.\n */\nexport function createInterval(options: IntervalOptions): Interval {\n return new IntervalImpl(options)\n}\n\n/**\n * Create a simple delay/sleep promise.\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * Format milliseconds as a human-readable time string.\n *\n * @example\n * ```typescript\n * formatTime(90000) // \"1:30\"\n * formatTime(3661000) // \"1:01:01\"\n * formatTime(45000) // \"0:45\"\n * ```\n */\nexport function formatTime(ms: number): string {\n const totalSeconds = Math.ceil(ms / 1000)\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0)\n return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`\n return `${minutes}:${String(seconds).padStart(2, '0')}`\n}\n\n/**\n * Format milliseconds as a compact string for display.\n *\n * @example\n * ```typescript\n * formatCompact(90000) // \"1m 30s\"\n * formatCompact(3600000) // \"1h\"\n * formatCompact(7230000) // \"2h 0m\"\n * ```\n */\nexport function formatCompact(ms: number): string {\n const totalSeconds = Math.ceil(ms / 1000)\n const hours = Math.floor(totalSeconds / 3600)\n const minutes = Math.floor((totalSeconds % 3600) / 60)\n const seconds = totalSeconds % 60\n\n if (hours > 0) {\n if (minutes > 0)\n return `${hours}h ${minutes}m`\n return `${hours}h`\n }\n if (minutes > 0) {\n if (seconds > 0)\n return `${minutes}m ${seconds}s`\n return `${minutes}m`\n }\n return `${seconds}s`\n}\n",
18
- "/**\n * Shared internals for craft bridge wrappers.\n *\n * Every public module in this package follows the same shape:\n * 1. Detect whether `window.craft.<namespace>` is available.\n * 2. Forward to it when running inside a Craft native window.\n * 3. Fall back gracefully (or refuse with a clear error) elsewhere.\n *\n * Centralising these helpers keeps the per-module wrappers small and\n * means a future bridge-detection change (e.g. version negotiation)\n * lives in exactly one place.\n *\n * Internal — not re-exported from index.ts. Apps that want to call the\n * bridge directly should use the namespaced public modules.\n */\n\n// The bridge is built on the Zig side and exposes far more namespaces than\n// craft-native's published types declare (audio, bluetooth, menu, updater,\n// touchbar, iap, …). Widen the published interface instead of re-declaring\n// `Window.craft` here: craft-native already declares that property globally as\n// `CraftBridgeAPI & CraftEventEmitter`, so a second, looser declaration is a\n// conflicting merge (TS2717) — and the narrower published type wins, which made\n// every `craft.<ns>` access fail with TS2339 and every `craft[ns]` lookup with\n// TS7053.\n//\n// An index signature keeps the declared namespaces exactly as typed while\n// letting the ones the bridge ships ahead of the types resolve, which preserves\n// the original intent: don't make the TS layer drift out of sync when a single\n// field renames.\ndeclare module 'craft-native' {\n interface CraftBridgeAPI {\n [namespace: string]: any\n }\n\n // `app` IS a declared namespace with precise signatures, so widen it by\n // naming the two macOS dock methods the bridge ships rather than with an\n // index signature — that keeps a typo in `craft.app.*` an error.\n interface CraftAppAPI {\n setBadge: (count: number) => Promise<void>\n bounce: (type?: 'critical' | 'informational') => Promise<void>\n }\n}\n\ndeclare global {\n interface Window {\n __craftPendingDeepLink?: string\n __craftCurrentTheme?: { appearance: 'light' | 'dark' }\n }\n}\n\n/** True when `window.craft.<ns>` exists. Cheap; do not memoize. */\nexport function hasBridge(ns: string): boolean {\n if (typeof window === 'undefined') return false\n const c = window.craft as Record<string, any> | undefined\n return !!(c && c[ns])\n}\n\n/**\n * Get the bridge namespace, or throw a clear error if it isn't there.\n * Use this in the rare case where a sensible web fallback doesn't exist\n * (e.g. system-level battery info). For everything else, prefer\n * `hasBridge` + manual fallback so the call works in browsers too.\n */\nexport function requireBridge<T = Record<string, any>>(ns: string): T {\n if (!hasBridge(ns)) {\n throw new Error(`craft.${ns} is not available — this API requires a Craft native window`)\n }\n return (window as Window).craft![ns] as T\n}\n\n/**\n * Central index of every `craft:*` event the SDK currently knows about,\n * mapped to its payload shape. Apps that subscribe via `onCraftEvent`\n * with a literal name get fully-typed `detail` automatically — no\n * `<unknown>` casts. Internal modules also use the map to keep their\n * own `onXxx` callbacks honest.\n *\n * When adding a new event name on the native side, add a row here so\n * the public TS surface stays in sync.\n */\nexport interface CraftEventMap {\n // power / system-wide\n 'craft:powerSleep': void\n 'craft:powerWake': void\n 'craft:networkChange': { type: import('./network').ConnectionType, online: boolean }\n 'craft:screen:change': void\n 'craft:screenSharing:change': import('./screen-sharing').ScreenSharingState\n 'craft:theme': import('./theme').ThemeInfo\n\n // bluetooth\n 'craft:bluetooth:deviceFound': import('./bluetooth').BluetoothDevice\n 'craft:bluetooth:deviceConnected': import('./bluetooth').BluetoothDevice\n 'craft:bluetooth:deviceDisconnected': import('./bluetooth').BluetoothDevice\n 'craft:bluetooth:characteristicValue': import('./bluetooth').BluetoothCharacteristicValueEvent\n\n // bonjour\n 'craft:bonjour:found': import('./bonjour').BonjourService\n 'craft:bonjour:lost': import('./bonjour').BonjourService\n\n // deep link\n 'craft:deepLink': import('./deep-link').DeepLinkEvent\n\n // file system\n 'craft:fs:change': import('./fs').FSChangeEvent\n\n // global shortcuts\n 'craft:shortcut': import('./global-shortcuts').ShortcutFireEvent\n\n // handoff / continuity\n 'craft:handoff:incoming': import('./handoff').HandoffIncomingEvent\n\n // in-app purchases\n 'craft:iap:purchased': import('./iap').IAPTransactionEvent\n 'craft:iap:failed': import('./iap').IAPFailureEvent\n 'craft:iap:restored': import('./iap').IAPTransactionEvent\n 'craft:iap:productsLoaded': { products?: import('./iap').IAPProduct[] }\n 'craft:iap:refunded': import('./iap').IAPRefundEvent\n 'craft:iap:subscriptionStatusChanged': import('./iap').IAPSubscriptionStatusEvent\n\n // local HTTP server\n 'craft:localServer:request': import('./local-server').LocalServerRequestEvent\n\n // location\n 'craft:location:update': import('./location').LocationCoordinate\n 'craft:location:error': { message: string }\n 'craft:location:authChanged': { status: import('./location').LocationAuthStatus }\n\n // menu\n 'craft:menu:action': import('./menu').MenuActionEvent\n\n // midi\n 'craft:midi:message': import('./midi').MIDIMessageEvent\n\n // notifications\n 'craft:notification:actionClicked': import('./notifications').NotificationActionEvent\n 'craft:notification:reply': import('./notifications').NotificationReplyEvent\n\n // serial\n 'craft:serial:data': import('./serial').SerialDataEvent\n\n // service menu\n 'craft:serviceMenu:invoked': import('./service-menu').ServiceMenuInvokedEvent\n\n // shell\n 'craft:shell:stdout': import('./shell').ShellOutputEvent\n 'craft:shell:stderr': import('./shell').ShellOutputEvent\n 'craft:shell:exit': import('./shell').ShellExitEvent\n\n // speech recognition\n 'craft:speechRecognition:partial': { transcript: string }\n 'craft:speechRecognition:final': { transcript: string }\n\n // touch bar\n 'craft:touchbar:action': import('./touchbar').TouchBarActionEvent\n\n // updater\n 'craft:updateAvailable': import('./updater').UpdateInfo\n 'craft:updateDownloaded': import('./updater').UpdateInfo\n\n // window\n 'craft:window:focus': void\n 'craft:window:blur': void\n 'craft:window:resize': import('./window-events').WindowSize\n 'craft:window:move': import('./window-events').WindowPosition\n 'craft:window:close': void\n 'craft:window:minimize': void\n 'craft:window:restore': void\n\n // tray\n 'craft:tray:menu': { id?: string }\n}\n\n/**\n * Subscribe to a `craft:*` window event with auto-detached cleanup.\n *\n * Two overloads:\n * - **Known event** (string literal in `CraftEventMap`): `detail` is\n * typed to the matching payload, no generic argument needed.\n * - **Custom event** (any other name): pass an explicit `T` to type\n * the payload yourself, or default to `unknown`.\n */\nexport function onCraftEvent<K extends keyof CraftEventMap>(\n name: K,\n cb: (detail: CraftEventMap[K]) => void,\n): () => void\nexport function onCraftEvent<T = unknown>(\n name: string,\n cb: (detail: T) => void,\n): () => void\nexport function onCraftEvent(name: string, cb: (detail: any) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const h = (e: Event) => cb((e as CustomEvent).detail ?? {})\n window.addEventListener(name, h as EventListener)\n return () => window.removeEventListener(name, h as EventListener)\n}\n",
19
- "/**\n * Clipboard\n *\n * Read/write the system clipboard — text and HTML. When running inside a\n * Craft native window, uses NSPasteboard (macOS) / GTK clipboard (Linux)\n * / OpenClipboard (Windows). When running in a browser, falls back to\n * the Async Clipboard API (`navigator.clipboard.{read,write}Text`).\n *\n * **Permissions:** browsers require a user gesture (click, key) for\n * `writeText`. The native side has no such requirement.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface Clipboard {\n /** Write plain text to the clipboard. */\n writeText: (text: string) => Promise<void>\n /** Read plain text from the clipboard. Returns \"\" if empty/unavailable. */\n readText: () => Promise<string>\n /** Write HTML to the clipboard (useful for rich-text paste targets). */\n writeHTML: (html: string) => Promise<void>\n /** Read HTML from the clipboard. Returns \"\" if no HTML payload present. */\n readHTML: () => Promise<string>\n /** Empty the clipboard. */\n clear: () => Promise<void>\n /** True when the clipboard currently contains plain text. */\n hasText: () => Promise<boolean>\n /** True when the clipboard currently contains HTML. */\n hasHTML: () => Promise<boolean>\n /** True when the clipboard currently contains an image. */\n hasImage: () => Promise<boolean>\n}\n\nexport const clipboard: Clipboard = {\n async writeText(text: string): Promise<void> {\n if (hasBridge('clipboard')) {\n await window.craft!.clipboard.writeText(text)\n return\n }\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n await navigator.clipboard.writeText(text)\n }\n },\n\n async readText(): Promise<string> {\n if (hasBridge('clipboard')) {\n const v = await window.craft!.clipboard.readText()\n return typeof v === 'string' ? v : ''\n }\n if (typeof navigator !== 'undefined' && navigator.clipboard?.readText) {\n try { return await navigator.clipboard.readText() }\n catch { return '' }\n }\n return ''\n },\n\n async writeHTML(html: string): Promise<void> {\n if (hasBridge('clipboard')) {\n await window.craft!.clipboard.writeHTML(html)\n return\n }\n // Web Clipboard API: ClipboardItem with text/html. Browsers gate this\n // behind a user gesture *and* a runtime permission, so callers may\n // see a silent no-op when neither condition is met.\n if (typeof navigator !== 'undefined' && (navigator as any).clipboard?.write) {\n try {\n const item = new (window as any).ClipboardItem({\n 'text/html': new Blob([html], { type: 'text/html' }),\n 'text/plain': new Blob([stripHtml(html)], { type: 'text/plain' }),\n })\n await (navigator as any).clipboard.write([item])\n }\n catch {\n // Best-effort; fall through.\n }\n }\n },\n\n async readHTML(): Promise<string> {\n if (hasBridge('clipboard')) {\n const v = await window.craft!.clipboard.readHTML()\n return typeof v === 'string' ? v : ''\n }\n if (typeof navigator !== 'undefined' && (navigator as any).clipboard?.read) {\n try {\n const items = await (navigator as any).clipboard.read()\n for (const item of items) {\n if (item.types.includes('text/html')) {\n const blob = await item.getType('text/html')\n return await blob.text()\n }\n }\n }\n catch { /* fall through */ }\n }\n return ''\n },\n\n async clear(): Promise<void> {\n if (hasBridge('clipboard')) {\n await window.craft!.clipboard.clear()\n return\n }\n // Web fallback: write an empty string (no dedicated API).\n if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {\n try { await navigator.clipboard.writeText('') } catch { /* ignore */ }\n }\n },\n\n async hasText(): Promise<boolean> {\n if (hasBridge('clipboard')) {\n return await window.craft!.clipboard.hasText()\n }\n return (await this.readText()).length > 0\n },\n\n async hasHTML(): Promise<boolean> {\n if (hasBridge('clipboard')) {\n return await window.craft!.clipboard.hasHTML()\n }\n return (await this.readHTML()).length > 0\n },\n\n async hasImage(): Promise<boolean> {\n if (hasBridge('clipboard')) {\n return await window.craft!.clipboard.hasImage()\n }\n // No reliable web API for \"is there an image in the clipboard\" without\n // actually trying to read it (which prompts for permission). Report\n // false rather than silently asking for permission.\n return false\n },\n}\n\n/**\n * Tiny HTML→text reducer for the writeHTML web fallback's plain alt.\n *\n * Drops `<script>`/`<style>` content entirely (common XSS vector when\n * naively stripped — `<script>alert(1)</script>` would otherwise leave\n * the literal `alert(1)` in the plaintext clipboard, looking innocuous\n * but still potentially dangerous if pasted into a code editor that\n * runs it). Replaces `<br>`/`</p>` with newlines so the plaintext\n * mirrors the HTML's visible structure.\n */\nfunction stripHtml(html: string): string {\n return html\n .replace(/<(script|style)[^>]*>[\\s\\S]*?<\\/\\1>/gi, '')\n .replace(/<\\/?(br|p|div|li|h[1-6])\\b[^>]*>/gi, '\\n')\n .replace(/<[^>]+>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&amp;/g, '&')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n",
20
- "/**\n * System Notifications\n *\n * Send banner notifications and update the dock badge. When running\n * inside a Craft native window, uses UNUserNotificationCenter (macOS)\n * / D-Bus org.freedesktop.Notifications (Linux) / Toast (Windows).\n * In a browser, falls back to the standard `Notification` web API.\n *\n * **NOT** the same as `alerts.ts` — that module displays in-app toasts\n * (DOM overlays). This module dispatches to the OS notification center,\n * which persists in Notification Center / Action Center / etc.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface NotificationAttachment {\n /** Stable id within the notification. Optional — UNNotificationAttachment auto-generates one when omitted. */\n id?: string\n /** Local file URL or absolute path. UNNotificationAttachment requires a file URL. */\n url: string\n /**\n * MIME-ish hint. UNNotificationAttachment infers from the file\n * extension when absent; pass when the extension is missing or\n * ambiguous.\n */\n type?: 'image' | 'audio' | 'video' | string\n}\n\nexport interface NotificationAction {\n /** Stable id sent back via `onActionClicked`. */\n id: string\n /** Visible label on the action button. */\n title: string\n /**\n * UNNotificationActionOptions — `'destructive'` shows the action in\n * red (delete-style), `'foreground'` brings the app to the foreground\n * after handling. Default is the standard non-destructive background\n * action.\n */\n style?: 'default' | 'destructive' | 'foreground'\n /** When present, hide the action behind FaceID / Touch ID before firing. */\n authenticationRequired?: boolean\n}\n\nexport interface NotificationOptions {\n /** Required title shown in bold at the top. */\n title: string\n /** Body text — may wrap. */\n body?: string\n /** Subtitle (macOS only — second line above body). */\n subtitle?: string\n /** Stable identifier so callers can `cancel(id)` later. */\n id?: string\n /** ISO timestamp / Date / epoch ms. Defaults to \"now\". */\n triggerAt?: string | number | Date\n /** Sound to play. `'default'` plays the system sound. */\n sound?: 'default' | 'silent' | string\n /** Icon URL (web fallback only — native uses the app icon). */\n icon?: string\n /** Number badge to display on the app icon. */\n badge?: number\n /** Custom data passed back to your `onClick` handler. */\n data?: unknown\n /**\n * Image / audio / video attachments shown alongside the notification\n * (UNNotificationAttachment on macOS, image-payload on Linux/Windows\n * where supported). Each entry needs a file URL or absolute path that\n * the OS can read.\n */\n attachments?: NotificationAttachment[]\n /**\n * Custom buttons added to the notification. macOS lets you ship up to\n * four; users see \"More\" if more are present. The `id` you set here\n * comes back via `onActionClicked` when the user taps the action.\n */\n actions?: NotificationAction[]\n /**\n * Inline reply text-field (macOS only). When set, the notification\n * shows a reply field; the user's text comes back via `onReply`.\n */\n reply?: {\n /** Placeholder text inside the reply box. */\n placeholder?: string\n /** Submit button label. Defaults to the system's \"Send\". */\n sendButtonTitle?: string\n }\n /**\n * Category identifier — pre-registered via UNUserNotificationCenter\n * before sending. When present, the notification reuses the actions\n * registered against that category instead of repeating them inline.\n */\n categoryId?: string\n /**\n * Replace any earlier notifications with the same thread id (groups\n * them in macOS's notification center; behaves as a \"bucket\" elsewhere).\n */\n threadId?: string\n}\n\nexport interface NotificationActionEvent {\n /** Notification id (`options.id`). */\n notificationId?: string\n /** Action id (matches `NotificationAction.id`). */\n actionId: string\n /** When `actionId` is the system-supplied \"default\" tap action. */\n isDefault?: boolean\n}\n\nexport interface NotificationReplyEvent {\n notificationId?: string\n /** Text the user typed into the inline reply field. */\n text: string\n}\n\nexport interface NotificationCategory {\n /** Stable id referenced via `NotificationOptions.categoryId`. */\n id: string\n /** Default actions attached to every notification of this category. */\n actions: NotificationAction[]\n}\n\nexport interface SystemNotifications {\n /** Show a notification immediately. */\n show: (options: NotificationOptions) => Promise<void>\n /** Schedule a future notification. Use `triggerAt` to set the time. */\n schedule: (options: NotificationOptions) => Promise<void>\n /** Cancel a scheduled or visible notification by id. */\n cancel: (id: string) => Promise<void>\n /** Cancel everything we've scheduled or shown. */\n cancelAll: () => Promise<void>\n /** Set the dock/taskbar badge count. */\n setBadge: (n: number) => Promise<void>\n /** Clear the dock/taskbar badge. */\n clearBadge: () => Promise<void>\n /**\n * Ask the user for notification permission.\n * Returns `true` if granted (or already granted).\n */\n requestPermission: () => Promise<boolean>\n /**\n * Pre-register a category — same shape as `actions` on a single\n * notification, but reusable across many. Apps generally do this once\n * at boot so the notification center has the actions ready before any\n * notification fires.\n */\n registerCategories: (categories: NotificationCategory[]) => Promise<void>\n /**\n * Subscribe to user taps on actions (including the default tap on the\n * notification body — `event.isDefault === true` for that case).\n */\n onActionClicked: (cb: (event: NotificationActionEvent) => void) => () => void\n /**\n * Subscribe to inline-reply submissions. Only fires for notifications\n * that opted into `reply`.\n */\n onReply: (cb: (event: NotificationReplyEvent) => void) => () => void\n}\n\nexport const notifications: SystemNotifications = {\n async show(options: NotificationOptions): Promise<void> {\n if (!options.title) throw new Error('notification title is required')\n if (hasBridge('notifications')) {\n await window.craft!.notifications.show(options)\n return\n }\n // Web fallback: standard Notification API.\n if (typeof window !== 'undefined' && 'Notification' in window) {\n const N = (window as any).Notification\n if (N.permission === 'granted') {\n new N(options.title, { body: options.body, icon: options.icon })\n }\n else if (N.permission === 'default') {\n const granted = (await N.requestPermission()) === 'granted'\n if (granted) new N(options.title, { body: options.body, icon: options.icon })\n }\n }\n },\n\n async schedule(options: NotificationOptions): Promise<void> {\n if (hasBridge('notifications')) {\n // The native side accepts a flat object. Normalize trigger to ISO so\n // the parser on the Zig side doesn't have to deal with Date objects.\n const o = { ...options }\n if (o.triggerAt instanceof Date) o.triggerAt = o.triggerAt.toISOString()\n await window.craft!.notifications.schedule(o)\n return\n }\n // Web has no scheduling primitive — fall back to setTimeout.\n const fireAt = toEpochMs(options.triggerAt)\n const delay = Math.max(0, fireAt - Date.now())\n setTimeout(() => { this.show(options).catch(() => {}) }, delay)\n },\n\n async cancel(id: string): Promise<void> {\n if (hasBridge('notifications')) {\n await window.craft!.notifications.cancel(id)\n }\n // Web has no per-id cancellation; nothing to do.\n },\n\n async cancelAll(): Promise<void> {\n if (hasBridge('notifications')) {\n await window.craft!.notifications.cancelAll()\n }\n },\n\n async setBadge(n: number): Promise<void> {\n // Negative counts cause native-side display glitches (Apple\n // documents non-negative). Clamp at the JS boundary so apps don't\n // have to remember the constraint, and round so a fractional value\n // (e.g. from a divide) doesn't render as \"5.5\".\n const safe = Math.max(0, Math.round(Number.isFinite(n) ? n : 0))\n if (hasBridge('notifications')) {\n await window.craft!.notifications.setBadge(safe)\n return\n }\n // Some browsers expose navigator.setAppBadge (PWA Badging API).\n if (typeof navigator !== 'undefined' && (navigator as any).setAppBadge) {\n try { await (navigator as any).setAppBadge(safe) } catch { /* ignore */ }\n }\n },\n\n async clearBadge(): Promise<void> {\n if (hasBridge('notifications')) {\n await window.craft!.notifications.clearBadge()\n return\n }\n if (typeof navigator !== 'undefined' && (navigator as any).clearAppBadge) {\n try { await (navigator as any).clearAppBadge() } catch { /* ignore */ }\n }\n },\n\n async requestPermission(): Promise<boolean> {\n if (hasBridge('notifications')) {\n return await window.craft!.notifications.requestPermission()\n }\n if (typeof window !== 'undefined' && 'Notification' in window) {\n const N = (window as any).Notification\n if (N.permission === 'granted') return true\n if (N.permission === 'denied') return false\n const result = await N.requestPermission()\n return result === 'granted'\n }\n return false\n },\n\n async registerCategories(categories) {\n if (!Array.isArray(categories) || categories.length === 0) return\n if (hasBridge('notifications')) {\n const fn = window.craft!.notifications.registerCategories\n if (typeof fn === 'function') await fn(categories)\n }\n // No web fallback — the standard Notification API has no equivalent.\n },\n\n onActionClicked(cb) { return onCraftEvent<NotificationActionEvent>('craft:notification:actionClicked', cb) },\n onReply(cb) { return onCraftEvent<NotificationReplyEvent>('craft:notification:reply', cb) },\n}\n\nfunction toEpochMs(t: string | number | Date | undefined): number {\n if (t == null) return Date.now()\n if (t instanceof Date) return t.getTime()\n if (typeof t === 'number') return t\n const parsed = Date.parse(t)\n return Number.isNaN(parsed) ? Date.now() : parsed\n}\n",
21
- "/**\n * Filesystem\n *\n * Read/write files and directories from inside the renderer. When\n * running in a Craft native window this dispatches to the native `fs`\n * bridge (full POSIX-style access). In a browser this throws — there's\n * no equivalent web API that doesn't require user-gesture-gated picker\n * flows, and silently degrading would mask real bugs.\n *\n * If you want graceful fallbacks for path-y operations, layer them on\n * top: prefer `dialog.showOpenDialog()` to prompt for paths in\n * browser builds.\n */\nimport { onCraftEvent, requireBridge } from './_bridge'\n\nexport interface FileStat {\n /** True if the path points at a regular file. */\n isFile: boolean\n /** True if the path points at a directory. */\n isDirectory: boolean\n /** True if the path is a symbolic link. */\n isSymlink: boolean\n /** Size in bytes (0 for directories). */\n size: number\n /** Last-modified time in epoch ms. */\n modifiedAt: number\n}\n\nexport interface FSChangeEvent {\n /** The watcher id passed to `watch()`. */\n id: string\n /** The path that triggered the event. */\n path: string\n /** Kind of change: created / modified / deleted / renamed / unknown. */\n kind?: 'created' | 'modified' | 'deleted' | 'renamed' | 'unknown'\n}\n\nexport interface WatchOptions {\n /**\n * Watch the path and all its descendants. On macOS this maps directly\n * to `FSEventStreamCreate` with `kFSEventStreamCreateFlagWatchRoot`;\n * on Linux/Windows the native side walks the tree.\n */\n recursive?: boolean\n /**\n * Buffer events for `coalesceMs` then fire them as a single batch.\n * Defaults to `0` (no coalescing). Useful for editors that save +\n * rename + chmod three times within a few milliseconds.\n */\n coalesceMs?: number\n /**\n * Only deliver events whose `kind` is in this set. Defaults to all\n * kinds.\n */\n kinds?: Array<NonNullable<FSChangeEvent['kind']>>\n}\n\nexport interface WatchHandle {\n /** Stop the watcher. Idempotent — calling multiple times is safe. */\n stop: () => Promise<void>\n /** Stable id assigned to this watcher (matches the native id). */\n id: string\n}\n\nexport interface DirEntry {\n /** Entry name (no path). */\n name: string\n /**\n * Absolute path. Synthesized in the TS layer by joining the dir we\n * read against the entry name — the native side returns just the\n * basename, so we don't pay the cost of N path-joins on the bridge\n * boundary.\n */\n path: string\n /** True if the entry is itself a directory. */\n isDirectory: boolean\n}\n\nexport interface MkdirOptions {\n /** Create intermediate directories as needed. */\n recursive?: boolean\n}\n\nexport interface RmdirOptions {\n /** Recursively remove the directory and all its contents. */\n recursive?: boolean\n}\n\nexport interface FS {\n /** Read a file as a UTF-8 string. */\n readFile: (path: string) => Promise<string>\n /**\n * Read a file as raw bytes. Use this for images, archives, or any\n * non-text data — `readFile` would corrupt those because it goes\n * through a UTF-8 decode round-trip on the bridge.\n */\n readBuffer: (path: string) => Promise<Uint8Array>\n /** Write a UTF-8 string to a file (overwrites). */\n writeFile: (path: string, data: string) => Promise<void>\n /** Write raw bytes to a file (overwrites). */\n writeBuffer: (path: string, data: Uint8Array) => Promise<void>\n /** Append a UTF-8 string to a file. Creates the file if missing. */\n appendFile: (path: string, data: string) => Promise<void>\n /** Delete a file. */\n deleteFile: (path: string) => Promise<void>\n /** True if the path exists. Doesn't throw for missing paths. */\n exists: (path: string) => Promise<boolean>\n /** Get file/dir metadata. Throws if the path doesn't exist. */\n stat: (path: string) => Promise<FileStat>\n /** List directory contents. Doesn't recurse. */\n readDir: (path: string) => Promise<DirEntry[]>\n /** Create a directory. */\n mkdir: (path: string, opts?: MkdirOptions) => Promise<void>\n /** Remove a directory. */\n rmdir: (path: string, opts?: RmdirOptions) => Promise<void>\n /** Copy a file from one path to another. */\n copy: (from: string, to: string) => Promise<void>\n /** Move/rename a file. */\n move: (from: string, to: string) => Promise<void>\n /**\n * Watch a path for changes. The native side fires events on the\n * `craft:fs:<id>` window event; pass `id` in to correlate.\n */\n watch: (path: string, id?: string) => Promise<void>\n /** Stop watching. */\n unwatch: (id: string) => Promise<void>\n /**\n * Subscribe to file-system change events. The native watcher fires\n * for every modification (creation, deletion, rename, content\n * change) under any path passed to `watch()`. Subscribers get the\n * event detail; payload shape depends on the platform watcher.\n */\n onChange: (cb: (event: FSChangeEvent) => void) => () => void\n /**\n * Watch a tree with coalescing + filtering. Returns a `WatchHandle`\n * with a `stop()` that detaches the listener AND unwatches the\n * native side. When `coalesceMs` is set, events that arrive within\n * the window are buffered and delivered to `cb` as one batch — handy\n * for editors that emit many events for a single save.\n */\n watchTree: (\n path: string,\n options: WatchOptions,\n cb: (events: FSChangeEvent[]) => void,\n ) => Promise<WatchHandle>\n /** Path to the user's home directory. */\n homeDir: () => Promise<string>\n /** Path to the system's temp directory. */\n tempDir: () => Promise<string>\n /** Path to this app's data directory (per-OS conventions). */\n appDataDir: () => Promise<string>\n}\n\n// Each method is `async` so that the synchronous `requireBridge` throw\n// surfaces as a rejected promise — matching the rest of the surface and\n// keeping call sites uniformly awaitable.\nexport const fs: FS = {\n async readFile(path) { const r = await requireBridge('fs').readFile(path); return (r && r.data) || '' },\n async readBuffer(path) {\n // The native fs bridge currently round-trips through UTF-8, so binary\n // data gets mangled. We base64-encode on the way out and decode here\n // — once the native side gains a `readFileBytes` action that returns\n // an ArrayBuffer (Bun's WKScriptMessage supports it), this can become\n // a single-hop call.\n const r = await requireBridge('fs').readFile(path)\n const text = (r && r.data) || ''\n // If the native side wraps as base64, decode; otherwise treat as\n // raw text. We probe by checking whether the bridge supplied a\n // `base64` flag; old Craft versions don't, in which case we encode\n // the text as UTF-8 bytes (lossy for true binary).\n if (r && r.base64 === true) {\n return base64ToBytes(text)\n }\n return new TextEncoder().encode(text)\n },\n async writeFile(path, data) { await requireBridge('fs').writeFile(path, data) },\n async writeBuffer(path, data) {\n // Same shape concern as readBuffer — until the native side accepts\n // ArrayBuffer payloads, we send a base64 string with a marker the\n // bridge can detect. Apps that need true binary today should chunk\n // smaller payloads or use shell + tempfile flows.\n const b64 = bytesToBase64(data)\n // Pass the base64 marker so a future bridge_fs.writeFile can decode\n // before writing; current bridge ignores extra fields and writes\n // the literal base64 to disk (consistent with readBuffer's mirror\n // path that re-decodes on read). When the native gains a\n // `writeFileBytes` action this becomes a single-hop call.\n const bridge = requireBridge('fs')\n if (typeof bridge.writeFileBytes === 'function') {\n await bridge.writeFileBytes(path, b64)\n }\n else {\n await bridge.writeFile(path, b64)\n }\n },\n\n async copy(from, to) {\n if (from === to) throw new Error('fs.copy: source and destination must differ')\n await requireBridge('fs').copy(from, to)\n },\n async move(from, to) {\n if (from === to) throw new Error('fs.move: source and destination must differ')\n await requireBridge('fs').move(from, to)\n },\n async appendFile(path, data) { await requireBridge('fs').appendFile(path, data) },\n async deleteFile(path) { await requireBridge('fs').deleteFile(path) },\n async exists(path) { return await requireBridge('fs').exists(path) },\n // The translator already normalizes the stat response shape, so the\n // local `normalizeStat` here is now a defence-in-depth: handle the\n // case where a non-Craft host (e.g. an unmocked test or a future\n // bridge) returns the raw native shape directly.\n async stat(path) { return normalizeStat(await requireBridge('fs').stat(path)) },\n async readDir(path) {\n const r = await requireBridge('fs').readDir(path)\n const raw = (r && r.entries) || []\n // Synthesize an absolute `path` per entry by joining the dir +\n // basename. We trim a trailing slash on the dir to keep the result\n // canonical (`/a/b` + `c` → `/a/b/c`, not `/a/b//c`).\n const base = path.endsWith('/') ? path.slice(0, -1) : path\n return raw.map((e: any) => ({\n name: e.name,\n path: `${base}/${e.name}`,\n isDirectory: !!e.isDirectory,\n }))\n },\n async mkdir(path, opts) { await requireBridge('fs').mkdir(path, opts) },\n async rmdir(path, opts) { await requireBridge('fs').rmdir(path, opts) },\n async watch(path, id) { await requireBridge('fs').watch(path, id) },\n async unwatch(id) { await requireBridge('fs').unwatch(id) },\n onChange(cb) { return onCraftEvent<FSChangeEvent>('craft:fs:change', cb) },\n\n async watchTree(path, options, cb) {\n const id = `watch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`\n const bridge = requireBridge('fs')\n // Always call the basic `watch(path, id, options)` — newer Craft\n // versions interpret a third `options` arg (`{ recursive: true }`)\n // and route to FSEvents/RDCW; older versions ignore it and watch\n // the immediate path only. This keeps a single bridge surface.\n await bridge.watch(path, id, { recursive: !!options.recursive })\n\n const allowed = options.kinds && options.kinds.length > 0 ? new Set(options.kinds) : null\n const coalesceMs = Math.max(0, Math.floor(options.coalesceMs ?? 0))\n\n let buffer: FSChangeEvent[] = []\n let flushTimer: ReturnType<typeof setTimeout> | null = null\n let stopped = false\n\n const flush = (): void => {\n flushTimer = null\n if (buffer.length === 0) return\n const batch = buffer\n buffer = []\n try { cb(batch) }\n catch { /* user callback errors mustn't break the watcher */ }\n }\n\n const off = onCraftEvent<FSChangeEvent>('craft:fs:change', (e) => {\n if (stopped) return\n if (e.id !== id) return\n if (allowed && e.kind && !allowed.has(e.kind)) return\n buffer.push(e)\n if (coalesceMs === 0) {\n flush()\n return\n }\n if (flushTimer == null) {\n flushTimer = setTimeout(flush, coalesceMs)\n }\n })\n\n return {\n id,\n async stop() {\n if (stopped) return\n stopped = true\n off()\n if (flushTimer) {\n clearTimeout(flushTimer)\n flushTimer = null\n }\n // Drain any pending buffered events before tearing down the\n // native watcher — otherwise stop() racing with the timer can\n // silently drop events that arrived right before stop().\n if (buffer.length > 0) flush()\n try { await bridge.unwatch(id) }\n catch { /* native may already be gone — ignore */ }\n },\n }\n },\n async homeDir() { return await requireBridge('fs').homeDir() },\n async tempDir() { return await requireBridge('fs').tempDir() },\n async appDataDir() { return await requireBridge('fs').appDataDir() },\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let s = ''\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i])\n // btoa accepts only ASCII strings; the byte→char conversion above\n // satisfies that constraint per byte.\n return typeof btoa === 'function' ? btoa(s) : Buffer.from(bytes).toString('base64')\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const bin = typeof atob === 'function' ? atob(b64) : Buffer.from(b64, 'base64').toString('binary')\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out\n}\n\nfunction normalizeStat(raw: any): FileStat {\n return {\n isFile: !!raw.isFile,\n isDirectory: !!raw.isDirectory,\n isSymlink: !!raw.isSymlink,\n size: Number(raw.size) || 0,\n // Native side reports a unix timestamp in seconds; normalize to ms\n // so callers don't have to remember which one to multiply.\n modifiedAt: raw.modifiedAt != null\n ? (raw.modifiedAt < 1e12 ? raw.modifiedAt * 1000 : raw.modifiedAt)\n : 0,\n }\n}\n",
22
- "/**\n * Shell\n *\n * Open URLs/paths in the user's default app, reveal files in Finder/\n * Explorer, and spawn child processes. When running in a Craft native\n * window this uses NSWorkspace / xdg-open / ShellExecute under the hood.\n *\n * `openExternal` has a sensible browser fallback (`window.open`); the\n * filesystem-touching APIs (`openPath`, `showInFinder`, `spawn`) throw\n * if the bridge isn't available — they have no meaningful web fallback.\n */\nimport { hasBridge, onCraftEvent, requireBridge } from './_bridge'\n\nexport interface SpawnOptions {\n /** Working directory for the spawned process. Defaults to cwd. */\n cwd?: string\n /** Environment variable overrides; merged on top of process env. */\n env?: Record<string, string>\n /** Stream stdout/stderr to JS via `craft:shell:<id>` events. */\n streamOutput?: boolean\n}\n\nexport interface Shell {\n /**\n * Open a URL in the user's default browser.\n * Browser fallback uses `window.open(url, '_blank')`.\n */\n openExternal: (url: string) => Promise<void>\n /** Open a file/directory in its default app (Finder, etc). */\n openPath: (path: string) => Promise<void>\n /** Reveal a file in Finder / Explorer. */\n showInFinder: (path: string) => Promise<void>\n /**\n * Spawn a process. Use `kill(id)` to terminate it later. Output\n * streams to `craft:shell:<id>` window events when `streamOutput` is\n * true.\n */\n spawn: (id: string, command: string, args?: string[], opts?: SpawnOptions) => Promise<void>\n /** Kill a previously spawned process by id. */\n kill: (id: string) => Promise<void>\n /** Read an environment variable. Returns undefined if unset. */\n getEnv: (name: string) => Promise<string | undefined>\n /** Set an environment variable for this process and its children. */\n setEnv: (name: string, value: string) => Promise<void>\n /** Subscribe to stdout for a spawned process. */\n onStdout: (cb: (event: ShellOutputEvent) => void) => () => void\n /** Subscribe to stderr for a spawned process. */\n onStderr: (cb: (event: ShellOutputEvent) => void) => () => void\n /** Subscribe to process-exit events. */\n onExit: (cb: (event: ShellExitEvent) => void) => () => void\n}\n\n/** Output chunk from a spawned process. */\nexport interface ShellOutputEvent {\n /** id passed to `spawn()`. */\n id: string\n /** UTF-8 chunk. May or may not align with line boundaries. */\n data: string\n}\n\nexport interface ShellExitEvent {\n id: string\n /** Process exit code (0 = success). null when the process was killed by signal. */\n exitCode: number | null\n /** Termination signal name (e.g. \"SIGTERM\"), if killed. */\n signal?: string\n}\n\n/**\n * Set of currently-active spawn ids. Tracked in JS so we can fail\n * fast on duplicate ids before the call hits native — the native side\n * silently overwrites a previous spawn under the same id, which\n * leaks processes and orphans their event streams.\n *\n * Auto-clean: an exit event from the native side removes the id; the\n * `kill()` wrapper does the same on demand. If the native fires an\n * exit without our wrapper (rare race), the id stays in the set —\n * worst case is a misleading \"already in use\" error on a subsequent\n * spawn, which is recoverable.\n */\nconst activeSpawnIds = new Set<string>()\n\n// Lazy-attach the exit-event listener on first spawn. Attaching at\n// module-load time runs before the test environment's window-event\n// polyfill is ready (very-happy-dom doesn't ship `addEventListener`),\n// which silently dropped the cleanup hook and made id-reuse tests\n// flake. Doing it on demand sidesteps the load-order race.\nlet exitListenerAttached = false\nfunction ensureExitListener(): void {\n if (exitListenerAttached) return\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') return\n window.addEventListener('craft:shell:exit', (e) => {\n const detail = (e as CustomEvent).detail as { id?: string } | undefined\n if (detail?.id) activeSpawnIds.delete(detail.id)\n })\n exitListenerAttached = true\n}\n\n// Schemes blocked outright in `openExternal`. `javascript:` is the\n// classic XSS vector; `data:` is also dangerous because attacker-\n// controlled HTML can be loaded by the system handler. `file:` is a\n// less obvious one — opening a local file via the OS handler can\n// execute scripts from disk.\nconst BLOCKED_SCHEMES = new Set(['javascript:', 'data:', 'file:', 'vbscript:'])\n\nexport const shell: Shell = {\n async openExternal(url: string): Promise<void> {\n // Reject obviously dangerous schemes — `javascript:` and `data:`\n // can be used by attacker-controlled URLs to execute code in\n // whatever app the OS resolves them to. `file:` is conservative\n // but matches Electron's default behaviour for the same reason.\n const lc = url.trim().toLowerCase()\n for (const s of BLOCKED_SCHEMES) {\n if (lc.startsWith(s)) {\n throw new Error(`shell.openExternal: ${s} URLs are blocked for safety`)\n }\n }\n if (hasBridge('shell')) {\n await window.craft!.shell.openExternal(url)\n return\n }\n if (typeof window !== 'undefined' && typeof window.open === 'function') {\n window.open(url, '_blank', 'noopener,noreferrer')\n }\n },\n\n // These have no sensible web fallback, so they throw via requireBridge.\n // Wrap each in async so the throw arrives as a rejected promise.\n async openPath(path) { await requireBridge('shell').openPath(path) },\n async showInFinder(path) { await requireBridge('shell').showInFinder(path) },\n async spawn(id, command, args = [], opts = {}) {\n ensureExitListener()\n if (!id || typeof id !== 'string') throw new Error('shell.spawn: id must be a non-empty string')\n if (!command || typeof command !== 'string') throw new Error('shell.spawn: command must be a non-empty string')\n if (!Array.isArray(args)) throw new Error('shell.spawn: args must be an array')\n for (const a of args) {\n if (typeof a !== 'string') throw new Error('shell.spawn: args entries must be strings')\n }\n // Track active ids in JS to fail fast on duplicates. Earlier the\n // native side silently overwrote a previous spawn under the same\n // id, leaking the original process and orphaning its event stream.\n if (activeSpawnIds.has(id)) {\n throw new Error(`shell.spawn: id \"${id}\" is already in use — call kill(id) first or pick a different id`)\n }\n activeSpawnIds.add(id)\n try {\n await requireBridge('shell').spawn(id, command, args, opts)\n }\n catch (e) {\n activeSpawnIds.delete(id)\n throw e\n }\n },\n async kill(id) {\n await requireBridge('shell').kill(id)\n activeSpawnIds.delete(id)\n },\n\n async getEnv(name: string): Promise<string | undefined> {\n if (hasBridge('shell')) {\n const v = await window.craft!.shell.getEnv(name)\n return v == null ? undefined : String(v)\n }\n return undefined\n },\n\n async setEnv(name, value) { await requireBridge('shell').setEnv(name, value) },\n onStdout(cb) { return onCraftEvent<ShellOutputEvent>('craft:shell:stdout', cb) },\n onStderr(cb) { return onCraftEvent<ShellOutputEvent>('craft:shell:stderr', cb) },\n onExit(cb) { return onCraftEvent<ShellExitEvent>('craft:shell:exit', cb) },\n}\n",
23
- "/**\n * Global Shortcuts (system-level hotkeys)\n *\n * **Different from `hotkeys.ts`.** That module registers in-window\n * shortcuts via document-level keyboard listeners — they only fire\n * while the Craft window has focus. This module talks to the native\n * `craft.shortcuts` bridge, which uses `RegisterEventHotKey` (macOS) /\n * `RegisterHotKey` (Windows) to make shortcuts fire **even when the\n * app isn't focused.** Choose whichever matches your use case.\n *\n * Browser builds: this module is a graceful no-op (you can call it,\n * but the shortcuts won't fire). Use `hotkeys.ts` for in-window-only\n * shortcuts that should work everywhere.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface GlobalShortcutOptions {\n /**\n * If true, the shortcut continues to fire while the user holds the\n * keys down. Defaults to false (single fire on press).\n */\n repeats?: boolean\n}\n\nexport interface ShortcutFireEvent {\n /** The id passed at registration time. */\n id: string\n /** The accelerator string that triggered this fire. */\n accelerator: string\n /** Epoch ms when the OS dispatched the shortcut. */\n timestamp: number\n}\n\nexport interface GlobalShortcuts {\n /**\n * Register a system-wide hotkey under a stable id.\n * @param id - your identifier; reuse to listen via `on()`.\n * @param accelerator - e.g. `'Cmd+Shift+P'`, `'Ctrl+Alt+Space'`.\n */\n register: (id: string, accelerator: string, opts?: GlobalShortcutOptions) => Promise<void>\n /** Remove a previously-registered hotkey. */\n unregister: (id: string) => Promise<void>\n /** Remove every shortcut this app has registered. */\n unregisterAll: () => Promise<void>\n /** Re-enable a temporarily-disabled shortcut. */\n enable: (id: string) => Promise<void>\n /** Disable a shortcut without removing its registration. */\n disable: (id: string) => Promise<void>\n /** Returns true if `id` is currently registered. */\n isRegistered: (id: string) => Promise<boolean>\n /** List every registered shortcut for this app. */\n list: () => Promise<Array<{ id: string, accelerator: string, enabled: boolean }>>\n /** Subscribe to fire events. Returns an unsubscribe function. */\n on: (cb: (e: ShortcutFireEvent) => void) => () => void\n}\n\nexport const globalShortcuts: GlobalShortcuts = {\n async register(id, accelerator, opts) {\n if (!hasBridge('shortcuts')) return\n await window.craft!.shortcuts.register(id, accelerator, opts)\n },\n async unregister(id) {\n if (!hasBridge('shortcuts')) return\n await window.craft!.shortcuts.unregister(id)\n },\n async unregisterAll() {\n if (!hasBridge('shortcuts')) return\n await window.craft!.shortcuts.unregisterAll()\n },\n async enable(id) {\n if (!hasBridge('shortcuts')) return\n await window.craft!.shortcuts.enable(id)\n },\n async disable(id) {\n if (!hasBridge('shortcuts')) return\n await window.craft!.shortcuts.disable(id)\n },\n async isRegistered(id) {\n if (!hasBridge('shortcuts')) return false\n return await window.craft!.shortcuts.isRegistered(id)\n },\n async list() {\n if (!hasBridge('shortcuts')) return []\n return await window.craft!.shortcuts.list()\n },\n on(cb) {\n return onCraftEvent<ShortcutFireEvent>('craft:shortcut', cb)\n },\n}\n",
24
- "/**\n * System Theme (Light / Dark)\n *\n * Read the OS appearance and subscribe to changes (e.g. macOS auto\n * mode flipping at sunset). When running in a Craft native window the\n * value comes from `NSApplication.effectiveAppearance` (kept in sync\n * via KVO). Browser fallback uses `prefers-color-scheme` media query.\n *\n * The two paths report identical values, so call sites don't need to\n * branch on environment.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport type Appearance = 'light' | 'dark'\n\nexport interface ThemeInfo {\n appearance: Appearance\n}\n\nexport interface SystemTheme {\n /** Synchronous read of the current appearance. */\n get: () => ThemeInfo\n /**\n * Subscribe to appearance changes. Fires once on subscribe with the\n * current value, so call sites don't need a separate `get()` call.\n * Returns an unsubscribe function.\n */\n onChange: (cb: (info: ThemeInfo) => void) => () => void\n /** Promise alternative to `get()`. Useful when you want to await once. */\n current: () => Promise<ThemeInfo>\n}\n\nexport const theme: SystemTheme = {\n get(): ThemeInfo {\n if (hasBridge('theme')) {\n try { return window.craft!.theme.get() } catch { /* fall through */ }\n }\n return { appearance: detectWebAppearance() }\n },\n\n onChange(cb): () => void {\n // Fire immediately so callers don't need a separate snapshot read.\n cb(this.get())\n\n if (hasBridge('theme')) {\n return onCraftEvent<ThemeInfo>('craft:theme', cb)\n }\n\n if (typeof window !== 'undefined' && window.matchMedia) {\n const mq = window.matchMedia('(prefers-color-scheme: dark)')\n const handler = () => cb({ appearance: mq.matches ? 'dark' : 'light' })\n // Use the modern `addEventListener('change', ...)` form. Old Safari\n // (<14) only had `addListener`; that hasn't been supported by stx\n // anyway, so we don't fall back.\n mq.addEventListener('change', handler)\n return () => mq.removeEventListener('change', handler)\n }\n\n return () => {}\n },\n\n async current(): Promise<ThemeInfo> {\n return this.get()\n },\n}\n\nfunction detectWebAppearance(): Appearance {\n if (typeof window === 'undefined' || !window.matchMedia) return 'light'\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'\n}\n",
25
- "/**\n * Drag-out\n *\n * Start a native OS drag from a DOM element so the user can drag a\n * file *out* of the app onto Finder, Slack, an email composer, etc.\n *\n * Browsers can't do this — `dataTransfer.setData('DownloadURL', ...)` is\n * Chrome-specific, deprecated, and gated behind weird user-gesture\n * rules. Inside a Craft window we install a real `NSDraggingItem`-based\n * drag, identical to dragging from Finder.\n *\n * Typical usage:\n *\n * const onMouseDown = (e: MouseEvent) => {\n * dragOut(['/Users/me/export.png'], { event: e })\n * }\n *\n * The mousedown event is preferred over a synthetic call because AppKit\n * uses the current mouse event to anchor the drag preview.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface DragOutOptions {\n /**\n * The mouse event that triggered the drag. Optional — when supplied,\n * the native side anchors the drag preview at the click point.\n */\n event?: MouseEvent\n /** Override anchor x. Used when `event` isn't available. */\n x?: number\n /** Override anchor y. Used when `event` isn't available. */\n y?: number\n}\n\n/**\n * Start a native drag with the given file path(s). Returns a promise\n * that resolves when the drag has *started* (not when it ends — there's\n * no reliable native callback for that without per-source delegate\n * scaffolding, and the OS handles the success path on the destination\n * side anyway).\n *\n * Outside a Craft window this rejects with a descriptive error so\n * callers can offer a fallback (e.g. trigger a download).\n */\nexport async function dragOut(paths: string | string[], options: DragOutOptions = {}): Promise<void> {\n if (!hasBridge('dragOut')) {\n throw new Error('dragOut requires a Craft native window')\n }\n const arr = Array.isArray(paths) ? paths : [paths]\n if (arr.length === 0) throw new Error('dragOut: at least one path required')\n await window.craft!.dragOut.start(arr, options)\n}\n\n/** True when native drag-out is available. */\nexport function isDragOutAvailable(): boolean {\n return hasBridge('dragOut')\n}\n",
26
- "/**\n * Deep Links (Custom URL Schemes)\n *\n * When the OS opens `myapp://path?foo=bar` the URL is delivered into\n * the running process. This module surfaces those URLs to your app.\n *\n * **Required setup on macOS:** declare the scheme in your `Info.plist`\n * under `CFBundleURLTypes`. Craft can't do that for you — bundling is\n * the app's responsibility — but with the entry present, the OS will\n * route URLs into Craft's AppleEvent handler, which fires `craft:deepLink`.\n *\n * **First-launch URLs:** if the app launched *because* the user clicked\n * a deep link, the URL may arrive before your subscriber attaches. Use\n * `getInitialUrl()` after subscribing to recover it.\n *\n * Browser fallback: when not in a Craft window, this module is a\n * graceful no-op (subscriptions never fire). For browser-side custom\n * URL schemes, register a service worker or use `navigator.registerProtocolHandler`.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface DeepLinkEvent {\n /** The full URL the OS delivered, exactly as received. */\n url: string\n}\n\nexport interface DeepLinks {\n /**\n * Subscribe to deep link arrivals. Returns an unsubscribe function.\n * Subscribers do NOT receive past URLs — pair with `getInitialUrl()`\n * to handle the case where the app launched in response to a URL.\n */\n onUrl: (cb: (e: DeepLinkEvent) => void) => () => void\n /**\n * Returns the URL that launched the app, if any. Idempotent — multiple\n * reads return the same value. Use `consumeInitialUrl()` if you only\n * want to handle the launch URL once.\n */\n getInitialUrl: () => string | null\n /**\n * Like `getInitialUrl()` but clears the stored URL after reading.\n * Useful for \"process pending deep link on boot, ignore on re-render\"\n * flows in framework code that mounts/remounts repeatedly.\n */\n consumeInitialUrl: () => string | null\n /** True when the deep-link bridge is available. */\n isAvailable: () => boolean\n}\n\nexport const deepLinks: DeepLinks = {\n onUrl(cb): () => void {\n if (!hasBridge('deepLink')) return () => {}\n return onCraftEvent<DeepLinkEvent>('craft:deepLink', cb)\n },\n getInitialUrl(): string | null {\n if (typeof window === 'undefined') return null\n if (hasBridge('deepLink')) {\n try { return window.craft!.deepLink.getInitialUrl() } catch { return null }\n }\n return window.__craftPendingDeepLink || null\n },\n consumeInitialUrl(): string | null {\n const url = this.getInitialUrl()\n // Native side stores its own copy; we can only clear the JS-side\n // mirror. Subsequent `getInitialUrl()` calls into the bridge will\n // still return the URL until a new one arrives, but\n // `consumeInitialUrl()` returns null on second read, which matches\n // the consume-once contract callers expect.\n if (typeof window !== 'undefined') window.__craftPendingDeepLink = undefined\n return url\n },\n isAvailable(): boolean {\n return hasBridge('deepLink')\n },\n}\n",
27
- "/**\n * Battery & Power State\n *\n * Read battery level, charging status, thermal pressure, and tell the\n * OS to keep the system awake while a long task runs.\n *\n * **Different from `power.ts`** — that module wraps the macOS\n * `caffeinate` *subprocess* (works without a Craft window). This\n * module talks to the native `craft.power` bridge for richer metrics\n * (battery %, thermal state) and uses IOKit's\n * `IOPMAssertionCreateWithName` instead of spawning a child process.\n *\n * Browser fallback: most fields use the deprecated `BatteryManager`\n * API where it's still available; `preventSleep`/`allowSleep` use the\n * Wake Lock API (`navigator.wakeLock.request('screen')`).\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport type ThermalState = 'nominal' | 'fair' | 'serious' | 'critical' | 'unknown'\n\nexport interface BatteryAPI {\n /** True if currently charging (plugged in AND filling). */\n isCharging: () => Promise<boolean>\n /** True if connected to AC power, regardless of fill state. */\n isPluggedIn: () => Promise<boolean>\n /** True if Low Power Mode is on. */\n isLowPowerMode: () => Promise<boolean>\n /**\n * Battery fill, 0..1. Returns null when the system has no battery\n * (typical desktops) so callers can distinguish \"no battery\" from\n * \"fully charged\".\n */\n level: () => Promise<number | null>\n /** Minutes until empty (discharging) or full (charging). null if unknown. */\n timeRemaining: () => Promise<number | null>\n /** OS thermal state. */\n thermalState: () => Promise<ThermalState>\n /** System uptime in seconds. */\n uptimeSeconds: () => Promise<number>\n /**\n * Tell the OS to keep the display/system awake.\n * `reason` is shown in tools like Activity Monitor.\n */\n preventSleep: (reason?: string) => Promise<void>\n /** Release a previous `preventSleep` call. Idempotent. */\n allowSleep: () => Promise<void>\n /** Subscribe to OS sleep events. */\n onSleep: (cb: () => void) => () => void\n /** Subscribe to OS wake events. */\n onWake: (cb: () => void) => () => void\n}\n\nexport const battery: BatteryAPI = {\n async isCharging() {\n if (hasBridge('power')) return await window.craft!.power.isCharging()\n const b = await getWebBatteryManager()\n return b ? !!b.charging : false\n },\n\n async isPluggedIn() {\n if (hasBridge('power')) return await window.craft!.power.isPluggedIn()\n const b = await getWebBatteryManager()\n // BatteryManager has no \"pluggedIn\" — proxy via charging-or-fully-charged.\n return b ? !!b.charging || b.level >= 0.999 : false\n },\n\n async isLowPowerMode() {\n if (hasBridge('power')) return await window.craft!.power.isLowPowerMode()\n return false\n },\n\n async level() {\n if (hasBridge('power')) {\n const v = await window.craft!.power.batteryLevel()\n return typeof v === 'number' ? v : null\n }\n const b = await getWebBatteryManager()\n return b ? b.level : null\n },\n\n async timeRemaining() {\n if (hasBridge('power')) {\n const r = await window.craft!.power.timeRemaining()\n return typeof r === 'number' ? r : null\n }\n const b = await getWebBatteryManager()\n if (!b) return null\n // BatteryManager reports seconds; we return minutes for parity with\n // the native side. Infinity means \"unknown / not on battery.\"\n const sec = b.charging ? b.chargingTime : b.dischargingTime\n return Number.isFinite(sec) ? Math.round(sec / 60) : null\n },\n\n async thermalState() {\n if (hasBridge('power')) {\n const s = await window.craft!.power.thermalState()\n return (s as ThermalState) || 'unknown'\n }\n return 'unknown'\n },\n\n async uptimeSeconds() {\n if (hasBridge('power')) return await window.craft!.power.uptimeSeconds()\n if (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n return Math.round(performance.now() / 1000)\n }\n return 0\n },\n\n async preventSleep(reason = 'app is busy') {\n if (hasBridge('power')) {\n await window.craft!.power.preventSleep(reason)\n return\n }\n // Web fallback: Screen Wake Lock API. Earlier this overwrote the\n // sentinel on every call and silently leaked the previous lock.\n // Now release any in-flight lock first, then acquire fresh — same\n // observable behaviour from the caller's perspective, no leak.\n if (typeof navigator === 'undefined' || !(navigator as any).wakeLock) return\n const w = window as any\n if (w.__craftWebWakeLock?.release) {\n try { await w.__craftWebWakeLock.release() } catch { /* ignore */ }\n w.__craftWebWakeLock = null\n }\n try {\n const sentinel = await (navigator as any).wakeLock.request('screen')\n w.__craftWebWakeLock = sentinel\n }\n catch { /* user denied or unsupported */ }\n },\n\n async allowSleep() {\n if (hasBridge('power')) {\n await window.craft!.power.allowSleep()\n return\n }\n const s = (window as any).__craftWebWakeLock\n if (s && typeof s.release === 'function') {\n try { await s.release() } catch { /* ignore */ }\n ;(window as any).__craftWebWakeLock = null\n }\n },\n\n onSleep(cb) {\n return onCraftEvent<void>('craft:powerSleep', cb)\n },\n onWake(cb) {\n return onCraftEvent<void>('craft:powerWake', cb)\n },\n}\n\nasync function getWebBatteryManager(): Promise<any | null> {\n if (typeof navigator === 'undefined') return null\n const nav = navigator as any\n if (typeof nav.getBattery !== 'function') return null\n try { return await nav.getBattery() } catch { return null }\n}\n",
28
- "/**\n * Network / Reachability\n *\n * Connection type, WiFi info, IP/MAC addresses, VPN status, proxy\n * settings. When running in a Craft native window this dispatches to\n * the `craft.network` bridge (SystemConfiguration on macOS / NLM on\n * Windows / NetworkManager on Linux). Browser fallback uses the\n * `navigator.connection` API where available.\n *\n * Some fields (MAC address, VPN, proxy) are unavailable in browsers\n * for security reasons — they return empty/false there rather than\n * throwing, so feature-detection on the result is the cleanest pattern.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport type ConnectionType =\n| 'wifi'\n| 'ethernet'\n| 'cellular'\n| 'bluetooth'\n| 'vpn'\n| 'none'\n| 'unknown'\n\nexport interface NetworkInterface {\n name: string\n /** IPv4/IPv6 address. */\n address: string\n /** True if the interface is up and has carrier. */\n isUp: boolean\n /** True for loopback (127.0.0.1 / ::1). */\n isLoopback: boolean\n}\n\nexport interface ProxySettings {\n http?: string\n https?: string\n ftp?: string\n socks?: string\n /** Hosts that should bypass the proxy. */\n exceptions?: string[]\n}\n\nexport interface NetworkAPI {\n /** Coarse-grained type of the active connection. */\n connectionType: () => Promise<ConnectionType>\n /** SSID of the joined WiFi network, or undefined if not on WiFi. */\n wifiSSID: () => Promise<string | undefined>\n /** Signal strength in dBm (negative — closer to 0 = stronger). */\n wifiSignalStrength: () => Promise<number | undefined>\n /** Primary IP address. */\n ipAddress: () => Promise<string>\n /** Hardware address of the active interface. May be empty in browsers. */\n macAddress: () => Promise<string>\n /** Every active network interface. */\n interfaces: () => Promise<NetworkInterface[]>\n /** True if a VPN tunnel is up. False on web (always). */\n isVPNConnected: () => Promise<boolean>\n /** System proxy settings. Empty object on web. */\n proxySettings: () => Promise<ProxySettings>\n /** Open the system Network preference pane / settings page. */\n openPreferences: () => Promise<void>\n /** Subscribe to reachability changes. */\n onChange: (cb: (info: { type: ConnectionType, online: boolean }) => void) => () => void\n}\n\nexport const network: NetworkAPI = {\n async connectionType() {\n if (hasBridge('network')) return await window.craft!.network.connectionType()\n return webConnectionType()\n },\n async wifiSSID() {\n if (hasBridge('network')) {\n const v = await window.craft!.network.wifiSSID()\n return v || undefined\n }\n return undefined\n },\n async wifiSignalStrength() {\n if (hasBridge('network')) {\n const v = await window.craft!.network.wifiSignalStrength()\n return typeof v === 'number' ? v : undefined\n }\n return undefined\n },\n async ipAddress() {\n if (hasBridge('network')) return await window.craft!.network.ipAddress()\n return ''\n },\n async macAddress() {\n if (hasBridge('network')) return await window.craft!.network.macAddress()\n return ''\n },\n async interfaces() {\n if (hasBridge('network')) return await window.craft!.network.interfaces()\n return []\n },\n async isVPNConnected() {\n if (hasBridge('network')) return await window.craft!.network.isVPNConnected()\n return false\n },\n async proxySettings() {\n if (hasBridge('network')) {\n const r = await window.craft!.network.proxySettings()\n return r || {}\n }\n return {}\n },\n async openPreferences() {\n if (hasBridge('network')) await window.craft!.network.openPreferences()\n },\n onChange(cb): () => void {\n if (hasBridge('network')) {\n return onCraftEvent<{ type: ConnectionType, online: boolean }>('craft:networkChange', cb)\n }\n if (typeof window === 'undefined') return () => {}\n const onlineH = () => cb({ type: webConnectionType(), online: true })\n const offlineH = () => cb({ type: 'none', online: false })\n window.addEventListener('online', onlineH)\n window.addEventListener('offline', offlineH)\n return () => {\n window.removeEventListener('online', onlineH)\n window.removeEventListener('offline', offlineH)\n }\n },\n}\n\nfunction webConnectionType(): ConnectionType {\n if (typeof navigator === 'undefined') return 'unknown'\n if (navigator.onLine === false) return 'none'\n const conn = (navigator as any).connection\n if (!conn) return 'unknown'\n // navigator.connection.type: 'wifi'|'cellular'|'ethernet'|'bluetooth'|'wimax'|'none'|'other'|'unknown'\n const t = String(conn.type || conn.effectiveType || 'unknown').toLowerCase()\n if (t === 'wifi' || t === 'cellular' || t === 'ethernet' || t === 'bluetooth' || t === 'none') return t\n return 'unknown'\n}\n",
29
- "/**\n * Auto-Updater\n *\n * Configure and trigger app updates. On macOS this routes to Sparkle\n * (`SUUpdater`); on Windows to WinSparkle; on Linux to a custom feed\n * checker. The shape of the API is provider-neutral — a feed URL plus\n * \"check now\" / \"check in background.\"\n *\n * Apps still need to bundle the updater framework and ship signed\n * appcasts; Craft only exposes the runtime knobs and event surface.\n *\n * Browser fallback: this module is an inert no-op (calls resolve, but\n * nothing happens). Outside a native shell there's no update flow.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface UpdateInfo {\n version: string\n releaseDate?: string\n releaseNotes?: string\n /** Direct download URL for the new build. */\n downloadUrl?: string\n}\n\nexport interface VerifyOptions {\n /** Raw bytes of the update bundle (zip / dmg / msi / appimage). */\n payload: Uint8Array | ArrayBuffer\n /** Base64-encoded Ed25519 signature over `payload`. */\n signatureB64: string\n /** Base64-encoded raw Ed25519 public key (32 bytes). */\n publicKeyB64: string\n}\n\nexport interface VerifyDownloadOptions {\n /** Where to fetch the bundle from. */\n url: string\n /** Base64-encoded Ed25519 signature over the bundle bytes. */\n signatureB64: string\n /** Base64-encoded raw Ed25519 public key (32 bytes). */\n publicKeyB64: string\n /** Optional fetch init (timeout / auth headers / etc.). */\n fetchInit?: RequestInit\n}\n\nexport interface VerifyDownloadResult {\n ok: boolean\n /** The downloaded bytes — only populated when `ok === true`. */\n payload?: Uint8Array\n /** When `ok === false`, why. */\n reason?: 'fetch-failed' | 'http-error' | 'bad-signature' | 'bad-key'\n /** HTTP status when applicable. */\n status?: number\n}\n\nexport interface Updater {\n /** Show the updater UI and check for updates. */\n checkForUpdates: () => Promise<void>\n /** Silent check — no UI unless an update is found. */\n checkInBackground: () => Promise<void>\n /** Toggle scheduled background checks. */\n setAutomaticChecks: (on: boolean) => Promise<void>\n /** Background check interval in seconds. Default is provider-defined. */\n setCheckInterval: (seconds: number) => Promise<void>\n /** Set the appcast URL. Persists across launches. */\n setFeedURL: (url: string) => Promise<void>\n /** ISO date of the most recent check, or null. */\n getLastUpdateCheckDate: () => Promise<string | null>\n /** Latest known update info if an update has been found, else null. */\n getUpdateInfo: () => Promise<UpdateInfo | null>\n /** Subscribe to \"update available\" events. */\n onAvailable: (cb: (info: UpdateInfo) => void) => () => void\n /** Subscribe to \"update downloaded and ready to install\" events. */\n onDownloaded: (cb: (info: UpdateInfo) => void) => () => void\n /**\n * Verify an in-memory bundle against an Ed25519 signature. Sparkle-style:\n * publisher signs the file with their Ed25519 private key, the app pins\n * the matching public key, and rejects bundles whose signature doesn't\n * verify before staging the install.\n */\n verifySignature: (options: VerifyOptions) => Promise<boolean>\n /**\n * Fetch a bundle and verify its signature in one shot. On success the\n * downloaded bytes come back so the caller can hand them to the native\n * installer; on failure the `reason` says why so the UI can surface it.\n */\n verifyDownload: (options: VerifyDownloadOptions) => Promise<VerifyDownloadResult>\n}\n\nexport const updater: Updater = {\n async checkForUpdates() {\n if (!hasBridge('updater')) return\n await window.craft!.updater.checkForUpdates()\n },\n async checkInBackground() {\n if (!hasBridge('updater')) return\n await window.craft!.updater.checkInBackground()\n },\n async setAutomaticChecks(on: boolean) {\n if (!hasBridge('updater')) return\n await window.craft!.updater.setAutomaticChecks(on)\n },\n async setCheckInterval(seconds: number) {\n if (!hasBridge('updater')) return\n // Sparkle / WinSparkle interpret a 0 or negative interval as\n // \"disable scheduled checks\" via the API of their respective\n // platforms — but several callers report unstable behaviour when\n // setting a tiny positive interval (e.g. 1s = check storm). Clamp\n // to a sensible range: ≤0 disables, ≥60s otherwise.\n if (!Number.isFinite(seconds)) {\n throw new Error('setCheckInterval: must be a finite number')\n }\n const safe = seconds <= 0 ? 0 : Math.max(60, Math.round(seconds))\n await window.craft!.updater.setCheckInterval(safe)\n },\n async setFeedURL(url: string) {\n if (!hasBridge('updater')) return\n await window.craft!.updater.setFeedURL(url)\n },\n async getLastUpdateCheckDate() {\n if (!hasBridge('updater')) return null\n const v = await window.craft!.updater.getLastUpdateCheckDate()\n return v || null\n },\n async getUpdateInfo() {\n if (!hasBridge('updater')) return null\n const v = await window.craft!.updater.getUpdateInfo()\n // Earlier `!v.version` rejected `'0.0.0'` (a valid downgrade\n // marker some apps use during testing). Distinguish \"no info\" from\n // \"info with version\" by checking presence of the field.\n if (!v || typeof v.version !== 'string' || v.version.length === 0) return null\n return v as UpdateInfo\n },\n onAvailable(cb) {\n return onCraftEvent<UpdateInfo>('craft:updateAvailable', cb)\n },\n onDownloaded(cb) {\n return onCraftEvent<UpdateInfo>('craft:updateDownloaded', cb)\n },\n\n async verifySignature({ payload, signatureB64, publicKeyB64 }) {\n const data = toArrayBufferBytes(payload)\n let publicKey: CryptoKey\n try {\n publicKey = await crypto.subtle.importKey(\n 'raw',\n base64ToBytes(publicKeyB64),\n { name: 'Ed25519' },\n false,\n ['verify'],\n )\n }\n catch {\n return false\n }\n try {\n return await crypto.subtle.verify('Ed25519', publicKey, base64ToBytes(signatureB64), data)\n }\n catch {\n return false\n }\n },\n\n async verifyDownload({ url, signatureB64, publicKeyB64, fetchInit }) {\n let response: Response\n try {\n response = await fetch(url, fetchInit)\n }\n catch {\n return { ok: false, reason: 'fetch-failed' }\n }\n if (!response.ok) {\n return { ok: false, reason: 'http-error', status: response.status }\n }\n const buffer = new Uint8Array(await response.arrayBuffer())\n\n let publicKey: CryptoKey\n try {\n publicKey = await crypto.subtle.importKey(\n 'raw',\n base64ToBytes(publicKeyB64),\n { name: 'Ed25519' },\n false,\n ['verify'],\n )\n }\n catch {\n return { ok: false, reason: 'bad-key' }\n }\n\n let valid = false\n try {\n valid = await crypto.subtle.verify('Ed25519', publicKey, base64ToBytes(signatureB64), toArrayBufferBytes(buffer))\n }\n catch {\n valid = false\n }\n if (!valid) return { ok: false, reason: 'bad-signature' }\n return { ok: true, payload: buffer }\n },\n}\n\n/**\n * Coerce arbitrary `BufferSource`-ish input into a `Uint8Array` whose\n * underlying storage is a plain `ArrayBuffer`. The Web Crypto types\n * insist on `ArrayBufferView<ArrayBuffer>`, which excludes the looser\n * `ArrayBufferLike` (covers `SharedArrayBuffer`) you get back from\n * `Response.arrayBuffer()` under TS strict mode.\n */\nfunction toArrayBufferBytes(input: Uint8Array | ArrayBuffer): Uint8Array<ArrayBuffer> {\n if (input instanceof ArrayBuffer) return new Uint8Array(input)\n // Copy into a fresh ArrayBuffer to satisfy the strict crypto types\n // even when the source view points at a SharedArrayBuffer.\n const out = new ArrayBuffer(input.byteLength)\n const view = new Uint8Array(out)\n view.set(input)\n return view\n}\n\nfunction base64ToBytes(b64: string): Uint8Array<ArrayBuffer> {\n // atob exists in webview + Bun; if neither (older Node test runner), fall\n // back to a hand-rolled decoder so this module loads everywhere.\n if (typeof atob === 'function') {\n const bin = atob(b64)\n const buffer = new ArrayBuffer(bin.length)\n const out = new Uint8Array(buffer)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out\n }\n // eslint-disable-next-line node/prefer-global/buffer\n const node = Buffer.from(b64, 'base64')\n const buf = new ArrayBuffer(node.length)\n new Uint8Array(buf).set(node)\n return new Uint8Array(buf)\n}\n",
30
- "/**\n * Window Lifecycle Events\n *\n * Subscribe to focus, blur, resize, move, minimize, restore, and close\n * events on the main Craft window. Backed by an `NSWindowDelegate` on\n * the macOS side; in browser builds these fall back to the equivalent\n * `window.addEventListener('focus' | 'blur' | 'resize' | 'beforeunload')`.\n *\n * **Note on close:** the native `onClose` event fires *after* AppKit\n * has committed to closing — you can't `event.preventDefault()` from\n * here. For a real \"are you sure you want to close?\" gate, attach\n * `beforeunload` in JS, which fires before AppKit's close path runs.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface WindowSize {\n /**\n * Stable window identifier — opaque string. In multi-window apps, use\n * this to correlate events back to the right window. Single-window\n * apps can ignore it.\n */\n id?: string\n width: number\n height: number\n}\n\nexport interface WindowPosition {\n id?: string\n x: number\n y: number\n}\n\nexport interface WindowEvents {\n /** Window became key (received focus). */\n onFocus: (cb: () => void) => () => void\n /** Window lost focus / resigned key state. */\n onBlur: (cb: () => void) => () => void\n /** Window was resized. Detail contains the new size. */\n onResize: (cb: (size: WindowSize) => void) => () => void\n /** Window was moved. Detail contains the new origin. */\n onMove: (cb: (pos: WindowPosition) => void) => () => void\n /** Window is closing (fires after AppKit commits — not interceptable). */\n onClose: (cb: () => void) => () => void\n /** Window was minimized to the dock. */\n onMinimize: (cb: () => void) => () => void\n /** Window was restored from minimize. */\n onRestore: (cb: () => void) => () => void\n}\n\nexport const windowEvents: WindowEvents = {\n onFocus(cb) {\n if (hasBridge('window')) return onCraftEvent('craft:window:focus', () => cb())\n return webEvent('focus', cb)\n },\n onBlur(cb) {\n if (hasBridge('window')) return onCraftEvent('craft:window:blur', () => cb())\n return webEvent('blur', cb)\n },\n onResize(cb) {\n if (hasBridge('window')) return onCraftEvent<WindowSize>('craft:window:resize', cb)\n if (typeof window === 'undefined') return () => {}\n const h = () => cb({ width: window.innerWidth, height: window.innerHeight })\n window.addEventListener('resize', h)\n return () => window.removeEventListener('resize', h)\n },\n onMove(cb) {\n if (hasBridge('window')) return onCraftEvent<WindowPosition>('craft:window:move', cb)\n // Browsers don't expose window-position changes, so this is no-op\n // outside Craft. Returning the same shape keeps callers branchless.\n return () => {}\n },\n onClose(cb) {\n if (hasBridge('window')) return onCraftEvent('craft:window:close', () => cb())\n return webEvent('beforeunload', cb)\n },\n onMinimize(cb) {\n if (hasBridge('window')) return onCraftEvent('craft:window:minimize', () => cb())\n // Closest browser equivalent is visibilitychange → 'hidden'.\n if (typeof document === 'undefined') return () => {}\n const h = () => { if (document.visibilityState === 'hidden') cb() }\n document.addEventListener('visibilitychange', h)\n return () => document.removeEventListener('visibilitychange', h)\n },\n onRestore(cb) {\n if (hasBridge('window')) return onCraftEvent('craft:window:restore', () => cb())\n if (typeof document === 'undefined') return () => {}\n const h = () => { if (document.visibilityState === 'visible') cb() }\n document.addEventListener('visibilitychange', h)\n return () => document.removeEventListener('visibilitychange', h)\n },\n}\n\nfunction webEvent(name: string, cb: () => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const h = () => cb()\n window.addEventListener(name, h)\n return () => window.removeEventListener(name, h)\n}\n",
31
- "/**\n * App Metadata + Process Controls\n *\n * Companion to `window.ts`. While that module is about the visible\n * window, this is about the *application* — bundle metadata, dock\n * badge, dock-icon bounce.\n *\n * Outside a Craft window, the metadata getters return best-effort\n * defaults (empty / \"0.0.0\") so call sites can render an About panel\n * without branching on environment.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface AppInfo {\n /** Bundle name (e.g. \"Photo Booth\"). */\n name: string\n /** CFBundleShortVersionString — the user-facing version. */\n version: string\n /** Bundle identifier (e.g. \"com.example.app\"). */\n bundleId?: string\n /** Absolute path to the .app bundle. */\n bundlePath?: string\n /** Path to the executable inside the bundle. */\n executablePath?: string\n}\n\nexport interface AppNotifyOptions {\n title: string\n body?: string\n /** macOS UNNotificationSound name, or 'default'. */\n sound?: string\n}\n\nexport interface AppAPI {\n /** Hide the dock icon (turn the app into a menubar-only / accessory app). */\n hideDockIcon: () => Promise<void>\n /** Restore the dock icon. */\n showDockIcon: () => Promise<void>\n /** Quit the application. */\n quit: () => Promise<void>\n /** Read bundle metadata. Resolves to defaults outside Craft. */\n getInfo: () => Promise<AppInfo>\n /** Post a system notification (alias for `notifications.show` with smaller surface). */\n notify: (options: AppNotifyOptions) => Promise<void>\n /** Set the dock-icon badge. Pass 0 to clear. */\n setBadge: (count: number) => Promise<void>\n /**\n * Bounce the dock icon to draw attention.\n * `'critical'` keeps bouncing until the user activates the app;\n * `'informational'` bounces once.\n */\n bounce: (type?: 'critical' | 'informational') => Promise<void>\n}\n\nconst DEFAULT_INFO: AppInfo = { name: '', version: '0.0.0' }\n\nexport const app: AppAPI = {\n async hideDockIcon() { if (hasBridge('app')) await window.craft!.app.hideDockIcon() },\n async showDockIcon() { if (hasBridge('app')) await window.craft!.app.showDockIcon() },\n async quit() { if (hasBridge('app')) await window.craft!.app.quit() },\n async getInfo() {\n if (!hasBridge('app')) return DEFAULT_INFO\n const r = await window.craft!.app.getInfo()\n return { ...DEFAULT_INFO, ...(r || {}) }\n },\n async notify(options) {\n if (!options.title) throw new Error('notify: title is required')\n if (hasBridge('app')) await window.craft!.app.notify(options)\n },\n async setBadge(count: number) {\n if (hasBridge('app')) await window.craft!.app.setBadge(count)\n },\n async bounce(type = 'informational') {\n if (hasBridge('app')) await window.craft!.app.bounce(type)\n },\n}\n",
32
- "/**\n * Application Menu (macOS top-of-screen menubar) + Dock Menu\n *\n * Build the native menubar (`File`, `Edit`, `View`, ...) and the\n * dock-icon contextual menu. When running outside a Craft window this\n * module is a no-op — there's no portable web equivalent to the\n * macOS menubar.\n *\n * Each menu item is identified by an `id`. The native side fires a\n * `craft:menu:action` event with `{id}` when the user picks it; use\n * `menu.onAction(cb)` to listen.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface MenuItem {\n /** Stable identifier. The same id is reported by `onAction`. */\n id: string\n /** Visible label. */\n label?: string\n /**\n * Apple's stock menu roles (e.g. `'copy'`, `'paste'`, `'close'`,\n * `'quit'`). When set, AppKit hooks the system behaviour for free\n * — you don't need to reimplement Copy/Paste yourself.\n */\n role?: string\n /** Keyboard accelerator (e.g. `'Cmd+S'`). */\n accelerator?: string\n /** True for a separator line. Other fields ignored. */\n separator?: boolean\n /** Render as a checkbox; toggle via `menu.checkItem(id)`. */\n checkable?: boolean\n /** Initial checked state for checkable items. */\n checked?: boolean\n /** Disabled at startup (still renders, can't be picked). */\n disabled?: boolean\n /** Submenu under this item. */\n submenu?: MenuItem[]\n /** SF Symbol or asset name (macOS only). */\n icon?: string\n}\n\nexport interface MenuActionEvent {\n id: string\n}\n\nexport interface MenuAPI {\n /** Set the application menu (replaces the entire menubar). */\n set: (items: MenuItem[]) => Promise<void>\n /** Set the dock-icon contextual menu. */\n setDock: (items: MenuItem[]) => Promise<void>\n /** Append an item under the parent id (or top-level if parent is \"\" or \"menubar\"). */\n addItem: (parent: string, item: MenuItem) => Promise<void>\n removeItem: (id: string) => Promise<void>\n enableItem: (id: string) => Promise<void>\n disableItem: (id: string) => Promise<void>\n checkItem: (id: string) => Promise<void>\n uncheckItem: (id: string) => Promise<void>\n setItemLabel: (id: string, label: string) => Promise<void>\n /** Clear the dock-icon contextual menu. */\n clearDock: () => Promise<void>\n /** Subscribe to \"user picked a menu item\" events. */\n onAction: (cb: (event: MenuActionEvent) => void) => () => void\n}\n\nexport const menu: MenuAPI = {\n async set(items) {\n if (hasBridge('menu')) await window.craft!.menu.set(items)\n },\n async setDock(items) {\n if (hasBridge('menu')) await window.craft!.menu.setDock(items)\n },\n async addItem(parent, item) {\n if (hasBridge('menu')) await window.craft!.menu.addItem(parent, item)\n },\n async removeItem(id) { if (hasBridge('menu')) await window.craft!.menu.removeItem(id) },\n async enableItem(id) { if (hasBridge('menu')) await window.craft!.menu.enableItem(id) },\n async disableItem(id) { if (hasBridge('menu')) await window.craft!.menu.disableItem(id) },\n async checkItem(id) { if (hasBridge('menu')) await window.craft!.menu.checkItem(id) },\n async uncheckItem(id) { if (hasBridge('menu')) await window.craft!.menu.uncheckItem(id) },\n async setItemLabel(id, lbl) { if (hasBridge('menu')) await window.craft!.menu.setItemLabel(id, lbl) },\n async clearDock() { if (hasBridge('menu')) await window.craft!.menu.clearDock() },\n onAction(cb) {\n return onCraftEvent<MenuActionEvent>('craft:menu:action', cb)\n },\n}\n",
33
- "/**\n * System / Host Info\n *\n * Read the OS-level facts an app needs for \"render correctly on this\n * machine\" — accent colour, locale, timezone, accessibility flags\n * (reduce motion / contrast / transparency), system version, hostname.\n *\n * In a browser, falls back to whatever standard web APIs surface\n * (mostly `Intl.DateTimeFormat().resolvedOptions()` + `matchMedia` for\n * the accessibility flags).\n */\nimport { hasBridge } from './_bridge'\n\nexport interface SystemInfo {\n /** macOS accent colour as a hex string (\"#0a84ff\"). Empty in browser. */\n accentColor: () => Promise<string>\n /** Selection / text-selection highlight colour. Empty in browser. */\n highlightColor: () => Promise<string>\n /** Primary user language code (e.g. \"en\"). */\n language: () => Promise<string>\n /** BCP-47 locale (e.g. \"en-US\"). */\n locale: () => Promise<string>\n /** IANA timezone name (e.g. \"America/Los_Angeles\"). */\n timezone: () => Promise<string>\n /** True if the user prefers 24-hour time. */\n is24HourTime: () => Promise<boolean>\n /** True if the user has Reduce Motion enabled. */\n reduceMotion: () => Promise<boolean>\n /** True if the user has Reduce Transparency enabled. */\n reduceTransparency: () => Promise<boolean>\n /** True if the user has Increase Contrast enabled. */\n increaseContrast: () => Promise<boolean>\n /** OS version string (e.g. \"14.4.1\"). */\n systemVersion: () => Promise<string>\n /** Machine hostname. Empty in browser. */\n hostname: () => Promise<string>\n /** Login username. Empty in browser. */\n username: () => Promise<string>\n /** Open System Settings / Preferences. */\n openPreferences: () => Promise<void>\n}\n\nexport const system: SystemInfo = {\n accentColor: () => bridgeOr('system', 'accentColor', () => ''),\n highlightColor: () => bridgeOr('system', 'highlightColor', () => ''),\n language: () => bridgeOr('system', 'language', () => {\n if (typeof navigator === 'undefined') return ''\n return navigator.language?.split('-')[0] || ''\n }),\n locale: () => bridgeOr('system', 'locale', () => {\n if (typeof navigator === 'undefined') return ''\n return navigator.language || ''\n }),\n timezone: () => bridgeOr('system', 'timezone', () => {\n try { return Intl.DateTimeFormat().resolvedOptions().timeZone || '' } catch { return '' }\n }),\n is24HourTime: () => bridgeOr('system', 'is24HourTime', () => {\n try {\n const opts = new Intl.DateTimeFormat([], { hour: 'numeric' }).resolvedOptions() as any\n return opts.hourCycle === 'h23' || opts.hourCycle === 'h24'\n }\n catch { return false }\n }),\n reduceMotion: () => bridgeOr('system', 'reduceMotion', () => mediaMatches('(prefers-reduced-motion: reduce)')),\n reduceTransparency: () => bridgeOr('system', 'reduceTransparency', () => mediaMatches('(prefers-reduced-transparency: reduce)')),\n increaseContrast: () => bridgeOr('system', 'increaseContrast', () => mediaMatches('(prefers-contrast: more)')),\n systemVersion: () => bridgeOr('system', 'systemVersion', () => ''),\n hostname: () => bridgeOr('system', 'hostname', () => ''),\n username: () => bridgeOr('system', 'username', () => ''),\n async openPreferences() {\n if (hasBridge('system')) await window.craft!.system.openPreferences()\n },\n}\n\nasync function bridgeOr<T>(ns: string, method: string, fallback: () => T | Promise<T>): Promise<T> {\n if (hasBridge(ns)) return (await window.craft![ns][method]()) as T\n return await fallback()\n}\n\nfunction mediaMatches(query: string): boolean {\n if (typeof window === 'undefined' || !window.matchMedia) return false\n return window.matchMedia(query).matches\n}\n",
34
- "/**\n * Display / Screen Info\n *\n * Multi-monitor info: every connected display's bounds, work area\n * (excluding menu bar + dock), and `backingScaleFactor` (1.0 / 2.0).\n *\n * Browser fallback returns a single Display synthesised from\n * `window.screen`, which is \"good enough\" for layout heuristics but\n * misses secondary monitors (browsers can't see those).\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface Display {\n /** Stable id within this app run (0 = primary). */\n id: number\n /** Full screen rect (origin in AppKit / display-space coords). */\n x: number\n y: number\n width: number\n height: number\n /** Work area excluding menu bar + dock. */\n workX: number\n workY: number\n workWidth: number\n workHeight: number\n /** 1.0 (Retina = 2.0). Multiply CSS px by this for device px. */\n scaleFactor: number\n}\n\nexport interface ScreenAPI {\n /** Every connected display. */\n getDisplays: () => Promise<Display[]>\n /** The primary display (the one with the menu bar). */\n getPrimary: () => Promise<Display | null>\n /**\n * Subscribe to display-arrangement changes — monitor hot-plug,\n * resolution change, dock relocation. The callback receives no\n * payload; re-fetch with `getDisplays()` to read the new state.\n */\n onChange: (cb: () => void) => () => void\n}\n\nexport const screen: ScreenAPI = {\n async getDisplays() {\n if (hasBridge('screen')) return await window.craft!.screen.getDisplays()\n return webDisplays()\n },\n async getPrimary() {\n if (hasBridge('screen')) {\n const r = await window.craft!.screen.getPrimary()\n return r && typeof r.width === 'number' ? r : null\n }\n return webDisplays()[0] ?? null\n },\n onChange(cb) {\n if (hasBridge('screen')) return onCraftEvent('craft:screen:change', () => cb())\n // Web fallback: window-level resize events. Not strictly equivalent\n // — they fire for window resizes too, not just monitor changes —\n // but it's the closest thing browsers expose.\n if (typeof window === 'undefined') return () => {}\n const h = () => cb()\n window.addEventListener('resize', h)\n return () => window.removeEventListener('resize', h)\n },\n}\n\nfunction webDisplays(): Display[] {\n if (typeof window === 'undefined' || !window.screen) return []\n const s = window.screen as any\n return [{\n id: 0,\n x: s.left ?? 0,\n y: s.top ?? 0,\n width: s.width || 0,\n height: s.height || 0,\n workX: s.availLeft ?? 0,\n workY: s.availTop ?? 0,\n workWidth: s.availWidth ?? s.width ?? 0,\n workHeight: s.availHeight ?? s.height ?? 0,\n scaleFactor: window.devicePixelRatio || 1,\n }]\n}\n",
35
- "/**\n * Keychain — Secure Secret Storage\n *\n * Wraps platform-specific credential stores: macOS Keychain Services,\n * iOS Keychain, Windows Credential Manager, Linux Secret Service\n * (D-Bus / GNOME Keyring).\n *\n * Use this for OAuth refresh tokens, API keys, login passwords —\n * anything you'd be uncomfortable storing in `localStorage`. Items\n * are scoped under a `service` namespace, typically your app's\n * bundle identifier.\n *\n * No web fallback. The whole point is OS-protected storage; falling\n * back to localStorage would silently downgrade security guarantees.\n * Calls outside a Craft window throw.\n */\nimport { requireBridge } from './_bridge'\n\nexport interface KeychainAPI {\n /**\n * Store a secret. Overwrites any existing entry under (service, account).\n * The password may be any UTF-8 string.\n */\n set: (service: string, account: string, password: string) => Promise<void>\n /**\n * Read a secret. Returns `null` (not undefined) if no entry exists,\n * so callers can distinguish \"not found\" from \"found, value is empty\".\n */\n get: (service: string, account: string) => Promise<string | null>\n /** Delete a secret. No-op if it doesn't exist. */\n delete: (service: string, account: string) => Promise<void>\n /** Check whether a secret exists, without reading it (no decrypt cost). */\n has: (service: string, account: string) => Promise<boolean>\n}\n\nexport const keychain: KeychainAPI = {\n async set(service, account, password) {\n if (!service) throw new Error('keychain.set: service is required')\n if (!account) throw new Error('keychain.set: account is required')\n await requireBridge('keychain').set(service, account, password)\n },\n async get(service, account) {\n if (!service) throw new Error('keychain.get: service is required')\n if (!account) throw new Error('keychain.get: account is required')\n const v = await requireBridge('keychain').get(service, account)\n return typeof v === 'string' ? v : null\n },\n async delete(service, account) {\n if (!service) throw new Error('keychain.delete: service is required')\n if (!account) throw new Error('keychain.delete: account is required')\n await requireBridge('keychain').delete(service, account)\n },\n async has(service, account) {\n if (!service) throw new Error('keychain.has: service is required')\n if (!account) throw new Error('keychain.has: account is required')\n return await requireBridge('keychain').has(service, account)\n },\n}\n",
36
- "/**\n * Privacy Permissions\n *\n * Check and request OS-level permission for sensitive capabilities\n * (camera, microphone, screen recording, etc). Wraps macOS TCC\n * (`AVCaptureDevice authorizationStatusForMediaType:`) and equivalents.\n *\n * Browser fallback uses the (limited) `navigator.permissions.query`\n * API where available — note that the web API only knows about a small\n * subset of names ('camera', 'microphone', 'geolocation', 'notifications').\n */\nimport { hasBridge } from './_bridge'\n\n/** Status values match the macOS TCC convention. */\nexport type PermissionStatus = 'granted' | 'denied' | 'restricted' | 'undetermined' | 'not-supported'\n\nexport type PermissionName =\n| 'camera'\n| 'microphone'\n| 'screen_recording'\n| 'accessibility'\n| 'full_disk_access'\n| 'input_monitoring'\n| 'location'\n| 'notifications'\n| 'contacts'\n| 'calendar'\n| 'reminders'\n| 'photos'\n| 'bluetooth'\n\nexport interface PermissionsAPI {\n /** Read current status without prompting. */\n check: (name: PermissionName) => Promise<PermissionStatus>\n /**\n * Request permission. On macOS this triggers the system modal for\n * permissions that haven't been answered yet; for ones already in\n * a non-undetermined state, the user has to flip it manually in\n * System Settings — call `openSettings(name)` to jump them there.\n */\n request: (name: PermissionName) => Promise<PermissionStatus>\n /** Open the Privacy pane scoped to the named permission. */\n openSettings: (name?: PermissionName) => Promise<void>\n}\n\nexport const permissions: PermissionsAPI = {\n async check(name) {\n if (hasBridge('permissions')) return await window.craft!.permissions.check(name)\n return await webCheck(name)\n },\n async request(name) {\n if (hasBridge('permissions')) return await window.craft!.permissions.request(name)\n return await webRequest(name)\n },\n async openSettings(name) {\n if (hasBridge('permissions')) await window.craft!.permissions.openSettings(name)\n },\n}\n\nasync function webCheck(name: PermissionName): Promise<PermissionStatus> {\n if (typeof navigator === 'undefined' || !(navigator as any).permissions?.query) return 'not-supported'\n try {\n const result = await (navigator as any).permissions.query({ name })\n return mapWebState(result.state)\n }\n catch { return 'not-supported' }\n}\n\nasync function webRequest(name: PermissionName): Promise<PermissionStatus> {\n // The web has no general-purpose `request` — most APIs prompt\n // implicitly when you try to use them. We special-case the well-known\n // ones and otherwise fall back to a `check`.\n if (name === 'notifications' && typeof window !== 'undefined' && 'Notification' in window) {\n const r = await (window as any).Notification.requestPermission()\n return r === 'granted' ? 'granted' : r === 'denied' ? 'denied' : 'undetermined'\n }\n return await webCheck(name)\n}\n\nfunction mapWebState(s: string): PermissionStatus {\n if (s === 'granted') return 'granted'\n if (s === 'denied') return 'denied'\n if (s === 'prompt') return 'undetermined'\n return 'undetermined'\n}\n",
37
- "/**\n * Printing\n *\n * Print the current page (system print sheet) or save it as a PDF.\n * Uses `[WKWebView printOperationWithPrintInfo:]` on macOS — i.e.\n * the same code path Safari uses.\n *\n * Browser fallback uses `window.print()` for `print()`. There's no\n * portable web equivalent for \"silently save current page as PDF\" —\n * that path throws.\n */\nimport { hasBridge, requireBridge } from './_bridge'\n\nexport interface PrintToPDFResult {\n ok: boolean\n /** Where the PDF was written. */\n path?: string\n}\n\nexport interface PrintingAPI {\n /** Open the system print sheet for the current webview. */\n print: () => Promise<void>\n /** Render the current page to a PDF on disk. Path must be absolute. */\n printToPDF: (path: string) => Promise<PrintToPDFResult>\n}\n\nexport const printing: PrintingAPI = {\n async print() {\n if (hasBridge('printing')) {\n await window.craft!.printing.print()\n return\n }\n if (typeof window !== 'undefined' && typeof window.print === 'function') {\n window.print()\n }\n },\n\n async printToPDF(path: string): Promise<PrintToPDFResult> {\n if (!path) throw new Error('printToPDF: path is required')\n // Earlier we only accepted POSIX-style absolute paths (starts with\n // `/`), which broke on Windows where `C:\\Users\\...` is the norm.\n // Accept either: POSIX `/` prefix OR Windows drive-letter prefix\n // (`X:\\` or `X:/`). UNC paths (`\\\\server\\share`) also welcome.\n const isPosixAbs = path.startsWith('/')\n const isWinAbs = /^[a-zA-Z]:[\\\\/]/.test(path) || path.startsWith('\\\\\\\\')\n if (!isPosixAbs && !isWinAbs) {\n throw new Error('printToPDF: path must be absolute')\n }\n const r = await requireBridge('printing').printToPDF(path)\n return { ok: !!(r && r.ok), path: r?.path }\n },\n}\n",
38
- "/**\n * Native Auto-Launch (start at login)\n *\n * Tells the OS to launch the app automatically when the user signs in.\n * Backed by `SMAppService` on macOS Ventura+. **Different from\n * `autolaunch.ts`** — that older module shells out to subprocesses\n * (`osascript`, etc); this one uses the modern Apple API.\n *\n * For a clean migration: prefer this module for new code. Keep\n * `autolaunch.ts` for backward compatibility with apps that haven't\n * adopted the Craft bridge yet.\n *\n * On systems where SMAppService isn't available (older macOS, Linux,\n * Windows) `enable`/`disable` resolve to `false` — let the caller\n * fall back to the legacy module.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface NativeAutoLaunchAPI {\n /** Register the app to launch at login. Resolves to true on success. */\n enable: () => Promise<boolean>\n /** Unregister. Resolves to true on success. */\n disable: () => Promise<boolean>\n /** True if currently registered. */\n isEnabled: () => Promise<boolean>\n}\n\nexport const nativeAutoLaunch: NativeAutoLaunchAPI = {\n async enable() {\n if (!hasBridge('autoLaunch')) return false\n return await window.craft!.autoLaunch.enable()\n },\n async disable() {\n if (!hasBridge('autoLaunch')) return false\n return await window.craft!.autoLaunch.disable()\n },\n async isEnabled() {\n if (!hasBridge('autoLaunch')) return false\n return await window.craft!.autoLaunch.isEnabled()\n },\n}\n",
39
- "/**\n * Touch Bar (legacy macOS hardware)\n *\n * Apple has stopped shipping Touch Bar on new MacBooks, but a large\n * fleet of 2016-2022 Pros still has them. Apps that want to do the\n * right thing for those users can hand a small set of contextual\n * controls here.\n *\n * No fallback outside Craft windows — Touch Bar is hardware-only.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport type TouchBarItemType = 'button' | 'label' | 'slider' | 'spacer' | 'colorPicker' | 'segmented'\n\nexport interface TouchBarItem {\n /** Unique id for later updates / event correlation. */\n id: string\n type: TouchBarItemType\n label?: string\n /** SF Symbol name or asset id. */\n icon?: string\n /** Initial state for sliders. 0..1. */\n value?: number\n /** Initial enabled state. */\n enabled?: boolean\n /** For segmented controls. */\n segments?: Array<{ id: string, label?: string, icon?: string }>\n}\n\nexport interface TouchBarActionEvent {\n /** id of the item the user touched. */\n id: string\n /** Slider value if applicable. */\n value?: number\n /** Selected segment id if applicable. */\n segment?: string\n}\n\nexport interface TouchBarAPI {\n addItem: (item: TouchBarItem) => Promise<void>\n removeItem: (id: string) => Promise<void>\n updateItem: (id: string, props: Partial<TouchBarItem>) => Promise<void>\n setLabel: (id: string, label: string) => Promise<void>\n setIcon: (id: string, icon: string) => Promise<void>\n setEnabled: (id: string, enabled: boolean) => Promise<void>\n setSliderValue: (id: string, value: number) => Promise<void>\n clear: () => Promise<void>\n show: () => Promise<void>\n hide: () => Promise<void>\n onAction: (cb: (event: TouchBarActionEvent) => void) => () => void\n}\n\nexport const touchbar: TouchBarAPI = {\n async addItem(item) { if (hasBridge('touchbar')) await window.craft!.touchbar.addItem(item) },\n async removeItem(id) { if (hasBridge('touchbar')) await window.craft!.touchbar.removeItem(id) },\n async updateItem(id, props) { if (hasBridge('touchbar')) await window.craft!.touchbar.updateItem(id, props) },\n async setLabel(id, label) { if (hasBridge('touchbar')) await window.craft!.touchbar.setLabel(id, label) },\n async setIcon(id, icon) { if (hasBridge('touchbar')) await window.craft!.touchbar.setIcon(id, icon) },\n async setEnabled(id, enabled) { if (hasBridge('touchbar')) await window.craft!.touchbar.setEnabled(id, enabled) },\n async setSliderValue(id, value) { if (hasBridge('touchbar')) await window.craft!.touchbar.setSliderValue(id, value) },\n async clear() { if (hasBridge('touchbar')) await window.craft!.touchbar.clear() },\n async show() { if (hasBridge('touchbar')) await window.craft!.touchbar.show() },\n async hide() { if (hasBridge('touchbar')) await window.craft!.touchbar.hide() },\n onAction(cb) {\n return onCraftEvent<TouchBarActionEvent>('craft:touchbar:action', cb)\n },\n}\n",
40
- "/**\n * Bluetooth\n *\n * Discover, pair, and connect to nearby devices. Uses CoreBluetooth on\n * macOS (`CBCentralManager`); equivalents on Linux/Windows.\n *\n * No web fallback — `navigator.bluetooth.requestDevice()` exists but\n * the model is fundamentally different (per-call user prompt, no\n * persistent pairings). Calls outside Craft return defaults.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface BluetoothDevice {\n /** Stable identifier. */\n id: string\n /** Friendly device name. May be empty. */\n name: string\n /** True if currently connected. */\n connected: boolean\n /** RSSI (signal strength, dBm). Negative — closer to 0 = stronger. */\n rssi?: number\n /** Manufacturer-data when present. */\n manufacturer?: string\n}\n\nexport type BluetoothPowerState = 'unknown' | 'resetting' | 'unsupported' | 'unauthorized' | 'poweredOff' | 'poweredOn'\n\nexport interface BluetoothService {\n /** UUID string (16- or 128-bit). CoreBluetooth normalizes both forms. */\n uuid: string\n /** True for \"primary\" services (vs \"included\" sub-services). */\n primary?: boolean\n}\n\nexport interface BluetoothCharacteristic {\n uuid: string\n /** Service this characteristic belongs to. */\n serviceUuid: string\n /** Properties advertised by the peripheral. */\n properties?: Array<'read' | 'write' | 'writeWithoutResponse' | 'notify' | 'indicate' | 'broadcast' | 'authenticatedSignedWrites' | 'extendedProperties'>\n}\n\nexport interface BluetoothCharacteristicValueEvent {\n deviceId: string\n serviceUuid: string\n characteristicUuid: string\n /** Hex-encoded bytes. */\n valueHex: string\n}\n\nexport type BluetoothWriteMode = 'with-response' | 'without-response'\n\nexport interface BluetoothAPI {\n isEnabled: () => Promise<boolean>\n powerState: () => Promise<BluetoothPowerState>\n connectedDevices: () => Promise<BluetoothDevice[]>\n pairedDevices: () => Promise<BluetoothDevice[]>\n startDiscovery: () => Promise<void>\n stopDiscovery: () => Promise<void>\n isDiscovering: () => Promise<boolean>\n connect: (id: string) => Promise<void>\n disconnect: (id: string) => Promise<void>\n openPreferences: () => Promise<void>\n /**\n * Discover GATT services on a connected peripheral. Resolves once the\n * native side returns the service list — does not stream incrementally.\n */\n discoverServices: (deviceId: string) => Promise<BluetoothService[]>\n /** Discover characteristics for one service. */\n discoverCharacteristics: (deviceId: string, serviceUuid: string) => Promise<BluetoothCharacteristic[]>\n /**\n * Read the current value of a characteristic. Returns hex-encoded bytes\n * — keeps the bridge JSON-friendly without forcing an opinion about\n * encoding (UTF-8 / float32 / etc.) at this layer.\n */\n readCharacteristic: (deviceId: string, serviceUuid: string, characteristicUuid: string) => Promise<{ ok: boolean, valueHex?: string, reason?: string }>\n /**\n * Write a value to a characteristic. `valueHex` should be a hex string\n * (`\"01ff\"`); `mode` defaults to `with-response` (CBCharacteristicWriteWithResponse).\n */\n writeCharacteristic: (\n deviceId: string,\n serviceUuid: string,\n characteristicUuid: string,\n valueHex: string,\n mode?: BluetoothWriteMode,\n ) => Promise<{ ok: boolean, reason?: string }>\n /**\n * Subscribe to value notifications/indications. Pass `false` to stop.\n * Updates arrive via `onCharacteristicValue`.\n */\n setCharacteristicNotify: (deviceId: string, serviceUuid: string, characteristicUuid: string, on: boolean) => Promise<{ ok: boolean, reason?: string }>\n /** Fired when a new device is discovered. */\n onDeviceFound: (cb: (device: BluetoothDevice) => void) => () => void\n /** Fired when a device finishes connecting. */\n onDeviceConnected: (cb: (device: BluetoothDevice) => void) => () => void\n /** Fired when a connected device disconnects. */\n onDeviceDisconnected: (cb: (device: BluetoothDevice) => void) => () => void\n /**\n * Fired when a subscribed characteristic delivers a new value. Tied to\n * `setCharacteristicNotify(..., true)`.\n */\n onCharacteristicValue: (cb: (event: BluetoothCharacteristicValueEvent) => void) => () => void\n}\n\nconst HEX_RE = /^[\\da-f]*$/i\n\nfunction assertHex(label: string, hex: string): void {\n if (typeof hex !== 'string' || !HEX_RE.test(hex) || hex.length % 2 !== 0) {\n throw new Error(`${label}: must be a hex string with even length, got ${JSON.stringify(hex)}`)\n }\n}\n\nexport const bluetooth: BluetoothAPI = {\n async isEnabled() { return hasBridge('bluetooth') ? await window.craft!.bluetooth.isEnabled() : false },\n async powerState() { return hasBridge('bluetooth') ? await window.craft!.bluetooth.powerState() : 'unknown' as BluetoothPowerState },\n async connectedDevices() { return hasBridge('bluetooth') ? await window.craft!.bluetooth.connectedDevices() : [] },\n async pairedDevices() { return hasBridge('bluetooth') ? await window.craft!.bluetooth.pairedDevices() : [] },\n async startDiscovery() { if (hasBridge('bluetooth')) await window.craft!.bluetooth.startDiscovery() },\n async stopDiscovery() { if (hasBridge('bluetooth')) await window.craft!.bluetooth.stopDiscovery() },\n async isDiscovering() { return hasBridge('bluetooth') ? await window.craft!.bluetooth.isDiscovering() : false },\n async connect(id) { if (hasBridge('bluetooth')) await window.craft!.bluetooth.connect(id) },\n async disconnect(id) { if (hasBridge('bluetooth')) await window.craft!.bluetooth.disconnect(id) },\n async openPreferences() { if (hasBridge('bluetooth')) await window.craft!.bluetooth.openPreferences() },\n\n async discoverServices(deviceId) {\n if (!deviceId) throw new Error('bluetooth.discoverServices: deviceId is required')\n if (!hasBridge('bluetooth')) return []\n const r = await window.craft!.bluetooth.discoverServices(deviceId)\n return Array.isArray(r) ? r as BluetoothService[] : []\n },\n\n async discoverCharacteristics(deviceId, serviceUuid) {\n if (!deviceId || !serviceUuid) throw new Error('bluetooth.discoverCharacteristics: deviceId and serviceUuid are required')\n if (!hasBridge('bluetooth')) return []\n const r = await window.craft!.bluetooth.discoverCharacteristics(deviceId, serviceUuid)\n return Array.isArray(r) ? r as BluetoothCharacteristic[] : []\n },\n\n async readCharacteristic(deviceId, serviceUuid, characteristicUuid) {\n if (!deviceId || !serviceUuid || !characteristicUuid) {\n throw new Error('bluetooth.readCharacteristic: deviceId, serviceUuid, characteristicUuid are required')\n }\n if (!hasBridge('bluetooth')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.bluetooth.readCharacteristic(deviceId, serviceUuid, characteristicUuid)\n },\n\n async writeCharacteristic(deviceId, serviceUuid, characteristicUuid, valueHex, mode = 'with-response') {\n if (!deviceId || !serviceUuid || !characteristicUuid) {\n throw new Error('bluetooth.writeCharacteristic: deviceId, serviceUuid, characteristicUuid are required')\n }\n assertHex('bluetooth.writeCharacteristic.valueHex', valueHex)\n if (!hasBridge('bluetooth')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.bluetooth.writeCharacteristic(deviceId, serviceUuid, characteristicUuid, valueHex, mode)\n },\n\n async setCharacteristicNotify(deviceId, serviceUuid, characteristicUuid, on) {\n if (!deviceId || !serviceUuid || !characteristicUuid) {\n throw new Error('bluetooth.setCharacteristicNotify: deviceId, serviceUuid, characteristicUuid are required')\n }\n if (!hasBridge('bluetooth')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.bluetooth.setCharacteristicNotify(deviceId, serviceUuid, characteristicUuid, on)\n },\n\n onDeviceFound(cb) { return onCraftEvent<BluetoothDevice>('craft:bluetooth:deviceFound', cb) },\n onDeviceConnected(cb) { return onCraftEvent<BluetoothDevice>('craft:bluetooth:deviceConnected', cb) },\n onDeviceDisconnected(cb) { return onCraftEvent<BluetoothDevice>('craft:bluetooth:deviceDisconnected', cb) },\n onCharacteristicValue(cb) {\n return onCraftEvent<BluetoothCharacteristicValueEvent>('craft:bluetooth:characteristicValue', cb)\n },\n}\n",
41
- "/**\n * Text-to-Speech\n *\n * Speak text aloud through the system synthesizer. macOS uses\n * `AVSpeechSynthesizer` (the modern, system-wide voice that respects\n * the user's preferred voice + rate).\n *\n * Browser fallback uses `window.speechSynthesis` — same shape, similar\n * voice list. The two paths are deliberately compatible so call sites\n * don't need to branch.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface SpeakOptions {\n /** Voice identifier (e.g. `com.apple.voice.compact.en-US.Samantha`)\n * or BCP-47 language tag (`en-US`). Optional — system default used. */\n voice?: string\n /** Rate, 0..1. AVSpeechUtterance treats ~0.5 as natural. */\n rate?: number\n /** Pitch multiplier, 0.5..2.0. Default 1.0. */\n pitch?: number\n /** Volume, 0..1. Default 1.0. */\n volume?: number\n}\n\nexport interface SpeechVoice {\n /** Stable identifier for `voice` option. */\n id: string\n /** Human-readable voice name (e.g. \"Samantha\"). */\n name: string\n /** BCP-47 language code. */\n language: string\n /** \"default\" or \"enhanced\" (premium installed voice). */\n quality: 'default' | 'enhanced'\n}\n\nexport interface SpeechAPI {\n /** Speak the given text. Returns once the utterance is *queued*, not finished. */\n speak: (text: string, options?: SpeakOptions) => Promise<void>\n /** Stop speaking immediately. */\n stop: () => Promise<void>\n /** Pause at the next word boundary. Resume with `resume()`. */\n pause: () => Promise<void>\n /** Resume a paused utterance. */\n resume: () => Promise<void>\n /** True if the synthesizer currently has an utterance. */\n isSpeaking: () => Promise<boolean>\n /** All installed voices on the system. */\n getVoices: () => Promise<SpeechVoice[]>\n}\n\nexport const speech: SpeechAPI = {\n async speak(text, options) {\n if (!text) throw new Error('speech.speak: text is required')\n if (hasBridge('speech')) {\n await window.craft!.speech.speak(text, options)\n return\n }\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n const u = new (window as any).SpeechSynthesisUtterance(text)\n if (options) {\n if (options.rate != null) u.rate = options.rate\n if (options.pitch != null) u.pitch = options.pitch\n if (options.volume != null) u.volume = options.volume\n if (options.voice) {\n // Web SpeechSynthesisVoice is matched by name OR voiceURI;\n // try both to be permissive.\n const voices = (window as any).speechSynthesis.getVoices()\n const match = voices.find((v: any) => v.voiceURI === options.voice || v.name === options.voice || v.lang === options.voice)\n if (match) u.voice = match\n }\n }\n ;(window as any).speechSynthesis.speak(u)\n }\n },\n\n async stop() {\n if (hasBridge('speech')) {\n await window.craft!.speech.stop()\n return\n }\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n ;(window as any).speechSynthesis.cancel()\n }\n },\n\n async pause() {\n if (hasBridge('speech')) {\n await window.craft!.speech.pause()\n return\n }\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n ;(window as any).speechSynthesis.pause()\n }\n },\n\n async resume() {\n if (hasBridge('speech')) {\n await window.craft!.speech.resume()\n return\n }\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n ;(window as any).speechSynthesis.resume()\n }\n },\n\n async isSpeaking() {\n if (hasBridge('speech')) return await window.craft!.speech.isSpeaking()\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n return !!(window as any).speechSynthesis.speaking\n }\n return false\n },\n\n async getVoices() {\n if (hasBridge('speech')) return await window.craft!.speech.getVoices()\n if (typeof window !== 'undefined' && (window as any).speechSynthesis) {\n const raw = (window as any).speechSynthesis.getVoices() as any[]\n return raw.map(v => ({\n id: v.voiceURI || v.name,\n name: v.name,\n language: v.lang || '',\n quality: 'default' as const,\n }))\n }\n return []\n },\n}\n",
42
- "/**\n * Crash Reporter\n *\n * Capture unhandled exceptions and queue them for forwarding to a\n * backend of your choice. The native side stores up to 64 most-recent\n * entries in memory (ring buffer); call `flush()` periodically to\n * drain and forward.\n *\n * **Why the design**: we deliberately don't ship a built-in HTTP\n * uploader. Apps care strongly about WHERE crash reports go (data\n * residency, privacy disclosures, retention) — picking a default\n * would surprise users. `flush()` returns the queue, `clear()` empties\n * it; that's enough to compose any backend on top.\n *\n * Browser fallback: keeps a JS-side queue with the same shape so\n * call sites don't branch. No automatic upload either way.\n */\nimport { hasBridge } from './_bridge'\n\nexport type CrashSeverity = 'fatal' | 'error' | 'warning'\n\nexport interface CrashReport {\n severity?: CrashSeverity\n message: string\n /** Where the crash originated. Defaults to `'js'`. */\n source?: 'js' | 'native'\n /** Stack trace, if available. */\n stack?: string\n}\n\nexport interface StoredCrashEntry {\n timestamp: number\n severity: string\n message: string\n source: string\n stack: string\n userId?: string\n appVersion?: string\n}\n\nexport interface CrashForwarderOptions {\n /** Where to POST the JSON payload. */\n endpoint: string\n /**\n * How often to drain the queue, in ms. Default: 60_000 (one minute).\n * Set to 0 to disable the timer (you'll call `flushNow()` yourself).\n */\n intervalMs?: number\n /**\n * Optional shared secret. If supplied, every POST gets an\n * `X-Craft-Signature: hex(HMAC-SHA256(secret, body))` header so the\n * receiver can authenticate the report.\n */\n signingSecret?: string\n /**\n * PII redaction. Defaults to `true` — strips emails, IPv4 addresses,\n * and absolute home paths from `message` and `stack`. Pass `false`\n * to send raw, or a custom function to do your own scrubbing.\n */\n redact?: boolean | ((entry: StoredCrashEntry) => StoredCrashEntry)\n /**\n * Extra headers to merge onto every request (auth tokens, etc.).\n */\n headers?: Record<string, string>\n /**\n * How many retries to attempt before dropping a batch. Default: 5.\n * Backoff doubles each attempt starting from 1 second.\n */\n maxRetries?: number\n /**\n * Persist the pending queue under this `localStorage` key so reports\n * survive a webview reload. Default: `'craft:crashReporter:pending'`.\n * Pass `null` to disable persistence.\n */\n persistKey?: string | null\n}\n\nexport interface CrashForwarderHandle {\n /** Force a flush right now, bypassing the timer. */\n flushNow: () => Promise<void>\n /** Stop the timer and detach. The pending queue stays persisted. */\n stop: () => void\n /** Inspect what's currently waiting to be sent. */\n pending: () => StoredCrashEntry[]\n}\n\nexport interface CrashReporterAPI {\n /**\n * Report a crash. Accepts either a `CrashReport` object or a\n * native `Error` — both get normalized to the storage shape.\n */\n report: (entry: CrashReport | Error) => Promise<void>\n /** Drain the queue and return the entries. Doesn't clear the queue. */\n flush: () => Promise<StoredCrashEntry[]>\n /** Empty the queue. */\n clear: () => Promise<void>\n /** Toggle reporting on/off. When off, `report()` is a no-op. */\n setEnabled: (on: boolean) => Promise<void>\n isEnabled: () => Promise<boolean>\n /** Tag every subsequent crash with this user id. */\n setUser: (id: string) => Promise<void>\n /** Tag every subsequent crash with this app version. */\n setAppVersion: (version: string) => Promise<void>\n /**\n * One-shot setup: hook `window.onerror` and `unhandledrejection`\n * so every uncaught failure routes through `report()` automatically.\n * Returns an `off()` to detach the global handlers.\n */\n attachGlobalHandlers: () => () => void\n /**\n * Wire a periodic HTTP forwarder. Drains `flush()` on a timer and\n * POSTs `{ entries: [...] }` to `endpoint`. Failed requests retry\n * with exponential backoff; the unsent batch is persisted to\n * localStorage so a reload doesn't lose it. Returns a handle with\n * `stop()` and `flushNow()`.\n */\n forwardTo: (options: CrashForwarderOptions) => CrashForwarderHandle\n}\n\n// JS-side fallback queue when native isn't available.\nconst jsQueue: StoredCrashEntry[] = []\nlet jsEnabled = true\nlet jsUserId: string | undefined\nlet jsAppVersion: string | undefined\n\nexport const crashReporter: CrashReporterAPI = {\n async report(entry) {\n if (hasBridge('crashReporter')) {\n await window.craft!.crashReporter.report(entry)\n return\n }\n if (!jsEnabled) return\n const normalized: StoredCrashEntry = entry instanceof Error\n ? {\n timestamp: Date.now(),\n severity: 'error',\n message: entry.message,\n source: 'js',\n stack: entry.stack || '',\n userId: jsUserId,\n appVersion: jsAppVersion,\n }\n : {\n timestamp: Date.now(),\n severity: entry.severity || 'error',\n message: entry.message || '',\n source: entry.source || 'js',\n stack: entry.stack || '',\n userId: jsUserId,\n appVersion: jsAppVersion,\n }\n if (jsQueue.length >= 64) jsQueue.shift()\n jsQueue.push(normalized)\n },\n\n async flush() {\n if (hasBridge('crashReporter')) return await window.craft!.crashReporter.flush()\n return [...jsQueue]\n },\n\n async clear() {\n if (hasBridge('crashReporter')) {\n await window.craft!.crashReporter.clear()\n return\n }\n jsQueue.length = 0\n },\n\n async setEnabled(on) {\n if (hasBridge('crashReporter')) {\n await window.craft!.crashReporter.setEnabled(on)\n return\n }\n jsEnabled = on\n },\n\n async isEnabled() {\n if (hasBridge('crashReporter')) return await window.craft!.crashReporter.isEnabled()\n return jsEnabled\n },\n\n async setUser(id) {\n if (hasBridge('crashReporter')) {\n await window.craft!.crashReporter.setUser(id)\n return\n }\n jsUserId = id || undefined\n },\n\n async setAppVersion(version) {\n if (hasBridge('crashReporter')) {\n await window.craft!.crashReporter.setAppVersion(version)\n return\n }\n jsAppVersion = version || undefined\n },\n\n attachGlobalHandlers() {\n if (hasBridge('crashReporter') && window.craft!.crashReporter.attachGlobalHandlers) {\n return window.craft!.crashReporter.attachGlobalHandlers()\n }\n if (typeof window === 'undefined') return () => {}\n const errorH = (e: ErrorEvent) => {\n crashReporter.report({\n severity: 'error',\n message: e.message,\n source: 'js',\n stack: e.error?.stack || `${e.message}\\n at ${e.filename}:${e.lineno}:${e.colno}`,\n }).catch(() => {})\n }\n const rejectH = (e: PromiseRejectionEvent) => {\n const r: any = e.reason\n crashReporter.report({\n severity: 'error',\n message: r?.message || String(r),\n source: 'js',\n stack: r?.stack || '',\n }).catch(() => {})\n }\n window.addEventListener('error', errorH)\n window.addEventListener('unhandledrejection', rejectH)\n return () => {\n window.removeEventListener('error', errorH)\n window.removeEventListener('unhandledrejection', rejectH)\n }\n },\n\n forwardTo(options) {\n return startForwarder(options)\n },\n}\n\n// =============================================================================\n// HTTP Forwarder\n// =============================================================================\n\nconst DEFAULT_PERSIST_KEY = 'craft:crashReporter:pending'\n\nconst EMAIL_RE = /[\\w.+-]+@[\\w-]+\\.[\\w.-]+/g\nconst IPV4_RE = /\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b/g\nconst HOME_PATH_RE = /\\/(?:Users|home)\\/[^\\s/'\"`]+/g\n\n/** Default redactor — replaces emails, IPv4s, and home paths with placeholders. */\nexport function redactPII(entry: StoredCrashEntry): StoredCrashEntry {\n const scrub = (s: string): string => s\n .replace(EMAIL_RE, '<email>')\n .replace(IPV4_RE, '<ip>')\n .replace(HOME_PATH_RE, '/<home>')\n return {\n ...entry,\n message: scrub(entry.message),\n stack: scrub(entry.stack),\n }\n}\n\n/** Sign `body` with HMAC-SHA256 + `secret`. Returns lowercase hex. */\nexport async function signPayload(secret: string, body: string): Promise<string> {\n const enc = new TextEncoder()\n const key = await crypto.subtle.importKey(\n 'raw',\n enc.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await crypto.subtle.sign('HMAC', key, enc.encode(body))\n return [...new Uint8Array(sig)].map(b => b.toString(16).padStart(2, '0')).join('')\n}\n\nfunction loadPersisted(key: string | null | undefined): StoredCrashEntry[] {\n if (!key || typeof localStorage === 'undefined') return []\n try {\n const raw = localStorage.getItem(key)\n if (!raw) return []\n const parsed = JSON.parse(raw)\n return Array.isArray(parsed) ? parsed as StoredCrashEntry[] : []\n }\n catch {\n return []\n }\n}\n\nfunction savePersisted(key: string | null | undefined, entries: StoredCrashEntry[]): void {\n if (!key || typeof localStorage === 'undefined') return\n try {\n if (entries.length === 0) localStorage.removeItem(key)\n else localStorage.setItem(key, JSON.stringify(entries))\n }\n catch { /* quota / disabled — best effort */ }\n}\n\nfunction startForwarder(options: CrashForwarderOptions): CrashForwarderHandle {\n const {\n endpoint,\n intervalMs = 60_000,\n signingSecret,\n redact = true,\n headers = {},\n maxRetries = 5,\n persistKey,\n } = options\n\n // Default the persist key only when the caller didn't explicitly opt out.\n // `persistKey === null` disables persistence; `undefined` falls back to\n // the standard key.\n const storageKey: string | null = persistKey === null\n ? null\n : (persistKey ?? DEFAULT_PERSIST_KEY)\n\n let pending: StoredCrashEntry[] = loadPersisted(storageKey)\n let stopped = false\n let timer: ReturnType<typeof setInterval> | null = null\n let inFlight: Promise<void> | null = null\n\n const redactor = typeof redact === 'function'\n ? redact\n : redact === false\n ? (e: StoredCrashEntry) => e\n : redactPII\n\n async function postBatch(batch: StoredCrashEntry[]): Promise<void> {\n const body = JSON.stringify({ entries: batch })\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...headers,\n }\n if (signingSecret) {\n requestHeaders['X-Craft-Signature'] = await signPayload(signingSecret, body)\n }\n\n let attempt = 0\n let delay = 1000\n while (!stopped) {\n try {\n const res = await fetch(endpoint, { method: 'POST', headers: requestHeaders, body })\n if (res.ok) return\n // 4xx — drop, since retrying would just fail again.\n if (res.status >= 400 && res.status < 500) return\n throw new Error(`HTTP ${res.status}`)\n }\n catch (err) {\n attempt += 1\n if (attempt > maxRetries) {\n // Re-queue at the front so the next tick retries from a fresh batch.\n pending = [...batch, ...pending]\n savePersisted(storageKey, pending)\n throw err\n }\n await new Promise<void>((r) => { setTimeout(r, delay) })\n delay = Math.min(delay * 2, 60_000)\n }\n }\n }\n\n async function drain(): Promise<void> {\n if (stopped || inFlight) return inFlight ?? undefined\n const fresh = await crashReporter.flush()\n if (fresh.length > 0) await crashReporter.clear()\n pending = [...pending, ...fresh.map(e => redactor(e))]\n if (pending.length === 0) return\n\n const batch = pending\n pending = []\n savePersisted(storageKey, pending)\n\n inFlight = postBatch(batch)\n .catch(() => { /* batch was already requeued in postBatch */ })\n .finally(() => { inFlight = null })\n return inFlight\n }\n\n if (intervalMs > 0) {\n timer = setInterval(() => { drain().catch(() => {}) }, intervalMs)\n }\n\n return {\n async flushNow() { await drain() },\n stop() {\n stopped = true\n if (timer) clearInterval(timer)\n timer = null\n },\n pending() { return [...pending] },\n }\n}\n",
43
- "/**\n * In-App Purchases (StoreKit on macOS)\n *\n * **Scope**: minimal. Full StoreKit support involves SKProductsRequest\n * delegates, transaction observers, receipt validation, family sharing,\n * promotional offers — months of work. The native side currently\n * implements `isAvailable`, `restorePurchases`, and `getReceiptData`\n * fully; `getProducts`, `purchase`, and `finishTransaction` are stubs\n * pending the StoreKit observer wiring.\n *\n * Apps that need a working IAP flow today should:\n * 1. Use `getReceiptData()` to grab the bundled App Store receipt\n * and verify it server-side via Apple's verifyReceipt API.\n * 2. Implement product fetch + purchase via a separate SDK or\n * direct StoreKit code in your bundle.\n *\n * This shape is intentionally stable so apps can write against it now\n * and switch over to a richer implementation when it lands.\n */\nimport { hasBridge } from './_bridge'\n\nexport type IAPProductType =\n| 'consumable'\n| 'non-consumable'\n| 'auto-subscription'\n| 'non-auto-subscription'\n\nexport type IAPSubscriptionPeriod = 'day' | 'week' | 'month' | 'year'\n\nexport interface IAPSubscriptionInfo {\n /** Length of one period — `1` + `month` means a one-month subscription. */\n numberOfUnits: number\n unit: IAPSubscriptionPeriod\n /** Free trial / intro offer attached to this subscription, if any. */\n introductoryOffer?: IAPIntroductoryOffer\n /** True when the subscription is shareable with iCloud Family. */\n familyShareable?: boolean\n /** Subscription group identifier. Used by StoreKit for upgrade/downgrade math. */\n groupIdentifier?: string\n}\n\nexport interface IAPIntroductoryOffer {\n /** \"free-trial\" | \"pay-as-you-go\" | \"pay-up-front\". */\n paymentMode: 'free-trial' | 'pay-as-you-go' | 'pay-up-front'\n /** Localized price including currency symbol; `\"0.00\"` for free trials. */\n localizedPrice: string\n /** How long the intro lasts. */\n numberOfUnits: number\n unit: IAPSubscriptionPeriod\n /** How many billing periods the intro repeats over (>=1). */\n numberOfPeriods?: number\n}\n\nexport interface IAPProduct {\n id: string\n title: string\n description?: string\n price: string\n /** Currency code (e.g. \"USD\"). */\n currency?: string\n /** Localized price including currency symbol. */\n localizedPrice?: string\n type?: IAPProductType\n /** Present only when `type === 'auto-subscription'`. */\n subscription?: IAPSubscriptionInfo\n}\n\nexport interface IAPPurchaseResult {\n /** True when the purchase was queued successfully. */\n queued: boolean\n productId?: string\n /** Why the purchase couldn't be queued (transient stub limitation, etc). */\n reason?: string\n}\n\nexport interface IAPTransactionEvent {\n productId: string\n transactionId: string\n /** ISO date string. */\n date?: string\n /** Original transaction id — populated for renewals / restores. */\n originalTransactionId?: string\n /** True when this purchase was issued under iCloud Family Sharing. */\n familyShared?: boolean\n /** True when restoring a previously purchased non-consumable. */\n restored?: boolean\n /** Subscription auto-renewal status, if applicable. */\n autoRenewing?: boolean\n /** ISO date when the current subscription period expires. */\n expiresAt?: string\n /** True when StoreKit reports this transaction is in the intro/free-trial period. */\n inIntroPeriod?: boolean\n}\n\nexport interface IAPFailureEvent {\n productId: string\n /** Apple's SKErrorCode value. */\n code?: number\n message?: string\n}\n\nexport interface IAPRefundEvent {\n productId: string\n transactionId: string\n /** ISO date when the refund was issued. */\n refundedAt?: string\n /** \"voluntary\" | \"issue-app\" | \"other\" — Apple's refund preference. */\n reason?: string\n}\n\nexport interface IAPSubscriptionStatusEvent {\n productId: string\n /** \"active\" | \"expired\" | \"in-grace-period\" | \"in-billing-retry\" | \"revoked\". */\n status: 'active' | 'expired' | 'in-grace-period' | 'in-billing-retry' | 'revoked'\n /** ISO date when status takes effect. */\n changedAt?: string\n /** ISO date the current period ends. */\n expiresAt?: string\n}\n\nexport interface IAPAPI {\n /** True if the device is allowed to make payments. */\n isAvailable: () => Promise<boolean>\n /** Fetch products by id. May return an empty array if native fetch isn't wired yet. */\n getProducts: (ids: string[] | string) => Promise<IAPProduct[]>\n /** Queue a purchase. Result fires via `onPurchased` / `onFailed`. */\n purchase: (productId: string) => Promise<IAPPurchaseResult>\n /** Restore previously-bought non-consumables tied to the user's Apple ID. */\n restorePurchases: () => Promise<{ ok: boolean }>\n /**\n * Mark a transaction as finished — required for non-consumables to\n * stop StoreKit re-delivering them.\n */\n finishTransaction: (transactionId: string) => Promise<void>\n /**\n * Read the App Store receipt as a base64 string. Hand this to your\n * server and call Apple's `verifyReceipt` for trusted validation.\n */\n getReceiptData: () => Promise<string | null>\n /** Subscribe to successful purchase events. */\n onPurchased: (cb: (e: IAPTransactionEvent) => void) => () => void\n /** Subscribe to purchase-failure events. */\n onFailed: (cb: (e: IAPFailureEvent) => void) => () => void\n /** Subscribe to \"purchase restored\" events. */\n onRestored: (cb: (e: IAPTransactionEvent) => void) => () => void\n /** Subscribe to async products-fetch results. */\n onProductsLoaded: (cb: (products: IAPProduct[]) => void) => () => void\n /**\n * Fires when a previous purchase has been refunded by the user via the\n * App Store. Apps should immediately revoke the entitlement granted by\n * the original transaction.\n */\n onRefunded: (cb: (e: IAPRefundEvent) => void) => () => void\n /**\n * Fires whenever a subscription's lifecycle status changes — the user\n * lapses out of grace period, billing retry resolves, etc.\n */\n onSubscriptionStatusChanged: (cb: (e: IAPSubscriptionStatusEvent) => void) => () => void\n /**\n * Returns the currently-active subscription product ids, plus their\n * status. Use on app boot to gate features rather than re-running\n * `restorePurchases()` every time.\n */\n getActiveSubscriptions: () => Promise<IAPSubscriptionStatusEvent[]>\n /**\n * True if the user is eligible for the introductory offer attached to\n * `productId`. Apple gates intro eligibility per subscription group:\n * if the user has ever subscribed to *any* product in the same group,\n * they're ineligible for further intro offers.\n */\n isEligibleForIntroOffer: (productId: string) => Promise<boolean>\n}\n\nimport { onCraftEvent } from './_bridge'\n\nexport const iap: IAPAPI = {\n async isAvailable() {\n if (!hasBridge('iap')) return false\n return await window.craft!.iap.isAvailable()\n },\n async getProducts(ids) {\n if (!hasBridge('iap')) return []\n // Normalize to array at the TS boundary so the bridge always sees\n // the same shape, regardless of whether the caller passed a\n // single id or a list.\n const arr = Array.isArray(ids) ? ids : [String(ids)]\n return await window.craft!.iap.getProducts(arr)\n },\n async purchase(productId) {\n if (!hasBridge('iap')) return { queued: false, productId, reason: 'IAP bridge not available' }\n const r = await window.craft!.iap.purchase(productId)\n return { queued: !!(r && r.queued), productId: r?.productId, reason: r?.reason }\n },\n async restorePurchases() {\n if (!hasBridge('iap')) return { ok: false }\n const r = await window.craft!.iap.restorePurchases()\n return { ok: !!(r && r.ok) }\n },\n async finishTransaction(transactionId) {\n if (!hasBridge('iap')) return\n await window.craft!.iap.finishTransaction(transactionId)\n },\n async getReceiptData() {\n if (!hasBridge('iap')) return null\n const r = await window.craft!.iap.getReceiptData()\n return r ? String(r) : null\n },\n onPurchased(cb) { return onCraftEvent<IAPTransactionEvent>('craft:iap:purchased', cb) },\n onFailed(cb) { return onCraftEvent<IAPFailureEvent>('craft:iap:failed', cb) },\n onRestored(cb) { return onCraftEvent<IAPTransactionEvent>('craft:iap:restored', cb) },\n onProductsLoaded(cb) {\n return onCraftEvent<{ products?: IAPProduct[] }>('craft:iap:productsLoaded', (e) => cb(e.products || []))\n },\n onRefunded(cb) { return onCraftEvent<IAPRefundEvent>('craft:iap:refunded', cb) },\n onSubscriptionStatusChanged(cb) {\n return onCraftEvent<IAPSubscriptionStatusEvent>('craft:iap:subscriptionStatusChanged', cb)\n },\n async getActiveSubscriptions() {\n if (!hasBridge('iap')) return []\n // Older bridges may not implement this — defensive default keeps the\n // call shape stable so callers can ship before the native side ships.\n const fn = window.craft!.iap.getActiveSubscriptions\n if (typeof fn !== 'function') return []\n const r = await fn()\n return Array.isArray(r) ? r as IAPSubscriptionStatusEvent[] : []\n },\n async isEligibleForIntroOffer(productId) {\n if (!hasBridge('iap')) return false\n const fn = window.craft!.iap.isEligibleForIntroOffer\n if (typeof fn !== 'function') return false\n return !!(await fn(productId))\n },\n}\n",
44
- "/**\n * Handoff (Apple Continuity)\n *\n * `NSUserActivity` lets one of the user's Apple devices pick up a\n * task started on another. A reading app can publish \"currently\n * reading X at chapter Y\" and have the user's iPad pick up exactly\n * where they left off, etc.\n *\n * The bridge exposes:\n *\n * - `startActivity(type, opts)` — broadcast a new activity. The\n * `type` is the activity name\n * declared in `Info.plist`'s\n * `NSUserActivityTypes`.\n * - `updateActivity(opts)` — mutate the in-flight activity.\n * - `stopActivity()` — invalidate.\n * - `getCurrentActivity()` — read the current snapshot.\n * - `onIncoming(cb)` — subscribe to incoming handoffs\n * from another device.\n *\n * **Required Info.plist setup:** add a `NSUserActivityTypes` array\n * listing the activity-type strings your app will use. Without that\n * declaration, macOS rejects the activity at registration time.\n *\n * Browser fallback: this module is a graceful no-op (subscriptions\n * never fire). Handoff has no web equivalent.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface HandoffActivityOptions {\n /** Human-readable title shown in the Handoff UI. */\n title?: string\n /** URL to fall back to on devices without the app installed. */\n webpageURL?: string\n /**\n * Arbitrary state to send to the receiving device. Must be plist-\n * compatible (strings, numbers, bools, arrays, dicts of the same).\n * Round-trips through NSJSONSerialization.\n */\n userInfo?: Record<string, unknown>\n}\n\nexport interface HandoffSnapshot {\n type: string\n title: string\n webpageURL: string\n}\n\nexport interface HandoffIncomingEvent {\n type: string\n title?: string\n webpageURL?: string\n userInfo?: Record<string, unknown>\n}\n\nexport interface HandoffAPI {\n /** Start broadcasting a new activity. Resolves to true on success. */\n startActivity: (type: string, options?: HandoffActivityOptions) => Promise<boolean>\n /** Update the in-flight activity (title / webpageURL / userInfo). */\n updateActivity: (options: HandoffActivityOptions) => Promise<boolean>\n /** Invalidate the current activity. Idempotent. */\n stopActivity: () => Promise<void>\n /** Read the current activity, or null if none. */\n getCurrentActivity: () => Promise<HandoffSnapshot | null>\n /** Subscribe to incoming handoffs from another device. */\n onIncoming: (cb: (event: HandoffIncomingEvent) => void) => () => void\n}\n\nexport const handoff: HandoffAPI = {\n async startActivity(type, options) {\n if (!type) throw new Error('handoff.startActivity: type is required')\n if (!hasBridge('handoff')) return false\n // Tolerate both shapes: the production JS facade in craft-bridge.js\n // extracts `{ok:boolean}` to a bare boolean, but the TS-only mock\n // path returns the raw `{ok}` envelope. Either way we surface a\n // single boolean to the caller so call sites stay clean.\n const r = await window.craft!.handoff.startActivity(type, options)\n return typeof r === 'boolean' ? r : !!(r && r.ok)\n },\n async updateActivity(options) {\n if (!hasBridge('handoff')) return false\n const r = await window.craft!.handoff.updateActivity(options)\n return typeof r === 'boolean' ? r : !!(r && r.ok)\n },\n async stopActivity() {\n if (!hasBridge('handoff')) return\n await window.craft!.handoff.stopActivity()\n },\n async getCurrentActivity() {\n if (!hasBridge('handoff')) return null\n const r = await window.craft!.handoff.getCurrentActivity()\n return r && typeof r.type === 'string' ? r : null\n },\n onIncoming(cb) {\n return onCraftEvent<HandoffIncomingEvent>('craft:handoff:incoming', cb)\n },\n}\n",
45
- "/**\n * Live Activities — a thin wrapper over Handoff.\n *\n * **Apple's \"Live Activities\" are an iOS-only ActivityKit feature**\n * that lights up Lock Screens and Dynamic Island. They require an\n * iOS 16+ Widget Extension target and can't be invoked from a\n * Craft window directly.\n *\n * What this module ships is the *macOS-compatible approximation*:\n * we publish an NSUserActivity that nearby Apple devices (including\n * the user's iPhone, if it's running a companion app) can pick up\n * via Handoff. It's not a Live Activity in the iOS sense, but it\n * exposes the same conceptual API so app code can be future-ready\n * and dual-targeted.\n *\n * For real iOS Live Activities, ship a Widget Extension target and\n * call `Activity.request(...)` from Swift. This module is the\n * cross-platform glue — same surface, best-effort behaviour.\n */\nimport { handoff } from './handoff'\n\nexport interface LiveActivityState {\n /** Title shown in the Lock Screen / nearby device UI. */\n title?: string\n /** URL to fall back to on devices without the app. */\n webpageURL?: string\n /** Free-form payload passed through to the receiving device. */\n state?: Record<string, unknown>\n}\n\nexport interface LiveActivitiesAPI {\n /**\n * Start a live-activity-shaped session. On macOS this maps to an\n * `NSUserActivity` published via Handoff.\n * @param type — the activity type identifier (must be declared in\n * `Info.plist > NSUserActivityTypes`).\n */\n start: (type: string, state?: LiveActivityState) => Promise<boolean>\n /** Push a new state. Devices receiving the activity see the latest. */\n update: (state: LiveActivityState) => Promise<boolean>\n /** End the activity. Idempotent. */\n stop: () => Promise<void>\n}\n\nexport const liveActivities: LiveActivitiesAPI = {\n async start(type, state) {\n return handoff.startActivity(type, {\n title: state?.title,\n webpageURL: state?.webpageURL,\n userInfo: state?.state,\n })\n },\n async update(state) {\n return handoff.updateActivity({\n title: state.title,\n webpageURL: state.webpageURL,\n userInfo: state.state,\n })\n },\n async stop() {\n await handoff.stopActivity()\n },\n}\n",
46
- "/**\n * Geolocation (CoreLocation on macOS).\n *\n * Apps that need higher-than-browser-grade accuracy use this module —\n * the macOS native path delivers GPS/WiFi-positioning samples directly\n * from `CLLocationManager`. Browser fallback uses the standard\n * `navigator.geolocation` API, which is good enough for \"what city\n * am I in\" but not for navigation-grade tracking.\n *\n * **Required Info.plist keys** for the permission prompt:\n * - `NSLocationWhenInUseUsageDescription` — when in use only\n * - `NSLocationAlwaysAndWhenInUseUsageDescription` — background access\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport type LocationAuthStatus =\n| 'undetermined'\n| 'restricted-or-denied'\n| 'authorizedAlways'\n| 'authorizedWhenInUse'\n| 'not-supported'\n| 'unknown'\n\nexport interface LocationCoordinate {\n latitude: number\n longitude: number\n altitude?: number\n /** Horizontal accuracy in meters. Negative = invalid. */\n horizontalAccuracy?: number\n verticalAccuracy?: number\n /** Speed in m/s. Negative = invalid. */\n speed?: number\n}\n\nexport interface LocationWatchOptions {\n /** `'continuous'` (high accuracy, more battery) or `'significant'`. */\n mode?: 'continuous' | 'significant'\n /** Distance in meters between updates. */\n distanceFilter?: number\n}\n\nexport interface LocationAPI {\n /** Trigger the system permission prompt. */\n requestPermission: (mode?: 'whenInUse' | 'always') => Promise<LocationAuthStatus>\n /** Read current authorization status without prompting. */\n getAuthorization: () => Promise<LocationAuthStatus>\n /**\n * Request a single location sample. The result arrives via `onUpdate`,\n * not as the resolution value of this call (CoreLocation is async).\n */\n getCurrentLocation: () => Promise<{ requested: boolean }>\n /** Start streaming updates via `onUpdate`. */\n startWatching: (options?: LocationWatchOptions) => Promise<boolean>\n /** Stop the update stream. */\n stopWatching: () => Promise<void>\n /** Subscribe to location samples. */\n onUpdate: (cb: (loc: LocationCoordinate) => void) => () => void\n /** Subscribe to errors (e.g. denied, location unavailable). */\n onError: (cb: (err: { message: string }) => void) => () => void\n /** Subscribe to authorization-status changes. */\n onAuthChanged: (cb: (info: { status: LocationAuthStatus }) => void) => () => void\n}\n\nexport const location: LocationAPI = {\n async requestPermission(mode = 'whenInUse') {\n if (hasBridge('location')) return await window.craft!.location.requestPermission(mode)\n if (typeof navigator !== 'undefined' && (navigator as any).geolocation) {\n // Browser geolocation prompts implicitly on the first\n // getCurrentPosition() call — there's no separate request API.\n return 'undetermined'\n }\n return 'not-supported'\n },\n async getAuthorization() {\n if (hasBridge('location')) return await window.craft!.location.getAuthorization()\n return 'unknown'\n },\n async getCurrentLocation() {\n if (hasBridge('location')) return await window.craft!.location.getCurrentLocation()\n // Web fallback: kick off navigator.geolocation.getCurrentPosition,\n // and synthesize a `craft:location:update` event so apps that\n // subscribe via `onUpdate` see the result through the same channel.\n if (typeof navigator !== 'undefined' && (navigator as any).geolocation) {\n ;(navigator as any).geolocation.getCurrentPosition(\n (pos: any) => {\n window.dispatchEvent(new CustomEvent('craft:location:update', {\n detail: {\n latitude: pos.coords.latitude,\n longitude: pos.coords.longitude,\n altitude: pos.coords.altitude,\n horizontalAccuracy: pos.coords.accuracy,\n verticalAccuracy: pos.coords.altitudeAccuracy,\n speed: pos.coords.speed,\n },\n }))\n },\n (err: any) => {\n window.dispatchEvent(new CustomEvent('craft:location:error', {\n detail: { message: err.message || String(err) },\n }))\n },\n )\n return { requested: true }\n }\n return { requested: false }\n },\n async startWatching(options) {\n if (hasBridge('location')) return await window.craft!.location.startWatching(options)\n if (typeof navigator !== 'undefined' && (navigator as any).geolocation) {\n const watchId = (navigator as any).geolocation.watchPosition(\n (pos: any) => {\n window.dispatchEvent(new CustomEvent('craft:location:update', {\n detail: {\n latitude: pos.coords.latitude,\n longitude: pos.coords.longitude,\n altitude: pos.coords.altitude,\n horizontalAccuracy: pos.coords.accuracy,\n verticalAccuracy: pos.coords.altitudeAccuracy,\n speed: pos.coords.speed,\n },\n }))\n },\n )\n ;(window as any).__craftWebLocationWatchId = watchId\n return true\n }\n return false\n },\n async stopWatching() {\n if (hasBridge('location')) {\n await window.craft!.location.stopWatching()\n return\n }\n if (typeof navigator !== 'undefined' && (navigator as any).geolocation) {\n const id = (window as any).__craftWebLocationWatchId\n if (id != null) {\n ;(navigator as any).geolocation.clearWatch(id)\n ;(window as any).__craftWebLocationWatchId = null\n }\n }\n },\n onUpdate(cb) { return onCraftEvent<LocationCoordinate>('craft:location:update', cb) },\n onError(cb) { return onCraftEvent<{ message: string }>('craft:location:error', cb) },\n onAuthChanged(cb) { return onCraftEvent<{ status: LocationAuthStatus }>('craft:location:authChanged', cb) },\n}\n",
47
- "/**\n * Programmatic screen + window capture.\n *\n * macOS uses `CGWindowListCreateImage` (works on every supported\n * release; permission-gated by Privacy → Screen Recording). Apps\n * should guide the user via `permissions.openSettings('screen_recording')`\n * before calling — otherwise the capture returns a black image.\n *\n * No web fallback — `getDisplayMedia()` exists but it's a different\n * shape (live stream vs still). Calls outside Craft return null.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface CapturableWindow {\n /** CGWindowID — pass to `captureWindow()`. */\n id: number\n /** Window title. May be empty. */\n name: string\n /** Owning app's name (e.g. \"Safari\", \"Finder\"). */\n ownerName: string\n}\n\nexport interface ScreenCaptureAPI {\n /**\n * Capture the entire primary display. Returns a `data:image/png;base64,...`\n * data URL ready to drop into an `<img src>`, or null if the capture\n * failed (typically permission-denied).\n */\n captureScreen: () => Promise<string | null>\n /** Capture a specific window by its CGWindowID. */\n captureWindow: (id: number) => Promise<string | null>\n /** List every on-screen window the OS will let us capture. */\n listWindows: () => Promise<CapturableWindow[]>\n}\n\nexport const screenCapture: ScreenCaptureAPI = {\n async captureScreen() {\n if (!hasBridge('screenCapture')) return null\n const r = await window.craft!.screenCapture.captureScreen()\n return r ? String(r) : null\n },\n async captureWindow(id) {\n if (!hasBridge('screenCapture')) return null\n if (!Number.isFinite(id) || id <= 0) throw new Error('captureWindow: id must be a positive number')\n const r = await window.craft!.screenCapture.captureWindow(id)\n return r ? String(r) : null\n },\n async listWindows() {\n if (!hasBridge('screenCapture')) return []\n return await window.craft!.screenCapture.listWindows()\n },\n}\n",
48
- "/**\n * Screen-sharing and screen-recording detection.\n *\n * macOS exposes no direct \"is my screen being captured?\" API, so Craft\n * combines four independent signals: the CGSession dictionary's shared-screen\n * and off-console keys, the floating sharing control conferencing apps show\n * while a share is live, and recorder windows.\n *\n * The window-level signals match the sharing *indicator*, never the presence\n * of the app. \"Zoom is running\" describes most of a working day; acting on it\n * would silence notifications permanently.\n *\n * No web fallback: `getDisplayMedia()` tells a page about its own capture, not\n * about the machine. Outside Craft, `getState()` reports nothing detected and\n * `watch()` resolves without starting anything.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\n/** Which signal produced a detection. */\nexport type ScreenSharingKind = 'system' | 'remote' | 'conference' | 'recording'\n\nexport interface ScreenSharingSource {\n /** Owning application, as the window server reports it. */\n app: string\n /** Window title that matched. Empty when the owner alone was the signal. */\n window: string\n kind: ScreenSharingKind\n}\n\nexport interface ScreenSharingSignals {\n /** macOS Screen Sharing / Apple Remote Desktop has the session. */\n systemScreenShare: boolean\n /** The session is being driven from somewhere other than this console. */\n remoteSession: boolean\n /** A conferencing app is showing its live sharing control. */\n conferenceSharing: boolean\n /** A recorder is capturing the screen. */\n screenRecording: boolean\n}\n\nexport interface ScreenSharingState {\n /** True when any signal fired. */\n sharing: boolean\n signals: ScreenSharingSignals\n /** Every indicator that matched, so apps can explain *why* they reacted. */\n sources: ScreenSharingSource[]\n}\n\n/** Interval bounds enforced natively; mirrored here so callers get the same clamp. */\nexport const MIN_WATCH_INTERVAL_MS = 250\nexport const MAX_WATCH_INTERVAL_MS = 60_000\nexport const DEFAULT_WATCH_INTERVAL_MS = 2000\n\nexport interface ScreenSharingAPI {\n /** One-shot evaluation of every signal. */\n getState: () => Promise<ScreenSharingState>\n /**\n * Start polling. Fires `onChange` once immediately, then only when the\n * resolved state actually differs. Returns the interval the native side\n * settled on after clamping.\n */\n watch: (intervalMs?: number) => Promise<number>\n stop: () => Promise<void>\n /** Subscribe to state changes. Returns an unsubscribe function. */\n onChange: (cb: (state: ScreenSharingState) => void) => () => void\n}\n\nconst IDLE: ScreenSharingState = {\n sharing: false,\n signals: {\n systemScreenShare: false,\n remoteSession: false,\n conferenceSharing: false,\n screenRecording: false,\n },\n sources: [],\n}\n\nfunction idleState(): ScreenSharingState {\n return { ...IDLE, signals: { ...IDLE.signals }, sources: [] }\n}\n\nexport const screenSharing: ScreenSharingAPI = {\n async getState() {\n if (!hasBridge('screenSharing')) return idleState()\n return await window.craft!.screenSharing.getState()\n },\n\n async watch(intervalMs = DEFAULT_WATCH_INTERVAL_MS) {\n const clamped = Math.min(MAX_WATCH_INTERVAL_MS, Math.max(MIN_WATCH_INTERVAL_MS, Math.round(intervalMs)))\n if (!hasBridge('screenSharing')) return clamped\n const r = await window.craft!.screenSharing.watch(clamped)\n return (r && r.intervalMs) || clamped\n },\n\n async stop() {\n if (!hasBridge('screenSharing')) return\n await window.craft!.screenSharing.unwatch()\n },\n\n // Subscribing to the window event directly, rather than through the bridge\n // facade's own `onChange`, keeps this working before the bridge has\n // finished injecting — a listener registered early still receives the first\n // emission that `watch()` sends immediately on start.\n onChange(cb) {\n return onCraftEvent('craft:screenSharing:change', cb)\n },\n}\n\n/**\n * Subscribe and start polling in one call, returning a single teardown.\n *\n * The two halves are easy to leak apart — `onChange` without `watch` never\n * fires, and `watch` without a matching `stop` keeps the timer alive across a\n * page reload.\n */\nexport async function watchScreenSharing(\n cb: (state: ScreenSharingState) => void,\n intervalMs: number = DEFAULT_WATCH_INTERVAL_MS,\n): Promise<() => void> {\n const off = screenSharing.onChange(cb)\n await screenSharing.watch(intervalMs)\n return () => {\n off()\n void screenSharing.stop()\n }\n}\n",
49
- "/**\n * Do Not Disturb / Focus.\n *\n * Reading Focus is public macOS API (`INFocusStatusCenter`, macOS 12+) but\n * permission-gated: the app must call `requestAuthorization()` and declare\n * `NSFocusStatusUsageDescription` in its `Info.plist`.\n *\n * Writing Focus is *not* available to third-party apps. The system service\n * rejects every client without an Apple-private entitlement, so the only\n * sanctioned path is to run a user-created Shortcut containing the **Set\n * Focus** action — which is what `setEnabled()` does. Apps are expected to\n * walk the user through creating those shortcuts once and to verify them with\n * `listShortcuts()` before offering the feature.\n *\n * No web fallback exists: a browser cannot read or set the system's Focus.\n * Outside Craft every call resolves to an unsupported result rather than\n * throwing, so cross-platform code can call unconditionally.\n */\nimport { hasBridge } from './_bridge'\n\n/**\n * Mirrors `INFocusStatusAuthorizationStatus`. `unsupported` is Craft's own\n * value for platforms where the framework isn't present at all.\n */\nexport type FocusAuthorization = 'notDetermined' | 'restricted' | 'denied' | 'authorized' | 'unsupported'\n\n/**\n * How the shortcut is run.\n *\n * `cli` execs `/usr/bin/shortcuts` and reports the shortcut's real exit\n * status. `url` opens `shortcuts://run-shortcut`, the only route the App\n * Sandbox permits — but it is fire-and-forget: LaunchServices confirms it\n * handed the URL over, never that the shortcut ran. `auto` picks `url` under\n * sandbox and `cli` everywhere else, so a real status is used where one\n * exists.\n */\nexport type FocusStrategy = 'auto' | 'cli' | 'url'\n\nexport interface FocusStatus {\n /** False when Focus isn't available on this platform. */\n supported: boolean\n /**\n * Whether the user is in *any* Focus. `null` means the system declined to\n * answer — almost always missing authorization, which is not the same as\n * \"not focused\". Branch on the two separately.\n */\n isFocused: boolean | null\n authorization: FocusAuthorization\n}\n\nexport interface FocusShortcutOptions {\n /** Shortcut to run when turning Focus on. */\n onShortcut?: string\n /** Shortcut to run when turning Focus off. */\n offShortcut?: string\n /** Defaults to `auto`. */\n strategy?: FocusStrategy\n}\n\nexport interface FocusResult {\n ok: boolean\n strategy?: 'shortcut' | 'url'\n /** Exit status of the Shortcuts CLI. Absent for the `url` strategy. */\n exitCode?: number\n /**\n * `url` strategy only: the request reached Shortcuts. Not a claim that the\n * shortcut ran — that signal does not exist on this route.\n */\n dispatched?: boolean\n shortcut?: string\n error?: string\n}\n\nexport interface FocusShortcutList {\n /**\n * False when enumeration was not possible — inside the App Sandbox, or off\n * platform. An empty `shortcuts` then means *could not check*, not *none\n * installed*, and must not send the user through setup again.\n */\n canList: boolean\n shortcuts: string[]\n}\n\nexport interface FocusAPI {\n /** Current Focus state. Never throws — check `supported` first. */\n getStatus: () => Promise<FocusStatus>\n /** Present the system permission prompt for Focus status. */\n requestAuthorization: () => Promise<FocusAuthorization>\n /**\n * Turn Focus on or off by running the matching user shortcut. Resolves with\n * `ok: false` and a reason rather than throwing, because the common failure\n * — the shortcut doesn't exist yet — is something the app should surface to\n * the user, not treat as a crash.\n */\n setEnabled: (enabled: boolean, options?: FocusShortcutOptions) => Promise<FocusResult>\n /** Run any shortcut by name — for per-mode or timed Focus flows. */\n runShortcut: (name: string) => Promise<FocusResult>\n /** Every shortcut installed for the current user. Empty off-platform. */\n listShortcuts: () => Promise<string[]>\n /** Same, plus whether enumeration was possible at all. */\n listShortcutsResult: () => Promise<FocusShortcutList>\n}\n\nconst UNSUPPORTED: FocusStatus = { supported: false, isFocused: null, authorization: 'unsupported' }\n\nfunction unavailable(): FocusResult {\n return { ok: false, error: 'Focus control is only available in a Craft window on macOS' }\n}\n\nexport const focus: FocusAPI = {\n async getStatus() {\n if (!hasBridge('focus')) return { ...UNSUPPORTED }\n return await window.craft!.focus.getStatus()\n },\n\n async requestAuthorization() {\n if (!hasBridge('focus')) return 'unsupported'\n return await window.craft!.focus.requestAuthorization()\n },\n\n async setEnabled(enabled, options = {}) {\n if (!hasBridge('focus')) return unavailable()\n const name = enabled ? options.onShortcut : options.offShortcut\n if (!name) {\n return {\n ok: false,\n error: `focus.setEnabled: no ${enabled ? 'onShortcut' : 'offShortcut'} configured`,\n }\n }\n return await window.craft!.focus.setEnabled(enabled, options)\n },\n\n async runShortcut(name) {\n if (!hasBridge('focus')) return unavailable()\n if (!name) throw new Error('focus.runShortcut: name is required')\n return await window.craft!.focus.runShortcut(name)\n },\n\n async listShortcuts() {\n if (!hasBridge('focus')) return []\n return await window.craft!.focus.listShortcuts()\n },\n\n async listShortcutsResult() {\n if (!hasBridge('focus')) return { canList: false, shortcuts: [] }\n const r = await window.craft!.focus.listShortcutsResult()\n return { canList: Boolean(r?.canList), shortcuts: (r?.shortcuts as string[]) || [] }\n },\n}\n\n/**\n * Whether every shortcut the app depends on is installed.\n *\n * Worth calling on launch: the shortcuts are user-created, so the honest time\n * to discover they're missing is before the user is relying on the feature,\n * not at the moment a meeting starts.\n */\nexport async function hasFocusShortcuts(...names: string[]): Promise<boolean> {\n if (names.length === 0) return false\n const installed = new Set(await focus.listShortcuts())\n return names.every(name => installed.has(name))\n}\n\n/**\n * Like `hasFocusShortcuts`, but distinguishes \"not installed\" from \"could not\n * check\". Prefer this anywhere the answer drives a setup prompt.\n */\nexport async function focusShortcutsReady(...names: string[]): Promise<boolean | 'unknown'> {\n if (names.length === 0) return false\n const { canList, shortcuts } = await focus.listShortcutsResult()\n if (!canList) return 'unknown'\n const installed = new Set(shortcuts)\n return names.every(name => installed.has(name))\n}\n",
50
- "/**\n * Local HTTP listener — for OAuth callback flows.\n *\n * The native side binds a TCP socket on `127.0.0.1` and accepts one\n * request at a time. Each incoming request fires `craft:localServer:request`\n * with the parsed URL; apps respond via `respond({ status, body })`\n * within 5 seconds (the listener auto-replies with a default 200 page\n * after that to avoid hung sockets).\n *\n * **Typical OAuth flow:**\n * ```ts\n * const { port } = await localServer.start()\n * const off = localServer.onRequest(({ url }) => {\n * const code = new URL(`http://x${url}`).searchParams.get('code')\n * localServer.respond({ status: 200, body: '<h1>Done</h1>' })\n * resolveCode(code)\n * })\n * await shell.openExternal(`https://provider.com/oauth?redirect=http://127.0.0.1:${port}/cb`)\n * ```\n *\n * No web fallback — there's no socket-binding equivalent.\n */\nimport { hasBridge, onCraftEvent, requireBridge } from './_bridge'\n\nexport interface LocalServerStartResult {\n port: number\n started: boolean\n alreadyRunning?: boolean\n reason?: string\n}\n\nexport interface LocalServerRequestEvent {\n /** HTTP method (GET / POST / etc). */\n method: string\n /** Request path including query string (e.g. `/cb?code=abc`). */\n url: string\n}\n\nexport interface LocalServerRespondOptions {\n /** HTTP status code. Default 200. */\n status?: number\n /** Response body. Default \"OK\". */\n body?: string\n /** Content-Type header. Default `text/html; charset=utf-8`. */\n contentType?: string\n}\n\nexport interface LocalServerAPI {\n /**\n * Start the listener. Pass `port: 0` (default) to let the OS pick a\n * free port — read it from the resolved `port` field. Idempotent;\n * a second call while already running returns the existing port.\n */\n start: (port?: number, host?: string) => Promise<LocalServerStartResult>\n stop: () => Promise<void>\n /** Reply to the in-flight request. Must be called within 5s. */\n respond: (options?: LocalServerRespondOptions) => Promise<void>\n onRequest: (cb: (event: LocalServerRequestEvent) => void) => () => void\n\n /**\n * One-shot helper for OAuth flows: start the server, await the first\n * request, capture the URL, respond with a confirmation page, return\n * the URL. Throws if the bridge is unavailable.\n */\n awaitOAuthCallback: (options?: { port?: number, host?: string, timeoutMs?: number, successHTML?: string }) => Promise<{ url: string, port: number }>\n}\n\nexport const localServer: LocalServerAPI = {\n async start(port = 0, host = '127.0.0.1') {\n if (!hasBridge('localServer')) return { port: 0, started: false, reason: 'bridge unavailable' }\n return await window.craft!.localServer.start(port, host)\n },\n async stop() {\n if (!hasBridge('localServer')) return\n await window.craft!.localServer.stop()\n },\n async respond(options) {\n if (!hasBridge('localServer')) return\n await window.craft!.localServer.respond(options || { status: 200, body: 'OK' })\n },\n onRequest(cb) {\n return onCraftEvent<LocalServerRequestEvent>('craft:localServer:request', cb)\n },\n\n async awaitOAuthCallback(options = {}) {\n requireBridge('localServer')\n\n const { port: requestedPort = 0, host = '127.0.0.1', timeoutMs = 5 * 60 * 1000, successHTML } = options\n const start = await this.start(requestedPort, host)\n if (!start.started) throw new Error(`localServer: start failed${start.reason ? ` — ${start.reason}` : ''}`)\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n off()\n this.stop().catch(() => {})\n reject(new Error('localServer: OAuth callback timed out'))\n }, timeoutMs)\n\n const off = this.onRequest(({ url }) => {\n clearTimeout(timer)\n off()\n // Send a friendly success page so the user knows it worked.\n // The page closes itself after a moment — feels more polished\n // than leaving a blank tab open.\n const body = successHTML ?? `<!doctype html><meta charset=\"utf-8\"><title>Done</title>\n<style>body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f5f5f7}</style>\n<div><h1>You can close this tab.</h1><p>Returning to the app…</p></div>\n<script>setTimeout(()=>window.close(),1500)</script>`\n this.respond({ status: 200, body, contentType: 'text/html; charset=utf-8' })\n .catch(() => {})\n .finally(() => this.stop().catch(() => {}))\n resolve({ url, port: start.port })\n })\n })\n },\n}\n",
51
- "/**\n * Biometric authentication (TouchID / FaceID / OpticID).\n *\n * Wraps `LAContext` on macOS. Apps that secure features behind a\n * biometric gate (password managers, finance, encrypted notes) call\n * `evaluate(reason)` to present the system prompt; the call resolves\n * with `{success: true|false}` once the user dismisses the sheet.\n *\n * **Required Info.plist key**: `NSFaceIDUsageDescription` — without\n * it, evaluate() fails immediately on devices that have FaceID.\n *\n * No web fallback — WebAuthn covers a subset (security keys, browser-\n * level passkeys) but doesn't expose macOS biometrics directly.\n */\nimport { hasBridge } from './_bridge'\n\nexport type BiometryType = 'none' | 'touchID' | 'faceID' | 'opticID'\n\nexport interface BiometricEvaluateOptions {\n /** Allow falling back to the device passcode after biometry fails. */\n allowPasscodeFallback?: boolean\n}\n\nexport interface BiometricEvaluateResult {\n success: boolean\n /** When `success` is false, Apple's `LAError` numeric code. */\n errorCode?: number\n}\n\nexport interface BiometricAPI {\n /** True if the device has biometry hardware AND it's enrolled. */\n isAvailable: () => Promise<boolean>\n /** Which biometry hardware is present. `'none'` if unavailable. */\n getBiometryType: () => Promise<BiometryType>\n /**\n * Present the prompt and resolve once the user dismisses it.\n * `reason` is shown in the prompt body — required by Apple.\n */\n evaluate: (reason: string, options?: BiometricEvaluateOptions) => Promise<BiometricEvaluateResult>\n}\n\nexport const biometric: BiometricAPI = {\n async isAvailable() {\n if (!hasBridge('biometric')) return false\n return await window.craft!.biometric.isAvailable()\n },\n async getBiometryType() {\n if (!hasBridge('biometric')) return 'none'\n return await window.craft!.biometric.getBiometryType()\n },\n async evaluate(reason, options) {\n if (!reason) throw new Error('biometric.evaluate: reason is required')\n if (!hasBridge('biometric')) return { success: false, errorCode: -1 }\n return await window.craft!.biometric.evaluate(reason, options)\n },\n}\n",
52
- "/**\n * Audio playback + recording.\n *\n * macOS uses `NSSound` for playback (one sound at a time per bridge\n * instance) and `AVAudioRecorder` for recording (M4A AAC by default).\n *\n * Browser fallback uses `Audio` element for playback. Recording has\n * no clean fallback — `MediaRecorder` requires `getUserMedia` which\n * has its own permission prompt; apps that need cross-environment\n * recording should provide their own stream-based path.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface AudioPlayOptions {\n /** Volume 0..1. Default 1.0. */\n volume?: number\n /** Loop indefinitely until `stop()`. */\n loops?: boolean\n}\n\nexport interface AudioRecordOptions {\n /** Maximum recording duration in seconds. Indefinite if omitted. */\n maxDurationSec?: number\n}\n\nexport interface AudioAPI {\n /** Play an audio file from disk. */\n play: (path: string, options?: AudioPlayOptions) => Promise<boolean>\n /**\n * Play a system sound by name (e.g. \"Funk\", \"Glass\", \"Hero\").\n * Names live under `/System/Library/Sounds/`.\n */\n playSystemSound: (name: string) => Promise<boolean>\n /** Stop the current playback. Idempotent. */\n stop: () => Promise<void>\n isPlaying: () => Promise<boolean>\n /** Begin recording into the given path (creates a file). */\n startRecording: (path: string, options?: AudioRecordOptions) => Promise<boolean>\n /** Stop and finalize the current recording. */\n stopRecording: () => Promise<void>\n isRecording: () => Promise<boolean>\n}\n\nlet webAudio: HTMLAudioElement | null = null\n\nexport const audio: AudioAPI = {\n async play(path, options) {\n if (hasBridge('audio')) {\n return await window.craft!.audio.play(path, options)\n }\n if (typeof window === 'undefined' || typeof Audio === 'undefined') return false\n if (webAudio) { webAudio.pause(); webAudio = null }\n webAudio = new Audio(path)\n if (options?.volume != null) webAudio.volume = options.volume\n if (options?.loops) webAudio.loop = true\n try { await webAudio.play(); return true } catch { return false }\n },\n\n async playSystemSound(name) {\n if (hasBridge('audio')) return await window.craft!.audio.playSystemSound(name)\n // Web has no system-sound concept. Best-effort fallback: try a path\n // under /System/Library/Sounds — won't work in browsers but works\n // when this code runs under Bun against a non-Craft host.\n if (typeof window === 'undefined' || typeof Audio === 'undefined') return false\n try {\n webAudio = new Audio(`/System/Library/Sounds/${name}.aiff`)\n await webAudio.play()\n return true\n } catch { return false }\n },\n\n async stop() {\n if (hasBridge('audio')) {\n await window.craft!.audio.stop()\n return\n }\n if (webAudio) { webAudio.pause(); webAudio.currentTime = 0; webAudio = null }\n },\n\n async isPlaying() {\n if (hasBridge('audio')) return await window.craft!.audio.isPlaying()\n return !!(webAudio && !webAudio.paused)\n },\n\n async startRecording(path, options) {\n if (hasBridge('audio')) return await window.craft!.audio.startRecording(path, options)\n // Web fallback would need MediaRecorder + getUserMedia; we don't\n // bake that in because it requires a permission prompt apps need\n // to surface themselves. Return false so callers can branch.\n return false\n },\n\n async stopRecording() {\n if (hasBridge('audio')) await window.craft!.audio.stopRecording()\n },\n\n async isRecording() {\n if (hasBridge('audio')) return await window.craft!.audio.isRecording()\n return false\n },\n}\n",
53
- "/**\n * AppleScript executor.\n *\n * `craft.appleScript.execute(source)` compiles + runs an AppleScript\n * source string and resolves with the script's `stringValue`. Apps\n * use this to drive system automation flows: telling Mail to compose\n * a message, asking Music to play a track, mounting a disk image.\n *\n * No web fallback — AppleScript is a macOS-only system facility.\n * Calls outside Craft resolve with `{ok: false}`.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface AppleScriptResult {\n ok: boolean\n /** Stringified script result (NSAppleEventDescriptor.stringValue). */\n result?: string\n}\n\nexport interface AppleScriptAPI {\n /** Compile and run an AppleScript source string. */\n execute: (source: string) => Promise<AppleScriptResult>\n}\n\nexport const appleScript: AppleScriptAPI = {\n async execute(source) {\n if (!source) throw new Error('appleScript.execute: source is required')\n if (!hasBridge('appleScript')) return { ok: false }\n return await window.craft!.appleScript.execute(source)\n },\n}\n",
54
- "/**\n * File-association controls (LaunchServices on macOS).\n *\n * Apps register themselves as the default handler for a content type\n * — e.g. \"open `.myext` files in MyApp\" or \"myapp:// URLs go here.\"\n *\n * The system attaches our bundle id to the named UTI. `getDefault`\n * returns the current handler so apps can decide whether to prompt\n * \"make us the default?\" — Apple's HIG says you only ask once per\n * launch, but they don't enforce it.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface FileAssociationsAPI {\n /** Bundle id of the current default handler for the given UTI, or null. */\n getDefault: (uti: string) => Promise<string | null>\n /** Register the bundle id as the default handler for the given UTI. */\n setDefault: (uti: string, bundleId: string) => Promise<boolean>\n}\n\nexport const fileAssociations: FileAssociationsAPI = {\n async getDefault(uti) {\n if (!uti) throw new Error('fileAssociations.getDefault: uti is required')\n if (!hasBridge('fileAssociations')) return null\n const v = await window.craft!.fileAssociations.getDefault(uti)\n return v ? String(v) : null\n },\n async setDefault(uti, bundleId) {\n if (!uti || !bundleId) throw new Error('fileAssociations.setDefault: uti and bundleId are required')\n if (!hasBridge('fileAssociations')) return false\n return await window.craft!.fileAssociations.setDefault(uti, bundleId)\n },\n}\n",
55
- "/**\n * Finder colour tags.\n *\n * Read and write the tag list users see in Finder's sidebar — the\n * coloured dots next to file names. Stored as a binary plist xattr\n * (`com.apple.metadata:_kMDItemUserTags`).\n *\n * Tag entries often look like `\"Red\\n0\"` where the trailing `\\nN`\n * encodes the colour index. We pass them through unchanged so apps\n * can preserve or strip the suffix as they like.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface TagsAPI {\n /** Read the Finder tag list for `path`. Empty array if untagged. */\n get: (path: string) => Promise<string[]>\n /** Replace the tag list. Pass `[]` to clear (or use `clear`). */\n set: (path: string, tags: string[] | string) => Promise<boolean>\n /** Remove the tags xattr entirely. */\n clear: (path: string) => Promise<boolean>\n}\n\nexport const tags: TagsAPI = {\n async get(path) {\n if (!path) throw new Error('tags.get: path is required')\n if (!hasBridge('tags')) return []\n return await window.craft!.tags.get(path)\n },\n async set(path, t) {\n if (!path) throw new Error('tags.set: path is required')\n if (!hasBridge('tags')) return false\n // Normalize at the TS boundary so the bridge always sees an array\n // regardless of whether the caller passed a single string or list.\n const arr = Array.isArray(t) ? t : [String(t)]\n return await window.craft!.tags.set(path, arr)\n },\n async clear(path) {\n if (!path) throw new Error('tags.clear: path is required')\n if (!hasBridge('tags')) return false\n return await window.craft!.tags.clear(path)\n },\n}\n",
56
- "/**\n * PDF reader (PDFKit on macOS).\n *\n * Two operations covering the common \"read the file and grep its\n * text\" use case:\n *\n * - `countPages(path)` — total page count\n * - `extractText(path)` — concatenated plaintext of all pages\n *\n * Apps that need richer extraction (per-page text, embedded images,\n * annotations, form-field values) should walk the document directly\n * via the lower-level PDFKit surface.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface PDFAPI {\n /** Number of pages in the PDF, or 0 on error. */\n countPages: (path: string) => Promise<number>\n /** Concatenated plain text of all pages. Empty string on error. */\n extractText: (path: string) => Promise<string>\n}\n\nexport const pdf: PDFAPI = {\n async countPages(path) {\n if (!path) throw new Error('pdf.countPages: path is required')\n if (!hasBridge('pdf')) return 0\n return await window.craft!.pdf.countPages(path)\n },\n async extractText(path) {\n if (!path) throw new Error('pdf.extractText: path is required')\n if (!hasBridge('pdf')) return ''\n return await window.craft!.pdf.extractText(path)\n },\n}\n",
57
- "/**\n * Unified system log (`os_log` on macOS).\n *\n * Apps call `log.{debug,info,warn,error}(message)` and entries land\n * in Console.app, `log show`, and any aggregator the user has wired\n * up (e.g. log-shipper daemons, MDM agents).\n *\n * Outside a Craft window, falls through to the equivalent\n * `console.*` call so library code can call `log.info()` from web\n * builds without branching.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface LogAPI {\n debug: (message: string) => Promise<void>\n info: (message: string) => Promise<void>\n warn: (message: string) => Promise<void>\n error: (message: string) => Promise<void>\n}\n\nexport const log: LogAPI = {\n async debug(m) { if (hasBridge('log')) await window.craft!.log.debug(m); else console.debug(m) },\n async info(m) { if (hasBridge('log')) await window.craft!.log.info(m); else console.info(m) },\n async warn(m) { if (hasBridge('log')) await window.craft!.log.warn(m); else console.warn(m) },\n async error(m) { if (hasBridge('log')) await window.craft!.log.error(m); else console.error(m) },\n}\n",
58
- "/**\n * mDNS / Bonjour service discovery.\n *\n * `browse(serviceType)` starts watching for services of the given\n * type (e.g. `_http._tcp.`, `_airplay._tcp.`); discovered services\n * arrive on the `craft:bonjour:found` event, and `craft:bonjour:lost`\n * fires when an advertised service goes away.\n *\n * Service browsing is opt-in — apps must call `browse()` before\n * subscribers see anything, and `stop()` to release the network\n * resources. Forgetting `stop()` keeps the system browsing in the\n * background which is wasteful but not harmful.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface BonjourService {\n /** Service instance name (e.g. \"Living Room AppleTV\"). */\n name: string\n /** Resolved hostname when known; absent until address resolution. */\n host?: string\n port?: number\n /** Service type (the same string passed to `browse`). */\n type: string\n}\n\nexport interface BonjourAPI {\n /**\n * Start browsing for services of the given type\n * (e.g. `_http._tcp.`, `_airplay._tcp.`).\n */\n browse: (serviceType: string) => Promise<{ started: boolean, reason?: string }>\n stop: () => Promise<void>\n onFound: (cb: (service: BonjourService) => void) => () => void\n onLost: (cb: (service: BonjourService) => void) => () => void\n}\n\nexport const bonjour: BonjourAPI = {\n async browse(serviceType) {\n if (!hasBridge('bonjour')) return { started: false, reason: 'bridge unavailable' }\n return await window.craft!.bonjour.browse(serviceType)\n },\n async stop() { if (hasBridge('bonjour')) await window.craft!.bonjour.stop() },\n onFound(cb) { return onCraftEvent<BonjourService>('craft:bonjour:found', cb) },\n onLost(cb) { return onCraftEvent<BonjourService>('craft:bonjour:lost', cb) },\n}\n",
59
- "/**\n * Spotlight indexing.\n *\n * Surfaces app content (notes, contacts, conversations) in macOS\n * system search. Each item gets a stable identifier the app provides\n * — apps later use that id to remove or update entries as content\n * changes.\n *\n * Backend: `CSSearchableIndex` (Core Spotlight). Items are\n * permission-free to write; the index lives per-app in the user's\n * library directory and is queryable from Spotlight as soon as the\n * write completes.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface SpotlightItem {\n /** Stable id; pass back to `remove(...)` to drop this entry. */\n id: string\n /** Title shown in the Spotlight result. */\n title: string\n /** Secondary text (subtitle / one-line description). */\n description?: string\n /** Keywords to match on, in addition to title + description. */\n keywords?: string[]\n}\n\nexport interface SpotlightAPI {\n index: (items: SpotlightItem[]) => Promise<{ ok: boolean, reason?: string }>\n remove: (ids: string[]) => Promise<{ ok: boolean }>\n removeAll: () => Promise<{ ok: boolean }>\n}\n\nexport const spotlight: SpotlightAPI = {\n async index(items) {\n if (!hasBridge('spotlight')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.spotlight.index(items)\n },\n async remove(ids) {\n if (!hasBridge('spotlight')) return { ok: false }\n return await window.craft!.spotlight.remove(ids)\n },\n async removeAll() {\n if (!hasBridge('spotlight')) return { ok: false }\n return await window.craft!.spotlight.removeAll()\n },\n}\n",
60
- "/**\n * Speech-to-text via `SFSpeechRecognizer`.\n *\n * Apps call `start()` to begin capturing microphone input; partial\n * transcripts arrive on `craft:speechRecognition:partial` while the\n * user speaks, and a final transcript arrives on\n * `craft:speechRecognition:final` once the recognizer settles.\n *\n * **Required Info.plist keys**:\n * - `NSMicrophoneUsageDescription` — for AVAudioEngine input\n * - `NSSpeechRecognitionUsageDescription` — for the recognizer\n *\n * Without both, the system rejects the request and `isAvailable()`\n * returns false.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface SpeechRecognitionStartOptions {\n /** BCP-47 language code (e.g. `en-US`). Defaults to system locale. */\n language?: string\n /** Emit partial transcripts while the user is still speaking. */\n partialResults?: boolean\n}\n\nexport interface SpeechRecognitionAPI {\n /** True if the recognizer is enrolled, authorized, and online. */\n isAvailable: () => Promise<boolean>\n /** Begin listening. Resolves when the audio session is established. */\n start: (opts?: SpeechRecognitionStartOptions) => Promise<{ started: boolean, reason?: string }>\n /** Stop listening; the recognizer flushes the final transcript. */\n stop: () => Promise<void>\n /** Subscribe to partial transcripts (only when `partialResults: true`). */\n onPartial: (cb: (e: { transcript: string }) => void) => () => void\n /** Subscribe to the final transcript per session. */\n onFinal: (cb: (e: { transcript: string }) => void) => () => void\n}\n\nexport const speechRecognition: SpeechRecognitionAPI = {\n async isAvailable() {\n if (!hasBridge('speechRecognition')) return false\n return await window.craft!.speechRecognition.isAvailable()\n },\n async start(opts) {\n if (!hasBridge('speechRecognition')) return { started: false, reason: 'bridge unavailable' }\n return await window.craft!.speechRecognition.start(opts)\n },\n async stop() { if (hasBridge('speechRecognition')) await window.craft!.speechRecognition.stop() },\n onPartial(cb) { return onCraftEvent<{ transcript: string }>('craft:speechRecognition:partial', cb) },\n onFinal(cb) { return onCraftEvent<{ transcript: string }>('craft:speechRecognition:final', cb) },\n}\n",
61
- "/**\n * Vision framework — OCR, face detection, barcode scanning.\n *\n * Each function reads an image from disk and returns an array of\n * results. Results are coordinate-tagged where geometry matters\n * (faces, barcodes); text recognition returns a plain string per\n * detected block plus the recognizer's confidence score.\n *\n * No web fallback — Vision is a macOS / iOS framework. Browsers\n * have OCR-via-Tesseract-WASM but the shape is different and apps\n * that want both should layer that themselves.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface VisionTextResult {\n text: string\n /** 0..1 confidence score from VNRecognizedText.confidence. */\n confidence?: number\n}\n\nexport interface VisionFaceResult {\n /** Face bounding box in image-pixel coordinates. */\n bounds: { x: number, y: number, width: number, height: number }\n}\n\nexport interface VisionBarcodeResult {\n /** Decoded payload (URL, text, contact card, etc). */\n payload: string\n /** Symbology — `qr`, `ean8`, `ean13`, `code128`, etc. */\n type?: string\n}\n\nexport interface VisionAPI {\n /** OCR an image at a path. Returns recognized text blocks. */\n recognizeText: (path: string) => Promise<VisionTextResult[]>\n /** Find faces in an image. */\n detectFaces: (path: string) => Promise<VisionFaceResult[]>\n /** Decode barcodes / QR codes. */\n detectBarcodes: (path: string) => Promise<VisionBarcodeResult[]>\n}\n\nexport const vision: VisionAPI = {\n async recognizeText(path) {\n if (!path) throw new Error('vision.recognizeText: path is required')\n if (!hasBridge('vision')) return []\n return await window.craft!.vision.recognizeText(path)\n },\n async detectFaces(path) {\n if (!path) throw new Error('vision.detectFaces: path is required')\n if (!hasBridge('vision')) return []\n return await window.craft!.vision.detectFaces(path)\n },\n async detectBarcodes(path) {\n if (!path) throw new Error('vision.detectBarcodes: path is required')\n if (!hasBridge('vision')) return []\n return await window.craft!.vision.detectBarcodes(path)\n },\n}\n",
62
- "/**\n * CoreMIDI bindings — list endpoints, send and receive MIDI messages.\n *\n * `listSources()` returns inputs (other apps + hardware sending TO us);\n * `listDestinations()` returns outputs we can send TO. Each entry has\n * a stable `index` for the lifetime of the process — apps pass it back\n * to `send` / `subscribe`.\n *\n * Messages flow as raw bytes (`Uint8Array` / `number[]`); apps that\n * want note-on / note-off / CC parsing can layer that on top.\n *\n * Browser fallback: the Web MIDI API (`navigator.requestMIDIAccess`)\n * exposes the same conceptual surface but a different shape; this\n * module doesn't try to bridge them — apps targeting both should\n * detect and route per-environment.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface MIDIEndpoint {\n /** Stable index for the lifetime of the process. */\n index: number\n name: string\n}\n\nexport interface MIDIMessageEvent {\n /** Source index the message came from. */\n index: number\n /** Raw MIDI bytes (status + 1–2 data bytes for channel messages). */\n data: number[]\n}\n\nexport interface MIDIAPI {\n listSources: () => Promise<MIDIEndpoint[]>\n listDestinations: () => Promise<MIDIEndpoint[]>\n send: (destinationIndex: number, data: Uint8Array | number[]) => Promise<{ ok: boolean, reason?: string }>\n subscribe: (sourceIndex: number) => Promise<{ ok: boolean, reason?: string }>\n unsubscribe: (sourceIndex: number) => Promise<{ ok: boolean }>\n onMessage: (cb: (event: MIDIMessageEvent) => void) => () => void\n}\n\nexport const midi: MIDIAPI = {\n async listSources() {\n if (!hasBridge('midi')) return []\n return await window.craft!.midi.listSources()\n },\n async listDestinations() {\n if (!hasBridge('midi')) return []\n return await window.craft!.midi.listDestinations()\n },\n async send(destinationIndex, data) {\n if (!hasBridge('midi')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.midi.send(destinationIndex, data)\n },\n async subscribe(sourceIndex) {\n if (!hasBridge('midi')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.midi.subscribe(sourceIndex)\n },\n async unsubscribe(sourceIndex) {\n if (!hasBridge('midi')) return { ok: false }\n return await window.craft!.midi.unsubscribe(sourceIndex)\n },\n onMessage(cb) { return onCraftEvent<MIDIMessageEvent>('craft:midi:message', cb) },\n}\n",
63
- "/**\n * CoreML bindings — load + run on-device ML models.\n *\n * Workflow:\n * 1. `loadModel(id, path)` compiles (if needed) and caches the model\n * under the caller-provided id.\n * 2. `predict(id, input)` runs inference. Input shape varies wildly\n * by model — apps should consult their `MLModelDescription` and\n * pass a dictionary that matches the input feature names.\n * 3. `unloadModel(id)` releases the underlying `MLModel` reference.\n *\n * Browser fallback: WebNN / TensorFlow.js fill the same role with a\n * different API shape; apps targeting both should detect at runtime.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface CoreMLAPI {\n loadModel: (id: string, path: string) => Promise<boolean>\n unloadModel: (id: string) => Promise<void>\n predict: (id: string, input: Record<string, unknown>) => Promise<unknown>\n}\n\nexport const coreml: CoreMLAPI = {\n async loadModel(id, path) {\n if (!id || !path) throw new Error('coreml.loadModel: id and path are required')\n if (!hasBridge('coreml')) return false\n return await window.craft!.coreml.loadModel(id, path)\n },\n async unloadModel(id) {\n if (!hasBridge('coreml')) return\n await window.craft!.coreml.unloadModel(id)\n },\n async predict(id, input) {\n if (!id) throw new Error('coreml.predict: id is required')\n if (!hasBridge('coreml')) return null\n return await window.craft!.coreml.predict(id, input)\n },\n}\n",
64
- "/**\n * Continuity Camera — list paired iPhone (and other Apple) cameras.\n *\n * Once the user has enabled it in Settings → General → AirPlay & Handoff,\n * the iPhone shows up alongside built-in cameras in `AVCaptureDevice`'s\n * device list. We surface the list so apps can populate a \"choose camera\"\n * UI; binding the actual capture session is the app's responsibility\n * (or `navigator.mediaDevices.getUserMedia` from the renderer side).\n *\n * The `isContinuity` flag distinguishes Continuity-paired devices from\n * regular built-in / USB cameras so apps can label them appropriately.\n */\nimport { hasBridge } from './_bridge'\n\nexport interface ContinuityCameraDevice {\n /** Stable AVCaptureDevice unique identifier. */\n id: string\n /** Localized name (e.g. \"iPhone Camera\"). */\n name: string\n /** Manufacturer string from AVCaptureDevice. */\n manufacturer: string\n /** True if the device is paired via Continuity Camera. */\n isContinuity: boolean\n}\n\nexport interface ContinuityCameraAPI {\n listCameras: () => Promise<ContinuityCameraDevice[]>\n}\n\nexport const continuityCamera: ContinuityCameraAPI = {\n async listCameras() {\n if (!hasBridge('continuityCamera')) return []\n return await window.craft!.continuityCamera.listCameras()\n },\n}\n",
65
- "/**\n * macOS Services menu integration.\n *\n * The Services submenu (`AppName → Services → ...` and the right-click\n * contextual menu) lets users hand selected text/files to other apps.\n * Apps that want to appear there declare entries in `Info.plist`'s\n * `NSServices` array AND register handlers for the named selectors.\n *\n * `register(name)` records that we'll handle a service. The\n * `Info.plist` entry is still required for the system to surface the\n * menu item; runtime registration wires our handler so the user's\n * pick fires `craft:serviceMenu:invoked`.\n *\n * macOS reads `NSServices` once at app launch — there's no API for\n * adding services dynamically. Apps that need dynamic services should\n * ship a worker app extension instead.\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface ServiceMenuInvokedEvent {\n /** Service name matching the registration. */\n name: string\n /** Pasteboard payload the user invoked the service against. */\n payload?: { type: string, value: string }\n}\n\nexport interface ServiceMenuAPI {\n register: (name: string) => Promise<{ ok: boolean, reason?: string }>\n unregister: (name: string) => Promise<void>\n onInvoked: (cb: (event: ServiceMenuInvokedEvent) => void) => () => void\n}\n\nexport const serviceMenu: ServiceMenuAPI = {\n async register(name) {\n if (!name) throw new Error('serviceMenu.register: name is required')\n if (!hasBridge('serviceMenu')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.serviceMenu.register(name)\n },\n async unregister(name) {\n if (!name) throw new Error('serviceMenu.unregister: name is required')\n if (!hasBridge('serviceMenu')) return\n await window.craft!.serviceMenu.unregister(name)\n },\n onInvoked(cb) { return onCraftEvent<ServiceMenuInvokedEvent>('craft:serviceMenu:invoked', cb) },\n}\n",
66
- "/**\n * Serial-port I/O — for IoT, Arduino, label printers, etc.\n *\n * `list()` enumerates `/dev/cu.*` + `/dev/tty.*` (macOS) or\n * `/dev/ttyUSB*` / `/dev/ttyACM*` / `/dev/ttyS*` (Linux). Apps use\n * the resulting paths to populate \"choose device\" UIs.\n *\n * Open + read + write needs platform-specific termios setup; the\n * native side stubs those today and returns `ok:false` with a\n * reason. The list is the part most apps need first (the \"which\n * device\" UI).\n */\nimport { hasBridge, onCraftEvent } from './_bridge'\n\nexport interface SerialPort {\n /** Absolute device path (e.g. `/dev/cu.usbmodem14101`). */\n path: string\n}\n\nexport interface SerialDataEvent {\n /** Open-handle id returned from `open()`. */\n id: string\n /** Raw bytes received since the last event. */\n data: number[]\n}\n\nexport interface SerialAPI {\n list: () => Promise<SerialPort[]>\n open: (path: string, baud?: number) => Promise<{ id?: string, ok: boolean, reason?: string }>\n write: (id: string, data: string) => Promise<{ ok: boolean, reason?: string }>\n close: (id: string) => Promise<void>\n onData: (cb: (event: SerialDataEvent) => void) => () => void\n}\n\nexport const serial: SerialAPI = {\n async list() {\n if (!hasBridge('serial')) return []\n return await window.craft!.serial.list()\n },\n async open(path, baud = 9600) {\n if (!path) throw new Error('serial.open: path is required')\n if (!hasBridge('serial')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.serial.open(path, baud)\n },\n async write(id, data) {\n if (!id) throw new Error('serial.write: id is required')\n if (!hasBridge('serial')) return { ok: false, reason: 'bridge unavailable' }\n return await window.craft!.serial.write(id, data)\n },\n async close(id) {\n if (!hasBridge('serial')) return\n await window.craft!.serial.close(id)\n },\n onData(cb) { return onCraftEvent<SerialDataEvent>('craft:serial:data', cb) },\n}\n",
67
- "/**\n * Capabilities — single place to ask \"is this bridge usable on the\n * current host?\" rather than scattering `hasBridge('xxx')` checks.\n *\n * The TypeScript SDK is largely cross-platform — every module has a\n * sensible fallback when the bridge is missing — but a number of\n * macOS-specific APIs (Vision, AppleScript, Spotlight, Continuity,\n * etc.) only return real data inside a Craft window on macOS.\n *\n * `getCapabilities()` returns a snapshot of which bridges respond. App\n * code can use this to enable or hide UI rather than relying on calls\n * that fail silently.\n */\nimport { hasBridge } from './_bridge'\n\n/**\n * The set of bridges the SDK knows about, plus the platforms each is\n * implemented on. Used to power the `capabilities` map and to drive\n * docs / tooling.\n *\n * `'all'` means the bridge has a working web/non-bridge fallback too;\n * `'macos'` means it requires a Craft macOS host; `'native'` means it\n * needs *some* Craft host (mac/linux/windows) but has no web fallback.\n */\nexport type BridgePlatformSupport = 'all' | 'native' | 'macos'\n\nexport interface BridgeCapability {\n /** Bridge namespace as it appears under `window.craft`. */\n name: string\n /** Where the bridge is implemented today. */\n support: BridgePlatformSupport\n /** True when the bridge is reachable from the current host. */\n available: boolean\n}\n\n/**\n * Authoritative list. Keep in sync with the TS modules + native side.\n * When a new bridge ships, add a row here; the public capabilities\n * surface picks it up automatically.\n */\nconst BRIDGE_INDEX: Array<{ name: string, support: BridgePlatformSupport }> = [\n // Cross-platform with sensible web fallback\n { name: 'fs', support: 'native' },\n { name: 'shell', support: 'native' },\n { name: 'system', support: 'all' },\n { name: 'clipboard', support: 'all' },\n { name: 'dialog', support: 'all' },\n { name: 'window', support: 'native' },\n { name: 'tray', support: 'native' },\n { name: 'menu', support: 'native' },\n { name: 'theme', support: 'all' },\n { name: 'screen', support: 'all' },\n { name: 'network', support: 'all' },\n { name: 'power', support: 'all' },\n { name: 'battery', support: 'all' },\n { name: 'notifications', support: 'all' },\n { name: 'globalShortcuts', support: 'native' },\n { name: 'autolaunch', support: 'native' },\n { name: 'appInfo', support: 'all' },\n { name: 'localServer', support: 'native' },\n { name: 'bluetooth', support: 'native' },\n { name: 'crashReporter', support: 'all' },\n { name: 'updater', support: 'native' },\n { name: 'iap', support: 'macos' },\n { name: 'keychain', support: 'native' },\n { name: 'log', support: 'all' },\n\n // macOS-specific\n { name: 'biometric', support: 'macos' },\n { name: 'location', support: 'macos' },\n { name: 'audio', support: 'macos' },\n { name: 'deepLink', support: 'native' },\n { name: 'handoff', support: 'macos' },\n { name: 'liveActivities', support: 'macos' },\n { name: 'touchbar', support: 'macos' },\n { name: 'dragOut', support: 'macos' },\n { name: 'appleScript', support: 'macos' },\n { name: 'fileAssociations', support: 'native' },\n { name: 'tags', support: 'macos' },\n { name: 'pdf', support: 'macos' },\n { name: 'bonjour', support: 'macos' },\n { name: 'spotlight', support: 'macos' },\n { name: 'speechRecognition', support: 'macos' },\n { name: 'vision', support: 'macos' },\n { name: 'midi', support: 'macos' },\n { name: 'coreml', support: 'macos' },\n { name: 'continuityCamera', support: 'macos' },\n { name: 'serviceMenu', support: 'macos' },\n { name: 'serial', support: 'native' },\n]\n\n/**\n * Snapshot of every known bridge's availability on the current host.\n * Re-call after the bridge IIFE loads (e.g. `DOMContentLoaded`) — the\n * `available` field is computed against `window.craft` at call time.\n */\nexport function getCapabilities(): BridgeCapability[] {\n return BRIDGE_INDEX.map(({ name, support }) => ({\n name,\n support,\n available: hasBridge(name),\n }))\n}\n\n/**\n * Lookup a single capability by name. Returns `undefined` for bridges\n * the SDK doesn't know about.\n */\nexport function getCapability(name: string): BridgeCapability | undefined {\n const entry = BRIDGE_INDEX.find(b => b.name === name)\n if (!entry) return undefined\n return { ...entry, available: hasBridge(name) }\n}\n\n/**\n * Convenience predicate — `true` when a bridge is *both* known to the\n * SDK and currently reachable.\n */\nexport function isAvailable(name: string): boolean {\n const cap = getCapability(name)\n return !!cap && cap.available\n}\n"
68
- ],
69
- "mappings": "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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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",
70
- "debugId": "4BACEAAC5AF2924164756E2164756E21",
71
- "names": []
72
- }