qnce-engine
Version:
Core QNCE (Quantum Narrative Convergence Engine) - Framework agnostic narrative engine with performance optimization
144 lines • 7.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.UndoRedoControls = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const types_1 = require("../types");
const react_2 = require("../../integrations/react");
/**
* UndoRedoControls Component
*
* Provides accessible undo/redo buttons with real-time state updates,
* tooltips, keyboard support, and customizable theming.
*
* Features:
* - Real-time enable/disable based on undo/redo availability
* - Accessible with ARIA labels and keyboard navigation
* - Customizable themes and layouts
* - Integration with QNCE Engine undo/redo system
*/
const UndoRedoControls = ({ engine, theme: customTheme, className = '', style, disabled = false, showLabels = true, labels = { undo: 'Undo', redo: 'Redo' }, size = 'md', layout = 'horizontal', onUndo, onRedo }) => {
const { undo, redo, canUndo, canRedo, undoCount, redoCount } = (0, react_2.useUndoRedo)(engine);
// Merge custom theme with default theme
const theme = (0, react_1.useMemo)(() => ({
...types_1.defaultTheme,
...customTheme,
colors: { ...types_1.defaultTheme.colors, ...customTheme?.colors },
spacing: { ...types_1.defaultTheme.spacing, ...customTheme?.spacing },
borderRadius: { ...types_1.defaultTheme.borderRadius, ...customTheme?.borderRadius },
typography: {
...types_1.defaultTheme.typography,
...customTheme?.typography,
fontSize: { ...types_1.defaultTheme.typography.fontSize, ...customTheme?.typography?.fontSize },
fontWeight: { ...types_1.defaultTheme.typography.fontWeight, ...customTheme?.typography?.fontWeight }
},
shadows: { ...types_1.defaultTheme.shadows, ...customTheme?.shadows }
}), [customTheme]);
// Size configurations
const sizeConfig = {
sm: {
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
fontSize: theme.typography.fontSize.sm,
iconSize: '16px'
},
md: {
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
fontSize: theme.typography.fontSize.md,
iconSize: '20px'
},
lg: {
padding: `${theme.spacing.md} ${theme.spacing.lg}`,
fontSize: theme.typography.fontSize.lg,
iconSize: '24px'
}
};
const currentSize = sizeConfig[size];
// Button styles
const buttonBaseStyle = {
fontFamily: theme.typography.fontFamily,
fontSize: currentSize.fontSize,
fontWeight: theme.typography.fontWeight.medium,
padding: currentSize.padding,
borderRadius: theme.borderRadius.md,
border: `1px solid ${theme.colors.primary}`,
backgroundColor: theme.colors.background,
color: theme.colors.primary,
cursor: 'pointer',
transition: 'all 0.2s ease-in-out',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: theme.spacing.xs,
boxShadow: theme.shadows.sm,
outline: 'none',
position: 'relative'
};
const buttonDisabledStyle = {
...buttonBaseStyle,
backgroundColor: theme.colors.surface,
color: theme.colors.disabled,
borderColor: theme.colors.disabled,
cursor: 'not-allowed',
boxShadow: 'none'
};
const buttonHoverStyle = {
backgroundColor: theme.colors.primary,
color: theme.colors.background,
transform: 'translateY(-1px)',
boxShadow: theme.shadows.md
};
// Container styles
const containerStyle = {
display: 'flex',
flexDirection: layout === 'horizontal' ? 'row' : 'column',
gap: theme.spacing.sm,
alignItems: layout === 'horizontal' ? 'center' : 'stretch',
...style
};
// Handle button actions
const handleUndo = async () => {
if (!disabled && canUndo) {
try {
const result = await undo();
onUndo?.(result);
}
catch (error) {
onUndo?.({ success: false, error: error instanceof Error ? error.message : 'Undo failed' });
}
}
};
const handleRedo = async () => {
if (!disabled && canRedo) {
try {
const result = await redo();
onRedo?.(result);
}
catch (error) {
onRedo?.({ success: false, error: error instanceof Error ? error.message : 'Redo failed' });
}
}
};
// Hover state management
const [undoHovered, setUndoHovered] = (0, react_1.useState)(false);
const [redoHovered, setRedoHovered] = (0, react_1.useState)(false);
// Icons (using Unicode symbols for simplicity - can be replaced with icon library)
const UndoIcon = () => ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: currentSize.iconSize, lineHeight: 1 }, children: "\u21B6" }));
const RedoIcon = () => ((0, jsx_runtime_1.jsx)("span", { style: { fontSize: currentSize.iconSize, lineHeight: 1 }, children: "\u21B7" }));
return ((0, jsx_runtime_1.jsxs)("div", { className: `qnce-undo-redo-controls ${className}`, style: containerStyle, role: "group", "aria-label": "Undo and redo controls", children: [(0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleUndo, disabled: disabled || !canUndo, style: {
...(disabled || !canUndo ? buttonDisabledStyle : buttonBaseStyle),
...(undoHovered && !disabled && canUndo ? buttonHoverStyle : {})
}, onMouseEnter: () => setUndoHovered(true), onMouseLeave: () => setUndoHovered(false), onFocus: () => setUndoHovered(true), onBlur: () => setUndoHovered(false), "aria-label": `${labels.undo}${undoCount > 0 ? ` (${undoCount} available)` : ''}`, title: `${labels.undo}${undoCount > 0 ? ` (${undoCount} available)` : ''}`, "aria-disabled": disabled || !canUndo, children: [(0, jsx_runtime_1.jsx)(UndoIcon, {}), showLabels && (0, jsx_runtime_1.jsx)("span", { children: labels.undo }), undoCount > 0 && ((0, jsx_runtime_1.jsxs)("span", { style: {
fontSize: theme.typography.fontSize.sm,
opacity: 0.8,
fontWeight: theme.typography.fontWeight.normal
}, children: ["(", undoCount, ")"] }))] }), (0, jsx_runtime_1.jsxs)("button", { type: "button", onClick: handleRedo, disabled: disabled || !canRedo, style: {
...(disabled || !canRedo ? buttonDisabledStyle : buttonBaseStyle),
...(redoHovered && !disabled && canRedo ? buttonHoverStyle : {})
}, onMouseEnter: () => setRedoHovered(true), onMouseLeave: () => setRedoHovered(false), onFocus: () => setRedoHovered(true), onBlur: () => setRedoHovered(false), "aria-label": `${labels.redo}${redoCount > 0 ? ` (${redoCount} available)` : ''}`, title: `${labels.redo}${redoCount > 0 ? ` (${redoCount} available)` : ''}`, "aria-disabled": disabled || !canRedo, children: [(0, jsx_runtime_1.jsx)(RedoIcon, {}), showLabels && (0, jsx_runtime_1.jsx)("span", { children: labels.redo }), redoCount > 0 && ((0, jsx_runtime_1.jsxs)("span", { style: {
fontSize: theme.typography.fontSize.sm,
opacity: 0.8,
fontWeight: theme.typography.fontWeight.normal
}, children: ["(", redoCount, ")"] }))] })] }));
};
exports.UndoRedoControls = UndoRedoControls;
//# sourceMappingURL=UndoRedoControls.js.map