@burdenoff/microfe-bigconsole 2026.710.3 → 2026.711.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.
@@ -279,10 +279,18 @@ var F = {
279
279
  category: t,
280
280
  label: e[t],
281
281
  widgets: h.filter((e) => e.category === t)
282
- })) : t()).map((e) => e.category === "Installed" ? {
283
- ...e,
284
- widgets: p
285
- } : e).filter((e) => e.category !== "Installed" || e.widgets.length > 0), [p, h]), E = a(() => {
282
+ })) : t()).map((e) => {
283
+ if (e.category === "Installed") {
284
+ let t = /* @__PURE__ */ new Map();
285
+ for (let e of p) t.set(e.name.toLowerCase(), e);
286
+ for (let n of e.widgets) t.set(n.name.toLowerCase(), n);
287
+ return {
288
+ ...e,
289
+ widgets: Array.from(t.values())
290
+ };
291
+ }
292
+ return e;
293
+ }).filter((e) => e.category !== "Installed" || e.widgets.length > 0), [p, h]), E = a(() => {
286
294
  if (!g.trim()) return w;
287
295
  let e = g.toLowerCase();
288
296
  return w.map((t) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetPalette.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/WidgetPalette.tsx"],"sourcesContent":["/**\n * WidgetPalette Component\n *\n * Sidebar panel with draggable widget types for the dashboard builder.\n * Uses semantic tokens for consistent theming.\n * Features categorized widgets, search, and drag-and-drop support.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport {\n Search,\n ChevronDown,\n ChevronRight,\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n GripVertical,\n X,\n Layers,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n getWidgetCategories,\n getWidgetKey,\n WIDGET_CATEGORY_LABELS,\n type WidgetDefinition,\n} from '../widgets/WidgetRegistry';\nimport type { WidgetType, WidgetCategory } from '../../types';\n\n// ============================================================================\n// Icon Mapping\n// ============================================================================\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n};\n\nfunction getIconComponent(iconName: string): LucideIcon {\n return ICON_MAP[iconName] || Puzzle;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetPaletteProps {\n /** Whether the palette is open */\n isOpen: boolean;\n /** Callback to close the palette */\n onClose: () => void;\n /** Callback when a widget is selected (for quick add without drag) */\n onWidgetSelect?: (type: WidgetType, definition?: WidgetDefinition) => void;\n /** Callback when drag starts */\n onDragStart?: (type: WidgetType, definition: WidgetDefinition) => void;\n /** Callback when drag ends */\n onDragEnd?: () => void;\n /** Installed widgets from the store (fetched by parent) */\n installedWidgets?: WidgetDefinition[];\n /** Whether installed widgets are still loading */\n installedWidgetsLoading?: boolean;\n /**\n * Built-in widget catalog (from the backend `getWidgetTypes`, fetched by the\n * parent via useWidgetCatalog). When omitted, falls back to the bundled\n * static registry.\n */\n definitions?: WidgetDefinition[];\n}\n\n// ============================================================================\n// Styles using semantic tokens\n// ============================================================================\n\nconst styles = {\n container: {\n width: '300px',\n height: '100%',\n backgroundColor: 'var(--color-bg-surface)',\n borderRight: '1px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column' as const,\n flexShrink: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n header: {\n padding: 'var(--space-formGap)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n headerTop: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n },\n headerTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n },\n headerIcon: {\n width: '32px',\n height: '32px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n title: {\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-primary)',\n margin: 0,\n },\n subtitle: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: '2px 0 0 0',\n },\n closeButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n border: 'none',\n background: 'transparent',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n color: 'var(--color-text-secondary)',\n transition: 'background-color 0.15s',\n },\n searchContainer: {\n position: 'relative' as const,\n },\n searchIcon: {\n position: 'absolute' as const,\n left: '10px',\n top: '50%',\n transform: 'translateY(-50%)',\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n pointerEvents: 'none' as const,\n },\n searchInput: {\n width: '100%',\n paddingLeft: '36px',\n height: 'var(--size-controlHeight-sm)',\n fontSize: 'var(--font-size-body-sm)',\n },\n content: {\n flex: '1 1 0',\n minHeight: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n scrollArea: {\n position: 'absolute' as const,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflowY: 'auto' as const,\n overflowX: 'hidden' as const,\n padding: 'var(--space-controlGap)',\n },\n categoryContainer: {\n marginBottom: 'var(--space-controlGap)',\n },\n categoryHeader: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-iconGap)',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: 'var(--radius-button)',\n transition: 'background-color 0.15s',\n },\n categoryChevron: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n flexShrink: 0,\n },\n categoryLabel: {\n flex: 1,\n textAlign: 'left' as const,\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-secondary)',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n categoryCount: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n backgroundColor: 'var(--color-bg-sunken)',\n padding: '2px 8px',\n borderRadius: 'var(--radius-full)',\n },\n widgetList: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '4px',\n marginTop: 'var(--space-controlGap)',\n paddingLeft: '4px',\n },\n widgetCard: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-card)',\n cursor: 'grab',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border)',\n transition: 'all 0.15s ease',\n },\n widgetCardHover: {\n backgroundColor: 'var(--color-bg-hover)',\n borderColor: 'var(--color-action-primary-border)',\n boxShadow: 'var(--shadow-elevation-1)',\n },\n dragHandle: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n opacity: 0.5,\n flexShrink: 0,\n },\n widgetIcon: {\n width: '36px',\n height: '36px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n widgetIconInner: {\n width: '18px',\n height: '18px',\n color: 'var(--color-action-primary-bg)',\n },\n widgetText: {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n },\n widgetName: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-text-primary)',\n whiteSpace: 'nowrap' as const,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n marginBottom: '2px',\n },\n widgetDescription: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n lineHeight: 1.3,\n overflow: 'hidden',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical' as const,\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: 'var(--space-pagePadding)',\n },\n emptyIcon: {\n width: '48px',\n height: '48px',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto var(--space-formGap)',\n },\n emptyText: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n margin: 0,\n },\n clearButton: {\n marginTop: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-action-primary-text)',\n backgroundColor: 'var(--color-action-primary-bg)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n },\n footer: {\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n footerText: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: 0,\n textAlign: 'center' as const,\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetPalette: FC<WidgetPaletteProps> = memo(function WidgetPalette({\n isOpen,\n onClose,\n onWidgetSelect,\n onDragStart,\n onDragEnd,\n installedWidgets = [],\n installedWidgetsLoading = false,\n definitions,\n}) {\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedCategories, setExpandedCategories] = useState<Set<WidgetCategory>>(\n new Set(['KPI', 'Visualization', 'Data', 'Content', 'Temporal', 'Custom', 'Installed'])\n );\n const [hoveredWidget, setHoveredWidget] = useState<string | null>(null);\n\n // Get categorized widgets, merging in installed widgets. When the parent\n // supplies a backend-sourced catalog (`definitions`), group that by category;\n // otherwise fall back to the bundled static registry.\n const categories = useMemo(() => {\n const baseCategories = definitions\n ? (Object.keys(WIDGET_CATEGORY_LABELS) as WidgetCategory[]).map((category) => ({\n category,\n label: WIDGET_CATEGORY_LABELS[category],\n widgets: definitions.filter((def) => def.category === category),\n }))\n : getWidgetCategories();\n\n return baseCategories\n .map((cat) => {\n if (cat.category === 'Installed') {\n return { ...cat, widgets: installedWidgets };\n }\n return cat;\n })\n .filter((cat) => cat.category !== 'Installed' || cat.widgets.length > 0);\n }, [installedWidgets, definitions]);\n\n // Filter widgets by search query\n const filteredCategories = useMemo(() => {\n if (!searchQuery.trim()) {\n return categories;\n }\n\n const query = searchQuery.toLowerCase();\n return categories\n .map((cat) => ({\n ...cat,\n widgets: cat.widgets.filter(\n (w) =>\n w.name.toLowerCase().includes(query) ||\n w.description.toLowerCase().includes(query) ||\n w.tags.some((tag) => tag.includes(query))\n ),\n }))\n .filter((cat) => cat.widgets.length > 0);\n }, [categories, searchQuery]);\n\n // Toggle category expansion\n const toggleCategory = useCallback((category: WidgetCategory) => {\n setExpandedCategories((prev) => {\n const next = new Set(prev);\n if (next.has(category)) {\n next.delete(category);\n } else {\n next.add(category);\n }\n return next;\n });\n }, []);\n\n // Handle drag start\n const handleDragStart = useCallback(\n (e: React.DragEvent, widget: WidgetDefinition) => {\n e.dataTransfer.setData(\n 'application/json',\n JSON.stringify({\n type: widget.type,\n name: widget.name,\n defaultSize: widget.defaultSize,\n defaultConfig: widget.defaultConfig,\n category: widget.category,\n })\n );\n e.dataTransfer.effectAllowed = 'copy';\n\n // Create custom drag image\n const dragImage = document.createElement('div');\n dragImage.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 dragImage.textContent = widget.name;\n document.body.appendChild(dragImage);\n e.dataTransfer.setDragImage(dragImage, 0, 0);\n\n setTimeout(() => {\n document.body.removeChild(dragImage);\n }, 0);\n\n onDragStart?.(widget.type, widget);\n },\n [onDragStart]\n );\n\n // Handle drag end\n const handleDragEnd = useCallback(() => {\n onDragEnd?.();\n }, [onDragEnd]);\n\n // Handle click to quick-add\n const handleWidgetClick = useCallback(\n (widget: WidgetDefinition) => {\n onWidgetSelect?.(widget.type, widget);\n },\n [onWidgetSelect]\n );\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.headerTitle}>\n <div style={styles.headerIcon}>\n <Layers style={{ width: '18px', height: '18px', color: 'var(--color-action-primary-text)' }} />\n </div>\n <div>\n <h3 style={styles.title}>Widgets</h3>\n <p style={styles.subtitle}>Drag or click to add</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n style={styles.closeButton}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n <X style={{ width: '16px', height: '16px' }} />\n </button>\n </div>\n\n {/* Search */}\n <div style={styles.searchContainer}>\n <Search style={styles.searchIcon} />\n <Input\n type=\"text\"\n placeholder=\"Search widgets...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={styles.searchInput}\n />\n </div>\n </div>\n\n {/* Widget Categories */}\n <div style={styles.content}>\n <div style={styles.scrollArea}>\n {filteredCategories.map((category) => (\n <div key={category.category} style={styles.categoryContainer}>\n {/* Category Header */}\n <button\n type=\"button\"\n onClick={() => toggleCategory(category.category)}\n style={styles.categoryHeader}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {expandedCategories.has(category.category) ? (\n <ChevronDown style={styles.categoryChevron} />\n ) : (\n <ChevronRight style={styles.categoryChevron} />\n )}\n <span style={styles.categoryLabel}>{category.label}</span>\n <span style={styles.categoryCount}>{category.widgets.length}</span>\n </button>\n\n {/* Widget Items */}\n {expandedCategories.has(category.category) && (\n <div style={styles.widgetList}>\n {installedWidgetsLoading && category.category === 'Installed' && (\n <div\n style={{\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n padding: 'var(--space-controlGap)',\n }}\n >\n Loading...\n </div>\n )}\n {category.widgets.map((widget) => {\n const IconComponent = getIconComponent(widget.icon);\n const widgetKey = getWidgetKey(widget);\n const isHovered = hoveredWidget === widgetKey;\n\n return (\n <div\n key={widgetKey}\n draggable\n onDragStart={(e) => handleDragStart(e, widget)}\n onDragEnd={handleDragEnd}\n onClick={() => handleWidgetClick(widget)}\n onMouseEnter={() => setHoveredWidget(widgetKey)}\n onMouseLeave={() => setHoveredWidget(null)}\n style={{\n ...styles.widgetCard,\n ...(isHovered ? styles.widgetCardHover : {}),\n }}\n >\n {/* Drag Handle */}\n <GripVertical style={styles.dragHandle} />\n\n {/* Icon */}\n <div style={styles.widgetIcon}>\n <IconComponent style={styles.widgetIconInner} />\n </div>\n\n {/* Text */}\n <div style={styles.widgetText}>\n <div style={styles.widgetName}>{widget.name}</div>\n <div style={styles.widgetDescription}>{widget.description}</div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n ))}\n\n {filteredCategories.length === 0 && (\n <div style={styles.emptyState}>\n <div style={styles.emptyIcon}>\n <Search style={{ width: '24px', height: '24px', color: 'var(--color-text-muted)' }} />\n </div>\n <p style={styles.emptyText}>\n No widgets found for \"<strong>{searchQuery}</strong>\"\n </p>\n <button type=\"button\" onClick={() => setSearchQuery('')} style={styles.clearButton}>\n Clear search\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <div style={styles.footer}>\n <p style={styles.footerText}>Drag widgets to position them on the canvas</p>\n </div>\n </div>\n );\n});\n\nexport default WidgetPalette;\n"],"mappings":"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"}
1
+ {"version":3,"file":"WidgetPalette.js","names":[],"sources":["../../../../src/bigconsole/components/dashboard/WidgetPalette.tsx"],"sourcesContent":["/**\n * WidgetPalette Component\n *\n * Sidebar panel with draggable widget types for the dashboard builder.\n * Uses semantic tokens for consistent theming.\n * Features categorized widgets, search, and drag-and-drop support.\n */\n\nimport { type FC, memo, useState, useCallback, useMemo } from 'react';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport {\n Search,\n ChevronDown,\n ChevronRight,\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n GripVertical,\n X,\n Layers,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n getWidgetCategories,\n getWidgetKey,\n WIDGET_CATEGORY_LABELS,\n type WidgetDefinition,\n} from '../widgets/WidgetRegistry';\nimport type { WidgetType, WidgetCategory } from '../../types';\n\n// ============================================================================\n// Icon Mapping\n// ============================================================================\n\nconst ICON_MAP: Record<string, LucideIcon> = {\n TrendingUp,\n BarChart3,\n Filter,\n Table,\n Grid3x3,\n Gauge,\n Activity,\n List,\n FileText,\n Type,\n ExternalLink,\n MapPin,\n Calendar,\n Columns,\n GitBranch,\n Puzzle,\n LayoutDashboard,\n};\n\nfunction getIconComponent(iconName: string): LucideIcon {\n return ICON_MAP[iconName] || Puzzle;\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetPaletteProps {\n /** Whether the palette is open */\n isOpen: boolean;\n /** Callback to close the palette */\n onClose: () => void;\n /** Callback when a widget is selected (for quick add without drag) */\n onWidgetSelect?: (type: WidgetType, definition?: WidgetDefinition) => void;\n /** Callback when drag starts */\n onDragStart?: (type: WidgetType, definition: WidgetDefinition) => void;\n /** Callback when drag ends */\n onDragEnd?: () => void;\n /** Installed widgets from the store (fetched by parent) */\n installedWidgets?: WidgetDefinition[];\n /** Whether installed widgets are still loading */\n installedWidgetsLoading?: boolean;\n /**\n * Built-in widget catalog (from the backend `getWidgetTypes`, fetched by the\n * parent via useWidgetCatalog). When omitted, falls back to the bundled\n * static registry.\n */\n definitions?: WidgetDefinition[];\n}\n\n// ============================================================================\n// Styles using semantic tokens\n// ============================================================================\n\nconst styles = {\n container: {\n width: '300px',\n height: '100%',\n backgroundColor: 'var(--color-bg-surface)',\n borderRight: '1px solid var(--color-border)',\n display: 'flex',\n flexDirection: 'column' as const,\n flexShrink: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n header: {\n padding: 'var(--space-formGap)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n headerTop: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n },\n headerTitle: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n },\n headerIcon: {\n width: '32px',\n height: '32px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-action-primary-bg)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n },\n title: {\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-primary)',\n margin: 0,\n },\n subtitle: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: '2px 0 0 0',\n },\n closeButton: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '28px',\n height: '28px',\n border: 'none',\n background: 'transparent',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n color: 'var(--color-text-secondary)',\n transition: 'background-color 0.15s',\n },\n searchContainer: {\n position: 'relative' as const,\n },\n searchIcon: {\n position: 'absolute' as const,\n left: '10px',\n top: '50%',\n transform: 'translateY(-50%)',\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n pointerEvents: 'none' as const,\n },\n searchInput: {\n width: '100%',\n paddingLeft: '36px',\n height: 'var(--size-controlHeight-sm)',\n fontSize: 'var(--font-size-body-sm)',\n },\n content: {\n flex: '1 1 0',\n minHeight: 0,\n overflow: 'hidden',\n position: 'relative' as const,\n },\n scrollArea: {\n position: 'absolute' as const,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n overflowY: 'auto' as const,\n overflowX: 'hidden' as const,\n padding: 'var(--space-controlGap)',\n },\n categoryContainer: {\n marginBottom: 'var(--space-controlGap)',\n },\n categoryHeader: {\n width: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap) var(--space-iconGap)',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: 'var(--radius-button)',\n transition: 'background-color 0.15s',\n },\n categoryChevron: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n flexShrink: 0,\n },\n categoryLabel: {\n flex: 1,\n textAlign: 'left' as const,\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-semibold)' as const,\n color: 'var(--color-text-secondary)',\n textTransform: 'uppercase' as const,\n letterSpacing: '0.05em',\n },\n categoryCount: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n backgroundColor: 'var(--color-bg-sunken)',\n padding: '2px 8px',\n borderRadius: 'var(--radius-full)',\n },\n widgetList: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '4px',\n marginTop: 'var(--space-controlGap)',\n paddingLeft: '4px',\n },\n widgetCard: {\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-card)',\n cursor: 'grab',\n backgroundColor: 'var(--color-bg-surface)',\n border: '1px solid var(--color-border)',\n transition: 'all 0.15s ease',\n },\n widgetCardHover: {\n backgroundColor: 'var(--color-bg-hover)',\n borderColor: 'var(--color-action-primary-border)',\n boxShadow: 'var(--shadow-elevation-1)',\n },\n dragHandle: {\n width: '16px',\n height: '16px',\n color: 'var(--color-text-muted)',\n opacity: 0.5,\n flexShrink: 0,\n },\n widgetIcon: {\n width: '36px',\n height: '36px',\n borderRadius: 'var(--radius-button)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n widgetIconInner: {\n width: '18px',\n height: '18px',\n color: 'var(--color-action-primary-bg)',\n },\n widgetText: {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n },\n widgetName: {\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-text-primary)',\n whiteSpace: 'nowrap' as const,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n marginBottom: '2px',\n },\n widgetDescription: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n lineHeight: 1.3,\n overflow: 'hidden',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical' as const,\n },\n emptyState: {\n textAlign: 'center' as const,\n padding: 'var(--space-pagePadding)',\n },\n emptyIcon: {\n width: '48px',\n height: '48px',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-bg-sunken)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n margin: '0 auto var(--space-formGap)',\n },\n emptyText: {\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n margin: 0,\n },\n clearButton: {\n marginTop: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap) var(--space-formGap)',\n fontSize: 'var(--font-size-body-xs)',\n fontWeight: 'var(--font-weight-medium)' as const,\n color: 'var(--color-action-primary-text)',\n backgroundColor: 'var(--color-action-primary-bg)',\n border: 'none',\n borderRadius: 'var(--radius-button)',\n cursor: 'pointer',\n },\n footer: {\n padding: 'var(--space-controlGap) var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n },\n footerText: {\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n margin: 0,\n textAlign: 'center' as const,\n },\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetPalette: FC<WidgetPaletteProps> = memo(function WidgetPalette({\n isOpen,\n onClose,\n onWidgetSelect,\n onDragStart,\n onDragEnd,\n installedWidgets = [],\n installedWidgetsLoading = false,\n definitions,\n}) {\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedCategories, setExpandedCategories] = useState<Set<WidgetCategory>>(\n new Set(['KPI', 'Visualization', 'Data', 'Content', 'Temporal', 'Custom', 'Installed'])\n );\n const [hoveredWidget, setHoveredWidget] = useState<string | null>(null);\n\n // Get categorized widgets, merging in installed widgets. When the parent\n // supplies a backend-sourced catalog (`definitions`), group that by category;\n // otherwise fall back to the bundled static registry.\n const categories = useMemo(() => {\n const baseCategories = definitions\n ? (Object.keys(WIDGET_CATEGORY_LABELS) as WidgetCategory[]).map((category) => ({\n category,\n label: WIDGET_CATEGORY_LABELS[category],\n widgets: definitions.filter((def) => def.category === category),\n }))\n : getWidgetCategories();\n\n return baseCategories\n .map((cat) => {\n if (cat.category === 'Installed') {\n // Two sources feed \"Installed from Store\": the registry-driven backend\n // catalog (getWidgetTypes store types — rich metadata, install-gated,\n // BOFF-2858) which arrives via `definitions` under this category, and\n // the legacy workspaceInstalledApps listing passed as `installedWidgets`.\n // Merge both, deduping by name (the catalog entry wins) so a widget\n // present in both sources shows once with the richer definition, while\n // legacy installs not yet in the registry are still preserved.\n const byName = new Map<string, WidgetDefinition>();\n for (const w of installedWidgets) byName.set(w.name.toLowerCase(), w);\n for (const w of cat.widgets) byName.set(w.name.toLowerCase(), w);\n return { ...cat, widgets: Array.from(byName.values()) };\n }\n return cat;\n })\n .filter((cat) => cat.category !== 'Installed' || cat.widgets.length > 0);\n }, [installedWidgets, definitions]);\n\n // Filter widgets by search query\n const filteredCategories = useMemo(() => {\n if (!searchQuery.trim()) {\n return categories;\n }\n\n const query = searchQuery.toLowerCase();\n return categories\n .map((cat) => ({\n ...cat,\n widgets: cat.widgets.filter(\n (w) =>\n w.name.toLowerCase().includes(query) ||\n w.description.toLowerCase().includes(query) ||\n w.tags.some((tag) => tag.includes(query))\n ),\n }))\n .filter((cat) => cat.widgets.length > 0);\n }, [categories, searchQuery]);\n\n // Toggle category expansion\n const toggleCategory = useCallback((category: WidgetCategory) => {\n setExpandedCategories((prev) => {\n const next = new Set(prev);\n if (next.has(category)) {\n next.delete(category);\n } else {\n next.add(category);\n }\n return next;\n });\n }, []);\n\n // Handle drag start\n const handleDragStart = useCallback(\n (e: React.DragEvent, widget: WidgetDefinition) => {\n e.dataTransfer.setData(\n 'application/json',\n JSON.stringify({\n type: widget.type,\n name: widget.name,\n defaultSize: widget.defaultSize,\n defaultConfig: widget.defaultConfig,\n category: widget.category,\n })\n );\n e.dataTransfer.effectAllowed = 'copy';\n\n // Create custom drag image\n const dragImage = document.createElement('div');\n dragImage.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 dragImage.textContent = widget.name;\n document.body.appendChild(dragImage);\n e.dataTransfer.setDragImage(dragImage, 0, 0);\n\n setTimeout(() => {\n document.body.removeChild(dragImage);\n }, 0);\n\n onDragStart?.(widget.type, widget);\n },\n [onDragStart]\n );\n\n // Handle drag end\n const handleDragEnd = useCallback(() => {\n onDragEnd?.();\n }, [onDragEnd]);\n\n // Handle click to quick-add\n const handleWidgetClick = useCallback(\n (widget: WidgetDefinition) => {\n onWidgetSelect?.(widget.type, widget);\n },\n [onWidgetSelect]\n );\n\n if (!isOpen) {\n return null;\n }\n\n return (\n <div style={styles.container}>\n {/* Header */}\n <div style={styles.header}>\n <div style={styles.headerTop}>\n <div style={styles.headerTitle}>\n <div style={styles.headerIcon}>\n <Layers style={{ width: '18px', height: '18px', color: 'var(--color-action-primary-text)' }} />\n </div>\n <div>\n <h3 style={styles.title}>Widgets</h3>\n <p style={styles.subtitle}>Drag or click to add</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n style={styles.closeButton}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n <X style={{ width: '16px', height: '16px' }} />\n </button>\n </div>\n\n {/* Search */}\n <div style={styles.searchContainer}>\n <Search style={styles.searchIcon} />\n <Input\n type=\"text\"\n placeholder=\"Search widgets...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n style={styles.searchInput}\n />\n </div>\n </div>\n\n {/* Widget Categories */}\n <div style={styles.content}>\n <div style={styles.scrollArea}>\n {filteredCategories.map((category) => (\n <div key={category.category} style={styles.categoryContainer}>\n {/* Category Header */}\n <button\n type=\"button\"\n onClick={() => toggleCategory(category.category)}\n style={styles.categoryHeader}\n onMouseOver={(e) => (e.currentTarget.style.backgroundColor = 'var(--color-bg-hover)')}\n onMouseOut={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}\n >\n {expandedCategories.has(category.category) ? (\n <ChevronDown style={styles.categoryChevron} />\n ) : (\n <ChevronRight style={styles.categoryChevron} />\n )}\n <span style={styles.categoryLabel}>{category.label}</span>\n <span style={styles.categoryCount}>{category.widgets.length}</span>\n </button>\n\n {/* Widget Items */}\n {expandedCategories.has(category.category) && (\n <div style={styles.widgetList}>\n {installedWidgetsLoading && category.category === 'Installed' && (\n <div\n style={{\n fontSize: 'var(--font-size-body-xs)',\n color: 'var(--color-text-muted)',\n padding: 'var(--space-controlGap)',\n }}\n >\n Loading...\n </div>\n )}\n {category.widgets.map((widget) => {\n const IconComponent = getIconComponent(widget.icon);\n const widgetKey = getWidgetKey(widget);\n const isHovered = hoveredWidget === widgetKey;\n\n return (\n <div\n key={widgetKey}\n draggable\n onDragStart={(e) => handleDragStart(e, widget)}\n onDragEnd={handleDragEnd}\n onClick={() => handleWidgetClick(widget)}\n onMouseEnter={() => setHoveredWidget(widgetKey)}\n onMouseLeave={() => setHoveredWidget(null)}\n style={{\n ...styles.widgetCard,\n ...(isHovered ? styles.widgetCardHover : {}),\n }}\n >\n {/* Drag Handle */}\n <GripVertical style={styles.dragHandle} />\n\n {/* Icon */}\n <div style={styles.widgetIcon}>\n <IconComponent style={styles.widgetIconInner} />\n </div>\n\n {/* Text */}\n <div style={styles.widgetText}>\n <div style={styles.widgetName}>{widget.name}</div>\n <div style={styles.widgetDescription}>{widget.description}</div>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n ))}\n\n {filteredCategories.length === 0 && (\n <div style={styles.emptyState}>\n <div style={styles.emptyIcon}>\n <Search style={{ width: '24px', height: '24px', color: 'var(--color-text-muted)' }} />\n </div>\n <p style={styles.emptyText}>\n No widgets found for \"<strong>{searchQuery}</strong>\"\n </p>\n <button type=\"button\" onClick={() => setSearchQuery('')} style={styles.clearButton}>\n Clear search\n </button>\n </div>\n )}\n </div>\n </div>\n\n {/* Footer */}\n <div style={styles.footer}>\n <p style={styles.footerText}>Drag widgets to position them on the canvas</p>\n </div>\n </div>\n );\n});\n\nexport default WidgetPalette;\n"],"mappings":"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"}
@@ -1,17 +1,59 @@
1
1
  import { GetWidgetTypesDocument as e } from "../../generated/wspace-operations.js";
2
2
  import t, { WIDGET_CATEGORY_LABELS as n, getAllWidgetDefinitions as r, getWidgetDefinition as i } from "../components/widgets/WidgetRegistry.js";
3
- import { mapFromFederationWidgetType as a } from "../utils/widgetTypeMapping.js";
4
- import { useEffect as o, useMemo as s } from "react";
5
- import { useQuery as c } from "@tanstack/react-query";
6
- import { print as l } from "graphql";
3
+ import { isFederationAccessible as a, mapFromFederationWidgetType as o } from "../utils/widgetTypeMapping.js";
4
+ import { useEffect as s, useMemo as c } from "react";
5
+ import { useQuery as l } from "@tanstack/react-query";
6
+ import { print as u } from "graphql";
7
7
  //#region src/bigconsole/hooks/useWidgetCatalog.ts
8
- var u = new Set(Object.keys(n));
9
- function d(e) {
8
+ var d = new Set(Object.keys(n)), f = "Puzzle", p = "Installed";
9
+ function m(e) {
10
10
  let n = String(e).toLowerCase();
11
- return Object.prototype.hasOwnProperty.call(t, n) ? n : a(e);
11
+ return Object.prototype.hasOwnProperty.call(t, n) || a(e);
12
12
  }
13
- function f(e) {
14
- let t = d(e.type), n = i(t), r = u.has(e.category) ? e.category : n.category;
13
+ function h(e) {
14
+ let n = String(e).toLowerCase();
15
+ return Object.prototype.hasOwnProperty.call(t, n) ? n : o(e);
16
+ }
17
+ function g(e) {
18
+ return {
19
+ type: "custom",
20
+ name: e.label,
21
+ description: e.description,
22
+ icon: e.icon || f,
23
+ category: p,
24
+ component: null,
25
+ defaultConfig: {
26
+ ...e.defaultConfig ?? {},
27
+ widgetTypeKey: e.type,
28
+ isStoreWidget: !0
29
+ },
30
+ defaultSize: {
31
+ width: e.defaultSize.width,
32
+ height: e.defaultSize.height
33
+ },
34
+ minSize: {
35
+ width: e.minSize.width,
36
+ height: e.minSize.height
37
+ },
38
+ maxSize: {
39
+ width: e.maxSize.width,
40
+ height: e.maxSize.height
41
+ },
42
+ defaultResponsive: {
43
+ xs: 12,
44
+ sm: 6,
45
+ md: 4,
46
+ lg: 4
47
+ },
48
+ supportsDataBinding: !0,
49
+ supportsDrilldown: !0,
50
+ supportsAutoRefresh: !0,
51
+ tags: ["store", "installed"]
52
+ };
53
+ }
54
+ function _(e) {
55
+ if (!m(e.type)) return g(e);
56
+ let t = h(e.type), n = i(t), r = d.has(e.category) ? e.category : n.category;
15
57
  return {
16
58
  type: t,
17
59
  name: e.label,
@@ -39,8 +81,8 @@ function f(e) {
39
81
  tags: n.tags
40
82
  };
41
83
  }
42
- function p(t = {}) {
43
- let { workspaceId: n, apiGatewayUrl: i, authToken: a, enabled: u = !0 } = t, { data: d, isLoading: p, error: m } = c({
84
+ function v(t = {}) {
85
+ let { workspaceId: n, apiGatewayUrl: i, authToken: a, enabled: o = !0 } = t, { data: d, isLoading: f, error: p } = l({
44
86
  queryKey: ["widgetCatalog", n],
45
87
  queryFn: async () => {
46
88
  let t = { "Content-Type": "application/json" };
@@ -48,35 +90,35 @@ function p(t = {}) {
48
90
  let r = i ? `${i}/workspaces/graphql` : "/workspaces/graphql", o = await fetch(r, {
49
91
  method: "POST",
50
92
  headers: t,
51
- body: JSON.stringify({ query: l(e) })
93
+ body: JSON.stringify({ query: u(e) })
52
94
  });
53
95
  if (!o.ok) throw Error(`Failed to fetch widget catalog: ${o.status}`);
54
96
  let s = await o.json();
55
97
  if (s.errors?.length) throw Error(s.errors[0].message);
56
98
  return s.data?.getWidgetTypes ?? [];
57
99
  },
58
- enabled: u && !!n,
100
+ enabled: o && !!n,
59
101
  staleTime: 600 * 1e3
60
102
  });
61
- return o(() => {
62
- m && console.warn("Falling back to bundled widget registry:", m.message);
63
- }, [m]), s(() => d && d.length > 0 ? {
64
- definitions: d.map(f),
103
+ return s(() => {
104
+ p && console.warn("Falling back to bundled widget registry:", p.message);
105
+ }, [p]), c(() => d && d.length > 0 ? {
106
+ definitions: d.map(_),
65
107
  source: "backend",
66
- loading: p,
67
- error: m ?? void 0
108
+ loading: f,
109
+ error: p ?? void 0
68
110
  } : {
69
111
  definitions: r(),
70
112
  source: "static",
71
- loading: p,
72
- error: m ?? void 0
113
+ loading: f,
114
+ error: p ?? void 0
73
115
  }, [
74
116
  d,
75
- p,
76
- m
117
+ f,
118
+ p
77
119
  ]);
78
120
  }
79
121
  //#endregion
80
- export { p as default };
122
+ export { v as default };
81
123
 
82
124
  //# sourceMappingURL=useWidgetCatalog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useWidgetCatalog.js","names":[],"sources":["../../../src/bigconsole/hooks/useWidgetCatalog.ts"],"sourcesContent":["/**\n * Hook to fetch the widget-type catalog from the backend (`getWidgetTypes`) and\n * merge it over the bundled static registry.\n *\n * The backend is the source of truth for which widget types exist and their\n * palette metadata (label, description, icon, category, defaultConfig, sizes).\n * A few presentational fields the backend doesn't model — defaultResponsive,\n * supports* capability flags, tags, and the (always-null) `component` — are\n * filled in from the matching static `WIDGET_DEFINITIONS` entry.\n *\n * Resilient by design: while the query is loading, or if it errors / returns\n * nothing (e.g. an older supergraph that hasn't picked up the schema yet), the\n * hook returns the full bundled registry so the palette always works.\n *\n * Follows the same fetch/auth convention as {@link useInstalledWidgets}:\n * workspaceId, apiGatewayUrl, and authToken come from BigConsoleProvider context.\n */\n\nimport { useEffect, useMemo } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { GetWidgetTypesDocument } from '../../generated/wspace-operations';\nimport type { GetWidgetTypesQuery } from '../../generated/wspace-operations';\nimport {\n WIDGET_CATEGORY_LABELS,\n WIDGET_DEFINITIONS,\n getAllWidgetDefinitions,\n getWidgetDefinition,\n type WidgetDefinition,\n} from '../components/widgets/WidgetRegistry';\nimport { mapFromFederationWidgetType } from '../utils/widgetTypeMapping';\nimport type { WidgetType, WidgetCategory } from '../types';\n\ntype BackendWidgetType = GetWidgetTypesQuery['getWidgetTypes'][number];\n\nconst KNOWN_CATEGORIES = new Set<string>(Object.keys(WIDGET_CATEGORY_LABELS));\n\n/**\n * Resolve a backend `type` value to a valid internal widget-type key.\n *\n * Handles both shapes the field can take:\n * - canonical front-end keys (`metric_card`, `chart`, `map`, …) once the\n * supergraph serves `WidgetTypeInfo.type` as String — used as-is; and\n * - federation `WidgetType` enum values (`KPI`, `LINE_CHART`, `FUNNEL`, …)\n * if an older supergraph still serves the enum — reverse-mapped to the\n * internal key via the shared widgetTypeMapping util.\n *\n * Naive lowercasing alone is wrong: `KPI` -> `kpi`, `LINE_CHART` -> `line_chart`\n * are not internal types and would render as the \"unknown\" definition.\n */\nfunction resolveInternalType(rawType: string): WidgetType {\n const lower = String(rawType).toLowerCase();\n if (Object.prototype.hasOwnProperty.call(WIDGET_DEFINITIONS, lower)) {\n return lower as WidgetType;\n }\n return mapFromFederationWidgetType(rawType);\n}\n\nexport interface UseWidgetCatalogParams {\n workspaceId?: string;\n apiGatewayUrl?: string;\n authToken?: string;\n /** When false, the query is skipped and the static registry is returned. */\n enabled?: boolean;\n}\n\nexport interface UseWidgetCatalogResult {\n /** Merged catalog (backend metadata over static), or the static registry as fallback. */\n definitions: WidgetDefinition[];\n /** Whether the catalog came from the backend (`backend`) or the bundled registry (`static`). */\n source: 'backend' | 'static';\n loading: boolean;\n error: Error | undefined;\n}\n\n/**\n * Build a WidgetDefinition from one backend catalog entry, filling presentational\n * gaps from the matching static definition.\n */\nfunction mergeBackendType(entry: BackendWidgetType): WidgetDefinition {\n // Resolve to a valid internal widget-type key, whether the backend returns a\n // canonical key (\"metric_card\") or a federation enum value (\"KPI\").\n const typeKey = resolveInternalType(entry.type);\n const staticDef = getWidgetDefinition(typeKey);\n\n const category: WidgetCategory = KNOWN_CATEGORIES.has(entry.category)\n ? (entry.category as WidgetCategory)\n : staticDef.category;\n\n return {\n type: typeKey,\n name: entry.label,\n description: entry.description,\n icon: entry.icon,\n category,\n component: null,\n defaultConfig: (entry.defaultConfig as Record<string, unknown>) ?? staticDef.defaultConfig,\n defaultSize: { width: entry.defaultSize.width, height: entry.defaultSize.height },\n minSize: { width: entry.minSize.width, height: entry.minSize.height },\n maxSize: { width: entry.maxSize.width, height: entry.maxSize.height },\n // Fields the backend WidgetTypeInfo does not model — keep the static values.\n defaultResponsive: staticDef.defaultResponsive,\n supportsDataBinding: staticDef.supportsDataBinding,\n supportsDrilldown: staticDef.supportsDrilldown,\n supportsAutoRefresh: staticDef.supportsAutoRefresh,\n tags: staticDef.tags,\n };\n}\n\nexport function useWidgetCatalog(params: UseWidgetCatalogParams = {}): UseWidgetCatalogResult {\n const { workspaceId, apiGatewayUrl, authToken, enabled = true } = params;\n\n const {\n data: backendTypes,\n isLoading: loading,\n error,\n } = useQuery<BackendWidgetType[], Error>({\n // Only workspaceId is part of the cache key; token/url are used inside queryFn\n // but should not invalidate the cache on rotation.\n queryKey: ['widgetCatalog', workspaceId],\n queryFn: async () => {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (workspaceId) headers['x-workspace-id'] = workspaceId;\n if (authToken) headers['Authorization'] = `Bearer ${authToken}`;\n\n const url = apiGatewayUrl ? `${apiGatewayUrl}/workspaces/graphql` : '/workspaces/graphql';\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({ query: print(GetWidgetTypesDocument) }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch widget catalog: ${response.status}`);\n }\n\n const result: { data?: GetWidgetTypesQuery; errors?: { message: string }[] } = await response.json();\n\n if (result.errors?.length) {\n throw new Error(result.errors[0].message);\n }\n\n return result.data?.getWidgetTypes ?? [];\n },\n enabled: enabled && !!workspaceId,\n // The catalog is effectively static config; avoid refetching on every remount.\n staleTime: 10 * 60 * 1000,\n });\n\n useEffect(() => {\n if (error) {\n // Non-fatal: the palette falls back to the bundled registry.\n console.warn('Falling back to bundled widget registry:', error.message);\n }\n }, [error]);\n\n return useMemo<UseWidgetCatalogResult>(() => {\n if (backendTypes && backendTypes.length > 0) {\n return {\n definitions: backendTypes.map(mergeBackendType),\n source: 'backend',\n loading,\n error: error ?? undefined,\n };\n }\n return {\n definitions: getAllWidgetDefinitions(),\n source: 'static',\n loading,\n error: error ?? undefined,\n };\n }, [backendTypes, loading, error]);\n}\n\nexport default useWidgetCatalog;\n"],"mappings":";;;;;;;AAmCA,IAAM,IAAmB,IAAI,IAAY,OAAO,KAAK,EAAuB,CAAC;AAe7E,SAAS,EAAoB,GAA6B;CACxD,IAAM,IAAQ,OAAO,EAAQ,CAAC,aAAa;AAI3C,QAHI,OAAO,UAAU,eAAe,KAAK,GAAoB,EAAM,GAC1D,IAEF,EAA4B,EAAQ;;AAwB7C,SAAS,EAAiB,GAA4C;CAGpE,IAAM,IAAU,EAAoB,EAAM,KAAK,EACzC,IAAY,EAAoB,EAAQ,EAExC,IAA2B,EAAiB,IAAI,EAAM,SAAS,GAChE,EAAM,WACP,EAAU;AAEd,QAAO;EACL,MAAM;EACN,MAAM,EAAM;EACZ,aAAa,EAAM;EACnB,MAAM,EAAM;EACZ;EACA,WAAW;EACX,eAAgB,EAAM,iBAA6C,EAAU;EAC7E,aAAa;GAAE,OAAO,EAAM,YAAY;GAAO,QAAQ,EAAM,YAAY;GAAQ;EACjF,SAAS;GAAE,OAAO,EAAM,QAAQ;GAAO,QAAQ,EAAM,QAAQ;GAAQ;EACrE,SAAS;GAAE,OAAO,EAAM,QAAQ;GAAO,QAAQ,EAAM,QAAQ;GAAQ;EAErE,mBAAmB,EAAU;EAC7B,qBAAqB,EAAU;EAC/B,mBAAmB,EAAU;EAC7B,qBAAqB,EAAU;EAC/B,MAAM,EAAU;EACjB;;AAGH,SAAgB,EAAiB,IAAiC,EAAE,EAA0B;CAC5F,IAAM,EAAE,gBAAa,kBAAe,cAAW,aAAU,OAAS,GAE5D,EACJ,MAAM,GACN,WAAW,GACX,aACE,EAAqC;EAGvC,UAAU,CAAC,iBAAiB,EAAY;EACxC,SAAS,YAAY;GACnB,IAAM,IAAkC,EAAE,gBAAgB,oBAAoB;AAE9E,GADI,MAAa,EAAQ,oBAAoB,IACzC,MAAW,EAAQ,gBAAmB,UAAU;GAEpD,IAAM,IAAM,IAAgB,GAAG,EAAc,uBAAuB,uBAE9D,IAAW,MAAM,MAAM,GAAK;IAChC,QAAQ;IACR;IACA,MAAM,KAAK,UAAU,EAAE,OAAO,EAAM,EAAuB,EAAE,CAAC;IAC/D,CAAC;AAEF,OAAI,CAAC,EAAS,GACZ,OAAU,MAAM,mCAAmC,EAAS,SAAS;GAGvE,IAAM,IAAyE,MAAM,EAAS,MAAM;AAEpG,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,GAAG,QAAQ;AAG3C,UAAO,EAAO,MAAM,kBAAkB,EAAE;;EAE1C,SAAS,KAAW,CAAC,CAAC;EAEtB,WAAW,MAAU;EACtB,CAAC;AASF,QAPA,QAAgB;AACd,EAAI,KAEF,QAAQ,KAAK,4CAA4C,EAAM,QAAQ;IAExE,CAAC,EAAM,CAAC,EAEJ,QACD,KAAgB,EAAa,SAAS,IACjC;EACL,aAAa,EAAa,IAAI,EAAiB;EAC/C,QAAQ;EACR;EACA,OAAO,KAAS,KAAA;EACjB,GAEI;EACL,aAAa,GAAyB;EACtC,QAAQ;EACR;EACA,OAAO,KAAS,KAAA;EACjB,EACA;EAAC;EAAc;EAAS;EAAM,CAAC"}
1
+ {"version":3,"file":"useWidgetCatalog.js","names":[],"sources":["../../../src/bigconsole/hooks/useWidgetCatalog.ts"],"sourcesContent":["/**\n * Hook to fetch the widget-type catalog from the backend (`getWidgetTypes`) and\n * merge it over the bundled static registry.\n *\n * The backend is the source of truth for which widget types exist and their\n * palette metadata (label, description, icon, category, defaultConfig, sizes).\n * A few presentational fields the backend doesn't model — defaultResponsive,\n * supports* capability flags, tags, and the (always-null) `component` — are\n * filled in from the matching static `WIDGET_DEFINITIONS` entry.\n *\n * Resilient by design: while the query is loading, or if it errors / returns\n * nothing (e.g. an older supergraph that hasn't picked up the schema yet), the\n * hook returns the full bundled registry so the palette always works.\n *\n * Follows the same fetch/auth convention as {@link useInstalledWidgets}:\n * workspaceId, apiGatewayUrl, and authToken come from BigConsoleProvider context.\n */\n\nimport { useEffect, useMemo } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { GetWidgetTypesDocument } from '../../generated/wspace-operations';\nimport type { GetWidgetTypesQuery } from '../../generated/wspace-operations';\nimport {\n WIDGET_CATEGORY_LABELS,\n WIDGET_DEFINITIONS,\n getAllWidgetDefinitions,\n getWidgetDefinition,\n type WidgetDefinition,\n} from '../components/widgets/WidgetRegistry';\nimport { isFederationAccessible, mapFromFederationWidgetType } from '../utils/widgetTypeMapping';\nimport type { WidgetType, WidgetCategory } from '../types';\n\ntype BackendWidgetType = GetWidgetTypesQuery['getWidgetTypes'][number];\n\nconst KNOWN_CATEGORIES = new Set<string>(Object.keys(WIDGET_CATEGORY_LABELS));\n\n/** Fallbacks for store/custom types whose manifest omits presentational metadata. */\nconst STORE_WIDGET_FALLBACK_ICON = 'Puzzle';\nconst STORE_WIDGET_CATEGORY: WidgetCategory = 'Installed';\n\n/**\n * Whether a backend `type` value corresponds to one of the built-in widget types\n * (either a canonical front-end key like \"metric_card\" or a federation enum value\n * like \"KPI\"). Store/custom types installed from the marketplace (BOFF-2858) use\n * namespaced keys such as \"store/stripe-mrr-card\" and match neither.\n */\nfunction isBuiltInType(rawType: string): boolean {\n const lower = String(rawType).toLowerCase();\n return Object.prototype.hasOwnProperty.call(WIDGET_DEFINITIONS, lower) || isFederationAccessible(rawType);\n}\n\n/**\n * Resolve a backend `type` value to a valid internal widget-type key.\n *\n * Handles both shapes the field can take:\n * - canonical front-end keys (`metric_card`, `chart`, `map`, …) once the\n * supergraph serves `WidgetTypeInfo.type` as String — used as-is; and\n * - federation `WidgetType` enum values (`KPI`, `LINE_CHART`, `FUNNEL`, …)\n * if an older supergraph still serves the enum — reverse-mapped to the\n * internal key via the shared widgetTypeMapping util.\n *\n * Naive lowercasing alone is wrong: `KPI` -> `kpi`, `LINE_CHART` -> `line_chart`\n * are not internal types and would render as the \"unknown\" definition.\n */\nfunction resolveInternalType(rawType: string): WidgetType {\n const lower = String(rawType).toLowerCase();\n if (Object.prototype.hasOwnProperty.call(WIDGET_DEFINITIONS, lower)) {\n return lower as WidgetType;\n }\n return mapFromFederationWidgetType(rawType);\n}\n\nexport interface UseWidgetCatalogParams {\n workspaceId?: string;\n apiGatewayUrl?: string;\n authToken?: string;\n /** When false, the query is skipped and the static registry is returned. */\n enabled?: boolean;\n}\n\nexport interface UseWidgetCatalogResult {\n /** Merged catalog (backend metadata over static), or the static registry as fallback. */\n definitions: WidgetDefinition[];\n /** Whether the catalog came from the backend (`backend`) or the bundled registry (`static`). */\n source: 'backend' | 'static';\n loading: boolean;\n error: Error | undefined;\n}\n\n/**\n * Build a WidgetDefinition for a store/custom widget type (BOFF-2858).\n *\n * Store types have no matching static definition, so everything comes from the\n * backend catalog entry. The namespaced key (e.g. \"store/stripe-mrr-card\") is\n * kept verbatim as the definition `type` and the entry is filed under the\n * \"Installed from Store\" category so the palette groups it separately.\n */\nfunction buildStoreType(entry: BackendWidgetType): WidgetDefinition {\n return {\n // Store types persist as `custom` widget instances — the namespaced key is\n // NOT a valid federated WidgetType enum value, so it cannot be sent to\n // createBigConsoleWidget directly. The real key travels in config\n // (widgetTypeKey), matching the convention useInstalledWidgets already uses\n // for store-installed widgets (isStoreWidget + custom type).\n type: 'custom' as WidgetType,\n name: entry.label,\n description: entry.description,\n icon: entry.icon || STORE_WIDGET_FALLBACK_ICON,\n category: STORE_WIDGET_CATEGORY,\n component: null,\n defaultConfig: {\n ...((entry.defaultConfig as Record<string, unknown>) ?? {}),\n // Preserve the namespaced type so the create flow can set Widget.widgetTypeKey\n // and the renderer can resolve the store type's template.\n widgetTypeKey: entry.type,\n isStoreWidget: true,\n },\n defaultSize: { width: entry.defaultSize.width, height: entry.defaultSize.height },\n minSize: { width: entry.minSize.width, height: entry.minSize.height },\n maxSize: { width: entry.maxSize.width, height: entry.maxSize.height },\n // The backend WidgetTypeInfo does not model these; store widgets support the\n // full data-binding feature set by default.\n defaultResponsive: { xs: 12, sm: 6, md: 4, lg: 4 },\n supportsDataBinding: true,\n supportsDrilldown: true,\n supportsAutoRefresh: true,\n tags: ['store', 'installed'],\n };\n}\n\n/**\n * Build a WidgetDefinition from one backend catalog entry, filling presentational\n * gaps from the matching static definition. Store/custom types (no static match)\n * are handled by {@link buildStoreType} instead of being collapsed onto a\n * built-in key.\n */\nfunction mergeBackendType(entry: BackendWidgetType): WidgetDefinition {\n if (!isBuiltInType(entry.type)) {\n return buildStoreType(entry);\n }\n\n // Resolve to a valid internal widget-type key, whether the backend returns a\n // canonical key (\"metric_card\") or a federation enum value (\"KPI\").\n const typeKey = resolveInternalType(entry.type);\n const staticDef = getWidgetDefinition(typeKey);\n\n const category: WidgetCategory = KNOWN_CATEGORIES.has(entry.category)\n ? (entry.category as WidgetCategory)\n : staticDef.category;\n\n return {\n type: typeKey,\n name: entry.label,\n description: entry.description,\n icon: entry.icon,\n category,\n component: null,\n defaultConfig: (entry.defaultConfig as Record<string, unknown>) ?? staticDef.defaultConfig,\n defaultSize: { width: entry.defaultSize.width, height: entry.defaultSize.height },\n minSize: { width: entry.minSize.width, height: entry.minSize.height },\n maxSize: { width: entry.maxSize.width, height: entry.maxSize.height },\n // Fields the backend WidgetTypeInfo does not model — keep the static values.\n defaultResponsive: staticDef.defaultResponsive,\n supportsDataBinding: staticDef.supportsDataBinding,\n supportsDrilldown: staticDef.supportsDrilldown,\n supportsAutoRefresh: staticDef.supportsAutoRefresh,\n tags: staticDef.tags,\n };\n}\n\nexport function useWidgetCatalog(params: UseWidgetCatalogParams = {}): UseWidgetCatalogResult {\n const { workspaceId, apiGatewayUrl, authToken, enabled = true } = params;\n\n const {\n data: backendTypes,\n isLoading: loading,\n error,\n } = useQuery<BackendWidgetType[], Error>({\n // Only workspaceId is part of the cache key; token/url are used inside queryFn\n // but should not invalidate the cache on rotation.\n queryKey: ['widgetCatalog', workspaceId],\n queryFn: async () => {\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (workspaceId) headers['x-workspace-id'] = workspaceId;\n if (authToken) headers['Authorization'] = `Bearer ${authToken}`;\n\n const url = apiGatewayUrl ? `${apiGatewayUrl}/workspaces/graphql` : '/workspaces/graphql';\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify({ query: print(GetWidgetTypesDocument) }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch widget catalog: ${response.status}`);\n }\n\n const result: { data?: GetWidgetTypesQuery; errors?: { message: string }[] } = await response.json();\n\n if (result.errors?.length) {\n throw new Error(result.errors[0].message);\n }\n\n return result.data?.getWidgetTypes ?? [];\n },\n enabled: enabled && !!workspaceId,\n // The catalog is effectively static config; avoid refetching on every remount.\n staleTime: 10 * 60 * 1000,\n });\n\n useEffect(() => {\n if (error) {\n // Non-fatal: the palette falls back to the bundled registry.\n console.warn('Falling back to bundled widget registry:', error.message);\n }\n }, [error]);\n\n return useMemo<UseWidgetCatalogResult>(() => {\n if (backendTypes && backendTypes.length > 0) {\n return {\n definitions: backendTypes.map(mergeBackendType),\n source: 'backend',\n loading,\n error: error ?? undefined,\n };\n }\n return {\n definitions: getAllWidgetDefinitions(),\n source: 'static',\n loading,\n error: error ?? undefined,\n };\n }, [backendTypes, loading, error]);\n}\n\nexport default useWidgetCatalog;\n"],"mappings":"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"}
@@ -52,6 +52,6 @@ function r(t) {
52
52
  return n(t) ? t.toUpperCase() : e(t);
53
53
  }
54
54
  //#endregion
55
- export { t as mapFromFederationWidgetType, r as normalizeWidgetTypeForApi };
55
+ export { n as isFederationAccessible, t as mapFromFederationWidgetType, r as normalizeWidgetTypeForApi };
56
56
 
57
57
  //# sourceMappingURL=widgetTypeMapping.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-bigconsole",
3
- "version": "2026.710.3",
3
+ "version": "2026.711.1",
4
4
  "description": "BigConsole - AI-powered analytics and dashboard platform",
5
5
  "type": "module",
6
6
  "files": [