UNPKG

react-antd-admin-panel

Version:

Modern TypeScript-first React admin panel builder with Ant Design 6

115 lines 4.06 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { useState, useCallback } from 'react'; import { Button, Modal } from 'antd'; import { ExclamationCircleOutlined } from '@ant-design/icons'; import { useAccess } from '../hooks/useAccess'; /** * ActionButton - Renders an Action as an Ant Design Button * * Handles confirmation dialogs, loading states, and access control. * * @example * ```tsx * const deleteAction = new Action() * .label('Delete') * .danger(true) * .confirm('Are you sure?') * .callback(async () => { * await api.deleteUser(id); * }); * * <ActionButton action={deleteAction} /> * * // With formula submission * const saveAction = new Action() * .label('Save') * .buttonType('primary'); * * <ActionButton action={saveAction} formula={formula} /> * ``` */ export function ActionButton({ action, formula, args, navigate, disabled: disabledProp, className, size, }) { const [loading, setLoading] = useState(false); const access = useAccess(); // Check access requirements const accessConfig = action.getAccess(); const hasAccess = useCallback(() => { if (!accessConfig) return true; if (accessConfig.role && !access.hasRole(accessConfig.role)) { return false; } if (accessConfig.roles && !access.hasAnyRole(accessConfig.roles)) { return false; } if (accessConfig.permission && !access.hasPermission(accessConfig.permission)) { return false; } if (accessConfig.feature && !access.hasFeature(accessConfig.feature, accessConfig.level)) { return false; } return true; }, [accessConfig, access]); // Don't render if no access if (!hasAccess()) { return null; } const isDisabled = disabledProp ?? action.isDisabled(); const isLoading = loading || action.isLoading(); const confirmConfig = action.getConfirm(); const executeAction = async () => { const actionType = action.getType(); try { setLoading(true); switch (actionType) { case 'submit': if (formula) { await formula.submit(); } break; case 'callback': await action.execute(args); break; case 'link': const route = action.getRoute(); if (route && navigate) { navigate(route); } else if (route) { window.location.href = route; } break; case 'reset': if (formula) { formula.reset(); } break; } } catch { // Error already handled by callbacks in Action/Formula } finally { setLoading(false); } }; const handleClick = () => { if (confirmConfig) { Modal.confirm({ title: confirmConfig.title || 'Confirm', icon: _jsx(ExclamationCircleOutlined, {}), content: confirmConfig.content, okText: confirmConfig.okText || 'OK', cancelText: confirmConfig.cancelText || 'Cancel', okButtonProps: confirmConfig.danger ? { danger: true } : undefined, onOk: executeAction, }); } else { executeAction(); } }; return (_jsx(Button, { type: action.getButtonType(), danger: action.isDanger(), disabled: isDisabled, loading: isLoading, icon: action.getIcon(), onClick: handleClick, className: className, size: size, "aria-label": !action.getLabel() && action.getIcon() ? action.getTooltip() || 'Action button' : undefined, children: action.getLabel() })); } export default ActionButton; //# sourceMappingURL=ActionButton.js.map