@ichigo_san/graphing
Version:
A lightweight UML-style diagram editor built with React Flow and Tailwind CSS
277 lines (266 loc) • 13.3 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 _shadowUtils = require("../utils/shadowUtils");
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 shadow picker component for the Properties Editor
// Provides professional shadow effects and visual controls
const ShadowPicker = ({
value,
onChange,
label = "Shadow",
disabled = false,
showPresets = true
}) => {
const [isPresetsExpanded, setIsPresetsExpanded] = (0, _react.useState)(false);
const [shadowDef, setShadowDef] = (0, _react.useState)(() => {
// Initialize from value - could be CSS string or shadow object
if (typeof value === 'string') {
return (0, _shadowUtils.cssToShadow)(value);
}
return value || (0, _shadowUtils.createShadow)(_shadowUtils.SHADOW_TYPES.NONE);
});
// Update shadow definition when value changes externally
(0, _react.useEffect)(() => {
if (typeof value === 'string') {
setShadowDef((0, _shadowUtils.cssToShadow)(value));
} else if (value) {
setShadowDef(value);
}
}, [value]);
// Handle shadow changes
const handleShadowChange = (0, _react.useCallback)(newShadowDef => {
setShadowDef(newShadowDef);
const cssValue = (0, _shadowUtils.shadowToCss)(newShadowDef);
onChange(cssValue);
}, [onChange]);
// Handle type change
const handleTypeChange = (0, _react.useCallback)(newType => {
if (newType === _shadowUtils.SHADOW_TYPES.NONE) {
handleShadowChange((0, _shadowUtils.createShadow)(_shadowUtils.SHADOW_TYPES.NONE));
} else {
// Start with a basic shadow for non-none types
const basicShadow = (0, _shadowUtils.createCustomShadow)({
offsetY: 4,
blur: 8
});
handleShadowChange({
...basicShadow,
type: newType
});
}
}, [handleShadowChange]);
// Update shadow parameter
const updateShadowParam = (0, _react.useCallback)((index, param, value) => {
const shadows = [...shadowDef.shadows];
if (shadows[index]) {
shadows[index] = {
...shadows[index],
[param]: value
};
handleShadowChange({
...shadowDef,
shadows
});
}
}, [shadowDef, handleShadowChange]);
// Add shadow layer
const addShadowLayer = (0, _react.useCallback)(() => {
const shadows = [...shadowDef.shadows];
shadows.push({
x: 0,
y: 4,
blur: 8,
spread: 0,
color: 'rgba(0, 0, 0, 0.15)'
});
handleShadowChange({
...shadowDef,
shadows
});
}, [shadowDef, handleShadowChange]);
// Remove shadow layer
const removeShadowLayer = (0, _react.useCallback)(index => {
if (shadowDef.shadows.length <= 1) {
handleShadowChange((0, _shadowUtils.createShadow)(_shadowUtils.SHADOW_TYPES.NONE));
return;
}
const shadows = shadowDef.shadows.filter((_, i) => i !== index);
handleShadowChange({
...shadowDef,
shadows
});
}, [shadowDef, handleShadowChange]);
// Apply preset
const applyPreset = (0, _react.useCallback)(presetShadow => {
handleShadowChange(presetShadow);
}, [handleShadowChange]);
// Render shadow layer editor
const renderShadowLayer = (shadow, index) => {
var _shadow$color;
return /*#__PURE__*/_react.default.createElement("div", {
key: index,
className: "p-3 bg-gray-50 dark:bg-gray-700 rounded border mb-2"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center justify-between mb-2"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "text-xs font-medium text-gray-600 dark:text-gray-400"
}, "Shadow Layer ", index + 1), shadowDef.shadows.length > 1 && /*#__PURE__*/_react.default.createElement("button", {
onClick: () => removeShadowLayer(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
}))), /*#__PURE__*/_react.default.createElement("div", {
className: "grid grid-cols-2 gap-2 mb-2"
}, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
className: "block text-xs text-gray-600 dark:text-gray-400 mb-1"
}, "X:"), /*#__PURE__*/_react.default.createElement("input", {
type: "number",
value: shadow.x || 0,
onChange: e => updateShadowParam(index, 'x', parseInt(e.target.value) || 0),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded",
disabled: disabled
})), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
className: "block text-xs text-gray-600 dark:text-gray-400 mb-1"
}, "Y:"), /*#__PURE__*/_react.default.createElement("input", {
type: "number",
value: shadow.y || 0,
onChange: e => updateShadowParam(index, 'y', parseInt(e.target.value) || 0),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded",
disabled: disabled
})), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
className: "block text-xs text-gray-600 dark:text-gray-400 mb-1"
}, "Blur:"), /*#__PURE__*/_react.default.createElement("input", {
type: "number",
value: shadow.blur || 0,
min: "0",
onChange: e => updateShadowParam(index, 'blur', Math.max(0, parseInt(e.target.value) || 0)),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded",
disabled: disabled
})), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
className: "block text-xs text-gray-600 dark:text-gray-400 mb-1"
}, "Spread:"), /*#__PURE__*/_react.default.createElement("input", {
type: "number",
value: shadow.spread || 0,
onChange: e => updateShadowParam(index, 'spread', parseInt(e.target.value) || 0),
className: "w-full px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded",
disabled: disabled
}))), /*#__PURE__*/_react.default.createElement("div", {
className: "mb-2"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "block text-xs text-gray-600 dark:text-gray-400 mb-1"
}, "Color:"), /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center gap-2"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "color",
value: (_shadow$color = shadow.color) !== null && _shadow$color !== void 0 && _shadow$color.includes('rgba') ? '#000000' : shadow.color || '#000000',
onChange: e => updateShadowParam(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: shadow.color || 'rgba(0, 0, 0, 0.15)',
onChange: e => updateShadowParam(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",
placeholder: "rgba(0, 0, 0, 0.15)",
disabled: disabled
}))), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", {
className: "flex items-center gap-2 cursor-pointer"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "checkbox",
checked: shadow.inset || false,
onChange: e => updateShadowParam(index, 'inset', e.target.checked),
className: "rounded",
disabled: disabled
}), /*#__PURE__*/_react.default.createElement("span", {
className: "text-xs text-gray-600 dark:text-gray-400"
}, "Inner shadow"))));
};
// Get current CSS value for preview
const previewStyle = {
background: '#ffffff',
width: '60px',
height: '40px',
borderRadius: '4px',
border: '1px solid #e5e7eb',
boxShadow: (0, _shadowUtils.ensureShadowCompatibility)(shadowDef),
margin: '10px auto'
};
const presets = (0, _shadowUtils.getShadowPresets)();
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 p-3 bg-gray-100 dark:bg-gray-800 rounded"
}, /*#__PURE__*/_react.default.createElement("div", {
style: previewStyle
}), /*#__PURE__*/_react.default.createElement("div", {
className: "text-center text-xs text-gray-500 dark:text-gray-400 mt-1"
}, "Preview")), /*#__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: shadowDef.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: _shadowUtils.SHADOW_TYPES.NONE
}, "No Shadow"), /*#__PURE__*/_react.default.createElement("option", {
value: _shadowUtils.SHADOW_TYPES.BOX_SHADOW
}, "Box Shadow"), /*#__PURE__*/_react.default.createElement("option", {
value: _shadowUtils.SHADOW_TYPES.DROP_SHADOW
}, "Drop Shadow"), /*#__PURE__*/_react.default.createElement("option", {
value: _shadowUtils.SHADOW_TYPES.GLOW
}, "Glow Effect"), /*#__PURE__*/_react.default.createElement("option", {
value: _shadowUtils.SHADOW_TYPES.MULTI_LAYER
}, "Multi-layer"))), shadowDef.type !== _shadowUtils.SHADOW_TYPES.NONE && /*#__PURE__*/_react.default.createElement("div", null, /*#__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"
}, "Shadow Layers:"), /*#__PURE__*/_react.default.createElement("button", {
onClick: addShadowLayer,
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 Layer")), shadowDef.shadows.map((shadow, index) => renderShadowLayer(shadow, index)))), showPresets && /*#__PURE__*/_react.default.createElement("div", {
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("button", {
onClick: () => setIsPresetsExpanded(!isPresetsExpanded),
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 ${isPresetsExpanded ? 'rotate-90' : ''}`,
size: 12
}), "Shadow Presets"), isPresetsExpanded && /*#__PURE__*/_react.default.createElement("div", {
className: "mt-2"
}, Object.entries(presets).map(([categoryName, categoryPresets]) => /*#__PURE__*/_react.default.createElement("div", {
key: categoryName,
className: "mb-3"
}, /*#__PURE__*/_react.default.createElement("div", {
className: "text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2"
}, categoryName), /*#__PURE__*/_react.default.createElement("div", {
className: "grid grid-cols-2 gap-2"
}, Object.entries(categoryPresets).map(([name, preset]) => /*#__PURE__*/_react.default.createElement("button", {
key: name,
onClick: () => applyPreset(preset),
className: "relative p-3 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded hover:border-indigo-500 transition-colors",
style: {
boxShadow: (0, _shadowUtils.shadowToCss)(preset)
},
disabled: disabled,
title: name.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())
}, /*#__PURE__*/_react.default.createElement("div", {
className: "text-xs font-medium text-gray-700 dark:text-gray-300 capitalize"
}, name.replace(/([A-Z])/g, ' $1'))))))))));
};
var _default = exports.default = ShadowPicker;