@burdenoff/microfe-bigconsole 2026.711.3 → 2026.713.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/bigconsole/assistant/createSandboxAssistantTransport.js.map +1 -1
  2. package/dist/bigconsole/components/builder/BuilderCanvas.js +21 -0
  3. package/dist/bigconsole/components/builder/BuilderCanvas.js.map +1 -0
  4. package/dist/bigconsole/components/builder/BuilderTopbar.js +33 -0
  5. package/dist/bigconsole/components/builder/BuilderTopbar.js.map +1 -0
  6. package/dist/bigconsole/components/builder/DashboardEditorShell.js +20 -0
  7. package/dist/bigconsole/components/builder/DashboardEditorShell.js.map +1 -0
  8. package/dist/bigconsole/components/builder/WidgetInspector.js +14 -0
  9. package/dist/bigconsole/components/builder/WidgetInspector.js.map +1 -0
  10. package/dist/bigconsole/components/builder/index.js +4 -0
  11. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js +45 -0
  12. package/dist/bigconsole/components/builder/inspector/AdvancedSection.js.map +1 -0
  13. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js +43 -0
  14. package/dist/bigconsole/components/builder/inspector/AppearanceSection.js.map +1 -0
  15. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js +124 -0
  16. package/dist/bigconsole/components/builder/inspector/DataBindingSection.js.map +1 -0
  17. package/dist/bigconsole/components/builder/inspector/GeneralSection.js +50 -0
  18. package/dist/bigconsole/components/builder/inspector/GeneralSection.js.map +1 -0
  19. package/dist/bigconsole/components/builder/inspector/index.js +4 -0
  20. package/dist/bigconsole/components/dashboard/DashboardCanvas.js +221 -199
  21. package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
  22. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +196 -188
  23. package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
  24. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js +135 -122
  25. package/dist/bigconsole/components/dashboard/ShareDialog/ShareDialog.js.map +1 -1
  26. package/dist/bigconsole/components/dashboard/WidgetPalette.js +145 -102
  27. package/dist/bigconsole/components/dashboard/WidgetPalette.js.map +1 -1
  28. package/dist/bigconsole/components/dashboard/index.js +4 -0
  29. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js +166 -158
  30. package/dist/bigconsole/components/datasink/ImportDataSinkDialog.js.map +1 -1
  31. package/dist/bigconsole/components/widgets/PropertiesPanel.js +529 -742
  32. package/dist/bigconsole/components/widgets/PropertiesPanel.js.map +1 -1
  33. package/dist/bigconsole/components/widgets/WidgetWrapper.js +227 -226
  34. package/dist/bigconsole/components/widgets/WidgetWrapper.js.map +1 -1
  35. package/dist/bigconsole/hooks/index.js +1 -0
  36. package/dist/bigconsole/hooks/useBigConsoleAnalytics.js +13 -0
  37. package/dist/bigconsole/hooks/useBigConsoleAnalytics.js.map +1 -0
  38. package/dist/bigconsole/hooks/useWidgetOperations.js +102 -68
  39. package/dist/bigconsole/hooks/useWidgetOperations.js.map +1 -1
  40. package/dist/bigconsole/pages/DashboardBuilderPage.js +221 -316
  41. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  42. package/dist/bigconsole/pages/InsightsPage.js +102 -87
  43. package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
  44. package/dist/bigconsole/utils/widgetBinding.js +115 -0
  45. package/dist/bigconsole/utils/widgetBinding.js.map +1 -0
  46. package/package.json +3 -3
  47. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js +0 -883
  48. package/dist/bigconsole/components/widgets/WidgetConfigDialog.js.map +0 -1
  49. package/dist/bigconsole/components/widgets/WidgetTypeSelector.js +0 -311
  50. package/dist/bigconsole/components/widgets/WidgetTypeSelector.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ShareDialog.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/ShareDialog/ShareDialog.tsx"],"sourcesContent":["/**\n * ShareDialog Component\n *\n * Dialog for sharing dashboards with users and roles.\n */\n\nimport React, { useState, useEffect, useCallback, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n useDashboardSharing,\n type DashboardShare,\n type SharePermission,\n type ShareRecipientType,\n} from '../../../hooks';\n\n// Dark mode aware colors\nconst getColors = (isDark: boolean) => ({\n bgPrimary: isDark ? '#1a1a2e' : '#ffffff',\n bgSecondary: isDark ? '#252542' : '#f4f4f5',\n bgTertiary: isDark ? '#2d2d4a' : '#e4e4e7',\n textPrimary: isDark ? '#f4f4f5' : '#18181b',\n textSecondary: isDark ? '#a1a1aa' : '#71717a',\n textTertiary: isDark ? '#71717a' : '#a1a1aa',\n borderDefault: isDark ? '#3f3f5c' : '#e4e4e7',\n actionPrimaryBg: '#6366f1',\n actionPrimaryBgHover: '#4f46e5',\n statusSuccessBg: '#22c55e',\n statusErrorText: '#ef4444',\n});\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ShareDialogProps {\n dashboardId: string;\n dashboardName: string;\n isOpen: boolean;\n onClose: () => void;\n}\n\ninterface ShareRecipient {\n id: string;\n name: string;\n email?: string;\n type: ShareRecipientType;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Permission options as per spec (03-graphql-contract.md)\n * Spec values: view, edit\n */\nconst PERMISSION_OPTIONS: { value: SharePermission; label: string; description: string }[] = [\n { value: 'VIEW', label: 'View', description: 'Can view the dashboard' },\n { value: 'EDIT', label: 'Edit', description: 'Can edit widgets, layout, and share' },\n];\n\n// Use shared semantic tokens for portal rendering\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function ShareDialog({ dashboardId, dashboardName, isOpen, onClose }: ShareDialogProps) {\n const { shares, loading, fetchShares, shareWithUser, shareWithGroup, updateShare, revokeShare, revokeAllShares } =\n useDashboardSharing();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedRecipient, setSelectedRecipient] = useState<ShareRecipient | null>(null);\n const [selectedPermission, setSelectedPermission] = useState<SharePermission>('VIEW');\n const [shareLink, setShareLink] = useState('');\n const [copySuccess, setCopySuccess] = useState(false);\n\n // Fetch shares when dialog opens\n useEffect(() => {\n if (isOpen && dashboardId) {\n fetchShares(dashboardId);\n // Generate share link\n setShareLink(`${window.location.origin}/dashboard/${dashboardId}?shared=true`);\n }\n }, [isOpen, dashboardId, fetchShares]);\n\n // Handle share - per spec: only USER and GROUP recipient types\n const handleShare = useCallback(async () => {\n if (!selectedRecipient) return;\n\n if (selectedRecipient.type === 'USER') {\n await shareWithUser(dashboardId, selectedRecipient.id, selectedPermission);\n } else if (selectedRecipient.type === 'GROUP') {\n await shareWithGroup(dashboardId, selectedRecipient.id, selectedPermission);\n }\n\n setSelectedRecipient(null);\n setSearchQuery('');\n }, [dashboardId, selectedRecipient, selectedPermission, shareWithUser, shareWithGroup]);\n\n // Handle update permission\n const handleUpdatePermission = useCallback(\n async (shareId: string, newPermission: SharePermission) => {\n await updateShare({ id: shareId, permission: newPermission });\n },\n [updateShare]\n );\n\n // Handle revoke\n const handleRevoke = useCallback(\n async (shareId: string) => {\n if (window.confirm('Are you sure you want to revoke this access?')) {\n await revokeShare(shareId);\n }\n },\n [revokeShare]\n );\n\n // Handle revoke all\n const handleRevokeAll = useCallback(async () => {\n if (window.confirm('Are you sure you want to revoke all shared access?')) {\n await revokeAllShares(dashboardId);\n }\n }, [dashboardId, revokeAllShares]);\n\n // Copy link to clipboard\n const handleCopyLink = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(shareLink);\n setCopySuccess(true);\n setTimeout(() => setCopySuccess(false), 2000);\n } catch (err) {}\n }, [shareLink]);\n\n // Mock search results (in real app, this would come from an API)\n // Per spec: ShareRecipientType is 'user' or 'group' only\n const searchResults: ShareRecipient[] = searchQuery\n ? (\n [\n { id: 'user-1', name: 'John Doe', email: 'john@example.com', type: 'USER' as ShareRecipientType },\n { id: 'user-2', name: 'Jane Smith', email: 'jane@example.com', type: 'USER' as ShareRecipientType },\n { id: 'group-admin', name: 'Administrators', type: 'GROUP' as ShareRecipientType },\n { id: 'group-editor', name: 'Editors', type: 'GROUP' as ShareRecipientType },\n ] as ShareRecipient[]\n ).filter(\n (r) =>\n r.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.email?.toLowerCase().includes(searchQuery.toLowerCase())\n )\n : [];\n\n // Check if dark mode is enabled\n const isDarkMode = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');\n const colors = useMemo(() => getColors(isDarkMode), [isDarkMode]);\n\n if (!isOpen) return null;\n\n // Use portal to render at document.body level to avoid z-index/stacking context issues\n const dialogContent = (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 99999,\n isolation: 'isolate',\n }}\n onClick={onClose}\n >\n <div\n style={{\n width: '520px',\n maxHeight: '80vh',\n backgroundColor: colors.bgPrimary,\n borderRadius: '12px',\n boxShadow: '0 8px 32px rgba(0, 0, 0, 0.3)',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 100000,\n color: colors.textPrimary,\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div\n style={{\n padding: '20px 24px',\n borderBottom: `1px solid ${colors.borderDefault}`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n backgroundColor: colors.bgPrimary,\n }}\n >\n <div>\n <h3 style={{ margin: 0, fontSize: '18px', fontWeight: 600, color: colors.textPrimary }}>Share Dashboard</h3>\n <p style={{ margin: '4px 0 0', fontSize: '13px', color: colors.textSecondary }}>{dashboardName}</p>\n </div>\n <button\n onClick={onClose}\n style={{\n background: 'none',\n border: 'none',\n fontSize: '24px',\n cursor: 'pointer',\n color: colors.textSecondary,\n padding: '4px',\n lineHeight: 1,\n }}\n >\n ×\n </button>\n </div>\n\n {/* Content */}\n <div\n style={{\n padding: '24px',\n overflowY: 'auto',\n maxHeight: 'calc(80vh - 200px)',\n backgroundColor: colors.bgPrimary,\n }}\n >\n {/* Share Link Section */}\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n Share Link\n </label>\n <div style={{ display: 'flex', gap: '8px' }}>\n <input\n type=\"text\"\n value={shareLink}\n readOnly\n style={{\n flex: 1,\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgSecondary,\n color: colors.textPrimary,\n }}\n />\n <button\n onClick={handleCopyLink}\n style={{\n padding: '10px 16px',\n backgroundColor: copySuccess ? colors.statusSuccessBg : colors.actionPrimaryBg,\n color: 'white',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n fontSize: '13px',\n fontWeight: 500,\n minWidth: '80px',\n }}\n >\n {copySuccess ? 'Copied!' : 'Copy'}\n </button>\n </div>\n </div>\n\n {/* Add People Section */}\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n Add People\n </label>\n <div style={{ display: 'flex', gap: '8px', marginBottom: '8px' }}>\n <div style={{ flex: 1, position: 'relative' }}>\n <input\n type=\"text\"\n value={selectedRecipient ? selectedRecipient.name : searchQuery}\n onChange={(e) => {\n setSearchQuery(e.target.value);\n setSelectedRecipient(null);\n }}\n placeholder=\"Search by name or email...\"\n style={{\n width: '100%',\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n />\n {/* Search Results Dropdown */}\n {searchQuery && !selectedRecipient && searchResults.length > 0 && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n right: 0,\n marginTop: '4px',\n backgroundColor: colors.bgPrimary,\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.25)',\n zIndex: 100001,\n maxHeight: '200px',\n overflowY: 'auto',\n }}\n >\n {searchResults.map((result) => (\n <button\n key={result.id}\n onClick={() => setSelectedRecipient(result)}\n style={{\n display: 'block',\n width: '100%',\n padding: '10px 12px',\n textAlign: 'left',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n borderBottom: `1px solid ${colors.borderDefault}`,\n }}\n >\n <div style={{ fontSize: '13px', fontWeight: 500, color: colors.textPrimary }}>\n {result.name}\n </div>\n {result.email && (\n <div style={{ fontSize: '11px', color: colors.textSecondary }}>{result.email}</div>\n )}\n <span\n style={{\n fontSize: '10px',\n color: colors.textTertiary,\n textTransform: 'uppercase',\n }}\n >\n {result.type}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n <select\n value={selectedPermission}\n onChange={(e) => setSelectedPermission(e.target.value as SharePermission)}\n style={{\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n >\n {PERMISSION_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n <button\n onClick={handleShare}\n disabled={!selectedRecipient || loading}\n style={{\n padding: '10px 16px',\n backgroundColor: selectedRecipient ? colors.actionPrimaryBg : colors.bgTertiary,\n color: selectedRecipient ? 'white' : colors.textSecondary,\n border: 'none',\n borderRadius: '6px',\n cursor: selectedRecipient ? 'pointer' : 'not-allowed',\n fontSize: '13px',\n fontWeight: 500,\n }}\n >\n Share\n </button>\n </div>\n </div>\n\n {/* Current Shares */}\n <div>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: '12px',\n }}\n >\n <label\n style={{\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n People with Access ({shares.length})\n </label>\n {shares.length > 0 && (\n <button\n onClick={handleRevokeAll}\n style={{\n padding: '4px 8px',\n backgroundColor: 'transparent',\n color: colors.statusErrorText,\n border: 'none',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n Revoke All\n </button>\n )}\n </div>\n\n {loading && shares.length === 0 ? (\n <p style={{ color: colors.textSecondary, fontSize: '13px' }}>Loading...</p>\n ) : shares.length === 0 ? (\n <p style={{ color: colors.textSecondary, fontSize: '13px' }}>No one has access to this dashboard yet.</p>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {shares.map((share) => (\n <ShareItem\n key={share.id}\n share={share}\n onUpdatePermission={handleUpdatePermission}\n onRevoke={handleRevoke}\n colors={colors}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n\n // Render via portal to document.body to escape any stacking context issues\n return createPortal(dialogContent, document.body);\n}\n\n// ============================================================================\n// ShareItem Sub-component\n// ============================================================================\n\ninterface ShareItemProps {\n share: DashboardShare;\n onUpdatePermission: (shareId: string, permission: SharePermission) => void;\n onRevoke: (shareId: string) => void;\n colors: ReturnType<typeof getColors>;\n}\n\nfunction ShareItem({ share, onUpdatePermission, onRevoke, colors }: ShareItemProps) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '10px 12px',\n backgroundColor: colors.bgSecondary,\n borderRadius: '6px',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n backgroundColor: colors.actionPrimaryBg,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'white',\n fontWeight: 600,\n fontSize: '14px',\n }}\n >\n {share.recipientType === 'USER' ? 'U' : 'R'}\n </div>\n <div>\n <div style={{ fontSize: '13px', fontWeight: 500, color: colors.textPrimary }}>{share.recipientId}</div>\n <div style={{ fontSize: '11px', color: colors.textSecondary }}>\n {share.recipientType} - Shared {new Date(share.createdAt).toLocaleDateString()}\n </div>\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <select\n value={share.permission}\n onChange={(e) => onUpdatePermission(share.id, e.target.value as SharePermission)}\n style={{\n padding: '6px 10px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '4px',\n fontSize: '12px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n >\n {PERMISSION_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n <button\n onClick={() => onRevoke(share.id)}\n style={{\n padding: '6px 10px',\n backgroundColor: 'transparent',\n color: colors.statusErrorText,\n border: `1px solid ${colors.statusErrorText}`,\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n Revoke\n </button>\n </div>\n </div>\n );\n}\n\nexport default ShareDialog;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ShareDialog.js","names":[],"sources":["../../../../../src/bigconsole/components/dashboard/ShareDialog/ShareDialog.tsx"],"sourcesContent":["/**\n * ShareDialog Component\n *\n * Dialog for sharing dashboards with users and roles.\n */\n\nimport React, { useState, useEffect, useCallback, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n useDashboardSharing,\n type DashboardShare,\n type SharePermission,\n type ShareRecipientType,\n} from '../../../hooks';\nimport { useBigConsoleAnalytics } from '../../../hooks/useBigConsoleAnalytics';\n\n// Dark mode aware colors\nconst getColors = (isDark: boolean) => ({\n bgPrimary: isDark ? '#1a1a2e' : '#ffffff',\n bgSecondary: isDark ? '#252542' : '#f4f4f5',\n bgTertiary: isDark ? '#2d2d4a' : '#e4e4e7',\n textPrimary: isDark ? '#f4f4f5' : '#18181b',\n textSecondary: isDark ? '#a1a1aa' : '#71717a',\n textTertiary: isDark ? '#71717a' : '#a1a1aa',\n borderDefault: isDark ? '#3f3f5c' : '#e4e4e7',\n actionPrimaryBg: '#6366f1',\n actionPrimaryBgHover: '#4f46e5',\n statusSuccessBg: '#22c55e',\n statusErrorText: '#ef4444',\n});\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ShareDialogProps {\n dashboardId: string;\n dashboardName: string;\n isOpen: boolean;\n onClose: () => void;\n}\n\ninterface ShareRecipient {\n id: string;\n name: string;\n email?: string;\n type: ShareRecipientType;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Permission options as per spec (03-graphql-contract.md)\n * Spec values: view, edit\n */\nconst PERMISSION_OPTIONS: { value: SharePermission; label: string; description: string }[] = [\n { value: 'VIEW', label: 'View', description: 'Can view the dashboard' },\n { value: 'EDIT', label: 'Edit', description: 'Can edit widgets, layout, and share' },\n];\n\n// Use shared semantic tokens for portal rendering\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function ShareDialog({ dashboardId, dashboardName, isOpen, onClose }: ShareDialogProps) {\n const { shares, loading, fetchShares, shareWithUser, shareWithGroup, updateShare, revokeShare, revokeAllShares } =\n useDashboardSharing();\n const emitBigConsoleEvent = useBigConsoleAnalytics();\n\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedRecipient, setSelectedRecipient] = useState<ShareRecipient | null>(null);\n const [selectedPermission, setSelectedPermission] = useState<SharePermission>('VIEW');\n const [shareLink, setShareLink] = useState('');\n const [copySuccess, setCopySuccess] = useState(false);\n\n // Fetch shares when dialog opens\n useEffect(() => {\n if (isOpen && dashboardId) {\n fetchShares(dashboardId);\n // Generate share link\n setShareLink(`${window.location.origin}/dashboard/${dashboardId}?shared=true`);\n }\n }, [isOpen, dashboardId, fetchShares]);\n\n // Handle share - per spec: only USER and GROUP recipient types\n const handleShare = useCallback(async () => {\n if (!selectedRecipient) return;\n\n emitBigConsoleEvent('bigconsole.dashboard.share_clicked', {\n dashboardId,\n permission: selectedPermission,\n recipientType: selectedRecipient.type,\n });\n\n let share: DashboardShare | null = null;\n if (selectedRecipient.type === 'USER') {\n share = await shareWithUser(dashboardId, selectedRecipient.id, selectedPermission);\n } else if (selectedRecipient.type === 'GROUP') {\n share = await shareWithGroup(dashboardId, selectedRecipient.id, selectedPermission);\n }\n\n if (share) {\n emitBigConsoleEvent('bigconsole.dashboard.shared', {\n dashboardId,\n permission: selectedPermission,\n recipientType: selectedRecipient.type,\n });\n }\n\n setSelectedRecipient(null);\n setSearchQuery('');\n }, [dashboardId, emitBigConsoleEvent, selectedRecipient, selectedPermission, shareWithGroup, shareWithUser]);\n\n // Handle update permission\n const handleUpdatePermission = useCallback(\n async (shareId: string, newPermission: SharePermission) => {\n await updateShare({ id: shareId, permission: newPermission });\n },\n [updateShare]\n );\n\n // Handle revoke\n const handleRevoke = useCallback(\n async (shareId: string) => {\n if (window.confirm('Are you sure you want to revoke this access?')) {\n await revokeShare(shareId);\n }\n },\n [revokeShare]\n );\n\n // Handle revoke all\n const handleRevokeAll = useCallback(async () => {\n if (window.confirm('Are you sure you want to revoke all shared access?')) {\n await revokeAllShares(dashboardId);\n }\n }, [dashboardId, revokeAllShares]);\n\n // Copy link to clipboard\n const handleCopyLink = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(shareLink);\n setCopySuccess(true);\n setTimeout(() => setCopySuccess(false), 2000);\n } catch (err) {}\n }, [shareLink]);\n\n // Mock search results (in real app, this would come from an API)\n // Per spec: ShareRecipientType is 'user' or 'group' only\n const searchResults: ShareRecipient[] = searchQuery\n ? (\n [\n { id: 'user-1', name: 'John Doe', email: 'john@example.com', type: 'USER' as ShareRecipientType },\n { id: 'user-2', name: 'Jane Smith', email: 'jane@example.com', type: 'USER' as ShareRecipientType },\n { id: 'group-admin', name: 'Administrators', type: 'GROUP' as ShareRecipientType },\n { id: 'group-editor', name: 'Editors', type: 'GROUP' as ShareRecipientType },\n ] as ShareRecipient[]\n ).filter(\n (r) =>\n r.name.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.email?.toLowerCase().includes(searchQuery.toLowerCase())\n )\n : [];\n\n // Check if dark mode is enabled\n const isDarkMode = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');\n const colors = useMemo(() => getColors(isDarkMode), [isDarkMode]);\n\n if (!isOpen) return null;\n\n // Use portal to render at document.body level to avoid z-index/stacking context issues\n const dialogContent = (\n <div\n style={{\n position: 'fixed',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: 'rgba(0, 0, 0, 0.6)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 99999,\n isolation: 'isolate',\n }}\n onClick={onClose}\n >\n <div\n style={{\n width: '520px',\n maxHeight: '80vh',\n backgroundColor: colors.bgPrimary,\n borderRadius: '12px',\n boxShadow: '0 8px 32px rgba(0, 0, 0, 0.3)',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 100000,\n color: colors.textPrimary,\n }}\n onClick={(e) => e.stopPropagation()}\n >\n {/* Header */}\n <div\n style={{\n padding: '20px 24px',\n borderBottom: `1px solid ${colors.borderDefault}`,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n backgroundColor: colors.bgPrimary,\n }}\n >\n <div>\n <h3 style={{ margin: 0, fontSize: '18px', fontWeight: 600, color: colors.textPrimary }}>Share Dashboard</h3>\n <p style={{ margin: '4px 0 0', fontSize: '13px', color: colors.textSecondary }}>{dashboardName}</p>\n </div>\n <button\n onClick={onClose}\n style={{\n background: 'none',\n border: 'none',\n fontSize: '24px',\n cursor: 'pointer',\n color: colors.textSecondary,\n padding: '4px',\n lineHeight: 1,\n }}\n >\n ×\n </button>\n </div>\n\n {/* Content */}\n <div\n style={{\n padding: '24px',\n overflowY: 'auto',\n maxHeight: 'calc(80vh - 200px)',\n backgroundColor: colors.bgPrimary,\n }}\n >\n {/* Share Link Section */}\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n Share Link\n </label>\n <div style={{ display: 'flex', gap: '8px' }}>\n <input\n type=\"text\"\n value={shareLink}\n readOnly\n style={{\n flex: 1,\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgSecondary,\n color: colors.textPrimary,\n }}\n />\n <button\n onClick={handleCopyLink}\n style={{\n padding: '10px 16px',\n backgroundColor: copySuccess ? colors.statusSuccessBg : colors.actionPrimaryBg,\n color: 'white',\n border: 'none',\n borderRadius: '6px',\n cursor: 'pointer',\n fontSize: '13px',\n fontWeight: 500,\n minWidth: '80px',\n }}\n >\n {copySuccess ? 'Copied!' : 'Copy'}\n </button>\n </div>\n </div>\n\n {/* Add People Section */}\n <div style={{ marginBottom: '24px' }}>\n <label\n style={{\n display: 'block',\n marginBottom: '8px',\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n Add People\n </label>\n <div style={{ display: 'flex', gap: '8px', marginBottom: '8px' }}>\n <div style={{ flex: 1, position: 'relative' }}>\n <input\n type=\"text\"\n value={selectedRecipient ? selectedRecipient.name : searchQuery}\n onChange={(e) => {\n setSearchQuery(e.target.value);\n setSelectedRecipient(null);\n }}\n placeholder=\"Search by name or email...\"\n style={{\n width: '100%',\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n />\n {/* Search Results Dropdown */}\n {searchQuery && !selectedRecipient && searchResults.length > 0 && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n right: 0,\n marginTop: '4px',\n backgroundColor: colors.bgPrimary,\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n boxShadow: '0 8px 24px rgba(0,0,0,0.25)',\n zIndex: 100001,\n maxHeight: '200px',\n overflowY: 'auto',\n }}\n >\n {searchResults.map((result) => (\n <button\n key={result.id}\n onClick={() => setSelectedRecipient(result)}\n style={{\n display: 'block',\n width: '100%',\n padding: '10px 12px',\n textAlign: 'left',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: 'pointer',\n borderBottom: `1px solid ${colors.borderDefault}`,\n }}\n >\n <div style={{ fontSize: '13px', fontWeight: 500, color: colors.textPrimary }}>\n {result.name}\n </div>\n {result.email && (\n <div style={{ fontSize: '11px', color: colors.textSecondary }}>{result.email}</div>\n )}\n <span\n style={{\n fontSize: '10px',\n color: colors.textTertiary,\n textTransform: 'uppercase',\n }}\n >\n {result.type}\n </span>\n </button>\n ))}\n </div>\n )}\n </div>\n <select\n value={selectedPermission}\n onChange={(e) => setSelectedPermission(e.target.value as SharePermission)}\n style={{\n padding: '10px 12px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '6px',\n fontSize: '13px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n >\n {PERMISSION_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n <button\n onClick={handleShare}\n disabled={!selectedRecipient || loading}\n style={{\n padding: '10px 16px',\n backgroundColor: selectedRecipient ? colors.actionPrimaryBg : colors.bgTertiary,\n color: selectedRecipient ? 'white' : colors.textSecondary,\n border: 'none',\n borderRadius: '6px',\n cursor: selectedRecipient ? 'pointer' : 'not-allowed',\n fontSize: '13px',\n fontWeight: 500,\n }}\n >\n Share\n </button>\n </div>\n </div>\n\n {/* Current Shares */}\n <div>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: '12px',\n }}\n >\n <label\n style={{\n fontSize: '13px',\n fontWeight: 600,\n color: colors.textPrimary,\n }}\n >\n People with Access ({shares.length})\n </label>\n {shares.length > 0 && (\n <button\n onClick={handleRevokeAll}\n style={{\n padding: '4px 8px',\n backgroundColor: 'transparent',\n color: colors.statusErrorText,\n border: 'none',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n Revoke All\n </button>\n )}\n </div>\n\n {loading && shares.length === 0 ? (\n <p style={{ color: colors.textSecondary, fontSize: '13px' }}>Loading...</p>\n ) : shares.length === 0 ? (\n <p style={{ color: colors.textSecondary, fontSize: '13px' }}>No one has access to this dashboard yet.</p>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n {shares.map((share) => (\n <ShareItem\n key={share.id}\n share={share}\n onUpdatePermission={handleUpdatePermission}\n onRevoke={handleRevoke}\n colors={colors}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n\n // Render via portal to document.body to escape any stacking context issues\n return createPortal(dialogContent, document.body);\n}\n\n// ============================================================================\n// ShareItem Sub-component\n// ============================================================================\n\ninterface ShareItemProps {\n share: DashboardShare;\n onUpdatePermission: (shareId: string, permission: SharePermission) => void;\n onRevoke: (shareId: string) => void;\n colors: ReturnType<typeof getColors>;\n}\n\nfunction ShareItem({ share, onUpdatePermission, onRevoke, colors }: ShareItemProps) {\n return (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '10px 12px',\n backgroundColor: colors.bgSecondary,\n borderRadius: '6px',\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>\n <div\n style={{\n width: '36px',\n height: '36px',\n borderRadius: '50%',\n backgroundColor: colors.actionPrimaryBg,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'white',\n fontWeight: 600,\n fontSize: '14px',\n }}\n >\n {share.recipientType === 'USER' ? 'U' : 'R'}\n </div>\n <div>\n <div style={{ fontSize: '13px', fontWeight: 500, color: colors.textPrimary }}>{share.recipientId}</div>\n <div style={{ fontSize: '11px', color: colors.textSecondary }}>\n {share.recipientType} - Shared {new Date(share.createdAt).toLocaleDateString()}\n </div>\n </div>\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\n <select\n value={share.permission}\n onChange={(e) => onUpdatePermission(share.id, e.target.value as SharePermission)}\n style={{\n padding: '6px 10px',\n border: `1px solid ${colors.borderDefault}`,\n borderRadius: '4px',\n fontSize: '12px',\n backgroundColor: colors.bgPrimary,\n color: colors.textPrimary,\n }}\n >\n {PERMISSION_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n <button\n onClick={() => onRevoke(share.id)}\n style={{\n padding: '6px 10px',\n backgroundColor: 'transparent',\n color: colors.statusErrorText,\n border: `1px solid ${colors.statusErrorText}`,\n borderRadius: '4px',\n cursor: 'pointer',\n fontSize: '12px',\n }}\n >\n Revoke\n </button>\n </div>\n </div>\n );\n}\n\nexport default ShareDialog;\n"],"mappings":"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"}
@@ -1,20 +1,20 @@
1
1
  import { WIDGET_CATEGORY_LABELS as e, getWidgetCategories as t, getWidgetKey as n } from "../widgets/WidgetRegistry.js";
2
2
  import { memo as r, useCallback as i, useMemo as a, useState as o } from "react";
3
- import { Activity as s, BarChart3 as c, Calendar as l, ChevronDown as u, ChevronRight as d, Columns as f, ExternalLink as p, FileText as m, Filter as h, Gauge as g, GitBranch as _, Grid3x3 as v, GripVertical as y, Layers as b, LayoutDashboard as x, List as S, MapPin as C, Puzzle as w, Search as T, Table as E, TrendingUp as D, Type as O, X as k } from "lucide-react";
4
- import { Input as A } from "@burdenoff/fe-libs/ui";
5
- import { jsx as j, jsxs as M } from "react/jsx-runtime";
3
+ import { Activity as s, BarChart3 as c, Calendar as l, ChevronDown as u, ChevronRight as d, Columns as f, ExternalLink as p, FileText as m, Filter as h, Gauge as g, GitBranch as _, Grid3x3 as v, GripVertical as y, Layers as b, LayoutDashboard as x, List as S, MapPin as C, Puzzle as w, Search as T, Store as E, Table as D, TrendingUp as O, Type as k, X as A } from "lucide-react";
4
+ import { Input as j } from "@burdenoff/fe-libs/ui";
5
+ import { jsx as M, jsxs as N } from "react/jsx-runtime";
6
6
  //#region src/bigconsole/components/dashboard/WidgetPalette.tsx
7
- var N = {
8
- TrendingUp: D,
7
+ var P = {
8
+ TrendingUp: O,
9
9
  BarChart3: c,
10
10
  Filter: h,
11
- Table: E,
11
+ Table: D,
12
12
  Grid3x3: v,
13
13
  Gauge: g,
14
14
  Activity: s,
15
15
  List: S,
16
16
  FileText: m,
17
- Type: O,
17
+ Type: k,
18
18
  ExternalLink: p,
19
19
  MapPin: C,
20
20
  Calendar: l,
@@ -23,10 +23,10 @@ var N = {
23
23
  Puzzle: w,
24
24
  LayoutDashboard: x
25
25
  };
26
- function P(e) {
27
- return N[e] || w;
26
+ function F(e) {
27
+ return P[e] || w;
28
28
  }
29
- var F = {
29
+ var I = {
30
30
  container: {
31
31
  width: "300px",
32
32
  height: "100%",
@@ -265,9 +265,26 @@ var F = {
265
265
  color: "var(--color-text-muted)",
266
266
  margin: 0,
267
267
  textAlign: "center"
268
+ },
269
+ browseStoreButton: {
270
+ display: "flex",
271
+ alignItems: "center",
272
+ justifyContent: "center",
273
+ gap: "var(--space-iconGap)",
274
+ width: "100%",
275
+ padding: "var(--space-controlGap)",
276
+ marginBottom: "var(--space-controlGap)",
277
+ borderRadius: "var(--radius-button)",
278
+ border: "1px dashed var(--color-border)",
279
+ backgroundColor: "transparent",
280
+ color: "var(--color-text-secondary)",
281
+ fontSize: "var(--font-size-body-sm)",
282
+ fontWeight: "var(--font-weight-semibold)",
283
+ cursor: "pointer",
284
+ transition: "border-color 0.15s, color 0.15s"
268
285
  }
269
- }, I = r(function({ isOpen: r, onClose: s, onWidgetSelect: c, onDragStart: l, onDragEnd: f, installedWidgets: p = [], installedWidgetsLoading: m = !1, definitions: h }) {
270
- let [g, _] = o(""), [v, x] = o(new Set([
286
+ }, L = r(function({ isOpen: r, onClose: s, onWidgetSelect: c, onDragStart: l, onDragEnd: f, installedWidgets: m = [], installedWidgetsLoading: h = !1, definitions: g }) {
287
+ let [_, v] = o(""), [x, S] = o(new Set([
271
288
  "KPI",
272
289
  "Visualization",
273
290
  "Data",
@@ -275,14 +292,14 @@ var F = {
275
292
  "Temporal",
276
293
  "Custom",
277
294
  "Installed"
278
- ])), [S, C] = o(null), w = a(() => (h ? Object.keys(e).map((t) => ({
295
+ ])), [C, w] = o(null), D = a(() => (g ? Object.keys(e).map((t) => ({
279
296
  category: t,
280
297
  label: e[t],
281
- widgets: h.filter((e) => e.category === t)
298
+ widgets: g.filter((e) => e.category === t)
282
299
  })) : t()).map((e) => {
283
300
  if (e.category === "Installed") {
284
301
  let t = /* @__PURE__ */ new Map();
285
- for (let e of p) t.set(e.name.toLowerCase(), e);
302
+ for (let e of m) t.set(e.name.toLowerCase(), e);
286
303
  for (let n of e.widgets) {
287
304
  let e = n.name.toLowerCase(), r = t.get(e);
288
305
  t.set(e, r ? {
@@ -299,19 +316,19 @@ var F = {
299
316
  };
300
317
  }
301
318
  return e;
302
- }).filter((e) => e.category !== "Installed" || e.widgets.length > 0), [p, h]), E = a(() => {
303
- if (!g.trim()) return w;
304
- let e = g.toLowerCase();
305
- return w.map((t) => ({
319
+ }).filter((e) => e.category !== "Installed" || e.widgets.length > 0), [m, g]), O = a(() => {
320
+ if (!_.trim()) return D;
321
+ let e = _.toLowerCase();
322
+ return D.map((t) => ({
306
323
  ...t,
307
324
  widgets: t.widgets.filter((t) => t.name.toLowerCase().includes(e) || t.description.toLowerCase().includes(e) || t.tags.some((t) => t.includes(e)))
308
325
  })).filter((e) => e.widgets.length > 0);
309
- }, [w, g]), D = i((e) => {
310
- x((t) => {
326
+ }, [D, _]), k = i((e) => {
327
+ S((t) => {
311
328
  let n = new Set(t);
312
329
  return n.has(e) ? n.delete(e) : n.add(e), n;
313
330
  });
314
- }, []), O = i((e, t) => {
331
+ }, []), P = i((e, t) => {
315
332
  e.dataTransfer.setData("application/json", JSON.stringify({
316
333
  type: t.type,
317
334
  name: t.name,
@@ -323,82 +340,86 @@ var F = {
323
340
  n.style.cssText = "\n position: absolute;\n top: -1000px;\n left: -1000px;\n padding: 8px 12px;\n background: var(--color-bg-surface);\n border: 2px solid var(--color-action-primary-bg);\n border-radius: 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--color-text-primary);\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n ", n.textContent = t.name, document.body.appendChild(n), e.dataTransfer.setDragImage(n, 0, 0), setTimeout(() => {
324
341
  document.body.removeChild(n);
325
342
  }, 0), l?.(t.type, t);
326
- }, [l]), N = i(() => {
343
+ }, [l]), L = i(() => {
327
344
  f?.();
328
- }, [f]), I = i((e) => {
345
+ }, [f]), R = i((e) => {
329
346
  c?.(e.type, e);
330
- }, [c]);
331
- return r ? /* @__PURE__ */ M("div", {
332
- style: F.container,
347
+ }, [c]), z = i(() => {
348
+ if (typeof window > "u") return;
349
+ let e = `${window.location.origin}/bigconsole/store${window.location.search}`;
350
+ window.open(e, "_blank", "noopener,noreferrer");
351
+ }, []);
352
+ return r ? /* @__PURE__ */ N("div", {
353
+ style: I.container,
333
354
  children: [
334
- /* @__PURE__ */ M("div", {
335
- style: F.header,
336
- children: [/* @__PURE__ */ M("div", {
337
- style: F.headerTop,
338
- children: [/* @__PURE__ */ M("div", {
339
- style: F.headerTitle,
340
- children: [/* @__PURE__ */ j("div", {
341
- style: F.headerIcon,
342
- children: /* @__PURE__ */ j(b, { style: {
355
+ /* @__PURE__ */ N("div", {
356
+ style: I.header,
357
+ children: [/* @__PURE__ */ N("div", {
358
+ style: I.headerTop,
359
+ children: [/* @__PURE__ */ N("div", {
360
+ style: I.headerTitle,
361
+ children: [/* @__PURE__ */ M("div", {
362
+ style: I.headerIcon,
363
+ children: /* @__PURE__ */ M(b, { style: {
343
364
  width: "18px",
344
365
  height: "18px",
345
366
  color: "var(--color-action-primary-text)"
346
367
  } })
347
- }), /* @__PURE__ */ M("div", { children: [/* @__PURE__ */ j("h3", {
348
- style: F.title,
368
+ }), /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("h3", {
369
+ style: I.title,
349
370
  children: "Widgets"
350
- }), /* @__PURE__ */ j("p", {
351
- style: F.subtitle,
371
+ }), /* @__PURE__ */ M("p", {
372
+ style: I.subtitle,
352
373
  children: "Drag or click to add"
353
374
  })] })]
354
- }), /* @__PURE__ */ j("button", {
375
+ }), /* @__PURE__ */ M("button", {
355
376
  type: "button",
356
377
  onClick: s,
357
- style: F.closeButton,
378
+ style: I.closeButton,
358
379
  onMouseOver: (e) => e.currentTarget.style.backgroundColor = "var(--color-bg-hover)",
359
380
  onMouseOut: (e) => e.currentTarget.style.backgroundColor = "transparent",
360
- children: /* @__PURE__ */ j(k, { style: {
381
+ children: /* @__PURE__ */ M(A, { style: {
361
382
  width: "16px",
362
383
  height: "16px"
363
384
  } })
364
385
  })]
365
- }), /* @__PURE__ */ M("div", {
366
- style: F.searchContainer,
367
- children: [/* @__PURE__ */ j(T, { style: F.searchIcon }), /* @__PURE__ */ j(A, {
386
+ }), /* @__PURE__ */ N("div", {
387
+ style: I.searchContainer,
388
+ children: [/* @__PURE__ */ M(T, { style: I.searchIcon }), /* @__PURE__ */ M(j, {
368
389
  type: "text",
369
390
  placeholder: "Search widgets...",
370
- value: g,
371
- onChange: (e) => _(e.target.value),
372
- style: F.searchInput
391
+ value: _,
392
+ onChange: (e) => v(e.target.value),
393
+ style: I.searchInput
373
394
  })]
374
395
  })]
375
396
  }),
376
- /* @__PURE__ */ j("div", {
377
- style: F.content,
378
- children: /* @__PURE__ */ M("div", {
379
- style: F.scrollArea,
380
- children: [E.map((e) => /* @__PURE__ */ M("div", {
381
- style: F.categoryContainer,
382
- children: [/* @__PURE__ */ M("button", {
397
+ /* @__PURE__ */ M("div", {
398
+ style: I.content,
399
+ children: /* @__PURE__ */ N("div", {
400
+ style: I.scrollArea,
401
+ children: [O.map((e) => /* @__PURE__ */ N("div", {
402
+ style: I.categoryContainer,
403
+ children: [/* @__PURE__ */ N("button", {
383
404
  type: "button",
384
- onClick: () => D(e.category),
385
- style: F.categoryHeader,
405
+ onClick: () => k(e.category),
406
+ style: I.categoryHeader,
386
407
  onMouseOver: (e) => e.currentTarget.style.backgroundColor = "var(--color-bg-hover)",
387
408
  onMouseOut: (e) => e.currentTarget.style.backgroundColor = "transparent",
388
409
  children: [
389
- v.has(e.category) ? /* @__PURE__ */ j(u, { style: F.categoryChevron }) : /* @__PURE__ */ j(d, { style: F.categoryChevron }),
390
- /* @__PURE__ */ j("span", {
391
- style: F.categoryLabel,
410
+ x.has(e.category) ? /* @__PURE__ */ M(u, { style: I.categoryChevron }) : /* @__PURE__ */ M(d, { style: I.categoryChevron }),
411
+ /* @__PURE__ */ M("span", {
412
+ style: I.categoryLabel,
392
413
  children: e.label
393
414
  }),
394
- /* @__PURE__ */ j("span", {
395
- style: F.categoryCount,
415
+ /* @__PURE__ */ M("span", {
416
+ style: I.categoryCount,
396
417
  children: e.widgets.length
397
418
  })
398
419
  ]
399
- }), v.has(e.category) && /* @__PURE__ */ M("div", {
400
- style: F.widgetList,
401
- children: [m && e.category === "Installed" && /* @__PURE__ */ j("div", {
420
+ }), x.has(e.category) && /* @__PURE__ */ N("div", {
421
+ style: I.widgetList,
422
+ children: [h && e.category === "Installed" && /* @__PURE__ */ M("div", {
402
423
  style: {
403
424
  fontSize: "var(--font-size-body-xs)",
404
425
  color: "var(--color-text-muted)",
@@ -406,31 +427,31 @@ var F = {
406
427
  },
407
428
  children: "Loading..."
408
429
  }), e.widgets.map((e) => {
409
- let t = P(e.icon), r = n(e), i = S === r;
410
- return /* @__PURE__ */ M("div", {
430
+ let t = F(e.icon), r = n(e), i = C === r;
431
+ return /* @__PURE__ */ N("div", {
411
432
  draggable: !0,
412
- onDragStart: (t) => O(t, e),
413
- onDragEnd: N,
414
- onClick: () => I(e),
415
- onMouseEnter: () => C(r),
416
- onMouseLeave: () => C(null),
433
+ onDragStart: (t) => P(t, e),
434
+ onDragEnd: L,
435
+ onClick: () => R(e),
436
+ onMouseEnter: () => w(r),
437
+ onMouseLeave: () => w(null),
417
438
  style: {
418
- ...F.widgetCard,
419
- ...i ? F.widgetCardHover : {}
439
+ ...I.widgetCard,
440
+ ...i ? I.widgetCardHover : {}
420
441
  },
421
442
  children: [
422
- /* @__PURE__ */ j(y, { style: F.dragHandle }),
423
- /* @__PURE__ */ j("div", {
424
- style: F.widgetIcon,
425
- children: /* @__PURE__ */ j(t, { style: F.widgetIconInner })
426
- }),
443
+ /* @__PURE__ */ M(y, { style: I.dragHandle }),
427
444
  /* @__PURE__ */ M("div", {
428
- style: F.widgetText,
429
- children: [/* @__PURE__ */ j("div", {
430
- style: F.widgetName,
445
+ style: I.widgetIcon,
446
+ children: /* @__PURE__ */ M(t, { style: I.widgetIconInner })
447
+ }),
448
+ /* @__PURE__ */ N("div", {
449
+ style: I.widgetText,
450
+ children: [/* @__PURE__ */ M("div", {
451
+ style: I.widgetName,
431
452
  children: e.name
432
- }), /* @__PURE__ */ j("div", {
433
- style: F.widgetDescription,
453
+ }), /* @__PURE__ */ M("div", {
454
+ style: I.widgetDescription,
434
455
  children: e.description
435
456
  })]
436
457
  })
@@ -438,46 +459,68 @@ var F = {
438
459
  }, r);
439
460
  })]
440
461
  })]
441
- }, e.category)), E.length === 0 && /* @__PURE__ */ M("div", {
442
- style: F.emptyState,
462
+ }, e.category)), O.length === 0 && /* @__PURE__ */ N("div", {
463
+ style: I.emptyState,
443
464
  children: [
444
- /* @__PURE__ */ j("div", {
445
- style: F.emptyIcon,
446
- children: /* @__PURE__ */ j(T, { style: {
465
+ /* @__PURE__ */ M("div", {
466
+ style: I.emptyIcon,
467
+ children: /* @__PURE__ */ M(T, { style: {
447
468
  width: "24px",
448
469
  height: "24px",
449
470
  color: "var(--color-text-muted)"
450
471
  } })
451
472
  }),
452
- /* @__PURE__ */ M("p", {
453
- style: F.emptyText,
473
+ /* @__PURE__ */ N("p", {
474
+ style: I.emptyText,
454
475
  children: [
455
476
  "No widgets found for \"",
456
- /* @__PURE__ */ j("strong", { children: g }),
477
+ /* @__PURE__ */ M("strong", { children: _ }),
457
478
  "\""
458
479
  ]
459
480
  }),
460
- /* @__PURE__ */ j("button", {
481
+ /* @__PURE__ */ M("button", {
461
482
  type: "button",
462
- onClick: () => _(""),
463
- style: F.clearButton,
483
+ onClick: () => v(""),
484
+ style: I.clearButton,
464
485
  children: "Clear search"
465
486
  })
466
487
  ]
467
488
  })]
468
489
  })
469
490
  }),
470
- /* @__PURE__ */ j("div", {
471
- style: F.footer,
472
- children: /* @__PURE__ */ j("p", {
473
- style: F.footerText,
491
+ /* @__PURE__ */ N("div", {
492
+ style: I.footer,
493
+ children: [/* @__PURE__ */ N("button", {
494
+ type: "button",
495
+ onClick: z,
496
+ style: I.browseStoreButton,
497
+ onMouseOver: (e) => {
498
+ e.currentTarget.style.borderColor = "var(--color-action-primary-bg)", e.currentTarget.style.color = "var(--color-action-primary-text)";
499
+ },
500
+ onMouseOut: (e) => {
501
+ e.currentTarget.style.borderColor = "var(--color-border)", e.currentTarget.style.color = "var(--color-text-secondary)";
502
+ },
503
+ children: [
504
+ /* @__PURE__ */ M(E, { style: {
505
+ width: "15px",
506
+ height: "15px"
507
+ } }),
508
+ "Browse widget store",
509
+ /* @__PURE__ */ M(p, { style: {
510
+ width: "13px",
511
+ height: "13px",
512
+ opacity: .7
513
+ } })
514
+ ]
515
+ }), /* @__PURE__ */ M("p", {
516
+ style: I.footerText,
474
517
  children: "Drag widgets to position them on the canvas"
475
- })
518
+ })]
476
519
  })
477
520
  ]
478
521
  }) : null;
479
522
  });
480
523
  //#endregion
481
- export { I as default };
524
+ export { L as default };
482
525
 
483
526
  //# sourceMappingURL=WidgetPalette.js.map