From 982d1ed84a0ab80b1f085833ceffd14273d63195 Mon Sep 17 00:00:00 2001 From: rofrischmann Date: Fri, 25 Sep 2015 23:37:40 +0200 Subject: [PATCH] updated version + refixed childindexes --- package.json | 100 +++++++++++++++++++++---------------------- src/core/resolver.js | 80 ++++++++++++++++++++++++++++++---- 2 files changed, 122 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index ea16d4d..e9c793b 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "react-look", - "version": "0.4.7", - "description": "Processable, dynamic & stateful Component Styling for React & React Native", - "main": "look.js", - "files": [ + "name": "react-look", + "version": "0.4.8", + "description": "Processable, dynamic & stateful Component Styling for React & React Native", + "main": "look.js", + "files": [ "LICENSE", "README.md", "dom.js", @@ -12,24 +12,24 @@ "lib/", "docs/" ], - "repository": { - "type": "git", - "url": "https://github.com/rofrischmann/react-look" - }, - "scripts": { - "clean": "rimraf lib", - "pretest": "npm run transpile", - "test": "mocha --recursive --compilers js:babel/register", - "test:watch": "mocha --recursive --compilers js:babel/register -w", - "transpile": "npm run clean && babel src --out-dir lib", - "package": "npm run transpile && node build-package.js", - "release": "npm run package && npm publish", - "demo": "npm run build:demo && open demo/index.html", - "demo-dev": "npm run build:demo-dev && open demo/index.html", - "build:demo": "npm run transpile && browserify ./demo/app.jsx -t babelify -d -p [minifyify --no-map] > ./demo/bundle.js", - "build:demo-dev": "npm run transpile && browserify ./demo/app.jsx -t babelify --outfile ./demo/bundle.js" - }, - "keywords": [ + "repository": { + "type": "git", + "url": "https://github.com/rofrischmann/react-look" + }, + "scripts": { + "clean": "rimraf lib", + "pretest": "npm run transpile", + "test": "mocha --recursive --compilers js:babel/register", + "test:watch": "mocha --recursive --compilers js:babel/register -w", + "transpile": "npm run clean && babel src --out-dir lib", + "package": "npm run transpile && node build-package.js", + "release": "npm run package && npm publish", + "demo": "npm run build:demo && open demo/index.html", + "demo-dev": "npm run build:demo-dev && open demo/index.html", + "build:demo": "npm run transpile && browserify ./demo/app.jsx -t babelify -d -p [minifyify --no-map] > ./demo/bundle.js", + "build:demo-dev": "npm run transpile && browserify ./demo/app.jsx -t babelify --outfile ./demo/bundle.js" + }, + "keywords": [ "react", "layout", "react-native", @@ -44,30 +44,30 @@ "stateful style", "cssinjs" ], - "author": "Robin Frischmann", - "license": "MIT", - "dependencies": { - "assign-styles": "^1.0.2", - "dynamic-style-sheets": "^0.2.2", - "inline-style-prefixer": "0.2.5", - "object-assign": "^4.0.1", - "param-case": "^1.1.1", - "react": "^0.14.0-rc1" - }, - "devDependencies": { - "babel": "^5.8.23", - "babelify": "^6.3.0", - "browserify": "^11.1.0", - "chai": "^3.3.0", - "color": "^0.10.1", - "minifyify": "^7.1.0", - "mocha": "^2.3.3", - "rimraf": "^2.4.3", - "sinon": "^1.17.0", - "sinon-chai": "^2.8.0", - "react-dom": "^0.14.0-rc1" - }, - "peerDependecies": { - "react-native": "0.11" - } -} \ No newline at end of file + "author": "Robin Frischmann", + "license": "MIT", + "dependencies": { + "assign-styles": "^1.0.2", + "dynamic-style-sheets": "^0.2.2", + "inline-style-prefixer": "^0.2.5", + "object-assign": "^4.0.1", + "param-case": "^1.1.1", + "react": "^0.14.0-rc1" + }, + "devDependencies": { + "babel": "^5.8.23", + "babelify": "^6.3.0", + "browserify": "^11.1.0", + "chai": "^3.3.0", + "color": "^0.10.1", + "minifyify": "^7.1.0", + "mocha": "^2.3.3", + "rimraf": "^2.4.3", + "sinon": "^1.17.0", + "sinon-chai": "^2.8.0", + "react-dom": "^0.14.0-rc1" + }, + "peerDependecies": { + "react-native": "0.11" + } +} diff --git a/src/core/resolver.js b/src/core/resolver.js index 67f92ce..4d55851 100644 --- a/src/core/resolver.js +++ b/src/core/resolver.js @@ -10,15 +10,15 @@ import Config from '../api/Config' * Maps the final style objects to the element * @param {Object} Component - wrapping React Component providing styles and elements * @param {Object} element - previously rendered React element - * @param {Object} parent - referencing element's parent + * @param {Object} childIndexMap - information on child index and child types */ -export default function resolveStyles(Component, element, parent) { +export default function resolveStyles(Component, element, childIndexMap) { if (element && element.props) { let props = element.props //resolving child looks recursively to make sure they will be rendered correctly let newProps = assign({}, props) - newProps.children = resolveChildren(Component, flattenArray(props.children), element) + newProps.children = resolveChildren(Component, flattenArray(props.children)) //Extracts only relevant styles according to the look prop let styles = extractStyles(props, Component.lookStyles) @@ -26,7 +26,9 @@ export default function resolveStyles(Component, element, parent) { if (styles) { //Triggers style processing //Uses the exact processor lineup defined within Config - let processArgs = {newProps, Component, element, Config, parent} + let processArgs = { + newProps, Component, element, childIndexMap, Config + } styles = processStyles(styles, Component._processors, processArgs) if (props.style) { styles = assignStyles(styles, props.style) @@ -59,21 +61,36 @@ export default function resolveStyles(Component, element, parent) { * Resolves provided styles for an elements children * @param {Object} Component - wrapping React Component providing looks and elements * @param {Array|string|number} children - children that get resolved - * @param {Object} parent - referencing element's parent */ -export function resolveChildren(Component, children, parent) { +export function resolveChildren(Component, children) { if (children) { //If there are more than one child, iterate over them if (children instanceof Array) { let newChildren = [] + let typeMap = generateTypeMap(children) + let indexMap = {} + let childType, childIndex + //Recursively resolve styles for child elements first //Generate index-maps to resolve child-index-sensitive pseudo classes children.forEach((child, index) => { //only resolve child if it actually is a valid react element if (isValidElement(child)) { - newChildren.push(resolveStyles(Component, child, parent)) + + //Provides information on child (type-sensitive) child indexes to resolve index-sensitive pseudo-classes + indexMap = generateIndexMap(child, indexMap) + + childType = getChildType(child) + childIndex = { + 'index': index + 1, + 'length': children.length, + 'typeIndex': indexMap[childType], + 'typeLength': typeMap[childType] + } + newChildren.push(resolveStyles(Component, child, childIndex)) + } else { //This clears undefined childs as they would falsely render //e.g. if you're trying to map {this.props.title} but it is not defined @@ -88,7 +105,7 @@ export function resolveChildren(Component, children, parent) { }) return newChildren } else { - return resolveStyles(Component, children, parent) + return resolveStyles(Component, children) } } else { return children === 0 ? children : false @@ -127,4 +144,51 @@ export function extractStyles(props, styles) { } else { return false } +} + +/** + * Generates a index map with information on type/index of each child + * This is needed to validate type-specific index-sensitive pseudo-classes + * e.g. :last-type-of + * @param {Array} children - an array of children + * @pararam {Object} indexMap - an object which stores the information + */ +export function generateIndexMap(child, indexMap) { + + // use component displayName if child is a function (ES6 component) + let childType = getChildType(child) + + if (indexMap.hasOwnProperty(childType)) { + ++indexMap[childType] + } else { + indexMap[childType] = 1; + } + return indexMap +} + +/** + * Iterate through all children and create a map with type/index information + * @param {Array} children - an array of children + */ +export function generateTypeMap(children) { + let indexMap = {} + children.forEach((child, index) => { + generateIndexMap(child, indexMap) + }) + return indexMap +} + +/** + * Returns a childs type + * If child is an ES6 class it returns the displayName + * @param {Object} child - child which type gets identified + */ +export function getChildType(child) { + let childType + if (child.type instanceof Function) { + childType = (child.type.hasOwnProperty('name') ? child.type.name : child.type) + } else { + childType = child.type + } + return childType } \ No newline at end of file