UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

164 lines (163 loc) 5.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.suppressTransitions = suppressTransitions; exports.transition = transition; var _includes = _interopRequireDefault(require("core-js-pure/stable/instance/includes.js")); var _push = _interopRequireDefault(require("core-js-pure/stable/instance/push.js")); var _react = require("react"); var _clsx = require("clsx"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function transition(states) { const entries = Object.entries(states); const [defaultName, defaultIcon] = entries[0]; const defaultPoints = parsePath(extractPathD(defaultIcon)); const canMorph = defaultPoints.length > 0 && entries.every(([name, icon]) => { const d = extractPathD(icon); if (!isFullyParseable(d)) { return false; } if (name === defaultName) { return true; } const points = parsePath(d); return points.length === defaultPoints.length; }); const iconFn = props => { const activeState = props?.['data-transition-state'] || defaultName; const { 'data-transition-state': _, ...svgProps } = props || {}; return (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, { children: entries.map(([name, iconRenderer]) => { const element = iconRenderer(svgProps); return (0, _react.cloneElement)(element, { key: name, 'data-icon-state': name, className: (0, _clsx.clsx)(element.props.className, name === activeState && 'dnb-icon__state--active') }); }) }); }; iconFn.__iconTransitionFallback = true; if (canMorph) { const style = {}; for (const [name, icon] of entries) { const points = name === defaultName ? defaultPoints : alignPath(defaultPoints, parsePath(extractPathD(icon))); style[`--icon-transition-${name}`] = `path('${pointsToString(points)}')`; } style['--icon-transition-default'] = `var(--icon-transition-${defaultName})`; iconFn.__iconTransitionStyle = style; } Object.defineProperty(iconFn, 'name', { value: defaultIcon.name }); return iconFn; } transition.activate = (element, state) => { element.querySelectorAll('svg[data-icon-state]').forEach(svg => { svg.classList.toggle('dnb-icon__state--active', svg.dataset.iconState === state); }); if (element.style.getPropertyValue('--icon-transition-default')) { element.style.setProperty('--icon-transition', `var(--icon-transition-${state})`); } }; function suppressTransitions(element, callback) { const targets = [element, ...Array.from(element.querySelectorAll('svg, svg path'))]; for (const el of targets) { el.style.setProperty('transition', 'none'); } callback(); element.getBoundingClientRect(); for (const el of targets) { el.style.removeProperty('transition'); } } transition.isSupported = typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('d: path("M0 0")'); function extractPathD(iconFn) { const svg = iconFn(); return svg.props.children?.props?.d; } function isFullyParseable(d) { if (!d) { return false; } const parts = d.match(/[a-zA-Z][^a-zA-Z]*/g) || []; return parts.every(part => { var _context; return (0, _includes.default)(_context = 'mlhvMLHV').call(_context, part[0]); }); } function parsePath(d) { if (!d) { return []; } const parts = d.match(/[a-zA-Z][^a-zA-Z]*/g) || []; const points = []; let x = 0; let y = 0; for (const part of parts) { const command = part[0]; const type = command.toLowerCase(); const numbers = Array.from(part.slice(1).matchAll(/-?\d*\.?\d+/g), match => Number(match[0])); const isRelative = command === type; const resolve = (current, value) => isRelative ? current + value : value; if (type === 'm' || type === 'l') { for (let i = 0; i < numbers.length; i += 2) { x = resolve(x, numbers[i]); y = resolve(y, numbers[i + 1]); (0, _push.default)(points).call(points, { cmd: i === 0 && type === 'm' ? 'M' : 'L', x, y }); } } else if (type === 'h') { x = resolve(x, numbers[0]); (0, _push.default)(points).call(points, { cmd: 'L', x, y }); } else if (type === 'v') { y = resolve(y, numbers[0]); (0, _push.default)(points).call(points, { cmd: 'L', x, y }); } } return points; } function pointsToString(points) { return points.map(point => `${point.cmd}${point.x} ${point.y}`).join(' '); } function squaredDistance(pointsA, pointsB) { return pointsA.reduce((sum, point, i) => sum + (point.x - pointsB[i].x) ** 2 + (point.y - pointsB[i].y) ** 2, 0); } function alignPath(reference, target) { if (reference.length !== target.length || reference.length === 0) { return target; } const subpaths = []; for (let i = 0; i < reference.length; i++) { var _context2, _context3; if (reference[i].cmd === 'M') { (0, _push.default)(subpaths).call(subpaths, [[], []]); } (0, _push.default)(_context2 = subpaths[subpaths.length - 1][0]).call(_context2, reference[i]); (0, _push.default)(_context3 = subpaths[subpaths.length - 1][1]).call(_context3, target[i]); } return subpaths.flatMap(([referenceSubpath, targetSubpath]) => { const reversed = [...targetSubpath].reverse().map((point, index) => ({ ...point, cmd: index === 0 ? 'M' : 'L' })); return squaredDistance(referenceSubpath, reversed) < squaredDistance(referenceSubpath, targetSubpath) ? reversed : targetSubpath; }); } //# sourceMappingURL=IconTransition.js.map