Skip to content

Commit cec8f05

Browse files
authored
feat: inject support priority (#456)
* feat: inject support priority * fix: lint
1 parent 43394c4 commit cec8f05

File tree

4 files changed

+62
-12
lines changed

4 files changed

+62
-12
lines changed

docs/examples/dynaymicCSS.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import React from 'react';
2-
import { updateCSS, removeCSS } from 'rc-util/es/Dom/dynamicCSS';
31
import type { Prepend } from 'rc-util/es/Dom/dynamicCSS';
2+
import { removeCSS, updateCSS } from 'rc-util/es/Dom/dynamicCSS';
3+
import React from 'react';
44

5-
function injectStyle(id: number, prepend?: Prepend) {
5+
function injectStyle(id: number, prepend?: Prepend, priority?: number) {
66
const randomColor = Math.floor(Math.random() * 16777215).toString(16);
77

88
updateCSS(`body { background: #${randomColor} }`, `style-${id}`, {
99
prepend,
10+
priority,
1011
});
1112
}
1213

@@ -35,6 +36,15 @@ export default () => {
3536
Prepend Queue: {id}
3637
</button>
3738

39+
<button
40+
onClick={() => {
41+
injectStyle(id, 'queue', -1);
42+
setId(id + 1);
43+
}}
44+
>
45+
Prepend Queue Priority: {id}
46+
</button>
47+
3848
<button
3949
onClick={() => {
4050
injectStyle(-1);

src/Dom/dynamicCSS.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import canUseDom from './canUseDom';
22
import contains from './contains';
33

44
const APPEND_ORDER = 'data-rc-order';
5+
const APPEND_PRIORITY = 'data-rc-priority';
56
const MARK_KEY = `rc-util-key`;
67

78
const containerCache = new Map<ContainerType, Node & ParentNode>();
@@ -14,6 +15,11 @@ interface Options {
1415
attachTo?: ContainerType;
1516
csp?: { nonce?: string };
1617
prepend?: Prepend;
18+
/**
19+
* Config the `priority` of `prependQueue`. Default is `0`.
20+
* It's useful if you need to insert style before other style.
21+
*/
22+
priority?: number;
1723
mark?: string;
1824
}
1925

@@ -55,10 +61,16 @@ export function injectCSS(css: string, option: Options = {}) {
5561
return null;
5662
}
5763

58-
const { csp, prepend } = option;
64+
const { csp, prepend, priority = 0 } = option;
65+
const mergedOrder = getOrder(prepend);
66+
const isPrependQueue = mergedOrder === 'prependQueue';
5967

6068
const styleNode = document.createElement('style');
61-
styleNode.setAttribute(APPEND_ORDER, getOrder(prepend));
69+
styleNode.setAttribute(APPEND_ORDER, mergedOrder);
70+
71+
if (isPrependQueue && priority) {
72+
styleNode.setAttribute(APPEND_PRIORITY, `${priority}`);
73+
}
6274

6375
if (csp?.nonce) {
6476
styleNode.nonce = csp?.nonce;
@@ -70,10 +82,20 @@ export function injectCSS(css: string, option: Options = {}) {
7082

7183
if (prepend) {
7284
// If is queue `prepend`, it will prepend first style and then append rest style
73-
if (prepend === 'queue') {
74-
const existStyle = findStyles(container).filter(node =>
75-
['prepend', 'prependQueue'].includes(node.getAttribute(APPEND_ORDER)),
76-
);
85+
if (isPrependQueue) {
86+
const existStyle = findStyles(container).filter(node => {
87+
// Ignore style which not injected by rc-util with prepend
88+
if (
89+
!['prepend', 'prependQueue'].includes(node.getAttribute(APPEND_ORDER))
90+
) {
91+
return false;
92+
}
93+
94+
// Ignore style which priority less then new style
95+
const nodePriority = Number(node.getAttribute(APPEND_PRIORITY) || 0);
96+
return priority >= nodePriority;
97+
});
98+
7799
if (existStyle.length) {
78100
container.insertBefore(
79101
styleNode,

tests/dynamicCSS.test.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* eslint-disable no-eval */
22
import {
3+
clearContainerCache,
34
injectCSS,
4-
updateCSS,
55
removeCSS,
6-
clearContainerCache,
6+
updateCSS,
77
} from '../src/Dom/dynamicCSS';
88

99
const TEST_STYLE = '.bamboo { context: "light" }';
@@ -86,6 +86,24 @@ describe('dynamicCSS', () => {
8686
expect(nextStyleNodes[2]).toBe(prependStyle);
8787
expect(nextStyleNodes[3]).toBe(appendStyle);
8888
});
89+
90+
it('prepend with queue and priority', () => {
91+
const style2 = injectCSS(TEST_STYLE, { prepend: 'queue', priority: 2 });
92+
const style1 = injectCSS(TEST_STYLE, { prepend: 'queue', priority: 1 });
93+
const style0 = injectCSS(TEST_STYLE, { prepend: 'queue', priority: 0 });
94+
const style = injectCSS(TEST_STYLE, { prepend: 'queue' });
95+
const stylePrepend = injectCSS(TEST_STYLE, { prepend: true });
96+
97+
const head = document.querySelector('head');
98+
const styleNodes = Array.from(head.querySelectorAll('style'));
99+
expect(styleNodes).toHaveLength(5);
100+
101+
const styles = [stylePrepend, style0, style, style1, style2];
102+
103+
for (let i = 0; i < styleNodes.length; i += 1) {
104+
expect(styles[i]).toBe(styleNodes[i]);
105+
}
106+
});
89107
});
90108
});
91109

tests/index.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* eslint-disable react/prefer-es6-class, react/no-render-return-value */
1+
/* eslint-disable react/prefer-es6-class, react/no-render-return-value, react/no-deprecated */
22
import React from 'react';
33
import ReactDOM from 'react-dom';
44
import createReactClass from 'create-react-class';

0 commit comments

Comments
 (0)