@@ -10,38 +10,41 @@ function addStylesheetRule(rule) {
1010
1111const generateCssClassName = customAlphabet (
1212 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' ,
13- 32
13+ 16
1414)
1515
1616// Inspired by https://codesandbox.io/s/pseudo-class-sticker-sheet-jiu2x
1717const useAddSelector = ( ref , selector ) => {
1818 const [ modifiedClassName , setModifiedClassName ] = useState ( '' )
1919 useEffect ( ( ) => {
20- const className = ref . current . classList [ ref . current . classList . length - 1 ]
20+ const className = ref . current ? .classList [ ref . current . classList . length - 1 ]
2121 const fullSelector = `${ className && `.${ className } ` } ${ selector } `
22- // NOTE: This could be improved, because checking the provided selector starts with a '.'
23- // is probably not the best way to determine the selector is a class name or not.
24- const isClassNameSelector = selector . startsWith ( '.' )
25- let newRule = ''
26- for ( const ss of document . styleSheets ) {
27- for ( const rule of ss . cssRules ) {
28- if ( fullSelector === rule . selectorText ) {
29- const cssClassName = isClassNameSelector ? selector : `.${ generateCssClassName ( ) } `
30- newRule = `${ cssClassName } { ${ rule . style . cssText } }`
31- setModifiedClassName ( cssClassName . substring ( 1 ) )
32- break
22+ const newClassName = generateCssClassName ( )
23+ let newRules = [ ]
24+ for ( const styleSheet of document . styleSheets ) {
25+ for ( const rule of styleSheet . cssRules ) {
26+ if ( rule . selectorText ?. startsWith ( fullSelector ) ) {
27+ /**
28+ * Replace current CSS selector with the generated one so that
29+ * after adding the newClassName all children can be matched
30+ * i.e. we map:
31+ * .component:focus > input -> .generatedClass > input
32+ */
33+ const CSSSelector = rule . selectorText . replace ( fullSelector , `.${ newClassName } ` )
34+ newRules . push ( `${ CSSSelector } { ${ rule . style . cssText } }` )
3335 }
3436 }
35- if ( newRule ) {
36- addStylesheetRule ( newRule )
37- break
37+ if ( newRules . length > 0 ) {
38+ newRules . forEach ( addStylesheetRule )
39+ setModifiedClassName ( newClassName )
40+ break // Avoid triggering infinite loop since we're modifying stylesheets
3841 }
3942 }
4043 } , [ ref , selector ] )
4144 return [ modifiedClassName ]
4245}
4346
44- const WithSelector = props => {
47+ const WithSelector = ( props ) => {
4548 const ref = useRef ( null )
4649 const [ modifiedClassName ] = useAddSelector ( ref , props . selector )
4750
0 commit comments