Skip to content

Commit 93d921b

Browse files
committed
docs: cache parsed color results to speed up rerenders
1 parent 079728f commit 93d921b

1 file changed

Lines changed: 66 additions & 43 deletions

File tree

packages/__docs__/src/ColorCard/index.tsx

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,58 +29,81 @@ import { View } from '@instructure/ui-view'
2929
import { ColorName } from '../ColorName'
3030
import type { ColorCardProps } from './props'
3131
import { allowedProps } from './props'
32-
class ColorCard extends Component<ColorCardProps> {
33-
static displayName = 'ColorCard'
34-
static allowedProps = allowedProps
35-
static defaultProps = {
36-
minimal: false
37-
}
3832

39-
parseColor(value: string) {
40-
// 6-digit hex: #RRGGBB
41-
const hex6 = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(value)
42-
if (hex6) {
43-
return {
44-
hex: value.toUpperCase(),
45-
rgb: `${parseInt(hex6[1], 16)},${parseInt(hex6[2], 16)},${parseInt(
46-
hex6[3],
47-
16
48-
)}`
49-
}
33+
type ParsedColor = {
34+
hex?: string
35+
rgb?: string
36+
alpha?: string
37+
} | null
38+
39+
// Cache parsed results so theme re-renders skip the regex work.
40+
const colorCache = new Map<string, ParsedColor>()
41+
42+
function parseColor(value: string): ParsedColor {
43+
if (colorCache.has(value)) return colorCache.get(value)!
44+
45+
// 6-digit hex: #RRGGBB
46+
const hex6 = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(value)
47+
if (hex6) {
48+
const result: ParsedColor = {
49+
hex: value.toUpperCase(),
50+
rgb: `${parseInt(hex6[1], 16)},${parseInt(hex6[2], 16)},${parseInt(
51+
hex6[3],
52+
16
53+
)}`
54+
}
55+
colorCache.set(value, result)
56+
return result
57+
}
58+
// 8-digit hex with alpha: #RRGGBBAA
59+
const hex8 = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(
60+
value
61+
)
62+
if (hex8) {
63+
const alpha = Math.round((parseInt(hex8[4], 16) / 255) * 100)
64+
const result: ParsedColor = {
65+
hex: value.toUpperCase(),
66+
rgb: `${parseInt(hex8[1], 16)},${parseInt(hex8[2], 16)},${parseInt(
67+
hex8[3],
68+
16
69+
)}`,
70+
alpha: `${alpha}%`
5071
}
51-
// 8-digit hex with alpha: #RRGGBBAA
52-
const hex8 = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(
72+
colorCache.set(value, result)
73+
return result
74+
}
75+
// rgba(r,g,b,a)
76+
const rgba =
77+
/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/i.exec(
5378
value
5479
)
55-
if (hex8) {
56-
const alpha = Math.round((parseInt(hex8[4], 16) / 255) * 100)
57-
return {
58-
hex: value.toUpperCase(),
59-
rgb: `${parseInt(hex8[1], 16)},${parseInt(hex8[2], 16)},${parseInt(
60-
hex8[3],
61-
16
62-
)}`,
63-
alpha: `${alpha}%`
64-
}
65-
}
66-
// rgba(r,g,b,a)
67-
const rgba =
68-
/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/i.exec(
69-
value
70-
)
71-
if (rgba) {
72-
const alpha =
73-
rgba[4] !== undefined
74-
? `${Math.round(parseFloat(rgba[4]) * 100)}%`
75-
: undefined
76-
return { rgb: `${rgba[1]},${rgba[2]},${rgba[3]}`, alpha }
80+
if (rgba) {
81+
const alpha =
82+
rgba[4] !== undefined
83+
? `${Math.round(parseFloat(rgba[4]) * 100)}%`
84+
: undefined
85+
const result: ParsedColor = {
86+
rgb: `${rgba[1]},${rgba[2]},${rgba[3]}`,
87+
alpha
7788
}
78-
return null
89+
colorCache.set(value, result)
90+
return result
91+
}
92+
93+
colorCache.set(value, null)
94+
return null
95+
}
96+
97+
class ColorCard extends Component<ColorCardProps> {
98+
static displayName = 'ColorCard'
99+
static allowedProps = allowedProps
100+
static defaultProps = {
101+
minimal: false
79102
}
80103

81104
render() {
82105
const { name, hex, minimal } = this.props
83-
const parsed = this.parseColor(hex)
106+
const parsed = parseColor(hex)
84107
return (
85108
<View
86109
as="figure"

0 commit comments

Comments
 (0)