Skip to content

Commit c9750bf

Browse files
committed
feat: validate field value before updating CodeSnippet
if the value is invalid, the default value will be used and the CodeSnippet will be updated accordingly
1 parent f777843 commit c9750bf

File tree

2 files changed

+42
-18
lines changed

2 files changed

+42
-18
lines changed

docs/.vitepress/components/Example.vue

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<script setup>
2-
/// <reference lib="es2021" />
32
import Container from './Container.vue';
43
import Button from './Button.vue';
54
import Content from './Content.vue';
@@ -17,7 +16,8 @@
1716
* contentList?: Object[],
1817
* animOpts?: Object,
1918
* fieldsList?: string[],
20-
* codeSnippet?: Object
19+
* codeSnippet?: Object,
20+
* animationFormValidation?: Object,
2121
* }}
2222
*/
2323
const props = defineProps([
@@ -30,6 +30,7 @@
3030
'animOpts',
3131
'fieldsList',
3232
'codeSnippet',
33+
'animationFormValidation',
3334
]);
3435
3536
const codeSnippetRef = ref(props.codeSnippet);
@@ -48,7 +49,7 @@
4849
function titleId() {
4950
return props.title
5051
?.toLowerCase()
51-
.replaceAll(/[\W_]/g, '-')
52+
.replace(/[\W_]/g, '-')
5253
.replace('---', '-');
5354
}
5455
@@ -59,13 +60,23 @@
5960
};
6061
/** @type {Object} */
6162
const codeSnippetRefVal = codeSnippetRef.value;
63+
const proxyHandler = {
64+
get: function (target, name) {
65+
return target.hasOwnProperty(name) ? target[name] : _ => true;
66+
},
67+
};
68+
const validateField = new Proxy(
69+
props.animationFormValidation,
70+
proxyHandler
71+
);
6272
6373
if (opts[fieldLabel] !== '') {
64-
const newValue =
65-
['duration', 'delay', 'staggerDelay'].includes(fieldLabel) &&
66-
opts[fieldLabel].match(/^(\d+|\d+\.\d+)$/)
74+
const newValue = validateField[fieldLabel](opts[fieldLabel])
75+
? ['duration', 'delay', 'staggerDelay'].includes(fieldLabel) &&
76+
opts[fieldLabel].match(/^(\d+|\d+\.\d+)$/)
6777
? `${opts[fieldLabel]}ms`
68-
: opts[fieldLabel];
78+
: opts[fieldLabel]
79+
: defaultValue[fieldLabel];
6980
7081
if (defaultValue[fieldLabel] !== newValue) {
7182
const newField =
@@ -89,15 +100,15 @@
89100
newSnippet += `${str}\n`;
90101
}
91102
}
92-
codeSnippetRefVal.code = newSnippet;
93-
reloadSnippet();
103+
codeSnippetRefVal.code = newSnippet.trimEnd();
94104
} else {
95-
codeSnippetRefVal.code = codeSnippetRefVal.code.replaceAll(
105+
codeSnippetRefVal.code = codeSnippetRefVal.code.replace(
96106
new RegExp(`\n.+${fieldLabel}:.+\n`, 'g'),
97107
'\n'
98108
);
99-
reloadSnippet();
100109
}
110+
if (codeSnippetRefVal.highlight) codeSnippetRefVal.highlight = [];
111+
reloadSnippet();
101112
102113
if (fieldLabel === 'maintainSpace') {
103114
if (opts[fieldLabel] === false) {

docs/examples/index.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,18 @@ aside: false
7474
jsCssAnimations.init.collapse(collapseOpts)
7575
}
7676

77+
const validateAnimationFormField = {
78+
timePropertyValidation: val => val.match(/^(\d+|\d+\.\d+)(ms|s)?$/),
79+
blur: val => val.match(/^(\d+|\d+\.\d+)(px|rem|em)$/),
80+
easing: val => {
81+
const easingRegEx = /^(ease(-in|-out|-in-out)?|linear|cubic-bezier\((0|1|0.\d+), -?[\d\.]+, (0|1|0.\d+), -?[\d\.]+\)|step\((100|[0-9][0-9]|[0-9]),\s?(jump-start|jump-end|jump-none|jump-both|start|end)\)|step\(step-(start|end)\))$/;
82+
return val && val.match(easingRegEx)
83+
},
84+
duration: val => validateAnimationFormField.timePropertyValidation(val),
85+
delay: val => validateAnimationFormField.timePropertyValidation(val),
86+
staggerDelay: val => validateAnimationFormField.timePropertyValidation(val),
87+
}
88+
7789
function resetAnimation(animName, {opts}) {
7890
const btnList = examples[animName].btnList;
7991
btnList.forEach(btn => {
@@ -88,22 +100,20 @@ aside: false
88100
blur: '0.5px'
89101
}
90102

91-
const easingRegEx = /^(ease(-in|-out|-in-out)?|linear|cubic-bezier\((0|1|0.\d+), -?[\d\.]+, (0|1|0.\d+), -?[\d\.]+\)|step\((100|[0-9][0-9]|[0-9]),\s?(jump-start|jump-end|jump-none|jump-both|start|end)\)|step\(step-(start|end)\))$/;
92-
93103
if (opts.maintainSpace) opts.dimensionsTransition = false;
94-
if (!opts.blur.match(/^(\d+|\d+\.\d+)(px|rem|em)$/)) opts.blur = defaultValue.blur;
95-
if (!opts.easing || !opts.easing.match(easingRegEx))
104+
if (!validateAnimationFormField.blur(opts.blur)) opts.blur = defaultValue.blur;
105+
if (!validateAnimationFormField.easing(opts.easing))
96106
opts.easing = defaultValue.timingFunction;
97107
['duration', 'delay', 'staggerDelay'].forEach(prop => {
98-
if (opts[prop].match(/^\d+$/)) opts[prop] = `${opts[prop]}ms`;
99-
else if (!opts[prop].match(/^(\d+|\d+\.\d+)(ms|s)$/)) {
108+
if (opts[prop].match(/^(\d+|\d+\.\d+)$/)) opts[prop] = `${opts[prop]}ms`;
109+
else if (!validateAnimationFormField[prop](opts[prop])) {
100110
opts[prop] = defaultValue[prop];
101111
}
102112
});
103113

104114
const animation = animName === 'slide'
105115
? (triggerSelector.replace('--btn','')
106-
.replace(/-(\w)/,(l) => l.toUpperCase()).replaceAll(/[-\.]/g,''))
116+
.replace(/-(\w)/,(l) => l.toUpperCase()).replace(/[-\.]/g,''))
107117
: animName;
108118
jsCssAnimations.init[animation]({
109119
trigger: triggerSelector,
@@ -132,6 +142,7 @@ aside: false
132142
:anim-opts="{}"
133143
@reset-animation="(opts) => {resetAnimation('slide', opts);}"
134144
:fields-list="['duration', 'delay', 'staggerDelay', 'maintainSpace', 'easing', 'dimensionsTransition', 'overflowHidden']"
145+
:animation-form-validation="validateAnimationFormField"
135146
:code-snippet="{
136147
code: `jsCssAnimations.init.slideUp({
137148
trigger: '.slide-up--btn',
@@ -164,6 +175,7 @@ highlight: [4]
164175
:anim-opts="fadeOpts"
165176
:fields-list="['duration', 'delay', 'staggerDelay', 'maintainSpace', 'easing', 'blur', 'dimensionsTransition', 'iteration', 'direction']"
166177
@reset-animation="(opts) => {resetAnimation('fade', opts);}"
178+
:animation-form-validation="validateAnimationFormField"
167179
:code-snippet="{
168180
code: `// When 'trigger' option is omitted, .init will look for
169181
// any element(s) that have the 'js-anim--trigger' class
@@ -192,6 +204,7 @@ highlight: [4],
192204
:anim-opts="collapseOpts"
193205
:fields-list="['duration', 'delay', 'staggerDelay', 'maintainSpace', 'easing', 'dimensionsTransition', 'transfOrigin']"
194206
@reset-animation="(opts) => {resetAnimation('collapse', opts);}"
207+
:animation-form-validation="validateAnimationFormField"
195208
:code-snippet="{
196209
code: `jsCssAnimations.init.collapse({
197210
trigger: '.collapse--btn',

0 commit comments

Comments
 (0)