animot-presenter 0.2.3 → 0.2.5
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/README.md +35 -3
- package/dist/AnimotPresenter.svelte +262 -36
- package/dist/cdn/animot-presenter.css +1 -1
- package/dist/cdn/animot-presenter.esm.js +4263 -4148
- package/dist/cdn/animot-presenter.min.js +9 -9
- package/dist/types.d.ts +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -472,7 +472,7 @@ animot-presenter .animot-controls { display: none; }
|
|
|
472
472
|
|
|
473
473
|
## Features
|
|
474
474
|
|
|
475
|
-
- **Morphing animations** — Elements with the same ID across slides smoothly morph position, size, rotation, color, opacity, and
|
|
475
|
+
- **Morphing animations** — Elements with the same ID across slides smoothly morph position, size, rotation, color, opacity, border radius, and CSS filters (blur, brightness, contrast, saturate, grayscale)
|
|
476
476
|
- **Code highlighting** — Syntax highlighting via Shiki with typewriter, highlight-changes, and instant animation modes
|
|
477
477
|
- **Shape morphing** — Rectangles, circles, triangles, stars, hexagons with smooth transitions
|
|
478
478
|
- **Charts** — Animated bar, line, area, pie, and donut charts
|
|
@@ -483,7 +483,8 @@ animot-presenter .animot-controls { display: none; }
|
|
|
483
483
|
- **Transitions** — Fade, slide, zoom, flip, and morphing (none) transition types
|
|
484
484
|
- **Responsive** — Automatically scales to fit any container size
|
|
485
485
|
- **Keyboard navigation** — Arrow keys, spacebar, Home/End
|
|
486
|
-
- **
|
|
486
|
+
- **CSS filters** — Blur, brightness, contrast, saturate, and grayscale on any element, animated across slides
|
|
487
|
+
- **Property sequencing** — Fine-grained control over which properties animate first (including filters via the `blur` property sequence)
|
|
487
488
|
|
|
488
489
|
## JSON Schema
|
|
489
490
|
|
|
@@ -517,7 +518,12 @@ Animot JSON files follow this structure:
|
|
|
517
518
|
"color": "#ffffff",
|
|
518
519
|
"rotation": 0,
|
|
519
520
|
"visible": true,
|
|
520
|
-
"zIndex": 1
|
|
521
|
+
"zIndex": 1,
|
|
522
|
+
"blur": 0,
|
|
523
|
+
"brightness": 100,
|
|
524
|
+
"contrast": 100,
|
|
525
|
+
"saturate": 100,
|
|
526
|
+
"grayscale": 0
|
|
521
527
|
}
|
|
522
528
|
]
|
|
523
529
|
},
|
|
@@ -563,6 +569,32 @@ You can replace the base64 data URL with a remote or local URL:
|
|
|
563
569
|
|
|
564
570
|
This lets you keep your JSON files lightweight by hosting images separately instead of embedding them as base64. The same applies to text elements with `backgroundImage` and background `image` fields.
|
|
565
571
|
|
|
572
|
+
### CSS Filters
|
|
573
|
+
|
|
574
|
+
All element types support CSS filter properties that animate smoothly between slides:
|
|
575
|
+
|
|
576
|
+
```json
|
|
577
|
+
{
|
|
578
|
+
"id": "hero-image",
|
|
579
|
+
"type": "image",
|
|
580
|
+
"blur": 5,
|
|
581
|
+
"brightness": 120,
|
|
582
|
+
"contrast": 110,
|
|
583
|
+
"saturate": 80,
|
|
584
|
+
"grayscale": 0
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
| Property | Range | Default | Description |
|
|
589
|
+
|--------------|---------|---------|----------------------------------|
|
|
590
|
+
| `blur` | 0–20 | 0 | Gaussian blur in pixels |
|
|
591
|
+
| `brightness` | 0–200 | 100 | Brightness percentage (100 = normal) |
|
|
592
|
+
| `contrast` | 0–200 | 100 | Contrast percentage (100 = normal) |
|
|
593
|
+
| `saturate` | 0–200 | 100 | Saturation percentage (100 = normal) |
|
|
594
|
+
| `grayscale` | 0–100 | 0 | Grayscale percentage (0 = none) |
|
|
595
|
+
|
|
596
|
+
Set different filter values on the same element across slides to create smooth animated transitions (e.g., blur 10 on slide 1 to blur 0 on slide 2 for a reveal effect). Use the `blur` property sequence in `animationConfig.propertySequences` to control filter animation timing independently.
|
|
597
|
+
|
|
566
598
|
> **Note:** Remote URLs must allow cross-origin requests (CORS) if served from a different domain.
|
|
567
599
|
|
|
568
600
|
## Bundle Size
|
|
@@ -30,6 +30,11 @@
|
|
|
30
30
|
strokeWidth: TweenValue | null;
|
|
31
31
|
shapeMorph: TweenValue | null;
|
|
32
32
|
motionPathProgress: TweenValue | null;
|
|
33
|
+
blur: TweenValue;
|
|
34
|
+
brightness: TweenValue;
|
|
35
|
+
contrast: TweenValue;
|
|
36
|
+
saturate: TweenValue;
|
|
37
|
+
grayscale: TweenValue;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
interface ShapeMorphState { fromType: string; toType: string; }
|
|
@@ -205,8 +210,26 @@
|
|
|
205
210
|
textTypewriterState = new Map(textTypewriterState);
|
|
206
211
|
}
|
|
207
212
|
|
|
208
|
-
//
|
|
209
|
-
function
|
|
213
|
+
// Build SVG path for 3+ control points using Catmull-Rom spline
|
|
214
|
+
function buildCatmullRomPath(start: {x:number,y:number}, cps: {x:number,y:number}[], end: {x:number,y:number}): string {
|
|
215
|
+
const pts = [start, ...cps, end];
|
|
216
|
+
let d = `M ${pts[0].x} ${pts[0].y}`;
|
|
217
|
+
for (let i = 0; i < pts.length - 1; i++) {
|
|
218
|
+
const p0 = pts[i === 0 ? 0 : i - 1];
|
|
219
|
+
const p1 = pts[i];
|
|
220
|
+
const p2 = pts[i + 1];
|
|
221
|
+
const p3 = pts[i + 2 < pts.length ? i + 2 : pts.length - 1];
|
|
222
|
+
const c1x = p1.x + (p2.x - p0.x) / 6;
|
|
223
|
+
const c1y = p1.y + (p2.y - p0.y) / 6;
|
|
224
|
+
const c2x = p2.x - (p3.x - p1.x) / 6;
|
|
225
|
+
const c2y = p2.y - (p3.y - p1.y) / 6;
|
|
226
|
+
d += ` C ${c1x} ${c1y} ${c2x} ${c2y} ${p2.x} ${p2.y}`;
|
|
227
|
+
}
|
|
228
|
+
return d;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Arrow draw/undraw/draw-undraw animation action
|
|
232
|
+
function animateStyledArrowDraw(node: SVGPathElement, params: { enabled: boolean; mode: string; duration: number; dashPattern: string; startX: number; endX: number; slideIndex: number }) {
|
|
210
233
|
let lastSlideIndex = params.slideIndex;
|
|
211
234
|
let animationId: number | null = null;
|
|
212
235
|
function runAnimation() {
|
|
@@ -215,24 +238,63 @@
|
|
|
215
238
|
const svg = node.closest('svg') as SVGSVGElement | null;
|
|
216
239
|
if (!svg) return;
|
|
217
240
|
const goesLeftToRight = params.endX >= params.startX;
|
|
218
|
-
|
|
219
|
-
const startTime = performance.now();
|
|
241
|
+
const mode = params.mode;
|
|
220
242
|
const dur = params.duration;
|
|
243
|
+
const startTime = performance.now();
|
|
244
|
+
if (mode === 'draw' || mode === 'draw-undraw') {
|
|
245
|
+
svg.style.clipPath = goesLeftToRight ? 'inset(0 100% 0 0)' : 'inset(0 0 0 100%)';
|
|
246
|
+
} else if (mode === 'undraw') {
|
|
247
|
+
svg.style.clipPath = 'none';
|
|
248
|
+
}
|
|
221
249
|
function animate(currentTime: number) {
|
|
222
250
|
const elapsed = currentTime - startTime;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
251
|
+
if (mode === 'draw') {
|
|
252
|
+
const progress = Math.min(elapsed / dur, 1);
|
|
253
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
254
|
+
const inset = 100 * (1 - eased);
|
|
255
|
+
svg!.style.clipPath = goesLeftToRight ? `inset(0 ${inset}% 0 0)` : `inset(0 0 0 ${inset}%)`;
|
|
256
|
+
if (progress < 1) { animationId = requestAnimationFrame(animate); }
|
|
257
|
+
else { svg!.style.clipPath = 'none'; animationId = null; }
|
|
258
|
+
} else if (mode === 'undraw') {
|
|
259
|
+
const progress = Math.min(elapsed / dur, 1);
|
|
260
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
261
|
+
const inset = 100 * eased;
|
|
262
|
+
svg!.style.clipPath = goesLeftToRight ? `inset(0 0 0 ${inset}%)` : `inset(0 ${inset}% 0 0)`;
|
|
263
|
+
if (progress < 1) { animationId = requestAnimationFrame(animate); }
|
|
264
|
+
else { svg!.style.clipPath = 'inset(0 0 0 100%)'; animationId = null; }
|
|
265
|
+
} else if (mode === 'draw-undraw') {
|
|
266
|
+
const halfDur = dur / 2;
|
|
267
|
+
if (elapsed < halfDur) {
|
|
268
|
+
const progress = Math.min(elapsed / halfDur, 1);
|
|
269
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
270
|
+
const inset = 100 * (1 - eased);
|
|
271
|
+
svg!.style.clipPath = goesLeftToRight ? `inset(0 ${inset}% 0 0)` : `inset(0 0 0 ${inset}%)`;
|
|
272
|
+
animationId = requestAnimationFrame(animate);
|
|
273
|
+
} else {
|
|
274
|
+
const progress = Math.min((elapsed - halfDur) / halfDur, 1);
|
|
275
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
276
|
+
const inset = 100 * eased;
|
|
277
|
+
svg!.style.clipPath = goesLeftToRight ? `inset(0 0 0 ${inset}%)` : `inset(0 ${inset}% 0 0)`;
|
|
278
|
+
if (progress < 1) { animationId = requestAnimationFrame(animate); }
|
|
279
|
+
else { svg!.style.clipPath = 'inset(0 0 0 100%)'; animationId = null; }
|
|
280
|
+
}
|
|
281
|
+
}
|
|
229
282
|
}
|
|
230
283
|
animationId = requestAnimationFrame(animate);
|
|
231
284
|
}
|
|
232
285
|
runAnimation();
|
|
233
286
|
return {
|
|
234
287
|
update(newParams: typeof params) {
|
|
235
|
-
|
|
288
|
+
const slideChanged = newParams.slideIndex !== lastSlideIndex;
|
|
289
|
+
params = newParams;
|
|
290
|
+
if (!params.enabled) {
|
|
291
|
+
if (animationId) { cancelAnimationFrame(animationId); animationId = null; }
|
|
292
|
+
const svg = node.closest('svg') as SVGSVGElement | null;
|
|
293
|
+
if (svg) svg.style.clipPath = '';
|
|
294
|
+
lastSlideIndex = newParams.slideIndex;
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (slideChanged) { lastSlideIndex = newParams.slideIndex; runAnimation(); }
|
|
236
298
|
},
|
|
237
299
|
destroy() { if (animationId) cancelAnimationFrame(animationId); }
|
|
238
300
|
};
|
|
@@ -278,7 +340,12 @@
|
|
|
278
340
|
strokeColor: shapeEl ? tween(shapeEl.strokeColor, { duration: 500 }) : null,
|
|
279
341
|
strokeWidth: shapeEl ? tween(shapeEl.strokeWidth, { duration: 500 }) : null,
|
|
280
342
|
shapeMorph: shapeEl ? tween(1, { duration: 500 }) : null,
|
|
281
|
-
motionPathProgress: element.motionPathConfig ? tween(0, { duration: 500 }) : null
|
|
343
|
+
motionPathProgress: element.motionPathConfig ? tween(0, { duration: 500 }) : null,
|
|
344
|
+
blur: tween(element.blur ?? 0, { duration: 500 }),
|
|
345
|
+
brightness: tween(element.brightness ?? 100, { duration: 500 }),
|
|
346
|
+
contrast: tween(element.contrast ?? 100, { duration: 500 }),
|
|
347
|
+
saturate: tween(element.saturate ?? 100, { duration: 500 }),
|
|
348
|
+
grayscale: tween(element.grayscale ?? 0, { duration: 500 })
|
|
282
349
|
});
|
|
283
350
|
const currentSlideEl = getElementInSlide(currentSlide, element.id);
|
|
284
351
|
elementContent.set(element.id, JSON.parse(JSON.stringify(currentSlideEl || element)));
|
|
@@ -370,6 +437,11 @@
|
|
|
370
437
|
animated.perspective.to(targetEl.perspective ?? 1000, { duration: 0 });
|
|
371
438
|
animated.opacity.to(1, { duration: 0 });
|
|
372
439
|
animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: 0 });
|
|
440
|
+
animated.blur.to(targetEl.blur ?? 0, { duration: 0 });
|
|
441
|
+
animated.brightness.to(targetEl.brightness ?? 100, { duration: 0 });
|
|
442
|
+
animated.contrast.to(targetEl.contrast ?? 100, { duration: 0 });
|
|
443
|
+
animated.saturate.to(targetEl.saturate ?? 100, { duration: 0 });
|
|
444
|
+
animated.grayscale.to(targetEl.grayscale ?? 0, { duration: 0 });
|
|
373
445
|
if (targetEl.type === 'text') animated.fontSize?.to((targetEl as TextElement).fontSize, { duration: 0 });
|
|
374
446
|
if (targetEl.type === 'shape') {
|
|
375
447
|
const s = targetEl as ShapeElement;
|
|
@@ -433,6 +505,11 @@
|
|
|
433
505
|
await animated.tiltY.to(currentEl.tiltY ?? 0, { duration: 0 });
|
|
434
506
|
await animated.perspective.to(currentEl.perspective ?? 1000, { duration: 0 });
|
|
435
507
|
await animated.borderRadius.to((currentEl as any).borderRadius ?? 0, { duration: 0 });
|
|
508
|
+
await animated.blur.to(currentEl.blur ?? 0, { duration: 0 });
|
|
509
|
+
await animated.brightness.to(currentEl.brightness ?? 100, { duration: 0 });
|
|
510
|
+
await animated.contrast.to(currentEl.contrast ?? 100, { duration: 0 });
|
|
511
|
+
await animated.saturate.to(currentEl.saturate ?? 100, { duration: 0 });
|
|
512
|
+
await animated.grayscale.to(currentEl.grayscale ?? 0, { duration: 0 });
|
|
436
513
|
await animated.opacity.to(1, { duration: 0 });
|
|
437
514
|
if (currentEl.type === 'text' && animated.fontSize) await animated.fontSize.to((currentEl as TextElement).fontSize, { duration: 0 });
|
|
438
515
|
if (currentEl.type === 'shape') {
|
|
@@ -493,6 +570,13 @@
|
|
|
493
570
|
if (!sequencedProps.has('skew')) { anims.push(animated.skewX.to(targetEl.skewX ?? 0, { duration: elementDuration, easing })); anims.push(animated.skewY.to(targetEl.skewY ?? 0, { duration: elementDuration, easing })); }
|
|
494
571
|
if (!sequencedProps.has('size')) { anims.push(animated.width.to(targetEl.size.width, { duration: elementDuration, easing })); anims.push(animated.height.to(targetEl.size.height, { duration: elementDuration, easing })); }
|
|
495
572
|
if (!sequencedProps.has('borderRadius')) anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: elementDuration, easing }));
|
|
573
|
+
if (!sequencedProps.has('blur')) {
|
|
574
|
+
animated.blur.to(targetEl.blur ?? 0, { duration: elementDuration, easing });
|
|
575
|
+
animated.brightness.to(targetEl.brightness ?? 100, { duration: elementDuration, easing });
|
|
576
|
+
animated.contrast.to(targetEl.contrast ?? 100, { duration: elementDuration, easing });
|
|
577
|
+
animated.saturate.to(targetEl.saturate ?? 100, { duration: elementDuration, easing });
|
|
578
|
+
animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing });
|
|
579
|
+
}
|
|
496
580
|
if (!sequencedProps.has('perspective')) anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: elementDuration, easing }));
|
|
497
581
|
const sortedSeqs = [...propertySequences].sort((a, b) => a.order - b.order);
|
|
498
582
|
let cumulativeDelay = 0;
|
|
@@ -506,6 +590,13 @@
|
|
|
506
590
|
else if (seq.property === 'skew') { animated.skewX.to(targetEl.skewX ?? 0, { duration: seqDuration, easing }); animated.skewY.to(targetEl.skewY ?? 0, { duration: seqDuration, easing }); }
|
|
507
591
|
else if (seq.property === 'size') { animated.width.to(targetEl.size.width, { duration: seqDuration, easing }); animated.height.to(targetEl.size.height, { duration: seqDuration, easing }); }
|
|
508
592
|
else if (seq.property === 'borderRadius') animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: seqDuration, easing });
|
|
593
|
+
else if (seq.property === 'blur') {
|
|
594
|
+
animated.blur.to(targetEl.blur ?? 0, { duration: seqDuration, easing });
|
|
595
|
+
animated.brightness.to(targetEl.brightness ?? 100, { duration: seqDuration, easing });
|
|
596
|
+
animated.contrast.to(targetEl.contrast ?? 100, { duration: seqDuration, easing });
|
|
597
|
+
animated.saturate.to(targetEl.saturate ?? 100, { duration: seqDuration, easing });
|
|
598
|
+
animated.grayscale.to(targetEl.grayscale ?? 0, { duration: seqDuration, easing });
|
|
599
|
+
}
|
|
509
600
|
else if (seq.property === 'color' && targetEl.type === 'shape') {
|
|
510
601
|
const s = targetEl as ShapeElement;
|
|
511
602
|
animated.fillColor?.to(s.fillColor, { duration: seqDuration, easing });
|
|
@@ -529,6 +620,11 @@
|
|
|
529
620
|
anims.push(animated.tiltY.to(targetEl.tiltY ?? 0, { duration: elementDuration, easing }));
|
|
530
621
|
anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: elementDuration, easing }));
|
|
531
622
|
anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: elementDuration, easing }));
|
|
623
|
+
anims.push(animated.blur.to(targetEl.blur ?? 0, { duration: elementDuration, easing }));
|
|
624
|
+
anims.push(animated.brightness.to(targetEl.brightness ?? 100, { duration: elementDuration, easing }));
|
|
625
|
+
anims.push(animated.contrast.to(targetEl.contrast ?? 100, { duration: elementDuration, easing }));
|
|
626
|
+
anims.push(animated.saturate.to(targetEl.saturate ?? 100, { duration: elementDuration, easing }));
|
|
627
|
+
anims.push(animated.grayscale.to(targetEl.grayscale ?? 0, { duration: elementDuration, easing }));
|
|
532
628
|
}
|
|
533
629
|
// Motion path progress — await reset, then animate forward
|
|
534
630
|
if (animated.motionPathProgress && targetEl.motionPathConfig) {
|
|
@@ -575,6 +671,11 @@
|
|
|
575
671
|
anims.push(animated.tiltY.to(targetEl.tiltY ?? 0, { duration: 0 }));
|
|
576
672
|
anims.push(animated.perspective.to(targetEl.perspective ?? 1000, { duration: 0 }));
|
|
577
673
|
anims.push(animated.borderRadius.to((targetEl as any).borderRadius ?? 0, { duration: 0 }));
|
|
674
|
+
anims.push(animated.blur.to(targetEl.blur ?? 0, { duration: 0 }));
|
|
675
|
+
anims.push(animated.brightness.to(targetEl.brightness ?? 100, { duration: 0 }));
|
|
676
|
+
anims.push(animated.contrast.to(targetEl.contrast ?? 100, { duration: 0 }));
|
|
677
|
+
anims.push(animated.saturate.to(targetEl.saturate ?? 100, { duration: 0 }));
|
|
678
|
+
anims.push(animated.grayscale.to(targetEl.grayscale ?? 0, { duration: 0 }));
|
|
578
679
|
if (targetEl.type === 'text' && animated.fontSize) {
|
|
579
680
|
anims.push(animated.fontSize.to((targetEl as TextElement).fontSize, { duration: 0 }));
|
|
580
681
|
}
|
|
@@ -659,6 +760,13 @@
|
|
|
659
760
|
elementContent = newElementContent;
|
|
660
761
|
currentSlideIndex = targetIndex;
|
|
661
762
|
isTransitioning = false;
|
|
763
|
+
// Ensure elements not on the new slide are fully hidden
|
|
764
|
+
const newSlide = slides[targetIndex];
|
|
765
|
+
for (const elementId of allElementIds) {
|
|
766
|
+
const onSlide = getElementInSlide(newSlide, elementId);
|
|
767
|
+
const animated = animatedElements.get(elementId);
|
|
768
|
+
if (!onSlide && animated) { animated.opacity.to(0, { duration: 0 }); }
|
|
769
|
+
}
|
|
662
770
|
animateMotionPaths(slides[targetIndex]);
|
|
663
771
|
onslidechange?.(targetIndex, slides.length);
|
|
664
772
|
if (targetIndex === slides.length - 1 && !loop) oncomplete?.();
|
|
@@ -736,6 +844,64 @@
|
|
|
736
844
|
export function getTotalSlides() { return slides.length; }
|
|
737
845
|
export function getIsPlaying() { return isAutoplay; }
|
|
738
846
|
|
|
847
|
+
// Auto-load Google Fonts used by text elements in the project.
|
|
848
|
+
// Generic CSS font families that don't need loading
|
|
849
|
+
const GENERIC_FONTS = new Set([
|
|
850
|
+
'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy',
|
|
851
|
+
'system-ui', 'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded',
|
|
852
|
+
'math', 'emoji', 'fangsong', 'inherit', 'initial', 'unset'
|
|
853
|
+
]);
|
|
854
|
+
|
|
855
|
+
// Extract individual font names from a CSS font-family string.
|
|
856
|
+
// e.g. '"JetBrains Mono", system-ui, monospace' → ['JetBrains Mono']
|
|
857
|
+
function extractFontNames(fontFamily: string): string[] {
|
|
858
|
+
return fontFamily
|
|
859
|
+
.split(',')
|
|
860
|
+
.map(f => f.trim().replace(/^['"]|['"]$/g, ''))
|
|
861
|
+
.filter(f => f && !GENERIC_FONTS.has(f.toLowerCase()));
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// Auto-load fonts used by text/counter elements.
|
|
865
|
+
// Uses fontsource CDN (jsDelivr) which registers the SAME font-family names
|
|
866
|
+
// as the app (e.g. "Plus Jakarta Sans Variable"), unlike Google Fonts which
|
|
867
|
+
// strips the "Variable" suffix.
|
|
868
|
+
function loadProjectFonts(proj: AnimotProject) {
|
|
869
|
+
const fonts = new Set<string>();
|
|
870
|
+
for (const slide of proj.slides) {
|
|
871
|
+
for (const el of slide.canvas.elements) {
|
|
872
|
+
if (el.type === 'text' || el.type === 'counter') {
|
|
873
|
+
const f = (el as any).fontFamily as string | undefined;
|
|
874
|
+
if (f) {
|
|
875
|
+
for (const name of extractFontNames(f)) fonts.add(name);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
if (fonts.size === 0) return;
|
|
881
|
+
|
|
882
|
+
// Deduplicate against already-injected links to avoid double-loading
|
|
883
|
+
const loaded = new Set<string>();
|
|
884
|
+
document.querySelectorAll<HTMLLinkElement>('link[data-animot-font]').forEach(l => loaded.add(l.dataset.animotFont!));
|
|
885
|
+
|
|
886
|
+
for (const font of fonts) {
|
|
887
|
+
if (loaded.has(font)) continue;
|
|
888
|
+
const isVariable = /\s+Variable$/i.test(font);
|
|
889
|
+
// Convert font name to fontsource package slug:
|
|
890
|
+
// "Plus Jakarta Sans Variable" → "plus-jakarta-sans"
|
|
891
|
+
// "JetBrains Mono" → "jetbrains-mono"
|
|
892
|
+
const baseName = font.replace(/\s*Variable$/i, '');
|
|
893
|
+
const slug = baseName.toLowerCase().replace(/\s+/g, '-');
|
|
894
|
+
const pkg = isVariable
|
|
895
|
+
? `@fontsource-variable/${slug}`
|
|
896
|
+
: `@fontsource/${slug}`;
|
|
897
|
+
const link = document.createElement('link');
|
|
898
|
+
link.rel = 'stylesheet';
|
|
899
|
+
link.href = `https://cdn.jsdelivr.net/npm/${pkg}/index.css`;
|
|
900
|
+
link.dataset.animotFont = font;
|
|
901
|
+
document.head.appendChild(link);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
739
905
|
// Load data
|
|
740
906
|
async function loadProject() {
|
|
741
907
|
loading = true; error = null;
|
|
@@ -746,6 +912,7 @@
|
|
|
746
912
|
if (!res.ok) throw new Error(`Failed to load: ${res.status}`);
|
|
747
913
|
project = await res.json();
|
|
748
914
|
} else { throw new Error('Either src or data prop is required'); }
|
|
915
|
+
loadProjectFonts(project!);
|
|
749
916
|
currentSlideIndex = startSlide;
|
|
750
917
|
await new Promise(r => setTimeout(r, 10));
|
|
751
918
|
initAllAnimatedElements();
|
|
@@ -840,33 +1007,59 @@
|
|
|
840
1007
|
style:--float-speed="{hasFloat ? computeFloatSpeed(floatCfg, floatGroupId || elementId) : 3}s"
|
|
841
1008
|
style:--float-delay="{hashFraction(floatGroupId || elementId, 3) * 2}s"
|
|
842
1009
|
style:animation-name={hasFloat ? getFloatAnimName(floatCfg!.direction, floatGroupId || elementId) : 'none'}
|
|
1010
|
+
style:filter={(() => { const parts: string[] = []; const b = animated.blur.current; const br2 = animated.brightness.current; const c = animated.contrast.current; const s = animated.saturate.current; const g = animated.grayscale.current; if (b) parts.push(`blur(${b}px)`); if (br2 !== 100) parts.push(`brightness(${br2}%)`); if (c !== 100) parts.push(`contrast(${c}%)`); if (s !== 100) parts.push(`saturate(${s}%)`); if (g) parts.push(`grayscale(${g}%)`); return parts.length ? parts.join(' ') : 'none'; })()}
|
|
843
1011
|
>
|
|
844
1012
|
{#if element.type === 'code'}
|
|
845
1013
|
{@const codeEl = element as CodeElement}
|
|
846
1014
|
{@const morphState = codeMorphState.get(codeEl.id)}
|
|
847
|
-
<div class="animot-code-block" class:transparent-bg={codeEl.transparentBackground} style:font-size="{codeEl.fontSize}px" style:font-weight={codeEl.fontWeight || 400} style:padding="{codeEl.padding}px" style:border-radius="{animated.borderRadius.current}px">
|
|
1015
|
+
<div class="animot-code-block" class:transparent-bg={codeEl.transparentBackground} style:font-size="{codeEl.fontSize}px" style:font-weight={codeEl.fontWeight || 400} style:padding="{codeEl.padding}px" style:border-radius="{animated.borderRadius.current}px" style:background={codeEl.bgColor ?? '#0d1117'}>
|
|
848
1016
|
{#if codeEl.showHeader}
|
|
849
|
-
<div class="animot-code-header" class:macos={codeEl.headerStyle === 'macos'}>
|
|
1017
|
+
<div class="animot-code-header" class:macos={codeEl.headerStyle === 'macos'} class:windows={codeEl.headerStyle === 'windows'} style:border-radius="{codeEl.headerRadius ?? animated.borderRadius.current}px {codeEl.headerRadius ?? animated.borderRadius.current}px 0 0">
|
|
850
1018
|
{#if codeEl.headerStyle === 'macos'}
|
|
851
1019
|
<div class="animot-window-controls">
|
|
852
1020
|
<span class="animot-control close"></span>
|
|
853
1021
|
<span class="animot-control minimize"></span>
|
|
854
1022
|
<span class="animot-control maximize"></span>
|
|
855
1023
|
</div>
|
|
1024
|
+
{:else if codeEl.headerStyle === 'windows'}
|
|
1025
|
+
<div class="animot-window-controls">
|
|
1026
|
+
<span class="animot-control win-minimize">
|
|
1027
|
+
<svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 5h6" stroke="currentColor" stroke-width="1.2"/></svg>
|
|
1028
|
+
</span>
|
|
1029
|
+
<span class="animot-control win-maximize">
|
|
1030
|
+
<svg width="10" height="10" viewBox="0 0 10 10"><rect x="1.5" y="1.5" width="7" height="7" rx="0.5" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>
|
|
1031
|
+
</span>
|
|
1032
|
+
<span class="animot-control win-close">
|
|
1033
|
+
<svg width="10" height="10" viewBox="0 0 10 10"><path d="M2 2l6 6M8 2l-6 6" stroke="currentColor" stroke-width="1.2"/></svg>
|
|
1034
|
+
</span>
|
|
1035
|
+
</div>
|
|
856
1036
|
{/if}
|
|
857
|
-
<
|
|
1037
|
+
<div class="animot-filename-tab" style:border-radius="{codeEl.tabRadius ?? 6}px">
|
|
1038
|
+
<svg class="animot-file-icon" width="14" height="14" viewBox="0 0 16 16" fill="none">
|
|
1039
|
+
<path d="M4 1h5.5L13 4.5V14a1 1 0 01-1 1H4a1 1 0 01-1-1V2a1 1 0 011-1z" stroke="currentColor" stroke-width="1.2" opacity="0.5"/>
|
|
1040
|
+
<path d="M9.5 1v3.5H13" stroke="currentColor" stroke-width="1.2" opacity="0.5"/>
|
|
1041
|
+
</svg>
|
|
1042
|
+
<span class="animot-filename">{codeEl.filename}</span>
|
|
1043
|
+
</div>
|
|
1044
|
+
<button class="animot-copy-code-btn" onclick={(e) => { e.stopPropagation(); navigator.clipboard.writeText(codeEl.code); const btn = e.currentTarget as HTMLElement; btn.classList.add('copied'); setTimeout(() => btn.classList.remove('copied'), 1500); }}>
|
|
1045
|
+
<span class="animot-copy-label">Copy</span><span class="animot-copied-label">Copied!</span>
|
|
1046
|
+
<svg class="animot-copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
|
|
1047
|
+
<svg class="animot-check-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
|
|
1048
|
+
</button>
|
|
858
1049
|
</div>
|
|
1050
|
+
{:else}
|
|
1051
|
+
<button class="animot-copy-code-btn animot-floating" onclick={(e) => { e.stopPropagation(); navigator.clipboard.writeText(codeEl.code); const btn = e.currentTarget as HTMLElement; btn.classList.add('copied'); setTimeout(() => btn.classList.remove('copied'), 1500); }}>
|
|
1052
|
+
<span class="animot-copy-label">Copy</span><span class="animot-copied-label">Copied!</span>
|
|
1053
|
+
<svg class="animot-copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
|
|
1054
|
+
<svg class="animot-check-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>
|
|
1055
|
+
</button>
|
|
859
1056
|
{/if}
|
|
860
1057
|
<div class="animot-code-content">
|
|
861
1058
|
<div class="animot-highlighted-code">
|
|
862
|
-
{#if morphState}
|
|
863
|
-
{#
|
|
864
|
-
{#
|
|
865
|
-
|
|
866
|
-
{/key}
|
|
867
|
-
{:else}
|
|
868
|
-
{@html getCodeHighlight(codeEl.id)}
|
|
869
|
-
{/if}
|
|
1059
|
+
{#if morphState && morphState.oldCode !== morphState.newCode && morphState.mode !== 'instant'}
|
|
1060
|
+
{#key currentSlideIndex}
|
|
1061
|
+
<CodeMorph oldCode={morphState?.oldCode ?? ''} newCode={morphState?.newCode ?? ''} language={codeEl.language} theme={codeEl.theme} mode={morphState?.mode ?? 'highlight-changes'} speed={morphState?.speed ?? 50} highlightColor={morphState?.highlightColor ?? '#fef08a'} highlightDuration={codeEl.animation?.highlightDuration || 1000} showLineNumbers={(getElementInSlide(currentSlide, codeEl.id) as CodeElement | undefined)?.showLineNumbers ?? false} />
|
|
1062
|
+
{/key}
|
|
870
1063
|
{:else}
|
|
871
1064
|
{@html getCodeHighlight(codeEl.id)}
|
|
872
1065
|
{/if}
|
|
@@ -905,25 +1098,27 @@
|
|
|
905
1098
|
{:else if element.type === 'arrow'}
|
|
906
1099
|
{@const arrowEl = element as ArrowElement}
|
|
907
1100
|
{@const cp = arrowEl.controlPoints || []}
|
|
908
|
-
{@const pathD = cp.length === 0 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 1 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} Q ${cp[0].x} ${cp[0].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} C ${cp[0].x} ${cp[0].y} ${cp[1].x} ${cp[1].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}`}
|
|
909
|
-
{@const
|
|
1101
|
+
{@const pathD = cp.length === 0 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 1 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} Q ${cp[0].x} ${cp[0].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : cp.length === 2 ? `M ${arrowEl.startPoint.x} ${arrowEl.startPoint.y} C ${cp[0].x} ${cp[0].y} ${cp[1].x} ${cp[1].y} ${arrowEl.endPoint.x} ${arrowEl.endPoint.y}` : buildCatmullRomPath(arrowEl.startPoint, cp, arrowEl.endPoint)}
|
|
1102
|
+
{@const lastCp = cp.length > 0 ? cp[cp.length - 1] : arrowEl.startPoint}
|
|
1103
|
+
{@const endAngle = Math.atan2(arrowEl.endPoint.y - lastCp.y, arrowEl.endPoint.x - lastCp.x)}
|
|
910
1104
|
{@const headAngle = Math.PI / 6}
|
|
911
1105
|
{@const headSize = arrowEl.headSize}
|
|
912
1106
|
{@const arrowHeadPath = `M ${arrowEl.endPoint.x - headSize * Math.cos(endAngle - headAngle)} ${arrowEl.endPoint.y - headSize * Math.sin(endAngle - headAngle)} L ${arrowEl.endPoint.x} ${arrowEl.endPoint.y} L ${arrowEl.endPoint.x - headSize * Math.cos(endAngle + headAngle)} ${arrowEl.endPoint.y - headSize * Math.sin(endAngle + headAngle)}`}
|
|
913
1107
|
{@const arrowAnimMode = arrowEl.animation?.mode ?? 'none'}
|
|
914
1108
|
{@const arrowAnimDuration = arrowEl.animation?.duration ?? 500}
|
|
915
1109
|
{@const isStyledArrow = arrowEl.style !== 'solid'}
|
|
1110
|
+
{@const isDrawType = arrowAnimMode === 'draw' || arrowAnimMode === 'undraw' || arrowAnimMode === 'draw-undraw'}
|
|
916
1111
|
{@const baseDashArray = arrowEl.style === 'dashed' ? '10,5' : arrowEl.style === 'dotted' ? '2,5' : 'none'}
|
|
917
|
-
<svg class="animot-arrow-element" class:arrow-animate-draw={arrowAnimMode === 'draw' && !isStyledArrow} class:arrow-animate-grow={arrowAnimMode === 'grow'} viewBox="0 0 {arrowEl.size.width} {arrowEl.size.height}" preserveAspectRatio="none" style="--arrow-anim-duration: {arrowAnimDuration}ms;">
|
|
918
|
-
<path class="arrow-path" d={pathD} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-dasharray={baseDashArray} stroke-linecap="round" stroke-linejoin="round" use:animateStyledArrowDraw={{ enabled:
|
|
1112
|
+
<svg class="animot-arrow-element" class:arrow-animate-draw={arrowAnimMode === 'draw' && !isStyledArrow} class:arrow-animate-undraw={arrowAnimMode === 'undraw' && !isStyledArrow} class:arrow-animate-draw-undraw={arrowAnimMode === 'draw-undraw' && !isStyledArrow} class:arrow-animate-grow={arrowAnimMode === 'grow'} viewBox="0 0 {arrowEl.size.width} {arrowEl.size.height}" preserveAspectRatio="none" style="--arrow-anim-duration: {arrowAnimDuration}ms;">
|
|
1113
|
+
<path class="arrow-path" d={pathD} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-dasharray={baseDashArray} stroke-linecap="round" stroke-linejoin="round" use:animateStyledArrowDraw={{ enabled: isDrawType && isStyledArrow, mode: arrowAnimMode, duration: arrowAnimDuration, dashPattern: baseDashArray, startX: arrowEl.startPoint.x, endX: arrowEl.endPoint.x, slideIndex: currentSlideIndex }} />
|
|
919
1114
|
{#if arrowEl.showHead !== false}
|
|
920
|
-
<path class="arrow-head" class:arrow-head-styled-draw={arrowAnimMode === '
|
|
1115
|
+
<path class="arrow-head" class:arrow-head-styled-draw={isDrawType && isStyledArrow} class:arrow-head-undraw={arrowAnimMode === 'undraw'} class:arrow-head-draw-undraw={arrowAnimMode === 'draw-undraw'} d={arrowHeadPath} fill="none" stroke={arrowEl.color} stroke-width={arrowEl.strokeWidth} stroke-linecap="round" stroke-linejoin="round" style={isDrawType && isStyledArrow ? `--arrow-anim-duration: ${arrowAnimDuration}ms;` : ''} />
|
|
921
1116
|
{/if}
|
|
922
1117
|
</svg>
|
|
923
1118
|
{:else if element.type === 'image'}
|
|
924
1119
|
{@const imgEl = element as ImageElement}
|
|
925
1120
|
{@const clipPath = imgEl.clipMask?.enabled ? (imgEl.clipMask.shapeType === 'circle' ? 'circle(50% at 50% 50%)' : imgEl.clipMask.shapeType === 'ellipse' ? 'ellipse(50% 50% at 50% 50%)' : imgEl.clipMask.shapeType === 'triangle' ? 'polygon(50% 0%, 0% 100%, 100% 100%)' : imgEl.clipMask.shapeType === 'star' ? 'polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%)' : imgEl.clipMask.shapeType === 'hexagon' ? 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)' : (imgEl.clipMask.borderRadius ?? 0) > 0 ? `inset(0 round ${imgEl.clipMask.borderRadius}px)` : 'none') : 'none'}
|
|
926
|
-
<img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:opacity={imgEl.opacity} style:
|
|
1121
|
+
<img class="animot-image-element" src={imgEl.src} alt="" style:object-fit={imgEl.objectFit} style:border-radius="{imgEl.clipMask?.enabled ? 0 : imgEl.borderRadius}px" style:opacity={imgEl.opacity} style:clip-path={clipPath} style:background-color={imgEl.backgroundColor ?? 'transparent'} />
|
|
927
1122
|
{:else if element.type === 'shape'}
|
|
928
1123
|
{@const shapeEl = element as ShapeElement}
|
|
929
1124
|
{@const animFill = animated.fillColor?.current ?? shapeEl.fillColor}
|
|
@@ -1031,6 +1226,14 @@
|
|
|
1031
1226
|
</script>
|
|
1032
1227
|
|
|
1033
1228
|
<style>
|
|
1229
|
+
/* Universal reset — mirrors the animot app's global * reset to prevent
|
|
1230
|
+
host page defaults (margins on p/h1, padding, box-sizing) from leaking in */
|
|
1231
|
+
.animot-presenter :global(*) {
|
|
1232
|
+
margin: 0;
|
|
1233
|
+
padding: 0;
|
|
1234
|
+
box-sizing: border-box;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1034
1237
|
.animot-presenter {
|
|
1035
1238
|
position: relative;
|
|
1036
1239
|
width: 100%;
|
|
@@ -1080,19 +1283,34 @@
|
|
|
1080
1283
|
|
|
1081
1284
|
/* Code */
|
|
1082
1285
|
.animot-code-block {
|
|
1083
|
-
width: 100%; height: 100%;
|
|
1286
|
+
width: 100%; height: 100%; overflow: hidden;
|
|
1084
1287
|
display: flex; flex-direction: column; box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
1085
1288
|
margin: 0; box-sizing: border-box;
|
|
1086
1289
|
}
|
|
1087
|
-
.animot-code-block.transparent-bg { background: transparent; box-shadow: none; }
|
|
1088
|
-
.animot-code-block.transparent-bg .animot-code-header { background: transparent; border-bottom-color: rgba(255,255,255,0.
|
|
1089
|
-
.animot-code-header { display: flex; align-items: center; gap:
|
|
1090
|
-
.animot-window-controls { display: flex; gap: 8px; }
|
|
1091
|
-
.animot-control { width: 12px; height: 12px; border-radius: 50%; display: block; }
|
|
1290
|
+
.animot-code-block.transparent-bg { background: transparent !important; box-shadow: none; }
|
|
1291
|
+
.animot-code-block.transparent-bg .animot-code-header { background: transparent; border-bottom-color: rgba(255,255,255,0.06); }
|
|
1292
|
+
.animot-code-header { display: flex; align-items: center; gap: 8px; padding: 8px 12px; background: rgba(0, 0, 0, 0.2); border-bottom: 1px solid rgba(255, 255, 255, 0.06); flex-shrink: 0; min-height: 40px; }
|
|
1293
|
+
.animot-window-controls { display: flex; gap: 8px; align-items: center; flex-shrink: 0; }
|
|
1294
|
+
.macos .animot-control { width: 12px; height: 12px; border-radius: 50%; display: block; }
|
|
1092
1295
|
.macos .animot-control.close { background: #ff5f57; }
|
|
1093
1296
|
.macos .animot-control.minimize { background: #febc2e; }
|
|
1094
1297
|
.macos .animot-control.maximize { background: #28c840; }
|
|
1095
|
-
.animot-
|
|
1298
|
+
.windows .animot-window-controls { order: 99; margin-left: auto; gap: 0; }
|
|
1299
|
+
.windows .animot-control { display: flex; align-items: center; justify-content: center; width: 28px; height: 24px; border-radius: 4px; color: rgba(255,255,255,0.45); }
|
|
1300
|
+
.animot-filename-tab { display: flex; align-items: center; gap: 6px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.08); border-radius: 6px; padding: 4px 10px; max-width: 220px; color: rgba(255,255,255,0.4); }
|
|
1301
|
+
.animot-file-icon { flex-shrink: 0; }
|
|
1302
|
+
.animot-filename { color: rgba(255,255,255,0.55); font-size: 12px; line-height: 18px; }
|
|
1303
|
+
.animot-copy-code-btn { display: flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px; margin-left: auto; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; color: rgba(255,255,255,0.4); cursor: pointer; opacity: 0; transition: opacity 0.2s, background 0.15s, color 0.15s; flex-shrink: 0; font-size: 12px; font-family: inherit; white-space: nowrap; }
|
|
1304
|
+
.animot-copy-code-btn:hover { background: rgba(255,255,255,0.12); color: rgba(255,255,255,0.8); }
|
|
1305
|
+
.animot-copy-code-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
|
|
1306
|
+
.animot-copy-code-btn .animot-check-icon { display: none; }
|
|
1307
|
+
.animot-copy-code-btn .animot-copied-label { display: none; }
|
|
1308
|
+
.animot-copy-code-btn.copied .animot-copy-icon { display: none; }
|
|
1309
|
+
.animot-copy-code-btn.copied .animot-copy-label { display: none; }
|
|
1310
|
+
.animot-copy-code-btn.copied .animot-check-icon { display: block; color: #4ade80; }
|
|
1311
|
+
.animot-copy-code-btn.copied .animot-copied-label { display: inline; color: #4ade80; }
|
|
1312
|
+
.animot-copy-code-btn.animot-floating { position: absolute; top: 8px; right: 8px; z-index: 2; }
|
|
1313
|
+
.animot-code-block:hover .animot-copy-code-btn { opacity: 1; }
|
|
1096
1314
|
.animot-code-content { flex: 1; overflow: hidden; position: relative; }
|
|
1097
1315
|
.animot-highlighted-code { width: 100%; height: 100%; }
|
|
1098
1316
|
.animot-code-content :global(pre), .animot-highlighted-code :global(pre) { margin: 0; padding: 16px; background: transparent !important; line-height: 1.6; font-size: inherit; overflow: visible; }
|
|
@@ -1107,11 +1325,19 @@
|
|
|
1107
1325
|
/* Arrow */
|
|
1108
1326
|
.animot-arrow-element { width: 100%; height: 100%; }
|
|
1109
1327
|
.arrow-animate-draw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: animot-arrow-draw var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1328
|
+
.arrow-animate-undraw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 0; animation: animot-arrow-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1329
|
+
.arrow-animate-draw-undraw .arrow-path { stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: animot-arrow-draw-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1110
1330
|
.arrow-head-styled-draw { opacity: 0; animation: animot-arrow-head-appear var(--arrow-anim-duration, 500ms) ease-out forwards; animation-delay: calc(var(--arrow-anim-duration, 500ms) * 0.7); }
|
|
1111
1331
|
.arrow-animate-draw .arrow-head { opacity: 0; animation: animot-arrow-head-appear var(--arrow-anim-duration, 500ms) ease-out forwards; animation-delay: calc(var(--arrow-anim-duration, 500ms) * 0.7); }
|
|
1332
|
+
.arrow-animate-undraw .arrow-head, .arrow-head-undraw { opacity: 1; animation: animot-arrow-head-disappear var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1333
|
+
.arrow-animate-draw-undraw .arrow-head, .arrow-head-draw-undraw { opacity: 0; animation: animot-arrow-head-draw-undraw var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1112
1334
|
.arrow-animate-grow { transform-origin: left center; animation: animot-arrow-grow var(--arrow-anim-duration, 500ms) ease-out forwards; }
|
|
1113
1335
|
@keyframes animot-arrow-draw { to { stroke-dashoffset: 0; } }
|
|
1336
|
+
@keyframes animot-arrow-undraw { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 1000; } }
|
|
1337
|
+
@keyframes animot-arrow-draw-undraw { 0% { stroke-dashoffset: 1000; } 50% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 1000; } }
|
|
1114
1338
|
@keyframes animot-arrow-head-appear { from { opacity: 0; } to { opacity: 1; } }
|
|
1339
|
+
@keyframes animot-arrow-head-disappear { 0% { opacity: 1; } 70% { opacity: 1; } 100% { opacity: 0; } }
|
|
1340
|
+
@keyframes animot-arrow-head-draw-undraw { 0% { opacity: 0; } 35% { opacity: 1; } 65% { opacity: 1; } 100% { opacity: 0; } }
|
|
1115
1341
|
@keyframes animot-arrow-grow { from { transform: scaleX(0); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }
|
|
1116
1342
|
|
|
1117
1343
|
/* Image */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.code-morph.svelte-1hmk0l{width:100%;height:100%;margin:0;padding:0;background:transparent;font-family:var(--font-mono, "JetBrains Mono", monospace);font-size:inherit;line-height:1.6;white-space:pre-wrap;word-wrap:break-word;color:#e6edf3;box-sizing:border-box;overflow:visible}.code-morph.svelte-1hmk0l pre{margin:0;padding:16px;background:transparent!important;font-family:var(--font-mono);font-size:inherit;line-height:1.6;overflow:visible}.code-morph.svelte-1hmk0l code{font-family:inherit;font-size:inherit;font-weight:inherit}.code-morph.svelte-1hmk0l .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.code-morph.svelte-1hmk0l .word-highlight{background:var(--highlight-color, #facc15);color:#000;border-radius:3px;padding:1px 3px;margin:0 -3px;-webkit-box-decoration-break:clone;box-decoration-break:clone;animation:svelte-1hmk0l-fadeHighlight var(--duration, 1s) ease-out forwards}@keyframes svelte-1hmk0l-fadeHighlight{0%{background:var(--highlight-color, #facc15);color:#000}70%{background:var(--highlight-color, #facc15);color:#000}to{background:transparent;color:inherit}}.counter.svelte-1er5jjj{width:100%;height:100%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;overflow:hidden;white-space:nowrap}.chart.svelte-1mq2d7j{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden}.chart-title.svelte-1mq2d7j{font-weight:600;text-align:center;margin-bottom:8px}.chart-content.svelte-1mq2d7j{flex:1;min-height:0}.chart-content.svelte-1mq2d7j svg:where(.svelte-1mq2d7j){width:100%;height:100%}.bar-chart.svelte-1mq2d7j,.line-chart.svelte-1mq2d7j{overflow:visible}.icon-element.svelte-2ld65o{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.icon-element.svelte-2ld65o svg{width:100%;height:100%}@keyframes float-vertical{0%,to{translate:0 0}50%{translate:0 calc(-1 * var(--float-amp, 10px))}}@keyframes float-horizontal{0%,to{translate:0 0}50%{translate:var(--float-amp, 10px) 0}}@keyframes float-both-0{0%{translate:0 0}15%{translate:calc(.8 * var(--float-amp, 10px)) calc(-.6 * var(--float-amp, 10px))}35%{translate:calc(-.4 * var(--float-amp, 10px)) calc(-1 * var(--float-amp, 10px))}55%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.3 * var(--float-amp, 10px))}75%{translate:calc(.3 * var(--float-amp, 10px)) calc(.7 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-1{0%{translate:0 0}20%{translate:calc(-.7 * var(--float-amp, 10px)) calc(-.8 * var(--float-amp, 10px))}40%{translate:calc(.5 * var(--float-amp, 10px)) calc(-.3 * var(--float-amp, 10px))}60%{translate:calc(.9 * var(--float-amp, 10px)) calc(.6 * var(--float-amp, 10px))}80%{translate:calc(-.4 * var(--float-amp, 10px)) calc(.9 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-2{0%{translate:0 0}12%{translate:calc(.6 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}30%{translate:calc(1 * var(--float-amp, 10px)) calc(-.4 * var(--float-amp, 10px))}50%{translate:calc(-.3 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}70%{translate:calc(-.8 * var(--float-amp, 10px)) calc(.2 * var(--float-amp, 10px))}88%{translate:calc(.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-3{0%{translate:0 0}17%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.4 * var(--float-amp, 10px))}33%{translate:calc(-.5 * var(--float-amp, 10px)) calc(-.7 * var(--float-amp, 10px))}50%{translate:calc(.7 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}67%{translate:calc(.9 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}83%{translate:calc(-.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}.animot-presenter.svelte-16ocdv9{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden;background:transparent;line-height:normal;font-size:16px;font-weight:400;font-style:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0;text-align:left;color:inherit}.animot-canvas-wrapper.svelte-16ocdv9{display:flex;align-items:center;justify-content:center}.animot-canvas.svelte-16ocdv9{position:relative;overflow:hidden}.animot-element.svelte-16ocdv9{position:absolute;box-sizing:border-box;will-change:transform,opacity,left,top,width,height;isolation:isolate}.animot-element.floating.svelte-16ocdv9{animation-duration:var(--float-speed, 3s);animation-timing-function:ease-in-out;animation-iteration-count:infinite;animation-delay:var(--float-delay, 0s)}.animot-code-block.svelte-16ocdv9{width:100%;height:100%;background:#0d1117;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 32px #0006;margin:0;box-sizing:border-box}.animot-code-block.transparent-bg.svelte-16ocdv9{background:transparent;box-shadow:none}.animot-code-block.transparent-bg.svelte-16ocdv9 .animot-code-header:where(.svelte-16ocdv9){background:transparent;border-bottom-color:#ffffff1a}.animot-code-header.svelte-16ocdv9{display:flex;align-items:center;gap:12px;padding:12px 16px;background:#161b22;border-bottom:1px solid #30363d;flex-shrink:0}.animot-window-controls.svelte-16ocdv9{display:flex;gap:8px}.animot-control.svelte-16ocdv9{width:12px;height:12px;border-radius:50%;display:block}.macos.svelte-16ocdv9 .animot-control.close:where(.svelte-16ocdv9){background:#ff5f57}.macos.svelte-16ocdv9 .animot-control.minimize:where(.svelte-16ocdv9){background:#febc2e}.macos.svelte-16ocdv9 .animot-control.maximize:where(.svelte-16ocdv9){background:#28c840}.animot-filename.svelte-16ocdv9{color:#8b949e;font-size:14px;flex:1}.animot-code-content.svelte-16ocdv9{flex:1;overflow:hidden;position:relative}.animot-highlighted-code.svelte-16ocdv9{width:100%;height:100%}.animot-code-content.svelte-16ocdv9 pre,.animot-highlighted-code.svelte-16ocdv9 pre{margin:0;padding:16px;background:transparent!important;line-height:1.6;font-size:inherit;overflow:visible}.animot-highlighted-code.svelte-16ocdv9 code{font-family:inherit;font-size:inherit;font-weight:inherit}.animot-highlighted-code.svelte-16ocdv9 .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.animot-text-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;white-space:pre-wrap;word-wrap:break-word}.animot-typewriter-cursor.svelte-16ocdv9{animation:svelte-16ocdv9-animot-blink .7s infinite;font-weight:100}@keyframes svelte-16ocdv9-animot-blink{0%,50%{opacity:1}51%,to{opacity:0}}.animot-arrow-element.svelte-16ocdv9{width:100%;height:100%}.arrow-animate-draw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-head-styled-draw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-draw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9){opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-grow.svelte-16ocdv9{transform-origin:left center;animation:svelte-16ocdv9-animot-arrow-grow var(--arrow-anim-duration, .5s) ease-out forwards}@keyframes svelte-16ocdv9-animot-arrow-draw{to{stroke-dashoffset:0}}@keyframes svelte-16ocdv9-animot-arrow-head-appear{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-arrow-grow{0%{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}.animot-image-element.svelte-16ocdv9{width:100%;height:100%;display:block}.animot-shape-element.svelte-16ocdv9{width:100%;height:100%;display:block;overflow:visible}.animot-canvas.svelte-16ocdv9{--transition-duration: .5s;transition:transform calc(var(--transition-duration) * .4) ease,opacity calc(var(--transition-duration) * .4) ease}.animot-canvas.transition-fade-out.svelte-16ocdv9{opacity:0}.animot-canvas.transition-fade-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-fadeIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.forward.svelte-16ocdv9{transform:translate(-100%);opacity:0}.animot-canvas.transition-slide-left-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromRight calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.backward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-left-in.backward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-right-out.forward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-right-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-up-out.svelte-16ocdv9{transform:translateY(-100%);opacity:0}.animot-canvas.transition-slide-up-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromBottom calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-down-out.svelte-16ocdv9{transform:translateY(100%);opacity:0}.animot-canvas.transition-slide-down-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromTop calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-in-out.svelte-16ocdv9{transform:scale(.5);opacity:0}.animot-canvas.transition-zoom-in-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-out-out.svelte-16ocdv9{transform:scale(1.5);opacity:0}.animot-canvas.transition-zoom-out-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomOut calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-flip-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromBottom{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromTop{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomIn{0%{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomOut{0%{transform:scale(1.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-flipIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-canvas.transition-flip-x-out.svelte-16ocdv9{transform:perspective(1000px) rotateX(90deg);opacity:0}.animot-canvas.transition-flip-x-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipXIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipXIn{0%{transform:perspective(1000px) rotateX(-90deg);opacity:0}to{transform:perspective(1000px) rotateX(0);opacity:1}}.animot-canvas.transition-flip-y-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-y-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipYIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipYIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-svg-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.animot-svg-element.svelte-16ocdv9 svg{width:100%;height:100%}.animot-controls.svelte-16ocdv9{position:absolute;bottom:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:8px 16px;background:#000000b3;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;opacity:0;transition:opacity .3s ease .15s;z-index:100}.animot-presenter.svelte-16ocdv9:hover .animot-controls:where(.svelte-16ocdv9),.animot-menu-visible.svelte-16ocdv9 .animot-controls:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;border:none;cursor:pointer;background:#ffffff1a;color:#fff;transition:background .2s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):hover:not(:disabled){background:#fff3}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-controls.svelte-16ocdv9 button.active:where(.svelte-16ocdv9){background:#6366f199}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9) svg:where(.svelte-16ocdv9){width:16px;height:16px}.animot-slide-indicator.svelte-16ocdv9{font-size:12px;color:#fff;min-width:50px;text-align:center;font-family:system-ui,sans-serif}.animot-arrow.svelte-16ocdv9{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;border:none;cursor:pointer;background:#00000080;color:#fff;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .3s .15s;z-index:100;padding:0;margin:0}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-arrow.svelte-16ocdv9:hover:not(:disabled){background:#000000b3}.animot-arrow.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:20px;height:20px}.animot-arrow-left.svelte-16ocdv9{left:8px}.animot-arrow-right.svelte-16ocdv9{right:8px}.animot-progress-bar.svelte-16ocdv9{position:absolute;bottom:0;left:0;right:0;height:3px;background:#ffffff1a;z-index:100;opacity:0;transition:opacity .3s .15s}.animot-presenter.svelte-16ocdv9:hover .animot-progress-bar:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-progress-fill.svelte-16ocdv9{height:100%;background:linear-gradient(135deg,#7c3aed,#ec4899);transition:width .6s ease}.animot-loading.svelte-16ocdv9{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.animot-spinner.svelte-16ocdv9{width:32px;height:32px;border:3px solid rgba(255,255,255,.2);border-top-color:#7c3aed;border-radius:50%;animation:svelte-16ocdv9-animot-spin .8s linear infinite}@keyframes svelte-16ocdv9-animot-spin{to{transform:rotate(360deg)}}.animot-error.svelte-16ocdv9{color:#ef4444;padding:20px;text-align:center;font-family:system-ui,sans-serif}
|
|
1
|
+
.code-morph.svelte-1hmk0l{width:100%;height:100%;margin:0;padding:0;background:transparent;font-family:var(--font-mono, "JetBrains Mono", monospace);font-size:inherit;line-height:1.6;white-space:pre-wrap;word-wrap:break-word;color:#e6edf3;box-sizing:border-box;overflow:visible}.code-morph.svelte-1hmk0l pre{margin:0;padding:16px;background:transparent!important;font-family:var(--font-mono);font-size:inherit;line-height:1.6;overflow:visible}.code-morph.svelte-1hmk0l code{font-family:inherit;font-size:inherit;font-weight:inherit}.code-morph.svelte-1hmk0l .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.code-morph.svelte-1hmk0l .word-highlight{background:var(--highlight-color, #facc15);color:#000;border-radius:3px;padding:1px 3px;margin:0 -3px;-webkit-box-decoration-break:clone;box-decoration-break:clone;animation:svelte-1hmk0l-fadeHighlight var(--duration, 1s) ease-out forwards}@keyframes svelte-1hmk0l-fadeHighlight{0%{background:var(--highlight-color, #facc15);color:#000}70%{background:var(--highlight-color, #facc15);color:#000}to{background:transparent;color:inherit}}.counter.svelte-1er5jjj{width:100%;height:100%;display:flex;align-items:center;justify-content:center;box-sizing:border-box;overflow:hidden;white-space:nowrap}.chart.svelte-1mq2d7j{width:100%;height:100%;display:flex;flex-direction:column;box-sizing:border-box;overflow:hidden}.chart-title.svelte-1mq2d7j{font-weight:600;text-align:center;margin-bottom:8px}.chart-content.svelte-1mq2d7j{flex:1;min-height:0}.chart-content.svelte-1mq2d7j svg:where(.svelte-1mq2d7j){width:100%;height:100%}.bar-chart.svelte-1mq2d7j,.line-chart.svelte-1mq2d7j{overflow:visible}.icon-element.svelte-2ld65o{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.icon-element.svelte-2ld65o svg{width:100%;height:100%}@keyframes float-vertical{0%,to{translate:0 0}50%{translate:0 calc(-1 * var(--float-amp, 10px))}}@keyframes float-horizontal{0%,to{translate:0 0}50%{translate:var(--float-amp, 10px) 0}}@keyframes float-both-0{0%{translate:0 0}15%{translate:calc(.8 * var(--float-amp, 10px)) calc(-.6 * var(--float-amp, 10px))}35%{translate:calc(-.4 * var(--float-amp, 10px)) calc(-1 * var(--float-amp, 10px))}55%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.3 * var(--float-amp, 10px))}75%{translate:calc(.3 * var(--float-amp, 10px)) calc(.7 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-1{0%{translate:0 0}20%{translate:calc(-.7 * var(--float-amp, 10px)) calc(-.8 * var(--float-amp, 10px))}40%{translate:calc(.5 * var(--float-amp, 10px)) calc(-.3 * var(--float-amp, 10px))}60%{translate:calc(.9 * var(--float-amp, 10px)) calc(.6 * var(--float-amp, 10px))}80%{translate:calc(-.4 * var(--float-amp, 10px)) calc(.9 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-2{0%{translate:0 0}12%{translate:calc(.6 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}30%{translate:calc(1 * var(--float-amp, 10px)) calc(-.4 * var(--float-amp, 10px))}50%{translate:calc(-.3 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}70%{translate:calc(-.8 * var(--float-amp, 10px)) calc(.2 * var(--float-amp, 10px))}88%{translate:calc(.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}@keyframes float-both-3{0%{translate:0 0}17%{translate:calc(-.9 * var(--float-amp, 10px)) calc(.4 * var(--float-amp, 10px))}33%{translate:calc(-.5 * var(--float-amp, 10px)) calc(-.7 * var(--float-amp, 10px))}50%{translate:calc(.7 * var(--float-amp, 10px)) calc(-.9 * var(--float-amp, 10px))}67%{translate:calc(.9 * var(--float-amp, 10px)) calc(.5 * var(--float-amp, 10px))}83%{translate:calc(-.2 * var(--float-amp, 10px)) calc(.8 * var(--float-amp, 10px))}to{translate:0 0}}.animot-presenter.svelte-16ocdv9 *{margin:0;padding:0;box-sizing:border-box}.animot-presenter.svelte-16ocdv9{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden;background:transparent;line-height:normal;font-size:16px;font-weight:400;font-style:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0;text-align:left;color:inherit}.animot-canvas-wrapper.svelte-16ocdv9{display:flex;align-items:center;justify-content:center}.animot-canvas.svelte-16ocdv9{position:relative;overflow:hidden}.animot-element.svelte-16ocdv9{position:absolute;box-sizing:border-box;will-change:transform,opacity,left,top,width,height;isolation:isolate}.animot-element.floating.svelte-16ocdv9{animation-duration:var(--float-speed, 3s);animation-timing-function:ease-in-out;animation-iteration-count:infinite;animation-delay:var(--float-delay, 0s)}.animot-code-block.svelte-16ocdv9{width:100%;height:100%;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 8px 32px #0006;margin:0;box-sizing:border-box}.animot-code-block.transparent-bg.svelte-16ocdv9{background:transparent!important;box-shadow:none}.animot-code-block.transparent-bg.svelte-16ocdv9 .animot-code-header:where(.svelte-16ocdv9){background:transparent;border-bottom-color:#ffffff0f}.animot-code-header.svelte-16ocdv9{display:flex;align-items:center;gap:8px;padding:8px 12px;background:#0003;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:40px}.animot-window-controls.svelte-16ocdv9{display:flex;gap:8px;align-items:center;flex-shrink:0}.macos.svelte-16ocdv9 .animot-control:where(.svelte-16ocdv9){width:12px;height:12px;border-radius:50%;display:block}.macos.svelte-16ocdv9 .animot-control.close:where(.svelte-16ocdv9){background:#ff5f57}.macos.svelte-16ocdv9 .animot-control.minimize:where(.svelte-16ocdv9){background:#febc2e}.macos.svelte-16ocdv9 .animot-control.maximize:where(.svelte-16ocdv9){background:#28c840}.windows.svelte-16ocdv9 .animot-window-controls:where(.svelte-16ocdv9){order:99;margin-left:auto;gap:0}.windows.svelte-16ocdv9 .animot-control:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:28px;height:24px;border-radius:4px;color:#ffffff73}.animot-filename-tab.svelte-16ocdv9{display:flex;align-items:center;gap:6px;background:#ffffff0f;border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:4px 10px;max-width:220px;color:#fff6}.animot-file-icon.svelte-16ocdv9{flex-shrink:0}.animot-filename.svelte-16ocdv9{color:#ffffff8c;font-size:12px;line-height:18px}.animot-copy-code-btn.svelte-16ocdv9{display:flex;align-items:center;gap:5px;height:28px;padding:0 8px;margin-left:auto;background:#ffffff0f;border:1px solid rgba(255,255,255,.1);border-radius:6px;color:#fff6;cursor:pointer;opacity:0;transition:opacity .2s,background .15s,color .15s;flex-shrink:0;font-size:12px;font-family:inherit;white-space:nowrap}.animot-copy-code-btn.svelte-16ocdv9:hover{background:#ffffff1f;color:#fffc}.animot-copy-code-btn.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:14px;height:14px;flex-shrink:0}.animot-copy-code-btn.svelte-16ocdv9 .animot-check-icon:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.svelte-16ocdv9 .animot-copied-label:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copy-icon:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copy-label:where(.svelte-16ocdv9){display:none}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-check-icon:where(.svelte-16ocdv9){display:block;color:#4ade80}.animot-copy-code-btn.copied.svelte-16ocdv9 .animot-copied-label:where(.svelte-16ocdv9){display:inline;color:#4ade80}.animot-copy-code-btn.animot-floating.svelte-16ocdv9{position:absolute;top:8px;right:8px;z-index:2}.animot-code-block.svelte-16ocdv9:hover .animot-copy-code-btn:where(.svelte-16ocdv9){opacity:1}.animot-code-content.svelte-16ocdv9{flex:1;overflow:hidden;position:relative}.animot-highlighted-code.svelte-16ocdv9{width:100%;height:100%}.animot-code-content.svelte-16ocdv9 pre,.animot-highlighted-code.svelte-16ocdv9 pre{margin:0;padding:16px;background:transparent!important;line-height:1.6;font-size:inherit;overflow:visible}.animot-highlighted-code.svelte-16ocdv9 code{font-family:inherit;font-size:inherit;font-weight:inherit}.animot-highlighted-code.svelte-16ocdv9 .line-number{display:inline-block;width:2.5em;margin-right:1em;text-align:right;color:#6e7681;-webkit-user-select:none;user-select:none;opacity:.6}.animot-text-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;white-space:pre-wrap;word-wrap:break-word}.animot-typewriter-cursor.svelte-16ocdv9{animation:svelte-16ocdv9-animot-blink .7s infinite;font-weight:100}@keyframes svelte-16ocdv9-animot-blink{0%,50%{opacity:1}51%,to{opacity:0}}.animot-arrow-element.svelte-16ocdv9{width:100%;height:100%}.arrow-animate-draw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-undraw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:0;animation:svelte-16ocdv9-animot-arrow-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-draw-undraw.svelte-16ocdv9 .arrow-path:where(.svelte-16ocdv9){stroke-dasharray:1000;stroke-dashoffset:1000;animation:svelte-16ocdv9-animot-arrow-draw-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-head-styled-draw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-draw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9){opacity:0;animation:svelte-16ocdv9-animot-arrow-head-appear var(--arrow-anim-duration, .5s) ease-out forwards;animation-delay:calc(var(--arrow-anim-duration, .5s) * .7)}.arrow-animate-undraw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9),.arrow-head-undraw.svelte-16ocdv9{opacity:1;animation:svelte-16ocdv9-animot-arrow-head-disappear var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-draw-undraw.svelte-16ocdv9 .arrow-head:where(.svelte-16ocdv9),.arrow-head-draw-undraw.svelte-16ocdv9{opacity:0;animation:svelte-16ocdv9-animot-arrow-head-draw-undraw var(--arrow-anim-duration, .5s) ease-out forwards}.arrow-animate-grow.svelte-16ocdv9{transform-origin:left center;animation:svelte-16ocdv9-animot-arrow-grow var(--arrow-anim-duration, .5s) ease-out forwards}@keyframes svelte-16ocdv9-animot-arrow-draw{to{stroke-dashoffset:0}}@keyframes svelte-16ocdv9-animot-arrow-undraw{0%{stroke-dashoffset:0}to{stroke-dashoffset:1000}}@keyframes svelte-16ocdv9-animot-arrow-draw-undraw{0%{stroke-dashoffset:1000}50%{stroke-dashoffset:0}to{stroke-dashoffset:1000}}@keyframes svelte-16ocdv9-animot-arrow-head-appear{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-arrow-head-disappear{0%{opacity:1}70%{opacity:1}to{opacity:0}}@keyframes svelte-16ocdv9-animot-arrow-head-draw-undraw{0%{opacity:0}35%{opacity:1}65%{opacity:1}to{opacity:0}}@keyframes svelte-16ocdv9-animot-arrow-grow{0%{transform:scaleX(0);opacity:0}to{transform:scaleX(1);opacity:1}}.animot-image-element.svelte-16ocdv9{width:100%;height:100%;display:block}.animot-shape-element.svelte-16ocdv9{width:100%;height:100%;display:block;overflow:visible}.animot-canvas.svelte-16ocdv9{--transition-duration: .5s;transition:transform calc(var(--transition-duration) * .4) ease,opacity calc(var(--transition-duration) * .4) ease}.animot-canvas.transition-fade-out.svelte-16ocdv9{opacity:0}.animot-canvas.transition-fade-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-fadeIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.forward.svelte-16ocdv9{transform:translate(-100%);opacity:0}.animot-canvas.transition-slide-left-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromRight calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-left-out.backward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-left-in.backward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-right-out.forward.svelte-16ocdv9{transform:translate(100%);opacity:0}.animot-canvas.transition-slide-right-in.forward.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromLeft calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-up-out.svelte-16ocdv9{transform:translateY(-100%);opacity:0}.animot-canvas.transition-slide-up-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromBottom calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-slide-down-out.svelte-16ocdv9{transform:translateY(100%);opacity:0}.animot-canvas.transition-slide-down-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-slideInFromTop calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-in-out.svelte-16ocdv9{transform:scale(.5);opacity:0}.animot-canvas.transition-zoom-in-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomIn calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-zoom-out-out.svelte-16ocdv9{transform:scale(1.5);opacity:0}.animot-canvas.transition-zoom-out-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-zoomOut calc(var(--transition-duration) * .6) ease forwards}.animot-canvas.transition-flip-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-fadeIn{0%{opacity:0}to{opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromBottom{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-slideInFromTop{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomIn{0%{transform:scale(.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-zoomOut{0%{transform:scale(1.5);opacity:0}to{transform:scale(1);opacity:1}}@keyframes svelte-16ocdv9-animot-flipIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-canvas.transition-flip-x-out.svelte-16ocdv9{transform:perspective(1000px) rotateX(90deg);opacity:0}.animot-canvas.transition-flip-x-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipXIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipXIn{0%{transform:perspective(1000px) rotateX(-90deg);opacity:0}to{transform:perspective(1000px) rotateX(0);opacity:1}}.animot-canvas.transition-flip-y-out.svelte-16ocdv9{transform:perspective(1000px) rotateY(90deg);opacity:0}.animot-canvas.transition-flip-y-in.svelte-16ocdv9{animation:svelte-16ocdv9-animot-flipYIn calc(var(--transition-duration) * .6) ease forwards}@keyframes svelte-16ocdv9-animot-flipYIn{0%{transform:perspective(1000px) rotateY(-90deg);opacity:0}to{transform:perspective(1000px) rotateY(0);opacity:1}}.animot-svg-element.svelte-16ocdv9{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.animot-svg-element.svelte-16ocdv9 svg{width:100%;height:100%}.animot-controls.svelte-16ocdv9{position:absolute;bottom:12px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:8px;padding:8px 16px;background:#000000b3;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;opacity:0;transition:opacity .3s ease .15s;z-index:100}.animot-presenter.svelte-16ocdv9:hover .animot-controls:where(.svelte-16ocdv9),.animot-menu-visible.svelte-16ocdv9 .animot-controls:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9){display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;border:none;cursor:pointer;background:#ffffff1a;color:#fff;transition:background .2s}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):hover:not(:disabled){background:#fff3}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-controls.svelte-16ocdv9 button.active:where(.svelte-16ocdv9){background:#6366f199}.animot-controls.svelte-16ocdv9 button:where(.svelte-16ocdv9) svg:where(.svelte-16ocdv9){width:16px;height:16px}.animot-slide-indicator.svelte-16ocdv9{font-size:12px;color:#fff;min-width:50px;text-align:center;font-family:system-ui,sans-serif}.animot-arrow.svelte-16ocdv9{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border-radius:50%;border:none;cursor:pointer;background:#00000080;color:#fff;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .3s .15s;z-index:100;padding:0;margin:0}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-presenter.svelte-16ocdv9:hover .animot-arrow:where(.svelte-16ocdv9):disabled{opacity:.3;cursor:not-allowed}.animot-arrow.svelte-16ocdv9:hover:not(:disabled){background:#000000b3}.animot-arrow.svelte-16ocdv9 svg:where(.svelte-16ocdv9){width:20px;height:20px}.animot-arrow-left.svelte-16ocdv9{left:8px}.animot-arrow-right.svelte-16ocdv9{right:8px}.animot-progress-bar.svelte-16ocdv9{position:absolute;bottom:0;left:0;right:0;height:3px;background:#ffffff1a;z-index:100;opacity:0;transition:opacity .3s .15s}.animot-presenter.svelte-16ocdv9:hover .animot-progress-bar:where(.svelte-16ocdv9){opacity:1;transition-delay:0s}.animot-progress-fill.svelte-16ocdv9{height:100%;background:linear-gradient(135deg,#7c3aed,#ec4899);transition:width .6s ease}.animot-loading.svelte-16ocdv9{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.animot-spinner.svelte-16ocdv9{width:32px;height:32px;border:3px solid rgba(255,255,255,.2);border-top-color:#7c3aed;border-radius:50%;animation:svelte-16ocdv9-animot-spin .8s linear infinite}@keyframes svelte-16ocdv9-animot-spin{to{transform:rotate(360deg)}}.animot-error.svelte-16ocdv9{color:#ef4444;padding:20px;text-align:center;font-family:system-ui,sans-serif}
|