@burdenoff/microfe-bigconsole 2026.804.2 → 2026.805.2

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 (53) hide show
  1. package/dist/bigconsole/AdminRoot.js +21 -16
  2. package/dist/bigconsole/AdminRoot.js.map +1 -1
  3. package/dist/bigconsole/BigConsoleRoot.js +44 -39
  4. package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
  5. package/dist/bigconsole/components/dashboard/DashboardToolbar.js +115 -100
  6. package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
  7. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
  8. package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
  9. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +164 -161
  10. package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
  11. package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
  12. package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
  13. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +216 -49
  14. package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
  15. package/dist/bigconsole/components/widgets/ActionConfigDialog.js +96 -90
  16. package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
  17. package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
  18. package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
  19. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
  20. package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
  21. package/dist/bigconsole/pages/DashboardBuilderPage.js +113 -104
  22. package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
  23. package/dist/bigconsole/pages/DashboardViewPage.js +208 -199
  24. package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
  25. package/dist/bigconsole/pages/DashboardsPage.js +376 -325
  26. package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
  27. package/dist/bigconsole/pages/DataParsersPage.js +135 -125
  28. package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
  29. package/dist/bigconsole/pages/DataSinkBuilderPage.js +182 -172
  30. package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
  31. package/dist/bigconsole/pages/DataSinkViewPage.js +233 -198
  32. package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
  33. package/dist/bigconsole/pages/DataSinksPage.js +281 -268
  34. package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
  35. package/dist/bigconsole/pages/ParserBuilderPage.js +238 -223
  36. package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
  37. package/dist/bigconsole/pages/ParserViewPage.js +162 -144
  38. package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
  39. package/dist/bigconsole/pages/PipelineBuilderPage.js +212 -204
  40. package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
  41. package/dist/bigconsole/pages/PipelineViewPage.js +191 -183
  42. package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
  43. package/dist/bigconsole/pages/PipelinesPage.js +128 -103
  44. package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
  45. package/dist/bigconsole/pages/WorkflowViewPage.js +238 -217
  46. package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
  47. package/dist/bigconsole/pages/WorkflowsPage.js +116 -102
  48. package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
  49. package/dist/bigconsole/utils/csv.js +91 -0
  50. package/dist/bigconsole/utils/csv.js.map +1 -0
  51. package/dist/constants/permissions.js +83 -0
  52. package/dist/constants/permissions.js.map +1 -0
  53. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"WidgetMenu.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/WidgetMenu.tsx"],"sourcesContent":["/**\n * WidgetMenu Component\n *\n * Dropdown menu with widget actions (edit, duplicate, delete, etc.)\n */\n\nimport { type FC, type ReactElement, useState, useRef, useEffect, useCallback, memo } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { Widget } from '../../types';\nimport { useWidgetStore } from '../../store';\nimport { useWidgetOperations } from '../../hooks';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetMenuProps {\n /** The widget data */\n widget: Widget;\n /** Whether in edit mode */\n isEditMode?: boolean;\n /** Callback to refresh widget */\n onRefresh?: () => void;\n /** Callback to export as CSV */\n onExportCSV?: () => void;\n /** Callback to export as PNG */\n onExportPNG?: () => void;\n}\n\ninterface MenuItem {\n id: string;\n label: string;\n icon: ReactElement;\n action: () => void;\n disabled?: boolean;\n destructive?: boolean;\n divider?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetMenu: FC<WidgetMenuProps> = memo(function WidgetMenu({\n widget,\n isEditMode,\n onRefresh,\n onExportCSV,\n onExportPNG,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n const menuRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n // Store actions\n const selectWidget = useWidgetStore((state) => state.selectWidget);\n const copyWidget = useWidgetStore((state) => state.copyWidget);\n const cutWidget = useWidgetStore((state) => state.cutWidget);\n const removeWidget = useWidgetStore((state) => state.removeWidget);\n const openConfigPanel = useWidgetStore((state) => state.openConfigPanel);\n\n // API operations - skipFetch since parent page fetches\n const {\n duplicateWidget: duplicateWidgetApi,\n deleteWidget: deleteWidgetApi,\n refreshWidgetData,\n } = useWidgetOperations(widget.pageId, widget.dashboardId, { skipFetch: true });\n\n // Close menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n menuRef.current &&\n !menuRef.current.contains(event.target as Node) &&\n buttonRef.current &&\n !buttonRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n\n // Close menu on escape\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n buttonRef.current?.focus();\n }\n };\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n }\n\n return () => {\n document.removeEventListener('keydown', handleEscape);\n };\n }, [isOpen]);\n\n // Toggle menu with collision detection\n const toggleMenu = useCallback((event: React.MouseEvent) => {\n event.stopPropagation();\n setIsOpen((prev) => {\n if (!prev && buttonRef.current) {\n // Calculate position when opening with collision detection\n const rect = buttonRef.current.getBoundingClientRect();\n const menuWidth = 160;\n const menuHeight = 320; // Approximate max height of menu\n const collisionPadding = 10;\n\n // Calculate initial position\n let top = rect.bottom + 4;\n let left = rect.right - menuWidth;\n\n // Check right overflow - ensure menu doesn't go past viewport right edge\n if (left + menuWidth > window.innerWidth - collisionPadding) {\n left = window.innerWidth - menuWidth - collisionPadding;\n }\n\n // Check left overflow - ensure menu doesn't go past viewport left edge\n if (left < collisionPadding) {\n left = collisionPadding;\n }\n\n // Check bottom overflow - flip to top if needed\n if (top + menuHeight > window.innerHeight - collisionPadding) {\n top = rect.top - menuHeight - 4;\n // If still overflows at top, position at top of viewport\n if (top < collisionPadding) {\n top = collisionPadding;\n }\n }\n\n setMenuPosition({\n top: top + window.scrollY,\n left: left + window.scrollX,\n });\n }\n return !prev;\n });\n }, []);\n\n // Menu items\n const menuItems: MenuItem[] = [\n {\n id: 'edit',\n label: 'Edit Widget',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n action: () => {\n selectWidget(widget.id);\n openConfigPanel();\n setIsOpen(false);\n },\n disabled: !isEditMode,\n },\n {\n id: 'refresh',\n label: 'Refresh Data',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n action: async () => {\n setIsOpen(false);\n if (onRefresh) {\n onRefresh();\n } else {\n await refreshWidgetData(widget.id);\n }\n },\n disabled: false,\n },\n {\n id: 'exportCSV',\n label: 'Export CSV',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n ),\n action: () => {\n setIsOpen(false);\n onExportCSV?.();\n },\n disabled: !onExportCSV,\n },\n {\n id: 'exportPNG',\n label: 'Export PNG',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n ),\n action: () => {\n setIsOpen(false);\n onExportPNG?.();\n },\n disabled: !onExportPNG,\n },\n {\n id: 'divider1',\n label: '',\n icon: <></>,\n action: () => {},\n divider: true,\n },\n {\n id: 'copy',\n label: 'Copy',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n ),\n action: () => {\n copyWidget(widget.id);\n setIsOpen(false);\n },\n disabled: !isEditMode,\n },\n {\n id: 'cut',\n label: 'Cut',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z\"\n />\n </svg>\n ),\n action: () => {\n cutWidget(widget.id);\n setIsOpen(false);\n },\n disabled: !isEditMode,\n },\n {\n id: 'duplicate',\n label: 'Duplicate',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2\"\n />\n </svg>\n ),\n action: async () => {\n setIsOpen(false);\n // Calculate new position (offset from original)\n const newPosition = {\n x: (widget.positionX ?? 0) + 1,\n y: (widget.positionY ?? 0) + 1,\n width: widget.positionWidth ?? 4,\n height: widget.positionHeight ?? 4,\n };\n await duplicateWidgetApi(widget.id, newPosition, `${widget.title} (Copy)`);\n },\n disabled: !isEditMode,\n },\n {\n id: 'divider2',\n label: '',\n icon: <></>,\n action: () => {},\n divider: true,\n },\n {\n id: 'delete',\n label: 'Delete',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n action: async () => {\n if (window.confirm('Are you sure you want to delete this widget?')) {\n setIsOpen(false);\n const success = await deleteWidgetApi(widget.id);\n if (!success) {\n // Fallback to local store removal if API fails\n removeWidget(widget.id);\n }\n } else {\n setIsOpen(false);\n }\n },\n disabled: !isEditMode,\n destructive: true,\n },\n ];\n\n return (\n <div className=\"relative\">\n {/* Menu Button */}\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={toggleMenu}\n className={`\n p-1.5 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n ${isOpen ? 'bg-bg-sunken' : ''}\n `}\n title=\"Widget options\"\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n >\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"19\" r=\"2\" />\n </svg>\n </button>\n\n {/* Dropdown Menu - Rendered via Portal to avoid overflow clipping */}\n {isOpen &&\n createPortal(\n <div\n ref={menuRef}\n style={{\n position: 'fixed',\n top: menuPosition.top,\n left: menuPosition.left,\n zIndex: 99999,\n }}\n className=\"\n min-w-[160px]\n py-1\n bg-bg-surface\n border border-border-default\n rounded-lg shadow-lg\n \"\n role=\"menu\"\n aria-orientation=\"vertical\"\n >\n {menuItems.map((item) => {\n if (item.divider) {\n return <div key={item.id} className=\"my-1 border-t border-border-default\" />;\n }\n\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n item.action();\n }}\n disabled={item.disabled}\n className={`\n w-full flex items-center gap-2\n px-3 py-2 text-left text-sm\n transition-colors\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-bg-sunken'}\n ${item.destructive ? 'text-status-error-text hover:text-status-error-text' : 'text-text-primary'}\n `}\n role=\"menuitem\"\n >\n {item.icon}\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>,\n document.body\n )}\n </div>\n );\n});\n\nexport default WidgetMenu;\n"],"mappings":"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"}
1
+ {"version":3,"file":"WidgetMenu.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/WidgetMenu.tsx"],"sourcesContent":["/**\n * WidgetMenu Component\n *\n * Dropdown menu with widget actions (edit, duplicate, delete, etc.)\n */\n\nimport { type FC, type ReactElement, useState, useRef, useEffect, useCallback, memo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport type { Widget } from '../../types';\nimport { useWidgetStore } from '../../store';\nimport { useWidgetOperations } from '../../hooks';\nimport { BIGCONSOLE_PERMISSIONS } from '../../../constants/permissions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface WidgetMenuProps {\n /** The widget data */\n widget: Widget;\n /** Whether in edit mode */\n isEditMode?: boolean;\n /** Callback to refresh widget */\n onRefresh?: () => void;\n /** Callback to export as CSV */\n onExportCSV?: () => void;\n /** Callback to export as PNG */\n onExportPNG?: () => void;\n}\n\ninterface MenuItem {\n id: string;\n label: string;\n icon: ReactElement;\n action: () => void;\n disabled?: boolean;\n destructive?: boolean;\n divider?: boolean;\n /**\n * When `false`, the item is filtered out entirely because the caller lacks the\n * matching widget permission. `undefined`/`true` = always shown (read-only\n * actions and dividers).\n */\n permitted?: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WidgetMenu: FC<WidgetMenuProps> = memo(function WidgetMenu({\n widget,\n isEditMode,\n onRefresh,\n onExportCSV,\n onExportPNG,\n}) {\n const [isOpen, setIsOpen] = useState(false);\n const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });\n const menuRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n // Permission gating for the widget CRUD actions. Read-only actions (refresh,\n // export) are always available; mutating actions are hidden when denied. The\n // menu items are custom portalled <button>s (not fe-libs Button), so we filter\n // by capability rather than wrapping in PermissionButton.\n const { hasPermission } = usePermissions();\n const canUpdate = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_UPDATE);\n const canCreate = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_CREATE);\n const canDelete = hasPermission(BIGCONSOLE_PERMISSIONS.WIDGET_DELETE);\n\n // Store actions\n const selectWidget = useWidgetStore((state) => state.selectWidget);\n const copyWidget = useWidgetStore((state) => state.copyWidget);\n const cutWidget = useWidgetStore((state) => state.cutWidget);\n const removeWidget = useWidgetStore((state) => state.removeWidget);\n const openConfigPanel = useWidgetStore((state) => state.openConfigPanel);\n\n // API operations - skipFetch since parent page fetches\n const {\n duplicateWidget: duplicateWidgetApi,\n deleteWidget: deleteWidgetApi,\n refreshWidgetData,\n } = useWidgetOperations(widget.pageId, widget.dashboardId, { skipFetch: true });\n\n // Close menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n menuRef.current &&\n !menuRef.current.contains(event.target as Node) &&\n buttonRef.current &&\n !buttonRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n\n // Close menu on escape\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n buttonRef.current?.focus();\n }\n };\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n }\n\n return () => {\n document.removeEventListener('keydown', handleEscape);\n };\n }, [isOpen]);\n\n // Toggle menu with collision detection\n const toggleMenu = useCallback((event: React.MouseEvent) => {\n event.stopPropagation();\n setIsOpen((prev) => {\n if (!prev && buttonRef.current) {\n // Calculate position when opening with collision detection\n const rect = buttonRef.current.getBoundingClientRect();\n const menuWidth = 160;\n const menuHeight = 320; // Approximate max height of menu\n const collisionPadding = 10;\n\n // Calculate initial position\n let top = rect.bottom + 4;\n let left = rect.right - menuWidth;\n\n // Check right overflow - ensure menu doesn't go past viewport right edge\n if (left + menuWidth > window.innerWidth - collisionPadding) {\n left = window.innerWidth - menuWidth - collisionPadding;\n }\n\n // Check left overflow - ensure menu doesn't go past viewport left edge\n if (left < collisionPadding) {\n left = collisionPadding;\n }\n\n // Check bottom overflow - flip to top if needed\n if (top + menuHeight > window.innerHeight - collisionPadding) {\n top = rect.top - menuHeight - 4;\n // If still overflows at top, position at top of viewport\n if (top < collisionPadding) {\n top = collisionPadding;\n }\n }\n\n setMenuPosition({\n top: top + window.scrollY,\n left: left + window.scrollX,\n });\n }\n return !prev;\n });\n }, []);\n\n // Menu items\n const menuItems: MenuItem[] = [\n {\n id: 'edit',\n label: 'Edit Widget',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z\"\n />\n </svg>\n ),\n action: () => {\n selectWidget(widget.id);\n openConfigPanel();\n setIsOpen(false);\n },\n disabled: !isEditMode,\n permitted: canUpdate,\n },\n {\n id: 'refresh',\n label: 'Refresh Data',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\"\n />\n </svg>\n ),\n action: async () => {\n setIsOpen(false);\n if (onRefresh) {\n onRefresh();\n } else {\n await refreshWidgetData(widget.id);\n }\n },\n disabled: false,\n },\n {\n id: 'exportCSV',\n label: 'Export CSV',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n ),\n action: () => {\n setIsOpen(false);\n onExportCSV?.();\n },\n disabled: !onExportCSV,\n },\n {\n id: 'exportPNG',\n label: 'Export PNG',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n ),\n action: () => {\n setIsOpen(false);\n onExportPNG?.();\n },\n disabled: !onExportPNG,\n },\n {\n id: 'divider1',\n label: '',\n icon: <></>,\n action: () => {},\n divider: true,\n },\n {\n id: 'copy',\n label: 'Copy',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z\"\n />\n </svg>\n ),\n action: () => {\n copyWidget(widget.id);\n setIsOpen(false);\n },\n disabled: !isEditMode,\n permitted: canCreate,\n },\n {\n id: 'cut',\n label: 'Cut',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M14.121 14.121L19 19m-7-7l7-7m-7 7l-2.879 2.879M12 12L9.121 9.121m0 5.758a3 3 0 10-4.243 4.243 3 3 0 004.243-4.243zm0-5.758a3 3 0 10-4.243-4.243 3 3 0 004.243 4.243z\"\n />\n </svg>\n ),\n action: () => {\n cutWidget(widget.id);\n setIsOpen(false);\n },\n disabled: !isEditMode,\n // Cut both removes the source widget and stages a paste, so it needs\n // create AND update rights.\n permitted: canCreate && canUpdate,\n },\n {\n id: 'duplicate',\n label: 'Duplicate',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M8 7v8a2 2 0 002 2h6M8 7V5a2 2 0 012-2h4.586a1 1 0 01.707.293l4.414 4.414a1 1 0 01.293.707V15a2 2 0 01-2 2h-2M8 7H6a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2v-2\"\n />\n </svg>\n ),\n action: async () => {\n setIsOpen(false);\n // Calculate new position (offset from original)\n const newPosition = {\n x: (widget.positionX ?? 0) + 1,\n y: (widget.positionY ?? 0) + 1,\n width: widget.positionWidth ?? 4,\n height: widget.positionHeight ?? 4,\n };\n await duplicateWidgetApi(widget.id, newPosition, `${widget.title} (Copy)`);\n },\n disabled: !isEditMode,\n permitted: canCreate,\n },\n {\n id: 'divider2',\n label: '',\n icon: <></>,\n action: () => {},\n divider: true,\n },\n {\n id: 'delete',\n label: 'Delete',\n icon: (\n <svg fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\" className=\"w-4 h-4\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\"\n />\n </svg>\n ),\n action: async () => {\n if (window.confirm('Are you sure you want to delete this widget?')) {\n setIsOpen(false);\n const success = await deleteWidgetApi(widget.id);\n if (!success) {\n // Fallback to local store removal if API fails\n removeWidget(widget.id);\n }\n } else {\n setIsOpen(false);\n }\n },\n disabled: !isEditMode,\n destructive: true,\n permitted: canDelete,\n },\n ];\n\n // Drop items the caller lacks permission for, then collapse any dividers that\n // are now leading, trailing, or adjacent to another divider (so removing a\n // gated action never leaves an orphaned separator line).\n const permittedItems = menuItems.filter((item) => item.permitted !== false);\n const visibleMenuItems = permittedItems.filter((item, index) => {\n if (!item.divider) return true;\n const prev = permittedItems[index - 1];\n const next = permittedItems[index + 1];\n return prev !== undefined && next !== undefined && !prev.divider && !next.divider;\n });\n\n return (\n <div className=\"relative\">\n {/* Menu Button */}\n <button\n ref={buttonRef}\n type=\"button\"\n onClick={toggleMenu}\n className={`\n p-1.5 rounded-md\n text-text-secondary\n hover:text-text-primary\n hover:bg-bg-sunken\n transition-colors\n ${isOpen ? 'bg-bg-sunken' : ''}\n `}\n title=\"Widget options\"\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n >\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"5\" r=\"2\" />\n <circle cx=\"12\" cy=\"12\" r=\"2\" />\n <circle cx=\"12\" cy=\"19\" r=\"2\" />\n </svg>\n </button>\n\n {/* Dropdown Menu - Rendered via Portal to avoid overflow clipping */}\n {isOpen &&\n createPortal(\n <div\n ref={menuRef}\n style={{\n position: 'fixed',\n top: menuPosition.top,\n left: menuPosition.left,\n zIndex: 99999,\n }}\n className=\"\n min-w-[160px]\n py-1\n bg-bg-surface\n border border-border-default\n rounded-lg shadow-lg\n \"\n role=\"menu\"\n aria-orientation=\"vertical\"\n >\n {visibleMenuItems.map((item) => {\n if (item.divider) {\n return <div key={item.id} className=\"my-1 border-t border-border-default\" />;\n }\n\n return (\n <button\n key={item.id}\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n item.action();\n }}\n disabled={item.disabled}\n className={`\n w-full flex items-center gap-2\n px-3 py-2 text-left text-sm\n transition-colors\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-bg-sunken'}\n ${item.destructive ? 'text-status-error-text hover:text-status-error-text' : 'text-text-primary'}\n `}\n role=\"menuitem\"\n >\n {item.icon}\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>,\n document.body\n )}\n </div>\n );\n});\n\nexport default WidgetMenu;\n"],"mappings":";;;;;;;;;;AAmDA,IAAa,IAAkC,EAAK,SAAoB,EACtE,WACA,eACA,cACA,gBACA,kBACC;CACD,IAAM,CAAC,GAAQ,KAAa,EAAS,GAAM,EACrC,CAAC,GAAc,KAAmB,EAAS;EAAE,KAAK;EAAG,MAAM;EAAG,CAAC,EAC/D,IAAU,EAAuB,KAAK,EACtC,IAAY,EAA0B,KAAK,EAM3C,EAAE,qBAAkB,GAAgB,EACpC,IAAY,EAAc,EAAuB,cAAc,EAC/D,IAAY,EAAc,EAAuB,cAAc,EAC/D,IAAY,EAAc,EAAuB,cAAc,EAG/D,IAAe,GAAgB,MAAU,EAAM,aAAa,EAC5D,IAAa,GAAgB,MAAU,EAAM,WAAW,EACxD,IAAY,GAAgB,MAAU,EAAM,UAAU,EACtD,IAAe,GAAgB,MAAU,EAAM,aAAa,EAC5D,IAAkB,GAAgB,MAAU,EAAM,gBAAgB,EAGlE,EACJ,iBAAiB,GACjB,cAAc,GACd,yBACE,EAAoB,EAAO,QAAQ,EAAO,aAAa,EAAE,WAAW,IAAM,CAAC;AAyB/E,CAtBA,QAAgB;EACd,IAAM,KAAsB,MAAsB;AAChD,GACE,EAAQ,WACR,CAAC,EAAQ,QAAQ,SAAS,EAAM,OAAe,IAC/C,EAAU,WACV,CAAC,EAAU,QAAQ,SAAS,EAAM,OAAe,IAEjD,EAAU,GAAM;;AAQpB,SAJI,KACF,SAAS,iBAAiB,aAAa,EAAmB,QAG/C;AACX,YAAS,oBAAoB,aAAa,EAAmB;;IAE9D,CAAC,EAAO,CAAC,EAGZ,QAAgB;EACd,IAAM,KAAgB,MAAyB;AAC7C,GAAI,EAAM,QAAQ,aAChB,EAAU,GAAM,EAChB,EAAU,SAAS,OAAO;;AAQ9B,SAJI,KACF,SAAS,iBAAiB,WAAW,EAAa,QAGvC;AACX,YAAS,oBAAoB,WAAW,EAAa;;IAEtD,CAAC,EAAO,CAAC;CAGZ,IAAM,IAAa,GAAa,MAA4B;AAE1D,EADA,EAAM,iBAAiB,EACvB,GAAW,MAAS;AAClB,OAAI,CAAC,KAAQ,EAAU,SAAS;IAE9B,IAAM,IAAO,EAAU,QAAQ,uBAAuB,EAMlD,IAAM,EAAK,SAAS,GACpB,IAAO,EAAK,QAAQ;AAqBxB,IAlBI,IAAO,MAAY,OAAO,aAAa,OACzC,IAAO,OAAO,aAAa,MAAY,KAIrC,IAAO,OACT,IAAO,KAIL,IAAM,MAAa,OAAO,cAAc,OAC1C,IAAM,EAAK,MAAM,MAAa,GAE1B,IAAM,OACR,IAAM,MAIV,EAAgB;KACd,KAAK,IAAM,OAAO;KAClB,MAAM,IAAO,OAAO;KACrB,CAAC;;AAEJ,UAAO,CAAC;IACR;IACD,EAAE,CAAC,EA2MA,IAxMwB;EAC5B;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,cAAc;AAGZ,IAFA,EAAa,EAAO,GAAG,EACvB,GAAiB,EACjB,EAAU,GAAM;;GAElB,UAAU,CAAC;GACX,WAAW;GACZ;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,QAAQ,YAAY;AAElB,IADA,EAAU,GAAM,EACZ,IACF,GAAW,GAEX,MAAM,EAAkB,EAAO,GAAG;;GAGtC,UAAU;GACX;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,cAAc;AAEZ,IADA,EAAU,GAAM,EAChB,KAAe;;GAEjB,UAAU,CAAC;GACZ;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,cAAc;AAEZ,IADA,EAAU,GAAM,EAChB,KAAe;;GAEjB,UAAU,CAAC;GACZ;EACD;GACE,IAAI;GACJ,OAAO;GACP,MAAM,kBAAA,GAAA,EAAK,CAAA;GACX,cAAc;GACd,SAAS;GACV;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,cAAc;AAEZ,IADA,EAAW,EAAO,GAAG,EACrB,EAAU,GAAM;;GAElB,UAAU,CAAC;GACX,WAAW;GACZ;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,cAAc;AAEZ,IADA,EAAU,EAAO,GAAG,EACpB,EAAU,GAAM;;GAElB,UAAU,CAAC;GAGX,WAAW,KAAa;GACzB;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,QAAQ,YAAY;AAClB,MAAU,GAAM;IAEhB,IAAM,IAAc;KAClB,IAAI,EAAO,aAAa,KAAK;KAC7B,IAAI,EAAO,aAAa,KAAK;KAC7B,OAAO,EAAO,iBAAiB;KAC/B,QAAQ,EAAO,kBAAkB;KAClC;AACD,UAAM,EAAmB,EAAO,IAAI,GAAa,GAAG,EAAO,MAAM,SAAS;;GAE5E,UAAU,CAAC;GACX,WAAW;GACZ;EACD;GACE,IAAI;GACJ,OAAO;GACP,MAAM,kBAAA,GAAA,EAAK,CAAA;GACX,cAAc;GACd,SAAS;GACV;EACD;GACE,IAAI;GACJ,OAAO;GACP,MACE,kBAAC,OAAD;IAAK,MAAK;IAAO,QAAO;IAAe,SAAQ;IAAY,WAAU;cACnE,kBAAC,QAAD;KACE,eAAc;KACd,gBAAe;KACf,aAAa;KACb,GAAE;KACF,CAAA;IACE,CAAA;GAER,QAAQ,YAAY;AAClB,IAAI,OAAO,QAAQ,+CAA+C,IAChE,EAAU,GAAM,EACA,MAAM,EAAgB,EAAO,GAAG,IAG9C,EAAa,EAAO,GAAG,IAGzB,EAAU,GAAM;;GAGpB,UAAU,CAAC;GACX,aAAa;GACb,WAAW;GACZ;EACF,CAKgC,QAAQ,MAAS,EAAK,cAAc,GAAM,EACrE,IAAmB,EAAe,QAAQ,GAAM,MAAU;AAC9D,MAAI,CAAC,EAAK,QAAS,QAAO;EAC1B,IAAM,IAAO,EAAe,IAAQ,IAC9B,IAAO,EAAe,IAAQ;AACpC,SAAO,MAAS,KAAA,KAAa,MAAS,KAAA,KAAa,CAAC,EAAK,WAAW,CAAC,EAAK;GAC1E;AAEF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CAEE,kBAAC,UAAD;GACE,KAAK;GACL,MAAK;GACL,SAAS;GACT,WAAW;;;;;;YAMP,IAAS,iBAAiB,GAAG;;GAEjC,OAAM;GACN,iBAAc;GACd,iBAAe;aAEf,kBAAC,OAAD;IAAK,WAAU;IAAU,MAAK;IAAe,SAAQ;cAArD;KACE,kBAAC,UAAD;MAAQ,IAAG;MAAK,IAAG;MAAI,GAAE;MAAM,CAAA;KAC/B,kBAAC,UAAD;MAAQ,IAAG;MAAK,IAAG;MAAK,GAAE;MAAM,CAAA;KAChC,kBAAC,UAAD;MAAQ,IAAG;MAAK,IAAG;MAAK,GAAE;MAAM,CAAA;KAC5B;;GACC,CAAA,EAGR,KACC,EACE,kBAAC,OAAD;GACE,KAAK;GACL,OAAO;IACL,UAAU;IACV,KAAK,EAAa;IAClB,MAAM,EAAa;IACnB,QAAQ;IACT;GACD,WAAU;GAOV,MAAK;GACL,oBAAiB;aAEhB,EAAiB,KAAK,MACjB,EAAK,UACA,kBAAC,OAAD,EAAmB,WAAU,uCAAwC,EAA3D,EAAK,GAAsD,GAI5E,kBAAC,UAAD;IAEE,MAAK;IACL,UAAU,MAAM;AAEd,KADA,EAAE,iBAAiB,EACnB,EAAK,QAAQ;;IAEf,UAAU,EAAK;IACf,WAAW;;;;oBAIT,EAAK,WAAW,kCAAkC,qBAAqB;oBACvE,EAAK,cAAc,wDAAwD,oBAAoB;;IAEjG,MAAK;cAfP,CAiBG,EAAK,MACN,kBAAC,QAAD,EAAA,UAAO,EAAK,OAAa,CAAA,CAClB;MAlBF,EAAK,GAkBH,CAEX;GACE,CAAA,EACN,SAAS,KACV,CACC;;EAER"}
@@ -1,8 +1,10 @@
1
- import { memo as e, useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
2
- import { Fragment as o, jsx as s, jsxs as c } from "react/jsx-runtime";
3
- import { createPortal as l } from "react-dom";
1
+ import { BIGCONSOLE_PERMISSIONS as e } from "../../../../constants/permissions.js";
2
+ import { memo as t, useCallback as n, useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
3
+ import { usePermissions as s } from "@burdenoff/fe-libs/shared/providers/shell";
4
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import { createPortal as d } from "react-dom";
4
6
  //#region src/bigconsole/components/widgets/widget-actions/WidgetActions.tsx
5
- function u(e, t, n) {
7
+ function f(e, t, n) {
6
8
  let r = {
7
9
  sm: "px-2.5 py-1.5 text-xs",
8
10
  md: "px-4 py-2 text-sm",
@@ -16,7 +18,7 @@ function u(e, t, n) {
16
18
  }, a = n ? "opacity-50 cursor-not-allowed" : "cursor-pointer", o = i[e || "SECONDARY"] || i.SECONDARY;
17
19
  return `inline-flex items-center justify-center font-medium rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 ${r[t]} ${o} ${a}`;
18
20
  }
19
- function d(e) {
21
+ function p(e) {
20
22
  let t = {
21
23
  PRIMARY: {
22
24
  backgroundColor: "var(--color-action-primary-bg)",
@@ -41,7 +43,7 @@ function d(e) {
41
43
  };
42
44
  return t[e || "SECONDARY"] || t.SECONDARY;
43
45
  }
44
- function f(e) {
46
+ function m(e) {
45
47
  let t = {
46
48
  PRIMARY: "bg-action-primary text-white hover:bg-action-primary/90",
47
49
  SECONDARY: "bg-secondary text-white hover:bg-secondary/90",
@@ -51,7 +53,7 @@ function f(e) {
51
53
  };
52
54
  return `px-4 py-2 text-sm font-medium rounded-md transition-colors ${t[e || "PRIMARY"] || t.PRIMARY}`;
53
55
  }
54
- function p(e) {
56
+ function h(e) {
55
57
  let t = {
56
58
  PRIMARY: {
57
59
  backgroundColor: "var(--color-action-primary-bg)",
@@ -91,134 +93,134 @@ function p(e) {
91
93
  };
92
94
  return t[e || "PRIMARY"] || t.PRIMARY;
93
95
  }
94
- var m = e(function({ name: e, className: t = "w-4 h-4" }) {
96
+ var g = t(function({ name: e, className: t = "w-4 h-4" }) {
95
97
  return {
96
- "external-link": /* @__PURE__ */ s("svg", {
98
+ "external-link": /* @__PURE__ */ l("svg", {
97
99
  className: t,
98
100
  fill: "none",
99
101
  stroke: "currentColor",
100
102
  viewBox: "0 0 24 24",
101
- children: /* @__PURE__ */ s("path", {
103
+ children: /* @__PURE__ */ l("path", {
102
104
  strokeLinecap: "round",
103
105
  strokeLinejoin: "round",
104
106
  strokeWidth: 2,
105
107
  d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
106
108
  })
107
109
  }),
108
- save: /* @__PURE__ */ s("svg", {
110
+ save: /* @__PURE__ */ l("svg", {
109
111
  className: t,
110
112
  fill: "none",
111
113
  stroke: "currentColor",
112
114
  viewBox: "0 0 24 24",
113
- children: /* @__PURE__ */ s("path", {
115
+ children: /* @__PURE__ */ l("path", {
114
116
  strokeLinecap: "round",
115
117
  strokeLinejoin: "round",
116
118
  strokeWidth: 2,
117
119
  d: "M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"
118
120
  })
119
121
  }),
120
- trash: /* @__PURE__ */ s("svg", {
122
+ trash: /* @__PURE__ */ l("svg", {
121
123
  className: t,
122
124
  fill: "none",
123
125
  stroke: "currentColor",
124
126
  viewBox: "0 0 24 24",
125
- children: /* @__PURE__ */ s("path", {
127
+ children: /* @__PURE__ */ l("path", {
126
128
  strokeLinecap: "round",
127
129
  strokeLinejoin: "round",
128
130
  strokeWidth: 2,
129
131
  d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
130
132
  })
131
133
  }),
132
- edit: /* @__PURE__ */ s("svg", {
134
+ edit: /* @__PURE__ */ l("svg", {
133
135
  className: t,
134
136
  fill: "none",
135
137
  stroke: "currentColor",
136
138
  viewBox: "0 0 24 24",
137
- children: /* @__PURE__ */ s("path", {
139
+ children: /* @__PURE__ */ l("path", {
138
140
  strokeLinecap: "round",
139
141
  strokeLinejoin: "round",
140
142
  strokeWidth: 2,
141
143
  d: "M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
142
144
  })
143
145
  }),
144
- refresh: /* @__PURE__ */ s("svg", {
146
+ refresh: /* @__PURE__ */ l("svg", {
145
147
  className: t,
146
148
  fill: "none",
147
149
  stroke: "currentColor",
148
150
  viewBox: "0 0 24 24",
149
- children: /* @__PURE__ */ s("path", {
151
+ children: /* @__PURE__ */ l("path", {
150
152
  strokeLinecap: "round",
151
153
  strokeLinejoin: "round",
152
154
  strokeWidth: 2,
153
155
  d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
154
156
  })
155
157
  }),
156
- download: /* @__PURE__ */ s("svg", {
158
+ download: /* @__PURE__ */ l("svg", {
157
159
  className: t,
158
160
  fill: "none",
159
161
  stroke: "currentColor",
160
162
  viewBox: "0 0 24 24",
161
- children: /* @__PURE__ */ s("path", {
163
+ children: /* @__PURE__ */ l("path", {
162
164
  strokeLinecap: "round",
163
165
  strokeLinejoin: "round",
164
166
  strokeWidth: 2,
165
167
  d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
166
168
  })
167
169
  }),
168
- upload: /* @__PURE__ */ s("svg", {
170
+ upload: /* @__PURE__ */ l("svg", {
169
171
  className: t,
170
172
  fill: "none",
171
173
  stroke: "currentColor",
172
174
  viewBox: "0 0 24 24",
173
- children: /* @__PURE__ */ s("path", {
175
+ children: /* @__PURE__ */ l("path", {
174
176
  strokeLinecap: "round",
175
177
  strokeLinejoin: "round",
176
178
  strokeWidth: 2,
177
179
  d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
178
180
  })
179
181
  }),
180
- plus: /* @__PURE__ */ s("svg", {
182
+ plus: /* @__PURE__ */ l("svg", {
181
183
  className: t,
182
184
  fill: "none",
183
185
  stroke: "currentColor",
184
186
  viewBox: "0 0 24 24",
185
- children: /* @__PURE__ */ s("path", {
187
+ children: /* @__PURE__ */ l("path", {
186
188
  strokeLinecap: "round",
187
189
  strokeLinejoin: "round",
188
190
  strokeWidth: 2,
189
191
  d: "M12 4v16m8-8H4"
190
192
  })
191
193
  }),
192
- check: /* @__PURE__ */ s("svg", {
194
+ check: /* @__PURE__ */ l("svg", {
193
195
  className: t,
194
196
  fill: "none",
195
197
  stroke: "currentColor",
196
198
  viewBox: "0 0 24 24",
197
- children: /* @__PURE__ */ s("path", {
199
+ children: /* @__PURE__ */ l("path", {
198
200
  strokeLinecap: "round",
199
201
  strokeLinejoin: "round",
200
202
  strokeWidth: 2,
201
203
  d: "M5 13l4 4L19 7"
202
204
  })
203
205
  }),
204
- x: /* @__PURE__ */ s("svg", {
206
+ x: /* @__PURE__ */ l("svg", {
205
207
  className: t,
206
208
  fill: "none",
207
209
  stroke: "currentColor",
208
210
  viewBox: "0 0 24 24",
209
- children: /* @__PURE__ */ s("path", {
211
+ children: /* @__PURE__ */ l("path", {
210
212
  strokeLinecap: "round",
211
213
  strokeLinejoin: "round",
212
214
  strokeWidth: 2,
213
215
  d: "M6 18L18 6M6 6l12 12"
214
216
  })
215
217
  }),
216
- "more-horizontal": /* @__PURE__ */ s("svg", {
218
+ "more-horizontal": /* @__PURE__ */ l("svg", {
217
219
  className: t,
218
220
  fill: "none",
219
221
  stroke: "currentColor",
220
222
  viewBox: "0 0 24 24",
221
- children: /* @__PURE__ */ s("path", {
223
+ children: /* @__PURE__ */ l("path", {
222
224
  strokeLinecap: "round",
223
225
  strokeLinejoin: "round",
224
226
  strokeWidth: 2,
@@ -226,8 +228,8 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
226
228
  })
227
229
  })
228
230
  }[e] || null;
229
- }), h = e(function({ title: e, message: t, confirmLabel: n, cancelLabel: r, style: i, onConfirm: a, onCancel: o }) {
230
- return /* @__PURE__ */ c("div", {
231
+ }), _ = t(function({ title: e, message: t, confirmLabel: n, cancelLabel: r, style: i, onConfirm: a, onCancel: o }) {
232
+ return /* @__PURE__ */ u("div", {
231
233
  className: "fixed inset-0 z-50 flex items-center justify-center",
232
234
  style: {
233
235
  position: "fixed",
@@ -240,7 +242,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
240
242
  alignItems: "center",
241
243
  justifyContent: "center"
242
244
  },
243
- children: [/* @__PURE__ */ s("div", {
245
+ children: [/* @__PURE__ */ l("div", {
244
246
  className: "absolute inset-0 bg-black/50",
245
247
  style: {
246
248
  position: "absolute",
@@ -251,7 +253,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
251
253
  backgroundColor: "rgba(0,0,0,0.5)"
252
254
  },
253
255
  onClick: o
254
- }), /* @__PURE__ */ c("div", {
256
+ }), /* @__PURE__ */ u("div", {
255
257
  className: "relative bg-surface rounded-lg shadow-xl max-w-md w-full mx-4 p-6 animate-in fade-in zoom-in-95 duration-200",
256
258
  style: {
257
259
  position: "relative",
@@ -265,7 +267,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
265
267
  zIndex: 1e4
266
268
  },
267
269
  children: [
268
- /* @__PURE__ */ s("h3", {
270
+ /* @__PURE__ */ l("h3", {
269
271
  className: "text-lg font-semibold text-primary",
270
272
  style: {
271
273
  fontSize: "18px",
@@ -275,7 +277,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
275
277
  },
276
278
  children: e
277
279
  }),
278
- /* @__PURE__ */ s("p", {
280
+ /* @__PURE__ */ l("p", {
279
281
  className: "mt-2 text-sm text-secondary",
280
282
  style: {
281
283
  marginTop: "8px",
@@ -284,7 +286,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
284
286
  },
285
287
  children: t
286
288
  }),
287
- /* @__PURE__ */ c("div", {
289
+ /* @__PURE__ */ u("div", {
288
290
  className: "mt-4 flex justify-end gap-3",
289
291
  style: {
290
292
  marginTop: "16px",
@@ -292,7 +294,7 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
292
294
  justifyContent: "flex-end",
293
295
  gap: "12px"
294
296
  },
295
- children: [/* @__PURE__ */ s("button", {
297
+ children: [/* @__PURE__ */ l("button", {
296
298
  type: "button",
297
299
  onClick: o,
298
300
  className: "px-4 py-2 text-sm font-medium text-secondary bg-bg-sunken hover:bg-bg-sunken/80 rounded-md transition-colors",
@@ -307,63 +309,63 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
307
309
  cursor: "pointer"
308
310
  },
309
311
  children: r
310
- }), /* @__PURE__ */ s("button", {
312
+ }), /* @__PURE__ */ l("button", {
311
313
  type: "button",
312
314
  onClick: a,
313
- className: f(i),
314
- style: p(i),
315
+ className: m(i),
316
+ style: h(i),
315
317
  children: n
316
318
  })]
317
319
  })
318
320
  ]
319
321
  })]
320
322
  });
321
- }), g = e(function({ actions: e, context: r, onAction: d, disabled: f, size: p }) {
322
- let [h, g] = a(!1), _ = i(null), [v, y] = a({
323
+ }), v = t(function({ actions: e, context: t, onAction: i, disabled: s, size: p }) {
324
+ let [m, h] = o(!1), _ = a(null), [v, y] = o({
323
325
  top: 0,
324
326
  left: 0
325
- }), b = t(() => {
326
- f || g((e) => !e);
327
- }, [f]), x = t((e) => {
328
- g(!1), d(e);
329
- }, [d]), S = t(() => {
330
- g(!1);
327
+ }), b = n(() => {
328
+ s || h((e) => !e);
329
+ }, [s]), x = n((e) => {
330
+ h(!1), i(e);
331
+ }, [i]), S = n(() => {
332
+ h(!1);
331
333
  }, []);
332
- return n(() => {
333
- if (h && _.current) {
334
+ return r(() => {
335
+ if (m && _.current) {
334
336
  let e = _.current.getBoundingClientRect();
335
337
  y({
336
338
  top: e.bottom + 4,
337
339
  left: e.right - 192
338
340
  });
339
341
  }
340
- }, [h]), e.length === 0 ? null : /* @__PURE__ */ c("div", {
342
+ }, [m]), e.length === 0 ? null : /* @__PURE__ */ u("div", {
341
343
  className: "relative",
342
- children: [/* @__PURE__ */ s("button", {
344
+ children: [/* @__PURE__ */ l("button", {
343
345
  ref: _,
344
346
  type: "button",
345
347
  onClick: b,
346
- disabled: f,
347
- className: u("SECONDARY", p, f ?? !1),
348
+ disabled: s,
349
+ className: f("SECONDARY", p, s ?? !1),
348
350
  "aria-label": "More actions",
349
- children: /* @__PURE__ */ s(m, { name: "more-horizontal" })
350
- }), h && l(/* @__PURE__ */ c(o, { children: [/* @__PURE__ */ s("div", {
351
+ children: /* @__PURE__ */ l(g, { name: "more-horizontal" })
352
+ }), m && d(/* @__PURE__ */ u(c, { children: [/* @__PURE__ */ l("div", {
351
353
  className: "fixed inset-0 z-[9998]",
352
354
  onClick: S
353
- }), /* @__PURE__ */ s("div", {
355
+ }), /* @__PURE__ */ l("div", {
354
356
  className: "fixed w-48 bg-surface rounded-md shadow-lg ring-1 ring-border z-[9999] animate-in fade-in slide-in-from-top-2 duration-150",
355
357
  style: {
356
358
  top: v.top,
357
359
  left: Math.max(8, v.left)
358
360
  },
359
- children: /* @__PURE__ */ s("div", {
361
+ children: /* @__PURE__ */ l("div", {
360
362
  className: "py-1",
361
- children: e.map((e) => /* @__PURE__ */ c("button", {
363
+ children: e.map((e) => /* @__PURE__ */ u("button", {
362
364
  type: "button",
363
365
  onClick: () => x(e),
364
366
  disabled: e.disabled,
365
367
  className: "w-full text-left px-4 py-2 text-sm text-secondary hover:bg-bg-sunken hover:text-primary disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors",
366
- children: [e.icon && /* @__PURE__ */ s(m, {
368
+ children: [e.icon && /* @__PURE__ */ l(g, {
367
369
  name: e.icon,
368
370
  className: "w-4 h-4"
369
371
  }), e.label]
@@ -371,97 +373,97 @@ var m = e(function({ name: e, className: t = "w-4 h-4" }) {
371
373
  })
372
374
  })] }), document.body)]
373
375
  });
374
- }), _ = e(function({ action: e, context: n, onAction: r, disabled: i, size: a, showLabel: o = !0 }) {
375
- let l = i || e.disabled, f = t(() => {
376
- l || r(e);
376
+ }), y = t(function({ action: e, context: t, onAction: r, disabled: i, size: a, showLabel: o = !0 }) {
377
+ let s = i || e.disabled, c = n(() => {
378
+ s || r(e);
377
379
  }, [
378
380
  e,
379
- l,
381
+ s,
380
382
  r
381
- ]), p = u(e.style, a, l), h = d(e.style);
382
- return e.type === "LINK" && e.metadata?.url ? /* @__PURE__ */ c("a", {
383
+ ]), d = f(e.style, a, s), m = p(e.style);
384
+ return e.type === "LINK" && e.metadata?.url ? /* @__PURE__ */ u("a", {
383
385
  href: e.metadata.url,
384
386
  target: e.metadata.target || "_blank",
385
387
  rel: "noopener noreferrer",
386
- className: p,
387
- style: h,
388
- "aria-disabled": l,
388
+ className: d,
389
+ style: m,
390
+ "aria-disabled": s,
389
391
  children: [
390
- e.icon && /* @__PURE__ */ s(m, {
392
+ e.icon && /* @__PURE__ */ l(g, {
391
393
  name: e.icon,
392
394
  className: "w-4 h-4 mr-1.5"
393
395
  }),
394
396
  o && e.label,
395
- !e.icon && /* @__PURE__ */ s(m, {
397
+ !e.icon && /* @__PURE__ */ l(g, {
396
398
  name: "external-link",
397
399
  className: "w-4 h-4 ml-1.5"
398
400
  })
399
401
  ]
400
- }) : /* @__PURE__ */ c("button", {
402
+ }) : /* @__PURE__ */ u("button", {
401
403
  type: e.type === "SUBMIT" ? "submit" : "button",
402
- onClick: f,
403
- disabled: l,
404
- className: p,
405
- style: h,
406
- children: [e.icon && /* @__PURE__ */ s(m, {
404
+ onClick: c,
405
+ disabled: s,
406
+ className: d,
407
+ style: m,
408
+ children: [e.icon && /* @__PURE__ */ l(g, {
407
409
  name: e.icon,
408
410
  className: "w-4 h-4 mr-1.5"
409
411
  }), o && e.label]
410
412
  });
411
- }), v = e(function({ actions: e, context: n, onAction: i, disabled: l = !1, layout: u = "horizontal", size: d = "md", showLabels: f = !0, maxVisible: p = 3, className: m = "" }) {
412
- let [v, y] = a(null), [b, x] = a(!1), S = r(() => e.filter((e) => !e.hidden).sort((e, t) => e.order - t.order), [e]), { mainActions: C, overflowActions: w } = r(() => S.length <= p ? {
413
- mainActions: S,
413
+ }), b = t(function({ actions: t, context: r, onAction: a, disabled: d = !1, layout: f = "horizontal", size: p = "md", showLabels: m = !0, maxVisible: h = 3, className: g = "" }) {
414
+ let [b, x] = o(null), [S, C] = o(!1), { hasPermission: w } = s(), T = w(e.WIDGET_ACTION_EXECUTE), E = i(() => t.filter((e) => !e.hidden).sort((e, t) => e.order - t.order), [t]), { mainActions: D, overflowActions: O } = i(() => E.length <= h ? {
415
+ mainActions: E,
414
416
  overflowActions: []
415
417
  } : {
416
- mainActions: S.slice(0, p - 1),
417
- overflowActions: S.slice(p - 1)
418
- }, [S, p]), T = t(async (e) => {
419
- if (i) {
420
- x(!0);
418
+ mainActions: E.slice(0, h - 1),
419
+ overflowActions: E.slice(h - 1)
420
+ }, [E, h]), k = n(async (e) => {
421
+ if (a) {
422
+ C(!0);
421
423
  try {
422
- await i(e, n);
424
+ await a(e, r);
423
425
  } catch {} finally {
424
- x(!1);
426
+ C(!1);
425
427
  }
426
428
  }
427
- }, [i, n]), E = t((e) => {
429
+ }, [a, r]), A = n((e) => {
428
430
  if (e.confirmation) {
429
- y(e);
431
+ x(e);
430
432
  return;
431
433
  }
432
- T(e);
433
- }, [T]), D = t(() => {
434
- v && (T(v), y(null));
435
- }, [v, T]), O = t(() => {
436
- y(null);
434
+ k(e);
435
+ }, [k]), j = n(() => {
436
+ b && (k(b), x(null));
437
+ }, [b, k]), M = n(() => {
438
+ x(null);
437
439
  }, []);
438
- return S.length === 0 ? null : /* @__PURE__ */ c(o, { children: [/* @__PURE__ */ c("div", {
439
- className: `${u === "horizontal" ? "flex flex-row flex-wrap gap-2" : "flex flex-col gap-2"} ${m}`,
440
- children: [C.map((e) => /* @__PURE__ */ s(_, {
440
+ return E.length === 0 ? null : /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ u("div", {
441
+ className: `${f === "horizontal" ? "flex flex-row flex-wrap gap-2" : "flex flex-col gap-2"} ${g}`,
442
+ children: [D.map((e) => /* @__PURE__ */ l(y, {
441
443
  action: e,
442
- context: n,
443
- onAction: E,
444
- disabled: l || b,
445
- size: d,
446
- showLabel: f
447
- }, e.id)), w.length > 0 && /* @__PURE__ */ s(g, {
448
- actions: w,
449
- context: n,
450
- onAction: E,
451
- disabled: l || b,
452
- size: d
444
+ context: r,
445
+ onAction: A,
446
+ disabled: d || S || !T && e.type !== "LINK",
447
+ size: p,
448
+ showLabel: m
449
+ }, e.id)), O.length > 0 && /* @__PURE__ */ l(v, {
450
+ actions: O,
451
+ context: r,
452
+ onAction: A,
453
+ disabled: d || S || !T,
454
+ size: p
453
455
  })]
454
- }), v?.confirmation && /* @__PURE__ */ s(h, {
455
- title: v.confirmation.title || "Confirm Action",
456
- message: v.confirmation.message || "Are you sure you want to proceed?",
457
- confirmLabel: v.confirmation.confirmLabel || "OK",
458
- cancelLabel: v.confirmation.cancelLabel || "Cancel",
459
- style: v.style,
460
- onConfirm: D,
461
- onCancel: O
456
+ }), b?.confirmation && /* @__PURE__ */ l(_, {
457
+ title: b.confirmation.title || "Confirm Action",
458
+ message: b.confirmation.message || "Are you sure you want to proceed?",
459
+ confirmLabel: b.confirmation.confirmLabel || "OK",
460
+ cancelLabel: b.confirmation.cancelLabel || "Cancel",
461
+ style: b.style,
462
+ onConfirm: j,
463
+ onCancel: M
462
464
  })] });
463
465
  });
464
466
  //#endregion
465
- export { v as default };
467
+ export { b as default };
466
468
 
467
469
  //# sourceMappingURL=WidgetActions.js.map