MVP complete
This commit is contained in:
parent
e21173c8e4
commit
7c7b152d79
@ -7,7 +7,7 @@ interface ColorPaletteProps {
|
|||||||
|
|
||||||
const ColorPalette: React.FC<ColorPaletteProps> = ({ colors, size = 'small' }) => {
|
const ColorPalette: React.FC<ColorPaletteProps> = ({ colors, size = 'small' }) => {
|
||||||
const [copiedColor, setCopiedColor] = useState<string | null>(null);
|
const [copiedColor, setCopiedColor] = useState<string | null>(null);
|
||||||
const [hoveredColor, setHoveredColor] = useState<string | null>(null);
|
const [hoveredColorId, setHoveredColorId] = useState<string | null>(null);
|
||||||
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
const textAreaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const handleColorClick = (color: string) => {
|
const handleColorClick = (color: string) => {
|
||||||
@ -39,33 +39,36 @@ const ColorPalette: React.FC<ColorPaletteProps> = ({ colors, size = 'small' }) =
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={`grid grid-cols-8 gap-2 ${size === 'large' ? 'mb-4' : 'mb-2'} z-10`}>
|
<div className={`grid grid-cols-8 gap-2 ${size === 'large' ? 'mb-4' : 'mb-2'} z-10`}>
|
||||||
{colors.map((color, index) => (
|
{colors.map((color, index) => {
|
||||||
<div
|
const colorId = `color-${index}-${color}`;
|
||||||
key={index}
|
return (
|
||||||
className={`${sizeClasses} rounded-sm cursor-pointer relative group`}
|
<div
|
||||||
style={{backgroundColor: color}}
|
key={colorId}
|
||||||
onClick={() => handleColorClick(color)}
|
className={`${sizeClasses} rounded-sm cursor-pointer relative group`}
|
||||||
onMouseEnter={() => setHoveredColor(color)}
|
style={{backgroundColor: color}}
|
||||||
onMouseLeave={() => setHoveredColor(null)}
|
onClick={() => handleColorClick(color)}
|
||||||
>
|
onMouseEnter={() => setHoveredColorId(colorId)}
|
||||||
{size === 'small' && hoveredColor === color && (
|
onMouseLeave={() => setHoveredColorId(null)}
|
||||||
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-2 py-1 bg-white dark:bg-gray-800 rounded shadow-lg z-10">
|
>
|
||||||
<div className="w-4 h-4 rounded-sm mb-1" style={{backgroundColor: color}}></div>
|
{size === 'small' && hoveredColorId === colorId && (
|
||||||
<span className="text-xs">{color}</span>
|
<div className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-2 px-2 py-1 bg-white dark:bg-gray-800 rounded shadow-lg z-10">
|
||||||
</div>
|
<div className="w-4 h-4 rounded-sm mb-1" style={{backgroundColor: color}}></div>
|
||||||
)}
|
<span className="text-xs">{color}</span>
|
||||||
{size === 'large' && (
|
</div>
|
||||||
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-black bg-opacity-50 text-white text-[8px]">
|
)}
|
||||||
{color}
|
{size === 'large' && (
|
||||||
</div>
|
<div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-black bg-opacity-50 text-white text-[8px]">
|
||||||
)}
|
{color}
|
||||||
{copiedColor === color && (
|
</div>
|
||||||
<div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-70 text-white text-xs">
|
)}
|
||||||
Copied!
|
{copiedColor === color && (
|
||||||
</div>
|
<div className="absolute inset-0 flex items-center justify-center bg-black bg-opacity-70 text-white text-xs">
|
||||||
)}
|
Copied!
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
<textarea
|
<textarea
|
||||||
ref={textAreaRef}
|
ref={textAreaRef}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { ColorScheme } from '../utils/colorSchemes';
|
import { ColorScheme } from '../utils/colorSchemes';
|
||||||
import { generateYAML } from '../utils/yamlExport';
|
import { generateYAML, generateJSON, generateXResources, generateTOML } from '../utils/exportFormats';
|
||||||
import { Highlight, themes } from 'prism-react-renderer';
|
import { Highlight, themes } from 'prism-react-renderer';
|
||||||
import { motion, useAnimation } from 'framer-motion';
|
import { motion, useAnimation } from 'framer-motion';
|
||||||
import ColorPalette from './ColorPalette';
|
import ColorPalette from './ColorPalette';
|
||||||
@ -12,49 +12,238 @@ interface ColorSchemeCardProps {
|
|||||||
onDislike: () => void;
|
onDislike: () => void;
|
||||||
index: number;
|
index: number;
|
||||||
isDarkMode: boolean;
|
isDarkMode: boolean;
|
||||||
|
codeSample: string;
|
||||||
|
outputFormat: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ColorSchemeCard: React.FC<ColorSchemeCardProps> = ({ scheme, onLike, onDislike, index, isDarkMode }) => {
|
const ColorSchemeCard: React.FC<ColorSchemeCardProps> = ({ scheme, onLike, onDislike, index, isDarkMode, codeSample, outputFormat }) => {
|
||||||
const [overlayColor, setOverlayColor] = useState('rgba(0, 0, 0, 0)');
|
const [overlayColor, setOverlayColor] = useState('rgba(0, 0, 0, 0)');
|
||||||
const controls = useAnimation();
|
const controls = useAnimation();
|
||||||
|
|
||||||
const codeExample = `
|
const getCodeExample = () => {
|
||||||
// User object and function
|
// Add code samples for each language here
|
||||||
const user = {
|
const samples = {
|
||||||
name: 'DWS',
|
c: `#include <stdio.h>
|
||||||
power: 8999
|
|
||||||
};
|
|
||||||
|
|
||||||
class Shape {
|
int is_prime(int n) {
|
||||||
constructor(color) {
|
if (n <= 1) return 0;
|
||||||
this.color = color;
|
for (int i = 2; i * i <= n; i++) {
|
||||||
|
if (n % i == 0) return 0;
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Async data fetch simulation
|
void print_primes(int limit) {
|
||||||
async function fetchData() {
|
printf("Primes up to %d:\n", limit);
|
||||||
return await new Promise(resolve => setTimeout(() => resolve('Data loaded'), 500));
|
for (int i = 2; i <= limit; i++) {
|
||||||
|
if (is_prime(i)) {
|
||||||
|
printf("%d ", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
const [even, odd] = [2, 4, 6, 8].reduce(([e, o], n) => n % 2 ? [e, [...o, n]] : [
|
|
||||||
[...e, n], o
|
|
||||||
], [
|
|
||||||
[],
|
|
||||||
[]
|
|
||||||
]);
|
|
||||||
|
|
||||||
/*
|
int main() {
|
||||||
Logging here
|
int limit = 50;
|
||||||
*/
|
print_primes(limit);
|
||||||
fetchData().then(data => console.log(data)); `;
|
|
||||||
|
int num = 7;
|
||||||
|
printf("Is %d prime? %s\n", num, is_prime(num) ? "Yes" : "No");
|
||||||
|
return 0;
|
||||||
|
}`,
|
||||||
|
python: `import numpy as np
|
||||||
|
|
||||||
|
@timeit
|
||||||
|
def is_prime(n):
|
||||||
|
if n <= 1:
|
||||||
|
return False
|
||||||
|
for i in range(2, int(n ** 0.5) + 1):
|
||||||
|
if n % i == 0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def primes_up_to(limit):
|
||||||
|
"""
|
||||||
|
This function returns a list of prime numbers up to a given limit.
|
||||||
|
"""
|
||||||
|
primes = []
|
||||||
|
for i in range(2, limit + 1):
|
||||||
|
if is_prime(i):
|
||||||
|
primes.append(i)
|
||||||
|
return primes
|
||||||
|
|
||||||
|
def fibonacci(n):
|
||||||
|
fib_sequence = [0, 1] # Create a list with the first two numbers in the Fibonacci sequence
|
||||||
|
for i in range(2, n):
|
||||||
|
fib_sequence.append(fib_sequence[-1] + fib_sequence[-2])
|
||||||
|
return fib_sequence
|
||||||
|
|
||||||
|
limit = 50
|
||||||
|
print(f"Primes up to {limit}: {primes_up_to(limit)}")
|
||||||
|
print(f"Fibonacci sequence up to 10: {fibonacci(10)}")
|
||||||
|
`,
|
||||||
|
rust: `fn is_prime(n: u32) -> bool {
|
||||||
|
if n <= 1 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for i in 2..=((n as f64).sqrt() as u32) {
|
||||||
|
if n % i == 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn primes_up_to(limit: u32) -> Vec<u32> {
|
||||||
|
let mut primes = Vec::new();
|
||||||
|
for i in 2..=limit {
|
||||||
|
if is_prime(i) {
|
||||||
|
primes.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
primes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let limit = 50;
|
||||||
|
let primes = primes_up_to(limit);
|
||||||
|
println!("Primes up to {}: {:?}", limit, primes);
|
||||||
|
|
||||||
|
let num = 7;
|
||||||
|
println!("Is {} prime? {}", num, is_prime(num));
|
||||||
|
}`,
|
||||||
|
go: `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isPrime(n int) bool {
|
||||||
|
if n <= 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 2; i <= int(math.Sqrt(float64(n))); i++ {
|
||||||
|
if n%i == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func primesUpTo(limit int) []int {
|
||||||
|
primes := []int{}
|
||||||
|
for i := 2; i <= limit; i++ {
|
||||||
|
if isPrime(i) {
|
||||||
|
primes = append(primes, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primes
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
limit := 50
|
||||||
|
fmt.Printf("Primes up to %d: %v\n", limit, primesUpTo(limit))
|
||||||
|
|
||||||
|
num := 7
|
||||||
|
fmt.Printf("Is %d prime? %v\n", num, isPrime(num))
|
||||||
|
}`,
|
||||||
|
javascript: `function isPrime(n) {
|
||||||
|
if (n <= 1) return false;
|
||||||
|
for (let i = 2; i <= Math.sqrt(n); i++) {
|
||||||
|
if (n % i === 0) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function primesUpTo(limit) {
|
||||||
|
let primes = [];
|
||||||
|
for (let i = 2; i <= limit; i++) {
|
||||||
|
if (isPrime(i)) primes.push(i);
|
||||||
|
}
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fibonacci(n) {
|
||||||
|
let fib = [0, 1];
|
||||||
|
for (let i = 2; i < n; i++) {
|
||||||
|
fib.push(fib[i - 1] + fib[i - 2]);
|
||||||
|
}
|
||||||
|
return fib;
|
||||||
|
}
|
||||||
|
|
||||||
|
let limit = 50;`,
|
||||||
|
bash: `#!/bin/bash
|
||||||
|
|
||||||
|
is_prime() {
|
||||||
|
local n=$1
|
||||||
|
if [ $n -le 1 ]; then
|
||||||
|
echo 0
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
for ((i=2; i*i<=n; i++)); do
|
||||||
|
if ((n % i == 0)); then
|
||||||
|
echo 0
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo 1
|
||||||
|
}
|
||||||
|
|
||||||
|
primes_up_to() {
|
||||||
|
local limit=$1
|
||||||
|
for ((i=2; i<=limit; i++)); do
|
||||||
|
if [ $(is_prime $i) -eq 1 ]; then
|
||||||
|
echo -n "$i "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
limit=50
|
||||||
|
echo "Primes up to $limit: $(primes_up_to $limit)"
|
||||||
|
|
||||||
|
num=7
|
||||||
|
if [ $(is_prime $num) -eq 1 ]; then
|
||||||
|
echo "$num is prime"
|
||||||
|
else
|
||||||
|
echo "$num is not prime"
|
||||||
|
fi`
|
||||||
|
};
|
||||||
|
|
||||||
|
return samples[codeSample] || samples.javascript;
|
||||||
|
};
|
||||||
|
|
||||||
const handleDownload = (e: React.MouseEvent) => {
|
const handleDownload = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const yaml = generateYAML(scheme);
|
let content: string;
|
||||||
const blob = new Blob([yaml], { type: 'text/yaml' });
|
let fileExtension: string;
|
||||||
|
|
||||||
|
switch (outputFormat) {
|
||||||
|
case 'json':
|
||||||
|
content = generateJSON(scheme);
|
||||||
|
fileExtension = 'json';
|
||||||
|
break;
|
||||||
|
case 'xresources':
|
||||||
|
content = generateXResources(scheme);
|
||||||
|
fileExtension = 'Xresources';
|
||||||
|
break;
|
||||||
|
case 'toml':
|
||||||
|
content = generateTOML(scheme);
|
||||||
|
fileExtension = 'toml';
|
||||||
|
break;
|
||||||
|
case 'yaml':
|
||||||
|
default:
|
||||||
|
content = generateYAML(scheme);
|
||||||
|
fileExtension = 'yaml';
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob([content], { type: 'text/plain' });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = `${scheme.name.replace(/\s+/g, '_').toLowerCase()}.yaml`;
|
a.download = `${scheme.name.replace(/\s+/g, '_').toLowerCase()}.${fileExtension}`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
@ -71,55 +260,114 @@ fetchData().then(data => console.log(data)); `;
|
|||||||
controls.start({ x: -300, opacity: 0, transition: { duration: 0.3 } }).then(onDislike);
|
controls.start({ x: -300, opacity: 0, transition: { duration: 0.3 } }).then(onDislike);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const paletteColors = [
|
||||||
|
scheme.colors.normal.black,
|
||||||
|
scheme.colors.normal.red,
|
||||||
|
scheme.colors.normal.green,
|
||||||
|
scheme.colors.normal.yellow,
|
||||||
|
scheme.colors.normal.blue,
|
||||||
|
scheme.colors.normal.magenta,
|
||||||
|
scheme.colors.normal.cyan,
|
||||||
|
scheme.colors.normal.white,
|
||||||
|
scheme.colors.bright.black,
|
||||||
|
scheme.colors.bright.red,
|
||||||
|
scheme.colors.bright.green,
|
||||||
|
scheme.colors.bright.yellow,
|
||||||
|
scheme.colors.bright.blue,
|
||||||
|
scheme.colors.bright.magenta,
|
||||||
|
scheme.colors.bright.cyan,
|
||||||
|
scheme.colors.bright.white,
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute w-[350px] h-[600px] bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
|
className="absolute w-[80vw] max-w-[480px] h-[90vh] max-h-[600px] bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
|
||||||
initial={{ scale: 1 - index * 0.05, y: index * 15, opacity: 1 }}
|
initial={{ scale: 1 - index * 0.05, y: index * 15, opacity: 1 }}
|
||||||
animate={controls}
|
animate={controls}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 3 - index
|
zIndex: 3 - index
|
||||||
}}
|
}}
|
||||||
drag="x"
|
drag="x"
|
||||||
dragConstraints={{ left: -100, right: 100 }}
|
dragConstraints={{ left: -50, right: 50 }}
|
||||||
onDragEnd={(e, { offset, velocity }) => {
|
onDragEnd={(e, { offset, velocity }) => {
|
||||||
if (offset.x > 100) handleLike();
|
if (offset.x > 50) handleLike();
|
||||||
else if (offset.x < -100) handleDislike();
|
else if (offset.x < -50) handleDislike();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="p-6 h-full flex flex-col relative">
|
<div className="p-4 h-full flex flex-col relative">
|
||||||
<motion.div
|
<motion.div
|
||||||
className="absolute inset-0 rounded-lg"
|
className="absolute inset-0 rounded-lg"
|
||||||
animate={{ backgroundColor: overlayColor }}
|
animate={{ backgroundColor: overlayColor }}
|
||||||
initial={{ backgroundColor: 'rgba(0, 0, 0, 0)' }}
|
initial={{ backgroundColor: 'rgba(0, 0, 0, 0)' }}
|
||||||
transition={{ duration: 0.2 }}
|
transition={{ duration: 0.2 }}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-between items-center mb-4 z-10">
|
<div className="flex justify-between items-center mb-2 z-10">
|
||||||
<h2 className="text-xl font-semibold">{scheme.name}</h2>
|
<h2 className="text-lg font-semibold truncate">{scheme.name}</h2>
|
||||||
<button
|
<button
|
||||||
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors duration-300"
|
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors duration-300"
|
||||||
onClick={handleDownload}
|
onClick={handleDownload}
|
||||||
>
|
>
|
||||||
<Image src={isDarkMode ? "/download-icon-dark.svg" : "/download-icon-light.svg"} alt="Download" width={24} height={24} />
|
<Image src={isDarkMode ? "/download-icon-dark.svg" : "/download-icon-light.svg"} alt="Download" width={20} height={20} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-gray-100 dark:bg-gray-700 rounded-md mb-4 flex-grow overflow-hidden z-10 shadow-md">
|
<div className="bg-gray-100 dark:bg-gray-700 rounded-md mb-2 flex-grow overflow-hidden z-10 shadow-md">
|
||||||
<Highlight theme={themes.dracula} code={codeExample} language="javascript">
|
<Highlight theme={themes.dracula} code={getCodeExample()} language={codeSample}>
|
||||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
||||||
<pre className={`${className} text-xs p-4 overflow-x-auto`} style={{ ...style, backgroundColor: scheme.colors.primary.background }}>
|
<pre className={`${className} text-sm p-4 h-full overflow-auto`} style={{ ...style, backgroundColor: scheme.colors.primary.background }}>
|
||||||
{tokens.slice(0, 20).map((line, i) => (
|
{tokens.map((line, i) => (
|
||||||
<div key={i} {...getLineProps({ line, key: i })}>
|
<div key={i} {...getLineProps({ line, key: i })}>
|
||||||
{line.map((token, key) => {
|
{line.map((token, key) => {
|
||||||
let color = scheme.colors.primary.foreground;
|
let color = scheme.colors.primary.foreground;
|
||||||
if (token.types.includes('keyword')) color = scheme.colors.normal.blue;
|
if (token.types.includes('keyword')) color = scheme.colors.normal.blue;
|
||||||
if (token.types.includes('string')) color = scheme.colors.normal.green;
|
if (token.types.includes('string')) color = scheme.colors.normal.green;
|
||||||
if (token.types.includes('number')) color = scheme.colors.normal.magenta;
|
if (token.types.includes('number')) color = scheme.colors.normal.magenta;
|
||||||
if (token.types.includes('comment')) color = scheme.colors.bright.black;
|
if (token.types.includes('comment')) color = scheme.colors.bright.black;
|
||||||
if (token.types.includes('function')) color = scheme.colors.normal.yellow;
|
if (token.types.includes('function')) color = scheme.colors.normal.yellow;
|
||||||
if (token.types.includes('operator')) color = scheme.colors.normal.cyan;
|
if (token.types.includes('operator')) color = scheme.colors.normal.cyan;
|
||||||
if (token.types.includes('class-name')) color = scheme.colors.bright.magenta;
|
if (token.types.includes('class-name')) color = scheme.colors.bright.magenta;
|
||||||
if (token.types.includes('constant')) color = scheme.colors.bright.red;
|
if (token.types.includes('constant')) color = scheme.colors.bright.red;
|
||||||
if (token.types.includes('punctuation')) color = scheme.colors.bright.cyan;
|
if (token.types.includes('punctuation')) color = scheme.colors.bright.cyan;
|
||||||
if (token.types.includes('variable')) color = scheme.colors.bright.yellow;
|
if (token.types.includes('variable')) color = scheme.colors.bright.yellow;
|
||||||
|
if (token.types.includes('boolean')) color = scheme.colors.bright.yellow;
|
||||||
|
if (token.types.includes('builtin')) color = scheme.colors.bright.magenta;
|
||||||
|
if (token.types.includes('attr-name')) color = scheme.colors.normal.red;
|
||||||
|
if (token.types.includes('attr-value')) color = scheme.colors.bright.green;
|
||||||
|
if (token.types.includes('tag')) color = scheme.colors.normal.blue;
|
||||||
|
if (token.types.includes('namespace')) color = scheme.colors.normal.magenta;
|
||||||
|
if (token.types.includes('selector')) color = scheme.colors.normal.yellow;
|
||||||
|
if (token.types.includes('property')) color = scheme.colors.normal.cyan;
|
||||||
|
if (token.types.includes('unit')) color = scheme.colors.bright.yellow;
|
||||||
|
if (token.types.includes('important')) color = scheme.colors.bright.red;
|
||||||
|
if (token.types.includes('symbol')) color = scheme.colors.normal.magenta; // Symbols (e.g., special characters)
|
||||||
|
if (token.types.includes('regex')) color = scheme.colors.bright.green; // Regular expressions
|
||||||
|
if (token.types.includes('template-string')) color = scheme.colors.normal.green; // Template literals
|
||||||
|
if (token.types.includes('char')) color = scheme.colors.bright.yellow; // Individual characters
|
||||||
|
if (token.types.includes('module')) color = scheme.colors.normal.cyan; // Modules
|
||||||
|
if (token.types.includes('directive')) color = scheme.colors.normal.magenta; // Directives (e.g., preprocessor)
|
||||||
|
if (token.types.includes('annotation')) color = scheme.colors.normal.green; // Annotations (e.g., decorators)
|
||||||
|
if (token.types.includes('parameter')) color = scheme.colors.bright.yellow; // Parameters in functions
|
||||||
|
if (token.types.includes('method')) color = scheme.colors.normal.yellow; // Methods
|
||||||
|
if (token.types.includes('field')) color = scheme.colors.bright.blue; // Fields within classes
|
||||||
|
if (token.types.includes('property-access')) color = scheme.colors.normal.cyan; // Property accessors (e.g., dot notation)
|
||||||
|
if (token.types.includes('escape')) color = scheme.colors.bright.red; // Escape sequences
|
||||||
|
if (token.types.includes('meta')) color = scheme.colors.bright.magenta; // Meta information (e.g., HTML meta tags)
|
||||||
|
if (token.types.includes('label')) color = scheme.colors.bright.yellow; // Labels (e.g., in loops)
|
||||||
|
if (token.types.includes('alias')) color = scheme.colors.normal.magenta; // Aliases (e.g., imports or type aliases)
|
||||||
|
if (token.types.includes('error')) color = scheme.colors.bright.red; // Error handling, error literals
|
||||||
|
if (token.types.includes('debug')) color = scheme.colors.bright.magenta; // Debugging statements (e.g., console logs)
|
||||||
|
if (token.types.includes('property-declaration')) color = scheme.colors.normal.blue; // Property declarations in classes
|
||||||
|
if (token.types.includes('module-declaration')) color = scheme.colors.normal.cyan; // Declarations of modules
|
||||||
|
if (token.types.includes('generic')) color = scheme.colors.bright.magenta; // Generics (e.g., <T>)
|
||||||
|
if (token.types.includes('type')) color = scheme.colors.bright.blue; // Types in TypeScript, Flow, etc.
|
||||||
|
if (token.types.includes('interface')) color = scheme.colors.normal.green; // Interfaces (e.g., TypeScript)
|
||||||
|
if (token.types.includes('enums')) color = scheme.colors.bright.cyan; // Enums in languages like TypeScript, Java
|
||||||
|
if (token.types.includes('modifier')) color = scheme.colors.normal.yellow; // Modifiers (e.g., public, static)
|
||||||
|
if (token.types.includes('event')) color = scheme.colors.bright.blue; // Events (e.g., DOM events or custom events)
|
||||||
|
if (token.types.includes('keyword-control')) color = scheme.colors.bright.yellow; // Control-flow keywords (e.g., if, for)
|
||||||
|
if (token.types.includes('loop')) color = scheme.colors.normal.magenta; // Loop keywords (e.g., for, while)
|
||||||
|
if (token.types.includes('storage')) color = scheme.colors.normal.red; // Storage-related keywords (e.g., var, let)
|
||||||
|
if (token.types.includes('annotation-function')) color = scheme.colors.bright.green; // Annotated functions
|
||||||
|
if (token.types.includes('doc-string')) color = scheme.colors.bright.blue; // Docstrings or comments that are part of documentation
|
||||||
return <span key={key} {...getTokenProps({ token, key })} style={{ ...getTokenProps({ token, key }).style, color }} />;
|
return <span key={key} {...getTokenProps({ token, key })} style={{ ...getTokenProps({ token, key }).style, color }} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@ -128,22 +376,24 @@ fetchData().then(data => console.log(data)); `;
|
|||||||
)}
|
)}
|
||||||
</Highlight>
|
</Highlight>
|
||||||
</div>
|
</div>
|
||||||
<ColorPalette
|
<div className="mt-2 z-10">
|
||||||
colors={Object.values(scheme.colors.normal).concat(Object.values(scheme.colors.bright))}
|
<ColorPalette
|
||||||
size="large"
|
colors={paletteColors}
|
||||||
/>
|
size="small"
|
||||||
<div className="flex justify-center space-x-8 mt-4 z-10">
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center space-x-4 mt-2 z-10">
|
||||||
<button
|
<button
|
||||||
className="bg-red-500 text-white p-3 rounded-full shadow-lg hover:bg-red-600 transition-colors duration-300"
|
className="bg-red-500 text-white p-2 rounded-full shadow-lg hover:bg-red-600 transition-colors duration-300"
|
||||||
onClick={handleDislike}
|
onClick={handleDislike}
|
||||||
>
|
>
|
||||||
<Image src={isDarkMode ? "/cross-icon-dark.svg" : "/cross-icon-light.svg"} alt="Dislike" width={28} height={28} />
|
<Image src={isDarkMode ? "/cross-icon-dark.svg" : "/cross-icon-light.svg"} alt="Dislike" width={24} height={24} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="bg-green-500 text-white p-3 rounded-full shadow-lg hover:bg-green-600 transition-colors duration-300"
|
className="bg-green-500 text-white p-2 rounded-full shadow-lg hover:bg-green-600 transition-colors duration-300"
|
||||||
onClick={handleLike}
|
onClick={handleLike}
|
||||||
>
|
>
|
||||||
<Image src={isDarkMode ? "/heart-icon-dark.svg" : "/heart-icon-light.svg"} alt="Like" width={28} height={28} />
|
<Image src={isDarkMode ? "/heart-icon-dark.svg" : "/heart-icon-light.svg"} alt="Like" width={24} height={24} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { ColorScheme } from '../utils/colorSchemes';
|
import { ColorScheme } from '../utils/colorSchemes';
|
||||||
import { generateYAML } from '../utils/yamlExport';
|
import { generateYAML, generateJSON, generateXResources, generateTOML } from '../utils/exportFormats';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import ColorPalette from './ColorPalette';
|
import ColorPalette from './ColorPalette';
|
||||||
|
|
||||||
@ -9,18 +9,40 @@ interface HistoryPopupProps {
|
|||||||
dislikedSchemes: ColorScheme[];
|
dislikedSchemes: ColorScheme[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
isDarkMode: boolean;
|
isDarkMode: boolean;
|
||||||
|
outputFormat: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HistoryPopup: React.FC<HistoryPopupProps> = ({ likedSchemes, dislikedSchemes, onClose, isDarkMode }) => {
|
const HistoryPopup: React.FC<HistoryPopupProps> = ({ likedSchemes, dislikedSchemes, onClose, isDarkMode, outputFormat }) => {
|
||||||
const [copiedColor, setCopiedColor] = useState<string | null>(null);
|
const [copiedColor, setCopiedColor] = useState<string | null>(null);
|
||||||
|
|
||||||
const handleDownload = (scheme: ColorScheme) => {
|
const handleDownload = (scheme: ColorScheme) => {
|
||||||
const yaml = generateYAML(scheme);
|
let content: string;
|
||||||
const blob = new Blob([yaml], { type: 'text/yaml' });
|
let fileExtension: string;
|
||||||
|
|
||||||
|
switch (outputFormat) {
|
||||||
|
case 'json':
|
||||||
|
content = generateJSON(scheme);
|
||||||
|
fileExtension = 'json';
|
||||||
|
break;
|
||||||
|
case 'xresources':
|
||||||
|
content = generateXResources(scheme);
|
||||||
|
fileExtension = 'Xresources';
|
||||||
|
break;
|
||||||
|
case 'toml':
|
||||||
|
content = generateTOML(scheme);
|
||||||
|
fileExtension = 'toml';
|
||||||
|
break;
|
||||||
|
case 'yaml':
|
||||||
|
default:
|
||||||
|
content = generateYAML(scheme);
|
||||||
|
fileExtension = 'yaml';
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob([content], { type: 'text/plain' });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = `${scheme.name.replace(/\s+/g, '_').toLowerCase()}.yaml`;
|
a.download = `${scheme.name.replace(/\s+/g, '_').toLowerCase()}.${fileExtension}`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
|
@ -1,41 +1,128 @@
|
|||||||
import React from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import Image from 'next/image';
|
||||||
|
|
||||||
interface SettingsProps {
|
interface SettingsProps {
|
||||||
isDarkMode: boolean;
|
|
||||||
onToggleDarkMode: () => void;
|
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
isDarkMode: boolean;
|
||||||
|
onToggleDarkMode: () => void;
|
||||||
|
outputFormat: string;
|
||||||
|
setOutputFormat: (format: string) => void;
|
||||||
|
codeSample: string;
|
||||||
|
setCodeSample: (sample: string) => void;
|
||||||
|
saveSettings: boolean;
|
||||||
|
setSaveSettings: (save: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Settings: React.FC<SettingsProps> = ({ isDarkMode, onToggleDarkMode, isOpen, onClose }) => {
|
const Settings: React.FC<SettingsProps> = ({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
isDarkMode,
|
||||||
|
onToggleDarkMode,
|
||||||
|
outputFormat,
|
||||||
|
setOutputFormat,
|
||||||
|
codeSample,
|
||||||
|
setCodeSample,
|
||||||
|
saveSettings,
|
||||||
|
setSaveSettings
|
||||||
|
}) => {
|
||||||
|
const [showCookieNotice, setShowCookieNotice] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (saveSettings && !localStorage.getItem('cookieNoticeShown')) {
|
||||||
|
setShowCookieNotice(true);
|
||||||
|
}
|
||||||
|
}, [saveSettings]);
|
||||||
|
|
||||||
|
const handleSaveSettingsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newValue = e.target.checked;
|
||||||
|
setSaveSettings(newValue);
|
||||||
|
if (newValue && !localStorage.getItem('cookieNoticeShown')) {
|
||||||
|
setShowCookieNotice(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCookieNoticeClose = () => {
|
||||||
|
setShowCookieNotice(false);
|
||||||
|
localStorage.setItem('cookieNoticeShown', 'true');
|
||||||
|
};
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||||
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-xl">
|
<div className="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-xl w-[90vw] max-w-md">
|
||||||
<h2 className="text-xl font-bold mb-4">Settings</h2>
|
<div className="flex justify-between items-center mb-4">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<h2 className="text-2xl font-bold">Settings</h2>
|
||||||
<span>Dark Mode</span>
|
<button onClick={onClose} className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
|
||||||
<button
|
<Image src={isDarkMode ? "/close-icon-dark.svg" : "/close-icon-light.svg"} alt="Close" width={24} height={24} />
|
||||||
onClick={onToggleDarkMode}
|
|
||||||
className={`w-12 h-6 rounded-full p-1 transition-colors duration-300 ease-in-out ${
|
|
||||||
isDarkMode ? 'bg-blue-600' : 'bg-gray-300'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`w-4 h-4 rounded-full bg-white transform transition-transform duration-300 ease-in-out ${
|
|
||||||
isDarkMode ? 'translate-x-6' : ''
|
|
||||||
}`}
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div className="space-y-4">
|
||||||
onClick={onClose}
|
<div className="flex items-center justify-between">
|
||||||
className="mt-4 bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded transition-colors duration-300"
|
<span>Dark Mode</span>
|
||||||
>
|
<button
|
||||||
Close
|
onClick={onToggleDarkMode}
|
||||||
</button>
|
className={`w-12 h-6 rounded-full p-1 transition-colors duration-300 ease-in-out ${
|
||||||
|
isDarkMode ? 'bg-blue-600' : 'bg-gray-300'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={`w-4 h-4 rounded-full bg-white transform transition-transform duration-300 ease-in-out ${
|
||||||
|
isDarkMode ? 'translate-x-6' : ''
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block mb-2">Output Format</label>
|
||||||
|
<select
|
||||||
|
value={outputFormat}
|
||||||
|
onChange={(e) => setOutputFormat(e.target.value)}
|
||||||
|
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
>
|
||||||
|
<option value="json">JSON</option>
|
||||||
|
<option value="xresources">XResources</option>
|
||||||
|
<option value="yaml">YAML (Alacritty)</option>
|
||||||
|
<option value="toml">TOML (Alacritty)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="block mb-2">Code Sample</label>
|
||||||
|
<select
|
||||||
|
value={codeSample}
|
||||||
|
onChange={(e) => setCodeSample(e.target.value)}
|
||||||
|
className="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
>
|
||||||
|
<option value="c">C</option>
|
||||||
|
<option value="python">Python</option>
|
||||||
|
<option value="rust">Rust</option>
|
||||||
|
<option value="go">Go</option>
|
||||||
|
<option value="javascript">JavaScript</option>
|
||||||
|
<option value="java">Java</option>
|
||||||
|
<option value="bash">Bash</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="saveSettings"
|
||||||
|
checked={saveSettings}
|
||||||
|
onChange={handleSaveSettingsChange}
|
||||||
|
className="mr-2"
|
||||||
|
/>
|
||||||
|
<label htmlFor="saveSettings">Save settings in cookie</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{showCookieNotice && (
|
||||||
|
<div className="fixed bottom-0 left-0 right-0 bg-blue-500 text-white p-4">
|
||||||
|
<p>We will save your settings in a cookie. Is this okay?</p>
|
||||||
|
<button onClick={handleCookieNoticeClose} className="mt-2 bg-white text-blue-500 px-4 py-2 rounded">
|
||||||
|
Accept
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
96
app/page.tsx
96
app/page.tsx
@ -4,6 +4,7 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import ColorSchemeCard from "./components/ColorSchemeCard";
|
import ColorSchemeCard from "./components/ColorSchemeCard";
|
||||||
import HistoryPopup from "./components/HistoryPopup";
|
import HistoryPopup from "./components/HistoryPopup";
|
||||||
|
import Settings from "./components/Settings";
|
||||||
import { ColorScheme, knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm } from './utils/colorSchemes';
|
import { ColorScheme, knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm } from './utils/colorSchemes';
|
||||||
import { AnimatePresence } from 'framer-motion';
|
import { AnimatePresence } from 'framer-motion';
|
||||||
|
|
||||||
@ -13,6 +14,10 @@ export default function Home() {
|
|||||||
const [likedSchemes, setLikedSchemes] = useState<ColorScheme[]>([]);
|
const [likedSchemes, setLikedSchemes] = useState<ColorScheme[]>([]);
|
||||||
const [dislikedSchemes, setDislikedSchemes] = useState<ColorScheme[]>([]);
|
const [dislikedSchemes, setDislikedSchemes] = useState<ColorScheme[]>([]);
|
||||||
const [isHistoryOpen, setIsHistoryOpen] = useState(false);
|
const [isHistoryOpen, setIsHistoryOpen] = useState(false);
|
||||||
|
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
|
||||||
|
const [outputFormat, setOutputFormat] = useState('yaml');
|
||||||
|
const [codeSample, setCodeSample] = useState('javascript');
|
||||||
|
const [saveSettings, setSaveSettings] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateNewSchemes(8);
|
generateNewSchemes(8);
|
||||||
@ -25,6 +30,15 @@ export default function Home() {
|
|||||||
if (storedDislikedSchemes) {
|
if (storedDislikedSchemes) {
|
||||||
setDislikedSchemes(JSON.parse(storedDislikedSchemes));
|
setDislikedSchemes(JSON.parse(storedDislikedSchemes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load settings from cookie if available
|
||||||
|
const storedSettings = document.cookie.split('; ').find(row => row.startsWith('settings='));
|
||||||
|
if (storedSettings) {
|
||||||
|
const settings = JSON.parse(storedSettings.split('=')[1]);
|
||||||
|
setOutputFormat(settings.outputFormat);
|
||||||
|
setCodeSample(settings.codeSample);
|
||||||
|
setSaveSettings(true);
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -40,30 +54,27 @@ export default function Home() {
|
|||||||
}, [dislikedSchemes]);
|
}, [dislikedSchemes]);
|
||||||
|
|
||||||
const generateNewSchemes = (count: number) => {
|
const generateNewSchemes = (count: number) => {
|
||||||
const newSchemes = Array(count).fill(null).map(() => {
|
const knownCount = Math.floor(count / 2);
|
||||||
const schemeType = Math.random();
|
const generatedCount = count - knownCount;
|
||||||
if (schemeType < 0.25) {
|
const newSchemes = [
|
||||||
// 25% chance of known scheme
|
...knownSchemes.sort(() => 0.5 - Math.random()).slice(0, knownCount),
|
||||||
return knownSchemes[Math.floor(Math.random() * knownSchemes.length)];
|
...Array(generatedCount).fill(null).map(() =>
|
||||||
} else if (schemeType < 0.5) {
|
likedSchemes.length > 0 ? generateSchemeFromGeneticAlgorithm(likedSchemes, dislikedSchemes) : generateRandomScheme()
|
||||||
// 25% chance of random scheme
|
)
|
||||||
return generateRandomScheme();
|
];
|
||||||
} else if (likedSchemes.length > 2 && dislikedSchemes.length > 2) {
|
|
||||||
// 50% chance of genetic scheme if there are more than 2 liked and disliked schemes
|
|
||||||
return generateSchemeFromGeneticAlgorithm(likedSchemes, dislikedSchemes);
|
|
||||||
} else {
|
|
||||||
// 30% known, 20% random for other cases
|
|
||||||
if (Math.random() < 0.3) {
|
|
||||||
return generateRandomScheme();
|
|
||||||
} else {
|
|
||||||
return knownSchemes[Math.floor(Math.random() * knownSchemes.length)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setSchemes(prevSchemes => [...prevSchemes, ...newSchemes]);
|
setSchemes(prevSchemes => [...prevSchemes, ...newSchemes].sort(() => 0.5 - Math.random()));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (saveSettings) {
|
||||||
|
const settings = JSON.stringify({ outputFormat, codeSample });
|
||||||
|
document.cookie = `settings=${settings}; max-age=31536000; path=/`; // 1 year expiration
|
||||||
|
} else {
|
||||||
|
document.cookie = 'settings=; max-age=0; path=/';
|
||||||
|
}
|
||||||
|
}, [saveSettings, outputFormat, codeSample]);
|
||||||
|
|
||||||
const handleLike = (scheme: ColorScheme) => {
|
const handleLike = (scheme: ColorScheme) => {
|
||||||
setLikedSchemes(prev => [...prev, scheme]);
|
setLikedSchemes(prev => [...prev, scheme]);
|
||||||
removeTopScheme();
|
removeTopScheme();
|
||||||
@ -92,6 +103,10 @@ export default function Home() {
|
|||||||
setIsHistoryOpen(!isHistoryOpen);
|
setIsHistoryOpen(!isHistoryOpen);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleSettings = () => {
|
||||||
|
setIsSettingsOpen(!isSettingsOpen);
|
||||||
|
};
|
||||||
|
|
||||||
const getAllSchemes = () => {
|
const getAllSchemes = () => {
|
||||||
const allSchemes = [...likedSchemes, ...dislikedSchemes];
|
const allSchemes = [...likedSchemes, ...dislikedSchemes];
|
||||||
const uniqueSchemes = allSchemes.filter((scheme, index, self) =>
|
const uniqueSchemes = allSchemes.filter((scheme, index, self) =>
|
||||||
@ -101,17 +116,19 @@ export default function Home() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-screen overflow-hidden font-[family-name:var(--font-geist-sans)] dark:bg-gray-900 dark:text-white transition-colors duration-300">
|
<div className="min-h-screen w-screen overflow-hidden font-[family-name:var(--font-geist-sans)] dark:bg-gray-900 dark:text-white transition-colors duration-300">
|
||||||
<header className="absolute top-4 left-4 z-10">
|
<header className="absolute top-4 left-4 z-20">
|
||||||
<Image src="/app-icon.svg" alt="App Icon" width={40} height={40} />
|
<Image src="/app-icon.svg" alt="App Icon" width={32} height={32} />
|
||||||
</header>
|
</header>
|
||||||
<button
|
<div className="absolute top-4 right-4 z-20 flex space-x-2">
|
||||||
className="absolute top-4 right-4 z-10"
|
<button onClick={toggleHistory}>
|
||||||
onClick={toggleHistory}
|
<Image src={isDarkMode ? "/history-icon-dark.svg" : "/history-icon-light.svg"} alt="History" width={24} height={24} />
|
||||||
>
|
</button>
|
||||||
<Image src={isDarkMode ? "/history-icon-dark.svg" : "/history-icon-light.svg"} alt="History" width={32} height={32} />
|
<button onClick={toggleSettings}>
|
||||||
</button>
|
<Image src={isDarkMode ? "/settings-icon-dark.svg" : "/settings-icon-light.svg"} alt="Settings" width={24} height={24} />
|
||||||
<main className="flex flex-col items-center justify-center h-full">
|
</button>
|
||||||
|
</div>
|
||||||
|
<main className="flex flex-col items-center justify-center h-screen">
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{schemes.slice(0, 3).map((scheme, index) => (
|
{schemes.slice(0, 3).map((scheme, index) => (
|
||||||
<ColorSchemeCard
|
<ColorSchemeCard
|
||||||
@ -121,6 +138,8 @@ export default function Home() {
|
|||||||
onDislike={() => handleDislike(scheme)}
|
onDislike={() => handleDislike(scheme)}
|
||||||
index={index}
|
index={index}
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
|
codeSample={codeSample}
|
||||||
|
outputFormat={outputFormat}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
@ -131,6 +150,21 @@ export default function Home() {
|
|||||||
dislikedSchemes={dislikedSchemes}
|
dislikedSchemes={dislikedSchemes}
|
||||||
onClose={toggleHistory}
|
onClose={toggleHistory}
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
|
outputFormat={outputFormat}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isSettingsOpen && (
|
||||||
|
<Settings
|
||||||
|
isOpen={isSettingsOpen}
|
||||||
|
onClose={toggleSettings}
|
||||||
|
isDarkMode={isDarkMode}
|
||||||
|
onToggleDarkMode={() => setIsDarkMode(!isDarkMode)}
|
||||||
|
outputFormat={outputFormat}
|
||||||
|
setOutputFormat={setOutputFormat}
|
||||||
|
codeSample={codeSample}
|
||||||
|
setCodeSample={setCodeSample}
|
||||||
|
saveSettings={saveSettings}
|
||||||
|
setSaveSettings={setSaveSettings}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
type Color = string; // Hex color code
|
import Color from 'color';
|
||||||
|
|
||||||
type ColorScheme = {
|
type ColorScheme = {
|
||||||
name: string;
|
name: string;
|
||||||
colors: {
|
colors: {
|
||||||
primary: { background: Color; foreground: Color };
|
primary: { background: string; foreground: string };
|
||||||
normal: {
|
normal: {
|
||||||
black: Color; red: Color; green: Color; yellow: Color;
|
black: string; red: string; green: string; yellow: string;
|
||||||
blue: Color; magenta: Color; cyan: Color; white: Color;
|
blue: string; magenta: string; cyan: string; white: string;
|
||||||
};
|
};
|
||||||
bright: {
|
bright: {
|
||||||
black: Color; red: Color; green: Color; yellow: Color;
|
black: string; red: string; green: string; yellow: string;
|
||||||
blue: Color; magenta: Color; cyan: Color; white: Color;
|
blue: string; magenta: string; cyan: string; white: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -18,61 +19,108 @@ import knownSchemesData from '../../formatted_themes.json';
|
|||||||
|
|
||||||
const knownSchemes: ColorScheme[] = knownSchemesData;
|
const knownSchemes: ColorScheme[] = knownSchemesData;
|
||||||
|
|
||||||
function generateRandomColor(): Color {
|
function generateRandomColor(): string {
|
||||||
return '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');
|
return '#' + Math.floor(Math.random()*16777215).toString(16).padStart(6, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateCreativeName(): string {
|
function generateCreativeName(colors: { [key: string]: string }): string {
|
||||||
const adjectives = ['Cosmic', 'Neon', 'Mystic', 'Retro', 'Cyber', 'Ethereal', 'Vibrant', 'Dreamy', 'Futuristic', 'Nostalgic'];
|
const allColors = Object.values(colors);
|
||||||
const nouns = ['Sunset', 'Aurora', 'Galaxy', 'Ocean', 'Forest', 'Desert', 'Nebula', 'Horizon', 'Oasis', 'Metropolis'];
|
const dominantColor = getDominantColor(allColors);
|
||||||
return `${adjectives[Math.floor(Math.random() * adjectives.length)]} ${nouns[Math.floor(Math.random() * nouns.length)]}`;
|
const mood = getMood(allColors);
|
||||||
|
const theme = getTheme(dominantColor);
|
||||||
|
|
||||||
|
const nameComponents = [mood, theme].filter(Boolean);
|
||||||
|
if (nameComponents.length === 1) {
|
||||||
|
nameComponents.push(getRandomAdjective(dominantColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nameComponents.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDominantColor(colors: string[]): Color {
|
||||||
|
return colors.reduce((dominant, color) => {
|
||||||
|
const current = Color(color);
|
||||||
|
return current.luminosity() > dominant.luminosity() ? current : dominant;
|
||||||
|
}, Color(colors[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMood(colors: string[]): string {
|
||||||
|
const avgSaturation = colors.reduce((sum, color) => sum + Color(color).saturationl(), 0) / colors.length;
|
||||||
|
const avgLightness = colors.reduce((sum, color) => sum + Color(color).lightness(), 0) / colors.length;
|
||||||
|
|
||||||
|
if (avgSaturation > 50 && avgLightness > 50) return 'Vibrant';
|
||||||
|
if (avgSaturation < 30 && avgLightness < 40) return 'Muted';
|
||||||
|
if (avgLightness > 70) return 'Bright';
|
||||||
|
if (avgLightness < 30) return 'Dark';
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTheme(dominantColor: Color): string {
|
||||||
|
const hue = dominantColor.hue();
|
||||||
|
const themes = [
|
||||||
|
{ name: 'Sunset', range: [0, 60] },
|
||||||
|
{ name: 'Citrus', range: [45, 90] },
|
||||||
|
{ name: 'Forest', range: [90, 150] },
|
||||||
|
{ name: 'Ocean', range: [150, 210] },
|
||||||
|
{ name: 'Twilight', range: [210, 270] },
|
||||||
|
{ name: 'Lavender', range: [270, 330] },
|
||||||
|
{ name: 'Berry', range: [330, 360] },
|
||||||
|
];
|
||||||
|
|
||||||
|
const theme = themes.find(t => hue >= t.range[0] && hue < t.range[1]);
|
||||||
|
return theme ? theme.name : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomAdjective(color: Color): string {
|
||||||
|
const adjectives = {
|
||||||
|
warm: ['Cozy', 'Toasty', 'Snug'],
|
||||||
|
cool: ['Crisp', 'Fresh', 'Breezy'],
|
||||||
|
neutral: ['Balanced', 'Harmonious', 'Zen'],
|
||||||
|
bright: ['Radiant', 'Luminous', 'Gleaming'],
|
||||||
|
dark: ['Mysterious', 'Enigmatic', 'Shadowy'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const hue = color.hue();
|
||||||
|
const lightness = color.lightness();
|
||||||
|
|
||||||
|
let category: keyof typeof adjectives;
|
||||||
|
if (hue < 60 || hue > 300) category = 'warm';
|
||||||
|
else if (hue >= 60 && hue <= 300) category = 'cool';
|
||||||
|
else if (lightness > 70) category = 'bright';
|
||||||
|
else if (lightness < 30) category = 'dark';
|
||||||
|
else category = 'neutral';
|
||||||
|
|
||||||
|
return adjectives[category][Math.floor(Math.random() * adjectives[category].length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateRandomScheme(): ColorScheme {
|
function generateRandomScheme(): ColorScheme {
|
||||||
let x = {
|
const colors = {
|
||||||
name: generateCreativeName() + "rand",
|
primary: { background: generateRandomColor(), foreground: generateRandomColor() },
|
||||||
colors: {
|
normal: {
|
||||||
primary: { background: generateRandomColor(), foreground: generateRandomColor() },
|
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
|
||||||
normal: {
|
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
|
||||||
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
|
},
|
||||||
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
|
bright: {
|
||||||
},
|
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
|
||||||
bright: {
|
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
|
||||||
black: generateRandomColor(), red: generateRandomColor(), green: generateRandomColor(), yellow: generateRandomColor(),
|
|
||||||
blue: generateRandomColor(), magenta: generateRandomColor(), cyan: generateRandomColor(), white: generateRandomColor()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
x.colors.primary.background = x.colors.normal.black;
|
colors.primary.background = colors.normal.black;
|
||||||
x.colors.primary.foreground = x.colors.bright.white;
|
colors.primary.foreground = colors.bright.white;
|
||||||
|
|
||||||
return x;
|
return {
|
||||||
}
|
name: generateCreativeName({ ...colors.normal, ...colors.bright }),
|
||||||
|
colors: colors
|
||||||
function crossTitles(title1: string, title2: string): string {
|
|
||||||
const words1 = title1.split(' ');
|
|
||||||
const words2 = title2.split(' ');
|
|
||||||
const firstWord = Math.random() < 0.5 ? words1[0] : words2[1];
|
|
||||||
const secondWord = Math.random() < 0.5 ? words2[0] : words1[1];
|
|
||||||
return `${firstWord} ${secondWord}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mutateColor(color: Color): Color {
|
|
||||||
const r = parseInt(color.slice(1, 3), 16);
|
|
||||||
const g = parseInt(color.slice(3, 5), 16);
|
|
||||||
const b = parseInt(color.slice(5, 7), 16);
|
|
||||||
|
|
||||||
const mutateComponent = (component: number) => {
|
|
||||||
const mutation = Math.floor(Math.random() * 51) - 25; // Random number between -25 and 25
|
|
||||||
return Math.max(0, Math.min(255, component + mutation));
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const newR = mutateComponent(r);
|
function mutateColor(color: string): string {
|
||||||
const newG = mutateComponent(g);
|
const c = Color(color);
|
||||||
const newB = mutateComponent(b);
|
const hue = (c.hue() + Math.random() * 30 - 15 + 360) % 360;
|
||||||
|
const saturation = Math.max(0, Math.min(100, c.saturationl() + Math.random() * 20 - 10));
|
||||||
return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}`;
|
const lightness = Math.max(0, Math.min(100, c.lightness() + Math.random() * 20 - 10));
|
||||||
|
return c.hsl(hue, saturation, lightness).hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislikedSchemes: ColorScheme[]): ColorScheme {
|
function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislikedSchemes: ColorScheme[]): ColorScheme {
|
||||||
@ -84,26 +132,26 @@ function generateSchemeFromGeneticAlgorithm(likedSchemes: ColorScheme[], dislike
|
|||||||
const newScheme: ColorScheme = JSON.parse(JSON.stringify(parentScheme)); // Deep copy
|
const newScheme: ColorScheme = JSON.parse(JSON.stringify(parentScheme)); // Deep copy
|
||||||
|
|
||||||
// Mutate colors
|
// Mutate colors
|
||||||
Object.keys(newScheme.colors).forEach((colorGroup) => {
|
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
|
||||||
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
|
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
|
||||||
if (Math.random() < 0.3) { // 30% chance of mutation
|
if (Math.random() < 0.3) { // 30% chance of mutation
|
||||||
newScheme.colors[colorGroup][colorName] = mutateColor(newScheme.colors[colorGroup][colorName]);
|
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Avoid similarities with disliked schemes
|
// Avoid similarities with disliked schemes
|
||||||
dislikedSchemes.forEach(dislikedScheme => {
|
dislikedSchemes.forEach(dislikedScheme => {
|
||||||
Object.keys(newScheme.colors).forEach((colorGroup) => {
|
Object.keys(newScheme.colors).forEach((colorGroup: keyof typeof newScheme.colors) => {
|
||||||
Object.keys(newScheme.colors[colorGroup]).forEach((colorName) => {
|
Object.keys(newScheme.colors[colorGroup]).forEach((colorName: string) => {
|
||||||
if (newScheme.colors[colorGroup][colorName] === dislikedScheme.colors[colorGroup][colorName]) {
|
if ((newScheme.colors[colorGroup] as any)[colorName] === (dislikedScheme.colors[colorGroup] as any)[colorName]) {
|
||||||
newScheme.colors[colorGroup][colorName] = mutateColor(newScheme.colors[colorGroup][colorName]);
|
(newScheme.colors[colorGroup] as any)[colorName] = mutateColor((newScheme.colors[colorGroup] as any)[colorName]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
newScheme.name = generateCreativeName() + "gen";
|
newScheme.name = generateCreativeName({ ...newScheme.colors.normal, ...newScheme.colors.bright });
|
||||||
return newScheme;
|
return newScheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
87
app/utils/exportFormats.ts
Normal file
87
app/utils/exportFormats.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { ColorScheme } from './colorSchemes';
|
||||||
|
|
||||||
|
export function generateYAML(scheme: ColorScheme): string {
|
||||||
|
return `colors:
|
||||||
|
# Default colors
|
||||||
|
primary:
|
||||||
|
background: '${scheme.colors.primary.background}'
|
||||||
|
foreground: '${scheme.colors.primary.foreground}'
|
||||||
|
|
||||||
|
# Normal colors
|
||||||
|
normal:
|
||||||
|
black: '${scheme.colors.normal.black}'
|
||||||
|
red: '${scheme.colors.normal.red}'
|
||||||
|
green: '${scheme.colors.normal.green}'
|
||||||
|
yellow: '${scheme.colors.normal.yellow}'
|
||||||
|
blue: '${scheme.colors.normal.blue}'
|
||||||
|
magenta: '${scheme.colors.normal.magenta}'
|
||||||
|
cyan: '${scheme.colors.normal.cyan}'
|
||||||
|
white: '${scheme.colors.normal.white}'
|
||||||
|
|
||||||
|
# Bright colors
|
||||||
|
bright:
|
||||||
|
black: '${scheme.colors.bright.black}'
|
||||||
|
red: '${scheme.colors.bright.red}'
|
||||||
|
green: '${scheme.colors.bright.green}'
|
||||||
|
yellow: '${scheme.colors.bright.yellow}'
|
||||||
|
blue: '${scheme.colors.bright.blue}'
|
||||||
|
magenta: '${scheme.colors.bright.magenta}'
|
||||||
|
cyan: '${scheme.colors.bright.cyan}'
|
||||||
|
white: '${scheme.colors.bright.white}'
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateJSON(scheme: ColorScheme): string {
|
||||||
|
return JSON.stringify(scheme.colors, null, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateXResources(scheme: ColorScheme): string {
|
||||||
|
return `*background: ${scheme.colors.primary.background}
|
||||||
|
*foreground: ${scheme.colors.primary.foreground}
|
||||||
|
|
||||||
|
*color0: ${scheme.colors.normal.black}
|
||||||
|
*color1: ${scheme.colors.normal.red}
|
||||||
|
*color2: ${scheme.colors.normal.green}
|
||||||
|
*color3: ${scheme.colors.normal.yellow}
|
||||||
|
*color4: ${scheme.colors.normal.blue}
|
||||||
|
*color5: ${scheme.colors.normal.magenta}
|
||||||
|
*color6: ${scheme.colors.normal.cyan}
|
||||||
|
*color7: ${scheme.colors.normal.white}
|
||||||
|
|
||||||
|
*color8: ${scheme.colors.bright.black}
|
||||||
|
*color9: ${scheme.colors.bright.red}
|
||||||
|
*color10: ${scheme.colors.bright.green}
|
||||||
|
*color11: ${scheme.colors.bright.yellow}
|
||||||
|
*color12: ${scheme.colors.bright.blue}
|
||||||
|
*color13: ${scheme.colors.bright.magenta}
|
||||||
|
*color14: ${scheme.colors.bright.cyan}
|
||||||
|
*color15: ${scheme.colors.bright.white}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateTOML(scheme: ColorScheme): string {
|
||||||
|
return `[colors.primary]
|
||||||
|
background = "${scheme.colors.primary.background}"
|
||||||
|
foreground = "${scheme.colors.primary.foreground}"
|
||||||
|
|
||||||
|
[colors.normal]
|
||||||
|
black = "${scheme.colors.normal.black}"
|
||||||
|
red = "${scheme.colors.normal.red}"
|
||||||
|
green = "${scheme.colors.normal.green}"
|
||||||
|
yellow = "${scheme.colors.normal.yellow}"
|
||||||
|
blue = "${scheme.colors.normal.blue}"
|
||||||
|
magenta = "${scheme.colors.normal.magenta}"
|
||||||
|
cyan = "${scheme.colors.normal.cyan}"
|
||||||
|
white = "${scheme.colors.normal.white}"
|
||||||
|
|
||||||
|
[colors.bright]
|
||||||
|
black = "${scheme.colors.bright.black}"
|
||||||
|
red = "${scheme.colors.bright.red}"
|
||||||
|
green = "${scheme.colors.bright.green}"
|
||||||
|
yellow = "${scheme.colors.bright.yellow}"
|
||||||
|
blue = "${scheme.colors.bright.blue}"
|
||||||
|
magenta = "${scheme.colors.bright.magenta}"
|
||||||
|
cyan = "${scheme.colors.bright.cyan}"
|
||||||
|
white = "${scheme.colors.bright.white}"
|
||||||
|
`;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
66
package-lock.json
generated
66
package-lock.json
generated
@ -8,6 +8,8 @@
|
|||||||
"name": "terminaltinder",
|
"name": "terminaltinder",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/color": "^3.0.6",
|
||||||
|
"color": "^4.2.3",
|
||||||
"framer-motion": "^11.5.4",
|
"framer-motion": "^11.5.4",
|
||||||
"next": "14.2.8",
|
"next": "14.2.8",
|
||||||
"prism-react-renderer": "^2.4.0",
|
"prism-react-renderer": "^2.4.0",
|
||||||
@ -485,6 +487,30 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/color": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-NMiNcZFRUAiUUCCf7zkAelY8eV3aKqfbzyFQlXpPIEeoNDbsEHGpb854V3gzTsGKYj830I5zPuOwU/TP5/cW6A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/color-convert": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/color-convert": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-2Q6wzrNiuEvYxVQqhh7sXM2mhIhvZR/Paq4FdsQkOMgWsCIkKvSGj8Le1/XalulrmgOzPMqNa0ix+ePY4hTrfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/color-name": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-hulKeREDdLFesGQjl96+4aoJSHY5b2GRjagzzcqCfIrWhe5vkCqIvrLbqzBaI1q94Vg8DNJZZqTR5ocdWmWclg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@ -1288,11 +1314,23 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/color": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1",
|
||||||
|
"color-string": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color-name": "~1.1.4"
|
"color-name": "~1.1.4"
|
||||||
@ -1305,9 +1343,18 @@
|
|||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/color-string": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "^1.0.0",
|
||||||
|
"simple-swizzle": "^0.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||||
@ -2856,6 +2903,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arrayish": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/is-async-function": {
|
"node_modules/is-async-function": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
|
||||||
@ -4582,6 +4635,15 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-swizzle": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-arrayish": "^0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/color": "^3.0.6",
|
||||||
|
"color": "^4.2.3",
|
||||||
"framer-motion": "^11.5.4",
|
"framer-motion": "^11.5.4",
|
||||||
"next": "14.2.8",
|
"next": "14.2.8",
|
||||||
"prism-react-renderer": "^2.4.0",
|
"prism-react-renderer": "^2.4.0",
|
||||||
|
7
public/settings-icon-dark.svg
Normal file
7
public/settings-icon-dark.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<g id="SVGRepo_iconCarrier"> <path d="M15 12C15 13.6569 13.6569 15 12 15C10.3431 15 9 13.6569 9 12C9 10.3431 10.3431 9 12 9C13.6569 9 15 10.3431 15 12Z" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12.9046 3.06005C12.6988 3 12.4659 3 12 3C11.5341 3 11.3012 3 11.0954 3.06005C10.7942 3.14794 10.5281 3.32808 10.3346 3.57511C10.2024 3.74388 10.1159 3.96016 9.94291 4.39272C9.69419 5.01452 9.00393 5.33471 8.36857 5.123L7.79779 4.93281C7.3929 4.79785 7.19045 4.73036 6.99196 4.7188C6.70039 4.70181 6.4102 4.77032 6.15701 4.9159C5.98465 5.01501 5.83376 5.16591 5.53197 5.4677C5.21122 5.78845 5.05084 5.94882 4.94896 6.13189C4.79927 6.40084 4.73595 6.70934 4.76759 7.01551C4.78912 7.2239 4.87335 7.43449 5.04182 7.85566C5.30565 8.51523 5.05184 9.26878 4.44272 9.63433L4.16521 9.80087C3.74031 10.0558 3.52786 10.1833 3.37354 10.3588C3.23698 10.5141 3.13401 10.696 3.07109 10.893C3 11.1156 3 11.3658 3 11.8663C3 12.4589 3 12.7551 3.09462 13.0088C3.17823 13.2329 3.31422 13.4337 3.49124 13.5946C3.69158 13.7766 3.96395 13.8856 4.50866 14.1035C5.06534 14.3261 5.35196 14.9441 5.16236 15.5129L4.94721 16.1584C4.79819 16.6054 4.72367 16.829 4.7169 17.0486C4.70875 17.3127 4.77049 17.5742 4.89587 17.8067C5.00015 18.0002 5.16678 18.1668 5.5 18.5C5.83323 18.8332 5.99985 18.9998 6.19325 19.1041C6.4258 19.2295 6.68733 19.2913 6.9514 19.2831C7.17102 19.2763 7.39456 19.2018 7.84164 19.0528L8.36862 18.8771C9.00393 18.6654 9.6942 18.9855 9.94291 19.6073C10.1159 20.0398 10.2024 20.2561 10.3346 20.4249C10.5281 20.6719 10.7942 20.8521 11.0954 20.94C11.3012 21 11.5341 21 12 21C12.4659 21 12.6988 21 12.9046 20.94C13.2058 20.8521 13.4719 20.6719 13.6654 20.4249C13.7976 20.2561 13.8841 20.0398 14.0571 19.6073C14.3058 18.9855 14.9961 18.6654 15.6313 18.8773L16.1579 19.0529C16.605 19.2019 16.8286 19.2764 17.0482 19.2832C17.3123 19.2913 17.5738 19.2296 17.8063 19.1042C17.9997 18.9999 18.1664 18.8333 18.4996 18.5001C18.8328 18.1669 18.9994 18.0002 19.1037 17.8068C19.2291 17.5743 19.2908 17.3127 19.2827 17.0487C19.2759 16.8291 19.2014 16.6055 19.0524 16.1584L18.8374 15.5134C18.6477 14.9444 18.9344 14.3262 19.4913 14.1035C20.036 13.8856 20.3084 13.7766 20.5088 13.5946C20.6858 13.4337 20.8218 13.2329 20.9054 13.0088C21 12.7551 21 12.4589 21 11.8663C21 11.3658 21 11.1156 20.9289 10.893C20.866 10.696 20.763 10.5141 20.6265 10.3588C20.4721 10.1833 20.2597 10.0558 19.8348 9.80087L19.5569 9.63416C18.9478 9.26867 18.6939 8.51514 18.9578 7.85558C19.1262 7.43443 19.2105 7.22383 19.232 7.01543C19.2636 6.70926 19.2003 6.40077 19.0506 6.13181C18.9487 5.94875 18.7884 5.78837 18.4676 5.46762C18.1658 5.16584 18.0149 5.01494 17.8426 4.91583C17.5894 4.77024 17.2992 4.70174 17.0076 4.71872C16.8091 4.73029 16.6067 4.79777 16.2018 4.93273L15.6314 5.12287C14.9961 5.33464 14.3058 5.0145 14.0571 4.39272C13.8841 3.96016 13.7976 3.74388 13.6654 3.57511C13.4719 3.32808 13.2058 3.14794 12.9046 3.06005Z" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
7
public/settings-icon-light.svg
Normal file
7
public/settings-icon-light.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||||
|
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<g id="SVGRepo_iconCarrier"> <path d="M15 12C15 13.6569 13.6569 15 12 15C10.3431 15 9 13.6569 9 12C9 10.3431 10.3431 9 12 9C13.6569 9 15 10.3431 15 12Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12.9046 3.06005C12.6988 3 12.4659 3 12 3C11.5341 3 11.3012 3 11.0954 3.06005C10.7942 3.14794 10.5281 3.32808 10.3346 3.57511C10.2024 3.74388 10.1159 3.96016 9.94291 4.39272C9.69419 5.01452 9.00393 5.33471 8.36857 5.123L7.79779 4.93281C7.3929 4.79785 7.19045 4.73036 6.99196 4.7188C6.70039 4.70181 6.4102 4.77032 6.15701 4.9159C5.98465 5.01501 5.83376 5.16591 5.53197 5.4677C5.21122 5.78845 5.05084 5.94882 4.94896 6.13189C4.79927 6.40084 4.73595 6.70934 4.76759 7.01551C4.78912 7.2239 4.87335 7.43449 5.04182 7.85566C5.30565 8.51523 5.05184 9.26878 4.44272 9.63433L4.16521 9.80087C3.74031 10.0558 3.52786 10.1833 3.37354 10.3588C3.23698 10.5141 3.13401 10.696 3.07109 10.893C3 11.1156 3 11.3658 3 11.8663C3 12.4589 3 12.7551 3.09462 13.0088C3.17823 13.2329 3.31422 13.4337 3.49124 13.5946C3.69158 13.7766 3.96395 13.8856 4.50866 14.1035C5.06534 14.3261 5.35196 14.9441 5.16236 15.5129L4.94721 16.1584C4.79819 16.6054 4.72367 16.829 4.7169 17.0486C4.70875 17.3127 4.77049 17.5742 4.89587 17.8067C5.00015 18.0002 5.16678 18.1668 5.5 18.5C5.83323 18.8332 5.99985 18.9998 6.19325 19.1041C6.4258 19.2295 6.68733 19.2913 6.9514 19.2831C7.17102 19.2763 7.39456 19.2018 7.84164 19.0528L8.36862 18.8771C9.00393 18.6654 9.6942 18.9855 9.94291 19.6073C10.1159 20.0398 10.2024 20.2561 10.3346 20.4249C10.5281 20.6719 10.7942 20.8521 11.0954 20.94C11.3012 21 11.5341 21 12 21C12.4659 21 12.6988 21 12.9046 20.94C13.2058 20.8521 13.4719 20.6719 13.6654 20.4249C13.7976 20.2561 13.8841 20.0398 14.0571 19.6073C14.3058 18.9855 14.9961 18.6654 15.6313 18.8773L16.1579 19.0529C16.605 19.2019 16.8286 19.2764 17.0482 19.2832C17.3123 19.2913 17.5738 19.2296 17.8063 19.1042C17.9997 18.9999 18.1664 18.8333 18.4996 18.5001C18.8328 18.1669 18.9994 18.0002 19.1037 17.8068C19.2291 17.5743 19.2908 17.3127 19.2827 17.0487C19.2759 16.8291 19.2014 16.6055 19.0524 16.1584L18.8374 15.5134C18.6477 14.9444 18.9344 14.3262 19.4913 14.1035C20.036 13.8856 20.3084 13.7766 20.5088 13.5946C20.6858 13.4337 20.8218 13.2329 20.9054 13.0088C21 12.7551 21 12.4589 21 11.8663C21 11.3658 21 11.1156 20.9289 10.893C20.866 10.696 20.763 10.5141 20.6265 10.3588C20.4721 10.1833 20.2597 10.0558 19.8348 9.80087L19.5569 9.63416C18.9478 9.26867 18.6939 8.51514 18.9578 7.85558C19.1262 7.43443 19.2105 7.22383 19.232 7.01543C19.2636 6.70926 19.2003 6.40077 19.0506 6.13181C18.9487 5.94875 18.7884 5.78837 18.4676 5.46762C18.1658 5.16584 18.0149 5.01494 17.8426 4.91583C17.5894 4.77024 17.2992 4.70174 17.0076 4.71872C16.8091 4.73029 16.6067 4.79777 16.2018 4.93273L15.6314 5.12287C14.9961 5.33464 14.3058 5.0145 14.0571 4.39272C13.8841 3.96016 13.7976 3.74388 13.6654 3.57511C13.4719 3.32808 13.2058 3.14794 12.9046 3.06005Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
@ -28,7 +28,7 @@ def map_theme_colors(theme_data):
|
|||||||
"foreground": theme_data.get("foreground", "#FFFFFF"),
|
"foreground": theme_data.get("foreground", "#FFFFFF"),
|
||||||
},
|
},
|
||||||
"normal": {
|
"normal": {
|
||||||
"black": theme_data.get("color_01", "#000000"),
|
"black": theme_data.get("background", "#000000"),
|
||||||
"red": theme_data.get("color_02", "#000000"),
|
"red": theme_data.get("color_02", "#000000"),
|
||||||
"green": theme_data.get("color_03", "#000000"),
|
"green": theme_data.get("color_03", "#000000"),
|
||||||
"yellow": theme_data.get("color_04", "#000000"),
|
"yellow": theme_data.get("color_04", "#000000"),
|
||||||
@ -45,7 +45,7 @@ def map_theme_colors(theme_data):
|
|||||||
"blue": theme_data.get("color_13", "#000000"),
|
"blue": theme_data.get("color_13", "#000000"),
|
||||||
"magenta": theme_data.get("color_14", "#000000"),
|
"magenta": theme_data.get("color_14", "#000000"),
|
||||||
"cyan": theme_data.get("color_15", "#000000"),
|
"cyan": theme_data.get("color_15", "#000000"),
|
||||||
"white": theme_data.get("color_16", "#000000"),
|
"white": theme_data.get("foreground", "#000000"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user