@ichigo_san/graphing
Version:
A lightweight UML-style diagram editor built with React Flow and Tailwind CSS
263 lines (250 loc) • 12.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _lucideReact = require("lucide-react");
var _gradientUtils = require("../utils/gradientUtils");
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); }
// Advanced gradient picker component for the Properties Editor
// Provides both simple and advanced gradient controls
const GradientPicker = ({
value,
onChange,
label = "Background",
disabled = false,
showPresets = true,
allowPatterns = false
}) => {
var _gradientDef$colors$, _gradientDef$colors$2;
const [isAdvancedMode, setIsAdvancedMode] = (0, _react.useState)(false);
const [gradientDef, setGradientDef] = (0, _react.useState)(() => {
// Initialize from value - could be color string or gradient object
if (typeof value === 'string') {
return (0, _gradientUtils.cssToGradient)(value);
}
return value || (0, _gradientUtils.createGradient)(_gradientUtils.GRADIENT_TYPES.SOLID, [{
color: '#ffffff',
position: 0
}]);
});
// Update gradient definition when value changes externally
(0, _react.useEffect)(() => {
if (typeof value === 'string') {
setGradientDef((0, _gradientUtils.cssToGradient)(value));
} else if (value) {
setGradientDef(value);
}
}, [value]);
// Handle gradient changes
const handleGradientChange = (0, _react.useCallback)(newGradientDef => {
setGradientDef(newGradientDef);
const cssValue = (0, _gradientUtils.gradientToCss)(newGradientDef);
onChange(cssValue);
}, [onChange]);
// Handle type change
const handleTypeChange = (0, _react.useCallback)(newType => {
const newGradient = {
...gradientDef,
type: newType
};
// Ensure we have at least 2 colors for gradients
if (newType !== _gradientUtils.GRADIENT_TYPES.SOLID && newGradient.colors.length < 2) {
var _newGradient$colors$;
newGradient.colors = [{
color: ((_newGradient$colors$ = newGradient.colors[0]) === null || _newGradient$colors$ === void 0 ? void 0 : _newGradient$colors$.color) || '#3b82f6',
position: 0
}, {
color: '#6366f1',
position: 100
}];
}
handleGradientChange(newGradient);
}, [gradientDef, handleGradientChange]);
// Handle direction change
const handleDirectionChange = (0, _react.useCallback)(newDirection => {
handleGradientChange({
...gradientDef,
direction: newDirection
});
}, [gradientDef, handleGradientChange]);
// Add color stop
const addColorStop = (0, _react.useCallback)(() => {
const colors = [...gradientDef.colors];
const newPosition = colors.length > 0 ? Math.min(100, Math.max(...colors.map(c => c.position)) + 25) : 50;
colors.push({
color: '#6366f1',
position: newPosition
});
handleGradientChange({
...gradientDef,
colors
});
}, [gradientDef, handleGradientChange]);
// Remove color stop
const removeColorStop = (0, _react.useCallback)(index => {
if (gradientDef.colors.length <= 1) return; // Keep at least one color
const colors = gradientDef.colors.filter((_, i) => i !== index);
handleGradientChange({
...gradientDef,
colors
});
}, [gradientDef, handleGradientChange]);
// Update color stop
const updateColorStop = (0, _react.useCallback)((index, updates) => {
const colors = [...gradientDef.colors];
colors[index] = {
...colors[index],
...updates
};
handleGradientChange({
...gradientDef,
colors
});
}, [gradientDef, handleGradientChange]);
// Apply preset
const applyPreset = (0, _react.useCallback)(presetGradient => {
handleGradientChange(presetGradient);
}, [handleGradientChange]);
// Render color stop editor
const renderColorStop = (colorStop, index) => /*#__PURE__*/_react.default.createElement("div", {
key: index,
className: "flex items-center gap-2 mb-2 p-2 bg-gray-50 dark:bg-gray-700 rounded"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "color",
value: colorStop.color,
onChange: e => updateColorStop(index, {
color: e.target.value
}),
className: "w-8 h-8 p-0 border border-gray-300 dark:border-gray-600 rounded cursor-pointer",
disabled: disabled
}), /*#__PURE__*/_react.default.createElement("input", {
type: "text",
value: colorStop.color,
onChange: e => updateColorStop(index, {
color: e.target.value
}),
className: "flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded font-mono",
disabled: disabled
}), /*#__PURE__*/_react.default.createElement("input", {
type: "number",
value: colorStop.position,
onChange: e => updateColorStop(index, {
position: Math.max(0, Math.min(100, parseFloat(e.target.value) || 0))
}),
min: "0",
max: "100",
className: "w-16 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded",
disabled: disabled
}), /*#__PURE__*/_react.default.createElement("span", {
className: "text-xs text-gray-500"
}, "%"), gradientDef.colors.length > 1 && /*#__PURE__*/_react.default.createElement("button", {
onClick: () => removeColorStop(index),
className: "p-1 text-red-500 hover:bg-red-100 dark:hover:bg-red-900/20 rounded",
disabled: disabled
}, /*#__PURE__*/_react.default.createElement(_lucideReact.X, {
size: 12
})));
// Get current CSS value for preview
const previewStyle = {
background: (0, _gradientUtils.ensureBackwardCompatibility)(gradientDef),
width: '100%',
height: '40px',
borderRadius: '4px',
border: '1px solid #e5e7eb'
};
const presets = (0, _gradientUtils.getGradientPresets)();
return /*#__PURE__*/_react.default.createElement("div", {
className: "mb-4"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "block mb-2 text-sm font-medium text-gray-700 dark:text-gray-300"
}, label, ":"), /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("div", {
style: previewStyle
})), /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "block mb-1 text-xs font-medium text-gray-600 dark:text-gray-400"
}, "Type:"), /*#__PURE__*/_react.default.createElement("select", {
value: gradientDef.type,
onChange: e => handleTypeChange(e.target.value),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500",
disabled: disabled
}, /*#__PURE__*/_react.default.createElement("option", {
value: _gradientUtils.GRADIENT_TYPES.SOLID
}, "Solid Color"), /*#__PURE__*/_react.default.createElement("option", {
value: _gradientUtils.GRADIENT_TYPES.LINEAR
}, "Linear Gradient"), /*#__PURE__*/_react.default.createElement("option", {
value: _gradientUtils.GRADIENT_TYPES.RADIAL
}, "Radial Gradient"), /*#__PURE__*/_react.default.createElement("option", {
value: _gradientUtils.GRADIENT_TYPES.CONIC
}, "Conic Gradient"))), gradientDef.type === _gradientUtils.GRADIENT_TYPES.SOLID && /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center gap-2"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "color",
value: ((_gradientDef$colors$ = gradientDef.colors[0]) === null || _gradientDef$colors$ === void 0 ? void 0 : _gradientDef$colors$.color) || '#ffffff',
onChange: e => updateColorStop(0, {
color: e.target.value
}),
className: "w-12 h-10 p-0 border border-gray-300 dark:border-gray-600 rounded cursor-pointer",
disabled: disabled
}), /*#__PURE__*/_react.default.createElement("input", {
type: "text",
value: ((_gradientDef$colors$2 = gradientDef.colors[0]) === null || _gradientDef$colors$2 === void 0 ? void 0 : _gradientDef$colors$2.color) || '#ffffff',
onChange: e => updateColorStop(0, {
color: e.target.value
}),
className: "flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 font-mono",
disabled: disabled
})), gradientDef.type !== _gradientUtils.GRADIENT_TYPES.SOLID && /*#__PURE__*/_react.default.createElement("div", null, gradientDef.type === _gradientUtils.GRADIENT_TYPES.LINEAR && /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "block mb-1 text-xs font-medium text-gray-600 dark:text-gray-400"
}, "Direction:"), /*#__PURE__*/_react.default.createElement("select", {
value: gradientDef.direction,
onChange: e => handleDirectionChange(e.target.value),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500",
disabled: disabled
}, Object.entries(_gradientUtils.GRADIENT_DIRECTIONS).map(([key, value]) => /*#__PURE__*/_react.default.createElement("option", {
key: key,
value: value
}, value.replace('to ', '').replace(/\b\w/g, l => l.toUpperCase()))))), /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center justify-between mb-2"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "text-xs font-medium text-gray-600 dark:text-gray-400"
}, "Colors:"), /*#__PURE__*/_react.default.createElement("button", {
onClick: addColorStop,
className: "flex items-center gap-1 px-2 py-1 text-xs bg-indigo-500 text-white rounded hover:bg-indigo-600",
disabled: disabled
}, /*#__PURE__*/_react.default.createElement(_lucideReact.Plus, {
size: 12
}), "Add")), gradientDef.colors.map((colorStop, index) => renderColorStop(colorStop, index)))), showPresets && /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("button", {
onClick: () => setIsAdvancedMode(!isAdvancedMode),
className: "flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200"
}, /*#__PURE__*/_react.default.createElement(_lucideReact.ChevronRight, {
className: `transition-transform ${isAdvancedMode ? 'rotate-90' : ''}`,
size: 12
}), "Presets"), isAdvancedMode && /*#__PURE__*/_react.default.createElement("div", {
className: "mt-2 grid grid-cols-3 gap-2"
}, Object.entries(presets).map(([name, preset]) => /*#__PURE__*/_react.default.createElement("button", {
key: name,
onClick: () => applyPreset(preset),
className: "relative h-8 rounded border border-gray-300 dark:border-gray-600 hover:border-indigo-500 overflow-hidden group",
style: {
background: (0, _gradientUtils.gradientToCss)(preset)
},
disabled: disabled,
title: name.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())
}, /*#__PURE__*/_react.default.createElement("div", {
className: "absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-10 flex items-center justify-center"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "text-xs text-white opacity-0 group-hover:opacity-100 drop-shadow"
}, name.charAt(0).toUpperCase())))))));
};
var _default = exports.default = GradientPicker;