@ichigo_san/graphing
Version:
A lightweight UML-style diagram editor built with React Flow and Tailwind CSS
280 lines (278 loc) • 11.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _lucideReact = require("lucide-react");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const EnhancedMenuBar = _ref => {
let {
onNew,
onOpen,
onSave,
onSaveAs,
onImportJSON,
onImportJSONText,
onImportDrawio,
onExportJSON,
onExportDrawio,
onExportPNG,
onExportJPG,
onExportSVG,
onUndo,
onRedo,
onCut,
onCopy,
onPaste,
onDelete,
onSelectAll,
onDeselectAll,
onAddContainer,
onAddComponent,
onAddShape,
onLinkNodes,
onUnlinkNodes,
onValidateJSON,
onAutoLayout,
onTogglePropertiesPanel,
onToggleStatsPanel,
onToggleTheme,
showThemeToggle = false,
onToggleMini,
showMiniToggle = false,
canUndo = false,
canRedo = false,
hasSelection = false,
hasClipboard = false,
canLink = false
} = _ref;
const [activeMenu, setActiveMenu] = (0, _react.useState)(null);
const menuRef = (0, _react.useRef)(null);
// Close menu when clicking outside
(0, _react.useEffect)(() => {
const handleClickOutside = event => {
if (menuRef.current && !menuRef.current.contains(event.target)) {
setActiveMenu(null);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
const handleMenuClick = (0, _react.useCallback)(menuName => {
setActiveMenu(activeMenu === menuName ? null : menuName);
}, [activeMenu]);
const handleMenuItemClick = (0, _react.useCallback)(action => {
if (action) {
action();
}
setActiveMenu(null);
}, []);
const MenuButton = _ref2 => {
let {
name,
icon: Icon,
children
} = _ref2;
return /*#__PURE__*/_react.default.createElement("div", {
className: "relative"
}, /*#__PURE__*/_react.default.createElement("button", {
className: "flex items-center gap-2 px-3 py-1.5 text-gray-800 dark:text-gray-100 bg-white dark:bg-gray-900 text-sm font-medium rounded-md transition-colors ".concat(activeMenu === name ? 'bg-gray-200 dark:bg-gray-700 shadow-sm' : 'hover:bg-gray-100 dark:hover:bg-gray-700'),
onClick: () => handleMenuClick(name)
}, /*#__PURE__*/_react.default.createElement(Icon, {
size: 16
}), /*#__PURE__*/_react.default.createElement("span", null, name), /*#__PURE__*/_react.default.createElement(_lucideReact.ChevronDown, {
size: 12
})), activeMenu === name && /*#__PURE__*/_react.default.createElement("div", {
className: "absolute top-full left-0 mt-1 bg-white dark:bg-gray-800 shadow-lg rounded-lg min-w-[200px] z-50 animate-fadeIn"
}, children));
};
const MenuItem = _ref3 => {
let {
onClick,
disabled = false,
children,
shortcut = null,
separator = false,
icon: Icon = null
} = _ref3;
if (separator) {
return /*#__PURE__*/_react.default.createElement("div", {
className: "h-px my-1 bg-gray-200 dark:bg-gray-700"
});
}
return /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center justify-between px-4 py-2.5 text-gray-700 dark:text-gray-200 text-sm cursor-pointer transition-all ".concat(disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-100 dark:hover:bg-gray-700 hover:translate-x-0.5'),
onClick: disabled ? undefined : () => handleMenuItemClick(onClick)
}, /*#__PURE__*/_react.default.createElement("span", {
className: "flex items-center gap-2"
}, Icon && /*#__PURE__*/_react.default.createElement(Icon, {
size: 14
}), children), shortcut && /*#__PURE__*/_react.default.createElement("span", {
className: "text-xs bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 px-1.5 py-0.5 rounded font-mono border border-gray-200 dark:border-gray-600"
}, shortcut));
};
return /*#__PURE__*/_react.default.createElement("div", {
ref: menuRef,
className: "flex items-center bg-white dark:bg-gray-900 p-0 relative z-10 border-b border-gray-200 dark:border-gray-700"
}, /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "File",
icon: _lucideReact.File
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onNew,
shortcut: "Ctrl+N"
}, "New Diagram"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onOpen,
shortcut: "Ctrl+O"
}, "Open..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onSave,
shortcut: "Ctrl+S"
}, "Save"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onSaveAs,
shortcut: "Ctrl+Shift+S"
}, "Save As..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onImportJSON
}, "Import JSON..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onImportJSONText
}, "Paste JSON..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onImportDrawio
}, "Import Draw.io XML..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onExportJSON
}, "Export as JSON"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onExportDrawio
}, "Export as Draw.io XML"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onExportPNG
}, "Export as PNG"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onExportJPG
}, "Export as JPG"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onExportSVG
}, "Export as SVG")), /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "Edit",
icon: _lucideReact.Edit
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onUndo,
disabled: !canUndo,
shortcut: "Ctrl+Z",
icon: _lucideReact.ChevronDown
}, "Undo"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onRedo,
disabled: !canRedo,
shortcut: "Ctrl+Y"
}, "Redo"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onCut,
disabled: !hasSelection,
shortcut: "Ctrl+X"
}, "Cut"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onCopy,
disabled: !hasSelection,
shortcut: "Ctrl+C",
icon: _lucideReact.Copy
}, "Copy"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onPaste,
disabled: !hasClipboard,
shortcut: "Ctrl+V"
}, "Paste"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onDelete,
disabled: !hasSelection,
shortcut: "Delete",
icon: _lucideReact.Trash
}, "Delete"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onSelectAll,
shortcut: "Ctrl+A"
}, "Select All"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onDeselectAll,
disabled: !hasSelection
}, "Deselect All"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onAddContainer,
icon: _lucideReact.Plus
}, "Add Container"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onAddComponent
}, "Add Component"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onAddShape
}, "Add Shape")), /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "Connect",
icon: _lucideReact.Link
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onLinkNodes,
disabled: !canLink,
icon: _lucideReact.Link
}, "Link Selected Nodes"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onUnlinkNodes,
disabled: !hasSelection,
icon: _lucideReact.Unlink
}, "Unlink Selected")), /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "View",
icon: _lucideReact.Eye
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Zoom In"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Zoom Out"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Fit to Screen"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Show Grid"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Show Rulers"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Toggle Minimap"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onTogglePropertiesPanel
}, "Toggle Properties Panel"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onToggleStatsPanel
}, "Toggle Diagram Stats"), showMiniToggle && /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onToggleMini
}, "Toggle Mini Editor"), showThemeToggle && /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onToggleTheme
}, "Toggle Dark Mode")), /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "Settings",
icon: _lucideReact.Settings
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Diagram Templates..."), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onValidateJSON
}, "JSON Schema Validator"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: onAutoLayout
}, "Auto-Layout"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Align Elements"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Preferences...")), /*#__PURE__*/_react.default.createElement(MenuButton, {
name: "Help",
icon: _lucideReact.HelpCircle
}, /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "Keyboard Shortcuts"), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "User Guide"), /*#__PURE__*/_react.default.createElement(MenuItem, {
separator: true
}), /*#__PURE__*/_react.default.createElement(MenuItem, {
onClick: () => {}
}, "About")));
};
var _default = exports.default = EnhancedMenuBar;