@fgv/ts-app-shell 5.1.0-2 → 5.1.0-21
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.browser.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/packlets/ai-assist/index.js.map +1 -0
- package/dist/packlets/ai-assist/useAiAssist.js +216 -15
- package/dist/packlets/ai-assist/useAiAssist.js.map +1 -0
- package/dist/packlets/badge/index.js +23 -0
- package/dist/packlets/badge/index.js.map +1 -0
- package/dist/packlets/badge/renderStatusBadge.js +44 -0
- package/dist/packlets/badge/renderStatusBadge.js.map +1 -0
- package/dist/packlets/cascade/CascadeContainer.js.map +1 -0
- package/dist/packlets/cascade/ComparisonView.js.map +1 -0
- package/dist/packlets/cascade/EntityTabLayout.js.map +1 -0
- package/dist/packlets/cascade/MobileCascadeStack.js.map +1 -0
- package/dist/packlets/cascade/index.js.map +1 -0
- package/dist/packlets/cascade/model.js.map +1 -0
- package/dist/packlets/cascade/useCascadeOps.js.map +1 -0
- package/dist/packlets/cascade/useCascadeTransitions.js.map +1 -0
- package/dist/packlets/detail/DetailHelpers.js.map +1 -0
- package/dist/packlets/detail/index.js.map +1 -0
- package/dist/packlets/drop-zone/JsonDropZone.js.map +1 -0
- package/dist/packlets/drop-zone/index.js.map +1 -0
- package/dist/packlets/editing/EditFieldHelpers.js +4 -4
- package/dist/packlets/editing/EditFieldHelpers.js.map +1 -0
- package/dist/packlets/editing/MultiActionButton.js.map +1 -0
- package/dist/packlets/editing/NumericInput.js.map +1 -0
- package/dist/packlets/editing/TypeaheadInput.js.map +1 -0
- package/dist/packlets/editing/index.js.map +1 -0
- package/dist/packlets/editing/useTypeaheadMatch.js.map +1 -0
- package/dist/packlets/keyboard/index.js.map +1 -0
- package/dist/packlets/keyboard/registry.js.map +1 -0
- package/dist/packlets/keyboard/useKeyboardShortcuts.js.map +1 -0
- package/dist/packlets/messages/MessagesContext.js.map +1 -0
- package/dist/packlets/messages/MessagesLogger.js.map +1 -0
- package/dist/packlets/messages/StatusBar.js.map +1 -0
- package/dist/packlets/messages/Toast.js.map +1 -0
- package/dist/packlets/messages/index.js.map +1 -0
- package/dist/packlets/messages/model.js.map +1 -0
- package/dist/packlets/messages/useLogReporter.js.map +1 -0
- package/dist/packlets/modal/ConfirmDialog.js.map +1 -0
- package/dist/packlets/modal/Modal.js.map +1 -0
- package/dist/packlets/modal/index.js.map +1 -0
- package/dist/packlets/print/PrintEnclosure.js.map +1 -0
- package/dist/packlets/print/index.js.map +1 -0
- package/dist/packlets/print/openPrintWindow.js.map +1 -0
- package/dist/packlets/responsive/ResponsiveProvider.js.map +1 -0
- package/dist/packlets/responsive/index.js.map +1 -0
- package/dist/packlets/responsive/useResponsiveLayout.js.map +1 -0
- package/dist/packlets/selectors/EntityRow.js.map +1 -0
- package/dist/packlets/selectors/PreferredSelector.js.map +1 -0
- package/dist/packlets/selectors/index.js.map +1 -0
- package/dist/packlets/sidebar/CollectionSection.js +158 -43
- package/dist/packlets/sidebar/CollectionSection.js.map +1 -0
- package/dist/packlets/sidebar/EntityList.js.map +1 -0
- package/dist/packlets/sidebar/FilterBar.js.map +1 -0
- package/dist/packlets/sidebar/FilterRow.js.map +1 -0
- package/dist/packlets/sidebar/GroupedEntityList.js.map +1 -0
- package/dist/packlets/sidebar/SearchBar.js.map +1 -0
- package/dist/packlets/sidebar/SidebarLayout.js.map +1 -0
- package/dist/packlets/sidebar/index.js.map +1 -0
- package/dist/packlets/theme/ThemeProvider.js.map +1 -0
- package/dist/packlets/theme/index.js.map +1 -0
- package/dist/packlets/top-bar/ModeSelector.js.map +1 -0
- package/dist/packlets/top-bar/TabBar.js +4 -1
- package/dist/packlets/top-bar/TabBar.js.map +1 -0
- package/dist/packlets/top-bar/index.js.map +1 -0
- package/dist/packlets/url-sync/index.js.map +1 -0
- package/dist/packlets/url-sync/useUrlSync.js.map +1 -0
- package/lib/index.browser.d.ts.map +1 -0
- package/lib/index.browser.js.map +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js.map +1 -0
- package/lib/packlets/ai-assist/index.d.ts.map +1 -0
- package/lib/packlets/ai-assist/index.js.map +1 -0
- package/lib/packlets/ai-assist/useAiAssist.d.ts +26 -0
- package/lib/packlets/ai-assist/useAiAssist.d.ts.map +1 -0
- package/lib/packlets/ai-assist/useAiAssist.js +216 -15
- package/lib/packlets/ai-assist/useAiAssist.js.map +1 -0
- package/lib/packlets/badge/index.d.ts +2 -0
- package/lib/packlets/badge/index.d.ts.map +1 -0
- package/lib/packlets/badge/index.js +27 -0
- package/lib/packlets/badge/index.js.map +1 -0
- package/lib/packlets/badge/renderStatusBadge.d.ts +11 -0
- package/lib/packlets/badge/renderStatusBadge.d.ts.map +1 -0
- package/lib/packlets/badge/renderStatusBadge.js +50 -0
- package/lib/packlets/badge/renderStatusBadge.js.map +1 -0
- package/lib/packlets/cascade/CascadeContainer.d.ts.map +1 -0
- package/lib/packlets/cascade/CascadeContainer.js.map +1 -0
- package/lib/packlets/cascade/ComparisonView.d.ts.map +1 -0
- package/lib/packlets/cascade/ComparisonView.js.map +1 -0
- package/lib/packlets/cascade/EntityTabLayout.d.ts.map +1 -0
- package/lib/packlets/cascade/EntityTabLayout.js.map +1 -0
- package/lib/packlets/cascade/MobileCascadeStack.d.ts.map +1 -0
- package/lib/packlets/cascade/MobileCascadeStack.js.map +1 -0
- package/lib/packlets/cascade/index.d.ts.map +1 -0
- package/lib/packlets/cascade/index.js.map +1 -0
- package/lib/packlets/cascade/model.d.ts.map +1 -0
- package/lib/packlets/cascade/model.js.map +1 -0
- package/lib/packlets/cascade/useCascadeOps.d.ts.map +1 -0
- package/lib/packlets/cascade/useCascadeOps.js.map +1 -0
- package/lib/packlets/cascade/useCascadeTransitions.d.ts.map +1 -0
- package/lib/packlets/cascade/useCascadeTransitions.js.map +1 -0
- package/lib/packlets/detail/DetailHelpers.d.ts.map +1 -0
- package/lib/packlets/detail/DetailHelpers.js.map +1 -0
- package/lib/packlets/detail/index.d.ts.map +1 -0
- package/lib/packlets/detail/index.js.map +1 -0
- package/lib/packlets/drop-zone/JsonDropZone.d.ts.map +1 -0
- package/lib/packlets/drop-zone/JsonDropZone.js.map +1 -0
- package/lib/packlets/drop-zone/index.d.ts.map +1 -0
- package/lib/packlets/drop-zone/index.js.map +1 -0
- package/lib/packlets/editing/EditFieldHelpers.d.ts +6 -2
- package/lib/packlets/editing/EditFieldHelpers.d.ts.map +1 -0
- package/lib/packlets/editing/EditFieldHelpers.js +4 -4
- package/lib/packlets/editing/EditFieldHelpers.js.map +1 -0
- package/lib/packlets/editing/MultiActionButton.d.ts.map +1 -0
- package/lib/packlets/editing/MultiActionButton.js.map +1 -0
- package/lib/packlets/editing/NumericInput.d.ts.map +1 -0
- package/lib/packlets/editing/NumericInput.js.map +1 -0
- package/lib/packlets/editing/TypeaheadInput.d.ts.map +1 -0
- package/lib/packlets/editing/TypeaheadInput.js.map +1 -0
- package/lib/packlets/editing/index.d.ts.map +1 -0
- package/lib/packlets/editing/index.js.map +1 -0
- package/lib/packlets/editing/useTypeaheadMatch.d.ts.map +1 -0
- package/lib/packlets/editing/useTypeaheadMatch.js.map +1 -0
- package/lib/packlets/keyboard/index.d.ts.map +1 -0
- package/lib/packlets/keyboard/index.js.map +1 -0
- package/lib/packlets/keyboard/registry.d.ts.map +1 -0
- package/lib/packlets/keyboard/registry.js.map +1 -0
- package/lib/packlets/keyboard/useKeyboardShortcuts.d.ts.map +1 -0
- package/lib/packlets/keyboard/useKeyboardShortcuts.js.map +1 -0
- package/lib/packlets/messages/MessagesContext.d.ts.map +1 -0
- package/lib/packlets/messages/MessagesContext.js.map +1 -0
- package/lib/packlets/messages/MessagesLogger.d.ts.map +1 -0
- package/lib/packlets/messages/MessagesLogger.js.map +1 -0
- package/lib/packlets/messages/StatusBar.d.ts.map +1 -0
- package/lib/packlets/messages/StatusBar.js.map +1 -0
- package/lib/packlets/messages/Toast.d.ts.map +1 -0
- package/lib/packlets/messages/Toast.js.map +1 -0
- package/lib/packlets/messages/index.d.ts.map +1 -0
- package/lib/packlets/messages/index.js.map +1 -0
- package/lib/packlets/messages/model.d.ts.map +1 -0
- package/lib/packlets/messages/model.js.map +1 -0
- package/lib/packlets/messages/useLogReporter.d.ts.map +1 -0
- package/lib/packlets/messages/useLogReporter.js.map +1 -0
- package/lib/packlets/modal/ConfirmDialog.d.ts.map +1 -0
- package/lib/packlets/modal/ConfirmDialog.js.map +1 -0
- package/lib/packlets/modal/Modal.d.ts.map +1 -0
- package/lib/packlets/modal/Modal.js.map +1 -0
- package/lib/packlets/modal/index.d.ts.map +1 -0
- package/lib/packlets/modal/index.js.map +1 -0
- package/lib/packlets/print/PrintEnclosure.d.ts.map +1 -0
- package/lib/packlets/print/PrintEnclosure.js.map +1 -0
- package/lib/packlets/print/index.d.ts.map +1 -0
- package/lib/packlets/print/index.js.map +1 -0
- package/lib/packlets/print/openPrintWindow.d.ts.map +1 -0
- package/lib/packlets/print/openPrintWindow.js.map +1 -0
- package/lib/packlets/responsive/ResponsiveProvider.d.ts.map +1 -0
- package/lib/packlets/responsive/ResponsiveProvider.js.map +1 -0
- package/lib/packlets/responsive/index.d.ts.map +1 -0
- package/lib/packlets/responsive/index.js.map +1 -0
- package/lib/packlets/responsive/useResponsiveLayout.d.ts.map +1 -0
- package/lib/packlets/responsive/useResponsiveLayout.js.map +1 -0
- package/lib/packlets/selectors/EntityRow.d.ts.map +1 -0
- package/lib/packlets/selectors/EntityRow.js.map +1 -0
- package/lib/packlets/selectors/PreferredSelector.d.ts.map +1 -0
- package/lib/packlets/selectors/PreferredSelector.js.map +1 -0
- package/lib/packlets/selectors/index.d.ts.map +1 -0
- package/lib/packlets/selectors/index.js.map +1 -0
- package/lib/packlets/sidebar/CollectionSection.d.ts +40 -2
- package/lib/packlets/sidebar/CollectionSection.d.ts.map +1 -0
- package/lib/packlets/sidebar/CollectionSection.js +157 -42
- package/lib/packlets/sidebar/CollectionSection.js.map +1 -0
- package/lib/packlets/sidebar/EntityList.d.ts.map +1 -0
- package/lib/packlets/sidebar/EntityList.js.map +1 -0
- package/lib/packlets/sidebar/FilterBar.d.ts.map +1 -0
- package/lib/packlets/sidebar/FilterBar.js.map +1 -0
- package/lib/packlets/sidebar/FilterRow.d.ts.map +1 -0
- package/lib/packlets/sidebar/FilterRow.js.map +1 -0
- package/lib/packlets/sidebar/GroupedEntityList.d.ts.map +1 -0
- package/lib/packlets/sidebar/GroupedEntityList.js.map +1 -0
- package/lib/packlets/sidebar/SearchBar.d.ts.map +1 -0
- package/lib/packlets/sidebar/SearchBar.js.map +1 -0
- package/lib/packlets/sidebar/SidebarLayout.d.ts.map +1 -0
- package/lib/packlets/sidebar/SidebarLayout.js.map +1 -0
- package/lib/packlets/sidebar/index.d.ts +1 -1
- package/lib/packlets/sidebar/index.d.ts.map +1 -0
- package/lib/packlets/sidebar/index.js.map +1 -0
- package/lib/packlets/theme/ThemeProvider.d.ts.map +1 -0
- package/lib/packlets/theme/ThemeProvider.js.map +1 -0
- package/lib/packlets/theme/index.d.ts.map +1 -0
- package/lib/packlets/theme/index.js.map +1 -0
- package/lib/packlets/top-bar/ModeSelector.d.ts.map +1 -0
- package/lib/packlets/top-bar/ModeSelector.js.map +1 -0
- package/lib/packlets/top-bar/TabBar.d.ts +12 -0
- package/lib/packlets/top-bar/TabBar.d.ts.map +1 -0
- package/lib/packlets/top-bar/TabBar.js +4 -1
- package/lib/packlets/top-bar/TabBar.js.map +1 -0
- package/lib/packlets/top-bar/index.d.ts +1 -1
- package/lib/packlets/top-bar/index.d.ts.map +1 -0
- package/lib/packlets/top-bar/index.js.map +1 -0
- package/lib/packlets/url-sync/index.d.ts.map +1 -0
- package/lib/packlets/url-sync/index.js.map +1 -0
- package/lib/packlets/url-sync/useUrlSync.d.ts.map +1 -0
- package/lib/packlets/url-sync/useUrlSync.js.map +1 -0
- package/package.json +16 -16
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatusBar.js","sourceRoot":"","sources":["../../../src/packlets/messages/StatusBar.tsx"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { useCallback, useMemo, useState } from 'react';\n\nimport { Logging, type MessageLogLevel } from '@fgv/ts-utils';\nimport { FunnelIcon, DocumentDuplicateIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';\nimport { CheckIcon } from '@heroicons/react/24/solid';\n\nimport { IMessage, MessageSeverity } from './model';\nimport { useResponsive } from '../responsive';\n\n// ============================================================================\n// Severity display config\n// ============================================================================\n\nconst SEVERITY_ICONS: Record<MessageSeverity, string> = {\n info: '\\u2139',\n success: '\\u2713',\n warning: '\\u26A0',\n error: '\\u2717'\n};\n\nconst SEVERITY_COLORS: Record<MessageSeverity, string> = {\n info: 'text-status-info-icon',\n success: 'text-status-success-icon',\n warning: 'text-status-warning-icon',\n error: 'text-status-error-icon'\n};\n\nconst LOG_ROW_COLORS: Record<MessageSeverity, string> = {\n info: '',\n success: 'bg-status-success-bg',\n warning: 'bg-status-warning-bg',\n error: 'bg-status-error-bg'\n};\n\n// ============================================================================\n// Level filter config\n// ============================================================================\n\n/**\n * Maps MessageSeverity to MessageLogLevel for shouldLog filtering.\n * 'success' is treated as 'info' since it doesn't exist in the log level hierarchy.\n */\nfunction severityToLogLevel(severity: MessageSeverity): MessageLogLevel {\n return severity === 'success' ? 'info' : severity;\n}\n\n/**\n * Filter choices exposed in the UI, mapping labels to ReporterLogLevel values.\n */\nconst FILTER_LEVELS: ReadonlyArray<{ readonly label: string; readonly level: Logging.ReporterLogLevel }> = [\n { label: 'All', level: 'all' },\n { label: 'Info+', level: 'info' },\n { label: 'Warn+', level: 'warning' },\n { label: 'Error', level: 'error' }\n] as const;\n\n// ============================================================================\n// Status Bar\n// ============================================================================\n\n/**\n * Props for the StatusBar component.\n * @public\n */\nexport interface IStatusBarProps {\n readonly messages: ReadonlyArray<IMessage>;\n readonly onClear: () => void;\n /** Initial filter level for the log panel. Defaults to 'all'. */\n readonly initialFilterLevel?: Logging.ReporterLogLevel;\n}\n\n/**\n * Collapsible status bar / log panel at the bottom of the application.\n *\n * Collapsed: shows severity counts.\n * Expanded: filterable, searchable, copyable log of all messages.\n * @public\n */\nexport function StatusBar(props: IStatusBarProps): React.ReactElement {\n const { messages, onClear, initialFilterLevel } = props;\n const { layoutMode } = useResponsive();\n const isMobile = layoutMode === 'mobile';\n const [expanded, setExpanded] = useState(false);\n const [showFilters, setShowFilters] = useState(false);\n const [filterLevel, setFilterLevel] = useState<Logging.ReporterLogLevel>(initialFilterLevel ?? 'all');\n const [searchTerm, setSearchTerm] = useState('');\n const [copySuccessId, setCopySuccessId] = useState<string | null>(null);\n\n const counts = useMemo(() => {\n const result: Record<MessageSeverity, number> = { info: 0, success: 0, warning: 0, error: 0 };\n for (const msg of messages) {\n result[msg.severity]++;\n }\n return result;\n }, [messages]);\n\n const filteredMessages = useMemo(() => {\n return messages.filter((msg) => {\n const passesLevel = Logging.shouldLog(severityToLogLevel(msg.severity), filterLevel);\n const passesSearch = searchTerm === '' || msg.text.toLowerCase().includes(searchTerm.toLowerCase());\n return passesLevel && passesSearch;\n });\n }, [messages, filterLevel, searchTerm]);\n\n const isFiltered = filteredMessages.length !== messages.length;\n\n const formatTime = useCallback((timestamp: number): string => {\n return new Date(timestamp).toLocaleTimeString();\n }, []);\n\n const copyToClipboard = useCallback((text: string, id: string): void => {\n navigator.clipboard\n .writeText(text)\n .then(() => {\n setCopySuccessId(id);\n setTimeout(() => setCopySuccessId(null), 2000);\n })\n .catch(() => undefined);\n }, []);\n\n const copyAllFiltered = useCallback((): void => {\n const text = filteredMessages\n .map((msg) => `[${msg.severity.toUpperCase()}] ${formatTime(msg.timestamp)} - ${msg.text}`)\n .join('\\n');\n copyToClipboard(text, '__all__');\n }, [filteredMessages, formatTime, copyToClipboard]);\n\n return (\n <div className=\"border-t border-border bg-surface\">\n {/* Collapsed bar */}\n <button\n onClick={(): void => setExpanded(!expanded)}\n className=\"flex items-center justify-between w-full px-4 py-1.5 text-xs text-secondary hover:bg-hover\"\n >\n <div className=\"flex items-center gap-4\">\n {(Object.keys(counts) as MessageSeverity[]).map((severity) =>\n counts[severity] > 0 ? (\n <span key={severity} className={`flex items-center gap-1 ${SEVERITY_COLORS[severity]}`}>\n <span>{SEVERITY_ICONS[severity]}</span>\n <span>{counts[severity]}</span>\n </span>\n ) : null\n )}\n {messages.length === 0 && <span className=\"text-muted\">No messages</span>}\n </div>\n <span className=\"text-muted\">{expanded ? '\\u25BC' : '\\u25B2'}</span>\n </button>\n\n {/* Expanded log — fixed slide-up sheet on mobile, inline on desktop */}\n {expanded && (\n <>\n {isMobile && (\n <div className=\"fixed inset-0 z-40 bg-backdrop\" onClick={(): void => setExpanded(false)} />\n )}\n <div\n className={\n isMobile\n ? 'fixed inset-x-0 bottom-8 z-50 flex flex-col bg-surface border-t border-border shadow-xl rounded-t-lg max-h-[70vh]'\n : 'border-t border-border-subtle'\n }\n >\n {/* Header toolbar */}\n <div className=\"flex items-center justify-between px-4 py-1 bg-surface-alt border-b border-border-subtle shrink-0\">\n <span className=\"text-xs font-medium text-muted\">\n {isFiltered\n ? `${filteredMessages.length} of ${messages.length} messages`\n : `${messages.length} message${messages.length !== 1 ? 's' : ''}`}\n </span>\n <div className=\"flex items-center gap-1\">\n <button\n onClick={(): void => setShowFilters(!showFilters)}\n className={`p-1 rounded hover:bg-surface-raised ${showFilters ? 'bg-surface-raised' : ''}`}\n title=\"Filter messages\"\n >\n <FunnelIcon className=\"h-3.5 w-3.5 text-muted\" />\n </button>\n <button\n onClick={copyAllFiltered}\n className={`p-1 rounded transition-colors ${\n copySuccessId === '__all__' ? 'bg-status-success-bg' : 'hover:bg-surface-raised'\n }`}\n title={copySuccessId === '__all__' ? 'Copied!' : 'Copy filtered messages'}\n >\n {copySuccessId === '__all__' ? (\n <CheckIcon className=\"h-3.5 w-3.5 text-status-success-icon\" />\n ) : (\n <DocumentDuplicateIcon className=\"h-3.5 w-3.5 text-muted\" />\n )}\n </button>\n <button onClick={onClear} className=\"text-xs text-muted hover:text-secondary ml-1\">\n Clear\n </button>\n </div>\n </div>\n\n {/* Filter toolbar */}\n {showFilters && (\n <div className=\"px-4 py-1.5 bg-surface-raised border-b border-border-subtle flex items-center gap-3 shrink-0\">\n {/* Level filter buttons */}\n <div className=\"flex items-center gap-1\">\n {FILTER_LEVELS.map(({ label, level }) => (\n <button\n key={level}\n onClick={(): void => setFilterLevel(level)}\n className={`text-xs px-2 py-0.5 rounded border ${\n filterLevel === level\n ? 'bg-status-info-bg border-status-info-border text-status-info-text'\n : 'bg-surface border-border text-secondary hover:bg-hover'\n }`}\n >\n {label}\n </button>\n ))}\n </div>\n\n {/* Search input */}\n <div className=\"relative flex-1\">\n <MagnifyingGlassIcon className=\"absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted\" />\n <input\n type=\"text\"\n placeholder=\"Search messages...\"\n value={searchTerm}\n onChange={(e): void => setSearchTerm(e.target.value)}\n className=\"w-full pl-7 pr-6 py-0.5 text-xs border border-border rounded bg-surface text-primary focus:outline-none focus:ring-1 focus:ring-focus-ring focus:border-focus-ring\"\n />\n {searchTerm.length > 0 && (\n <button\n onClick={(): void => setSearchTerm('')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 text-muted hover:text-secondary text-xs\"\n aria-label=\"Clear search\"\n >\n ×\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* Message list */}\n <div className={`overflow-y-auto ${isMobile ? 'flex-1' : 'max-h-48'}`}>\n {filteredMessages.length === 0 ? (\n <div className=\"px-4 py-3 text-xs text-muted text-center\">\n {isFiltered ? 'No messages match the current filter' : 'No messages'}\n </div>\n ) : (\n filteredMessages.map((msg) => (\n <div\n key={msg.id}\n className={`group flex items-start gap-2 px-4 py-1.5 text-xs border-b border-border-subtle ${\n LOG_ROW_COLORS[msg.severity]\n }`}\n >\n <span className={`shrink-0 ${SEVERITY_COLORS[msg.severity]}`}>\n {SEVERITY_ICONS[msg.severity]}\n </span>\n <span className=\"flex-1 text-secondary\">{msg.text}</span>\n <button\n onClick={(): void => copyToClipboard(msg.text, msg.id)}\n className={`shrink-0 p-0.5 rounded transition-colors ${\n copySuccessId === msg.id\n ? 'opacity-100 bg-status-success-surface'\n : 'opacity-0 group-hover:opacity-100 hover:bg-surface-raised'\n }`}\n title={copySuccessId === msg.id ? 'Copied!' : 'Copy message'}\n >\n {copySuccessId === msg.id ? (\n <CheckIcon className=\"h-3 w-3 text-status-success-icon\" />\n ) : (\n <DocumentDuplicateIcon className=\"h-3 w-3 text-muted\" />\n )}\n </button>\n <span className=\"shrink-0 text-muted\">{formatTime(msg.timestamp)}</span>\n </div>\n ))\n )}\n </div>\n </div>\n </>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/packlets/messages/Toast.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAEzC,OAAO,EAAwB,QAAQ,EAAmB,MAAM,SAAS,CAAC;AAkB1E;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,CA0CpE;AAMD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,sDAAsD;IACtD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAoBrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.js","sourceRoot":"","sources":["../../../src/packlets/messages/Toast.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,8BA0CC;AAqBD,wCAoBC;AApHD,+CAAyC;AAEzC,mCAA0E;AAC1E,8CAA8C;AAE9C,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E,MAAM,eAAe,GAAoC;IACvD,IAAI,EAAE,mEAAmE;IACzE,OAAO,EAAE,4EAA4E;IACrF,OAAO,EAAE,4EAA4E;IACrF,KAAK,EAAE,sEAAsE;CAC9E,CAAC;AAeF;;;GAGG;AACH,SAAgB,SAAS,CAAC,KAAsB;IAC9C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACrC,MAAM,MAAM,GAAG,4BAAoB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,0BAAa,GAAE,CAAC;IAEvC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;YAC5E,OAAO,GAAS,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;IAElD,OAAO,CACL,uCACE,SAAS,EAAE,gEACT,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UACvC,IAAI,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EACvC,IAAI,EAAC,OAAO;QAEZ,uCAAK,SAAS,EAAC,6BAA6B,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,IAC7D,OAAO,CAAC,IAAI,CACT;QACN,uCAAK,SAAS,EAAC,kCAAkC;YAC9C,OAAO,CAAC,MAAM,IAAI,CACjB,0CACE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,EAChC,SAAS,EAAC,kDAAkD,IAE3D,OAAO,CAAC,MAAM,CAAC,KAAK,CACd,CACV;YACD,0CACE,OAAO,EAAE,GAAS,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,EAC1C,SAAS,EAAC,2CAA2C,gBAC1C,SAAS,aAGb,CACL,CACF,CACP,CAAC;AACJ,CAAC;AAiBD;;;GAGG;AACH,SAAgB,cAAc,CAAC,KAA2B;IACxD,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC;IACpD,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,0BAAa,GAAE,CAAC;IACvC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC;IAE1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,uCACE,SAAS,EAAE,4CACT,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAC/C,EAAE,IAED,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACtB,8BAAC,SAAS,IAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,GAAI,CACnE,CAAC,CACE,CACP,CAAC;AACJ,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { useEffect } from 'react';\n\nimport { DEFAULT_TOAST_CONFIG, IMessage, MessageSeverity } from './model';\nimport { useResponsive } from '../responsive';\n\n// ============================================================================\n// Severity Styles\n// ============================================================================\n\nconst SEVERITY_STYLES: Record<MessageSeverity, string> = {\n info: 'bg-status-info-bg border-status-info-border text-status-info-text',\n success: 'bg-status-success-bg border-status-success-border text-status-success-text',\n warning: 'bg-status-warning-bg border-status-warning-border text-status-warning-text',\n error: 'bg-status-error-bg border-status-error-border text-status-error-text'\n};\n\n// ============================================================================\n// Single Toast\n// ============================================================================\n\n/**\n * Props for a single Toast item.\n * @public\n */\nexport interface IToastItemProps {\n readonly message: IMessage;\n readonly onDismiss: (id: string) => void;\n}\n\n/**\n * A single toast notification.\n * @public\n */\nexport function ToastItem(props: IToastItemProps): React.ReactElement {\n const { message, onDismiss } = props;\n const config = DEFAULT_TOAST_CONFIG[message.severity];\n const { layoutMode } = useResponsive();\n\n useEffect(() => {\n if (config.autoDismissMs > 0) {\n const timer = setTimeout(() => onDismiss(message.id), config.autoDismissMs);\n return (): void => clearTimeout(timer);\n }\n return undefined;\n }, [message.id, config.autoDismissMs, onDismiss]);\n\n return (\n <div\n className={`flex items-start gap-3 px-4 py-3 rounded-lg border shadow-lg ${\n layoutMode === 'mobile' ? 'w-full' : 'max-w-sm'\n } ${SEVERITY_STYLES[message.severity]}`}\n role=\"alert\"\n >\n <div className=\"flex-1 text-sm line-clamp-4\" title={message.text}>\n {message.text}\n </div>\n <div className=\"flex items-center gap-2 shrink-0\">\n {message.action && (\n <button\n onClick={message.action.onAction}\n className=\"text-sm font-medium underline hover:no-underline\"\n >\n {message.action.label}\n </button>\n )}\n <button\n onClick={(): void => onDismiss(message.id)}\n className=\"text-current opacity-50 hover:opacity-100\"\n aria-label=\"Dismiss\"\n >\n ×\n </button>\n </div>\n </div>\n );\n}\n\n// ============================================================================\n// Toast Container\n// ============================================================================\n\n/**\n * Props for the ToastContainer.\n * @public\n */\nexport interface IToastContainerProps {\n readonly toasts: ReadonlyArray<IMessage>;\n readonly onDismiss: (id: string) => void;\n /** Maximum number of toasts to show simultaneously */\n readonly maxVisible?: number;\n}\n\n/**\n * Container that renders active toasts in the bottom-right corner.\n * @public\n */\nexport function ToastContainer(props: IToastContainerProps): React.ReactElement | null {\n const { toasts, onDismiss, maxVisible = 5 } = props;\n const { layoutMode } = useResponsive();\n const visible = toasts.slice(-maxVisible);\n\n if (visible.length === 0) {\n return null;\n }\n\n return (\n <div\n className={`fixed bottom-16 z-50 flex flex-col gap-2 ${\n layoutMode === 'mobile' ? 'left-4 right-4' : 'right-4'\n }`}\n >\n {visible.map((toast) => (\n <ToastItem key={toast.id} message={toast} onDismiss={onDismiss} />\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/messages/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,gBAAgB,EAChB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAErG,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/messages/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAQiB;AAHf,6GAAA,oBAAoB,OAAA;AACpB,sGAAA,aAAa,OAAA;AACb,0GAAA,iBAAiB,OAAA;AAGnB,qDAK2B;AAFzB,mHAAA,gBAAgB,OAAA;AAChB,8GAAA,WAAW,OAAA;AAGb,iCAAqG;AAA5F,kGAAA,SAAS,OAAA;AAAE,uGAAA,cAAc,OAAA;AAElC,yCAA8D;AAArD,sGAAA,SAAS,OAAA;AAElB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AAEvB,mDAA+E;AAAtE,gHAAA,cAAc,OAAA","sourcesContent":["/**\n * Messages packlet - observability context, toast system, and log panel.\n * @packageDocumentation\n */\n\nexport {\n type MessageSeverity,\n type IMessage,\n type IMessageAction,\n type IToastConfig,\n DEFAULT_TOAST_CONFIG,\n createMessage,\n generateMessageId\n} from './model';\n\nexport {\n type IMessagesContextValue,\n type IMessagesProviderProps,\n MessagesProvider,\n useMessages\n} from './MessagesContext';\n\nexport { ToastItem, ToastContainer, type IToastItemProps, type IToastContainerProps } from './Toast';\n\nexport { StatusBar, type IStatusBarProps } from './StatusBar';\n\nexport { MessagesLogger } from './MessagesLogger';\n\nexport { useLogReporter, type IUseLogReporterOptions } from './useLogReporter';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/packlets/messages/model.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AAMH;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAMvE;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,mBAAmB;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAMD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,eAAe,EAAE,YAAY,CAK7D,CAAC;AAQX;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,QAAQ,CAQxG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/packlets/messages/model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAmFH,8CAEC;AAMD,sCAQC;AArCD;;;GAGG;AACU,QAAA,oBAAoB,GAA0C;IACzE,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;IAC7B,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;IAChC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;IAChC,KAAK,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;CACnB,CAAC;AAEX,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E,IAAI,OAAO,GAAW,CAAC,CAAC;AAExB;;;GAGG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAAC,QAAyB,EAAE,IAAY,EAAE,MAAuB;IAC5F,OAAO;QACL,EAAE,EAAE,iBAAiB,EAAE;QACvB,QAAQ;QACR,IAAI;QACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * Message model types for the observability system.\n * @packageDocumentation\n */\n\n// ============================================================================\n// Message Severity\n// ============================================================================\n\n/**\n * Severity levels for messages.\n * @public\n */\nexport type MessageSeverity = 'info' | 'success' | 'warning' | 'error';\n\n// ============================================================================\n// Message\n// ============================================================================\n\n/**\n * A single message in the observability stream.\n * @public\n */\nexport interface IMessage {\n /** Unique message ID */\n readonly id: string;\n /** Message severity */\n readonly severity: MessageSeverity;\n /** Message text */\n readonly text: string;\n /** Timestamp (ms since epoch) */\n readonly timestamp: number;\n /** Optional action (e.g., a link or callback) */\n readonly action?: IMessageAction;\n}\n\n/**\n * An actionable element attached to a message (e.g., \"Go to Session\" link).\n * @public\n */\nexport interface IMessageAction {\n /** Action label */\n readonly label: string;\n /** Callback when the action is triggered */\n readonly onAction: () => void;\n}\n\n// ============================================================================\n// Toast Configuration\n// ============================================================================\n\n/**\n * Configuration for toast auto-dismiss behavior.\n * @public\n */\nexport interface IToastConfig {\n /** Auto-dismiss duration in ms. 0 = no auto-dismiss. */\n readonly autoDismissMs: number;\n}\n\n/**\n * Default toast configuration by severity.\n * @public\n */\nexport const DEFAULT_TOAST_CONFIG: Record<MessageSeverity, IToastConfig> = {\n info: { autoDismissMs: 3000 },\n success: { autoDismissMs: 3000 },\n warning: { autoDismissMs: 5000 },\n error: { autoDismissMs: 0 }\n} as const;\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nlet _nextId: number = 0;\n\n/**\n * Generates a unique message ID.\n * @internal\n */\nexport function generateMessageId(): string {\n return `msg-${++_nextId}-${Date.now().toString(36)}`;\n}\n\n/**\n * Creates a new message.\n * @public\n */\nexport function createMessage(severity: MessageSeverity, text: string, action?: IMessageAction): IMessage {\n return {\n id: generateMessageId(),\n severity,\n text,\n timestamp: Date.now(),\n action\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLogReporter.d.ts","sourceRoot":"","sources":["../../../src/packlets/messages/useLogReporter.ts"],"names":[],"mappings":"AA8CA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAKxC;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC;CAC9C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAQ7F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLogReporter.js","sourceRoot":"","sources":["../../../src/packlets/messages/useLogReporter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;AAmDH,wCAQC;AAzDD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,iCAAgC;AAEhC,4CAAwC;AAExC,uDAAgD;AAChD,qDAAkD;AAWlD;;;;;;;;;;GAUG;AACH,SAAgB,cAAc,CAAC,OAAgC;IAC7D,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,6BAAW,GAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC;IAEnC,OAAO,IAAA,eAAO,EAAC,GAAG,EAAE;QAClB,MAAM,MAAM,GAAG,IAAI,+BAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACxD,OAAO,IAAI,kBAAO,CAAC,WAAW,CAAU,EAAE,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC,EAAE,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * React hook that provides a LogReporter wired into the MessagesContext.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const reporter = useLogReporter();\n *\n * const handleSave = () => {\n * const result = workspace.save(data);\n * // Automatically shows success toast or error in log panel\n * result.report(reporter, {\n * success: { level: 'info', message: () => 'Saved successfully' },\n * failure: 'error'\n * });\n * };\n * }\n * ```\n *\n * @packageDocumentation\n */\n\nimport { useMemo } from 'react';\n\nimport { Logging } from '@fgv/ts-utils';\n\nimport { useMessages } from './MessagesContext';\nimport { MessagesLogger } from './MessagesLogger';\n\n/**\n * Options for the useLogReporter hook.\n * @public\n */\nexport interface IUseLogReporterOptions {\n /** Minimum log level (default: 'info') */\n readonly logLevel?: Logging.ReporterLogLevel;\n}\n\n/**\n * React hook that creates a {@link @fgv/ts-utils#Logging.LogReporter | LogReporter}\n * backed by the MessagesContext.\n *\n * The returned reporter implements both `ILogger` and `IResultReporter<unknown>`,\n * so it can be used with `Result.report()` and direct logging calls.\n *\n * @param options - Optional configuration\n * @returns A LogReporter that routes messages into the toast/log system\n * @public\n */\nexport function useLogReporter(options?: IUseLogReporterOptions): Logging.LogReporter<unknown> {\n const { addMessage } = useMessages();\n const logLevel = options?.logLevel;\n\n return useMemo(() => {\n const logger = new MessagesLogger(addMessage, logLevel);\n return new Logging.LogReporter<unknown>({ logger });\n }, [addMessage, logLevel]);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.d.ts","sourceRoot":"","sources":["../../../src/packlets/modal/ConfirmDialog.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAiC,MAAM,OAAO,CAAC;AAGtD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAElE;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,mBAAmB;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IAC1C,oCAAoC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,IAAI,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAcD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAoHnF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfirmDialog.js","sourceRoot":"","sources":["../../../src/packlets/modal/ConfirmDialog.tsx"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { useCallback, useEffect } from 'react';\nimport { useResponsive } from '../responsive';\n\n/**\n * Severity level for the confirm dialog.\n * Controls the color of the confirm button.\n * @public\n */\nexport type ConfirmDialogSeverity = 'danger' | 'warning' | 'info';\n\n/**\n * Props for the ConfirmDialog component.\n * @public\n */\nexport interface IConfirmDialogProps {\n /** Whether the dialog is open */\n readonly isOpen: boolean;\n /** Dialog title */\n readonly title: string;\n /** Dialog message body */\n readonly message: React.ReactNode;\n /** Label for the confirm button (defaults to 'Confirm') */\n readonly confirmLabel?: string;\n /** Label for the cancel button (defaults to 'Cancel') */\n readonly cancelLabel?: string;\n /** Severity level controlling confirm button color (defaults to 'danger') */\n readonly severity?: ConfirmDialogSeverity;\n /** Called when the user confirms */\n readonly onConfirm: () => void;\n /** Called when the user cancels or closes */\n readonly onCancel: () => void;\n}\n\nconst severityClasses: Record<ConfirmDialogSeverity, string> = {\n danger: 'bg-status-error-btn hover:bg-status-error-btn-hover focus:ring-status-error-accent',\n warning: 'bg-status-warning-btn hover:bg-status-warning-btn-hover focus:ring-status-warning-strong',\n info: 'bg-status-info-btn hover:bg-status-info-btn-hover focus:ring-status-info-icon'\n};\n\nconst severityIconClasses: Record<ConfirmDialogSeverity, string> = {\n danger: 'text-status-error-icon',\n warning: 'text-status-warning-icon',\n info: 'text-status-info-icon'\n};\n\n/**\n * Generic confirmation dialog.\n *\n * Renders a modal overlay with a title, message, and confirm/cancel buttons.\n * Closes on Escape key or backdrop click (treated as cancel).\n *\n * @public\n */\nexport function ConfirmDialog(props: IConfirmDialogProps): React.ReactElement | null {\n const {\n isOpen,\n title,\n message,\n confirmLabel = 'Confirm',\n cancelLabel = 'Cancel',\n severity = 'danger',\n onConfirm,\n onCancel\n } = props;\n const { layoutMode } = useResponsive();\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n onCancel();\n }\n },\n [onCancel]\n );\n\n useEffect(() => {\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n return (): void => document.removeEventListener('keydown', handleKeyDown);\n }\n return undefined;\n }, [isOpen, handleKeyDown]);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-backdrop\" onClick={onCancel} role=\"presentation\" />\n\n {/* Dialog */}\n <div\n className={`relative bg-surface rounded-lg shadow-xl ${\n layoutMode === 'mobile' ? 'w-[95vw]' : 'max-w-md w-full mx-4'\n }`}\n role=\"alertdialog\"\n aria-modal=\"true\"\n aria-labelledby=\"confirm-dialog-title\"\n aria-describedby=\"confirm-dialog-message\"\n >\n <div className=\"p-6\">\n <div className=\"flex items-start gap-4\">\n {/* Icon */}\n <div\n className={`flex-shrink-0 w-10 h-10 flex items-center justify-center rounded-full ${\n severity === 'danger'\n ? 'bg-status-error-bg'\n : severity === 'warning'\n ? 'bg-status-warning-bg'\n : 'bg-status-info-bg'\n }`}\n >\n <svg\n className={`w-6 h-6 ${severityIconClasses[severity]}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n {severity === 'info' ? (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n ) : (\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n )}\n </svg>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 min-w-0\">\n <h3 id=\"confirm-dialog-title\" className=\"text-base font-semibold text-primary leading-6\">\n {title}\n </h3>\n <div id=\"confirm-dialog-message\" className=\"mt-2 text-sm text-secondary\">\n {typeof message === 'string' ? <p>{message}</p> : message}\n </div>\n </div>\n </div>\n\n {/* Buttons */}\n <div className=\"mt-6 flex justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"px-4 py-2 text-sm font-medium text-secondary bg-surface border border-border rounded-md hover:bg-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-focus-ring transition-colors\"\n >\n {cancelLabel}\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={`px-4 py-2 text-sm font-medium text-white rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 transition-colors ${severityClasses[severity]}`}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/packlets/modal/Modal.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAiC,MAAM,OAAO,CAAC;AAGtD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,kCAAkC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,kBAAkB;IAClB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAwDnE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../../src/packlets/modal/Modal.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyBH,sBAwDC;AA/ED,+CAAsD;AACtD,8CAA8C;AAiB9C;;;;GAIG;AACH,SAAgB,KAAK,CAAC,KAAkB;IACtC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IACnD,MAAM,EAAE,UAAU,EAAE,GAAG,IAAA,0BAAa,GAAE,CAAC;IAEvC,MAAM,aAAa,GAAG,IAAA,mBAAW,EAC/B,CAAC,CAAgB,EAAQ,EAAE;QACzB,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACvB,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;YACpD,OAAO,GAAS,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IAE5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,uCAAK,SAAS,EAAC,qDAAqD;QAElE,uCAAK,SAAS,EAAC,8BAA8B,EAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAC,cAAc,GAAG;QAGtF,uCACE,SAAS,EAAE,0DACT,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,mCACtD,EAAE,EACF,IAAI,EAAC,QAAQ,gBACF,MAAM,gBACL,KAAK;YAGjB,uCAAK,SAAS,EAAC,oEAAoE;gBACjF,sCAAI,SAAS,EAAC,oCAAoC,IAAE,KAAK,CAAM;gBAC/D,0CACE,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,mDAAmD,gBAClD,OAAO,aAGX,CACL;YAGN,uCAAK,SAAS,EAAC,kCAAkC,IAAE,QAAQ,CAAO,CAC9D,CACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { useCallback, useEffect } from 'react';\nimport { useResponsive } from '../responsive';\n\n/**\n * Props for the Modal component.\n * @public\n */\nexport interface IModalProps {\n /** Whether the modal is open */\n readonly isOpen: boolean;\n /** Callback to close the modal */\n readonly onClose: () => void;\n /** Modal title */\n readonly title: string;\n /** Modal content */\n readonly children: React.ReactNode;\n}\n\n/**\n * Generic modal overlay component.\n * Renders a centered dialog with a backdrop that closes on click or Escape.\n * @public\n */\nexport function Modal(props: IModalProps): React.ReactElement | null {\n const { isOpen, onClose, title, children } = props;\n const { layoutMode } = useResponsive();\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent): void => {\n if (e.key === 'Escape') {\n onClose();\n }\n },\n [onClose]\n );\n\n useEffect(() => {\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n return (): void => document.removeEventListener('keydown', handleKeyDown);\n }\n return undefined;\n }, [isOpen, handleKeyDown]);\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div className=\"absolute inset-0 bg-backdrop\" onClick={onClose} role=\"presentation\" />\n\n {/* Dialog */}\n <div\n className={`relative bg-surface rounded-lg shadow-xl flex flex-col ${\n layoutMode === 'mobile' ? 'w-[95vw] max-h-[95vh]' : 'max-w-lg w-full mx-4 max-h-[80vh]'\n }`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold text-primary\">{title}</h2>\n <button\n onClick={onClose}\n className=\"text-muted hover:text-secondary transition-colors\"\n aria-label=\"Close\"\n >\n ×\n </button>\n </div>\n\n {/* Content */}\n <div className=\"px-6 py-4 overflow-y-auto flex-1\">{children}</div>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/modal/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/modal/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAAkD;AAAzC,8FAAA,KAAK,OAAA;AAEd,iDAAsG;AAA7F,8GAAA,aAAa,OAAA","sourcesContent":["/**\n * Modal packlet - generic overlay dialog component.\n * @packageDocumentation\n */\n\nexport { Modal, type IModalProps } from './Modal';\n\nexport { ConfirmDialog, type IConfirmDialogProps, type ConfirmDialogSeverity } from './ConfirmDialog';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrintEnclosure.d.ts","sourceRoot":"","sources":["../../../src/packlets/print/PrintEnclosure.tsx"],"names":[],"mappings":"AAsBA;;;GAGG;AAEH,OAAO,KAAsB,MAAM,OAAO,CAAC;AAG3C;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzC,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAa,EACb,WAAW,EACX,QAAQ,EACT,EAAE,oBAAoB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAuC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PrintEnclosure.js","sourceRoot":"","sources":["../../../src/packlets/print/PrintEnclosure.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCH,wCA4CC;AA/ED;;;GAGG;AAEH,+CAA2C;AAC3C,yDAAqE;AAiBrE;;;;;;;;;;;GAWG;AACH,SAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAa,EACb,WAAW,EACX,QAAQ,EACa;IACrB,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,GAAS,EAAE;QACzC,WAAW,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,GAAS,EAAE;QACzC,WAAW,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,OAAO,CACL;QAEE,uCAAK,SAAS,EAAC,oIAAoI;YACjJ,sCAAI,SAAS,EAAC,6CAA6C,IAAE,KAAK,CAAM;YACxE,uCAAK,SAAS,EAAC,kCAAkC;gBAC9C,aAAa;gBACd,0CACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,SAAS,EAAC,qJAAqJ;oBAE/J,8BAAC,qBAAW,IAAC,SAAS,EAAC,SAAS,GAAG;4BAE5B;gBACT,0CACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,WAAW,EACpB,SAAS,EAAC,wJAAwJ;oBAElK,8BAAC,mBAAS,IAAC,SAAS,EAAC,SAAS,GAAG;4BAE1B,CACL,CACF;QAGN,uCAAK,SAAS,EAAC,wBAAwB,IAAE,QAAQ,CAAO,CACpD,CACP,CAAC;AACJ,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * Print enclosure component rendered inside the popup window.\n * @packageDocumentation\n */\n\nimport React, { useCallback } from 'react';\nimport { PrinterIcon, XMarkIcon } from '@heroicons/react/24/outline';\n\n/**\n * Props for {@link PrintEnclosure}.\n * @public\n */\nexport interface IPrintEnclosureProps {\n /** Title displayed in the toolbar. */\n readonly title: string;\n /** Optional extra controls rendered in the toolbar (e.g. toggles). */\n readonly toolbarExtras?: React.ReactNode;\n /** Reference to the popup window (used for print and close actions). */\n readonly popupWindow: Window;\n /** Content to display and print. */\n readonly children: React.ReactNode;\n}\n\n/**\n * A container component rendered inside a popup window that provides a\n * toolbar with Print and Close buttons and renders children as the\n * printable content.\n *\n * @remarks\n * The toolbar is hidden when printing via CSS (`print-toolbar` class).\n * Children are rendered at full width with no scroll constraints so\n * multi-page content flows naturally to the printer.\n *\n * @public\n */\nexport function PrintEnclosure({\n title,\n toolbarExtras,\n popupWindow,\n children\n}: IPrintEnclosureProps): React.JSX.Element {\n const handlePrint = useCallback((): void => {\n popupWindow.print();\n }, [popupWindow]);\n\n const handleClose = useCallback((): void => {\n popupWindow.close();\n }, [popupWindow]);\n\n return (\n <div>\n {/* Toolbar - hidden when printing */}\n <div className=\"print-toolbar sticky top-0 z-10 flex items-center justify-between gap-4 bg-surface border-b border-border px-6 py-3 mb-6 shadow-sm\">\n <h1 className=\"text-lg font-semibold text-primary truncate\">{title}</h1>\n <div className=\"flex items-center gap-3 shrink-0\">\n {toolbarExtras}\n <button\n type=\"button\"\n onClick={handlePrint}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-white bg-brand-primary hover:bg-brand-primary/90 rounded-md transition-colors\"\n >\n <PrinterIcon className=\"w-4 h-4\" />\n Print\n </button>\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-secondary bg-surface-raised hover:bg-surface-raised rounded-md transition-colors\"\n >\n <XMarkIcon className=\"w-4 h-4\" />\n Close\n </button>\n </div>\n </div>\n\n {/* Printable content */}\n <div className=\"max-w-4xl mx-auto px-6\">{children}</div>\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/print/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/print/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,qDAA8E;AAArE,kHAAA,eAAe,OAAA;AACxB,mDAA6E;AAApE,gHAAA,cAAc,OAAA","sourcesContent":["/**\n * Print packlet - popup window for print-optimized content rendering.\n * @packageDocumentation\n */\n\nexport { openPrintWindow, type IPrintWindowOptions } from './openPrintWindow';\nexport { PrintEnclosure, type IPrintEnclosureProps } from './PrintEnclosure';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openPrintWindow.d.ts","sourceRoot":"","sources":["../../../src/packlets/print/openPrintWindow.tsx"],"names":[],"mappings":"AAsBA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1C;AAiBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAiExG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openPrintWindow.js","sourceRoot":"","sources":["../../../src/packlets/print/openPrintWindow.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;AAwDH,0CAiEC;AAvHD;;;GAGG;AAEH,kDAA0B;AAC1B,6CAA8C;AAE9C,qDAAkD;AAiBlD;;;GAGG;AACH,SAAS,WAAW,CAAC,MAAgB,EAAE,MAAgB;IACrD,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAC5E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,eAAe,CAAC,OAA2B,EAAE,OAA4B;IACvF,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IAEpE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,KAAK,WAAW,MAAM,EAAE,CAAC,CAAC;IACrE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;;;;WAIZ,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8B9B,CAAC,CAAC;IACR,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IAEvB,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAG,IAAA,mBAAU,EAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CACT,8BAAC,+BAAc,IAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,KAAK,IAC3E,OAAO,CACO,CAClB,CAAC;IAEF,KAAK,CAAC,gBAAgB,CAAC,cAAc,EAAE,GAAG,EAAE;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * Opens a popup window for print-optimized content rendering.\n * @packageDocumentation\n */\n\nimport React from 'react';\nimport { createRoot } from 'react-dom/client';\n\nimport { PrintEnclosure } from './PrintEnclosure';\n\n/**\n * Options for {@link openPrintWindow}.\n * @public\n */\nexport interface IPrintWindowOptions {\n /** Title for the popup window. */\n readonly title: string;\n /** Width of the popup window in pixels (default 900). */\n readonly width?: number;\n /** Height of the popup window in pixels (default 700). */\n readonly height?: number;\n /** Extra toolbar controls to render in the print enclosure header. */\n readonly toolbarExtras?: React.ReactNode;\n}\n\n/**\n * Clones all stylesheet-related elements from the source document head\n * into the target document head so that styles are available in the popup.\n */\nfunction cloneStyles(source: Document, target: Document): void {\n const styles = Array.from(source.querySelectorAll('style'));\n for (const style of styles) {\n target.head.appendChild(style.cloneNode(true));\n }\n const links = Array.from(source.querySelectorAll('link[rel=\"stylesheet\"]'));\n for (const link of links) {\n target.head.appendChild(link.cloneNode(true));\n }\n}\n\n/**\n * Opens a popup window and renders the given React content inside a\n * {@link PrintEnclosure} with Print and Close toolbar buttons.\n *\n * @remarks\n * Must be called synchronously from a user click handler to avoid\n * popup blockers. If the popup is blocked, returns `null`.\n *\n * Styles are cloned from the parent document so that Tailwind and other\n * CSS frameworks work in the popup. An independent React root is created\n * in the popup (not a portal) so the popup is fully self-contained.\n *\n * @public\n */\nexport function openPrintWindow(content: React.ReactElement, options: IPrintWindowOptions): Window | null {\n const { title, width = 900, height = 700, toolbarExtras } = options;\n\n const popup = window.open('', '', `width=${width},height=${height}`);\n if (!popup) {\n return null;\n }\n\n popup.document.write(`<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <title>${title.replace(/</g, '<')}</title>\n <style>\n @media screen {\n body {\n background: #f9fafb;\n padding: 2rem;\n margin: 0;\n }\n }\n @media print {\n body {\n margin: 0;\n padding: 0;\n background: white;\n }\n .print-toolbar {\n display: none !important;\n }\n .break-before-page {\n break-before: page;\n }\n .break-inside-avoid {\n break-inside: avoid;\n }\n }\n </style>\n</head>\n<body>\n <div id=\"print-root\"></div>\n</body>\n</html>`);\n popup.document.close();\n\n cloneStyles(document, popup.document);\n\n const container = popup.document.getElementById('print-root');\n if (!container) {\n popup.close();\n return null;\n }\n\n const root = createRoot(container);\n root.render(\n <PrintEnclosure title={title} toolbarExtras={toolbarExtras} popupWindow={popup}>\n {content}\n </PrintEnclosure>\n );\n\n popup.addEventListener('beforeunload', () => {\n root.unmount();\n });\n\n return popup;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponsiveProvider.d.ts","sourceRoot":"","sources":["../../../src/packlets/responsive/ResponsiveProvider.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAuB,MAAM,uBAAuB,CAAC;AAMrG;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,gEAAgE;IAChE,QAAQ,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;IACtC,eAAe;IACf,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,eAAe,EACf,QAAQ,EACT,EAAE,wBAAwB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAG9C;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,CAMjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResponsiveProvider.js","sourceRoot":"","sources":["../../../src/packlets/responsive/ResponsiveProvider.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCH,gDAMC;AAQD,sCAMC;AApDD,+CAAyD;AACzD,+DAAqG;AAErG,MAAM,iBAAiB,GAAiD,IAAA,qBAAa,EAEnF,SAAS,CAAC,CAAC;AAab;;;;;;;;;;;;;GAaG;AACH,SAAgB,kBAAkB,CAAC,EACjC,eAAe,EACf,QAAQ,EACiB;IACzB,MAAM,MAAM,GAAG,IAAA,yCAAmB,EAAC,eAAe,CAAC,CAAC;IACpD,OAAO,8BAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IAAG,QAAQ,CAA8B,CAAC;AAC5F,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAA,kBAAU,EAAC,iBAAiB,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, { createContext, useContext } from 'react';\nimport { type IResponsiveLayout, type LayoutMode, useResponsiveLayout } from './useResponsiveLayout';\n\nconst ResponsiveContext: React.Context<IResponsiveLayout | undefined> = createContext<\n IResponsiveLayout | undefined\n>(undefined);\n\n/**\n * Props for {@link ResponsiveProvider}.\n * @public\n */\nexport interface IResponsiveProviderProps {\n /** Optional layout mode override (for testing or storybook). */\n readonly forceLayoutMode?: LayoutMode;\n /** Children */\n readonly children: React.ReactNode;\n}\n\n/**\n * Provides responsive layout information to the component tree via context.\n *\n * Wrap your app (or a subtree) with this provider. Descendants use\n * {@link useResponsive} to read the current layout mode, device type, etc.\n *\n * @example\n * ```tsx\n * <ResponsiveProvider>\n * <App />\n * </ResponsiveProvider>\n * ```\n * @public\n */\nexport function ResponsiveProvider({\n forceLayoutMode,\n children\n}: IResponsiveProviderProps): React.JSX.Element {\n const layout = useResponsiveLayout(forceLayoutMode);\n return <ResponsiveContext.Provider value={layout}>{children}</ResponsiveContext.Provider>;\n}\n\n/**\n * Access the current responsive layout information.\n *\n * Must be called within a {@link ResponsiveProvider}.\n * @public\n */\nexport function useResponsive(): IResponsiveLayout {\n const context = useContext(ResponsiveContext);\n if (!context) {\n throw new Error('useResponsive must be used within a ResponsiveProvider');\n }\n return context;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/responsive/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,KAAK,wBAAwB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/responsive/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6DAM+B;AAL7B,0HAAA,mBAAmB,OAAA;AAOrB,2DAAwG;AAA/F,wHAAA,kBAAkB,OAAA;AAAE,mHAAA,aAAa,OAAA","sourcesContent":["/**\n * Responsive layout detection and context provider.\n * @packageDocumentation\n */\n\nexport {\n useResponsiveLayout,\n type DeviceType,\n type ScreenOrientation,\n type LayoutMode,\n type IResponsiveLayout\n} from './useResponsiveLayout';\n\nexport { ResponsiveProvider, useResponsive, type IResponsiveProviderProps } from './ResponsiveProvider';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResponsiveLayout.d.ts","sourceRoot":"","sources":["../../../src/packlets/responsive/useResponsiveLayout.ts"],"names":[],"mappings":"AAwBA;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAEhC,iCAAiC;IACjC,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAExC,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAEhC,+BAA+B;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,gCAAgC;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,8CAA8C;IAC9C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAsED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,CAAC,EAAE,UAAU,GAAG,iBAAiB,CA8BnF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResponsiveLayout.js","sourceRoot":"","sources":["../../../src/packlets/responsive/useResponsiveLayout.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { useState, useEffect } from 'react';\n\n/**\n * Device type detection result.\n * @public\n */\nexport type DeviceType = 'mobile' | 'tablet' | 'desktop';\n\n/**\n * Screen orientation.\n * @public\n */\nexport type ScreenOrientation = 'portrait' | 'landscape';\n\n/**\n * Layout mode that drives structural rendering decisions.\n * - `full`: Desktop — sidebar visible, cascade columns side-by-side.\n * - `compact`: Tablet — sidebar as drawer, cascade still horizontal.\n * - `mobile`: Phone — sidebar as drawer, cascade becomes a view stack.\n * @public\n */\nexport type LayoutMode = 'full' | 'compact' | 'mobile';\n\n/**\n * Responsive layout information exposed by the hook and context.\n * @public\n */\nexport interface IResponsiveLayout {\n /** Device type based on screen size and touch capability */\n readonly deviceType: DeviceType;\n\n /** Current screen orientation */\n readonly orientation: ScreenOrientation;\n\n /** Structural layout mode driving component tree decisions */\n readonly layoutMode: LayoutMode;\n\n /** Viewport width in pixels */\n readonly screenWidth: number;\n\n /** Viewport height in pixels */\n readonly screenHeight: number;\n\n /** Whether the device supports touch input */\n readonly isTouchDevice: boolean;\n}\n\n/**\n * Breakpoints for responsive design (in CSS pixels).\n */\nconst BREAKPOINTS = {\n /** At or below this width, use mobile layout */\n mobile: 640,\n /** At or below this width, use compact layout */\n compact: 1024\n} as const;\n\n/**\n * Detect if the device supports touch input.\n */\nfunction detectTouchSupport(): boolean {\n return (\n 'ontouchstart' in window ||\n navigator.maxTouchPoints > 0 ||\n ((navigator as unknown as { msMaxTouchPoints?: number }).msMaxTouchPoints ?? 0) > 0\n );\n}\n\n/**\n * Determine device type from viewport dimensions and touch capability.\n */\nfunction determineDeviceType(width: number, isTouch: boolean): DeviceType {\n if (width <= BREAKPOINTS.mobile) {\n return 'mobile';\n }\n if (width <= BREAKPOINTS.compact && isTouch) {\n return 'tablet';\n }\n return 'desktop';\n}\n\n/**\n * Determine the structural layout mode from viewport width.\n */\nfunction determineLayoutMode(width: number): LayoutMode {\n if (width <= BREAKPOINTS.mobile) {\n return 'mobile';\n }\n if (width <= BREAKPOINTS.compact) {\n return 'compact';\n }\n return 'full';\n}\n\n/**\n * Compute the full layout info from current viewport state.\n */\nfunction computeLayout(forceLayoutMode?: LayoutMode): IResponsiveLayout {\n const width = window.innerWidth;\n const height = window.innerHeight;\n const isTouchDevice = detectTouchSupport();\n const orientation: ScreenOrientation = width > height ? 'landscape' : 'portrait';\n const deviceType = determineDeviceType(width, isTouchDevice);\n const layoutMode = forceLayoutMode ?? determineLayoutMode(width);\n\n return {\n deviceType,\n orientation,\n layoutMode,\n screenWidth: width,\n screenHeight: height,\n isTouchDevice\n };\n}\n\n/**\n * Hook that tracks responsive layout information for the current viewport.\n *\n * Listens to `resize` and `orientationchange` events and recomputes layout\n * on every change. Use the `layoutMode` field to drive structural rendering\n * decisions (e.g., sidebar as drawer vs. fixed panel).\n *\n * @param forceLayoutMode - Optional override for testing or storybook use.\n * @public\n */\nexport function useResponsiveLayout(forceLayoutMode?: LayoutMode): IResponsiveLayout {\n const [layout, setLayout] = useState<IResponsiveLayout>(() => computeLayout(forceLayoutMode));\n\n useEffect(() => {\n if (forceLayoutMode) {\n return;\n }\n\n function updateLayout(): void {\n setLayout(computeLayout());\n }\n\n window.addEventListener('resize', updateLayout);\n\n const onOrientationChange = (): void => {\n // Small delay to let the browser update viewport dimensions\n setTimeout(updateLayout, 100);\n };\n window.addEventListener('orientationchange', onOrientationChange);\n\n // Sync on mount in case viewport changed between SSR and hydration\n updateLayout();\n\n return () => {\n window.removeEventListener('resize', updateLayout);\n window.removeEventListener('orientationchange', onOrientationChange);\n };\n }, [forceLayoutMode]);\n\n return layout;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityRow.d.ts","sourceRoot":"","sources":["../../../src/packlets/selectors/EntityRow.tsx"],"names":[],"mappings":"AAsBA;;;;;;;;;;GAUG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAGjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAM3D;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC1D,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,wDAAwD;IACxD,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,qDAAqD;IACrD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,YAAY,CA+XtG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntityRow.js","sourceRoot":"","sources":["../../../src/packlets/selectors/EntityRow.tsx"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * EntityRow — clickable text row with optional discrete swap-icon for alternates.\n *\n * Renders a uniform row regardless of whether alternates exist:\n * - Left slot: swap icon (when alternates exist) or empty spacer\n * - Name text: clickable for drill-down\n * - Optional right-side content (amount, sublabel, etc.)\n * - Drill-down chevron ›\n *\n * @packageDocumentation\n */\n\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport ReactDOM from 'react-dom';\n\nimport type { ISelectableItem } from './PreferredSelector';\n\n// ============================================================================\n// EntityRow Types\n// ============================================================================\n\n/**\n * Props for the EntityRow component.\n * @public\n */\nexport interface IEntityRowProps<TId extends string = string> {\n /** All options (preferred + alternates). If length === 1, no swap icon is shown. */\n readonly items: ReadonlyArray<ISelectableItem<TId>>;\n /** ID of the preferred/default item (shows ★ marker) */\n readonly preferredId?: TId;\n /** Controlled selected ID (overrides internal state). Use with onSelect. */\n readonly selectedId?: TId;\n /** Callback when the displayed item changes via the swap picker */\n readonly onSelect?: (id: TId) => void;\n /** Callback when the row is clicked (drill-down navigation) */\n readonly onClick?: (id: TId) => void;\n /** Callback to compare items. When provided, popover shows compare buttons. */\n readonly onCompare?: (ids: ReadonlyArray<TId>) => void;\n /** Optional right-side content rendered before the › chevron */\n readonly rightContent?: React.ReactNode;\n /** Optional section label displayed above the row */\n readonly label?: string;\n}\n\n// ============================================================================\n// EntityRow Component\n// ============================================================================\n\n/**\n * A clickable text row with an optional discrete swap-icon popover for\n * switching between alternates. Clicking the row itself always triggers\n * drill-down navigation. The swap icon opens a small picker to change\n * which alternate is displayed.\n *\n * @public\n */\nexport function EntityRow<TId extends string = string>(props: IEntityRowProps<TId>): React.ReactElement {\n const { items, preferredId, onClick, onSelect, onCompare, rightContent, label } = props;\n\n const hasAlternates = items.length > 1;\n const [internalId, setInternalId] = useState<TId>(preferredId ?? items[0]?.id ?? ('' as TId));\n const displayedId = props.selectedId ?? internalId;\n const [pickerOpen, setPickerOpen] = useState(false);\n const [compareMode, setCompareMode] = useState(false);\n const [checkedIds, setCheckedIds] = useState<ReadonlySet<TId>>(new Set());\n const [focusIndex, setFocusIndex] = useState(-1);\n const pickerRef = useRef<HTMLDivElement>(null);\n const pickerBtnRef = useRef<HTMLButtonElement>(null);\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);\n const [pickerPos, setPickerPos] = useState<{ top: number; left: number }>({ top: 0, left: 0 });\n\n // Reset displayed item when items or preferred change (e.g. variation switch)\n useEffect(() => {\n setInternalId(preferredId ?? items[0]?.id ?? ('' as TId));\n }, [preferredId, items]);\n\n // Reset compare mode when picker closes; set initial focus when it opens\n useEffect(() => {\n if (!pickerOpen) {\n setCompareMode(false);\n setCheckedIds(new Set());\n setFocusIndex(-1);\n } else {\n const idx = items.findIndex((i) => i.id === displayedId);\n setFocusIndex(idx >= 0 ? idx : 0);\n }\n }, [pickerOpen, items, displayedId]);\n\n const displayedItem = useMemo(\n () => items.find((i) => i.id === displayedId) ?? items[0],\n [items, displayedId]\n );\n const isPreferred = displayedId === preferredId;\n\n // Position the portal popover relative to the swap button\n useEffect(() => {\n if (pickerOpen && pickerBtnRef.current) {\n const rect = pickerBtnRef.current.getBoundingClientRect();\n setPickerPos({ top: rect.bottom + 2, left: rect.left });\n }\n }, [pickerOpen]);\n\n // Close picker on outside click or scroll\n useEffect(() => {\n if (!pickerOpen) {\n return;\n }\n const handleClickOutside = (e: MouseEvent): void => {\n if (\n pickerRef.current &&\n !pickerRef.current.contains(e.target as Node) &&\n pickerBtnRef.current &&\n !pickerBtnRef.current.contains(e.target as Node)\n ) {\n setPickerOpen(false);\n }\n };\n const handleScroll = (): void => {\n setPickerOpen(false);\n };\n document.addEventListener('mousedown', handleClickOutside);\n // Close on any scroll so the popover doesn't float away from the button\n document.addEventListener('scroll', handleScroll, true);\n return (): void => {\n document.removeEventListener('mousedown', handleClickOutside);\n document.removeEventListener('scroll', handleScroll, true);\n };\n }, [pickerOpen]);\n\n const handleRowClick = useCallback((): void => {\n if (onClick) {\n onClick(displayedId);\n }\n }, [onClick, displayedId]);\n\n const handleRowKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (onClick && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onClick(displayedId);\n }\n },\n [onClick, displayedId]\n );\n\n const handlePickerToggle = useCallback((e: React.MouseEvent): void => {\n e.stopPropagation();\n setPickerOpen((prev) => !prev);\n }, []);\n\n const handlePickItem = useCallback(\n (id: TId): void => {\n setInternalId(id);\n if (onSelect) {\n onSelect(id);\n }\n setPickerOpen(false);\n },\n [onSelect]\n );\n\n const handleCompareAll = useCallback((): void => {\n if (onCompare) {\n onCompare(items.map((i) => i.id));\n }\n setPickerOpen(false);\n }, [onCompare, items]);\n\n const toggleChecked = useCallback((id: TId): void => {\n setCheckedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else if (next.size < 4) {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const handleCompareSelected = useCallback((): void => {\n if (onCompare && checkedIds.size >= 2) {\n onCompare(Array.from(checkedIds));\n setPickerOpen(false);\n }\n }, [onCompare, checkedIds]);\n\n const handlePickerKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n switch (e.key) {\n case 'Escape': {\n e.preventDefault();\n e.stopPropagation();\n if (compareMode) {\n setCompareMode(false);\n setCheckedIds(new Set());\n } else {\n setPickerOpen(false);\n }\n break;\n }\n case 'ArrowDown': {\n e.preventDefault();\n setFocusIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0));\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n setFocusIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1));\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (focusIndex >= 0 && focusIndex < items.length) {\n if (compareMode) {\n toggleChecked(items[focusIndex].id);\n } else {\n handlePickItem(items[focusIndex].id);\n }\n }\n break;\n }\n case ' ': {\n if (compareMode && focusIndex >= 0 && focusIndex < items.length) {\n e.preventDefault();\n toggleChecked(items[focusIndex].id);\n }\n break;\n }\n default:\n break;\n }\n },\n [items, focusIndex, compareMode, toggleChecked, handlePickItem]\n );\n\n // Render the picker popover via portal so it escapes ancestor overflow clipping\n const pickerPopover = pickerOpen\n ? ReactDOM.createPortal(\n <div\n ref={pickerRef}\n style={{ position: 'fixed', top: pickerPos.top, left: pickerPos.left }}\n className=\"z-50 min-w-[180px] max-h-[200px] bg-surface border border-border rounded-lg shadow-lg flex flex-col overflow-hidden\"\n onKeyDown={handlePickerKeyDown}\n >\n <div className=\"flex items-center justify-between px-2.5 py-1 border-b border-border-subtle shrink-0\">\n {onCompare && items.length >= 2 ? (\n compareMode ? (\n <>\n <div className=\"flex items-center gap-1.5\">\n {checkedIds.size >= 2 && (\n <button\n onClick={(e): void => {\n e.stopPropagation();\n handleCompareSelected();\n }}\n className=\"text-[10px] text-white bg-brand-primary rounded px-1.5 py-0.5 hover:bg-brand-primary/90 transition-colors font-medium\"\n >\n Compare {checkedIds.size}\n </button>\n )}\n <button\n onClick={(e): void => {\n e.stopPropagation();\n handleCompareAll();\n }}\n className=\"text-[10px] text-brand-accent hover:text-brand-primary transition-colors font-medium\"\n >\n All\n </button>\n </div>\n <button\n onClick={(e): void => {\n e.stopPropagation();\n setCompareMode(false);\n setCheckedIds(new Set());\n }}\n className=\"text-muted hover:text-secondary transition-colors\"\n aria-label=\"Exit compare\"\n >\n <svg\n className=\"w-3.5 h-3.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </>\n ) : (\n <>\n <span className=\"text-[10px] font-medium text-muted uppercase tracking-wider\">Options</span>\n <button\n onClick={(e): void => {\n e.stopPropagation();\n setCompareMode(true);\n }}\n className=\"text-[10px] text-brand-accent hover:text-brand-primary transition-colors font-medium\"\n >\n Compare…\n </button>\n </>\n )\n ) : (\n <span className=\"text-[10px] font-medium text-muted uppercase tracking-wider\">Alternates</span>\n )}\n </div>\n <div className=\"overflow-y-auto flex-1\">\n {items.map((item, index) => {\n const isCurrent = item.id === displayedId;\n const isPref = item.id === preferredId;\n const isFocused = index === focusIndex;\n const isChecked = compareMode && checkedIds.has(item.id);\n return (\n <button\n key={item.id}\n ref={(el): void => {\n itemRefs.current[index] = el;\n }}\n onClick={(e): void => {\n e.stopPropagation();\n if (compareMode) {\n toggleChecked(item.id);\n } else {\n handlePickItem(item.id);\n }\n }}\n className={`flex items-center gap-2 w-full px-2.5 py-1.5 text-left text-sm transition-colors ${\n isChecked\n ? 'bg-selected text-brand-primary'\n : isCurrent && !compareMode\n ? 'bg-selected text-brand-primary font-medium'\n : isFocused\n ? 'bg-surface-alt text-primary'\n : 'text-secondary hover:bg-hover'\n }`}\n >\n {compareMode ? (\n <span\n className={`flex items-center justify-center w-3.5 h-3.5 rounded border shrink-0 transition-colors ${\n isChecked\n ? 'bg-brand-accent border-brand-accent text-white'\n : 'border-border bg-surface'\n }`}\n >\n {isChecked && (\n <svg\n className=\"w-2.5 h-2.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n ) : (\n <span className=\"w-3 shrink-0 text-center text-xs\">\n {isPref ? <span className=\"text-star\">★</span> : ''}\n </span>\n )}\n <span className=\"flex-1 min-w-0 truncate\">\n {item.label}\n {item.sublabel && <span className=\"ml-1.5 text-xs text-muted\">{item.sublabel}</span>}\n </span>\n {!compareMode && isCurrent && (\n <svg\n className=\"w-3.5 h-3.5 text-brand-accent shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </button>\n );\n })}\n </div>\n </div>,\n document.body\n )\n : null;\n\n return (\n <div>\n {label && <div className=\"text-xs font-semibold text-muted uppercase tracking-wider mb-1\">{label}</div>}\n <div\n className={`flex items-center gap-1.5 py-1.5 pl-0 pr-2 rounded-md ${\n onClick ? 'cursor-pointer hover:bg-hover transition-colors' : ''\n }`}\n onClick={handleRowClick}\n role={onClick ? 'button' : undefined}\n tabIndex={onClick ? 0 : undefined}\n onKeyDown={handleRowKeyDown}\n >\n {/* Fixed-width left slot for swap icon — keeps names aligned */}\n <span className=\"w-4 shrink-0 flex items-center justify-center\">\n {hasAlternates ? (\n <button\n ref={pickerBtnRef}\n onClick={handlePickerToggle}\n className=\"text-muted hover:text-brand-accent p-0 transition-colors\"\n aria-label=\"Switch alternate\"\n tabIndex={-1}\n >\n <svg\n className=\"w-3.5 h-3.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4\"\n />\n </svg>\n </button>\n ) : null}\n </span>\n <span className=\"text-sm text-primary flex-1 truncate\">\n {displayedItem?.label ?? ''}\n {hasAlternates && isPreferred && <span className=\"ml-1 text-xs text-star\">★</span>}\n {displayedItem?.sublabel && (\n <span className=\"ml-1.5 text-xs text-muted\">{displayedItem.sublabel}</span>\n )}\n </span>\n {rightContent}\n {onClick && <span className=\"text-faint text-xs shrink-0\">›</span>}\n </div>\n {pickerPopover}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreferredSelector.d.ts","sourceRoot":"","sources":["../../../src/packlets/selectors/PreferredSelector.tsx"],"names":[],"mappings":"AAsBA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE;;;GAGG;AACH,MAAM,WAAW,eAAe,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC1D,wBAAwB;IACxB,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAClE,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,iCAAiC;IACjC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IACrC,oFAAoF;IACpF,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACvD,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IACzC,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3D,KAAK,EAAE,uBAAuB,CAAC,GAAG,CAAC,GAClC,KAAK,CAAC,YAAY,CAqXpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreferredSelector.js","sourceRoot":"","sources":["../../../src/packlets/selectors/PreferredSelector.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DH,8CAuXC;AAnbD;;;GAGG;AAEH,+CAAwE;AAwCxE,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E;;;;;;;;;;GAUG;AACH,SAAgB,iBAAiB,CAC/B,KAAmC;;IAEnC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAC1F,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAmB,IAAI,GAAG,EAAE,CAAC,CAAC;IAC1E,MAAM,UAAU,GAAG,IAAA,cAAM,EAAoB,IAAI,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,IAAA,cAAM,EAAiB,IAAI,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,IAAA,cAAM,EAAkC,EAAE,CAAC,CAAC;IAE7D,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAEhE,yCAAyC;IACzC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,cAAc,CAAC,KAAK,CAAC,CAAC;YACtB,aAAa,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,sCAAsC;IACtC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QACD,MAAM,kBAAkB,GAAG,CAAC,CAAa,EAAQ,EAAE;YACjD,IACE,UAAU,CAAC,OAAO;gBAClB,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC;gBAC9C,UAAU,CAAC,OAAO;gBAClB,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAC9C,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAC3D,OAAO,GAAS,EAAE;YAChB,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;QAChE,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,sCAAsC;IACtC,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;YACtE,aAAa,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAE9B,gCAAgC;IAChC,IAAA,iBAAS,EAAC,GAAG,EAAE;;QACb,IAAI,IAAI,IAAI,UAAU,IAAI,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5D,MAAA,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,0CAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;IAEvB,MAAM,YAAY,GAAG,IAAA,mBAAW,EAAC,GAAS,EAAE;QAC1C,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,MAAM,YAAY,GAAG,IAAA,mBAAW,EAC9B,CAAC,EAAO,EAAQ,EAAE;QAChB,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,MAAM,eAAe,GAAG,IAAA,mBAAW,EACjC,CAAC,EAAO,EAAE,CAAmB,EAAQ,EAAE;QACrC,CAAC,CAAC,eAAe,EAAE,CAAC;QACpB,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAG,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,MAAM,aAAa,GAAG,IAAA,mBAAW,EAAC,CAAC,EAAO,EAAQ,EAAE;QAClD,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACjB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAClB,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAAC,GAAS,EAAE;QAC9C,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACxC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvB,MAAM,qBAAqB,GAAG,IAAA,mBAAW,EAAC,GAAS,EAAE;QACnD,IAAI,SAAS,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;YACtC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAE5B,MAAM,aAAa,GAAG,IAAA,mBAAW,EAC/B,CAAC,CAAsB,EAAQ,EAAE;;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAChE,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;YACD,OAAO;QACT,CAAC;QAED,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;YACd,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,CAAC,CAAC,eAAe,EAAE,CAAC;gBACpB,IAAI,WAAW,EAAE,CAAC;oBAChB,cAAc,CAAC,KAAK,CAAC,CAAC;oBACtB,aAAa,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;gBAC3B,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,KAAK,CAAC,CAAC;oBACf,MAAA,UAAU,CAAC,OAAO,0CAAE,KAAK,EAAE,CAAC;gBAC9B,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,WAAW,CAAC,CAAC,CAAC;gBACjB,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClE,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,aAAa,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClE,MAAM;YACR,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,CAAC,CAAC,cAAc,EAAE,CAAC;gBACnB,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;oBACjD,IAAI,WAAW,EAAE,CAAC;wBAChB,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;oBACtC,CAAC;yBAAM,CAAC;wBACN,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;oBACrC,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;YACD,KAAK,GAAG,CAAC,CAAC,CAAC;gBACT,IAAI,WAAW,IAAI,UAAU,IAAI,CAAC,IAAI,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;oBAChE,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtC,CAAC;gBACD,MAAM;YACR,CAAC;YACD;gBACE,MAAM;QACV,CAAC;IACH,CAAC,EACD,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,CAAC,CACpE,CAAC;IAEF,OAAO,CACL,uCAAK,SAAS,EAAC,UAAU;QAEtB,KAAK,IAAI,uCAAK,SAAS,EAAC,qCAAqC,IAAE,KAAK,CAAO;QAG5E,0CACE,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,oGACT,WAAW;gBACT,CAAC,CAAC,oEAAoE;gBACtE,CAAC,CAAC,kDACN,IAAI,IAAI,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,EAAE,EAAE,mBACnD,IAAI,mBACL,SAAS;YAEvB,wCAAM,SAAS,EAAC,sCAAsC,IACnD,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,mCAAI,UAAU;gBACjC,WAAW,KAAK,SAAS,IAAI,UAAU,KAAK,WAAW,IAAI,CAC1D,wCAAM,SAAS,EAAC,wBAAwB,aAAS,CAClD,CACI;YACN,WAAW,IAAI,CACd;gBACE,wCAAM,SAAS,EAAC,8CAA8C,IAAE,KAAK,CAAC,MAAM,CAAQ;gBACpF,uCACE,SAAS,EAAE,oDAAoD,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,EACzF,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,CAAC;oBAEd,wCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,gBAAgB,GAAG,CACpE,CACL,CACJ,CACM;QAGR,IAAI,IAAI,CACP,uCACE,GAAG,EAAE,UAAU,EACf,SAAS,EAAC,0IAA0I,EACpJ,IAAI,EAAC,SAAS,EACd,SAAS,EAAE,aAAa;YAGvB,UAAU,IAAI,CACb,uCAAK,SAAS,EAAC,wFAAwF;gBACpG,WAAW,CAAC,CAAC,CAAC,CACb,uCAAK,SAAS,EAAC,2BAA2B;oBACvC,UAAU,CAAC,IAAI,IAAI,CAAC,IAAI,CACvB,0CACE,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAC,mHAAmH;;wBAEpH,UAAU,CAAC,IAAI,CACjB,CACV;oBACD,0CACE,OAAO,EAAE,gBAAgB,EACzB,SAAS,EAAC,kFAAkF,UAGrF,CACL,CACP,CAAC,CAAC,CAAC,CACF,0CACE,OAAO,EAAE,GAAS,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,EACzC,SAAS,EAAC,kFAAkF,oBAGrF,CACV;gBACD,0CACE,OAAO,EAAE,GAAS,EAAE;wBAClB,IAAI,WAAW,EAAE,CAAC;4BAChB,cAAc,CAAC,KAAK,CAAC,CAAC;4BACtB,aAAa,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;wBAC3B,CAAC;6BAAM,CAAC;4BACN,OAAO,CAAC,KAAK,CAAC,CAAC;wBACjB,CAAC;oBACH,CAAC,EACD,SAAS,EAAC,mDAAmD,gBACjD,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO;oBAElD,uCACE,SAAS,EAAC,aAAa,EACvB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,CAAC;wBAEd,wCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,sBAAsB,GAAG,CAC1E,CACC,CACL,CACP;YAGD,uCAAK,SAAS,EAAC,wBAAwB,IACpC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBACzB,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,KAAK,UAAU,CAAC;gBAC1C,MAAM,WAAW,GAAG,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,EAAE,KAAK,WAAW,CAAC;gBACzE,MAAM,SAAS,GAAG,KAAK,KAAK,UAAU,CAAC;gBACvC,MAAM,SAAS,GAAG,WAAW,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAEzD,OAAO,CACL,0CACE,GAAG,EAAE,IAAI,CAAC,EAAE,EACZ,GAAG,EAAE,CAAC,EAAE,EAAQ,EAAE;wBAChB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;oBAC/B,CAAC,EACD,IAAI,EAAC,QAAQ,mBACE,UAAU,EACzB,OAAO,EAAE,GAAS,EAAE;wBAClB,IAAI,WAAW,EAAE,CAAC;4BAChB,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACzB,CAAC;6BAAM,CAAC;4BACN,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACxB,CAAC;oBACH,CAAC,EACD,SAAS,EAAE,oFACT,SAAS;wBACP,CAAC,CAAC,gCAAgC;wBAClC,CAAC,CAAC,UAAU,IAAI,CAAC,WAAW;4BAC5B,CAAC,CAAC,4CAA4C;4BAC9C,CAAC,CAAC,SAAS;gCACX,CAAC,CAAC,6BAA6B;gCAC/B,CAAC,CAAC,+BACN,EAAE;oBAGD,WAAW,CAAC,CAAC,CAAC,CACb,wCACE,SAAS,EAAE,0FACT,SAAS;4BACP,CAAC,CAAC,gDAAgD;4BAClD,CAAC,CAAC,0BACN,EAAE,IAED,SAAS,IAAI,CACZ,uCACE,SAAS,EAAC,aAAa,EACvB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,CAAC;wBAEd,wCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,gBAAgB,GAAG,CACpE,CACP,CACI,CACR,CAAC,CAAC,CAAC,CACF,wCAAM,SAAS,EAAC,kCAAkC,IAC/C,WAAW,CAAC,CAAC,CAAC,wCAAM,SAAS,EAAC,WAAW,aAAS,CAAC,CAAC,CAAC,EAAE,CACnD,CACR;oBAGD,wCAAM,SAAS,EAAC,gBAAgB;wBAC9B,wCAAM,SAAS,EAAC,gBAAgB,IAAE,IAAI,CAAC,KAAK,CAAQ;wBACnD,IAAI,CAAC,QAAQ,IAAI,CAChB,wCAAM,SAAS,EAAC,mCAAmC,IAAE,IAAI,CAAC,QAAQ,CAAQ,CAC3E,CACI;oBAGN,CAAC,WAAW,IAAI,UAAU,IAAI,CAC7B,uCACE,SAAS,EAAC,wCAAwC,EAClD,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,CAAC;wBAEd,wCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,gBAAgB,GAAG,CACpE,CACP;oBAGA,CAAC,WAAW,IAAI,WAAW,IAAI,CAC9B,0CACE,OAAO,EAAE,CAAC,CAAC,EAAQ,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,EACjD,SAAS,EAAC,yDAAyD,gBACvD,QAAQ,IAAI,CAAC,KAAK,EAAE;wBAEhC,uCACE,SAAS,EAAC,SAAS,EACnB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,CAAC;4BAEd,wCAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,CAAC,EAAC,cAAc,GAAG,CAClE,CACC,CACV,CACM,CACV,CAAC;YACJ,CAAC,CAAC,CACE,CACF,CACP,CACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * PreferredSelector — compact popover for choosing one item from a set of options.\n * @packageDocumentation\n */\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\n// ============================================================================\n// PreferredSelector Types\n// ============================================================================\n\n/**\n * A single selectable item in the PreferredSelector.\n * @public\n */\nexport interface ISelectableItem<TId extends string = string> {\n /** Unique identifier */\n readonly id: TId;\n /** Primary display label */\n readonly label: string;\n /** Optional secondary label */\n readonly sublabel?: string;\n}\n\n/**\n * Props for the PreferredSelector component.\n * @public\n */\nexport interface IPreferredSelectorProps<TId extends string = string> {\n /** Available items to choose from */\n readonly items: ReadonlyArray<ISelectableItem<TId>>;\n /** Currently selected item ID */\n readonly selectedId: TId;\n /** ID of the preferred/default item (shows ★ marker) */\n readonly preferredId?: TId;\n /** Callback when an item is selected */\n readonly onSelect: (id: TId) => void;\n /** Callback to compare selected items side-by-side. Receives the IDs to compare. */\n readonly onCompare?: (ids: ReadonlyArray<TId>) => void;\n /** Callback for drill-down navigation on an item (shows › chevron per row) */\n readonly onDrillDown?: (id: TId) => void;\n /** Section title displayed above the trigger */\n readonly label?: string;\n}\n\n// ============================================================================\n// PreferredSelector Component\n// ============================================================================\n\n/**\n * Compact inline selector with popover for choosing one item from a set.\n *\n * When there is only one item, renders as a static label.\n * When there are multiple items, renders a clickable trigger that opens\n * a popover with all options. If `onCompare` is provided, the popover\n * includes a compare toggle that enables checkboxes for multi-select,\n * with \"Compare All\" and \"Compare Selected\" actions.\n *\n * @public\n */\nexport function PreferredSelector<TId extends string = string>(\n props: IPreferredSelectorProps<TId>\n): React.ReactElement {\n const { items, selectedId, preferredId, onSelect, onCompare, onDrillDown, label } = props;\n const [open, setOpen] = useState(false);\n const [focusIndex, setFocusIndex] = useState(-1);\n const [compareMode, setCompareMode] = useState(false);\n const [checkedIds, setCheckedIds] = useState<ReadonlySet<TId>>(new Set());\n const triggerRef = useRef<HTMLButtonElement>(null);\n const popoverRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);\n\n const selectedItem = items.find((item) => item.id === selectedId);\n const hasMultiple = items.length > 1;\n const canCompare = onCompare !== undefined && items.length >= 2;\n\n // Reset compare mode when popover closes\n useEffect(() => {\n if (!open) {\n setCompareMode(false);\n setCheckedIds(new Set());\n }\n }, [open]);\n\n // Close popover when clicking outside\n useEffect(() => {\n if (!open) {\n return;\n }\n const handleClickOutside = (e: MouseEvent): void => {\n if (\n popoverRef.current &&\n !popoverRef.current.contains(e.target as Node) &&\n triggerRef.current &&\n !triggerRef.current.contains(e.target as Node)\n ) {\n setOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return (): void => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [open]);\n\n // Focus first item when popover opens\n useEffect(() => {\n if (open) {\n const selectedIdx = items.findIndex((item) => item.id === selectedId);\n setFocusIndex(selectedIdx >= 0 ? selectedIdx : 0);\n }\n }, [open, items, selectedId]);\n\n // Scroll focused item into view\n useEffect(() => {\n if (open && focusIndex >= 0 && itemRefs.current[focusIndex]) {\n itemRefs.current[focusIndex]?.scrollIntoView({ block: 'nearest' });\n }\n }, [open, focusIndex]);\n\n const handleToggle = useCallback((): void => {\n if (hasMultiple) {\n setOpen((prev) => !prev);\n }\n }, [hasMultiple]);\n\n const handleSelect = useCallback(\n (id: TId): void => {\n onSelect(id);\n setOpen(false);\n },\n [onSelect]\n );\n\n const handleDrillDown = useCallback(\n (id: TId, e: React.MouseEvent): void => {\n e.stopPropagation();\n onDrillDown?.(id);\n setOpen(false);\n },\n [onDrillDown]\n );\n\n const toggleChecked = useCallback((id: TId): void => {\n setCheckedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else if (next.size < 4) {\n next.add(id);\n }\n return next;\n });\n }, []);\n\n const handleCompareAll = useCallback((): void => {\n if (onCompare) {\n onCompare(items.map((item) => item.id));\n setOpen(false);\n }\n }, [onCompare, items]);\n\n const handleCompareSelected = useCallback((): void => {\n if (onCompare && checkedIds.size >= 2) {\n onCompare(Array.from(checkedIds));\n setOpen(false);\n }\n }, [onCompare, checkedIds]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent): void => {\n if (!open) {\n if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {\n e.preventDefault();\n setOpen(true);\n }\n return;\n }\n\n switch (e.key) {\n case 'Escape': {\n e.preventDefault();\n e.stopPropagation();\n if (compareMode) {\n setCompareMode(false);\n setCheckedIds(new Set());\n } else {\n setOpen(false);\n triggerRef.current?.focus();\n }\n break;\n }\n case 'ArrowDown': {\n e.preventDefault();\n setFocusIndex((prev) => (prev < items.length - 1 ? prev + 1 : 0));\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n setFocusIndex((prev) => (prev > 0 ? prev - 1 : items.length - 1));\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (focusIndex >= 0 && focusIndex < items.length) {\n if (compareMode) {\n toggleChecked(items[focusIndex].id);\n } else {\n handleSelect(items[focusIndex].id);\n }\n }\n break;\n }\n case ' ': {\n if (compareMode && focusIndex >= 0 && focusIndex < items.length) {\n e.preventDefault();\n toggleChecked(items[focusIndex].id);\n }\n break;\n }\n default:\n break;\n }\n },\n [open, items, focusIndex, handleSelect, compareMode, toggleChecked]\n );\n\n return (\n <div className=\"relative\">\n {/* Section label */}\n {label && <div className=\"text-xs font-medium text-muted mb-1\">{label}</div>}\n\n {/* Trigger */}\n <button\n ref={triggerRef}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n className={`flex items-center gap-1.5 px-2 py-1 text-sm rounded-md border transition-colors w-full text-left ${\n hasMultiple\n ? 'border-border hover:border-brand-primary cursor-pointer bg-surface'\n : 'border-transparent cursor-default bg-transparent'\n } ${open ? 'border-brand-primary ring-1 ring-focus-ring/20' : ''}`}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n >\n <span className=\"flex-1 min-w-0 truncate text-primary\">\n {selectedItem?.label ?? selectedId}\n {preferredId !== undefined && selectedId === preferredId && (\n <span className=\"ml-1 text-xs text-star\">★</span>\n )}\n </span>\n {hasMultiple && (\n <>\n <span className=\"text-[10px] text-muted shrink-0 tabular-nums\">{items.length}</span>\n <svg\n className={`w-3 h-3 text-muted shrink-0 transition-transform ${open ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </>\n )}\n </button>\n\n {/* Popover */}\n {open && (\n <div\n ref={popoverRef}\n className=\"absolute z-50 mt-1 w-full min-w-[200px] max-h-[280px] bg-surface border border-border rounded-lg shadow-lg flex flex-col overflow-hidden\"\n role=\"listbox\"\n onKeyDown={handleKeyDown}\n >\n {/* Popover header */}\n {canCompare && (\n <div className=\"flex items-center justify-between px-2.5 py-1.5 border-b border-border-subtle shrink-0\">\n {compareMode ? (\n <div className=\"flex items-center gap-1.5\">\n {checkedIds.size >= 2 && (\n <button\n onClick={handleCompareSelected}\n className=\"text-xs text-white bg-brand-primary rounded px-1.5 py-0.5 hover:bg-brand-primary/90 transition-colors font-medium\"\n >\n Compare {checkedIds.size}\n </button>\n )}\n <button\n onClick={handleCompareAll}\n className=\"text-xs text-brand-accent hover:text-brand-primary transition-colors font-medium\"\n >\n All\n </button>\n </div>\n ) : (\n <button\n onClick={(): void => setCompareMode(true)}\n className=\"text-xs text-brand-accent hover:text-brand-primary transition-colors font-medium\"\n >\n Compare…\n </button>\n )}\n <button\n onClick={(): void => {\n if (compareMode) {\n setCompareMode(false);\n setCheckedIds(new Set());\n } else {\n setOpen(false);\n }\n }}\n className=\"text-muted hover:text-secondary transition-colors\"\n aria-label={compareMode ? 'Exit compare' : 'Close'}\n >\n <svg\n className=\"w-3.5 h-3.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n )}\n\n {/* Items list */}\n <div className=\"overflow-y-auto flex-1\">\n {items.map((item, index) => {\n const isSelected = item.id === selectedId;\n const isPreferred = preferredId !== undefined && item.id === preferredId;\n const isFocused = index === focusIndex;\n const isChecked = compareMode && checkedIds.has(item.id);\n\n return (\n <button\n key={item.id}\n ref={(el): void => {\n itemRefs.current[index] = el;\n }}\n role=\"option\"\n aria-selected={isSelected}\n onClick={(): void => {\n if (compareMode) {\n toggleChecked(item.id);\n } else {\n handleSelect(item.id);\n }\n }}\n className={`flex items-center gap-2 w-full px-2.5 py-1.5 text-left text-sm transition-colors ${\n isChecked\n ? 'bg-selected text-brand-primary'\n : isSelected && !compareMode\n ? 'bg-selected text-brand-primary font-medium'\n : isFocused\n ? 'bg-surface-alt text-primary'\n : 'text-secondary hover:bg-hover'\n }`}\n >\n {/* Checkbox (compare mode) or preferred star */}\n {compareMode ? (\n <span\n className={`flex items-center justify-center w-3.5 h-3.5 rounded border shrink-0 transition-colors ${\n isChecked\n ? 'bg-brand-accent border-brand-accent text-white'\n : 'border-border bg-surface'\n }`}\n >\n {isChecked && (\n <svg\n className=\"w-2.5 h-2.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n </span>\n ) : (\n <span className=\"w-3 shrink-0 text-center text-xs\">\n {isPreferred ? <span className=\"text-star\">★</span> : ''}\n </span>\n )}\n\n {/* Label + sublabel */}\n <span className=\"flex-1 min-w-0\">\n <span className=\"truncate block\">{item.label}</span>\n {item.sublabel && (\n <span className=\"text-xs text-muted truncate block\">{item.sublabel}</span>\n )}\n </span>\n\n {/* Selection check (normal mode only) */}\n {!compareMode && isSelected && (\n <svg\n className=\"w-3.5 h-3.5 text-brand-accent shrink-0\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={3}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M5 13l4 4L19 7\" />\n </svg>\n )}\n\n {/* Drill-down chevron (normal mode only) */}\n {!compareMode && onDrillDown && (\n <button\n onClick={(e): void => handleDrillDown(item.id, e)}\n className=\"text-faint hover:text-brand-accent shrink-0 p-0.5 -mr-1\"\n aria-label={`Open ${item.label}`}\n >\n <svg\n className=\"w-3 h-3\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n )}\n </button>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/selectors/index.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/selectors/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAEH,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAElB,yDAAwD;AAA/C,sHAAA,iBAAiB,OAAA","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport { EntityRow } from './EntityRow';\nexport type { IEntityRowProps } from './EntityRow';\nexport { PreferredSelector } from './PreferredSelector';\nexport type { IPreferredSelectorProps, ISelectableItem } from './PreferredSelector';\n"]}
|
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
import React from 'react';
|
|
10
|
+
/**
|
|
11
|
+
* Describes a single collection for rendering in the sidebar.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export interface ICollectionBadge {
|
|
15
|
+
readonly kind: 'dot' | 'count';
|
|
16
|
+
readonly tone?: 'info' | 'warning' | 'danger';
|
|
17
|
+
readonly count?: number;
|
|
18
|
+
readonly ariaLabel?: string;
|
|
19
|
+
}
|
|
10
20
|
/**
|
|
11
21
|
* Describes a single collection for rendering in the sidebar.
|
|
12
22
|
* @public
|
|
@@ -33,18 +43,38 @@ export interface ICollectionRowItem {
|
|
|
33
43
|
* in another storage root. When true, a repair action should be offered.
|
|
34
44
|
*/
|
|
35
45
|
readonly hasConflict?: boolean;
|
|
46
|
+
/** Whether this collection is explicitly hidden by the user */
|
|
47
|
+
readonly isHidden?: boolean;
|
|
48
|
+
/** The name of the storage source this collection was loaded from */
|
|
49
|
+
readonly sourceName?: string;
|
|
50
|
+
/** Optional badge rendered alongside the collection name */
|
|
51
|
+
readonly badge?: ICollectionBadge;
|
|
52
|
+
/**
|
|
53
|
+
* Label shown for immutable collections. Defaults to `"(built-in)"` when
|
|
54
|
+
* omitted. Set to e.g. `"(trading post)"` for imported read-only content.
|
|
55
|
+
*/
|
|
56
|
+
readonly readOnlyLabel?: string;
|
|
57
|
+
/**
|
|
58
|
+
* When true, the collection can be deleted even though it is not mutable.
|
|
59
|
+
* Use for user-imported read-only content (e.g., Trading Post collections)
|
|
60
|
+
* that the user should be able to remove but not edit.
|
|
61
|
+
*/
|
|
62
|
+
readonly isDeletable?: boolean;
|
|
36
63
|
}
|
|
37
64
|
/**
|
|
38
65
|
* Props for the CollectionSection component.
|
|
39
66
|
* @public
|
|
40
67
|
*/
|
|
68
|
+
/**
|
|
69
|
+
* Maps source names to Tailwind border color classes for the left-border indicator.
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export type SourceColorMap = Readonly<Record<string, string>>;
|
|
41
73
|
export interface ICollectionSectionProps {
|
|
42
74
|
/** Collection items to display */
|
|
43
75
|
readonly collections: ReadonlyArray<ICollectionRowItem>;
|
|
44
76
|
/** Callback when visibility is toggled for a collection */
|
|
45
77
|
readonly onToggleVisibility: (collectionId: string) => void;
|
|
46
|
-
/** Callback when all-visible toggle is clicked; receives true to show all, false to hide all */
|
|
47
|
-
readonly onToggleAllVisibility?: (showAll: boolean) => void;
|
|
48
78
|
/** Callback when "Add Directory" is clicked */
|
|
49
79
|
readonly onAddDirectory?: () => void;
|
|
50
80
|
/** Callback when "New Collection" is clicked */
|
|
@@ -67,8 +97,16 @@ export interface ICollectionSectionProps {
|
|
|
67
97
|
readonly onRenameCollection?: (collectionId: string) => void;
|
|
68
98
|
/** Callback when merge is clicked for a mutable collection */
|
|
69
99
|
readonly onMergeCollection?: (collectionId: string) => void;
|
|
100
|
+
/** Callback when hide is selected from the context menu */
|
|
101
|
+
readonly onHideCollection?: (collectionId: string) => void;
|
|
102
|
+
/** Callback when show (unhide) is selected from the context menu */
|
|
103
|
+
readonly onShowCollection?: (collectionId: string) => void;
|
|
70
104
|
/** Whether the section starts collapsed */
|
|
71
105
|
readonly defaultCollapsed?: boolean;
|
|
106
|
+
/** Maps sourceName values to Tailwind border-l color classes */
|
|
107
|
+
readonly sourceColorMap?: SourceColorMap;
|
|
108
|
+
/** Fallback border-l color class when sourceName is not in the map */
|
|
109
|
+
readonly sourceColorFallback?: string;
|
|
72
110
|
}
|
|
73
111
|
/**
|
|
74
112
|
* Collapsible sidebar section for managing collections.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CollectionSection.d.ts","sourceRoot":"","sources":["../../../src/packlets/sidebar/CollectionSection.tsx"],"names":[],"mappings":"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"}
|