@luisitoluis/viewfx 0.0.3
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/LICENSE.txt +21 -0
- package/README.es.md +109 -0
- package/README.md +109 -0
- package/package.json +57 -0
- package/src/compound.cjs +47 -0
- package/src/effects.cjs +212 -0
- package/src/engine.cjs +136 -0
- package/src/index.css +704 -0
- package/src/masks.cjs +99 -0
- package/src/masks.css +2 -0
- package/src/masks.js +97 -0
- package/src/plugin.cjs +41 -0
- package/src/plugin.js +1 -0
- package/src/theme.json +43 -0
package/src/masks.cjs
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mask shapes for the ViewFX Tailwind plugin.
|
|
3
|
+
*
|
|
4
|
+
* Declared as readable SVG and emitted as base64 custom properties
|
|
5
|
+
* (`pnpm emit:masks` → `src/masks.css`). Base64 matters: an SVG data URI
|
|
6
|
+
* containing a nested `url(#id)` filter reference breaks CSS minifiers
|
|
7
|
+
* when written literally into a stylesheet.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const svg = (viewBox, body) =>
|
|
11
|
+
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}">${body}</svg>`
|
|
12
|
+
|
|
13
|
+
const blur = (deviation) =>
|
|
14
|
+
`<defs><filter id="b"><feGaussianBlur stdDeviation="${deviation}"/></filter></defs>`
|
|
15
|
+
|
|
16
|
+
const MASK_SVG = {
|
|
17
|
+
circle: svg('0 0 40 40', '<circle cx="20" cy="20" r="20" fill="#fff"/>'),
|
|
18
|
+
|
|
19
|
+
'circle-blur': svg(
|
|
20
|
+
'0 0 40 40',
|
|
21
|
+
`${blur(2)}<circle cx="20" cy="20" r="18" fill="#fff" filter="url(#b)"/>`
|
|
22
|
+
),
|
|
23
|
+
|
|
24
|
+
'corner-tl': svg(
|
|
25
|
+
'0 0 40 40',
|
|
26
|
+
`${blur(2)}<circle cx="0" cy="0" r="18" fill="#fff" filter="url(#b)"/>`
|
|
27
|
+
),
|
|
28
|
+
|
|
29
|
+
'corner-tr': svg(
|
|
30
|
+
'0 0 40 40',
|
|
31
|
+
`${blur(1.5)}<circle cx="40" cy="0" r="18" fill="#fff" filter="url(#b)"/>`
|
|
32
|
+
),
|
|
33
|
+
|
|
34
|
+
'corner-bl': svg(
|
|
35
|
+
'0 0 40 40',
|
|
36
|
+
`${blur(2)}<circle cx="0" cy="40" r="18" fill="#fff" filter="url(#b)"/>`
|
|
37
|
+
),
|
|
38
|
+
|
|
39
|
+
'corner-br': svg(
|
|
40
|
+
'0 0 40 40',
|
|
41
|
+
`${blur(1.5)}<circle cx="40" cy="40" r="18" fill="#fff" filter="url(#b)"/>`
|
|
42
|
+
),
|
|
43
|
+
|
|
44
|
+
square: svg('0 0 40 40', '<rect x="4" y="4" width="32" height="32" fill="#fff"/>'),
|
|
45
|
+
|
|
46
|
+
soft: svg(
|
|
47
|
+
'0 0 40 40',
|
|
48
|
+
`${blur(3.2)}<ellipse cx="20" cy="20" rx="16" ry="12" fill="#fff" filter="url(#b)"/>`
|
|
49
|
+
),
|
|
50
|
+
|
|
51
|
+
diamond: svg('0 0 40 40', '<polygon points="20,0 40,20 20,40 0,20" fill="#fff"/>'),
|
|
52
|
+
|
|
53
|
+
hexagon: svg(
|
|
54
|
+
'0 0 100 100',
|
|
55
|
+
'<polygon points="50,0 93.3,25 93.3,75 50,100 6.7,75 6.7,25" fill="#fff"/>'
|
|
56
|
+
),
|
|
57
|
+
|
|
58
|
+
star: svg(
|
|
59
|
+
'0 0 100 100',
|
|
60
|
+
'<polygon points="50,0 61,35 95,35 68,57 79,91 50,70 21,91 32,57 5,35 39,35" fill="#fff"/>'
|
|
61
|
+
),
|
|
62
|
+
|
|
63
|
+
ink: svg(
|
|
64
|
+
'0 0 100 100',
|
|
65
|
+
'<defs><filter id="t">' +
|
|
66
|
+
'<feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="3" result="n"/>' +
|
|
67
|
+
'<feDisplacementMap in="SourceGraphic" in2="n" scale="15" xChannelSelector="R" yChannelSelector="G"/>' +
|
|
68
|
+
'</filter></defs>' +
|
|
69
|
+
'<circle cx="50" cy="50" r="50" fill="#fff" filter="url(#t)"/>'
|
|
70
|
+
),
|
|
71
|
+
|
|
72
|
+
heart: svg(
|
|
73
|
+
'0 0 100 100',
|
|
74
|
+
'<path fill="#fff" d="M50 88C25 65 5 50 5 30 5 15 15 5 30 5c10 0 18 7 20 13 2-6 10-13 20-13 15 0 25 10 25 25 0 20-20 35-45 58Z"/>'
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toBase64(markup) {
|
|
79
|
+
return Buffer.from(markup, 'utf8').toString('base64')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function maskVariables() {
|
|
83
|
+
const vars = {}
|
|
84
|
+
for (const [name, markup] of Object.entries(MASK_SVG)) {
|
|
85
|
+
vars[`--mask-${name}`] = `url("data:image/svg+xml;base64,${toBase64(markup)}")`
|
|
86
|
+
}
|
|
87
|
+
return vars
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** `:root` declaration block exposing every shape as `--mask-<name>`. */
|
|
91
|
+
function maskCustomProperties() {
|
|
92
|
+
const declarations = Object.entries(maskVariables())
|
|
93
|
+
.map(([name, value]) => `${name}:${value}`)
|
|
94
|
+
.join(';')
|
|
95
|
+
|
|
96
|
+
return `:root{${declarations}}`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = { MASK_SVG, maskCustomProperties, maskVariables }
|
package/src/masks.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/* Generated by scripts/emit-masks.mjs — do not edit by hand. */
|
|
2
|
+
:root{--mask-circle:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iMjAiIGZpbGw9IiNmZmYiLz48L3N2Zz4=");--mask-circle-blur:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIvPjwvZmlsdGVyPjwvZGVmcz48Y2lyY2xlIGN4PSIyMCIgY3k9IjIwIiByPSIxOCIgZmlsbD0iI2ZmZiIgZmlsdGVyPSJ1cmwoI2IpIi8+PC9zdmc+");--mask-corner-tl:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIvPjwvZmlsdGVyPjwvZGVmcz48Y2lyY2xlIGN4PSIwIiBjeT0iMCIgcj0iMTgiIGZpbGw9IiNmZmYiIGZpbHRlcj0idXJsKCNiKSIvPjwvc3ZnPg==");--mask-corner-tr:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMS41Ii8+PC9maWx0ZXI+PC9kZWZzPjxjaXJjbGUgY3g9IjQwIiBjeT0iMCIgcj0iMTgiIGZpbGw9IiNmZmYiIGZpbHRlcj0idXJsKCNiKSIvPjwvc3ZnPg==");--mask-corner-bl:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMiIvPjwvZmlsdGVyPjwvZGVmcz48Y2lyY2xlIGN4PSIwIiBjeT0iNDAiIHI9IjE4IiBmaWxsPSIjZmZmIiBmaWx0ZXI9InVybCgjYikiLz48L3N2Zz4=");--mask-corner-br:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMS41Ii8+PC9maWx0ZXI+PC9kZWZzPjxjaXJjbGUgY3g9IjQwIiBjeT0iNDAiIHI9IjE4IiBmaWxsPSIjZmZmIiBmaWx0ZXI9InVybCgjYikiLz48L3N2Zz4=");--mask-square:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHJlY3QgeD0iNCIgeT0iNCIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZmZmIi8+PC9zdmc+");--mask-soft:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PGRlZnM+PGZpbHRlciBpZD0iYiI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMy4yIi8+PC9maWx0ZXI+PC9kZWZzPjxlbGxpcHNlIGN4PSIyMCIgY3k9IjIwIiByeD0iMTYiIHJ5PSIxMiIgZmlsbD0iI2ZmZiIgZmlsdGVyPSJ1cmwoI2IpIi8+PC9zdmc+");--mask-diamond:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBvbHlnb24gcG9pbnRzPSIyMCwwIDQwLDIwIDIwLDQwIDAsMjAiIGZpbGw9IiNmZmYiLz48L3N2Zz4=");--mask-hexagon:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cG9seWdvbiBwb2ludHM9IjUwLDAgOTMuMywyNSA5My4zLDc1IDUwLDEwMCA2LjcsNzUgNi43LDI1IiBmaWxsPSIjZmZmIi8+PC9zdmc+");--mask-star:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cG9seWdvbiBwb2ludHM9IjUwLDAgNjEsMzUgOTUsMzUgNjgsNTcgNzksOTEgNTAsNzAgMjEsOTEgMzIsNTcgNSwzNSAzOSwzNSIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==");--mask-ink:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48ZmlsdGVyIGlkPSJ0Ij48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iMC4wMiIgbnVtT2N0YXZlcz0iMyIgcmVzdWx0PSJuIi8+PGZlRGlzcGxhY2VtZW50TWFwIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9Im4iIHNjYWxlPSIxNSIgeENoYW5uZWxTZWxlY3Rvcj0iUiIgeUNoYW5uZWxTZWxlY3Rvcj0iRyIvPjwvZmlsdGVyPjwvZGVmcz48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIgZmlsbD0iI2ZmZiIgZmlsdGVyPSJ1cmwoI3QpIi8+PC9zdmc+");--mask-heart:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNTAgODhDMjUgNjUgNSA1MCA1IDMwIDUgMTUgMTUgNSAzMCA1YzEwIDAgMTggNyAyMCAxMyAyLTYgMTAtMTMgMjAtMTMgMTUgMCAyNSAxMCAyNSAyNSAwIDIwLTIwIDM1LTQ1IDU4WiIvPjwvc3ZnPg==")}
|
package/src/masks.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mask shapes for the ViewFX Tailwind plugin.
|
|
3
|
+
*
|
|
4
|
+
* Declared as readable SVG and emitted as base64 custom properties
|
|
5
|
+
* (`pnpm emit:masks` → `src/masks.css`). Base64 matters: an SVG data URI
|
|
6
|
+
* containing a nested `url(#id)` filter reference breaks CSS minifiers
|
|
7
|
+
* when written literally into a stylesheet.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const svg = (viewBox, body) =>
|
|
11
|
+
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBox}">${body}</svg>`
|
|
12
|
+
|
|
13
|
+
const blur = (deviation) =>
|
|
14
|
+
`<defs><filter id="b"><feGaussianBlur stdDeviation="${deviation}"/></filter></defs>`
|
|
15
|
+
|
|
16
|
+
export const MASK_SVG = {
|
|
17
|
+
circle: svg('0 0 40 40', '<circle cx="20" cy="20" r="20" fill="#fff"/>'),
|
|
18
|
+
|
|
19
|
+
'circle-blur': svg(
|
|
20
|
+
'0 0 40 40',
|
|
21
|
+
`${blur(2)}<circle cx="20" cy="20" r="18" fill="#fff" filter="url(#b)"/>`
|
|
22
|
+
),
|
|
23
|
+
|
|
24
|
+
'corner-tl': svg(
|
|
25
|
+
'0 0 40 40',
|
|
26
|
+
`${blur(2)}<circle cx="0" cy="0" r="18" fill="#fff" filter="url(#b)"/>`
|
|
27
|
+
),
|
|
28
|
+
|
|
29
|
+
'corner-tr': svg(
|
|
30
|
+
'0 0 40 40',
|
|
31
|
+
`${blur(1.5)}<circle cx="40" cy="0" r="18" fill="#fff" filter="url(#b)"/>`
|
|
32
|
+
),
|
|
33
|
+
|
|
34
|
+
'corner-bl': svg(
|
|
35
|
+
'0 0 40 40',
|
|
36
|
+
`${blur(2)}<circle cx="0" cy="40" r="18" fill="#fff" filter="url(#b)"/>`
|
|
37
|
+
),
|
|
38
|
+
|
|
39
|
+
'corner-br': svg(
|
|
40
|
+
'0 0 40 40',
|
|
41
|
+
`${blur(1.5)}<circle cx="40" cy="40" r="18" fill="#fff" filter="url(#b)"/>`
|
|
42
|
+
),
|
|
43
|
+
|
|
44
|
+
square: svg('0 0 40 40', '<rect x="4" y="4" width="32" height="32" fill="#fff"/>'),
|
|
45
|
+
|
|
46
|
+
soft: svg(
|
|
47
|
+
'0 0 40 40',
|
|
48
|
+
`${blur(3.2)}<ellipse cx="20" cy="20" rx="16" ry="12" fill="#fff" filter="url(#b)"/>`
|
|
49
|
+
),
|
|
50
|
+
|
|
51
|
+
diamond: svg('0 0 40 40', '<polygon points="20,0 40,20 20,40 0,20" fill="#fff"/>'),
|
|
52
|
+
|
|
53
|
+
hexagon: svg(
|
|
54
|
+
'0 0 100 100',
|
|
55
|
+
'<polygon points="50,0 93.3,25 93.3,75 50,100 6.7,75 6.7,25" fill="#fff"/>'
|
|
56
|
+
),
|
|
57
|
+
|
|
58
|
+
star: svg(
|
|
59
|
+
'0 0 100 100',
|
|
60
|
+
'<polygon points="50,0 61,35 95,35 68,57 79,91 50,70 21,91 32,57 5,35 39,35" fill="#fff"/>'
|
|
61
|
+
),
|
|
62
|
+
|
|
63
|
+
ink: svg(
|
|
64
|
+
'0 0 100 100',
|
|
65
|
+
'<defs><filter id="t">' +
|
|
66
|
+
'<feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="3" result="n"/>' +
|
|
67
|
+
'<feDisplacementMap in="SourceGraphic" in2="n" scale="15" xChannelSelector="R" yChannelSelector="G"/>' +
|
|
68
|
+
'</filter></defs>' +
|
|
69
|
+
'<circle cx="50" cy="50" r="50" fill="#fff" filter="url(#t)"/>'
|
|
70
|
+
),
|
|
71
|
+
|
|
72
|
+
heart: svg(
|
|
73
|
+
'0 0 100 100',
|
|
74
|
+
'<path fill="#fff" d="M50 88C25 65 5 50 5 30 5 15 15 5 30 5c10 0 18 7 20 13 2-6 10-13 20-13 15 0 25 10 25 25 0 20-20 35-45 58Z"/>'
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function toBase64(markup) {
|
|
79
|
+
return Buffer.from(markup, 'utf8').toString('base64')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function maskVariables() {
|
|
83
|
+
const vars = {}
|
|
84
|
+
for (const [name, markup] of Object.entries(MASK_SVG)) {
|
|
85
|
+
vars[`--mask-${name}`] = `url("data:image/svg+xml;base64,${toBase64(markup)}")`
|
|
86
|
+
}
|
|
87
|
+
return vars
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** `:root` declaration block exposing every shape as `--mask-<name>`. */
|
|
91
|
+
export function maskCustomProperties() {
|
|
92
|
+
const declarations = Object.entries(maskVariables())
|
|
93
|
+
.map(([name, value]) => `${name}:${value}`)
|
|
94
|
+
.join(';')
|
|
95
|
+
|
|
96
|
+
return `:root{${declarations}}`
|
|
97
|
+
}
|
package/src/plugin.cjs
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const plugin = require('tailwindcss/plugin')
|
|
2
|
+
const { engineBase } = require('./engine.cjs')
|
|
3
|
+
const effects = require('./effects.cjs')
|
|
4
|
+
const { registerCompound } = require('./compound.cjs')
|
|
5
|
+
const { duration, delay, steps } = require('./theme.json')
|
|
6
|
+
|
|
7
|
+
module.exports = plugin(
|
|
8
|
+
function viewfx({ addBase, addUtilities, matchUtilities, theme }) {
|
|
9
|
+
addBase(engineBase())
|
|
10
|
+
addUtilities(effects)
|
|
11
|
+
registerCompound({ matchUtilities })
|
|
12
|
+
|
|
13
|
+
matchUtilities(
|
|
14
|
+
{
|
|
15
|
+
'fx-duration': (value) => ({ '--fx-duration-override': value })
|
|
16
|
+
},
|
|
17
|
+
{ values: theme('fxDuration') }
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
matchUtilities(
|
|
21
|
+
{
|
|
22
|
+
'fx-delay': (value) => ({ '--fx-delay': value })
|
|
23
|
+
},
|
|
24
|
+
{ values: theme('fxDelay') }
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
matchUtilities(
|
|
28
|
+
{
|
|
29
|
+
'fx-steps': (value) => ({ '--fx-ease-override': `steps(${value})` })
|
|
30
|
+
},
|
|
31
|
+
{ values: theme('fxSteps') }
|
|
32
|
+
)
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
theme: {
|
|
36
|
+
fxDuration: duration,
|
|
37
|
+
fxDelay: delay,
|
|
38
|
+
fxSteps: steps
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
)
|
package/src/plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './plugin.cjs'
|
package/src/theme.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"duration": {
|
|
3
|
+
"none": "0ms",
|
|
4
|
+
"slower": "500ms",
|
|
5
|
+
"slow": "400ms",
|
|
6
|
+
"normal": "300ms",
|
|
7
|
+
"fast": "200ms",
|
|
8
|
+
"faster": "100ms",
|
|
9
|
+
"0": "0ms",
|
|
10
|
+
"100": "100ms",
|
|
11
|
+
"150": "150ms",
|
|
12
|
+
"200": "200ms",
|
|
13
|
+
"250": "250ms",
|
|
14
|
+
"300": "300ms",
|
|
15
|
+
"400": "400ms",
|
|
16
|
+
"500": "500ms",
|
|
17
|
+
"700": "700ms",
|
|
18
|
+
"800": "800ms",
|
|
19
|
+
"900": "900ms",
|
|
20
|
+
"1000": "1000ms"
|
|
21
|
+
},
|
|
22
|
+
"delay": {
|
|
23
|
+
"none": "0ms",
|
|
24
|
+
"0": "0ms",
|
|
25
|
+
"100": "100ms",
|
|
26
|
+
"150": "150ms",
|
|
27
|
+
"200": "200ms",
|
|
28
|
+
"250": "250ms",
|
|
29
|
+
"300": "300ms",
|
|
30
|
+
"400": "400ms",
|
|
31
|
+
"500": "500ms",
|
|
32
|
+
"700": "700ms",
|
|
33
|
+
"800": "800ms",
|
|
34
|
+
"900": "900ms",
|
|
35
|
+
"1000": "1000ms"
|
|
36
|
+
},
|
|
37
|
+
"steps": {
|
|
38
|
+
"none": "0",
|
|
39
|
+
"retro": "8",
|
|
40
|
+
"normal": "16",
|
|
41
|
+
"modern": "24"
|
|
42
|
+
}
|
|
43
|
+
}
|