Release v1.01 Enhanced: Vi Control, TUI Gen5, Core Stability
This commit is contained in:
141
bin/ui/components/Toast.mjs
Normal file
141
bin/ui/components/Toast.mjs
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Toast Component - Minimal confirmations
|
||||
*
|
||||
* DESIGN:
|
||||
* - Copy/applied/saved/reverted appear as brief toasts
|
||||
* - Don't add to transcript (displayed separately)
|
||||
* - Auto-dismiss after timeout
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { colors } from '../../tui-theme.mjs';
|
||||
import { icon } from '../../icons.mjs';
|
||||
import { getCapabilities } from '../../terminal-profile.mjs';
|
||||
|
||||
const h = React.createElement;
|
||||
|
||||
/**
|
||||
* Toast - Single toast notification
|
||||
*/
|
||||
const Toast = ({
|
||||
message,
|
||||
type = 'info', // info, success, warning, error
|
||||
duration = 3000,
|
||||
onDismiss = null
|
||||
}) => {
|
||||
const caps = getCapabilities();
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setVisible(false);
|
||||
onDismiss?.();
|
||||
}, duration);
|
||||
return () => clearTimeout(timer);
|
||||
}, [duration, onDismiss]);
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
const typeConfig = {
|
||||
info: { color: colors.accent, icon: caps.unicodeOK ? 'ℹ' : 'i' },
|
||||
success: { color: colors.success, icon: caps.unicodeOK ? '✓' : '+' },
|
||||
warning: { color: colors.warning, icon: caps.unicodeOK ? '⚠' : '!' },
|
||||
error: { color: colors.error, icon: caps.unicodeOK ? '✗' : 'X' }
|
||||
};
|
||||
|
||||
const config = typeConfig[type] || typeConfig.info;
|
||||
|
||||
return h(Box, {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
paddingX: 1
|
||||
},
|
||||
h(Text, { color: config.color }, config.icon + ' '),
|
||||
h(Text, { color: config.color }, message)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* ToastContainer - Manages multiple toasts
|
||||
*/
|
||||
const ToastContainer = ({ toasts = [], onDismiss }) => {
|
||||
if (toasts.length === 0) return null;
|
||||
|
||||
return h(Box, {
|
||||
flexDirection: 'column',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: 0
|
||||
},
|
||||
...toasts.map((toast, i) =>
|
||||
h(Toast, {
|
||||
key: toast.id || i,
|
||||
message: toast.message,
|
||||
type: toast.type,
|
||||
duration: toast.duration,
|
||||
onDismiss: () => onDismiss?.(toast.id || i)
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* useToasts - Hook for managing toasts
|
||||
*/
|
||||
const createToastManager = () => {
|
||||
let toasts = [];
|
||||
let listeners = [];
|
||||
let nextId = 0;
|
||||
|
||||
const subscribe = (listener) => {
|
||||
listeners.push(listener);
|
||||
return () => {
|
||||
listeners = listeners.filter(l => l !== listener);
|
||||
};
|
||||
};
|
||||
|
||||
const notify = () => {
|
||||
listeners.forEach(l => l(toasts));
|
||||
};
|
||||
|
||||
const add = (message, type = 'info', duration = 3000) => {
|
||||
const id = nextId++;
|
||||
toasts = [...toasts, { id, message, type, duration }];
|
||||
notify();
|
||||
|
||||
setTimeout(() => {
|
||||
toasts = toasts.filter(t => t.id !== id);
|
||||
notify();
|
||||
}, duration);
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
const dismiss = (id) => {
|
||||
toasts = toasts.filter(t => t.id !== id);
|
||||
notify();
|
||||
};
|
||||
|
||||
return { subscribe, add, dismiss, get: () => toasts };
|
||||
};
|
||||
|
||||
// Global toast manager (singleton)
|
||||
const toastManager = createToastManager();
|
||||
|
||||
// Convenience methods
|
||||
const showToast = (message, type, duration) => toastManager.add(message, type, duration);
|
||||
const showSuccess = (message) => showToast(message, 'success', 2000);
|
||||
const showError = (message) => showToast(message, 'error', 4000);
|
||||
const showInfo = (message) => showToast(message, 'info', 3000);
|
||||
|
||||
export default Toast;
|
||||
export {
|
||||
Toast,
|
||||
ToastContainer,
|
||||
toastManager,
|
||||
showToast,
|
||||
showSuccess,
|
||||
showError,
|
||||
showInfo
|
||||
};
|
||||
Reference in New Issue
Block a user