UNPKG

@ichigo_san/graphing

Version:

A lightweight UML-style diagram editor built with React Flow and Tailwind CSS

349 lines (334 loc) 8.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.shadowToCss = exports.isValidShadow = exports.getShadowPresets = exports.ensureShadowCompatibility = exports.cssToShadow = exports.createShadow = exports.createOpacity = exports.createCustomShadow = exports.SHADOW_TYPES = exports.SHADOW_PRESETS = void 0; // Shadow and effects utility functions for advanced styling // Provides professional shadow effects and visual enhancements const SHADOW_TYPES = exports.SHADOW_TYPES = { NONE: 'none', DROP_SHADOW: 'drop-shadow', BOX_SHADOW: 'box-shadow', INNER_SHADOW: 'inner-shadow', GLOW: 'glow', MULTI_LAYER: 'multi-layer' }; const SHADOW_PRESETS = exports.SHADOW_PRESETS = { // No shadow none: { type: SHADOW_TYPES.NONE, shadows: [] }, // Subtle shadows subtle: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 1, blur: 3, spread: 0, color: 'rgba(0, 0, 0, 0.1)' }] }, // Standard drop shadows small: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 2, blur: 4, spread: 0, color: 'rgba(0, 0, 0, 0.15)' }] }, medium: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 4, blur: 8, spread: 0, color: 'rgba(0, 0, 0, 0.15)' }] }, large: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 8, blur: 16, spread: 0, color: 'rgba(0, 0, 0, 0.15)' }] }, // Elevated shadows elevated: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 4, blur: 12, spread: -2, color: 'rgba(0, 0, 0, 0.12)' }, { x: 0, y: 8, blur: 24, spread: -4, color: 'rgba(0, 0, 0, 0.08)' }] }, // Floating effect floating: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 12, blur: 20, spread: -8, color: 'rgba(0, 0, 0, 0.2)' }, { x: 0, y: 4, blur: 8, spread: -2, color: 'rgba(0, 0, 0, 0.1)' }] }, // Glow effects blueGlow: { type: SHADOW_TYPES.GLOW, shadows: [{ x: 0, y: 0, blur: 8, spread: 0, color: 'rgba(59, 130, 246, 0.5)' }] }, greenGlow: { type: SHADOW_TYPES.GLOW, shadows: [{ x: 0, y: 0, blur: 8, spread: 0, color: 'rgba(34, 197, 94, 0.5)' }] }, // Inner shadows inset: { type: SHADOW_TYPES.INNER_SHADOW, shadows: [{ x: 0, y: 2, blur: 4, spread: 0, color: 'rgba(0, 0, 0, 0.1)', inset: true }] }, // Professional card style card: { type: SHADOW_TYPES.BOX_SHADOW, shadows: [{ x: 0, y: 1, blur: 3, spread: 0, color: 'rgba(0, 0, 0, 0.12)' }, { x: 0, y: 1, blur: 2, spread: 0, color: 'rgba(0, 0, 0, 0.24)' }] } }; /** * Creates a shadow definition object * @param {string} type - Type of shadow effect * @param {Array} shadows - Array of shadow objects * @returns {Object} Shadow definition */ const createShadow = (type = SHADOW_TYPES.NONE, shadows = []) => { return { type, shadows: shadows || [] }; }; /** * Converts shadow definition to CSS box-shadow string * @param {Object|string} shadowDef - Shadow definition object or 'none' * @returns {string} CSS box-shadow value */ exports.createShadow = createShadow; const shadowToCss = shadowDef => { var _shadowDef$shadows; // Backward compatibility: if it's a string, return as-is if (typeof shadowDef === 'string') { return shadowDef; } // If no shadow definition or none type, return none if (!shadowDef || shadowDef.type === SHADOW_TYPES.NONE || !((_shadowDef$shadows = shadowDef.shadows) !== null && _shadowDef$shadows !== void 0 && _shadowDef$shadows.length)) { return 'none'; } const { shadows } = shadowDef; // Convert shadow objects to CSS strings const shadowStrings = shadows.map(shadow => { const { x = 0, y = 0, blur = 0, spread = 0, color = 'rgba(0, 0, 0, 0.15)', inset = false } = shadow; const insetStr = inset ? 'inset ' : ''; const spreadStr = spread !== 0 ? ` ${spread}px` : ''; return `${insetStr}${x}px ${y}px ${blur}px${spreadStr} ${color}`; }); return shadowStrings.join(', '); }; /** * Parses CSS box-shadow to shadow definition (basic implementation) * @param {string} cssBoxShadow - CSS box-shadow value * @returns {Object} Shadow definition object */ exports.shadowToCss = shadowToCss; const cssToShadow = cssBoxShadow => { if (!cssBoxShadow || cssBoxShadow === 'none') { return createShadow(SHADOW_TYPES.NONE); } // Simple parsing - for complex shadows, this is a basic implementation // In production, you might want a more robust parser try { const shadowStrings = cssBoxShadow.split(', '); const shadows = shadowStrings.map(shadowStr => { const parts = shadowStr.trim().split(/\s+/); const inset = parts[0] === 'inset'; const startIndex = inset ? 1 : 0; return { x: parseInt(parts[startIndex]) || 0, y: parseInt(parts[startIndex + 1]) || 0, blur: parseInt(parts[startIndex + 2]) || 0, spread: parseInt(parts[startIndex + 3]) || 0, color: parts.slice(startIndex + 4).join(' ') || 'rgba(0, 0, 0, 0.15)', inset }; }); return createShadow(SHADOW_TYPES.BOX_SHADOW, shadows); } catch (error) { console.warn('Failed to parse shadow CSS:', error); return createShadow(SHADOW_TYPES.NONE); } }; /** * Gets shadow presets organized by category * @returns {Object} Categorized shadow presets */ exports.cssToShadow = cssToShadow; const getShadowPresets = () => { return { basic: { none: SHADOW_PRESETS.none, subtle: SHADOW_PRESETS.subtle, small: SHADOW_PRESETS.small, medium: SHADOW_PRESETS.medium, large: SHADOW_PRESETS.large }, elevated: { elevated: SHADOW_PRESETS.elevated, floating: SHADOW_PRESETS.floating, card: SHADOW_PRESETS.card }, effects: { blueGlow: SHADOW_PRESETS.blueGlow, greenGlow: SHADOW_PRESETS.greenGlow, inset: SHADOW_PRESETS.inset } }; }; /** * Creates custom shadow with common parameters * @param {Object} options - Shadow options * @returns {Object} Shadow definition */ exports.getShadowPresets = getShadowPresets; const createCustomShadow = ({ offsetX = 0, offsetY = 4, blur = 8, spread = 0, color = 'rgba(0, 0, 0, 0.15)', inset = false } = {}) => { return createShadow(SHADOW_TYPES.BOX_SHADOW, [{ x: offsetX, y: offsetY, blur, spread, color, inset }]); }; /** * Validates shadow definition * @param {Object} shadowDef - Shadow definition to validate * @returns {boolean} True if valid */ exports.createCustomShadow = createCustomShadow; const isValidShadow = shadowDef => { if (!shadowDef || typeof shadowDef !== 'object') { return false; } const { type, shadows } = shadowDef; if (!Object.values(SHADOW_TYPES).includes(type)) { return false; } if (type === SHADOW_TYPES.NONE) { return true; // None type doesn't need shadows array } if (!Array.isArray(shadows)) { return false; } // Validate shadow objects for (const shadow of shadows) { if (typeof shadow !== 'object' || !shadow.color) { return false; } } return true; }; /** * Ensures backward compatibility with existing shadow properties * @param {*} shadowOrString - Either a shadow object or CSS string * @returns {string} CSS box-shadow value */ exports.isValidShadow = isValidShadow; const ensureShadowCompatibility = shadowOrString => { if (typeof shadowOrString === 'string') { return shadowOrString; } if (isValidShadow(shadowOrString)) { return shadowToCss(shadowOrString); } // Fallback to no shadow if invalid return 'none'; }; /** * Creates opacity effect * @param {number} opacity - Opacity value (0-1) * @returns {number} Clamped opacity value */ exports.ensureShadowCompatibility = ensureShadowCompatibility; const createOpacity = (opacity = 1) => { return Math.max(0, Math.min(1, opacity)); }; exports.createOpacity = createOpacity;