~james/core

core/web/src/lib/components/ui/AnimatedLogo.svelte -rw-r--r-- 7.7 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
<script module lang="ts">
	import { WORDMARK } from "#lib/components/ui/logotype.ts";

	const FUR =
		"M21.0971 30.866C20.0566 30.8575 19.2628 30.5542 18.4016 30.0269C17.1668 29.3753 16.2237 28.2808 15.5497 27.0739C14.4789 28.4065 13.0476 29.215 11.4453 29.6718C10.763 29.8705 9.56809 30.0721 7.58737 29.3523C4.73277 28.3905 2.65342 25.4114 2.88973 22.3758C2.8465 21.1175 3.30392 19.8825 3.95228 18.8208C2.22264 17.8897 0.81225 16.3266 0.272148 14.4098C-0.0560731 13.3604 -0.042271 12.2299 0.0787626 11.1512C0.512215 8.60429 2.41697 6.38956 4.86912 5.59294C5.8479 3.35574 7.98378 1.68743 10.4037 1.34778C12.0104 1.12338 13.6735 1.46075 15.0792 2.27979C17.1272 0.00158595 20.6952 -0.671697 23.4195 0.727793C25.4978 1.72322 26.9839 3.80003 27.3447 6.06471C29.3222 6.85928 30.9877 8.47971 31.6413 10.5368C32.0784 11.8104 32.0928 13.2132 31.8098 14.5209C31.3041 16.5615 29.8679 18.2987 28.009 19.2482C28.0135 19.6113 29.2037 22.2296 29.0047 24.2056C28.9612 26.676 27.399 29.0172 25.2325 30.1544C23.9683 30.8945 22.4702 30.8805 21.0971 30.866Z";
	const FACE =
		"M15.1733 23.755C16.9256 23.5593 18.0743 22.0269 18.9665 20.6469C19.3883 20.0182 19.7105 19.3146 20.0306 18.6454C20.4458 19.0271 20.7975 19.7461 21.4541 19.9173C22.1457 20.1333 22.9566 19.9579 23.38 19.3277C24.1902 17.8118 23.7908 15.9827 23.319 14.4119C23.0284 13.5097 22.6472 12.5841 21.9218 11.9446C22.0765 10.85 21.4299 9.73834 20.5106 9.16542C19.7272 9.79198 18.5352 9.78821 17.7794 9.11795C16.3309 10.5997 15.0034 10.5505 13.7212 9.37618C13.4331 9.11226 12.8832 10.9871 10.9535 9.92506C9.84488 10.8567 8.98526 11.753 8.22356 13.0435C7.48342 14.4347 6.70829 15.6703 6.64151 17.1811C6.6094 18.0641 7.29731 18.9892 8.22942 18.9174C9.16105 19.0009 9.7952 18.0813 10.5006 17.6993C10.6058 18.9316 10.7243 20.2556 11.1395 21.4587C11.6161 23.0155 13.2947 24.005 14.8835 23.7784C14.9959 23.7696 15.1733 23.7549 15.1733 23.755Z";
	const EYE_R =
		"M16.0828 19.1062C15.2306 18.5823 15.6407 17.4452 15.6066 16.6193C15.6914 15.6227 15.7594 14.575 16.2061 13.667C16.6788 13.0197 17.8318 13.2694 17.8827 14.0999C17.8488 14.9353 17.4664 15.767 17.5121 16.633C17.4129 17.3561 17.5839 18.1684 17.265 18.8293C17.0033 19.195 16.4703 19.3013 16.0828 19.1062Z";
	const EYE_L =
		"M12.3606 18.6302C11.5578 18.1933 11.8129 17.0941 11.687 16.3298C11.7914 15.445 11.7045 14.3226 12.4431 13.7021C13.1653 13.1969 14.1485 14.0621 13.8069 14.8564C13.4426 15.8602 13.6814 16.957 13.6891 17.9748C13.5512 18.5752 12.911 18.894 12.3606 18.6302Z";
	const LID_L = "M11.5 16.3C12 15.4 13.45 15.3 14 16.05C13.4 15.75 12.1 15.85 11.5 16.3Z";
</script>

<script lang="ts">
	import { cn } from "tailwind-variants";

	interface Props {
		wordmark?: boolean;
		class?: string;
	}

	let { wordmark = false, class: className = "" }: Props = $props();

	const face = $props.id();
</script>

<svg
	class={cn(wordmark ? "h-8" : "size-8", "overflow-visible", className)}
	viewBox={wordmark ? "0 0 117 32" : "0 0 32 32"}
	fill="currentColor"
	xmlns="http://www.w3.org/2000/svg"
	role="img"
	aria-label="tangled"
>
	<defs>
		<mask id={face} maskUnits="userSpaceOnUse" x="-8" y="-8" width="48" height="48">
			<rect x="-8" y="-8" width="48" height="48" fill="#fff" />
			<path class="face" d={FACE} fill="#000" />
		</mask>
	</defs>
	<g class="body">
		<path d={FUR} mask="url(#{face})" />
		<path class="eye eye-l" d={EYE_L} />
		<path class="eye eye-r" d={EYE_R} />
		<path class="lid" d={LID_L} />
	</g>
	{#if wordmark}
		{#each WORDMARK as d (d)}
			<path {d} fill-rule="evenodd" />
		{/each}
	{/if}
</svg>

<style>
	.body,
	.face,
	.eye,
	.lid {
		animation-duration: 2970ms;
		animation-fill-mode: both;
	}

	.body {
		transform-box: view-box;
		transform-origin: 16px 15.5px;
		animation-name: spin-in;
	}

	.face {
		transform-box: view-box;
		transform-origin: 15.2px 16.5px;
		animation-name: open-face;
	}

	.eye {
		transform-box: fill-box;
		transform-origin: center;
	}

	.eye-l {
		animation-name: wink-eye;
	}

	.eye-r {
		animation-name: squint-eye;
	}

	.lid {
		opacity: 0;
		animation-name: close-lid;
	}

	@media (prefers-reduced-motion: reduce) {
		.body,
		.face,
		.eye,
		.lid {
			animation: none;
		}
	}

	@keyframes spin-in {
		0% {
			transform: translate(0, 0px) rotate(-300deg) scale(0);
			animation-timing-function: linear(
				0,
				0.17,
				0.321,
				0.454,
				0.572,
				0.674,
				0.761,
				0.835,
				0.896,
				0.946,
				0.986,
				1.016,
				1.038,
				1.052,
				1.059,
				1.062,
				1.059,
				1.054,
				1.045,
				1.036,
				1.025,
				1.016,
				1.008,
				1.002,
				1
			);
		}
		30.3% {
			transform: translate(0, 0px) rotate(0deg) scale(1);
		}
		83.84% {
			transform: translate(0, 0px) rotate(0deg) scale(1);
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		87.21% {
			transform: translate(0, -0.3px) rotate(-5deg) scale(1);
		}
		89.9% {
			transform: translate(0, -0.3px) rotate(-5deg) scale(1);
			animation-timing-function: linear(
				0,
				0.189,
				0.356,
				0.502,
				0.63,
				0.739,
				0.831,
				0.908,
				0.97,
				1.02,
				1.057,
				1.083,
				1.1,
				1.109,
				1.11,
				1.105,
				1.096,
				1.084,
				1.069,
				1.053,
				1.037,
				1.023,
				1.011,
				1.003,
				1
			);
		}
		100% {
			transform: translate(0, 0px) rotate(0deg) scale(1);
		}
	}
	@keyframes open-face {
		0% {
			transform: scale(0);
		}
		23.57% {
			transform: scale(0);
			animation-timing-function: linear(
				0,
				0.193,
				0.405,
				0.611,
				0.792,
				0.94,
				1.05,
				1.124,
				1.164,
				1.177,
				1.17,
				1.149,
				1.12,
				1.088,
				1.058,
				1.031,
				1.009,
				0.993,
				0.982,
				0.976,
				0.974,
				0.975,
				0.978,
				0.982,
				0.987,
				0.991,
				0.995,
				0.999,
				1.001,
				1.003,
				1.004,
				1.004,
				1.004,
				1.003,
				1.003,
				1.002,
				1.001,
				1.001,
				1,
				1,
				1
			);
		}
		42.09% {
			transform: scale(1);
		}
	}
	@keyframes wink-eye {
		0% {
			transform: scaleY(0);
			opacity: 1;
		}
		37.04% {
			transform: scaleY(0);
			opacity: 1;
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		44.44% {
			transform: scaleY(1);
			opacity: 1;
		}
		63.3% {
			transform: scaleY(1);
			opacity: 1;
			animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
		}
		65.66% {
			transform: scaleY(0.06);
			opacity: 1;
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		70.37% {
			transform: scaleY(1);
			opacity: 1;
		}
		84.51% {
			transform: scaleY(1);
			opacity: 1;
			animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
		}
		86.87% {
			transform: scaleY(0.06);
			opacity: 0;
		}
		89.9% {
			transform: scaleY(0.06);
			opacity: 0;
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		93.94% {
			transform: scaleY(1);
			opacity: 1;
		}
	}
	@keyframes squint-eye {
		0% {
			transform: scaleY(0);
		}
		39.06% {
			transform: scaleY(0);
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		46.46% {
			transform: scaleY(1);
		}
		63.3% {
			transform: scaleY(1);
			animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
		}
		65.66% {
			transform: scaleY(0.06);
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		70.37% {
			transform: scaleY(1);
		}
		84.51% {
			transform: scaleY(1);
			animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
		}
		86.87% {
			transform: scaleY(0.85);
		}
		89.9% {
			transform: scaleY(0.85);
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		93.94% {
			transform: scaleY(1);
		}
	}
	@keyframes close-lid {
		0% {
			opacity: 0;
		}
		84.51% {
			opacity: 0;
			animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
		}
		86.87% {
			opacity: 1;
		}
		89.9% {
			opacity: 1;
			animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
		}
		93.94% {
			opacity: 0;
		}
	}
</style>