@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.
- package/dist/bigconsole/AdminRoot.js +21 -16
- package/dist/bigconsole/AdminRoot.js.map +1 -1
- package/dist/bigconsole/BigConsoleRoot.js +44 -39
- package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +115 -100
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js +100 -98
- package/dist/bigconsole/components/dashboard/PageTabsManager/PageTabsManager.js.map +1 -1
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js +164 -161
- package/dist/bigconsole/components/dashboard/ShareDialog/EmbedTab.js.map +1 -1
- package/dist/bigconsole/components/datasink/DataSinkCard.js +20 -20
- package/dist/bigconsole/components/datasink/DataSinkCard.js.map +1 -1
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js +216 -49
- package/dist/bigconsole/components/datasink/ImportDataGuideDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js +96 -90
- package/dist/bigconsole/components/widgets/ActionConfigDialog.js.map +1 -1
- package/dist/bigconsole/components/widgets/WidgetMenu.js +87 -76
- package/dist/bigconsole/components/widgets/WidgetMenu.js.map +1 -1
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js +120 -118
- package/dist/bigconsole/components/widgets/widget-actions/WidgetActions.js.map +1 -1
- package/dist/bigconsole/pages/DashboardBuilderPage.js +113 -104
- package/dist/bigconsole/pages/DashboardBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +208 -199
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +376 -325
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/DataParsersPage.js +135 -125
- package/dist/bigconsole/pages/DataParsersPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkBuilderPage.js +182 -172
- package/dist/bigconsole/pages/DataSinkBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinkViewPage.js +233 -198
- package/dist/bigconsole/pages/DataSinkViewPage.js.map +1 -1
- package/dist/bigconsole/pages/DataSinksPage.js +281 -268
- package/dist/bigconsole/pages/DataSinksPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserBuilderPage.js +238 -223
- package/dist/bigconsole/pages/ParserBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/ParserViewPage.js +162 -144
- package/dist/bigconsole/pages/ParserViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineBuilderPage.js +212 -204
- package/dist/bigconsole/pages/PipelineBuilderPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelineViewPage.js +191 -183
- package/dist/bigconsole/pages/PipelineViewPage.js.map +1 -1
- package/dist/bigconsole/pages/PipelinesPage.js +128 -103
- package/dist/bigconsole/pages/PipelinesPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowViewPage.js +238 -217
- package/dist/bigconsole/pages/WorkflowViewPage.js.map +1 -1
- package/dist/bigconsole/pages/WorkflowsPage.js +116 -102
- package/dist/bigconsole/pages/WorkflowsPage.js.map +1 -1
- package/dist/bigconsole/utils/csv.js +91 -0
- package/dist/bigconsole/utils/csv.js.map +1 -0
- package/dist/constants/permissions.js +83 -0
- package/dist/constants/permissions.js.map +1 -0
- 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":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
96
|
+
var g = t(function({ name: e, className: t = "w-4 h-4" }) {
|
|
95
97
|
return {
|
|
96
|
-
"external-link": /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
-
}),
|
|
230
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
312
|
+
}), /* @__PURE__ */ l("button", {
|
|
311
313
|
type: "button",
|
|
312
314
|
onClick: a,
|
|
313
|
-
className:
|
|
314
|
-
style:
|
|
315
|
+
className: m(i),
|
|
316
|
+
style: h(i),
|
|
315
317
|
children: n
|
|
316
318
|
})]
|
|
317
319
|
})
|
|
318
320
|
]
|
|
319
321
|
})]
|
|
320
322
|
});
|
|
321
|
-
}),
|
|
322
|
-
let [
|
|
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 =
|
|
326
|
-
|
|
327
|
-
}, [
|
|
328
|
-
|
|
329
|
-
}, [
|
|
330
|
-
|
|
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
|
|
333
|
-
if (
|
|
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
|
-
}, [
|
|
342
|
+
}, [m]), e.length === 0 ? null : /* @__PURE__ */ u("div", {
|
|
341
343
|
className: "relative",
|
|
342
|
-
children: [/* @__PURE__ */
|
|
344
|
+
children: [/* @__PURE__ */ l("button", {
|
|
343
345
|
ref: _,
|
|
344
346
|
type: "button",
|
|
345
347
|
onClick: b,
|
|
346
|
-
disabled:
|
|
347
|
-
className:
|
|
348
|
+
disabled: s,
|
|
349
|
+
className: f("SECONDARY", p, s ?? !1),
|
|
348
350
|
"aria-label": "More actions",
|
|
349
|
-
children: /* @__PURE__ */
|
|
350
|
-
}),
|
|
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__ */
|
|
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__ */
|
|
361
|
+
children: /* @__PURE__ */ l("div", {
|
|
360
362
|
className: "py-1",
|
|
361
|
-
children: e.map((e) => /* @__PURE__ */
|
|
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__ */
|
|
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
|
-
}),
|
|
375
|
-
let
|
|
376
|
-
|
|
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
|
-
|
|
381
|
+
s,
|
|
380
382
|
r
|
|
381
|
-
]),
|
|
382
|
-
return e.type === "LINK" && e.metadata?.url ? /* @__PURE__ */
|
|
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:
|
|
387
|
-
style:
|
|
388
|
-
"aria-disabled":
|
|
388
|
+
className: d,
|
|
389
|
+
style: m,
|
|
390
|
+
"aria-disabled": s,
|
|
389
391
|
children: [
|
|
390
|
-
e.icon && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
402
|
+
}) : /* @__PURE__ */ u("button", {
|
|
401
403
|
type: e.type === "SUBMIT" ? "submit" : "button",
|
|
402
|
-
onClick:
|
|
403
|
-
disabled:
|
|
404
|
-
className:
|
|
405
|
-
style:
|
|
406
|
-
children: [e.icon && /* @__PURE__ */
|
|
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
|
-
}),
|
|
412
|
-
let [
|
|
413
|
-
mainActions:
|
|
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:
|
|
417
|
-
overflowActions:
|
|
418
|
-
}, [
|
|
419
|
-
if (
|
|
420
|
-
|
|
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
|
|
424
|
+
await a(e, r);
|
|
423
425
|
} catch {} finally {
|
|
424
|
-
|
|
426
|
+
C(!1);
|
|
425
427
|
}
|
|
426
428
|
}
|
|
427
|
-
}, [
|
|
429
|
+
}, [a, r]), A = n((e) => {
|
|
428
430
|
if (e.confirmation) {
|
|
429
|
-
|
|
431
|
+
x(e);
|
|
430
432
|
return;
|
|
431
433
|
}
|
|
432
|
-
|
|
433
|
-
}, [
|
|
434
|
-
|
|
435
|
-
}, [
|
|
436
|
-
|
|
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
|
|
439
|
-
className: `${
|
|
440
|
-
children: [
|
|
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:
|
|
443
|
-
onAction:
|
|
444
|
-
disabled:
|
|
445
|
-
size:
|
|
446
|
-
showLabel:
|
|
447
|
-
}, e.id)),
|
|
448
|
-
actions:
|
|
449
|
-
context:
|
|
450
|
-
onAction:
|
|
451
|
-
disabled:
|
|
452
|
-
size:
|
|
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
|
-
}),
|
|
455
|
-
title:
|
|
456
|
-
message:
|
|
457
|
-
confirmLabel:
|
|
458
|
-
cancelLabel:
|
|
459
|
-
style:
|
|
460
|
-
onConfirm:
|
|
461
|
-
onCancel:
|
|
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 {
|
|
467
|
+
export { b as default };
|
|
466
468
|
|
|
467
469
|
//# sourceMappingURL=WidgetActions.js.map
|