UNPKG

@servicenow/library-enhanced-element

Version:

Base element for Now Design System components

106 lines (88 loc) 2.91 kB
import makeScopedActionName from './scoped-action-name'; import reduce from 'lodash/reduce'; import forEach from 'lodash/forEach'; import omit from 'lodash/omit'; import mapValues from 'lodash/mapValues'; import get from 'lodash/get'; import constantCase from './constant-case'; const toManagedPropName = (propName) => 'manage' + propName[0].toUpperCase() + propName.slice(1); const omitManagedKey = (descriptor) => omit(descriptor, 'manageable'); /* Extracted from https://code.devsnc.com/dev/sn-seismic/blob/5aff3fb9bc51ada3bc487f78a5d3b02c04bf410b/packages/core/src/utils/combinePropertyDefs.js */ const getComponentProperties = (config) => { const {properties = {}, behaviors = []} = config; return reduce( behaviors, (acc, behavior) => { const properties = get( behavior, 'behavior.properties', get(behavior, 'properties', {}) ); forEach(properties, (value, key) => { acc[key] = value; }); return acc; }, {...properties} ); }; export const extendWithManageableProperties = (tagName, baseConfig) => { const properties = getComponentProperties(baseConfig); const propNamesToManage = Object.keys(properties).reduce((acc, propName) => { if (properties[propName].manageable) { acc.push(propName); } return acc; }, []); if (!propNamesToManage.length) { return baseConfig; } const managedActions = propNamesToManage.reduce((acc, propName) => { const actionName = makeScopedActionName( tagName, constantCase(propName) + '_SET' ); const managedPropName = toManagedPropName(propName); const actionHandler = ({host, state, action, updateProperties}) => { let value = action.payload.value; const isPropertySelector = typeof value === 'string' && value[0] === '@' && value.indexOf('/') > 0; const isManaged = state.properties[managedPropName]; // if a component is a descendant of itself, need to make sure that SET // actions from the child don't change the property of the parent const isActionForCurrentHost = host.nowId === action.meta.id; if (isManaged || !isActionForCurrentHost) { return; } /* * Here we're escaping the value to prevent selectable properties from * intercepting and overriding the original value. Managed properties * need to be escaped by the customer. * * This only happens when the value matches the pattern: '@abc/def' */ if (isPropertySelector) { value = `\\${value}`; } updateProperties({[propName]: value}); }; acc[actionName] = actionHandler; return acc; }, {}); const managedProperties = propNamesToManage.reduce((acc, propName) => { acc[toManagedPropName(propName)] = {}; return acc; }, {}); return { ...baseConfig, actionHandlers: { ...managedActions, ...baseConfig.actionHandlers }, properties: { ...managedProperties, ...mapValues(baseConfig.properties, omitManagedKey) } }; };