171 lines
4.7 KiB
TypeScript
171 lines
4.7 KiB
TypeScript
import { Main } from "./common.tsx";
|
||
import { Html, debug_render, render } from "./html.ts";
|
||
import { Component } from "./jsx/jsx-runtime.ts";
|
||
|
||
const peopleify = (...people: string[]): string[] =>
|
||
people.map(p => `${p} people`);
|
||
|
||
const animation_length = (num_items: number): number => /*num_items / 5*/ 3;
|
||
|
||
const wheel_style = (num_items: number): string =>
|
||
`transform: translateY(calc(2rem * -${num_items})); animation: ${animation_length(
|
||
num_items
|
||
)}s ease-in-out reverse none running spin;`;
|
||
|
||
const get_delays = (...lengths: number[]): number[] => {
|
||
let out = [0];
|
||
for (const l of lengths) {
|
||
out.push((out.at(-1) ?? 0) + animation_length(l));
|
||
}
|
||
return out;
|
||
};
|
||
|
||
const Wheel: Component = ({ items }, _) => (
|
||
<details class="wheel">
|
||
<summary>
|
||
{...items.map((i: string) => <div class="wheel-item">{i}</div>)}
|
||
</summary>
|
||
<div class="wheel-inner" style={wheel_style(items.length)}>
|
||
{/* <div class="wheel-item empty"></div> */}
|
||
{...items.map((item: string, i: number) => (
|
||
<div
|
||
class={`wheel-item ${i + 1 == items.length ? "last" : ""}`}
|
||
>
|
||
{item}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</details>
|
||
);
|
||
|
||
function slices<T>(arr: T[]): T[][] {
|
||
return arr.map((_, i) => arr.slice(0, i));
|
||
}
|
||
|
||
const MultiWheel: Component = ({ items }, _) => (
|
||
<div class="multiwheel">
|
||
{slices(items).map(items => (
|
||
<Wheel items={items} />
|
||
))}
|
||
</div>
|
||
);
|
||
|
||
// i'll probably just hardcode the delays... lame but w/e
|
||
// nope
|
||
// it would be possible to have it so the final text is actually properyly selectable maybe but eh
|
||
const Take: Component = ({ subjects, objects, adjectives }, _) => (
|
||
<div class="take">
|
||
<MultiWheel items={subjects} /> <div class="bridge">who eat</div>{" "}
|
||
<MultiWheel items={objects} /> <div class="bridge">are</div>{" "}
|
||
<MultiWheel items={adjectives} />
|
||
</div>
|
||
);
|
||
|
||
const Checkmark: Component = () => (
|
||
<img
|
||
class="checkmark"
|
||
src="https://static.pyrope.net/white-twitter-checkmark.png"
|
||
alt="the old, white twitter verified checkmark"
|
||
/>
|
||
);
|
||
|
||
const Author: Component = () => (
|
||
<div class="author">
|
||
<img
|
||
class="pfp"
|
||
src="https://static.pyrope.net/phoebe_bridgers-pfp.jpg"
|
||
alt="a picture of a blonde, white woman wearing a black coat and looking at her phone. presumably phoebe bridgers"
|
||
/>
|
||
<div class="names">
|
||
<div class="display-name">
|
||
traitor joe <Checkmark />
|
||
</div>
|
||
<div class="username">@phoebe_bridgers</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
|
||
const Info: Component = () => (
|
||
<div class="info">
|
||
<span class="time">10:02 PM</span> ·{" "}
|
||
<span class="date">Feb 20, 2021</span> ·{" "}
|
||
<span class="device">Twitter for iPhone</span>
|
||
</div>
|
||
);
|
||
|
||
const Stats: Component = () => (
|
||
<div class="stats">
|
||
<span class="retweets">
|
||
<span class="stat">3,228</span> Retweets
|
||
</span>
|
||
<span class="quote-tweets">
|
||
<span class="stat">803</span> Quote Tweets
|
||
</span>
|
||
<span class="likes">
|
||
<span class="stat">39.3K</span> Likes
|
||
</span>
|
||
</div>
|
||
);
|
||
|
||
// might want to have the final item be seperate
|
||
// turned out to be unnecessary
|
||
debug_render(
|
||
<Main>
|
||
<Author />
|
||
<Take
|
||
subjects={peopleify(
|
||
"poor",
|
||
"fat",
|
||
"dumb",
|
||
"tall",
|
||
"short",
|
||
"poor",
|
||
"fat",
|
||
"dumb",
|
||
"tall",
|
||
"hot"
|
||
)}
|
||
objects={[
|
||
"apples",
|
||
"bread",
|
||
"pasta",
|
||
"candy",
|
||
"rice",
|
||
"beans",
|
||
"apples",
|
||
"bread",
|
||
"candy",
|
||
"rice",
|
||
"beans",
|
||
"apples",
|
||
"bread",
|
||
"pasta",
|
||
"candy",
|
||
"rice",
|
||
"croissants",
|
||
]}
|
||
adjectives={[
|
||
"vibes",
|
||
"mean",
|
||
"dumb",
|
||
"cool",
|
||
"hot",
|
||
"stupid",
|
||
"funny",
|
||
"vibes",
|
||
"mean",
|
||
"dumb",
|
||
"cool",
|
||
"hot",
|
||
"stupid",
|
||
"dangerous",
|
||
]}
|
||
/>
|
||
<Info />
|
||
<hr />
|
||
<Stats />
|
||
<hr />
|
||
<div class="bottom"></div>
|
||
</Main>
|
||
);
|