Compare commits
10 Commits
da0db483aa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
326ef4bf5e
|
|||
|
0018e56938
|
|||
|
178f5c88e8
|
|||
|
6c67604efc
|
|||
|
378dae159f
|
|||
|
c55ce3ad77
|
|||
|
434a27d90d
|
|||
|
94f0f3ca13
|
|||
|
637b3a0c34
|
|||
|
a61e7ce19a
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -7,10 +7,7 @@ dist
|
|||||||
*.local
|
*.local
|
||||||
.tanstack
|
.tanstack
|
||||||
*.tgz
|
*.tgz
|
||||||
test/coverage
|
coverage
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode
|
|
||||||
|
|
||||||
# Sonarqube
|
# Sonarqube
|
||||||
sonarBuild.sh
|
sonarBuild.sh
|
||||||
|
|||||||
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"sonarlint.connectedMode.project": {
|
||||||
|
"connectionId": "mattrixwvSonarqube",
|
||||||
|
"projectKey": "MattrixwvReactComponents"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,5 @@
|
|||||||
|
# Mattrixwv React Components
|
||||||
|
|
||||||
|
[](https://sonarqube.mattrixwv.com/dashboard?id=MattrixwvReactComponents)
|
||||||
|
|
||||||
Under Construction
|
Under Construction
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import type { CheckboxProps } from "$/types/InputTypes";
|
import type { CheckboxProps } from "$/types/InputTypes";
|
||||||
import { Checkbox } from "@headlessui/react";
|
import { Checkbox, Field, Label } from "@headlessui/react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvCheckbox({
|
export default function MattrixwvCheckbox({
|
||||||
id = crypto.randomUUID().replaceAll("-", ""),
|
|
||||||
className,
|
className,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
name,
|
name,
|
||||||
@@ -19,11 +18,13 @@ export default function MattrixwvCheckbox({
|
|||||||
children
|
children
|
||||||
}: Readonly<CheckboxProps>){
|
}: Readonly<CheckboxProps>){
|
||||||
return (
|
return (
|
||||||
|
<Field
|
||||||
|
className="flex flex-row items-center justify-center gap-x-2"
|
||||||
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={id}
|
data-testid="mattrixwv-checkbox"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group",
|
"group",
|
||||||
"flex flex-row items-center justify-start gap-x-2",
|
|
||||||
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
|
||||||
{
|
{
|
||||||
"cursor-pointer": !disabled,
|
"cursor-pointer": !disabled,
|
||||||
@@ -36,10 +37,10 @@ export default function MattrixwvCheckbox({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
value={value}
|
value={value}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
aria-labelledby={`${id}Label`}
|
|
||||||
>
|
>
|
||||||
{/* Checkbox */}
|
{/* Checkbox */}
|
||||||
<div
|
<div
|
||||||
|
data-testid="mattrixwv-checkbox-graphic"
|
||||||
className={clsx(
|
className={clsx(
|
||||||
className,
|
className,
|
||||||
{
|
{
|
||||||
@@ -68,16 +69,17 @@ export default function MattrixwvCheckbox({
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
</Checkbox>
|
||||||
{/* Label */}
|
{/* Label */}
|
||||||
{
|
{
|
||||||
children &&
|
children &&
|
||||||
<span
|
<Label
|
||||||
id={`${id}Label`}
|
data-testid="mattrixwv-checkbox-label"
|
||||||
className={labelClassName}
|
className={labelClassName}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</Label>
|
||||||
}
|
}
|
||||||
</Checkbox>
|
</Field>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,50 @@
|
|||||||
|
import { DangerButton } from "$/component/button";
|
||||||
import type { FileInputProps } from "$/types/InputTypes";
|
import type { FileInputProps } from "$/types/InputTypes";
|
||||||
import { humanReadableBytes } from "$/util/FileUtil";
|
import { humanReadableBytes } from "$/util/FileUtil";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
import { MdClose } from "react-icons/md";
|
||||||
|
|
||||||
|
|
||||||
export default function DragAndDropFileInput({
|
export default function DragAndDropFileInput({
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
name,
|
name,
|
||||||
|
ariaLabel,
|
||||||
minSize,
|
minSize,
|
||||||
maxSize,
|
maxSize,
|
||||||
showFileName,
|
showFileName = true,
|
||||||
showSize,
|
showSize = true,
|
||||||
onChange,
|
onChange,
|
||||||
disabled,
|
disabled,
|
||||||
children
|
children
|
||||||
}: FileInputProps){
|
}: Readonly<FileInputProps>){
|
||||||
const [ file, setFile ] = useState<File>();
|
const [ file, setFile ] = useState<File>();
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
onChange?.(file);
|
|
||||||
}, [ file, onChange ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-col items-center justify-center border-2 rounded-lg w-full h-full cursor-pointer",
|
"flex flex-col items-center justify-center border-2 rounded-lg cursor-pointer",
|
||||||
|
"data-drag:border-primary data-drag:text-primary",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
onDragOver={(e) => e.preventDefault()}
|
onDragOver={(e) => { e.preventDefault(); e.currentTarget.dataset.drag = "true"; }}
|
||||||
|
onDragLeave={(e) => { e.preventDefault(); delete e.currentTarget.dataset.drag; }}
|
||||||
onDrop={(e) => {
|
onDrop={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setFile(e.dataTransfer.files[0]);
|
delete e.currentTarget.dataset.drag;
|
||||||
|
|
||||||
|
const currentFile = e.dataTransfer.files[0];
|
||||||
|
setFile(currentFile);
|
||||||
|
|
||||||
|
if ((minSize && currentFile.size < minSize) || (maxSize && currentFile.size > maxSize)) return;
|
||||||
|
|
||||||
|
onChange?.(currentFile);
|
||||||
if(inputRef.current){ inputRef.current.files = e.dataTransfer.files; }
|
if(inputRef.current){ inputRef.current.files = e.dataTransfer.files; }
|
||||||
}}
|
}}
|
||||||
|
aria-label={ariaLabel}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
@@ -43,24 +52,40 @@ export default function DragAndDropFileInput({
|
|||||||
id={id}
|
id={id}
|
||||||
className="sr-only"
|
className="sr-only"
|
||||||
name={name}
|
name={name}
|
||||||
onChange={(e) => setFile(e.target.files?.[0])}
|
onChange={(e) => {
|
||||||
|
const currentFile = e.target.files?.[0];
|
||||||
|
setFile(currentFile);
|
||||||
|
if ((minSize && currentFile && currentFile.size < minSize) || (maxSize && currentFile && currentFile.size > maxSize)) return;
|
||||||
|
onChange?.(currentFile);
|
||||||
|
}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-between w-full h-full px-2"
|
className="flex flex-col items-center justify-between px-2"
|
||||||
>
|
>
|
||||||
|
<div className="flex flex-row items-center justify-center">
|
||||||
{children}
|
{children}
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className="flex flex-row items-center justify-between gap-x-8 w-full"
|
className="flex flex-row items-center justify-between gap-x-2 w-full"
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
showFileName &&
|
showFileName &&
|
||||||
<div
|
<div className="flex flex-row items-center justify-center gap-x-2">
|
||||||
className="text-center"
|
|
||||||
>
|
|
||||||
{file?.name}
|
{file?.name}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
file &&
|
||||||
|
<DangerButton
|
||||||
|
className="mr-4"
|
||||||
|
shape="square"
|
||||||
|
variant="icon"
|
||||||
|
onClick={(e) => { e.preventDefault(); setFile(undefined); onChange?.(undefined); }}
|
||||||
|
>
|
||||||
|
<MdClose size={22} className="fill-danger"/>
|
||||||
|
</DangerButton>
|
||||||
|
}
|
||||||
{
|
{
|
||||||
showSize &&
|
showSize &&
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
import { SecondaryButton } from "$/component/button";
|
import { DangerButton, SecondaryButton } from "$/component/button";
|
||||||
import type { FileInputProps } from "$/types/InputTypes";
|
import type { FileInputProps } from "$/types/InputTypes";
|
||||||
import { humanReadableBytes } from "$/util/FileUtil";
|
import { humanReadableBytes } from "$/util/FileUtil";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
import { FaRegFolderOpen } from "react-icons/fa6";
|
||||||
|
import { MdClose } from "react-icons/md";
|
||||||
|
|
||||||
|
|
||||||
export default function FileInput({
|
export default function FileInput({
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
name,
|
name,
|
||||||
|
ariaLabel,
|
||||||
minSize,
|
minSize,
|
||||||
maxSize,
|
maxSize,
|
||||||
showFileName,
|
showFileName = true,
|
||||||
showSize,
|
showSize = true,
|
||||||
onChange,
|
onChange,
|
||||||
disabled,
|
disabled,
|
||||||
children
|
children
|
||||||
}: FileInputProps){
|
}: Readonly<FileInputProps>){
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [ file, setFile ] = useState<File>();
|
const [ file, setFile ] = useState<File>();
|
||||||
|
|
||||||
@@ -24,7 +27,7 @@ export default function FileInput({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-row items-center justify-between w-full border-2 rounded-lg",
|
"flex flex-row items-center justify-between border-2 rounded-lg",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -34,7 +37,13 @@ export default function FileInput({
|
|||||||
type="file"
|
type="file"
|
||||||
className="sr-only"
|
className="sr-only"
|
||||||
name={name}
|
name={name}
|
||||||
onChange={(e) => { setFile(e.target.files?.[0]); onChange?.(e.target.files?.[0]); }}
|
aria-label={ariaLabel}
|
||||||
|
onChange={(e) => {
|
||||||
|
const currentFile = e.target.files?.[0];
|
||||||
|
setFile(currentFile);
|
||||||
|
if ((minSize && currentFile && currentFile.size < minSize) || (maxSize && currentFile && currentFile.size > maxSize)) return;
|
||||||
|
onChange?.(currentFile);
|
||||||
|
}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@@ -48,6 +57,16 @@ export default function FileInput({
|
|||||||
showFileName &&
|
showFileName &&
|
||||||
<div>{file?.name}</div>
|
<div>{file?.name}</div>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
file &&
|
||||||
|
<DangerButton
|
||||||
|
shape="square"
|
||||||
|
variant="icon"
|
||||||
|
onClick={(e) => { e.preventDefault(); setFile(undefined); onChange?.(undefined); }}
|
||||||
|
>
|
||||||
|
<MdClose size={22} className="fill-danger"/>
|
||||||
|
</DangerButton>
|
||||||
|
}
|
||||||
{
|
{
|
||||||
!children && !showFileName &&
|
!children && !showFileName &&
|
||||||
<> </>
|
<> </>
|
||||||
@@ -56,12 +75,13 @@ export default function FileInput({
|
|||||||
showSize &&
|
showSize &&
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
"ml-4",
|
||||||
{
|
{
|
||||||
"text-red-600": minSize && file?.size && file?.size < minSize,
|
"text-danger": minSize && file?.size && file?.size < minSize,
|
||||||
"text-red-600 ": maxSize && file?.size && file?.size > maxSize,
|
"text-danger ": maxSize && file?.size && file?.size > maxSize,
|
||||||
"text-green-600": minSize && !maxSize && file?.size && file?.size > minSize,
|
"text-success": minSize && !maxSize && file?.size && file?.size > minSize,
|
||||||
"text-green-600 ": !minSize && maxSize && file?.size && file?.size < maxSize,
|
"text-success ": !minSize && maxSize && file?.size && file?.size < maxSize,
|
||||||
" text-green-600": minSize && maxSize && file?.size && file?.size > minSize && file?.size < maxSize
|
" text-success": minSize && maxSize && file?.size && file?.size > minSize && file?.size < maxSize
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -75,10 +95,13 @@ export default function FileInput({
|
|||||||
<SecondaryButton
|
<SecondaryButton
|
||||||
className="text-nowrap rounded-r-lg"
|
className="text-nowrap rounded-r-lg"
|
||||||
rounding="none"
|
rounding="none"
|
||||||
|
shape="square"
|
||||||
|
size="lg"
|
||||||
onClick={() => { inputRef.current?.click(); }}
|
onClick={() => { inputRef.current?.click(); }}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
aria-label="Select File"
|
||||||
>
|
>
|
||||||
Click Me
|
<FaRegFolderOpen />
|
||||||
</SecondaryButton>
|
</SecondaryButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,22 +10,24 @@ export default function NumberInput({
|
|||||||
name,
|
name,
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
defaultValue,
|
step,
|
||||||
|
prefix,
|
||||||
|
suffix,
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disabled,
|
disabled,
|
||||||
children
|
children
|
||||||
}: NumberInputProps){
|
}: Readonly<NumberInputProps>){
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-row items-center justify-center rounded-lg border-2 w-full",
|
"flex flex-row items-center justify-center rounded-lg border-2",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div className="relative flex flex-row items-center justify-center px-2 py-1 w-full">
|
||||||
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
|
<div className="flex flex-row items-center justify-start">
|
||||||
>
|
{ prefix && <span>{prefix}</span> }
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id={id}
|
id={id}
|
||||||
@@ -37,11 +39,13 @@ export default function NumberInput({
|
|||||||
name={name}
|
name={name}
|
||||||
min={min}
|
min={min}
|
||||||
max={max}
|
max={max}
|
||||||
defaultValue={defaultValue}
|
step={step}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange?.(e.target.valueAsNumber)}
|
onChange={(e) => onChange(e.target.valueAsNumber || 0)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
|
{ suffix && <span>{suffix}</span> }
|
||||||
|
</div>
|
||||||
<label
|
<label
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
|
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
|
||||||
|
|||||||
@@ -9,28 +9,31 @@ export default function NumberSlider({
|
|||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
step,
|
step,
|
||||||
defaultValue,
|
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disabled
|
disabled,
|
||||||
}: NumberSliderProps){
|
ariaLabel
|
||||||
|
}: Readonly<NumberSliderProps>){
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
id={id}
|
id={id}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"w-full appearance-none [-moz-range-thumb:background:#04AA6D]",
|
"appearance-none [-moz-range-thumb:background:#04AA6D]",
|
||||||
"h-6 bg-blue-300 accent-blue-600",
|
"h-5 px-0.5 rounded-full bg-primary",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
name={name}
|
name={name}
|
||||||
min={min}
|
min={min}
|
||||||
max={max}
|
max={max}
|
||||||
step={step}
|
step={step}
|
||||||
defaultValue={defaultValue}
|
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange?.(e.target.valueAsNumber)}
|
onChange={(e) => onChange(e.target.valueAsNumber || 0)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
aria-valuemin={min}
|
||||||
|
aria-valuemax={max}
|
||||||
|
aria-valuenow={value}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,15 +3,13 @@ import { ListboxOption } from "@headlessui/react";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function OptionInput(props: OptionInputProps){
|
export default function OptionInput({
|
||||||
const {
|
|
||||||
id,
|
id,
|
||||||
className,
|
className,
|
||||||
value,
|
value,
|
||||||
|
disabled,
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<OptionInputProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListboxOption
|
<ListboxOption
|
||||||
id={id}
|
id={id}
|
||||||
@@ -20,6 +18,7 @@ export default function OptionInput(props: OptionInputProps){
|
|||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
value={value}
|
value={value}
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</ListboxOption>
|
</ListboxOption>
|
||||||
|
|||||||
@@ -4,28 +4,28 @@ import clsx from "clsx";
|
|||||||
import { BsChevronDown } from "react-icons/bs";
|
import { BsChevronDown } from "react-icons/bs";
|
||||||
|
|
||||||
|
|
||||||
export default function SelectInput(props: SelectInputProps){
|
export default function SelectInput({
|
||||||
const {
|
placeholder,
|
||||||
label,
|
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
disabled,
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<SelectInputProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Listbox
|
<Listbox
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<ListboxButton
|
<ListboxButton
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"group relative flex flex-row items-center justify-between w-full",
|
"group relative flex flex-row items-center justify-between w-full",
|
||||||
"border-2 px-2 py-1 rounded-lg"
|
"border-2 px-2 py-1 rounded-lg",
|
||||||
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2"
|
||||||
//"not-data-open:rounded-lg data-open:rounded-t-lg"
|
//"not-data-open:rounded-lg data-open:rounded-t-lg"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span>{label}</span>
|
<span>{placeholder}</span>
|
||||||
<span className="block group-data-open:rotate-180 transition-transform duration-250"><BsChevronDown size={22}/></span>
|
<span className="block group-data-open:rotate-180 transition-transform duration-250"><BsChevronDown size={22}/></span>
|
||||||
</ListboxButton>
|
</ListboxButton>
|
||||||
<ListboxOptions
|
<ListboxOptions
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
import type { TextAreaProps } from "$/types/InputTypes";
|
import type { TextAreaProps } from "$/types/InputTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function TextArea({
|
export default function TextArea({
|
||||||
id = crypto.randomUUID().replaceAll("-", ""),
|
id,
|
||||||
className,
|
className,
|
||||||
inputClassName,
|
inputClassName,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
name,
|
name,
|
||||||
maxLength,
|
maxLength,
|
||||||
rows,
|
rows = 3,
|
||||||
cols,
|
cols,
|
||||||
spellCheck,
|
spellCheck,
|
||||||
placeholder,
|
placeholder,
|
||||||
defaultValue,
|
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disabled
|
disabled
|
||||||
}: TextAreaProps){
|
}: Readonly<TextAreaProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -29,7 +33,7 @@ export default function TextArea({
|
|||||||
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
|
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
|
||||||
>
|
>
|
||||||
<textarea
|
<textarea
|
||||||
id={id}
|
id={activeId}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"peer bg-transparent outline-none placeholder-transparent w-full",
|
"peer bg-transparent outline-none placeholder-transparent w-full",
|
||||||
inputClassName
|
inputClassName
|
||||||
@@ -39,7 +43,6 @@ export default function TextArea({
|
|||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
cols={cols}
|
cols={cols}
|
||||||
defaultValue={defaultValue}
|
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
@@ -54,7 +57,7 @@ export default function TextArea({
|
|||||||
labelClassName
|
labelClassName
|
||||||
)}
|
)}
|
||||||
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
||||||
htmlFor={id}
|
htmlFor={activeId}
|
||||||
>
|
>
|
||||||
{placeholder}
|
{placeholder}
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import type { TextInputProps } from "$/types/InputTypes";
|
import type { TextInputProps } from "$/types/InputTypes";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function TextInput({
|
export default function TextInput({
|
||||||
id = crypto.randomUUID().replaceAll("-", ""),
|
id,
|
||||||
className,
|
className,
|
||||||
inputClassName,
|
inputClassName,
|
||||||
labelClassName,
|
labelClassName,
|
||||||
@@ -11,11 +12,14 @@ export default function TextInput({
|
|||||||
maxLength,
|
maxLength,
|
||||||
spellCheck,
|
spellCheck,
|
||||||
placeholder,
|
placeholder,
|
||||||
defaultValue,
|
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disabled
|
disabled
|
||||||
}: TextInputProps){
|
}: Readonly<TextInputProps>){
|
||||||
|
const componentId = useId();
|
||||||
|
const activeId = id ?? componentId;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -28,7 +32,7 @@ export default function TextInput({
|
|||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
id={id}
|
id={activeId}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"peer bg-transparent outline-none placeholder-transparent w-full",
|
"peer bg-transparent outline-none placeholder-transparent w-full",
|
||||||
inputClassName
|
inputClassName
|
||||||
@@ -36,7 +40,6 @@ export default function TextInput({
|
|||||||
name={name}
|
name={name}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
maxLength={maxLength}
|
maxLength={maxLength}
|
||||||
defaultValue={defaultValue}
|
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
@@ -51,7 +54,7 @@ export default function TextInput({
|
|||||||
labelClassName
|
labelClassName
|
||||||
)}
|
)}
|
||||||
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
|
||||||
htmlFor={id}
|
htmlFor={activeId}
|
||||||
>
|
>
|
||||||
{placeholder}
|
{placeholder}
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function CenterGrowingBars({
|
export default function CenterGrowingBars({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBarsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBarsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale-middle.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale-middle.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -26,22 +36,22 @@ export default function CenterGrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
@@ -52,22 +62,22 @@ export default function CenterGrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
@@ -78,23 +88,23 @@ export default function CenterGrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle3_${id}`}
|
id={`rectangle3_${id}`}
|
||||||
begin={`0;rectangle5_${id}.end-${animationDuration / 6}s`}
|
begin={`0;rectangle5_${id}.end-${dur / 6}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle5_${id}.end-${animationDuration / 6}s`}
|
begin={`0;rectangle5_${id}.end-${dur / 6}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
@@ -105,22 +115,22 @@ export default function CenterGrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
@@ -131,23 +141,23 @@ export default function CenterGrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle5_${id}`}
|
id={`rectangle5_${id}`}
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle3_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle3_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
keySplines=".14,.73,.34,1;.65,.26,.82,.45"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleBars({
|
export default function CircleBars({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBarsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBarsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-rotate-fade.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-rotate-fade.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,8 +36,8 @@ export default function CircleBars({
|
|||||||
height="5"
|
height="5"
|
||||||
opacity=".14"
|
opacity=".14"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -38,8 +47,8 @@ export default function CircleBars({
|
|||||||
transform="rotate(30 12 12)"
|
transform="rotate(30 12 12)"
|
||||||
opacity=".29"
|
opacity=".29"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -49,8 +58,8 @@ export default function CircleBars({
|
|||||||
transform="rotate(60 12 12)"
|
transform="rotate(60 12 12)"
|
||||||
opacity=".43"
|
opacity=".43"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -60,8 +69,8 @@ export default function CircleBars({
|
|||||||
transform="rotate(90 12 12)"
|
transform="rotate(90 12 12)"
|
||||||
opacity=".57"
|
opacity=".57"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -71,8 +80,8 @@ export default function CircleBars({
|
|||||||
transform="rotate(120 12 12)"
|
transform="rotate(120 12 12)"
|
||||||
opacity=".71"
|
opacity=".71"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -82,8 +91,8 @@ export default function CircleBars({
|
|||||||
transform="rotate(150 12 12)"
|
transform="rotate(150 12 12)"
|
||||||
opacity=".86"
|
opacity=".86"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -92,14 +101,14 @@ export default function CircleBars({
|
|||||||
height="5"
|
height="5"
|
||||||
transform="rotate(180 12 12)"
|
transform="rotate(180 12 12)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
calcMode="discrete"
|
calcMode="discrete"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12"
|
values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function FadingBars({
|
export default function FadingBars({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBarsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBarsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-fade.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-fade.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,14 +37,14 @@ export default function FadingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity="1"
|
opacity="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_${id}`}
|
id={`rectangle1_${id}`}
|
||||||
begin={`0;rectangle3_${id}.end-${animationDuration / 3}s`}
|
begin={`0;rectangle3_${id}.end-${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -46,13 +56,13 @@ export default function FadingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity=".4"
|
opacity=".4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -64,14 +74,14 @@ export default function FadingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity=".3"
|
opacity=".3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle3_${id}`}
|
id={`rectangle3_${id}`}
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function FadingGrowingBars({
|
export default function FadingGrowingBars({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBarsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBarsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale-fade.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale-fade.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,28 +37,28 @@ export default function FadingGrowingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity="1"
|
opacity="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_${id}`}
|
id={`rectangle1_${id}`}
|
||||||
begin={`0;rectangle3_${id}.end-${animationDuration / 3}s`}
|
begin={`0;rectangle3_${id}.end-${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;5"
|
values="1;5"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle3_${id}.end-${animationDuration / 3}s`}
|
begin={`0;rectangle3_${id}.end-${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="22;14"
|
values="22;14"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle3_${id}.end-${animationDuration / 3}s`}
|
begin={`0;rectangle3_${id}.end-${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -60,27 +70,27 @@ export default function FadingGrowingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity=".4"
|
opacity=".4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;5"
|
values="1;5"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="22;14"
|
values="22;14"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -92,28 +102,28 @@ export default function FadingGrowingBars({
|
|||||||
height="14"
|
height="14"
|
||||||
opacity=".3"
|
opacity=".3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle3_${id}`}
|
id={`rectangle3_${id}`}
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 5}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;5"
|
values="1;5"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 5}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="22;14"
|
values="22;14"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 5}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
import type { LoadingBarsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function GrowingBars({
|
export default function GrowingBars({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBarsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBarsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bars-scale.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -26,23 +36,23 @@ export default function GrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_${id}`}
|
id={`rectangle1_${id}`}
|
||||||
begin={`0;rectangle5_${id}.end-${animationDuration / 6}s`}
|
begin={`0;rectangle5_${id}.end-${dur / 6}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle5_${id}.end-${animationDuration / 6}s`}
|
begin={`0;rectangle5_${id}.end-${dur / 6}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
@@ -53,22 +63,22 @@ export default function GrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
@@ -79,22 +89,22 @@ export default function GrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
@@ -105,22 +115,22 @@ export default function GrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
@@ -131,23 +141,23 @@ export default function GrowingBars({
|
|||||||
width="2.8"
|
width="2.8"
|
||||||
height="12"
|
height="12"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle5_${id}`}
|
id={`rectangle5_${id}`}
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="6;1;6"
|
values="6;1;6"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;22;12"
|
values="12;22;12"
|
||||||
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
keySplines=".36,.61,.3,.98;.36,.61,.3,.98"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function PulsingBlocks({
|
export default function PulsingBlocks({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBlocksProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBlocksProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-scale.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-scale.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,35 +37,35 @@ export default function PulsingBlocks({
|
|||||||
width="9"
|
width="9"
|
||||||
height="9"
|
height="9"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_${id}`}
|
id={`rectangle1_${id}`}
|
||||||
begin={`0;rectangle4_${id}.end+${animationDuration / 4}s`}
|
begin={`0;rectangle4_${id}.end+${dur / 4}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;.5;1.5"
|
values="1.5;.5;1.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle4_${id}.end+${animationDuration / 4}s`}
|
begin={`0;rectangle4_${id}.end+${dur / 4}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;.5;1.5"
|
values="1.5;.5;1.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle4_${id}.end+${animationDuration / 4}s`}
|
begin={`0;rectangle4_${id}.end+${dur / 4}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle4_${id}.end+${animationDuration / 4}s`}
|
begin={`0;rectangle4_${id}.end+${dur / 4}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
@@ -67,34 +77,34 @@ export default function PulsingBlocks({
|
|||||||
width="9"
|
width="9"
|
||||||
height="9"
|
height="9"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur / 4}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13.5;12.5;13.5"
|
values="13.5;12.5;13.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur / 4}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;.5;1.5"
|
values="1.5;.5;1.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur / 4}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur / 4}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
@@ -106,34 +116,34 @@ export default function PulsingBlocks({
|
|||||||
width="9"
|
width="9"
|
||||||
height="9"
|
height="9"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13.5;12.5;13.5"
|
values="13.5;12.5;13.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13.5;12.5;13.5"
|
values="13.5;12.5;13.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
@@ -145,35 +155,35 @@ export default function PulsingBlocks({
|
|||||||
width="9"
|
width="9"
|
||||||
height="9"
|
height="9"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle4_${id}`}
|
id={`rectangle4_${id}`}
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 3 / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur * 3 / 4}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;.5;1.5"
|
values="1.5;.5;1.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 3 / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur * 3 / 4}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13.5;12.5;13.5"
|
values="13.5;12.5;13.5"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 3 / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur * 3 / 4}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_${id}.begin+${animationDuration * 3 / 4}s`}
|
begin={`rectangle1_${id}.begin+${dur * 3 / 4}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="9;11;9"
|
values="9;11;9"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function SlidingBlocks2({
|
export default function SlidingBlocks2({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.2,
|
animationDuration = 200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBlocksProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBlocksProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-shuffle-2.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-shuffle-2.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,14 +37,14 @@ export default function SlidingBlocks2({
|
|||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_1_${id}`}
|
id={`rectangle1_1_${id}`}
|
||||||
begin={`0;rectangle2_4_${id}.end`}
|
begin={`0;rectangle2_4_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -42,7 +52,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle1_2_${id}`}
|
id={`rectangle1_2_${id}`}
|
||||||
begin={`rectangle2_1_${id}.end`}
|
begin={`rectangle2_1_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -50,7 +60,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle1_3_${id}`}
|
id={`rectangle1_3_${id}`}
|
||||||
begin={`rectangle2_2_${id}.end`}
|
begin={`rectangle2_2_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -58,7 +68,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle1_4_${id}`}
|
id={`rectangle1_4_${id}`}
|
||||||
begin={`rectangle2_3_${id}.end`}
|
begin={`rectangle2_3_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -70,14 +80,14 @@ export default function SlidingBlocks2({
|
|||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle2_1_${id}`}
|
id={`rectangle2_1_${id}`}
|
||||||
begin={`rectangle1_1_${id}.end`}
|
begin={`rectangle1_1_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -85,7 +95,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle2_2_${id}`}
|
id={`rectangle2_2_${id}`}
|
||||||
begin={`rectangle1_2_${id}.end`}
|
begin={`rectangle1_2_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -93,7 +103,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle2_3_${id}`}
|
id={`rectangle2_3_${id}`}
|
||||||
begin={`rectangle1_3_${id}.end`}
|
begin={`rectangle1_3_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -101,7 +111,7 @@ export default function SlidingBlocks2({
|
|||||||
id={`rectangle2_4_${id}`}
|
id={`rectangle2_4_${id}`}
|
||||||
begin={`rectangle1_4_${id}.end`}
|
begin={`rectangle1_4_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function SlidingBlocks3({
|
export default function SlidingBlocks3({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.2,
|
animationDuration = 200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBlocksProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBlocksProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-shuffle-3.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-shuffle-3.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,14 +37,14 @@ export default function SlidingBlocks3({
|
|||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_1_${id}`}
|
id={`rectangle1_1_${id}`}
|
||||||
begin={`0;rectangle3_4_${id}.end`}
|
begin={`0;rectangle3_4_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -42,7 +52,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle1_2_${id}`}
|
id={`rectangle1_2_${id}`}
|
||||||
begin={`rectangle3_1_${id}.end`}
|
begin={`rectangle3_1_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -50,7 +60,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle1_3_${id}`}
|
id={`rectangle1_3_${id}`}
|
||||||
begin={`rectangle3_2_${id}.end`}
|
begin={`rectangle3_2_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -58,7 +68,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle1_4_${id}`}
|
id={`rectangle1_4_${id}`}
|
||||||
begin={`rectangle3_3_${id}.end`}
|
begin={`rectangle3_3_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -70,14 +80,14 @@ export default function SlidingBlocks3({
|
|||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle2_1_${id}`}
|
id={`rectangle2_1_${id}`}
|
||||||
begin={`rectangle1_1_${id}.end`}
|
begin={`rectangle1_1_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -85,7 +95,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle2_2_${id}`}
|
id={`rectangle2_2_${id}`}
|
||||||
begin={`rectangle1_2_${id}.end`}
|
begin={`rectangle1_2_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -93,7 +103,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle2_3_${id}`}
|
id={`rectangle2_3_${id}`}
|
||||||
begin={`rectangle1_3_${id}.end`}
|
begin={`rectangle1_3_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -101,7 +111,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle2_4_${id}`}
|
id={`rectangle2_4_${id}`}
|
||||||
begin={`rectangle1_4_${id}.end`}
|
begin={`rectangle1_4_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -113,14 +123,14 @@ export default function SlidingBlocks3({
|
|||||||
width="10"
|
width="10"
|
||||||
height="10"
|
height="10"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle3_1_${id}`}
|
id={`rectangle3_1_${id}`}
|
||||||
begin={`rectangle2_1_${id}.end`}
|
begin={`rectangle2_1_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -128,7 +138,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle3_2_${id}`}
|
id={`rectangle3_2_${id}`}
|
||||||
begin={`rectangle2_2_${id}.end`}
|
begin={`rectangle2_2_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="13;1"
|
values="13;1"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -136,7 +146,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle3_3_${id}`}
|
id={`rectangle3_3_${id}`}
|
||||||
begin={`rectangle2_3_${id}.end`}
|
begin={`rectangle2_3_${id}.end`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -144,7 +154,7 @@ export default function SlidingBlocks3({
|
|||||||
id={`rectangle3_4_${id}`}
|
id={`rectangle3_4_${id}`}
|
||||||
begin={`rectangle2_4_${id}.end`}
|
begin={`rectangle2_4_${id}.end`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;13"
|
values="1;13"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
import type { LoadingBlocksProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function WaveBlocks({
|
export default function WaveBlocks({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingBlocksProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingBlocksProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-wave.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/blocks-wave.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -26,32 +36,32 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle1_1_${id}`}
|
id={`rectangle1_1_${id}`}
|
||||||
begin={`0;rectangle9_1_${id}.end+${animationDuration / 3}s`}
|
begin={`0;rectangle9_1_${id}.end+${dur / 3}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle9_1_${id}.end+${animationDuration / 3}s`}
|
begin={`0;rectangle9_1_${id}.end+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle9_1_${id}.end+${animationDuration / 3}s`}
|
begin={`0;rectangle9_1_${id}.end+${dur / 3}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;rectangle9_1_${id}.end+${animationDuration / 3}s`}
|
begin={`0;rectangle9_1_${id}.end+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -61,31 +71,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -95,31 +105,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 6}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -129,31 +139,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -163,31 +173,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -197,31 +207,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;4;1"
|
values="1;4;1"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -231,31 +241,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -265,31 +275,31 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8.33;11.33;8.33"
|
values="8.33;11.33;8.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration / 2}s`}
|
begin={`rectangle1_1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
@@ -299,32 +309,32 @@ export default function WaveBlocks({
|
|||||||
width="7.33"
|
width="7.33"
|
||||||
height="7.33"
|
height="7.33"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`rectangle9_1_${id}`}
|
id={`rectangle9_1_${id}`}
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="x"
|
attributeName="x"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="y"
|
attributeName="y"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15.66;18.66;15.66"
|
values="15.66;18.66;15.66"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="width"
|
attributeName="width"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`rectangle1_1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`rectangle1_1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="height"
|
attributeName="height"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="7.33;1.33;7.33"
|
values="7.33;1.33;7.33"
|
||||||
/>
|
/>
|
||||||
</rect>
|
</rect>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function BouncingDots({
|
export default function BouncingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-bounce.svg?short_path=50864c0
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-bounce.svg?short_path=50864c0
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,15 +35,15 @@ export default function BouncingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`firstBouncingDots_${id}`}
|
id={`firstBouncingDots_${id}`}
|
||||||
begin={`0;lastBouncingDots_${id}.end+${animationDuration / 2}s`}
|
begin={`0;lastBouncingDots_${id}.end+${dur / 2}s`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;6;12"
|
values="12;6;12"
|
||||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
/>
|
/>
|
||||||
@@ -43,15 +53,15 @@ export default function BouncingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`secondBouncingDots_${id}`}
|
id={`secondBouncingDots_${id}`}
|
||||||
begin={`firstBouncingDots_${id}.begin+${animationDuration / 5}s`}
|
begin={`firstBouncingDots_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;6;12"
|
values="12;6;12"
|
||||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
/>
|
/>
|
||||||
@@ -61,15 +71,15 @@ export default function BouncingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`lastBouncingDots_${id}`}
|
id={`lastBouncingDots_${id}`}
|
||||||
begin={`secondBouncingDots_${id}.begin+${animationDuration / 5}s`}
|
begin={`secondBouncingDots_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12;6;12"
|
values="12;6;12"
|
||||||
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
keySplines=".33,.66,.66,1;.33,0,.66,.33"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleCenterDots({
|
export default function CircleCenterDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-scale-middle.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-scale-middle.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,15 +35,15 @@ export default function CircleCenterDots({
|
|||||||
cy="3"
|
cy="3"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle1_${id}`}
|
id={`circle1_${id}`}
|
||||||
begin={`0;circle3_${id}.end-${animationDuration * 5 / 6}s`}
|
begin={`0;circle3_${id}.end-${dur * 5 / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -43,15 +53,15 @@ export default function CircleCenterDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle2_${id}`}
|
id={`circle2_${id}`}
|
||||||
begin={`circle1_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -61,15 +71,15 @@ export default function CircleCenterDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle3_${id}`}
|
id={`circle3_${id}`}
|
||||||
begin={`circle5_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle5_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -79,15 +89,15 @@ export default function CircleCenterDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle4_${id}`}
|
id={`circle4_${id}`}
|
||||||
begin={`circle2_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle2_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -97,15 +107,15 @@ export default function CircleCenterDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle5_${id}`}
|
id={`circle5_${id}`}
|
||||||
begin={`circle7_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle7_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -115,14 +125,14 @@ export default function CircleCenterDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle6_${id}`}
|
id={`circle6_${id}`}
|
||||||
begin={`circle4_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle4_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -132,15 +142,15 @@ export default function CircleCenterDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle7_${id}`}
|
id={`circle7_${id}`}
|
||||||
begin={`circle9_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle9_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -150,15 +160,15 @@ export default function CircleCenterDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle8_${id}`}
|
id={`circle8_${id}`}
|
||||||
begin={`circle6_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle6_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -168,15 +178,15 @@ export default function CircleCenterDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle9_${id}`}
|
id={`circle9_${id}`}
|
||||||
begin={`circle11_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle11_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -186,15 +196,15 @@ export default function CircleCenterDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle10_${id}`}
|
id={`circle10_${id}`}
|
||||||
begin={`circle8_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle8_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -204,15 +214,15 @@ export default function CircleCenterDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle11_${id}`}
|
id={`circle11_${id}`}
|
||||||
begin={`circle12_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle12_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -221,16 +231,16 @@ export default function CircleCenterDots({
|
|||||||
cx="12"
|
cx="12"
|
||||||
cy="21"
|
cy="21"
|
||||||
r="0"
|
r="0"
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
className={className}
|
className={className}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle12_${id}`}
|
id={`circle12_${id}`}
|
||||||
begin={`circle10_${id}.begin+${animationDuration / 6}s`}
|
begin={`circle10_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleFadingDots({
|
export default function CircleFadingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-rotate.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-rotate.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,8 +35,8 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".14"
|
opacity=".14"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="16.75"
|
cx="16.75"
|
||||||
@@ -33,8 +44,8 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".29"
|
opacity=".29"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="20.23"
|
cx="20.23"
|
||||||
@@ -42,8 +53,8 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".43"
|
opacity=".43"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="21.50"
|
cx="21.50"
|
||||||
@@ -51,8 +62,8 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".57"
|
opacity=".57"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="20.23"
|
cx="20.23"
|
||||||
@@ -60,8 +71,8 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".71"
|
opacity=".71"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="16.75"
|
cx="16.75"
|
||||||
@@ -69,22 +80,22 @@ export default function CircleFadingDots({
|
|||||||
r="1.5"
|
r="1.5"
|
||||||
opacity=".86"
|
opacity=".86"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="12"
|
cx="12"
|
||||||
cy="21.5"
|
cy="21.5"
|
||||||
r="1.5"
|
r="1.5"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
calcMode="discrete"
|
calcMode="discrete"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12"
|
values="0 12 12;30 12 12;60 12 12;90 12 12;120 12 12;150 12 12;180 12 12;210 12 12;240 12 12;270 12 12;300 12 12;330 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,23 +1,34 @@
|
|||||||
import type { CirclePulsingDotsProps } from "$/types/LoadingTypes";
|
import type { CirclePulsingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function CirclePulsingDots({
|
export default function CirclePulsingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
rotationAnimationDuration = 6,
|
rotationAnimationDuration = 6000,
|
||||||
growingAnimationDuration = 0.6,
|
growingAnimationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: CirclePulsingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<CirclePulsingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/12-dots-scale-rotate.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/12-dots-scale-rotate.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const rotationAnimationDur = reducedMotion ? rotationAnimationDuration / 100 : rotationAnimationDuration / 1000;
|
||||||
|
const growingAnimationDur = reducedMotion ? growingAnimationDuration / 100 : growingAnimationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -27,15 +38,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="3"
|
cy="3"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle1_${id}`}
|
id={`circle1_${id}`}
|
||||||
begin={`0;circle3_${id}.end-${growingAnimationDuration * 5 / 6}s`}
|
begin={`0;circle3_${id}.end-${growingAnimationDur * 5 / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -45,15 +56,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle2_${id}`}
|
id={`circle2_${id}`}
|
||||||
begin={`circle1_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle1_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -63,15 +74,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle3_${id}`}
|
id={`circle3_${id}`}
|
||||||
begin={`circle5_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle5_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -81,15 +92,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle4_${id}`}
|
id={`circle4_${id}`}
|
||||||
begin={`circle2_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle2_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -99,15 +110,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle5_${id}`}
|
id={`circle5_${id}`}
|
||||||
begin={`circle7_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle7_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -117,15 +128,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle6_${id}`}
|
id={`circle6_${id}`}
|
||||||
begin={`circle4_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle4_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -135,15 +146,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle7_${id}`}
|
id={`circle7_${id}`}
|
||||||
begin={`circle9_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle9_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -153,15 +164,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle8_${id}`}
|
id={`circle8_${id}`}
|
||||||
begin={`circle6_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle6_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -171,15 +182,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle9_${id}`}
|
id={`circle9_${id}`}
|
||||||
begin={`circle11_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle11_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -189,15 +200,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle10_${id}`}
|
id={`circle10_${id}`}
|
||||||
begin={`circle8_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle8_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -207,15 +218,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle11_${id}`}
|
id={`circle11_${id}`}
|
||||||
begin={`circle12_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle12_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -225,15 +236,15 @@ export default function CirclePulsingDots({
|
|||||||
cy="21"
|
cy="21"
|
||||||
r="1"
|
r="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`circle12_${id}`}
|
id={`circle12_${id}`}
|
||||||
begin={`circle10_${id}.begin+${growingAnimationDuration / 6}s`}
|
begin={`circle10_${id}.begin+${growingAnimationDur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={growingAnimationDuration}
|
dur={growingAnimationDur}
|
||||||
values="1;2;1"
|
values="1;2;1"
|
||||||
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
keySplines=".27,.42,.37,.99;.53,0,.61,.73"
|
||||||
/>
|
/>
|
||||||
@@ -241,7 +252,7 @@ export default function CirclePulsingDots({
|
|||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={rotationAnimationDuration}
|
dur={rotationAnimationDur}
|
||||||
values="360 12 12;0 12 12"
|
values="360 12 12;0 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleRotatingDots({
|
export default function CircleRotatingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.5,
|
animationDuration = 1500,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/8-dots-rotate.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/8-dots-rotate.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,69 +34,69 @@ export default function CircleRotatingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="21"
|
cx="21"
|
||||||
cy="12"
|
cy="12"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="12"
|
cx="12"
|
||||||
cy="21"
|
cy="21"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="12"
|
cx="12"
|
||||||
cy="3"
|
cy="3"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="5.64"
|
cx="5.64"
|
||||||
cy="5.64"
|
cy="5.64"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="18.36"
|
cx="18.36"
|
||||||
cy="18.36"
|
cy="18.36"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="5.64"
|
cx="5.64"
|
||||||
cy="18.36"
|
cy="18.36"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="18.36"
|
cx="18.36"
|
||||||
cy="5.64"
|
cy="5.64"
|
||||||
r="2"
|
r="2"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleShrinkingDots({
|
export default function CircleShrinkingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-scale.svg?short_path=17d1946
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/6-dots-scale.svg?short_path=17d1946
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,15 +35,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="3"
|
cy="3"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`firstShrinkingDot_${id}`}
|
id={`firstShrinkingDot_${id}`}
|
||||||
begin={`0;thirdShrinkingDot_${id}.end-${animationDuration * 4 / 5}s`}
|
begin={`0;thirdShrinkingDot_${id}.end-${dur * 4 / 5}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -45,15 +55,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`secondShrinkingDot_${id}`}
|
id={`secondShrinkingDot_${id}`}
|
||||||
begin={`firstShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`firstShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -65,15 +75,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="4.21"
|
cy="4.21"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`thirdShrinkingDot_${id}`}
|
id={`thirdShrinkingDot_${id}`}
|
||||||
begin={`fifthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`fifthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -85,15 +95,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`fourthShrinkingDot_${id}`}
|
id={`fourthShrinkingDot_${id}`}
|
||||||
begin={`secondShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`secondShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"
|
keySplines="0,1,0,1;.53,0,.61,.73" fill="freeze"
|
||||||
@@ -104,15 +114,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="7.50"
|
cy="7.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`fifthShrinkingDot_${id}`}
|
id={`fifthShrinkingDot_${id}`}
|
||||||
begin={`seventhShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`seventhShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -124,15 +134,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`sixthShrinkingDot_${id}`}
|
id={`sixthShrinkingDot_${id}`}
|
||||||
begin={`fourthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`fourthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -144,15 +154,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="12.00"
|
cy="12.00"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`seventhShrinkingDot_${id}`}
|
id={`seventhShrinkingDot_${id}`}
|
||||||
begin={`ninthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`ninthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -164,15 +174,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`eighthShrinkingDot_${id}`}
|
id={`eighthShrinkingDot_${id}`}
|
||||||
begin={`sixthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`sixthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -184,15 +194,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="16.50"
|
cy="16.50"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`ninthShrinkingDot_${id}`}
|
id={`ninthShrinkingDot_${id}`}
|
||||||
begin={`eleventhShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`eleventhShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -204,15 +214,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`tenthShrinkingDot_${id}`}
|
id={`tenthShrinkingDot_${id}`}
|
||||||
begin={`eighthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`eighthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -224,15 +234,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="19.79"
|
cy="19.79"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`eleventhShrinkingDot_${id}`}
|
id={`eleventhShrinkingDot_${id}`}
|
||||||
begin={`twelfthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`twelfthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
@@ -244,15 +254,15 @@ export default function CircleShrinkingDots({
|
|||||||
cy="21"
|
cy="21"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`twelfthShrinkingDot_${id}`}
|
id={`twelfthShrinkingDot_${id}`}
|
||||||
begin={`tenthShrinkingDot_${id}.begin+${animationDuration / 6}s`}
|
begin={`tenthShrinkingDot_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;2;0"
|
values="0;2;0"
|
||||||
keyTimes="0;.2;1"
|
keyTimes="0;.2;1"
|
||||||
keySplines="0,1,0,1;.53,0,.61,.73"
|
keySplines="0,1,0,1;.53,0,.61,.73"
|
||||||
|
|||||||
@@ -1,21 +1,33 @@
|
|||||||
import type { CircleSpinningDotProps } from "$/types/LoadingTypes";
|
import type { CircleSpinningDotProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function CircleSpinningDot({
|
export default function CircleSpinningDot({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill,
|
fill,
|
||||||
trackClassName = "fill-transparent",
|
trackClassName = "fill-transparent",
|
||||||
trackStroke,
|
trackStroke,
|
||||||
trackFill
|
trackFill,
|
||||||
}: CircleSpinningDotProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<CircleSpinningDotProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/dot-revolve.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/dot-revolve.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -30,13 +42,13 @@ export default function CircleSpinningDot({
|
|||||||
cy="2.5"
|
cy="2.5"
|
||||||
r="1.5"
|
r="1.5"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function CyclingDots({
|
export default function CyclingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.5,
|
animationDuration = 500,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-move.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-move.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,14 +35,14 @@ export default function CyclingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin="0;spinner_z0Or.end"
|
begin="0;spinner_z0Or.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="0;3"
|
values="0;3"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -40,7 +51,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_OLMs.end"
|
begin="spinner_OLMs.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="4;12"
|
values="4;12"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -49,7 +60,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_UHR2.end"
|
begin="spinner_UHR2.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="12;20"
|
values="12;20"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -59,7 +70,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_Aguh.end"
|
begin="spinner_Aguh.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="3;0"
|
values="3;0"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -78,14 +89,14 @@ export default function CyclingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin="0;spinner_z0Or.end"
|
begin="0;spinner_z0Or.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="4;12"
|
values="4;12"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -94,7 +105,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_OLMs.end"
|
begin="spinner_OLMs.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="12;20"
|
values="12;20"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -104,7 +115,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_UHR2.end"
|
begin="spinner_UHR2.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="3;0"
|
values="3;0"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -121,7 +132,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_Aguh.end"
|
begin="spinner_Aguh.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="0;3"
|
values="0;3"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -132,14 +143,14 @@ export default function CyclingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin="0;spinner_z0Or.end"
|
begin="0;spinner_z0Or.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="12;20"
|
values="12;20"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -149,7 +160,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_OLMs.end"
|
begin="spinner_OLMs.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="3;0"
|
values="3;0"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -166,7 +177,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_UHR2.end"
|
begin="spinner_UHR2.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="0;3"
|
values="0;3"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -175,7 +186,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_Aguh.end"
|
begin="spinner_Aguh.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="4;12"
|
values="4;12"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -186,15 +197,15 @@ export default function CyclingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`fourthDotFirstAnimate_${id}`}
|
id={`fourthDotFirstAnimate_${id}`}
|
||||||
begin="0;spinner_z0Or.end"
|
begin="0;spinner_z0Or.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="3;0"
|
values="3;0"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -211,7 +222,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_OLMs.end"
|
begin="spinner_OLMs.end"
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="0;3"
|
values="0;3"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -220,7 +231,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_UHR2.end"
|
begin="spinner_UHR2.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="4;12"
|
values="4;12"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -229,7 +240,7 @@ export default function CyclingDots({
|
|||||||
begin="spinner_Aguh.end"
|
begin="spinner_Aguh.end"
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1"
|
keySplines=".36,.6,.31,1"
|
||||||
values="12;20"
|
values="12;20"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function FadingDots({
|
export default function FadingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-fade.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-fade.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -26,14 +36,14 @@ export default function FadingDots({
|
|||||||
r="3"
|
r="3"
|
||||||
opacity="1"
|
opacity="1"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`firstFadingDots_${id}`}
|
id={`firstFadingDots_${id}`}
|
||||||
begin={`0;lastFadingDots_${id}.end-${animationDuration / 3}s`}
|
begin={`0;lastFadingDots_${id}.end-${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -44,14 +54,14 @@ export default function FadingDots({
|
|||||||
r="3"
|
r="3"
|
||||||
opacity=".4"
|
opacity=".4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`secondFadingDots_${id}`}
|
id={`secondFadingDots_${id}`}
|
||||||
begin={`firstFadingDots_${id}.begin+${animationDuration / 5}s`}
|
begin={`firstFadingDots_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
@@ -62,14 +72,14 @@ export default function FadingDots({
|
|||||||
r="3"
|
r="3"
|
||||||
opacity=".3"
|
opacity=".3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`lastFadingDots_${id}`}
|
id={`lastFadingDots_${id}`}
|
||||||
begin={`secondFadingDots_${id}.begin+${animationDuration / 5}s`}
|
begin={`secondFadingDots_${id}.begin+${dur / 5}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;.2"
|
values="1;.2"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function PulsingDots({
|
export default function PulsingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-scale-middle.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-scale-middle.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -22,12 +33,12 @@ export default function PulsingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="1.5"
|
r="1.5"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;3;1.5"
|
values="1.5;3;1.5"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
@@ -37,12 +48,12 @@ export default function PulsingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="3;1.5;3"
|
values="3;1.5;3"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
@@ -52,12 +63,12 @@ export default function PulsingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="1.5"
|
r="1.5"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1.5;3;1.5"
|
values="1.5;3;1.5"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,18 +1,29 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
export default function RotatingDots({
|
export default function RotatingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1,
|
animationDuration = 1000,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-rotate.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-rotate.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -21,8 +32,8 @@ export default function RotatingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<g>
|
<g>
|
||||||
<circle
|
<circle
|
||||||
@@ -30,22 +41,22 @@ export default function RotatingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<circle
|
<circle
|
||||||
cx="20"
|
cx="20"
|
||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
keySplines=".36,.6,.31,1;.36,.6,.31,1"
|
keySplines=".36,.6,.31,1;.36,.6,.31,1"
|
||||||
values="0 12 12;180 12 12;360 12 12"
|
values="0 12 12;180 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
import type { LoadingDotsProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function SwellingDots({
|
export default function SwellingDots({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingDotsProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingDotsProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-scale.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/3-dots-scale.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,14 +35,14 @@ export default function SwellingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`firstDot_${id}`}
|
id={`firstDot_${id}`}
|
||||||
begin={`0;lastDot_${id}.end-${animationDuration / 3}s`}
|
begin={`0;lastDot_${id}.end-${dur / 3}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="3;.2;3"
|
values="3;.2;3"
|
||||||
/>
|
/>
|
||||||
</circle>
|
</circle>
|
||||||
@@ -41,13 +51,13 @@ export default function SwellingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
begin={`firstDot_${id}.end-${animationDuration * 4 / 5}s`}
|
begin={`firstDot_${id}.end-${dur * 4 / 5}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="3;.2;3"
|
values="3;.2;3"
|
||||||
/>
|
/>
|
||||||
</circle>
|
</circle>
|
||||||
@@ -56,14 +66,14 @@ export default function SwellingDots({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`lastDot_${id}`}
|
id={`lastDot_${id}`}
|
||||||
begin={`firstDot_${id}.end-${animationDuration * 2 / 3}s`}
|
begin={`firstDot_${id}.end-${dur * 2 / 3}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="3;.2;3"
|
values="3;.2;3"
|
||||||
/>
|
/>
|
||||||
</circle>
|
</circle>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function DoubleDrop({
|
export default function DoubleDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-2.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-2.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,24 +35,24 @@ export default function DoubleDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
begin={`0;drop2_${id}.begin+${animationDuration / 2}s`}
|
begin={`0;drop2_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;drop2_${id}.begin+${animationDuration / 2}s`}
|
begin={`0;drop2_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -53,24 +63,24 @@ export default function DoubleDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 2}s`}
|
begin={`drop1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 2}s`}
|
begin={`drop1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function DoubleWaveDrop({
|
export default function DoubleWaveDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-2.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-2.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,34 +34,34 @@ export default function DoubleWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
begin={`0;drop2_${id}.begin+${animationDuration / 2}s`}
|
begin={`0;drop2_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`0;drop2_${id}.begin+${animationDuration / 2}s`}
|
begin={`0;drop2_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;drop2_${id}.begin+${animationDuration / 2}s`}
|
begin={`0;drop2_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -60,34 +70,34 @@ export default function DoubleWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 2}s`}
|
begin={`drop1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 2}s`}
|
begin={`drop1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 2}s`}
|
begin={`drop1_${id}.begin+${dur / 2}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function Drop({
|
export default function Drop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,13 +33,13 @@ export default function Drop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -38,7 +47,7 @@ export default function Drop({
|
|||||||
<animate
|
<animate
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function QuickDrop({
|
export default function QuickDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-multiple.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-multiple.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,15 +35,15 @@ export default function QuickDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
begin={`0;drop3_${id}.end`}
|
begin={`0;drop3_${id}.end`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -42,7 +52,7 @@ export default function QuickDrop({
|
|||||||
begin={`0;drop3_${id}.end`}
|
begin={`0;drop3_${id}.end`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -53,24 +63,24 @@ export default function QuickDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 6}`}
|
begin={`drop1_${id}.begin+${dur / 6}`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 6}`}
|
begin={`drop1_${id}.begin+${dur / 6}`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -81,24 +91,24 @@ export default function QuickDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop3_${id}`}
|
id={`drop3_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}`}
|
begin={`drop1_${id}.begin+${dur / 3}`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}`}
|
begin={`drop1_${id}.begin+${dur / 3}`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function QuickWaveDrop({
|
export default function QuickWaveDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-multiple.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-multiple.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,8 +34,8 @@ export default function QuickWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
@@ -33,7 +43,7 @@ export default function QuickWaveDrop({
|
|||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -43,7 +53,7 @@ export default function QuickWaveDrop({
|
|||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -51,7 +61,7 @@ export default function QuickWaveDrop({
|
|||||||
begin={`0;drop3_${id}.end`}
|
begin={`0;drop3_${id}.end`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -60,34 +70,34 @@ export default function QuickWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 6}s`}
|
begin={`drop1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 6}s`}
|
begin={`drop1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 6}s`}
|
begin={`drop1_${id}.begin+${dur / 6}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -96,34 +106,34 @@ export default function QuickWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop3_${id}`}
|
id={`drop3_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function TripleDrop({
|
export default function TripleDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-3.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-3.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -25,24 +35,24 @@ export default function TripleDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
begin={`0;drop3_${id}.begin+${animationDuration / 3}s`}
|
begin={`0;drop3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;drop3_${id}.begin+${animationDuration / 3}s`}
|
begin={`0;drop3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -53,24 +63,24 @@ export default function TripleDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -81,24 +91,24 @@ export default function TripleDrop({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="0"
|
r="0"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`drop3_${id}`}
|
id={`drop3_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`drop1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;11"
|
values="0;11"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`drop1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function TripleWaveDrop({
|
export default function TripleWaveDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-3.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-rings-3.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -24,34 +34,34 @@ export default function TripleWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop1_${id}`}
|
id={`drop1_${id}`}
|
||||||
begin={`0;drop3_${id}.begin+${animationDuration / 3}s`}
|
begin={`0;drop3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`0;drop3_${id}.begin+${animationDuration / 3}s`}
|
begin={`0;drop3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`0;drop3_${id}.begin+${animationDuration / 3}s`}
|
begin={`0;drop3_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -60,34 +70,34 @@ export default function TripleWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop2_${id}`}
|
id={`drop2_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration / 3}s`}
|
begin={`drop1_${id}.begin+${dur / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
@@ -96,34 +106,34 @@ export default function TripleWaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
id={`drop3_${id}`}
|
id={`drop3_${id}`}
|
||||||
begin={`drop1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`drop1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
begin={`drop1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`drop1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
begin={`drop1_${id}.begin+${animationDuration * 2 / 3}s`}
|
begin={`drop1_${id}.begin+${dur * 2 / 3}s`}
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
import type { LoadingPulseProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function WaveDrop({
|
export default function WaveDrop({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.2,
|
animationDuration = 1200,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingPulseProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingPulseProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-ring.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/pulse-ring.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -23,14 +32,14 @@ export default function WaveDrop({
|
|||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
transform="translate(12, 12) scale(0)"
|
transform="translate(12, 12) scale(0)"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
type="translate"
|
type="translate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="12 12;0 0"
|
values="12 12;0 0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -40,7 +49,7 @@ export default function WaveDrop({
|
|||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
additive="sum"
|
additive="sum"
|
||||||
type="scale"
|
type="scale"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0;1"
|
values="0;1"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -48,7 +57,7 @@ export default function WaveDrop({
|
|||||||
<animate
|
<animate
|
||||||
attributeName="opacity"
|
attributeName="opacity"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="1;0"
|
values="1;0"
|
||||||
keySplines=".52,.6,.25,.99"
|
keySplines=".52,.6,.25,.99"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function HalfSpinner({
|
export default function HalfSpinner({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
animationDuration = 1,
|
animationDuration = 1000,
|
||||||
|
color,
|
||||||
className,
|
className,
|
||||||
stroke,
|
stroke,
|
||||||
fill,
|
fill,
|
||||||
trackClassName = "fill-transparent",
|
trackClassName = "fill-transparent",
|
||||||
trackStroke,
|
trackStroke,
|
||||||
trackFill
|
trackFill,
|
||||||
}: LoadingSpinnerProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingSpinnerProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/180-ring-with-bg.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/180-ring-with-bg.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -29,13 +40,13 @@ export default function HalfSpinner({
|
|||||||
<path
|
<path
|
||||||
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"
|
d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function QuarterSpinner({
|
export default function QuarterSpinner({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
animationDuration = 1,
|
animationDuration = 1000,
|
||||||
|
color,
|
||||||
className,
|
className,
|
||||||
stroke,
|
stroke,
|
||||||
fill,
|
fill,
|
||||||
trackClassName = "fill-transparent",
|
trackClassName = "fill-transparent",
|
||||||
trackStroke,
|
trackStroke,
|
||||||
trackFill
|
trackFill,
|
||||||
}: LoadingSpinnerProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingSpinnerProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/90-ring-with-bg.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/90-ring-with-bg.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -29,13 +40,13 @@ export default function QuarterSpinner({
|
|||||||
<path
|
<path
|
||||||
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
|
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,23 +1,35 @@
|
|||||||
import type { RubberLoadingSpinnerProps } from "$/types/LoadingTypes";
|
import type { RubberLoadingSpinnerProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function RubberSpinner({
|
export default function RubberSpinner({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
animationDuration = 2,
|
animationDuration = 2000,
|
||||||
stretchDuration = 1.5,
|
stretchDuration = 1500,
|
||||||
|
color,
|
||||||
className,
|
className,
|
||||||
stroke,
|
stroke,
|
||||||
fill = "none",
|
fill = "none",
|
||||||
trackClassName = "fill-transparent",
|
trackClassName = "fill-transparent",
|
||||||
trackStroke,
|
trackStroke,
|
||||||
trackFill
|
trackFill,
|
||||||
}: RubberLoadingSpinnerProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<RubberLoadingSpinnerProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/ring-resize.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/ring-resize.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const animationDur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
const stretchDur = reducedMotion ? stretchDuration / 100 : stretchDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -33,14 +45,14 @@ export default function RubberSpinner({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="9.5"
|
r="9.5"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
strokeWidth="3"
|
strokeWidth="3"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="stroke-dasharray"
|
attributeName="stroke-dasharray"
|
||||||
dur={stretchDuration}
|
dur={stretchDur}
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
values="0 150;42 150;42 150;42 150"
|
values="0 150;42 150;42 150;42 150"
|
||||||
keyTimes="0;0.475;0.95;1"
|
keyTimes="0;0.475;0.95;1"
|
||||||
@@ -49,7 +61,7 @@ export default function RubberSpinner({
|
|||||||
/>
|
/>
|
||||||
<animate
|
<animate
|
||||||
attributeName="stroke-dashoffset"
|
attributeName="stroke-dashoffset"
|
||||||
dur={stretchDuration}
|
dur={stretchDur}
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
values="0;-16;-59;-59"
|
values="0;-16;-59;-59"
|
||||||
keyTimes="0;0.475;0.95;1"
|
keyTimes="0;0.475;0.95;1"
|
||||||
@@ -60,7 +72,7 @@ export default function RubberSpinner({
|
|||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={animationDur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,33 @@
|
|||||||
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
import type { LoadingSpinnerProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function ThreeQuarterSpinner({
|
export default function ThreeQuarterSpinner({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
animationDuration = 1,
|
animationDuration = 1000,
|
||||||
|
color,
|
||||||
className,
|
className,
|
||||||
stroke,
|
stroke,
|
||||||
fill,
|
fill,
|
||||||
trackClassName = "fill-transparent",
|
trackClassName = "fill-transparent",
|
||||||
trackStroke,
|
trackStroke,
|
||||||
trackFill
|
trackFill,
|
||||||
}: LoadingSpinnerProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingSpinnerProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/270-ring-with-bg.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/270-ring-with-bg.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -29,13 +40,13 @@ export default function ThreeQuarterSpinner({
|
|||||||
<path
|
<path
|
||||||
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"
|
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function BouncingDot({
|
export default function BouncingDot({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.9,
|
animationDuration = 900,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bouncing-ball.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/bouncing-ball.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -26,15 +36,15 @@ export default function BouncingDot({
|
|||||||
rx="4"
|
rx="4"
|
||||||
ry="4"
|
ry="4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
id={`dot1_1_${id}`}
|
id={`dot1_1_${id}`}
|
||||||
begin={`0;dot1_5_${id}.end`}
|
begin={`0;dot1_5_${id}.end`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration * 5 / 12}
|
dur={dur * 5 / 12}
|
||||||
values="5;20"
|
values="5;20"
|
||||||
keySplines=".33,0,.66,.33"
|
keySplines=".33,0,.66,.33"
|
||||||
fill="freeze"
|
fill="freeze"
|
||||||
@@ -43,7 +53,7 @@ export default function BouncingDot({
|
|||||||
begin={`dot1_1_${id}.end`}
|
begin={`dot1_1_${id}.end`}
|
||||||
attributeName="rx"
|
attributeName="rx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration / 18}
|
dur={dur / 18}
|
||||||
values="4;4.8;4"
|
values="4;4.8;4"
|
||||||
keySplines=".33,0,.66,.33;.33,.66,.66,1"
|
keySplines=".33,0,.66,.33;.33,.66,.66,1"
|
||||||
/>
|
/>
|
||||||
@@ -51,7 +61,7 @@ export default function BouncingDot({
|
|||||||
begin={`dot1_1_${id}.end`}
|
begin={`dot1_1_${id}.end`}
|
||||||
attributeName="ry"
|
attributeName="ry"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration / 18}
|
dur={dur / 18}
|
||||||
values="4;3;4"
|
values="4;3;4"
|
||||||
keySplines=".33,0,.66,.33;.33,.66,.66,1"
|
keySplines=".33,0,.66,.33;.33,.66,.66,1"
|
||||||
/>
|
/>
|
||||||
@@ -60,7 +70,7 @@ export default function BouncingDot({
|
|||||||
begin={`dot1_1_${id}.end`}
|
begin={`dot1_1_${id}.end`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration / 36}
|
dur={dur / 36}
|
||||||
values="20;20.5"
|
values="20;20.5"
|
||||||
keySplines=".33,0,.66,.33"
|
keySplines=".33,0,.66,.33"
|
||||||
/>
|
/>
|
||||||
@@ -69,7 +79,7 @@ export default function BouncingDot({
|
|||||||
begin={`dot1_4_${id}.end`}
|
begin={`dot1_4_${id}.end`}
|
||||||
attributeName="cy"
|
attributeName="cy"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration * 4 / 9}
|
dur={dur * 4 / 9}
|
||||||
values="20.5;5"
|
values="20.5;5"
|
||||||
keySplines=".33,.66,.66,1"
|
keySplines=".33,.66,.66,1"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function PulsingLine({
|
export default function PulsingLine({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/gooey-balls-1.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/gooey-balls-1.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -44,13 +53,13 @@ export default function PulsingLine({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="3"
|
r="3"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="4;9;4"
|
values="4;9;4"
|
||||||
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -58,7 +67,7 @@ export default function PulsingLine({
|
|||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="3;8;3"
|
values="3;8;3"
|
||||||
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -69,13 +78,13 @@ export default function PulsingLine({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="8"
|
r="8"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="15;20;15"
|
values="15;20;15"
|
||||||
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -83,7 +92,7 @@ export default function PulsingLine({
|
|||||||
<animate
|
<animate
|
||||||
attributeName="r"
|
attributeName="r"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="8;3;8"
|
values="8;3;8"
|
||||||
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
keySplines=".56,.52,.17,.98;.56,.52,.17,.98"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
|
|||||||
@@ -1,22 +1,32 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningBinary({
|
export default function SpinningBinary({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 2,
|
animationDuration = 2000,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/gooey-balls-2.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/gooey-balls-2.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
@@ -49,13 +59,13 @@ export default function SpinningBinary({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="4"
|
r="4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="5;8;5"
|
values="5;8;5"
|
||||||
keySplines=".36,.62,.43,.99;.79,0,.58,.57"
|
keySplines=".36,.62,.43,.99;.79,0,.58,.57"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -66,13 +76,13 @@ export default function SpinningBinary({
|
|||||||
cy="12"
|
cy="12"
|
||||||
r="4"
|
r="4"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animate
|
<animate
|
||||||
attributeName="cx"
|
attributeName="cx"
|
||||||
calcMode="spline"
|
calcMode="spline"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="19;16;19"
|
values="19;16;19"
|
||||||
keySplines=".36,.62,.43,.99;.79,0,.58,.57"
|
keySplines=".36,.62,.43,.99;.79,0,.58,.57"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
@@ -81,7 +91,7 @@ export default function SpinningBinary({
|
|||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration * 3 / 8}
|
dur={dur * 3 / 8}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,29 +1,38 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningClock({
|
export default function SpinningClock({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 9,
|
animationDuration = 9000,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/clock.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/clock.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,20a9,9,0,1,1,9-9A9,9,0,0,1,12,21Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
/>
|
/>
|
||||||
<rect
|
<rect
|
||||||
x="11"
|
x="11"
|
||||||
@@ -32,13 +41,13 @@ export default function SpinningClock({
|
|||||||
width="2"
|
width="2"
|
||||||
height="9"
|
height="9"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration / 12}
|
dur={dur / 12}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
@@ -54,7 +63,7 @@ export default function SpinningClock({
|
|||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningEclipse({
|
export default function SpinningEclipse({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/eclipse.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/eclipse.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M2,12A11.2,11.2,0,0,1,13,1.05C12.67,1,12.34,1,12,1a11,11,0,0,0,0,22c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"
|
d="M2,12A11.2,11.2,0,0,1,13,1.05C12.67,1,12.34,1,12,1a11,11,0,0,0,0,22c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningEclipseHalf({
|
export default function SpinningEclipseHalf({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.6,
|
animationDuration = 600,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/eclipse-half.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/eclipse-half.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M2,12A10.94,10.94,0,0,1,5,4.65c-.21-.19-.42-.36-.62-.55h0A11,11,0,0,0,12,23c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"
|
d="M2,12A10.94,10.94,0,0,1,5,4.65c-.21-.19-.42-.36-.62-.55h0A11,11,0,0,0,12,23c.34,0,.67,0,1-.05C6,23,2,17.74,2,12Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningGalaxy({
|
export default function SpinningGalaxy({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 1.5,
|
animationDuration = 1500,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/wind-toy.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/wind-toy.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M20.27,4.74a4.93,4.93,0,0,1,1.52,4.61,5.32,5.32,0,0,1-4.1,4.51,5.12,5.12,0,0,1-5.2-1.5,5.53,5.53,0,0,0,6.13-1.48A5.66,5.66,0,0,0,20.27,4.74ZM12.32,11.53a5.49,5.49,0,0,0-1.47-6.2A5.57,5.57,0,0,0,4.71,3.72,5.17,5.17,0,0,1,9.53,2.2,5.52,5.52,0,0,1,13.9,6.45,5.28,5.28,0,0,1,12.32,11.53ZM19.2,20.29a4.92,4.92,0,0,1-4.72,1.49,5.32,5.32,0,0,1-4.34-4.05A5.2,5.2,0,0,1,11.6,12.5a5.6,5.6,0,0,0,1.51,6.13A5.63,5.63,0,0,0,19.2,20.29ZM3.79,19.38A5.18,5.18,0,0,1,2.32,14a5.3,5.3,0,0,1,4.59-4,5,5,0,0,1,4.58,1.61,5.55,5.55,0,0,0-6.32,1.69A5.46,5.46,0,0,0,3.79,19.38ZM12.23,12a5.11,5.11,0,0,0,3.66-5,5.75,5.75,0,0,0-3.18-6,5,5,0,0,1,4.42,2.3,5.21,5.21,0,0,1,.24,5.92A5.4,5.4,0,0,1,12.23,12ZM11.76,12a5.18,5.18,0,0,0-3.68,5.09,5.58,5.58,0,0,0,3.19,5.79c-1,.35-2.9-.46-4-1.68A5.51,5.51,0,0,1,11.76,12ZM23,12.63a5.07,5.07,0,0,1-2.35,4.52,5.23,5.23,0,0,1-5.91.2,5.24,5.24,0,0,1-2.67-4.77,5.51,5.51,0,0,0,5.45,3.33A5.52,5.52,0,0,0,23,12.63ZM1,11.23a5,5,0,0,1,2.49-4.5,5.23,5.23,0,0,1,5.81-.06,5.3,5.3,0,0,1,2.61,4.74A5.56,5.56,0,0,0,6.56,8.06,5.71,5.71,0,0,0,1,11.23Z"
|
d="M20.27,4.74a4.93,4.93,0,0,1,1.52,4.61,5.32,5.32,0,0,1-4.1,4.51,5.12,5.12,0,0,1-5.2-1.5,5.53,5.53,0,0,0,6.13-1.48A5.66,5.66,0,0,0,20.27,4.74ZM12.32,11.53a5.49,5.49,0,0,0-1.47-6.2A5.57,5.57,0,0,0,4.71,3.72,5.17,5.17,0,0,1,9.53,2.2,5.52,5.52,0,0,1,13.9,6.45,5.28,5.28,0,0,1,12.32,11.53ZM19.2,20.29a4.92,4.92,0,0,1-4.72,1.49,5.32,5.32,0,0,1-4.34-4.05A5.2,5.2,0,0,1,11.6,12.5a5.6,5.6,0,0,0,1.51,6.13A5.63,5.63,0,0,0,19.2,20.29ZM3.79,19.38A5.18,5.18,0,0,1,2.32,14a5.3,5.3,0,0,1,4.59-4,5,5,0,0,1,4.58,1.61,5.55,5.55,0,0,0-6.32,1.69A5.46,5.46,0,0,0,3.79,19.38ZM12.23,12a5.11,5.11,0,0,0,3.66-5,5.75,5.75,0,0,0-3.18-6,5,5,0,0,1,4.42,2.3,5.21,5.21,0,0,1,.24,5.92A5.4,5.4,0,0,1,12.23,12ZM11.76,12a5.18,5.18,0,0,0-3.68,5.09,5.58,5.58,0,0,0,3.19,5.79c-1,.35-2.9-.46-4-1.68A5.51,5.51,0,0,1,11.76,12ZM23,12.63a5.07,5.07,0,0,1-2.35,4.52,5.23,5.23,0,0,1-5.91.2,5.24,5.24,0,0,1-2.67-4.77,5.51,5.51,0,0,0,5.45,3.33A5.52,5.52,0,0,0,23,12.63ZM1,11.23a5,5,0,0,1,2.49-4.5,5.23,5.23,0,0,1,5.81-.06,5.3,5.3,0,0,1,2.61,4.74A5.56,5.56,0,0,0,6.56,8.06,5.71,5.71,0,0,0,1,11.23Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,34 +1,43 @@
|
|||||||
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
import type { LoadingVariousProps } from "$/types/LoadingTypes";
|
||||||
|
import { usePrefersReducedMotion } from "$/util/AccessibilityUtil";
|
||||||
|
|
||||||
|
|
||||||
export default function SpinningTadpole({
|
export default function SpinningTadpole({
|
||||||
|
size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
className,
|
className,
|
||||||
animationDuration = 0.75,
|
animationDuration = 750,
|
||||||
|
color,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill,
|
||||||
}: LoadingVariousProps){
|
ariaLabel = "Loading"
|
||||||
|
}: Readonly<LoadingVariousProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/tadpole.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/tadpole.svg
|
||||||
|
const reducedMotion = usePrefersReducedMotion();
|
||||||
|
const dur = reducedMotion ? animationDuration / 100 : animationDuration / 1000;
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width={width}
|
width={size ?? width}
|
||||||
height={height}
|
height={size ?? height}
|
||||||
|
role="status"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-label={ariaLabel}
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M12,23a9.63,9.63,0,0,1-8-9.5,9.51,9.51,0,0,1,6.79-9.1A1.66,1.66,0,0,0,12,2.81h0a1.67,1.67,0,0,0-1.94-1.64A11,11,0,0,0,12,23Z"
|
d="M12,23a9.63,9.63,0,0,1-8-9.5,9.51,9.51,0,0,1,6.79-9.1A1.66,1.66,0,0,0,12,2.81h0a1.67,1.67,0,0,0-1.94-1.64A11,11,0,0,0,12,23Z"
|
||||||
className={className}
|
className={className}
|
||||||
stroke={stroke}
|
stroke={color ?? stroke}
|
||||||
fill={fill}
|
fill={color ?? fill}
|
||||||
>
|
>
|
||||||
<animateTransform
|
<animateTransform
|
||||||
attributeName="transform"
|
attributeName="transform"
|
||||||
type="rotate"
|
type="rotate"
|
||||||
dur={animationDuration}
|
dur={dur}
|
||||||
values="0 12 12;360 12 12"
|
values="0 12 12;360 12 12"
|
||||||
repeatCount="indefinite"
|
repeatCount="indefinite"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { LoadingWifiProps } from "$/types/LoadingTypes";
|
import type { LoadingWifiProps } from "$/types/LoadingTypes";
|
||||||
|
import { useId } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function Wifi({
|
export default function Wifi({
|
||||||
@@ -9,9 +10,9 @@ export default function Wifi({
|
|||||||
fadeDuration = 0.001,
|
fadeDuration = 0.001,
|
||||||
stroke,
|
stroke,
|
||||||
fill
|
fill
|
||||||
}: LoadingWifiProps){
|
}: Readonly<LoadingWifiProps>){
|
||||||
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/wifi.svg
|
//https://github.com/n3r4zzurr0/svg-spinners/blob/main/svg-smil/wifi.svg
|
||||||
const id = crypto.randomUUID().replaceAll("-", "");
|
const id = useId();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,17 +3,14 @@ import { Dialog, DialogBackdrop, DialogPanel } from "@headlessui/react";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function Modal(props: ModalProps){
|
export default function Modal({
|
||||||
const {
|
|
||||||
display,
|
display,
|
||||||
onClose,
|
onClose,
|
||||||
className,
|
className,
|
||||||
backgroundType = "blur",
|
backgroundType = "blur",
|
||||||
top,
|
top,
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<ModalProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={display}
|
open={display}
|
||||||
|
|||||||
@@ -2,19 +2,18 @@ import type { ModalBodyProps } from "$/types/ModalTypes";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function ModalBody(props: ModalBodyProps){
|
export default function ModalBody({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
children
|
children,
|
||||||
} = props;
|
...props
|
||||||
|
}: Readonly<ModalBodyProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-col items-center justify-start h-full w-full overflow-scroll",
|
"flex flex-col items-center justify-start h-full w-full overflow-scroll",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,19 +2,18 @@ import type { ModalFooterProps } from "$/types/ModalTypes";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function ModalFooter(props: ModalFooterProps){
|
export default function ModalFooter({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
children
|
children,
|
||||||
} = props;
|
...props
|
||||||
|
}: Readonly<ModalFooterProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-row items-center justify-center w-full rounded-b-lg",
|
"flex flex-row items-center justify-center w-full rounded-b-lg",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="flex flex-row items-center justify-center mx-8 my-3"
|
className="flex flex-row items-center justify-center mx-8 my-3"
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
|
import Button from "$/component/button/Button";
|
||||||
import type { ModalHeaderProps } from "$/types/ModalTypes";
|
import type { ModalHeaderProps } from "$/types/ModalTypes";
|
||||||
import { DialogTitle } from "@headlessui/react";
|
import { DialogTitle } from "@headlessui/react";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { BsXLg } from "react-icons/bs";
|
import { BsXLg } from "react-icons/bs";
|
||||||
|
|
||||||
|
|
||||||
export default function ModalHeader(props: ModalHeaderProps){
|
export default function ModalHeader({
|
||||||
const {
|
|
||||||
onClose,
|
onClose,
|
||||||
className,
|
className,
|
||||||
children
|
children,
|
||||||
} = props;
|
...props
|
||||||
|
}: Readonly<ModalHeaderProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex flex-row items-center justify-center w-full rounded-t-lg",
|
"flex flex-row items-center justify-center w-full rounded-t-lg",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
<DialogTitle
|
<DialogTitle
|
||||||
as="div"
|
as="div"
|
||||||
@@ -27,14 +27,14 @@ export default function ModalHeader(props: ModalHeaderProps){
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
{
|
{
|
||||||
onClose &&
|
onClose &&
|
||||||
<div
|
<Button
|
||||||
className="absolute top-1 right-1 cursor-pointer"
|
className="absolute top-1 right-1 cursor-pointer"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<BsXLg
|
<BsXLg
|
||||||
size={20}
|
size={20}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default function DarkModeSwitch(){
|
|||||||
|
|
||||||
const updateTheme = () => {
|
const updateTheme = () => {
|
||||||
if(theme === "system"){
|
if(theme === "system"){
|
||||||
if(window.document.documentElement.classList.contains("dark")){
|
if(globalThis.document.documentElement.classList.contains("dark")){
|
||||||
setTheme("light");
|
setTheme("light");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|||||||
@@ -2,13 +2,11 @@ import type { NavBarProps } from "$/types/NavTypes";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function NavBar(props: NavBarProps){
|
export default function NavBar({
|
||||||
const {
|
|
||||||
className,
|
className,
|
||||||
children
|
children,
|
||||||
} = props;
|
...props
|
||||||
|
}: Readonly<NavBarProps>){
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -16,6 +14,7 @@ export default function NavBar(props: NavBarProps){
|
|||||||
"fixed top-0 left-0 w-full z-10",
|
"fixed top-0 left-0 w-full z-10",
|
||||||
"flex flex-row flex-nowrap items-center justify-center"
|
"flex flex-row flex-nowrap items-center justify-center"
|
||||||
)}
|
)}
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -3,14 +3,11 @@ import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { RiArrowRightSLine } from "react-icons/ri";
|
import { RiArrowRightSLine } from "react-icons/ri";
|
||||||
|
|
||||||
export default function PopoverMenu(props: PopoverMenuProps){
|
export default function PopoverMenu({
|
||||||
const {
|
|
||||||
buttonContent,
|
buttonContent,
|
||||||
anchor,
|
anchor,
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<PopoverMenuProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverButton
|
<PopoverButton
|
||||||
|
|||||||
20
lib/component/pill/DangerPill.tsx
Normal file
20
lib/component/pill/DangerPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function DangerPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-danger-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-danger text-white"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/DarkPill.tsx
Normal file
20
lib/component/pill/DarkPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function DarkPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-dark-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-dark text-white"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/InfoPill.tsx
Normal file
20
lib/component/pill/InfoPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function InfoPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-info-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-info text-black"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/LightPill.tsx
Normal file
20
lib/component/pill/LightPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function LightPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-light-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-light text-black"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/MoltenPill.tsx
Normal file
20
lib/component/pill/MoltenPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function MoltenPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-molten-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-molten text-black"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
lib/component/pill/Pill.tsx
Normal file
26
lib/component/pill/Pill.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
|
export default function Pill({
|
||||||
|
className,
|
||||||
|
rounding = "full",
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-testid="mattrixwv-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"px-2 text-sm whitespace-nowrap",
|
||||||
|
{
|
||||||
|
"rounded-sm": rounding === "sm",
|
||||||
|
"rounded": rounding === "md",
|
||||||
|
"rounded-lg": rounding === "lg",
|
||||||
|
"rounded-full": rounding === "full"
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/PrimaryPill.tsx
Normal file
20
lib/component/pill/PrimaryPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function PrimaryPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-primary-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-primary text-white"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/SecondaryPill.tsx
Normal file
20
lib/component/pill/SecondaryPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function SecondaryPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-secondary-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-secondary text-white"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/SuccessPill.tsx
Normal file
20
lib/component/pill/SuccessPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function SuccessPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-success-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-success text-black"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/TertiaryPill.tsx
Normal file
20
lib/component/pill/TertiaryPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function TertiaryPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-tertiary-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-tertiary text-white"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
20
lib/component/pill/WarningPill.tsx
Normal file
20
lib/component/pill/WarningPill.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import Pill from "./Pill";
|
||||||
|
|
||||||
|
|
||||||
|
export default function WarningPill({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Readonly<PillProps>){
|
||||||
|
return (
|
||||||
|
<Pill
|
||||||
|
data-testid="mattrixwv-warning-pill"
|
||||||
|
className={clsx(
|
||||||
|
className,
|
||||||
|
"bg-warning text-black"
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,12 +3,9 @@ import { Tab } from "@headlessui/react";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvTab(props: MattrixwvTabProps){
|
export default function MattrixwvTab({
|
||||||
const {
|
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<MattrixwvTabProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab
|
<Tab
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
|||||||
@@ -7,13 +7,10 @@ import MattrixwvTabPanel from "./MattrixwvTabPanel";
|
|||||||
import MattrixwvTabPanels from "./MattrixwvTabPanels";
|
import MattrixwvTabPanels from "./MattrixwvTabPanels";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvTabGroup(props: MattrixwvTabGroupProps){
|
export default function MattrixwvTabGroup({
|
||||||
const {
|
|
||||||
tabs,
|
tabs,
|
||||||
className
|
className
|
||||||
} = props;
|
}: Readonly<MattrixwvTabGroupProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabGroup
|
<TabGroup
|
||||||
className={clsx(
|
className={clsx(
|
||||||
@@ -24,9 +21,7 @@ export default function MattrixwvTabGroup(props: MattrixwvTabGroupProps){
|
|||||||
<MattrixwvTabList>
|
<MattrixwvTabList>
|
||||||
{
|
{
|
||||||
tabs.map((tab, index) => (
|
tabs.map((tab, index) => (
|
||||||
<MattrixwvTab
|
<MattrixwvTab key={index}>
|
||||||
key={index}
|
|
||||||
>
|
|
||||||
{tab.tab}
|
{tab.tab}
|
||||||
</MattrixwvTab>
|
</MattrixwvTab>
|
||||||
))
|
))
|
||||||
@@ -35,9 +30,7 @@ export default function MattrixwvTabGroup(props: MattrixwvTabGroupProps){
|
|||||||
<MattrixwvTabPanels>
|
<MattrixwvTabPanels>
|
||||||
{
|
{
|
||||||
tabs.map((tab, index) => (
|
tabs.map((tab, index) => (
|
||||||
<MattrixwvTabPanel
|
<MattrixwvTabPanel key={index}>
|
||||||
key={index}
|
|
||||||
>
|
|
||||||
{tab.content}
|
{tab.content}
|
||||||
</MattrixwvTabPanel>
|
</MattrixwvTabPanel>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -2,16 +2,11 @@ import type { MattrixwvTabListProps } from "$/types/TabTypes";
|
|||||||
import { TabList } from "@headlessui/react";
|
import { TabList } from "@headlessui/react";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvTabList(props: MattrixwvTabListProps){
|
export default function MattrixwvTabList({
|
||||||
const {
|
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<MattrixwvTabListProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabList
|
<TabList className="flex flex-row items-center justify-start w-full border-b">
|
||||||
className="flex flex-row items-center justify-start w-full border-b"
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</TabList>
|
</TabList>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,16 +2,11 @@ import type { MattrixwvTabPanelProps } from "$/types/TabTypes";
|
|||||||
import { TabPanel } from "@headlessui/react";
|
import { TabPanel } from "@headlessui/react";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvTabPanel(props: MattrixwvTabPanelProps){
|
export default function MattrixwvTabPanel({
|
||||||
const {
|
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<MattrixwvTabPanelProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabPanel
|
<TabPanel className="flex flex-row items-start justify-center w-full h-full">
|
||||||
className="flex flex-row items-start justify-center w-full h-full"
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,16 +2,11 @@ import type { MattrixwvTabPanelsProps } from "$/types/TabTypes";
|
|||||||
import { TabPanels } from "@headlessui/react";
|
import { TabPanels } from "@headlessui/react";
|
||||||
|
|
||||||
|
|
||||||
export default function MattrixwvTabPanels(props: MattrixwvTabPanelsProps){
|
export default function MattrixwvTabPanels({
|
||||||
const {
|
|
||||||
children
|
children
|
||||||
} = props;
|
}: Readonly<MattrixwvTabPanelsProps>){
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabPanels
|
<TabPanels className="flex flex-row items-start justify-center w-full h-full overflow-scroll">
|
||||||
className="flex flex-row items-start justify-center w-full h-full overflow-scroll"
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import clsx from "clsx";
|
|||||||
export default function Toaster({
|
export default function Toaster({
|
||||||
toast,
|
toast,
|
||||||
className
|
className
|
||||||
}: ToasterProps){
|
}: Readonly<ToasterProps>){
|
||||||
return (
|
return (
|
||||||
<Transition
|
<Transition
|
||||||
show={toast.length > 1 || (toast.length === 1 && toast[0].hideTime > new Date())}
|
show={toast.length > 1 || (toast.length === 1 && toast[0].hideTime > new Date())}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const themeInitialState: ThemeProviderState = {
|
|||||||
const ThemeProviderContext = createContext<ThemeProviderState>(themeInitialState);
|
const ThemeProviderContext = createContext<ThemeProviderState>(themeInitialState);
|
||||||
|
|
||||||
|
|
||||||
export default function ThemeProvider(props: ThemeProviderProps){
|
export default function ThemeProvider(props: Readonly<ThemeProviderProps>){
|
||||||
const {
|
const {
|
||||||
children,
|
children,
|
||||||
defaultTheme = "system",
|
defaultTheme = "system",
|
||||||
@@ -20,12 +20,12 @@ export default function ThemeProvider(props: ThemeProviderProps){
|
|||||||
const [ theme, setTheme ] = useState<Theme>((localStorage.getItem(storageKey) as Theme) || defaultTheme);
|
const [ theme, setTheme ] = useState<Theme>((localStorage.getItem(storageKey) as Theme) || defaultTheme);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const root = window.document.documentElement;
|
const root = globalThis.document.documentElement;
|
||||||
|
|
||||||
root.classList.remove("light", "dark");
|
root.classList.remove("light", "dark");
|
||||||
|
|
||||||
if(theme === "system"){
|
if(theme === "system"){
|
||||||
const systemTheme = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
const systemTheme = globalThis.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
||||||
|
|
||||||
root.classList.add(systemTheme);
|
root.classList.add(systemTheme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const ToasterProviderContext = createContext<ToastProviderState>(toastInitialSta
|
|||||||
export default function ToasterProvider({
|
export default function ToasterProvider({
|
||||||
className,
|
className,
|
||||||
children
|
children
|
||||||
}: ToastProviderProps){
|
}: Readonly<ToastProviderProps>){
|
||||||
const [ toast, setToast ] = useState<Toast[]>([]);
|
const [ toast, setToast ] = useState<Toast[]>([]);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ButtonHTMLAttributes } from "react";
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
export type ButtonRounding = "none" | "sm" | "md" | "lg" | "full";
|
export type ButtonRounding = "none" | "sm" | "md" | "lg" | "full";
|
||||||
@@ -7,7 +7,7 @@ export type ButtonSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|||||||
export type ButtonVariant = "standard" | "outline" | "ghost" | "outline-ghost" | "icon";
|
export type ButtonVariant = "standard" | "outline" | "ghost" | "outline-ghost" | "icon";
|
||||||
|
|
||||||
|
|
||||||
export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "size" | "type"> {
|
export interface ButtonProps extends Omit<ComponentProps<"button">, "size" | "type"> {
|
||||||
type?: "button" | "submit" | "reset";
|
type?: "button" | "submit" | "reset";
|
||||||
rounding?: ButtonRounding;
|
rounding?: ButtonRounding;
|
||||||
shape?: ButtonShape;
|
shape?: ButtonShape;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type React from "react";
|
import type React from "react";
|
||||||
import type { ChangeEventHandler, InputHTMLAttributes } from "react";
|
import type { ChangeEventHandler, ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
export interface TextInputProps {
|
export interface TextInputProps {
|
||||||
@@ -11,7 +11,6 @@ export interface TextInputProps {
|
|||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
spellCheck?: boolean;
|
spellCheck?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
defaultValue?: string;
|
|
||||||
value?: string;
|
value?: string;
|
||||||
onChange?: ChangeEventHandler<HTMLInputElement>;
|
onChange?: ChangeEventHandler<HTMLInputElement>;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@@ -26,7 +25,6 @@ export interface TextAreaProps {
|
|||||||
maxLength?: number;
|
maxLength?: number;
|
||||||
spellCheck?: boolean;
|
spellCheck?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
defaultValue?: string;
|
|
||||||
value?: string;
|
value?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
rows?: number;
|
rows?: number;
|
||||||
@@ -35,9 +33,10 @@ export interface TextAreaProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectInputProps {
|
export interface SelectInputProps {
|
||||||
label: React.ReactNode;
|
placeholder: React.ReactNode;
|
||||||
value?: string;
|
value?: string;
|
||||||
onChange?: (newValue: string) => void;
|
onChange?: (newValue: string) => void;
|
||||||
|
disabled?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +44,7 @@ export interface OptionInputProps {
|
|||||||
id?: string;
|
id?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
disabled?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +88,11 @@ export interface NumberInputProps {
|
|||||||
name?: string;
|
name?: string;
|
||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
defaultValue?: number;
|
step?: number;
|
||||||
value?: number;
|
prefix?: string;
|
||||||
onChange?: (newValue: number) => void;
|
suffix?: string;
|
||||||
|
value: number;
|
||||||
|
onChange: (newValue: number) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
@@ -102,20 +104,21 @@ export interface NumberSliderProps {
|
|||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
defaultValue?: number;
|
value: number;
|
||||||
value?: number;
|
onChange: (newValue: number) => void;
|
||||||
onChange?: (newValue: number) => void;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileInputProps {
|
export interface FileInputProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
ariaLabel?: string;
|
||||||
minSize?: number;
|
minSize?: number;
|
||||||
maxSize?: number;
|
maxSize?: number;
|
||||||
showFileName?: boolean;
|
showFileName: boolean;
|
||||||
showSize?: boolean;
|
showSize: boolean;
|
||||||
onChange?: (newFile: File | undefined) => void;
|
onChange?: (newFile: File | undefined) => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
@@ -125,7 +128,6 @@ export interface FileInputProps {
|
|||||||
export type CheckboxSize = "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
export type CheckboxSize = "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
|
|
||||||
export interface CheckboxProps {
|
export interface CheckboxProps {
|
||||||
id?: string;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
labelClassName?: string;
|
labelClassName?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -164,7 +166,7 @@ export interface RadioListProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface DateInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "step">{
|
export interface DateInputProps extends Omit<ComponentProps<"input">, "value" | "onChange" | "step">{
|
||||||
step?: number;
|
step?: number;
|
||||||
value: Date | undefined;
|
value: Date | undefined;
|
||||||
onChange: (newValue: Date | undefined) => void;
|
onChange: (newValue: Date | undefined) => void;
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
/* eslint-disable @typescript-eslint/no-empty-object-type */
|
||||||
interface LoadingDefaultProps {
|
interface LoadingDefaultProps {
|
||||||
width?: string | number;
|
size?: number;
|
||||||
height?: string | number;
|
width?: number;
|
||||||
|
height?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
animationDuration?: number;
|
animationDuration?: number;
|
||||||
|
color?: string;
|
||||||
stroke?: string;
|
stroke?: string;
|
||||||
fill?: string;
|
fill?: string;
|
||||||
|
|
||||||
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -26,13 +30,16 @@ export interface LoadingDotsProps extends LoadingDefaultProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CirclePulsingDotsProps {
|
export interface CirclePulsingDotsProps {
|
||||||
width?: string | number;
|
size?: number;
|
||||||
height?: string | number;
|
width?: number;
|
||||||
|
height?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
rotationAnimationDuration?: number;
|
rotationAnimationDuration?: number;
|
||||||
growingAnimationDuration?: number;
|
growingAnimationDuration?: number;
|
||||||
|
color?: string;
|
||||||
stroke?: string;
|
stroke?: string;
|
||||||
fill?: string;
|
fill?: string;
|
||||||
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CircleSpinningDotProps extends LoadingDefaultProps {
|
export interface CircleSpinningDotProps extends LoadingDefaultProps {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { HTMLProps } from "react";
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
export interface MessageBlockProps extends HTMLProps<HTMLDivElement> {
|
export interface MessageBlockProps extends ComponentProps<"div"> {
|
||||||
outline?: "none" | "sm" | "md" | "lg";
|
outline?: "none" | "sm" | "md" | "lg";
|
||||||
rounded?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
rounded?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
export type ModalBackgroundType = "darken" | "lighten" | "blur" | "darken-blur" | "lighten-blur" | "darken-blur-radial" | "lighten-blur-radial" | "transparent" | "none";
|
export type ModalBackgroundType = "darken" | "lighten" | "blur" | "darken-blur" | "lighten-blur" | "darken-blur-radial" | "lighten-blur-radial" | "transparent" | "none";
|
||||||
|
|
||||||
|
|
||||||
export interface ModalHeaderProps {
|
export interface ModalHeaderProps extends ComponentProps<"div"> {
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModalFooterProps {
|
export interface ModalFooterProps extends ComponentProps<"div"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModalBodyProps {
|
export interface ModalBodyProps extends ComponentProps<"div"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
export type Align = "start" | "end";
|
export type Align = "start" | "end";
|
||||||
export type Placement = "top" | "bottom" | "left" | "right";
|
export type Placement = "top" | "bottom" | "left" | "right";
|
||||||
export type AnchorTo = `${Placement}` | `${Placement} ${Align}`;
|
export type AnchorTo = `${Placement}` | `${Placement} ${Align}`;
|
||||||
@@ -9,7 +12,7 @@ export interface PopoverMenuProps {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NavBarProps {
|
export interface NavBarProps extends ComponentProps<"nav"> {
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|||||||
9
lib/types/PillTypes.ts
Normal file
9
lib/types/PillTypes.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import type { ComponentProps } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
export type PillRounding = "none" | "sm" | "md" | "lg" | "full";
|
||||||
|
|
||||||
|
|
||||||
|
export interface PillProps extends ComponentProps<"div"> {
|
||||||
|
rounding?: PillRounding;
|
||||||
|
}
|
||||||
14
lib/util/AccessibilityUtil.ts
Normal file
14
lib/util/AccessibilityUtil.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
export function usePrefersReducedMotion(){
|
||||||
|
const [ reduced, setReduced ] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const media = globalThis.matchMedia("(prefers-reduced-motion: reduce)");
|
||||||
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||||
|
setReduced(media.matches);
|
||||||
|
}, [ ]);
|
||||||
|
|
||||||
|
return reduced;
|
||||||
|
}
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mattrixwv-components",
|
"name": "mattrixwv-components",
|
||||||
"version": "0.0.8",
|
"version": "0.0.9",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mattrixwv-components",
|
"name": "mattrixwv-components",
|
||||||
"version": "0.0.8",
|
"version": "0.0.9",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mattrixwv-components",
|
"name": "mattrixwv-components",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "0.0.8",
|
"version": "0.0.9",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -18,12 +18,14 @@
|
|||||||
"versionMinor": "npm version minor",
|
"versionMinor": "npm version minor",
|
||||||
"versionMajor": "npm version major"
|
"versionMajor": "npm version major"
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"react-icons": "^5.5.0"
|
||||||
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@headlessui/react": "^2.2.9",
|
"@headlessui/react": "^2.2.9",
|
||||||
"clsx": "^2.1.1",
|
|
||||||
"react": "^19.2.3",
|
"react": "^19.2.3",
|
||||||
"react-dom": "^19.2.3",
|
"react-dom": "^19.2.3"
|
||||||
"react-icons": "^5.5.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.2",
|
"@eslint/js": "^9.39.2",
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ declare module "@tanstack/react-router" {
|
|||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<ThemeProvider defaultTheme="dark">
|
<ThemeProvider defaultTheme="dark">
|
||||||
<ToasterProvider className="bg-zinc-700 text-white px-4 py-2 min-w-32 max-w-128 rounded-lg gap-y-4">
|
<ToasterProvider className="bg-zinc-700 text-white px-4 py-2 min-w-32 max-w-lg rounded-lg gap-y-4">
|
||||||
<RouterProvider router={router}/>
|
<RouterProvider router={router}/>
|
||||||
</ToasterProvider>
|
</ToasterProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { Route as rootRouteImport } from './routes/__root'
|
|||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as IndexRouteImport } from './routes/index'
|
||||||
import { Route as TabIndexRouteImport } from './routes/tab/index'
|
import { Route as TabIndexRouteImport } from './routes/tab/index'
|
||||||
import { Route as ProgressIndexRouteImport } from './routes/progress/index'
|
import { Route as ProgressIndexRouteImport } from './routes/progress/index'
|
||||||
|
import { Route as PillIndexRouteImport } from './routes/pill/index'
|
||||||
import { Route as ModalIndexRouteImport } from './routes/modal/index'
|
import { Route as ModalIndexRouteImport } from './routes/modal/index'
|
||||||
import { Route as MessageIndexRouteImport } from './routes/message/index'
|
import { Route as MessageIndexRouteImport } from './routes/message/index'
|
||||||
import { Route as LoadingIndexRouteImport } from './routes/loading/index'
|
import { Route as LoadingIndexRouteImport } from './routes/loading/index'
|
||||||
@@ -33,6 +34,11 @@ const ProgressIndexRoute = ProgressIndexRouteImport.update({
|
|||||||
path: '/progress/',
|
path: '/progress/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const PillIndexRoute = PillIndexRouteImport.update({
|
||||||
|
id: '/pill/',
|
||||||
|
path: '/pill/',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const ModalIndexRoute = ModalIndexRouteImport.update({
|
const ModalIndexRoute = ModalIndexRouteImport.update({
|
||||||
id: '/modal/',
|
id: '/modal/',
|
||||||
path: '/modal/',
|
path: '/modal/',
|
||||||
@@ -66,6 +72,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/loading': typeof LoadingIndexRoute
|
'/loading': typeof LoadingIndexRoute
|
||||||
'/message': typeof MessageIndexRoute
|
'/message': typeof MessageIndexRoute
|
||||||
'/modal': typeof ModalIndexRoute
|
'/modal': typeof ModalIndexRoute
|
||||||
|
'/pill': typeof PillIndexRoute
|
||||||
'/progress': typeof ProgressIndexRoute
|
'/progress': typeof ProgressIndexRoute
|
||||||
'/tab': typeof TabIndexRoute
|
'/tab': typeof TabIndexRoute
|
||||||
}
|
}
|
||||||
@@ -76,6 +83,7 @@ export interface FileRoutesByTo {
|
|||||||
'/loading': typeof LoadingIndexRoute
|
'/loading': typeof LoadingIndexRoute
|
||||||
'/message': typeof MessageIndexRoute
|
'/message': typeof MessageIndexRoute
|
||||||
'/modal': typeof ModalIndexRoute
|
'/modal': typeof ModalIndexRoute
|
||||||
|
'/pill': typeof PillIndexRoute
|
||||||
'/progress': typeof ProgressIndexRoute
|
'/progress': typeof ProgressIndexRoute
|
||||||
'/tab': typeof TabIndexRoute
|
'/tab': typeof TabIndexRoute
|
||||||
}
|
}
|
||||||
@@ -87,6 +95,7 @@ export interface FileRoutesById {
|
|||||||
'/loading/': typeof LoadingIndexRoute
|
'/loading/': typeof LoadingIndexRoute
|
||||||
'/message/': typeof MessageIndexRoute
|
'/message/': typeof MessageIndexRoute
|
||||||
'/modal/': typeof ModalIndexRoute
|
'/modal/': typeof ModalIndexRoute
|
||||||
|
'/pill/': typeof PillIndexRoute
|
||||||
'/progress/': typeof ProgressIndexRoute
|
'/progress/': typeof ProgressIndexRoute
|
||||||
'/tab/': typeof TabIndexRoute
|
'/tab/': typeof TabIndexRoute
|
||||||
}
|
}
|
||||||
@@ -99,6 +108,7 @@ export interface FileRouteTypes {
|
|||||||
| '/loading'
|
| '/loading'
|
||||||
| '/message'
|
| '/message'
|
||||||
| '/modal'
|
| '/modal'
|
||||||
|
| '/pill'
|
||||||
| '/progress'
|
| '/progress'
|
||||||
| '/tab'
|
| '/tab'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
@@ -109,6 +119,7 @@ export interface FileRouteTypes {
|
|||||||
| '/loading'
|
| '/loading'
|
||||||
| '/message'
|
| '/message'
|
||||||
| '/modal'
|
| '/modal'
|
||||||
|
| '/pill'
|
||||||
| '/progress'
|
| '/progress'
|
||||||
| '/tab'
|
| '/tab'
|
||||||
id:
|
id:
|
||||||
@@ -119,6 +130,7 @@ export interface FileRouteTypes {
|
|||||||
| '/loading/'
|
| '/loading/'
|
||||||
| '/message/'
|
| '/message/'
|
||||||
| '/modal/'
|
| '/modal/'
|
||||||
|
| '/pill/'
|
||||||
| '/progress/'
|
| '/progress/'
|
||||||
| '/tab/'
|
| '/tab/'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
@@ -130,6 +142,7 @@ export interface RootRouteChildren {
|
|||||||
LoadingIndexRoute: typeof LoadingIndexRoute
|
LoadingIndexRoute: typeof LoadingIndexRoute
|
||||||
MessageIndexRoute: typeof MessageIndexRoute
|
MessageIndexRoute: typeof MessageIndexRoute
|
||||||
ModalIndexRoute: typeof ModalIndexRoute
|
ModalIndexRoute: typeof ModalIndexRoute
|
||||||
|
PillIndexRoute: typeof PillIndexRoute
|
||||||
ProgressIndexRoute: typeof ProgressIndexRoute
|
ProgressIndexRoute: typeof ProgressIndexRoute
|
||||||
TabIndexRoute: typeof TabIndexRoute
|
TabIndexRoute: typeof TabIndexRoute
|
||||||
}
|
}
|
||||||
@@ -157,6 +170,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof ProgressIndexRouteImport
|
preLoaderRoute: typeof ProgressIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/pill/': {
|
||||||
|
id: '/pill/'
|
||||||
|
path: '/pill'
|
||||||
|
fullPath: '/pill'
|
||||||
|
preLoaderRoute: typeof PillIndexRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/modal/': {
|
'/modal/': {
|
||||||
id: '/modal/'
|
id: '/modal/'
|
||||||
path: '/modal'
|
path: '/modal'
|
||||||
@@ -202,6 +222,7 @@ const rootRouteChildren: RootRouteChildren = {
|
|||||||
LoadingIndexRoute: LoadingIndexRoute,
|
LoadingIndexRoute: LoadingIndexRoute,
|
||||||
MessageIndexRoute: MessageIndexRoute,
|
MessageIndexRoute: MessageIndexRoute,
|
||||||
ModalIndexRoute: ModalIndexRoute,
|
ModalIndexRoute: ModalIndexRoute,
|
||||||
|
PillIndexRoute: PillIndexRoute,
|
||||||
ProgressIndexRoute: ProgressIndexRoute,
|
ProgressIndexRoute: ProgressIndexRoute,
|
||||||
TabIndexRoute: TabIndexRoute,
|
TabIndexRoute: TabIndexRoute,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const navLinks = [
|
|||||||
{ to: "/loading", label: "Loading" },
|
{ to: "/loading", label: "Loading" },
|
||||||
{ to: "/message", label: "Message" },
|
{ to: "/message", label: "Message" },
|
||||||
{ to: "/modal", label: "Modal" },
|
{ to: "/modal", label: "Modal" },
|
||||||
|
{ to: "/pill", label: "Pill" },
|
||||||
{ to: "/progress", label: "Progress" },
|
{ to: "/progress", label: "Progress" },
|
||||||
{ to: "/tab", label: "Tab" }
|
{ to: "/tab", label: "Tab" }
|
||||||
];
|
];
|
||||||
@@ -20,7 +21,7 @@ export const Route = createRootRoute({
|
|||||||
component: () => (
|
component: () => (
|
||||||
<>
|
<>
|
||||||
<NavBar
|
<NavBar
|
||||||
className="bg-neutral-300 dark:bg-neutral-900 h-12"
|
className="bg-neutral-300 dark:bg-neutral-900 h-12 gap-x-4"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="flex flex-row items-center justify-end gap-x-4"
|
className="flex flex-row items-center justify-end gap-x-4"
|
||||||
|
|||||||
@@ -120,10 +120,10 @@ function generateTabContent(Fn: (props: ButtonProps) => JSX.Element, onClick: ()
|
|||||||
function ButtonDisplay({
|
function ButtonDisplay({
|
||||||
title,
|
title,
|
||||||
children
|
children
|
||||||
}:{
|
}: Readonly<{
|
||||||
title: React.ReactNode;
|
title: React.ReactNode;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}){
|
}>){
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center gap-y-2"
|
className="flex flex-col items-center justify-center gap-y-2"
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { DangerMessageBlock, DarkMessageBlock, LightMessageBlock, PrimaryMessageBlock, SecondaryMessageBlock, SuccessMessageBlock, TertiaryMessageBlock, WarningMessageBlock } from '$/component/message';
|
import { DangerMessageBlock, DarkMessageBlock, LightMessageBlock, PrimaryMessageBlock, SecondaryMessageBlock, SuccessMessageBlock, TertiaryMessageBlock, WarningMessageBlock } from '$/component/message';
|
||||||
import InfoMessageBlock from '$/component/message/InfoMessageBlock';
|
import InfoMessageBlock from "$/component/message/InfoMessageBlock";
|
||||||
import MoltenMessageBlock from '$/component/message/MoltenMessageBlock';
|
import MoltenMessageBlock from "$/component/message/MoltenMessageBlock";
|
||||||
import { MattrixwvTabGroup } from '$/component/tab';
|
import { MattrixwvTabGroup } from "$/component/tab";
|
||||||
import type { MessageBlockProps } from '$/types/MessageTypes';
|
import type { MessageBlockProps } from "$/types/MessageTypes";
|
||||||
import type { TabGroupContent } from '$/types/TabTypes';
|
import type { TabGroupContent } from "$/types/TabTypes";
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/message/')({
|
export const Route = createFileRoute("/message/")({
|
||||||
component: MessagePage
|
component: MessagePage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -77,10 +77,10 @@ function ModalPage(){
|
|||||||
function DemoCenteredModal({
|
function DemoCenteredModal({
|
||||||
display,
|
display,
|
||||||
onClose
|
onClose
|
||||||
}:{
|
}: Readonly<{
|
||||||
display: boolean;
|
display: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}){
|
}>){
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
display={display}
|
display={display}
|
||||||
@@ -97,10 +97,10 @@ function DemoCenteredModal({
|
|||||||
function DemoTopModal({
|
function DemoTopModal({
|
||||||
display,
|
display,
|
||||||
onClose
|
onClose
|
||||||
}:{
|
}: Readonly<{
|
||||||
display: boolean;
|
display: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}){
|
}>){
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
display={display}
|
display={display}
|
||||||
|
|||||||
56
src/routes/pill/index.tsx
Normal file
56
src/routes/pill/index.tsx
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import DangerPill from "$/component/pill/DangerPill";
|
||||||
|
import DarkPill from "$/component/pill/DarkPill";
|
||||||
|
import InfoPill from "$/component/pill/InfoPill";
|
||||||
|
import LightPill from "$/component/pill/LightPill";
|
||||||
|
import MoltenPill from "$/component/pill/MoltenPill";
|
||||||
|
import PrimaryPill from "$/component/pill/PrimaryPill";
|
||||||
|
import SecondaryPill from "$/component/pill/SecondaryPill";
|
||||||
|
import SuccessPill from "$/component/pill/SuccessPill";
|
||||||
|
import TertiaryPill from "$/component/pill/TertiaryPill";
|
||||||
|
import WarningPill from "$/component/pill/WarningPill";
|
||||||
|
import type { PillProps } from "$/types/PillTypes";
|
||||||
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/pill/")({
|
||||||
|
component: PillPage
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function PillPage(){
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center gap-y-8">
|
||||||
|
<PillLayout PillType={PrimaryPill} pillName="Primary"/>
|
||||||
|
<PillLayout PillType={SecondaryPill} pillName="Secondary"/>
|
||||||
|
<PillLayout PillType={TertiaryPill} pillName="Tertiary"/>
|
||||||
|
<PillLayout PillType={InfoPill} pillName="Info"/>
|
||||||
|
<PillLayout PillType={SuccessPill} pillName="Success"/>
|
||||||
|
<PillLayout PillType={WarningPill} pillName="Warning"/>
|
||||||
|
<PillLayout PillType={DangerPill} pillName="Danger"/>
|
||||||
|
<PillLayout PillType={MoltenPill} pillName="Molten"/>
|
||||||
|
<PillLayout PillType={DarkPill} pillName="Dark"/>
|
||||||
|
<PillLayout PillType={LightPill} pillName="Light"/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function PillLayout({
|
||||||
|
PillType,
|
||||||
|
pillName
|
||||||
|
}: Readonly<{
|
||||||
|
PillType: (props: PillProps) => React.ReactNode;
|
||||||
|
pillName: string;
|
||||||
|
}>){
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center justify-center gap-y-2">
|
||||||
|
<h2 className="text-2xl">{pillName}</h2>
|
||||||
|
<div className="flex flex-row items-center justify-center gap-x-8">
|
||||||
|
<PillType rounding="none">None</PillType>
|
||||||
|
<PillType rounding="sm">Small</PillType>
|
||||||
|
<PillType rounding="md">Medium</PillType>
|
||||||
|
<PillType rounding="lg">Large</PillType>
|
||||||
|
<PillType rounding="full">Full</PillType>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -128,13 +128,13 @@ function ProgressPage() {
|
|||||||
function ProgressBlock({
|
function ProgressBlock({
|
||||||
label,
|
label,
|
||||||
children
|
children
|
||||||
}:{
|
}: Readonly<{
|
||||||
label: string;
|
label: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}){
|
}>){
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center w-128 gap-y-2"
|
className="flex flex-col items-center justify-center w-lg gap-y-2"
|
||||||
>
|
>
|
||||||
<h3
|
<h3
|
||||||
className="font-bold text-2xl"
|
className="font-bold text-2xl"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import WarningCheckbox from "$/component/input/checkbox/WarningCheckbox";
|
|||||||
import DateInput from "$/component/input/date/DateInput";
|
import DateInput from "$/component/input/date/DateInput";
|
||||||
import DateTimeInput from "$/component/input/date/DateTimeInput";
|
import DateTimeInput from "$/component/input/date/DateTimeInput";
|
||||||
import TimeInput from "$/component/input/date/TimeInput";
|
import TimeInput from "$/component/input/date/TimeInput";
|
||||||
|
import NumberSlider from "$/component/input/number/NumberSlider";
|
||||||
import DangerRadioButton from "$/component/input/radio/DangerRadioButton";
|
import DangerRadioButton from "$/component/input/radio/DangerRadioButton";
|
||||||
import DarkRadioButton from "$/component/input/radio/DarkRadioButton";
|
import DarkRadioButton from "$/component/input/radio/DarkRadioButton";
|
||||||
import InfoRadioButton from "$/component/input/radio/InfoRadioButton";
|
import InfoRadioButton from "$/component/input/radio/InfoRadioButton";
|
||||||
@@ -572,19 +573,20 @@ export function TextContent(){
|
|||||||
];
|
];
|
||||||
|
|
||||||
const [ selected, setSelected ] = useState(selectOptions[0]);
|
const [ selected, setSelected ] = useState(selectOptions[0]);
|
||||||
|
const [ numberValue, setNumberValue ] = useState(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
||||||
>
|
>
|
||||||
<TextDisplay title="Text Input">
|
<GeneralInputDisplay title="Text Input">
|
||||||
<TextInput placeholder="Text Input" labelClassName="bg-(--bg-color) peer-focus:bg-(--bg-color)"/>
|
<TextInput placeholder="Text Input" labelClassName="bg-(--bg-color) peer-focus:bg-(--bg-color)"/>
|
||||||
</TextDisplay>
|
</GeneralInputDisplay>
|
||||||
<TextDisplay title="Text Area">
|
<GeneralInputDisplay title="Text Area">
|
||||||
<TextArea placeholder="Textarea" className="resize" labelClassName="bg-(--bg-color) peer-focus:bg-(--bg-color)"/>
|
<TextArea placeholder="Textarea" className="resize" labelClassName="bg-(--bg-color) peer-focus:bg-(--bg-color)"/>
|
||||||
</TextDisplay>
|
</GeneralInputDisplay>
|
||||||
<TextDisplay title="Select">
|
<GeneralInputDisplay title="Select">
|
||||||
<SelectInput label={selected.label} onChange={(newValue) => setSelected(selectOptions.find((option) => option.value === newValue) || selectOptions[0])}>
|
<SelectInput placeholder={selected.label} onChange={(newValue) => setSelected(selectOptions.find((option) => option.value === newValue) || selectOptions[0])}>
|
||||||
{
|
{
|
||||||
selectOptions.map((option) => (
|
selectOptions.map((option) => (
|
||||||
<OptionInput
|
<OptionInput
|
||||||
@@ -597,31 +599,35 @@ export function TextContent(){
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
</TextDisplay>
|
</GeneralInputDisplay>
|
||||||
<TextDisplay
|
<GeneralInputDisplay
|
||||||
title="Number Input"
|
title="Number Input"
|
||||||
>
|
>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
labelClassName="bg-(--bg-color)"
|
labelClassName="bg-(--bg-color)"
|
||||||
|
value={numberValue}
|
||||||
|
onChange={setNumberValue}
|
||||||
>
|
>
|
||||||
Number Test
|
Number Test
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
</TextDisplay>
|
</GeneralInputDisplay>
|
||||||
{/*
|
{/* */
|
||||||
<TextDisplay
|
<GeneralInputDisplay
|
||||||
title="Number Slider"
|
title="Number Slider"
|
||||||
>
|
>
|
||||||
<NumberSlider
|
<NumberSlider
|
||||||
min={0}
|
min={0}
|
||||||
max={10}
|
max={10}
|
||||||
|
value={numberValue}
|
||||||
|
onChange={setNumberValue}
|
||||||
/>
|
/>
|
||||||
</TextDisplay>
|
</GeneralInputDisplay>
|
||||||
*/}
|
/* */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TextDisplay({
|
function GeneralInputDisplay({
|
||||||
title,
|
title,
|
||||||
children
|
children
|
||||||
}:Readonly<{
|
}:Readonly<{
|
||||||
@@ -643,13 +649,13 @@ export function FileContent(){
|
|||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
||||||
>
|
>
|
||||||
<FileDisplay title="File Input">
|
<GeneralInputDisplay title="File Input">
|
||||||
<FileInput
|
<FileInput
|
||||||
showFileName={true}
|
showFileName={true}
|
||||||
showSize={true}
|
showSize={true}
|
||||||
/>
|
/>
|
||||||
</FileDisplay>
|
</GeneralInputDisplay>
|
||||||
<FileDisplay title="Drag and Drop File Input">
|
<GeneralInputDisplay title="Drag and Drop File Input">
|
||||||
<DragAndDropFileInput
|
<DragAndDropFileInput
|
||||||
showFileName={true}
|
showFileName={true}
|
||||||
showSize={true}
|
showSize={true}
|
||||||
@@ -658,24 +664,7 @@ export function FileContent(){
|
|||||||
>
|
>
|
||||||
Drag And Drop File Input
|
Drag And Drop File Input
|
||||||
</DragAndDropFileInput>
|
</DragAndDropFileInput>
|
||||||
</FileDisplay>
|
</GeneralInputDisplay>
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function FileDisplay({
|
|
||||||
title,
|
|
||||||
children
|
|
||||||
}:Readonly<{
|
|
||||||
title: React.ReactNode;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}>){
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="flex flex-col items-center justify-center gap-y-2 w-full"
|
|
||||||
>
|
|
||||||
<h2 className="text-2xl">{title}</h2>
|
|
||||||
{children}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -685,7 +674,7 @@ export function CheckboxContent(){
|
|||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
||||||
>
|
>
|
||||||
<CheckboxDisplay title="Checkbox">
|
<GeneralInputDisplay title="Checkbox">
|
||||||
<div className="flex flex-row items-center justify-center gap-x-8">
|
<div className="flex flex-row items-center justify-center gap-x-8">
|
||||||
<MattrixwvCheckbox className="group-data-checked:stroke-white group-data-checked:bg-amber-400" defaultChecked={true}>Default</MattrixwvCheckbox>
|
<MattrixwvCheckbox className="group-data-checked:stroke-white group-data-checked:bg-amber-400" defaultChecked={true}>Default</MattrixwvCheckbox>
|
||||||
<PrimaryCheckbox defaultChecked={true} >Primary</PrimaryCheckbox>
|
<PrimaryCheckbox defaultChecked={true} >Primary</PrimaryCheckbox>
|
||||||
@@ -699,8 +688,8 @@ export function CheckboxContent(){
|
|||||||
<LightCheckbox defaultChecked={true}>Light</LightCheckbox>
|
<LightCheckbox defaultChecked={true}>Light</LightCheckbox>
|
||||||
<DarkCheckbox defaultChecked={true}>Dark</DarkCheckbox>
|
<DarkCheckbox defaultChecked={true}>Dark</DarkCheckbox>
|
||||||
</div>
|
</div>
|
||||||
</CheckboxDisplay>
|
</GeneralInputDisplay>
|
||||||
<CheckboxDisplay title="Checks">
|
<GeneralInputDisplay title="Checks">
|
||||||
<div className="flex flex-row items-center justify-center gap-x-8">
|
<div className="flex flex-row items-center justify-center gap-x-8">
|
||||||
<MattrixwvCheckbox className="group-data-checked:stroke-amber-400" defaultChecked={true} showBox={false}>Default</MattrixwvCheckbox>
|
<MattrixwvCheckbox className="group-data-checked:stroke-amber-400" defaultChecked={true} showBox={false}>Default</MattrixwvCheckbox>
|
||||||
<PrimaryCheckbox defaultChecked={true} showBox={false}>Primary</PrimaryCheckbox>
|
<PrimaryCheckbox defaultChecked={true} showBox={false}>Primary</PrimaryCheckbox>
|
||||||
@@ -714,24 +703,7 @@ export function CheckboxContent(){
|
|||||||
<LightCheckbox defaultChecked={true} showBox={false}>Light</LightCheckbox>
|
<LightCheckbox defaultChecked={true} showBox={false}>Light</LightCheckbox>
|
||||||
<DarkCheckbox defaultChecked={true} showBox={false}>Dark</DarkCheckbox>
|
<DarkCheckbox defaultChecked={true} showBox={false}>Dark</DarkCheckbox>
|
||||||
</div>
|
</div>
|
||||||
</CheckboxDisplay>
|
</GeneralInputDisplay>
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function CheckboxDisplay({
|
|
||||||
title,
|
|
||||||
children
|
|
||||||
}:Readonly<{
|
|
||||||
title: React.ReactNode;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}>){
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="flex flex-col items-center justify-center gap-y-2 w-full"
|
|
||||||
>
|
|
||||||
<h2 className="text-2xl">{title}</h2>
|
|
||||||
{children}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -741,7 +713,7 @@ export function RadioContent(){
|
|||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
className="flex flex-col items-center justify-center gap-y-8 mt-8 w-full"
|
||||||
>
|
>
|
||||||
<RadioDisplay title="Sizes">
|
<GeneralInputDisplay title="Sizes">
|
||||||
<RadioList
|
<RadioList
|
||||||
>
|
>
|
||||||
<PrimaryRadioButton size="xs" value="xs">Extra Small</PrimaryRadioButton>
|
<PrimaryRadioButton size="xs" value="xs">Extra Small</PrimaryRadioButton>
|
||||||
@@ -750,8 +722,8 @@ export function RadioContent(){
|
|||||||
<PrimaryRadioButton size="lg" value="lg">Large</PrimaryRadioButton>
|
<PrimaryRadioButton size="lg" value="lg">Large</PrimaryRadioButton>
|
||||||
<PrimaryRadioButton size="xl" value="xl">Extra Large</PrimaryRadioButton>
|
<PrimaryRadioButton size="xl" value="xl">Extra Large</PrimaryRadioButton>
|
||||||
</RadioList>
|
</RadioList>
|
||||||
</RadioDisplay>
|
</GeneralInputDisplay>
|
||||||
<RadioDisplay title="Radio Checked">
|
<GeneralInputDisplay title="Radio Checked">
|
||||||
<div
|
<div
|
||||||
className="flex flex-row items-center justify-center gap-x-8"
|
className="flex flex-row items-center justify-center gap-x-8"
|
||||||
>
|
>
|
||||||
@@ -766,8 +738,8 @@ export function RadioContent(){
|
|||||||
<RadioList value="Light"><LightRadioButton value="Light">Light</LightRadioButton></RadioList>
|
<RadioList value="Light"><LightRadioButton value="Light">Light</LightRadioButton></RadioList>
|
||||||
<RadioList value="Dark"><DarkRadioButton value="Dark">Dark</DarkRadioButton></RadioList>
|
<RadioList value="Dark"><DarkRadioButton value="Dark">Dark</DarkRadioButton></RadioList>
|
||||||
</div>
|
</div>
|
||||||
</RadioDisplay>
|
</GeneralInputDisplay>
|
||||||
<RadioDisplay title="Radio Horizontal">
|
<GeneralInputDisplay title="Radio Horizontal">
|
||||||
<RadioList
|
<RadioList
|
||||||
direction="horizontal"
|
direction="horizontal"
|
||||||
>
|
>
|
||||||
@@ -783,8 +755,8 @@ export function RadioContent(){
|
|||||||
<LightRadioButton value="light">Light</LightRadioButton>
|
<LightRadioButton value="light">Light</LightRadioButton>
|
||||||
<DarkRadioButton value="dark">Dark</DarkRadioButton>
|
<DarkRadioButton value="dark">Dark</DarkRadioButton>
|
||||||
</RadioList>
|
</RadioList>
|
||||||
</RadioDisplay>
|
</GeneralInputDisplay>
|
||||||
<RadioDisplay title="Radio Vertical">
|
<GeneralInputDisplay title="Radio Vertical">
|
||||||
<RadioList
|
<RadioList
|
||||||
direction="vertical"
|
direction="vertical"
|
||||||
>
|
>
|
||||||
@@ -800,24 +772,7 @@ export function RadioContent(){
|
|||||||
<LightRadioButton value="light">Light</LightRadioButton>
|
<LightRadioButton value="light">Light</LightRadioButton>
|
||||||
<DarkRadioButton value="dark">Dark</DarkRadioButton>
|
<DarkRadioButton value="dark">Dark</DarkRadioButton>
|
||||||
</RadioList>
|
</RadioList>
|
||||||
</RadioDisplay>
|
</GeneralInputDisplay>
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function RadioDisplay({
|
|
||||||
title,
|
|
||||||
children
|
|
||||||
}:Readonly<{
|
|
||||||
title: React.ReactNode;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}>){
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="flex flex-col items-center justify-center gap-y-2 w-full"
|
|
||||||
>
|
|
||||||
<h2 className="text-2xl">{title}</h2>
|
|
||||||
{children}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ import type { JSX } from "react";
|
|||||||
function LoadingGroup({
|
function LoadingGroup({
|
||||||
label,
|
label,
|
||||||
elements
|
elements
|
||||||
}:{
|
}: Readonly<{
|
||||||
label: React.ReactNode;
|
label: React.ReactNode;
|
||||||
elements: JSX.Element[];
|
elements: JSX.Element[];
|
||||||
}){
|
}>){
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="flex flex-col items-center justify-center"
|
className="flex flex-col items-center justify-center"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user