Add share button and share view. and cleanup
This commit is contained in:
295
app/components/CodePreview.tsx
Normal file
295
app/components/CodePreview.tsx
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Highlight, themes } from 'prism-react-renderer';
|
||||||
|
import { ColorScheme } from '../utils/colorSchemes';
|
||||||
|
import { CodeSample } from '../utils/types';
|
||||||
|
|
||||||
|
interface CodePreviewProps {
|
||||||
|
scheme: ColorScheme;
|
||||||
|
codeSample: CodeSample;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CodePreview: React.FC<CodePreviewProps> = ({ scheme, codeSample }) => {
|
||||||
|
const getCodeExample = () => {
|
||||||
|
const samples = {
|
||||||
|
c: `#include <stdio.h>
|
||||||
|
|
||||||
|
int is_prime(int n) {
|
||||||
|
if (n <= 1) return 0;
|
||||||
|
for (int i = 2; i * i <= n; i++) {
|
||||||
|
if (n % i == 0) return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_primes(int limit) {
|
||||||
|
printf("Primes up to %d:\n", limit);
|
||||||
|
for (int i = 2; i <= limit; i++) {
|
||||||
|
if (is_prime(i)) {
|
||||||
|
printf("%d ", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int limit = 50;
|
||||||
|
print_primes(limit);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}`,
|
||||||
|
java: `public class PrimeNumbers {
|
||||||
|
public static boolean isPrime(int n) {
|
||||||
|
if (n <= 1) return false;
|
||||||
|
for (int i = 2; i <= Math.sqrt(n); i++) {
|
||||||
|
if (n % i == 0) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void primesUpTo(int limit) {
|
||||||
|
System.out.println("Primes up to " + limit + ":");
|
||||||
|
for (int i = 2; i <= limit; i++) {
|
||||||
|
if (isPrime(i)) {
|
||||||
|
System.out.print(i + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
|
||||||
|
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: `/* Calculate the area and circumference of a circle */
|
||||||
|
const pi = 3.14;
|
||||||
|
|
||||||
|
function calculateArea(r) {
|
||||||
|
return pi * r ** 2; // Exponentiation, constant, operator
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateCircumference(r) {
|
||||||
|
return 2 * pi * r; // Function, return, operators
|
||||||
|
}
|
||||||
|
|
||||||
|
if (radius > 0) {
|
||||||
|
console.log(\`Area: $\{calculateArea(radius)\}\`); // Template string, method
|
||||||
|
console.log(\`Circumference: $\{calculateCircumference(radius)\}\`);
|
||||||
|
} else {
|
||||||
|
console.error("Invalid radius!"); // Error handling
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
radius = -1;
|
||||||
|
if (radius < 0) throw new Error("Negative radius"); // Throw, error
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e.message); // Catch block, method
|
||||||
|
}`,
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-100 dark:bg-gray-700 rounded-md overflow-x-auto">
|
||||||
|
<Highlight theme={themes.dracula} code={getCodeExample()} language={codeSample}>
|
||||||
|
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
||||||
|
<pre className={`${className} text-sm`} style={{ ...style, backgroundColor: scheme.colors.primary.background }}>
|
||||||
|
{tokens.map((line, i) => (
|
||||||
|
<div key={i} {...getLineProps({ line, key: i })}>
|
||||||
|
{line.map((token, key) => {
|
||||||
|
let color = scheme.colors.primary.foreground;
|
||||||
|
if (token.types.includes('keyword')) color = scheme.colors.normal.blue;
|
||||||
|
if (token.types.includes('string')) color = scheme.colors.normal.green;
|
||||||
|
if (token.types.includes('number')) color = scheme.colors.normal.magenta;
|
||||||
|
if (token.types.includes('comment')) color = scheme.colors.bright.black;
|
||||||
|
if (token.types.includes('function')) color = scheme.colors.normal.yellow;
|
||||||
|
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('constant')) color = scheme.colors.bright.red;
|
||||||
|
if (token.types.includes('punctuation')) color = scheme.colors.bright.cyan;
|
||||||
|
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 }} />;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</pre>
|
||||||
|
)}
|
||||||
|
</Highlight>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CodePreview;
|
@ -1,12 +1,12 @@
|
|||||||
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, encodeThemeForUrl } from '../utils/colorSchemes';
|
||||||
import { generateYAML, generateJSON, generateXResources, generateTOML, generateITerm2, generateWindowsTerminal, generateTerminalApp } from '../utils/exportFormats';
|
import { generateYAML, generateJSON, generateXResources, generateTOML, generateITerm2, generateWindowsTerminal, generateTerminalApp } from '../utils/exportFormats';
|
||||||
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';
|
||||||
import confetti from 'canvas-confetti';
|
import confetti from 'canvas-confetti';
|
||||||
import { AppSettings } from '../utils/types';
|
import { AppSettings } from '../utils/types';
|
||||||
|
import CodePreview from './CodePreview';
|
||||||
|
|
||||||
interface ColorSchemeCardProps {
|
interface ColorSchemeCardProps {
|
||||||
scheme: ColorScheme;
|
scheme: ColorScheme;
|
||||||
@ -21,234 +21,6 @@ const ColorSchemeCard: React.FC<ColorSchemeCardProps> = ({ scheme, onLike, onDis
|
|||||||
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 getCodeExample = () => {
|
|
||||||
if (settings.juniorDevMode) {
|
|
||||||
return `
|
|
||||||
// This code is perfect, no need to review
|
|
||||||
function makeItWork() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function does everything
|
|
||||||
function doEverything() {
|
|
||||||
// TODO: Implement
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore this, it's probably not important
|
|
||||||
try {
|
|
||||||
somethingRisky();
|
|
||||||
} catch (e) {
|
|
||||||
// This will never happen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy-pasted from StackOverflow
|
|
||||||
const regex = /^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,4})+$/;
|
|
||||||
|
|
||||||
// I'll fix this later
|
|
||||||
while (true) {
|
|
||||||
// Infinite loop for extra performance
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
const samples = {
|
|
||||||
c: `#include <stdio.h>
|
|
||||||
|
|
||||||
int is_prime(int n) {
|
|
||||||
if (n <= 1) return 0;
|
|
||||||
for (int i = 2; i * i <= n; i++) {
|
|
||||||
if (n % i == 0) return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_primes(int limit) {
|
|
||||||
printf("Primes up to %d:\n", limit);
|
|
||||||
for (int i = 2; i <= limit; i++) {
|
|
||||||
if (is_prime(i)) {
|
|
||||||
printf("%d ", i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
int limit = 50;
|
|
||||||
print_primes(limit);
|
|
||||||
|
|
||||||
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: `/* Calculate the area and circumference of a circle */
|
|
||||||
const pi = 3.14;
|
|
||||||
|
|
||||||
function calculateArea(r) {
|
|
||||||
return pi * r ** 2; // Exponentiation, constant, operator
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateCircumference(r) {
|
|
||||||
return 2 * pi * r; // Function, return, operators
|
|
||||||
}
|
|
||||||
|
|
||||||
if (radius > 0) {
|
|
||||||
console.log(\`Area: $\{calculateArea(radius)\}\`); // Template string, method
|
|
||||||
console.log(\`Circumference: $\{calculateCircumference(radius)\}\`);
|
|
||||||
} else {
|
|
||||||
console.error("Invalid radius!"); // Error handling
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
radius = -1;
|
|
||||||
if (radius < 0) throw new Error("Negative radius"); // Throw, error
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e.message); // Catch block, method
|
|
||||||
}`,
|
|
||||||
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`
|
|
||||||
};
|
|
||||||
|
|
||||||
type SampleLanguage = keyof typeof samples;
|
|
||||||
|
|
||||||
// Type guard to check if codeSample is a valid key of samples
|
|
||||||
const isValidSample = (sample: string): sample is SampleLanguage => {
|
|
||||||
return sample in samples;
|
|
||||||
};
|
|
||||||
|
|
||||||
return isValidSample(settings.codeSample) ? samples[settings.codeSample] : samples.javascript;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDownload = (e: React.MouseEvent) => {
|
const handleDownload = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
let content: string;
|
let content: string;
|
||||||
@ -315,6 +87,12 @@ fi`
|
|||||||
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 handleShare = (e: React.MouseEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const encodedTheme = encodeThemeForUrl(scheme);
|
||||||
|
window.open(`/share/${encodedTheme}`, '_blank');
|
||||||
|
};
|
||||||
|
|
||||||
const paletteColors = [
|
const paletteColors = [
|
||||||
scheme.colors.normal.black,
|
scheme.colors.normal.black,
|
||||||
scheme.colors.normal.red,
|
scheme.colors.normal.red,
|
||||||
@ -358,6 +136,13 @@ fi`
|
|||||||
/>
|
/>
|
||||||
<div className="flex justify-between items-center mb-2 z-10">
|
<div className="flex justify-between items-center mb-2 z-10">
|
||||||
<h2 className="text-lg font-semibold truncate">{scheme.name}</h2>
|
<h2 className="text-lg font-semibold truncate">{scheme.name}</h2>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<button
|
||||||
|
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors duration-300"
|
||||||
|
onClick={handleShare}
|
||||||
|
>
|
||||||
|
<Image src={isDarkMode ? "/share-icon-dark.svg" : "/share-icon-light.svg"} alt="Share" width={20} height={20} />
|
||||||
|
</button>
|
||||||
<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}
|
||||||
@ -365,71 +150,9 @@ fi`
|
|||||||
<Image src={isDarkMode ? "/download-icon-dark.svg" : "/download-icon-light.svg"} alt="Download" width={20} height={20} />
|
<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-2 flex-grow overflow-hidden z-10 shadow-md">
|
|
||||||
<Highlight theme={themes.dracula} code={getCodeExample()} language={settings.codeSample}>
|
|
||||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
|
||||||
<pre className={`${className} text-sm p-4 h-full overflow-auto`} style={{ ...style, backgroundColor: scheme.colors.primary.background }}>
|
|
||||||
{tokens.map((line, i) => (
|
|
||||||
<div key={i} {...getLineProps({ line, key: i })}>
|
|
||||||
{line.map((token, key) => {
|
|
||||||
let color = scheme.colors.primary.foreground;
|
|
||||||
if (token.types.includes('keyword')) color = scheme.colors.normal.blue;
|
|
||||||
if (token.types.includes('string')) color = scheme.colors.normal.green;
|
|
||||||
if (token.types.includes('number')) color = scheme.colors.normal.magenta;
|
|
||||||
if (token.types.includes('comment')) color = scheme.colors.bright.black;
|
|
||||||
if (token.types.includes('function')) color = scheme.colors.normal.yellow;
|
|
||||||
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('constant')) color = scheme.colors.bright.red;
|
|
||||||
if (token.types.includes('punctuation')) color = scheme.colors.bright.cyan;
|
|
||||||
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 }} />;
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
<div className="bg-gray-100 dark:bg-gray-700 rounded-md mb-2 flex-grow overflow-hidden z-10 shadow-md">
|
||||||
</pre>
|
<CodePreview scheme={scheme} codeSample={settings.codeSample} />
|
||||||
)}
|
|
||||||
</Highlight>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 z-10">
|
<div className="mt-2 z-10">
|
||||||
<ColorPalette
|
<ColorPalette
|
||||||
@ -437,18 +160,18 @@ fi`
|
|||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-center space-x-4 mt-2 z-10">
|
<div className="flex justify-center space-x-6 mt-4 z-10">
|
||||||
<button
|
<button
|
||||||
className="bg-red-500 text-white p-2 rounded-full shadow-lg hover:bg-red-600 transition-colors duration-300"
|
className="bg-red-500 text-white p-3 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={24} height={24} />
|
<Image src={isDarkMode ? "/cross-icon-dark.svg" : "/cross-icon-light.svg"} alt="Dislike" width={32} height={32} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="bg-green-500 text-white p-2 rounded-full shadow-lg hover:bg-green-600 transition-colors duration-300"
|
className="bg-green-500 text-white p-3 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={24} height={24} />
|
<Image src={isDarkMode ? "/heart-icon-dark.svg" : "/heart-icon-light.svg"} alt="Like" width={32} height={32} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,6 @@ interface SettingsProps {
|
|||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
isDarkMode: boolean;
|
isDarkMode: boolean;
|
||||||
onToggleDarkMode: () => void;
|
|
||||||
settings: AppSettings;
|
settings: AppSettings;
|
||||||
setSettings: (settings: AppSettings) => void;
|
setSettings: (settings: AppSettings) => void;
|
||||||
saveSettings: boolean;
|
saveSettings: boolean;
|
||||||
@ -18,7 +17,6 @@ const Settings: React.FC<SettingsProps> = ({
|
|||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
isDarkMode,
|
isDarkMode,
|
||||||
onToggleDarkMode,
|
|
||||||
settings,
|
settings,
|
||||||
setSettings,
|
setSettings,
|
||||||
saveSettings,
|
saveSettings,
|
||||||
@ -58,21 +56,6 @@ const Settings: React.FC<SettingsProps> = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span>Dark Mode</span>
|
|
||||||
<button
|
|
||||||
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>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block mb-2">Output Format</label>
|
<label className="block mb-2">Output Format</label>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
@ -176,7 +176,6 @@ export default function Home() {
|
|||||||
isOpen={isSettingsOpen}
|
isOpen={isSettingsOpen}
|
||||||
onClose={toggleSettings}
|
onClose={toggleSettings}
|
||||||
isDarkMode={isDarkMode}
|
isDarkMode={isDarkMode}
|
||||||
onToggleDarkMode={() => setIsDarkMode(!isDarkMode)}
|
|
||||||
settings={settings}
|
settings={settings}
|
||||||
setSettings={setSettings}
|
setSettings={setSettings}
|
||||||
saveSettings={saveSettings}
|
saveSettings={saveSettings}
|
||||||
|
143
app/share/[id]/page.tsx
Normal file
143
app/share/[id]/page.tsx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useParams } from 'next/navigation';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { ColorScheme, decodeThemeFromUrl } from '../../utils/colorSchemes';
|
||||||
|
import ColorPalette from '../../components/ColorPalette';
|
||||||
|
import CodePreview from '../../components/CodePreview';
|
||||||
|
import { CodeSample } from '../../utils/types';
|
||||||
|
import { generateYAML, generateJSON, generateXResources, generateTOML, generateITerm2, generateWindowsTerminal, generateTerminalApp } from '../../utils/exportFormats';
|
||||||
|
|
||||||
|
const SharedTheme: React.FC = () => {
|
||||||
|
const params = useParams();
|
||||||
|
const [scheme, setScheme] = useState<ColorScheme | null>(null);
|
||||||
|
const [codeSample, setCodeSample] = useState<CodeSample>('javascript');
|
||||||
|
const [outputFormat, setOutputFormat] = useState('yaml');
|
||||||
|
const [isDarkMode, setIsDarkMode] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (params.id) {
|
||||||
|
const decodedScheme = decodeThemeFromUrl(params.id as string);
|
||||||
|
setScheme(decodedScheme);
|
||||||
|
}
|
||||||
|
setIsDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
|
}, [params.id]);
|
||||||
|
|
||||||
|
if (!scheme) {
|
||||||
|
return <div>Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDownload = () => {
|
||||||
|
let content: string;
|
||||||
|
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 'iterm2':
|
||||||
|
content = generateITerm2(scheme);
|
||||||
|
fileExtension = 'itermcolors';
|
||||||
|
break;
|
||||||
|
case 'windows-terminal':
|
||||||
|
content = generateWindowsTerminal(scheme);
|
||||||
|
fileExtension = 'json';
|
||||||
|
break;
|
||||||
|
case 'terminal-app':
|
||||||
|
content = generateTerminalApp(scheme);
|
||||||
|
fileExtension = 'terminal';
|
||||||
|
break;
|
||||||
|
case 'yaml':
|
||||||
|
default:
|
||||||
|
content = generateYAML(scheme);
|
||||||
|
fileExtension = 'yaml';
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob([content], { type: 'text/plain' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${scheme.name.replace(/\s+/g, '_').toLowerCase()}.${fileExtension}`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<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-2 left-2 right-2 flex justify-between items-start z-20">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Image src="/app-icon.svg" alt="App Icon" width={32} height={32} className="mr-2" />
|
||||||
|
<div>
|
||||||
|
<h1 className="text-lg font-bold">TerminalTinder</h1>
|
||||||
|
<p className="text-xs">Fall in love with your next color scheme</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main className="pt-16 px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="max-w-3xl mx-auto bg-white dark:bg-gray-800 shadow-xl rounded-lg overflow-hidden">
|
||||||
|
<div className="p-8">
|
||||||
|
<h1 className="text-3xl font-bold mb-4">{scheme.name}</h1>
|
||||||
|
<div className="mb-6">
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Color Palette</h2>
|
||||||
|
<ColorPalette
|
||||||
|
colors={Object.values(scheme.colors.normal).concat(Object.values(scheme.colors.bright))}
|
||||||
|
size="large"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-6">
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Code Preview</h2>
|
||||||
|
<CodePreview scheme={scheme} codeSample={codeSample} />
|
||||||
|
</div>
|
||||||
|
<div className="mb-6">
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Download</h2>
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<select
|
||||||
|
value={outputFormat}
|
||||||
|
onChange={(e) => setOutputFormat(e.target.value)}
|
||||||
|
className="p-2 border rounded dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
>
|
||||||
|
<option value="yaml">YAML (Alacritty)</option>
|
||||||
|
<option value="json">JSON</option>
|
||||||
|
<option value="xresources">XResources</option>
|
||||||
|
<option value="toml">TOML (Alacritty)</option>
|
||||||
|
<option value="iterm2">iTerm2</option>
|
||||||
|
<option value="windows-terminal">Windows Terminal</option>
|
||||||
|
<option value="terminal-app">Terminal.app</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
onClick={handleDownload}
|
||||||
|
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 transition-colors duration-300"
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2 className="text-xl font-semibold mb-2">Share</h2>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={window.location.href}
|
||||||
|
readOnly
|
||||||
|
className="w-full p-2 border rounded bg-gray-100 dark:bg-gray-700 dark:border-gray-600"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SharedTheme;
|
@ -166,28 +166,6 @@ function getTheme(dominantColor: Color): string {
|
|||||||
return theme ? theme.name : '';
|
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(totalSchemes: number): ColorScheme {
|
function generateRandomScheme(totalSchemes: number): ColorScheme {
|
||||||
if (totalSchemes < 30) {
|
if (totalSchemes < 30) {
|
||||||
return generateCompletelyRandomScheme();
|
return generateCompletelyRandomScheme();
|
||||||
@ -351,5 +329,49 @@ function generateNoun(): string {
|
|||||||
return nouns[Math.floor(Math.random() * nouns.length)];
|
return nouns[Math.floor(Math.random() * nouns.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
|
||||||
|
export function encodeThemeForUrl(scheme: ColorScheme): string {
|
||||||
|
const encodedColors = Object.entries(scheme.colors).flatMap(([group, colors]) =>
|
||||||
|
Object.entries(colors).map(([name, color]) => color.slice(1))
|
||||||
|
).join('');
|
||||||
|
|
||||||
|
const data = JSON.stringify({
|
||||||
|
name: scheme.name,
|
||||||
|
colors: encodedColors
|
||||||
|
});
|
||||||
|
|
||||||
|
return Buffer.from(data).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decodeThemeFromUrl(encodedTheme: string): ColorScheme {
|
||||||
|
const base64 = encodedTheme.replace(/-/g, '+').replace(/_/g, '/');
|
||||||
|
const paddedBase64 = base64 + '='.repeat((4 - base64.length % 4) % 4);
|
||||||
|
const decodedString = Buffer.from(paddedBase64, 'base64').toString('utf-8');
|
||||||
|
const decoded = JSON.parse(decodedString);
|
||||||
|
const colors = decoded.colors.match(/.{6}/g);
|
||||||
|
|
||||||
|
const colorGroups = ['primary', 'normal', 'bright'];
|
||||||
|
const colorNames = {
|
||||||
|
primary: ['background', 'foreground'],
|
||||||
|
normal: ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'],
|
||||||
|
bright: ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']
|
||||||
|
};
|
||||||
|
|
||||||
|
let colorIndex = 0;
|
||||||
|
const decodedColors = colorGroups.reduce((acc: Record<string, Record<string, string>>, group) => {
|
||||||
|
acc[group] = colorNames[group as keyof typeof colorNames].reduce((groupAcc: Record<string, string>, name: string) => {
|
||||||
|
groupAcc[name] = `#${colors[colorIndex++]}`;
|
||||||
|
return groupAcc;
|
||||||
|
}, {});
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: decoded.name,
|
||||||
|
colors: decodedColors as ColorScheme['colors']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export type { ColorScheme };
|
export type { ColorScheme };
|
||||||
export { knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm };
|
export { knownSchemes, generateRandomScheme, generateSchemeFromGeneticAlgorithm };
|
7
public/share-icon-dark.svg
Normal file
7
public/share-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"/>
|
After Width: | Height: | Size: 936 B |
7
public/share-icon-light.svg
Normal file
7
public/share-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"/>
|
After Width: | Height: | Size: 936 B |
Reference in New Issue
Block a user