keyframekit 1.2.0 → 1.2.1
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/dist/KeyframeKit.min.js +1 -0
- package/dist/KeyframeKit.min.js.map +1 -0
- package/package.json +6 -3
- package/docs/.vitepress/components/Playground/Playground.js +0 -243
- package/docs/.vitepress/components/Playground/Playground.vue +0 -208
- package/docs/.vitepress/components/Playground/defaultExample.js +0 -175
- package/docs/.vitepress/components/Playground/interFont.js +0 -14
- package/docs/.vitepress/components/Playground/themes/githubDark.js +0 -402
- package/docs/.vitepress/components/Playground/themes/githubLight.js +0 -399
- package/docs/.vitepress/components/Playground/themes.js +0 -24
- package/docs/.vitepress/config.ts +0 -136
- package/docs/.vitepress/referenceNavigation.ts +0 -37
- package/docs/.vitepress/theme/base-styles.css +0 -147
- package/docs/.vitepress/theme/env.d.ts +0 -5
- package/docs/.vitepress/theme/index.ts +0 -40
- package/docs/docs/get-started.md +0 -131
- package/docs/docs/index.md +0 -17
- package/docs/docs/public/icon.png +0 -0
- package/docs/docs/public/og-image.png +0 -0
- package/docs/docs/public/playground/KeyframeKit/dist/KeyframeKit.d.ts +0 -172
- package/docs/docs/public/playground/KeyframeKit/dist/KeyframeKit.d.ts.map +0 -1
- package/docs/docs/public/playground/KeyframeKit/dist/KeyframeKit.js +0 -327
- package/docs/docs/public/playground/KeyframeKit/dist/KeyframeKit.js.map +0 -1
- package/docs/docs/public/playground/KeyframeKit/dist/KeyframeKit.min.js +0 -5
- package/docs/docs/reference/classes/KeyframeEffectParameters.md +0 -104
- package/docs/docs/reference/classes/ParsedKeyframes.md +0 -58
- package/docs/docs/reference/index.md +0 -20
- package/docs/docs/reference/interfaces/KeyframesFactory.md +0 -189
- package/docs/docs/reference/navigation.json +0 -64
- package/docs/docs/reference/type-aliases/CSSStyleSheetSource.md +0 -13
- package/docs/docs/reference/type-aliases/KeyframeArgument.md +0 -15
- package/docs/docs/reference/type-aliases/ParsedKeyframesRules.md +0 -22
- package/docs/docs/reference/variables/default.md +0 -12
- package/docs/package-lock.json +0 -2321
- package/docs/package.json +0 -22
- package/docs/typedoc/plugin-markdown-mdn-links-fix.js +0 -43
- package/docs/typedoc/plugin-markdown-see-also.js +0 -262
- package/docs/typedoc/plugin-param-names.js +0 -17
- package/docs/typedoc.config.js +0 -81
- package/docs/vercel.json +0 -14
- package/rollup.config.js +0 -42
- package/tsconfig.default.json +0 -44
- package/tsconfig.json +0 -10
package/dist/KeyframeKit.min.js
CHANGED
|
@@ -3,3 +3,4 @@
|
|
|
3
3
|
* MIT License
|
|
4
4
|
*/
|
|
5
5
|
const e="%",t="-",s="--",r="-webkit-";var o=new class{Error={KeyframesRuleNameTypeError:class extends TypeError{message="Keyframes rule name must be a string."},SourceTypeError:class extends TypeError{message="Source must be either a CSSStyleSheet or a StyleSheetList."},StyleSheetImportError:class extends Error{message="The stylesheet could not be imported."}};async getDocumentStyleSheetsOnLoad({document:e=window.document}={}){return await async function({document:e}){if("complete"===e.readyState)return;const{promise:t,resolve:s}=Promise.withResolvers();function r(){"complete"===e.readyState&&s(null)}const o=["readystatechange",r];e.addEventListener(...o),await t,e.removeEventListener(...o)}({document:e}),e.styleSheets}async importStyleSheet(e){const t=await fetch(e);if(!t.ok)throw new this.Error.StyleSheetImportError;const s=await t.text(),r=e.split("/").slice(0,-1).join("/"),o=new CSSStyleSheet({baseURL:r});return await o.replace(s),o}getStyleSheetKeyframes({of:e,in:t}){if("string"!=typeof e)throw new this.Error.KeyframesRuleNameTypeError;if(t instanceof StyleSheetList)return this.#e({of:e,styleSheetList:t});if(t instanceof CSSStyleSheet)return this.#t({of:e,styleSheet:t});throw new this.Error.SourceTypeError}#e({of:e,styleSheetList:t}){for(const s of t){const t=this.#t({of:e,styleSheet:s});if(void 0!==t)return t}}#t({of:e,styleSheet:t}){for(const s of t.cssRules)if(s instanceof CSSKeyframesRule&&s.name===e){return this.parseKeyframesRule({rule:s})}}getAllStyleSheetKeyframesRules({in:e}){if(e instanceof StyleSheetList)return this.#s({styleSheetList:e});if(e instanceof CSSStyleSheet)return this.#r({styleSheet:e});throw new this.Error.SourceTypeError}#s({styleSheetList:e}){let t={};for(const s of e){const e=this.#r({styleSheet:s});t={...t,...e}}return t}#r({styleSheet:e}){let t={};for(const s of e.cssRules){if(!(s instanceof CSSKeyframesRule))continue;const e=this.parseKeyframesRule({rule:s});t[s.name]=e}return t}parseKeyframesRule({rule:t}){let s=[];for(const r of t){const t=l({of:r.keyText,suffix:e}),o=Number(t)/100;let n={};for(const e of r.style){const t=r.style.getPropertyValue(e);n[this.#o(e)]=t}const i={...n,offset:o};s.push(i)}return new i(s)}#o(e){if(this.#n(e))return e;if("float"===e)return"cssFloat";if("offset"===e)return"cssOffset";const t=this.#i(e);return this.#l(e,t)}#l(e,s=!1){let r="",o=!1;s&&(e=e.slice(1));for(const s of e)s===t?o=!0:o?(o=!1,r+=s.toUpperCase()):r+=s;return r}#n(e){return e.startsWith(s)&&e!==s}#i(e){return e.startsWith(r)}};class n{keyframes;options;constructor({keyframes:e,options:t={}}){this.keyframes=e,this.options=this.#a(t)}toAnimation({target:e,options:t={},timeline:s=document.timeline}){t=this.#a(t);const r={...this.options,...t},o=new KeyframeEffect(e,this.keyframes,r);return new Animation(o,s)}#a(e){return"number"==typeof e?{duration:e}:e}}class i{keyframes;constructor(e){this.keyframes=e}toKeyframeEffect(e){let t;return t=new n(null!==e?{keyframes:this.keyframes,options:e}:{keyframes:this.keyframes}),t}}function l({of:e,suffix:t}){return e.slice(0,-t.length)}export{n as KeyframeEffectParameters,i as ParsedKeyframes,o as default};
|
|
6
|
+
//# sourceMappingURL=KeyframeKit.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeyframeKit.min.js","sources":["../src/KeyframeKit.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;AAQA"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyframekit",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Unlock fine-grained control over your CSS animations with JavaScript.",
|
|
5
5
|
"main": "./dist/KeyframeKit.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "tsc && rollup -c",
|
|
8
|
-
"docs:bump": "(cd docs && npm run bump)"
|
|
9
|
-
"docs:build": "(cd docs && npm run build)"
|
|
8
|
+
"docs:bump": "(cd docs && npm run bump)"
|
|
10
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
11
14
|
"repository": {
|
|
12
15
|
"type": "git",
|
|
13
16
|
"url": "git+https://github.com/benhatsor/KeyframeKit.git"
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
2
|
-
|
|
3
|
-
import { themes } from './themes.js'
|
|
4
|
-
//import * as monaco from 'monaco-editor'
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import loader from '@monaco-editor/loader'
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const langMap = { HTML: 'html', CSS: 'css', JS: 'javascript' }
|
|
11
|
-
|
|
12
|
-
export function playground(props, previewFrame, getDefaultExample, interFontDec) {
|
|
13
|
-
const tabs = ['JS', 'CSS', 'HTML']
|
|
14
|
-
const activeTab = ref('JS')
|
|
15
|
-
const code = ref({ HTML: '', CSS: '', JS: '' })
|
|
16
|
-
const isLoaded = ref(false);
|
|
17
|
-
|
|
18
|
-
const libCode = {
|
|
19
|
-
decLibSrc: '',
|
|
20
|
-
libImportMap: ''
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const editorRefs = {}
|
|
24
|
-
const editorInstances = {}
|
|
25
|
-
|
|
26
|
-
const models = {}
|
|
27
|
-
|
|
28
|
-
function setEditorRef(tab, el) {
|
|
29
|
-
if (el) editorRefs[tab] = el
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
let updateTimer = null
|
|
33
|
-
function scheduleUpdate() {
|
|
34
|
-
if (updateTimer !== null) clearTimeout(updateTimer)
|
|
35
|
-
updateTimer = setTimeout(updatePreview, 300)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function updatePreview() {
|
|
39
|
-
|
|
40
|
-
if (!previewFrame.value) return;
|
|
41
|
-
|
|
42
|
-
const doc = `
|
|
43
|
-
<!DOCTYPE html>
|
|
44
|
-
<html>
|
|
45
|
-
<head>
|
|
46
|
-
<base href="${window.location.href}">
|
|
47
|
-
<style>${code.value.CSS}</style>
|
|
48
|
-
<link rel="stylesheet" href="${interFontDec}">
|
|
49
|
-
</head>
|
|
50
|
-
<body>
|
|
51
|
-
${code.value.HTML}
|
|
52
|
-
${libCode.libImportMap}
|
|
53
|
-
<script type="module">${code.value.JS}<\/script>
|
|
54
|
-
</body>
|
|
55
|
-
</html>`
|
|
56
|
-
const blob = new Blob([doc], { type: 'text/html' })
|
|
57
|
-
previewFrame.value.src = URL.createObjectURL(blob)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function addLibrary(monaco) {
|
|
61
|
-
|
|
62
|
-
// validation settings
|
|
63
|
-
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
|
64
|
-
noSemanticValidation: false,
|
|
65
|
-
noSyntaxValidation: false
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// compiler options
|
|
69
|
-
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
|
70
|
-
target: 'esnext',
|
|
71
|
-
module: 'esnext',
|
|
72
|
-
allowNonTsExtensions: true,
|
|
73
|
-
allowImportingTsExtensions: true,
|
|
74
|
-
paths: {
|
|
75
|
-
"keyframekit": ["file:///KeyframeKit"]
|
|
76
|
-
},
|
|
77
|
-
baseUrl: './',
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const decLibModel = createModel(
|
|
81
|
-
libCode.decLibSrc,
|
|
82
|
-
'typescript',
|
|
83
|
-
'file:///KeyframeKit.d.ts',
|
|
84
|
-
monaco
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function createModel(srcStr, language, uriStr, monaco) {
|
|
90
|
-
|
|
91
|
-
const uri = monaco.Uri.parse(uriStr);
|
|
92
|
-
|
|
93
|
-
const existing = monaco.editor.getModel(uri)
|
|
94
|
-
|
|
95
|
-
if (existing) existing.dispose()
|
|
96
|
-
|
|
97
|
-
const model = monaco.editor.createModel(srcStr, language, uri);
|
|
98
|
-
|
|
99
|
-
models[uriStr] = model;
|
|
100
|
-
|
|
101
|
-
return model;
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function applyTheme(monaco) {
|
|
106
|
-
const dark = document.documentElement.classList.contains('dark')
|
|
107
|
-
monaco.editor.setTheme(dark ? 'vp-dark' : 'vp-light')
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function watchTheme(monaco) {
|
|
111
|
-
applyTheme(monaco)
|
|
112
|
-
new MutationObserver(() => applyTheme(monaco))
|
|
113
|
-
.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
onMounted(async () => {
|
|
117
|
-
|
|
118
|
-
const isTouchDevice = window.matchMedia('(hover: none)').matches;
|
|
119
|
-
|
|
120
|
-
code.value = getDefaultExample({ isTouchDevice });
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// note: the absolute URLs here are important, because if they were relative,
|
|
124
|
-
// they would return an invalid response when navigating from another page due to a vue bug.
|
|
125
|
-
|
|
126
|
-
libCode.decLibSrc = await (await fetch('/playground/KeyframeKit/dist/KeyframeKit.d.ts')).text();
|
|
127
|
-
|
|
128
|
-
const jsLibSrc = await (await fetch('/playground/KeyframeKit/dist/KeyframeKit.js')).text();
|
|
129
|
-
|
|
130
|
-
libCode.libImportMap = `
|
|
131
|
-
<script type="importmap">
|
|
132
|
-
{
|
|
133
|
-
"imports": {
|
|
134
|
-
"keyframekit": "data:text/javascript;base64,${btoa(jsLibSrc)}"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
</script>
|
|
138
|
-
`;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
updatePreview()
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
//const monaco = await import('monaco-editor')
|
|
145
|
-
|
|
146
|
-
loader.config({
|
|
147
|
-
paths: {
|
|
148
|
-
vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs'
|
|
149
|
-
}
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
const monaco = await loader.init()
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const config = {
|
|
156
|
-
fontSize: 16,
|
|
157
|
-
fontFamily: 'var(--vp-font-family-mono)',
|
|
158
|
-
minimap: { enabled: false },
|
|
159
|
-
scrollBeyondLastLine: false,
|
|
160
|
-
padding: { top: 20, bottom: 20 },
|
|
161
|
-
automaticLayout: true,
|
|
162
|
-
fixedOverflowWidgets: true,
|
|
163
|
-
renderLineHighlightOnlyWhenFocus: true,
|
|
164
|
-
|
|
165
|
-
inertialScroll: isTouchDevice,
|
|
166
|
-
mouseWheelScrollSensitivity: isTouchDevice ? 10 : 1,
|
|
167
|
-
scrollPredominantAxis: !isTouchDevice,
|
|
168
|
-
smoothScrolling: isTouchDevice,
|
|
169
|
-
contextmenu: !isTouchDevice,
|
|
170
|
-
|
|
171
|
-
tabSize: 2,
|
|
172
|
-
lineNumbers: "off",
|
|
173
|
-
scrollbar: {
|
|
174
|
-
ignoreHorizontalScrollbarInContentHeight: true
|
|
175
|
-
},
|
|
176
|
-
lightbulb: {
|
|
177
|
-
enabled: 'off'
|
|
178
|
-
}
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
monaco.editor.defineTheme('vp-dark', themes.dark);
|
|
182
|
-
monaco.editor.defineTheme('vp-light', themes.light);
|
|
183
|
-
|
|
184
|
-
watchTheme(monaco);
|
|
185
|
-
|
|
186
|
-
addLibrary(monaco);
|
|
187
|
-
|
|
188
|
-
tabs.forEach(tab => {
|
|
189
|
-
|
|
190
|
-
let instance;
|
|
191
|
-
|
|
192
|
-
if (langMap[tab] === 'javascript') {
|
|
193
|
-
|
|
194
|
-
// Mark as lang: typescript so we can see the full type annotations on hover,
|
|
195
|
-
// but prefix the file with .js so as to not allow actual type annotations in the file's code.
|
|
196
|
-
const mainModel = createModel(
|
|
197
|
-
code.value[tab],
|
|
198
|
-
'typescript',
|
|
199
|
-
'file:///main.js',
|
|
200
|
-
monaco
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
instance = monaco.editor.create(editorRefs[tab], {
|
|
204
|
-
model: mainModel,
|
|
205
|
-
...config
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
} else {
|
|
209
|
-
|
|
210
|
-
instance = monaco.editor.create(editorRefs[tab], {
|
|
211
|
-
value: code.value[tab],
|
|
212
|
-
language: langMap[tab],
|
|
213
|
-
...config
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
instance.onDidChangeModelContent(() => {
|
|
219
|
-
code.value[tab] = instance.getValue()
|
|
220
|
-
scheduleUpdate()
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
editorInstances[tab] = instance
|
|
224
|
-
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
isLoaded.value = true;
|
|
229
|
-
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
onBeforeUnmount(() => {
|
|
233
|
-
|
|
234
|
-
Object.values(editorInstances).forEach(e => e.dispose())
|
|
235
|
-
|
|
236
|
-
Object.values(models).forEach(e => e.dispose())
|
|
237
|
-
|
|
238
|
-
if (updateTimer) clearTimeout(updateTimer)
|
|
239
|
-
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
return { tabs, activeTab, setEditorRef, isLoaded }
|
|
243
|
-
}
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="playground" :class="{ loaded: isLoaded === true }">
|
|
3
|
-
<div class="editor-pane">
|
|
4
|
-
<div class="tabs">
|
|
5
|
-
<button
|
|
6
|
-
v-for="tab in tabs"
|
|
7
|
-
:key="tab"
|
|
8
|
-
class="tab"
|
|
9
|
-
:class="{ active: activeTab === tab }"
|
|
10
|
-
@click="activeTab = tab"
|
|
11
|
-
>
|
|
12
|
-
{{ tab }}
|
|
13
|
-
</button>
|
|
14
|
-
</div>
|
|
15
|
-
<div class="editor-container">
|
|
16
|
-
|
|
17
|
-
<div
|
|
18
|
-
v-for="tab in tabs"
|
|
19
|
-
:key="tab"
|
|
20
|
-
:ref="el => setEditorRef(tab, el)"
|
|
21
|
-
class="editor-mount"
|
|
22
|
-
:style="{ visibility: activeTab === tab ? 'visible' : 'hidden' }"
|
|
23
|
-
/>
|
|
24
|
-
|
|
25
|
-
<svg class="loader" width="18" height="18" viewBox="0 0 100 100"><rect fill="#555555" height="10" opacity="0" rx="5" ry="5" transform="rotate(-90 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.125" rx="5" ry="5" transform="rotate(-45 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.25" rx="5" ry="5" transform="rotate(0 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.375" rx="5" ry="5" transform="rotate(45 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.5" rx="5" ry="5" transform="rotate(90 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.625" rx="5" ry="5" transform="rotate(135 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.75" rx="5" ry="5" transform="rotate(180 50 50)" width="28" x="67" y="45"></rect><rect fill="#555555" height="10" opacity="0.875" rx="5" ry="5" transform="rotate(225 50 50)" width="28" x="67" y="45"></rect></svg>
|
|
26
|
-
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
|
|
30
|
-
<div class="preview-pane">
|
|
31
|
-
<iframe ref="previewFrame" class="preview-frame" sandbox="allow-scripts" />
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
</template>
|
|
35
|
-
|
|
36
|
-
<script setup>
|
|
37
|
-
import { ref } from 'vue'
|
|
38
|
-
import { playground } from './Playground.js'
|
|
39
|
-
|
|
40
|
-
import { getDefaultExample } from './defaultExample.js';
|
|
41
|
-
//import * as libCode from './libCode.js';
|
|
42
|
-
|
|
43
|
-
import { interFontDec } from './interFont.js';
|
|
44
|
-
|
|
45
|
-
const props = defineProps({
|
|
46
|
-
//initialHtml: { type: String, default: defaultExample.html },
|
|
47
|
-
//initialCss: { type: String, default: defaultExample.css },
|
|
48
|
-
//initialJs: { type: String, default: defaultExample.js },
|
|
49
|
-
|
|
50
|
-
//decLibSrc: { type: String, default: libCode.decLibSrc },
|
|
51
|
-
//libImportMap: { type: String, default: libCode.libImportMap }
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const previewFrame = ref(null)
|
|
55
|
-
const { tabs, activeTab, isLoaded, setEditorRef } = playground(props, previewFrame, getDefaultExample, interFontDec)
|
|
56
|
-
</script>
|
|
57
|
-
|
|
58
|
-
<style scoped>
|
|
59
|
-
.playground {
|
|
60
|
-
display: flex;
|
|
61
|
-
height: 500px;
|
|
62
|
-
--border-radius: 8px;
|
|
63
|
-
border-radius: var(--border-radius);
|
|
64
|
-
overflow: hidden;
|
|
65
|
-
/* margin-bottom: 48px; */
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
@media (max-width: 1000px) {
|
|
69
|
-
.playground {
|
|
70
|
-
flex-flow: column-reverse;
|
|
71
|
-
}
|
|
72
|
-
.playground .preview-pane {
|
|
73
|
-
border-bottom-width: 0;
|
|
74
|
-
border-left-width: 1px;
|
|
75
|
-
border-radius: var(--border-radius) var(--border-radius) 0 0;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@media (max-width: 640px) {
|
|
80
|
-
.playground {
|
|
81
|
-
margin-left: -24px;
|
|
82
|
-
margin-right: -24px;
|
|
83
|
-
--border-radius: 0;
|
|
84
|
-
}
|
|
85
|
-
.playground .preview-pane {
|
|
86
|
-
border-right-width: 0;
|
|
87
|
-
border-left-width: 0;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/*
|
|
92
|
-
@media (min-width: 640px) {
|
|
93
|
-
.playground {
|
|
94
|
-
margin-bottom: 64px;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
*/
|
|
98
|
-
|
|
99
|
-
.editor-pane {
|
|
100
|
-
display: flex;
|
|
101
|
-
flex-direction: column;
|
|
102
|
-
background: var(--vp-code-block-bg);
|
|
103
|
-
flex: 1;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.tabs {
|
|
107
|
-
display: flex;
|
|
108
|
-
flex-shrink: 0;
|
|
109
|
-
padding: 0 12px;
|
|
110
|
-
background-color: var(--vp-code-tab-bg);
|
|
111
|
-
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.tab {
|
|
115
|
-
position: relative;
|
|
116
|
-
display: inline-block;
|
|
117
|
-
border-bottom: 1px solid transparent;
|
|
118
|
-
padding: 0 12px;
|
|
119
|
-
line-height: 48px;
|
|
120
|
-
font-size: 14px;
|
|
121
|
-
font-weight: 500;
|
|
122
|
-
color: var(--vp-code-tab-text-color);
|
|
123
|
-
white-space: nowrap;
|
|
124
|
-
cursor: pointer;
|
|
125
|
-
transition: color 0.25s;
|
|
126
|
-
}
|
|
127
|
-
.tab:hover {
|
|
128
|
-
color: var(--vp-code-tab-hover-text-color);
|
|
129
|
-
}
|
|
130
|
-
.tab.active {
|
|
131
|
-
color: var(--vp-code-tab-active-text-color);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.tab::after {
|
|
135
|
-
position: absolute;
|
|
136
|
-
right: 8px;
|
|
137
|
-
bottom: -1px;
|
|
138
|
-
left: 8px;
|
|
139
|
-
z-index: 1;
|
|
140
|
-
height: 2px;
|
|
141
|
-
border-radius: 2px;
|
|
142
|
-
content: '';
|
|
143
|
-
background-color: transparent;
|
|
144
|
-
/* transition: background-color 0.25s; */
|
|
145
|
-
}
|
|
146
|
-
.tab.active::after {
|
|
147
|
-
background-color: var(--vp-code-tab-active-bar-color);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.editor-container {
|
|
151
|
-
flex: 1;
|
|
152
|
-
/* overflow: hidden; */
|
|
153
|
-
position: relative;
|
|
154
|
-
}
|
|
155
|
-
.editor-mount {
|
|
156
|
-
width: 100%;
|
|
157
|
-
height: 100%;
|
|
158
|
-
position: absolute;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.editor-container .loader {
|
|
162
|
-
translate: -50% -50%;
|
|
163
|
-
left: 50%;
|
|
164
|
-
top: 50%;
|
|
165
|
-
position: relative;
|
|
166
|
-
color: var(--vp-c-text-2);
|
|
167
|
-
pointer-events: none;
|
|
168
|
-
animation: spin8 0.8s steps(8) infinite;
|
|
169
|
-
transition: .18s ease-in-out .18s opacity;
|
|
170
|
-
|
|
171
|
-
@starting-style {
|
|
172
|
-
opacity: 0;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.editor-container .loader rect {
|
|
177
|
-
fill: currentColor;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.playground.loaded .loader {
|
|
181
|
-
display: none;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
@keyframes spin8 {
|
|
185
|
-
from {
|
|
186
|
-
transform: rotate(180deg);
|
|
187
|
-
}
|
|
188
|
-
to {
|
|
189
|
-
transform: rotate(540deg);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.preview-pane {
|
|
194
|
-
border: 1px solid var(--vp-code-block-bg);
|
|
195
|
-
border-left-width: 0;
|
|
196
|
-
flex: 1;
|
|
197
|
-
display: flex;
|
|
198
|
-
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
|
199
|
-
overflow: hidden;
|
|
200
|
-
background: #f0f7ff;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.preview-frame {
|
|
204
|
-
flex: 1;
|
|
205
|
-
width: 100%;
|
|
206
|
-
border: none;
|
|
207
|
-
}
|
|
208
|
-
</style>
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
// const isTouchDevice = window.matchMedia('(hover: none)').matches;
|
|
3
|
-
export function getDefaultExample({ isTouchDevice }) {
|
|
4
|
-
|
|
5
|
-
const jsAnimActivateEvent = isTouchDevice ? 'touchstart' : 'mouseenter';
|
|
6
|
-
const jsAnimDeactivateEvent = isTouchDevice ? 'touchend' : 'mouseleave';
|
|
7
|
-
|
|
8
|
-
const js = `import KeyframeKit from 'keyframekit';
|
|
9
|
-
|
|
10
|
-
const documentStyleSheets = await KeyframeKit.getDocumentStyleSheetsOnLoad();
|
|
11
|
-
|
|
12
|
-
// get animation keyframes from the document's stylesheets
|
|
13
|
-
const rotateAnimKeyframes = KeyframeKit.getStyleSheetKeyframes({
|
|
14
|
-
of: 'rotate',
|
|
15
|
-
in: documentStyleSheets
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// then, define your animation
|
|
19
|
-
const rotateAnim = rotateAnimKeyframes.toKeyframeEffect({
|
|
20
|
-
duration: 700,
|
|
21
|
-
easing: 'ease'
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// finally, attach it to your elements:
|
|
25
|
-
|
|
26
|
-
let attachedAnims = [];
|
|
27
|
-
let animDelay = 0;
|
|
28
|
-
|
|
29
|
-
const spans = document.querySelectorAll('.text-anim span');
|
|
30
|
-
|
|
31
|
-
for (const span of spans) {
|
|
32
|
-
|
|
33
|
-
const attachedAnim = rotateAnim.toAnimation({
|
|
34
|
-
target: span,
|
|
35
|
-
options: {
|
|
36
|
-
delay: animDelay * 1000,
|
|
37
|
-
endDelay: -animDelay * 1000
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
attachedAnims.push(attachedAnim);
|
|
42
|
-
|
|
43
|
-
animDelay += .02;
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
attachedAnims.forEach(anim => anim.play());
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// the primary reason to play your animation with JS
|
|
51
|
-
// is because you get way more control over its playback:
|
|
52
|
-
|
|
53
|
-
const textAnimEl = document.querySelector('.text-anim');
|
|
54
|
-
|
|
55
|
-
textAnimEl.addEventListener('${jsAnimActivateEvent}', () => {
|
|
56
|
-
attachedAnims.forEach(anim => {
|
|
57
|
-
anim.playbackRate = 1;
|
|
58
|
-
anim.play();
|
|
59
|
-
});
|
|
60
|
-
updateProgressBar();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
textAnimEl.addEventListener('${jsAnimDeactivateEvent}', () => {
|
|
64
|
-
// reverse the animation
|
|
65
|
-
attachedAnims.forEach(anim => {
|
|
66
|
-
anim.playbackRate = -1;
|
|
67
|
-
});
|
|
68
|
-
updateProgressBar();
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const progressBar = document.querySelector('.progress-bar');
|
|
73
|
-
|
|
74
|
-
function updateProgressBar() {
|
|
75
|
-
let progress = 0;
|
|
76
|
-
for (const anim of attachedAnims) {
|
|
77
|
-
progress += anim.overallProgress;
|
|
78
|
-
}
|
|
79
|
-
progress = progress / attachedAnims.length * 100;
|
|
80
|
-
progressBar.style.setProperty(
|
|
81
|
-
'--progress', progress + '%'
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
const isPlaying = attachedAnims.some(anim =>
|
|
85
|
-
anim.playState === 'running'
|
|
86
|
-
);
|
|
87
|
-
if (!isPlaying) return;
|
|
88
|
-
requestAnimationFrame(updateProgressBar);
|
|
89
|
-
}`;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const css = `@keyframes rotate {
|
|
93
|
-
from {
|
|
94
|
-
clip-path: inset(0 0 0 0);
|
|
95
|
-
translate: 0 0;
|
|
96
|
-
}
|
|
97
|
-
49.99% {
|
|
98
|
-
clip-path: inset(100% 0 0 0);
|
|
99
|
-
translate: 0 -50px;
|
|
100
|
-
}
|
|
101
|
-
50% {
|
|
102
|
-
clip-path: inset(0 0 100% 0);
|
|
103
|
-
translate: 0 50px;
|
|
104
|
-
}
|
|
105
|
-
to {
|
|
106
|
-
clip-path: inset(0 0 0 0);
|
|
107
|
-
translate: 0 0;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
.text-anim {
|
|
113
|
-
display: flex;
|
|
114
|
-
font-size: 85px;
|
|
115
|
-
font-weight: 600;
|
|
116
|
-
color: #7ab6ff;
|
|
117
|
-
cursor: pointer;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.progress-bar {
|
|
121
|
-
width: ${isTouchDevice ? '180px' : '232px'};
|
|
122
|
-
height: 3px;
|
|
123
|
-
border-radius: 3px;
|
|
124
|
-
background: #82868942;
|
|
125
|
-
position: relative;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
.progress-bar::before {
|
|
129
|
-
content: '';
|
|
130
|
-
height: 100%;
|
|
131
|
-
width: var(--progress, 0%);
|
|
132
|
-
border-radius: inherit;
|
|
133
|
-
position: absolute;
|
|
134
|
-
background: #7ab6ff;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
body {
|
|
138
|
-
font-family: 'Inter', system-ui;
|
|
139
|
-
background: #f0f7ff;
|
|
140
|
-
height: 100vh;
|
|
141
|
-
margin: 0;
|
|
142
|
-
display: flex;
|
|
143
|
-
align-items: center;
|
|
144
|
-
justify-content: center;
|
|
145
|
-
flex-flow: column;
|
|
146
|
-
user-select: none;
|
|
147
|
-
-webkit-user-select: none;
|
|
148
|
-
}`;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const htmlDesktop = `<div class="text-anim">
|
|
152
|
-
<span>H</span>
|
|
153
|
-
<span>o</span>
|
|
154
|
-
<span>v</span>
|
|
155
|
-
<span>e</span>
|
|
156
|
-
<span>r</span>
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
|
-
<div class="progress-bar"></div>`;
|
|
160
|
-
|
|
161
|
-
const htmlMobile = `<div class="text-anim">
|
|
162
|
-
<span>H</span>
|
|
163
|
-
<span>o</span>
|
|
164
|
-
<span>l</span>
|
|
165
|
-
<span>d</span>
|
|
166
|
-
</div>
|
|
167
|
-
|
|
168
|
-
<div class="progress-bar"></div>`;
|
|
169
|
-
|
|
170
|
-
const html = isTouchDevice ? htmlMobile : htmlDesktop;
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return { JS: js, CSS: css, HTML: html };
|
|
174
|
-
|
|
175
|
-
}
|