Skip to content

Commit 5a4c3cd

Browse files
committed
Resolve #40 with component selectors
1 parent b5167d7 commit 5a4c3cd

4 files changed

Lines changed: 106 additions & 8 deletions

File tree

src/createStyled.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const createStyled = (jss: Function) => (baseStyles: BaseStylesType = {}): Style
4242
const {tagName, style} = getStyledArgs(tagNameOrStyledElement)
4343
const elementStyle = {...style, ...ownStyle}
4444

45-
return styled({tagName, baseStyles, elementStyle, mountSheet})
45+
return styled({tagName, baseStyles, elementStyle, mountSheet, jss})
4646
}
4747

4848
Object.defineProperty(styledWrapper, 'sheet', ({

src/styled.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,30 @@ import type {
1414
type StyledArgs = {
1515
tagName: string,
1616
elementStyle: ComponentStyleType,
17-
mountSheet: Function
17+
mountSheet: Function,
18+
jss: Function
1819
}
1920

20-
const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
21+
const styled = ({tagName, elementStyle, mountSheet, jss}: StyledArgs) => {
2122
const {dynamicStyle, staticStyle} = getSeparatedStyles(elementStyle)
2223
const staticTagName = staticStyle && generateTagName(tagName)
2324

2425
const availableDynamicTagNames = []
2526
const classMap = {}
2627

27-
return class StyledElement extends Component<StyledElementPropsType> {
28+
let staticClassName
29+
30+
class StyledElement extends Component<StyledElementPropsType> {
2831
static tagName: string = tagName
2932
static style: ComponentStyleType = elementStyle
3033

31-
dynamicTagName = ''
32-
33-
sheet: JssSheet
34-
3534
constructor(props: StyledElementPropsType) {
3635
super(props)
3736
if (!this.dynamicTagName && dynamicStyle) {
3837
this.dynamicTagName = availableDynamicTagNames.pop() || generateTagName(tagName)
3938
}
39+
40+
this.staticClassName = staticClassName
4041
}
4142

4243
componentWillMount() {
@@ -66,6 +67,12 @@ const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
6667
availableDynamicTagNames.push(this.dynamicTagName)
6768
}
6869

70+
dynamicTagName = ''
71+
72+
sheet: JssSheet
73+
74+
staticClassName = ''
75+
6976
updateSheet(props: StyledElementPropsType) {
7077
let rule
7178
let ruleIndex = 0
@@ -83,6 +90,7 @@ const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
8390

8491
const props = filterProps(tagName, attrs)
8592
const tagClass = composeClasses([
93+
this.staticClassName,
8694
staticTagName && this.sheet.classes[staticTagName],
8795
this.dynamicTagName && this.sheet.classes[this.dynamicTagName],
8896
className
@@ -91,6 +99,22 @@ const styled = ({tagName, elementStyle, mountSheet}: StyledArgs) => {
9199
return createElement(tagName, {...props, className: tagClass}, children)
92100
}
93101
}
102+
103+
// $FlowIgnore
104+
StyledElement.valueOf = () => {
105+
if (!staticClassName) {
106+
staticClassName = `.${jss.generateClassName({
107+
key: generateTagName('static')
108+
})}`
109+
}
110+
111+
return staticClassName
112+
}
113+
114+
// $FlowIgnore
115+
StyledElement.toString = StyledElement.valueOf
116+
117+
return StyledElement
94118
}
95119

96120
export default styled

src/tests/__snapshots__/functional.spec.jsx.snap

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,48 @@ exports[`functional tests should update props and unmount 2`] = `
100100
}"
101101
`;
102102

103+
exports[`functional tests should use Styled Component classname in string 1`] = `
104+
".div-4-id:not(:first-child) .static-2-id {
105+
display: none;
106+
}
107+
.div-4-id:not(:last-child) .static-3-id {
108+
visibility: hidden;
109+
}
110+
.div-4-id .static-2-id {
111+
color: green;
112+
}
113+
.div-1-id {
114+
color: red;
115+
}
116+
.img-5-id {
117+
width: 30px;
118+
}"
119+
`;
120+
121+
exports[`functional tests should use Styled Component classname in string 2`] = `
122+
<StyledElement>
123+
<div
124+
className="div-4-id"
125+
>
126+
<StyledElement>
127+
<div
128+
className=".static-2-id div-1-id"
129+
>
130+
name
131+
</div>
132+
</StyledElement>
133+
<StyledElement
134+
width={30}
135+
>
136+
<img
137+
className=".static-3-id img-5-id"
138+
width={30}
139+
/>
140+
</StyledElement>
141+
</div>
142+
</StyledElement>
143+
`;
144+
103145
exports[`functional tests should use props on remount 1`] = `
104146
".button-1-id {
105147
color: black;

src/tests/functional.spec.jsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,36 @@ describe('functional tests', () => {
134134

135135
wrapper.unmount()
136136
})
137+
138+
it('should use Styled Component classname in string', () => {
139+
const AuthorName = styled('div')({color: 'red'})
140+
const Avatar = styled('img')({width: props => props.width})
141+
142+
const Message = styled('div')({
143+
[`&:not(:first-child) ${AuthorName}`]: {
144+
display: 'none'
145+
},
146+
[`&:not(:last-child) ${Avatar}`]: {
147+
visibility: 'hidden'
148+
},
149+
[`& ${AuthorName}`]: {
150+
color: 'green'
151+
}
152+
})
153+
154+
const wrapper = mount(
155+
<Message>
156+
<AuthorName>name</AuthorName>
157+
<Avatar width={30} />
158+
</Message>
159+
)
160+
161+
const {sheet} = styled
162+
163+
assertSheet(sheet)
164+
165+
expect(wrapper).toMatchSnapshot()
166+
167+
wrapper.unmount()
168+
})
137169
})

0 commit comments

Comments
 (0)