UNPKG

views-morph

Version:
123 lines (102 loc) 3.33 kB
import { enter } from '../react/properties-style.js' import { getActionableParent, getAllowedStyleKeys, hasKeys, hasKeysInChildren, } from '../utils.js' import hash from '../hash.js' export { enter } export function leave(node, parent, state) { const { dynamic, static: staticStyle } = node.style const allowedStyleKeys = getAllowedStyleKeys(node) let scopedUnderParent = !node.isCapture && !node.action && getActionableParent(node) if (scopedUnderParent) { scopedUnderParent = scopedUnderParent.styleName } // dynamic merges static styles if (hasKeysInChildren(dynamic)) { state.cssDynamic = true node.styleName = node.nameFinal let cssStatic = Object.keys(staticStyle) .filter( key => allowedStyleKeys.includes(key) && hasKeys(staticStyle[key]) ) .map(key => asCss( asStaticCss(staticStyle[key], Object.keys(dynamic[key])), key, scopedUnderParent ).join('\n') ) .join(',\n') let cssDynamic = ['({ props }) => ({'] cssDynamic = cssDynamic.concat( Object.keys(dynamic) .filter(key => allowedStyleKeys.includes(key) && hasKeys(dynamic[key])) .map(key => asCss(asDynamicCss(dynamic[key]), key, scopedUnderParent).join('\n') ) .join(',\n') ) cssDynamic.push('})') cssDynamic = cssDynamic.join('\n') if (cssStatic || cssDynamic) { state.styles[node.nameFinal] = `const ${node.nameFinal} = styled('${ node.nameTag }')(${cssStatic ? `{${cssStatic}}, ` : ''}${cssDynamic})` // TODO we may want to be smarter here and only pass what's needed state.render.push(` props={props}`) } } else if (hasKeysInChildren(staticStyle)) { state.cssStatic = true const id = `${node.is || node.name}_${hash(staticStyle)}` node.styleName = id node.className.push(`\${${id}}`) const css = Object.keys(staticStyle) .filter( key => allowedStyleKeys.includes(key) && hasKeys(staticStyle[key]) ) .map(key => asCss(asStaticCss(staticStyle[key]), key, scopedUnderParent).join('\n') ) .join(',\n') if (css) { state.styles[id] = `const ${id} = css({${css}})` } } } const asDynamicCss = styles => Object.keys(styles).map(prop => `${prop}: ${styles[prop]}`) const safe = str => typeof str === 'string' ? `"${str.replace(/"/g, "'")}"` : str const asStaticCss = (styles, dynamicStyles = []) => Object.keys(styles) .filter(prop => !dynamicStyles.includes(prop)) .map(prop => `${prop}: ${safe(styles[prop])}`) const asCss = (styles, key, scopedUnderParent) => { let css = [] if (key !== 'base') { if (scopedUnderParent) { let parent = `\${${scopedUnderParent}}` if (/_/.test(scopedUnderParent)) { parent = `.${parent}` } css.push(`[\`${parent}:${key} &, ${parent}.${key} &\`]: {`) } else if ( key === 'hover' || key === 'disabled' || key === 'focus' || key === 'placeholder' ) { css.push(`"&:${key}, &.${key}": {`) } else if (key === 'print') { // TODO can we use this to support all media queries? css.push('"@media print": {') } } css.push(styles.join(',\n')) if (key !== 'base') css.push(`}`) return css }