@plotdb/lotion 0.1.0

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/index.css ADDED
@@ -0,0 +1,191 @@
1
+ .lotion {
2
+ --lotion-bg: #eceae5;
3
+ --lotion-paper: #fbfaf7;
4
+ --lotion-ink: #18181a;
5
+ --lotion-mute: #8a877f;
6
+ --lotion-line: #d9d6cf;
7
+ position: relative;
8
+ border: 1px solid var(--lotion-line);
9
+ border-radius: 12px;
10
+ overflow: hidden;
11
+ outline: none;
12
+ }
13
+ .lotion .lotion-viewport {
14
+ position: relative;
15
+ width: 100%;
16
+ overflow: hidden;
17
+ background: var(--lotion-bg);
18
+ }
19
+ .lotion .lotion-stage {
20
+ position: absolute;
21
+ left: 0;
22
+ top: 0;
23
+ transform-origin: 0 0;
24
+ background: var(--lotion-bg);
25
+ overflow: hidden;
26
+ line-height: normal;
27
+ }
28
+ .lotion .lotion-bar {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 18px;
32
+ height: 64px;
33
+ padding: 0 24px;
34
+ background: var(--lotion-paper);
35
+ border-top: 1px solid var(--lotion-line);
36
+ user-select: none;
37
+ }
38
+ .lotion .lotion-btn {
39
+ flex: none;
40
+ width: 40px;
41
+ height: 40px;
42
+ border-radius: 50%;
43
+ background: var(--lotion-ink);
44
+ color: #fff;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ cursor: pointer;
49
+ }
50
+ .lotion .lotion-play:before {
51
+ content: "";
52
+ margin-left: 3px;
53
+ border-style: solid;
54
+ border-width: 7px 0 7px 12px;
55
+ border-color: transparent transparent transparent #fff;
56
+ }
57
+ .lotion.lotion-playing .lotion-play:before {
58
+ margin-left: 0;
59
+ width: 4px;
60
+ height: 14px;
61
+ border-width: 0 4px;
62
+ border-color: #fff;
63
+ }
64
+ .lotion .lotion-fs {
65
+ background: transparent;
66
+ color: var(--lotion-ink);
67
+ border: 1px solid var(--lotion-line);
68
+ }
69
+ .lotion .lotion-time {
70
+ font: 15px/1 sans-serif;
71
+ color: var(--lotion-mute);
72
+ font-variant-numeric: tabular-nums;
73
+ white-space: nowrap;
74
+ }
75
+ .lotion .lotion-track {
76
+ position: relative;
77
+ flex: 1;
78
+ height: 40px;
79
+ cursor: pointer;
80
+ }
81
+ .lotion .lotion-rail,
82
+ .lotion .lotion-fill {
83
+ position: absolute;
84
+ left: 0;
85
+ top: 18px;
86
+ height: 4px;
87
+ border-radius: 2px;
88
+ }
89
+ .lotion .lotion-rail {
90
+ right: 0;
91
+ background: var(--lotion-line);
92
+ }
93
+ .lotion .lotion-fill {
94
+ background: var(--lotion-ink);
95
+ }
96
+ .lotion .lotion-knob {
97
+ position: absolute;
98
+ top: 13px;
99
+ width: 14px;
100
+ height: 14px;
101
+ margin-left: -7px;
102
+ border-radius: 50%;
103
+ background: var(--lotion-ink);
104
+ }
105
+ .lotion .lotion-chapters {
106
+ position: absolute;
107
+ inset: 0;
108
+ pointer-events: none;
109
+ }
110
+ .lotion .lotion-ch {
111
+ position: absolute;
112
+ top: 14px;
113
+ width: 2px;
114
+ height: 12px;
115
+ margin-left: -1px;
116
+ border-radius: 1px;
117
+ background: var(--lotion-mute);
118
+ opacity: 0.5;
119
+ }
120
+ .lotion.lotion-loading .lotion-stage {
121
+ visibility: hidden;
122
+ }
123
+ .lotion.lotion-loading .lotion-bar {
124
+ opacity: 0.5;
125
+ pointer-events: none;
126
+ }
127
+ .lotion .lotion-loading-screen {
128
+ position: absolute;
129
+ inset: 0;
130
+ display: flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ background: var(--lotion-bg);
134
+ color: var(--lotion-mute);
135
+ }
136
+ .lotion .lotion-spinner {
137
+ width: 36px;
138
+ height: 36px;
139
+ border-radius: 50%;
140
+ border: 3px solid var(--lotion-line);
141
+ border-top-color: var(--lotion-ink);
142
+ animation: lotion-spin 0.8s linear infinite;
143
+ }
144
+ .lotion:fullscreen {
145
+ display: flex;
146
+ flex-direction: column;
147
+ border: 0;
148
+ border-radius: 0;
149
+ }
150
+ .lotion:fullscreen .lotion-viewport {
151
+ flex: 1;
152
+ aspect-ratio: auto !important;
153
+ }
154
+ .lotion:fullscreen .lotion-bar {
155
+ flex: none;
156
+ }
157
+ .lotion.lotion-render {
158
+ position: fixed;
159
+ inset: 0;
160
+ z-index: 99999;
161
+ border: 0;
162
+ border-radius: 0;
163
+ }
164
+ .lotion.lotion-render .lotion-viewport {
165
+ width: 100vw;
166
+ height: 100vh;
167
+ aspect-ratio: auto !important;
168
+ }
169
+ .lotion.lotion-render .lotion-bar {
170
+ display: none;
171
+ }
172
+ @-moz-keyframes lotion-spin {
173
+ to {
174
+ transform: rotate(360deg);
175
+ }
176
+ }
177
+ @-webkit-keyframes lotion-spin {
178
+ to {
179
+ transform: rotate(360deg);
180
+ }
181
+ }
182
+ @-o-keyframes lotion-spin {
183
+ to {
184
+ transform: rotate(360deg);
185
+ }
186
+ }
187
+ @keyframes lotion-spin {
188
+ to {
189
+ transform: rotate(360deg);
190
+ }
191
+ }
package/index.js ADDED
@@ -0,0 +1,437 @@
1
+ (function(){
2
+ var PI, sin, cos, exp, sqrt, round, clamp, lerp, ss, spring, presets, track, vis, bump, typing, hex, mixc, rgb, mk, put, txt, NS, svg, player, ref$, lotion;
3
+ PI = Math.PI, sin = Math.sin, cos = Math.cos, exp = Math.exp, sqrt = Math.sqrt, round = Math.round;
4
+ clamp = function(v, a, b){
5
+ a == null && (a = 0);
6
+ b == null && (b = 1);
7
+ if (v < a) {
8
+ return a;
9
+ } else if (v > b) {
10
+ return b;
11
+ } else {
12
+ return v;
13
+ }
14
+ };
15
+ lerp = function(a, b, f){
16
+ return a + (b - a) * f;
17
+ };
18
+ ss = function(x){
19
+ x = clamp(x);
20
+ return x * x * (3 - 2 * x);
21
+ };
22
+ spring = function(t, w, z){
23
+ var wd;
24
+ w == null && (w = 14);
25
+ z == null && (z = 0.8);
26
+ if (t <= 0) {
27
+ return 0;
28
+ }
29
+ if (z >= 1) {
30
+ return 1 - exp(-w * t) * (1 + w * t);
31
+ }
32
+ wd = w * sqrt(1 - z * z);
33
+ return 1 - exp(-z * w * t) * (cos(wd * t) + (z * w / wd) * sin(wd * t));
34
+ };
35
+ presets = {
36
+ fast: {
37
+ w: 22,
38
+ z: 0.86
39
+ },
40
+ std: {
41
+ w: 14,
42
+ z: 0.8
43
+ },
44
+ soft: {
45
+ w: 9,
46
+ z: 0.9
47
+ },
48
+ move: {
49
+ w: 11,
50
+ z: 0.85
51
+ },
52
+ ease: {
53
+ w: 10,
54
+ z: 1
55
+ }
56
+ };
57
+ track = function(keys, opt){
58
+ var p, def;
59
+ opt == null && (opt = 'std');
60
+ p = function(o){
61
+ if (typeof o === 'string') {
62
+ return presets[o];
63
+ } else {
64
+ return o;
65
+ }
66
+ };
67
+ def = p(opt);
68
+ return function(t){
69
+ var v, i$, to$, i, k, c;
70
+ v = keys[0][1];
71
+ for (i$ = 1, to$ = keys.length; i$ < to$; ++i$) {
72
+ i = i$;
73
+ k = keys[i];
74
+ c = k[2] ? p(k[2]) : def;
75
+ v += (k[1] - keys[i - 1][1]) * spring(t - k[0], c.w, c.z);
76
+ }
77
+ return v;
78
+ };
79
+ };
80
+ vis = function(t, t0, t1, din, dout){
81
+ t1 == null && (t1 = 1e9);
82
+ din == null && (din = 0.4);
83
+ dout == null && (dout = 0.35);
84
+ return ss((t - t0) / din) * (1 - ss((t - t1) / dout));
85
+ };
86
+ bump = function(t, t0, d){
87
+ d == null && (d = 0.6);
88
+ if (t < t0 || t > t0 + d) {
89
+ return 0;
90
+ } else {
91
+ return Math.pow(sin(PI * (t - t0) / d), 2);
92
+ }
93
+ };
94
+ typing = function(t, t0, text, dt){
95
+ var chars;
96
+ dt == null && (dt = 0.06);
97
+ chars = Array.from(text);
98
+ return chars.slice(0, clamp(Math.floor((t - t0) / dt) + 1, 0, chars.length)).join('');
99
+ };
100
+ hex = function(h){
101
+ return [1, 3, 5].map(function(i){
102
+ return parseInt(h.slice(i, i + 2), 16);
103
+ });
104
+ };
105
+ mixc = function(a, b, f){
106
+ return [0, 1, 2].map(function(i){
107
+ return lerp(a[i], b[i], f);
108
+ });
109
+ };
110
+ rgb = function(c, a){
111
+ if (a != null) {
112
+ return "rgba(" + c.map(function(it){
113
+ return round(it);
114
+ }).join(',') + "," + a + ")";
115
+ } else {
116
+ return "rgb(" + c.map(function(it){
117
+ return round(it);
118
+ }).join(',') + ")";
119
+ }
120
+ };
121
+ mk = function(cls, html, parent, prefix){
122
+ var e;
123
+ cls == null && (cls = '');
124
+ html == null && (html = '');
125
+ prefix == null && (prefix = '');
126
+ e = document.createElement('div');
127
+ e.className = cls.split(' ').filter(function(it){
128
+ return it;
129
+ }).map(function(it){
130
+ return prefix + it;
131
+ }).join(' ');
132
+ e.innerHTML = html;
133
+ if (parent) {
134
+ parent.appendChild(e);
135
+ }
136
+ return e;
137
+ };
138
+ put = function(e, x, y, s, o, opt){
139
+ var hide, ref$;
140
+ s == null && (s = 1);
141
+ o == null && (o = 1);
142
+ opt == null && (opt = {});
143
+ hide = (ref$ = opt.hide) != null ? ref$ : true;
144
+ if (hide && o <= 0.002) {
145
+ if (e._lv !== false) {
146
+ e.style.visibility = 'hidden';
147
+ e._lv = false;
148
+ }
149
+ return;
150
+ }
151
+ if (hide && e._lv !== true) {
152
+ e.style.visibility = 'visible';
153
+ e._lv = true;
154
+ }
155
+ e.style.transform = "translate(" + x.toFixed(2) + "px," + y.toFixed(2) + "px) scale(" + s.toFixed(4) + ")";
156
+ e.style.opacity = o.toFixed(3);
157
+ if (opt.blur != null) {
158
+ return e.style.filter = opt.blur > 0.05 ? "blur(" + opt.blur.toFixed(2) + "px)" : '';
159
+ }
160
+ };
161
+ txt = function(e, v){
162
+ if (e._lt !== v) {
163
+ e.innerHTML = v;
164
+ return e._lt = v;
165
+ }
166
+ };
167
+ NS = 'http://www.w3.org/2000/svg';
168
+ svg = function(tag, attrs, parent){
169
+ var e, k, v;
170
+ attrs == null && (attrs = {});
171
+ e = document.createElementNS(NS, tag);
172
+ for (k in attrs) {
173
+ v = attrs[k];
174
+ e.setAttribute(k, v);
175
+ }
176
+ if (parent) {
177
+ parent.appendChild(e);
178
+ }
179
+ return e;
180
+ };
181
+ player = function(opt){
182
+ var this$ = this;
183
+ opt == null && (opt = {});
184
+ this.opt = opt;
185
+ this.root = typeof opt.root === 'string'
186
+ ? document.querySelector(opt.root)
187
+ : opt.root;
188
+ this.width = opt.width || 1920;
189
+ this.height = opt.height || 1080;
190
+ this.duration = opt.duration || 0;
191
+ this.chapters = opt.chapters || [];
192
+ this.t = 0;
193
+ this.playing = false;
194
+ this.last = null;
195
+ this.started = false;
196
+ this.ready = new Promise(function(res){
197
+ return this$.readyRes = res;
198
+ });
199
+ this.renderMode = /[?&]render\b/.test(location.search);
200
+ this.init();
201
+ return this;
202
+ };
203
+ player.prototype = (ref$ = Object.create(Object.prototype), ref$.constructor = player, ref$.init = function(){
204
+ var r, ref$, html, q, this$ = this;
205
+ r = this.root;
206
+ r.classList.add('lotion');
207
+ if (!r.hasAttribute('tabindex')) {
208
+ r.setAttribute('tabindex', 0);
209
+ }
210
+ this.viewport = mk('lotion-viewport', '', r);
211
+ this.stage = mk('lotion-stage', '', this.viewport);
212
+ ref$ = this.stage.style;
213
+ ref$.width = this.width + "px";
214
+ ref$.height = this.height + "px";
215
+ this.viewport.style.aspectRatio = this.width + " / " + this.height;
216
+ r.classList.add('lotion-loading');
217
+ if (this.opt.loading !== false) {
218
+ html = typeof this.opt.loading === 'string' ? this.opt.loading : '<div class="lotion-spinner"></div>';
219
+ this.loading = mk('lotion-loading-screen', html, this.viewport);
220
+ }
221
+ this.bar = mk('lotion-bar', '<div class="lotion-btn lotion-play"></div>\n<div class="lotion-track"><div class="lotion-rail"></div><div class="lotion-fill"></div>\n<div class="lotion-chapters"></div><div class="lotion-knob"></div></div>\n<div class="lotion-time"></div>\n<div class="lotion-btn lotion-fs" title="全螢幕"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"\nstroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M2 6V2h4M10 2h4v4M14 10v4h-4M6 14H2v-4"/></svg></div>', r);
222
+ q = function(n){
223
+ return this$.bar.querySelector(".lotion-" + n);
224
+ };
225
+ this.el = {
226
+ play: q('play'),
227
+ fill: q('fill'),
228
+ knob: q('knob'),
229
+ time: q('time'),
230
+ track: q('track'),
231
+ chapters: q('chapters'),
232
+ fs: q('fs')
233
+ };
234
+ this.chapters.map(function(arg$){
235
+ var t, name, e;
236
+ t = arg$[0], name = arg$[1];
237
+ e = mk('lotion-ch', '', this$.el.chapters);
238
+ e.title = name;
239
+ return e.style.left = 100 * t / this$.duration + "%";
240
+ });
241
+ this.bind();
242
+ if (this.renderMode) {
243
+ r.classList.add('lotion-render');
244
+ }
245
+ this.fit();
246
+ if (typeof ResizeObserver !== 'undefined') {
247
+ return new ResizeObserver(function(){
248
+ return this$.fit();
249
+ }).observe(this.viewport);
250
+ } else {
251
+ return window.addEventListener('resize', function(){
252
+ return this$.fit();
253
+ });
254
+ }
255
+ }, ref$.start = function(){
256
+ var m, this$ = this;
257
+ this.started = true;
258
+ this.root.classList.remove('lotion-loading');
259
+ if (this.loading) {
260
+ this.loading.remove();
261
+ }
262
+ if (this.renderMode) {
263
+ window.seek = function(t){
264
+ return this$.opt.seek(t);
265
+ };
266
+ window.DURATION = this.duration;
267
+ if (this.opt.cues) {
268
+ window.cues = this.opt.cues;
269
+ }
270
+ }
271
+ this.readyRes(this);
272
+ m = /[?&]t=([\d.]+)/.exec(location.search);
273
+ this.seek(m
274
+ ? +m[1]
275
+ : this.renderMode
276
+ ? 0
277
+ : this.opt.start || 0);
278
+ if (this.opt.autoplay && !this.renderMode) {
279
+ document.fonts.ready.then(function(){
280
+ return this$.play(true);
281
+ });
282
+ }
283
+ return this;
284
+ }, ref$.bind = function(){
285
+ var dragging, fromEvent, this$ = this;
286
+ this.el.play.addEventListener('click', function(e){
287
+ e.stopPropagation();
288
+ return this$.toggle();
289
+ });
290
+ this.el.fs.addEventListener('click', function(e){
291
+ e.stopPropagation();
292
+ return this$.fullscreen();
293
+ });
294
+ this.viewport.addEventListener('click', function(){
295
+ this$.root.focus();
296
+ return this$.toggle();
297
+ });
298
+ dragging = false;
299
+ fromEvent = function(e){
300
+ var b;
301
+ b = this$.el.track.getBoundingClientRect();
302
+ return this$.seek(this$.duration * clamp((e.clientX - b.left) / b.width));
303
+ };
304
+ this.el.track.addEventListener('pointerdown', function(e){
305
+ dragging = true;
306
+ this$.el.track.setPointerCapture(e.pointerId);
307
+ return fromEvent(e);
308
+ });
309
+ this.el.track.addEventListener('pointermove', function(e){
310
+ if (dragging) {
311
+ return fromEvent(e);
312
+ }
313
+ });
314
+ this.el.track.addEventListener('pointerup', function(){
315
+ return dragging = false;
316
+ });
317
+ return this.root.addEventListener('keydown', function(e){
318
+ var starts, ref$;
319
+ starts = this$.chapters.map(function(c){
320
+ return c[0];
321
+ });
322
+ if (e.code === 'Space') {
323
+ e.preventDefault();
324
+ return this$.toggle();
325
+ } else if (e.key === 'f') {
326
+ return this$.fullscreen();
327
+ } else if (e.key === 'ArrowRight') {
328
+ return this$.seek((ref$ = starts.find(function(s){
329
+ return s > this$.t + 0.05;
330
+ })) != null
331
+ ? ref$
332
+ : this$.duration);
333
+ } else if (e.key === 'ArrowLeft') {
334
+ return this$.seek((ref$ = starts.filter(function(s){
335
+ return s < this$.t - 0.5;
336
+ }).pop()) != null ? ref$ : 0);
337
+ }
338
+ });
339
+ }, ref$.fit = function(){
340
+ var w, h, s;
341
+ w = this.viewport.clientWidth;
342
+ h = this.viewport.clientHeight;
343
+ if (!w || !h) {
344
+ return;
345
+ }
346
+ s = Math.min(w / this.width, h / this.height);
347
+ return this.stage.style.transform = "translate(" + (w - this.width * s) / 2 + "px," + (h - this.height * s) / 2 + "px) scale(" + s + ")";
348
+ }, ref$.fmt = function(t){
349
+ return Math.floor(t / 60) + ":" + ("0" + Math.floor(t % 60)).slice(-2);
350
+ }, ref$.seek = function(t){
351
+ var p, ch;
352
+ if (!this.started) {
353
+ return;
354
+ }
355
+ this.t = t = clamp(t, 0, this.duration);
356
+ this.opt.seek(t);
357
+ p = 100 * t / this.duration + "%";
358
+ this.el.fill.style.width = p;
359
+ this.el.knob.style.left = p;
360
+ ch = this.chapters.filter(function(c){
361
+ return c[0] <= t;
362
+ }).pop();
363
+ this.el.time.textContent = (ch ? ch[1] + " · " : '') + (this.fmt(t) + " / " + this.fmt(this.duration));
364
+ return this.root.classList.toggle('lotion-playing', this.playing);
365
+ }, ref$.tick = function(now){
366
+ var this$ = this;
367
+ if (!this.playing) {
368
+ return;
369
+ }
370
+ if (this.last != null) {
371
+ this.seek(this.t + (now - this.last) / 1000);
372
+ }
373
+ this.last = now;
374
+ if (this.t >= this.duration) {
375
+ this.playing = false;
376
+ this.seek(this.t);
377
+ return;
378
+ }
379
+ return requestAnimationFrame(function(n){
380
+ return this$.tick(n);
381
+ });
382
+ }, ref$.play = function(go){
383
+ var this$ = this;
384
+ go == null && (go = true);
385
+ if (!this.started) {
386
+ return;
387
+ }
388
+ if (go && this.t >= this.duration) {
389
+ this.t = 0;
390
+ }
391
+ this.playing = go;
392
+ this.last = null;
393
+ this.seek(this.t);
394
+ if (go) {
395
+ return requestAnimationFrame(function(n){
396
+ return this$.tick(n);
397
+ });
398
+ }
399
+ }, ref$.pause = function(){
400
+ return this.play(false);
401
+ }, ref$.toggle = function(){
402
+ return this.play(!this.playing);
403
+ }, ref$.fullscreen = function(){
404
+ var d;
405
+ d = document;
406
+ if (d.fullscreenElement || d.webkitFullscreenElement) {
407
+ (d.exitFullscreen || d.webkitExitFullscreen).call(d);
408
+ } else {
409
+ (this.root.requestFullscreen || this.root.webkitRequestFullscreen).call(this.root);
410
+ }
411
+ return this.root.focus();
412
+ }, ref$);
413
+ lotion = {
414
+ clamp: clamp,
415
+ lerp: lerp,
416
+ ss: ss,
417
+ spring: spring,
418
+ presets: presets,
419
+ track: track,
420
+ vis: vis,
421
+ bump: bump,
422
+ typing: typing,
423
+ hex: hex,
424
+ mixc: mixc,
425
+ rgb: rgb,
426
+ mk: mk,
427
+ put: put,
428
+ txt: txt,
429
+ svg: svg,
430
+ player: player
431
+ };
432
+ if (typeof module != 'undefined' && module !== null) {
433
+ module.exports = lotion;
434
+ } else if (typeof window != 'undefined' && window !== null) {
435
+ window.lotion = lotion;
436
+ }
437
+ }).call(this);
package/index.min.css ADDED
@@ -0,0 +1 @@
1
+ .lotion{--lotion-bg:#eceae5;--lotion-paper:#fbfaf7;--lotion-ink:#18181a;--lotion-mute:#8a877f;--lotion-line:#d9d6cf;position:relative;border:1px solid var(--lotion-line);border-radius:12px;overflow:hidden;outline:none}.lotion .lotion-viewport{position:relative;width:100%;overflow:hidden;background:var(--lotion-bg)}.lotion .lotion-stage{position:absolute;left:0;top:0;transform-origin:0 0;background:var(--lotion-bg);overflow:hidden;line-height:normal}.lotion .lotion-bar{display:flex;align-items:center;gap:18px;height:64px;padding:0 24px;background:var(--lotion-paper);border-top:1px solid var(--lotion-line);user-select:none}.lotion .lotion-btn{flex:none;width:40px;height:40px;border-radius:50%;background:var(--lotion-ink);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer}.lotion .lotion-play:before{content:"";margin-left:3px;border-style:solid;border-width:7px 0 7px 12px;border-color:transparent transparent transparent #fff}.lotion.lotion-playing .lotion-play:before{margin-left:0;width:4px;height:14px;border-width:0 4px;border-color:#fff}.lotion .lotion-fs{background:transparent;color:var(--lotion-ink);border:1px solid var(--lotion-line)}.lotion .lotion-time{font:15px/1 sans-serif;color:var(--lotion-mute);font-variant-numeric:tabular-nums;white-space:nowrap}.lotion .lotion-track{position:relative;flex:1;height:40px;cursor:pointer}.lotion .lotion-rail,.lotion .lotion-fill{position:absolute;left:0;top:18px;height:4px;border-radius:2px}.lotion .lotion-rail{right:0;background:var(--lotion-line)}.lotion .lotion-fill{background:var(--lotion-ink)}.lotion .lotion-knob{position:absolute;top:13px;width:14px;height:14px;margin-left:-7px;border-radius:50%;background:var(--lotion-ink)}.lotion .lotion-chapters{position:absolute;inset:0;pointer-events:none}.lotion .lotion-ch{position:absolute;top:14px;width:2px;height:12px;margin-left:-1px;border-radius:1px;background:var(--lotion-mute);opacity:.5}.lotion.lotion-loading .lotion-stage{visibility:hidden}.lotion.lotion-loading .lotion-bar{opacity:.5;pointer-events:none}.lotion .lotion-loading-screen{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:var(--lotion-bg);color:var(--lotion-mute)}.lotion .lotion-spinner{width:36px;height:36px;border-radius:50%;border:3px solid var(--lotion-line);border-top-color:var(--lotion-ink);animation:lotion-spin .8s linear infinite}.lotion:fullscreen{display:flex;flex-direction:column;border:0;border-radius:0}.lotion:fullscreen .lotion-viewport{flex:1;aspect-ratio:auto !important}.lotion:fullscreen .lotion-bar{flex:none}.lotion.lotion-render{position:fixed;inset:0;z-index:99999;border:0;border-radius:0}.lotion.lotion-render .lotion-viewport{width:100vw;height:100vh;aspect-ratio:auto !important}.lotion.lotion-render .lotion-bar{display:none}@-moz-keyframes lotion-spin{to{transform:rotate(360deg)}}@-webkit-keyframes lotion-spin{to{transform:rotate(360deg)}}@-o-keyframes lotion-spin{to{transform:rotate(360deg)}}@keyframes lotion-spin{to{transform:rotate(360deg)}}
package/index.min.js ADDED
@@ -0,0 +1 @@
1
+ !function(){var t,n=Math.PI,r=Math.sin,s=Math.cos,o=Math.exp,l=Math.sqrt,e=Math.round,u=function(t,i,e){return null==e&&(e=1),t<(i=null==i?0:i)?i:e<t?e:t},a=function(t,i,e){return t+(i-t)*e},h=function(t){return(t=u(t))*t*(3-2*t)},c=function(t,i,e){var n;return null==i&&(i=14),t<=0?0:1<=(e=null==e?.8:e)?1-o(-i*t)*(1+i*t):(n=i*l(1-e*e),1-o(-e*i*t)*(s(n*t)+e*i/n*r(n*t)))},i={fast:{w:22,z:.86},std:{w:14,z:.8},soft:{w:9,z:.9},move:{w:11,z:.85},ease:{w:10,z:1}},d=function(l,t){var u,a=(u=function(t){return"string"==typeof t?i[t]:t})(t=null==t?"std":t);return function(t){for(var i,e,n,r=l[0][1],s=1,o=l.length;s<o;++s)n=(e=l[i=s])[2]?u(e[2]):a,r+=(e[1]-l[i-1][1])*c(t-e[0],n.w,n.z);return r}},f=function(t,i,e,n,r){return h((t-i)/(n=null==n?.4:n))*(1-h((t-(e=null==e?1e9:e))/(r=null==r?.35:r)))},p=function(t,i,e){return null==e&&(e=.6),t<i||i+e<t?0:Math.pow(r(n*(t-i)/e),2)},v=function(t,i,e,n){return null==n&&(n=.06),(e=Array.from(e)).slice(0,u(Math.floor((t-i)/n)+1,0,e.length)).join("")},g=function(i){return[1,3,5].map(function(t){return parseInt(i.slice(t,t+2),16)})},w=function(i,e,n){return[0,1,2].map(function(t){return a(i[t],e[t],n)})},y=function(t,i){return null!=i?"rgba("+t.map(function(t){return e(t)}).join(",")+","+i+")":"rgb("+t.map(function(t){return e(t)}).join(",")+")"},m=function(t,i,e,n){var r;return null==t&&(t=""),null==i&&(i=""),null==n&&(n=""),(r=document.createElement("div")).className=t.split(" ").filter(function(t){return t}).map(function(t){return n+t}).join(" "),r.innerHTML=i,e&&e.appendChild(r),r},k=function(t,i,e,n,r,s){var o;if(null==n&&(n=1),null==r&&(r=1),!((o=null==(o=(s=null==s?{}:s).hide)||o)&&r<=.002))return o&&!0!==t._lv&&(t.style.visibility="visible",t._lv=!0),t.style.transform="translate("+i.toFixed(2)+"px,"+e.toFixed(2)+"px) scale("+n.toFixed(4)+")",t.style.opacity=r.toFixed(3),null!=s.blur?t.style.filter=.05<s.blur?"blur("+s.blur.toFixed(2)+"px)":"":void 0;!1!==t._lv&&(t.style.visibility="hidden",t._lv=!1)},b=function(t,i){if(t._lt!==i)return t.innerHTML=i,t._lt=i},x=function(t,i,e){var n,r,s;for(r in null==i&&(i={}),n=document.createElementNS("http://www.w3.org/2000/svg",t),i)s=i[r],n.setAttribute(r,s);return e&&e.appendChild(n),n},M=function(t){var i=this;return this.opt=t=null==t?{}:t,this.root="string"==typeof t.root?document.querySelector(t.root):t.root,this.width=t.width||1920,this.height=t.height||1080,this.duration=t.duration||0,this.chapters=t.chapters||[],this.t=0,this.playing=!1,this.last=null,this.started=!1,this.ready=new Promise(function(t){return i.readyRes=t}),this.renderMode=/[?&]render\b/.test(location.search),this.init(),this};M.prototype=((t=Object.create(Object.prototype)).constructor=M,t.init=function(){var t,n=this,i=this.root;return i.classList.add("lotion"),i.hasAttribute("tabindex")||i.setAttribute("tabindex",0),this.viewport=m("lotion-viewport","",i),this.stage=m("lotion-stage","",this.viewport),(t=this.stage.style).width=this.width+"px",t.height=this.height+"px",this.viewport.style.aspectRatio=this.width+" / "+this.height,i.classList.add("lotion-loading"),!1!==this.opt.loading&&(t="string"==typeof this.opt.loading?this.opt.loading:'<div class="lotion-spinner"></div>',this.loading=m("lotion-loading-screen",t,this.viewport)),this.bar=m("lotion-bar",'<div class="lotion-btn lotion-play"></div>\n<div class="lotion-track"><div class="lotion-rail"></div><div class="lotion-fill"></div>\n<div class="lotion-chapters"></div><div class="lotion-knob"></div></div>\n<div class="lotion-time"></div>\n<div class="lotion-btn lotion-fs" title="全螢幕"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"\nstroke="currentColor" stroke-width="1.8" stroke-linecap="round"><path d="M2 6V2h4M10 2h4v4M14 10v4h-4M6 14H2v-4"/></svg></div>',i),this.el={play:(t=function(t){return n.bar.querySelector(".lotion-"+t)})("play"),fill:t("fill"),knob:t("knob"),time:t("time"),track:t("track"),chapters:t("chapters"),fs:t("fs")},this.chapters.map(function(t){var i=t[0],t=t[1],e=m("lotion-ch","",n.el.chapters);return e.title=t,e.style.left=100*i/n.duration+"%"}),this.bind(),this.renderMode&&i.classList.add("lotion-render"),this.fit(),"undefined"!=typeof ResizeObserver?new ResizeObserver(function(){return n.fit()}).observe(this.viewport):window.addEventListener("resize",function(){return n.fit()})},t.start=function(){var t,i=this;return this.started=!0,this.root.classList.remove("lotion-loading"),this.loading&&this.loading.remove(),this.renderMode&&(window.seek=function(t){return i.opt.seek(t)},window.DURATION=this.duration,this.opt.cues)&&(window.cues=this.opt.cues),this.readyRes(this),t=/[?&]t=([\d.]+)/.exec(location.search),this.seek(t?+t[1]:!this.renderMode&&this.opt.start||0),this.opt.autoplay&&!this.renderMode&&document.fonts.ready.then(function(){return i.play(!0)}),this},t.bind=function(){var i,e,n=this;return this.el.play.addEventListener("click",function(t){return t.stopPropagation(),n.toggle()}),this.el.fs.addEventListener("click",function(t){return t.stopPropagation(),n.fullscreen()}),this.viewport.addEventListener("click",function(){return n.root.focus(),n.toggle()}),i=!1,e=function(t){var i=n.el.track.getBoundingClientRect();return n.seek(n.duration*u((t.clientX-i.left)/i.width))},this.el.track.addEventListener("pointerdown",function(t){return i=!0,n.el.track.setPointerCapture(t.pointerId),e(t)}),this.el.track.addEventListener("pointermove",function(t){if(i)return e(t)}),this.el.track.addEventListener("pointerup",function(){return i=!1}),this.root.addEventListener("keydown",function(t){var i,e=n.chapters.map(function(t){return t[0]});return"Space"===t.code?(t.preventDefault(),n.toggle()):"f"===t.key?n.fullscreen():"ArrowRight"===t.key?n.seek(null!=(i=e.find(function(t){return t>n.t+.05}))?i:n.duration):"ArrowLeft"===t.key?n.seek(null!=(i=e.filter(function(t){return t<n.t-.5}).pop())?i:0):void 0})},t.fit=function(){var t,i=this.viewport.clientWidth,e=this.viewport.clientHeight;if(i&&e)return t=Math.min(i/this.width,e/this.height),this.stage.style.transform="translate("+(i-this.width*t)/2+"px,"+(e-this.height*t)/2+"px) scale("+t+")"},t.fmt=function(t){return Math.floor(t/60)+":"+("0"+Math.floor(t%60)).slice(-2)},t.seek=function(i){var t;if(this.started)return this.t=i=u(i,0,this.duration),this.opt.seek(i),t=100*i/this.duration+"%",this.el.fill.style.width=t,this.el.knob.style.left=t,t=this.chapters.filter(function(t){return t[0]<=i}).pop(),this.el.time.textContent=(t?t[1]+" · ":"")+this.fmt(i)+" / "+this.fmt(this.duration),this.root.classList.toggle("lotion-playing",this.playing)},t.tick=function(t){var i=this;if(this.playing){if(null!=this.last&&this.seek(this.t+(t-this.last)/1e3),this.last=t,!(this.t>=this.duration))return requestAnimationFrame(function(t){return i.tick(t)});this.playing=!1,this.seek(this.t)}},t.play=function(t){var i=this;if(null==t&&(t=!0),this.started)return t&&this.t>=this.duration&&(this.t=0),this.playing=t,this.last=null,this.seek(this.t),t?requestAnimationFrame(function(t){return i.tick(t)}):void 0},t.pause=function(){return this.play(!1)},t.toggle=function(){return this.play(!this.playing)},t.fullscreen=function(){var t=document;return t.fullscreenElement||t.webkitFullscreenElement?(t.exitFullscreen||t.webkitExitFullscreen).call(t):(this.root.requestFullscreen||this.root.webkitRequestFullscreen).call(this.root),this.root.focus()},t),t={clamp:u,lerp:a,ss:h,spring:c,presets:i,track:d,vis:f,bump:p,typing:v,hex:g,mixc:w,rgb:y,mk:m,put:k,txt:b,svg:x,player:M},"undefined"!=typeof module&&null!==module?module.exports=t:"undefined"!=typeof window&&null!==window&&(window.lotion=t)}.call(this);
package/package.json ADDED
@@ -0,0 +1 @@
1
+ {"author":"zbryikt","name":"@plotdb/lotion","version":"0.1.0","description":"deterministic motion toolkit: animation as a pure function of time, with player, frame renderer, block packaging and audio tools","license":"MIT","main":"index.min.js","browser":"index.min.js","bin":{"lotion":"./cli.js"},"homepage":"https://github.com/plotdb/lotion","repository":{"type":"git","url":"git+https://github.com/plotdb/lotion.git"},"scripts":{"start":"npx server -r web -o true"},"engines":{"node":">=14"},"keywords":["motion","animation","video","playwright","block"],"dependencies":{"@plotdb/block":"^5.7.3","@plotdb/csscope":"^5.0.4","@plotdb/rescope":"^5.1.0","@plotdb/semver":"^0.0.4","proxise":"^1.0.1"},"peerDependencies":{"playwright":">=1.40"},"peerDependenciesMeta":{"playwright":{"optional":true}},"devDependencies":{"@plotdb/guides":"github:plotdb/guides","@zbryikt/template":"^2.5.0","fedep":"^1.9.0","livescript":"^1.6.0","playwright":"^1.63.0","stylus":"^0.64.0","uglify-js":"^3.19.3"},"frontendDependencies":{"root":"web/static/assets/lib","modules":[]}}