Add back extension popup files

This commit is contained in:
SethBurkart123
2023-09-19 20:50:04 +10:00
parent 88df9ec157
commit f34d0a3e77
33 changed files with 71 additions and 104 deletions
+6
View File
@@ -0,0 +1,6 @@
interface ColorPickerProps {
color: string;
onChange: (color: string) => void;
}
declare const Picker: ({ color, onChange }: ColorPickerProps) => import("react/jsx-runtime").JSX.Element;
export default Picker;
+45
View File
@@ -0,0 +1,45 @@
// TODO: Create types for ColorPicker
// @ts-expect-error No typescript declarations available
import ColorPicker from 'react-best-gradient-color-picker';
import { useState, useRef, useEffect } from 'react';
interface ColorPickerProps {
color: string;
onChange: (color: string) => void;
}
const Picker = ({ color, onChange }: ColorPickerProps) => {
const [showPicker, setShowPicker] = useState<boolean>(false);
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent): void => {
if (ref.current && !ref.current.contains(event.target as Node)) {
setShowPicker(false);
}
};
if (showPicker) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [showPicker]);
return (
<div className="">
<button
onClick={() => setShowPicker(!showPicker)}
style={{ background: color }}
className="w-16 h-8 rounded-md"
></button>
{showPicker && (
<div ref={ref} className="fixed top-0 left-0 z-50 p-4 bg-white border rounded-lg shadow-lg border-zinc-00">
<ColorPicker value={color} onChange={onChange} />
</div>
)}
</div>
);
};
export default Picker;
+21
View File
@@ -0,0 +1,21 @@
.range-slider{
margin: 20px;
appearance: none;
outline: none;
width: 150px;
height: 3px;
border-radius: 5px;
background-color: #ccc;
}
.range-slide::-webkit-slider-runnable-track{
background-color: #4BD663 !important;
}
.range-slider::-webkit-slider-thumb {
background: #fafafa;
appearance: none;
box-shadow: 1px 2px 26px 1px #bdbdbd;
width: 15px;
height: 15px;
border-radius: 50%;
}
+7
View File
@@ -0,0 +1,7 @@
import React from 'react';
import "./Slider.css";
interface Slider {
onValueChange: (value: number) => void;
}
declare const Slider: React.FC<Slider>;
export default Slider;
+35
View File
@@ -0,0 +1,35 @@
import React, { useState } from 'react';
import "./Slider.css";
interface Slider {
onValueChange: (value: number) => void;
}
const Slider: React.FC<Slider> = ({ onValueChange }) => {
const [sliderValue, setSliderValue] = useState(0);
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = parseInt(event.target.value, 10);
setSliderValue(value);
};
const handleMouseUp = () => {
onValueChange(sliderValue);
};
return (
<div className="relative">
<input
type="range"
min="0"
max="100"
value={sliderValue}
onChange={handleInputChange}
onMouseUp={handleMouseUp}
className="absolute w-full h-1 rounded-full cursor-pointer range-slider focus:outline-none"
/>
</div>
);
};
export default Slider;
+3
View File
@@ -0,0 +1,3 @@
.switch[data-ison="true"] {
background-color: #30D259;
}
+7
View File
@@ -0,0 +1,7 @@
import "./Switch.css";
interface SwitchProps {
onChange: (isOn: boolean) => void;
state: boolean;
}
export default function Switch(props: SwitchProps): import("react/jsx-runtime").JSX.Element;
export {};
+36
View File
@@ -0,0 +1,36 @@
import { motion } from "framer-motion";
import "./Switch.css";
interface SwitchProps {
onChange: (isOn: boolean) => void;
state: boolean;
}
export default function Switch(props: SwitchProps) {
const toggleSwitch = () => {
const newIsOn = !props.state;
props.onChange(newIsOn);
};
return (
<div
className="flex w-14 p-1 cursor-pointer rounded-full dark:bg-[#38373D] bg-[#DDDDDD] switch"
data-isOn={props.state}
onClick={toggleSwitch}
>
<motion.div
className="w-6 h-6 bg-white dark:bg-[#FEFEFE] rounded-full drop-shadow-md"
initial={{ x: props.state ? 0 : 0 }}
animate={{ x: props.state ? 24 : 0 }}
transition={spring}
/>
</div>
);
}
const spring = {
type: "spring",
stiffness: 700,
damping: 30
};
+11
View File
@@ -0,0 +1,11 @@
import React, { JSX } from 'react';
interface Tab {
title: string;
content: JSX.Element;
}
interface TabbedContainerProps {
tabs: Tab[];
themeColor: string;
}
declare const TabbedContainer: React.FC<TabbedContainerProps>;
export default TabbedContainer;
@@ -0,0 +1,92 @@
import React, { useState, useRef, useEffect } from 'react';
import { motion } from 'framer-motion';
interface Tab {
title: string;
content: JSX.Element;
}
interface TabbedContainerProps {
tabs: Tab[];
themeColor: string;
}
const TabbedContainer: React.FC<TabbedContainerProps> = ({ tabs, themeColor }) => {
const [activeTab, setActiveTab] = useState(0);
const [hoveredTab, setHoveredTab] = useState<number | null>(null);
const [tabWidth, setTabWidth] = useState(0);
const [position, setPosition] = useState(0);
const positionRef = useRef(position);
useEffect(() => {
const newPosition = -activeTab * 100;
setPosition(newPosition);
positionRef.current = newPosition;
}, [activeTab]);
const containerRef = useRef(null);
const springTransition = { type: 'spring', stiffness: 250, damping: 25 };
useEffect(() => {
if (containerRef.current) {
// @ts-expect-error for some reason its giving an error in TS but it works...
const width = containerRef.current.getBoundingClientRect().width;
setTabWidth(width / tabs.length);
}
}, [tabs.length]);
const calcXPos = (index: number | null) => {
if (index !== null) {
return tabWidth * index;
}
return tabWidth * activeTab;
};
return (
<div className="h-full px-4 overflow-y-scroll overflow-x-clip">
<div ref={containerRef} className="sticky top-0 z-10 text-[0.875rem] mb-2 pb-2 bg-white">
<div className="relative flex">
<motion.div
className="absolute top-0 left-0 z-0 h-full rounded-full opacity-40"
style={{ width: `${tabWidth}px`, background: themeColor }}
initial={false}
animate={{ x: calcXPos(hoveredTab) }}
transition={springTransition}
/>
{tabs.map((tab, index) => (
<button
key={index}
className="relative z-10 flex-1 px-4 py-2"
onClick={() => setActiveTab(index)}
onMouseEnter={() => setHoveredTab(index)}
onMouseLeave={() => setHoveredTab(null)}
>
{tab.title}
</button>
))}
</div>
</div>
<div className="relative">
<motion.div
initial={false}
animate={{ x: `${position}%` }}
transition={springTransition}
>
<div className="absolute flex w-full" style={{ left: `${-position}%` }}>
{tabs.map((tab, index) => (
<div
key={index}
className={`w-full ${activeTab === index ? '' : 'hidden'}`}
>
{tab.content}
</div>
))}
</div>
</motion.div>
</div>
</div>
);
};
export default TabbedContainer;