diff --git a/src/pacomo.js b/src/pacomo.js index f646526..c5fc647 100644 --- a/src/pacomo.js +++ b/src/pacomo.js @@ -1,13 +1,29 @@ import classNames from 'classnames' import { isValidElement, cloneElement, Children, PropTypes } from 'react' +function pacomoStrategy(packageName){ + const strategy = { + getComponentName: function(component){ + return component.displayName || component.name; + }, + getComponentClassName: function(component){ + const componentName = strategy.getComponentName(component); + return `${packageName}-${componentName}`; + }, + getPropClassName: function(component, name){ + const prefix = strategy.getComponentClassName(component); + return `${prefix}-${name}`; + } + }; + return strategy; +} -export function prefixedClassNames(prefix, ...args) { +export function prefixedClassNames(strategy, component, ...args) { return ( classNames(...args) .split(/\s+/) - .filter(name => name !== "") - .map(name => `${prefix}-${name}`) + .filter(name => !!name) + .map(name => strategy.getPropClassName(component, name)) .join(' ') ) } @@ -46,7 +62,7 @@ function transformElementProps(props, fn, childrenOnly) { changes.children = transformedChildren } } - + if (!childrenOnly) { for (let key of Object.keys(props)) { if (key == 'children') continue @@ -75,7 +91,7 @@ function skipPropElements(props) { } -export function transformWithPrefix(prefix) { +export function transformWithPrefix(strategy, componentFunction) { const childTransform = element => transform(element) // Prefix all `className` props on the passed in ReactElement object, its @@ -92,7 +108,7 @@ export function transformWithPrefix(prefix) { ) if (element.props.className) { - changes.className = `${rootClass || ''} ${prefixedClassNames(prefix, element.props.className)} ${suffixClasses}` + changes.className = `${rootClass || ''} ${prefixedClassNames(strategy, componentFunction, element.props.className)} ${suffixClasses}` } else if (rootClass) { changes.className = `${rootClass} ${suffixClasses}` @@ -108,19 +124,21 @@ export function transformWithPrefix(prefix) { return transform } +export function withPackageName(packageName){ + return withStrategy(pacomoStrategy(packageName)); +} -export function withPackageName(packageName) { +export function withStrategy(strategy) { return { // Transform a stateless function component transformer(componentFunction) { - const componentName = componentFunction.displayName || componentFunction.name - const prefix = `${packageName}-${componentName}` - const transform = transformWithPrefix(prefix) + const componentName = strategy.getComponentName(componentFunction); + const transform = transformWithPrefix(strategy, componentFunction) const transformedComponent = (props, ...args) => transform( componentFunction(skipPropElements(props), ...args), - prefix, + strategy.getComponentClassName(componentFunction), props.className ) @@ -135,15 +153,14 @@ export function withPackageName(packageName) { // Transform a React.Component class decorator(componentClass) { - const componentName = componentClass.displayName || componentClass.name - const prefix = `${packageName}-${componentName}` - const transform = transformWithPrefix(prefix) + const componentName = strategy.getComponentName(componentClass); + const transform = transformWithPrefix(strategy, componentClass) const DecoratedComponent = class DecoratedComponent extends componentClass { render() { const rawProps = this.props this.props = skipPropElements(this.props) - const transformed = transform(super.render(), prefix, this.props.className) + const transformed = transform(super.render(), strategy.getComponentClassName(componentClass), this.props.className) this.props = rawProps return transformed } @@ -151,10 +168,7 @@ export function withPackageName(packageName) { DecoratedComponent.displayName = `pacomo(${componentName})` - // Add `className` propType, if none exists - DecoratedComponent.propTypes = { className: PropTypes.string, ...componentClass.propTypes } - - return DecoratedComponent + return DecoratedComponent }, } } diff --git a/test.js b/test.js index 2ecbc36..051ee67 100644 --- a/test.js +++ b/test.js @@ -1,11 +1,17 @@ import 'babel-polyfill' -import {prefixedClassNames, withPackageName, transformWithPrefix} from './lib/pacomo' +import { + PacomoStrategy, + prefixedClassNames, + withPackageName, + transformWithPrefix +} from './lib/pacomo' import React, {Component, PropTypes} from 'react' import TestUtils from 'react-addons-test-utils' import assert from 'assert' - -const testTransform = transformWithPrefix('test') +const testTransform = transformWithPrefix({ + getPropClassName: (component, name)=> `test-${name}` +}); const { transformer, decorator } = withPackageName('prefix') @@ -16,7 +22,7 @@ const { transformer, decorator } = withPackageName('prefix') function shallowRenderElement(element) { const shallowRenderer = TestUtils.createRenderer() shallowRenderer.render(element) - return shallowRenderer.getRenderOutput() + return shallowRenderer.getRenderOutput() } function shallowRenderComponent(Component, props) { @@ -127,16 +133,6 @@ describe('decorator', () => { "other propTypes from original class is passed through" ) }) - - it("should add a className propType if one doesn't already exist", () => { - const decoratedClass = decorator(BareComponent) - - assert.equal( - decoratedClass.propTypes.className, - PropTypes.string, - "className propType exists" - ) - }) }) @@ -260,9 +256,16 @@ describe('stateless render', () => { describe('prefixedClassNames', () => { + let strategy; + beforeEach(()=>{ + strategy = { + getPropClassName: (component, name)=> `test-prefix-${name}` + }; + }) + it("accepts an object, producing the correct result", () => { assert.equal( - prefixedClassNames('test-prefix', { + prefixedClassNames(strategy, null, { active: true, inactive: false, }), @@ -273,7 +276,7 @@ describe('prefixedClassNames', () => { it("accepts a string, producing the correct result", () => { assert.equal( - prefixedClassNames('test-prefix', 'test1', 'test2'), + prefixedClassNames(strategy, null, 'test1', 'test2'), 'test-prefix-test1 test-prefix-test2', "`classNames` produces the correct string when a string is passed in" )