@startlibs/utils 1.1.2 → 1.2.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ActionUtils.mjs +4 -4
- package/lib/ActionUtils.mjs.map +1 -1
- package/lib/FetchUtils.mjs.map +1 -1
- package/lib/animationKeyframes.mjs +11 -0
- package/lib/animationKeyframes.mjs.map +1 -0
- package/lib/createPressEvent.mjs +1 -1
- package/lib/createPressEvent.mjs.map +1 -1
- package/lib/fixMediaQuery.mjs +43 -17
- package/lib/fixMediaQuery.mjs.map +1 -1
- package/lib/fixMediaText.mjs +16 -0
- package/lib/fixMediaText.mjs.map +1 -0
- package/lib/formatDate.mjs.map +1 -1
- package/lib/formatUtils.mjs +2 -2
- package/lib/formatUtils.mjs.map +1 -1
- package/lib/getClosestOffsetScroll.mjs.map +1 -1
- package/lib/hooks/useEventListener.mjs.map +1 -1
- package/lib/index.cjs +311 -199
- package/lib/index.cjs.map +1 -1
- package/lib/index.mjs +5 -3
- package/lib/index.mjs.map +1 -1
- package/lib/insertKeyframes.mjs +68 -0
- package/lib/insertKeyframes.mjs.map +1 -0
- package/lib/lodashUtils.mjs +6 -6
- package/lib/lodashUtils.mjs.map +1 -1
- package/lib/promiseUtils.mjs.map +1 -1
- package/lib/reactUtils.mjs +1 -1
- package/lib/reactUtils.mjs.map +1 -1
- package/lib/reduceUtils.mjs.map +1 -1
- package/lib/smoothScroll.mjs.map +1 -1
- package/lib/styled.mjs +25 -144
- package/lib/styled.mjs.map +1 -1
- package/lib/styledShared.mjs +125 -0
- package/lib/styledShared.mjs.map +1 -0
- package/lib/timeUtils.mjs +1 -1
- package/lib/timeUtils.mjs.map +1 -1
- package/lib/timerUtils.mjs +0 -1
- package/lib/timerUtils.mjs.map +1 -1
- package/lib/utils.mjs +1 -1
- package/lib/utils.mjs.map +1 -1
- package/lib/wrapLazy.mjs +2 -2
- package/lib/wrapLazy.mjs.map +1 -1
- package/lib/yakDomTag.mjs +44 -0
- package/lib/yakDomTag.mjs.map +1 -0
- package/lib-yak/ActionUtils.mjs +117 -0
- package/lib-yak/ActionUtils.mjs.map +1 -0
- package/lib-yak/FetchUtils.mjs +100 -0
- package/lib-yak/FetchUtils.mjs.map +1 -0
- package/lib-yak/animationKeyframes.mjs +31 -0
- package/lib-yak/animationKeyframes.mjs.map +1 -0
- package/lib-yak/createPressEvent.mjs +74 -0
- package/lib-yak/createPressEvent.mjs.map +1 -0
- package/lib-yak/fixMediaQuery.mjs +90 -0
- package/lib-yak/fixMediaQuery.mjs.map +1 -0
- package/lib-yak/fixMediaText.mjs +16 -0
- package/lib-yak/fixMediaText.mjs.map +1 -0
- package/lib-yak/formatDate.mjs +110 -0
- package/lib-yak/formatDate.mjs.map +1 -0
- package/lib-yak/formatUtils.mjs +64 -0
- package/lib-yak/formatUtils.mjs.map +1 -0
- package/lib-yak/getClosestOffsetScroll.mjs +15 -0
- package/lib-yak/getClosestOffsetScroll.mjs.map +1 -0
- package/lib-yak/hooks/useEventListener.mjs +27 -0
- package/lib-yak/hooks/useEventListener.mjs.map +1 -0
- package/lib-yak/index.mjs +21 -0
- package/lib-yak/index.mjs.map +1 -0
- package/lib-yak/insertKeyframes.mjs +68 -0
- package/lib-yak/insertKeyframes.mjs.map +1 -0
- package/lib-yak/lodashUtils.mjs +131 -0
- package/lib-yak/lodashUtils.mjs.map +1 -0
- package/lib-yak/promiseUtils.mjs +92 -0
- package/lib-yak/promiseUtils.mjs.map +1 -0
- package/lib-yak/reactUtils.mjs +12 -0
- package/lib-yak/reactUtils.mjs.map +1 -0
- package/lib-yak/reduceUtils.mjs +14 -0
- package/lib-yak/reduceUtils.mjs.map +1 -0
- package/lib-yak/smoothScroll.mjs +59 -0
- package/lib-yak/smoothScroll.mjs.map +1 -0
- package/lib-yak/styled.mjs +23 -0
- package/lib-yak/styled.mjs.map +1 -0
- package/lib-yak/styledShared.mjs +129 -0
- package/lib-yak/styledShared.mjs.map +1 -0
- package/lib-yak/timeUtils.mjs +81 -0
- package/lib-yak/timeUtils.mjs.map +1 -0
- package/lib-yak/timerUtils.mjs +10 -0
- package/lib-yak/timerUtils.mjs.map +1 -0
- package/lib-yak/utils.mjs +386 -0
- package/lib-yak/utils.mjs.map +1 -0
- package/lib-yak/wrapLazy.mjs +132 -0
- package/lib-yak/wrapLazy.mjs.map +1 -0
- package/lib-yak/yakDomTag.mjs +44 -0
- package/lib-yak/yakDomTag.mjs.map +1 -0
- package/package.json +14 -3
- package/src/animationKeyframes.js +10 -0
- package/src/animationKeyframes.test.mjs +75 -0
- package/src/animationKeyframes.yak.js +30 -0
- package/src/fixMediaQuery.js +40 -19
- package/src/fixMediaText.js +18 -0
- package/src/fixMediaText.test.mjs +60 -0
- package/src/index.js +1 -0
- package/src/insertKeyframes.js +73 -0
- package/src/insertKeyframes.test.mjs +144 -0
- package/src/styled.js +5 -97
- package/src/styled.yak.js +30 -0
- package/src/styledShared.js +96 -0
- package/src/timerUtils.jsx +0 -2
- package/src/yakDomTag.jsx +42 -0
- package/src/yakDomTag.test.mjs +49 -0
package/src/styled.js
CHANGED
|
@@ -1,52 +1,13 @@
|
|
|
1
|
+
/* @startlibs-yak keep-styled-components */
|
|
1
2
|
// @flow
|
|
3
|
+
// Na lib-yak, este arquivo é trocado por styled.yak.js (sem styled-components).
|
|
2
4
|
import _ from 'lodash/fp'
|
|
3
|
-
import {darken} from 'polished'
|
|
4
|
-
import React from 'react'
|
|
5
5
|
import styled, {css} from 'styled-components'
|
|
6
|
-
import createEmotion from 'create-emotion'
|
|
7
6
|
import {scrollWidth} from './fixMediaQuery'
|
|
8
|
-
import {_s} from './lodashUtils'
|
|
9
7
|
import {callIfFunction} from './utils'
|
|
8
|
+
import {ifPropValue} from './styledShared'
|
|
10
9
|
|
|
11
|
-
export
|
|
12
|
-
if (propsOrColor === undefined) {
|
|
13
|
-
return ({theme})=>theme.colors.gray150
|
|
14
|
-
}
|
|
15
|
-
if (typeof propsOrColor==='string') {
|
|
16
|
-
return ({theme})=>theme.colors[propsOrColor] || propsOrColor
|
|
17
|
-
}
|
|
18
|
-
const {theme,...props} = propsOrColor
|
|
19
|
-
if (props.dark) {
|
|
20
|
-
return darken(0.1, getColor({theme, ..._.unset( 'dark', props)}))
|
|
21
|
-
} else if (hover && props.hover) {
|
|
22
|
-
return getColor({theme, color: props.hover})
|
|
23
|
-
} else if (props.color) {
|
|
24
|
-
return theme.colors[props.color] || props.color
|
|
25
|
-
} else if (props.highlight) {
|
|
26
|
-
return theme.colors.main
|
|
27
|
-
} else if (props.alert) {
|
|
28
|
-
return theme.colors.alert
|
|
29
|
-
} else if (props.success) {
|
|
30
|
-
return theme.colors.success
|
|
31
|
-
} else {
|
|
32
|
-
return theme.colors.gray150
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export const getMargin = (enumeratedMargins) => (props) => enumeratedMargins[props.margin] || props.margin || enumeratedMargins['default'] || 0
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Returns the value of `props[path]` or `defaultValue`
|
|
40
|
-
* @example
|
|
41
|
-
* const Button = styled.button`
|
|
42
|
-
* color: ${prop('color', 'red')};
|
|
43
|
-
* `
|
|
44
|
-
*/
|
|
45
|
-
export const prop = (path,defaultValue) =>
|
|
46
|
-
(props = {}) => _.get(path.trim(), props) || defaultValue
|
|
47
|
-
|
|
48
|
-
export const customTheme = (type) =>
|
|
49
|
-
(props = {}) => _.get(["theme","startlibs",type], props) || ''
|
|
10
|
+
export {getColor, getMargin, prop, customTheme, vheight, oneWayAnimation, twoWayAnimation, animationTiming, identityTranslateFrames, identityOpacityFrames} from './styledShared'
|
|
50
11
|
|
|
51
12
|
/**
|
|
52
13
|
* Returns `pass` if prop is truthy. Otherwise returns `fail`
|
|
@@ -64,17 +25,7 @@ export const customTheme = (type) =>
|
|
|
64
25
|
*/
|
|
65
26
|
export const ifProp = (path, pass, fail) => {
|
|
66
27
|
if (pass && !_.isFunction(pass)) { // old version
|
|
67
|
-
return (
|
|
68
|
-
let result = false
|
|
69
|
-
if (Array.isArray(path)) {
|
|
70
|
-
result = path.every(p=> testSinglePath(props,p))
|
|
71
|
-
} else if (typeof path === 'object') {
|
|
72
|
-
result = !Object.entries(path).find(([k,v])=>props[k]!==v)
|
|
73
|
-
} else {
|
|
74
|
-
result = testSinglePath(props,path)
|
|
75
|
-
}
|
|
76
|
-
return result ? pass : fail
|
|
77
|
-
}
|
|
28
|
+
return ifPropValue(path, pass, fail)
|
|
78
29
|
} else {
|
|
79
30
|
return (...argsTrue) => {
|
|
80
31
|
const check = pass || _.identity
|
|
@@ -116,49 +67,6 @@ media.max = (n) => media([n,'max-width'])
|
|
|
116
67
|
media.min = (n) => media([n,'min-width'])
|
|
117
68
|
media.desktop = media([601,'min-width'])
|
|
118
69
|
|
|
119
|
-
export const vheight = (strings,size) => {
|
|
120
|
-
const propType = strings[0]
|
|
121
|
-
const calc = (strings[1]||"").replace(";","").trim()
|
|
122
|
-
return `
|
|
123
|
-
${propType} ${calc ? `calc(${size}vh ${calc})` : `${size}vh`};
|
|
124
|
-
${propType} ${calc ? `calc(calc(var(--vh, 1vh) * ${size}) ${calc})` : `calc(var(--vh, 1vh) * ${size})`};
|
|
125
|
-
`
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function testSinglePath(props,path) {
|
|
129
|
-
if (typeof path === 'string') {
|
|
130
|
-
return !!_s.get(path, props)
|
|
131
|
-
} else if (typeof path === 'number') {
|
|
132
|
-
return !!props[path]
|
|
133
|
-
} else {
|
|
134
|
-
return false
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const getFrameOffset = (i,total) => Math.round(i*100/(total-1))
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const emotion = createEmotion({
|
|
142
|
-
nonce: (typeof document !== 'undefined' &&
|
|
143
|
-
(document.querySelector('meta[property="csp-nonce"]') || {}).content) || 'animation_nonce'
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
export const oneWayAnimation = (...frames) => {
|
|
147
|
-
return emotion.keyframes`
|
|
148
|
-
${frames.map((frame,i) =>
|
|
149
|
-
!frame ? '' : `${getFrameOffset(i,frames.length)}% {
|
|
150
|
-
${frame}
|
|
151
|
-
}`
|
|
152
|
-
)}`
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export const twoWayAnimation = (...frames) => [frames,_.reverse(frames)].map((frames)=>oneWayAnimation(...frames))
|
|
156
|
-
|
|
157
|
-
export const animationTiming = (props) => (...animations) => animations.filter(_=>_).map(_=>_+' '+props).join(',')
|
|
158
|
-
|
|
159
|
-
export const identityTranslateFrames = oneWayAnimation('transform: translateY(0);', 'transform: translateY(0);')
|
|
160
|
-
export const identityOpacityFrames = oneWayAnimation('opacity: 1;', 'opacity:1;')
|
|
161
|
-
|
|
162
70
|
export const styledExtend = ({target,componentStyle}) => (...template) => {
|
|
163
71
|
const wasStatic = !_.find(_.isFunction,componentStyle.rules)
|
|
164
72
|
const v = styled(target)(...template,...(wasStatic ? [] : [() => ""]))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Saída yak (lib-yak/) de styled.js, sem styled-components: o runtime dele não vai para o bundle.
|
|
2
|
+
// O plugin startlibs-to-yak reduz ifProp (template), media, styledExtend e printerMedia a CSS
|
|
3
|
+
// estático no build da startlibs. No app em modo yak, esses helpers não têm como funcionar em
|
|
4
|
+
// runtime: falham com uma mensagem clara em vez de gerar CSS errado.
|
|
5
|
+
import _ from 'lodash/fp'
|
|
6
|
+
import {ifPropValue} from './styledShared'
|
|
7
|
+
|
|
8
|
+
export {getColor, getMargin, prop, customTheme, vheight, oneWayAnimation, twoWayAnimation, animationTiming, identityTranslateFrames, identityOpacityFrames} from './styledShared'
|
|
9
|
+
|
|
10
|
+
const notInYak = (name, instead) => () => {
|
|
11
|
+
throw new Error(`@startlibs/utils: ${name} usa styled-components e não existe no modo yak. Use ${instead}.`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ifProp = (path, pass, fail) =>
|
|
15
|
+
pass && !_.isFunction(pass)
|
|
16
|
+
? ifPropValue(path, pass, fail)
|
|
17
|
+
: notInYak('ifProp com template', 'uma função de props com css`` do @yak/react')
|
|
18
|
+
export const ifPropEquals = (path,str) => ifProp(path,_.isEqual(str))
|
|
19
|
+
export const ifNotProp = (path) => ifProp(path,v => !v)
|
|
20
|
+
|
|
21
|
+
export const media = () => notInYak('media', '@media no próprio CSS')
|
|
22
|
+
media.mobile = media()
|
|
23
|
+
media.between = media
|
|
24
|
+
media.max = media
|
|
25
|
+
media.min = media
|
|
26
|
+
media.desktop = media()
|
|
27
|
+
|
|
28
|
+
export const styledExtend = notInYak('styledExtend', 'styled(Componente)')
|
|
29
|
+
export const printerMedia = notInYak('printerMedia', '@media print')
|
|
30
|
+
export const notPrinterMedia = notInYak('notPrinterMedia', '@media screen')
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Helpers de estilo que não dependem de styled-components: valem na lib/ e na lib-yak/.
|
|
2
|
+
import _ from 'lodash/fp'
|
|
3
|
+
import {darken} from 'polished'
|
|
4
|
+
import {animationKeyframes} from './animationKeyframes'
|
|
5
|
+
import {_s} from './lodashUtils'
|
|
6
|
+
|
|
7
|
+
export const getColor = (propsOrColor, hover) => {
|
|
8
|
+
if (propsOrColor === undefined) {
|
|
9
|
+
return ({theme})=>theme.colors.gray150
|
|
10
|
+
}
|
|
11
|
+
if (typeof propsOrColor==='string') {
|
|
12
|
+
return ({theme})=>theme.colors[propsOrColor] || propsOrColor
|
|
13
|
+
}
|
|
14
|
+
const {theme,...props} = propsOrColor
|
|
15
|
+
if (props.dark) {
|
|
16
|
+
return darken(0.1, getColor({theme, ..._.unset( 'dark', props)}))
|
|
17
|
+
} else if (hover && props.hover) {
|
|
18
|
+
return getColor({theme, color: props.hover})
|
|
19
|
+
} else if (props.color) {
|
|
20
|
+
return theme.colors[props.color] || props.color
|
|
21
|
+
} else if (props.highlight) {
|
|
22
|
+
return theme.colors.main
|
|
23
|
+
} else if (props.alert) {
|
|
24
|
+
return theme.colors.alert
|
|
25
|
+
} else if (props.success) {
|
|
26
|
+
return theme.colors.success
|
|
27
|
+
} else {
|
|
28
|
+
return theme.colors.gray150
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const getMargin = (enumeratedMargins) => (props) => enumeratedMargins[props.margin] || props.margin || enumeratedMargins['default'] || 0
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns the value of `props[path]` or `defaultValue`
|
|
36
|
+
* @example
|
|
37
|
+
* const Button = styled.button`
|
|
38
|
+
* color: ${prop('color', 'red')};
|
|
39
|
+
* `
|
|
40
|
+
*/
|
|
41
|
+
export const prop = (path,defaultValue) =>
|
|
42
|
+
(props = {}) => _.get(path.trim(), props) || defaultValue
|
|
43
|
+
|
|
44
|
+
export const customTheme = (type) =>
|
|
45
|
+
(props = {}) => _.get(["theme","startlibs",type], props) || ''
|
|
46
|
+
|
|
47
|
+
export const vheight = (strings,size) => {
|
|
48
|
+
const propType = strings[0]
|
|
49
|
+
const calc = (strings[1]||"").replace(";","").trim()
|
|
50
|
+
return `
|
|
51
|
+
${propType} ${calc ? `calc(${size}vh ${calc})` : `${size}vh`};
|
|
52
|
+
${propType} ${calc ? `calc(calc(var(--vh, 1vh) * ${size}) ${calc})` : `calc(var(--vh, 1vh) * ${size})`};
|
|
53
|
+
`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const getFrameOffset = (i,total) => Math.round(i*100/(total-1))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export const oneWayAnimation = (...frames) => {
|
|
60
|
+
return animationKeyframes`
|
|
61
|
+
${frames.map((frame,i) =>
|
|
62
|
+
!frame ? '' : `${getFrameOffset(i,frames.length)}% {
|
|
63
|
+
${frame}
|
|
64
|
+
}`
|
|
65
|
+
)}`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const twoWayAnimation = (...frames) => [frames,_.reverse(frames)].map((frames)=>oneWayAnimation(...frames))
|
|
69
|
+
|
|
70
|
+
export const animationTiming = (props) => (...animations) => animations.filter(_=>_).map(_=>_+' '+props).join(',')
|
|
71
|
+
|
|
72
|
+
export const identityTranslateFrames = oneWayAnimation('transform: translateY(0);', 'transform: translateY(0);')
|
|
73
|
+
export const identityOpacityFrames = oneWayAnimation('opacity: 1;', 'opacity:1;')
|
|
74
|
+
|
|
75
|
+
function testSinglePath(props,path) {
|
|
76
|
+
if (typeof path === 'string') {
|
|
77
|
+
return !!_s.get(path, props)
|
|
78
|
+
} else if (typeof path === 'number') {
|
|
79
|
+
return !!props[path]
|
|
80
|
+
} else {
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ifProp na forma antiga (valor pronto, não template): devolve pass ou fail
|
|
86
|
+
export const ifPropValue = (path, pass, fail) => (props = {}) => {
|
|
87
|
+
let result = false
|
|
88
|
+
if (Array.isArray(path)) {
|
|
89
|
+
result = path.every(p=> testSinglePath(props,p))
|
|
90
|
+
} else if (typeof path === 'object') {
|
|
91
|
+
result = !Object.entries(path).find(([k,v])=>props[k]!==v)
|
|
92
|
+
} else {
|
|
93
|
+
result = testSinglePath(props,path)
|
|
94
|
+
}
|
|
95
|
+
return result ? pass : fail
|
|
96
|
+
}
|
package/src/timerUtils.jsx
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import isPropValid from '@emotion/is-prop-valid'
|
|
3
|
+
|
|
4
|
+
// Task 13c: @yak/react só filtra props `$`-prefixadas e `undefined` antes de repassar pro
|
|
5
|
+
// elemento real; qualquer prop custom (string, número, objeto) lida por um `styled.<tag>` no yak
|
|
6
|
+
// vaza como atributo no DOM. styled-components v5 evita isso sozinho pra tags string, usando
|
|
7
|
+
// @emotion/is-prop-valid. yakDomTag(tag) devolve um componente equivalente: filtra pelas mesmas
|
|
8
|
+
// regras antes de renderizar `tag`, pra o DOM do yak ficar idêntico ao do sc.
|
|
9
|
+
//
|
|
10
|
+
// Resolvido via `@startlibs/utils/yakDomTag` (exports["./*"] do package.json) — não passa pelo
|
|
11
|
+
// index: só existe nessa saída porque o babel-plugin-startlibs-to-yak importa explicitamente
|
|
12
|
+
// (ver tools/babel-plugin-startlibs-to-yak/domTag.cjs), nunca no fonte sc.
|
|
13
|
+
//
|
|
14
|
+
// Memoizado por nome de tag: `styled(yakDomTag('div'))` precisa devolver sempre o MESMO
|
|
15
|
+
// componente de DOM final pra identidade ficar estável entre `${X}` e composições
|
|
16
|
+
// (`styled(X)`/`styledExtend(X)`) de um mesmo `styled.div` — ver @yak/react runtime, que carrega
|
|
17
|
+
// esse componente até o fim da cadeia de composição.
|
|
18
|
+
//
|
|
19
|
+
// `as` (styled-components troca a tag renderizada com essa prop, ex.: components/src/containers/
|
|
20
|
+
// usePositioning.jsx's Placeholder as={placeholderAs}, form/src/TextInput.jsx's Input
|
|
21
|
+
// as={inputTag}) não é filtrada pelo @emotion/is-prop-valid (`isPropValid('as')` é false) — sem
|
|
22
|
+
// tratar à parte, o yak renderizaria sempre a tag original, ignorando a troca.
|
|
23
|
+
const cache = new Map()
|
|
24
|
+
|
|
25
|
+
export const yakDomTag = (tag) => {
|
|
26
|
+
let Component = cache.get(tag)
|
|
27
|
+
if (!Component) {
|
|
28
|
+
Component = React.forwardRef((props, ref) => {
|
|
29
|
+
const domProps = {}
|
|
30
|
+
for (const key in props) {
|
|
31
|
+
// `as` troca a tag renderizada (como styled-components faz); não é uma prop do DOM.
|
|
32
|
+
if (key === 'as') continue
|
|
33
|
+
if (key === 'className' || isPropValid(key)) domProps[key] = props[key]
|
|
34
|
+
}
|
|
35
|
+
domProps.ref = ref
|
|
36
|
+
return React.createElement(props.as || tag, domProps)
|
|
37
|
+
})
|
|
38
|
+
Component.displayName = `yakDomTag(${tag})`
|
|
39
|
+
cache.set(tag, Component)
|
|
40
|
+
}
|
|
41
|
+
return Component
|
|
42
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {test} from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import {yakDomTag} from './yakDomTag.jsx'
|
|
5
|
+
|
|
6
|
+
// yakDomTag's component is a React.forwardRef — `.render(props, ref)` runs the exact same logic
|
|
7
|
+
// a real render would, and React.createElement just returns a plain element descriptor
|
|
8
|
+
// ({type, props, ...}), so this is enough to assert on without react-dom/mounting.
|
|
9
|
+
const render = (tag, props, ref) => yakDomTag(tag).render(props, ref)
|
|
10
|
+
|
|
11
|
+
test('filtra prop custom (não aceita por @emotion/is-prop-valid)', () => {
|
|
12
|
+
const el = render('div', {rounded: true, children: 'x'})
|
|
13
|
+
assert.equal(el.type, 'div')
|
|
14
|
+
assert.equal('rounded' in el.props, false)
|
|
15
|
+
assert.equal(el.props.children, 'x')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('mantém className, style e props de DOM válidas', () => {
|
|
19
|
+
const el = render('div', {className: 'a', style: {color: 'red'}, id: 'x', 'data-foo': '1'})
|
|
20
|
+
assert.equal(el.props.className, 'a')
|
|
21
|
+
assert.deepEqual(el.props.style, {color: 'red'})
|
|
22
|
+
assert.equal(el.props.id, 'x')
|
|
23
|
+
assert.equal(el.props['data-foo'], '1')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('repassa ref pro elemento real', () => {
|
|
27
|
+
// React.createElement extrai `ref` do objeto de config pro próprio elemento (el.ref), não
|
|
28
|
+
// deixa em el.props (acessar el.props.ref em dev dispara um warning do React — por isso o
|
|
29
|
+
// teste não toca em el.props aqui, só em el.ref).
|
|
30
|
+
const ref = {current: null}
|
|
31
|
+
const el = render('div', {}, ref)
|
|
32
|
+
assert.equal(el.ref, ref)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('as troca a tag renderizada (como no sc) e não vaza pro DOM', () => {
|
|
36
|
+
const el = render('span', {as: 'textarea', children: 'x'})
|
|
37
|
+
assert.equal(el.type, 'textarea')
|
|
38
|
+
assert.equal('as' in el.props, false)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('sem as, renderiza a tag original', () => {
|
|
42
|
+
const el = render('input', {type: 'text'})
|
|
43
|
+
assert.equal(el.type, 'input')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
test('memoiza por nome de tag: mesmo tag devolve o mesmo componente', () => {
|
|
47
|
+
assert.equal(yakDomTag('div'), yakDomTag('div'))
|
|
48
|
+
assert.notEqual(yakDomTag('div'), yakDomTag('span'))
|
|
49
|
+
})
|