@jjlmoya/landings 0.5.0 → 0.7.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/package.json +1 -1
- package/scripts/copy-public-assets.mjs +42 -34
- package/src/landing/team/assets/gamebob-team-hero.webp +0 -0
- package/src/landing/team/assets/team-og.webp +0 -0
- package/src/landing/team/components/BobModelBook.astro +4 -4
- package/src/landing/team/components/CompanyWorks.astro +9 -78
- package/src/landing/team/components/HumanTouch.astro +102 -38
- package/src/landing/team/components/TeamHero.astro +21 -12
- package/src/landing/team/entry.ts +16 -6
- package/src/landing/team/i18n/de.ts +181 -0
- package/src/landing/team/i18n/en.ts +60 -157
- package/src/landing/team/i18n/es.ts +16 -112
- package/src/landing/team/i18n/fr.ts +181 -0
- package/src/landing/team/i18n/id.ts +181 -0
- package/src/landing/team/i18n/index.ts +28 -2
- package/src/landing/team/i18n/it.ts +181 -0
- package/src/landing/team/i18n/ja.ts +181 -0
- package/src/landing/team/i18n/ko.ts +181 -0
- package/src/landing/team/i18n/nl.ts +181 -0
- package/src/landing/team/i18n/pl.ts +181 -0
- package/src/landing/team/i18n/pt.ts +181 -0
- package/src/landing/team/i18n/ru.ts +181 -0
- package/src/landing/team/i18n/sv.ts +181 -0
- package/src/landing/team/i18n/tr.ts +181 -0
- package/src/landing/team/i18n/zh.ts +181 -0
- package/src/landing/team/styles/BobModelBook.css +8 -5
- package/src/landing/team/styles/HumanTouch.css +116 -12
- package/src/landing/team/styles/SupportTransition.css +7 -1
- package/src/landing/team/styles/TeamHero.css +101 -16
- package/src/layouts/PreviewLayout.astro +0 -3
- package/src/pages/[locale].astro +3 -4
- package/src/tests/no_en_dash.test.ts +1 -0
- package/src/types.ts +6 -5
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
import { cp, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
|
|
@@ -6,41 +7,48 @@ const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
|
6
7
|
const consumerRoot = packageRoot.includes("node_modules")
|
|
7
8
|
? join(packageRoot, "../../..")
|
|
8
9
|
: packageRoot;
|
|
9
|
-
const publicRoot = join(consumerRoot, "public", "landings"
|
|
10
|
-
const
|
|
11
|
-
"team-landing.css",
|
|
12
|
-
"TeamHero.css",
|
|
13
|
-
"CompanyWorks.css",
|
|
14
|
-
"BobMasterPlan.css",
|
|
15
|
-
"TeamComicScenes.css",
|
|
16
|
-
"HumanTouch.css",
|
|
17
|
-
"ProductManifesto.css",
|
|
18
|
-
"BobModelBook.css",
|
|
19
|
-
"SupportTransition.css",
|
|
20
|
-
"MemoryWall.css",
|
|
21
|
-
"TeamRoster.css",
|
|
22
|
-
"BehindJoke.css",
|
|
23
|
-
];
|
|
10
|
+
const publicRoot = join(consumerRoot, "public", "landings");
|
|
11
|
+
const srcLandingRoot = join(packageRoot, "src", "landing");
|
|
24
12
|
|
|
25
|
-
const
|
|
26
|
-
["src/landing/team/assets", "assets"],
|
|
27
|
-
];
|
|
13
|
+
const landings = await readdir(srcLandingRoot);
|
|
28
14
|
|
|
29
|
-
|
|
15
|
+
for (const name of landings) {
|
|
16
|
+
const landingPublicDir = join(publicRoot, name);
|
|
17
|
+
await mkdir(landingPublicDir, { recursive: true });
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
19
|
+
const stylesRoot = join(srcLandingRoot, name, "styles");
|
|
20
|
+
let hasStyles = false;
|
|
21
|
+
try {
|
|
22
|
+
const styleFiles = (await readdir(stylesRoot)).filter((f) =>
|
|
23
|
+
f.endsWith(".css"),
|
|
24
|
+
);
|
|
25
|
+
if (styleFiles.length > 0) {
|
|
26
|
+
const cssBundle = await Promise.all(
|
|
27
|
+
styleFiles.map(async (file) => {
|
|
28
|
+
const content = await readFile(join(stylesRoot, file), "utf8");
|
|
29
|
+
return `/* ${file} */\n${content.trim()}\n`;
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
await writeFile(
|
|
33
|
+
join(landingPublicDir, `${name}.css`),
|
|
34
|
+
`${cssBundle.join("\n")}\n`,
|
|
35
|
+
);
|
|
36
|
+
hasStyles = true;
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
// no styles dir
|
|
40
|
+
}
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return `/* ${file} */\n${content.trim()}\n`;
|
|
43
|
-
}),
|
|
44
|
-
);
|
|
42
|
+
if (!hasStyles) {
|
|
43
|
+
console.log(`[landings] No styles found for "${name}"`);
|
|
44
|
+
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
const assetsDir = join(srcLandingRoot, name, "assets");
|
|
47
|
+
if (existsSync(assetsDir)) {
|
|
48
|
+
await cp(assetsDir, join(landingPublicDir, "assets"), {
|
|
49
|
+
recursive: true,
|
|
50
|
+
force: true,
|
|
51
|
+
errorOnExist: false,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -37,10 +37,10 @@ const { t } = Astro.props;
|
|
|
37
37
|
const poses = [
|
|
38
38
|
{ image: coverPose, variant: 'large' },
|
|
39
39
|
{ image: attitudePose, variant: 'portrait' },
|
|
40
|
-
{ image: expensivePose, variant: 'wide' },
|
|
41
|
-
{ image: finalPose, variant: 'portrait' },
|
|
42
|
-
{ image: pose05, variant: 'portrait' },
|
|
43
|
-
{ image: pose06, variant: 'wide' },
|
|
40
|
+
{ image: expensivePose, variant: 'wide', locked: true },
|
|
41
|
+
{ image: finalPose, variant: 'portrait', locked: true },
|
|
42
|
+
{ image: pose05, variant: 'portrait', locked: true },
|
|
43
|
+
{ image: pose06, variant: 'wide', locked: true },
|
|
44
44
|
{ image: pose07Locked, variant: 'portrait', locked: true },
|
|
45
45
|
{ image: pose08Locked, variant: 'portrait', locked: true },
|
|
46
46
|
{ image: pose09Locked, variant: 'wide', locked: true },
|
|
@@ -11,15 +11,13 @@ interface Props {
|
|
|
11
11
|
eyebrow: string;
|
|
12
12
|
title: string;
|
|
13
13
|
text: string;
|
|
14
|
-
secretDossier: string;
|
|
15
|
-
closeDossier: string;
|
|
16
14
|
members: {
|
|
17
|
-
bob: { name: string; role: string; status: string
|
|
18
|
-
terra: { name: string; role: string; status: string
|
|
19
|
-
ambar: { name: string; role: string; status: string
|
|
20
|
-
ambarChiquilla: { name: string; role: string; status: string
|
|
21
|
-
drac: { name: string; role: string; status: string
|
|
22
|
-
jj: { name: string; role: string; status: string
|
|
15
|
+
bob: { name: string; role: string; status: string };
|
|
16
|
+
terra: { name: string; role: string; status: string };
|
|
17
|
+
ambar: { name: string; role: string; status: string };
|
|
18
|
+
ambarChiquilla: { name: string; role: string; status: string };
|
|
19
|
+
drac: { name: string; role: string; status: string };
|
|
20
|
+
jj: { name: string; role: string; status: string };
|
|
23
21
|
};
|
|
24
22
|
};
|
|
25
23
|
}
|
|
@@ -32,9 +30,7 @@ const members = [
|
|
|
32
30
|
name: t.members.bob.name,
|
|
33
31
|
role: t.members.bob.role,
|
|
34
32
|
status: t.members.bob.status,
|
|
35
|
-
dossier: t.members.bob.dossier,
|
|
36
33
|
hierarchy: 'chief',
|
|
37
|
-
mark: 'B',
|
|
38
34
|
sprite: bobSprite,
|
|
39
35
|
},
|
|
40
36
|
{
|
|
@@ -42,9 +38,7 @@ const members = [
|
|
|
42
38
|
name: t.members.terra.name,
|
|
43
39
|
role: t.members.terra.role,
|
|
44
40
|
status: t.members.terra.status,
|
|
45
|
-
dossier: t.members.terra.dossier,
|
|
46
41
|
hierarchy: 'orbit orbit-terra',
|
|
47
|
-
mark: 'T',
|
|
48
42
|
sprite: terraSprite,
|
|
49
43
|
},
|
|
50
44
|
{
|
|
@@ -52,9 +46,7 @@ const members = [
|
|
|
52
46
|
name: t.members.ambar.name,
|
|
53
47
|
role: t.members.ambar.role,
|
|
54
48
|
status: t.members.ambar.status,
|
|
55
|
-
dossier: t.members.ambar.dossier,
|
|
56
49
|
hierarchy: 'orbit orbit-ambar',
|
|
57
|
-
mark: 'A',
|
|
58
50
|
sprite: ambarSprite,
|
|
59
51
|
},
|
|
60
52
|
{
|
|
@@ -62,9 +54,7 @@ const members = [
|
|
|
62
54
|
name: t.members.ambarChiquilla.name,
|
|
63
55
|
role: t.members.ambarChiquilla.role,
|
|
64
56
|
status: t.members.ambarChiquilla.status,
|
|
65
|
-
dossier: t.members.ambarChiquilla.dossier,
|
|
66
57
|
hierarchy: 'orbit orbit-chiquilla',
|
|
67
|
-
mark: 'AC',
|
|
68
58
|
sprite: ambarChiquillaSprite,
|
|
69
59
|
},
|
|
70
60
|
{
|
|
@@ -72,9 +62,7 @@ const members = [
|
|
|
72
62
|
name: t.members.drac.name,
|
|
73
63
|
role: t.members.drac.role,
|
|
74
64
|
status: t.members.drac.status,
|
|
75
|
-
dossier: t.members.drac.dossier,
|
|
76
65
|
hierarchy: 'orbit orbit-drac',
|
|
77
|
-
mark: 'D',
|
|
78
66
|
sprite: dracSprite,
|
|
79
67
|
},
|
|
80
68
|
{
|
|
@@ -82,9 +70,7 @@ const members = [
|
|
|
82
70
|
name: t.members.jj.name,
|
|
83
71
|
role: t.members.jj.role,
|
|
84
72
|
status: t.members.jj.status,
|
|
85
|
-
dossier: t.members.jj.dossier,
|
|
86
73
|
hierarchy: 'human',
|
|
87
|
-
mark: 'JJ',
|
|
88
74
|
sprite: jjSprite,
|
|
89
75
|
},
|
|
90
76
|
];
|
|
@@ -98,18 +84,11 @@ const members = [
|
|
|
98
84
|
{t.text}
|
|
99
85
|
</p>
|
|
100
86
|
|
|
101
|
-
<div class="company-works-system"
|
|
87
|
+
<div class="company-works-system">
|
|
102
88
|
<div class="company-works-orbit-ring" aria-hidden="true"></div>
|
|
103
89
|
{
|
|
104
90
|
members.map((member) => (
|
|
105
|
-
<
|
|
106
|
-
class={`company-works-node company-works-node-${member.hierarchy}`}
|
|
107
|
-
type="button"
|
|
108
|
-
data-dossier-name={member.name}
|
|
109
|
-
data-dossier-role={member.role}
|
|
110
|
-
data-dossier-status={member.status}
|
|
111
|
-
data-dossier-copy={member.dossier}
|
|
112
|
-
>
|
|
91
|
+
<div class={`company-works-node company-works-node-${member.hierarchy}`}>
|
|
113
92
|
<span class="company-works-sprite" data-member={member.id} aria-hidden="true">
|
|
114
93
|
<img
|
|
115
94
|
src={member.sprite.src}
|
|
@@ -124,57 +103,9 @@ const members = [
|
|
|
124
103
|
<span class="company-works-role">{member.role}</span>
|
|
125
104
|
<span class="company-works-status">{member.status}</span>
|
|
126
105
|
</span>
|
|
127
|
-
</
|
|
106
|
+
</div>
|
|
128
107
|
))
|
|
129
108
|
}
|
|
130
109
|
</div>
|
|
131
110
|
</div>
|
|
132
|
-
|
|
133
|
-
<div class="company-works-focus" data-company-focus></div>
|
|
134
|
-
<aside class="company-works-drawer" data-company-drawer aria-hidden="true">
|
|
135
|
-
<button class="company-works-drawer-close" type="button" data-company-close aria-label={t.closeDossier}>×</button>
|
|
136
|
-
<p class="company-works-drawer-eyebrow">{t.secretDossier}</p>
|
|
137
|
-
<h3 data-company-drawer-name></h3>
|
|
138
|
-
<p class="company-works-drawer-role" data-company-drawer-role></p>
|
|
139
|
-
<p class="company-works-drawer-status" data-company-drawer-status></p>
|
|
140
|
-
<p class="company-works-drawer-copy" data-company-drawer-copy></p>
|
|
141
|
-
</aside>
|
|
142
111
|
</section>
|
|
143
|
-
|
|
144
|
-
<script>
|
|
145
|
-
const drawer = document.querySelector<HTMLElement>('[data-company-drawer]');
|
|
146
|
-
const closeButton = document.querySelector<HTMLButtonElement>('[data-company-close]');
|
|
147
|
-
const focusLayer = document.querySelector<HTMLElement>('[data-company-focus]');
|
|
148
|
-
const closeDrawer = () => {
|
|
149
|
-
drawer?.classList.remove('is-open');
|
|
150
|
-
drawer?.setAttribute('aria-hidden', 'true');
|
|
151
|
-
focusLayer?.classList.remove('is-drawer-open');
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
document.querySelectorAll<HTMLButtonElement>('[data-dossier-name]').forEach((card) => {
|
|
155
|
-
card.addEventListener('mouseenter', () => {
|
|
156
|
-
focusLayer?.classList.add('is-active');
|
|
157
|
-
card.classList.add('is-focused');
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
card.addEventListener('mouseleave', () => {
|
|
161
|
-
focusLayer?.classList.remove('is-active');
|
|
162
|
-
card.classList.remove('is-focused');
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
card.addEventListener('click', () => {
|
|
166
|
-
if (!drawer) return;
|
|
167
|
-
|
|
168
|
-
drawer.querySelector('[data-company-drawer-name]')!.textContent = card.dataset.dossierName ?? '';
|
|
169
|
-
drawer.querySelector('[data-company-drawer-role]')!.textContent = card.dataset.dossierRole ?? '';
|
|
170
|
-
drawer.querySelector('[data-company-drawer-status]')!.textContent = card.dataset.dossierStatus ?? '';
|
|
171
|
-
drawer.querySelector('[data-company-drawer-copy]')!.textContent = card.dataset.dossierCopy ?? '';
|
|
172
|
-
drawer.classList.add('is-open');
|
|
173
|
-
drawer.setAttribute('aria-hidden', 'false');
|
|
174
|
-
focusLayer?.classList.add('is-drawer-open');
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
closeButton?.addEventListener('click', closeDrawer);
|
|
179
|
-
focusLayer?.addEventListener('click', closeDrawer);
|
|
180
|
-
</script>
|
|
@@ -3,15 +3,16 @@ import tinderProfile from "../assets/jjlmoya/tinder-profile.webp";
|
|
|
3
3
|
import tinderProfileWinked from "../assets/jjlmoya/tinder-profile-winked.webp";
|
|
4
4
|
import bobPointingSprite from "../assets/bob-model-book/bob-pointing.webp";
|
|
5
5
|
import bobTechnoTrack from "../assets/music/bob-techno.mp3";
|
|
6
|
+
import { Icon } from "astro-icon/components";
|
|
6
7
|
|
|
7
8
|
interface Props {
|
|
8
9
|
t: {
|
|
10
|
+
eyebrow: string;
|
|
11
|
+
title: string;
|
|
9
12
|
textBefore: string;
|
|
10
13
|
wordWithRagebait: string;
|
|
11
14
|
textAfter: string;
|
|
12
15
|
ragebaitExplanation: string;
|
|
13
|
-
eyebrow: string;
|
|
14
|
-
title: string;
|
|
15
16
|
chipsLabel: string;
|
|
16
17
|
boardLabel: string;
|
|
17
18
|
alert: string;
|
|
@@ -38,17 +39,52 @@ interface Props {
|
|
|
38
39
|
const { t } = Astro.props;
|
|
39
40
|
---
|
|
40
41
|
|
|
41
|
-
<section
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
<section
|
|
43
|
+
class="team-section human-touch"
|
|
44
|
+
aria-labelledby="human-touch-title"
|
|
45
|
+
data-human-touch
|
|
46
|
+
>
|
|
47
|
+
<div class="human-touch-bg-wrap" aria-hidden="true">
|
|
48
|
+
<div class="human-touch-equalizer">
|
|
49
|
+
<span></span>
|
|
50
|
+
<span></span>
|
|
51
|
+
<span></span>
|
|
52
|
+
<span></span>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
<audio
|
|
56
|
+
src={bobTechnoTrack}
|
|
57
|
+
data-human-touch-audio
|
|
58
|
+
class="human-touch-audio"
|
|
59
|
+
loop
|
|
60
|
+
></audio>
|
|
61
|
+
|
|
62
|
+
<div class="human-touch-border-player top-border-player" aria-label={t.partyPlayer.audioLabel}>
|
|
46
63
|
<button
|
|
47
|
-
class="human-touch-
|
|
64
|
+
class="human-touch-border-toggle"
|
|
48
65
|
type="button"
|
|
66
|
+
data-human-touch-toggle
|
|
67
|
+
data-play-label={t.partyPlayer.playLabel}
|
|
68
|
+
data-pause-label={t.partyPlayer.pauseLabel}
|
|
49
69
|
aria-label={t.partyPlayer.playLabel}
|
|
70
|
+
>
|
|
71
|
+
<span class="border-toggle-icon"></span>
|
|
72
|
+
</button>
|
|
73
|
+
<div class="human-touch-border-progress-bar" data-human-touch-seek aria-hidden="true">
|
|
74
|
+
<span data-human-touch-progress></span>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div
|
|
79
|
+
class="human-touch-party-player"
|
|
80
|
+
aria-label={t.partyPlayer.audioLabel}
|
|
81
|
+
>
|
|
82
|
+
<button
|
|
83
|
+
class="human-touch-player-toggle"
|
|
84
|
+
type="button"
|
|
50
85
|
data-play-label={t.partyPlayer.playLabel}
|
|
51
86
|
data-pause-label={t.partyPlayer.pauseLabel}
|
|
87
|
+
aria-label={t.partyPlayer.playLabel}
|
|
52
88
|
data-human-touch-toggle
|
|
53
89
|
>
|
|
54
90
|
<span class="human-touch-player-icon" aria-hidden="true"></span>
|
|
@@ -83,12 +119,6 @@ const { t } = Astro.props;
|
|
|
83
119
|
</div>
|
|
84
120
|
<span class="human-touch-player-time" data-human-touch-current aria-hidden="true">0:00</span>
|
|
85
121
|
</div>
|
|
86
|
-
<div class="human-touch-equalizer" aria-hidden="true">
|
|
87
|
-
<span></span>
|
|
88
|
-
<span></span>
|
|
89
|
-
<span></span>
|
|
90
|
-
<span></span>
|
|
91
|
-
</div>
|
|
92
122
|
|
|
93
123
|
<div class="team-landing-inner">
|
|
94
124
|
<div class="human-touch-shell">
|
|
@@ -179,33 +209,57 @@ const { t } = Astro.props;
|
|
|
179
209
|
<a
|
|
180
210
|
href="https://es.linkedin.com/in/jjlmoya"
|
|
181
211
|
target="_blank"
|
|
182
|
-
rel="noreferrer"
|
|
212
|
+
rel="noreferrer"
|
|
213
|
+
aria-label="LinkedIn"
|
|
183
214
|
>
|
|
215
|
+
<Icon name="mdi:linkedin" style="width: 24px; height: 24px;" />
|
|
216
|
+
</a>
|
|
184
217
|
<a
|
|
185
218
|
href="https://github.com/jjlmoya"
|
|
186
219
|
target="_blank"
|
|
187
|
-
rel="noreferrer"
|
|
220
|
+
rel="noreferrer"
|
|
221
|
+
aria-label="GitHub"
|
|
188
222
|
>
|
|
223
|
+
<Icon name="mdi:github" style="width: 24px; height: 24px;" />
|
|
224
|
+
</a>
|
|
189
225
|
</div>
|
|
190
226
|
</div>
|
|
191
227
|
</div>
|
|
192
228
|
</div>
|
|
229
|
+
|
|
230
|
+
<div class="human-touch-border-player bottom-border-player" aria-label={t.partyPlayer.audioLabel}>
|
|
231
|
+
<button
|
|
232
|
+
class="human-touch-border-toggle"
|
|
233
|
+
type="button"
|
|
234
|
+
data-human-touch-toggle
|
|
235
|
+
data-play-label={t.partyPlayer.playLabel}
|
|
236
|
+
data-pause-label={t.partyPlayer.pauseLabel}
|
|
237
|
+
aria-label={t.partyPlayer.playLabel}
|
|
238
|
+
>
|
|
239
|
+
<span class="border-toggle-icon"></span>
|
|
240
|
+
</button>
|
|
241
|
+
<div class="human-touch-border-progress-bar" data-human-touch-seek aria-hidden="true">
|
|
242
|
+
<span data-human-touch-progress></span>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
193
245
|
</section>
|
|
194
246
|
|
|
195
247
|
<script>
|
|
196
248
|
const humanTouch = document.querySelector<HTMLElement>('[data-human-touch]');
|
|
197
249
|
const humanTouchAudio = document.querySelector<HTMLAudioElement>('[data-human-touch-audio]');
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
const
|
|
250
|
+
const humanTouchToggles = document.querySelectorAll<HTMLButtonElement>('[data-human-touch-toggle]');
|
|
251
|
+
const humanTouchProgresses = document.querySelectorAll<HTMLElement>('[data-human-touch-progress]');
|
|
252
|
+
const humanTouchSeeks = document.querySelectorAll<HTMLElement>('[data-human-touch-seek]');
|
|
201
253
|
const humanTouchCurrent = document.querySelector<HTMLElement>('[data-human-touch-current]');
|
|
202
254
|
|
|
203
|
-
|
|
204
|
-
|
|
255
|
+
humanTouchSeeks.forEach((seek) => {
|
|
256
|
+
seek.addEventListener('click', (event) => {
|
|
257
|
+
if (!humanTouchAudio || !seek || !humanTouchAudio.duration) return;
|
|
205
258
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
259
|
+
const bounds = seek.getBoundingClientRect();
|
|
260
|
+
const ratio = Math.min(1, Math.max(0, (event.clientX - bounds.left) / bounds.width));
|
|
261
|
+
humanTouchAudio.currentTime = ratio * humanTouchAudio.duration;
|
|
262
|
+
});
|
|
209
263
|
});
|
|
210
264
|
|
|
211
265
|
const formatAudioTime = (seconds: number) => {
|
|
@@ -223,40 +277,50 @@ const { t } = Astro.props;
|
|
|
223
277
|
const currentTime = humanTouchAudio.currentTime || 0;
|
|
224
278
|
const progress = duration > 0 ? currentTime / duration * 100 : 0;
|
|
225
279
|
|
|
226
|
-
|
|
280
|
+
humanTouchProgresses.forEach((el) => {
|
|
281
|
+
el.style.inlineSize = `${progress}%`;
|
|
282
|
+
});
|
|
227
283
|
if (humanTouchCurrent) humanTouchCurrent.textContent = formatAudioTime(currentTime);
|
|
228
284
|
};
|
|
229
285
|
|
|
230
286
|
humanTouchAudio?.addEventListener('play', () => {
|
|
231
287
|
humanTouch?.classList.add('is-partying');
|
|
232
|
-
|
|
233
|
-
|
|
288
|
+
humanTouchToggles.forEach((btn) => {
|
|
289
|
+
btn.classList.add('is-playing');
|
|
290
|
+
btn.setAttribute('aria-label', btn.dataset.pauseLabel ?? '');
|
|
291
|
+
});
|
|
234
292
|
});
|
|
235
293
|
|
|
236
294
|
humanTouchAudio?.addEventListener('pause', () => {
|
|
237
295
|
humanTouch?.classList.remove('is-partying');
|
|
238
|
-
|
|
239
|
-
|
|
296
|
+
humanTouchToggles.forEach((btn) => {
|
|
297
|
+
btn.classList.remove('is-playing');
|
|
298
|
+
btn.setAttribute('aria-label', btn.dataset.playLabel ?? '');
|
|
299
|
+
});
|
|
240
300
|
});
|
|
241
301
|
|
|
242
302
|
humanTouchAudio?.addEventListener('ended', () => {
|
|
243
303
|
humanTouch?.classList.remove('is-partying');
|
|
244
|
-
|
|
245
|
-
|
|
304
|
+
humanTouchToggles.forEach((btn) => {
|
|
305
|
+
btn.classList.remove('is-playing');
|
|
306
|
+
btn.setAttribute('aria-label', btn.dataset.playLabel ?? '');
|
|
307
|
+
});
|
|
246
308
|
updatePlayer();
|
|
247
309
|
});
|
|
248
310
|
|
|
249
311
|
humanTouchAudio?.addEventListener('loadedmetadata', updatePlayer);
|
|
250
312
|
humanTouchAudio?.addEventListener('timeupdate', updatePlayer);
|
|
251
313
|
|
|
252
|
-
|
|
253
|
-
|
|
314
|
+
humanTouchToggles.forEach((btn) => {
|
|
315
|
+
btn.addEventListener('click', () => {
|
|
316
|
+
if (!humanTouchAudio) return;
|
|
254
317
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
318
|
+
if (humanTouchAudio.paused) {
|
|
319
|
+
void humanTouchAudio.play();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
259
322
|
|
|
260
|
-
|
|
323
|
+
humanTouchAudio.pause();
|
|
324
|
+
});
|
|
261
325
|
});
|
|
262
326
|
</script>
|
|
@@ -25,18 +25,27 @@ const { t } = Astro.props;
|
|
|
25
25
|
<slot name="title" />
|
|
26
26
|
<p class="team-hero-lead">{t.lead}</p>
|
|
27
27
|
</div>
|
|
28
|
-
<div
|
|
29
|
-
class="team-hero-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
<div class="team-hero-stage">
|
|
29
|
+
<div class="team-hero-window" aria-label={t.stageLabel}>
|
|
30
|
+
<div class="team-hero-window-header">
|
|
31
|
+
<div class="team-hero-window-dots">
|
|
32
|
+
<span class="window-dot red"></span>
|
|
33
|
+
<span class="window-dot yellow"></span>
|
|
34
|
+
<span class="window-dot green"></span>
|
|
35
|
+
</div>
|
|
36
|
+
<span class="team-hero-window-title">gamebob_studio.webp</span>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="team-hero-window-content">
|
|
39
|
+
<img
|
|
40
|
+
class="team-hero-scene"
|
|
41
|
+
src={heroSceneUrl.src}
|
|
42
|
+
width={heroSceneUrl.width}
|
|
43
|
+
height={heroSceneUrl.height}
|
|
44
|
+
alt={t.sceneAlt}
|
|
45
|
+
loading="eager"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
40
49
|
</div>
|
|
41
50
|
</div>
|
|
42
51
|
</section>
|
|
@@ -2,7 +2,6 @@ import type { LandingEntry } from '../../types';
|
|
|
2
2
|
|
|
3
3
|
const assetsBasePath = '/landings/team/assets';
|
|
4
4
|
const cssPath = '/landings/team/team.css';
|
|
5
|
-
const openGraphImage = `${assetsBasePath}/gamebob-team-hero.webp`;
|
|
6
5
|
|
|
7
6
|
export const teamEntry: LandingEntry = {
|
|
8
7
|
id: 'team',
|
|
@@ -11,13 +10,24 @@ export const teamEntry: LandingEntry = {
|
|
|
11
10
|
cssPath,
|
|
12
11
|
},
|
|
13
12
|
seo: {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
image: openGraphImage,
|
|
17
|
-
openGraphImage,
|
|
13
|
+
image: `${assetsBasePath}/team-og.webp`,
|
|
14
|
+
openGraphImage: `${assetsBasePath}/team-og.webp`,
|
|
18
15
|
},
|
|
19
16
|
i18n: {
|
|
20
|
-
en: () => import('./i18n/en').then((m) => m.cardContent),
|
|
21
17
|
es: () => import('./i18n/es').then((m) => m.cardContent),
|
|
18
|
+
en: () => import('./i18n/en').then((m) => m.cardContent),
|
|
19
|
+
fr: () => import('./i18n/fr').then((m) => m.cardContent),
|
|
20
|
+
de: () => import('./i18n/de').then((m) => m.cardContent),
|
|
21
|
+
it: () => import('./i18n/it').then((m) => m.cardContent),
|
|
22
|
+
pt: () => import('./i18n/pt').then((m) => m.cardContent),
|
|
23
|
+
nl: () => import('./i18n/nl').then((m) => m.cardContent),
|
|
24
|
+
sv: () => import('./i18n/sv').then((m) => m.cardContent),
|
|
25
|
+
pl: () => import('./i18n/pl').then((m) => m.cardContent),
|
|
26
|
+
id: () => import('./i18n/id').then((m) => m.cardContent),
|
|
27
|
+
tr: () => import('./i18n/tr').then((m) => m.cardContent),
|
|
28
|
+
ru: () => import('./i18n/ru').then((m) => m.cardContent),
|
|
29
|
+
ja: () => import('./i18n/ja').then((m) => m.cardContent),
|
|
30
|
+
ko: () => import('./i18n/ko').then((m) => m.cardContent),
|
|
31
|
+
zh: () => import('./i18n/zh').then((m) => m.cardContent),
|
|
22
32
|
}
|
|
23
33
|
};
|