Compare commits

..

3 Commits

Author SHA1 Message Date
Derek 6d4bc1dac1 Better event cards! 2022-02-26 22:59:03 -07:00
Derek 3149a48913 Add some handy aliases 2022-02-26 21:37:32 -07:00
Derek 0db073f651 Fix bug where ws listeners would duplicate 2022-02-21 18:08:22 -07:00
30 changed files with 807 additions and 412 deletions

12
config-overrides.js Normal file
View File

@ -0,0 +1,12 @@
const {
override,
addWebpackAlias,
} = require("customize-cra");
const path = require("path");
module.exports = override(
addWebpackAlias({
'@': path.resolve(__dirname, 'src/'),
'@components': path.resolve(__dirname, 'src/components'),
}),
);

135
package-lock.json generated
View File

@ -11,11 +11,15 @@
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"canvas-confetti": "^1.5.1",
"customize-cra": "^1.0.0",
"polished": "^4.1.3",
"react": "^17.0.2",
"react-app-rewired": "^2.2.1",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"react-transition-group": "^4.4.2",
"styled-components": "^5.3.3"
}
},
@ -4895,6 +4899,15 @@
"url": "https://opencollective.com/browserslist"
}
},
"node_modules/canvas-confetti": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.5.1.tgz",
"integrity": "sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==",
"funding": {
"type": "donate",
"url": "https://www.paypal.me/kirilvatev"
}
},
"node_modules/case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@ -5718,6 +5731,19 @@
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
},
"node_modules/csstype": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
"integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
},
"node_modules/customize-cra": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz",
"integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==",
"dependencies": {
"lodash.flow": "^3.5.0"
}
},
"node_modules/damerau-levenshtein": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -6009,6 +6035,15 @@
"utila": "~0.4"
}
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
@ -10796,6 +10831,11 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"node_modules/lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
"integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -13140,6 +13180,28 @@
"node": ">=14"
}
},
"node_modules/react-app-rewired": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
"dependencies": {
"semver": "^5.6.0"
},
"bin": {
"react-app-rewired": "bin/index.js"
},
"peerDependencies": {
"react-scripts": ">=2.1.3"
}
},
"node_modules/react-app-rewired/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@ -13384,6 +13446,21 @@
}
}
},
"node_modules/react-transition-group": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
"integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
@ -19702,6 +19779,11 @@
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001294.tgz",
"integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g=="
},
"canvas-confetti": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.5.1.tgz",
"integrity": "sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg=="
},
"case-sensitive-paths-webpack-plugin": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
@ -20302,6 +20384,19 @@
}
}
},
"csstype": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz",
"integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA=="
},
"customize-cra": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/customize-cra/-/customize-cra-1.0.0.tgz",
"integrity": "sha512-DbtaLuy59224U+xCiukkxSq8clq++MOtJ1Et7LED1fLszWe88EoblEYFBJ895sB1mC6B4uu3xPT/IjClELhMbA==",
"requires": {
"lodash.flow": "^3.5.0"
}
},
"damerau-levenshtein": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz",
@ -20529,6 +20624,15 @@
"utila": "~0.4"
}
},
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
@ -23984,6 +24088,11 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
"lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/lodash.flow/-/lodash.flow-3.5.0.tgz",
"integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -25530,6 +25639,21 @@
"whatwg-fetch": "^3.6.2"
}
},
"react-app-rewired": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz",
"integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==",
"requires": {
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@ -25713,6 +25837,17 @@
"workbox-webpack-plugin": "^6.4.1"
}
},
"react-transition-group": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
"integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==",
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",

View File

@ -6,18 +6,21 @@
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"canvas-confetti": "^1.5.1",
"customize-cra": "^1.0.0",
"polished": "^4.1.3",
"react": "^17.0.2",
"react-app-rewired": "^2.2.1",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.1",
"react-scripts": "5.0.0",
"react-transition-group": "^4.4.2",
"styled-components": "^5.3.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
},
"eslintConfig": {
"extends": [

View File

@ -0,0 +1,42 @@
import { useRef, useCallback, useEffect } from 'react';
import confetti from 'canvas-confetti';
const commonOptions = (tier) => ({
ticks: 400,
particleCount: 25 * tier,
});
const delay = 1000;
export default function useZoom(count, tier) {
const canvasRef = useRef();
const doAnimation = useCallback(() => {
const confettiCannon = confetti.create(canvasRef.current, { useWorker: true });
let remainCount = count;
const pop = () => {
confettiCannon({
origin: { x: 0, y: 1 },
angle: 45,
drift: -0.5,
...commonOptions(tier),
});
confettiCannon({
origin: { x: 1, y: 1 },
angle: 135,
drift: 0.5,
...commonOptions(tier),
});
remainCount -= 1;
if (remainCount > 0) {
setTimeout(pop, Math.max(delay / remainCount, 200));
}
};
pop();
}, [canvasRef]);
return [canvasRef, doAnimation];
}

79
src/animations/useZoom.js Normal file
View File

@ -0,0 +1,79 @@
import { useRef, useCallback, useEffect } from 'react';
import XTERM_COLORS from '../xterm';
const RAIDERS_PER_SECOND = 5;
const MAX_SECONDS = 10;
const FPS_CAP = 120;
const LINE_HEIGHT = 5;
const LINE_WIDTH = 700;
// Speed is in "seconds to cross card width"
const START_SPEED = 0.06;
const MIN_SPEED = 0.2;
export default function useZoom(count) {
const canvasRef = useRef();
const doAnimation = useCallback(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
const height = canvas.height;
const width = canvas.width;
let delay = count / RAIDERS_PER_SECOND;
if (delay > MAX_SECONDS) { delay = MAX_SECONDS };
const lines = Array(count).fill(null).map(() => ({
y: Math.floor(Math.random() * height),
x: width + LINE_WIDTH,
offset: Math.floor(Math.random() * delay * 1000),
speed: width / START_SPEED,
decel: Math.random() * (width / (MIN_SPEED - START_SPEED)),
color: XTERM_COLORS[118 + Math.floor(Math.random() * 24)],
}));
const fpsInterval = FPS_CAP / 1000;
const start = Date.now();
let then = Date.now();
let now, dt, elapsed;
let animationFrameId = requestAnimationFrame(animStep);
function animStep() {
ctx.clearRect(0, 0, width, height);
animationFrameId = requestAnimationFrame(animStep);
let alive = false;
now = Date.now();
dt = now - then;
if (dt < fpsInterval) return;
then = now - (dt % fpsInterval);
elapsed = now - start;
dt = dt / 1000;
lines.forEach((line, i) => {
if (line.x < 0) { return; }
alive = true;
if (line.offset > elapsed) return;
const nextX = line.x - (dt * line.speed);
ctx.beginPath();
ctx.lineWidth = LINE_HEIGHT;
ctx.strokeStyle = line.color;
ctx.moveTo(line.x, line.y);
ctx.lineTo(nextX - LINE_WIDTH, line.y);
ctx.stroke();
ctx.closePath();
line.x = nextX;
if (line.speed - line.decel > (width / MIN_SPEED)) {
line.speed -= line.decel;
}
});
if (!alive) {
cancelAnimationFrame(animationFrameId);
ctx.clearRect(0, 0, width, height);
}
};
}, [canvasRef, count]);
return [canvasRef, doAnimation];
}

View File

@ -5,14 +5,6 @@ import ChatLog from '../chat-log';
const maxsize = 25;
const retryLoop = async (func) => {
try {
return await func();
} catch (error) {
retryLoop(func);
}
};
function App() {
const [messages, setMessages] = useState(Array(maxsize).fill(null));
const query = useQuery();
@ -21,12 +13,16 @@ function App() {
useEffect(() => {
const websocketAddress = query.get('ws') ?? 'ws://127.0.0.1:8080';
const attemptConnect = async () => {
const ws = new WebSocket(websocketAddress);
ws.addEventListener('message', onEvent);
ws.addEventListener('error', onDiscconect);
ws.addEventListener('close', onDiscconect);
socket.current = ws
const attemptConnect = () => {
try {
const ws = new WebSocket(websocketAddress);
socket.current = ws;
ws.addEventListener('message', onEvent);
ws.addEventListener('error', onDiscconect);
ws.addEventListener('close', onDiscconect);
} catch (error) {
setTimeout(attemptConnect, 100);
}
};
const onEvent = function (event) {
@ -38,16 +34,20 @@ function App() {
});
};
const onDiscconect = function (event) {
retryLoop(attemptConnect);
}
socket.current?.removeEventListener('message', onEvent);
socket.current?.removeEventListener('error', onDiscconect);
socket.current?.removeEventListener('close', onDiscconect);
socket.current?.close();
attemptConnect();
};
onDiscconect();
attemptConnect();
return () => {
socket.current.removeEventListener('message', onEvent);
socket.current.removeEventListener('error', onDiscconect);
socket.current.removeEventListener('close', onDiscconect);
socket.current.close();
socket.current?.removeEventListener('message', onEvent);
socket.current?.removeEventListener('error', onDiscconect);
socket.current?.removeEventListener('close', onDiscconect);
socket.current?.close();
}
}, [socket, maxsize, setMessages, query]);

View File

@ -1,9 +1,9 @@
import { useRef, useEffect } from 'react';
import { useRef, useLayoutEffect } from 'react';
import PropTypes from 'prop-types';
import Message from './message';
import Raid from './raid';
import Subscription from './sub';
import Follow from './follow';
import Raid from './event-card/raid';
import Subscription from './event-card/sub';
import Follow from './event-card/follow';
import { List, Spacer } from './chat-log.style';
@ -31,7 +31,7 @@ function ChatLog({
return [event, renderer, deemphasize];
}).filter(([event, renderer, deemphasize]) => !!renderer);
useEffect(() => {
useLayoutEffect(() => {
listRef.current.scrollTop = -1;
}, [renderableEvents]);

View File

@ -0,0 +1,31 @@
import styled, { css } from 'styled-components';
import XTERM_COLORS from '../../../xterm';
export const Root = styled.div`
width: 100%;
position: relative;
background-color: ${XTERM_COLORS[236]};
text-align: center;
`;
export const Foreground = styled.div`
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 1;
padding: 12px;
span {
text-shadow: 0 0 4px rgba(0, 0, 0, 60%);
}
`;
export const Background = styled.div`
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
`;

View File

@ -0,0 +1,16 @@
import React from 'react';
import { Root, Foreground, Channel } from './follow.style';
const Follow = ({
user_name,
}) => (
<Root>
<Foreground>
<Channel>{user_name}</Channel>
<span>joins the roost~</span>
</Foreground>
</Root>
);
export default Follow;

View File

@ -0,0 +1,8 @@
import styled from 'styled-components';
import XTERM_COLORS from '@/xterm';
export { Root, Background, Foreground } from '../common.styles';
export const Channel = styled.span`
color: ${XTERM_COLORS[6]};
`;

View File

@ -0,0 +1,26 @@
import React, { useRef, useCallback, useEffect } from 'react';
import { Root, Foreground, Background, Channel } from './raid.style';
import Canvas from '@components/responsive-canvas';
import useZoom from '@/animations/useZoom';
const Raid = ({
from_channel, user_count,
}) => {
const [canvasRef, doAnimation] = useZoom(user_count);
return (
<Root>
<Foreground>
<Channel>{from_channel}</Channel>
<span>soars in with their {user_count}-odd flock!</span>
</Foreground>
<Background>
<Canvas ref={canvasRef} onResize={doAnimation} />
</Background>
</Root>
);
};
export default Raid;

View File

@ -0,0 +1,9 @@
import styled from 'styled-components';
import XTERM_COLORS from '@/xterm';
export { Root, Background, Foreground } from '../common.styles';
export const Channel = styled.span`
color: ${XTERM_COLORS[223]};
font-size: 28px;
`;

View File

@ -0,0 +1,47 @@
import React from 'react';
import {
Root, Foreground, Background,
Channel, Streak,
} from './sub.style';
import Canvas from '@components/responsive-canvas';
import useConfetti from '@/animations/useConfetti';
const Sub = ({
user_name, gifted_to, streak,
}) => {
const [canvasRef, doAnimation] = useConfetti(gifted_to?.length ?? 1, 1);
let msg;
if (gifted_to?.length) {
msg = (
<>
<Channel>{user_name}</Channel>
<span>gifted {gifted_to.length} subscriptions!</span>
</>
);
} else {
msg = (
<>
<Channel>{user_name}</Channel>
<span>has subscribed!</span>
{streak > 1 ? (
<Streak>{streak} times and counting!</Streak>
) : null}
</>
);
}
return (
<Root>
<Foreground>{msg}</Foreground>
<Background>
<Canvas ref={canvasRef} onResize={doAnimation} />
</Background>
</Root>
);
};
export default Sub;

View File

@ -0,0 +1,14 @@
import styled from 'styled-components';
import XTERM_COLORS from '@/xterm';
export { Root, Background, Foreground } from '../common.styles';
export const Channel = styled.span`
color: ${XTERM_COLORS[6]};
font-size: 28px;
`;
export const Streak = styled.span`
color: ${XTERM_COLORS[247]};
font-size: 16px;
`;

View File

@ -1,15 +0,0 @@
import React from 'react';
import { Root, Channel } from './follow.style';
const Follow = ({
user_name,
}) => (
<Root>
<span>Thank you</span>
<Channel>{user_name}</Channel>
<span>for the follow~</span>
</Root>
);
export default Follow;

View File

@ -1,18 +0,0 @@
import styled from 'styled-components';
import { XTERM_COLORS } from '../../../index.style';
export const Root = styled.div`
width: 100%;
display: flex;
flex-direction: row;
flex-align: center;
justify-content: center;
background-color: ${XTERM_COLORS[255]};
padding: 8px;
gap: 1em;
`;
export const Channel = styled.span`
color: ${XTERM_COLORS[6]};
`;

View File

@ -1,7 +1,7 @@
import { useMemo } from 'react';
import PropTypes from 'prop-types';
import { XTERM_COLORS } from '../../../index.style';
import XTERM_COLORS from '../../../xterm';
import { Wrapper, Author, Body, Emote, Attachments } from './message.style';

View File

@ -1,6 +1,6 @@
import styled, { css } from 'styled-components';
import { toColorString, getContrast, rgbToColorString } from 'polished';
import { XTERM_COLORS } from '../../../index.style';
import XTERM_COLORS from '../../../xterm';
export const Author = styled.div`
width: fit-content;
@ -69,18 +69,6 @@ export const Wrapper = styled.div`
flex-direction: column;
width: 100%;
overflow-wrap: break-word;
@keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
animation: 420s fade cubic-bezier(.6,.04,.98,.34);
animation-fill-mode: forwards;
`;
export const Attachments = styled.div`

View File

@ -1,14 +0,0 @@
import React from 'react';
import { Root, Channel } from './raid.style';
const Raid = ({
from_channel, user_count,
}) => (
<Root>
<Channel>{from_channel}</Channel>
<span>has raided with a party of {user_count}!</span>
</Root>
);
export default Raid;

View File

@ -1,18 +0,0 @@
import styled from 'styled-components';
import { XTERM_COLORS } from '../../../index.style';
export const Root = styled.div`
width: 100%;
display: flex;
flex-direction: row;
flex-align: center;
justify-content: center;
background-color: ${XTERM_COLORS[255]};
padding: 8px;
gap: 1em;
`;
export const Channel = styled.span`
color: ${XTERM_COLORS[6]};
`;

View File

@ -1,26 +0,0 @@
import React from 'react';
import { Root, Channel } from './sub.style';
const Raid = ({
user_name, gifted_to,
}) => {
if (gifted_to?.length) {
return (
<Root>
<Channel>{user_name}</Channel>
<span>just gifted {gifted_to.length} subscriptions!</span>
</Root>
);
}
return (
<Root>
<span>Thank you</span>
<Channel>{user_name}</Channel>
<span>for the subscription!</span>
</Root>
);
};
export default Raid;

View File

@ -1,18 +0,0 @@
import styled from 'styled-components';
import { XTERM_COLORS } from '../../../index.style';
export const Root = styled.div`
width: 100%;
display: flex;
flex-direction: row;
flex-align: center;
justify-content: center;
background-color: ${XTERM_COLORS[255]};
padding: 8px;
gap: 1em;
`;
export const Channel = styled.span`
color: ${XTERM_COLORS[6]};
`;

View File

@ -0,0 +1,39 @@
/* Copyright 2018 Ross Zurowski
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
// via https://github.com/rosszurowski/react-responsive-canvas/blob/master/src/get-size.js
const parseNumber = prop => parseFloat(prop) || 0;
const getSize = (el: Element) => {
if (el === window || el === document.body) {
return [window.innerWidth, window.innerHeight];
}
let temporary = false;
if (!el.parentNode && document.body) {
temporary = true;
document.body.appendChild(el);
}
const rect = el.getBoundingClientRect();
const styles = getComputedStyle(el);
const height =
(rect.height | 0) +
parseNumber(styles.getPropertyValue('margin-top')) +
parseNumber(styles.getPropertyValue('margin-bottom'));
const width =
(rect.width | 0) +
parseNumber(styles.getPropertyValue('margin-left')) +
parseNumber(styles.getPropertyValue('margin-right'));
if (temporary && document.body) {
document.body.removeChild(el);
}
return [width, height];
};
export default getSize;

View File

@ -0,0 +1 @@
export { default } from './responsive-canvas';

View File

@ -0,0 +1,56 @@
import React, {
useEffect, useState, useCallback, useRef, useImperativeHandle, forwardRef,
} from 'react';
import PropTypes from 'prop-types';
import getSize from './get-size';
const ResponsiveCanvas = forwardRef(({ scale, onResize }, ref) => {
const [width, setWidth] = useState(null);
const [height, setHeight] = useState(null);
const canvasRef = useRef();
useImperativeHandle(ref, () => canvasRef.current);
const handleResize = useCallback(() => {
const parent = canvasRef.current.parentElement;
if (!parent) {
return;
}
const [width, height] = getSize(parent);
setWidth(width);
setHeight(height);
}, [canvasRef]);
useEffect(() => {
window.addEventListener('resize', handleResize, false);
handleResize();
return () => window.removeEventListener('resize', handleResize, false);
}, [handleResize]);
useEffect(() => {
if (onResize && width !== null && height !== null) onResize();
}, [width, height, onResize]);
return (
<canvas
ref={canvasRef}
width={width * scale}
height={height * scale}
style={{ width, height }}
/>
);
});
ResponsiveCanvas.propTypes = {
onResize: PropTypes.func,
scale: PropTypes.number,
};
const defaultScale = typeof window !== 'undefined' ? window.devicePixelRatio : 1;
ResponsiveCanvas.defaultProps = {
onResize: undefined,
scale: defaultScale,
};
export default ResponsiveCanvas;

View File

@ -62,262 +62,3 @@ export const GlobalStyle = createGlobalStyle`
overflow: none;
}
`;
export const XTERM_COLORS = [
rgb(0, 0, 0), // #000000
rgb(128, 0, 0), // #800000
rgb(0, 128, 0), // #008000
rgb(128, 128, 0), // #808000
rgb(0, 0, 128), // #000080
rgb(128, 0, 128), // #800080
rgb(0, 128, 128), // #008080
rgb(192, 192, 192), // #c0c0c0
rgb(128, 128, 128), // #808080
rgb(255, 0, 0), // #ff0000
rgb(0, 255, 0), // #00ff00
rgb(255, 255, 0), // #ffff00
rgb(0, 0, 255), // #0000ff
rgb(255, 0, 255), // #ff00ff
rgb(0, 255, 255), // #00ffff
rgb(255, 255, 255), // #ffffff
rgb(0, 0, 0), // #000000
rgb(0, 0, 95), // #00005f
rgb(0, 0, 135), // #000087
rgb(0, 0, 175), // #0000af
rgb(0, 0, 215), // #0000d7
rgb(0, 0, 255), // #0000ff
rgb(0, 95, 0), // #005f00
rgb(0, 95, 95), // #005f5f
rgb(0, 95, 135), // #005f87
rgb(0, 95, 175), // #005faf
rgb(0, 95, 215), // #005fd7
rgb(0, 95, 255), // #005fff
rgb(0, 135, 0), // #008700
rgb(0, 135, 95), // #00875f
rgb(0, 135, 135), // #008787
rgb(0, 135, 175), // #0087af
rgb(0, 135, 215), // #0087d7
rgb(0, 135, 255), // #0087ff
rgb(0, 175, 0), // #00af00
rgb(0, 175, 95), // #00af5f
rgb(0, 175, 135), // #00af87
rgb(0, 175, 175), // #00afaf
rgb(0, 175, 215), // #00afd7
rgb(0, 175, 255), // #00afff
rgb(0, 215, 0), // #00d700
rgb(0, 215, 95), // #00d75f
rgb(0, 215, 135), // #00d787
rgb(0, 215, 175), // #00d7af
rgb(0, 215, 215), // #00d7d7
rgb(0, 215, 255), // #00d7ff
rgb(0, 255, 0), // #00ff00
rgb(0, 255, 95), // #00ff5f
rgb(0, 255, 135), // #00ff87
rgb(0, 255, 175), // #00ffaf
rgb(0, 255, 215), // #00ffd7
rgb(0, 255, 255), // #00ffff
rgb(95, 0, 0), // #5f0000
rgb(95, 0, 95), // #5f005f
rgb(95, 0, 135), // #5f0087
rgb(95, 0, 175), // #5f00af
rgb(95, 0, 215), // #5f00d7
rgb(95, 0, 255), // #5f00ff
rgb(95, 95, 0), // #5f5f00
rgb(95, 95, 95), // #5f5f5f
rgb(95, 95, 135), // #5f5f87
rgb(95, 95, 175), // #5f5faf
rgb(95, 95, 215), // #5f5fd7
rgb(95, 95, 255), // #5f5fff
rgb(95, 135, 0), // #5f8700
rgb(95, 135, 95), // #5f875f
rgb(95, 135, 135), // #5f8787
rgb(95, 135, 175), // #5f87af
rgb(95, 135, 215), // #5f87d7
rgb(95, 135, 255), // #5f87ff
rgb(95, 175, 0), // #5faf00
rgb(95, 175, 95), // #5faf5f
rgb(95, 175, 135), // #5faf87
rgb(95, 175, 175), // #5fafaf
rgb(95, 175, 215), // #5fafd7
rgb(95, 175, 255), // #5fafff
rgb(95, 215, 0), // #5fd700
rgb(95, 215, 95), // #5fd75f
rgb(95, 215, 135), // #5fd787
rgb(95, 215, 175), // #5fd7af
rgb(95, 215, 215), // #5fd7d7
rgb(95, 215, 255), // #5fd7ff
rgb(95, 255, 0), // #5fff00
rgb(95, 255, 95), // #5fff5f
rgb(95, 255, 135), // #5fff87
rgb(95, 255, 175), // #5fffaf
rgb(95, 255, 215), // #5fffd7
rgb(95, 255, 255), // #5fffff
rgb(135, 0, 0), // #870000
rgb(135, 0, 95), // #87005f
rgb(135, 0, 135), // #870087
rgb(135, 0, 175), // #8700af
rgb(135, 0, 215), // #8700d7
rgb(135, 0, 255), // #8700ff
rgb(135, 95, 0), // #875f00
rgb(135, 95, 95), // #875f5f
rgb(135, 95, 135), // #875f87
rgb(135, 95, 175), // #875faf
rgb(135, 95, 215), // #875fd7
rgb(135, 95, 255), // #875fff
rgb(135, 135, 0), // #878700
rgb(135, 135, 95), // #87875f
rgb(135, 135, 135), // #878787
rgb(135, 135, 175), // #8787af
rgb(135, 135, 215), // #8787d7
rgb(135, 135, 255), // #8787ff
rgb(135, 175, 0), // #87af00
rgb(135, 175, 95), // #87af5f
rgb(135, 175, 135), // #87af87
rgb(135, 175, 175), // #87afaf
rgb(135, 175, 215), // #87afd7
rgb(135, 175, 255), // #87afff
rgb(135, 215, 0), // #87d700
rgb(135, 215, 95), // #87d75f
rgb(135, 215, 135), // #87d787
rgb(135, 215, 175), // #87d7af
rgb(135, 215, 215), // #87d7d7
rgb(135, 215, 255), // #87d7ff
rgb(135, 255, 0), // #87ff00
rgb(135, 255, 95), // #87ff5f
rgb(135, 255, 135), // #87ff87
rgb(135, 255, 175), // #87ffaf
rgb(135, 255, 215), // #87ffd7
rgb(135, 255, 255), // #87ffff
rgb(175, 0, 0), // #af0000
rgb(175, 0, 95), // #af005f
rgb(175, 0, 135), // #af0087
rgb(175, 0, 175), // #af00af
rgb(175, 0, 215), // #af00d7
rgb(175, 0, 255), // #af00ff
rgb(175, 95, 0), // #af5f00
rgb(175, 95, 95), // #af5f5f
rgb(175, 95, 135), // #af5f87
rgb(175, 95, 175), // #af5faf
rgb(175, 95, 215), // #af5fd7
rgb(175, 95, 255), // #af5fff
rgb(175, 135, 0), // #af8700
rgb(175, 135, 95), // #af875f
rgb(175, 135, 135), // #af8787
rgb(175, 135, 175), // #af87af
rgb(175, 135, 215), // #af87d7
rgb(175, 135, 255), // #af87ff
rgb(175, 175, 0), // #afaf00
rgb(175, 175, 95), // #afaf5f
rgb(175, 175, 135), // #afaf87
rgb(175, 175, 175), // #afafaf
rgb(175, 175, 215), // #afafd7
rgb(175, 175, 255), // #afafff
rgb(175, 215, 0), // #afd700
rgb(175, 215, 95), // #afd75f
rgb(175, 215, 135), // #afd787
rgb(175, 215, 175), // #afd7af
rgb(175, 215, 215), // #afd7d7
rgb(175, 215, 255), // #afd7ff
rgb(175, 255, 0), // #afff00
rgb(175, 255, 95), // #afff5f
rgb(175, 255, 135), // #afff87
rgb(175, 255, 175), // #afffaf
rgb(175, 255, 215), // #afffd7
rgb(175, 255, 255), // #afffff
rgb(215, 0, 0), // #d70000
rgb(215, 0, 95), // #d7005f
rgb(215, 0, 135), // #d70087
rgb(215, 0, 175), // #d700af
rgb(215, 0, 215), // #d700d7
rgb(215, 0, 255), // #d700ff
rgb(215, 95, 0), // #d75f00
rgb(215, 95, 95), // #d75f5f
rgb(215, 95, 135), // #d75f87
rgb(215, 95, 175), // #d75faf
rgb(215, 95, 215), // #d75fd7
rgb(215, 95, 255), // #d75fff
rgb(215, 135, 0), // #d78700
rgb(215, 135, 95), // #d7875f
rgb(215, 135, 135), // #d78787
rgb(215, 135, 175), // #d787af
rgb(215, 135, 215), // #d787d7
rgb(215, 135, 255), // #d787ff
rgb(215, 175, 0), // #d7af00
rgb(215, 175, 95), // #d7af5f
rgb(215, 175, 135), // #d7af87
rgb(215, 175, 175), // #d7afaf
rgb(215, 175, 215), // #d7afd7
rgb(215, 175, 255), // #d7afff
rgb(215, 215, 0), // #d7d700
rgb(215, 215, 95), // #d7d75f
rgb(215, 215, 135), // #d7d787
rgb(215, 215, 175), // #d7d7af
rgb(215, 215, 215), // #d7d7d7
rgb(215, 215, 255), // #d7d7ff
rgb(215, 255, 0), // #d7ff00
rgb(215, 255, 95), // #d7ff5f
rgb(215, 255, 135), // #d7ff87
rgb(215, 255, 175), // #d7ffaf
rgb(215, 255, 215), // #d7ffd7
rgb(215, 255, 255), // #d7ffff
rgb(255, 0, 0), // #ff0000
rgb(255, 0, 95), // #ff005f
rgb(255, 0, 135), // #ff0087
rgb(255, 0, 175), // #ff00af
rgb(255, 0, 215), // #ff00d7
rgb(255, 0, 255), // #ff00ff
rgb(255, 95, 0), // #ff5f00
rgb(255, 95, 95), // #ff5f5f
rgb(255, 95, 135), // #ff5f87
rgb(255, 95, 175), // #ff5faf
rgb(255, 95, 215), // #ff5fd7
rgb(255, 95, 255), // #ff5fff
rgb(255, 135, 0), // #ff8700
rgb(255, 135, 95), // #ff875f
rgb(255, 135, 135), // #ff8787
rgb(255, 135, 175), // #ff87af
rgb(255, 135, 215), // #ff87d7
rgb(255, 135, 255), // #ff87ff
rgb(255, 175, 0), // #ffaf00
rgb(255, 175, 95), // #ffaf5f
rgb(255, 175, 135), // #ffaf87
rgb(255, 175, 175), // #ffafaf
rgb(255, 175, 215), // #ffafd7
rgb(255, 175, 255), // #ffafff
rgb(255, 215, 0), // #ffd700
rgb(255, 215, 95), // #ffd75f
rgb(255, 215, 135), // #ffd787
rgb(255, 215, 175), // #ffd7af
rgb(255, 215, 215), // #ffd7d7
rgb(255, 215, 255), // #ffd7ff
rgb(255, 255, 0), // #ffff00
rgb(255, 255, 95), // #ffff5f
rgb(255, 255, 135), // #ffff87
rgb(255, 255, 175), // #ffffaf
rgb(255, 255, 215), // #ffffd7
rgb(255, 255, 255), // #ffffff
rgb(8, 8, 8), // #080808
rgb(18, 18, 18), // #121212
rgb(28, 28, 28), // #1c1c1c
rgb(38, 38, 38), // #262626
rgb(48, 48, 48), // #303030
rgb(58, 58, 58), // #3a3a3a
rgb(68, 68, 68), // #444444
rgb(78, 78, 78), // #4e4e4e
rgb(88, 88, 88), // #585858
rgb(98, 98, 98), // #626262
rgb(108, 108, 108), // #6c6c6c
rgb(118, 118, 118), // #767676
rgb(128, 128, 128), // #808080
rgb(138, 138, 138), // #8a8a8a
rgb(148, 148, 148), // #949494
rgb(158, 158, 158), // #9e9e9e
rgb(168, 168, 168), // #a8a8a8
rgb(178, 178, 178), // #b2b2b2
rgb(188, 188, 188), // #bcbcbc
rgb(198, 198, 198), // #c6c6c6
rgb(208, 208, 208), // #d0d0d0
rgb(218, 218, 218), // #dadada
rgb(228, 228, 228), // #e4e4e4
rgb(238, 238, 238), // #eeeeee
];

257
src/xterm.js Normal file
View File

@ -0,0 +1,257 @@
import { rgb } from 'polished'; export default [ rgb(0, 0, 0), // #000000
rgb(128, 0, 0), // #800000
rgb(0, 128, 0), // #008000
rgb(128, 128, 0), // #808000
rgb(0, 0, 128), // #000080
rgb(128, 0, 128), // #800080
rgb(0, 128, 128), // #008080
rgb(192, 192, 192), // #c0c0c0
rgb(128, 128, 128), // #808080
rgb(255, 0, 0), // #ff0000
rgb(0, 255, 0), // #00ff00
rgb(255, 255, 0), // #ffff00
rgb(0, 0, 255), // #0000ff
rgb(255, 0, 255), // #ff00ff
rgb(0, 255, 255), // #00ffff
rgb(255, 255, 255), // #ffffff
rgb(0, 0, 0), // #000000
rgb(0, 0, 95), // #00005f
rgb(0, 0, 135), // #000087
rgb(0, 0, 175), // #0000af
rgb(0, 0, 215), // #0000d7
rgb(0, 0, 255), // #0000ff
rgb(0, 95, 0), // #005f00
rgb(0, 95, 95), // #005f5f
rgb(0, 95, 135), // #005f87
rgb(0, 95, 175), // #005faf
rgb(0, 95, 215), // #005fd7
rgb(0, 95, 255), // #005fff
rgb(0, 135, 0), // #008700
rgb(0, 135, 95), // #00875f
rgb(0, 135, 135), // #008787
rgb(0, 135, 175), // #0087af
rgb(0, 135, 215), // #0087d7
rgb(0, 135, 255), // #0087ff
rgb(0, 175, 0), // #00af00
rgb(0, 175, 95), // #00af5f
rgb(0, 175, 135), // #00af87
rgb(0, 175, 175), // #00afaf
rgb(0, 175, 215), // #00afd7
rgb(0, 175, 255), // #00afff
rgb(0, 215, 0), // #00d700
rgb(0, 215, 95), // #00d75f
rgb(0, 215, 135), // #00d787
rgb(0, 215, 175), // #00d7af
rgb(0, 215, 215), // #00d7d7
rgb(0, 215, 255), // #00d7ff
rgb(0, 255, 0), // #00ff00
rgb(0, 255, 95), // #00ff5f
rgb(0, 255, 135), // #00ff87
rgb(0, 255, 175), // #00ffaf
rgb(0, 255, 215), // #00ffd7
rgb(0, 255, 255), // #00ffff
rgb(95, 0, 0), // #5f0000
rgb(95, 0, 95), // #5f005f
rgb(95, 0, 135), // #5f0087
rgb(95, 0, 175), // #5f00af
rgb(95, 0, 215), // #5f00d7
rgb(95, 0, 255), // #5f00ff
rgb(95, 95, 0), // #5f5f00
rgb(95, 95, 95), // #5f5f5f
rgb(95, 95, 135), // #5f5f87
rgb(95, 95, 175), // #5f5faf
rgb(95, 95, 215), // #5f5fd7
rgb(95, 95, 255), // #5f5fff
rgb(95, 135, 0), // #5f8700
rgb(95, 135, 95), // #5f875f
rgb(95, 135, 135), // #5f8787
rgb(95, 135, 175), // #5f87af
rgb(95, 135, 215), // #5f87d7
rgb(95, 135, 255), // #5f87ff
rgb(95, 175, 0), // #5faf00
rgb(95, 175, 95), // #5faf5f
rgb(95, 175, 135), // #5faf87
rgb(95, 175, 175), // #5fafaf
rgb(95, 175, 215), // #5fafd7
rgb(95, 175, 255), // #5fafff
rgb(95, 215, 0), // #5fd700
rgb(95, 215, 95), // #5fd75f
rgb(95, 215, 135), // #5fd787
rgb(95, 215, 175), // #5fd7af
rgb(95, 215, 215), // #5fd7d7
rgb(95, 215, 255), // #5fd7ff
rgb(95, 255, 0), // #5fff00
rgb(95, 255, 95), // #5fff5f
rgb(95, 255, 135), // #5fff87
rgb(95, 255, 175), // #5fffaf
rgb(95, 255, 215), // #5fffd7
rgb(95, 255, 255), // #5fffff
rgb(135, 0, 0), // #870000
rgb(135, 0, 95), // #87005f
rgb(135, 0, 135), // #870087
rgb(135, 0, 175), // #8700af
rgb(135, 0, 215), // #8700d7
rgb(135, 0, 255), // #8700ff
rgb(135, 95, 0), // #875f00
rgb(135, 95, 95), // #875f5f
rgb(135, 95, 135), // #875f87
rgb(135, 95, 175), // #875faf
rgb(135, 95, 215), // #875fd7
rgb(135, 95, 255), // #875fff
rgb(135, 135, 0), // #878700
rgb(135, 135, 95), // #87875f
rgb(135, 135, 135), // #878787
rgb(135, 135, 175), // #8787af
rgb(135, 135, 215), // #8787d7
rgb(135, 135, 255), // #8787ff
rgb(135, 175, 0), // #87af00
rgb(135, 175, 95), // #87af5f
rgb(135, 175, 135), // #87af87
rgb(135, 175, 175), // #87afaf
rgb(135, 175, 215), // #87afd7
rgb(135, 175, 255), // #87afff
rgb(135, 215, 0), // #87d700
rgb(135, 215, 95), // #87d75f
rgb(135, 215, 135), // #87d787
rgb(135, 215, 175), // #87d7af
rgb(135, 215, 215), // #87d7d7
rgb(135, 215, 255), // #87d7ff
rgb(135, 255, 0), // #87ff00
rgb(135, 255, 95), // #87ff5f
rgb(135, 255, 135), // #87ff87
rgb(135, 255, 175), // #87ffaf
rgb(135, 255, 215), // #87ffd7
rgb(135, 255, 255), // #87ffff
rgb(175, 0, 0), // #af0000
rgb(175, 0, 95), // #af005f
rgb(175, 0, 135), // #af0087
rgb(175, 0, 175), // #af00af
rgb(175, 0, 215), // #af00d7
rgb(175, 0, 255), // #af00ff
rgb(175, 95, 0), // #af5f00
rgb(175, 95, 95), // #af5f5f
rgb(175, 95, 135), // #af5f87
rgb(175, 95, 175), // #af5faf
rgb(175, 95, 215), // #af5fd7
rgb(175, 95, 255), // #af5fff
rgb(175, 135, 0), // #af8700
rgb(175, 135, 95), // #af875f
rgb(175, 135, 135), // #af8787
rgb(175, 135, 175), // #af87af
rgb(175, 135, 215), // #af87d7
rgb(175, 135, 255), // #af87ff
rgb(175, 175, 0), // #afaf00
rgb(175, 175, 95), // #afaf5f
rgb(175, 175, 135), // #afaf87
rgb(175, 175, 175), // #afafaf
rgb(175, 175, 215), // #afafd7
rgb(175, 175, 255), // #afafff
rgb(175, 215, 0), // #afd700
rgb(175, 215, 95), // #afd75f
rgb(175, 215, 135), // #afd787
rgb(175, 215, 175), // #afd7af
rgb(175, 215, 215), // #afd7d7
rgb(175, 215, 255), // #afd7ff
rgb(175, 255, 0), // #afff00
rgb(175, 255, 95), // #afff5f
rgb(175, 255, 135), // #afff87
rgb(175, 255, 175), // #afffaf
rgb(175, 255, 215), // #afffd7
rgb(175, 255, 255), // #afffff
rgb(215, 0, 0), // #d70000
rgb(215, 0, 95), // #d7005f
rgb(215, 0, 135), // #d70087
rgb(215, 0, 175), // #d700af
rgb(215, 0, 215), // #d700d7
rgb(215, 0, 255), // #d700ff
rgb(215, 95, 0), // #d75f00
rgb(215, 95, 95), // #d75f5f
rgb(215, 95, 135), // #d75f87
rgb(215, 95, 175), // #d75faf
rgb(215, 95, 215), // #d75fd7
rgb(215, 95, 255), // #d75fff
rgb(215, 135, 0), // #d78700
rgb(215, 135, 95), // #d7875f
rgb(215, 135, 135), // #d78787
rgb(215, 135, 175), // #d787af
rgb(215, 135, 215), // #d787d7
rgb(215, 135, 255), // #d787ff
rgb(215, 175, 0), // #d7af00
rgb(215, 175, 95), // #d7af5f
rgb(215, 175, 135), // #d7af87
rgb(215, 175, 175), // #d7afaf
rgb(215, 175, 215), // #d7afd7
rgb(215, 175, 255), // #d7afff
rgb(215, 215, 0), // #d7d700
rgb(215, 215, 95), // #d7d75f
rgb(215, 215, 135), // #d7d787
rgb(215, 215, 175), // #d7d7af
rgb(215, 215, 215), // #d7d7d7
rgb(215, 215, 255), // #d7d7ff
rgb(215, 255, 0), // #d7ff00
rgb(215, 255, 95), // #d7ff5f
rgb(215, 255, 135), // #d7ff87
rgb(215, 255, 175), // #d7ffaf
rgb(215, 255, 215), // #d7ffd7
rgb(215, 255, 255), // #d7ffff
rgb(255, 0, 0), // #ff0000
rgb(255, 0, 95), // #ff005f
rgb(255, 0, 135), // #ff0087
rgb(255, 0, 175), // #ff00af
rgb(255, 0, 215), // #ff00d7
rgb(255, 0, 255), // #ff00ff
rgb(255, 95, 0), // #ff5f00
rgb(255, 95, 95), // #ff5f5f
rgb(255, 95, 135), // #ff5f87
rgb(255, 95, 175), // #ff5faf
rgb(255, 95, 215), // #ff5fd7
rgb(255, 95, 255), // #ff5fff
rgb(255, 135, 0), // #ff8700
rgb(255, 135, 95), // #ff875f
rgb(255, 135, 135), // #ff8787
rgb(255, 135, 175), // #ff87af
rgb(255, 135, 215), // #ff87d7
rgb(255, 135, 255), // #ff87ff
rgb(255, 175, 0), // #ffaf00
rgb(255, 175, 95), // #ffaf5f
rgb(255, 175, 135), // #ffaf87
rgb(255, 175, 175), // #ffafaf
rgb(255, 175, 215), // #ffafd7
rgb(255, 175, 255), // #ffafff
rgb(255, 215, 0), // #ffd700
rgb(255, 215, 95), // #ffd75f
rgb(255, 215, 135), // #ffd787
rgb(255, 215, 175), // #ffd7af
rgb(255, 215, 215), // #ffd7d7
rgb(255, 215, 255), // #ffd7ff
rgb(255, 255, 0), // #ffff00
rgb(255, 255, 95), // #ffff5f
rgb(255, 255, 135), // #ffff87
rgb(255, 255, 175), // #ffffaf
rgb(255, 255, 215), // #ffffd7
rgb(255, 255, 255), // #ffffff
rgb(8, 8, 8), // #080808
rgb(18, 18, 18), // #121212
rgb(28, 28, 28), // #1c1c1c
rgb(38, 38, 38), // #262626
rgb(48, 48, 48), // #303030
rgb(58, 58, 58), // #3a3a3a
rgb(68, 68, 68), // #444444
rgb(78, 78, 78), // #4e4e4e
rgb(88, 88, 88), // #585858
rgb(98, 98, 98), // #626262
rgb(108, 108, 108), // #6c6c6c
rgb(118, 118, 118), // #767676
rgb(128, 128, 128), // #808080
rgb(138, 138, 138), // #8a8a8a
rgb(148, 148, 148), // #949494
rgb(158, 158, 158), // #9e9e9e
rgb(168, 168, 168), // #a8a8a8
rgb(178, 178, 178), // #b2b2b2
rgb(188, 188, 188), // #bcbcbc
rgb(198, 198, 198), // #c6c6c6
rgb(208, 208, 208), // #d0d0d0
rgb(218, 218, 218), // #dadada
rgb(228, 228, 228), // #e4e4e4
rgb(238, 238, 238), // #eeeeee
];